aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Schanzenbacher <ryan@rschanz.org>2026-07-09 22:15:53 -0400
committerRyan Schanzenbacher <ryan@rschanz.org>2026-07-09 22:15:53 -0400
commitd06784958d73159b5e4abafe5114804662114ed7 (patch)
treed8464262c1aa1f10553a5b11a9fda3e505e71f7f
parent1a71e94eb8ca1585201263cf654611ef6849d359 (diff)
move ubersicht modules in tree
-rw-r--r--users/ryan/modules/simple-bar/default.nix7
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.github/FUNDING.yml1
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/bug_report.md32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/documentation_error.md21
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/feature_request.md19
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.github/pull_request_template.md38
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.gitignore4
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/.prettierrc1
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/CODE_OF_CONDUCT.md128
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/CONTRIBUTING.md47
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/LICENSE21
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/README.md73
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/SECURITY.md9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/eslint.config.mjs52
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/images/logo-simple-bar.pngbin0 -> 6365 bytes
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/images/preview.pngbin0 -> 417752 bytes
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/index.jsx267
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/aerospace.js102
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/app-icons.js254
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace-context.jsx117
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx33
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx72
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx84
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx67
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx99
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/battery.jsx183
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/browser-track.jsx147
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/cpu.jsx153
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx160
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget-loader.jsx37
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget.jsx136
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/date-display.jsx118
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/github.jsx105
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/gpu.jsx128
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/graph.jsx87
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx108
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/memory.jsx134
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mic.jsx152
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mpd.jsx228
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/music.jsx161
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/netstats.jsx182
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/next-meeting.jsx310
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/notifications.jsx189
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/sound.jsx154
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/specter.jsx24
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/spotify.jsx189
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/stock.jsx211
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx144
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/user-widgets.jsx181
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/viscosity-vpn.jsx144
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/weather.jsx214
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/wifi.jsx154
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/youtube-music.jsx191
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/data/zoom.jsx107
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/error.jsx42
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icon.jsx40
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icons.jsx337
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ableton.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/activity.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/add.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-designer.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-photo.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-publisher.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/airmail.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/alfred.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-messages.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-studio.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anki.jsx16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/antigravity.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anytype.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/app-store.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple-simulator.jsx16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/aqua.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/arc.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/atom.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/audacity.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bambu-studio.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bank.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/battle-net.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bear.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/beekeeper.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell-off.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bit-warden.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bitcoin.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/blender.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/book.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/brave-browser.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bruno.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/c-lion.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ca-r-r-o-t.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/calendar.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera-off.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cancel.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/caprine.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/celo.jsx20
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/charging.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chat-gpt.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chatterino.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/check-box.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-bottom.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-left.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-right.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-top.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude-code.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/click-up.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cline.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/clock.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/close.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cloud.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/code.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/codex.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/coffee.jsx15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/color-picker.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/comfy-ui.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/copilot.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cp-u.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cursor.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/data-grip.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/date.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/de-v-o-nthink3.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/deezer.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/default.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/desktop.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/discord.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/docker.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dollar.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/down-arrow.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/download.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/drafts.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dropbox.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/element.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/emacs.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ethereum.jsx34
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/evernote-legacy.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/face-time.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/figma.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/final-cut-pro.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/finder.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox-developer-edition.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fleet.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fog.jsx20
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/folx.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/free-tube.jsx16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gear.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ghostty.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/git-hub.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gnu-cash.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/go-land.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/good-notes.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/google-chrome.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/goose.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/grammarly.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/helium.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/home-assistant.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ht-t-pie.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/idea.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/insomnia.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/iris.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/italic.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/joplin.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kakoune.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kee-pass-x-c.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard-maestro.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keynote.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/league-of-legends.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/libre-wolf.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/linear.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/lm-studio.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/maestro-ai.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mail.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mamp.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/manus.jsx17
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/matlab.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mattermost.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/messages.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-off.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-on.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-edge.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-excel.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-outlook.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-power-point.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-word.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mimestream.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/min-browser.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/miro.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/monero-gui.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mongo-db.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/moon.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mpv.jsx16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/music.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/n8n.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/net-news-wire.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/netease-music.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/no-volume.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notability.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notebook-lm.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notes.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notion.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/nova.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/numbers.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ob-s-studio.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/obsidian.jsx33
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ollama.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/omni-focus.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/one-password.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-book.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-claw.jsx16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/opencode.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/orb-stack.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pages.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/parallels.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/paused.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pdf.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/perplexity.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/php-storm.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pihole.jsx31
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pine.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pins.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/playing.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/plex.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/podcasts.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pomodone.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/postman.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/proton-mail.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/py-charm.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/quip.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/qute-browser.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/radar.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rain.jsx15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ram.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/redis.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reeder5.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reminders.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remnote.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remote-desktop.jsx15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remove.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/replit.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rider.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rocket-chat.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/roon.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/royal-tsx.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ruby-mine.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rust-rover.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/safari.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/screens4.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-ace.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-pro.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/setapp.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/signal.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch-up.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/skype.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/slack.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/snow.jsx18
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spark.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotify.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotlight.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotube.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/statistics.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/stopped.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/storm.jsx18
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sublime-text.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sun.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/super-productivity.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/table-plus.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tailscale.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/team-speak.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/teams.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/telegram.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/terminal.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/text.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thermostat.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/things.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thunderbird.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tick-tick.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tidal.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/todoist.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tor-browser.jsx15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tower.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/transmit.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/trello.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/twitter.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/up-arrow.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/upload.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vim.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vivaldi.jsx14
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vl-c.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vmware-fusion.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-high.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-low.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-muted.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n-off.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vs-codium.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/warp.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/web-storm.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wechat.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/whats-app.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/widget.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi-off.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/windows.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/xcode.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/youtube-music.jsx13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zed.jsx10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zen-browser.jsx11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zeplin.jsx43
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zoom.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zotero.jsx12
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zulip.jsx9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missive.jsx48
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missives.jsx40
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/aerospace-display-manager.jsx83
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/color-picker.jsx109
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/icon-picker.jsx130
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-component.jsx159
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-inner.jsx123
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-item.jsx143
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-widgets.jsx180
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings.jsx94
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx297
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/side-icon.jsx32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/simple-bar-context.jsx131
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai-context.jsx112
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/opened-apps.jsx55
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/process.jsx102
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space-options.jsx84
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space.jsx194
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/spaces.jsx109
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/stickies.jsx56
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/window.jsx119
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-server-socket.js221
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-widget-refresh.js37
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/schemas/config.json1159
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/browser-audio.applescript91
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-audio.applescript24
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-dev-audio.applescript24
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-aerospace.sh26
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-yabai.sh102
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/netstats.sh5
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh101
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-iterm2.applescript9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-terminal.applescript7
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode-server.sh38
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode.sh40
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-mute-status.applescript17
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-video-status.applescript17
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/settings.js1184
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/skhd.js17
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/battery.js134
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/browser-track.js40
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/cpu.js16
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/crypto.js9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget-loader.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget.js65
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/date-display.js10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/github.js10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/gpu.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/graph.js49
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/keyboard.js10
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/memory.js30
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mic.js83
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mpd.js80
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/music.js11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/netstats.js48
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/next-meeting.js71
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/notifications.js68
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/sound.js83
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/specter.js55
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/spotify.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/stock.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/time.js85
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/viscosity-vpn.js17
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/weather.js163
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/wifi.js13
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/youtube-music.js11
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/zoom.js26
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/missives.js89
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/process.js161
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/aerospace-display-manager.js101
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/color-picker.js83
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/icon-picker.js155
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/settings.js408
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/user-widgets-creator.js170
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/side-icon.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space-options.js137
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space.js152
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/spaces.js50
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/base.js120
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/variables.js107
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-colors.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-from-desktop.sh9
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-gen.sh7
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal.js15
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/theme.js21
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes.js72
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/amarena.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-frappe.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-latte.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-macchiato.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-mocha.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cisco.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/dracula.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-material.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/material-ocean.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/midsummer-night-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-owl.js33
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nord.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-dawn.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-moon.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-dark.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-light.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/spaceduck.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/sylens.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/tokyo-night.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/vscode-dark-modern.js32
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/utils.js828
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/yabai.js128
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/package-lock.json3267
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/package.json17
-rwxr-xr-x[-rw-r--r--]users/ryan/modules/taskwarrior-ubersicht/default.nix7
-rwxr-xr-xusers/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/README.md7
-rwxr-xr-xusers/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/style.css43
-rwxr-xr-xusers/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/taskwarrior.jsx203
-rwxr-xr-xusers/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/widget.json6
445 files changed, 23553 insertions, 12 deletions
diff --git a/users/ryan/modules/simple-bar/default.nix b/users/ryan/modules/simple-bar/default.nix
index 116216f..a309f61 100644
--- a/users/ryan/modules/simple-bar/default.nix
+++ b/users/ryan/modules/simple-bar/default.nix
@@ -4,12 +4,7 @@ with lib;
4 4
5let 5let
6 cfg = config.ryan.simple-bar; 6 cfg = config.ryan.simple-bar;
7 # Fetch the git repo at a specific rev 7 "simple-bar-upstream" = ./simple-bar-source
8 "simple-bar-upstream" = builtins.fetchGit {
9 url = "https://github.com/Jean-Tinland/simple-bar";
10 rev = "fb5cada548a05bd01f727772c0a18fd8c7f65b42";
11 shallow = true;
12 };
13in 8in
14{ 9{
15 options.ryan.simple-bar.enable = mkEnableOption "simple-bar"; 10 options.ryan.simple-bar.enable = mkEnableOption "simple-bar";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.github/FUNDING.yml b/users/ryan/modules/simple-bar/simple-bar-source/.github/FUNDING.yml
new file mode 100755
index 0000000..0067695
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.github/FUNDING.yml
@@ -0,0 +1 @@
github: [Jean-Tinland]
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/bug_report.md b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100755
index 0000000..07e7338
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,32 @@
1---
2name: Bug report
3about: Create a report to help us improve
4title: ""
5labels: bug
6assignees: ""
7---
8
9**Describe the bug**
10A clear and concise description of what the bug is.
11
12**To Reproduce**
13Steps to reproduce the behavior:
14
151. Go to '...'
162. Click on '....'
173. See error
18
19**Expected behavior**
20A clear and concise description of what you expected to happen.
21
22**Screenshots**
23If applicable, add screenshots to help explain your problem.
24
25**Information (please complete the following information):**
26
27- OS version [e.g. Sonoma 14.1.1]
28- yabai or AeroSpace version [e.g. yabai-v6.0.1]
29- Übersicht version [e.g. Version 1.6 (82)]
30
31**Additional context**
32Add any other context about the problem here.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/documentation_error.md b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/documentation_error.md
new file mode 100755
index 0000000..d0d287b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/documentation_error.md
@@ -0,0 +1,21 @@
1---
2name: Documentation error
3about: Create a report to help us improve
4title: ""
5labels: documentation
6assignees: ""
7---
8
9**Describe the bug**
10A clear and concise description of what the error is.
11
12**Where is located the error**
13
14Link to the documentation page where the error is located.
15
16**Expected content**
17
18What should be the correct content.
19
20**Additional context**
21Add any other context about the problem here.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/feature_request.md b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100755
index 0000000..d883b8f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,19 @@
1---
2name: Feature request
3about: Suggest an idea for this project
4title: ""
5labels: enhancement
6assignees: ""
7---
8
9**Is your feature request related to a problem? Please describe.**
10A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11
12**Describe the solution you'd like**
13A clear and concise description of what you want to happen.
14
15**Describe alternatives you've considered**
16A clear and concise description of any alternative solutions or features you've considered.
17
18**Additional context**
19Add any other context or screenshots about the feature request here.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.github/pull_request_template.md b/users/ryan/modules/simple-bar/simple-bar-source/.github/pull_request_template.md
new file mode 100755
index 0000000..d012be7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.github/pull_request_template.md
@@ -0,0 +1,38 @@
1# Description
2
3Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change.
4
5Fixes # (issue)
6
7## Type of change
8
9Please delete options that are not relevant.
10
11- [ ] Bug fix (non-breaking change which fixes an issue)
12- [ ] New feature (non-breaking change which adds functionality)
13- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
14- [ ] This change requires a documentation update
15
16# How Has This Been Tested?
17
18Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
19
20- [ ] Test A
21- [ ] Test B
22
23**Test Configuration**:
24
25- OS version [e.g. Sonoma 14.1.1]
26- yabai version [e.g. yabai-v6.0.1] (output of `yabai --version`)
27- Übersicht version [e.g. Version 1.6 (82)]
28
29# Checklist:
30
31- [ ] My code follows the style guidelines of this project
32- [ ] I have performed a self-review of my code
33- [ ] I have commented my code, particularly in hard-to-understand areas (make use of JSDoc if necessary)
34- [ ] My changes generate no new warnings
35
36# Changes to make to the documentation
37
38Please list any changes to the documentation that are required to reflect your changes.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.gitignore b/users/ryan/modules/simple-bar/simple-bar-source/.gitignore
new file mode 100755
index 0000000..7839ca3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.gitignore
@@ -0,0 +1,4 @@
1.DS_Store
2.idea
3/node_modules
4yarn.lock
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/.prettierrc b/users/ryan/modules/simple-bar/simple-bar-source/.prettierrc
new file mode 100755
index 0000000..0967ef4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/.prettierrc
@@ -0,0 +1 @@
{}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/CODE_OF_CONDUCT.md b/users/ryan/modules/simple-bar/simple-bar-source/CODE_OF_CONDUCT.md
new file mode 100755
index 0000000..f9218d4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/CODE_OF_CONDUCT.md
@@ -0,0 +1,128 @@
1# Contributor Covenant Code of Conduct
2
3## Our Pledge
4
5We as members, contributors, and leaders pledge to make participation in our
6community a harassment-free experience for everyone, regardless of age, body
7size, visible or invisible disability, ethnicity, sex characteristics, gender
8identity and expression, level of experience, education, socio-economic status,
9nationality, personal appearance, race, religion, or sexual identity
10and orientation.
11
12We pledge to act and interact in ways that contribute to an open, welcoming,
13diverse, inclusive, and healthy community.
14
15## Our Standards
16
17Examples of behavior that contributes to a positive environment for our
18community include:
19
20- Demonstrating empathy and kindness toward other people
21- Being respectful of differing opinions, viewpoints, and experiences
22- Giving and gracefully accepting constructive feedback
23- Accepting responsibility and apologizing to those affected by our mistakes,
24 and learning from the experience
25- Focusing on what is best not just for us as individuals, but for the
26 overall community
27
28Examples of unacceptable behavior include:
29
30- The use of sexualized language or imagery, and sexual attention or
31 advances of any kind
32- Trolling, insulting or derogatory comments, and personal or political attacks
33- Public or private harassment
34- Publishing others' private information, such as a physical or email
35 address, without their explicit permission
36- Other conduct which could reasonably be considered inappropriate in a
37 professional setting
38
39## Enforcement Responsibilities
40
41Community leaders are responsible for clarifying and enforcing our standards of
42acceptable behavior and will take appropriate and fair corrective action in
43response to any behavior that they deem inappropriate, threatening, offensive,
44or harmful.
45
46Community leaders have the right and responsibility to remove, edit, or reject
47comments, commits, code, wiki edits, issues, and other contributions that are
48not aligned to this Code of Conduct, and will communicate reasons for moderation
49decisions when appropriate.
50
51## Scope
52
53This Code of Conduct applies within all community spaces, and also applies when
54an individual is officially representing the community in public spaces.
55Examples of representing our community include using an official e-mail address,
56posting via an official social media account, or acting as an appointed
57representative at an online or offline event.
58
59## Enforcement
60
61Instances of abusive, harassing, or otherwise unacceptable behavior may be
62reported to the community leaders responsible for enforcement at
63https://www.jeantinland.com/contact/.
64All complaints will be reviewed and investigated promptly and fairly.
65
66All community leaders are obligated to respect the privacy and security of the
67reporter of any incident.
68
69## Enforcement Guidelines
70
71Community leaders will follow these Community Impact Guidelines in determining
72the consequences for any action they deem in violation of this Code of Conduct:
73
74### 1. Correction
75
76**Community Impact**: Use of inappropriate language or other behavior deemed
77unprofessional or unwelcome in the community.
78
79**Consequence**: A private, written warning from community leaders, providing
80clarity around the nature of the violation and an explanation of why the
81behavior was inappropriate. A public apology may be requested.
82
83### 2. Warning
84
85**Community Impact**: A violation through a single incident or series
86of actions.
87
88**Consequence**: A warning with consequences for continued behavior. No
89interaction with the people involved, including unsolicited interaction with
90those enforcing the Code of Conduct, for a specified period of time. This
91includes avoiding interactions in community spaces as well as external channels
92like social media. Violating these terms may lead to a temporary or
93permanent ban.
94
95### 3. Temporary Ban
96
97**Community Impact**: A serious violation of community standards, including
98sustained inappropriate behavior.
99
100**Consequence**: A temporary ban from any sort of interaction or public
101communication with the community for a specified period of time. No public or
102private interaction with the people involved, including unsolicited interaction
103with those enforcing the Code of Conduct, is allowed during this period.
104Violating these terms may lead to a permanent ban.
105
106### 4. Permanent Ban
107
108**Community Impact**: Demonstrating a pattern of violation of community
109standards, including sustained inappropriate behavior, harassment of an
110individual, or aggression toward or disparagement of classes of individuals.
111
112**Consequence**: A permanent ban from any sort of public interaction within
113the community.
114
115## Attribution
116
117This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118version 2.0, available at
119https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120
121Community Impact Guidelines were inspired by [Mozilla's code of conduct
122enforcement ladder](https://github.com/mozilla/diversity).
123
124[homepage]: https://www.contributor-covenant.org
125
126For answers to common questions about this code of conduct, see the FAQ at
127https://www.contributor-covenant.org/faq. Translations are available at
128https://www.contributor-covenant.org/translations.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/CONTRIBUTING.md b/users/ryan/modules/simple-bar/simple-bar-source/CONTRIBUTING.md
new file mode 100755
index 0000000..13ec1f9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/CONTRIBUTING.md
@@ -0,0 +1,47 @@
1# Contributor guidelines
2
3## What do I need to know to help?
4
5If you are looking to help to with a code contribution our project uses **React** in a mac os application names **Übersicht**. It is build on top of **yabai**. If you don't feel ready to make a code contribution yet, no problem! You can also check out the [documentation issues](https://github.com/Jean-Tinland/simple-bar/issues).
6
7If you are interested in making a code contribution and would like to learn more about the technologies that we use, check out the list below.
8
9- [React documentation](https://react.dev/learn)
10- [Übersicht documentation](https://github.com/felixhageloh/uebersicht#%C3%BCbersicht)
11- [yabai documentation](https://github.com/koekeishiya/yabai)
12
13## Coding style conventions
14
15Your PR should:
16
17- Be formatted with prettier
18- Pass the linter (run `yarn lint` to check)
19
20## How do I make a contribution?
21
22Never made an open source contribution before? Wondering how contributions work in the in our project? Here's a quick rundown!
23
241. Find an issue that you are interested in addressing or a feature that you would like to add.
252. Fork the repository associated with the issue to your local GitHub organization. This means that you will have a copy of the repository under `your-GitHub-username/simple-bar`.
263. Clone the repository to your local machine using `git clone https://github.com/Jean-Tinland/simple-bar.git`.
274. Create a new branch for your fix using `git checkout -b branch-name-here`.
285. Make the appropriate changes for the issue you are trying to address or the feature that you want to add.
296. Use `git add insert-paths-of-changed-files-here` to add the file contents of the changed files to the "snapshot" git uses to manage the state of the project, also known as the index.
307. Use `git commit -m "Insert a short message of the changes made here"` to store the contents of the index with a descriptive message.
318. Push the changes to the remote repository using `git push origin branch-name-here`.
329. Submit a pull request to the upstream repository.
3310. Title the pull request with a short description of the changes made and the issue or bug number associated with your change. For example, you can title an issue like so "Added more log outputting to resolve #4352".
3411. In the description of the pull request, explain the changes that you made, any issues you think exist with the pull request you made, and any questions you have for the maintainer. It's OK if your pull request is not perfect (no pull request is), the reviewer will be able to help you fix any problems and improve it!
3512. Wait for the pull request to be reviewed by a maintainer.
3613. Make changes to the pull request if the reviewing maintainer recommends them.
3714. Celebrate your success after your pull request is merged!
38
39## Where can I go for help?
40
41If you need help, you can ask questions on simple-bar's issue section on GitHub or with the contact form on [my website](https://www.jeantinland.com/en/contact/).
42
43## What does the Code of Conduct mean for me?
44
45Our Code of Conduct means that you are responsible for treating everyone on the project with respect and courtesy regardless of their identity. If you are the victim of any inappropriate behavior or comments as described in our Code of Conduct, we are here for you and will do the best to ensure that the abuser is reprimanded appropriately, per our code.
46
47> This contributor guide is adapted from the [opensource.com guide available here](https://opensource.com/life/16/3/contributor-guidelines-template-and-tips).
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/LICENSE b/users/ryan/modules/simple-bar/simple-bar-source/LICENSE
new file mode 100755
index 0000000..bb64387
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/LICENSE
@@ -0,0 +1,21 @@
1MIT License
2
3Copyright (c) 2020 Jean Tinland (https://www.jeantinland.com)
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/README.md b/users/ryan/modules/simple-bar/simple-bar-source/README.md
new file mode 100755
index 0000000..e3523b9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/README.md
@@ -0,0 +1,73 @@
1# <img src="./images/logo-simple-bar.png" width="200" alt="simple-bar" />
2
3A [yabai](https://github.com/koekeishiya/yabai) or [AeroSpace](https://github.com/nikitabobko/AeroSpace) status bar widget for [Übersicht](https://github.com/felixhageloh/uebersicht) inspired by [nibar](https://github.com/kkga/nibar), [yabar](https://github.com/AlexNaga/yabar) and [this reddit post](https://www.reddit.com/r/unixporn/comments/chwk89/yabai_yabai_and_gruvbox_with_custom_ubersicht_bar/).
4
5[Website](https://www.jeantinland.com/toolbox/simple-bar) • [Documentation](https://www.jeantinland.com/toolbox/simple-bar/documentation)
6
7[`simple-bar-server`](https://github.com/Jean-Tinland/simple-bar-server) is available to trigger refresh and toggle widgets more efficiently with `curl` commands.
8
9A more "lite" & basic version is available [here](https://github.com/Jean-Tinland/simple-bar-lite).
10
11**Notice: As I am working simultaneously on a lot of projects, things here may seem to move slowly but they are still in progress. I'm always monitoring my notifications and messages, so if you have any questions or want to chat about anything, feel free [to reach out](https://www.jeantinland.com/contact/)!**
12
13## Features
14
15Among the principal features of `simple-bar`, you'll find:
16
17- **Show all opened apps** in every space
18- **Show all opened windows** on the current space and its current layout mode (bsp, stack, float)
19- Interactions: **focus window** on click, launch scripts, toggle states
20- **Multi-monitor support**: enable individual widget on specific displays
21- Add your own custom widgets in settings (it displays scripts outputs)
22- **Refresh and toggle parts of simple-bar on the fly** with `curl` commands by installing [simple-bar-server](https://www.jeantinland.com/toolbox/simple-bar-server/documentation/introduction/) and enabling the server in settings. See [widgets](https://www.jeantinland.com/toolbox/simple-bar-server/documentation/widgets/), [yabai](https://www.jeantinland.com/toolbox/simple-bar-server/documentation/yabai/) or [AeroSpace](https://www.jeantinland.com/toolbox/simple-bar-server/documentation/aerospace/) options in its documentation
23- **Extensible** themes system with 3 theme behaviors: **dark**, **light**, or **system**
24- Numerous customization options, try them out in settings!
25- A handfull selection of widgets
26- Other features available only with SIP disabled and yabai scripting addition installed (**navigate to workspace**, **create new workspace on "+" click**, **move or destroy workspace on space hover**)
27
28[See all features in documentation](https://www.jeantinland.com/toolbox/simple-bar/documentation/features/).
29
30## Preview
31
32![image](./images/preview.png)
33
34<video src="https://github.com/Jean-Tinland/simple-bar/assets/43068795/0f988d1b-e21b-4b82-a1dc-4a1c76f580f3" type="video/mp4" muted autoplay loop></video>
35
36## Installation
37
38Simply clone this repo in your Übersicht widgets directory with the following command.
39
40```bash
41git clone --depth 1 https://github.com/Jean-Tinland/simple-bar $HOME/Library/Application\ Support/Übersicht/widgets/simple-bar
42```
43
44You'll find the full installation guide in the [documentation](https://www.jeantinland.com/toolbox/simple-bar/documentation/installation/).
45
46> [!WARNING]\
47> If you encounter this error: "simple-bar-index.jsx: Something went wrong…", it may be simply due to the fact that the default value for yabai or AeroSpace path is wrong in simple-bar. You can set this path in the settings module.\
48> The default paths are `$(which yabai)` and `$(which aerospace)`.
49
50> [!NOTE]\
51> `simple-bar` is trying to use yabai by default. If you want to switch to AeroSpace, you'll need to open the settings module (simply click on `simple-bar` then press `cmd` + `,`). You'll find the window manager choice in the "Global" tab.
52
53> [!TIP]\
54> If you experience some freezing issues with Übersicht or if you simply want to improve `simple-bar` responsiveness & energy consumption, please try to switch to `simple-bar-server` in order to trigger refresh with `curl` commands. You'll find more information about it in the repo [here](https://github.com/Jean-Tinland/simple-bar-server).
55
56## Roadmap
57
58Here are the features I'm planning to add in the future:
59
60- A timer widget ([#474](https://github.com/Jean-Tinland/simple-bar/issues/474))
61- Bars configurator (spawn multiple bars, place widgets anywhere…) [#380](https://github.com/Jean-Tinland/simple-bar/issues/380)
62- More accessibility settings like reading direction (LTR or RTL)
63- More default themes
64
65Feel free to open an issue if you have any feature request or if you want me to prioritize one of these features.
66
67## Special thanks
68
69I started this project with a simple idea and inspired by similar projects but over the year it has become a real community project. I want to thank everyone who contributed to this project, whether it's by opening issues, suggesting features, or even making pull requests. Furthermore, I also want to thank everyone who is using this project, I'm glad to see that it can be useful to others.
70
71So thank you, [@Amar1729](https://github.com/Amar1729), [@yorhodes](https://github.com/yorhodes), [@ZhongXiLu](https://github.com/ZhongXiLu), [@jamieweavis](https://github.com/jamieweavis), [@kvndrsslr](https://github.com/kvndrsslr), [@rosenpin](https://github.com/rosenpin), [@MikoMagni](https://github.com/MikoMagni), [@anujc4](https://github.com/anujc4), [@SijanC147](https://github.com/SijanC147), [@donaldguy](https://github.com/donaldguy), [@d-miketa](https://github.com/d-miketa), [@izifortune](https://github.com/izifortune), [@theshortcut](https://github.com/theshortcut), [@jming422](https://github.com/jming422), [@s00500](https://github.com/s00500), [@spwx](https://github.com/spwx), [@basbebe](https://github.com/basbebe), [@is0n](https://github.com/is0n), [@Joroovb](https://github.com/Joroovb), [@Sylenss](https://github.com/Sylenss), [@mrzone64](https://github.com/mrzone64), [@devinbhatt](https://github.com/devinbhatt), [@mdwitr0](https://github.com/mdwitr0), [@wr1159](https://github.com/wr1159), [@ardnep](https://github.com/ardnep), [@kntng](https://github.com/kntng) and every other that are helping me improve this little project by adding icons, fixing what they can, and more…
72
73I tried to keep track of everyone who contributed to this project in every page of the documentation. If you think I forgot you, please let me know. :)
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/SECURITY.md b/users/ryan/modules/simple-bar/simple-bar-source/SECURITY.md
new file mode 100755
index 0000000..1779c21
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/SECURITY.md
@@ -0,0 +1,9 @@
1# Security Policy
2
3## Supported Versions
4
5Only `simple-bar` latest version is supported (latest commit on master branch).
6
7## Reporting a Vulnerability
8
9If you think you have detected a vulnerability, please open a new issue in `simple-bar`'s repo, [here](https://github.com/Jean-Tinland/simple-bar/issues).
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/eslint.config.mjs b/users/ryan/modules/simple-bar/simple-bar-source/eslint.config.mjs
new file mode 100755
index 0000000..378720e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/eslint.config.mjs
@@ -0,0 +1,52 @@
1// eslint.config.js
2import js from "@eslint/js";
3import globals from "globals";
4import reactPlugin from "eslint-plugin-react";
5import reactHooks from "eslint-plugin-react-hooks";
6
7export default [
8 {
9 files: ["**/*.{js,jsx}"],
10 languageOptions: {
11 ecmaVersion: 12,
12 sourceType: "module",
13 globals: {
14 ...globals.browser,
15 },
16 parserOptions: {
17 ecmaFeatures: {
18 jsx: true,
19 },
20 },
21 },
22 plugins: {
23 react: reactPlugin,
24 "react-hooks": reactHooks,
25 },
26 rules: {
27 // Base ESLint recommended rules
28 ...js.configs.recommended.rules,
29
30 // React recommended rules
31 ...reactPlugin.configs.recommended.rules,
32
33 // React hooks recommended rules
34 ...reactHooks.configs.recommended.rules,
35
36 // Your custom rules
37 "no-console": "warn",
38 "react/prop-types": "off",
39 "react/react-in-jsx-scope": "off",
40 "react-hooks/rules-of-hooks": "error",
41 "react-hooks/exhaustive-deps": "warn",
42 "react-hooks/preserve-manual-memoization": "off",
43 "react-hooks/immutability": "off",
44 "react/no-unescaped-entities": "off",
45 },
46 settings: {
47 react: {
48 version: "18.0",
49 },
50 },
51 },
52];
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/images/logo-simple-bar.png b/users/ryan/modules/simple-bar/simple-bar-source/images/logo-simple-bar.png
new file mode 100755
index 0000000..4d1f5e4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/images/logo-simple-bar.png
Binary files differ
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/images/preview.png b/users/ryan/modules/simple-bar/simple-bar-source/images/preview.png
new file mode 100755
index 0000000..4c68dae
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/images/preview.png
Binary files differ
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/index.jsx b/users/ryan/modules/simple-bar/simple-bar-source/index.jsx
new file mode 100755
index 0000000..bc817ab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/index.jsx
@@ -0,0 +1,267 @@
1import * as Uebersicht from "uebersicht";
2import * as Error from "./lib/components/error.jsx";
3import SimpleBarContextProvider from "./lib/components/simple-bar-context.jsx";
4import UserWidgets from "./lib/components/data/user-widgets.jsx";
5// Each simple-bar widgets exports both a "Component" or "Widget" render function
6// and a "styles" string containing its own CSS
7import * as Variables from "./lib/styles/core/variables";
8import * as Base from "./lib/styles/core/base";
9import * as Spaces from "./lib/styles/components/spaces/spaces";
10import * as Process from "./lib/styles/components/process";
11import * as Zoom from "./lib/components/data/zoom.jsx";
12import * as Time from "./lib/components/data/time.jsx";
13import * as DateDisplay from "./lib/components/data/date-display.jsx";
14import * as GitHub from "./lib/components/data/github.jsx";
15import * as Weather from "./lib/components/data/weather.jsx";
16import * as Netstats from "./lib/components/data/netstats.jsx";
17import * as Cpu from "./lib/components/data/cpu.jsx";
18import * as Gpu from "./lib/components/data/gpu.jsx";
19import * as Memory from "./lib/components/data/memory.jsx";
20import * as Battery from "./lib/components/data/battery.jsx";
21import * as Sound from "./lib/components/data/sound.jsx";
22import * as Mic from "./lib/components/data/mic.jsx";
23import * as Wifi from "./lib/components/data/wifi.jsx";
24import * as ViscosityVPN from "./lib/components/data/viscosity-vpn.jsx";
25import * as Keyboard from "./lib/components/data/keyboard.jsx";
26import * as Spotify from "./lib/components/data/spotify.jsx";
27import * as YouTubeMusic from "./lib/components/data/youtube-music.jsx";
28import * as Crypto from "./lib/components/data/crypto.jsx";
29import * as Stock from "./lib/components/data/stock.jsx";
30import * as Music from "./lib/components/data/music.jsx";
31import * as Mpd from "./lib/components/data/mpd.jsx";
32import * as BrowserTrack from "./lib/components/data/browser-track.jsx";
33import * as Notifications from "./lib/components/data/notifications.jsx";
34import * as NextMeeting from "./lib/components/data/next-meeting.jsx";
35import * as Specter from "./lib/components/data/specter.jsx";
36import * as Graph from "./lib/components/data/graph.jsx";
37import * as DataWidgetLoader from "./lib/components/data/data-widget-loader.jsx";
38import * as DataWidget from "./lib/components/data/data-widget.jsx";
39import * as SideIcon from "./lib/components/side-icon.jsx";
40import * as Missives from "./lib/components/missives/missives.jsx";
41import * as Utils from "./lib/utils";
42import * as Settings from "./lib/settings";
43
44// Destructure React from Uebersicht in order to make eslint catch hook rules for example
45const { React } = Uebersicht;
46
47// Spaces & process components are lazy loaded to avoid loading them when not needed
48const YabaiContextProvider = React.lazy(
49 () => import("./lib/components/yabai-context.jsx"),
50);
51const AerospaceContextProvider = React.lazy(
52 () => import("./lib/components/aerospace-context.jsx"),
53);
54const YabaiSpaces = React.lazy(
55 () => import("./lib/components/yabai/spaces.jsx"),
56);
57const YabaiProcess = React.lazy(
58 () => import("./lib/components/yabai/process.jsx"),
59);
60const AerospaceSpaces = React.lazy(
61 () => import("./lib/components/aerospace/spaces.jsx"),
62);
63const AerospaceProcess = React.lazy(
64 () => import("./lib/components/aerospace/process.jsx"),
65);
66
67// Set refresh frequency to false
68// Übersicht auto-refresh system is not required as simple-bar works in sync with
69// yabai or AeroSpaces for spaces & process widgets and data widgets are refreshed with
70// their local refresh functions
71const refreshFrequency = false;
72
73// Init settings from file if existing
74Settings.init();
75
76// Get settings from the Settings module
77const settings = Settings.get();
78const {
79 // Do not edit the yabaiPath or aerospacePath lines, theses values are simply
80 // a default value used if nothing is defined in settings.
81 // You can setup your custom yabai or AeroSpace path in the settings module (Global tab) :
82 // while on an empty workspace, click on simple-bar then press cmd + , to open it.
83 yabaiPath = "/opt/homebrew/bin/yabai",
84 aerospacePath = "/opt/homebrew/bin/aerospace",
85 windowManager, // Window manager type (yabai or aerospace)
86 shell, // Shell to use for commands
87 enableServer, // Enable server mode
88 yabaiServerRefresh, // Refresh rate for yabai server
89} = settings.global;
90const { hideWindowTitle, displayOnlyIcon, displaySkhdMode } = settings.process;
91
92// Determine if signals should be disabled based on settings
93const disableSignals = enableServer && yabaiServerRefresh;
94const enableTitleChangedSignal = !hideWindowTitle && !displayOnlyIcon;
95
96// Construct command arguments based on window manager type
97const yabaiArgs = `${yabaiPath} ${displaySkhdMode} ${disableSignals} ${enableTitleChangedSignal}`;
98const aerospaceArgs = `${aerospacePath}`;
99const args = getArguments(windowManager, yabaiArgs, aerospaceArgs);
100const command = `${shell} simple-bar/lib/scripts/init-${windowManager}.sh ${args}`;
101
102// Inject global styles into the document
103// I prefer using native CSS instead of Emotion bundled by default in Übersicht
104Utils.injectStyles("simple-bar-index-styles", [
105 Variables.styles,
106 Base.styles,
107 Spaces.styles,
108 Process.styles,
109 Settings.styles,
110 DataWidget.styles,
111 DateDisplay.styles,
112 Zoom.styles,
113 Time.styles,
114 GitHub.styles,
115 Weather.styles,
116 Netstats.styles,
117 Cpu.styles,
118 Gpu.styles,
119 Memory.styles,
120 Crypto.styles,
121 Stock.styles,
122 Battery.styles,
123 Wifi.styles,
124 ViscosityVPN.styles,
125 Keyboard.styles,
126 Mic.styles,
127 Sound.styles,
128 Spotify.styles,
129 YouTubeMusic.styles,
130 Music.styles,
131 Mpd.styles,
132 BrowserTrack.styles,
133 Notifications.styles,
134 NextMeeting.styles,
135 Specter.styles,
136 Graph.styles,
137 DataWidgetLoader.styles,
138 settings.customStyles.styles,
139 SideIcon.styles,
140 Missives.styles,
141]);
142
143// Render function to display the bar
144function render({ output, error }) {
145 // Define base classes for the bar based on settings
146 const baseClasses = Utils.classNames("simple-bar", {
147 "simple-bar--floating": settings.global.floatingBar,
148 "simple-bar--no-bar-background": settings.global.noBarBg,
149 "simple-bar--no-color-in-data": settings.global.noColorInData,
150 "simple-bar--on-bottom": settings.global.bottomBar,
151 "simple-bar--inline-spaces-options": settings.global.inlineSpacesOptions,
152 "simple-bar--animations-disabled": settings.global.disableAnimations,
153 "simple-bar--spaces-background-color-as-foreground":
154 settings.global.spacesBackgroundColorAsForeground,
155 "simple-bar--widgets-background-color-as-foreground":
156 settings.global.widgetsBackgroundColorAsForeground,
157 "simple-bar--process-aligned-to-left": !settings.global.centered,
158 });
159
160 // Handle errors
161 if (error) {
162 // eslint-disable-next-line no-console
163 console.error("Error in index.jsx", error);
164 return <Error.Component type="error" classes={baseClasses} />;
165 }
166 if (!output) {
167 return <Error.Component type="noOutput" classes={baseClasses} />;
168 }
169
170 // Cleanup the output data
171 const cleanedUpOutput = Utils.cleanupOutput(output);
172
173 // Handle specific errors related to yabai or AeroSpace
174 const errors = ["yabaiError", "aerospaceError"];
175 if (errors.includes(cleanedUpOutput)) {
176 return <Error.Component type={cleanedUpOutput} classes={baseClasses} />;
177 }
178
179 // Parse the output data
180 const data = Utils.parseJson(cleanedUpOutput);
181 if (!data) return <Error.Component type="noData" classes={baseClasses} />;
182
183 const { displays, shadow, skhdMode, SIP, spaces, windows } = data;
184
185 // Check if SIP (System Integrity Protection) is disabled
186 const SIPDisabled = SIP !== "System Integrity Protection status: enabled.";
187
188 // Define additional classes based on data
189 const classes = Utils.classNames(baseClasses, {
190 "simple-bar--no-shadow": shadow !== "on",
191 });
192
193 // Handle bar focus ring on click
194 Utils.handleBarFocus();
195
196 // Render the bar with appropriate components and data
197 return (
198 <SimpleBarContextProvider
199 initialSettings={settings}
200 displays={displays}
201 SIPDisabled={SIPDisabled}
202 >
203 <div className={classes}>
204 <SideIcon.Component />
205 <React.Suspense fallback={<React.Fragment />}>
206 {windowManager === "yabai" && (
207 <YabaiContextProvider
208 spaces={spaces}
209 windows={windows}
210 skhdMode={skhdMode}
211 >
212 <YabaiSpaces />
213 <YabaiProcess />
214 </YabaiContextProvider>
215 )}
216 {windowManager === "aerospace" && (
217 <AerospaceContextProvider>
218 <AerospaceSpaces />
219 <AerospaceProcess />
220 </AerospaceContextProvider>
221 )}
222 </React.Suspense>
223 <Settings.Wrapper />
224 <div className="simple-bar__data">
225 <UserWidgets />
226 <Zoom.Widget />
227 <BrowserTrack.Widget />
228 <Spotify.Widget />
229 <YouTubeMusic.Widget />
230 <Crypto.Widget />
231 <Stock.Widget />
232 <Music.Widget />
233 <Mpd.Widget />
234 <GitHub.Widget />
235 <Weather.Widget />
236 <Netstats.Widget />
237 <Cpu.Widget />
238 <Gpu.Widget />
239 <Memory.Widget />
240 <Battery.Widget />
241 <Notifications.Widget />
242 <NextMeeting.Widget />
243 <Mic.Widget />
244 <Sound.Widget />
245 <ViscosityVPN.Widget />
246 <Wifi.Widget />
247 <Keyboard.Widget />
248 <DateDisplay.Widget />
249 <Time.Widget />
250 </div>
251 <Missives.Component />
252 </div>
253 </SimpleBarContextProvider>
254 );
255}
256
257export { command, refreshFrequency, render };
258
259function getArguments(windowManager, yabaiArgs, aerospaceArgs) {
260 if (windowManager === "yabai") {
261 return yabaiArgs;
262 }
263 if (windowManager === "aerospace") {
264 return aerospaceArgs;
265 }
266 return "";
267}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/aerospace.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/aerospace.js
new file mode 100755
index 0000000..5b403b1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/aerospace.js
@@ -0,0 +1,102 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "./settings";
3import * as Utils from "./utils";
4
5/**
6 * Switches to the specified workspace.
7 * @param {number} index - The index of the workspace to switch to.
8 */
9export async function goToSpace(index) {
10 const settings = Settings.get();
11 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
12 await Uebersicht.run(`${aerospacePath} workspace ${index}`);
13}
14
15/**
16 * Focuses the window with the specified ID.
17 * @param {number} id - The ID of the window to focus.
18 */
19export async function focusWindow(id) {
20 const settings = Settings.get();
21 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
22 await Uebersicht.run(`${aerospacePath} focus --window-id ${id}`);
23}
24
25/**
26 * Retrieves the list of workspaces for the specified display.
27 * @param {number} displayId - The ID of the display.
28 * @returns {Promise<Object[]>} The list of workspaces.
29 */
30export async function getSpaces(displayId) {
31 const settings = Settings.get();
32 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
33 const json = await Uebersicht.run(
34 `${aerospacePath} list-workspaces --monitor ${displayId} --json --format "%{workspace} %{monitor-appkit-nsscreen-screens-id}"`
35 );
36 return Utils.parseJson(json);
37}
38
39/**
40 * Retrieves the currently focused workspace.
41 * @returns {Promise<Object>} The focused workspace.
42 */
43export async function getFocusedSpace() {
44 const settings = Settings.get();
45 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
46 const json = await Uebersicht.run(
47 `${aerospacePath} list-workspaces --focused --json`
48 );
49 return Utils.parseJson(json);
50}
51
52/**
53 * Retrieves the list of windows for the specified workspace.
54 * @param {number} workspaceId - The ID of the workspace.
55 * @returns {Promise<Object[]>} The list of windows.
56 */
57export async function getWindows(workspaceId) {
58 const settings = Settings.get();
59 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
60 const json = await Uebersicht.run(
61 `${aerospacePath} list-windows --workspace ${workspaceId} --json`
62 );
63 const cleanedJson = json.replace(/\\\n/g, "").replace(/00000/g, "0");
64 return Utils.parseJson(cleanedJson);
65}
66
67/**
68 * Retrieves the currently focused window.
69 * @returns {Promise<Object>} The focused window.
70 */
71export async function getFocusedWindow() {
72 const settings = Settings.get();
73 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
74 const json = await Uebersicht.run(
75 `${aerospacePath} list-windows --focused --json`
76 );
77 return Utils.parseJson(json);
78}
79
80/**
81 * Retrieves the list of displays.
82 * @returns {Promise<Object[]>} The list of displays.
83 */
84export async function getDisplays() {
85 const settings = Settings.get();
86 const { aerospacePath = "/opt/homebrew/bin/aerospace" } = settings.global;
87 const json = await Uebersicht.run(`${aerospacePath} list-monitors --json`);
88 return Utils.parseJson(json);
89}
90
91/**
92 * Retrieves the custom display index for the specified display.
93 * @param {Object} display - The display object.
94 * @returns {number} The custom display index.
95 */
96export function getDisplayIndex(item) {
97 const settings = Settings.get();
98 const { customAeroSpaceDisplayIndexes } = settings.spacesDisplay;
99 const nativeId = item["monitor-appkit-nsscreen-screens-id"];
100 const customId = customAeroSpaceDisplayIndexes[nativeId];
101 return customId || nativeId;
102}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/app-icons.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/app-icons.js
new file mode 100755
index 0000000..3eef38d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/app-icons.js
@@ -0,0 +1,254 @@
1import * as Icons from "./components/icons/icons.jsx";
2
3// List of supported apps and their corresponding icons
4export const apps = {
5 "1Password 7": Icons.OnePassword,
6 "1Password": Icons.OnePassword,
7 "Acrobat Reader": Icons.PDF,
8 "Activity Monitor": Icons.Activity,
9 "Affinity Designer": Icons.AffinityDesigner,
10 "Affinity Photo": Icons.AffinityPhoto,
11 "Affinity Publisher": Icons.AffinityPublisher,
12 Airmail: Icons.Airmail,
13 Alacritty: Icons.Terminal,
14 Alfred: Icons.Alfred,
15 "Android Messages": Icons.AndroidMessages,
16 "Android Studio": Icons.AndroidStudio,
17 Anki: Icons.Anki,
18 Antigravity: Icons.Antigravity,
19 Anytype: Icons.Anytype,
20 "App Store": Icons.AppStore,
21 Arc: Icons.Arc,
22 Atom: Icons.Atom,
23 "Apple Simulator": Icons.AppleSimulator,
24 Audacity: Icons.Audacity,
25 Aqua: Icons.Aqua,
26 "Battle.net": Icons.BattleNet,
27 "Bambu Studio": Icons.BambuStudio,
28 Bear: Icons.Bear,
29 "Beekeeper Studio": Icons.Beekeeper,
30 Bitwarden: Icons.BitWarden,
31 Blender: Icons.Blender,
32 "Brave Browser": Icons.BraveBrowser,
33 Bruno: Icons.Bruno,
34 Claude: Icons.Claude,
35 ClaudeCode: Icons.ClaudeCode,
36 Cline: Icons.Cline,
37 CLion: Icons.CLion,
38 Calendar: Icons.Calendar,
39 Calibre: Icons.Book,
40 "Canary Mail": Icons.Mail,
41 Caprine: Icons.Caprine,
42 CARROT: Icons.CARROT,
43 ChatGPT: Icons.ChatGPT,
44 Chatterino: Icons.Chatterino,
45 Chromium: Icons.GoogleChrome,
46 "CleanMyMac X": Icons.Desktop,
47 ClickUp: Icons.ClickUp,
48 "Code - Insiders": Icons.Code,
49 Code: Icons.Code,
50 Codex: Icons.Codex,
51 "Color Picker": Icons.ColorPicker,
52 ComfyUI: Icons.ComfyUI,
53 Copilot: Icons.Copilot,
54 Cursor: Icons.Cursor,
55 DataGrip: Icons.DataGrip,
56 Deezer: Icons.Deezer,
57 Default: Icons.Default,
58 "DEVONthink 3": Icons.DEVONthink3,
59 "Discord Canary": Icons.Discord,
60 "Discord PTB": Icons.Discord,
61 Discord: Icons.Discord,
62 "Docker Desktop": Icons.Docker,
63 Drafts: Icons.Drafts,
64 Dropbox: Icons.Dropbox,
65 Element: Icons.Element,
66 Emacs: Icons.Emacs,
67 "Evernote Legacy": Icons.EvernoteLegacy,
68 FaceTime: Icons.FaceTime,
69 Fantastical: Icons.Calendar,
70 Figma: Icons.Figma,
71 "Figma Beta": Icons.Figma,
72 "Final Cut Pro": Icons.FinalCutPro,
73 "Find My": Icons.Radar,
74 Finder: Icons.Finder,
75 "Firefox Developer Edition": Icons.FirefoxDeveloperEdition,
76 "Firefox Nightly": Icons.FirefoxDeveloperEdition,
77 Firefox: Icons.Firefox,
78 Fleet: Icons.Fleet,
79 Folx: Icons.Folx,
80 FreeTube: Icons.FreeTube,
81 Ghostty: Icons.Ghostty,
82 "GitHub Desktop": Icons.GitHub,
83 Gnucash: Icons.GnuCash,
84 GoLand: Icons.GoLand,
85 GoodNotes: Icons.GoodNotes,
86 "Google Chrome Canary": Icons.GoogleChrome,
87 "Google Chrome": Icons.GoogleChrome,
88 Goose: Icons.Goose,
89 "Grammarly Editor": Icons.Grammarly,
90 GrandTotal: Icons.Dollar,
91 Helium: Icons.Helium,
92 HEY: Icons.Mail,
93 "Home Assistant": Icons.HomeAssistant,
94 HTTPie: Icons.HTTPie,
95 Hyper: Icons.Terminal,
96 Insomnia: Icons.Insomnia,
97 "IntelliJ IDEA": Icons.Idea,
98 Iris: Icons.Iris,
99 iTerm2: Icons.Terminal,
100 Joplin: Icons.Joplin,
101 Kakoune: Icons.Kakoune,
102 KeePassXC: Icons.KeePassXC,
103 "Keyboard Maestro": Icons.KeyboardMaestro,
104 Keynote: Icons.Keynote,
105 kitty: Icons.Terminal,
106 "League of Legends": Icons.LeagueOfLegends,
107 LibreWolf: Icons.LibreWolf,
108 Linear: Icons.Linear,
109 Live: Icons.Ableton,
110 "LM Studio": Icons.LMStudio,
111 MacVim: Icons.Vim,
112 Mail: Icons.Mail,
113 MailMate: Icons.Mail,
114 Mailspring: Icons.Mail,
115 "MAMP PRO": Icons.Mamp,
116 MAMP: Icons.Mamp,
117 Maestro: Icons.MaestroAI,
118 Manus: Icons.Manus,
119 Matlab: Icons.Matlab,
120 Mattermost: Icons.Mattermost,
121 Messages: Icons.Messages,
122 "Microsoft Edge": Icons.MicrosoftEdge,
123 "Microsoft Excel": Icons.MicrosoftExcel,
124 "Microsoft Outlook": Icons.MicrosoftOutlook,
125 "Microsoft PowerPoint": Icons.MicrosoftPowerPoint,
126 "Microsoft Teams": Icons.Teams,
127 "Microsoft To Do": Icons.Things,
128 "Microsoft Word": Icons.MicrosoftWord,
129 Mimestream: Icons.Mimestream,
130 Min: Icons.MinBrowser,
131 Miro: Icons.Miro,
132 "Monero GUI": Icons.MoneroGUI,
133 "MongoDB Compass": Icons.MongoDB,
134 MoneyMoney: Icons.Bank,
135 mpv: Icons.Mpv,
136 Music: Icons.Music,
137 n8n: Icons.N8n,
138 Neovide: Icons.Vim,
139 NetNewsWire: Icons.NetNewsWire,
140 Notability: Icons.Notability,
141 NotebookLM: Icons.NotebookLM,
142 Notes: Icons.Notes,
143 Notion: Icons.Notion,
144 Nova: Icons.Nova,
145 Numbers: Icons.Numbers,
146 "OBS Studio": Icons.OBSStudio,
147 OBS: Icons.OBSStudio,
148 Obsidian: Icons.Obsidian,
149 Ollama: Icons.Ollama,
150 OmniFocus: Icons.OmniFocus,
151 OpenClaw: Icons.OpenClaw,
152 opencode: Icons.Opencode,
153 OrbStack: Icons.OrbStack,
154 Pages: Icons.Pages,
155 "Parallels Desktop": Icons.Parallels,
156 Perplexity: Icons.Perplexity,
157 "Pi-hole Remote": Icons.Pihole,
158 Pine: Icons.Pine,
159 Pins: Icons.Pins,
160 Podcasts: Icons.Podcasts,
161 "PomoDone App": Icons.Pomodone,
162 Postman: Icons.Postman,
163 "Proton Mail": Icons.ProtonMail,
164 PyCharm: Icons.PyCharm,
165 Preview: Icons.PDF,
166 PHPStorm: Icons.PHPStorm,
167 Plex: Icons.Plex,
168 Quip: Icons.Quip,
169 qutebrowser: Icons.QuteBrowser,
170 Receipts: Icons.Dollar,
171 "Redis Insight": Icons.Redis,
172 Reeder: Icons.Reeder5,
173 Reminders: Icons.Reminders,
174 Remnote: Icons.Remnote,
175 "Remote Desktop": Icons.RemoteDesktop,
176 Replit: Icons.Replit,
177 Rider: Icons.Rider,
178 "Rocket.Chat": Icons.RocketChat,
179 Roon: Icons.Roon,
180 "Royal TSX": Icons.RoyalTSX,
181 RubyMine: Icons.RubyMine,
182 RustRover: Icons.RustRover,
183 "Safari Technology Preview": Icons.Safari,
184 Safari: Icons.Safari,
185 Screens4: Icons.Screens4,
186 "Sequel Ace": Icons.SequelAce,
187 "Sequel Pro": Icons.SequelPro,
188 Setapp: Icons.Setapp,
189 Signal: Icons.Signal,
190 sioyek: Icons.PDF,
191 Sketch: Icons.Sketch,
192 SketchUp: Icons.SketchUp,
193 Skim: Icons.PDF,
194 Skype: Icons.Skype,
195 Slack: Icons.Slack,
196 Spark: Icons.Spark,
197 Spotify: Icons.Spotify,
198 Spotlight: Icons.Spotlight,
199 spotube: Icons.Spotube,
200 Spotube: Icons.Spotube,
201 "Sublime Text": Icons.SublimeText,
202 "Super Productivity": Icons.SuperProductivity,
203 "System Preferences": Icons.Gear,
204 "System Settings": Icons.Gear,
205 TablePlus: Icons.TablePlus,
206 Tailscale: Icons.Tailscale,
207 "TeamSpeak 3": Icons.TeamSpeak,
208 Telegram: Icons.Telegram,
209 Terminal: Icons.Terminal,
210 Texts: Icons.Messages,
211 Things: Icons.Things,
212 Thunderbird: Icons.Thunderbird,
213 TickTick: Icons.TickTick,
214 TIDAL: Icons.Tidal,
215 Todoist: Icons.Todoist,
216 "Tor Browser": Icons.TorBrowser,
217 Tower: Icons.Tower,
218 Transmit: Icons.Transmit,
219 Trello: Icons.Trello,
220 Tweetbot: Icons.Twitter,
221 Twitter: Icons.Twitter,
222 Typora: Icons.Text,
223 Vim: Icons.Vim,
224 VimR: Icons.Vim,
225 Vivaldi: Icons.Vivaldi,
226 VLC: Icons.VLC,
227 "VMware Fusion": Icons.VMwareFusion,
228 VSCodium: Icons.VSCodium,
229 Warp: Icons.Warp,
230 WebStorm: Icons.WebStorm,
231 WezTerm: Icons.Terminal,
232 WhatsApp: Icons.WhatsApp,
233 "Windows App": Icons.Windows,
234 Xcode: Icons.Xcode,
235 "YouTube Music": Icons.YoutubeMusic,
236 zathura: Icons.PDF,
237 Zed: Icons.Zed,
238 Zen: Icons.ZenBrowser,
239 Zeplin: Icons.Zeplin,
240 "zoom.us": Icons.Zoom,
241 Zotero: Icons.Zotero,
242 Zulip: Icons.Zulip,
243
244 // German app names
245 Musik: Icons.Music,
246 Kalender: Icons.Calendar,
247 Nachrichten: Icons.Messages,
248
249 // Chinese app names
250 访达: Icons.Finder,
251 邮件: Icons.Mail,
252 微信: Icons.Wechat,
253 网易云音ä¹: Icons.NeteaseMusic,
254};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace-context.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace-context.jsx
new file mode 100755
index 0000000..f780a71
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace-context.jsx
@@ -0,0 +1,117 @@
1import * as Uebersicht from "uebersicht";
2import { useSimpleBarContext } from "./simple-bar-context.jsx";
3import useServerSocket from "../hooks/use-server-socket.js";
4import * as Aerospace from "../aerospace.js";
5
6const { React } = Uebersicht;
7
8// Create a context with default values
9const AerospaceContext = React.createContext({
10 spaces: [],
11 windows: [],
12 mode: "",
13});
14
15/**
16 * Custom hook to use the AerospaceContext
17 * @returns {Object} The context value
18 */
19export function useAerospaceContext() {
20 return React.useContext(AerospaceContext);
21}
22
23// Memoized AerospaceContextProvider component
24export default React.memo(AerospaceContextProvider);
25
26/**
27 * AerospaceContextProvider component
28 * @param {Object} props - The component props
29 * @param {React.ReactNode} props.children - The child components
30 * @returns {JSX.Element} The provider component
31 */
32function AerospaceContextProvider({ children }) {
33 // Get settings, displayIndex, and displays from SimpleBarContext
34 const { settings, displayIndex, displays } = useSimpleBarContext();
35 const { enableServer, aerospaceServerRefresh } = settings.global;
36 const serverEnabled = enableServer && aerospaceServerRefresh;
37
38 // State to store aerospace spaces
39 const [aerospaceSpaces, setAerospaceSpaces] = React.useState([]);
40 const latestRequestRef = React.useRef(0);
41
42 // Fetches and sets the aerospace spaces
43 const getSpaces = React.useCallback(async () => {
44 const requestId = latestRequestRef.current + 1;
45 latestRequestRef.current = requestId;
46
47 let focusedWindow = {};
48 const [focusedSpace] = await Aerospace.getFocusedSpace();
49 try {
50 [focusedWindow] = await Aerospace.getFocusedWindow();
51 // eslint-disable-next-line no-empty
52 } catch {}
53 const spaces = await Promise.all(
54 displays.map(async (display) => {
55 const id = display["monitor-id"];
56 const result = await Aerospace.getSpaces(id);
57 return Promise.all(
58 result.map(async (space) => {
59 const focused = space.workspace === focusedSpace.workspace;
60 const monitor = Aerospace.getDisplayIndex(space);
61 const windows = await Aerospace.getWindows(space.workspace);
62 const formatted = windows.map((window) => {
63 const focused =
64 window["window-id"] === focusedWindow["window-id"];
65 return {
66 ...window,
67 focused,
68 };
69 });
70 return { ...space, windows: formatted, focused, monitor };
71 })
72 );
73 })
74 );
75 if (requestId !== latestRequestRef.current) {
76 return;
77 }
78 setAerospaceSpaces(spaces.flat());
79 }, [displays]);
80
81 // Refreshes spaces with the data sent by simple-bar-server if it exists
82 // in order to speed up the process then refreshes everything in background
83 // else, simply refreshes everything
84 const refreshSpaces = React.useCallback(
85 async (data) => {
86 if (data) {
87 const { space } = data;
88 setAerospaceSpaces((current) => {
89 return current.map((s) => ({ ...s, focused: s.workspace === space }));
90 });
91 getSpaces();
92 } else {
93 await getSpaces();
94 }
95 },
96 [getSpaces]
97 );
98
99 // Resets the aerospace spaces state
100 const resetSpaces = () => {
101 setAerospaceSpaces([]);
102 };
103
104 // Use server socket to fetch and reset spaces
105 useServerSocket("spaces", serverEnabled, refreshSpaces, resetSpaces);
106
107 // Fetch spaces on component mount and when displayIndex changes
108 React.useEffect(() => {
109 refreshSpaces();
110 }, [refreshSpaces, displayIndex]);
111
112 return (
113 <AerospaceContext.Provider value={{ spaces: aerospaceSpaces }}>
114 {children}
115 </AerospaceContext.Provider>
116 );
117}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx
new file mode 100755
index 0000000..5b56966
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx
@@ -0,0 +1,33 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons.js";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import * as Utils from "../../utils.js";
5
6const { React } = Uebersicht;
7
8/**
9 * OpenedApps component to display icons of opened applications.
10 * @param {Object} props - The component props.
11 * @param {Array} props.apps - The list of opened applications.
12 * @returns {JSX.Element|null} The rendered component or null if no apps are opened.
13 */
14export default function OpenedApps({ apps }) {
15 if (!apps.length) return null;
16
17 return apps.map((app, i) => {
18 const { focused } = app;
19 const appName = Utils.normalizeAppName(app["app-name"]);
20 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
21
22 // Generate class names for the app icon
23 const classes = Utils.classNames("space__icon", {
24 "space__icon--focused": focused,
25 });
26
27 return (
28 <SuspenseIcon key={i}>
29 <Icon className={classes} />
30 </SuspenseIcon>
31 );
32 });
33}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx
new file mode 100755
index 0000000..0c461cc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx
@@ -0,0 +1,72 @@
1import * as Uebersicht from "uebersicht";
2import Window from "./window.jsx";
3import * as Utils from "../../utils";
4import { useAerospaceContext } from "../aerospace-context.jsx";
5import { useSimpleBarContext } from "../simple-bar-context.jsx";
6
7export { processStyles as styles } from "../../styles/components/process";
8
9const { React } = Uebersicht;
10
11/**
12 * Process component to display windows in the current space.
13 * @returns {JSX.Element|null} The rendered component or null if not visible.
14 */
15const Component = React.memo(() => {
16 // Get spaces from aerospace context
17 const { spaces } = useAerospaceContext();
18 // Get settings and display index from simple bar context
19 const { settings, displayIndex } = useSimpleBarContext();
20 const { spacesDisplay, process, widgets } = settings;
21 const { exclusionsAsRegex } = spacesDisplay;
22 const { processWidget } = widgets;
23 const { centered, showOnDisplay } = process;
24
25 // Determine if the component should be visible
26 const visible =
27 spaces?.length &&
28 processWidget &&
29 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay);
30
31 if (!visible) return null;
32
33 // Find the focused space on the current display
34 const { windows = [] } =
35 spaces.find((space) => space.focused && space.monitor === displayIndex) ||
36 {};
37
38 if (!windows.length) return null;
39
40 // Get exclusions for filtering windows
41 const exclusions = exclusionsAsRegex
42 ? spacesDisplay.exclusions
43 : spacesDisplay.exclusions.split(", ");
44
45 const titleExclusions = exclusionsAsRegex
46 ? spacesDisplay.titleExclusions
47 : spacesDisplay.titleExclusions.split(", ");
48
49 // Generate class names for the component
50 const classes = Utils.classNames("process", {
51 "process--centered": centered,
52 });
53
54 // Filter windows based on exclusions
55 const filteredWindows = windows.filter((window) =>
56 Utils.filterApps(window, exclusions, titleExclusions, exclusionsAsRegex),
57 );
58
59 return (
60 <div className={classes}>
61 <div className="process__container">
62 {filteredWindows.map((window, i) => (
63 <Window key={i} window={window} />
64 ))}
65 </div>
66 </div>
67 );
68});
69
70Component.displayName = "Process";
71
72export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx
new file mode 100755
index 0000000..ab91bbb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx
@@ -0,0 +1,84 @@
1import * as Uebersicht from "uebersicht";
2import OpenedApps from "./opened-apps.jsx";
3import { useSimpleBarContext } from "../simple-bar-context.jsx";
4import * as Utils from "../../utils.js";
5import * as Aerospace from "../../aerospace.js";
6
7const { React } = Uebersicht;
8
9/**
10 * Space component to display a single space.
11 * @param {Object} props - The component props.
12 * @param {Object} props.space - The space object.
13 * @param {boolean} props.lastOfSpace - Indicates if this is the last space of the monitor.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16export default function Space({ space, lastOfSpace }) {
17 const { windows } = space;
18 const { settings } = useSimpleBarContext();
19 const { spacesDisplay } = settings;
20 const {
21 displayAllSpacesOnAllScreens,
22 exclusionsAsRegex,
23 hideDuplicateAppsInSpaces,
24 } = spacesDisplay;
25 const { workspace, focused } = space;
26
27 /**
28 * Handle click event to switch to the clicked space.
29 * @param {Event} e - The click event.
30 */
31 const onClick = (e) => {
32 if (focused) return;
33 Aerospace.goToSpace(workspace);
34 Utils.clickEffect(e);
35 };
36
37 // Determine if the space should be hidden
38 const hidden = !focused && !windows.length && spacesDisplay.hideEmptySpaces;
39
40 if (hidden) return null;
41
42 // Get exclusions and title exclusions based on settings
43 const exclusions = exclusionsAsRegex
44 ? spacesDisplay.exclusions
45 : spacesDisplay.exclusions.split(", ");
46 const titleExclusions = exclusionsAsRegex
47 ? spacesDisplay.titleExclusions
48 : spacesDisplay.titleExclusions.split(", ");
49
50 // Filter windows based on exclusions
51 const filteredWindows = windows.filter((window) =>
52 Utils.filterApps(window, exclusions, titleExclusions, exclusionsAsRegex),
53 );
54
55 // Remove duplicate apps if the setting is enabled
56 const displayedWindows = hideDuplicateAppsInSpaces
57 ? filteredWindows.reduce((acc, window) => {
58 const isDuplicate = acc.find(
59 (w) => w["app-name"] === window["app-name"],
60 );
61 return isDuplicate ? acc : [...acc, window];
62 }, [])
63 : filteredWindows;
64
65 // Determine the CSS classes for the space
66 const classes = Utils.classNames("space", {
67 "space--focused": focused,
68 "space--empty": windows.length,
69 });
70
71 return (
72 <React.Fragment>
73 {displayAllSpacesOnAllScreens && lastOfSpace && (
74 <div className="spaces__separator" />
75 )}
76 <div className={classes}>
77 <button className="space__inner" onClick={onClick}>
78 {workspace}
79 <OpenedApps apps={displayedWindows} />
80 </button>
81 </div>
82 </React.Fragment>
83 );
84}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx
new file mode 100755
index 0000000..d576389
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx
@@ -0,0 +1,67 @@
1import * as Uebersicht from "uebersicht";
2import Space from "./space.jsx";
3import { useAerospaceContext } from "../aerospace-context.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils.js";
6import * as AeroSpace from "../../aerospace.js";
7
8export { spacesStyles as styles } from "../../styles/components/spaces/spaces.js";
9
10const { React } = Uebersicht;
11
12/**
13 * Spaces component to display spaces on the screen.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16const Component = React.memo(() => {
17 // Get spaces from aerospace context
18 const { spaces } = useAerospaceContext();
19 // Get displays, displayIndex, and settings from simple bar context
20 const { displays, displayIndex, settings } = useSimpleBarContext();
21 const { spacesDisplay, process } = settings;
22 const { displayAllSpacesOnAllScreens, showOnDisplay } = spacesDisplay;
23 // Determine if the component should be visible on the current display
24 const visible = Utils.isVisibleOnDisplay(displayIndex, showOnDisplay);
25 const isProcessVisible = Utils.isVisibleOnDisplay(
26 displayIndex,
27 process.showOnDisplay
28 );
29
30 // If not visible, return null
31 if (!visible) return null;
32
33 // If there are no spaces, return an empty div
34 if (!spaces?.length) {
35 return <div className="spaces spaces--empty" />;
36 }
37
38 // Map through displays and render spaces for the current display
39 return displays.map((display) => {
40 const displayId = AeroSpace.getDisplayIndex(display);
41 if (displayId !== displayIndex) return null;
42
43 // Filter spaces based on display settings
44 const filteredSpaces = displayAllSpacesOnAllScreens
45 ? spaces
46 : spaces.filter((space) => space.monitor === displayId);
47
48 return (
49 <div key={displayId} className="spaces">
50 {filteredSpaces.map((space, i) => {
51 const { workspace } = space;
52 const lastOfSpace =
53 i !== 0 && space.monitor !== spaces[i - 1].monitor;
54
55 return (
56 <Space key={workspace} space={space} lastOfSpace={lastOfSpace} />
57 );
58 })}
59 {isProcessVisible && <div className="spaces__end-separator" />}
60 </div>
61 );
62 });
63});
64
65Component.displayName = "Spaces";
66
67export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx
new file mode 100755
index 0000000..04b54d6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx
@@ -0,0 +1,99 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils";
6import * as Aerospace from "../../aerospace";
7
8const { React } = Uebersicht;
9
10/**
11 * Window component to display a window in the process bar.
12 * @param {Object} props - The component props.
13 * @param {Object} props.window - The window object.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16export default function Window({ window }) {
17 // Get settings from context
18 const { settings } = useSimpleBarContext();
19 // Create a ref for the button element
20 const ref = React.useRef();
21 // Destructure settings
22 const {
23 displayOnlyCurrent,
24 hideWindowTitle,
25 displayOnlyIcon,
26 expandAllProcesses,
27 } = settings.process;
28 // Destructure window properties
29 const {
30 focused,
31 "app-name": appName,
32 "window-title": title,
33 "window-id": id,
34 } = window;
35
36 // If displayOnlyCurrent is true and the window is not focused, return null
37 if (displayOnlyCurrent && !focused) {
38 return null;
39 }
40
41 // Get the icon for the app or use the default icon
42 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
43
44 /**
45 * Handle click event on the window button.
46 * @param {Event} e - The click event.
47 */
48 const onClick = (e) => {
49 !displayOnlyCurrent && Utils.clickEffect(e);
50 Aerospace.focusWindow(id);
51 };
52
53 /**
54 * Handle mouse enter event on the window button.
55 */
56 const onMouseEnter = () => {
57 Utils.startSliding(ref.current, ".process__inner", ".process__name");
58 };
59
60 /**
61 * Handle mouse leave event on the window button.
62 */
63 const onMouseLeave = () => {
64 Utils.stopSliding(ref.current, ".process__name");
65 };
66
67 // Generate class names based on settings and window state
68 const classes = Utils.classNames("process__window", {
69 "process__window--expanded": expandAllProcesses,
70 "process__window--focused": !displayOnlyCurrent && focused,
71 "process__window--only-current": displayOnlyCurrent,
72 "process__window--only-icon": displayOnlyIcon,
73 });
74
75 // Clean up the window title
76 const cleanedUpName =
77 appName !== title && title.length ? `${appName} / ${title}` : appName;
78 const processName = hideWindowTitle ? appName : cleanedUpName;
79
80 // Render the window button
81 return (
82 <button
83 ref={ref}
84 className={classes}
85 onClick={onClick}
86 onMouseEnter={displayOnlyIcon ? undefined : onMouseEnter}
87 onMouseLeave={displayOnlyIcon ? undefined : onMouseLeave}
88 >
89 <SuspenseIcon>
90 <Icon className="process__icon" />
91 </SuspenseIcon>
92 {!displayOnlyIcon && (
93 <span className="process__inner">
94 <span className="process__name">{processName}</span>
95 </span>
96 )}
97 </button>
98 );
99}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/battery.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/battery.jsx
new file mode 100755
index 0000000..1f08af6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/battery.jsx
@@ -0,0 +1,183 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils";
10
11export { batteryStyles as styles } from "../../styles/components/data/battery";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 10000;
16
17/**
18 * Battery widget component
19 * @returns {JSX.Element|null} The battery widget component
20 */
21export const Widget = React.memo(() => {
22 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
23 const { widgets, batteryWidgetOptions } = settings;
24 const { batteryWidget } = widgets;
25 const {
26 refreshFrequency,
27 toggleCaffeinateOnClick,
28 caffeinateOption,
29 disableCaffeinateInvertedBackground,
30 showOnDisplay,
31 showIcon,
32 } = batteryWidgetOptions;
33
34 // Determine if the widget should be visible based on display settings
35 const visible =
36 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && batteryWidget;
37
38 // Calculate the refresh frequency for the widget
39 const refresh = React.useMemo(
40 () =>
41 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
42 [refreshFrequency],
43 );
44
45 const [state, setState] = React.useState();
46 const [loading, setLoading] = React.useState(visible);
47
48 // Reset the widget state
49 const resetWidget = () => {
50 setState(undefined);
51 setLoading(false);
52 };
53
54 /**
55 * Fetch battery information and update the state
56 */
57 const getBattery = React.useCallback(async () => {
58 if (!visible) return;
59 // Fetch battery information and parse the results
60 const [system, percentage, status, caffeinate, lowPowerMode] =
61 await Promise.all([
62 Utils.getSystem(),
63 Utils.cachedRun(
64 `pmset -g batt | grep -Eo '[0-9]+%' | head -1 | tr -d '%'`,
65 refresh,
66 ),
67 Utils.cachedRun(
68 `pmset -g batt | head -1 | grep -q 'AC Power' && echo 'AC' || echo 'Batt'`,
69 refresh,
70 ),
71 Uebersicht.run(`pgrep caffeinate -d`),
72 Utils.cachedRun(
73 `pmset -g | awk '/lowpowermode|powermode/ {print $2; exit}'`,
74 refresh,
75 ),
76 ]);
77 setState({
78 system,
79 percentage: parseInt(percentage, 10),
80 charging: Utils.cleanupOutput(status) === "AC",
81 caffeinate: Utils.cleanupOutput(caffeinate),
82 lowPowerMode: Utils.cleanupOutput(lowPowerMode) === "1",
83 });
84 setLoading(false);
85 }, [visible, refresh]);
86
87 // Use server socket to fetch battery data
88 useServerSocket("battery", visible, getBattery, resetWidget, setLoading);
89 // Refresh the widget at the specified interval
90 useWidgetRefresh(visible, getBattery, refresh);
91
92 if (loading) return <DataWidgetLoader.Widget className="battery" />;
93 if (!state) return null;
94
95 const { system, percentage, charging, caffeinate, lowPowerMode } = state;
96 const isLowBattery = !charging && percentage < 20;
97
98 const classes = Utils.classNames("battery", {
99 "battery--low": isLowBattery,
100 "battery--low-power-mode": lowPowerMode,
101 "battery--caffeinate":
102 !disableCaffeinateInvertedBackground && caffeinate.length > 0,
103 });
104
105 const transformValue = getTransform(percentage);
106
107 /**
108 * Handle click event to toggle caffeinate mode
109 * @param {React.MouseEvent} e - The click event
110 */
111 const onClick = async (e) => {
112 Utils.clickEffect(e);
113 await toggleCaffeinate(system, caffeinate, caffeinateOption, pushMissive);
114 getBattery();
115 };
116
117 const onClickProp = toggleCaffeinateOnClick ? { onClick } : {};
118
119 const Icon = () => (
120 <div className="battery__icon">
121 <div className="battery__icon-inner">
122 <div
123 className="battery__icon-filler"
124 style={{ transform: transformValue }}
125 />
126 {charging && (
127 <SuspenseIcon>
128 <Icons.Charging className="battery__charging-icon" />
129 </SuspenseIcon>
130 )}
131 </div>
132 </div>
133 );
134
135 return (
136 <DataWidget.Widget
137 classes={classes}
138 Icon={showIcon ? Icon : null}
139 disableSlider
140 {...onClickProp}
141 >
142 {caffeinate.length > 0 && (
143 <SuspenseIcon>
144 <Icons.Coffee className="battery__caffeinate-icon" />
145 </SuspenseIcon>
146 )}
147 {percentage}%
148 </DataWidget.Widget>
149 );
150});
151
152Widget.displayName = "Battery";
153
154/**
155 * Get the transform value for the battery icon based on the percentage
156 * @param {number} value - The battery percentage
157 * @returns {string} The transform value
158 */
159function getTransform(value) {
160 let transform = `0.${value}`;
161 if (value === 100) transform = "1";
162 if (value < 10) transform = `0.0${value}`;
163 return `scaleX(${transform})`;
164}
165
166/**
167 * Toggle caffeinate mode on or off
168 * @param {string} system - The system architecture
169 * @param {string} caffeinate - The current caffeinate state
170 * @param {string} option - The caffeinate option
171 * @param {function} pushMissive - Function to push notifications
172 */
173async function toggleCaffeinate(system, caffeinate, option, pushMissive) {
174 const command =
175 system === "x86_64" ? "caffeinate" : "arch -arch arm64 caffeinate";
176 if (caffeinate.length === 0) {
177 Uebersicht.run(`${command} ${option} &`);
178 Utils.notification("Enabling caffeinate...", pushMissive);
179 } else {
180 await Uebersicht.run("pkill -f caffeinate");
181 Utils.notification("Disabling caffeinate...", pushMissive);
182 }
183}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/browser-track.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/browser-track.jsx
new file mode 100755
index 0000000..d320e4a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/browser-track.jsx
@@ -0,0 +1,147 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils";
10
11export { browserTrackStyles as styles } from "../../styles/components/data/browser-track";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 10000;
16
17/**
18 * BrowserTrack Widget component
19 * @returns {JSX.Element|null} The BrowserTrack widget
20 */
21export const Widget = React.memo(() => {
22 const { displayIndex, settings } = useSimpleBarContext();
23 const { widgets, browserTrackWidgetOptions } = settings;
24 const { browserTrackWidget } = widgets;
25 const { refreshFrequency, showSpecter, showOnDisplay, showIcon } =
26 browserTrackWidgetOptions;
27 const visible =
28 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && browserTrackWidget;
29
30 const refresh = React.useMemo(
31 () =>
32 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
33 [refreshFrequency],
34 );
35
36 const ref = React.useRef();
37
38 const [state, setState] = React.useState();
39 const [loading, setLoading] = React.useState(visible);
40
41 /**
42 * Resets the widget state
43 */
44 const resetWidget = () => {
45 setState(undefined);
46 setLoading(false);
47 };
48
49 /**
50 * Fetches the current browser track information
51 */
52 const getBrowserTrack = React.useCallback(async () => {
53 if (!visible) return;
54 const [firefoxStatus, firefoxDevStatus] = await Promise.all([
55 Utils.cachedRun(
56 `pgrep -xq 'Firefox' && echo "true" || echo "false"`,
57 refresh,
58 ),
59 Utils.cachedRun(
60 `pgrep -xq 'Firefox Developer Edition' && echo "true" || echo "false"`,
61 refresh,
62 ),
63 ]);
64 const isFirefoxDevRunning =
65 Utils.cleanupOutput(firefoxDevStatus) === "true";
66 const isFirefoxRunning = Utils.cleanupOutput(firefoxStatus) === "true";
67 const scriptNamePrefix = isFirefoxDevRunning
68 ? "firefox-dev"
69 : isFirefoxRunning
70 ? "firefox"
71 : "browser";
72
73 const [browserTrackOutput, spotifyStatus] = await Promise.all([
74 Utils.cachedRun(
75 `osascript ./simple-bar/lib/scripts/${scriptNamePrefix}-audio.applescript 2>&1`,
76 refresh,
77 ),
78 Utils.cachedRun(
79 `pgrep -fq '[S]potify Helper' && echo "true" || echo "false"`,
80 refresh,
81 ),
82 ]);
83 const browserTrack = JSON.parse(browserTrackOutput);
84 setState({
85 ...browserTrack,
86 isSpotifyRunning: Utils.cleanupOutput(spotifyStatus) === "true",
87 });
88 setLoading(false);
89 }, [visible, refresh]);
90
91 useServerSocket(
92 "browser-track",
93 visible,
94 getBrowserTrack,
95 resetWidget,
96 setLoading,
97 );
98 useWidgetRefresh(visible, getBrowserTrack, refresh);
99
100 if (loading) return <DataWidgetLoader.Widget className="browser-track" />;
101 if (!state) return null;
102 const { browser, title, isSpotifyRunning } = state;
103
104 if (!browser?.length || !title?.length || isSpotifyRunning) return null;
105
106 /**
107 * Icon component for displaying browser and playing icons
108 * @returns {JSX.Element} The icon component
109 */
110 const Icon = () => {
111 const BrowserIcon = getIcon(browser);
112 return (
113 <div className="browser-track__icons">
114 <SuspenseIcon>
115 <BrowserIcon />
116 <Icons.Playing />
117 </SuspenseIcon>
118 </div>
119 );
120 };
121
122 return (
123 <DataWidget.Widget
124 ref={ref}
125 classes="browser-track"
126 Icon={showIcon ? Icon : null}
127 showSpecter={showSpecter}
128 >
129 {title}
130 </DataWidget.Widget>
131 );
132});
133
134Widget.displayName = "BrowserTrack";
135
136/**
137 * Returns the appropriate icon component based on the browser name
138 * @param {string} browser - The name of the browser
139 * @returns {JSX.Element} The icon component for the browser
140 */
141function getIcon(browser) {
142 if (browser === "chrome") return Icons.GoogleChrome;
143 if (browser === "brave") return Icons.BraveBrowser;
144 if (browser === "safari") return Icons.Safari;
145 if (browser === "firefox") return Icons.Firefox;
146 return Icons.Default;
147}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/cpu.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/cpu.jsx
new file mode 100755
index 0000000..378b3c9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/cpu.jsx
@@ -0,0 +1,153 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import Graph from "./graph.jsx";
5import * as Icons from "../icons/icons.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils";
10
11export { cpuStyles as styles } from "../../styles/components/data/cpu";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 2000;
16const GRAPH_LENGTH = 50;
17
18/**
19 * CPU Widget component
20 * @returns {JSX.Element|null} The CPU widget
21 */
22export const Widget = React.memo(() => {
23 const { displayIndex, settings } = useSimpleBarContext();
24 const { widgets, cpuWidgetOptions } = settings;
25 const { cpuWidget } = widgets;
26 const {
27 refreshFrequency,
28 showOnDisplay,
29 displayAsGraph,
30 cpuMonitorApp,
31 showIcon,
32 cpuUsageThreshold,
33 } = cpuWidgetOptions;
34
35 // Determine if the widget should be visible based on display settings
36 const visible =
37 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && cpuWidget;
38
39 // Set the refresh frequency for the widget
40 const refresh = React.useMemo(
41 () =>
42 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
43 [refreshFrequency],
44 );
45
46 const [graph, setGraph] = React.useState([]);
47 const [state, setState] = React.useState();
48 const [loading, setLoading] = React.useState(visible);
49
50 /**
51 * Reset the widget state
52 */
53 const resetWidget = () => {
54 setState(undefined);
55 setLoading(false);
56 setGraph([]);
57 };
58
59 /**
60 * Fetch CPU usage data
61 */
62 const getCpu = React.useCallback(async () => {
63 if (!visible) return;
64 try {
65 const usage = await Utils.cachedRun(
66 `top -l 2 | awk '/CPU usage/ && NR > 10 {gsub(/%/, "", $7); print int(100 - $7); exit}'`,
67 refresh,
68 );
69 const formattedUsage = { usage: parseInt(usage, 10) };
70 setState(formattedUsage);
71 if (displayAsGraph) {
72 Utils.addToGraphHistory(formattedUsage, setGraph, GRAPH_LENGTH);
73 }
74 setLoading(false);
75 } catch {
76 setTimeout(getCpu, 1000);
77 }
78 }, [displayAsGraph, setGraph, visible, refresh]);
79
80 // Use server socket to fetch CPU data
81 useServerSocket("cpu", visible, getCpu, resetWidget, setLoading);
82 // Refresh the widget at the specified interval
83 useWidgetRefresh(visible, getCpu, refresh);
84
85 if (loading) return <DataWidgetLoader.Widget className="cpu" />;
86 if (!state) return null;
87
88 const { usage } = state;
89 const threshold = Number(cpuUsageThreshold) || 0;
90 const usageValue = Number(usage) || 0;
91
92 if (threshold > 0 && usageValue < threshold) return null;
93
94 // Handle click event to open CPU monitor app
95 const onClick =
96 cpuMonitorApp === "None"
97 ? undefined
98 : (e) => {
99 Utils.clickEffect(e);
100 openCpuUsageApp(cpuMonitorApp);
101 };
102
103 if (displayAsGraph) {
104 return (
105 <DataWidget.Widget
106 classes="cpu cpu--graph"
107 onClick={onClick}
108 disableSlider
109 >
110 <Graph
111 className="cpu__graph"
112 caption={{
113 usage: {
114 value: `${usage}%`,
115 icon: showIcon ? Icons.CPU : null,
116 color: "var(--yellow)",
117 },
118 }}
119 values={graph}
120 maxLength={GRAPH_LENGTH}
121 maxValue={100}
122 />
123 </DataWidget.Widget>
124 );
125 }
126
127 return (
128 <DataWidget.Widget
129 classes="cpu"
130 Icon={showIcon ? Icons.CPU : null}
131 onClick={onClick}
132 >
133 <span className="cpu__usage">{usage}%</span>
134 </DataWidget.Widget>
135 );
136});
137
138Widget.displayName = "Cpu";
139
140/**
141 * Open the specified CPU usage monitoring application
142 * @param {string} app - The name of the application to open
143 */
144function openCpuUsageApp(app) {
145 switch (app) {
146 case "Activity Monitor":
147 Uebersicht.run(`open -a "Activity Monitor"`);
148 break;
149 case "Top":
150 Utils.runInUserTerminal("top");
151 break;
152 }
153}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx
new file mode 100755
index 0000000..3faf4ea
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/crypto.jsx
@@ -0,0 +1,160 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { cryptoStyles as styles } from "../../styles/components/data/crypto";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 5 * 60 * 1000; // Default refresh frequency set to 5 minutes
15
16/**
17 * Crypto Widget Component
18 * @returns {JSX.Element|null} The Crypto Widget component
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
22 const { widgets, cryptoWidgetOptions } = settings;
23 const { cryptoWidget } = widgets;
24 const {
25 refreshFrequency,
26 denomination,
27 identifiers,
28 precision,
29 showOnDisplay,
30 showIcon,
31 } = cryptoWidgetOptions;
32
33 // Calculate the refresh frequency using the provided or default value
34 const refresh = React.useMemo(
35 () =>
36 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
37 [refreshFrequency],
38 );
39
40 // Determine if the widget should be visible on the current display
41 const visible =
42 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && cryptoWidget;
43
44 const ref = React.useRef();
45 const denominatorToken = getDenominatorToken(denomination);
46
47 // Memoize cleanedUpIdentifiers to prevent recreation on every render
48 const cleanedUpIdentifiers = React.useMemo(
49 () => identifiers.replace(/ /g, ""),
50 [identifiers],
51 );
52
53 // Memoize enumeratedIdentifiers to prevent recreation on every render
54 const enumeratedIdentifiers = React.useMemo(
55 () => cleanedUpIdentifiers.replace(/ /g, "").split(","),
56 [cleanedUpIdentifiers],
57 );
58
59 const [state, setState] = React.useState();
60 const [loading, setLoading] = React.useState(visible);
61
62 // Reset the widget state
63 const resetWidget = () => {
64 setState(undefined);
65 setLoading(false);
66 };
67
68 /**
69 * Fetches cryptocurrency prices from the CoinGecko API
70 */
71 const getCrypto = React.useCallback(async () => {
72 if (!visible) return;
73 const response = await fetch(
74 `https://api.coingecko.com/api/v3/simple/price?ids=${cleanedUpIdentifiers}&vs_currencies=${denomination}`,
75 );
76 const result = await response.json();
77
78 const prices = enumeratedIdentifiers.map((id) => {
79 const value = parseFloat(result[id][denomination]).toFixed(precision);
80 return `${denominatorToken}${value}`;
81 });
82 setState(prices);
83 setLoading(false);
84 }, [
85 visible,
86 cleanedUpIdentifiers,
87 denomination,
88 enumeratedIdentifiers,
89 precision,
90 denominatorToken,
91 ]);
92
93 useServerSocket("crypto", visible, getCrypto, resetWidget, setLoading);
94 useWidgetRefresh(visible, getCrypto, refresh);
95
96 /**
97 * Refreshes the cryptocurrency prices
98 * @param {Event} e - The event object
99 */
100 const refreshCrypto = (e) => {
101 Utils.clickEffect(e);
102 setLoading(true);
103 getCrypto();
104 Utils.notification("Refreshing price from coingecko.com...", pushMissive);
105 };
106
107 if (loading) return <DataWidgetLoader.Widget className="crypto" />;
108 if (!state) return null;
109
110 const classes = Utils.classNames("crypto");
111
112 return enumeratedIdentifiers.map((id, i) => (
113 <DataWidget.Widget
114 key={id}
115 classes={classes}
116 ref={ref}
117 Icon={showIcon ? getIcon(id) : null}
118 href={`https://coingecko.com/en/coins/${id}`}
119 onClick={(e) => openCrypto(e, pushMissive)}
120 onRightClick={refreshCrypto}
121 >
122 {state[i]}
123 </DataWidget.Widget>
124 ));
125});
126
127Widget.displayName = "Crypto";
128
129/**
130 * Returns the icon component for a given cryptocurrency identifier
131 * @param {string} identifier - The cryptocurrency identifier
132 * @returns {JSX.Element} The icon component
133 */
134function getIcon(identifier) {
135 if (identifier === "celo") return Icons.Celo;
136 if (identifier === "ethereum") return Icons.Ethereum;
137 if (identifier === "bitcoin") return Icons.Bitcoin;
138 return Icons.Moon;
139}
140
141/**
142 * Returns the symbol for a given denomination
143 * @param {string} denomination - The denomination (e.g., "usd", "eur")
144 * @returns {string} The symbol for the denomination
145 */
146function getDenominatorToken(denomination) {
147 if (denomination === "usd") return "$";
148 if (denomination === "eur") return "€";
149 return "";
150}
151
152/**
153 * Opens the cryptocurrency price chart
154 * @param {Event} e - The event object
155 * @param {Function} pushMissive - The function to push a notification
156 */
157function openCrypto(e, pushMissive) {
158 Utils.clickEffect(e);
159 Utils.notification("Opening price chart from coingecko.com...", pushMissive);
160}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget-loader.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget-loader.jsx
new file mode 100755
index 0000000..4115024
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget-loader.jsx
@@ -0,0 +1,37 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils";
3
4export { dataWidgetLoaderStyles as styles } from "../../styles/components/data/data-widget-loader";
5
6const { React } = Uebersicht;
7
8/**
9 * A memoized React component that renders a data widget loader.
10 *
11 * @param {Object} props - The properties object.
12 * @param {number} [props.width=14] - The width of the loader.
13 * @param {number} [props.height=14] - The height of the loader.
14 * @param {string} [props.className] - Additional class names for the loader.
15 * @param {Object} [props.style] - Additional styles for the loader.
16 * @returns {JSX.Element} The rendered data widget loader component.
17 */
18export const Widget = React.memo(
19 ({ width = 14, height = 14, className, style }) => {
20 // Generate class names using the Utils.classNames function
21 const classes = Utils.classNames("data-widget-loader", "data-widget", {
22 [className]: className,
23 });
24
25 // Return the JSX for the data widget loader
26 return (
27 <div className={classes} style={style}>
28 <div
29 className="data-widget-loader__inner"
30 style={{ width, height, flex: `0 0 ${width || height}px` }}
31 />
32 </div>
33 );
34 },
35);
36
37Widget.displayName = "DataWidgetLoader";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget.jsx
new file mode 100755
index 0000000..f5555a1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/data-widget.jsx
@@ -0,0 +1,136 @@
1import * as Uebersicht from "uebersicht";
2import * as Specter from "./specter.jsx";
3import * as Utils from "../../utils";
4import { SuspenseIcon } from "../icons/icon.jsx";
5export { dataWidgetStyles as styles } from "../../styles/components/data/data-widget";
6
7const { React } = Uebersicht;
8
9/**
10 * Widget component that renders a clickable data widget with optional icon and specter.
11 * @param {Object} props - The properties object.
12 * @param {React.Component} props.Icon - The icon component to display.
13 * @param {string} props.classes - Additional classes for the widget.
14 * @param {string} props.href - The URL to link to.
15 * @param {function} props.onClick - The click event handler.
16 * @param {function} props.onRightClick - The right-click event handler.
17 * @param {function} props.onMiddleClick - The middle-click event handler.
18 * @param {Object} props.style - The style object.
19 * @param {boolean} props.disableSlider - Flag to disable the slider effect.
20 * @param {boolean} props.showSpecter - Flag to show the specter widget.
21 * @param {boolean} props.useDivForClick - Render a div for click handling instead of a button.
22 * @param {React.ReactNode} props.children - The child elements to render inside the widget.
23 * @returns {React.ReactElement} The rendered widget component.
24 */
25export function Widget({
26 Icon,
27 classes,
28 href,
29 onClick,
30 onRightClick,
31 onMiddleClick,
32 style,
33 disableSlider,
34 showSpecter,
35 useDivForClick,
36 children,
37}) {
38 const ref = React.useRef();
39
40 let Tag = "div";
41 if (href) Tag = "a";
42 if (onClick && !href && !useDivForClick) Tag = "button";
43
44 const renderDivButton = Tag === "div" && Boolean(onClick);
45
46 const dataWidgetClasses = Utils.classNames("data-widget", classes, {
47 "data-widget--clickable": href || onClick,
48 });
49
50 /**
51 * Handles the click event, determining the appropriate action based on the event.
52 * @param {MouseEvent} e - The mouse event.
53 */
54 const onClickProp = (e) => {
55 const { metaKey } = e;
56 const action = metaKey || isMiddleClick(e) ? onMiddleClick : onClick;
57 if (action) action(e);
58 };
59
60 /**
61 * Handles the mouse enter event to start the sliding effect.
62 */
63 const onMouseEnter = () => {
64 Utils.startSliding(
65 ref.current,
66 ".data-widget__inner",
67 ".data-widget__slider",
68 );
69 };
70
71 /**
72 * Handles the mouse leave event to stop the sliding effect.
73 */
74 const onMouseLeave = () => {
75 Utils.stopSliding(ref.current, ".data-widget__slider");
76 };
77
78 /**
79 * Handles keyboard interaction for div-based clickable widgets.
80 * @param {KeyboardEvent} e - The keyboard event.
81 */
82 const onKeyDown = (e) => {
83 if (e.key !== "Enter" && e.key !== " ") return;
84 e.preventDefault();
85 onClickProp(e);
86 };
87
88 return (
89 <Tag
90 ref={ref}
91 className={dataWidgetClasses}
92 href={href}
93 onClick={onClickProp}
94 role={renderDivButton ? "button" : undefined}
95 tabIndex={renderDivButton ? 0 : undefined}
96 onKeyDown={renderDivButton ? onKeyDown : undefined}
97 onContextMenu={onRightClick || undefined}
98 onMouseEnter={!disableSlider ? onMouseEnter : undefined}
99 onMouseLeave={!disableSlider ? onMouseLeave : undefined}
100 style={style}
101 >
102 {Icon && (
103 <SuspenseIcon>
104 <Icon />
105 </SuspenseIcon>
106 )}
107 {showSpecter && <Specter.Widget />}
108 <Inner disableSlider={disableSlider}>{children}</Inner>
109 </Tag>
110 );
111}
112
113/**
114 * Inner component that optionally wraps children with sliding effect elements.
115 * @param {Object} props - The properties object.
116 * @param {boolean} props.disableSlider - Flag to disable the slider effect.
117 * @param {React.ReactNode} props.children - The child elements to render inside the inner component.
118 * @returns {React.ReactElement} The rendered inner component.
119 */
120function Inner({ disableSlider, children }) {
121 if (disableSlider) return children;
122 return (
123 <div className="data-widget__inner">
124 <div className="data-widget__slider">{children}</div>
125 </div>
126 );
127}
128
129/**
130 * Checks if the event is a middle-click.
131 * @param {MouseEvent} e - The mouse event.
132 * @returns {boolean} True if the event is a middle-click, false otherwise.
133 */
134function isMiddleClick(e) {
135 return e.button === 1 || e["button&2"] === 1;
136}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/date-display.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/date-display.jsx
new file mode 100755
index 0000000..af4c058
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/date-display.jsx
@@ -0,0 +1,118 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import * as Utils from "../../utils";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9
10export { dateStyles as styles } from "../../styles/components/data/date-display";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 30000;
15
16/**
17 * Date display widget component.
18 * @returns {JSX.Element} The date display widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const { widgets, dateWidgetOptions } = settings;
23 const { dateWidget } = widgets;
24 const {
25 refreshFrequency,
26 shortDateFormat,
27 locale,
28 calendarApp,
29 showOnDisplay,
30 showIcon,
31 } = dateWidgetOptions;
32
33 // Determine if the widget should be visible based on display settings
34 const visible =
35 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && dateWidget;
36
37 // Calculate the refresh frequency for the widget
38 const refresh = React.useMemo(
39 () =>
40 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
41 [refreshFrequency],
42 );
43
44 const [state, setState] = React.useState();
45 const [loading, setLoading] = React.useState(visible);
46
47 const formatOptions = shortDateFormat ? "short" : "long";
48
49 // Memoize the date format options
50 const options = React.useMemo(
51 () => ({
52 weekday: formatOptions,
53 month: formatOptions,
54 day: "numeric",
55 }),
56 [formatOptions],
57 );
58
59 // Ensure locale is valid, default to "en-UK" if not
60 const _locale = locale.length > 4 ? locale : "en-UK";
61
62 /**
63 * Reset the widget state.
64 */
65 const resetWidget = () => {
66 setState(undefined);
67 setLoading(false);
68 };
69
70 /**
71 * Get the current date and update the state.
72 */
73 const getDate = React.useCallback(() => {
74 if (!visible) return;
75 const now = new Date().toLocaleDateString(_locale, options);
76 setState({ now });
77 setLoading(false);
78 }, [_locale, options, visible]);
79
80 // Use server socket to get date updates
81 useServerSocket("date-display", visible, getDate, resetWidget, setLoading);
82 // Refresh the widget at the specified interval
83 useWidgetRefresh(visible, getDate, refresh);
84
85 if (loading) return <DataWidgetLoader.Widget className="date-display" />;
86 if (!state) return null;
87 const { now } = state;
88
89 /**
90 * Handle click event to open the calendar application.
91 * @param {Event} e - The click event.
92 */
93 const onClick = (e) => {
94 Utils.clickEffect(e);
95 openCalendarApp(calendarApp);
96 };
97
98 return (
99 <DataWidget.Widget
100 classes="date-display"
101 Icon={showIcon ? Icons.Date : null}
102 onClick={onClick}
103 >
104 {now}
105 </DataWidget.Widget>
106 );
107});
108
109Widget.displayName = "DateDisplay";
110
111/**
112 * Open the specified calendar application.
113 * @param {string} calendarApp - The name of the calendar application to open.
114 */
115function openCalendarApp(calendarApp) {
116 const appName = calendarApp || "Calendar";
117 Uebersicht.run(`open -a "${appName}"`);
118}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/github.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/github.jsx
new file mode 100755
index 0000000..89308b5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/github.jsx
@@ -0,0 +1,105 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh.js";
6import useServerSocket from "../../hooks/use-server-socket.js";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils.js";
9
10export { githubStyles as styles } from "../../styles/components/data/github.js";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 1000 * 60 * 10;
15
16/**
17 * GitHub notification widget component
18 * @returns {JSX.Element|null} The GitHub notification widget component
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const { widgets, githubWidgetOptions } = settings;
23 const { githubWidget } = widgets;
24 const {
25 refreshFrequency,
26 showOnDisplay,
27 hideWhenNoNotification,
28 notificationUrl,
29 ghBinaryPath,
30 showIcon,
31 } = githubWidgetOptions;
32
33 const isDisabled = React.useRef(false);
34
35 // Calculate the refresh frequency for the widget
36 const refresh = React.useMemo(
37 () =>
38 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
39 [refreshFrequency],
40 );
41
42 // Determine if the widget should be visible
43 const visible =
44 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && githubWidget;
45
46 const [state, setState] = React.useState();
47 const [loading, setLoading] = React.useState(visible);
48
49 /**
50 * Reset the widget state
51 */
52 const resetWidget = () => {
53 setState(undefined);
54 setLoading(false);
55 };
56
57 /**
58 * Fetch GPU data and update the widget state
59 */
60 const getGitHub = React.useCallback(async () => {
61 if (!visible) return;
62 setLoading(true);
63 const result = await Utils.cachedRun(
64 `${ghBinaryPath} api notifications`,
65 refresh,
66 );
67 if (!visible || isDisabled.current) {
68 return setLoading(false);
69 }
70 const json = JSON.parse(result);
71 const count = json.length;
72 setState({ count: count > 99 ? "99+" : count });
73 setLoading(false);
74 }, [ghBinaryPath, visible, refresh]);
75
76 // Update the disabled state based on visibility
77 React.useEffect(() => {
78 isDisabled.current = !visible;
79 }, [visible]);
80
81 // Use server socket to fetch GPU data
82 useServerSocket("github", visible, getGitHub, resetWidget, setLoading);
83 // Use widget refresh hook to periodically refresh the widget
84 useWidgetRefresh(visible, getGitHub, refresh);
85
86 if (loading) return <DataWidgetLoader.Widget className="github" />;
87 if (!state) return null;
88
89 const { count } = state;
90
91 if (hideWhenNoNotification && count === 0) return null;
92
93 return (
94 <DataWidget.Widget
95 classes="github"
96 href={notificationUrl}
97 Icon={showIcon ? Icons.GitHub : null}
98 onRightClick={getGitHub}
99 >
100 <span className="github__count">{count}</span>
101 </DataWidget.Widget>
102 );
103});
104
105Widget.displayName = "GitHub";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/gpu.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/gpu.jsx
new file mode 100755
index 0000000..6ac1dab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/gpu.jsx
@@ -0,0 +1,128 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import Graph from "./graph.jsx";
5import * as Icons from "../icons/icons.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh.js";
7import useServerSocket from "../../hooks/use-server-socket.js";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils.js";
10
11export { gpuStyles as styles } from "../../styles/components/data/gpu.js";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 2000;
16const GRAPH_LENGTH = 40;
17
18/**
19 * GPU Widget component
20 * @returns {JSX.Element|null} The GPU widget component
21 */
22export const Widget = React.memo(() => {
23 const { displayIndex, settings } = useSimpleBarContext();
24 const { widgets, gpuWidgetOptions } = settings;
25 const { gpuWidget } = widgets;
26 const {
27 refreshFrequency,
28 showOnDisplay,
29 displayAsGraph,
30 gpuMacmonBinaryPath,
31 showIcon,
32 } = gpuWidgetOptions;
33
34 const isDisabled = React.useRef(false);
35
36 // Calculate the refresh frequency for the widget
37 const refresh = React.useMemo(
38 () =>
39 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
40 [refreshFrequency],
41 );
42
43 // Determine if the widget should be visible
44 const visible =
45 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && gpuWidget;
46
47 const [graph, setGraph] = React.useState([]);
48 const [state, setState] = React.useState();
49 const [loading, setLoading] = React.useState(visible);
50
51 /**
52 * Reset the widget state
53 */
54 const resetWidget = () => {
55 setState(undefined);
56 setLoading(false);
57 setGraph([]);
58 };
59
60 /**
61 * Fetch GPU data and update the widget state
62 */
63 const getGpu = React.useCallback(async () => {
64 if (!visible) return;
65 try {
66 const result = await Utils.cachedRun(
67 `${gpuMacmonBinaryPath} pipe -s 1`,
68 refresh,
69 );
70 if (!visible || isDisabled.current) {
71 return;
72 }
73 const json = JSON.parse(result);
74 const { gpu_usage } = json;
75 const formattedUsage = { usage: Math.round(gpu_usage[1] * 100) };
76 setState(formattedUsage);
77 if (displayAsGraph) {
78 Utils.addToGraphHistory(formattedUsage, setGraph, GRAPH_LENGTH);
79 }
80 setLoading(false);
81 } catch {
82 setTimeout(getGpu, 1000);
83 }
84 }, [displayAsGraph, gpuMacmonBinaryPath, visible, refresh]);
85
86 // Update the disabled state based on visibility
87 React.useEffect(() => {
88 isDisabled.current = !visible;
89 }, [visible]);
90
91 // Use server socket to fetch GPU data
92 useServerSocket("gpu", visible, getGpu, resetWidget, setLoading);
93 // Use widget refresh hook to periodically refresh the widget
94 useWidgetRefresh(visible, getGpu, refresh);
95
96 if (loading) return <DataWidgetLoader.Widget className="cpu" />;
97 if (!state) return null;
98
99 const { usage } = state;
100
101 if (displayAsGraph) {
102 return (
103 <DataWidget.Widget classes="gpu gpu--graph" disableSlider>
104 <Graph
105 className="gpu__graph"
106 caption={{
107 usage: {
108 value: `${usage}%`,
109 icon: showIcon ? Icons.CPU : null,
110 color: "var(--cyan)",
111 },
112 }}
113 values={graph}
114 maxLength={GRAPH_LENGTH}
115 maxValue={100}
116 />
117 </DataWidget.Widget>
118 );
119 }
120
121 return (
122 <DataWidget.Widget classes="cpu" Icon={showIcon ? Icons.CPU : null}>
123 <span className="cpu__usage">{usage}%</span>
124 </DataWidget.Widget>
125 );
126});
127
128Widget.displayName = "Gpu";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/graph.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/graph.jsx
new file mode 100755
index 0000000..008e68e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/graph.jsx
@@ -0,0 +1,87 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils.js";
3import { SuspenseIcon } from "../icons/icon.jsx";
4
5const { React } = Uebersicht;
6
7export { graphStyles as styles } from "../../styles/components/data/graph";
8
9/**
10 * Graph component to display a bar graph with captions and values.
11 *
12 * @param {Object} props - The properties object.
13 * @param {string} props.className - Additional class names for the graph container.
14 * @param {Object} props.caption - Caption data containing value, icon, and color for each key.
15 * @param {Array} props.values - Array of value objects to be displayed as bars.
16 * @param {number} props.maxLength - Maximum length of the graph.
17 * @param {number} [props.maxValue] - Maximum value for scaling the bars.
18 * @returns {JSX.Element|null} The rendered graph component or null if no caption is provided.
19 */
20export default function Graph({
21 className,
22 caption,
23 values = [],
24 maxLength,
25 maxValue,
26}) {
27 // Return null if no caption is provided
28 if (!caption) {
29 return null;
30 }
31
32 const captionKeys = Object.keys(caption);
33
34 // Calculate maxValue if not provided
35 if (maxValue === undefined) {
36 const allValues = values.map((value) => Object.values(value)).flat();
37 maxValue = Math.max(...allValues);
38 }
39
40 const classes = Utils.classNames("graph", className);
41
42 return (
43 <div className={classes}>
44 <div className="graph__bars">
45 {values.map((value) => {
46 const keys = Object.keys(value);
47 return keys.map((key) => {
48 const height = (value[key] / maxValue) * 100;
49 const { color: backgroundColor } = caption[key];
50 return (
51 <div
52 key={key}
53 className="graph__bar"
54 style={{
55 flex: `0 0 calc(100% / ${maxLength * captionKeys.length})`,
56 height: `${height}%`,
57 backgroundColor,
58 }}
59 />
60 );
61 });
62 })}
63 </div>
64 <div className="graph__data">
65 {captionKeys.map((key) => {
66 const { value, icon: Icon, color } = caption[key];
67 return (
68 <div key={key} className="graph__data-item">
69 {Icon && (
70 <SuspenseIcon>
71 <Icon
72 className="graph__data-item-icon"
73 style={{ fill: color }}
74 />
75 </SuspenseIcon>
76 )}
77 <span
78 className="graph__data-item-value"
79 dangerouslySetInnerHTML={{ __html: value }}
80 />
81 </div>
82 );
83 })}
84 </div>
85 </div>
86 );
87}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx
new file mode 100755
index 0000000..d6e04f2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/keyboard.jsx
@@ -0,0 +1,108 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { keyboardStyles as styles } from "../../styles/components/data/keyboard";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 20000;
15
16/**
17 * Keyboard widget component.
18 * @returns {JSX.Element|null} The rendered widget or null if not visible.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const { widgets, keyboardWidgetOptions } = settings;
23 const { keyboardWidget } = widgets;
24 const { refreshFrequency, showOnDisplay, showIcon, keyboardMaxLength } =
25 keyboardWidgetOptions;
26
27 // Determine the refresh frequency for the widget
28 const refresh = React.useMemo(
29 () =>
30 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
31 [refreshFrequency],
32 );
33
34 // Determine if the widget should be visible based on display settings
35 const visible =
36 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && keyboardWidget;
37
38 const [state, setState] = React.useState();
39 const [loading, setLoading] = React.useState(visible);
40
41 /**
42 * Resets the widget state.
43 */
44 const resetWidget = () => {
45 setState(undefined);
46 setLoading(false);
47 };
48
49 /**
50 * Fetches the current keyboard layout or input mode.
51 */
52 const getKeyboard = React.useCallback(async () => {
53 if (!visible) return;
54 const keyboard = await Utils.cachedRun(
55 `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | awk '/KeyboardLayout Name/ {$1=$2=$3=""; print $0}'`,
56 refresh,
57 );
58 const layout = Utils.cleanupOutput(keyboard)
59 .replace(";", "")
60 .replaceAll('"', "");
61 if (layout.length) {
62 setState({ keyboard: layout });
63 setLoading(false);
64 return;
65 }
66
67 const inputMode = await Utils.cachedRun(
68 `defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources | awk '/"Input Mode" =/ {$1=$2=$3=""; print $0}'`,
69 refresh,
70 );
71 const cleanedInputMode = Utils.cleanupOutput(inputMode)
72 .replace(/"com.apple.inputmethod.(.*)"/, "$1")
73 .replace(";", "");
74
75 if (!cleanedInputMode.length) return setLoading(false);
76
77 const splitedInputMode = cleanedInputMode.split(".");
78 const inputModeName = splitedInputMode[splitedInputMode.length - 1];
79 setState({ keyboard: inputModeName });
80 setLoading(false);
81 }, [visible, refresh]);
82
83 // Use server socket to listen for keyboard events
84 useServerSocket("keyboard", visible, getKeyboard, resetWidget, setLoading);
85 // Refresh the widget at the specified interval
86 useWidgetRefresh(visible, getKeyboard, refresh);
87
88 if (loading) return <DataWidgetLoader.Widget className="keyboard" />;
89 if (!state) return null;
90 const { keyboard } = state;
91
92 const maxLength = Number(keyboardMaxLength) || 0;
93 const displayKeyboard =
94 maxLength > 0 ? keyboard.slice(0, maxLength) : keyboard;
95
96 if (!displayKeyboard?.length) return null;
97
98 return (
99 <DataWidget.Widget
100 classes="keyboard"
101 Icon={showIcon ? Icons.Keyboard : null}
102 >
103 {displayKeyboard}
104 </DataWidget.Widget>
105 );
106});
107
108Widget.displayName = "Keyboard";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/memory.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/memory.jsx
new file mode 100755
index 0000000..e4361db
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/memory.jsx
@@ -0,0 +1,134 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import useWidgetRefresh from "../../hooks/use-widget-refresh";
5import useServerSocket from "../../hooks/use-server-socket";
6import { useSimpleBarContext } from "../simple-bar-context.jsx";
7import * as Utils from "../../utils";
8
9export { memoryStyles as styles } from "../../styles/components/data/memory";
10
11const { React } = Uebersicht;
12
13const DEFAULT_REFRESH_FREQUENCY = 4000;
14
15/**
16 * Memory Widget component
17 * @returns {JSX.Element|null} The memory widget component
18 */
19export const Widget = () => {
20 const { displayIndex, settings } = useSimpleBarContext();
21 const { widgets, memoryWidgetOptions } = settings;
22 const { memoryWidget } = widgets;
23 const {
24 refreshFrequency,
25 showOnDisplay,
26 memoryMonitorApp,
27 showIcon,
28 memoryUsageThreshold,
29 } = memoryWidgetOptions;
30
31 // Determine the refresh frequency for the widget
32 const refresh = React.useMemo(
33 () =>
34 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
35 [refreshFrequency],
36 );
37
38 // Determine if the widget should be visible
39 const visible =
40 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && memoryWidget;
41
42 const [state, setState] = Uebersicht.React.useState();
43 const [loading, setLoading] = Uebersicht.React.useState(visible);
44
45 /**
46 * Reset the widget state
47 */
48 const resetWidget = () => {
49 setState(undefined);
50 setLoading(false);
51 };
52
53 /**
54 * Fetch memory usage data
55 */
56 const getMemory = React.useCallback(async () => {
57 const output = await Utils.cachedRun(
58 'vm_stat | awk \'BEGIN {page_size=4096} /page size of/ {page_size=$8} /Pages free/ {free=$3} /Pages inactive/ {inactive=$3} /Pages speculative/ {spec=$4} /Pages active/ {active=$3} /Pages wired/ {wired=$4} END {gsub(/\\./, "", free); gsub(/\\./, "", inactive); gsub(/\\./, "", spec); gsub(/\\./, "", active); gsub(/\\./, "", wired); available=free+inactive+spec; total=available+active+wired; printf "%.0f", (available/total)*100}\'',
59 refresh,
60 );
61 const free = parseInt(Utils.cleanupOutput(output), 10);
62 setState({ free });
63 setLoading(false);
64 }, [setLoading, setState, refresh]);
65
66 // Use server socket to get memory data
67 useServerSocket("memory", visible, getMemory, resetWidget, setLoading);
68 // Refresh the widget at the specified interval
69 useWidgetRefresh(visible, getMemory, refresh);
70
71 if (loading) return <DataWidgetLoader.Widget className="memory" />;
72 if (!state) return null;
73
74 const { free } = state;
75 const used = 100 - free;
76 const threshold = Number(memoryUsageThreshold) || 0;
77
78 if (threshold > 0 && used < threshold) return null;
79
80 // Handle click event to open memory usage app
81 const onClick =
82 memoryMonitorApp === "None"
83 ? undefined
84 : (e) => {
85 Utils.clickEffect(e);
86 openMemoryUsageApp(memoryMonitorApp);
87 };
88
89 /**
90 * Pie chart component for memory usage
91 * @returns {JSX.Element} The pie chart component
92 */
93 const Pie = () => {
94 return (
95 <div
96 className="memory__pie"
97 style={{
98 backgroundImage: `conic-gradient(var(--pie-color) ${used}%, var(--main-alt) ${used}% 100%)`,
99 }}
100 />
101 );
102 };
103
104 const classes = Utils.classNames("memory", {
105 "memory--low": used <= 30,
106 "memory--medium": used > 30 && used <= 70,
107 "memory--high": used > 70,
108 });
109
110 return (
111 <DataWidget.Widget
112 classes={classes}
113 Icon={showIcon ? Pie : null}
114 onClick={onClick}
115 >
116 <div className="memory__content">{used}%</div>
117 </DataWidget.Widget>
118 );
119};
120
121/**
122 * Open the specified memory usage application
123 * @param {string} app - The name of the application to open
124 */
125function openMemoryUsageApp(app) {
126 switch (app) {
127 case "Activity Monitor":
128 Uebersicht.run(`open -a "Activity Monitor"`);
129 break;
130 case "Top":
131 Utils.runInUserTerminal("top");
132 break;
133 }
134}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mic.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mic.jsx
new file mode 100755
index 0000000..5c071a8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mic.jsx
@@ -0,0 +1,152 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import * as Utils from "../../utils";
9import { useSimpleBarContext } from "../simple-bar-context.jsx";
10
11const { React } = Uebersicht;
12
13export { micStyles as styles } from "../../styles/components/data/mic";
14
15const DEFAULT_REFRESH_FREQUENCY = 20000;
16
17/**
18 * Mic widget component.
19 * @returns {JSX.Element} The rendered mic widget.
20 */
21export const Widget = React.memo(() => {
22 const { displayIndex, settings } = useSimpleBarContext();
23 const { widgets, micWidgetOptions } = settings;
24 const { micWidget } = widgets;
25 const { refreshFrequency, showOnDisplay, showIcon } = micWidgetOptions;
26
27 // Determine the refresh frequency for the widget.
28 const refresh = React.useMemo(
29 () =>
30 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
31 [refreshFrequency],
32 );
33
34 // Determine if the widget should be visible.
35 const visible =
36 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && micWidget;
37
38 const [state, setState] = React.useState();
39 const [loading, setLoading] = React.useState(visible);
40 const { volume: _volume } = state || {};
41 const [volume, setVolume] = React.useState(_volume && parseInt(_volume, 10));
42 const [dragging, setDragging] = React.useState(false);
43
44 /**
45 * Reset the widget state.
46 */
47 const resetWidget = () => {
48 setState(undefined);
49 setLoading(false);
50 };
51
52 /**
53 * Fetch the current microphone volume.
54 */
55 const getMic = React.useCallback(async () => {
56 if (!visible) return;
57 const volume = await Utils.cachedRun(
58 `osascript -e 'input volume of (get volume settings)'`,
59 refresh,
60 );
61 setState({ volume: Utils.cleanupOutput(volume) });
62 setLoading(false);
63 }, [visible, refresh]);
64
65 // Use server socket to get mic data.
66 useServerSocket("mic", visible, getMic, resetWidget, setLoading);
67 // Refresh the widget periodically.
68 useWidgetRefresh(visible, getMic, refresh);
69
70 // Update the mic volume when dragging state changes.
71 React.useEffect(() => {
72 if (!dragging) setMic(volume);
73 }, [dragging, volume]);
74
75 // Update the volume state when the fetched volume changes.
76 React.useEffect(() => {
77 setVolume((currentVolume) => {
78 if (_volume && currentVolume !== parseInt(_volume, 10)) {
79 return parseInt(_volume, 10);
80 }
81 return currentVolume;
82 });
83 }, [_volume]);
84
85 if (loading) return <DataWidgetLoader.Widget className="mic" />;
86 if (!state || volume === undefined || _volume === "missing value")
87 return null;
88
89 const Icon = !volume ? Icons.MicOff : Icons.MicOn;
90
91 /**
92 * Handle volume change event.
93 * @param {React.ChangeEvent<HTMLInputElement>} e - The change event.
94 */
95 const onChange = (e) => {
96 const value = parseInt(e.target.value, 10);
97 setVolume(value);
98 };
99
100 /**
101 * Handle mouse down event on the slider.
102 */
103 const onMouseDown = () => setDragging(true);
104
105 /**
106 * Handle mouse up event on the slider.
107 */
108 const onMouseUp = () => setDragging(false);
109
110 const formattedVolume = `${volume.toString().padStart(2, "0")}%`;
111
112 const classes = Utils.classNames("mic", {
113 "mic--dragging": dragging,
114 });
115
116 return (
117 <DataWidget.Widget classes={classes} disableSlider>
118 <div className="mic__display">
119 {showIcon && (
120 <SuspenseIcon>
121 <Icon />
122 </SuspenseIcon>
123 )}
124 <span className="mic__value">{formattedVolume}</span>
125 </div>
126 <div className="mic__slider-container">
127 <input
128 type="range"
129 min="0"
130 max="100"
131 step="1"
132 value={volume}
133 className="mic__slider"
134 onMouseDown={onMouseDown}
135 onMouseUp={onMouseUp}
136 onChange={onChange}
137 />
138 </div>
139 </DataWidget.Widget>
140 );
141});
142
143Widget.displayName = "Mic";
144
145/**
146 * Set the microphone volume.
147 * @param {number} volume - The volume level to set.
148 */
149function setMic(volume) {
150 if (volume === undefined) return;
151 Uebersicht.run(`osascript -e 'set volume input volume ${volume}'`);
152}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mpd.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mpd.jsx
new file mode 100755
index 0000000..53449b1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/mpd.jsx
@@ -0,0 +1,228 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { mpdStyles as styles } from "../../styles/components/data/mpd";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 10000;
15
16/**
17 * MPD Widget component
18 * @returns {JSX.Element|null} The MPD widget
19 */
20export const Widget = React.memo(() => {
21 const ref = React.useRef();
22 const { displayIndex, settings } = useSimpleBarContext();
23 const { widgets, mpdWidgetOptions } = settings;
24 const { mpdWidget } = widgets;
25 const {
26 refreshFrequency,
27 showSpecter,
28 mpdBinaryPath,
29 mpdHost,
30 mpdPort,
31 mpdFormatString,
32 showOnDisplay,
33 showIcon,
34 } = mpdWidgetOptions;
35
36 // Determine the refresh frequency for the widget
37 const refresh = React.useMemo(
38 () =>
39 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
40 [refreshFrequency],
41 );
42
43 // Determine if the widget should be visible on the current display
44 const visible =
45 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && mpdWidget;
46
47 const [state, setState] = React.useState();
48 const [loading, setLoading] = React.useState(visible);
49 const [isMpdActive, setIsMpdActive] = React.useState(false);
50 const { volume: _volume } = state || {};
51 const defaultVolume = _volume && parseInt(_volume);
52 const [volume, setVolume] = React.useState(defaultVolume);
53 const [dragging, setDragging] = React.useState(false);
54
55 /**
56 * Reset the widget state
57 */
58 const resetWidget = () => {
59 setState(undefined);
60 setLoading(false);
61 setIsMpdActive(false);
62 };
63
64 /**
65 * Fetch MPD data
66 */
67 const getMpd = React.useCallback(async () => {
68 if (!visible) return;
69
70 try {
71 const mpdProcess = await Utils.cachedRun(
72 `pgrep -x mpd > /dev/null && echo "true" || echo "false"`,
73 refresh,
74 );
75
76 if (Utils.cleanupOutput(mpdProcess) === "false") {
77 setLoading(false);
78 setIsMpdActive(false);
79 return;
80 }
81
82 const [playerState, trackInfo, volumeState] = await Promise.all([
83 Utils.cachedRun(
84 `${mpdBinaryPath} --host ${mpdHost} --port ${mpdPort} | head -n 2 | tail -n 1 | awk '{print substr($1,2,length($1)-2)}' 2>/dev/null || echo "stopped"`,
85 refresh,
86 ),
87 Utils.cachedRun(
88 `${mpdBinaryPath} --host ${mpdHost} --port ${mpdPort} --format "${mpdFormatString}" | head -n 1`,
89 refresh,
90 ),
91 Utils.cachedRun(
92 `${mpdBinaryPath} --host ${mpdHost} --port ${mpdPort} volume | sed -e 's/volume:[ ]*//g' -e 's/%//g'`,
93 refresh,
94 ),
95 ]);
96 if (Utils.cleanupOutput(trackInfo) === "") {
97 setLoading(false);
98 setIsMpdActive(false);
99 return;
100 }
101 setState({
102 playerState: Utils.cleanupOutput(playerState),
103 trackInfo: Utils.cleanupOutput(trackInfo),
104 volume: Utils.cleanupOutput(volumeState),
105 });
106 setIsMpdActive(true);
107 setLoading(false);
108 } catch {
109 setLoading(false);
110 setIsMpdActive(false);
111 }
112 }, [visible, mpdBinaryPath, mpdHost, mpdPort, mpdFormatString, refresh]);
113
114 // Update the volume when dragging ends
115 React.useEffect(() => {
116 if (!dragging) setSound(mpdBinaryPath, mpdHost, mpdPort, volume);
117 }, [dragging, mpdBinaryPath, mpdHost, mpdPort, volume]);
118
119 // Set the volume state when dragging ends
120 React.useEffect(() => {
121 if (!dragging) setVolume(volume);
122 }, [dragging, volume]);
123
124 useServerSocket("mpd", visible, getMpd, resetWidget, setLoading);
125 useWidgetRefresh(visible, getMpd, refresh);
126
127 if (loading) return <DataWidgetLoader.Widget className="mpd" />;
128 if (!state || !isMpdActive) return null;
129 const { playerState, trackInfo } = state;
130
131 if (!trackInfo.length) return null;
132
133 const isPlaying = playerState === "playing";
134 const Icon = isPlaying ? Icons.Playing : Icons.Paused;
135
136 /**
137 * Handle click event to toggle play/pause
138 * @param {React.MouseEvent} e - The click event
139 */
140 const onClick = async (e) => {
141 Utils.clickEffect(e);
142 await togglePlay(mpdBinaryPath, mpdHost, mpdPort);
143 await getMpd();
144 };
145
146 /**
147 * Handle volume change event
148 * @param {React.ChangeEvent<HTMLInputElement>} e - The change event
149 */
150 const onChange = (e) => {
151 const value = parseInt(e.target.value);
152 setVolume(value);
153 };
154
155 const onMouseDown = () => setDragging(true);
156
157 const onMouseUp = () => setDragging(false);
158
159 const stopPropagation = (e) => e.stopPropagation();
160
161 const onMouseEnter = () =>
162 Utils.startSliding(ref.current, ".mpd__inner", ".mpd__info");
163 const onMouseLeave = () => Utils.stopSliding(ref.current, ".mpd__slider");
164
165 const classes = Utils.classNames("sound", "mpd", {
166 "mpd--playing": isPlaying,
167 "mpd--dragging": dragging,
168 });
169
170 return (
171 <DataWidget.Widget
172 classes={classes}
173 Icon={showIcon ? Icon : null}
174 onClick={onClick}
175 showSpecter={showSpecter && isPlaying}
176 disableSlider
177 >
178 <div
179 ref={ref}
180 className="mpd__outer"
181 onMouseEnter={onMouseEnter}
182 onMouseLeave={onMouseLeave}
183 >
184 <div className="mpd__inner">
185 <div className="mpd__info">{trackInfo}</div>
186 </div>
187 <div className="mpd__slider-container" onClick={stopPropagation}>
188 <input
189 type="range"
190 min="0"
191 max="100"
192 step="1"
193 value={volume}
194 className="mpd__slider"
195 onMouseDown={onMouseDown}
196 onMouseUp={onMouseUp}
197 onChange={onChange}
198 />
199 </div>
200 </div>
201 </DataWidget.Widget>
202 );
203});
204
205Widget.displayName = "Mpd";
206
207/**
208 * Toggle play/pause state of MPD
209 * @param {string} path - The path to the MPD binary
210 * @param {string} host - The MPD host
211 * @param {string} port - The MPD port
212 * @returns {Promise<void>}
213 */
214async function togglePlay(path, host, port) {
215 return Uebersicht.run(`${path} --host ${host} --port ${port} toggle`);
216}
217
218/**
219 * Set the volume of MPD
220 * @param {string} path - The path to the MPD binary
221 * @param {string} host - The MPD host
222 * @param {string} port - The MPD port
223 * @param {number} volume - The volume level to set
224 */
225function setSound(path, host, port, volume) {
226 if (!volume) return;
227 Uebersicht.run(`${path} --host ${host} --port ${port} volume ${volume}`);
228}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/music.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/music.jsx
new file mode 100755
index 0000000..f0fabd6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/music.jsx
@@ -0,0 +1,161 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { musicStyles as styles } from "../../styles/components/data/music";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 10000;
15
16/**
17 * Music widget component.
18 * @returns {JSX.Element|null} The music widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const { widgets, musicWidgetOptions } = settings;
23 const { musicWidget } = widgets;
24 const { refreshFrequency, showSpecter, showOnDisplay, showIcon } =
25 musicWidgetOptions;
26
27 // Determine the refresh frequency for the widget
28 const refresh = React.useMemo(
29 () =>
30 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
31 [refreshFrequency],
32 );
33
34 // Determine if the widget should be visible on the current display
35 const visible =
36 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && musicWidget;
37
38 const [state, setState] = React.useState();
39 const [loading, setLoading] = React.useState(visible);
40 const [isMusicActive, setIsMusicActive] = React.useState(false);
41
42 /**
43 * Resets the widget state.
44 */
45 const resetWidget = () => {
46 setState(undefined);
47 setLoading(false);
48 setIsMusicActive(false);
49 };
50
51 /**
52 * Fetches the current music information.
53 */
54 const getMusic = React.useCallback(async () => {
55 if (!visible) return;
56 const osVersion = await Utils.cachedRun(`sw_vers -productVersion`, refresh);
57 const processName =
58 Utils.cleanupOutput(osVersion) === "10.15" ? "iTunes" : "Music";
59 const isRunning = await Utils.cachedRun(
60 `pgrep -xq "${processName}" && echo "true" || echo "false"`,
61 refresh,
62 );
63 if (Utils.cleanupOutput(isRunning) === "false") {
64 setLoading(false);
65 setIsMusicActive(false);
66 return;
67 }
68 const output = await Utils.cachedRun(
69 `osascript -e 'tell application "${processName}"' -e 'set output to (player state as string) & "|" & (name of current track as string) & "|" & (artist of current track as string)' -e 'end tell' 2>/dev/null || echo "stopped|unknown track|unknown artist"`,
70 refresh,
71 );
72 const [playerState, trackName, artistName] =
73 Utils.cleanupOutput(output).split("|");
74 setState({
75 playerState,
76 trackName,
77 artistName,
78 processName: Utils.cleanupOutput(processName),
79 });
80 setIsMusicActive(true);
81 setLoading(false);
82 }, [visible, refresh]);
83
84 // Use server socket to listen for music events
85 useServerSocket("music", visible, getMusic, resetWidget, setLoading);
86 // Refresh the widget at the specified interval
87 useWidgetRefresh(visible, getMusic, refresh);
88
89 if (loading) return <DataWidgetLoader.Widget className="music" />;
90 if (!state || !isMusicActive) return null;
91 const { processName, playerState, trackName, artistName } = state;
92
93 if (!trackName.length) return null;
94
95 const isPlaying = playerState === "playing";
96 const Icon = isPlaying ? Icons.Playing : Icons.Paused;
97
98 /**
99 * Handles click event to toggle play/pause.
100 * @param {React.MouseEvent} e - The click event.
101 */
102 const onClick = (e) => {
103 Utils.clickEffect(e);
104 togglePlay(!isPlaying, processName);
105 getMusic();
106 };
107
108 /**
109 * Handles right-click event to skip to the next track.
110 * @param {React.MouseEvent} e - The right-click event.
111 */
112 const onRightClick = (e) => {
113 Utils.clickEffect(e);
114 Uebersicht.run(
115 `osascript -e 'tell application "${processName}" to Next Track'`,
116 );
117 getMusic();
118 };
119
120 /**
121 * Handles middle-click event to open the music application.
122 * @param {React.MouseEvent} e - The middle-click event.
123 */
124 const onMiddleClick = (e) => {
125 Utils.clickEffect(e);
126 Uebersicht.run(`open -a '${processName}'`);
127 getMusic();
128 };
129
130 const classes = Utils.classNames("music", {
131 "music--playing": isPlaying,
132 });
133
134 return (
135 <DataWidget.Widget
136 classes={classes}
137 Icon={showIcon ? Icon : null}
138 onClick={onClick}
139 onRightClick={onRightClick}
140 onMiddleClick={onMiddleClick}
141 showSpecter={showSpecter && isPlaying}
142 >
143 {trackName} - {artistName}
144 </DataWidget.Widget>
145 );
146});
147
148Widget.displayName = "Music";
149
150/**
151 * Toggles play/pause state of the music application.
152 * @param {boolean} isPaused - Whether the music is paused.
153 * @param {string} processName - The name of the music application process.
154 */
155function togglePlay(isPaused, processName) {
156 if (isPaused) {
157 Uebersicht.run(`osascript -e 'tell application "${processName}" to play'`);
158 } else {
159 Uebersicht.run(`osascript -e 'tell application "${processName}" to pause'`);
160 }
161}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/netstats.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/netstats.jsx
new file mode 100755
index 0000000..ef3d7be
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/netstats.jsx
@@ -0,0 +1,182 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import Graph from "./graph.jsx";
7import useWidgetRefresh from "../../hooks/use-widget-refresh.js";
8import useServerSocket from "../../hooks/use-server-socket";
9import { useSimpleBarContext } from "../simple-bar-context.jsx";
10import * as Utils from "../../utils.js";
11
12export { netstatsStyles as styles } from "../../styles/components/data/netstats";
13
14const { React } = Uebersicht;
15
16const DEFAULT_REFRESH_FREQUENCY = 2000;
17const GRAPH_LENGTH = 30;
18
19/**
20 * Netstats widget component.
21 * @returns {JSX.Element|null} The rendered component.
22 */
23export const Widget = React.memo(() => {
24 const { displayIndex, settings } = useSimpleBarContext();
25 const { widgets, netstatsWidgetOptions } = settings;
26 const { netstatsWidget } = widgets;
27 const {
28 refreshFrequency,
29 showOnDisplay,
30 displayAsGraph,
31 showIcon,
32 netstatsThreshold,
33 } = netstatsWidgetOptions;
34
35 const isDisabled = React.useRef(false);
36
37 // Determine the refresh frequency for the widget
38 const refresh = React.useMemo(
39 () =>
40 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
41 [refreshFrequency],
42 );
43
44 // Determine if the widget should be visible
45 const visible =
46 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && netstatsWidget;
47
48 const [graph, setGraph] = React.useState([]);
49 const [state, setState] = React.useState();
50 const [loading, setLoading] = React.useState(visible);
51
52 /**
53 * Resets the widget state.
54 */
55 const resetWidget = () => {
56 setState(undefined);
57 setLoading(false);
58 setGraph([]);
59 };
60
61 /**
62 * Fetches network statistics.
63 */
64 const getNetstats = React.useCallback(async () => {
65 if (!visible) return;
66 try {
67 const output = await Utils.cachedRun(
68 `bash ./simple-bar/lib/scripts/netstats.sh 2>&1`,
69 refresh,
70 );
71 if (!visible || isDisabled.current) {
72 return;
73 }
74 const data = Utils.cleanupOutput(output);
75 const json = JSON.parse(data);
76 setState(json);
77 if (displayAsGraph) {
78 Utils.addToGraphHistory(json, setGraph, GRAPH_LENGTH);
79 }
80 setLoading(false);
81 } catch {
82 setTimeout(getNetstats, 1000);
83 }
84 }, [displayAsGraph, setGraph, visible, refresh]);
85
86 // Update the disabled state based on visibility
87 React.useEffect(() => {
88 isDisabled.current = !visible;
89 }, [visible]);
90
91 // Set up server socket and widget refresh hooks
92 useServerSocket("netstats", visible, getNetstats, resetWidget, setLoading);
93 useWidgetRefresh(visible, getNetstats, refresh);
94
95 if (loading)
96 return (
97 <React.Fragment>
98 <DataWidgetLoader.Widget className="netstats" />
99 {!displayAsGraph && <DataWidgetLoader.Widget className="netstats" />}
100 </React.Fragment>
101 );
102
103 if (!state) {
104 return null;
105 }
106
107 const { download, upload } = state;
108
109 if (download === undefined || upload === undefined) {
110 return null;
111 }
112
113 const threshold = (Number(netstatsThreshold) || 0) * 1024;
114 const isBelowThreshold =
115 threshold > 0 &&
116 Math.abs(download) < threshold &&
117 Math.abs(upload) < threshold;
118
119 if (isBelowThreshold) {
120 return null;
121 }
122
123 const formattedDownload = Utils.formatBytes(download);
124 const formattedUpload = Utils.formatBytes(upload);
125
126 if (displayAsGraph) {
127 return (
128 <DataWidget.Widget classes="netstats netstats--graph" disableSlider>
129 <Graph
130 className="netstats__graph"
131 caption={{
132 download: {
133 value: formattedDownload,
134 icon: showIcon ? Icons.Download : null,
135 color: "var(--magenta)",
136 },
137 upload: {
138 value: formattedUpload,
139 icon: showIcon ? Icons.Upload : null,
140 color: "var(--blue)",
141 },
142 }}
143 values={graph}
144 maxLength={GRAPH_LENGTH}
145 />
146 </DataWidget.Widget>
147 );
148 }
149
150 return (
151 <React.Fragment>
152 <DataWidget.Widget classes="netstats" disableSlider>
153 <div className="netstats__item">
154 {showIcon && (
155 <SuspenseIcon>
156 <Icons.Download className="netstats__icon netstats__icon--download" />
157 </SuspenseIcon>
158 )}
159 <span
160 className="netstats__value"
161 dangerouslySetInnerHTML={{ __html: formattedDownload }}
162 />
163 </div>
164 </DataWidget.Widget>
165 <DataWidget.Widget classes="netstats" disableSlider>
166 <div className="netstats__item">
167 {showIcon && (
168 <SuspenseIcon>
169 <Icons.Upload className="netstats__icon netstats__icon--upload" />
170 </SuspenseIcon>
171 )}
172 <span
173 className="netstats__value"
174 dangerouslySetInnerHTML={{ __html: formattedUpload }}
175 />
176 </div>
177 </DataWidget.Widget>
178 </React.Fragment>
179 );
180});
181
182Widget.displayName = "Netstats";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/next-meeting.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/next-meeting.jsx
new file mode 100755
index 0000000..74f6bf8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/next-meeting.jsx
@@ -0,0 +1,310 @@
1/**
2 * Next Meeting Widget
3 *
4 * Displays the next upcoming calendar event with time until start and optional join button.
5 * Uses icalBuddy for fast calendar access with proper recurring event support.
6 *
7 * Requirements:
8 * - macOS with Calendar.app or compatible calendar
9 * - icalBuddy installed (brew install ical-buddy)
10 * - Calendar access permissions granted
11 *
12 * @module next-meeting
13 */
14import * as Uebersicht from "uebersicht";
15import * as DataWidget from "./data-widget.jsx";
16import * as DataWidgetLoader from "./data-widget-loader.jsx";
17import * as Icons from "../icons/icons.jsx";
18import useWidgetRefresh from "../../hooks/use-widget-refresh";
19import useServerSocket from "../../hooks/use-server-socket";
20import { useSimpleBarContext } from "../simple-bar-context.jsx";
21import * as Utils from "../../utils";
22
23export { nextMeetingStyles as styles } from "../../styles/components/data/next-meeting";
24
25const { React } = Uebersicht;
26
27const DEFAULT_REFRESH_FREQUENCY = 60000; // 1 minute
28
29// Timing thresholds (in minutes)
30const URGENT_THRESHOLD = 5; // Red pulsing when ≤5 min until meeting
31const UPCOMING_THRESHOLD = 15; // Yellow when ≤15 min until meeting
32
33// Uses icalBuddy for fast calendar access (handles recurring events properly)
34// Note: Shell script automatically skips meetings that started more than 15 minutes ago
35const BASE_COMMAND = `./simple-bar/lib/scripts/next-meeting.sh`;
36
37/**
38 * Builds the shell command with optional custom icalBuddy path and look-ahead hours.
39 * @param {string} icalBuddyPath - Optional custom path to icalBuddy binary
40 * @param {number} lookAheadHours - Hours to look ahead for meetings (default: 12)
41 * @returns {string} Complete shell command
42 */
43function buildCommand(icalBuddyPath, lookAheadHours) {
44 const hours = lookAheadHours || 12;
45 if (icalBuddyPath && icalBuddyPath.trim()) {
46 // Escape special shell characters to prevent injection
47 const safePath = icalBuddyPath.replace(/["$`\\]/g, "\\$&");
48 return `${BASE_COMMAND} "${safePath}" ${hours}`;
49 }
50 return `${BASE_COMMAND} "" ${hours}`;
51}
52
53// Patterns to extract meeting URLs from notes
54const MEETING_URL_PATTERNS = [
55 /https?:\/\/[\w-]*\.?zoom\.us\/[^\s<>"]+/gi,
56 /https?:\/\/teams\.microsoft\.com\/l\/meetup-join\/[^\s<>"]+/gi,
57 /https?:\/\/meet\.google\.com\/[^\s<>"]+/gi,
58 /https?:\/\/[\w-]*\.?webex\.com\/[^\s<>"]+/gi,
59];
60
61// SafeLinks pattern (Microsoft Outlook protection wrapper)
62const SAFELINKS_PATTERN =
63 /https?:\/\/[\w.-]*safelinks\.protection\.outlook\.com\/[^\s<>">\]]+/gi;
64
65/**
66 * Decode a URL that may be URL-encoded
67 * @param {string} url - Possibly encoded URL
68 * @returns {string} Decoded URL
69 */
70function decodeUrl(url) {
71 try {
72 return decodeURIComponent(url);
73 } catch {
74 return url;
75 }
76}
77
78/**
79 * Extract the real URL from a SafeLink wrapper
80 * @param {string} safeLink - SafeLink URL
81 * @returns {string} Extracted real URL or original
82 */
83function extractFromSafeLink(safeLink) {
84 const urlParam = safeLink.match(/[?&]url=([^&]+)/i);
85 if (urlParam && urlParam[1]) {
86 return decodeUrl(urlParam[1]);
87 }
88 return safeLink;
89}
90
91/**
92 * Extract meeting URL from event URL or notes
93 * @param {string} url - Event URL
94 * @param {string} notes - Event notes/description
95 * @returns {string|null} Meeting URL or null
96 */
97function extractMeetingUrl(url, notes) {
98 // First check direct URL
99 if (url && url.trim() && url !== "missing value") {
100 for (const pattern of MEETING_URL_PATTERNS) {
101 pattern.lastIndex = 0;
102 const match = url.match(pattern);
103 if (match) return match[0];
104 }
105 if (url.startsWith("http")) return url;
106 }
107
108 // Check notes for meeting links
109 if (notes && notes.trim()) {
110 // First try direct meeting URLs
111 for (const pattern of MEETING_URL_PATTERNS) {
112 pattern.lastIndex = 0;
113 const match = notes.match(pattern);
114 if (match) return match[0];
115 }
116
117 // Check for SafeLinks that contain meeting URLs
118 SAFELINKS_PATTERN.lastIndex = 0;
119 const safeLinks = notes.match(SAFELINKS_PATTERN);
120 if (safeLinks) {
121 for (const safeLink of safeLinks) {
122 const realUrl = extractFromSafeLink(safeLink);
123 for (const pattern of MEETING_URL_PATTERNS) {
124 pattern.lastIndex = 0;
125 if (pattern.test(realUrl)) {
126 return realUrl;
127 }
128 }
129 }
130 }
131 }
132
133 return null;
134}
135
136/**
137 * Format time until meeting
138 * @param {number} minutes - Minutes until meeting
139 * @returns {string} Formatted time string
140 */
141function formatTimeUntil(minutes) {
142 if (minutes < 0) return "now";
143 if (minutes < 1) return "<1m";
144 if (minutes < 60) return `${minutes}m`;
145 const hours = Math.floor(minutes / 60);
146 const mins = minutes % 60;
147 if (mins === 0) return `${hours}h`;
148 return `${hours}h ${mins}m`;
149}
150
151/**
152 * Parse meeting data from shell script output
153 * @param {string} output - Raw command output
154 * @returns {Object|null} Meeting object or null
155 */
156function parseMeetingData(output) {
157 if (!output || !output.trim()) return null;
158
159 const parts = output.trim().split("|");
160 if (parts.length < 5) return null;
161
162 const [title, startTime, url, notes, minutesUntil] = parts;
163 if (!title) return null;
164
165 const meetingUrl = extractMeetingUrl(url, notes);
166
167 return {
168 title: title.trim(),
169 startTime: startTime,
170 url: meetingUrl,
171 minutesUntil: parseInt(minutesUntil, 10) || 0,
172 };
173}
174
175/**
176 * Join button sub-component for meeting URLs.
177 * @component
178 * @param {Object} props - Component props
179 * @param {string} props.url - Meeting URL to open
180 * @returns {JSX.Element} Join button element
181 */
182const JoinButton = React.memo(({ url }) => {
183 /**
184 * Opens the meeting URL when clicked.
185 * @param {React.MouseEvent} e - Click event
186 */
187 const handleJoin = async (e) => {
188 e.stopPropagation();
189 Utils.clickEffect(e);
190 // Escape special shell characters to prevent injection
191 const safeUrl = url.replace(/["$`\\]/g, "\\$&");
192 await Uebersicht.run(`open "${safeUrl}"`);
193 };
194
195 return (
196 <button
197 className="next-meeting__join"
198 onClick={handleJoin}
199 title="Join meeting"
200 aria-label="Join video meeting"
201 >
202 Join
203 </button>
204 );
205});
206
207JoinButton.displayName = "JoinButton";
208
209/**
210 * Next Meeting widget component
211 * Shows the next upcoming meeting with optional join button
212 * @returns {JSX.Element|null} The next meeting widget
213 */
214export const Widget = React.memo(() => {
215 const { displayIndex, settings } = useSimpleBarContext();
216 const { widgets, nextMeetingWidgetOptions, dateWidgetOptions } = settings;
217 const { nextMeetingWidget } = widgets;
218 const {
219 refreshFrequency,
220 showOnDisplay,
221 showJoinButton,
222 showTimeOnly,
223 icalBuddyPath,
224 lookAheadHours,
225 } = nextMeetingWidgetOptions;
226
227 // Calculate the refresh frequency for the widget
228 const refresh = React.useMemo(
229 () =>
230 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
231 [refreshFrequency],
232 );
233
234 // Determine if the widget should be visible based on display settings
235 const visible =
236 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && nextMeetingWidget;
237
238 const [state, setState] = React.useState(null);
239 const [loading, setLoading] = React.useState(visible);
240
241 /**
242 * Resets the widget state.
243 */
244 const resetWidget = React.useCallback(() => {
245 setState(null);
246 setLoading(false);
247 }, []);
248
249 /**
250 * Fetches next meeting and updates the state.
251 */
252 const getMeeting = React.useCallback(async () => {
253 if (!visible) return;
254 try {
255 const command = buildCommand(icalBuddyPath, lookAheadHours);
256 const output = await Uebersicht.run(command);
257 const meeting = parseMeetingData(output);
258 setState(meeting);
259 } catch (error) {
260 // eslint-disable-next-line no-console
261 console.error("Error fetching next meeting:", error);
262 setState(null);
263 }
264 setLoading(false);
265 }, [visible, icalBuddyPath, lookAheadHours]);
266
267 // Server socket for real-time updates
268 useServerSocket("next-meeting", visible, getMeeting, resetWidget, setLoading);
269
270 // Refresh the widget at the specified interval
271 useWidgetRefresh(visible, getMeeting, refresh);
272
273 if (loading) return <DataWidgetLoader.Widget className="next-meeting" />;
274 if (!state) return null;
275
276 const { title, minutesUntil, url } = state;
277 const timeDisplay = formatTimeUntil(minutesUntil);
278 const isUrgent = minutesUntil <= URGENT_THRESHOLD; // Red pulsing: ≤5 min or in progress (up to 15 min)
279 const isUpcoming = minutesUntil <= UPCOMING_THRESHOLD; // Yellow: ≤15 min (but not urgent/in-progress)
280
281 const widgetClasses = Utils.classNames("next-meeting", {
282 "next-meeting--urgent": isUrgent,
283 "next-meeting--upcoming": isUpcoming && !isUrgent,
284 });
285
286 /**
287 * Handle click event to open the calendar application
288 * @param {Event} e - The click event
289 */
290 const openCalendar = async (e) => {
291 Utils.clickEffect(e);
292 const calendarApp = dateWidgetOptions?.calendarApp || "Calendar";
293 await Uebersicht.run(`open -a "${calendarApp}"`);
294 };
295
296 return (
297 <DataWidget.Widget
298 classes={widgetClasses}
299 Icon={Icons.Calendar}
300 onClick={openCalendar}
301 useDivForClick
302 >
303 {!showTimeOnly && <span className="next-meeting__title">{title}</span>}
304 <span className="next-meeting__time">{timeDisplay}</span>
305 {showJoinButton && url && <JoinButton url={url} />}
306 </DataWidget.Widget>
307 );
308});
309
310Widget.displayName = "NextMeeting";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/notifications.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/notifications.jsx
new file mode 100755
index 0000000..b55e487
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/notifications.jsx
@@ -0,0 +1,189 @@
1/**
2 * Notifications Widget
3 *
4 * Displays badge counts from running applications with active notifications.
5 * Uses macOS lsappinfo to query app status labels (dock badges).
6 *
7 * Requirements:
8 * - macOS (lsappinfo is macOS-specific)
9 * - No special permissions required
10 *
11 * @module notifications
12 */
13import * as Uebersicht from "uebersicht";
14import * as AppIcons from "../../app-icons.js";
15import { SuspenseIcon } from "../icons/icon.jsx";
16import useWidgetRefresh from "../../hooks/use-widget-refresh";
17import useServerSocket from "../../hooks/use-server-socket";
18import { useSimpleBarContext } from "../simple-bar-context.jsx";
19import * as Utils from "../../utils";
20
21export { notificationsStyles as styles } from "../../styles/components/data/notifications";
22
23const { React } = Uebersicht;
24
25const DEFAULT_REFRESH_FREQUENCY = 10000;
26
27// Shell command to get notification badges from running apps
28const COMMAND = `lsappinfo -all list 2>/dev/null | perl -0777 -pe 's/---/\\n---\\n/g' | perl -ne '
29 if (/"CFBundleName"="([^"]+)"/) { $app = $1; }
30 if (/"StatusLabel"=\\{ "label"="([^"]*)"/) { $badge = $1; }
31 if (/"LSBundlePath"="([^"]+)"/) { $path = $1; }
32 if (/^---$/ || eof) {
33 print "$app|$badge|$path\\n" if ($app && $badge);
34 ($app, $badge, $path) = ("", "", "");
35 }
36'`;
37
38/**
39 * Parses shell command output into notification objects.
40 * @param {string} output - Raw command output from lsappinfo
41 * @returns {Array<{name: string, badge: string, bundlePath: string}>} Array of notification objects
42 */
43function parseNotifications(output) {
44 if (!output || !output.trim()) return [];
45
46 return output
47 .trim()
48 .split("\n")
49 .filter((line) => line.includes("|"))
50 .map((line) => {
51 const [name, badge, bundlePath] = line.split("|");
52 return { name, badge, bundlePath };
53 })
54 .filter((item) => item.name && item.badge);
55}
56
57/**
58 * Single app notification pill component.
59 * @component
60 * @param {Object} props - Component props
61 * @param {Object} props.app - Application notification data
62 * @param {string} props.app.name - Application name
63 * @param {string} props.app.badge - Badge count
64 * @param {string} props.app.bundlePath - Path to application bundle
65 * @returns {JSX.Element} Notification pill button
66 */
67const NotificationPill = React.memo(({ app }) => {
68 /**
69 * Opens the application when pill is clicked.
70 * @param {React.MouseEvent} e - Click event
71 */
72 const openApp = async (e) => {
73 Utils.clickEffect(e);
74 // Escape special shell characters to prevent injection
75 const safePath = app.bundlePath.replace(/["$`\\]/g, "\\$&");
76 await Uebersicht.run(`open "${safePath}"`);
77 };
78
79 // Get the SVG icon for this app, or use Default
80 const Icon = AppIcons.apps[app.name] || AppIcons.apps.Default;
81
82 return (
83 <button
84 className="notification-pill"
85 onClick={openApp}
86 title={`${app.name}: ${app.badge} notification${app.badge !== "1" ? "s" : ""}`}
87 aria-label={`Open ${app.name} - ${app.badge} notification${app.badge !== "1" ? "s" : ""}`}
88 >
89 <SuspenseIcon>
90 <Icon className="notification-pill__icon" />
91 </SuspenseIcon>
92 <span className="notification-pill__badge">{app.badge}</span>
93 </button>
94 );
95});
96
97NotificationPill.displayName = "NotificationPill";
98
99/**
100 * Notification Badges widget component.
101 * Shows each app with notifications as an inline pill.
102 * @component
103 * @returns {JSX.Element|null} The notifications widget component or null if no notifications
104 */
105export const Widget = React.memo(() => {
106 const { displayIndex, settings } = useSimpleBarContext();
107 const { widgets, notificationsWidgetOptions } = settings;
108 const { notificationsWidget } = widgets;
109 const { refreshFrequency, showOnDisplay, excludedApps } = notificationsWidgetOptions;
110
111 // Determine if the widget should be visible based on display settings
112 const visible =
113 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) &&
114 notificationsWidget;
115
116 // Calculate the refresh frequency for the widget
117 const refresh = React.useMemo(
118 () =>
119 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
120 [refreshFrequency],
121 );
122
123 const [state, setState] = React.useState([]);
124 const [loading, setLoading] = React.useState(visible);
125
126 /**
127 * Resets the widget state.
128 */
129 const resetWidget = React.useCallback(() => {
130 setState([]);
131 setLoading(false);
132 }, []);
133
134 // Build the exclusion list from the comma-separated setting
135 const exclusionList = React.useMemo(
136 () =>
137 excludedApps
138 ? excludedApps
139 .split(",")
140 .map((s) => s.trim().toLowerCase())
141 .filter(Boolean)
142 : [],
143 [excludedApps],
144 );
145
146 /**
147 * Fetches notification badges and updates the state.
148 */
149 const getNotifications = React.useCallback(async () => {
150 if (!visible) return;
151 try {
152 const output = await Utils.cachedRun(COMMAND, refresh);
153 const notifications = parseNotifications(output).filter(
154 (item) => !exclusionList.includes(item.name.toLowerCase()),
155 );
156 setState(notifications);
157 } catch (error) {
158 // eslint-disable-next-line no-console
159 console.error("Error fetching notifications:", error);
160 setState([]);
161 }
162 setLoading(false);
163 }, [visible, refresh, exclusionList]);
164
165 // Server socket for real-time updates
166 useServerSocket(
167 "notifications",
168 visible,
169 getNotifications,
170 resetWidget,
171 setLoading,
172 );
173
174 // Refresh the widget at the specified interval
175 useWidgetRefresh(visible, getNotifications, refresh);
176
177 // Don't render anything if loading or no notifications
178 if (loading || !state.length) return null;
179
180 return (
181 <div className="notifications">
182 {state.map((app) => (
183 <NotificationPill key={app.bundlePath} app={app} />
184 ))}
185 </div>
186 );
187});
188
189Widget.displayName = "Notifications";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/sound.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/sound.jsx
new file mode 100755
index 0000000..7301426
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/sound.jsx
@@ -0,0 +1,154 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils";
10
11export { soundStyles as styles } from "../../styles/components/data/sound";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 20000;
16
17/**
18 * Sound widget component.
19 * @returns {JSX.Element|null} The sound widget.
20 */
21export const Widget = React.memo(() => {
22 const { displayIndex, settings } = useSimpleBarContext();
23 const { widgets, soundWidgetOptions } = settings;
24 const { soundWidget } = widgets;
25 const { refreshFrequency, showOnDisplay, showIcon } = soundWidgetOptions;
26
27 // Determine the refresh frequency for the widget.
28 const refresh = React.useMemo(
29 () =>
30 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
31 [refreshFrequency],
32 );
33
34 // Determine if the widget should be visible on the current display.
35 const visible =
36 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && soundWidget;
37
38 const [state, setState] = React.useState();
39 const [loading, setLoading] = React.useState(visible);
40 const { volume: _volume } = state || {};
41 const [volume, setVolume] = React.useState(_volume && parseInt(_volume, 10));
42 const [dragging, setDragging] = React.useState(false);
43
44 /**
45 * Reset the widget state.
46 */
47 const resetWidget = () => {
48 setState(undefined);
49 setLoading(false);
50 };
51
52 /**
53 * Fetch the current sound settings.
54 */
55 const getSound = React.useCallback(async () => {
56 if (!visible) return;
57 const output = await Utils.cachedRun(
58 `osascript -e 'set v to get volume settings' -e 'output volume of v & output muted of v'`,
59 refresh,
60 );
61 const parts = Utils.cleanupOutput(output).split(",");
62 setState({
63 volume: parts[0],
64 muted: parts[1],
65 });
66 setLoading(false);
67 }, [visible, refresh]);
68
69 // Use server socket to listen for sound updates.
70 useServerSocket("sound", visible, getSound, resetWidget, setLoading);
71 // Refresh the widget at the specified interval.
72 useWidgetRefresh(visible, getSound, refresh);
73
74 // Update the sound settings when dragging ends.
75 React.useEffect(() => {
76 if (!dragging) setSound(volume);
77 }, [dragging, volume]);
78
79 // Update the volume state when the fetched volume changes.
80 React.useEffect(() => {
81 setVolume((currentVolume) => {
82 if (_volume && currentVolume !== parseInt(_volume, 10)) {
83 return parseInt(_volume, 10);
84 }
85 return currentVolume;
86 });
87 }, [_volume]);
88
89 if (loading) return <DataWidgetLoader.Widget className="sound" />;
90 if (!state || volume === undefined) return null;
91
92 const { muted } = state;
93 if (_volume === "missing value" || muted === "missing value") return null;
94
95 let Icon = Icons.VolumeHigh;
96 if (volume < 50) Icon = Icons.VolumeLow;
97 if (volume < 20) Icon = Icons.NoVolume;
98 if (muted === "true" || !volume) Icon = Icons.VolumeMuted;
99
100 /**
101 * Handle volume change event.
102 * @param {React.ChangeEvent<HTMLInputElement>} e - The change event.
103 */
104 const onChange = (e) => {
105 const value = parseInt(e.target.value, 10);
106 setVolume(value);
107 };
108
109 const onMouseDown = () => setDragging(true);
110 const onMouseUp = () => setDragging(false);
111
112 const formattedVolume = `${volume.toString().padStart(2, "0")}%`;
113
114 const classes = Utils.classNames("sound", {
115 "sound--dragging": dragging,
116 });
117
118 return (
119 <DataWidget.Widget classes={classes} disableSlider>
120 <div className="sound__display">
121 {showIcon && (
122 <SuspenseIcon>
123 <Icon />
124 </SuspenseIcon>
125 )}
126 <span className="sound__value">{formattedVolume}</span>
127 </div>
128 <div className="sound__slider-container">
129 <input
130 type="range"
131 min="0"
132 max="100"
133 step="1"
134 value={volume}
135 className="sound__slider"
136 onMouseDown={onMouseDown}
137 onMouseUp={onMouseUp}
138 onChange={onChange}
139 />
140 </div>
141 </DataWidget.Widget>
142 );
143});
144
145Widget.displayName = "Sound";
146
147/**
148 * Set the system volume.
149 * @param {number} volume - The volume to set.
150 */
151function setSound(volume) {
152 if (volume === undefined) return;
153 Uebersicht.run(`osascript -e 'set volume output volume ${volume}'`);
154}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/specter.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/specter.jsx
new file mode 100755
index 0000000..66b0850
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/specter.jsx
@@ -0,0 +1,24 @@
1import * as Uebersicht from "uebersicht";
2
3export { specterStyles as styles } from "../../styles/components/data/specter";
4
5const { React } = Uebersicht;
6
7/**
8 * Specter widget component
9 *
10 * This component renders a div with six span elements inside it. These are animated in CSS.
11 *
12 * @returns {JSX.Element} The rendered widget component
13 */
14export const Widget = React.memo(() => {
15 return (
16 <div className="specter">
17 {[...new Array(6)].map((_, i) => (
18 <span key={i} />
19 ))}
20 </div>
21 );
22});
23
24Widget.displayName = "Specter";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/spotify.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/spotify.jsx
new file mode 100755
index 0000000..bc9f6e6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/spotify.jsx
@@ -0,0 +1,189 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import useWidgetRefresh from "../../hooks/use-widget-refresh";
5import useServerSocket from "../../hooks/use-server-socket";
6import { useSimpleBarContext } from "../simple-bar-context.jsx";
7import * as Icons from "../icons/icons.jsx";
8import * as Utils from "../../utils";
9
10export { spotifyStyles as styles } from "../../styles/components/data/spotify";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 10000;
15
16/**
17 * Spotify widget component.
18 * @returns {JSX.Element|null} The Spotify widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const { widgets, spotifyWidgetOptions } = settings;
23 const { spotifyWidget } = widgets;
24 const {
25 refreshFrequency,
26 showSpecter,
27 showOnDisplay,
28 showIcon,
29 showSpotifyMetadata,
30 } = spotifyWidgetOptions;
31
32 // Determine the refresh frequency for the widget
33 const refresh = React.useMemo(
34 () =>
35 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
36 [refreshFrequency],
37 );
38
39 // Determine if the widget should be visible
40 const visible =
41 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && spotifyWidget;
42
43 const [state, setState] = React.useState();
44 const [loading, setLoading] = React.useState(visible);
45 const [isSpotifyActive, setIsSpotifyActive] = React.useState(false);
46
47 /**
48 * Resets the widget state.
49 */
50 const resetWidget = () => {
51 setState(undefined);
52 setLoading(false);
53 setIsSpotifyActive(false);
54 };
55
56 /**
57 * Fetches the current Spotify state.
58 */
59 const getSpotify = React.useCallback(async () => {
60 if (!visible) return;
61 const isRunning = await Utils.cachedRun(
62 `pgrep -fq '[S]potify Helper' && echo "true" || echo "false"`,
63 refresh,
64 );
65 if (Utils.cleanupOutput(isRunning) === "false") {
66 setLoading(false);
67 setIsSpotifyActive(false);
68 setState({
69 playerState: "",
70 trackName: "",
71 artistName: "",
72 });
73 return;
74 }
75 // if showSpotifyMetadata is enabled, retrieves all information
76 if (showSpotifyMetadata) {
77 const output = await Utils.cachedRun(
78 `osascript -e 'tell application "Spotify"' -e 'set output to (player state as string) & "|" & (name of current track as string) & "|" & (artist of current track as string)' -e 'end tell' 2>/dev/null || echo "stopped||"`,
79 refresh,
80 );
81 const [playerState, trackName, artistName] =
82 Utils.cleanupOutput(output).split("|");
83 setState({
84 playerState,
85 trackName,
86 artistName,
87 });
88 // else, only playerState
89 } else {
90 const playerState = await Utils.cachedRun(
91 `osascript -e 'tell application "Spotify" to player state as string' 2>/dev/null || echo "stopped"`,
92 refresh,
93 );
94 setState({
95 playerState: Utils.cleanupOutput(playerState),
96 trackName: "",
97 artistName: "",
98 });
99 }
100
101 setIsSpotifyActive(true);
102 setLoading(false);
103 }, [visible, showSpotifyMetadata, refresh]);
104
105 // Set up server socket and widget refresh hooks
106 useServerSocket("spotify", visible, getSpotify, resetWidget, setLoading);
107 useWidgetRefresh(visible, getSpotify, refresh);
108
109 if (loading) return <DataWidgetLoader.Widget className="spotify" />;
110 if (!state || !isSpotifyActive) return null;
111 const { playerState, trackName, artistName } = state;
112
113 if (!trackName.length && showSpotifyMetadata) return null;
114
115 const label = artistName.length ? `${trackName} - ${artistName}` : trackName;
116 const isPlaying = playerState === "playing";
117 const Icon = getIcon(playerState);
118
119 /**
120 * Handles click event to toggle play/pause.
121 * @param {React.MouseEvent} e - The click event.
122 */
123 const onClick = (e) => {
124 Utils.clickEffect(e);
125 togglePlay(!isPlaying);
126 getSpotify();
127 };
128
129 /**
130 * Handles right-click event to skip to the next track.
131 * @param {React.MouseEvent} e - The right-click event.
132 */
133 const onRightClick = (e) => {
134 Utils.clickEffect(e);
135 Uebersicht.run(`osascript -e 'tell application "Spotify" to Next Track'`);
136 getSpotify();
137 };
138
139 /**
140 * Handles middle-click event to open Spotify.
141 * @param {React.MouseEvent} e - The middle-click event.
142 */
143 const onMiddleClick = (e) => {
144 Utils.clickEffect(e);
145 Uebersicht.run(`open -a 'Spotify'`);
146 getSpotify();
147 };
148
149 const classes = Utils.classNames("spotify", {
150 "spotify--hidden-metadata": !showSpotifyMetadata,
151 "spotify--playing": isPlaying,
152 });
153
154 return (
155 <DataWidget.Widget
156 classes={classes}
157 Icon={showIcon ? Icon : null}
158 onClick={onClick}
159 onRightClick={onRightClick}
160 onMiddleClick={onMiddleClick}
161 showSpecter={showSpecter && isPlaying}
162 disableSlider={!showSpotifyMetadata}
163 >
164 {showSpotifyMetadata && label}
165 </DataWidget.Widget>
166 );
167});
168
169Widget.displayName = "Spotify";
170
171/**
172 * Toggles play/pause state of Spotify.
173 * @param {boolean} isPaused - Whether the player is paused.
174 */
175function togglePlay(isPaused) {
176 const state = isPaused ? "play" : "pause";
177 Uebersicht.run(`osascript -e 'tell application "Spotify" to ${state}'`);
178}
179
180/**
181 * Gets the appropriate icon based on the player state.
182 * @param {string} playerState - The current state of the player.
183 * @returns {JSX.Element} The icon component.
184 */
185function getIcon(playerState) {
186 if (playerState === "stopped") return Icons.Stopped;
187 if (playerState === "playing") return Icons.Playing;
188 return Icons.Paused;
189}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/stock.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/stock.jsx
new file mode 100755
index 0000000..4327f1c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/stock.jsx
@@ -0,0 +1,211 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { stockStyles as styles } from "../../styles/components/data/stock";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 15 * 60 * 1000; // 15 min
15
16/**
17 * Stock widget component
18 * @returns {JSX.Element|null} The stock widget
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
22 const { widgets, stockWidgetOptions } = settings;
23 const { stockWidget } = widgets;
24 const {
25 refreshFrequency,
26 yahooFinanceApiKey,
27 symbols,
28 showSymbol,
29 showCurrency,
30 showMarketPrice,
31 showMarketChange,
32 showMarketPercent,
33 showColor,
34 showOnDisplay,
35 showIcon,
36 } = stockWidgetOptions;
37
38 // Determine the refresh frequency for the widget
39 const refresh = React.useMemo(
40 () =>
41 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
42 [refreshFrequency],
43 );
44
45 // Check if the widget should be visible on the current display
46 const visible =
47 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && stockWidget;
48
49 const ref = React.useRef();
50
51 // Memoize cleanedUpSymbols to prevent recreation on every render
52 const cleanedUpSymbols = React.useMemo(
53 () => symbols.replace(/ /g, ""),
54 [symbols],
55 );
56
57 // Memoize enumeratedSymbols to prevent recreation on every render
58 const enumeratedSymbols = React.useMemo(
59 () => cleanedUpSymbols.replace(/ /g, "").split(","),
60 [cleanedUpSymbols],
61 );
62
63 const [state, setState] = React.useState();
64 const [loading, setLoading] = React.useState(visible);
65
66 /**
67 * Reset the widget state
68 */
69 const resetWidget = () => {
70 setState(undefined);
71 setLoading(false);
72 };
73
74 /**
75 * Fetch stock data from Yahoo Finance API
76 */
77 const getStocks = React.useCallback(async () => {
78 if (!visible) return;
79 const response = await fetch(
80 `https://yfapi.net/v6/finance/quote?symbols=${cleanedUpSymbols}`,
81 {
82 headers: new Headers({ "x-api-key": yahooFinanceApiKey }),
83 },
84 );
85 if (response.status === 429) {
86 // Exceeded daily quota
87 } else if (response.status === 403) {
88 Utils.notification("Invalid Yahoo Finance API key", pushMissive);
89 } else if (response.status === 200) {
90 const result = await response.json();
91 const symbolQuotes = result.quoteResponse.result;
92
93 if (symbolQuotes.length !== enumeratedSymbols.length) {
94 // One or more symbols is invalid
95 const receivedSymbols = symbolQuotes.map((s) => s.symbol.toLowerCase());
96 const invalidSymbols = enumeratedSymbols.filter(
97 (s) => !receivedSymbols.includes(s),
98 );
99 Utils.notification("Invalid stock symbol(s): " + invalidSymbols);
100 } else {
101 setState({ symbolQuotes });
102 }
103 } else {
104 // eslint-disable-next-line no-console
105 console.error("Unexpected response from Yahoo Finance API: ", response);
106 }
107
108 setLoading(false);
109 }, [
110 visible,
111 cleanedUpSymbols,
112 yahooFinanceApiKey,
113 pushMissive,
114 enumeratedSymbols,
115 ]);
116
117 // Use server socket to fetch stock data
118 useServerSocket("stock", visible, getStocks, resetWidget, setLoading);
119 // Refresh widget data periodically
120 useWidgetRefresh(visible, getStocks, refresh);
121
122 /**
123 * Refresh stock data on user interaction
124 * @param {Event} e - The event object
125 */
126 const refreshStocks = (e) => {
127 Utils.clickEffect(e);
128 setLoading(true);
129 getStocks();
130 };
131
132 if (loading) return <DataWidgetLoader.Widget className="stock" />;
133 if (!state || !state.symbolQuotes) return null;
134
135 return enumeratedSymbols.map((symbolName, i) => {
136 const symbolQuote = state.symbolQuotes[i];
137 const symbol = symbolQuote.symbol;
138 const currencySymbol = getCurrencySymbol(symbolQuote.currency);
139 const marketPrice = Number(symbolQuote.regularMarketPrice).toFixed(2);
140 const marketChange = Number(symbolQuote.regularMarketChange).toFixed(2);
141 const marketPercentChange = Number(
142 symbolQuote.regularMarketChangePercent,
143 ).toFixed(2);
144 const stockUp = !marketChange.startsWith("-");
145
146 return (
147 <DataWidget.Widget
148 key={symbolName}
149 classes="stock"
150 ref={ref}
151 Icon={showIcon ? (stockUp ? Icons.UpArrow : Icons.DownArrow) : null}
152 href={`https://finance.yahoo.com/quote/${symbolName}`}
153 onClick={openStock}
154 onRightClick={refreshStocks}
155 >
156 <span>
157 {showSymbol && symbol}
158 {(showCurrency || showMarketPrice) && showSymbol && (
159 <span>&nbsp;</span>
160 )}
161 {showCurrency && currencySymbol}
162 {showMarketPrice && marketPrice}
163 </span>
164 <span className={showColor ? (stockUp ? "stockUp" : "stockDown") : ""}>
165 {(showMarketChange || showMarketPercent) && <span>&nbsp;</span>}
166 {showMarketChange && formatPriceChange(marketChange)}
167 {showMarketPercent &&
168 showMarketChange &&
169 ` (${formatPriceChange(marketPercentChange)}%)`}
170 {showMarketPercent &&
171 !showMarketChange &&
172 `${formatPriceChange(marketPercentChange)}%`}
173 </span>
174 </DataWidget.Widget>
175 );
176 });
177});
178
179Widget.displayName = "Stock";
180
181/**
182 * Handle click event to open stock details
183 * @param {Event} e - The event object
184 */
185function openStock(e) {
186 Utils.clickEffect(e);
187}
188
189/**
190 * Get the currency symbol for a given currency code
191 * @param {string} currency - The currency code
192 * @returns {string} The currency symbol
193 */
194function getCurrencySymbol(currency) {
195 if (currency === "EUR") return "€";
196 if (currency === "USD") return "$";
197 if (currency === "GBP") return "£";
198 if (currency === "CNY") return "Â¥";
199 if (currency === "JPY") return "Â¥";
200 return `${currency} `;
201}
202
203/**
204 * Format the price change with a '+' for positive changes
205 * @param {string} priceChange - The price change
206 * @returns {string} The formatted price change
207 */
208function formatPriceChange(priceChange) {
209 // Add a '+' for positive changes
210 return (priceChange.startsWith("-") ? "" : "+") + priceChange;
211}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx
new file mode 100755
index 0000000..6890ffb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/time.jsx
@@ -0,0 +1,144 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import useWidgetRefresh from "../../hooks/use-widget-refresh";
5import useServerSocket from "../../hooks/use-server-socket";
6import { useSimpleBarContext } from "../simple-bar-context.jsx";
7import * as Utils from "../../utils";
8
9export { timeStyles as styles } from "../../styles/components/data/time";
10
11const { React } = Uebersicht;
12
13const DEFAULT_REFRESH_FREQUENCY = 1000;
14
15/**
16 * Time widget component.
17 * @returns {JSX.Element|null} The rendered widget.
18 */
19export const Widget = React.memo(() => {
20 const { displayIndex, settings } = useSimpleBarContext();
21 const { widgets, timeWidgetOptions } = settings;
22 const { timeWidget } = widgets;
23 const {
24 refreshFrequency,
25 hour12,
26 dayProgress,
27 showSeconds,
28 showOnDisplay,
29 showIcon,
30 } = timeWidgetOptions;
31
32 // Determine if the widget should be visible on the current display
33 const visible =
34 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && timeWidget;
35
36 // Calculate the refresh frequency for the widget
37 const refresh = React.useMemo(
38 () =>
39 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
40 [refreshFrequency],
41 );
42
43 const [state, setState] = React.useState();
44 const [loading, setLoading] = React.useState(visible);
45
46 // Options for formatting the time string
47 const options = React.useMemo(
48 () => ({
49 hour: "numeric",
50 minute: "numeric",
51 second: showSeconds ? "numeric" : undefined,
52 hour12,
53 }),
54 [hour12, showSeconds],
55 );
56
57 /**
58 * Resets the widget state.
59 */
60 const resetWidget = () => {
61 setState(undefined);
62 setLoading(false);
63 };
64
65 /**
66 * Fetches the current time and updates the widget state.
67 */
68 const getTime = React.useCallback(() => {
69 if (!visible) return;
70 const time = new Date().toLocaleString("en-UK", options);
71 setState({ time });
72 setLoading(false);
73 }, [visible, options]);
74
75 // Use server socket to get time updates
76 useServerSocket("time", visible, getTime, resetWidget, setLoading);
77 // Refresh the widget at the specified interval
78 useWidgetRefresh(visible, getTime, refresh);
79
80 if (loading) return <DataWidgetLoader.Widget className="time" />;
81 if (!state) return null;
82 const { time } = state;
83
84 // Calculate the progress of the current day
85 const [dayStart, dayEnd] = [new Date(), new Date()];
86 dayStart.setHours(0, 0, 0);
87 dayEnd.setHours(0, 0, 0);
88 dayEnd.setDate(dayEnd.getDate() + 1);
89 const range = dayEnd - dayStart;
90 const diff = Math.max(0, dayEnd - new Date());
91 const fillerWidth = (100 - (100 * diff) / range) / 100;
92
93 /**
94 * Icon component for the time widget.
95 * @returns {JSX.Element} The rendered icon.
96 */
97 const TimeIcon = () => {
98 return <Icon time={time} />;
99 };
100
101 return (
102 <DataWidget.Widget
103 classes="time"
104 Icon={showIcon ? TimeIcon : null}
105 disableSlider
106 >
107 {time}
108 {dayProgress && (
109 <div
110 className="time__filler"
111 style={{ transform: `scaleX(${fillerWidth})` }}
112 />
113 )}
114 </DataWidget.Widget>
115 );
116});
117
118Widget.displayName = "Time";
119
120/**
121 * Icon component for displaying the time as a clock.
122 * @param {Object} props - The component props.
123 * @param {string} props.time - The current time string.
124 * @returns {JSX.Element} The rendered icon.
125 */
126function Icon({ time }) {
127 const [hours, minutes] = time.split(":");
128
129 const hoursInDegree = ((parseInt(hours, 10) % 12) / 12) * 360;
130 const minutesInDegree = (parseInt(minutes, 10) / 60) * 360;
131
132 return (
133 <div className="time__icon">
134 <div
135 className="time__hours"
136 style={{ transform: `rotate(${hoursInDegree}deg)` }}
137 />
138 <div
139 className="time__minutes"
140 style={{ transform: `rotate(${minutesInDegree}deg)` }}
141 />
142 </div>
143 );
144}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/user-widgets.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/user-widgets.jsx
new file mode 100755
index 0000000..efa9876
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/user-widgets.jsx
@@ -0,0 +1,181 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Settings from "../../settings";
9import * as Utils from "../../utils";
10
11const { React } = Uebersicht;
12
13export default React.memo(UserWidgets);
14
15/**
16 * UserWidgets component that renders a list of user-defined widgets.
17 * @returns {JSX.Element[]} Array of UserWidget components.
18 */
19function UserWidgets() {
20 const { settings } = useSimpleBarContext();
21 const { userWidgetsList } = settings.userWidgets;
22
23 // Get the keys of the userWidgetsList object
24 const keys = Object.keys(userWidgetsList);
25
26 // Map over the keys and render a UserWidget for each key
27 return keys.map((key) => (
28 <UserWidget key={key} index={key} widget={userWidgetsList[key]} />
29 ));
30}
31
32UserWidgets.displayName = "UserWidgets";
33
34/**
35 * UserWidget component that renders an individual user-defined widget.
36 * @param {Object} props - The component props.
37 * @param {string} props.index - The index of the widget.
38 * @param {Object} props.widget - The widget configuration object.
39 * @returns {JSX.Element|null} The rendered UserWidget component or null if not visible.
40 */
41const UserWidget = React.memo(({ index, widget }) => {
42 const { displayIndex, settings } = useSimpleBarContext();
43 const [state, setState] = React.useState();
44 const [loading, setLoading] = React.useState(true);
45 const [isWidgetActive, setIsWidgetActive] = React.useState(true);
46 const {
47 icon,
48 backgroundColor,
49 output,
50 onClickAction,
51 onRightClickAction,
52 onMiddleClickAction,
53 refreshFrequency,
54 active,
55 noIcon,
56 hideWhenNoOutput = true,
57 showOnDisplay = "",
58 } = widget;
59
60 // Determine if the widget should be visible based on display settings and active status
61 const visible =
62 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && active;
63
64 /**
65 * Resets the widget state and loading status.
66 */
67 const resetWidget = () => {
68 setState(undefined);
69 setLoading(false);
70 setIsWidgetActive(true);
71 };
72
73 /**
74 * Fetches the widget output and updates the state.
75 */
76 const getUserWidget = React.useCallback(async () => {
77 if (!visible) return;
78 const widgetOutput = await Utils.cachedRun(output, refreshFrequency);
79 const cleanedOutput = Utils.cleanupOutput(widgetOutput);
80
81 // Hide widget if script returns empty output and hideWhenNoOutput is enabled
82 if (
83 hideWhenNoOutput &&
84 (!cleanedOutput.length || cleanedOutput.trim() === "")
85 ) {
86 setLoading(false);
87 setIsWidgetActive(false);
88 setState(undefined);
89 return;
90 }
91
92 setState(widgetOutput);
93 setIsWidgetActive(true);
94 setLoading(false);
95 }, [visible, output, hideWhenNoOutput, refreshFrequency]);
96
97 // Use server socket to listen for widget updates
98 useServerSocket(
99 "user-widget",
100 visible,
101 getUserWidget,
102 resetWidget,
103 setLoading,
104 index,
105 );
106
107 // Refresh the widget at the specified frequency
108 useWidgetRefresh(visible, getUserWidget, refreshFrequency);
109
110 // Hide widget if not visible or if script indicates it should be inactive (only when hideWhenNoOutput is enabled)
111 if (!visible || (hideWhenNoOutput && !isWidgetActive)) return null;
112
113 const isCustomColor = !Settings.userWidgetColors.includes(backgroundColor);
114
115 const property = settings.global.widgetsBackgroundColorAsForeground
116 ? "color"
117 : "backgroundColor";
118
119 const style = settings.global.noColorInData
120 ? undefined
121 : {
122 [property]: isCustomColor ? backgroundColor : `var(${backgroundColor})`,
123 };
124
125 if (loading) return <DataWidgetLoader.Widget style={style} />;
126
127 const Icon = !noIcon ? Icons[icon] : null;
128
129 const hasOnClickAction = onClickAction?.trim().length > 0;
130 const hasRightClickAction = onRightClickAction?.trim().length > 0;
131 const hasMiddleClickAction = onMiddleClickAction?.trim().length > 0;
132
133 /**
134 * Handles the click event for the widget.
135 * @param {Event} e - The click event.
136 */
137 const onClick = async (e) => {
138 Utils.clickEffect(e);
139 await Uebersicht.run(onClickAction);
140 getUserWidget();
141 };
142
143 /**
144 * Handles the right-click event for the widget.
145 * @param {Event} e - The right-click event.
146 */
147 const onRightClick = async (e) => {
148 Utils.clickEffect(e);
149 await Uebersicht.run(onRightClickAction);
150 getUserWidget();
151 };
152
153 /**
154 * Handles the middle-click event for the widget.
155 * @param {Event} e - The middle-click event.
156 */
157 const onMiddleClick = async (e) => {
158 Utils.clickEffect(e);
159 await Uebersicht.run(onMiddleClickAction);
160 getUserWidget();
161 };
162
163 const onClickProps = {
164 onClick: hasOnClickAction ? onClick : undefined,
165 onRightClick: hasRightClickAction ? onRightClick : undefined,
166 onMiddleClick: hasMiddleClickAction ? onMiddleClick : undefined,
167 };
168
169 return (
170 <DataWidget.Widget
171 classes={`user-widget user-widget--${index}`}
172 Icon={Icon}
173 style={style}
174 {...onClickProps}
175 >
176 {state}
177 </DataWidget.Widget>
178 );
179});
180
181UserWidget.displayName = "UserWidget";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/viscosity-vpn.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/viscosity-vpn.jsx
new file mode 100755
index 0000000..340c59b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/viscosity-vpn.jsx
@@ -0,0 +1,144 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { viscosityVPNStyles as styles } from "../../styles/components/data/viscosity-vpn";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 8000;
15
16/**
17 * Viscosity VPN Widget component.
18 * @returns {JSX.Element|null} The Viscosity VPN widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
22 const { widgets, vpnWidgetOptions } = settings;
23 const { vpnWidget } = widgets;
24 const {
25 refreshFrequency,
26 vpnConnectionName,
27 vpnShowConnectionName,
28 showOnDisplay,
29 showIcon,
30 } = vpnWidgetOptions;
31
32 // Determine the refresh frequency for the widget
33 const refresh = React.useMemo(
34 () =>
35 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
36 [refreshFrequency],
37 );
38
39 // Determine if the widget should be visible
40 const visible =
41 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && vpnWidget;
42
43 const [state, setState] = React.useState();
44 const [loading, setLoading] = React.useState(visible);
45 const [isViscosityActive, setIsViscosityActive] = React.useState(false);
46
47 /**
48 * Reset the widget state.
49 */
50 const resetWidget = () => {
51 setState(undefined);
52 setLoading(false);
53 setIsViscosityActive(false);
54 };
55
56 /**
57 * Fetch the current VPN status.
58 */
59 const getVPN = React.useCallback(async () => {
60 if (!visible) return;
61 const isRunning = await Utils.cachedRun(
62 `pgrep -xq 'Viscosity' && echo "true" || echo "false"`,
63 refresh,
64 );
65 if (Utils.cleanupOutput(isRunning) === "false") {
66 setLoading(false);
67 setIsViscosityActive(false);
68 return;
69 }
70 const status = await Utils.cachedRun(
71 `osascript -e "tell application \\"Viscosity\\" to return state of the first connection where name is equal to \\"${vpnConnectionName}\\"" 2>/dev/null`,
72 refresh,
73 );
74 if (!status.length) return;
75 setState({ status: Utils.cleanupOutput(status) });
76 setIsViscosityActive(true);
77 setLoading(false);
78 }, [visible, vpnConnectionName, refresh]);
79
80 // Use server socket to listen for VPN status updates
81 useServerSocket("viscosity-vpn", visible, getVPN, resetWidget, setLoading);
82 // Refresh the widget at the specified interval
83 useWidgetRefresh(visible, getVPN, refresh);
84
85 if (loading) return <DataWidgetLoader.Widget className="viscosity-vpn" />;
86 if (!state || !vpnConnectionName.length || !isViscosityActive) return null;
87
88 const { status } = state;
89 const isConnected = status === "Connected";
90
91 const classes = Utils.classNames("viscosity-vpn", {
92 "viscosity-vpn--disconnected": !isConnected,
93 });
94
95 const Icon = isConnected ? Icons.VPN : Icons.VPNOff;
96
97 /**
98 * Handle click event to toggle VPN connection.
99 * @param {Event} e - The click event.
100 */
101 const clicked = (e) => {
102 Utils.clickEffect(e);
103 toggleVPN(isConnected, vpnConnectionName, pushMissive);
104 setTimeout(getVPN, refreshFrequency / 2);
105 };
106
107 return (
108 <DataWidget.Widget
109 classes={classes}
110 Icon={showIcon ? Icon : null}
111 onClick={clicked}
112 >
113 {vpnShowConnectionName ? vpnConnectionName : status}
114 </DataWidget.Widget>
115 );
116});
117
118Widget.displayName = "ViscosityVPN";
119
120/**
121 * Toggle the VPN connection.
122 * @param {boolean} isConnected - Whether the VPN is currently connected.
123 * @param {string} vpnConnectionName - The name of the VPN connection.
124 * @param {function} pushMissive - Function to push notifications.
125 */
126function toggleVPN(isConnected, vpnConnectionName, pushMissive) {
127 if (isConnected) {
128 Uebersicht.run(
129 `osascript -e 'tell application "Viscosity" to disconnect "${vpnConnectionName}"'`,
130 );
131 Utils.notification(
132 `Disabling Viscosity ${vpnConnectionName} network...`,
133 pushMissive,
134 );
135 } else {
136 Uebersicht.run(
137 `osascript -e 'tell application "Viscosity" to connect "${vpnConnectionName}"'`,
138 );
139 Utils.notification(
140 `Enabling Viscosity ${vpnConnectionName} network...`,
141 pushMissive,
142 );
143 }
144}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/weather.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/weather.jsx
new file mode 100755
index 0000000..946fda1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/weather.jsx
@@ -0,0 +1,214 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import * as Utils from "../../utils";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9
10export { weatherStyles as styles } from "../../styles/components/data/weather";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 1000 * 60 * 30; // Default refresh frequency set to 30 minutes
15
16/**
17 * Weather widget component
18 */
19export const Widget = React.memo(() => {
20 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
21 const { widgets, weatherWidgetOptions } = settings;
22 const { weatherWidget } = widgets;
23 const {
24 refreshFrequency,
25 customLocation,
26 unit,
27 hideLocation,
28 hideGradient,
29 showOnDisplay,
30 showIcon,
31 } = weatherWidgetOptions;
32
33 const refresh = React.useMemo(
34 () =>
35 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
36 [refreshFrequency],
37 );
38
39 const visible =
40 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && weatherWidget;
41
42 const [state, setState] = React.useState();
43 const [loading, setLoading] = React.useState(visible);
44 const location = React.useRef(
45 visible && customLocation.length ? customLocation : undefined,
46 );
47
48 /**
49 * Resets the widget state and loading status
50 */
51 const resetWidget = () => {
52 setState(undefined);
53 setLoading(false);
54 };
55
56 /**
57 * Fetches weather data from wttr.in
58 */
59 const getWeather = React.useCallback(async () => {
60 if (!visible) return;
61 if (!location.current) {
62 const position = await Promise.race([getPosition(), Utils.timeout(5000)]);
63 if (!position) await getWeather();
64 const { city, zip } = position?.address || {};
65 location.current = zip || city;
66 if (!location.current) return setLoading(false);
67 }
68 try {
69 const result = await fetch(
70 `https://wttr.in/${location.current}?format=j1`,
71 );
72 const data = await result.json();
73 setState({ location: location.current, data });
74 } catch {
75 // eslint-disable-next-line no-console
76 console.error("Error while fetching weather")
77 }
78 setLoading(false);
79 }, [visible, location]);
80
81 useServerSocket("weather", visible, getWeather, resetWidget, setLoading);
82 useWidgetRefresh(visible, getWeather, refresh);
83
84 if (loading) return <DataWidgetLoader.Widget className="weather" />;
85 if (!state || !state.data.current_condition) return null;
86
87 const {
88 temp_C: tempC,
89 temp_F: tempF,
90 weatherDesc,
91 } = state.data.current_condition[0];
92 const temperature = unit === "C" ? tempC : tempF;
93 const wttrUnitParam = unit === "C" ? "?m" : "?u";
94
95 const description = weatherDesc[0].value;
96
97 const { astronomy } = state.data.weather[0];
98 const sunriseData = astronomy[0].sunrise.replace(" AM", "").split(":");
99 const sunsetData = astronomy[0].sunset.replace(" PM", "").split(":");
100
101 const now = new Date();
102 const nowIntervalStart = new Date();
103 nowIntervalStart.setHours(nowIntervalStart.getHours() - 1);
104 const nowIntervalStop = new Date();
105 nowIntervalStop.setHours(nowIntervalStop.getHours() + 1);
106 const sunriseTime = new Date();
107 sunriseTime.setHours(
108 parseInt(sunriseData[0], 10),
109 parseInt(sunriseData[1], 10),
110 0,
111 0,
112 );
113 const sunsetTime = new Date();
114 sunsetTime.setHours(
115 parseInt(sunsetData[0], 10) + 12,
116 parseInt(sunsetData[1], 10),
117 0,
118 0,
119 );
120
121 const atNight = sunriseTime >= now || now >= sunsetTime;
122
123 const Icon = getIcon(description, atNight);
124 const label = getLabel(state.location, temperature, unit, hideLocation);
125
126 const sunRising =
127 sunriseTime >= nowIntervalStart && sunriseTime <= nowIntervalStop;
128 const sunSetting =
129 sunsetTime >= nowIntervalStart && sunsetTime <= nowIntervalStop;
130
131 /**
132 * Handles right-click event to refresh weather data
133 * @param {Event} e - The event object
134 */
135 const onRightClick = (e) => {
136 Utils.clickEffect(e);
137 setLoading(true);
138 getWeather();
139 Utils.notification("Refreshing forecast from wttr.in...", pushMissive);
140 };
141
142 const classes = Utils.classNames("weather", {
143 "weather--sunrise": sunRising,
144 "weather--sunset": sunSetting,
145 });
146
147 return (
148 <DataWidget.Widget
149 classes={classes}
150 Icon={showIcon ? Icon : null}
151 href={`https://wttr.in/${state.location}${wttrUnitParam}`}
152 onClick={(e) => openWeather(e, pushMissive)}
153 onRightClick={onRightClick}
154 disableSlider
155 >
156 {!hideGradient && <div className="weather__gradient" />}
157 {label}
158 </DataWidget.Widget>
159 );
160});
161
162Widget.displayName = "Weather";
163
164/**
165 * Returns the appropriate weather icon based on the description and time of day
166 * @param {string} description - Weather description
167 * @param {boolean} atNight - Whether it is currently night time
168 * @returns {JSX.Element} - The weather icon component
169 */
170function getIcon(description, atNight) {
171 if (description.includes("fog") || description.includes("mist")) {
172 return Icons.Fog;
173 }
174 if (description.includes("storm")) return Icons.Storm;
175 if (description.includes("snow")) return Icons.Snow;
176 if (description.includes("rain")) return Icons.Rain;
177 if (description.includes("cloud")) return Icons.Cloud;
178 if (atNight) return Icons.Moon;
179 return Icons.Sun;
180}
181
182/**
183 * Returns the label for the weather widget
184 * @param {string} location - The location name
185 * @param {string} temperature - The temperature value
186 * @param {string} unit - The temperature unit (C or F)
187 * @param {boolean} hideLocation - Whether to hide the location name
188 * @returns {string} - The label text
189 */
190function getLabel(location, temperature, unit, hideLocation) {
191 if (!location) return "Fetching...";
192 if (hideLocation) return `${temperature}°${unit}`;
193 return `${location}, ${temperature}°${unit}`;
194}
195
196/**
197 * Opens the weather forecast in a new tab
198 * @param {Event} e - The event object
199 * @param {Function} pushMissive - Function to push notifications
200 */
201function openWeather(e, pushMissive) {
202 Utils.clickEffect(e);
203 Utils.notification("Opening forecast from wttr.in...", pushMissive);
204}
205
206/**
207 * Gets the current geographical position of the user
208 * @returns {Promise<GeolocationPosition>} - The position object
209 */
210async function getPosition() {
211 return new Promise((resolve) =>
212 navigator.geolocation.getCurrentPosition(resolve),
213 );
214}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/wifi.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/wifi.jsx
new file mode 100755
index 0000000..c7bedcd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/wifi.jsx
@@ -0,0 +1,154 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import useWidgetRefresh from "../../hooks/use-widget-refresh";
6import useServerSocket from "../../hooks/use-server-socket";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9
10export { wifiStyles as styles } from "../../styles/components/data/wifi";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 20000;
15
16/**
17 * Wifi widget component.
18 * @returns {JSX.Element|null} The Wifi widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings, pushMissive } = useSimpleBarContext();
22 const { widgets, networkWidgetOptions } = settings;
23 const { wifiWidget } = widgets;
24 const {
25 refreshFrequency,
26 hideWifiIfDisabled,
27 toggleWifiOnClick,
28 networkDevice,
29 hideNetworkName,
30 showOnDisplay,
31 showIcon,
32 } = networkWidgetOptions;
33 const visible =
34 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && wifiWidget;
35
36 const refresh = React.useMemo(
37 () =>
38 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
39 [refreshFrequency],
40 );
41
42 const [state, setState] = React.useState();
43 const [loading, setLoading] = React.useState(visible);
44
45 /**
46 * Resets the widget state.
47 */
48 const resetWidget = () => {
49 setState(undefined);
50 setLoading(false);
51 };
52
53 /**
54 * Fetches the wifi status and SSID.
55 */
56 const getWifi = React.useCallback(async () => {
57 if (!visible) return;
58 const [status, ssid] = await Promise.all([
59 Utils.cachedRun(
60 `ifconfig ${networkDevice} | grep status | cut -c 10-`,
61 refresh,
62 ),
63 Utils.cachedRun(
64 `system_profiler SPAirPortDataType | awk '/Current Network/ {getline;$1=$1;print $0 | "tr -d ':'";exit}'`,
65 refresh,
66 ),
67 ]);
68 setState({
69 status: Utils.cleanupOutput(status),
70 ssid: Utils.cleanupOutput(ssid),
71 });
72 setLoading(false);
73 }, [networkDevice, visible, refresh]);
74
75 useServerSocket("wifi", visible, getWifi, resetWidget, setLoading);
76 useWidgetRefresh(visible, getWifi, refresh);
77
78 if (loading) return <DataWidgetLoader.Widget className="wifi" />;
79 if (!state) return null;
80
81 const { status, ssid } = state;
82 const isActive = status === "active";
83 const name = renderName(ssid, hideNetworkName);
84
85 if (hideWifiIfDisabled && !isActive) return null;
86
87 const classes = Utils.classNames("wifi", {
88 "wifi--hidden-name": !name,
89 "wifi--inactive": !isActive,
90 });
91
92 const Icon = isActive ? Icons.Wifi : Icons.WifiOff;
93
94 /**
95 * Handles the click event to toggle wifi.
96 * @param {React.MouseEvent} e - The click event.
97 */
98 const onClick = async (e) => {
99 Utils.clickEffect(e);
100 await toggleWifi(isActive, networkDevice, pushMissive);
101 getWifi();
102 };
103
104 return (
105 <DataWidget.Widget
106 classes={classes}
107 Icon={showIcon ? Icon : null}
108 onClick={toggleWifiOnClick ? onClick : undefined}
109 onRightClick={openWifiPreferences}
110 >
111 {name}
112 </DataWidget.Widget>
113 );
114});
115
116Widget.displayName = "Wifi";
117
118/**
119 * Toggles the wifi on or off.
120 * @param {boolean} isActive - Whether the wifi is currently active.
121 * @param {string} networkDevice - The network device name.
122 * @param {function} pushMissive - Function to push notifications.
123 */
124async function toggleWifi(isActive, networkDevice, pushMissive) {
125 if (isActive) {
126 await Uebersicht.run(`networksetup -setairportpower ${networkDevice} off`);
127 Utils.notification("Disabling network...", pushMissive);
128 } else {
129 await Uebersicht.run(`networksetup -setairportpower ${networkDevice} on`);
130 Utils.notification("Enabling network...", pushMissive);
131 }
132}
133
134/**
135 * Opens the wifi preferences pane.
136 * @param {React.MouseEvent} e - The click event.
137 */
138function openWifiPreferences(e) {
139 Utils.clickEffect(e);
140 Uebersicht.run(`open /System/Library/PreferencePanes/Network.prefPane/`);
141}
142
143/**
144 * Renders the wifi network name.
145 * @param {string} name - The network name.
146 * @param {boolean} hideNetworkName - Whether to hide the network name.
147 * @returns {string} The rendered network name.
148 */
149function renderName(name, hideNetworkName) {
150 if (!name || hideNetworkName) return "";
151 if (name === "with an AirPort network.y off.") return "Disabled";
152 if (name === "with an AirPort network.") return "Searching...";
153 return name;
154}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/youtube-music.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/youtube-music.jsx
new file mode 100755
index 0000000..bf586b1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/youtube-music.jsx
@@ -0,0 +1,191 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import useWidgetRefresh from "../../hooks/use-widget-refresh";
5import useServerSocket from "../../hooks/use-server-socket";
6import { useSimpleBarContext } from "../simple-bar-context.jsx";
7import * as Icons from "../icons/icons.jsx";
8import * as Utils from "../../utils";
9
10export { youtubeMusicStyles as styles } from "../../styles/components/data/youtube-music";
11
12const { React } = Uebersicht;
13
14const DEFAULT_REFRESH_FREQUENCY = 10000;
15
16/**
17 * YouTube Music Widget component.
18 * @returns {JSX.Element} The YouTube Music widget.
19 */
20export const Widget = React.memo(() => {
21 const { displayIndex, settings } = useSimpleBarContext();
22 const {
23 widgets: { youtubeMusicWidget },
24 youtubeMusicWidgetOptions: {
25 refreshFrequency,
26 showSpecter,
27 showOnDisplay,
28 youtubeMusicPort,
29 showIcon,
30 },
31 } = settings;
32
33 // Determine the refresh frequency for the widget
34 const refresh = React.useMemo(
35 () =>
36 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
37 [refreshFrequency],
38 );
39
40 // Determine if the widget should be visible on the current display
41 const visible =
42 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && youtubeMusicWidget;
43
44 const [state, setState] = React.useState();
45 const [cachedAccessToken, setCachedAccessToken] = React.useState();
46 const [loading, setLoading] = React.useState(visible);
47
48 const apiUrl = `http://localhost:${youtubeMusicPort}`;
49
50 /**
51 * Resets the widget state.
52 */
53 const resetWidget = () => {
54 setState(undefined);
55 setCachedAccessToken(undefined);
56 setLoading(false);
57 };
58
59 /**
60 * Fetches the access token for the YouTube Music API.
61 * @returns {Promise<string>} The access token.
62 */
63 const getAccessToken = React.useCallback(async () => {
64 // As of 2024/12/01, the generated access tokens don't expire
65 if (cachedAccessToken) return cachedAccessToken;
66
67 const response = await fetch(`${apiUrl}/auth/simple-bar`, {
68 method: "POST",
69 });
70 const json = await response.json();
71 setCachedAccessToken(json.accessToken);
72 return json.accessToken;
73 }, [apiUrl, cachedAccessToken]);
74
75 /**
76 * Fetches data from a specified route.
77 * @param {string} route - The API route to fetch data from.
78 * @param {string} [method="POST"] - The HTTP method to use.
79 * @returns {Promise<Response>} The fetch response.
80 */
81 const fetchRoute = React.useCallback(
82 async (route, method = "POST") => {
83 const headers = {};
84 const url = new URL(route, apiUrl);
85
86 // All routes under /api are protected
87 const needsAuthentication = url.pathname.startsWith("/api");
88 if (needsAuthentication) {
89 const accessToken = await getAccessToken();
90 if (!accessToken) {
91 throw new Error("Failed to get access token");
92 }
93 headers.Authorization = `Bearer ${accessToken}`;
94 }
95
96 return await fetch(url, { method, headers });
97 },
98 [apiUrl, getAccessToken],
99 );
100
101 /**
102 * Refreshes the widget state by fetching the current song info.
103 */
104 const refreshState = React.useCallback(async () => {
105 if (!visible) return;
106
107 try {
108 const response = await fetchRoute("/api/v1/song-info", "GET");
109 const json = await response.json();
110 setState(json);
111 } catch {
112 // most likely due to offline server, reset state
113 resetWidget();
114 }
115 }, [visible, fetchRoute]);
116
117 // Use server socket to listen for updates
118 useServerSocket(
119 "youtube-music",
120 visible,
121 refreshState,
122 resetWidget,
123 setLoading,
124 );
125 // Use widget refresh hook to periodically refresh the state
126 useWidgetRefresh(visible, refreshState, refresh);
127
128 if (loading) return <DataWidgetLoader.Widget className="youtube-music" />;
129
130 /**
131 * Handles click event to toggle play/pause.
132 * @param {React.MouseEvent} e - The click event.
133 */
134 const onClick = async (e) => {
135 Utils.clickEffect(e);
136 await fetchRoute("/api/v1/toggle-play");
137 await refreshState();
138 };
139
140 /**
141 * Handles right-click event to skip to the next song.
142 * @param {React.MouseEvent} e - The right-click event.
143 */
144 const onRightClick = async (e) => {
145 Utils.clickEffect(e);
146 await fetchRoute("/api/v1/next");
147 await refreshState();
148 };
149
150 /**
151 * Handles middle-click event to open YouTube Music app.
152 * @param {React.MouseEvent} e - The middle-click event.
153 */
154 const onMiddleClick = async (e) => {
155 Utils.clickEffect(e);
156 Uebersicht.run(`open -a 'YouTube Music'`);
157 await refreshState();
158 };
159
160 const classes = Utils.classNames("youtube-music", {});
161 if (!state) return null;
162 const { title, artist, isPaused } = state;
163 if (!title) return null;
164
165 const label = artist.length ? `${title} - ${artist}` : title;
166 const Icon = getIcon(isPaused);
167
168 return (
169 <DataWidget.Widget
170 classes={classes}
171 Icon={showIcon ? Icon : null}
172 onClick={onClick}
173 onRightClick={onRightClick}
174 onMiddleClick={onMiddleClick}
175 showSpecter={showSpecter && !isPaused}
176 >
177 {label}
178 </DataWidget.Widget>
179 );
180});
181
182Widget.displayName = "YouTube Music";
183
184/**
185 * Returns the appropriate icon based on the play/pause state.
186 * @param {boolean} isPaused - Whether the music is paused.
187 * @returns {JSX.Element} The icon component.
188 */
189function getIcon(isPaused) {
190 return isPaused ? Icons.Paused : Icons.Playing;
191}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/zoom.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/zoom.jsx
new file mode 100755
index 0000000..2c123e9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/data/zoom.jsx
@@ -0,0 +1,107 @@
1import * as Uebersicht from "uebersicht";
2import * as DataWidget from "./data-widget.jsx";
3import * as DataWidgetLoader from "./data-widget-loader.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import useWidgetRefresh from "../../hooks/use-widget-refresh";
7import useServerSocket from "../../hooks/use-server-socket";
8import { useSimpleBarContext } from "../simple-bar-context.jsx";
9import * as Utils from "../../utils";
10
11export { zoomStyles as styles } from "../../styles/components/data/zoom";
12
13const { React } = Uebersicht;
14
15const DEFAULT_REFRESH_FREQUENCY = 5000;
16
17/**
18 * Zoom widget component.
19 * @returns {JSX.Element|null} The Zoom widget.
20 */
21export const Widget = React.memo(() => {
22 const { displayIndex, settings } = useSimpleBarContext();
23 const { widgets, zoomWidgetOptions } = settings;
24 const { zoomWidget } = widgets;
25 const { refreshFrequency, showVideo, showMic, showOnDisplay } =
26 zoomWidgetOptions;
27
28 // Determine the refresh frequency for the widget
29 const refresh = React.useMemo(
30 () =>
31 Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
32 [refreshFrequency],
33 );
34
35 // Determine if the widget should be visible
36 const visible =
37 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && zoomWidget;
38
39 const [state, setState] = React.useState();
40 const [loading, setLoading] = React.useState(visible);
41
42 /**
43 * Reset the widget state.
44 */
45 const resetWidget = React.useCallback(() => {
46 setState(undefined);
47 setLoading(false);
48 }, []);
49
50 /**
51 * Fetch the Zoom status for mic and video.
52 */
53 const getZoom = React.useCallback(async () => {
54 if (!visible) return;
55 try {
56 const [mic, video] = await Promise.all([
57 Utils.cachedRun(
58 `osascript ./simple-bar/lib/scripts/zoom-mute-status.applescript`,
59 refresh,
60 ),
61 Utils.cachedRun(
62 `osascript ./simple-bar/lib/scripts/zoom-video-status.applescript`,
63 refresh,
64 ),
65 ]);
66 setState({
67 mic: Utils.cleanupOutput(mic),
68 video: Utils.cleanupOutput(video),
69 });
70 setLoading(false);
71 } catch (error) {
72 // eslint-disable-next-line no-console
73 console.error("Error fetching Zoom status:", error);
74 setLoading(false);
75 }
76 }, [visible, refresh]);
77
78 // Use server socket to listen for Zoom events
79 useServerSocket("zoom", visible, getZoom, resetWidget, setLoading);
80 // Refresh the widget at the specified interval
81 useWidgetRefresh(visible, getZoom, refresh);
82
83 if (loading) return <DataWidgetLoader.Widget className="zoom" />;
84 if (!state || (!state.mic.length && !state.video.length)) return null;
85
86 const { mic, video } = state;
87
88 const VideoIcon = video === "off" ? Icons.CameraOff : Icons.Camera;
89 const MicIcon = mic === "off" ? Icons.MicOff : Icons.MicOn;
90
91 return (
92 <DataWidget.Widget classes="zoom">
93 {showVideo && (
94 <SuspenseIcon>
95 <VideoIcon className={`zoom__icon zoom__icon--${video}`} />
96 </SuspenseIcon>
97 )}
98 {showMic && (
99 <SuspenseIcon>
100 <MicIcon className={`zoom__icon zoom__icon--${mic}`} />
101 </SuspenseIcon>
102 )}
103 </DataWidget.Widget>
104 );
105});
106
107Widget.displayName = "Zoom";
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/error.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/error.jsx
new file mode 100755
index 0000000..135cb29
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/error.jsx
@@ -0,0 +1,42 @@
1import * as Settings from "./settings/settings.jsx";
2import * as Utils from "../utils";
3
4// Error messages for different types of errors
5const message = {
6 error: "Something went wrong…",
7 yabaiError: "yabai is not running",
8 aerospaceError: "AeroSpace is either not running or outdated",
9 noOutput: "Loading…",
10 noData: "JSON error…",
11};
12
13/**
14 * Component to display error messages based on the type of error.
15 * @param {Object} props - The properties object.
16 * @param {string} props.type - The type of error.
17 * @param {string} props.classes - Additional CSS classes.
18 * @returns {JSX.Element} The error component.
19 */
20export function Component({ type, classes }) {
21 // Combine base class with additional classes and conditional loading class
22 const errorClasses = Utils.classNames("simple-bar--empty", classes, {
23 "simple-bar--loading": type === "noOutput",
24 });
25
26 // Refresh the component after 2 seconds for general errors and JSON errors
27 if (type === "error" || type === "noData") {
28 setTimeout(Utils.softRefresh, 2000);
29 }
30
31 // Refresh the component after 15 seconds for yabai and aerospace errors
32 if (type === "yabaiError" || type === "aerospaceError") {
33 setTimeout(Utils.softRefresh, 15000);
34 }
35
36 return (
37 <div className={errorClasses}>
38 <span>simple-bar-index.jsx: {message[type]}</span>
39 <Settings.Wrapper />
40 </div>
41 );
42}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icon.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icon.jsx
new file mode 100755
index 0000000..c46f60c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icon.jsx
@@ -0,0 +1,40 @@
1import * as Uebersicht from "uebersicht";
2
3const { React } = Uebersicht;
4
5/**
6 * Icon component renders an SVG element.
7 *
8 * @param {Object} props - The properties object.
9 * @param {number} [props.width=24] - The width of the SVG.
10 * @param {number} [props.height=24] - The height of the SVG.
11 * @param {React.ReactNode} props.children - The children elements to be rendered inside the SVG.
12 * @returns {JSX.Element} The SVG element.
13 */
14export default function Icon({ width = 24, height = 24, children, ...props }) {
15 return (
16 <svg
17 viewBox={`0 0 ${width} ${height}`}
18 width={width}
19 height={height}
20 {...props}
21 >
22 {children}
23 </svg>
24 );
25}
26
27/**
28 * SuspenseIcon component renders its children within a React.Suspense component.
29 *
30 * @param {Object} props - The properties object.
31 * @param {React.ReactNode} props.children - The children elements to be rendered inside the Suspense component.
32 * @returns {JSX.Element} The Suspense component with a fallback SVG loader.
33 */
34export function SuspenseIcon({ children }) {
35 return (
36 <React.Suspense fallback={<svg className="simple-bar-icon-loader" />}>
37 {children}
38 </React.Suspense>
39 );
40}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icons.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icons.jsx
new file mode 100755
index 0000000..514a2f1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/icons.jsx
@@ -0,0 +1,337 @@
1import * as Uebersicht from "uebersicht";
2
3const { React } = Uebersicht;
4
5export const Default = React.lazy(() => import("./library/default.jsx"));
6export const Ableton = React.lazy(() => import("./library/ableton.jsx"));
7export const Activity = React.lazy(() => import("./library/activity.jsx"));
8export const Add = React.lazy(() => import("./library/add.jsx"));
9export const AffinityDesigner = React.lazy(
10 () => import("./library/affinity-designer.jsx"),
11);
12export const AffinityPhoto = React.lazy(
13 () => import("./library/affinity-photo.jsx"),
14);
15export const AffinityPublisher = React.lazy(
16 () => import("./library/affinity-publisher.jsx"),
17);
18export const Airmail = React.lazy(() => import("./library/airmail.jsx"));
19export const Alfred = React.lazy(() => import("./library/alfred.jsx"));
20export const AndroidMessages = React.lazy(
21 () => import("./library/android-messages.jsx"),
22);
23export const AndroidStudio = React.lazy(
24 () => import("./library/android-studio.jsx"),
25);
26export const Anki = React.lazy(() => import("./library/anki.jsx"));
27export const Antigravity = React.lazy(
28 () => import("./library/antigravity.jsx"),
29);
30export const Anytype = React.lazy(() => import("./library/anytype.jsx"));
31export const AppleSimulator = React.lazy(
32 () => import("./library/apple-simulator.jsx"),
33);
34export const AppStore = React.lazy(() => import("./library/app-store.jsx"));
35export const Apple = React.lazy(() => import("./library/apple.jsx"));
36export const Arc = React.lazy(() => import("./library/arc.jsx"));
37export const Atom = React.lazy(() => import("./library/atom.jsx"));
38export const Audacity = React.lazy(() => import("./library/audacity.jsx"));
39export const Aqua = React.lazy(() => import("./library/aqua.jsx"));
40export const Bank = React.lazy(() => import("./library/bank.jsx"));
41export const BattleNet = React.lazy(() => import("./library/battle-net.jsx"));
42export const BambuStudio = React.lazy(
43 () => import("./library/bambu-studio.jsx"),
44);
45export const Bear = React.lazy(() => import("./library/bear.jsx"));
46export const Beekeeper = React.lazy(() => import("./library/beekeeper.jsx"));
47export const Bell = React.lazy(() => import("./library/bell.jsx"));
48export const BellOff = React.lazy(() => import("./library/bell-off.jsx"));
49export const Bitcoin = React.lazy(() => import("./library/bitcoin.jsx"));
50export const BitWarden = React.lazy(() => import("./library/bit-warden.jsx"));
51export const Blender = React.lazy(() => import("./library/blender.jsx"));
52export const Book = React.lazy(() => import("./library/book.jsx"));
53export const BraveBrowser = React.lazy(
54 () => import("./library/brave-browser.jsx"),
55);
56export const Bruno = React.lazy(() => import("./library/bruno.jsx"));
57export const CLion = React.lazy(() => import("./library/c-lion.jsx"));
58export const Calendar = React.lazy(() => import("./library/calendar.jsx"));
59export const Camera = React.lazy(() => import("./library/camera.jsx"));
60export const CameraOff = React.lazy(() => import("./library/camera-off.jsx"));
61export const Cancel = React.lazy(() => import("./library/cancel.jsx"));
62export const Caprine = React.lazy(() => import("./library/caprine.jsx"));
63export const CARROT = React.lazy(() => import("./library/ca-r-r-o-t.jsx"));
64export const Celo = React.lazy(() => import("./library/celo.jsx"));
65export const Charging = React.lazy(() => import("./library/charging.jsx"));
66export const ChatGPT = React.lazy(() => import("./library/chat-gpt.jsx"));
67export const Chatterino = React.lazy(() => import("./library/chatterino.jsx"));
68export const ChevronBottom = React.lazy(
69 () => import("./library/chevron-bottom.jsx"),
70);
71export const ChevronLeft = React.lazy(
72 () => import("./library/chevron-left.jsx"),
73);
74export const ChevronRight = React.lazy(
75 () => import("./library/chevron-right.jsx"),
76);
77export const ChevronTop = React.lazy(() => import("./library/chevron-top.jsx"));
78export const CheckBox = React.lazy(() => import("./library/check-box.jsx"));
79export const ClickUp = React.lazy(() => import("./library/click-up.jsx"));
80export const Claude = React.lazy(() => import("./library/claude.jsx"));
81export const ClaudeCode = React.lazy(() => import("./library/claude-code.jsx"));
82export const Cline = React.lazy(() => import("./library/cline.jsx"));
83export const Clock = React.lazy(() => import("./library/clock.jsx"));
84export const Close = React.lazy(() => import("./library/close.jsx"));
85export const Cloud = React.lazy(() => import("./library/cloud.jsx"));
86export const Codex = React.lazy(() => import("./library/codex.jsx"));
87export const Code = React.lazy(() => import("./library/code.jsx"));
88export const Coffee = React.lazy(() => import("./library/coffee.jsx"));
89export const ColorPicker = React.lazy(
90 () => import("./library/color-picker.jsx"),
91);
92export const ComfyUI = React.lazy(() => import("./library/comfy-ui.jsx"));
93export const Copilot = React.lazy(() => import("./library/copilot.jsx"));
94export const CPU = React.lazy(() => import("./library/cp-u.jsx"));
95export const Cursor = React.lazy(() => import("./library/cursor.jsx"));
96export const DataGrip = React.lazy(() => import("./library/data-grip.jsx"));
97export const Date = React.lazy(() => import("./library/date.jsx"));
98export const Deezer = React.lazy(() => import("./library/deezer.jsx"));
99export const Desktop = React.lazy(() => import("./library/desktop.jsx"));
100export const DEVONthink3 = React.lazy(
101 () => import("./library/de-v-o-nthink3.jsx"),
102);
103export const Discord = React.lazy(() => import("./library/discord.jsx"));
104export const Docker = React.lazy(() => import("./library/docker.jsx"));
105export const Dollar = React.lazy(() => import("./library/dollar.jsx"));
106export const DownArrow = React.lazy(() => import("./library/down-arrow.jsx"));
107export const Download = React.lazy(() => import("./library/download.jsx"));
108export const Drafts = React.lazy(() => import("./library/drafts.jsx"));
109export const Dropbox = React.lazy(() => import("./library/dropbox.jsx"));
110export const Element = React.lazy(() => import("./library/element.jsx"));
111export const Emacs = React.lazy(() => import("./library/emacs.jsx"));
112export const Ethereum = React.lazy(() => import("./library/ethereum.jsx"));
113export const EvernoteLegacy = React.lazy(
114 () => import("./library/evernote-legacy.jsx"),
115);
116export const FaceTime = React.lazy(() => import("./library/face-time.jsx"));
117export const Figma = React.lazy(() => import("./library/figma.jsx"));
118export const FinalCutPro = React.lazy(
119 () => import("./library/final-cut-pro.jsx"),
120);
121export const Finder = React.lazy(() => import("./library/finder.jsx"));
122export const Firefox = React.lazy(() => import("./library/firefox.jsx"));
123export const FirefoxDeveloperEdition = React.lazy(
124 () => import("./library/firefox-developer-edition.jsx"),
125);
126export const Fleet = React.lazy(() => import("./library/fleet.jsx"));
127export const Fog = React.lazy(() => import("./library/fog.jsx"));
128export const Folx = React.lazy(() => import("./library/folx.jsx"));
129export const FreeTube = React.lazy(() => import("./library/free-tube.jsx"));
130export const Gear = React.lazy(() => import("./library/gear.jsx"));
131export const Ghostty = React.lazy(() => import("./library/ghostty.jsx"));
132export const GitHub = React.lazy(() => import("./library/git-hub.jsx"));
133export const GoodNotes = React.lazy(() => import("./library/good-notes.jsx"));
134export const GoogleChrome = React.lazy(
135 () => import("./library/google-chrome.jsx"),
136);
137export const GnuCash = React.lazy(() => import("./library/gnu-cash.jsx"));
138export const GoLand = React.lazy(() => import("./library/go-land.jsx"));
139export const Goose = React.lazy(() => import("./library/goose.jsx"));
140export const Grammarly = React.lazy(() => import("./library/grammarly.jsx"));
141export const Helium = React.lazy(() => import("./library/helium.jsx"));
142export const HomeAssistant = React.lazy(
143 () => import("./library/home-assistant.jsx"),
144);
145export const HTTPie = React.lazy(() => import("./library/ht-t-pie.jsx"));
146export const Idea = React.lazy(() => import("./library/idea.jsx"));
147export const Insomnia = React.lazy(() => import("./library/insomnia.jsx"));
148export const Iris = React.lazy(() => import("./library/iris.jsx"));
149export const Italic = React.lazy(() => import("./library/italic.jsx"));
150export const Joplin = React.lazy(() => import("./library/joplin.jsx"));
151export const Kakoune = React.lazy(() => import("./library/kakoune.jsx"));
152export const KeePassXC = React.lazy(() => import("./library/kee-pass-x-c.jsx"));
153export const Keyboard = React.lazy(() => import("./library/keyboard.jsx"));
154export const KeyboardMaestro = React.lazy(
155 () => import("./library/keyboard-maestro.jsx"),
156);
157export const Keynote = React.lazy(() => import("./library/keynote.jsx"));
158export const LeagueOfLegends = React.lazy(
159 () => import("./library/league-of-legends.jsx"),
160);
161export const LibreWolf = React.lazy(() => import("./library/libre-wolf.jsx"));
162export const Linear = React.lazy(() => import("./library/linear.jsx"));
163export const LMStudio = React.lazy(() => import("./library/lm-studio.jsx"));
164export const MaestroAI = React.lazy(() => import("./library/maestro-ai.jsx"));
165export const Mail = React.lazy(() => import("./library/mail.jsx"));
166export const Mamp = React.lazy(() => import("./library/mamp.jsx"));
167export const Manus = React.lazy(() => import("./library/manus.jsx"));
168export const Matlab = React.lazy(() => import("./library/matlab.jsx"));
169export const Mattermost = React.lazy(() => import("./library/mattermost.jsx"));
170export const Messages = React.lazy(() => import("./library/messages.jsx"));
171export const MicOff = React.lazy(() => import("./library/mic-off.jsx"));
172export const MicOn = React.lazy(() => import("./library/mic-on.jsx"));
173export const MicrosoftEdge = React.lazy(
174 () => import("./library/microsoft-edge.jsx"),
175);
176export const MicrosoftExcel = React.lazy(
177 () => import("./library/microsoft-excel.jsx"),
178);
179export const MicrosoftOutlook = React.lazy(
180 () => import("./library/microsoft-outlook.jsx"),
181);
182export const MicrosoftPowerPoint = React.lazy(
183 () => import("./library/microsoft-power-point.jsx"),
184);
185export const MicrosoftWord = React.lazy(
186 () => import("./library/microsoft-word.jsx"),
187);
188export const Mimestream = React.lazy(() => import("./library/mimestream.jsx"));
189export const MinBrowser = React.lazy(() => import("./library/min-browser.jsx"));
190export const Miro = React.lazy(() => import("./library/miro.jsx"));
191export const MoneroGUI = React.lazy(() => import("./library/monero-gui.jsx"));
192export const MongoDB = React.lazy(() => import("./library/mongo-db.jsx"));
193export const Moon = React.lazy(() => import("./library/moon.jsx"));
194export const Mpv = React.lazy(() => import("./library/mpv.jsx"));
195export const Music = React.lazy(() => import("./library/music.jsx"));
196export const N8n = React.lazy(() => import("./library/n8n.jsx"));
197export const NeteaseMusic = React.lazy(
198 () => import("./library/netease-music.jsx"),
199);
200export const NetNewsWire = React.lazy(
201 () => import("./library/net-news-wire.jsx"),
202);
203export const Notability = React.lazy(() => import("./library/notability.jsx"));
204export const NotebookLM = React.lazy(() => import("./library/notebook-lm.jsx"));
205export const Notes = React.lazy(() => import("./library/notes.jsx"));
206export const Notion = React.lazy(() => import("./library/notion.jsx"));
207export const Nova = React.lazy(() => import("./library/nova.jsx"));
208export const NoVolume = React.lazy(() => import("./library/no-volume.jsx"));
209export const Numbers = React.lazy(() => import("./library/numbers.jsx"));
210export const Obsidian = React.lazy(() => import("./library/obsidian.jsx"));
211export const OBSStudio = React.lazy(() => import("./library/ob-s-studio.jsx"));
212export const Ollama = React.lazy(() => import("./library/ollama.jsx"));
213export const OmniFocus = React.lazy(() => import("./library/omni-focus.jsx"));
214export const OnePassword = React.lazy(
215 () => import("./library/one-password.jsx"),
216);
217export const OpenBook = React.lazy(() => import("./library/open-book.jsx"));
218export const OpenClaw = React.lazy(() => import("./library/open-claw.jsx"));
219export const Opencode = React.lazy(() => import("./library/opencode.jsx"));
220export const OrbStack = React.lazy(() => import("./library/orb-stack.jsx"));
221export const Pages = React.lazy(() => import("./library/pages.jsx"));
222export const Parallels = React.lazy(() => import("./library/parallels.jsx"));
223export const Paused = React.lazy(() => import("./library/paused.jsx"));
224export const Perplexity = React.lazy(() => import("./library/perplexity.jsx"));
225export const PDF = React.lazy(() => import("./library/pdf.jsx"));
226export const PHPStorm = React.lazy(() => import("./library/php-storm.jsx"));
227export const Pihole = React.lazy(() => import("./library/pihole.jsx"));
228export const Pine = React.lazy(() => import("./library/pine.jsx"));
229export const Pins = React.lazy(() => import("./library/pins.jsx"));
230export const Playing = React.lazy(() => import("./library/playing.jsx"));
231export const Plex = React.lazy(() => import("./library/plex.jsx"));
232export const Podcasts = React.lazy(() => import("./library/podcasts.jsx"));
233export const Pomodone = React.lazy(() => import("./library/pomodone.jsx"));
234export const Postman = React.lazy(() => import("./library/postman.jsx"));
235export const ProtonMail = React.lazy(() => import("./library/proton-mail.jsx"));
236export const PyCharm = React.lazy(() => import("./library/py-charm.jsx"));
237export const Quip = React.lazy(() => import("./library/quip.jsx"));
238export const QuteBrowser = React.lazy(
239 () => import("./library/qute-browser.jsx"),
240);
241export const Radar = React.lazy(() => import("./library/radar.jsx"));
242export const Rain = React.lazy(() => import("./library/rain.jsx"));
243export const Ram = React.lazy(() => import("./library/ram.jsx"));
244export const Redis = React.lazy(() => import("./library/redis.jsx"));
245export const Reeder5 = React.lazy(() => import("./library/reeder5.jsx"));
246export const Reminders = React.lazy(() => import("./library/reminders.jsx"));
247export const Remnote = React.lazy(() => import("./library/remnote.jsx"));
248export const RemoteDesktop = React.lazy(
249 () => import("./library/remote-desktop.jsx"),
250);
251export const Remove = React.lazy(() => import("./library/remove.jsx"));
252export const Replit = React.lazy(() => import("./library/replit.jsx"));
253export const Rider = React.lazy(() => import("./library/rider.jsx"));
254export const RocketChat = React.lazy(() => import("./library/rocket-chat.jsx"));
255export const Roon = React.lazy(() => import("./library/roon.jsx"));
256export const RoyalTSX = React.lazy(() => import("./library/royal-tsx.jsx"));
257export const RubyMine = React.lazy(() => import("./library/ruby-mine.jsx"));
258export const RustRover = React.lazy(() => import("./library/rust-rover.jsx"));
259export const Safari = React.lazy(() => import("./library/safari.jsx"));
260export const Screens4 = React.lazy(() => import("./library/screens4.jsx"));
261export const SequelAce = React.lazy(() => import("./library/sequel-ace.jsx"));
262export const SequelPro = React.lazy(() => import("./library/sequel-pro.jsx"));
263export const Setapp = React.lazy(() => import("./library/setapp.jsx"));
264export const Signal = React.lazy(() => import("./library/signal.jsx"));
265export const Sketch = React.lazy(() => import("./library/sketch.jsx"));
266export const SketchUp = React.lazy(() => import("./library/sketch-up.jsx"));
267export const Skype = React.lazy(() => import("./library/skype.jsx"));
268export const Slack = React.lazy(() => import("./library/slack.jsx"));
269export const Snow = React.lazy(() => import("./library/snow.jsx"));
270export const Spark = React.lazy(() => import("./library/spark.jsx"));
271export const Spotify = React.lazy(() => import("./library/spotify.jsx"));
272export const Spotlight = React.lazy(() => import("./library/spotlight.jsx"));
273export const Spotube = React.lazy(() => import("./library/spotube.jsx"));
274export const Statistics = React.lazy(() => import("./library/statistics.jsx"));
275export const Stopped = React.lazy(() => import("./library/stopped.jsx"));
276export const Storm = React.lazy(() => import("./library/storm.jsx"));
277export const SublimeText = React.lazy(
278 () => import("./library/sublime-text.jsx"),
279);
280export const Sun = React.lazy(() => import("./library/sun.jsx"));
281export const SuperProductivity = React.lazy(
282 () => import("./library/super-productivity.jsx"),
283);
284export const TablePlus = React.lazy(() => import("./library/table-plus.jsx"));
285export const Tailscale = React.lazy(() => import("./library/tailscale.jsx"));
286export const Teams = React.lazy(() => import("./library/teams.jsx"));
287export const TeamSpeak = React.lazy(() => import("./library/team-speak.jsx"));
288export const Telegram = React.lazy(() => import("./library/telegram.jsx"));
289export const Terminal = React.lazy(() => import("./library/terminal.jsx"));
290export const Text = React.lazy(() => import("./library/text.jsx"));
291export const Thermostat = React.lazy(() => import("./library/thermostat.jsx"));
292export const Things = React.lazy(() => import("./library/things.jsx"));
293export const Thunderbird = React.lazy(
294 () => import("./library/thunderbird.jsx"),
295);
296export const TickTick = React.lazy(() => import("./library/tick-tick.jsx"));
297export const Tidal = React.lazy(() => import("./library/tidal.jsx"));
298export const Todoist = React.lazy(() => import("./library/todoist.jsx"));
299export const TorBrowser = React.lazy(() => import("./library/tor-browser.jsx"));
300export const Tower = React.lazy(() => import("./library/tower.jsx"));
301export const Transmit = React.lazy(() => import("./library/transmit.jsx"));
302export const Trello = React.lazy(() => import("./library/trello.jsx"));
303export const Twitter = React.lazy(() => import("./library/twitter.jsx"));
304export const UpArrow = React.lazy(() => import("./library/up-arrow.jsx"));
305export const Upload = React.lazy(() => import("./library/upload.jsx"));
306export const Vim = React.lazy(() => import("./library/vim.jsx"));
307export const Vivaldi = React.lazy(() => import("./library/vivaldi.jsx"));
308export const VLC = React.lazy(() => import("./library/vl-c.jsx"));
309export const VMwareFusion = React.lazy(
310 () => import("./library/vmware-fusion.jsx"),
311);
312export const VolumeHigh = React.lazy(() => import("./library/volume-high.jsx"));
313export const VolumeLow = React.lazy(() => import("./library/volume-low.jsx"));
314export const VolumeMuted = React.lazy(
315 () => import("./library/volume-muted.jsx"),
316);
317export const VPN = React.lazy(() => import("./library/vp-n.jsx"));
318export const VPNOff = React.lazy(() => import("./library/vp-n-off.jsx"));
319export const VSCodium = React.lazy(() => import("./library/vs-codium.jsx"));
320export const Warp = React.lazy(() => import("./library/warp.jsx"));
321export const WebStorm = React.lazy(() => import("./library/web-storm.jsx"));
322export const Wechat = React.lazy(() => import("./library/wechat.jsx"));
323export const WhatsApp = React.lazy(() => import("./library/whats-app.jsx"));
324export const Widget = React.lazy(() => import("./library/widget.jsx"));
325export const Wifi = React.lazy(() => import("./library/wifi.jsx"));
326export const WifiOff = React.lazy(() => import("./library/wifi-off.jsx"));
327export const Windows = React.lazy(() => import("./library/windows.jsx"));
328export const Xcode = React.lazy(() => import("./library/xcode.jsx"));
329export const YoutubeMusic = React.lazy(
330 () => import("./library/youtube-music.jsx"),
331);
332export const Zed = React.lazy(() => import("./library/zed.jsx"));
333export const ZenBrowser = React.lazy(() => import("./library/zen-browser.jsx"));
334export const Zeplin = React.lazy(() => import("./library/zeplin.jsx"));
335export const Zoom = React.lazy(() => import("./library/zoom.jsx"));
336export const Zotero = React.lazy(() => import("./library/zotero.jsx"));
337export const Zulip = React.lazy(() => import("./library/zulip.jsx"));
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ableton.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ableton.jsx
new file mode 100755
index 0000000..c57cf32
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ableton.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Ableton(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M1.58214 17.8332c0 .0971-.08573.1668-.17146.1668H.18559C.08573 18 0 17.9303 0 17.8332V7.16772c0-.06969.08573-.15332.18559-.15332h1.22557c.08573 0 .17147.08363.17147.15332L1.58214 17.8332zm3.20666 0c0 .0971-.08574.1668-.17147.1668H3.39225c-.09986 0-.18511-.0697-.18511-.1668V7.16772c0-.06969.08525-.15332.18511-.15332h1.22557c.08573 0 .17146.08363.17146.15332L4.7888 17.8332zm3.20665 0c0 .0971-.08524.1668-.17146.1668H6.59842c-.09986 0-.18511-.0697-.18511-.1668V7.16772c0-.06969.08525-.15332.18511-.15332h1.22557c.08622 0 .17146.08363.17146.15332V17.8332zm3.22075 0c0 .0971-.0857.1668-.1709.1668H9.81969c-.09986 0-.18559-.0697-.18559-.1668V7.16772c0-.06969.08573-.15332.18559-.15332h1.22561c.0852 0 .1709.08363.1709.15332V17.8332zM23.829 7c.0994 0 .171.08456.171.16772v1.2024c0 .09803-.0711.18166-.171.18166H12.9547c-.0711 0-.1563-.08363-.1563-.18166v-1.2024c0-.08363.0857-.16772.1563-.16772H23.829zm0 3.1593c.0994 0 .171.0841.171.1677v1.202c0 .0975-.0711.1816-.171.1816H12.9547c-.0711 0-.1563-.0841-.1563-.1816v-1.202c0-.0841.0857-.1677.1563-.1677H23.829zm0 3.1449c.0994 0 .171.0837.171.1678v1.2014c0 .099-.0711.1826-.171.1826H12.9547c-.0711 0-.1563-.0836-.1563-.1826V13.472c0-.0846.0857-.1678.1563-.1678H23.829zm0 3.144c.0994 0 .171.0846.171.1677v1.2024c0 .0981-.0711.1817-.171.1817H12.9547c-.0711 0-.1563-.0836-.1563-.1817v-1.2024c0-.0836.0857-.1677.1563-.1677H23.829z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/activity.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/activity.jsx
new file mode 100755
index 0000000..502cbc7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/activity.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Activity(props) {
4 return (
5 <Icon {...props}>
6 <path d="M9 2C9.43043 2 9.81257 2.27543 9.94868 2.68377L15 17.8377L17.0513 11.6838C17.1874 11.2754 17.5696 11 18 11H22C22.5523 11 23 11.4477 23 12C23 12.5523 22.5523 13 22 13H18.7208L15.9487 21.3162C15.8126 21.7246 15.4304 22 15 22C14.5696 22 14.1874 21.7246 14.0513 21.3162L9 6.16228L6.94868 12.3162C6.81257 12.7246 6.43043 13 6 13H2C1.44772 13 1 12.5523 1 12C1 11.4477 1.44772 11 2 11H5.27924L8.05132 2.68377C8.18743 2.27543 8.56957 2 9 2Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/add.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/add.jsx
new file mode 100755
index 0000000..fb2663d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/add.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Add(props) {
4 return (
5 <Icon {...props}>
6 <path d="M24 10.29v3.42H13.71V24H10.3V13.71H0V10.3h10.29V0h3.42v10.29H24z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-designer.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-designer.jsx
new file mode 100755
index 0000000..4840d80
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-designer.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function AffinityDesigner(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M24,15.7928906 L24,23 C24,23.5522847 23.5522847,24 23,24 L11.8164141,24 L7.07807813,15.7928906 L24,15.7928906 Z M14.52,0 L5.7,15.2767969 L10.7364141,24 L1,24 C0.44771525,24 2.04643073e-12,23.5522847 2.04636308e-12,23 L2.04636308e-12,18.0827344 L10.44,0 L14.52,0 Z M9.34651441,-0.000941031503 L-0.000485585763,16.188059 L2.15027995e-12,1 C2.1502123e-12,0.44771525 0.44771525,1.5286817e-13 1,1.52766688e-13 L9.34651441,-0.000941031503 Z M10.2,9.35320313 L13.3776797,14.8570313 L9.25253906,14.8570313 C8.79203906,14.8570313 8.36653125,14.6153906 8.13628125,14.2164844 C7.90603011,13.817726 7.90603011,13.3264146 8.13628125,12.9276563 C8.2344601,12.7576004 8.33529127,12.5829519 8.43707936,12.406647 L8.64142909,12.0526986 C9.4258093,10.6941005 10.2,9.35320313 10.2,9.35320313 Z M23,0 C23.5522847,-1.08246745e-15 24,0.44771525 24,1 L24,14.8570313 L14.4581484,14.8570313 L10.74,8.4178125 L15.6,0 L23,0 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-photo.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-photo.jsx
new file mode 100755
index 0000000..d4eb1a0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-photo.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function AffinityPhoto(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M24,15.7920082 L24,23 C24,23.5522847 23.5522847,24 23,24 L15.6562434,24 L10.9174908,15.7920082 L24,15.7920082 Z M9.299907,9.04129496 L0.663593364,23.999976 C0.299024142,23.999976 0.00342023664,23.7045519 0.00319844346,23.3399827 L-2.30926389e-14,18.0825899 L5.2199478,9.04129496 L9.299907,9.04129496 Z M8.1599184,12.8864511 L14.5762542,23.999976 L1.73638264,23.999976 L8.1599184,12.8864511 Z M9.26450411,-3.67739595e-06 L-0.000495891046,16.0469963 L-2.13162821e-14,1 C-2.13839363e-14,0.44771525 0.44771525,3.60701891e-13 1,3.60600438e-13 L9.26450411,-3.67739595e-06 Z M23.2797672,1.20792265e-13 C23.6774101,1.19659685e-13 23.9997652,0.322349875 23.9997716,0.7199928 L24,14.8560091 L14.702733,14.8560091 L23.2797672,1.20792265e-13 Z M10.9830102,9.02389498 L13.0189098,9.02439898 L13.0311497,9.02439898 C13.3470932,9.02572164 13.6509005,9.19092207 13.8436281,9.44504185 L13.9160208,9.55381445 L13.9160208,9.55381445 L14.9948101,11.4225486 C14.9948101,11.4225486 15.00105,11.4329886 15.00393,11.4380286 C15.1803282,11.7465003 15.1870481,12.1352039 15.0108899,12.4492916 C14.6492135,13.0820269 14.2820172,13.7117383 13.9177008,14.3429617 C13.7386626,14.6499454 13.399786,14.8502251 13.0397896,14.8547131 L12.9117873,14.8551763 L12.9117873,14.8551763 L12.6228707,14.855854 C12.5719021,14.8559418 12.519806,14.8560179 12.4670028,14.8560834 L10.9731703,14.8560091 L10.9731703,14.8560091 C10.6177338,14.8545211 10.2721373,14.6648973 10.0882991,14.3553216 C10.0842192,14.3486017 10.0762992,14.3349217 10.0762992,14.3349217 C10.0762992,14.3349217 8.99727003,12.4659955 8.99487005,12.4616515 C8.81847182,12.1531798 8.81871181,11.7546362 8.99487005,11.4405486 L9.00278997,11.4267006 C9.00278997,11.4267006 9.27248283,10.958682 9.56478703,10.4516591 L9.72498304,10.1738116 C9.85787327,9.9433462 9.98615347,9.72093828 10.0866191,9.54687845 C10.2656573,9.23989476 10.6050139,9.02869497 10.9650103,9.02418298 C10.9710103,9.02415898 10.9830102,9.02389498 10.9830102,9.02389498 Z M22.199778,1.20792265e-13 L15.8398416,11.015845 L9.9599004,0.831383169 L10.4398956,1.20792265e-13 L22.199778,1.20792265e-13 Z M9.4199058,1.76668623 L13.0798692,8.10599189 L5.7599424,8.10599189 L9.4199058,1.76668623 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-publisher.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-publisher.jsx
new file mode 100755
index 0000000..127ed96
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/affinity-publisher.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function AffinityPublisher(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M3.66,11.743296 L10.7364,24 L1,24 C0.44771525,24 1.04864034e-15,23.5522847 0,23 L0,18.082608 L3.66,11.743296 Z M12.36,0 L24,20.16108 L24,23 C24,23.5522847 23.5522847,24 23,24 L22.1364,24 L9.36,1.870608 L10.44,0 L12.36,0 Z M8.82,2.805912 L21.0564,24 L16.9764,24 L6.84,6.235392 L8.82,2.805912 Z M6.240096,7.274376 L15.8964,24 L11.8164,24 C11.8164,24 10.1629545,21.135146 8.39585019,18.0741035 L8.07364883,17.5159825 C6.78257585,15.2796038 5.48074536,13.025003 4.760472,11.778744 C4.41324,11.177976 4.413144,10.437552 4.760184,9.836688 C5.400432,8.728176 6.240096,7.274376 6.240096,7.274376 Z M23,0 C23.5522847,-2.12449416e-16 24,0.44771525 24,1 L24,18.290448 L13.44,0 L23,0 Z M9.1711219,-0.000294809315 L-0.00087810197,15.8857052 L1.24344979e-14,1 C1.23668437e-14,0.44771525 0.44771525,2.10599713e-13 1,2.10498285e-13 L9.1711219,-0.000294809315 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/airmail.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/airmail.jsx
new file mode 100755
index 0000000..bad0d1f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/airmail.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Airmail(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 Z M12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 Z M4.41330385,8.54740435 L10.9512111,13.3604352 L11.0977263,13.4587231 C11.796293,13.8840706 12.6921408,13.8429055 13.3514536,13.3390862 L13.3514536,13.3390862 L19.5962577,8.56845889 C20.0697419,9.61494176 20.3333333,10.7766883 20.3333333,12 C20.3333333,16.6023729 16.6023729,20.3333333 12,20.3333333 C7.39762708,20.3333333 3.66666667,16.6023729 3.66666667,12 C3.66666667,10.7684782 3.93380809,9.59935061 4.41330385,8.54740435 Z M12,3.66666667 C14.6579701,3.66666667 17.0252969,4.91105867 18.5511698,6.84903215 L12.1371028,11.7499506 L5.4605582,6.83417134 C6.98681826,4.90469947 9.3488301,3.66666667 12,3.66666667 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/alfred.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/alfred.jsx
new file mode 100755
index 0000000..909dccf
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/alfred.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Alfred(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12,4 C16.9705627,4 21,7.35786438 21,11.5 L21,11.5 L21.0012572,13.3275425 C22.8675988,14.1207509 24,15.1625646 24,16.3035607 C24,18.7888421 18.627417,20.8035607 12,20.8035607 C5.372583,20.8035607 0,18.7888421 0,16.3035607 C0,15.1623601 1.13280722,14.1203774 2.9997465,13.327116 L3,11.5 L3.0041259,11.2707046 C3.14956116,7.23465056 7.12148471,4 12,4 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-messages.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-messages.jsx
new file mode 100755
index 0000000..a074703
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-messages.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function AndroidMessages(props) {
4 return (
5 <Icon {...props}>
6 <path d="M.61 5.7a.3.3 0 0 1 0-.48l2.42-1.86a.3.3 0 0 1 .48.24V7.3a.3.3 0 0 1-.48.24L.6 5.69z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M22 3.3H3.18v16.1c0 1.1.9 2 2 2H22a2 2 0 0 0 2-2V5.3a2 2 0 0 0-2-2zM9.15 8.66a.64.64 0 1 0 0 1.28h8.88a.64.64 0 0 0 0-1.28H9.15zm-.64 3.67c0-.35.3-.64.64-.64h8.88a.64.64 0 1 1 0 1.28H9.15a.64.64 0 0 1-.64-.64zm.64 2.4a.64.64 0 1 0 0 1.27h8.88a.64.64 0 1 0 0-1.28H9.15z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-studio.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-studio.jsx
new file mode 100755
index 0000000..25fb85d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/android-studio.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function AndroidStudio(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 1c-5.436 0-9.85 4.415-9.85 9.85a9.835 9.835 0 003.496 7.526l4.134-7.15-.36-.357c-.106-.106-.159-.195-.16-.278v-.027h-.01V8.22c0-.564.467-1.03 1.031-1.03h.582V5.343h2.283V7.19h.573c.573 0 1.031.466 1.04 1.039v2.327h-.009v.01h-.002c-.003.08-.047.183-.16.295l-.008.009-.358.357 1.772 3.064a5.276 5.276 0 001.28-3.44h1.837a7.104 7.104 0 01-2.16 5.098l1.403 2.43a9.834 9.834 0 003.497-7.527C21.86 5.405 17.445 1 12 1zm6.354 17.377c-.47.398-.978.751-1.515 1.054l1.393 2.41a.52.52 0 00.181.187l1.379.94a.162.162 0 00.17.01.175.175 0 00.08-.153l-.143-1.656a.634.634 0 00-.08-.25l-1.465-2.54v-.002zm-1.515 1.054l-1.373-2.373a7.052 7.052 0 01-3.457.904 7.053 7.053 0 01-3.458-.904L7.176 19.44A9.796 9.796 0 0012 20.704c1.758 0 3.41-.463 4.84-1.272zm-9.662.009a9.889 9.889 0 01-1.53-1.064L4.18 20.91a.636.636 0 00-.08.251l-.126 1.665c-.01.063.027.116.08.152.054.037.117.028.17-.01l1.378-.93a.713.713 0 00.18-.187l1.394-2.41zM12 8.085v.018a1.366 1.366 0 00-1.369 1.375A1.376 1.376 0 0012 10.85h.01a1.383 1.383 0 001.369-1.374 1.384 1.384 0 00-1.37-1.375L12 8.085zm-.867 4.495l-1.668 2.885c.777.43 1.65.654 2.536.654a5.164 5.164 0 002.526-.646l-1.663-2.887-.344.344a.698.698 0 01-.51.214h-.018a.727.727 0 01-.51-.214l-.35-.35z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anki.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anki.jsx
new file mode 100755
index 0000000..6a177aa
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anki.jsx
@@ -0,0 +1,16 @@
1import Icon from "../icon.jsx";
2
3export default function Anki(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5.23077 0C2.3419 0 0 2.3419 0 5.23077V18.7692C0 21.6581 2.3419 24 5.23077 24H18.7692C21.6581 24 24 21.6581 24 18.7692V5.23077C24 2.3419 21.6581 0 18.7692 0H5.23077ZM3.07692 4.39008V10.4003C3.07692 11.403 3.56556 12.3429 4.38638 12.9189L10.1088 16.9347C11.1547 17.6686 12.5453 17.6798 13.6029 16.9628L19.5728 12.9154C20.4173 12.3429 20.9231 11.389 20.9231 10.3687V4.26178C20.9231 3.99273 20.8315 3.7317 20.6634 3.52161C20.4386 3.24054 20.0982 3.07692 19.7382 3.07692H4.39008C4.04181 3.07692 3.7078 3.21527 3.46154 3.46154C3.21527 3.7078 3.07692 4.04181 3.07692 4.39008Z"
10 />
11 <path d="M5.53846 6.15385C5.53846 5.98391 5.67622 5.84615 5.84615 5.84615H8.92308C9.09301 5.84615 9.23077 5.98391 9.23077 6.15385C9.23077 6.32378 9.09301 6.46154 8.92308 6.46154H5.84615C5.67622 6.46154 5.53846 6.32378 5.53846 6.15385Z" />
12 <path d="M5.53846 8.30769C5.53846 8.13776 5.67622 8 5.84615 8H18.1538C18.3238 8 18.4615 8.13776 18.4615 8.30769C18.4615 8.47763 18.3238 8.61538 18.1538 8.61538H5.84615C5.67622 8.61538 5.53846 8.47763 5.53846 8.30769Z" />
13 <path d="M5.53846 10.4615C5.53846 10.2916 5.67622 10.1538 5.84615 10.1538H18.1538C18.3238 10.1538 18.4615 10.2916 18.4615 10.4615C18.4615 10.6315 18.3238 10.7692 18.1538 10.7692H5.84615C5.67622 10.7692 5.53846 10.6315 5.53846 10.4615Z" />
14 </Icon>
15 );
16}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/antigravity.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/antigravity.jsx
new file mode 100755
index 0000000..0c71174
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/antigravity.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Antigravity(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21.751 22.607c1.34 1.005 3.35.335 1.508-1.508C17.73 15.74 18.904 1 12.037 1 5.17 1 6.342 15.74.815 21.1c-2.01 2.009.167 2.511 1.507 1.506 5.192-3.517 4.857-9.714 9.715-9.714 4.857 0 4.522 6.197 9.714 9.715z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anytype.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anytype.jsx
new file mode 100755
index 0000000..a585ecd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/anytype.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Anytype(props) {
4 return (
5 <Icon {...props}>
6 <path d="M3.6304 0h15.0261v5.2H3.6305V0Zm15.0261 5.2H24.5v18.7h-5.8435V5.2ZM8.326 24c4.3223 0 7.8262-3.3579 7.8262-7.5S12.6483 9 8.3261 9C4.0039 9 .5 12.3579.5 16.5S4.0039 24 8.326 24Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/app-store.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/app-store.jsx
new file mode 100755
index 0000000..91ebdc9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/app-store.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function AppStore(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 Z M7.85263158,16.2315789 C7.29473684,15.5578947 6.58947368,15.3526316 5.72631579,15.6210526 L5.72631579,15.6210526 L4.95789474,16.9473684 C4.66315789,17.4631579 4.83684211,18.1210526 5.35263158,18.4157895 C5.86842105,18.7105263 6.52631579,18.5368421 6.82105263,18.0210526 L6.82105263,18.0210526 Z M13.5789474,7.51052632 C12.9421053,8.03684211 12.3,9.59473684 13.2,11.1473684 C14.0789474,12.6736842 15.4052632,14.9631579 17.1684211,18.0210526 C17.4684211,18.5368421 18.1210526,18.7105263 18.6368421,18.4157895 C19.1526316,18.1157895 19.3263158,17.4631579 19.0315789,16.9473684 L19.0315789,16.9473684 L17.9842105,15.1315789 L19.5368421,15.1315789 C20.1315789,15.1315789 20.6105263,14.6526316 20.6105263,14.0578947 C20.6105263,13.4631579 20.1315789,12.9842105 19.5368421,12.9842105 L19.5368421,12.9842105 L16.7421053,12.9842105 C15.3368421,10.5473684 14.2842105,8.72105263 13.5789474,7.51052632 Z M13.9421053,3.53684211 C13.4263158,3.24210526 12.7684211,3.41578947 12.4736842,3.93157895 L12.4736842,3.93157895 L11.9947368,4.75789474 L11.5263158,3.93157895 C11.2263158,3.41578947 10.5736842,3.24210526 10.0578947,3.53684211 C9.54210526,3.83684211 9.36842105,4.48947368 9.66315789,5.00526316 L9.66315789,5.00526316 L10.7578947,6.90526316 L7.25263158,12.9789474 L4.51578947,12.9789474 C3.92105263,12.9789474 3.44210526,13.4578947 3.44210526,14.0526316 C3.44210526,14.6473684 3.92105263,15.1263158 4.51578947,15.1263158 L4.51578947,15.1263158 L14.2789474,15.1263158 C14.7473684,14.2473684 14.1421053,12.9789474 13.0631579,12.9789474 L13.0631579,12.9789474 L9.73157895,12.9789474 L14.3368421,5.00526316 C14.6315789,4.48947368 14.4578947,3.83157895 13.9421053,3.53684211 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple-simulator.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple-simulator.jsx
new file mode 100755
index 0000000..13abc8f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple-simulator.jsx
@@ -0,0 +1,16 @@
1import Icon from "../icon.jsx";
2
3export default function Ableton(props) {
4 return (
5 <Icon {...props}>
6 <path d="m11.084 2.681.62-1.07a1.393 1.393 0 1 1 2.415 1.391L8.153 13.33h4.315c1.399 0 2.182 1.643 1.575 2.783H1.39C.62 16.113 0 15.493 0 14.72c0-.772.62-1.391 1.391-1.391h3.547L9.48 5.46 8.061 2.999a1.395 1.395 0 0 1 2.416-1.392l.607 1.074ZM5.718 17.546l-1.338 2.32a1.393 1.393 0 1 1-2.415-1.391l.993-1.72c1.124-.348 2.038-.08 2.76.79Zm11.52-4.208h3.62c.772 0 1.391.619 1.391 1.39 0 .773-.62 1.392-1.391 1.392h-2.01l1.356 2.355a1.395 1.395 0 0 1-2.415 1.39c-2.286-3.963-4.002-6.929-5.141-8.905-1.166-2.01-.333-4.028.489-4.713.913 1.568 2.278 3.934 4.101 7.09Z" />
7 <path d="m16.693 9.093-5.081 8.801a1.016 1.016 0 0 0 .372 1.388l4.113 2.375c.486.28 1.108.114 1.388-.372l5.082-8.8a1.016 1.016 0 0 0-.372-1.388L18.08 8.72a1.016 1.016 0 0 0-1.388.372Zm-.587-.338a1.694 1.694 0 0 1 2.314-.62l4.113 2.375a1.694 1.694 0 0 1 .62 2.313l-5.08 8.8a1.694 1.694 0 0 1-2.314.62l-4.114-2.374a1.694 1.694 0 0 1-.62-2.314l5.081-8.8Zm-1.978 10.2a.678.678 0 1 1 1.173.679.678.678 0 0 1-1.173-.678Z" />
8 <path
9 fillOpacity=".75"
10 fillRule="evenodd"
11 clipRule="evenodd"
12 d="m16.693 9.093-5.081 8.8a1.016 1.016 0 0 0 .372 1.39l4.113 2.374c.486.28 1.108.114 1.388-.372l5.082-8.8a1.016 1.016 0 0 0-.372-1.389L18.08 8.721a1.016 1.016 0 0 0-1.388.372Zm-1.64 9.615a.678.678 0 1 0-.677 1.174.678.678 0 0 0 .677-1.174Z"
13 />
14 </Icon>
15 );
16}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple.jsx
new file mode 100755
index 0000000..dc8ffe8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/apple.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Apple(props) {
4 return (
5 <Icon {...props}>
6 <path d="M18.5373 12.7261c.0337 3.6251 3.1802 4.8315 3.215 4.8469-.0266.085-.5027 1.719-1.6576 3.4069-.9984 1.4593-2.0347 2.9131-3.6671 2.9432-1.6038.0296-2.1196-.9511-3.9534-.9511-1.8332 0-2.4062.921-3.9245.9807-1.5756.0596-2.7755-1.5779-3.7821-3.0319-2.0572-2.9739-3.6292-8.4038-1.5183-12.069 1.0486-1.8202 2.9226-2.9727 4.9566-3.0023 1.5472-.0295 3.0076 1.041 3.9534 1.041.9453 0 2.72-1.2873 4.5857-1.0983.7809.0326 2.9734.3155 4.3811 2.3761-.1135.0703-2.616 1.5272-2.5888 4.5579M15.523 3.8247C16.3596 2.812 16.9226 1.4026 16.769 0c-1.2058.0485-2.6638.8035-3.5287 1.8155-.7751.8962-1.4539 2.3306-1.2707 3.7053 1.344.104 2.7168-.683 3.5534-1.6961Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/aqua.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/aqua.jsx
new file mode 100755
index 0000000..8267772
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/aqua.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Aqua(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3.0002 19.1999h9.6v1.8h-9.6v-1.8Zm.5946-9.3264a4.3915 4.3915 0 0 0 1.653 1.6716c.4853.2807 1.013.4646 1.578.551l.0006.1018c0 .3774.078.7056.2346.984.1558.2779.391.5029.6756.6462.294.1518.636.228 1.026.228h1.4472v-1.299H9.11c-.1332 0-.2484-.0246-.3444-.0738a.5048.5048 0 0 1-.222-.219c-.0516-.096-.0774-.2112-.0774-.3438v-.0402a4.4563 4.4563 0 0 0 1.476-.5346 4.367 4.367 0 0 0 1.6494-1.6728c.399-.7092.5982-1.5012.5982-2.376 0-.8748-.1992-1.6668-.5976-2.3766a4.3674 4.3674 0 0 0-1.65-1.6722c-.7008-.405-1.4784-.6078-2.3442-.6078-.8658 0-1.6494.2034-2.3502.6084a4.3884 4.3884 0 0 0-1.653 1.6722c-.4014.7092-.6018 1.5012-.6018 2.376 0 .8748.201 1.6668.6018 2.3766Zm6.4344-.7782c-.24.4734-.5724.8448-.9966 1.1124-.4242.2682-.9024.402-1.434.402s-1.011-.1338-1.4376-.402c-.426-.2676-.7608-.6384-1.0032-1.1124-.2418-.474-.363-1.0068-.363-1.5984 0-.5916.1212-1.1244.363-1.5984A2.772 2.772 0 0 1 6.161 4.7861c.4266-.2682.906-.402 1.4376-.402s1.0092.1344 1.434.402c.428.2722.773.657.9966 1.1124.24.474.36 1.0068.36 1.5984 0 .5916-.12 1.1244-.36 1.5984Zm7.6146-6.1002H15.74l-3.2478 9.0036h1.8072l.6816-2.0898h3.5052l.7272 2.0898h1.7682l-3.3378-9.0036ZM16.808 5.118l1.215 3.4338h-2.6238L16.544 5.118l.129-.5724.135.5724Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/arc.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/arc.jsx
new file mode 100755
index 0000000..dd7a339
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/arc.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Arc(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M23.94 8.63c.14-.72.03-1.47-.34-2.1a2.85 2.85 0 0 0-2.47-1.4h-.01c-1.38 0-2.53.98-2.8 2.33-.17.8-.48 1.56-.93 2.27a.26.26 0 0 1-.45-.02l-2.86-6a2.88 2.88 0 0 0-5.23-.07L5.9 9.85c-.08.17-.31.16-.38 0a2.86 2.86 0 0 0-3.77-1.58 2.93 2.93 0 0 0-1.52 3.82 10.55 10.55 0 0 0 2.66 3.66c.08.08.1.2.06.3l-.96 2.02a2.92 2.92 0 0 0 1.27 3.85 2.88 2.88 0 0 0 3.9-1.33l.82-1.72a.25.25 0 0 1 .3-.14 11.46 11.46 0 0 0 6.3-.06.26.26 0 0 1 .3.14l.82 1.71a2.95 2.95 0 0 0 2.62 1.72c.46 0 .9-.1 1.31-.31a2.93 2.93 0 0 0 1.27-3.87l-1.02-2.15a.26.26 0 0 1 .05-.3 13.23 13.23 0 0 0 4-6.98ZM5.54 20.9c.29-.19.52-.45.67-.76l.75-1.56c.06-.13 0-.3-.14-.35a13.88 13.88 0 0 1-2.7-1.49c-.13-.1-.32-.04-.39.1l-.8 1.67c-.43.91-.09 2.04.82 2.48a1.85 1.85 0 0 0 1.79-.1Zm-4.38-9.3c1.47 3.64 5.92 6.5 10.13 6.5.93 0 1.85-.14 2.75-.37a.26.26 0 0 0 .16-.37l-1.37-2.9a.26.26 0 0 0-.29-.14 7.2 7.2 0 0 1-1.25.12c-2.73 0-5.82-1.93-6.74-4.21a1.83 1.83 0 1 0-3.39 1.37Zm10.17.23-.64 1.33c-.04.09.01.2.12.2a5.06 5.06 0 0 0 1.29-.02c.09-.02.14-.12.1-.2l-.62-1.31a.14.14 0 0 0-.25 0Zm7.12 9.34c.25-.01.48-.07.7-.18.9-.45 1.24-1.57.8-2.49L13.1 4.08a1.85 1.85 0 0 0-2.74-.7c-.22.15-.4.37-.52.61L6.5 11.03a.26.26 0 0 0 .05.29 7.47 7.47 0 0 0 2.79 1.72c.12.04.26-.02.32-.14l1.54-3.25c.1-.21.4-.21.5 0l4.99 10.48a1.83 1.83 0 0 0 1.76 1.04Zm-.77-9.97c0 .05 0 .1.02.14l1.47 3.07c.07.17.29.2.42.07a12.1 12.1 0 0 0 3.32-6.02c.2-.98-.36-2-1.33-2.23a1.83 1.83 0 0 0-2.24 1.42 8.2 8.2 0 0 1-1.6 3.42.26.26 0 0 0-.06.13Z"
10 />
11 <path d="M19.15 20.99a1.83 1.83 0 0 1-2.46-.86l-5-10.48c-.1-.21-.4-.21-.49 0L9.66 12.9a.26.26 0 0 1-.32.14 7.47 7.47 0 0 1-2.8-1.72.26.26 0 0 1-.04-.3L9.84 4c.12-.24.3-.46.52-.62a1.85 1.85 0 0 1 2.74.7l6.86 14.43c.43.92.1 2.04-.81 2.49ZM6.21 20.14a1.84 1.84 0 0 1-2.46.85 1.87 1.87 0 0 1-.81-2.48l.8-1.66c.06-.15.25-.2.38-.1a12.8 12.8 0 0 0 2.7 1.48c.14.06.2.22.14.35l-.75 1.56Z" />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/atom.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/atom.jsx
new file mode 100755
index 0000000..104203e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/atom.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Atom(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M8.272 2.184c-.525-.17-.908-.144-1.185 0l-.003.002-.004.001c-.356.179-.651.565-.824 1.234-.172.668-.205 1.56-.08 2.627.05.431.126.887.226 1.362.952-.15 1.98-.247 3.06-.287a27.316 27.316 0 0 1 1.883-2.17L10.044 3.19c-.663-.505-1.261-.842-1.772-1.006Zm3.792 2.06-1.299-1.76-.055-.043c-.735-.568-1.456-.991-2.132-1.209-.676-.218-1.355-.243-1.948.063-.706.354-1.128 1.047-1.342 1.876-.214.83-.238 1.856-.105 2.993.053.454.132.93.235 1.423a16.55 16.55 0 0 0-1.555.396c-1.093.339-2.021.774-2.693 1.303-.669.527-1.132 1.19-1.166 1.975-.041.682.242 1.304.711 1.842.467.535 1.138 1.013 1.944 1.433l.097.05 2.347.119c-.303.802-.54 1.572-.705 2.291-.255 1.114-.346 2.134-.232 2.98.114.845.443 1.583 1.091 2.015l.005.003.005.003c.642.407 1.42.43 2.214.218.793-.21 1.655-.665 2.537-1.298a.5.5 0 1 0-.582-.813c-.827.593-1.578.977-2.212 1.145-.63.168-1.092.11-1.417-.093-.317-.214-.558-.629-.65-1.313-.093-.685-.025-1.576.216-2.623.174-.76.436-1.59.781-2.462l2.049.103c1.391 2.55 3.005 4.686 4.551 6.114.842.777 1.684 1.364 2.478 1.684.794.32 1.6.395 2.3.04.68-.346 1.09-1.01 1.304-1.805.214-.795.25-1.775.137-2.862a17.458 17.458 0 0 0-.504-2.653l2.405.122.101-.041c.844-.338 1.555-.753 2.076-1.234.521-.48.88-1.052.945-1.696l.002-.015v-.014c.032-.785-.369-1.49-.987-2.085-.619-.595-1.5-1.125-2.553-1.576-1.64-.702-3.76-1.239-6.126-1.52l-1.67-2.265c.467-.446.928-.842 1.376-1.184.86-.657 1.648-1.094 2.313-1.298.663-.204 1.137-.158 1.459.039.335.226.57.61.673 1.199.106.6.068 1.379-.119 2.314a.5.5 0 1 0 .98.196c.2-1 .26-1.914.124-2.684-.137-.778-.482-1.442-1.11-1.861l-.007-.004-.006-.005c-.662-.412-1.472-.4-2.288-.15-.819.252-1.713.762-2.626 1.46-.448.341-.906.732-1.367 1.167Zm-.117 1.526c-.394.413-.79.858-1.184 1.332a32.255 32.255 0 0 1 2.231.089l-1.047-1.42Zm1.84 2.495a30.525 30.525 0 0 0-3.822-.157 31.426 31.426 0 0 0-2.252 3.418 30.327 30.327 0 0 0 1.105 2.365l8.288.418a28.413 28.413 0 0 0-1.422-3.472l-1.897-2.572Zm4.387 6.098 2.53.128c.72-.298 1.282-.642 1.67-1 .4-.369.59-.726.626-1.046.01-.39-.186-.832-.682-1.309-.5-.481-1.263-.953-2.253-1.377-1.322-.566-3.005-1.027-4.906-1.318l1.383 1.876.02.04a29.075 29.075 0 0 1 1.612 4.006Zm-.756.963-8.037-.405c1.278 2.235 2.709 4.08 4.052 5.32.79.73 1.531 1.232 2.173 1.49.643.26 1.126.252 1.474.076m.338-6.48c.285 1.012.473 1.96.56 2.808.105 1.018.064 1.864-.107 2.499-.171.634-.454 1.001-.791 1.173m-9.414-7.974c-.196-.396-.382-.79-.558-1.183-.193.38-.373.757-.54 1.128l1.098.055Zm-2.166-.11c.318-.738.688-1.497 1.107-2.264-.396-1-.717-1.974-.959-2.898-.532.109-1.03.235-1.49.377-1.027.319-1.829.708-2.369 1.133-.54.426-.77.847-.786 1.236v.011c-.023.348.113.724.466 1.128.34.39.862.781 1.556 1.153l2.475.125Zm1.136-5.338c.167.627.372 1.28.614 1.951a31.64 31.64 0 0 1 1.432-2.172c-.716.048-1.4.123-2.046.221Z"
10 />
11 <path d="M13.378 11.996a1.357 1.357 0 1 1-2.714 0 1.357 1.357 0 0 1 2.714 0Z" />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/audacity.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/audacity.jsx
new file mode 100755
index 0000000..c5b72ea
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/audacity.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Audacity(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 2.145c-2.487 0-4.755.776-6.428 2.08-1.673 1.303-2.76 3.169-2.76 5.244v.75C1.153 11.06 0 13.268 0 15.856c0 3.312 1.884 6 4.312 6V9.468c0-1.554.805-2.984 2.186-4.06C7.879 4.331 9.829 3.643 12 3.643c2.17 0 4.12.688 5.502 1.764 1.38 1.077 2.186 2.507 2.186 4.06v12.387c2.428 0 4.312-2.687 4.312-6 0-2.587-1.152-4.795-2.813-5.636v-.75c0-2.075-1.086-3.94-2.76-5.244-1.672-1.304-3.94-2.08-6.427-2.08zm0 6.153l-1.125 8.683L9.75 9.105l-.562 6.75-.376-.75-.375-4.5-.187 4.5-.563 1.313-.374-4.5-.376 3.562-.562-.937v2.625l-.563-2.11v-4.64a1.432 1.432 0 0 0-.937-.375v11.812c.375 0 .75-.187.937-.562v-3.375l.188.187.563 1.875.187-2.25.563 2.813v-3.562l.374.937.563 2.625v-3.562l.375.374.563 3.188.562-4.313 1.24 4.86.072-2.985.375-1.124.376 4.687 1.124-4.687.375 3.937.938-4.125.938 4.5.187-3.375.562-1.125.188 4.313.938-4.125.562 1.875.188-1.688.374.75v3.375c.188.375.563.562.938.562V10.043c-.375 0-.75.188-.938.375v4.813l-.374 1-.188-3.188-.375 2.437-.375-.75-.188-2.625-.937 3.563-.188-.75L15 9.293l-.562 4.875-.376 1.5-.75-5.062-.75 4.312-.375 1.125Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bambu-studio.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bambu-studio.jsx
new file mode 100755
index 0000000..66c60d0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bambu-studio.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function BambuStudio(props) {
4 return (
5 <Icon {...props}>
6 <path d="m 12.558,2 h 7.115 v 9.056 C 19.6,11.031 19.531,11.01 19.463,10.983 Q 16.088,9.652 12.712,8.325 A 0.207,0.207 0 0 1 12.556,8.093 q 0.006,-2.96 0,-5.917 V 2 Z M 11.437,22 H 4.52 a 0.176,0.176 0 0 1 -0.2,-0.2 q 0,-2.952 0,-5.9 a 0.209,0.209 0 0 1 0.154,-0.234 q 3.421,-1.341 6.839,-2.691 c 0.036,-0.015 0.075,-0.024 0.128,-0.041 V 22 Z M 4.326,2 h 7.107 c 0,0.051 0.008,0.1 0.008,0.14 0,0.169 0,0.338 0,0.507 q 0,4.442 0.011,8.883 a 0.237,0.237 0 0 1 -0.178,0.264 q -3.385,1.324 -6.767,2.66 c -0.055,0.022 -0.112,0.04 -0.182,0.064 V 2 Z m 8.24,7.465 1.184,0.464 q 2.89,1.139 5.783,2.274 a 0.2,0.2 0 0 1 0.152,0.219 q -0.006,4.7 0,9.393 v 0.175 c -0.067,0 -0.117,0.007 -0.167,0.007 q -3.39,0 -6.779,0 c -0.139,0 -0.181,-0.034 -0.181,-0.177 q 0.006,-6.1 0,-12.191 c 0,-0.05 0,-0.1 0.008,-0.167 z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bank.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bank.jsx
new file mode 100755
index 0000000..a777b0a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bank.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Bank(props) {
4 return (
5 <Icon {...props}>
6 <path d="M4 11.5v4a1.5 1.5 0 1 0 3 0v-4a1.5 1.5 0 1 0-3 0zm6 0v4a1.5 1.5 0 1 0 3 0v-4a1.5 1.5 0 1 0-3 0zM3.5 22h16a1.5 1.5 0 1 0 0-3h-16a1.5 1.5 0 1 0 0 3zM16 11.5v4a1.5 1.5 0 1 0 3 0v-4a1.5 1.5 0 1 0-3 0zM10.57 1.49l-7.9 4.16c-.41.21-.67.64-.67 1.1C2 7.44 2.56 8 3.25 8h16.51a1.25 1.25 0 0 0 .57-2.35l-7.9-4.16a1.98 1.98 0 0 0-1.86 0z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/battle-net.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/battle-net.jsx
new file mode 100755
index 0000000..120d215
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/battle-net.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function BattleNet(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21.07 10.577s1.9757.1005 1.9757-1.0615c0-1.5168-2.632-2.883-2.632-2.883s.4119-.874.6697-1.3629c.2579-.4889.9812-2.3908 1.0448-2.8261.0803-.5492-.0436-.72-.0436-.72-.1774 1.172-2.0861 4.5473-2.2401 4.6612-1.8618-.8706-4.4201-1.1151-4.4201-1.1151S12.9197-.001 10.5624-.001c-2.3373 0-2.324 4.5138-2.324 4.5138s-.6596-1.2791-1.49-1.2791c-1.2122 0-1.6107 1.8283-1.6107 3.814-2.3908 0-4.4033.5357-4.584.586-.1776.0502-.7435.462-.489.4118.5258-.1674 2.9836-.5491 5.1333-.3616.1206 1.8852 1.2222 4.343 1.2222 4.343s-2.364 3.4222-2.364 5.8633c0 .6429.2813 1.8182 1.9756 1.8182 1.4231 0 3.0204-.8538 3.3184-1.0246-.2612.3717-.4554 1.0849-.4554 1.4131 0 .2679.1607 1.028 1.2557 1.028 1.4064 0 2.9802-1.0783 2.9802-1.0783s1.4867 2.4646 2.7558 3.593c.3416.3047.6697.3617.6697.3617s-1.2624-1.2122-2.9232-4.3397c1.5436-.951 3.1509-3.2012 3.1509-3.2012s.1909.0067 1.6575.0067c2.2971 0 5.5586-.4822 5.5586-2.3072.0033-1.8818-2.93-3.5829-2.93-3.5829Zm.2545-1.1351c0 .6663-.6328.6596-.6328.6596l-.4822.0302s-.9142-.4789-1.47-.7066c0 0 .8605-1.3226 1.0614-1.691.1507.0904 1.5236.9476 1.5236 1.7078Zm-9.6136-6.7875c1.0816 0 2.6219 2.5449 2.6219 2.5449s-2.4042-.2143-4.3832.9476c.0536-1.8316.6697-3.4925 1.7613-3.4925Zm-4.276 2.0627c.3415 0 .6763.4186.817.7702 0 .2344.1205 1.6006.1205 1.6006l-1.9823-.077c0-1.7848.6998-2.2938 1.0447-2.2938Zm-.2077 12.4063c-1.0849 0-1.3059-.6027-1.3059-1.1452 0-1.2289.9811-2.9501.9811-2.9501s1.1017 2.3139 3.0204 3.2883c-.951.5592-1.7379.807-2.6956.807Zm3.5193 2.421c-.76 0-.8538-.4923-.8538-.6061 0-.3516.2779-.7702.2779-.7702s1.2758-.8605 1.3561-.9543l.9443 1.7613s-.9644.5693-1.7245.5693Zm2.3708-.9577c-.4621-.807-.8037-1.6508-.8037-1.6508s1.8987.1205 2.92-.9309c-.6363.2846-1.6509.6462-2.8295.5357 2.4645-2.1698 3.9043-3.7436 5.1198-5.3676-.1038-.1273-.6596-.5157-.7969-.5793-.7333.884-3.5896 3.9345-6.235 5.4447-3.3485-1.825-4.0517-7.1927-4.122-8.3077l1.8283.174s-.6864 1.219-.6864 2.1164c0 .894.1071.9409.1071.9409s-.0234-1.5604.941-2.7659c.7366 3.9111 1.5034 5.9135 2.0995 7.1089.3047-.1272.8706-.3783.8706-.3783s-1.6877-4.8655-1.594-8.157c.7669-.4086 1.9021-.8305 3.1812-.8305 3.3686 0 6.0776 1.4466 6.0776 1.4466l-1.0582 1.48s-.9443-1.7077-2.2803-2.0124c.7032.5223 1.4934 1.2155 1.9019 2.21-2.7926-1.0883-6.1612-1.6642-7.2428-1.7915-.0938.3985-.0804.9678-.0804.9678s4.5172.8337 7.8054 2.7123c-.0234 4.1119-4.5037 7.2696-5.1232 7.6346Zm4.2794-3.074s1.403-1.8383 1.3796-4.276c0 0 2.2669 1.403 2.2669 2.7726 0 1.5269-3.6465 1.5034-3.6465 1.5034Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bear.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bear.jsx
new file mode 100755
index 0000000..249f1d5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bear.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Bear(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.992,0.623C5.412,0.627 -0,6.043 0,12.622C0,15.462 1.008,18.211 2.842,20.377C3.275,18.108 3.903,15.88 4.717,13.717C5.437,11.845 6.45,10.098 7.717,8.543C8.985,6.987 7.492,6.158 8.542,6.158C9.463,6.279 10.312,6.72 10.942,7.403C11.572,8.085 14.752,6.893 15.997,8.378C17.324,9.592 18.916,10.481 20.647,10.973C22.377,11.464 21.802,10.643 21.322,12.472C20.842,14.302 19.252,15.862 16.057,15.862C14.902,15.862 14.557,16.567 14.557,17.467C14.923,19.185 15.61,20.819 16.582,22.282L17.302,23.377C21.385,21.357 23.979,17.178 23.979,12.622C23.979,6.044 18.57,0.63 11.992,0.623Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/beekeeper.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/beekeeper.jsx
new file mode 100755
index 0000000..121e00b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/beekeeper.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Beekeeper(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M7.23 0h11.56A5.21 5.21 0 0 1 24 5.21V18.8A5.21 5.21 0 0 1 18.79 24H5.2A5.21 5.21 0 0 1 0 18.79V5.2A5.21 5.21 0 0 1 4.6.04V13.5c0 1.7.9 3.3 2.4 4.16l2.6 1.51a4.67 4.67 0 0 0 4.79 0l2.6-1.5a4.78 4.78 0 0 0 2.4-4.17v-3c.02-1.72-.9-3.3-2.38-4.16l-2.6-1.5a4.88 4.88 0 0 0-2.4-.66v3A4.78 4.78 0 0 1 16.8 12a4.8 4.8 0 0 1-7.18 4.17A4.78 4.78 0 0 1 7.22 12V0Zm1.09 8.94c.2-.26.46-.49.71-.7V5.18l-.71.42v3.34Zm2.49-1.56c-.21.06-.44.12-.64.21V4.57c.23-.1.46-.17.71-.23v3.02l-.07.02Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell-off.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell-off.jsx
new file mode 100755
index 0000000..170e05f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell-off.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function BellOff(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm0-15.5c2.49 0 4 2.02 4 4.5v.1l2 2V11c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.24.06-.47.15-.69.23l1.64 1.64c.18-.02.36-.05.55-.05zM5.41 3.35L4 4.76l2.81 2.81C6.29 8.57 6 9.74 6 11v5l-2 2v1h14.24l1.74 1.74 1.41-1.41L5.41 3.35zM16 17H8v-6c0-.68.12-1.32.34-1.9L16 16.76V17z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell.jsx
new file mode 100755
index 0000000..db84ce4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bell.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Bell(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6zM7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bit-warden.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bit-warden.jsx
new file mode 100755
index 0000000..88ae754
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bit-warden.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function BitWarden(props) {
4 return (
5 <Icon {...props}>
6 <path d="M3.75 0A3.75 3.75 0 000 3.75v16.5A3.75 3.75 0 003.75 24h16.5A3.75 3.75 0 0024 20.25V3.75A3.75 3.75 0 0020.25 0zm1.36 2.92h13.8c.208 0 .388.076.54.228a.737.737 0 01.227.539v9.2c0 .687-.134 1.367-.401 2.042a7.618 7.618 0 01-.995 1.797 11.097 11.097 0 01-1.413 1.528c-.547.495-1.052.906-1.515 1.234-.464.327-.947.636-1.45.928-.503.291-.86.489-1.072.593-.212.104-.381.184-.51.24a.687.687 0 01-.31.071.688.688 0 01-.312-.072 13.784 13.784 0 01-.51-.24 20.61 20.61 0 01-1.071-.592 19.133 19.133 0 01-1.45-.928 16.457 16.457 0 01-1.515-1.234 11.11 11.11 0 01-1.414-1.528 7.617 7.617 0 01-.994-1.797 5.502 5.502 0 01-.401-2.042v-9.2c0-.208.076-.387.227-.54a.737.737 0 01.54-.227zm6.9 2.3v13.62c.95-.502 1.801-1.05 2.552-1.64 1.877-1.47 2.815-2.907 2.815-4.313V5.22Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bitcoin.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bitcoin.jsx
new file mode 100755
index 0000000..116e1af
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bitcoin.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Bitcoin(props) {
4 return (
5 <Icon width={256} height={256} {...props}>
6 <circle fill="#fa8a34" cx="128" cy="128" r="128" />
7 <path
8 fill="#fff"
9 d="M1204.1,462.447c-4.67,12.309-32.28,20.379-32.28,20.379l5.38,22.428-14.21,3.4-5.41-22.585-11.24,2.563,5.44,22.708-14.21,3.4-5.48-22.865-28.48,6.493-1.13-17.911s5.18-.648,9.9-1.581,4.82-6.292,4.19-8.909-12.85-53.641-14.15-59.061-6.97-6.829-9.44-6.434-10.29,3.255-10.29,3.255l-3.58-14.952,27.66-6.626-5.55-23.176,14.2-3.4,5.55,23.176c4.06-.972,7.9-1.89,11.22-2.686l-5.55-23.176,14.2-3.4,5.59,23.311c6.37-1.033,18.66-2.112,26.25.684,9.1,3.353,15.14,14.553,15.8,23.091s-8.38,17.817-8.38,17.817,14.2,0.988,20.24,8.591C1212.62,442.426,1206.19,456.916,1204.1,462.447Zm-78.62-64.174,6.81,28.41s12.27-1.557,19.83-6.33,10.78-9.509,9.66-15.754c-1.19-6.631-8.99-10.52-16.68-10.234A73.025,73.025,0,0,0,1125.48,398.273Zm9.46,42.794,7.35,30.652s19.47-3.676,25.8-7.763,13.55-11.94,9.34-20.419-15.95-8.035-23.8-6.947A145.286,145.286,0,0,0,1134.94,441.067Z"
10 transform="translate(-1016 -309)"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/blender.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/blender.jsx
new file mode 100755
index 0000000..5fcb14e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/blender.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Blender(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.93 12.87c-.14-.99-.48-1.93-1.02-2.79a7.8 7.8 0 0 0-1.79-1.99L13.6 2.3l-.01-.01c-.25-.2-.6-.3-.96-.3s-.71.1-.99.3c-.3.2-.46.48-.47.77a.9.9 0 0 0 .36.73l1.45 1.16 1.44 1.15H5.2c-1.05 0-1.77.5-1.92 1.32-.06.36.05.76.31 1.07.27.32.67.5 1.11.5h4.55L.89 15.18l-.04.03c-.46.36-.77.86-.84 1.37-.05.4.04.75.27 1.04.26.34.68.53 1.17.53.48 0 .96-.18 1.37-.51l4.52-3.7a6 6 0 0 0-.04.64c0 .3.1.91.26 1.4a7.4 7.4 0 0 0 1.6 2.78 8.26 8.26 0 0 0 2.8 2c1.14.5 2.37.77 3.65.77h.01a9 9 0 0 0 3.67-.78 8.3 8.3 0 0 0 2.79-2.01 7.46 7.46 0 0 0 1.9-4.33c.04-.5.02-1.02-.05-1.54zm-8.23 4.89c-2.82 0-5.11-2.05-5.11-4.58 0-2.53 2.29-4.58 5.11-4.58 2.83 0 5.12 2.05 5.12 4.58 0 2.53-2.3 4.58-5.12 4.58zm2.95-4.98c.04.75-.26 1.45-.79 1.97-.54.53-1.3.86-2.16.86-.86 0-1.63-.33-2.17-.86a2.55 2.55 0 0 1-.79-1.97c.04-.73.4-1.38.94-1.84a3.11 3.11 0 0 1 2.02-.72c.77 0 1.48.27 2.01.72.54.46.9 1.1.94 1.84z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/book.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/book.jsx
new file mode 100755
index 0000000..59c53a5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/book.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Book(props) {
4 return (
5 <Icon {...props}>
6 <path d="m18.15 1.35-4 4a.5.5 0 0 0-.15.36v8.17c0 .43.51.66.83.37l4-3.6a.48.48 0 0 0 .17-.37V1.71a.5.5 0 0 0-.85-.36zm4.32 3.85c-.47-.24-.96-.44-1.47-.61v12.03a10.29 10.29 0 0 0-9 .96V5.48A11 11 0 0 0 1.53 5.2a.97.97 0 0 0-.53.88v12.08a1 1 0 0 0 1.48.87A8.7 8.7 0 0 1 6.5 18c2.07 0 3.98.82 5.5 2a9.04 9.04 0 0 1 5.5-2c1.45 0 2.81.4 4.02 1.04a1 1 0 0 0 1.48-.87V6.08c0-.37-.2-.72-.53-.88z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/brave-browser.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/brave-browser.jsx
new file mode 100755
index 0000000..66e72a9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/brave-browser.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function BraveBrowser(props) {
4 return (
5 <Icon {...props}>
6 <path d="M15.68 0l2.096 2.38s1.84-.512 2.709.358c.868.87 1.584 1.638 1.584 1.638l-.562 1.381.715 2.047s-2.104 7.98-2.35 8.955c-.486 1.919-.818 2.66-2.198 3.633-1.38.972-3.884 2.66-4.293 2.916-.409.256-.92.692-1.38.692-.46 0-.97-.436-1.38-.692a185.796 185.796 0 01-4.293-2.916c-1.38-.973-1.712-1.714-2.197-3.633-.247-.975-2.351-8.955-2.351-8.955l.715-2.047-.562-1.381s.716-.768 1.585-1.638c.868-.87 2.708-.358 2.708-.358L8.321 0h7.36zm-3.679 14.936c-.14 0-1.038.317-1.758.69-.72.373-1.242.637-1.409.742-.167.104-.065.301.087.409.152.107 2.194 1.69 2.393 1.866.198.175.489.464.687.464.198 0 .49-.29.688-.464.198-.175 2.24-1.759 2.392-1.866.152-.108.254-.305.087-.41-.167-.104-.689-.368-1.41-.741-.72-.373-1.617-.69-1.757-.69zm0-11.278s-.409.001-1.022.206-1.278.46-1.584.46c-.307 0-2.581-.434-2.581-.434S4.119 7.152 4.119 7.849c0 .697.339.881.68 1.243l2.02 2.149c.192.203.59.511.356 1.066-.235.555-.58 1.26-.196 1.977.384.716 1.042 1.194 1.464 1.115.421-.08 1.412-.598 1.776-.834.364-.237 1.518-1.19 1.518-1.554 0-.365-1.193-1.02-1.413-1.168-.22-.15-1.226-.725-1.247-.95-.02-.227-.012-.293.284-.851.297-.559.831-1.304.742-1.8-.089-.495-.95-.753-1.565-.986-.615-.232-1.799-.671-1.947-.74-.148-.068-.11-.133.339-.175.448-.043 1.719-.212 2.292-.052.573.16 1.552.403 1.632.532.079.13.149.134.067.579-.081.445-.5 2.581-.541 2.96-.04.38-.12.63.288.724.409.094 1.097.256 1.333.256s.924-.162 1.333-.256c.408-.093.329-.344.288-.723-.04-.38-.46-2.516-.541-2.961-.082-.445-.012-.45.067-.579.08-.129 1.059-.372 1.632-.532.573-.16 1.845.009 2.292.052.449.042.487.107.339.175-.148.069-1.332.508-1.947.74-.615.233-1.476.49-1.565.986-.09.496.445 1.241.742 1.8.297.558.304.624.284.85-.02.226-1.026.802-1.247.95-.22.15-1.413.804-1.413 1.169 0 .364 1.154 1.317 1.518 1.554.364.236 1.355.755 1.776.834.422.079 1.08-.4 1.464-1.115.384-.716.039-1.422-.195-1.977-.235-.555.163-.863.355-1.066l2.02-2.149c.341-.362.68-.546.68-1.243 0-.697-2.695-3.96-2.695-3.96s-2.274.436-2.58.436c-.307 0-.972-.256-1.585-.461-.613-.205-1.022-.206-1.022-.206z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bruno.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bruno.jsx
new file mode 100755
index 0000000..a36f8b5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/bruno.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function Bruno(props) {
4 return (
5 <Icon width={190} height={190} {...props}>
6 <path d="M81.2 28c-4 1.1-9.4 3-12.1 4.4-2.6 1.3-7.3 3.1-10.4 4-14.4 4.2-30 22.6-39.8 47.1-2.8 7.1-3.1 8.7-2.7 15.5.5 8.7 3.7 16.5 11.4 28.2 7.2 10.7 10.5 13.8 14.8 13.8 3.7 0 8.6-3.5 8.6-6.1 0-.6 1 .1 2.2 1.7 9 12.1 21.3 19.9 23.2 14.8.9-2.3.9-2.2-2.6-4-5.6-2.8-11.8-8.4-15.5-14-3.2-4.9-3.4-5.5-2.3-8.8.9-2.7.8-4.7-.5-9.7-2.2-8.4-3-25.2-1.5-30.9 2.3-8.8 2.3-9.9.5-10.7-6.6-2.5-9.6 21.3-5.2 41.6 1.4 6.4 1.4 6.5-1.6 13-4.4 9.8-4.9 9.8-11.7 1.3-5.7-7.3-12.5-20.6-14.1-27.6-1.5-6.8-.9-9.1 6.5-24.9 8.2-17.5 21.5-32 31.9-34.8 2.3-.6 6.7-2.2 9.7-3.6C80.3 33.6 86.9 32 97.2 32c10.9 0 21 2.6 30.7 8 3 1.6 6.6 3 8 3 4.4 0 12.8 4.6 18 9.8 5.8 5.8 12.9 17.6 17.3 28.7 5.8 14.5 4 24.1-7.5 41.6-6 9.1-9 12.4-10.5 11.5-.6-.3-2.4-3.6-4.2-7.3l-3.1-6.8 1.6-8.2c4.1-20.5.1-45.4-6.2-39.1-1 1.1-1 2.2.2 6.2 2 6.6 1.9 22-.1 32.4-1.4 6.8-1.5 9-.5 12.3 1.1 3.6 1 4.4-1.1 7.7-3.4 5.7-10.8 13.2-15 15.3-2.4 1.2-3.8 2.7-3.8 3.8 0 6.9 14.1-1.7 21.7-13.1l2.5-3.7 2.5 2.9c3.4 4.1 8.8 4.2 12.5.2 9-9.7 18.2-26.4 20-36.2 1.4-7.4.4-12.2-5.1-24.9-5.6-13.1-9.7-19.7-16.8-26.9C152 42.8 143.7 38 138.8 38c-1.4 0-6-1.8-10.1-4-14.4-7.8-32.1-10-47.5-6z" />
7 <path d="M72.2 73.6c-2.9 2-3 6.8-.1 8.8 1.9 1.3 2.7 1.3 5.3.2 2.7-1.1 3.1-1.8 2.9-4.7-.1-3.1-2.4-5.9-4.8-5.9-.6 0-2.1.7-3.3 1.6zM123.8 73.1c-1.2.7-1.8 2.2-1.8 4.9 0 3.3.4 3.9 3 4.9 3.8 1.3 5.4.7 6.9-2.5 1.3-2.9.2-5.7-2.9-7.4-2.3-1.2-3-1.2-5.2.1zM88.2 98c-2.4 1-5 6.1-5.9 11.5-.5 2.8-.1 3.3 3.4 4.9 5.3 2.4 21.5 2.6 25.9.3 5.5-2.9 5.9-4 3-10.2-1.7-3.8-3.3-5.8-5.1-6.5-3.3-1.2-18.2-1.2-21.3 0z" />
8 <path d="M67 115.5c-3.4 4.1 2.2 17 9.4 21.4 3.3 2.1 3.4 2.2 3.8 10.4.8 14.6 5.3 20.9 16.3 22.2 6.8.9 12.9-.8 15.3-4.3 2.8-3.9 5.2-12.7 5.2-19.2v-5.7l5.3-3.9c5.9-4.4 9.7-10.8 9.7-16.5 0-4.4-2.2-6.8-4.5-4.9-.8.7-1.5 2.8-1.5 4.7 0 5.7-4 10.9-10.8 13.9-3.1 1.4-3.6 1.3-6-.2-5.8-3.6-7.2-5.6-7.2-10 0-2.9-.5-4.4-1.6-4.8-2.7-1-4.4 1.3-4.4 5.9 0 4-.3 4.5-4.7 7.4-5.2 3.5-6.8 3.4-12.1-.6-4.5-3.4-6.6-6.9-7.2-12.2-.5-4.9-2.6-6.4-5-3.6zm36.4 21.5c2.2 1.7 4.8 3 5.8 3 4.2 0 1 19.5-3.7 22.6-1.9 1.3-3.8 1.5-8 .9-8.7-1-10.9-4.4-11-16.4 0-6.3.1-6.5 3-7.3 1.7-.4 4.4-1.9 6-3.2 1.7-1.4 3.2-2.5 3.5-2.5.3 0 2.3 1.3 4.4 2.9z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/c-lion.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/c-lion.jsx
new file mode 100755
index 0000000..fb7ff5d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/c-lion.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function CLion(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3 19.1999h9.6v1.8H3v-1.8Zm.6018-9.3264a4.3723 4.3723 0 0 0 1.6464 1.6716v-.0012c.699.4056 1.479.6078 2.3406.6078.729 0 1.398-.135 2.007-.405a4.1173 4.1173 0 0 0 1.521-1.1352 3.8665 3.8665 0 0 0 .813-1.6752h-1.839a2.4132 2.4132 0 0 1-1.3956 1.428 2.9272 2.9272 0 0 1-1.0932.1992c-.5322 0-1.0122-.1326-1.4412-.3984a2.7627 2.7627 0 0 1-1.0062-1.0968c-.2424-.465-.3636-.9888-.3636-1.5726 0-.5826.1212-1.1064.3636-1.572a2.766 2.766 0 0 1 1.0062-1.0962c.429-.2658.909-.399 1.4412-.399a2.937 2.937 0 0 1 1.0932.1992c.3238.1263.6166.3207.8586.57.2373.2454.4202.538.537.8586h1.839a3.8665 3.8665 0 0 0-.813-1.6758 4.1173 4.1173 0 0 0-1.521-1.1352c-.609-.27-1.278-.405-2.007-.405-.8616 0-1.6422.2034-2.3406.6084A4.374 4.374 0 0 0 3.6018 5.121c-.399.7092-.5982 1.5012-.5982 2.376 0 .8748.1992 1.6668.5982 2.3766Zm11.5962.5436v-7.422h-1.7496v9.0036h6.0198v-1.5816H15.198Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ca-r-r-o-t.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ca-r-r-o-t.jsx
new file mode 100755
index 0000000..94339d1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ca-r-r-o-t.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function CARROT(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.5 3.6h1.7v.1h.4v.1H15l.1.1h.1l.1.1.6.3h.1v.1l.4.2c.6.4 1 1 1.4 1.6h.1v.2c.2.2.4.5.4.8l.1.2.1.2V8h.1V8h.2l.6.4c.5.3 1 .8 1.3 1.3l.2.5v.2h.1V10.9l.1.2V13h-.1v.2l-.1.1v.1l-.2.4a7.1 7.1 0 0 0-.5.6l-.4.4-.3.3h-.1l-.1.1-.2.1h-.1l-.2.1-.1.1h-.2v.1H18l-.2.1H5.8v-.1H5.5v-.1h-.1l-.3-.1-.3-.2-.1-.1h-.1l-.1-.1-.6-.6-.2-.2V14l-.2-.2v-.1l-.3-.4V13H3v-.2l-.1-.3V10.7l.1-.1v-.1l.1-.2.2-.5h.1c0-.2.1-.2.2-.3a6.3 6.3 0 0 1 .7-.8l.3-.2.2-.1c.2-.1.5-.3.8-.3L6 8h.4l.3-.1H8v-.3l.1-.2v-.1l.1-.2.1-.2v-.2a6.6 6.6 0 0 1 1.2-1.6l1.3-1h.1l.3-.1.1-.1.3-.1a1930 1930 0 0 1 .2 0v-.1H12l.1-.1h.4M8 9.4l-.8.2a2.4 2.4 0 0 0 1 4.6h7.3a2.4 2.4 0 0 0 .3-4.8H8m10.4 3.7h-.1v.1l-.2.1v.7l.2.1h.5l.2-.2v-.5l-.2-.2c-.2 0-.3-.1-.4 0Zm0 0" />
7 <path d="m11.6 10.7.2-.2h.2l2 2.2.2.2H13c-.1 0-.2 0-.3-.2l-.7-.8-.8 1H9.5v-.1l2.1-2.1ZM11 16.7h2v.1h.1v.4H13v.1h-.1v.1l-.1.1v.1h-.1v.2a2.2 2.2 0 0 1-.2 0v.2H14v.1h.1v.2l-.1.1v.1h-.1l-.1.1h-.1v.1h-.2v.1h-.1v.1h-.2v.1H13v.1h-.1v.1h-.1v.1h-.2v.1h-.1l-.1.1h-.1l-.1.1H12v.1H12v.1h-.2v.1h-.1v.1h-.2v.1h-.1l-.1.1h-.1v.1H11v.1h-.2v.1h-.5V20.1l.1-.2v-.1h.1v-.2h.1v-.1h.1v-.1l.1-.1v-.1h.1v-.1l.1-.1V19h.1v-.1h.1v-.1h.1H10.4v-.2.1h-.6v-.1h-.1V18h.1V18l.1-.1v-.1h.1v-.1h.1v-.1h.1v-.1l.1-.1v-.1h.1V17h.1V17h.1l.1-.2h.1v-.1h.1Zm0 0" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/calendar.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/calendar.jsx
new file mode 100755
index 0000000..613f1b0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/calendar.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Calendar(props) {
4 return (
5 <Icon {...props}>
6 <path d="M5 5c-.5523 0-1 .4477-1 1v14c0 .5523.4477 1 1 1h14c.5523 0 1-.4477 1-1V6c0-.5523-.4477-1-1-1H5ZM2 6c0-1.6569 1.3432-3 3-3h14c1.6569 0 3 1.3431 3 3v14c0 1.6569-1.3431 3-3 3H5c-1.6568 0-3-1.3431-3-3V6Z" />
7 <path d="M16 1c.5523 0 1 .4477 1 1v4c0 .5523-.4477 1-1 1s-1-.4477-1-1V2c0-.5523.4477-1 1-1ZM8 1c.5523 0 1 .4477 1 1v4c0 .5523-.4477 1-1 1s-1-.4477-1-1V2c0-.5523.4477-1 1-1ZM2 10c0-.5523.4477-1 1-1h18c.5523 0 1 .4477 1 1s-.4477 1-1 1H3c-.5523 0-1-.4477-1-1Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera-off.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera-off.jsx
new file mode 100755
index 0000000..a0f3891
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera-off.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function CameraOff(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21 14.2V8.91c0-.89-1.08-1.34-1.71-.71L17 10.5V7c0-.55-.45-1-1-1h-5.61l8.91 8.91c.62.63 1.7.18 1.7-.71zM2.71 2.56c-.39.39-.39 1.02 0 1.41L4.73 6H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.21 0 .39-.08.55-.18l2.48 2.48c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L4.12 2.56c-.39-.39-1.02-.39-1.41 0z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera.jsx
new file mode 100755
index 0000000..e18b0da
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/camera.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Camera(props) {
4 return (
5 <Icon {...props}>
6 <path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l2.29 2.29c.63.63 1.71.18 1.71-.71V8.91c0-.89-1.08-1.34-1.71-.71L17 10.5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cancel.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cancel.jsx
new file mode 100755
index 0000000..f96294f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cancel.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Cancel(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0a12 12 0 1 0 0 24 12 12 0 0 0 0-24zM2.4 12a9.6 9.6 0 0 1 15.5-7.6L4.4 18a9.5 9.5 0 0 1-2-5.9zm9.6 9.6c-2.2 0-4.3-.8-5.9-2L19.6 6A9.6 9.6 0 0 1 12 21.6z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/caprine.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/caprine.jsx
new file mode 100755
index 0000000..6e3c3f2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/caprine.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Caprine(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0C5.37 0 0 4.97 0 11.11c0 3.5 1.74 6.62 4.47 8.65V24l4.09-2.24c1.09.3 2.24.46 3.44.46 6.63 0 12-4.97 12-11.1C24 4.97 18.63 0 12 0zm1.2 14.96l-3.06-3.26-5.97 3.26L10.73 8l3.13 3.26L19.76 8l-6.57 6.96z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/celo.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/celo.jsx
new file mode 100755
index 0000000..155c73d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/celo.jsx
@@ -0,0 +1,20 @@
1import Icon from "../icon.jsx";
2
3export default function Celo(props) {
4 return (
5 <Icon width={950} height={950} {...props}>
6 <path
7 fill="#fbcc5c"
8 d="M375,850c151.88,0,275-123.12,275-275S526.88,300,375,300,100,423.12,100,575,223.12,850,375,850Zm0,100C167.9,950,0,782.1,0,575S167.9,200,375,200,750,367.9,750,575,582.1,950,375,950Z"
9 />
10 <path
11 fill="#35d07f"
12 d="M575,650c151.88,0,275-123.12,275-275S726.88,100,575,100,300,223.12,300,375,423.12,650,575,650Zm0,100c-207.1,0-375-167.9-375-375S367.9,0,575,0,950,167.9,950,375,782.1,750,575,750Z"
13 />
14 <path
15 fill="#5ea33b"
16 d="M587.39,750a274.38,274.38,0,0,0,54.55-108.06A274.36,274.36,0,0,0,750,587.4a373.63,373.63,0,0,1-29.16,133.45A373.62,373.62,0,0,1,587.39,750ZM308.06,308.06A274.36,274.36,0,0,0,200,362.6a373.63,373.63,0,0,1,29.16-133.45A373.62,373.62,0,0,1,362.61,200,274.38,274.38,0,0,0,308.06,308.06Z"
17 />
18 </Icon>
19 );
20}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/charging.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/charging.jsx
new file mode 100755
index 0000000..808f939
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/charging.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Charging(props) {
4 return (
5 <Icon {...props}>
6 <path d="M7 2v11h3v9l7-12h-4l3-8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chat-gpt.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chat-gpt.jsx
new file mode 100755
index 0000000..8efbe29
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chat-gpt.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function ChatGPT(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M.0098 5.7696C.0098 2.5886 2.5883.01 5.7694.01h12.4598c3.1821 0 5.7606 2.5786 5.7606 5.7596V24H5.7694c-3.181 0-5.7596-2.5785-5.7596-5.7596V5.7696Zm11.0354-2.786c-1.975 0-3.7297 1.2698-4.3412 3.1451l-.0012.0073A4.5265 4.5265 0 0 0 3.714 8.3185c-.9875 1.7105-.7651 3.8649.5532 5.3321l.0057.0048a4.5265 4.5265 0 0 0 .3957 3.6796c.9876 1.7104 2.9646 2.5951 4.8944 2.187l.0069-.0026a4.5261 4.5261 0 0 0 3.3845 1.4971c1.9751 0 3.7297-1.2698 4.3412-3.1451l.0012-.0073a4.5266 4.5266 0 0 0 2.9888-2.1826c.9875-1.7104.7651-3.8649-.5532-5.3321l-.0057-.0047a4.5265 4.5265 0 0 0-.3957-3.6796c-.9876-1.7105-2.9646-2.5951-4.8944-2.187l-.0069.0026a4.5265 4.5265 0 0 0-3.3845-1.4971ZM9.4568 15.5288l-3.478-2.0072a3.3702 3.3702 0 0 1-.885-.7384l-.0081.0086c-.9026-1.0579-1.0906-2.6112-.3567-3.8872l.0022.0081c.3957-.6853 1.0115-1.2082 1.7524-1.485v4.2571c0 .0477.0055.0942.016.1389.0344.1604.1372.3005.2848.3857l4.2096 2.4304-1.5372.889ZM5.282 14.4911l3.6867 2.1285a.6049.6049 0 0 0 .1288.0557c.156.0502.3285.0312.476-.0539l4.2095-2.4304.0013 1.7757-3.4773 2.0084a3.3702 3.3702 0 0 1-1.082.3973l.0034.0113c-1.3675.2527-2.8067-.3611-3.5447-1.6348l.0081.0022c-.3956-.6853-.5406-1.48-.4098-2.26Zm6.7178-.4282-1.7865-1.0314v-2.0629l1.7865-1.0315 1.7865 1.0315v2.0629l-1.7865 1.0314Zm-4.3275-2.5008 1.5385.8868V7.5881c0-.1704.0698-.3293.1913-.4392a.6035.6035 0 0 1 .1126-.0837l3.6867-2.1285c-.6101-.5033-1.3708-.775-2.1622-.775l.006-.006c-1.472.0023-2.7233.9418-3.1881 2.2524l.0114.0027a3.371 3.371 0 0 0-.1969 1.1357l.0007 4.0156Zm6.8126 5.3727-3.6867 2.1285c.6101.5033 1.3708.7751 2.1622.7751l-.006.006c1.472-.0023 2.7232-.9418 3.1881-2.2524l-.0115-.0028a3.3715 3.3715 0 0 0 .197-1.1357l-.0007-4.0156-1.5385-.8867v4.8608c0 .1703-.0698.3292-.1913.4392a.6006.6006 0 0 1-.1126.0836Zm3.0311-.3625c.7409-.2767 1.3567-.7996 1.7523-1.485l.0022.0082c.734-1.276.546-2.8293-.3566-3.8872l-.0081.0086a3.3704 3.3704 0 0 0-.8851-.7384l-3.4779-2.0072-1.5372.889 4.2096 2.4304c.1474.0851.2501.2249.2846.385a.601.601 0 0 1 .0162.1395v4.2571Zm-2.4851-9.1918 3.6867 2.1285c.1308-.78-.0142-1.5747-.4098-2.26l.0081.0021c-.738-1.2736-2.1772-1.8875-3.5447-1.6348l.0034.0114a3.3708 3.3708 0 0 0-1.082.3973l-3.4773 2.0084.0012 1.7757 4.2097-2.4304c.1475-.0852.3201-.1041.4761-.0539a.6034.6034 0 0 1 .1286.0557Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chatterino.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chatterino.jsx
new file mode 100755
index 0000000..6970765
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chatterino.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Chatterino(props) {
4 return (
5 <Icon {...props}>
6 <path d="M2.879 16.969s-.621-1.344-.957-2.856a9.693 9.693 0 0 1-.168-2.832c.285-4.008 2.973-8.57 7.629-10.008 3.48-1.082 7.082-.867 9.695 1.055 3.336 2.473 3.195 3 3.195 3l-4.73 4.656s-1.055-2.113-3.285-2.879c-1.563-.554-2.809-.335-3.89-.144C9 7.199 6.624 8.137 4.944 10.223c-.578.722-1.082 1.464-1.488 2.547-.723 1.992-.578 4.199-.578 4.199" />
7 <path d="M13.992 23.762h-.238c-3.531-.121-5.617-1.008-6.555-1.54-.36.364-.91.817-1.558 1.06-1.13.405-2.45.238-2.52.238l-1.754-.239 1.418-1.058c.024-.024.79-.621.79-1.606.027-1.273-.31-1.898-.575-2.426-1.32-2.566-1.848-4.703-1.68-6.96C1.61 7.343 4.223 2.448 9.238.91c3.84-1.177 7.489-.766 10.059 1.151 3.625 2.692 3.48 3.313 3.383 3.672l-.047.196-5.473 5.328-.433-.914c0-.024-.817-1.656-2.665-2.23-1.124-.36-2.496-.024-3.261.48-2.067 1.39-2.664 3.695-1.465 5.496.937 1.367 2.328 2.039 4.031 1.918 1.848-.121 3.387-2.352 3.387-2.375l.476-.723 5.692 5.547-.363.504c-.145.215-3.649 4.8-8.567 4.8m-7.031-3.48.574.453c.024 0 1.899 1.442 6.266 1.586 3.406.121 6.191-2.593 7.199-3.718l-3.55-3.48c-.747.862-2.184 2.23-3.962 2.35-2.23.145-4.105-.745-5.328-2.542-1.656-2.45-.863-5.664 1.848-7.489 1.055-.722 2.832-1.203 4.488-.671 1.512.476 2.496 1.46 3.024 2.16l3.55-3.457c-.308-.336-1.008-1.032-2.636-2.235-2.188-1.629-5.403-1.965-8.786-.933C5.281 3.625 3 7.922 2.762 11.352c-.145 1.968.308 3.816 1.535 6.168.383.746.766 1.609.742 3.12a3.16 3.16 0 0 1-.336 1.415c.145-.024.29-.07.434-.117.597-.22 1.199-.868 1.367-1.083Zm0 0" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/check-box.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/check-box.jsx
new file mode 100755
index 0000000..cf80ac0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/check-box.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function CheckBox(props) {
4 return (
5 <Icon {...props}>
6 <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM17.99 9l-1.41-1.42-6.59 6.59-2.58-2.57-1.42 1.41 4 3.99z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-bottom.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-bottom.jsx
new file mode 100755
index 0000000..1ed7678
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-bottom.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ChevronBottom(props) {
4 return (
5 <Icon {...props}>
6 <path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-left.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-left.jsx
new file mode 100755
index 0000000..f9da786
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-left.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ChevronLeft(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.25 12l8.25-8.25L15.75 0l-12 12 12 12 3.75-3.75L11.25 12z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-right.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-right.jsx
new file mode 100755
index 0000000..028c8b1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-right.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ChevronRight(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.75 12L4.5 3.75 8.25 0l12 12-12 12-3.75-3.75L12.75 12z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-top.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-top.jsx
new file mode 100755
index 0000000..37f5dfc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/chevron-top.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ChevronTop(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude-code.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude-code.jsx
new file mode 100755
index 0000000..65babc9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude-code.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function ClaudeCode(props) {
4 return (
5 <Icon {...props}>
6 <path
7 clipRule="evenodd"
8 d="M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude.jsx
new file mode 100755
index 0000000..53f843b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/claude.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Claude(props) {
4 return (
5 <Icon {...props}>
6 <path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/click-up.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/click-up.jsx
new file mode 100755
index 0000000..467588e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/click-up.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ClickUp(props) {
4 return (
5 <Icon {...props}>
6 <path d="M2,18.439 L5.69,15.611 C7.651,18.171 9.734,19.35 12.053,19.35 C14.36,19.35 16.383,18.184 18.256,15.646 L22,18.405 C19.298,22.065 15.941,24 12.053,24 C8.178,24 4.788,22.078 2,18.439 Z M12.04,6.15 L5.472,11.81 L2.436,8.29 L12.055,0 L21.598,8.296 L18.548,11.805 L12.04,6.15 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cline.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cline.jsx
new file mode 100755
index 0000000..11caeb8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cline.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Cline(props) {
4 return (
5 <Icon {...props}>
6 <path d="M17.035 3.991c2.75 0 4.98 2.24 4.98 5.003v1.667l1.45 2.896a1.01 1.01 0 01-.002.909l-1.448 2.864v1.668c0 2.762-2.23 5.002-4.98 5.002H7.074c-2.751 0-4.98-2.24-4.98-5.002V17.33l-1.48-2.855a1.01 1.01 0 01-.003-.927l1.482-2.887V8.994c0-2.763 2.23-5.003 4.98-5.003h9.962zM8.265 9.6a2.274 2.274 0 00-2.274 2.274v4.042a2.274 2.274 0 004.547 0v-4.042A2.274 2.274 0 008.265 9.6zm7.326 0a2.274 2.274 0 00-2.274 2.274v4.042a2.274 2.274 0 104.548 0v-4.042A2.274 2.274 0 0015.59 9.6z" />
7 <path d="M12.054 5.558a2.779 2.779 0 100-5.558 2.779 2.779 0 000 5.558z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/clock.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/clock.jsx
new file mode 100755
index 0000000..ce01a6c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/clock.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Clock(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 3c-4.9706 0-9 4.0294-9 9s4.0294 9 9 9 9-4.0294 9-9-4.0294-9-9-9ZM1 12C1 5.9249 5.9249 1 12 1s11 4.9249 11 11-4.9249 11-11 11S1 18.0751 1 12Z" />
7 <path d="M12 5c.5523 0 1 .4477 1 1v5.382l3.4472 1.7236c.494.247.6942.8476.4472 1.3416-.247.494-.8476.6942-1.3416.4472l-4-2A1 1 0 0 1 11 12V6c0-.5523.4477-1 1-1Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/close.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/close.jsx
new file mode 100755
index 0000000..627ff65
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/close.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Close(props) {
4 return (
5 <Icon {...props}>
6 <path d="M24 2.4L21.6 0L12 9.6L2.4 0L0 2.4L9.6 12L0 21.6L2.4 24L12 14.4L21.6 24L24 21.6L14.4 12L24 2.4Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cloud.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cloud.jsx
new file mode 100755
index 0000000..4b5b44a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cloud.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Cloud(props) {
5 return (
6 <Icon
7 {...props}
8 className={Utils.classNames(props.className, "cloud-icon")}
9 >
10 <path d="M17.173 8.725a2.181 2.181 0 0 1-2.112-1.636 6.544 6.544 0 1 0-6.331 8.18h9.817a3.272 3.272 0 1 0 0-6.544h-1.374ZM8.73 17.45a8.725 8.725 0 1 1 8.442-10.906h1.374a5.453 5.453 0 1 1 0 10.906H8.73Z" />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/code.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/code.jsx
new file mode 100755
index 0000000..d0bd4cb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/code.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Code(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8.54 14.69L2.6 19.3 0 18.02V5.99l2.58-1.3L8.5 9.33 17.85 0 24 2.44v19.08L17.88 24l-9.34-9.31zm9.12 1.62V7.7L12.06 12l5.6 4.3zM2.8 14.76l2.94-2.66L2.8 9.18v5.58z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/codex.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/codex.jsx
new file mode 100755
index 0000000..332ea52
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/codex.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Codex(props) {
4 return (
5 <Icon {...props}>
6 <path
7 clipRule="evenodd"
8 d="M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/coffee.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/coffee.jsx
new file mode 100755
index 0000000..e168da6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/coffee.jsx
@@ -0,0 +1,15 @@
1import Icon from "../icon.jsx";
2
3export default function Coffee(props) {
4 return (
5 <Icon {...props}>
6 <path d="M17 8C17 7.44772 17.4477 7 18 7H19C20.3261 7 21.5979 7.52678 22.5355 8.46447C23.4732 9.40215 24 10.6739 24 12C24 13.3261 23.4732 14.5979 22.5355 15.5355C21.5979 16.4732 20.3261 17 19 17H18C17.4477 17 17 16.5523 17 16C17 15.4477 17.4477 15 18 15H19C19.7956 15 20.5587 14.6839 21.1213 14.1213C21.6839 13.5587 22 12.7956 22 12C22 11.2044 21.6839 10.4413 21.1213 9.87868C20.5587 9.31607 19.7956 9 19 9H18C17.4477 9 17 8.55228 17 8Z" />
7 <path d="M1 8C1 7.44772 1.44772 7 2 7H18C18.5523 7 19 7.44772 19 8V17C19 18.3261 18.4732 19.5979 17.5355 20.5355C16.5979 21.4732 15.3261 22 14 22H6C4.67392 22 3.40215 21.4732 2.46447 20.5355C1.52678 19.5979 1 18.3261 1 17V8ZM3 9V17C3 17.7956 3.31607 18.5587 3.87868 19.1213C4.44129 19.6839 5.20435 20 6 20H14C14.7956 20 15.5587 19.6839 16.1213 19.1213C16.6839 18.5587 17 17.7956 17 17V9H3Z" />
8 <g>
9 <path d="M6 0C6.55228 0 7 0.447715 7 1V4C7 4.55228 6.55228 5 6 5C5.44772 5 5 4.55228 5 4V1C5 0.447715 5.44772 0 6 0Z" />
10 <path d="M10 0C10.5523 0 11 0.447715 11 1V4C11 4.55228 10.5523 5 10 5C9.44772 5 9 4.55228 9 4V1C9 0.447715 9.44772 0 10 0Z" />
11 <path d="M14 0C14.5523 0 15 0.447715 15 1V4C15 4.55228 14.5523 5 14 5C13.4477 5 13 4.55228 13 4V1C13 0.447715 13.4477 0 14 0Z" />
12 </g>
13 </Icon>
14 );
15}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/color-picker.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/color-picker.jsx
new file mode 100755
index 0000000..c02fd7a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/color-picker.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ColorPicker(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.64 4.22l-2.86-2.86a1.22 1.22 0 00-1.72 0l-3.81 3.81-1.5-1.48a1.22 1.22 0 10-1.72 1.72l.87.88L1.18 17.01a.6.6 0 00-.18.44v4.94c0 .34.27.61.61.61h4.94c.16 0 .32-.06.43-.18L17.69 12.1l.88.88a1.22 1.22 0 101.73-1.72l-1.5-1.5 3.82-3.8c.5-.5.5-1.27.02-1.74zM5.8 20.56L3.45 18.2l9.85-9.85 2.34 2.35-9.85 9.85z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/comfy-ui.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/comfy-ui.jsx
new file mode 100755
index 0000000..5afa497
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/comfy-ui.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function ComfyUI(props) {
4 return (
5 <Icon {...props}>
6 <path d="M5.485 23.76c-.568 0-1.026-.207-1.325-.598-.307-.402-.387-.964-.22-1.54l.672-2.315a.605.605 0 00-.1-.536.622.622 0 00-.494-.243H2.085c-.568 0-1.026-.207-1.325-.598-.307-.403-.387-.964-.22-1.54l2.31-7.917.255-.87c.343-1.18 1.592-2.14 2.786-2.14h2.313c.276 0 .519-.18.595-.442l.764-2.633C9.906 1.208 11.155.249 12.35.249l4.945-.008h3.62c.568 0 1.027.206 1.325.597.307.402.387.964.22 1.54l-1.035 3.566c-.343 1.178-1.593 2.137-2.787 2.137l-4.956.01H11.37a.618.618 0 00-.594.441l-1.928 6.604a.605.605 0 00.1.537c.118.153.3.243.495.243l3.275-.006h3.61c.568 0 1.026.206 1.325.598.307.402.387.964.22 1.54l-1.036 3.565c-.342 1.179-1.592 2.138-2.786 2.138l-4.957.01h-3.61z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/copilot.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/copilot.jsx
new file mode 100755
index 0000000..151595c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/copilot.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Copilot(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.961.394a.5.5 0 0 1 .645.645l-8.264 21.786a.5.5 0 0 1-.929.015l-3.58-8.591a.5.5 0 0 0-.251-.262l-9.5-4.384a.5.5 0 0 1 .032-.922L22.96.394Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cp-u.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cp-u.jsx
new file mode 100755
index 0000000..7705607
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cp-u.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function CPU(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6 5c-.5523 0-1 .4477-1 1v12c0 .5523.4477 1 1 1h12c.5523 0 1-.4477 1-1V6c0-.5523-.4477-1-1-1H6ZM3 6c0-1.6569 1.3431-3 3-3h12c1.6569 0 3 1.3431 3 3v12c0 1.6569-1.3431 3-3 3H6c-1.6569 0-3-1.3431-3-3V6Z" />
7 <path d="M8 9c0-.5523.4477-1 1-1h6c.5523 0 1 .4477 1 1v6c0 .5523-.4477 1-1 1H9c-.5523 0-1-.4477-1-1V9Zm2 1v4h4v-4h-4ZM9 0c.5523 0 1 .4477 1 1v3c0 .5523-.4477 1-1 1s-1-.4477-1-1V1c0-.5523.4477-1 1-1ZM15 0c.5523 0 1 .4477 1 1v3c0 .5523-.4477 1-1 1s-1-.4477-1-1V1c0-.5523.4477-1 1-1ZM9 19c.5523 0 1 .4477 1 1v3c0 .5523-.4477 1-1 1s-1-.4477-1-1v-3c0-.5523.4477-1 1-1ZM15 19c.5523 0 1 .4477 1 1v3c0 .5523-.4477 1-1 1s-1-.4477-1-1v-3c0-.5523.4477-1 1-1ZM19 9c0-.5523.4477-1 1-1h3c.5523 0 1 .4477 1 1s-.4477 1-1 1h-3c-.5523 0-1-.4477-1-1ZM19 14c0-.5523.4477-1 1-1h3c.5523 0 1 .4477 1 1s-.4477 1-1 1h-3c-.5523 0-1-.4477-1-1ZM0 9c0-.5523.4477-1 1-1h3c.5523 0 1 .4477 1 1s-.4477 1-1 1H1c-.5523 0-1-.4477-1-1ZM0 14c0-.5523.4477-1 1-1h3c.5523 0 1 .4477 1 1s-.4477 1-1 1H1c-.5523 0-1-.4477-1-1Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cursor.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cursor.jsx
new file mode 100755
index 0000000..1b40ec3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/cursor.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Cursor(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.106 5.68L12.5.135a.998.998 0 00-.998 0L1.893 5.68a.84.84 0 00-.419.726v11.186c0 .3.16.577.42.727l9.607 5.547a.999.999 0 00.998 0l9.608-5.547a.84.84 0 00.42-.727V6.407a.84.84 0 00-.42-.726zm-.603 1.176L12.228 22.92c-.063.108-.228.064-.228-.061V12.34a.59.59 0 00-.295-.51l-9.11-5.26c-.107-.062-.063-.228.062-.228h18.55c.264 0 .428.286.296.514z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/data-grip.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/data-grip.jsx
new file mode 100755
index 0000000..6203fe3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/data-grip.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function DataGrip(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3 19.1999h9.6v1.8H3v-1.8ZM6.435 2.9951H3.0072v9.0036H6.435c.8526 0 1.6176-.1926 2.2926-.5784a4.1341 4.1341 0 0 0 1.5852-1.6044c.3816-.684.5724-1.4568.5724-2.319 0-.8622-.1908-1.6344-.5724-2.3184a4.1292 4.1292 0 0 0-1.5852-1.6044c-.675-.3864-1.4394-.579-2.2926-.579Zm2.3214 6.0936c-.2184.4482-.5292.792-.9324 1.032s-.873.36-1.4088.36h-1.653V4.5125h1.653c.5364 0 1.0056.12 1.4088.36.4032.2406.714.5844.9324 1.0326.219.4476.3282.978.3282 1.5918 0 .6138-.1092 1.1436-.3282 1.5918Zm3.6528.7848a4.373 4.373 0 0 0 1.6464 1.6716v-.0006c.699.4056 1.5132.6078 2.3412.6078.8274 0 1.5744-.1842 2.2416-.5526a4.13 4.13 0 0 0 1.575-1.515c.384-.6408.576-1.3584.576-2.151v-.708h-3.8136v1.3824h2.0945a1.9786 1.9786 0 0 1-.3647.9138c-.2358.3258-.5544.5814-.9552.7656-.4008.1842-.8478.2766-1.341.2766-.5316 0-1.0122-.1326-1.4406-.3984a2.764 2.764 0 0 1-1.0068-1.0968c-.2418-.465-.363-.99-.363-1.5726s.1212-1.107.363-1.572a2.7672 2.7672 0 0 1 1.0068-1.0968c.429-.2658.909-.3984 1.4406-.3984.3606 0 .6966.057 1.0098.1704.3132.1134.5862.2742.8202.4818.2323.2064.4214.4569.5562.7368h1.878a3.8172 3.8172 0 0 0-.852-1.5564 4.1454 4.1454 0 0 0-1.4922-1.0482c-.5898-.2484-1.2342-.3732-1.9326-.3732-.8616 0-1.6428.2034-2.3412.6084-.6984.405-1.248.963-1.6464 1.6722-.3984.7092-.5982 1.5012-.5982 2.376 0 .8748.1998 1.6668.5982 2.3766Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/date.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/date.jsx
new file mode 100755
index 0000000..9e59c84
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/date.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Date(props) {
4 return (
5 <Icon {...props}>
6 <path d="M5 5c-.5523 0-1 .4477-1 1v14c0 .5523.4477 1 1 1h14c.5523 0 1-.4477 1-1V6c0-.5523-.4477-1-1-1H5ZM2 6c0-1.6569 1.3432-3 3-3h14c1.6569 0 3 1.3431 3 3v14c0 1.6569-1.3431 3-3 3H5c-1.6568 0-3-1.3431-3-3V6Z" />
7 <path d="M16 1c.5523 0 1 .4477 1 1v4c0 .5523-.4477 1-1 1s-1-.4477-1-1V2c0-.5523.4477-1 1-1ZM8 1c.5523 0 1 .4477 1 1v4c0 .5523-.4477 1-1 1s-1-.4477-1-1V2c0-.5523.4477-1 1-1ZM2 10c0-.5523.4477-1 1-1h18c.5523 0 1 .4477 1 1s-.4477 1-1 1H3c-.5523 0-1-.4477-1-1Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/de-v-o-nthink3.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/de-v-o-nthink3.jsx
new file mode 100755
index 0000000..5f5acd1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/de-v-o-nthink3.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function DEVONthink3(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5 0a5 5 0 0 0-5 5v14a5 5 0 0 0 5 5h14a5 5 0 0 0 5-5V5a5 5 0 0 0-5-5H5Zm9.916 6.223c-.577-.865-1.313-1.306-2.17-1.52-.81-.203-1.737-.203-2.703-.203H10c-1.12 0-2.218.418-3.097 1.026-.874.605-1.584 1.436-1.877 2.316l-.009.026c-.498 1.493-1.037 3.112-.502 5.253.267 1.069.795 2.118 1.31 2.954.512.832 1.035 1.492 1.321 1.779.11.11.259.206.4.288.149.085.324.172.512.258a20.47 20.47 0 0 0 2.54.917c.186.053.357.096.501.128.133.028.28.055.401.055.04 0 .125.006.283.017l.017.002c.144.01.328.023.54.035.44.024 1.006.04 1.624.008 1.216-.064 2.715-.321 3.836-1.162 1.675-1.256 2.787-2.957 3.147-3.676l.216-.432-5.568-3.037c.408-1.549.34-3.504-.679-5.032Zm-.832.554c.888 1.332.908 3.154.446 4.552a4.398 4.398 0 0 0-.043.114c-.213.487-.757.878-1.43 1.158-.704.294-1.388.399-1.557.399-.145 0-.66-.092-1.13-.457-.442-.343-.87-.948-.87-2.043 0-.837.338-1.312.73-1.594.417-.3.933-.406 1.27-.406.059 0 .22.052.42.252.187.187.342.44.41.692.068.248.043.453-.056.606-.098.155-.33.351-.872.46l.196.98c.709-.142 1.226-.445 1.518-.9.292-.455.299-.97.179-1.41a2.625 2.625 0 0 0-.668-1.135c-.284-.284-.686-.545-1.127-.545-.497 0-1.23.145-1.855.594C8.995 8.562 8.5 9.337 8.5 10.5c0 1.405.572 2.3 1.256 2.832.655.51 1.39.668 1.744.668.331 0 1.147-.145 1.942-.476a5.34 5.34 0 0 0 .732-.37l.001.12c.019.74.249 1.585 1.006 2.114.312.3 1.124.958 2.159 1.165.312.062.648.084.994.041A9.678 9.678 0 0 1 17.2 17.6c-.879.659-2.13.902-3.289.963-.57.03-1.097.015-1.517-.008a27.053 27.053 0 0 1-.523-.034l-.028-.002h-.005a5.156 5.156 0 0 0-.337-.019s-.014 0-.048-.006a2.31 2.31 0 0 1-.142-.027 7.587 7.587 0 0 1-.44-.112 19.41 19.41 0 0 1-2.398-.864 5.345 5.345 0 0 1-.429-.216 1.092 1.092 0 0 1-.19-.128c-.214-.214-.69-.804-1.178-1.596-.486-.79-.958-1.74-1.19-2.672-.462-1.846-.011-3.221.488-4.72.207-.62.747-1.29 1.498-1.81C8.218 5.832 9.121 5.5 10 5.5c1.018 0 1.826.003 2.504.173.644.16 1.157.47 1.58 1.104Zm1.09 6.473c-.008-.351.045-.71.12-1.02l4.46 2.433c-.347.412-.69.655-1.007.792-.415.18-.825.194-1.211.117-.8-.16-1.464-.707-1.682-.926l-.035-.035-.042-.027c-.409-.273-.587-.745-.602-1.334Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/deezer.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/deezer.jsx
new file mode 100755
index 0000000..ec0b2ae
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/deezer.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Deezer(props) {
4 return (
5 <Icon {...props}>
6 <path d="M20.1289 3.6616c.222-1.287.5479-2.0963.9088-2.0979h.0007c.6731.0023 1.2187 2.809 1.2187 6.2743s-.5464 6.2742-1.2201 6.2742c-.2763 0-.5312-.4769-.7364-1.2762-.3243 2.9258-.9973 4.937-1.7764 4.937-.6028 0-1.1438-1.2081-1.507-3.1135-.2479 3.6237-.8721 6.1947-1.6016 6.1947-.4578 0-.8752-1.0188-1.1842-2.6777-.3716 3.4243-1.2301 5.8236-2.2311 5.8236-1.0011 0-1.8611-2.3986-2.2312-5.8236-.3067 1.6589-.7241 2.6777-1.1842 2.6777-.7295 0-1.3521-2.571-1.6016-6.1947-.3632 1.9054-.9027 3.1135-1.507 3.1135-.7784 0-1.4521-2.0105-1.7764-4.937-.2037.8016-.4601 1.2762-.7363 1.2762-.6738 0-1.2202-2.8089-1.2202-6.2742 0-3.4653.5464-6.2743 1.2202-6.2743.3616 0 .6852.8116.9095 2.0979C4.2325 1.4424 4.8162 0 5.4763 0c.7836 0 1.4627 2.0399 1.784 5.002.3143-2.1559.7912-3.5303 1.3253-3.5303.7486 0 1.385 2.7031 1.6207 6.4737.4433-1.9332 1.0851-3.146 1.7955-3.146.7103 0 1.3521 1.2136 1.7946 3.146.2366-3.7706.8722-6.4737 1.6208-6.4737.5333 0 1.0094 1.3744 1.3254 3.5302C17.0631 2.04 17.7422 0 18.5258 0c.6577 0 1.2437 1.4431 1.6031 3.6616ZM0 7.2209c0-1.549.3098-2.8052.692-2.8052.3824 0 .6922 1.2561.6922 2.8052 0 1.549-.3098 2.8051-.6921 2.8051C.3098 10.026 0 8.7699 0 7.2209Zm22.6158 0c0-1.549.3098-2.8052.6921-2.8052.3822 0 .6921 1.2561.6921 2.8052 0 1.549-.3099 2.8051-.6921 2.8051-.3823 0-.6921-1.2561-.6921-2.8051Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/default.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/default.jsx
new file mode 100755
index 0000000..6a0902c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/default.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Default(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M2 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h20a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H2zm1.5 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM9 5.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zM11.5 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/desktop.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/desktop.jsx
new file mode 100755
index 0000000..c7fae7b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/desktop.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Desktop(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21 2H3a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h7l-1.63 2.45A1 1 0 0 0 9.2 22h5.6a1 1 0 0 0 .83-1.55L14 18h7a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zm0 12H3V5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v9z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/discord.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/discord.jsx
new file mode 100755
index 0000000..7b1a27b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/discord.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Discord(props) {
4 return (
5 <Icon {...props}>
6 <path d="M20.3170136,4.49210179 C18.7873347,3.80147275 17.1469855,3.29264772 15.4318982,3.00122249 C15.4006644,2.99559808 15.3694644,3.00965379 15.3533742,3.03776589 C15.1424109,3.40696539 14.908732,3.88861627 14.7450926,4.26719168 C12.9004053,3.99545024 11.0651828,3.99545024 9.25832087,4.26719168 C9.09464763,3.88020127 8.85248426,3.40696539 8.6405744,3.03776589 C8.62448426,3.01059175 8.59328426,2.99653603 8.56205046,3.00122249 C6.84790966,3.29171642 5.2075604,3.80054145 3.67693509,4.49210179 C3.66368438,4.49772288 3.65232664,4.50710245 3.64478861,4.51927593 C0.533391499,9.09311339 -0.318950227,13.554529 0.0991801295,17.9606319 C0.101072073,17.9821849 0.113369876,18.0028067 0.130398044,18.0159115 C2.18320892,19.4992804 4.17170691,20.3998189 6.12327869,20.9967188 C6.15451249,21.0060984 6.18760545,20.9948562 6.2074815,20.9695446 C6.66912656,20.3492291 7.08064205,19.6951538 7.43347584,19.0073187 C7.45429838,18.9670397 7.43442232,18.9192439 7.39186457,18.9033119 C6.7391322,18.6596759 6.11759982,18.3626229 5.51972941,18.025291 C5.47243927,17.9981169 5.46865335,17.9315618 5.51215758,17.8996979 C5.63797166,17.8069333 5.76381954,17.7104102 5.88395475,17.6129558 C5.90568996,17.5951612 5.93597729,17.5914028 5.96153221,17.6026449 C9.88928423,19.3671682 14.1415433,19.3671682 18.0229516,17.6026449 C18.0485066,17.5904715 18.0787939,17.5942299 18.1014756,17.6120245 C18.2216446,17.7094789 18.3474587,17.8069333 18.4742192,17.8996979 C18.5177235,17.9315618 18.514884,17.9981169 18.4675939,18.025291 C17.8697235,18.3691753 17.2481911,18.6596759 16.5945122,18.9023806 C16.5519545,18.9183125 16.5330249,18.9670397 16.5538475,19.0073187 C16.9142531,19.6941892 17.3257686,20.3482645 17.7788953,20.9686133 C17.7978249,20.9948562 17.8318643,21.0060984 17.8630981,20.9967188 C19.8241347,20.3998189 21.8126192,19.4992804 23.8654304,18.0159115 C23.8834135,18.0028067 23.8947712,17.9831162 23.8966642,17.9615632 C24.3970811,12.8676252 23.0584896,8.44279655 20.3482136,4.52020723 C20.3415882,4.50710245 20.3302643,4.49772288 20.3170136,4.49210179 Z M8.02002231,15.2777755 C6.83749839,15.2777755 5.86313222,14.2095357 5.86313222,12.8976266 C5.86313222,11.5857174 6.81860262,10.5174776 8.02002231,10.5174776 C9.23087298,10.5174776 10.1958082,11.595097 10.1768786,12.8976266 C10.1768786,14.2095357 9.22140819,15.2777755 8.02002231,15.2777755 Z M15.9947489,15.2777755 C14.8122588,15.2777755 13.8378926,14.2095357 13.8378926,12.8976266 C13.8378926,11.5857174 14.7933292,10.5174776 15.9947489,10.5174776 C17.2056334,10.5174776 18.1705347,11.595097 18.151639,12.8976266 C18.151639,14.2095357 17.2056334,15.2777755 15.9947489,15.2777755 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/docker.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/docker.jsx
new file mode 100755
index 0000000..2ed8850
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/docker.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function Windows(props) {
4 return (
5 <Icon {...props}>
6 <path d="M5 9.65h2.2v2.22H5zm-2.7 0h2.2v2.22H2.3z" />
7 <path d="M22.7 10.85a3.15 3.15 0 0 0-2.6-.3 3.3 3.3 0 0 0-1.45-2.2l-.25-.25-.25.3a3.05 3.05 0 0 0-.55 2.1 2.8 2.8 0 0 0 .5 1.4l-.75.35a5.3 5.3 0 0 1-1.5.25H1.1v.3a6.05 6.05 0 0 0 .5 3.25l.2.4c1.4 2.3 3.85 3.3 6.5 3.3 5.15 0 9.35-2.2 11.35-7 1.3.1 2.6-.25 3.25-1.5L23 11Zm-17.3 5.9a1.15 1.15 0 1 1 0-2.3 1.15 1.15 0 1 1 0 2.3M5 6.85h2.2v2.22H5z" />
8 <path d="M13.25 9.65h2.2v2.22h-2.2zM10.55 4h2.2v2.22h-2.2zm0 5.65h2.2v2.22h-2.2zM7.8 6.85H10v2.22H7.8zm2.75 0h2.2v2.22h-2.2zM7.8 9.65H10v2.22H7.8z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dollar.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dollar.jsx
new file mode 100755
index 0000000..5a24b9f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dollar.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Dollar(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm1.41 16.09v.58c0 .73-.6 1.33-1.33 1.33h-.01c-.73 0-1.33-.6-1.33-1.33v-.6c-1.33-.28-2.51-1.01-3.01-2.24-.23-.55.2-1.16.8-1.16h.24c.37 0 .67.25.81.6.29.75 1.05 1.27 2.51 1.27 1.96 0 2.4-.98 2.4-1.59 0-.83-.44-1.61-2.67-2.14-2.48-.6-4.18-1.62-4.18-3.67 0-1.72 1.39-2.84 3.11-3.21v-.6c0-.73.6-1.33 1.33-1.33h.01c.73 0 1.33.6 1.33 1.33v.62a3.56 3.56 0 0 1 2.63 2.26.85.85 0 0 1-.81 1.13h-.26a.8.8 0 0 1-.77-.62c-.23-.76-.86-1.25-2.12-1.25-1.5 0-2.4.68-2.4 1.64 0 .84.65 1.39 2.67 1.91s4.18 1.39 4.18 3.91c-.02 1.83-1.39 2.83-3.13 3.16z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/down-arrow.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/down-arrow.jsx
new file mode 100755
index 0000000..4cfd2e1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/down-arrow.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function DownArrow(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fill="var(--red)"
8 d="M0 7.33l2.829-2.83 9.175 9.339 9.167-9.339 2.829 2.83-11.996 12.17z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/download.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/download.jsx
new file mode 100755
index 0000000..e612225
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/download.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Download(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM13 8a1 1 0 1 1-2 0V5a1 1 0 1 1 2 0v3ZM13 20a1 1 0 1 1-2 0v-9a1 1 0 1 1 2 0v9Z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M12.707 22.707a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 1.414-1.414L12 20.586l6.293-6.293a1 1 0 0 1 1.414 1.414l-7 7Z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/drafts.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/drafts.jsx
new file mode 100755
index 0000000..7c4c114
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/drafts.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Drafts(props) {
4 return (
5 <Icon {...props}>
6 <path d="M3.355,20.645L15.871,20.645C16.797,20.645 17.548,21.397 17.548,22.323C17.548,23.248 16.797,24 15.871,24L1.677,24C0.751,24 0,23.249 0,22.323L0,8.129C-0,7.203 0.752,6.452 1.677,6.452C2.603,6.452 3.355,7.203 3.355,8.129L3.355,20.645ZM20.645,3.355L8.129,3.355C7.203,3.355 6.452,2.603 6.452,1.677C6.452,0.752 7.203,-0 8.129,0L22.323,0C23.249,-0 24,0.751 24,1.677L24,15.871C24,16.797 23.248,17.548 22.323,17.548C21.397,17.548 20.645,16.797 20.645,15.871L20.645,3.355ZM15.766,8.234L10.765,8.234C10.337,8.234 9.99,7.887 9.99,7.46C9.99,7.033 10.337,6.686 10.765,6.686L16.54,6.686C16.967,6.686 17.314,7.033 17.314,7.46L17.314,13.235C17.314,13.663 16.967,14.01 16.54,14.01C16.113,14.01 15.766,13.663 15.766,13.235L15.766,8.234Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dropbox.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dropbox.jsx
new file mode 100755
index 0000000..159fac3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/dropbox.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Dropbox(props) {
4 return (
5 <Icon {...props}>
6 <path d="M7.3125,0 L0,4.8 L5.025,8.625 L12,4.0875 L7.3125,0 Z M12,4.0875 L19.3125,8.4 L24,4.575 L16.9125,0 L12,4.0875 Z M19.3125,8.4 L12,13.0875 L16.8,16.8 L24,12.4875 L19.3125,8.4 Z M12,13.0875 L5.025,8.625 L0,12.4875 L7.3125,16.8 L12,13.0875 Z M12,15 L7.2,18.6 L4.8,17.175 L4.8,19.2 L12,24 L19.2,19.3125 L19.2,17.175 L16.8,18.6 L12,15 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/element.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/element.jsx
new file mode 100755
index 0000000..03de2a2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/element.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Element(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12 24a12 12 0 100-24 12 12 0 000 24zM9.8 5.6c0-.5.4-.9.9-.9a6 6 0 016 6 .9.9 0 01-1.8 0c0-2.4-1.9-4.2-4.2-4.2a.9.9 0 01-.9-1zm9.5 5a.9.9 0 00-1.8 0c0 2.4-1.9 4.2-4.2 4.2a.9.9 0 100 1.8 6 6 0 006-6zm-5 7.8c0 .5-.5.9-1 .9a6 6 0 01-6-6 .9.9 0 011.8 0c0 2.4 2 4.2 4.2 4.2.5 0 1 .4 1 1zm-9.6-5a.9.9 0 001.8 0c0-2.4 1.9-4.2 4.2-4.2a.9.9 0 100-1.8 6 6 0 00-6 6z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/emacs.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/emacs.jsx
new file mode 100755
index 0000000..59dd511
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/emacs.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Emacs(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12 23a11 11 0 100-22 11 11 0 000 22zm-1.65-3.31c-1.2.1-2.13.04-2.13.04.02 0 3.25-.72 4.49-1.07l.31-.09c.7-.19 1.95-.53 1.93-.68-.01-.13-.26-.18-1.84-.1a10.6 10.6 0 01-5.38-.62c-3.05-1-3.7-2.63-2.22-3.99 1.31-1.09 3.56-2.03 6.67-1.86 0 0-1.06-.32-1.42-.5l-.31-.14c-.95-.43-2.24-1.03-3.17-2.05l-.13-.15c-.26-.31-.63-.74-.4-1.23.38-.8 1.58-.86 3.3-.96l.44-.02s2.03-.2 3-.35c.9-.15 1.12-.43.97-.63-.25-.35-.81-.4-4.18-.38 0 0 2.72-.78 3.86-.99 1.2-.21 2.46.41 2.7 1.48.27 1.04-.37 1.7-1.35 1.86 0 0-.11.05-.82.06-1.4.02-2.94.21-4.03.52-.34.1-.95.43-.77.82.15.39.82.7 1.28.93l.07.04 1.18.55c1 .47 2.38 1.11 3.26 1.54 0 0-4.06.92-5.09 1.41-2.05.93-2.3 2-1.82 2.37.5.38 1.44.85 4.26.94l1.27.02c1.74.02 2.76.04 3.67.41.37.16.37.4.36.52v.05c-.23.4-.74.7-1.68 1.04-.9.33-2.58.69-2.58.69-1.37.3-3.22.47-3.7.52z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ethereum.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ethereum.jsx
new file mode 100755
index 0000000..7c29401
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ethereum.jsx
@@ -0,0 +1,34 @@
1import Icon from "../icon.jsx";
2
3export default function Ethereum(props) {
4 return (
5 <Icon width={156} height={256} {...props}>
6 <path
7 d="M0,128 L80,0 L80,93.5358372 L0,128 Z M156,128 L80,93.5809573 L80,0 L156,128 Z"
8 fill="#828384"
9 id="Combined-Shape"
10 />
11 <path
12 d="M80,176 L0,131.00396 L80,96 L80,176 Z M156,131.011473 L80,176 L80,96 L156,131.011473 Z"
13 fill="#343535"
14 id="Combined-Shape"
15 />
16 <path
17 d="M0,148 L80,194.180711 L80,256 L0,148 Z M156,148 L80,256 L80,194.175361 L156,148 Z"
18 fill="#828384"
19 id="Combined-Shape"
20 />
21 <polygon fill="#2F3030" id="Path-3" points="156 128 80 93.5809573 80 0" />
22 <polygon
23 fill="#131313"
24 id="Path-5"
25 points="156 131.011473 80 96 80 176"
26 />
27 <polygon
28 fill="#2F3030"
29 id="Path-7"
30 points="156 148 80 194.175361 80 256"
31 />
32 </Icon>
33 );
34}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/evernote-legacy.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/evernote-legacy.jsx
new file mode 100755
index 0000000..fcda973
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/evernote-legacy.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function EvernoteLegacy(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.92,23.85A11.93,11.93,0,1,1,23.85,12,11.91,11.91,0,0,1,11.92,23.85Zm-.4-10.34a1.93,1.93,0,0,0,.92,1.33,3.56,3.56,0,0,0,1.52.51,2.36,2.36,0,0,1,1.76,1.09,1.82,1.82,0,0,1-1.24,2.87,1.3,1.3,0,0,1-1.2-.4.73.73,0,0,1-.19-.74.68.68,0,0,1,.58-.46l.16,0a.66.66,0,0,0,.54-.7.64.64,0,0,0-.67-.6,2.31,2.31,0,0,0-.37,0A2.11,2.11,0,0,0,11.6,18a2,2,0,0,0,.75,2.22,3.16,3.16,0,0,0,2.46.65,4,4,0,0,0,3-1.89,5.69,5.69,0,0,0,.81-2.46c.09-.84.15-1.69.16-2.53,0-1,0-2-.06-3a25.23,25.23,0,0,0-.42-3.56,2.39,2.39,0,0,0-1.1-1.67,3.75,3.75,0,0,0-1.33-.49l-3.08-.53a.2.2,0,0,1-.18-.15,1.4,1.4,0,0,0-.89-.94,3.46,3.46,0,0,0-1.66-.13,1.11,1.11,0,0,0-1,1.14c0,.95,0,1.9,0,2.85a2.43,2.43,0,0,1,0,.38.88.88,0,0,1-.71.8,3,3,0,0,1-.61.08H5a.88.88,0,0,0-.55.17,1.22,1.22,0,0,0-.52,1.19,17.49,17.49,0,0,0,.52,2.67,4,4,0,0,0,1.42,2.27,5.36,5.36,0,0,0,3.66,1.1,1.35,1.35,0,0,0,1.15-.65,5.22,5.22,0,0,0,.64-1.35C11.39,13.94,11.46,13.73,11.52,13.51Zm-7-5.18c.16,0,.28-.07.39-.08l.92,0h2a.66.66,0,0,0,.75-.56.78.78,0,0,0,0-.22V5.68c0-.34,0-.68,0-1s0-.39.07-.6Z" />
7 <path d="M16.37,11.89a6.16,6.16,0,0,1-1.42-.2c-.16,0-.19-.11-.13-.27a.78.78,0,0,1,.34-.4,1.2,1.2,0,0,1,1.35.15.82.82,0,0,1,.24.48c0,.17,0,.23-.18.24Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/face-time.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/face-time.jsx
new file mode 100755
index 0000000..df94f94
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/face-time.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function FaceTime(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0 8.30857018L0 16.6914791C0 18.5218303 1.51470151 20 3.36768637 20L13.6323136 20C15.4953965 20 17 18.5119097 17 16.6914791L17 8.30857018C17 6.47821906 15.4852985 5 13.6323136 5L3.37778438 5C1.51470151 4.99012871 0 6.47821906 0 8.30857018zM21.8033208 5.34198159L17.9441174 8.81128664C17.601525 9.1246787 17.4 9.58102152 17.4 10.0648549L17.4 14.8701997C17.4 15.3540331 17.5914487 15.8048778 17.9290031 16.1182699L21.7882064 19.6535522C22.6698782 20.4562757 24 19.7745105 24 18.5264404L24 6.46909337C24.0100193 5.23201946 22.6799545 4.54475618 21.8033208 5.34198159z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/figma.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/figma.jsx
new file mode 100755
index 0000000..af80266
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/figma.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Figma(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8 24c.5 0 1 0 1.5-.3a4 4 0 0 0 1.3-.7c.4-.4.7-.7.9-1.2.2-.4.3-.8.3-1.3V17H8c-.5 0-1 0-1.5.3a4 4 0 0 0-1.3.7c-.4.4-.7.7-.9 1.2a3.1 3.1 0 0 0 0 2.6c.2.5.5.8.9 1.2.3.3.8.6 1.3.7L8 24zM4 12.5c0-1.2.4-2.3 1.2-3.2C5.9 8.5 6.9 8 8 8h4v9H8c-1 0-2-.5-2.8-1.3-.8-.9-1.2-2-1.2-3.2zM4 4a4 4 0 0 1 4-4h4v8H8a4 4 0 0 1-4-4zM12 0h4a4 4 0 1 1 0 8h-4V0z" />
7 <path d="M20 12.5a5 5 0 0 1-.7 2.5c-.4.7-1 1.3-1.8 1.7-.7.3-1.5.4-2.3.2-.8-.2-1.5-.6-2-1.2-.6-.6-1-1.4-1.1-2.3a5 5 0 0 1 .2-2.6c.3-.8.8-1.5 1.5-2 .6-.5 1.4-.8 2.2-.8 1 0 2 .5 2.8 1.3.8.9 1.2 2 1.2 3.2z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/final-cut-pro.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/final-cut-pro.jsx
new file mode 100755
index 0000000..6d9800b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/final-cut-pro.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function FinalCutPro(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.608,20.001l-1.743,-9.881l0,-0.001l-0.581,-3.294c-0.034,-0.191 -0.151,-0.346 -0.308,-0.435c-0.122,-0.07 -0.268,-0.098 -0.416,-0.072l-11.473,2.023l10.947,-3.985c0.325,-0.118 0.492,-0.476 0.374,-0.801l-1.144,-3.143c-0.057,-0.157 -0.173,-0.284 -0.323,-0.353c-0.151,-0.07 -0.323,-0.078 -0.479,-0.022l-17.667,6.431c-0.325,0.118 -0.493,0.478 -0.374,0.802l1.125,3.092l0.571,3.239l1.743,9.882c0.029,0.164 0.121,0.309 0.257,0.403c0.106,0.075 0.232,0.114 0.359,0.114c0.037,0 0.073,-0.003 0.109,-0.009l18.516,-3.265c0.163,-0.029 0.308,-0.121 0.403,-0.257c0.095,-0.136 0.133,-0.305 0.104,-0.468Zm-3.084,-10.281l-2.318,0.409l1.286,-2.352l0.669,-0.118l0.363,2.061Zm-17.646,0.986l2.325,-0.409l-1.286,2.352l-0.676,0.119l-0.363,-2.062Zm5.194,-5.555l-0.858,2.54l-2.536,0.923l0.858,-2.54l2.536,-0.923Zm4.043,-1.471l-0.858,2.539l-2.536,0.923l0.857,-2.539l2.537,-0.923Zm4.042,-1.472l-0.857,2.54l-2.537,0.923l0.858,-2.54l2.536,-0.923Zm-9.376,7.81l2.659,-0.469l-1.286,2.352l-2.659,0.469l1.286,-2.352Zm4.238,-0.746l2.657,-0.469l-1.285,2.352l-2.659,0.468l1.287,-2.351Zm4.236,-0.748l2.658,-0.469l-1.286,2.352l-2.658,0.469l1.286,-2.352Zm3.764,-5.13l-2.213,0.806l0.858,-2.539l0.638,-0.233l0.717,1.966Zm-14.989,3.229l-0.857,2.539l-0.647,0.235l-0.715,-1.967l2.219,-0.807Zm0.954,16.027l-1.526,-8.65l17.283,-3.047l1.525,8.649l-17.282,3.048Zm16.132,-12.017l-18.377,3.255l1.634,9.231l18.378,-3.255l-1.635,-9.231Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/finder.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/finder.jsx
new file mode 100755
index 0000000..e71536c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/finder.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Finder(props) {
4 return (
5 <Icon {...props}>
6 <path d="M2 2h-.2A2 2 0 000 4v16a2 2 0 001.8 2H22c1 0 2-1 2-2V4c0-1-1-2-2-2H2zm9.9 2H22v16h-8.3l-.3-2A12.5 12.5 0 015 15.7 1 1 0 016 14.2S8.5 16 12 16h1.2l-.2-3h-2.3a.7.7 0 01-.7-.7A21 21 0 0112 4zm1.3 12l.2 2c3.4-.5 5.6-2.1 5.7-2.2a1 1 0 00-1.2-1.6S16 15.6 13.2 16zM18 7a1 1 0 00-1 1v1a1 1 0 102 0V8a1 1 0 00-1-1zM6 7c.6 0 1 .4 1 1v1a1 1 0 11-2 0V8c0-.6.4-1 1-1z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox-developer-edition.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox-developer-edition.jsx
new file mode 100755
index 0000000..afd96d2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox-developer-edition.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function FirefoxDeveloperEdition(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8.855 7.333c.008 0 .004 0 0 0zM6.082 5.947c.007 0 .004 0 0 0zm16.59 2.14c-.5-1.203-1.514-2.503-2.31-2.914.648 1.27 1.023 2.544 1.166 3.495l.002.02c-1.302-3.246-3.51-4.555-5.314-7.404-.09-.145-.182-.289-.27-.441a3.51 3.51 0 01-.128-.238 2.097 2.097 0 01-.171-.456.03.03 0 00-.027-.03.038.038 0 00-.021 0l-.006.002a.037.037 0 00-.009.005.038.038 0 01.005-.007c-2.56 1.5-3.622 4.126-3.894 5.797a6.136 6.136 0 00-2.282.582.294.294 0 00-.146.366.29.29 0 00.392.169 5.567 5.567 0 011.988-.519l.067-.005A5.636 5.636 0 0112 6.5a5.79 5.79 0 011.652.229l.094.03a5.757 5.757 0 01.265.088 5.839 5.839 0 01.191.075c.052.02.103.041.154.063a5.676 5.676 0 01.235.111l.106.054a5.776 5.776 0 01.224.123 5.165 5.165 0 01.141.086 5.895 5.895 0 012.014 2.083c-.615-.432-1.716-.859-2.776-.674 4.142 2.07 3.03 9.201-2.71 8.932a5.113 5.113 0 01-1.498-.29 6.347 6.347 0 01-.339-.137 4.37 4.37 0 01-.194-.093c-1.406-.727-2.567-2.1-2.712-3.768 0 0 .531-1.981 3.806-1.981.354 0 1.366-.988 1.385-1.274-.005-.094-2.009-.891-2.79-1.66-.418-.412-.616-.61-.791-.76a3.436 3.436 0 00-.299-.225 5.335 5.335 0 01-.032-2.814c-1.183.539-2.103 1.39-2.772 2.142h-.006c-.456-.578-.424-2.486-.398-2.884-.006-.025-.34.174-.385.204a8.395 8.395 0 00-1.125.964 10.086 10.086 0 00-1.075 1.29v0A9.72 9.72 0 00.819 9.9c-.003.013-.11.482-.188 1.062a12.736 12.736 0 00-.037.27 7.724 7.724 0 00-.068.66l-.002.034a28.326 28.326 0 00-.023.383l-.001.06c0 6.358 5.156 11.513 11.516 11.513 5.695 0 10.424-4.135 11.35-9.566.02-.147.035-.295.052-.444.23-1.974-.025-4.05-.746-5.786zm-7.862 3.455z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox.jsx
new file mode 100755
index 0000000..fca522e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/firefox.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Firefox(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.76 8.17a.2.2 0 0 0-.2.12l-.27.6c-.1-.79-.3-2.05-.55-2.87a5.44 5.44 0 0 0-1.22-2.13.19.19 0 0 0-.23-.03.2.2 0 0 0-.1.21l.2.95a7.75 7.75 0 0 0-2.66-1.9A9.43 9.43 0 0 0 4.5 5.09c-.16-.13-.4-.36-.52-.7-.25-.59-.37-1.25-.37-1.26a.2.2 0 0 0-.13-.15.2.2 0 0 0-.2.04c-1.44 1.39-1.3 3.55-1.25 4.04-.17.19-.68.76-1.2 1.58A8.17 8.17 0 0 0 0 11.5c0 .09.04.17.11.2a.2.2 0 0 0 .23-.04l.42-.45c-.05.18-.1.37-.13.59-.2.94-.14 2.4-.13 2.46 0 .1.06.17.15.19a.2.2 0 0 0 .22-.11l.25-.53c.18 1.28.89 4.01 3.59 6.53a11.3 11.3 0 0 0 7.63 2.93c2.77 0 5.38-.99 7.56-2.86 2.57-2.21 3.53-5.38 3.88-7.64.38-2.45.16-4.34.15-4.43a.2.2 0 0 0-.17-.17zm-4.4.08c.01 0 .28.35.34 1.24.04.67-.1 1.74-.19 2.33l-.52-.6a.2.2 0 0 0-.23-.06.2.2 0 0 0-.12.2c0 .02.18 1.53-.12 2.85a4.12 4.12 0 0 1-.55 1.36l.07-1a.2.2 0 0 0-.15-.2.2.2 0 0 0-.22.11c-.01.02-.92 1.97-3.4 2.74-.36.11-.72.17-1.1.17a5.95 5.95 0 0 1-3.21-1.16h.17c.98 0 1.73-.41 2.34-.75.16-.1.3-.18.45-.25a3.28 3.28 0 0 1 1.59-.47c.16 0 .29-.1.33-.25.1-.38-.36-1.05-.92-1.36a1.88 1.88 0 0 0-.94-.22c-.57 0-1.28.18-2.3.45a2.1 2.1 0 0 1-.55.08 1.7 1.7 0 0 1-1.27-.56c-.32-.34-.5-.8-.48-1.17.01-.18.08-.36.5-.36.37 0 .78.15.78.16h.07c.11 0 .2-.08.2-.19v-.03L9.88 9.6c.2-.13.67-.44 1.12-.77 1.1-.8 1.26-1.1 1.14-1.34-.16-.32-.57-.37-1.05-.43-.27-.04-.58-.08-.86-.17-.58-.2-.96-.7-1.05-.82a1.2 1.2 0 0 1 .1-.75c.2-.33.83-.83 1.06-1a.2.2 0 0 0 .08-.2.2.2 0 0 0-.17-.15c-.02 0-.6-.06-1.57.25-.78.27-1.39.7-1.6.85a7.99 7.99 0 0 0-.5-.07A7.82 7.82 0 0 1 17.05 3.8l-1.33.22a.2.2 0 0 0-.16.19c-.01.09.05.17.13.2.02 0 1.78.56 3.1 1.57.29.23.56.53.8.88.21.47.38.96.5 1.45l-.44-.35a.2.2 0 0 0-.26.02.2.2 0 0 0-.01.27zm0 0" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fleet.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fleet.jsx
new file mode 100755
index 0000000..474d739
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fleet.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Fleet(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12 24c6.6271 0 12-5.3729 12-12 0-1.2155-.357-3.152-1.0914-4.3243-1.183-2.0006-3.6319-3.4782-6.5748-3.8479C15.0039 2.2176 13.4855.6724 12 0 5.3729 0 0 5.3729 0 12s5.3729 12 12 12Zm1.3181-2.99c4.5426-.9696 7.7048-4.1922 7.063-7.1976-.6418-3.0051-4.8442-4.6553-9.3864-3.6852-4.5425.9697-7.7047 4.1923-7.063 7.1977.6419 3.005 4.8442 4.6548 9.3864 3.6851Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fog.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fog.jsx
new file mode 100755
index 0000000..f1d9556
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/fog.jsx
@@ -0,0 +1,20 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Fog(props) {
5 return (
6 <Icon {...props} className={Utils.classNames(props.className, "fog-icon")}>
7 <g>
8 <path d="M3.38086 9.44531C3.46961 9.4487 3.55837 9.4552 3.64721 9.4552C10.0824 9.45567 16.5178 9.45661 22.953 9.45087C23.1516 9.45077 23.2511 9.50075 23.2876 9.70489C23.3266 9.92183 23.3938 10.1335 23.4569 10.3793C23.3474 10.3842 23.2626 10.3915 23.1778 10.3915C16.6946 10.392 10.2114 10.3921 3.72815 10.3912C3.44429 10.3912 3.43818 10.448 3.41804 10.1057C3.41493 10.0521 3.39375 9.99976 3.38086 9.94677V9.44531V9.44531Z" />
9 <path d="M23.5298 11.7442C23.4997 11.9058 23.4695 12.0676 23.4356 12.2488H23.2136C16.8542 12.2488 10.4948 12.2482 4.13554 12.2526C3.97469 12.2527 3.88538 12.2184 3.84255 12.0503C3.78288 11.8161 3.70015 11.5879 3.62109 11.3375C3.69902 11.3316 3.75672 11.3237 3.81451 11.3237C10.352 11.3232 16.8895 11.3232 23.4271 11.3234C23.4613 11.3234 23.4956 11.3254 23.5298 11.3265V11.7442V11.7442Z" />
10 <path d="M11.1112 2.00977C11.5427 2.08045 11.9781 2.13297 12.4049 2.22624C13.0137 2.35932 13.5901 2.59 14.1311 2.92591H7.27963C7.27294 2.90708 7.26635 2.88817 7.25977 2.86925C7.65393 2.70737 8.03755 2.50614 8.4449 2.3933C8.99002 2.24205 9.55341 2.15932 10.109 2.04704C10.169 2.03499 10.2288 2.02219 10.2887 2.00977H11.1112V2.00977Z" />
11 <path d="M4.36816 13.1953H23.2229C23.0772 13.5005 22.942 13.7888 22.7999 14.0737C22.787 14.0994 22.7309 14.1098 22.6935 14.1146C22.6395 14.1213 22.5842 14.1165 22.5294 14.1165C16.7683 14.1166 11.0072 14.1157 5.24628 14.1208C5.06219 14.121 4.94115 14.0729 4.84402 13.9123C4.70247 13.6781 4.54219 13.4555 4.36816 13.1953" />
12 <path d="M22.7964 8.52027H3.43945C3.49602 8.23114 3.54722 7.95481 3.60792 7.68074C3.61489 7.64921 3.67174 7.6174 3.71079 7.60799C3.76265 7.59528 3.81969 7.60432 3.87446 7.60432C9.87616 7.60432 15.8779 7.60535 21.8795 7.59961C22.0648 7.59952 22.1898 7.65288 22.2914 7.80215C22.4491 8.03377 22.6135 8.26079 22.7964 8.52027" />
13 <path d="M3.91406 6.6525C4.06456 6.3484 4.19604 6.07499 4.33703 5.80666C4.3567 5.76949 4.42126 5.74953 4.46898 5.73721C4.51406 5.72563 4.56432 5.73448 4.61223 5.73448C8.67453 5.73457 12.7368 5.71481 16.7987 5.75358C17.49 5.76008 18.1867 5.65909 18.8821 5.80017C19.6351 5.95302 20.3421 6.19857 21.038 6.6525L3.91406 6.65241V6.6525Z" />
14 <path d="M22.1028 15.1122C21.7725 15.3877 21.444 15.6655 21.1093 15.9353C21.068 15.9687 20.9932 15.9683 20.9339 15.9683C16.3859 15.9697 11.838 15.9698 7.28997 15.9675C7.21834 15.9675 7.13439 15.9553 7.07689 15.9168C6.68357 15.6538 6.2958 15.3823 5.90625 15.1136C5.91406 15.0963 5.92169 15.0788 5.9295 15.0615H22.0594C22.0738 15.0785 22.0883 15.0953 22.1028 15.1122" />
15 <path d="M16.3646 4.80359H5.04693C5.03366 4.78862 5.02029 4.77366 5.00684 4.75869C5.28825 4.4737 5.56712 4.18589 5.85455 3.9074C5.88966 3.87342 5.97164 3.88312 6.03187 3.88312C9.14858 3.88208 12.2654 3.88123 15.3822 3.88707C15.4789 3.88726 15.5985 3.93432 15.6681 4.00161C15.9193 4.24406 16.1538 4.50457 16.3948 4.75832C16.3846 4.77337 16.3746 4.78853 16.3646 4.80359Z" />
16 </g>
17 <path d="M12.7918 12.9437C12.7515 12.808 12.7102 12.6509 12.6584 12.4974C11.7422 9.78373 9.15539 8.23512 6.37205 8.73281C3.37506 9.26862 1.32847 12.3747 1.97675 15.4034C2.54767 18.0704 4.76339 19.8951 7.45421 19.902C9.87257 19.9082 12.2911 19.9083 14.7096 19.8977C15.0525 19.8962 15.4037 19.853 15.7366 19.7695C17.7103 19.2749 18.891 17.2023 18.3721 15.17C17.8694 13.2006 15.8162 11.9784 13.884 12.5152C13.5143 12.618 13.1645 12.7953 12.7918 12.9437V12.9437ZM0 14.6026V13.9555C0.0408471 13.6362 0.0719059 13.3153 0.123953 12.998C0.808377 8.82392 4.8352 6.02881 8.90635 6.91389C11.0136 7.37196 12.626 8.5569 13.7498 10.4234C13.8322 10.5599 13.9107 10.5961 14.0683 10.5843C14.4894 10.5526 14.9164 10.5084 15.3344 10.5461C18.8317 10.8609 21.1607 14.4454 20.0892 17.8444C19.3375 20.2293 17.2374 21.7692 14.7127 21.7751C12.308 21.7806 9.90334 21.7781 7.49882 21.7739C7.18127 21.7733 6.86231 21.7565 6.54664 21.7216C3.40395 21.3741 0.773271 18.9203 0.166871 15.7686C0.0928 15.3835 0.0547765 14.9914 0 14.6026" />
18 </Icon>
19 );
20}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/folx.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/folx.jsx
new file mode 100755
index 0000000..4fc7f48
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/folx.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Folx(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12.37 24.37a12 12 0 1 0-9.55-4.74l.93-.94a4.09 4.09 0 0 1 .67-4.04l-.02-.02.36-.5.06-.08a3.87 3.87 0 0 0-1.65-.36H3.1a.33.33 0 0 1-.2-.1.33.33 0 0 1-.1-.25c0-.05.01-.1.03-.13a.34.34 0 0 1 .06-.1l1.87-1.87a.77.77 0 0 1 .61-.2h.03a.9.9 0 0 1 .09.02l1.26.37a24.18 24.18 0 0 1 4.74-4.65l2.86 2.87.02-.02-2.8-2.79c.24-.71.65-1.36 1.23-1.94a4.8 4.8 0 0 1 3.51-1.46 4.8 4.8 0 0 1 3.52 1.46 4.8 4.8 0 0 1 1.46 3.52 4.8 4.8 0 0 1-1.46 3.52c-.57.58-1.22.98-1.94 1.22l-2.79-2.8-.01.02 2.87 2.88-.48.65a24.22 24.22 0 0 1-4.18 4.08l.38 1.26a.9.9 0 0 1 .02.15v.04c0 .21-.06.39-.2.54l-1.87 1.87a.34.34 0 0 1-.23.09.33.33 0 0 1-.25-.1.33.33 0 0 1-.1-.2v-.07c0-.6-.12-1.14-.36-1.63l-.08.06-.5.35-.02-.02c-.73.62-1.6.93-2.58.93-.52 0-1.01-.1-1.47-.27l-.95.92-.65-.52a11.95 11.95 0 0 0 7.92 2.98ZM4.35 21.3l-.37-.35.37.35Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/free-tube.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/free-tube.jsx
new file mode 100755
index 0000000..849131e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/free-tube.jsx
@@ -0,0 +1,16 @@
1import Icon from "../icon.jsx";
2
3export default function FreeTube(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1.59 3.244c0-.915.741-1.656 1.656-1.656h3.996c.915 0 1.656.741 1.656 1.656v19.984c0 .284-.23.514-.514.514H6.672A5.082 5.082 0 0 1 1.59 18.66V3.244Zm1.656-.628a.628.628 0 0 0-.628.628V18.66a4.054 4.054 0 0 0 4.054 4.054H7.87V3.244a.628.628 0 0 0-.629-.628H3.246Z" />
7 <path d="M7.87 3.244c0-.915.742-1.656 1.656-1.656H23.23c.284 0 .514.23.514.514v1.713a5.082 5.082 0 0 1-5.082 5.082H9.526A1.656 1.656 0 0 1 7.871 7.24V3.244Zm1.656-.628a.628.628 0 0 0-.628.628v3.997c0 .347.281.628.628.628h9.136a4.054 4.054 0 0 0 4.054-4.054v-1.2H9.526Z" />
8 <path d="M9.414 8.296a1.085 1.085 0 0 0-1.543.983Zm0 0 7.129 3.328c.834.39.834 1.576 0 1.966l-7.129 3.327a1.085 1.085 0 0 1-1.543-.983V9.279m1.109-.051a.057.057 0 0 0-.082.051v6.655c0 .042.044.07.082.052l7.128-3.328c.016-.007.022-.015.025-.02a.062.062 0 0 0 .008-.031.062.062 0 0 0-.008-.032c-.003-.005-.009-.012-.025-.02L8.98 9.228Z" />
9 <path
10 fillRule="evenodd"
11 clipRule="evenodd"
12 d="M8.384.931c.345-.17.732-.266 1.142-.266H23.23c.793 0 1.437.643 1.437 1.437v1.713a6.005 6.005 0 0 1-6.005 6.005H14.86l2.073.967c1.545.721 1.545 2.918 0 3.639l-7.112 3.32v5.482c0 .794-.643 1.437-1.437 1.437H6.672A6.005 6.005 0 0 1 .667 18.66V3.244A2.579 2.579 0 0 1 3.246.665h3.996c.41 0 .798.096 1.142.266ZM6.947 9.264V21.79h-.275a3.13 3.13 0 0 1-3.131-3.13V3.538h3.406v5.725Zm2.874-2.318h8.841a3.13 3.13 0 0 0 3.13-3.131v-.276H9.823v3.407Zm0 7.628 4.215-1.967-4.215-1.968v3.935Z"
13 />
14 </Icon>
15 );
16}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gear.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gear.jsx
new file mode 100755
index 0000000..faba81b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gear.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Gear(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21.175 13.175c.052-.375.077-.763.077-1.175 0-.4-.025-.8-.09-1.175l2.609-1.975a.598.598 0 0 0 .154-.762l-2.467-4.15a.623.623 0 0 0-.328-.273.644.644 0 0 0-.43-.002l-3.072 1.2a9.143 9.143 0 0 0-2.081-1.176L15.084.514a.602.602 0 0 0-.21-.368.633.633 0 0 0-.407-.145H9.533a.604.604 0 0 0-.604.513l-.463 3.175c-.758.3-1.452.712-2.082 1.174l-3.07-1.2a.621.621 0 0 0-.759.276L.101 8.088c-.155.262-.103.587.154.762l2.608 1.975A7.142 7.142 0 0 0 2.748 12c0 .387.026.8.09 1.175L.229 15.15a.598.598 0 0 0-.154.762l2.467 4.15c.154.275.476.363.758.275l3.072-1.2a9.142 9.142 0 0 0 2.081 1.175l.463 3.175c.064.3.308.513.617.513h4.934a.594.594 0 0 0 .604-.512l.463-3.175c.758-.3 1.452-.7 2.082-1.175l3.07 1.2c.284.1.605 0 .759-.276l2.467-4.15c.154-.275.09-.587-.154-.762l-2.583-1.975ZM12 16.5c-2.544 0-4.626-2.025-4.626-4.5S9.456 7.5 12 7.5c2.544 0 4.626 2.025 4.626 4.5S14.544 16.5 12 16.5Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ghostty.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ghostty.jsx
new file mode 100755
index 0000000..2a63aa0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ghostty.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Ghostty(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M2.335 23.543C.525 22.46 0 20.177 0 18.067V9.942c0-.996.14-1.989.51-2.914.583-1.459 1.636-3.679 3.006-4.804C5.56.547 7.258.058 9.89.004c2.795-.056 4.676.4 6.813 2.22 1.371 1.168 2.365 3.489 2.885 4.94.3.838.412 1.726.412 2.616v8.418c0 2.03-.478 4.216-2.182 5.317-.36.232-.738.405-1.115.462-1.53.234-2.192-1.434-3.736-1.331-1.305.086-1.77 1.368-3.077 1.331-1.228-.034-1.631-1.24-2.857-1.331-1.463-.11-2.057 1.479-3.517 1.331-.396-.04-.797-.204-1.18-.434ZM8.571 9.216a.643.643 0 0 1-.271.526l-4.124 2.915h-.352a1.186 1.186 0 0 1-.716-2.132L5.03 9.07a.22.22 0 0 0-.01-.357l-1.327-.894a.973.973 0 1 1 1.106-1.602l3.5 2.475c.171.12.272.317.272.525Zm3.082-1.22a1.065 1.065 0 0 0-.927 1.589l.1.176c.237.418.68.676 1.16.676h3.94c.48 0 .923-.258 1.16-.676l.1-.177a1.064 1.064 0 0 0-.927-1.589h-4.606Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/git-hub.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/git-hub.jsx
new file mode 100755
index 0000000..b2df650
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/git-hub.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function GitHub(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gnu-cash.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gnu-cash.jsx
new file mode 100755
index 0000000..9059b9a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/gnu-cash.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function GnuCash(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M4 4C1.7909 4 0 5.7909 0 8v1h24V8c0-2.2091-1.7909-4-4-4H4Zm20 8H0v4c0 2.2091 1.7909 4 4 4h16c2.2091 0 4-1.7909 4-4v-4Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/go-land.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/go-land.jsx
new file mode 100755
index 0000000..9f37eed
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/go-land.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function GoLand(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3.0029 9.8735a4.3708 4.3708 0 0 0 1.6458 1.6716v-.0006c.699.4056 1.5132.6078 2.3412.6078.828 0 1.575-.1842 2.2416-.5526a4.131 4.131 0 0 0 1.5756-1.515c.384-.6408.576-1.3584.576-2.151v-.708H7.5689v1.3824h2.0945a1.977 1.977 0 0 1-.3647.9138c-.2358.3258-.5538.5814-.9546.7656-.4014.1842-.8484.2766-1.341.2766-.5322 0-1.0122-.1326-1.4412-.3984a2.7633 2.7633 0 0 1-1.0062-1.0968c-.2424-.465-.3636-.99-.3636-1.5726s.1212-1.107.3636-1.572c.2289-.4506.5769-.83 1.0062-1.0968.429-.2658.909-.3984 1.4412-.3984.36 0 .6966.057 1.0098.1704.3132.1134.5862.2742.8202.4818a2.348 2.348 0 0 1 .5556.7368h1.878a3.8204 3.8204 0 0 0-.852-1.5564 4.1453 4.1453 0 0 0-1.4916-1.0482c-.5904-.2484-1.2342-.3732-1.9332-.3732-.8622 0-1.6422.2034-2.3412.6084-.6978.405-1.2468.963-1.6458 1.6722-.399.7092-.5982 1.5012-.5982 2.376 0 .8748.1992 1.6668.5982 2.3766Zm9.9066 0a4.3914 4.3914 0 0 0 1.653 1.6716c.7008.405 1.4886.6084 2.3508.6084.8616 0 1.6428-.2028 2.3436-.6078.7014-.405 1.2516-.9636 1.65-1.6728.3984-.7092.5982-1.5012.5982-2.376 0-.8748-.1998-1.6668-.5982-2.3766a4.3674 4.3674 0 0 0-1.6494-1.6722c-.7014-.405-1.4784-.6078-2.3442-.6078-.8664 0-1.65.2034-2.3508.6084a4.3878 4.3878 0 0 0-1.653 1.6722c-.4014.7092-.6012 1.5012-.6012 2.376 0 .8748.2004 1.6668.6012 2.3766Zm6.435-.7782c-.24.4734-.5724.8448-.9972 1.1124-.4242.2682-.9018.402-1.434.402-.531 0-1.011-.1338-1.437-.402-.4266-.2676-.7608-.6384-1.0032-1.1124-.2424-.474-.3636-1.0068-.3636-1.5984 0-.5916.1212-1.1244.3636-1.5984a2.7718 2.7718 0 0 1 1.0032-1.1124c.426-.2682.906-.402 1.437-.402.5316 0 1.0098.1344 1.434.402.4284.272.7735.657.9972 1.1124.24.474.36 1.0068.36 1.5984 0 .5916-.12 1.1244-.36 1.5984ZM2.9999 19.2h9.6v1.8h-9.6v-1.8Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/good-notes.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/good-notes.jsx
new file mode 100755
index 0000000..857c7ac
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/good-notes.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function GoodNotes(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6.375 5.625h8.25a.375.375 0 000-.75h-8.25a.375.375 0 000 .75zm0 0M6.375 7.875h8.25a.375.375 0 000-.75h-8.25a.375.375 0 000 .75zm0 0M6.375 10.125h8.25a.375.375 0 000-.75h-8.25a.375.375 0 000 .75zm0 0M6.375 12.375h8.25a.375.375 0 000-.75h-8.25a.375.375 0 000 .75zm0 0M6.375 14.625h3a.375.375 0 000-.75h-3a.375.375 0 000 .75zm0 0" />
7 <path d="M21.195 9.61a1.131 1.131 0 00-1.543.402l-.902 1.543V2.25a.375.375 0 00-.375-.375h-2.844S14.402.727 14.36.765A.353.353 0 0014.25.75H3.375A.375.375 0 003 1.125v1.172a1.5 1.5 0 000 2.906v.844a1.5 1.5 0 000 2.906v.844a1.5 1.5 0 000 2.906v.469a1.5 1.5 0 000 2.906v2.297c0 .207.168.375.375.375h.375v1.125c0 .207.168.375.375.375h9.531l-.258.438a.365.365 0 00-.046.128v.004l-.004.008-.297 1.992c-.024.153.047.301.18.38a.372.372 0 00.417-.028l1.598-1.238c.102-.082.152-.13.145-.196l.87-1.488h2.114a.375.375 0 00.375-.375v-3.871l2.844-4.856a1.123 1.123 0 00-.399-1.539zm-.664.609c.145-.04.301.015.395.136a.38.38 0 01.023.415l-.191.324-.645-.38.188-.323a.367.367 0 01.23-.172zm-5.648 10.906l-.649-.379 4.93-8.414.648.379zm-.258-19.094l1.344 1.344h-1.344zm4.918 9.653l.191-.32.645.378-.188.32zM18 2.625V12.75c0 .023.004.047.008.074l-.758 1.29V3.75a.379.379 0 00-.11-.266l-.859-.859zM3.75 1.5h10.125v2.25c0 .207.168.375.375.375h2.25v11.27L14.973 18H3.75v-1.922c.527-.137.941-.55 1.078-1.078a.375.375 0 00-.727-.188.736.736 0 01-.351.461v-2.57c.527-.137.941-.55 1.078-1.078a.375.375 0 00-.727-.188.736.736 0 01-.351.461V8.953c.527-.137.941-.55 1.078-1.078a.375.375 0 00-.727-.188.736.736 0 01-.351.461V5.203c.527-.137.941-.55 1.078-1.078a.375.375 0 00-.727-.188.736.736 0 01-.351.461zM2.625 3.75c0-.27.145-.516.375-.648v1.296a.748.748 0 01-.375-.648zm0 3.75c0-.27.145-.516.375-.648v1.296a.748.748 0 01-.375-.648zm0 3.75c0-.27.145-.516.375-.648v1.296a.748.748 0 01-.375-.648zm0 3.375c0-.27.145-.516.375-.648v1.296a.748.748 0 01-.375-.648zM4.5 19.5v-.75h10.035l-.441.75zm9.508 1.98l.34.2-.418.324zM18 19.5h-1.297L18 17.285zm0 0" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/google-chrome.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/google-chrome.jsx
new file mode 100755
index 0000000..90cb83f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/google-chrome.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function GoogleChrome(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 7.5a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z" />
7 <path d="M12 17.99a6 6 0 0 1-5.94-5.18L1.92 5.64v-.02l-.47.67c-.11.21-.23.42-.33.64l-.22.52c-.15.38-.29.76-.4 1.15l-.14.48c-.06.22-.1.44-.15.67l-.08.47-.08.66-.04.52c-.02.4-.02.8 0 1.2l.04.52.08.66.08.47.15.67.13.48.2.62.21.54.22.52.33.63.15.3.07.1c.13.23.28.45.42.66l.24.35c.14.2.3.38.45.57l.31.37.43.43c.14.14.28.29.43.42l.37.31.56.45.35.24c.22.15.43.3.66.42l.1.07.3.15c.2.12.42.23.64.33l.06.03.3.13c.81.34 1.66.59 2.53.75l3.42-5.94c-.4.08-.81.13-1.24.13v.01z" />
8 <path d="M23.97 11.17l-.02-.2c-.08-1-.5-2.45-.83-3.42h-7.1a5.97 5.97 0 0 1-.29 9.13L11.51 24c1.49 0 3.49-.27 4.92-.84l.05-.02.08-.03c.94-.39 1.83-.9 2.65-1.5l.02-.02c.37-.28.71-.57 1.04-.88l.05-.05.17-.17c.72-.72 1.35-1.53 1.86-2.4l.05-.08.1-.2c.17-.3.32-.6.46-.92l.18-.41c.12-.3.22-.6.31-.9l.13-.38c.11-.42.2-.84.27-1.27l.03-.24c.06-.36.1-.73.11-1.1v-.3c.01-.37 0-.75-.02-1.12z" />
9 <path d="M22.4 6c-.25-.44-.54-.85-.83-1.24l-.1-.12a11.6 11.6 0 0 0-.84-.98l-.2-.2c-.33-.32-.67-.63-1.02-.9l-.08-.07c-.4-.3-.81-.58-1.24-.83l-.08-.06-.33-.17c-.19-.1-.37-.2-.57-.29L16.55.9l-.47-.19L15.4.5 15 .4c-.25-.07-.5-.12-.75-.17L13.9.15l-.74-.1-.4-.03C12.54 0 12.33 0 12.12 0h-.52l-.4.03a12 12 0 0 0-2.68.49l-.18.04-.67.25-.42.17-.54.26-.52.26-.2.1-.28.19c-.34.2-.67.43-.99.67l-.41.33-.5.44-.3.3c-.18.17-.36.36-.52.54l-.11.14 3.41 5.92A6 6 0 0 1 12 5.99h10.4V6z" />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/goose.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/goose.jsx
new file mode 100755
index 0000000..740916a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/goose.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Goose(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M21.595 23.61c1.167-.254 2.405-.944 2.405-.944l-2.167-1.784a12.124 12.124 0 01-2.695-3.131 12.127 12.127 0 00-3.97-4.049l-.794-.462a1.115 1.115 0 01-.488-.815.844.844 0 01.154-.575c.413-.582 2.548-3.115 2.94-3.44.503-.416 1.065-.762 1.586-1.159.074-.056.148-.112.221-.17.003-.002.007-.004.009-.007.167-.131.325-.272.45-.438.453-.524.563-.988.59-1.193-.061-.197-.244-.639-.753-1.148.319.02.705.272 1.056.569.235-.376.481-.773.727-1.171.165-.266-.08-.465-.086-.471h-.001V3.22c-.007-.007-.206-.25-.471-.086-.567.35-1.134.702-1.639 1.021 0 0-.597-.012-1.305.599a2.464 2.464 0 00-.438.45l-.007.009c-.058.072-.114.147-.17.221-.397.521-.743 1.083-1.16 1.587-.323.391-2.857 2.526-3.44 2.94a.842.842 0 01-.574.153 1.115 1.115 0 01-.815-.488l-.462-.794a12.123 12.123 0 00-4.049-3.97 12.133 12.133 0 01-3.13-2.695L1.332 0S.643 1.238.39 2.405c.352.428 1.27 1.49 2.34 2.302C1.58 4.167.73 3.75.06 3.4c-.103.765-.063 1.92.043 2.816.726.317 1.961.806 3.219 1.066-1.006.236-2.11.278-2.961.262.15.554.358 1.119.64 1.688.119.263.25.52.39.77.452.125 2.222.383 3.164.171l-2.51.897a27.776 27.776 0 002.544 2.726c2.031-1.092 2.494-1.241 4.018-2.238-2.467 2.008-3.108 2.828-3.8 3.67l-.483.678c-.25.351-.469.725-.65 1.117-.61 1.31-1.47 4.1-1.47 4.1-.154.486.202.842.674.674 0 0 2.79-.861 4.1-1.47.392-.182.766-.4 1.118-.65l.677-.483c.227-.187.453-.37.701-.586 0 0 1.705 2.02 3.458 3.349l.896-2.511c-.211.942.046 2.712.17 3.163.252.142.509.272.772.392.569.28 1.134.49 1.688.64-.016-.853.026-1.956.261-2.962.26 1.258.75 2.493 1.067 3.219.895.106 2.051.146 2.816.043a73.87 73.87 0 01-1.308-2.67c.811 1.07 1.874 1.988 2.302 2.34h-.001z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/grammarly.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/grammarly.jsx
new file mode 100755
index 0000000..574fc84
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/grammarly.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Grammarly(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12,-7.10542736e-15 C18.6278824,-7.10542736e-15 24,5.37252139 24,12 C24,18.6268747 18.6278824,24 12,24 C5.37272042,24 8.8817842e-15,18.6262708 8.8817842e-15,12 C8.8817842e-15,5.37252139 5.37272042,-7.10542736e-15 12,-7.10542736e-15 Z M11.5177091,4.96426774 C8.00904295,5.19979869 5.16955539,8.07086059 4.96819894,11.5814796 C4.733685,15.6664318 7.97407687,19.0019124 12.0048229,19.0019124 C14.0393967,19.0101769 15.9763349,18.1288813 17.3088169,16.5886261 L17.1556895,17.4437846 L17.1556895,18.2168093 C17.1556895,18.6154001 17.4245667,18.9856064 17.8176338,19.0562657 C18.0554118,19.1011531 18.3007987,19.0377271 18.4872137,18.8831969 C18.6736288,18.7286668 18.7817407,18.4990573 18.7822155,18.2566683 L18.7822155,13.6257675 L14.3674454,13.6257675 C13.8688772,13.6257675 13.4752072,14.0750881 13.5686511,14.5908405 C13.6391861,14.983392 14.0087415,15.2527428 14.4078372,15.2527428 L15.6654107,15.2527428 L16.3942728,15.1500755 C15.2283346,16.8609965 13.2033157,17.6485153 10.9896006,17.3012582 C9.18703843,17.0180171 7.63948757,15.7986915 6.98658628,14.0962255 C5.50354182,10.2311022 8.32675207,6.53990941 12.0054258,6.53990941 C13.922532,6.53990941 15.6039186,7.66200302 16.5678975,9.0178158 L16.5691032,9.04680423 C16.8253203,9.41519879 17.3317257,9.52148968 17.7012811,9.26542526 C18.0479113,9.02702555 18.1511653,8.56050888 17.9376036,8.19768495 L17.9436323,8.19768495 C16.5534626,6.02337542 14.0888813,4.7832393 11.5177091,4.96426774 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/helium.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/helium.jsx
new file mode 100755
index 0000000..141b2ff
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/helium.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function Helium(props) {
4 return (
5 <Icon {...props}>
6 <path
7 d="M7.962 0h8.076c2.768 0 3.772.288 4.785.83a5.638 5.638 0 0 1 2.347 2.347c.542 1.013.83 2.016.83 4.785v8.076c0 2.768-.288 3.772-.83 4.785a5.638 5.638 0 0 1-2.347 2.347c-1.013.542-2.016.83-4.785.83H7.962c-2.768 0-3.772-.288-4.785-.83A5.638 5.638 0 0 1 .83 20.823C.288 19.809 0 18.806 0 16.038V7.962C0 5.194.288 4.19.83 3.177A5.638 5.638 0 0 1 3.177.83C4.191.288 5.194 0 7.962 0Zm2.791 12.504-5.835 5.853a.51.51 0 0 0 0 .716.507.507 0 0 0 .713 0l5.841-5.859v6.262c0 .283.233.516.516.516a.519.519 0 0 0 .516-.516v-6.27l5.849 5.867h.001a.506.506 0 0 0 .712 0 .51.51 0 0 0 0-.716l-5.836-5.853h6.27a.518.518 0 0 0 .516-.515l-.001-.001a.519.519 0 0 0-.516-.516h-6.29l5.858-5.875a.508.508 0 0 0 0-.715h-.002a.503.503 0 0 0-.712 0l-5.849 5.866V4.453a.519.519 0 0 0-.516-.516.519.519 0 0 0-.516.516v6.288L5.63 4.882a.504.504 0 1 0-.713.715l5.858 5.875H4.523a.519.519 0 0 0-.516.516c0 .283.233.516.516.516h6.23Z"
8 />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/home-assistant.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/home-assistant.jsx
new file mode 100755
index 0000000..3d94dc2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/home-assistant.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function HomeAssistant(props) {
4 return (
5 <Icon {...props}>
6 <path d="M24 22.5c0 .8-.7 1.5-1.5 1.5h-21C.7 24 0 23.3 0 22.5v-9c0-.8.5-2 1-2.6L11 1c.5-.5 1.5-.5 2 0l10 10c.5.5 1 1.7 1 2.5v9Z" />
7 <path d="M23 11 13 1c-.5-.5-1.5-.5-2 0L1 11c-.5.5-1 1.7-1 2.5v9c0 .8.7 1.5 1.5 1.5h9.2l-4-4A2 2 0 1 1 8 18.6l3.1 3.1V10.2a2 2 0 1 1 1.8 0v8.1l3.1-3.1a2 2 0 1 1 1.3 1.3l-4.4 4.4v3h9.6c.8 0 1.5-.6 1.5-1.4v-9c0-.8-.5-2-1-2.6Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ht-t-pie.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ht-t-pie.jsx
new file mode 100755
index 0000000..20d99d7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ht-t-pie.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function HTTPie(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.141 5.215C22.12 2.314 19.701 0 16.8 0H7.347C4.467 0 2.057 2.277 2 5.157a5.263 5.263 0 0 0 5.26 5.358h4.222a.306.306 0 0 1 .122.583l-6.473 2.838A5.264 5.264 0 0 0 2 18.783C2.023 21.684 4.44 24 7.343 24h2.215c2.923 0 5.356-2.344 5.351-5.266a5.265 5.265 0 0 0-3.293-4.867.303.303 0 0 1-.005-.559l7.404-3.246a5.264 5.264 0 0 0 3.126-4.847Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/idea.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/idea.jsx
new file mode 100755
index 0000000..bdd92cf
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/idea.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Idea(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1 1v22h22V1H1zm3.413 2.852h4.583v1.68H7.722v5.755h1.274v1.681H4.413v-1.681h1.323V5.533H4.413V3.852zm10.133 0h2.037V9.81c0 .561-.05 1.018-.203 1.426a2.719 2.719 0 01-.663 1.018c-.254.256-.61.51-1.017.612a3.605 3.605 0 01-1.325.255c-.713 0-1.324-.153-1.782-.408a4.41 4.41 0 01-1.172-.968l1.274-1.425c.254.306.508.508.763.662.254.153.56.254.867.254.356 0 .66-.101.916-.356.203-.255.306-.612.306-1.172V3.852zM3.036 18.875h8.25v1.375h-8.25v-1.375z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/insomnia.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/insomnia.jsx
new file mode 100755
index 0000000..5d1fc12
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/insomnia.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Insomnia(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0C5.417 0 0 5.417 0 12s5.417 12 12 12 12-5.417 12-12S18.583 0 12 0zm0 2.478c5.256 0 9.522 4.266 9.522 9.522S17.256 21.522 12 21.522 2.478 17.256 2.478 12c0-.885.12-1.741.347-2.554a4.76 4.76 0 0 0 3.925 2.066 4.764 4.764 0 0 0 4.762-4.762 4.758 4.758 0 0 0-2.067-3.925A9.526 9.526 0 0 1 12 2.478Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/iris.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/iris.jsx
new file mode 100755
index 0000000..cb35f76
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/iris.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Iris(props) {
4 return (
5 <Icon {...props}>
6 <path d="M3 24V0l7 7v10l-7 7zM23 12L10 0v4l9 8-9 8v4l13-12z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/italic.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/italic.jsx
new file mode 100755
index 0000000..cf19e23
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/italic.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Italic(props) {
4 return (
5 <Icon {...props}>
6 <path d="M10 5.5c0 .83.67 1.5 1.5 1.5h.71l-3.42 8H7.5c-.83 0-1.5.67-1.5 1.5S6.67 18 7.5 18h5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5h-.71l3.42-8h1.29c.83 0 1.5-.67 1.5-1.5S17.33 4 16.5 4h-5c-.83 0-1.5.67-1.5 1.5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/joplin.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/joplin.jsx
new file mode 100755
index 0000000..980784f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/joplin.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Joplin(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5 0a5 5 0 00-5 5v14a5 5 0 005 5h14a5 5 0 005-5V5a5 5 0 00-5-5H5zm7.01 2h7.58v2.61h-1.86l-.08 12.65c-.65 2.12-1.4 2.98-3.11 4.15-.93.43-1.47.59-2.48.59-1.4 0-2.14-.1-3.34-.69a8.78 8.78 0 01-2.96-2.36 9.54 9.54 0 01-1.34-3.1 6.7 6.7 0 01.59-3.36c.6-.86 1.04-1.3 2-1.98 1-.45 1.59-.64 2.72-.85a6.08 6.08 0 012.18.2v3.83a3.4 3.4 0 00-1.86-.46c-.84.32-1.22.55-1.7 1.04-.3.71-.32 1.1 0 1.82.46.78.8 1.18 1.6 1.79a6 6 0 002.55.41 2.6 2.6 0 001.36-1.51V4.72l-1.85-.1V2z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kakoune.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kakoune.jsx
new file mode 100755
index 0000000..9d8d2ab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kakoune.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Kakoune(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M8.16 3.84 12 0l4.08 4.08-6.4 6.63.4-6.87H8.16Zm-3.6 3.6L0 12l4.56 4.56V7.44Zm3.96 13.08L12 24l3.72-3.72H15l-4.44-4.09-1.28 1.52-.16 2.81h-.6Zm9.7-2.75L24 12l-5.36-5.36-4.84 5.72 4.43 5.41Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kee-pass-x-c.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kee-pass-x-c.jsx
new file mode 100755
index 0000000..1b73f58
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/kee-pass-x-c.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function KeePassXC(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13.67 3a1.73 1.73 0 1 1-3.37 0 8.14 8.14 0 0 1 3.37 0ZM7.2 5.07a4.79 4.79 0 0 0 2.74 4.34v8.72L12 20.2l2.06-2.06-.13-1.83.97-.97-.97-.96 1.46-1.47-1.46-1.46.13-2.03a4.82 4.82 0 0 0 2.67-5.28 9.16 9.16 0 0 1 3.16 12.59A9.18 9.18 0 1 1 7.28 4.15a5.7 5.7 0 0 0-.08.93Zm3.42 5.48h.68v6.87h-.68v-6.87Z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M12 .98a11.02 11.02 0 1 0 0 22.04A11.02 11.02 0 0 0 12 .98ZM.2 12a11.8 11.8 0 1 1 23.6 0A11.8 11.8 0 0 1 .2 12Z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard-maestro.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard-maestro.jsx
new file mode 100755
index 0000000..f171ac7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard-maestro.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function KeyboardMaestro(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6.25 13.2c-1.94 0-3.43.52-4.45 1.54a5.43 5.43 0 007.67 7.67c1.21-1.2 1.53-2.95 1.53-4.47v-1.1h2v1.1c0 1.52.32 3.26 1.53 4.47a5.39 5.39 0 007.67 0 5.43 5.43 0 000-7.67c-1.01-1.02-2.51-1.53-4.45-1.53h-1.12v-2.42h1.12c1.94 0 3.43-.51 4.45-1.53a5.43 5.43 0 00-7.67-7.67c-1.17 1.16-1.5 2.83-1.53 4.3l-.02 1.27h-1.96L11 5.9c-.02-1.48-.36-3.15-1.53-4.31a5.4 5.4 0 00-7.67 0 5.43 5.43 0 000 7.67c1.02 1.02 2.51 1.53 4.45 1.53h1.12v2.42H6.25zm10.59-9.32a2.14 2.14 0 013.04 0c.84.84.84 2.2 0 3.05-.37.37-1.13.57-2.13.57H16.2v-.95s-.11-2.02.63-2.67zm-.63 13.57v-.95h1.54c1 0 1.76.2 2.13.57a2.16 2.16 0 01-3.04 3.05c-.74-.65-.63-2.67-.63-2.67zm-5.98-7.22h3.54v3.54h-3.54v-3.54zM6.25 7.5c-1 0-1.76-.2-2.13-.57a2.16 2.16 0 013.04-3.05c.74.65.63 2.67.63 2.67v.95H6.25zm1.54 9v.95s.11 2.02-.63 2.67a2.14 2.14 0 01-3.04 0 2.16 2.16 0 010-3.05c.37-.37 1.13-.57 2.13-.57H7.8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard.jsx
new file mode 100755
index 0000000..1b5afc8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keyboard.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Keyboard(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22 5H2.01L2 19h20V5zM11 8h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keynote.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keynote.jsx
new file mode 100755
index 0000000..73dcd0c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/keynote.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Keynote(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23,13.2825938 C23,13.8134141 22.5487801,14.2438036 21.9920387,14.2438036 L21.9920387,14.2438036 L12.92,14.243 L12.9202327,21.345098 C12.9202327,21.8493498 13.3042333,22.2682927 13.8090168,22.3498578 L17.0339036,22.3490919 C17.1378682,22.3490919 17.22215,22.4754011 17.22215,22.6312087 L17.22215,22.7179135 C17.22215,22.8737212 17.1378847,23 17.0339036,23 L7.86311284,23 C7.75914825,23 7.67486643,22.8737212 7.67486643,22.7179135 L7.67486643,22.6312087 C7.67486643,22.4754011 7.75914825,22.3490919 7.86311284,22.3490919 L11.0229725,22.3498073 C11.527756,22.2682345 11.9117566,21.8492568 11.9117566,21.3450489 L11.911,14.243 L3.00796129,14.2438036 C2.49108277,14.2438036 2.06501202,13.8727871 2.00678191,13.3947017 L2,13.2825938 Z M11.7184208,1 C12.2274459,1 12.6400604,1.39347653 12.6400604,1.87889188 L12.6400604,1.87889188 L12.6400604,2.06556744 C12.6400604,2.55098278 12.2274459,2.94445932 11.7184208,2.94445932 L11.7184208,2.94445932 L9.64170756,2.94445932 C9.22111458,2.94445932 8.86702584,2.67546588 8.75645997,2.30829965 L8.75645997,2.30829965 L6.15723551,2.30829965 C5.70220651,2.30829965 5.33200645,2.661329 5.33200645,3.09525272 L5.33200645,3.09525272 L5.33200645,4.20406527 L20.7336056,4.20406527 C21.2835524,4.20406527 21.7379122,4.61344579 21.7691054,5.13705035 L21.7691054,5.13705035 L22.216053,12.64182 L2.61593631,12.64182 L3.06293538,5.13714852 C3.09412855,4.61349488 3.54848838,4.20416344 4.09843519,4.20416344 L4.09843519,4.20416344 L4.71607014,4.20416344 L4.71607014,3.0953018 C4.71607014,2.33750606 5.36258193,1.72093187 6.15728698,1.72093187 L6.15728698,1.72093187 L8.735716,1.72093187 C8.81385333,1.31101139 9.18930373,1 9.64170756,1 L9.64170756,1 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/league-of-legends.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/league-of-legends.jsx
new file mode 100755
index 0000000..808cfac
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/league-of-legends.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function LeagueOfLegends(props) {
4 return (
5 <Icon {...props}>
6 <path d="M 6.2109375 4 L 9 8.53125 L 9 23.451172 L 6.0273438 28 L 23.453125 28 L 28.017578 22 L 16 22 L 16 4 L 6.2109375 4 z M 9.7890625 6 L 14 6 L 14 24 L 23.982422 24 L 22.462891 26 L 9.7246094 26 L 11 24.048828 L 11 7.9667969 L 10.851562 7.7265625 L 9.7890625 6 z M 18 6.1914062 L 18 8.2324219 C 22.002 9.1454219 25 12.725 25 17 C 25 18.052 24.816422 19.061 24.482422 20 L 26.580078 20 C 26.851078 19.046 27 18.04 27 17 C 27 11.618 23.112 7.1354062 18 6.1914062 z M 7 10.695312 C 5.993 12.128312 5.3159375 13.807 5.0859375 15.625 C 5.0289375 16.075 5 16.534 5 17 C 5 17.561 5.0420469 18.112391 5.1230469 18.650391 C 5.3840469 20.362391 6.044 21.944688 7 23.304688 L 7 10.695312 z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/libre-wolf.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/libre-wolf.jsx
new file mode 100755
index 0000000..b1e856a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/libre-wolf.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function LibreWolf(props) {
4 return (
5 <Icon {...props}>
6 <path d="M10.479 23.941c-2.105-.27-4.118-1.109-5.875-2.448-.573-.437-1.648-1.52-2.117-2.132-1.314-1.715-2.131-3.66-2.4-5.718-.116-.88-.116-2.5 0-3.304C.667 6.315 3.2 2.864 6.834 1.14 8.525.339 10.073 0 12.038 0c3.18 0 6 1.14 8.287 3.346 1.102 1.063 1.84 2.071 2.473 3.375C23.654 8.485 24 10.02 24 12.044c0 2.665-.77 4.989-2.367 7.15-.475.643-1.403 1.62-2.019 2.124-1.688 1.385-3.84 2.322-5.977 2.602-.738.096-2.48.108-3.158.021Zm4.454-2.158c1.286-.406 2.334-.95 3.345-1.74.538-.42 1.468-1.358 1.858-1.875 1.057-1.403 1.776-3.16 1.988-4.857.102-.818.043-2.546-.113-3.297-.412-1.988-1.3-3.667-2.7-5.104-.872-.896-1.666-1.486-2.688-1.999-1.55-.777-2.88-1.092-4.624-1.093-1.848-.002-3.467.421-5.07 1.325-1.46.823-2.968 2.334-3.795 3.8-.608 1.08-1.054 2.36-1.227 3.531-.114.768-.117 2.292-.005 3.027.224 1.47.782 2.925 1.59 4.144.442.666.428.658.817.435.697-.398.879-.591 1.259-1.335.444-.87.918-1.63 1.347-2.158.495-.61.563-.718.811-1.293.125-.29.35-.715.498-.945l.271-.419-.35-.344c-.466-.458-.853-.977-.926-1.241-.074-.27.013-.42.363-.622.354-.205.607-.263 1.552-.36.46-.048.96-.135 1.118-.194.156-.06.624-.315 1.04-.566 1.199-.728 1.3-.765 2.019-.75.607.014.608.013.968-.204.755-.456 1.838-1.28 3.264-2.48.273-.23.537-.41.585-.4.202.038.572.947.628 1.541.035.36-.035.717-.249 1.275-.058.152-.085.297-.06.323.062.06.271-.202.271-.339 0-.175.116-.195.274-.047.114.108.213.138.443.138.252 0 .314.024.412.155.167.222.206.828.079 1.212-.124.374-.5.804-.84.964-.304.144-.92.746-1.209 1.181-.11.167-.317.515-.46.773-.143.259-.382.649-.532.868-.294.43-.547 1.03-.79 1.88-.143.5-.155.63-.161 1.743-.007 1.345-.077 1.675-.44 2.09-.414.47-.826 1.505-.861 2.157a4.937 4.937 0 0 1-.175 1.11c-.04.13.034.129.475-.01Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/linear.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/linear.jsx
new file mode 100755
index 0000000..a71356c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/linear.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Linear(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0.32174625,9.1633125 L14.8366875,23.67825 C14.127825,23.8504875 13.394325,23.9598375 12.64245,24 L12.64245,24 L-1.77635684e-14,11.35755 C0.04017375,10.605675 0.149504625,9.8722125 0.32174625,9.1633125 L0.32174625,9.1633125 Z M0.151129875,14.0246625 L9.9753375,23.848875 C4.9584375,23.00085 0.9991575,19.0415625 0.151129875,14.0246625 Z M1.81703625,5.62665 L18.37335,22.182975 C17.84925,22.5124125 17.2978875,22.802475 16.723425,23.0490375 L16.723425,23.0490375 L0.95097375,7.276575 C1.19752125,6.7021125 1.48759125,6.15075 1.81703625,5.62665 L1.81703625,5.62665 Z M11.9913375,2.48689958e-14 C18.62355,2.48689958e-14 24,5.37645 24,12.0086625 C24,15.6496125 22.3796625,18.9121125 19.8207375,21.114375 L2.88562875,4.1792625 C5.0878875,1.62034875 8.3503875,2.48689958e-14 11.9913375,2.48689958e-14 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/lm-studio.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/lm-studio.jsx
new file mode 100755
index 0000000..ad2f9be
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/lm-studio.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function LMStudio(props) {
4 return (
5 <Icon {...props}>
6 <path
7 d="M2.84 2a1.273 1.273 0 100 2.547h14.107a1.273 1.273 0 100-2.547H2.84zM7.935 5.33a1.273 1.273 0 000 2.548H22.04a1.274 1.274 0 000-2.547H7.935zM3.624 9.935c0-.704.57-1.274 1.274-1.274h14.106a1.274 1.274 0 010 2.547H4.898c-.703 0-1.274-.57-1.274-1.273zM1.273 12.188a1.273 1.273 0 100 2.547H15.38a1.274 1.274 0 000-2.547H1.273zM3.624 16.792c0-.704.57-1.274 1.274-1.274h14.106a1.273 1.273 0 110 2.547H4.898c-.703 0-1.274-.57-1.274-1.273zM13.029 18.849a1.273 1.273 0 100 2.547h9.698a1.273 1.273 0 100-2.547h-9.698z"
8 fillOpacity=".3"
9 />
10 <path d="M2.84 2a1.273 1.273 0 100 2.547h10.287a1.274 1.274 0 000-2.547H2.84zM7.935 5.33a1.273 1.273 0 000 2.548H18.22a1.274 1.274 0 000-2.547H7.935zM3.624 9.935c0-.704.57-1.274 1.274-1.274h10.286a1.273 1.273 0 010 2.547H4.898c-.703 0-1.274-.57-1.274-1.273zM1.273 12.188a1.273 1.273 0 100 2.547H11.56a1.274 1.274 0 000-2.547H1.273zM3.624 16.792c0-.704.57-1.274 1.274-1.274h10.286a1.273 1.273 0 110 2.547H4.898c-.703 0-1.274-.57-1.274-1.273zM13.029 18.849a1.273 1.273 0 100 2.547h5.78a1.273 1.273 0 100-2.547h-5.78z" />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/maestro-ai.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/maestro-ai.jsx
new file mode 100755
index 0000000..8ae6ab1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/maestro-ai.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function MaestroAI(props) {
4 return (
5 <Icon {...props}>
6 <path d="m23.43.2.04-.1q.32-.25.53.11 0 .12-.04.26l-.22.53-.13.28-1.98 4.52-1.23 2.85q-.08.15.01.3.16.27.1.56-.14.4-.32.8a.6.6 0 0 0-.03.5l.3.68c.1.33.2.65.17 1q-.02.19-.05.35-.22.67-.76 1.15-.46.3-.92.57-.37.22-.64.56l-.3.34q-.14.23-.32.03l-1.22-1.31q-.46-.49-.25-1.13.17-.62.32-1.28 0-.06.03-.1 0-.05.03-.09.14-.31.31-.61l.86-1.28.49-.78c.18-.3.31-.36.61-.28.17.11.23.27.26.48l.08-.12 1.7-3.5.65-1.35.08-.16.11-.22q.23-.45.43-.88l.92-1.93zM22.88 15.92l-.03.46q-.15.75-.33 1.43a2.4 2.4 0 0 1-1 1.41q-.41.21-.82.38c-.7.24-1.44.32-2.17.42q-.27.03-.37-.19l-.6-1.1q-.1-.21.04-.39l.26-.35.82-1.28q.14-.19.32-.32q.18-.1.4-.17l1.42-.68.52-.18.13.12q0 .11-.03.23l-.5.74.03.04 1.3-.72q.22-.12.45-.07z" />
7 <path d="M1.73 6.77q.09-.98.66-1.76a5.4 5.4 0 0 1 3.2-2.18c.77-.19 1.55-.19 2.31.08.36.13.73.24 1.12.2q.13.01.28.06l.06.03q.18.21.11.51-.12.19-.25.33-.08.09.02.16q.12.09.22.21c.32.38.46.82.51 1.3q.01.28.23.47l1.37.94.3.3q.36.42-.1.72-.11.08-.23.13-.19.09-.11.28l.44 1.26c.08.23.15.47.1.72q-.08.37-.37.62c-.24.22-.53.34-.83.45l-.24.1q-.86.25-1.48.88c-.28.3-.29.3-.63.06q-.15-.1-.3-.17c-.13-.07-.16-.04-.17.1q0 .15-.03.3-.05.23-.27.11-.53-.28-1.08-.55-.56-.24-1.15-.47l-.18-.04h-.01q.65.51 1.28 1.05a25 25 0 0 1 3.05 3.41l.46.62.1.13.04-.02-.63-1.93.04-.02.08.06 1.54 1.64c.13.15.12.2 0 .36l-.49.63a1 1 0 0 0-.09.26q.02.25.25.15.16-.1.28-.2l2.25-2.17q.87-.87 1.73-1.78c.2-.2.25-.2.44 0a116 116 0 0 1 2.3 2.43c.15.17.15.2.01.39q-.57.77-1.16 1.53-.79 1.01-1.74 1.9c-.64.61-1.3 1.2-2.08 1.64-.55.31-1.12.55-1.77.49a5 5 0 0 1-1.3-.35c-.2-.12-.35-.05-.5.07q-.22.2-.17.5.01.07.1.12.04.05.15.13-.19.11-.36.18a14 14 0 0 1-5.6.83l-1.75-.17q-.41-.05-.84-.14l-.5-.1c-.37-.08-.39-.1-.32-.46V23q.23-1.7.43-3.4c.14-1.22.33-2.43.77-3.6q.5-1.26 1.29-2.36l.46-.63q.4-.53.76-1.06q.15-.23.2-.49c.1-.28 0-.51-.22-.7q-.34-.32-.66-.64a5 5 0 0 1-1.2-1.86q-.02-.07-.07-.16V8l-.02-.13c-.05-.37-.1-.73-.04-1.1M17.9 21.04q-.07.09-.16.14-.2.1-.42.18l-.58.16q-1.45.43-2.95.66h-.11l.2-.19q1.03-.9 2.03-1.82.46-.46.88-.95c.09-.1.16-.23.32-.2.15.02.16.17.2.28z" />
8 <path d="M9.97 13q.13.4.13.8-.02.42-.07.86c-.1.15-.23.16-.38.13-.72-.19-.97-.94-.48-1.51q.25-.35.68-.49l.09.11z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mail.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mail.jsx
new file mode 100755
index 0000000..5f331f2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mail.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Mail(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 12.713l-11.985-9.713h23.971l-11.986 9.713zm-5.425-1.822l-6.575-5.329v12.501l6.575-7.172zm10.85 0l6.575 7.172v-12.501l-6.575 5.329zm-1.557 1.261l-3.868 3.135-3.868-3.135-8.11 8.848h23.956l-8.11-8.848z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mamp.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mamp.jsx
new file mode 100755
index 0000000..bdfadca
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mamp.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Mamp(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M0.102364475,8.12278348 C0.348208608,6.42298667 2.24084804,1.12581027 7.55587597,0.121484851 C10.6927782,-0.471873056 14.5606318,1.15832949 17.2761989,3.91963527 C15.9222542,4.85153866 15.0170652,5.65650713 14.3332769,6.63475433 C14.8429844,8.53233711 16.3497002,9.30494346 17.4104808,9.6263653 C16.235161,8.91392735 15.4932413,8.24170642 15.0338309,6.80771887 C17.5478966,3.81155207 20.2390202,2.84257363 20.4663751,2.81948027 C22.5683503,4.50073955 24.0520329,7.56650062 23.9986022,10.7945436 C23.9359268,14.5325256 21.9088487,18.3848747 19.5840626,19.9393562 C19.265045,20.0923693 18.5309597,19.6889425 18.4302091,19.2517397 C18.9063852,18.1437298 20.031408,15.4457344 20.170234,13.4307996 C20.3015389,11.4961418 19.0239015,10.3603256 17.9523094,11.7588091 C16.4625159,14.2590185 15.8122589,17.3649966 15.162002,20.7166754 C14.0676901,21.0302424 12.2099921,21.1091054 11.4071207,20.6796004 C11.3048031,18.605754 11.7870901,15.0641441 10.4149696,13.8216586 C9.82723132,13.2886262 9.24717079,13.5357409 8.85341279,14.0271424 C7.8612617,15.2587881 7.88100445,18.4527409 8.07341783,20.5234453 C6.96359374,21.2110618 5.083176,21.0673175 3.89406757,20.6409544 C3.41773477,17.386519 2.29741256,13.4199599 1.38156874,10.383419 C1.12663668,11.604225 1.00300952,13.0551791 1.04265169,14.3022204 C0.430626717,13.8031211 -0.265539937,11.1777048 0.102364475,8.12278348 Z"
9 transform="translate(0 1)"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/manus.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/manus.jsx
new file mode 100755
index 0000000..041df0d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/manus.jsx
@@ -0,0 +1,17 @@
1import Icon from "../icon.jsx";
2
3export default function Manus(props) {
4 return (
5 <Icon {...props}>
6 <path
7 d="M8.047 1.163A.936.936 0 119.863.709c.063.256.132.508.2.76l.005.016c.158.58.315 1.16.416 1.771a.936.936 0 11-1.847.305c-.085-.517-.203-.949-.346-1.473v-.002c-.075-.274-.157-.573-.244-.923zM3.67 2.753a.936.936 0 00.428 1.252c.667.327 1.245.65 1.818 1.295a.936.936 0 001.4-1.242C6.5 3.138 5.66 2.687 4.922 2.325a.936.936 0 00-1.252.428z">
8 </path>
9 <path clipRule="evenodd"
10 d="M15.672 21.284c-.17-.036-.356-.075-.546-.117-.7-.152-1.65-.365-2.097-.513l-.033-.011-.032-.012c-.198-.074-.534-.156-1.09-.283l-.103-.023c-.48-.11-1.07-.244-1.63-.413-.578-.176-1.294-.437-1.903-.862-.638-.446-1.364-1.232-1.404-2.412a5.024 5.024 0 01.009-.51 2.716 2.716 0 01-.65-1.24 2.632 2.632 0 01.03-1.275c.083-.317.21-.594.316-.8.036-.07.073-.14.11-.206-.35-.111-.747-.248-1.133-.412-.503-.215-1.218-.57-1.752-1.141a2.798 2.798 0 01-.71-1.327 2.55 2.55 0 01.226-1.68c.604-1.208 1.757-1.635 2.782-1.672.926-.033 1.912.226 2.795.536.804.282 1.955.807 2.933 1.264.322-.529.747-1.126 1.149-1.608l.08-.095.092-.084a3.43 3.43 0 012.06-.887 3.559 3.559 0 011.059.08l.036.008.023.007h.003l.002.001s.002 0-.477 1.786l.479-1.786.208.058.19.102c.964.516 1.238 1.406 1.31 1.876a2.9 2.9 0 01-.008.903l-.003.018v.005l-1.858-.37 1.857.371-.01.054-.3 1.19c-.058.292-.065.459-.062.547a.286.286 0 00.016.107v.001c.013.03.043.095.154.263.043.066.088.131.144.214l.058.084c.08.118.174.257.274.412.623.97.684 1.902.68 2.499v.026l.238.078.103.032.153.049c.076.024.173.056.267.09.11-.202.407-.636.945-.636.702 0 .99.987.99.987.275 1.838-.98 8.013-2.794 9.164-1.386.88-2.413-.427-3.176-2.437zM8.72 12.868c.118-.119.47-.37 1.136-.445a4.337 4.337 0 012.228.365c.623.276 1.053.908 1.233 1.667.088.371.104.731.066 1.025-.04.31-.128.465-.169.511-.05.058-.228.157-.721.053a3.417 3.417 0 01-.764-.266l-.006-.003a.936.936 0 00-.861 1.662h.001l.003.002.008.004.024.012a4.888 4.888 0 00.34.152c.215.086.52.194.866.267.615.13 1.75.23 2.52-.652.37-.424.548-.98.615-1.501a4.789 4.789 0 00-.1-1.697c-.268-1.128-.976-2.362-2.297-2.948a6.208 6.208 0 00-3.195-.513c-.619.07-1.211.242-1.69.504l-.02-.006h-.004c-1.183-.338-3.536-1.01-2.956-2.17.44-.88 1.643-.807 3.275-.234.663.232 1.584.647 2.453 1.051.27.125.534.25.784.367l.974.454c.693-.832.962-1.29 1.2-1.695.163-.278.312-.53.573-.862l.025-.032a9.902 9.902 0 01.146-.18.895.895 0 01.02-.017c.642-.567 1.389-.36 1.389-.36.427.228.318.806.318.806l-.296 1.178c-.284 1.386.03 1.845.547 2.6.09.133.188.275.29.433.412.643.392 1.26.377 1.765-.01.324-.019.602.09.809.224.425 1.06.69 1.61.862.132.042.247.078.333.11l.059.023c-.078.24-.148.489-.218.737-.313 1.103-.623 2.202-1.55 2.53-.632.225-1.263.214-1.71.156-.786-.17-1.716-.379-2.066-.495-.363-.135-.871-.25-1.424-.377-1.316-.3-2.883-.656-3.331-1.462a.975.975 0 01-.125-.447c-.026-.74.234-1.404.234-1.404s-.403.002-.685-.27a.853.853 0 01-.238-.431c-.03-.13-.042-.28-.025-.44.008 0 .012-.008.012-.028 0-.234.234-.702.702-1.17z">
11 </path>
12 <path
13 d="M14.077.604a.936.936 0 01.315 1.285c-.355.584-.561 1.181-.786 2.081a.936.936 0 11-1.816-.454c.243-.971.504-1.778 1.002-2.598a.936.936 0 011.285-.314z">
14 </path>
15 </Icon>
16 );
17}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/matlab.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/matlab.jsx
new file mode 100755
index 0000000..7208923
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/matlab.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Matlab(props) {
4 return (
5 <Icon {...props}>
6 <path d="M10.5,22.125c-0.152,0 -0.291,-0.092 -0.348,-0.237c-0.747,-1.883 -2.136,-5.388 -3.168,-5.388c-0.482,0 -0.959,0.309 -0.963,0.312c-0.13,0.087 -0.301,0.084 -0.427,-0.008l-4.688,-3.375c-0.11,-0.079 -0.169,-0.213 -0.153,-0.348c0.015,-0.136 0.104,-0.252 0.23,-0.303l6.174,-2.535c0.276,-0.406 1.346,-1.897 2.505,-2.343c0.175,-0.068 0.322,-0.123 0.446,-0.169c0.628,-0.235 0.628,-0.235 1.108,-0.686l0.106,-0.1c0.652,-0.611 1.896,-2.532 2.281,-3.157c0.044,-0.072 0.091,-0.152 0.141,-0.236c0.419,-0.708 0.992,-1.677 1.865,-1.677c1.002,-0 1.533,1.032 2.125,2.381c0.544,1.24 1.996,5.347 2.59,7.109c1.429,4.24 2.873,7.19 2.888,7.22c0.073,0.148 0.039,0.328 -0.083,0.441c-0.122,0.113 -0.303,0.132 -0.446,0.046c-0.031,-0.018 -0.757,-0.458 -1.948,-1.651c-0.884,-0.884 -1.604,-1.296 -2.266,-1.296c-1.166,0 -1.99,0.927 -3.033,2.101l-0.062,0.07c-0.123,0.139 -0.26,0.299 -0.408,0.473c-1.035,1.211 -2.599,3.043 -4.403,3.351c-0.021,0.004 -0.042,0.005 -0.063,0.005Zm-3.516,-6.375c1.385,0 2.481,2.39 3.746,5.563c1.427,-0.41 2.762,-1.974 3.665,-3.031c0.152,-0.178 0.292,-0.342 0.419,-0.484l0.062,-0.07c1.121,-1.263 2.09,-2.353 3.593,-2.353c1.136,0 2.091,0.81 2.796,1.516c0.224,0.224 0.431,0.42 0.618,0.59c-0.565,-1.288 -1.421,-3.36 -2.269,-5.877c-0.613,-1.819 -2.053,-5.877 -2.566,-7.047c-0.55,-1.253 -0.942,-1.932 -1.439,-1.932c-0.445,0 -0.93,0.819 -1.22,1.309c-0.052,0.088 -0.101,0.172 -0.148,0.247c-0.015,0.025 -1.545,2.503 -2.406,3.312l-0.106,0.099c-0.572,0.538 -0.61,0.562 -1.357,0.841c-0.123,0.047 -0.267,0.101 -0.44,0.167c-0.906,0.349 -1.902,1.67 -2.21,2.149c-0.042,0.065 -0.102,0.116 -0.173,0.145l-5.657,2.321l3.945,2.84c0.253,-0.129 0.684,-0.305 1.147,-0.305Zm-1.012,1.089l-0.32,-0.678c0.024,-0.011 2.322,-1.123 4.111,-3.895c1.699,-2.634 2.539,-4.691 2.989,-5.795c0.115,-0.282 0.203,-0.495 0.27,-0.634c0.165,-0.342 0.324,-0.753 0.493,-1.188c0.529,-1.364 1.076,-2.774 2.094,-2.774l0,0.75c-0.505,0 -1.019,1.326 -1.395,2.295c-0.174,0.45 -0.339,0.875 -0.517,1.243c-0.062,0.13 -0.143,0.329 -0.25,0.592c-0.46,1.127 -1.316,3.225 -3.053,5.917c-1.912,2.963 -4.32,4.119 -4.422,4.167Zm3.834,-4.023l-2.625,-1.969l0.45,-0.6l2.625,1.969l-0.45,0.6Zm4.509,4.414c1.169,-1.317 2.275,-2.561 4.06,-2.604c0,0 -1.266,-5.579 -2.344,-10.173c-0.219,-0.933 -0.306,-1.078 -0.397,-1.078c-0.062,0 -0.136,0.137 -0.194,0.452c-0.311,1.684 -1.784,7.956 -2.971,10.986c-0.454,1.157 -1.264,1.837 -1.969,2.156c-0.322,0.146 -0.787,0.281 -0.787,0.281c0.487,0.855 0.951,1.905 1.428,3.076c1.007,-0.568 1.992,-1.721 2.684,-2.531c0.155,-0.182 0.299,-0.35 0.428,-0.496l0.062,-0.069Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mattermost.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mattermost.jsx
new file mode 100755
index 0000000..eea42a9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mattermost.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Mattermost(props) {
4 return (
5 <Icon {...props}>
6 <path d="M19.052 2.29l.126 2.548c2.065 2.28 2.88 5.511 1.852 8.548-1.534 4.532-6.594 6.915-11.3 5.322s-7.28-6.56-5.745-11.092C5.017 4.569 7.64 2.494 10.68 1.945l1.642-1.94C7.2-.134 2.366 3.045.637 8.153c-2.124 6.276 1.24 13.086 7.516 15.21s13.086-1.24 15.21-7.516c1.727-5.1-.172-10.552-4.311-13.556z" />
7 <path d="M16.11 9.806l-.087-3.56-.07-2.05-.047-1.775s.01-.856-.02-1.057a.328.328 0 00-.036-.107l-.006-.012a.278.278 0 00-.358-.127l-.004.001a.33.33 0 00-.109.071c-.145.142-.658.828-.658.828L13.6 3.4l-1.3 1.585-2.232 2.776s-1.024 1.278-.798 2.851 1.396 2.34 2.303 2.647c.908.308 2.303.41 3.438-.703 1.136-1.113 1.099-2.75 1.099-2.75z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/messages.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/messages.jsx
new file mode 100755
index 0000000..afa1565
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/messages.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Messages(props) {
4 return (
5 <Icon {...props}>
6 <path d="M19.619 21.671c-5.038 1.227-8.711-1.861-8.711-5.167 0-3.175 3.11-5.467 6.546-5.467 3.457 0 6.546 2.309 6.546 5.467 0 1.12-.403 2.22-1.117 3.073-.029 1 .558 2.435 1.088 3.479-1.419-.257-3.438-.824-4.352-1.385zm-10.711-5.167c0-4.117 3.834-7.467 8.546-7.467.886 0 1.74.119 2.544.338-.021-4.834-4.761-8.319-9.998-8.319-5.281 0-10 3.527-10 8.352 0 1.71.615 3.391 1.705 4.695.047 1.527-.851 3.718-1.661 5.313 2.168-.391 5.252-1.258 6.649-2.115.803.196 1.576.304 2.328.363-.067-.379-.113-.765-.113-1.16z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-off.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-off.jsx
new file mode 100755
index 0000000..f71ff3e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-off.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function MicOff(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0 0h24v24H0zm0 0h24v24H0z" fill="none" />
7 <path d="M19 11h-1.7c0 .74-.16 1.43-.43 2.05l1.23 1.23c.56-.98.9-2.09.9-3.28zm-4.02.17c0-.06.02-.11.02-.17V5c0-1.66-1.34-3-3-3S9 3.34 9 5v.18l5.98 5.99zM4.27 3L3 4.27l6.01 6.01V11c0 1.66 1.33 3 2.99 3 .22 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c.91-.13 1.77-.45 2.54-.9L19.73 21 21 19.73 4.27 3z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-on.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-on.jsx
new file mode 100755
index 0000000..76524ad
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mic-on.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function MicOn(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0 0h24v24H0z" fill="none" />
7 <path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-edge.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-edge.jsx
new file mode 100755
index 0000000..48e6caf
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-edge.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function MicrosoftEdge(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21.7 17.9l-1 .4c-1.1.4-2.2.6-3.4.6C13 19 9 16 9 12a3 3 0 0 1 1.5-2.5c-4 .2-5 4.3-5 6.8 0 7 6.4 7.6 7.8 7.6.7 0 1.8-.2 2.5-.4h.1a12 12 0 0 0 6.3-5 .4.4 0 0 0-.5-.5z" />
7 <path d="M21.7 17.9l-1 .4c-1.1.4-2.2.6-3.4.6C13 19 9 16 9 12a3 3 0 0 1 1.5-2.5c-4 .2-5 4.3-5 6.8 0 7 6.4 7.6 7.8 7.6.7 0 1.8-.2 2.5-.4h.1a12 12 0 0 0 6.3-5 .4.4 0 0 0-.5-.5z" />
8 <path d="M10 22.6a7.6 7.6 0 0 1 .6-13.2c.2-.2.7-.4 1.4-.4a3 3 0 0 1 3 3s2.3-7.5-7.5-7.5c-4.1 0-7.5 4-7.5 7.3a12 12 0 0 0 15.8 11.5 7 7 0 0 1-5.9-.7z" />
9 <path d="M10 22.6a7.6 7.6 0 0 1 .6-13.2c.2-.2.7-.4 1.4-.4a3 3 0 0 1 3 3s2.3-7.5-7.5-7.5c-4.1 0-7.5 4-7.5 7.3a12 12 0 0 0 15.8 11.5 7 7 0 0 1-5.9-.7z" />
10 <path d="M14.3 14c-.1 0-.3.2-.3.5 0 .2.1.5.4.7 1.4.9 3.9.8 4 .8 1 0 1.9-.3 2.7-.8a5.8 5.8 0 0 0 2.9-5c0-2-.8-3.5-1-4A12 12 0 0 0 12 0 12 12 0 0 0 0 11.8c0-3.4 3.4-6.2 7.5-6.2a9 9 0 0 1 4 1A6 6 0 0 1 15 12c0 .5-.3 1.2-.8 1.9z" />
11 <path d="M14.3 14c-.1 0-.3.2-.3.5 0 .2.1.5.4.7 1.4.9 3.9.8 4 .8 1 0 1.9-.3 2.7-.8a5.8 5.8 0 0 0 2.9-5c0-2-.8-3.5-1-4A12 12 0 0 0 12 0 12 12 0 0 0 0 11.8c0-3.4 3.4-6.2 7.5-6.2a9 9 0 0 1 4 1A6 6 0 0 1 15 12c0 .5-.3 1.2-.8 1.9z" />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-excel.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-excel.jsx
new file mode 100755
index 0000000..6f4df55
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-excel.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function MicrosoftExcel(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0a2 2 0 00-.4 0l-10 2A2 2 0 000 4v16a2 2 0 001.6 2l10 2a2 2 0 002.4-2V2a2 2 0 00-2-2zm4 2v3h2v2h-2v2h2v2h-2v2h2v2h-2v2h2v2h-2v3h6a2 2 0 002-2V4a2 2 0 00-2-2h-6zm4 3h1a1 1 0 010 2h-1V5zM3.2 7h2.4l1.2 3 .3.8.3-.8 1.4-3H11l-2.6 5 2.7 5H8.7l-1.5-3.3-.2-.6c0 .1 0 .4-.2.7L5.3 17H2.9l2.8-5-2.5-5zM20 9h1a1 1 0 010 2h-1V9zm0 4h1a1 1 0 010 2h-1v-2zm0 4h1a1 1 0 010 2h-1v-2z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-outlook.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-outlook.jsx
new file mode 100755
index 0000000..2de1829
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-outlook.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function MicrosoftOutlook(props) {
4 return (
5 <Icon {...props}>
6 <path d="M14.9434 5.1811v4.632l1.6203 1.019a.4124.4124 0 0 0 .1776 0l6.9669-4.697a.9929.9929 0 0 0-.811-.954h-7.9538Z" />
7 <path d="m14.9432 11.5409 1.4775 1.0148a.4406.4406 0 0 0 .4592 0c-.2537.1531 6.8273-4.5481 6.8273-4.5481v8.5128a1.1915 1.1915 0 0 1-.7518 1.2363 1.1902 1.1902 0 0 1-.5083.0788h-7.5047l.0008-6.2946ZM7.2947 9.4053a1.3608 1.3608 0 0 0-1.2009.7087 3.4938 3.4938 0 0 0-.4448 1.8758 3.4252 3.4252 0 0 0 .4448 1.8707 1.3533 1.3533 0 0 0 1.8443.5098 1.3532 1.3532 0 0 0 .4992-.4912 3.3949 3.3949 0 0 0 .4355-1.8606 3.6948 3.6948 0 0 0-.4228-1.929 1.299 1.299 0 0 0-1.1553-.6842Z" />
8 <path d="M.2861 2.8283v18.1209l13.785 2.8906V.1602L.2861 2.8283Zm9.225 12.124a2.7326 2.7326 0 0 1-2.2835 1.151 2.6985 2.6985 0 0 1-2.2326-1.1146 4.6167 4.6167 0 0 1-.8584-2.9042 4.9626 4.9626 0 0 1 .8762-3.058A2.7629 2.7629 0 0 1 7.3334 7.856a2.6352 2.6352 0 0 1 2.2072 1.1172 4.7685 4.7685 0 0 1 .8457 2.9464 4.8736 4.8736 0 0 1-.8753 3.0327Z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-power-point.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-power-point.jsx
new file mode 100755
index 0000000..2cdab52
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-power-point.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function MicrosoftPowerPoint(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0a2 2 0 00-.4 0l-10 2A2 2 0 000 4v16a2 2 0 001.6 2l10 2a2 2 0 002.4-2V2a2 2 0 00-2-2zm4 2v5.2a3 3 0 011-.2v3h3a3 3 0 01-4 2.8V16h5a1 1 0 010 2h-5v4h6a2 2 0 002-2V4a2 2 0 00-2-2h-6zm3 3a3 3 0 013 3h-3V5zM4 7h3.5c2.5 0 3.8 1 3.8 3.2a3 3 0 01-1 2.4c-.8.6-1.8 1-3 1h-1V17H4V7zm2.3 1.7v3.1H7c1.2 0 1.8-.5 1.8-1.5s-.6-1.6-1.8-1.6h-.8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-word.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-word.jsx
new file mode 100755
index 0000000..7d3165b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/microsoft-word.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function MicrosoftWord(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0a2 2 0 00-.4 0l-10 2A2 2 0 000 4v16a2 2 0 001.6 2l10 2a2 2 0 002.4-2V2a2 2 0 00-2-2zm4 2v3h4a1 1 0 010 2h-4v2h4a1 1 0 010 2h-4v2h4a1 1 0 010 2h-4v2h4a1 1 0 010 2h-4v3h6a2 2 0 002-2V4a2 2 0 00-2-2h-6zM2.3 7H4l1 6.6L6.4 7h1.4L9 13.6 10 7h1.8L10 17H8.2L7 10.9 5.8 17H4L2.3 7z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mimestream.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mimestream.jsx
new file mode 100755
index 0000000..1ed0a2b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mimestream.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Mimestream(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M9.59.03c.4-.11.83.01 1.11.32l4.76 5.23 7.01-.94a1.1 1.1 0 0 1 1.1 1.63l-3.5 6.14 3.06 6.37a1.1 1.1 0 0 1-1.2 1.55l-6.94-1.44-5.1 4.89a1.1 1.1 0 0 1-1.85-.67l-.78-7.03-6.23-3.35a1.1 1.1 0 0 1 .07-1.97l6.45-2.9L8.81.88A1.1 1.1 0 0 1 9.6.03Zm.98 3.44L9.6 8.8a1.1 1.1 0 0 1-.62.8l-4.95 2.24 4.78 2.57a1.1 1.1 0 0 1 .57.84l.6 5.4 3.92-3.75a1.1 1.1 0 0 1 .98-.28l5.31 1.1-2.35-4.89a1.1 1.1 0 0 1 .03-1.02l2.7-4.71-5.39.72a1.1 1.1 0 0 1-.96-.34l-3.65-4.02Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/min-browser.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/min-browser.jsx
new file mode 100755
index 0000000..ed6060c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/min-browser.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function MinBrowser(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M2.4 0C1.1 0 0 1 0 2.4v19.2C0 22.9 1 24 2.4 24h19.2c1.3 0 2.4-1 2.4-2.4V2.4C24 1.1 23 0 21.6 0H2.4zm5.1 14.7C6.1 11.1 6 9.2 9.2 7c3.4-1 5.1-.8 7.6 1.7 1.9 3.7 1.8 5.5-1.1 8.5-2.6 1.7-7.8 1.2-8.2 1a7 7 0 00-.4 0c-.5-.2-1.1-.3-1.5-.6.3 1.2.7 1.8 2 2.9 1.9 1 3 1.4 5.8 1 2.2-.6 3.5-1.1 5.8-3.2l.1-.2c1.3-1.7 2-2.8 2.3-5a16 16 0 00-2.4-7.4l-.2-.2a10.3 10.3 0 00-5.2-3A11 11 0 008 3c-2.8 2.1-3.6 3-4.4 4.6-1.4 2.8-1.4 4-.9 6.1.8 2.3 1.2 2.8 1.8 3.4 2.8.4 3.4-.2 3-2.5z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/miro.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/miro.jsx
new file mode 100755
index 0000000..678bc73
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/miro.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Miro(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.728 1.024h-4.356l3.868 6-8.182-6h-4.362l3.872 7.862-8.182-7.862h-4.362l3.806 10.148-3.806 19.804h4.362l8.18-21.234-3.87 21.234h4.36l8.184-23.096-3.87 23.096h4.358l8.248-25.368-8.248-4.584z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/monero-gui.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/monero-gui.jsx
new file mode 100755
index 0000000..a5d95a7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/monero-gui.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function MoneroGUI(props) {
4 return (
5 <Icon {...props} width={16} height={16}>
6 <path
7 d="M11.28774193548387 12.046451612903226h3.426838709677419C13.34258064516129 14.31941935483871 10.848322580645162 15.84 8 15.84S2.6574193548387095 14.31941935483871 1.2854193548387096 12.046451612903226H4.71225806451613V8.006322580645161L8 11.319354838709677 11.28774193548387 8v4.046451612903225ZM2.9419354838709677 10.529032258064515V3.9535483870967743l5.039096774193548 5.039096774193548L13.058064516129033 3.9535483870967743V10.529032258064515h2.3646451612903228c0.2687096774193548 -0.7934838709677419 0.41729032258064513 -1.6438709677419354 0.41729032258064513 -2.5290322580645164C15.84 3.669032258064516 12.330967741935483 0.16 8 0.16S0.16 3.669032258064516 0.16 8c0 0.8851612903225806 0.14541935483870969 1.735548387096774 0.41729032258064513 2.5290322580645164H2.9419354838709677Z"
8 strokeWidth="0.0323"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mongo-db.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mongo-db.jsx
new file mode 100755
index 0000000..3d57187
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mongo-db.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function MongoDB(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M24 12c0 6.6274-5.3726 12-12 12S0 18.6274 0 12 5.3726 0 12 0s12 5.3726 12 12ZM12.813 6.0778c.6053.6257 1.8087 1.87 2.3947 4.456.0758.4394.1154.8843.1183 1.3303.0138 2.6732-1.3969 4.35-2.1816 5.0749l-.0168.0152a4.785 4.785 0 0 1-.4714.3856l-.0234.0152a17.0453 17.0453 0 0 0-.3047 1.8405h-.2892a42.3361 42.3361 0 0 0-.1978-1.7189v.0026l-.042-.0297c-.3691-.2693-3.0986-2.3815-2.9296-5.9262.1811-3.8006 2.4082-5.6693 2.8422-6.0087.2803-.299.2916-.4134.3134-.71.0046.0108.0087.0218.012.0304l.0037.0095s.2137.5274.4247.8239c.0437.0953.1699.2257.3475.4094Zm-.6407 4.3997c-.1641-.0009-.1641 4.9706-.1641 4.9706 0 .3867.2299 1.4147.4577 1.4421 0 0-.1657-6.4127-.2936-6.4127Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/moon.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/moon.jsx
new file mode 100755
index 0000000..d8a5e15
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/moon.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Moon(props) {
5 return (
6 <Icon {...props} className={Utils.classNames(props.className, "moon-icon")}>
7 <path d="M12.081 2.509a1 1 0 0 1-.067 1.085 6 6 0 0 0 8.392 8.392 1 1 0 0 1 1.59.896A10 10 0 1 1 11.118 2.004a1 1 0 0 1 .963.505Zm-2.765 1.93a8 8 0 1 0 10.245 10.245A8 8 0 0 1 9.316 4.439Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mpv.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mpv.jsx
new file mode 100755
index 0000000..eef4479
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/mpv.jsx
@@ -0,0 +1,16 @@
1import Icon from "../icon.jsx";
2
3export default function Mpv(props) {
4 return (
5 <Icon {...props}>
6 <g fillRule="evenodd" clipRule="evenodd">
7 <path d="M24 12a12 12 0 11-24 0 12 12 0 0124 0zm-2.46-1.1a8.59 8.59 0 11-17.17 0 8.59 8.59 0 0117.17 0z" />
8 <path
9 fillOpacity=".6"
10 d="M23.45 11.63a11.14 11.14 0 11-22.28 0 11.14 11.14 0 0122.28 0zm-6.51 2.53a5.52 5.52 0 10-10.2-4.22 5.52 5.52 0 0010.2 4.22z"
11 />
12 <path d="M10 9v6l5-3.07L10 9z" />
13 </g>
14 </Icon>
15 );
16}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/music.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/music.jsx
new file mode 100755
index 0000000..6deefcc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/music.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Music(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12 24a12 12 0 1 0 0-24 12 12 0 0 0 0 24zm4.28-18.93l.5-.07c.23 0 .39.12.45.34.02.07.01 9.1.01 10.6a1.9 1.9 0 0 1-1.37 1.76c-.47.14-1.15.2-1.48.12-.3-.07-.52-.2-.75-.44-.35-.34-.5-.7-.5-1.15 0-.25.04-.44.16-.7.17-.36.4-.57.79-.77.31-.16.6-.24 1.42-.41.54-.12.76-.16.87-.29.15-.17.04-5.36 0-5.43-.07-.1-.2-.14-.35-.12l-5.62 1.13a.4.4 0 0 0-.29.32l-.02 1.34c-.01 2.2-.05 6.39-.16 6.7a2.3 2.3 0 0 1-.18.37c-.14.2-.4.46-.6.58-.5.29-1.45.44-1.96.3-.54-.14-.94-.5-1.12-1.03-.09-.24-.1-.65-.05-.93.07-.28.22-.55.41-.75.35-.35.77-.52 1.88-.74l.55-.13a.64.64 0 0 0 .34-.32c.04-.1.07-8.5.07-8.5l.06-.1a.7.7 0 0 1 .36-.34c.1-.03 5.64-1.16 6.58-1.34z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/n8n.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/n8n.jsx
new file mode 100755
index 0000000..ab86385
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/n8n.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function N8n(props) {
4 return (
5 <Icon {...props}>
6 <path
7 clipRule="evenodd"
8 d="M24 8.4c0 1.325-1.102 2.4-2.462 2.4-1.146 0-2.11-.765-2.384-1.8h-3.436c-.602 0-1.115.424-1.214 1.003l-.101.592a2.38 2.38 0 01-.8 1.405c.412.354.704.844.8 1.405l.1.592A1.222 1.222 0 0015.719 15h.975c.273-1.035 1.237-1.8 2.384-1.8 1.36 0 2.461 1.075 2.461 2.4S20.436 18 19.078 18c-1.147 0-2.11-.765-2.384-1.8h-.975c-1.204 0-2.23-.848-2.428-2.005l-.101-.592a1.222 1.222 0 00-1.214-1.003H10.97c-.308.984-1.246 1.7-2.356 1.7-1.11 0-2.048-.716-2.355-1.7H4.817c-.308.984-1.246 1.7-2.355 1.7C1.102 14.3 0 13.225 0 11.9s1.102-2.4 2.462-2.4c1.183 0 2.172.815 2.408 1.9h1.337c.236-1.085 1.225-1.9 2.408-1.9 1.184 0 2.172.815 2.408 1.9h.952c.601 0 1.115-.424 1.213-1.003l.102-.592c.198-1.157 1.225-2.005 2.428-2.005h3.436c.274-1.035 1.238-1.8 2.384-1.8C22.898 6 24 7.075 24 8.4zm-1.23 0c0 .663-.552 1.2-1.232 1.2-.68 0-1.23-.537-1.23-1.2 0-.663.55-1.2 1.23-1.2.68 0 1.231.537 1.231 1.2zM2.461 13.1c.68 0 1.23-.537 1.23-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.231.537-1.231 1.2 0 .663.55 1.2 1.23 1.2zm6.153 0c.68 0 1.231-.537 1.231-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.231.537-1.231 1.2 0 .663.55 1.2 1.23 1.2zm10.462 3.7c.68 0 1.23-.537 1.23-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.23.537-1.23 1.2 0 .663.55 1.2 1.23 1.2z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/net-news-wire.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/net-news-wire.jsx
new file mode 100755
index 0000000..4db43e7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/net-news-wire.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function NetNewsWire(props) {
4 return (
5 <Icon {...props}>
6 <path d="M.193 5.012c-.2404.4848-.2737.7724 0 1.3369l4.9267 4.9296c.4604.1626.7184.2138 1.179 0L9.92 7.6857c.2106-.4384.2466-.6914 0-1.1697L4.9512 1.5445c-.4745-.2123-.7485-.238-1.2632 0L.193 5.012ZM5.4144 15.4144l-2.3159 2.256c-.1366.3308-.124.5027 0 .7938l2.316 2.2141c.2794.0963.4363.0773.7158 0l2.3159-2.2977.379.376c.4195.2302.6818.2486 1.2211 0l5.5161-5.4728c.2062-.4006.2013-.6485 0-1.128L11.899 8.4795c-.4277-.1998-.667-.1862-1.0948 0L5.246 13.9523c-.2108.6077-.215.9331.1684 1.4621ZM23.8155 9.8163 14.2992.2912c-.329-.3477-.5133-.4268-.8422 0-1.0863 1.653-1.2793 2.6305-1.179 4.4284.1785 1.3531.4348 2.0691 1.179 3.2586.6483 1.0549 1.118 1.54 2.1054 2.2559 1.4306 1.0571 2.2624 1.3902 3.7897 1.504 1.9629.1438 2.956-.0998 4.4634-1.3369.2536-.1901.2383-.3205 0-.5849ZM20.3627 1.461l-1.6843 1.7128c-.0938.1482-.0924.2311.0421.376l1.8106 1.7546c.2132.0718.3015.0559.4211-.0418l1.6001-1.6292c.2733-.5388.2356-.8407-.0421-1.3787-.1976-.3485-.3772-.5205-.8001-.7938-.4911-.1845-.7808-.2139-1.3474 0ZM16.4045 14.2029l-3.5791 3.6346c-.1692.3593-.1633.5598 0 .9191l5.0529 5.055c.4605.2631.7185.239 1.179 0l3.5792-3.4675c.2378-.4698.2466-.7417 0-1.2115l-5.0108-4.9297c-.4768-.2405-.7444-.2107-1.2212 0Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/netease-music.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/netease-music.jsx
new file mode 100755
index 0000000..0a31527
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/netease-music.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function NeteaseMusic(props) {
4 return (
5 <Icon {...props}>
6 <path d="M15.462 1c.222.036.447.063.667.11.772.17 1.463.512 2.074 1.012.4.328.563.757.449 1.266-.104.456-.395.764-.847.896-.426.124-.81.03-1.16-.251-.442-.355-.936-.602-1.524-.548-.5.045-.979.57-.934 1.04.02.21.094.415.148.621.094.366.19.73.287 1.093.016.063.032.113.12.12a6.5 6.5 0 013.63 1.321c1.059.797 1.927 1.754 2.511 2.955a7.45 7.45 0 01.73 2.79c.083 1.3-.07 2.57-.575 3.771-1.176 2.788-3.244 4.586-6.149 5.414-1.106.315-2.24.438-3.387.373-2.384-.134-4.451-1.037-6.191-2.667-1.72-1.607-2.788-3.582-3.16-5.901-.508-3.156.269-5.985 2.325-8.436 1.13-1.347 2.539-2.319 4.182-2.945a1.233 1.233 0 011.497.48 1.22 1.22 0 01-.197 1.558c-.124.115-.28.204-.438.267-2.505 1.02-4.162 2.822-4.82 5.448-.637 2.548-.074 4.883 1.554 6.937a7.317 7.317 0 003.935 2.579c1.033.274 2.074.292 3.125.13 1.084-.168 2.096-.523 3.003-1.145 1.25-.855 2.14-1.995 2.584-3.448.384-1.252.397-2.518-.076-3.76-.382-1-1.058-1.77-1.906-2.406-.454-.34-.939-.604-1.493-.734-.025-.007-.052-.01-.097-.016.077.29.146.566.218.84.175.662.355 1.324.528 1.989.375 1.44.011 2.704-.981 3.782-.918.997-2.088 1.428-3.43 1.3-1.493-.144-2.56-.954-3.255-2.268-.364-.686-.521-1.427-.55-2.202-.047-1.234.242-2.372.95-3.392.758-1.093 1.81-1.795 3.052-2.23.1-.035.198-.066.312-.104-.067-.254-.137-.5-.197-.752-.083-.344-.189-.687-.231-1.035-.124-1.033.193-1.933.907-2.685.583-.615 1.293-1.005 2.143-1.124l.28-.04C15.207 1 15.335 1 15.463 1zM12.81 9.02c-.736.234-1.372.591-1.848 1.186-.637.795-.765 1.708-.56 2.68.105.505.352.936.785 1.237.54.377 1.277.361 1.843-.031.579-.4.835-1.046.666-1.709-.183-.725-.381-1.448-.572-2.173-.105-.39-.206-.78-.314-1.19z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/no-volume.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/no-volume.jsx
new file mode 100755
index 0000000..0a146d1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/no-volume.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function NoVolume(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.4332 4.0987A1 1 0 0 1 12 5v14a1 1 0 0 1-1.6247.7809L5.6493 16H2c-.5523 0-1-.4477-1-1V9c0-.5523.4477-1 1-1h3.6492l4.7261-3.7809a1 1 0 0 1 1.0579-.1204ZM10 7.0807 6.6247 9.7808A1 1 0 0 1 6 10H3v4h3c.227 0 .4474.0773.6247.2191L10 16.9194V7.0806Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notability.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notability.jsx
new file mode 100755
index 0000000..8a4c560
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notability.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Notability(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M4 0a4 4 0 00-4 4v16a4 4 0 004 4h16a4 4 0 004-4V4a4 4 0 00-4-4H4zm.46 19.44l1.7-5.62 1-.97-.28.25c-.06-.86-.07-1.45 0-2.34.1-.33.2-.52.57-.86l5.07-5.13c.36.08.5.18.6.5l-2.1 1.92 1.07.87 3.4-3.3a3.24 3.24 0 012.26 0 4 4 0 011.6 1.6 3.1 3.1 0 010 2.15l-3.41 3.44.61.73 1.97-1.92c.4.07.54.2.66.52l-5.04 5.07c-.45.27-.7.37-1.17.5l-.86.13c-.45.06-.7.04-1.15 0l.42-.44-1.13 1.13-5.8 1.77zm7.48-3.47c.37.07.6.07 1.03 0 .99-.7 1.54-1.2 2.54-2.23l-.76-.6-2.8 2.83zm-.83-6.96l-3.36 3.27c-.1-.4-.1-.65 0-1.1.04-.35.14-.54.4-.88l1.91-1.95.9.8.15-.14z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notebook-lm.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notebook-lm.jsx
new file mode 100755
index 0000000..2be5095
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notebook-lm.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function NotebookLM(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.999 3.14C5.372 3.14 0 8.588 0 15.312v5.828h2.212v-.58c0-2.728 2.178-4.938 4.866-4.938 2.688 0 4.866 2.21 4.866 4.937v.581h2.212v-.58c0-3.967-3.17-7.18-7.078-7.18a6.966 6.966 0 00-4.086 1.318C4.2 12.262 6.687 10.59 9.56 10.59c4.057 0 7.347 3.338 7.347 7.453v3.097h2.212v-3.097c0-5.355-4.28-9.698-9.56-9.698a9.438 9.438 0 00-6.217 2.332C4.984 7.528 8.244 5.383 12 5.383c5.406 0 9.788 4.446 9.788 9.93v5.827H24v-5.828C23.999 8.588 18.627 3.14 11.999 3.14z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notes.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notes.jsx
new file mode 100755
index 0000000..23e8a43
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notes.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Notes(props) {
4 return (
5 <Icon {...props}>
6 <path d="M2 0v24h20v-24h-20zm18 22h-16v-15h16v15zm-3-4h-10v-1h10v1zm0-3h-10v-1h10v1zm0-3h-10v-1h10v1z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notion.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notion.jsx
new file mode 100755
index 0000000..ff12f11
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/notion.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Notion(props) {
4 return (
5 <Icon {...props}>
6 <path d="M4.459 4.208c.746.606 1.026.56 2.428.466l13.215-.793c.28 0 .047-.28-.046-.326L17.86 1.968c-.42-.326-.981-.7-2.055-.607L3.01 2.295c-.466.046-.56.28-.374.466zm.793 3.08v13.904c0 .747.373 1.027 1.214.98l14.523-.84c.841-.046.935-.56.935-1.167V6.354c0-.606-.233-.933-.748-.887l-15.177.887c-.56.047-.747.327-.747.933zm14.337.745c.093.42 0 .84-.42.888l-.7.14v10.264c-.608.327-1.168.514-1.635.514-.748 0-.935-.234-1.495-.933l-4.577-7.186v6.952L12.21 19s0 .84-1.168.84l-3.222.186c-.093-.186 0-.653.327-.746l.84-.233V9.854L7.822 9.76c-.094-.42.14-1.026.793-1.073l3.456-.233 4.764 7.279v-6.44l-1.215-.139c-.093-.514.28-.887.747-.933zM1.936 1.035l13.31-.98c1.634-.14 2.055-.047 3.082.7l4.249 2.986c.7.513.934.653.934 1.213v16.378c0 1.026-.373 1.634-1.68 1.726l-15.458.934c-.98.047-1.448-.093-1.962-.747l-3.129-4.06c-.56-.747-.793-1.306-.793-1.96V2.667c0-.839.374-1.54 1.447-1.632z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/nova.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/nova.jsx
new file mode 100755
index 0000000..ee0bf11
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/nova.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Nova(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M19.448908,7.93508793 C19.448908,7.93508793 19.2774379,0.389455004 12.5840983,0.0161227141 C5.94013132,-0.355859369 4.84459068,5.8105369 4.76185801,8.00664891 C4.69046773,9.90166471 5.81069473,15.5975138 10.7372916,15.8756565 C13.9538577,16.0572593 14.367521,13.2967607 14.367521,13.2967607 C13.8945761,14.4914516 12.6973133,15.2252033 11.4318457,15.0959118 C10.4917722,15.0577013 9.60841903,14.630677 8.98835928,13.9146991 C8.36829953,13.1987212 8.06590673,12.2565744 8.15189577,11.3085806 C8.28933875,8.4731455 9.90062416,5.67956681 14.2040573,6.00159122 C18.3313498,6.31078867 19.448908,7.93508793 19.448908,7.93508793 L19.448908,7.93508793 Z M12.878333,21.9536142 C12.878333,21.9536142 18.9952128,25.4020433 22.6628053,19.7358988 C26.3023754,14.1149863 21.5579239,10.073141 19.7151204,8.90183628 C18.1245182,7.88918088 12.3292283,6.01104267 10.0087104,9.87938629 C9.00892842,11.359559 9.16129721,13.3441628 10.3750026,14.6503434 C9.58615751,13.6415046 9.55536959,12.2252983 10.2996091,11.1823362 C11.4594542,9.49926874 13.7329451,9.05684456 15.4270329,10.1845331 C17.6327926,11.5819976 18.5688727,14.4984451 16.8775234,17.716664 C14.9406449,21.4081305 12.878333,21.9536142 12.878333,21.9536142 L12.878333,21.9536142 Z M4.09866228,9.05913542 C4.09866228,9.05913542 -2.20503321,12.9004749 0.822715534,18.9392766 C3.82511072,24.9301459 9.66643734,22.8103206 11.5926406,21.7821378 C13.2546332,20.8984272 17.5820854,17.0726151 15.3563098,12.6284081 C13.9024833,9.72546267 11.3270955,10.744194 11.3270955,10.744194 C12.5868611,10.5593815 13.8155916,11.2397906 14.340833,12.4130501 C15.3349594,14.3208929 14.1406734,16.5541356 12.492692,17.4533736 C10.4243753,18.5807966 6.56663112,17.5654408 5.24157404,15.0797093 C3.33138351,11.50031 4.09866228,9.05846032 4.09866228,9.05846032 L4.09866228,9.05913542 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/numbers.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/numbers.jsx
new file mode 100755
index 0000000..0f98a60
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/numbers.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Numbers(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.5267854,22.0919194 C23.788132,22.0919194 24,22.2681331 24,22.4855 L24,22.6064617 C24,22.8238286 23.7881734,23 23.5267854,23 L0.473214594,23 C0.211867974,23 7.10542736e-15,22.8238286 7.10542736e-15,22.6064617 L7.10542736e-15,22.4855 C7.10542736e-15,22.2681331 0.211867974,22.0919194 0.473214594,22.0919194 L23.5267854,22.0919194 Z M11.332473,12.1575222 C11.446809,12.1575222 11.5394967,12.2523006 11.5394967,12.3692158 L11.5394967,20.8974173 C11.5394967,21.0143325 11.446809,21.1091109 11.332473,21.1091109 L6.48219942,21.1091109 C6.36786343,21.1091109 6.2751758,21.0143325 6.2751758,20.8974173 L6.2751758,12.3692158 C6.2751758,12.2523006 6.36786343,12.1575222 6.48219942,12.1575222 L11.332473,12.1575222 Z M5.28580991,17.2381674 C5.37122786,17.2381674 5.44053937,17.3030726 5.44053937,17.3831774 L5.44053937,20.9641432 C5.44053937,21.0442057 5.37122786,21.1091109 5.28580991,21.1091109 L0.330947961,21.1091109 C0.245530015,21.1091109 0.176218507,21.0442057 0.176218507,20.9641432 L0.176218507,17.3831774 C0.176218507,17.3031149 0.245530015,17.2381674 0.330947961,17.2381674 L5.28580991,17.2381674 Z M17.4603722,2 C17.5747321,2 17.6673958,2.09462708 17.6673958,2.21135491 L17.6673958,20.8977984 C17.6673958,20.9538942 17.6455146,21.007674 17.6066889,21.047304 C17.5678633,21.086934 17.5152306,21.109111 17.4603722,21.109111 L12.6100986,21.109111 C12.4957388,21.109111 12.403075,21.0145262 12.403075,20.8977984 L12.403075,2.21135491 C12.403075,2.1552552 12.4249549,2.10147102 12.4637794,2.0618343 C12.5026039,2.02219757 12.5552365,2 12.6100986,2 L17.4603722,2 Z M23.6091808,7.59196981 C23.7119473,7.59196981 23.7952536,7.68054239 23.7952536,7.78977626 L23.7952536,20.9113468 C23.7952536,21.0205807 23.7119473,21.1091109 23.6091808,21.1091109 L18.7170884,21.1091109 C18.6143219,21.1091109 18.5309742,21.0205807 18.5309742,20.9113468 L18.5309742,7.78977626 C18.5309742,7.68054239 18.6142805,7.59196981 18.7170884,7.59196981 L23.6091808,7.59196981 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ob-s-studio.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ob-s-studio.jsx
new file mode 100755
index 0000000..e62cd93
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ob-s-studio.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function OBSStudio(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12,24C5.383,24,0,18.617,0,12S5.383,0,12,0s12,5.383,12,12S18.617,24,12,24z M12,1.109 C5.995,1.109,1.11,5.995,1.11,12C1.11,18.005,5.995,22.89,12,22.89S22.89,18.005,22.89,12C22.89,5.995,18.005,1.109,12,1.109z M6.182,5.99c0.352-1.698,1.503-3.229,3.05-3.996c-0.269,0.273-0.595,0.483-0.844,0.78c-1.02,1.1-1.48,2.692-1.199,4.156 c0.355,2.235,2.455,4.06,4.732,4.028c1.765,0.079,3.485-0.937,4.348-2.468c1.848,0.063,3.645,1.017,4.7,2.548 c0.54,0.799,0.962,1.736,0.991,2.711c-0.342-1.295-1.202-2.446-2.375-3.095c-1.135-0.639-2.529-0.802-3.772-0.425 c-1.56,0.448-2.849,1.723-3.293,3.293c-0.377,1.25-0.216,2.628,0.377,3.772c-0.825,1.429-2.315,2.449-3.932,2.756 c-1.244,0.261-2.551,0.059-3.709-0.464c1.036,0.302,2.161,0.355,3.191-0.011c1.381-0.457,2.522-1.567,3.024-2.935 c0.556-1.49,0.345-3.261-0.591-4.54c-0.7-1.007-1.803-1.717-3.002-1.969c-0.38-0.068-0.764-0.098-1.148-0.134 c-0.611-1.231-0.834-2.66-0.528-3.996L6.182,5.99z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/obsidian.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/obsidian.jsx
new file mode 100755
index 0000000..f581eab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/obsidian.jsx
@@ -0,0 +1,33 @@
1import Icon from "../icon.jsx";
2
3export default function Obsidian(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M15.15 0l4.25 6.49-2.32 14.8L15.72 24l-6.36-2.36L5 10.96l2.9-6.7L15.16 0zM8.46 4.81L5.8 10.97l4.1 10.06 5.56 2.03.94-2 2.25-14.39-3.7-5.66-6.48 3.8z"
10 />
11 <path
12 fillRule="evenodd"
13 clipRule="evenodd"
14 d="M14.88 3.1l4.52 3.3-2.27 14.52L15.72 24 8.79 8.32l6.09-5.22zm.05.92L9.66 8.54l6.07 13.73.73-1.59L18.63 6.5l-3.7-2.47z"
15 />
16 <path
17 fillRule="evenodd"
18 clipRule="evenodd"
19 d="M15.15 0l4.25 6.4-.45.57-4.1-2.98.3-3.99zm.54 1.49l-.14 2.08 2.39 1.73-2.25-3.81z"
20 />
21 <path
22 fillRule="evenodd"
23 clipRule="evenodd"
24 d="M15.15 0l.14 4.07-6.35 5.22-.9-4.92L15.14 0zM8.83 4.76l.6 3.2 5.18-4.28.18-2.36-5.96 3.44z"
25 />
26 <path
27 fillRule="evenodd"
28 clipRule="evenodd"
29 d="M8.79 8.7l.67-.18L15.72 24l-6.25-2.55L8.79 8.7zm.8 1.88l.55 10.32L15 22.7 9.6 10.57z"
30 />
31 </Icon>
32 );
33}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ollama.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ollama.jsx
new file mode 100755
index 0000000..afa63f7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ollama.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Ollama(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M16.361 10.26a.9.9 0 0 0-.558.47l-.072.148l.001.207c0 .193.004.217.059.353c.076.193.152.312.291.448c.24.238.51.3.872.205a.86.86 0 0 0 .517-.436a.75.75 0 0 0 .08-.498c-.064-.453-.33-.782-.724-.897a1.1 1.1 0 0 0-.466 0m-9.203.005c-.305.096-.533.32-.65.639a1.2 1.2 0 0 0-.06.52c.057.309.31.59.598.667c.362.095.632.033.872-.205c.14-.136.215-.255.291-.448c.055-.136.059-.16.059-.353l.001-.207l-.072-.148a.9.9 0 0 0-.565-.472a1 1 0 0 0-.474.007m4.184 2c-.131.071-.223.25-.195.383c.031.143.157.288.353.407c.105.063.112.072.117.136c.004.038-.01.146-.029.243c-.02.094-.036.194-.036.222c.002.074.07.195.143.253c.064.052.076.054.255.059c.164.005.198.001.264-.03c.169-.082.212-.234.15-.525c-.052-.243-.042-.28.087-.355c.137-.08.281-.219.324-.314a.365.365 0 0 0-.175-.48a.4.4 0 0 0-.181-.033c-.126 0-.207.03-.355.124l-.085.053l-.053-.032c-.219-.13-.259-.145-.391-.143a.4.4 0 0 0-.193.032m.39-2.195c-.373.036-.475.05-.654.086a4.5 4.5 0 0 0-.951.328c-.94.46-1.589 1.226-1.787 2.114c-.04.176-.045.234-.045.53c0 .294.005.357.043.524c.264 1.16 1.332 2.017 2.714 2.173c.3.033 1.596.033 1.896 0c1.11-.125 2.064-.727 2.493-1.571c.114-.226.169-.372.22-.602c.039-.167.044-.23.044-.523c0-.297-.005-.355-.045-.531c-.288-1.29-1.539-2.304-3.072-2.497a7 7 0 0 0-.855-.031zm.645.937a3.3 3.3 0 0 1 1.44.514c.223.148.537.458.671.662c.166.251.26.508.303.82c.02.143.01.251-.043.482c-.08.345-.332.705-.672.957a3 3 0 0 1-.689.348c-.382.122-.632.144-1.525.138c-.582-.006-.686-.01-.853-.042q-.856-.16-1.35-.68c-.264-.28-.385-.535-.45-.946c-.03-.192.025-.509.137-.776c.136-.326.488-.73.836-.963c.403-.269.934-.46 1.422-.512c.187-.02.586-.02.773-.002m-5.503-11a1.65 1.65 0 0 0-.683.298C5.617.74 5.173 1.666 4.985 2.819c-.07.436-.119 1.04-.119 1.503c0 .544.064 1.24.155 1.721c.02.107.031.202.023.208l-.187.152a5.3 5.3 0 0 0-.949 1.02a5.5 5.5 0 0 0-.94 2.339a6.6 6.6 0 0 0-.023 1.357c.091.78.325 1.438.727 2.04l.13.195l-.037.064c-.269.452-.498 1.105-.605 1.732c-.084.496-.095.629-.095 1.294c0 .67.009.803.088 1.266c.095.555.288 1.143.503 1.534c.071.128.243.393.264.407c.007.003-.014.067-.046.141a7.4 7.4 0 0 0-.548 1.873a5 5 0 0 0-.071.991c0 .56.031.832.148 1.279L3.42 24h1.478l-.05-.091c-.297-.552-.325-1.575-.068-2.597c.117-.472.25-.819.498-1.296l.148-.29v-.177c0-.165-.003-.184-.057-.293a.9.9 0 0 0-.194-.25a1.7 1.7 0 0 1-.385-.543c-.424-.92-.506-2.286-.208-3.451c.124-.486.329-.918.544-1.154a.8.8 0 0 0 .223-.531c0-.195-.07-.355-.224-.522a3.14 3.14 0 0 1-.817-1.729c-.14-.96.114-2.005.69-2.834c.563-.814 1.353-1.336 2.237-1.475c.199-.033.57-.028.776.01c.226.04.367.028.512-.041c.179-.085.268-.19.374-.431c.093-.215.165-.333.36-.576c.234-.29.46-.489.822-.729c.413-.27.884-.467 1.352-.561c.17-.035.25-.04.569-.04s.398.005.569.04a4.07 4.07 0 0 1 1.914.997c.117.109.398.457.488.602c.034.057.095.177.132.267c.105.241.195.346.374.43c.14.068.286.082.503.045c.343-.058.607-.053.943.016c1.144.23 2.14 1.173 2.581 2.437c.385 1.108.276 2.267-.296 3.153c-.097.15-.193.27-.333.419c-.301.322-.301.722-.001 1.053c.493.539.801 1.866.708 3.036c-.062.772-.26 1.463-.533 1.854a2 2 0 0 1-.224.258a.9.9 0 0 0-.194.25c-.054.109-.057.128-.057.293v.178l.148.29c.248.476.38.823.498 1.295c.253 1.008.231 2.01-.059 2.581a1 1 0 0 0-.044.098c0 .006.329.009.732.009h.73l.02-.074l.036-.134c.019-.076.057-.3.088-.516a9 9 0 0 0 0-1.258c-.11-.875-.295-1.57-.597-2.226c-.032-.074-.053-.138-.046-.141a1.4 1.4 0 0 0 .108-.152c.376-.569.607-1.284.724-2.228c.031-.26.031-1.378 0-1.628c-.083-.645-.182-1.082-.348-1.525a6 6 0 0 0-.329-.7l-.038-.064l.131-.194c.402-.604.636-1.262.727-2.04a6.6 6.6 0 0 0-.024-1.358a5.5 5.5 0 0 0-.939-2.339a5.3 5.3 0 0 0-.95-1.02l-.186-.152a.7.7 0 0 1 .023-.208c.208-1.087.201-2.443-.017-3.503c-.19-.924-.535-1.658-.98-2.082c-.354-.338-.716-.482-1.15-.455c-.996.059-1.8 1.205-2.116 3.01a7 7 0 0 0-.097.726c0 .036-.007.066-.015.066a1 1 0 0 1-.149-.078A4.86 4.86 0 0 0 12 3.03c-.832 0-1.687.243-2.456.698a1 1 0 0 1-.148.078c-.008 0-.015-.03-.015-.066a7 7 0 0 0-.097-.725C8.997 1.392 8.337.319 7.46.048a2 2 0 0 0-.585-.041Zm.293 1.402c.248.197.523.759.682 1.388c.03.113.06.244.069.292c.007.047.026.152.041.233c.067.365.098.76.102 1.24l.002.475l-.12.175l-.118.178h-.278c-.324 0-.646.041-.954.124l-.238.06c-.033.007-.038-.003-.057-.144a8.4 8.4 0 0 1 .016-2.323c.124-.788.413-1.501.696-1.711c.067-.05.079-.049.157.013m9.825-.012c.17.126.358.46.498.888c.28.854.36 2.028.212 3.145c-.019.14-.024.151-.057.144l-.238-.06a3.7 3.7 0 0 0-.954-.124h-.278l-.119-.178l-.119-.175l.002-.474c.004-.669.066-1.19.214-1.772c.157-.623.434-1.185.68-1.382c.078-.062.09-.063.159-.012"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/omni-focus.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/omni-focus.jsx
new file mode 100755
index 0000000..25b414f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/omni-focus.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function OmniFocus(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5.5 0A5.5 5.5 0 0 0 0 5.5v13A5.5 5.5 0 0 0 5.5 24h13a5.5 5.5 0 0 0 5.5-5.5v-13A5.5 5.5 0 0 0 18.5 0h-13ZM9 13.8 16.8 6s.96-.96 2.4 0 1.4 2 1.2 2.4L10.2 19.2c-.2.2-.84.48-1.8 0-.96-.48-3.6-3.4-4.8-4.8-.82-.96-.48-1.32 0-1.8l1.2-1.2c.2-.2.72-.48 1.2 0l2.4 2.4H9Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/one-password.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/one-password.jsx
new file mode 100755
index 0000000..4192696
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/one-password.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function OnePassword(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.9812 0C5.36008 0 0 5.36008 0 11.9812C0 18.6024 5.36008 24 11.9812 24C18.6024 24 24 18.6024 24 11.9812C24 5.35887 18.6024 0 11.9812 0ZM11.9812 2.40376C17.2719 2.40376 21.5962 6.69055 21.5962 11.9812C21.5962 17.2719 17.2719 21.5962 11.9812 21.5962C6.69055 21.5962 2.40376 17.2719 2.40376 11.9812C2.40376 6.69055 6.69055 2.40376 11.9812 2.40376ZM11.9812 3.56808C7.33837 3.56808 3.56808 7.33837 3.56808 11.9812C3.56808 16.6241 7.33837 20.3944 11.9812 20.3944C16.6241 20.3944 20.3944 16.6241 20.3944 11.9812C20.3944 7.33837 16.6241 3.56808 11.9812 3.56808ZM10.0657 7.17371H13.8967V11.9812L12.9577 12.9202L13.8967 13.8967V16.7512H10.0657V11.9812L11.0423 11.0047L10.0657 10.0657V7.17371Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-book.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-book.jsx
new file mode 100755
index 0000000..2381bbc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-book.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function OpenBook(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1 3a1 1 0 0 1 1-1h6a5 5 0 0 1 5 5v14a1 1 0 1 1-2 0 2 2 0 0 0-2-2H2a1 1 0 0 1-1-1V3Zm10 14.536V7a3 3 0 0 0-3-3H3v13h6a4 4 0 0 1 2 .536Z" />
7 <path d="M12.464 3.464A5 5 0 0 1 16 2h6a1 1 0 0 1 1 1v15a1 1 0 0 1-1 1h-7a2 2 0 0 0-2 2 1 1 0 1 1-2 0V7a5 5 0 0 1 1.464-3.536ZM13 17.536A4 4 0 0 1 15 17h6V4h-5a3 3 0 0 0-3 3v10.536Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-claw.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-claw.jsx
new file mode 100755
index 0000000..d314638
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/open-claw.jsx
@@ -0,0 +1,16 @@
1import Icon from "../icon.jsx";
2
3export default function OpenClaw(props) {
4 return (
5 <Icon {...props}>
6 <path d="M9.046 7.104a.527.527 0 110 1.055.527.527 0 010-1.055z" />
7 <path d="M15.376 7.104a.528.528 0 110 1.056.528.528 0 010-1.056z" />
8 <path
9 clipRule="evenodd"
10 d="M16.877 1.912c.58-.27 1.14-.323 1.616-.037a.317.317 0 01-.326.542c-.227-.136-.547-.153-1.022.068-.352.165-.765.45-1.234.866 2.683 1.17 4.4 3.5 5.148 5.921a6.421 6.421 0 00-.704.184c-.578.016-1.174.204-1.502.735-.338.55-.268 1.276.072 2.069l.005.012.007.014c.523 1.045 1.318 1.91 2.2 2.284-.912 3.274-3.44 6.144-5.972 6.988v2.109h-2.11v-2.11c-1.043.417-2.086.01-2.11 0v2.11h-2.11v-2.11c-2.531-.843-5.061-3.713-5.973-6.987.882-.373 1.678-1.238 2.2-2.284l.007-.014.006-.012c.34-.793.41-1.518.071-2.069-.327-.531-.923-.719-1.503-.735a6.409 6.409 0 00-.704-.183c.749-2.421 2.466-4.751 5.149-5.922-.47-.416-.88-.701-1.234-.866-.474-.221-.794-.204-1.021-.068a.318.318 0 01-.435-.109.317.317 0 01.109-.433c.476-.286 1.036-.233 1.615.037.49.229 1.031.628 1.621 1.182A9.924 9.924 0 0112 2.568c1.199 0 2.284.19 3.256.526.59-.554 1.13-.953 1.62-1.182zM8.835 6.577a1.266 1.266 0 100 2.532 1.266 1.266 0 000-2.532zm6.33 0a1.267 1.267 0 100 2.533 1.267 1.267 0 000-2.533z"
11 />
12 <path d="M.395 13.118c-.966-1.932-.163-3.863 2.41-3.365v-.001l.05.01c.084.018.17.038.26.06.033.009.067.017.1.027.084.022.168.048.255.076l.09.027c.528 0 .95.158 1.16.501.212.343.212.87-.105 1.61-.085.17-.178.333-.276.489l-.01.017a4.967 4.967 0 01-.62.791l-.019.02c-1.092 1.117-2.496 1.336-3.295-.262z" />
13 <path d="M21.193 9.753c2.574-.5 3.378 1.433 2.411 3.365-.58 1.159-1.476 1.361-2.342.96l-.011-.005a2.419 2.419 0 01-.114-.056l-.019-.01a2.751 2.751 0 01-.115-.067l-.023-.014c-.035-.022-.071-.044-.106-.068l-.05-.035c-.55-.388-1.062-1.007-1.44-1.76-.276-.647-.311-1.132-.174-1.472.176-.439.636-.639 1.23-.639.032-.011.066-.02.099-.03.08-.026.16-.05.238-.072l.117-.03a5.502 5.502 0 01.3-.067z" />
14 </Icon>
15 );
16}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/opencode.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/opencode.jsx
new file mode 100755
index 0000000..0e407e0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/opencode.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Opencode(props) {
4 return (
5 <Icon {...props}>
6 <path d="M16 6H8v12h8V6zm4 16H4V2h16v20z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/orb-stack.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/orb-stack.jsx
new file mode 100755
index 0000000..674c20d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/orb-stack.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function OrbStack(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6.348 0h8.511c1.45.04 2.907-.05 4.356.094 1.105.11 2.191.535 3.02 1.289a4.941 4.941 0 0 1 1.453 2.273c.269.856.292 1.758.312 2.649v11.46c-.023.801-.043 1.61-.258 2.387-.25.993-.82 1.891-1.594 2.559a5.151 5.151 0 0 1-2.261 1.102c-.696.156-1.418.164-2.13.187H6.255c-.89-.027-1.8-.047-2.652-.332a5 5 0 0 1-3-2.61c-.465-.949-.563-2.023-.579-3.066-.03-1.168.008-2.336-.023-3.504V7.16c.035-1.137-.023-2.3.297-3.41A5.017 5.017 0 0 1 3.016.574C4.05.07 5.219.047 6.348 0m4.539 3.324a8.536 8.536 0 0 0-5.102 2.461C4.34 7.2 3.434 9.141 3.235 11.152c-.016 1.036-.083 2.09.21 3.094.38 1.465 1.13 2.852 2.223 3.906 1.324 1.418 3.168 2.325 5.09 2.578 1.527.145 3.129.032 4.531-.64 1.168-.77 2.137-1.809 2.887-2.98.258-.485.605-.919.742-1.458.008.508-.438.844-.54 1.317a12.396 12.396 0 0 0 1.61-4.41c-.008-.473.125-.934.106-1.407 0-.437.156-.867.07-1.308a8.611 8.611 0 0 0-.777-2.176c-1.594-3.004-5.145-4.766-8.5-4.344Zm0 0" />
7 <path
8 fillOpacity=".7"
9 fillRule="evenodd"
10 d="M6.977 5.352c.343-.223.707-.543 1.148-.422-.703.578-1.21 1.355-1.836 2.011-.71.762-1.351 1.59-1.965 2.43-.238.36-.27.844-.625 1.121-.11-.765.332-1.433.543-2.133.551-.996 1.235-1.933 2.102-2.671.176-.118.36-.235.515-.38.016-.113.098-.253.235-.23-.032.094-.078.18-.117.274ZM13.633 6.063c.738-.055 1.539.019 2.172.445.238.133.515.219.703.43.332.351.71.667.937 1.101.242.445.528.871.703 1.352.207.504.293 1.046.364 1.582-.016.566.074 1.152-.145 1.691-.172.625-.656 1.176-1.285 1.352-.344-.133-.703-.34-.855-.696-.145-.308-.356-.586-.508-.89a17.213 17.213 0 0 0-1.192-2.192 32.978 32.978 0 0 0-1.054-1.75c-.348-.597-.641-1.261-.582-1.968.203-.207.43-.442.742-.457Zm0 0"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pages.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pages.jsx
new file mode 100755
index 0000000..1e83114
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pages.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Pages(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1.64911375,20.3170678 C2.13834893,19.9967724 2.55830887,19.7164073 2.58223208,19.6939395 C2.62025221,19.658347 2.57123421,19.5995081 2.19878053,19.2334615 C1.96393253,19.0026293 1.74979529,18.8138036 1.7229242,18.8138036 C1.67504,18.8138036 0.518902984,20.4936215 0.45718641,20.6528238 C0.399816072,20.8008663 0.517013316,20.941605 0.674762847,20.9141321 C0.721399866,20.9060125 1.15987856,20.6373262 1.64911375,20.3170678 Z M3.32404036,19.2309033 C4.11584928,18.7123279 4.58705703,18.3420547 5.70154575,17.3626677 C7.34041749,15.9224319 11.056942,12.4481216 11.056942,12.3563226 C11.056942,12.2979287 9.22607995,10.5007668 9.16655539,10.5007668 C9.09191348,10.5007668 6.16746243,13.4932806 4.69321861,15.078148 C3.70537548,16.1400652 3.21787878,16.6882268 2.86575795,17.1328736 C2.43699215,17.6743616 1.87432444,18.48309 1.87432444,18.5578713 C1.87432444,18.6131138 2.794782,19.5089697 2.85154764,19.5089697 C2.87788962,19.5089697 3.09047733,19.3838398 3.32404036,19.2309033 Z M13.0529233,12.6905585 C13.1355018,12.6095484 13.1533025,12.5702855 13.1533025,12.46944 C13.1533025,12.4019997 13.1379584,12.2964086 13.1191373,12.2348261 C13.0729538,12.0837063 13.1177012,11.9449697 13.2840298,11.7233322 C13.4601091,11.4886812 13.6415551,11.2972974 14.912395,10.0057715 C16.6091284,8.28146303 17.6287557,7.21201955 18.0973179,6.66526681 C18.3437685,6.37770904 18.4515552,6.13827531 18.4504214,5.88082288 C18.4495521,5.67913203 18.4450925,5.66552531 18.2769498,5.35060581 C18.2117563,5.22855319 18.2331473,5.11087548 18.3516295,4.93947533 C18.7854218,4.31193502 18.8056791,3.7284775 18.4083952,3.3057053 C18.0572948,2.9320211 17.4634475,2.89794869 16.9115509,3.21987547 C16.7329016,3.32405769 16.001411,3.94651866 15.1321256,4.73400278 C13.2162663,6.46958219 9.37396541,10.1854395 9.37396541,10.3026723 C9.37396541,10.3569879 11.2091737,12.151814 11.2646544,12.151814 C11.289787,12.151814 12.0751332,11.3990697 13.0098767,10.4790776 C14.7676464,8.74902246 15.5883672,7.91886441 16.5960519,6.85164546 C17.4642034,5.93224663 17.4712329,5.92535058 17.5526777,5.91719396 C17.6132604,5.91111358 17.628151,5.92386756 17.6357097,5.98804529 C17.6478414,6.09141185 17.6189294,6.13957296 17.3648446,6.43877243 C16.8782172,7.01188588 16.0148276,7.91004044 14.1143123,9.82035679 C13.4802152,10.4577221 12.8913189,11.0703581 12.8056413,11.1817329 C12.6075662,11.4393337 12.4300508,11.783135 12.3839051,11.9985067 C12.2965268,12.406078 12.5225689,12.7862133 12.8536011,12.7884427 C12.9272604,12.7888457 12.978168,12.7638568 13.0529233,12.6905585 L13.0529233,12.6905585 Z M0.372037945,21.1947567 C0.165723932,21.1947567 0,21.3748325 0,21.597953 C0,21.8210735 0.165723932,22 0.372037945,22 L23.9055166,22 L23.9308381,21.8119529 L23.9645876,21.602365 L23.9882085,21.4027133 L24,21.1947938 L0.372037945,21.1947938 L0.372037945,21.1947567 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/parallels.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/parallels.jsx
new file mode 100755
index 0000000..cf4063f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/parallels.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Parallels(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M8.002 0C6.902 0 6 .882 6 1.957v20.086C6 23.119 6.901 24 8.002 24c1.1 0 2.003-.881 2.003-1.957V1.957C10.005.882 9.103 0 8.002 0Zm7.996 0c-1.101 0-2.003.882-2.003 1.957v20.086c0 1.076.902 1.957 2.003 1.957 1.1 0 2.002-.881 2.002-1.957V1.957C18 .882 17.098 0 15.998 0Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/paused.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/paused.jsx
new file mode 100755
index 0000000..fe8ed21
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/paused.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Paused(props) {
4 return (
5 <Icon {...props}>
6 <path d="M4.8 20V4l14.4 8-14.4 8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pdf.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pdf.jsx
new file mode 100755
index 0000000..1fc252e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pdf.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function PDF(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21.47 6.8H2.53c-1.16 0-2.1.94-2.1 2.1v8.44c0 1.17.94 2.11 2.1 2.11h18.94c1.16 0 2.1-.94 2.1-2.1V8.9c0-1.17-.94-2.11-2.1-2.11zM5.99 14.22H5.2v1.62a.7.7 0 01-1.4 0L3.8 10.5a.7.7 0 01.7-.7h1.49c1.23 0 2.24.99 2.24 2.2 0 1.23-1 2.22-2.24 2.22zm6.03 2.16h-1.5a.7.7 0 01-.71-.7L9.8 10.5a.7.7 0 01.7-.7h1.47c1.67 0 2.8 1.32 2.8 3.3 0 1.87-1.16 3.25-2.75 3.28zm7.2-4.04a.7.7 0 010 1.41h-1.27v2a.7.7 0 01-1.4 0v-5.3c0-.4.31-.7.7-.7h2.15a.7.7 0 010 1.4h-1.45v1.2h1.28z" />
7 <path d="M11.97 11.2h-.77l.01 3.78H12c.94-.03 1.36-.96 1.36-1.89 0-.44-.1-1.89-1.4-1.89zM5.99 11.2H5.2a401.72 401.72 0 010 1.62h.78c.45 0 .83-.38.83-.81 0-.44-.38-.8-.83-.8zM20.74 5.4a3.5 3.5 0 00-.75-1.22L17.07 1.1C16.4.4 15.47 0 14.52 0H5.16C3.99 0 3.05.95 3.05 2.1v3.3h17.69zM3.05 20.86v1.03c0 1.16.94 2.11 2.1 2.11h13.7c1.16 0 2.1-.95 2.1-2.1v-1.04H3.05z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/perplexity.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/perplexity.jsx
new file mode 100755
index 0000000..9e095a0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/perplexity.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Perplexity(props) {
4 return (
5 <Icon {...props}>
6 <path d="M19.785 0v7.272H22.5V17.62h-2.935V24l-7.037-6.194v6.145h-1.091v-6.152L4.392 24v-6.465H1.5V7.188h2.884V0l7.053 6.494V.19h1.09v6.49L19.786 0zm-7.257 9.044v7.319l5.946 5.234V14.44l-5.946-5.397zm-1.099-.08l-5.946 5.398v7.235l5.946-5.234V8.965zm8.136 7.58h1.844V8.349H13.46l6.105 5.54v2.655zm-8.982-8.28H2.59v8.195h1.8v-2.576l6.192-5.62zM5.475 2.476v4.71h5.115l-5.115-4.71zm13.219 0l-5.115 4.71h5.115v-4.71z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/php-storm.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/php-storm.jsx
new file mode 100755
index 0000000..628771f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/php-storm.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function PHPStorm(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M.2998.896h24v24h-24v-24Zm3 19.1999h9.5999v1.8h-9.6v-1.8Zm3.861-16.2048H3.2954l-.0006.0006v9.0042h1.7562V9.4933h2.058c.6474 0 1.2132-.1164 1.698-.3504.4842-.234.858-.5628 1.122-.9876.2634-.4242.3954-.9264.3954-1.4796s-.1296-1.0392-.3888-1.4592c-.2598-.4206-.6282-.7464-1.107-.978-.4776-.2316-1.0338-.3474-1.668-.3474ZM8.3307 7.4c-.12.2034-.2899.36-.5113.4692-.2208.1092-.4788.1644-.7746.1644H5.0511v-2.682H7.045c.2958 0 .5538.0546.7746.1638.2208.1092.3912.2634.5112.4632.12.1992.18.4302.18.7044s-.06.513-.18.717Zm3.1289 4.3044c.285.4242.6792.7542 1.1832.99v.0006c.5028.2358 1.0812.354 1.7328.354.6522 0 1.2312-.12 1.737-.36.5058-.2406.8988-.5718 1.1802-.9936.2802-.4224.4206-.8994.4206-1.431 0-.4326-.0966-.8328-.2892-1.1994a2.6693 2.6693 0 0 0-.807-.9264c-.345-.2502-.7386-.4212-1.1802-.5112l-1.5306-.3342c-.279-.069-.4986-.1842-.6594-.3474-.1608-.1626-.2412-.3684-.2412-.6168a.9774.9774 0 0 1 .1734-.576 1.1416 1.1416 0 0 1 .486-.3858c.2076-.0924.4488-.138.7236-.138a1.7487 1.7487 0 0 1 .7296.144c.1992.0858.3699.2264.492.4056.1164.1734.174.3696.174.588h1.7556c-.0042-.5142-.1404-.9702-.4086-1.3662-.2676-.3966-.642-.7062-1.122-.9294-.48-.2232-1.035-.3348-1.6398-.3348s-1.1448.1146-1.6212.3438c-.4758.2292-.8466.549-1.1124.9582-.2658.4098-.399.8718-.399 1.386 0 .4248.0882.8064.264 1.1448.1755.3385.4289.6306.7392.852.3174.2298.6906.3918 1.1196.4854l1.5882.354c.3042.0732.543.204.717.3924.1734.189.2604.4266.2604.714 0 .2316-.0618.4374-.189.6174-.1272.18-.3048.3204-.534.4212-.2298.1008-.483.1506-.801.1506-.3174 0-.5982-.0558-.8424-.1668-.2442-.1116-.435-.2658-.5724-.4632-.1374-.1974-.2058-.4266-.2058-.6882h-1.7622c.009.5532.156 1.0416.441 1.4664Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pihole.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pihole.jsx
new file mode 100755
index 0000000..622efe3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pihole.jsx
@@ -0,0 +1,31 @@
1import Icon from "../icon.jsx";
2
3export default function Pihole(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M15.2099343,22.9818015 C16.2502717,21.9824223 16.7499613,20.7536773 16.7499613,19.1645005 C16.7499613,18.2716125 16.5205956,17.4196827 15.8652649,15.8632724 C14.9887602,13.7989809 14.8413108,13.2910997 14.8413108,12.2671456 C14.8331192,11.5298986 14.8658857,11.3087245 15.0624849,10.7516935 C15.4884498,9.52294853 16.2420801,8.61367727 17.2824174,8.09760439 C18.2899883,7.59791478 19.4532002,7.48323192 20.550879,7.76174744 C22.2301638,8.18771236 23.3360342,9.25262464 23.8521071,10.9319094 C24.0814728,11.6691564 24.0405146,13.0043925 23.7538075,13.9464303 C22.7871948,17.1985086 19.6088412,20.761869 15.7260072,22.949035 C15.2754674,23.2029756 14.8740774,23.4077664 14.8331192,23.4077664 C14.792161,23.4077664 14.9559937,23.2111672 15.2099343,22.9818015 Z"
10 />
11 <path
12 fillRule="evenodd"
13 clipRule="evenodd"
14 d="M0.38307863,15.9369971 C1.42341602,14.9376179 1.92310563,13.708873 1.92310563,12.1196962 C1.92310563,11.2268082 1.6937399,10.3748784 1.03840927,8.81846809 C0.161904539,6.75417659 0.014455146,6.24629534 0.014455146,5.22234122 C0.006263513,4.48509425 0.0390300449,4.26392016 0.235629236,3.70688912 C0.661594151,2.47814418 1.41522438,1.56887292 2.45556177,1.05280004 C3.46313263,0.553110428 4.62634451,0.438427567 5.72402333,0.716943088 C7.40330808,1.142908 8.50917854,2.20782029 9.02525141,3.88710505 C9.25461714,4.62435201 9.21365897,5.95958819 8.92695182,6.90162598 C7.96033913,10.1537043 4.78198553,13.7170646 0.899151507,15.9042306 C0.448611693,16.1581712 0.0472216778,16.3629621 0.006263513,16.3629621 C-0.0346946518,16.3629621 0.129138008,16.1663629 0.38307863,15.9369971 Z"
15 transform="rotate(-180 4.587 8.466)"
16 />
17 <path
18 fillRule="evenodd"
19 clipRule="evenodd"
20 d="M4.36782952,26.8846361 C5.40816691,25.8852568 5.90785652,24.6565119 5.90785652,23.0673351 C5.90785652,22.1744471 5.6784908,21.3225173 5.02316016,19.766107 C4.14665543,17.7018155 3.99920604,17.1939343 3.99920604,16.1699801 C3.99101441,15.4327332 4.02378094,15.2115591 4.22038013,14.654528 C4.64634504,13.4257831 5.39997528,12.5165118 6.44031267,12.000439 C7.44788352,11.5007493 8.6110954,11.3860665 9.70877422,11.664582 C11.388059,12.0905469 12.4939294,13.1554592 13.0100023,14.834744 C13.239368,15.5719909 13.1984099,16.9072271 12.9117027,17.8492649 C11.94509,21.1013432 8.76673643,24.6647035 4.8839024,26.8518695 C4.43336259,27.1058102 4.03197257,27.310601 3.99101441,27.310601 C3.95005624,27.310601 4.1138889,27.1140018 4.36782952,26.8846361 Z"
21 transform="rotate(90 8.571 19.413)"
22 />
23 <path
24 fillRule="evenodd"
25 clipRule="evenodd"
26 d="M11.2488012,12.0577804 C12.2891386,11.0584012 12.7888282,9.82965622 12.7888282,8.24047942 C12.7888282,7.34759143 12.5594625,6.4956616 11.9041319,4.93925134 C11.0276271,2.87495983 10.8801777,2.36707859 10.8801777,1.34312446 C10.8719861,0.605877497 10.9047526,0.384703407 11.1013518,-0.172327635 C11.5273167,-1.40107258 12.280947,-2.31034384 13.3212844,-2.82641672 C14.3288552,-3.32610633 15.4920671,-3.44078919 16.5897459,-3.16227367 C18.2690307,-2.73630875 19.3749011,-1.67139647 19.890974,0.00788829019 C20.1203397,0.745135257 20.0793816,2.08037143 19.7926744,3.02240922 C18.8260617,6.27448751 15.6477081,9.83784785 11.7648741,12.0250139 C11.3143343,12.2789545 10.9129443,12.4837453 10.8719861,12.4837453 C10.8310279,12.4837453 10.9948606,12.2871461 11.2488012,12.0577804 Z"
27 transform="rotate(-90 15.452 4.587)"
28 />
29 </Icon>
30 );
31}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pine.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pine.jsx
new file mode 100755
index 0000000..0e5e2fd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pine.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Pine(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M2.4 0A2.4 2.4 0 000 2.4v19.2A2.4 2.4 0 002.4 24h19.2a2.4 2.4 0 002.4-2.4V2.4A2.4 2.4 0 0021.6 0H2.4zm9.39 1.92l-3.32 6.6h.5l-1.19 2.33h.7l-1.35 2.56h.65l-1.21 2.27h.56L5.88 18.4h5.35v3.68h1.44V18.4h5.45l-1.31-2.72h.65l-1.21-2.27h.56l-1.35-2.56h.6l-1.19-2.33h.36l-3.44-6.6z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pins.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pins.jsx
new file mode 100755
index 0000000..5b63d82
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pins.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Pins(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11 17h2v5l-2 2v-7zm3.571-12c0-2.903 2.36-3.089 2.429-5h-10c.068 1.911 2.429 2.097 2.429 5 0 3.771-3.429 3.291-3.429 10h12c0-6.709-3.429-6.229-3.429-10z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/playing.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/playing.jsx
new file mode 100755
index 0000000..cc96548
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/playing.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Playing(props) {
4 return (
5 <Icon {...props}>
6 <path d="M5.7 4h3.8c.5 0 .9.4.9.9v14.2c0 .5-.4.9-1 .9H5.8a1 1 0 01-.9-.9V4.9c0-.5.4-.9 1-.9zm8.8 0h3.8c.5 0 .9.4.9.9v14.2c0 .5-.4.9-1 .9h-3.7a1 1 0 01-.9-.9V4.9c0-.5.4-.9 1-.9z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/plex.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/plex.jsx
new file mode 100755
index 0000000..ab8a1d0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/plex.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Plex(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M3.6 0h16.8c2 0 3.6 1.6 3.6 3.6v16.8c0 2-1.6 3.6-3.6 3.6H3.6c-2 0-3.6-1.6-3.6-3.6V3.6C0 1.6 1.6 0 3.6 0Zm3.3 3.3H12l5 8.7-5 8.7H7l5-8.7-5-8.7Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/podcasts.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/podcasts.jsx
new file mode 100755
index 0000000..767f73e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/podcasts.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Podcasts(props) {
4 return (
5 <Icon {...props}>
6 <path d="M14.4123403,14.6048442 C13.9466555,14.1135073 13.1287473,13.7985287 12.163216,13.7985287 C11.1975613,13.7985287 10.3796531,14.1135073 9.91396827,14.6048442 C9.67101302,14.8612421 9.54250572,15.1240531 9.50205429,15.4984755 C9.42361797,16.2235181 9.46764591,16.8478022 9.55261858,17.8458919 C9.63352145,18.7969939 9.78718756,20.0652943 9.98771814,21.357027 C10.1304081,22.2763105 10.246336,22.7724572 10.3519044,23.1277638 C10.523083,23.7035801 11.1627829,24.2071265 12.163216,24.2071265 C13.1635256,24.2071265 13.8032256,23.7034568 13.9744042,23.1277638 C14.0799726,22.7724572 14.1959005,22.2763105 14.3385904,21.357027 C14.539121,20.0652943 14.6927871,18.7969939 14.77369,17.8458919 C14.8586627,16.8476788 14.9026906,16.2233948 14.8242543,15.4984755 C14.7838029,15.1241764 14.6552956,14.8612421 14.4123403,14.6048442 Z M9.62587514,10.2300463 C9.62587514,11.6326505 10.7629551,12.7697304 12.1655592,12.7697304 C13.5682866,12.7697304 14.7053665,11.6326505 14.7053665,10.2300463 C14.7053665,8.8273189 13.5682866,7.69023898 12.1655592,7.69023898 C10.7629551,7.69023898 9.62587514,8.8273189 9.62587514,10.2300463 Z M12.1341107,0.207171687 C6.19428633,0.224113029 1.32716496,5.04289001 1.25366175,10.9823443 C1.19397122,15.7937217 4.26532028,19.9094083 8.55403549,21.4179508 C8.65812393,21.4545791 8.76381563,21.3681265 8.74741307,21.2589816 C8.69117571,20.8854225 8.63814487,20.5100135 8.58943049,20.1408941 C8.57216464,20.0104136 8.48904187,19.8979389 8.36855087,19.845278 C4.9787701,18.3643609 2.61174462,14.9647139 2.6497295,11.0267423 C2.69955383,5.85882501 6.9195756,1.64570958 12.0874928,1.60390155 C17.3707213,1.56123022 21.6823755,5.84661559 21.6823755,11.1201012 C21.6823755,15.0186081 19.3257095,18.3765703 15.9623208,19.845648 C15.8418298,19.8983089 15.7592004,20.0111536 15.7420578,20.1415108 C15.6933435,20.5105068 15.6403126,20.8857925 15.5841986,21.2589816 C15.5676727,21.3681265 15.6733644,21.4545791 15.7774528,21.4180741 C20.0252233,19.923961 23.0786899,15.8722813 23.0786899,11.1202245 C23.0784432,5.09209769 18.1659373,0.1899513 12.1341107,0.207171687 Z M11.9369099,5.21369865 C15.3041217,5.08334144 18.0849111,7.78470788 18.0849111,11.123431 C18.0849111,12.8214046 17.3655416,14.3543659 16.2157589,15.4339752 C16.1182068,15.5254843 16.0657926,15.6554715 16.0733156,15.7890352 C16.0962545,16.1951528 16.0878683,16.5898009 16.0608595,17.0355067 C16.0535832,17.1542711 16.1867769,17.2301175 16.285069,17.1631507 C18.2131718,15.8455192 19.4813489,13.62994 19.4813489,11.123431 C19.4813489,6.99639824 16.043717,3.65705844 11.8815358,3.81837086 C8.01349088,3.96833715 4.91019999,7.15746401 4.86062232,11.0282222 C4.82806384,13.5739493 6.10401058,15.82924 8.05690217,17.1633973 C8.15494757,17.2303642 8.28777133,17.1543944 8.280495,17.0357533 C8.25336295,16.5898009 8.2451,16.1951528 8.2679156,15.7890352 C8.27543858,15.6555948 8.2231477,15.5256076 8.12584227,15.4342219 C6.9401713,14.3210675 6.2120455,12.7258258 6.25841666,10.9647085 C6.34005949,7.86548742 8.83879878,5.33369635 11.9369099,5.21369865 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pomodone.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pomodone.jsx
new file mode 100755
index 0000000..48c503b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/pomodone.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Pomodone(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0,12.36v-.75a.61.61,0,0,0,0-.13c0-.34,0-.68.08-1A11.16,11.16,0,0,1,.68,8,11.92,11.92,0,0,1,6.57,1.3,11.61,11.61,0,0,1,12,0a13,13,0,0,1,1.39.09,10.2,10.2,0,0,1,2.18.46A12,12,0,0,1,24,12a7,7,0,0,1,0,.92,16.36,16.36,0,0,1-.24,1.69,11.74,11.74,0,0,1-3.9,6.48A11.71,11.71,0,0,1,12.5,24l-.12,0h-.75l-.1,0-.47,0c-.56-.08-1.12-.12-1.67-.25a11.71,11.71,0,0,1-6.49-3.9A11.71,11.71,0,0,1,0,12.48.53.53,0,0,0,0,12.36ZM18.92,12V6.27a1.18,1.18,0,0,0-1.2-1.21H6.28a1.18,1.18,0,0,0-1.2,1.2V17.71a1.18,1.18,0,0,0,1.2,1.2H17.72a1.18,1.18,0,0,0,1.2-1.21Z" />
7 <path d="M17.17,17.15H6.84V6.82H17.17Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/postman.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/postman.jsx
new file mode 100755
index 0000000..79d92e1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/postman.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Postman(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M23.9 13.52A12 12 0 1 0 .1 10.47a12 12 0 0 0 23.8 3.05Zm-15.12-.48 1.81-.39-.88.89a.12.12 0 0 0-.03.04l-3.79 3.79a.12.12 0 0 0-.06.03L4.8 18.43c-.06.05-.08.12-.1.2 0 .17.11.33.3.34l2.45.17c.05 0 .09-.03.11-.07a.1.1 0 0 0 0-.1l.04-.02a.38.38 0 0 0 .18-.41l-.2-.85a24.2 24.2 0 0 0 5.14-3.3l.08-.07a.11.11 0 0 0 .04-.04c2.6-2.46 4.1-4.14 4.13-5.47 0-.21-.04-.42-.12-.61a2.06 2.06 0 0 0 1.83-.11l.03-.01.03-.02c.15-.08.28-.19.4-.3.8-.82.8-2.12-.01-2.92l-.04-.03a2.06 2.06 0 0 0-3.5 1.5c0 .3.07.58.2.84-.85-.45-2 .06-6.05 4.1v.02l-.02.01L8.5 12.5a.33.33 0 0 0-.1.23c0 .18.13.33.31.33l.04-.01h.03Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/proton-mail.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/proton-mail.jsx
new file mode 100755
index 0000000..61cc2ee
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/proton-mail.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function ProtonMail(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="m15.24 8.998l3.656-3.073v15.81H2.482C1.11 21.735 0 20.609 0 19.223V6.944l7.58 6.38a2.186 2.186 0 0 0 2.871-.042l4.792-4.284h-.003zm-5.456 3.538l1.809-1.616a2.438 2.438 0 0 1-1.178-.533L.905 2.395A.552.552 0 0 0 0 2.826v2.811l8.226 6.923a1.186 1.186 0 0 0 1.558-.024zM23.871 2.463a.551.551 0 0 0-.776-.068l-3.199 2.688v16.653h1.623c1.371 0 2.481-1.127 2.481-2.513V2.824a.551.551 0 0 0-.129-.36z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/py-charm.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/py-charm.jsx
new file mode 100755
index 0000000..8845a8e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/py-charm.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function PyCharm(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm11.2797 19.4998h-9v1.5h9v-1.5Zm-4.98-16.38h-4.08v9.9h2.16v-3h1.68c2.22 0 4.02-1.2 4.02-3.48 0-2.04-1.38-3.42-3.78-3.42Zm-.24 2.04c1.14 0 1.8.54 1.8 1.5 0 .84-.561 1.56-1.74 1.56h-1.74v-3.06h1.68Zm6.3376-.6824a5.0492 5.0492 0 0 0-1.4776 3.6824 5.1002 5.1002 0 0 0 5.1 5.16c1.92 0 3.06-.72 4.08-1.8l-1.38-1.38c-.78.66-1.5 1.14-2.64 1.14-1.68 0-2.88-1.44-2.88-3.12 0-1.74 1.2-3.12 2.88-3.12.96 0 1.74.42 2.52 1.14l1.38-1.62c-.9-.96-2.04-1.56-3.9-1.56a5.049 5.049 0 0 0-3.6824 1.4776Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/quip.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/quip.jsx
new file mode 100755
index 0000000..b489fb4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/quip.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Quip(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21 21.75h-9A9.748 9.748 0 012.25 12 9.748 9.748 0 0112 2.25 9.748 9.748 0 0121.75 12v9a.75.75 0 01-.75.75zm-9-18A8.252 8.252 0 003.75 12 8.252 8.252 0 0012 20.25h8.25V12A8.252 8.252 0 0012 3.75zm0 0" />
7 <path d="M15.375 9.375h-6.75a.75.75 0 010-1.5h6.75a.75.75 0 010 1.5zm0 0M15.375 16.125h-6.75a.75.75 0 010-1.5h6.75a.75.75 0 010 1.5zm0 0M17.625 12.75H6.375a.75.75 0 010-1.5h11.25a.75.75 0 010 1.5zm0 0" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/qute-browser.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/qute-browser.jsx
new file mode 100755
index 0000000..9e5a4a8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/qute-browser.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function QuteBrowser(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M24 12a12 12 0 11-24 0 12 12 0 0124 0zM12.32 4.81l3.16-1.89v4.83l-3.16 1.89V4.8zM1.56 10.4c.02-6.22 5.52-7.06 8.42-7.04.89 0 1.53.09 1.7.12v6.71l-3.16 1.87V6.17c-1.38-.08-3.96 1-3.96 4.48 0 3.49 2.37 3 3.64 2.26 1.3-.75 2.65-1.56 4.02-2.38a723 723 0 013.31-1.98c1.29-.76 6.94-2.48 6.91 5.07-.02 6.22-5.52 7.06-8.42 7.04-.89 0-1.53-.09-1.7-.12v-6.71l3.16-1.87v5.88c1.38.07 3.96-1 3.96-4.49 0-3.48-2.38-3-3.64-2.25-1.3.75-2.65 1.56-4.02 2.38l-3.31 1.97c-1.29.77-6.94 2.49-6.91-5.06zm6.96 5.87l3.16-1.9v4.84l-3.16 1.88v-4.82z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/radar.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/radar.jsx
new file mode 100755
index 0000000..3dcbaf1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/radar.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function Radar(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.2308 10.3874a2.3999 2.3999 0 0 1 2.5472 1.1544h8.7234a1.2006 1.2006 0 0 1 1.2003 1.2006 12.0078 12.0078 0 0 1-3.5155 8.4895 12.0009 12.0009 0 0 1-8.487 3.5164 1.2 1.2 0 0 1-1.2003-1.2006v-8.7258a2.4003 2.4003 0 0 1-1.0175-1.1606 2.4017 2.4017 0 0 1 .5203-2.6168 2.4005 2.4005 0 0 1 1.2291-.6571Zm9.9951 3.5556h-8.3265v8.3288a9.6012 9.6012 0 0 0 5.5894-2.7378 9.6064 9.6064 0 0 0 2.7371-5.591Z" />
7 <path d="M10.1809 5.9936a7.2 7.2 0 0 1 8.2794 2.4267c.3978.5304.2903 1.283-.24 1.6808-.5303.3978-1.2826.2903-1.6804-.2401a4.8015 4.8015 0 0 0-3.5004-1.9089 4.8002 4.8002 0 0 0-3.7352 1.3945 4.8023 4.8023 0 0 0-1.3941 3.7362 4.8037 4.8037 0 0 0 1.9083 3.5015c.5303.3978.6378 1.1503.2401 1.6808-.3978.5305-1.15.638-1.6804.2401a7.2021 7.2021 0 0 1-2.002-2.3148 7.2053 7.2053 0 0 1 1.2307-8.5417 7.2014 7.2014 0 0 1 2.574-1.655Z" />
8 <path d="M9.3639 1.2226a11.9993 11.9993 0 0 1 11.3073 2.552 12.0056 12.0056 0 0 1 3.3444 4.9646c.2217.6248-.105 1.3112-.7297 1.5329-.6248.2218-1.3109-.1051-1.5326-.73a9.6041 9.6041 0 0 0-2.6755-3.9715 9.6009 9.6009 0 0 0-9.0458-2.0417 9.6014 9.6014 0 0 0-4.1213 2.4376A9.6054 9.6054 0 0 0 3.34 14.8788a9.6055 9.6055 0 0 0 2.1898 4.2589 9.602 9.602 0 0 0 3.9735 2.6718c.625.221.9525.907.7315 1.5321-.221.6252-.9068.9527-1.5317.7317a12.0025 12.0025 0 0 1-4.9669-3.3397 12.009 12.009 0 0 1 .4761-16.464 12.0018 12.0018 0 0 1 5.1516-3.047Z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rain.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rain.jsx
new file mode 100755
index 0000000..4518beb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rain.jsx
@@ -0,0 +1,15 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Rain(props) {
5 return (
6 <Icon {...props} className={Utils.classNames(props.className, "rain-icon")}>
7 <path d="M9.40229 0.0820312C9.91599 0.176996 10.4383 0.238172 10.9418 0.372572C13.1474 0.961467 14.8518 2.25747 16.0604 4.21737C16.2118 4.46283 16.3413 4.53013 16.6358 4.4953C18.7154 4.24965 20.4991 4.91318 21.9565 6.42603C23.3028 7.82358 23.8654 9.53022 23.7501 11.4753C23.6065 13.8922 21.8564 16.2545 19.6214 17.0449C19.5919 17.0554 19.5591 17.0565 19.5063 17.0659C19.4987 17.0043 19.4863 16.9511 19.4862 16.898C19.4847 16.2325 19.4796 15.5667 19.4919 14.9014C19.4938 14.8081 19.5614 14.6806 19.6377 14.6289C21.933 13.0737 22.3072 10.0168 20.4482 7.95921C19.1574 6.5305 16.9606 6.19356 15.2668 7.1641C15.1972 7.20401 15.126 7.241 15.0378 7.2889C14.9639 7.05333 14.9067 6.83064 14.8255 6.61737C13.8767 4.12467 12.103 2.63497 9.49462 2.31008C7.37283 2.0458 5.53377 2.76203 4.07599 4.36824C1.90883 6.7561 1.78902 10.2714 3.76606 12.8247C3.95269 13.0655 4.17716 13.276 4.37509 13.5084C4.43439 13.578 4.49933 13.6738 4.50027 13.7585C4.5094 14.5569 4.50554 15.3557 4.50422 16.1545C4.50422 16.1849 4.49236 16.2153 4.47015 16.3217C4.0038 15.9646 3.54187 15.6644 3.1414 15.2955C0.991751 13.3151 0.0218683 10.8394 0.274574 7.9049C0.593915 4.19676 3.35627 1.07422 6.96747 0.284102C7.3653 0.197043 7.77142 0.148478 8.17377 0.0820312H9.40229Z" />
8 <g>
9 <path d="M10.9289 18.5402C10.929 17.1176 10.9241 15.6949 10.9309 14.2723C10.9345 13.5176 11.5348 13.0124 12.2313 13.1592C12.6461 13.2467 12.9787 13.5967 13.0456 14.0237C13.0636 14.1381 13.0732 14.2552 13.0733 14.3711C13.0748 17.1663 13.0751 19.9617 13.0738 22.757C13.0736 23.3641 12.8188 23.7747 12.3503 23.9382C11.6461 24.1837 10.9426 23.6682 10.9317 22.8829C10.9203 22.0594 10.9289 21.2357 10.9288 20.412C10.9287 19.7882 10.9288 19.1641 10.9289 18.5402Z" />
10 <path d="M15.2072 16.3848C15.2072 14.9706 15.2045 13.5564 15.2084 12.1421C15.2103 11.4266 15.6723 10.9446 16.3239 10.9634C16.7935 10.9771 17.21 11.3197 17.3137 11.7843C17.3371 11.8891 17.3526 11.9983 17.3527 12.1055C17.3547 14.9588 17.3583 17.8123 17.3517 20.6656C17.35 21.4185 16.8111 21.9006 16.1151 21.8069C15.5796 21.7349 15.2111 21.2731 15.2085 20.6524C15.204 19.6208 15.2072 18.5893 15.2072 17.5578C15.2072 17.1667 15.2072 16.7758 15.2072 16.3848Z" />
11 <path d="M6.65064 16.3841C6.65074 14.9533 6.64612 13.5226 6.65252 12.0917C6.6561 11.2898 7.36095 10.7599 8.07304 11.0215C8.47445 11.1689 8.71587 11.4668 8.77064 11.9041C8.78608 12.0274 8.78947 12.1529 8.78956 12.2774C8.79059 15.0225 8.79116 17.7677 8.78843 20.5131C8.78824 20.6864 8.78363 20.8658 8.74165 21.0323C8.60998 21.554 8.12311 21.8705 7.57958 21.8075C7.06081 21.7477 6.66184 21.3074 6.6546 20.7514C6.64358 19.8947 6.65074 19.0378 6.65055 18.181C6.65036 17.5821 6.65045 16.983 6.65064 16.3841Z" />
12 </g>
13 </Icon>
14 );
15}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ram.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ram.jsx
new file mode 100755
index 0000000..c37d116
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ram.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Ram(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0 8l.2.3c.5.5.5 1.3 0 1.8l-.2.2v5.2h24v-5.2l-.2-.2c-.5-.5-.5-1.3 0-1.8L24 8V5.7H0V8zm18.3.5h1.4v4.2h-1.4V8.5zm-2.8 0H17v4.2h-1.4V8.5zm-2.8 0h1.4v4.2h-1.4V8.5zm-2.8 0h1.4v4.2H9.9V8.5zM7 8.5h1.4v4.2H7V8.5zm-2.8 0h1.4v4.2H4.3V8.5zM1.4 17h7v1.3h-7V17zM9.9 17h12.7v1.3H9.9V17z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/redis.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/redis.jsx
new file mode 100755
index 0000000..c1ed1cb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/redis.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Redis(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M23.9923 14.3401c-.0075.2303-.3128.4845-.9338.8085-1.281.6683-7.914 3.3983-9.3285 4.1325-1.4137.738-2.1952.7305-3.3127.195-1.1175-.531-8.1758-3.387-9.4493-3.9922-.633-.3045-.957-.5588-.969-.801v2.4255c0 .2422.336.4957.969.801 1.2735.6097 8.3363 3.4612 9.4493 3.9922 1.1175.5355 1.8982.543 3.3127-.195 1.4138-.7342 8.0468-3.465 9.3285-4.1325.6525-.336.9413-.6015.9413-.84v-2.391c0-.0037-.0038-.0037-.0075-.0037v.0007Zm0-3.9532c-.012.2265-.3128.4807-.9338.8085-1.281.6637-7.914 3.3945-9.3285 4.1287-1.4137.738-2.1952.7305-3.3127.1995-1.1175-.5355-8.1758-3.387-9.4493-3.996-.633-.3007-.957-.5587-.969-.801v2.4255c0 .2423.336.5003.969.801 1.2735.6098 8.3318 3.4613 9.4493 3.996 1.1175.531 1.8982.5393 3.3127-.195 1.4138-.738 8.0468-3.465 9.3285-4.1325.6525-.3397.9413-.6052.9413-.8437v-2.391h-.0075Zm0-4.1055c.012-.2423-.3045-.4568-.9495-.6915C21.797 5.133 15.1993 2.508 13.937 2.043c-1.2615-.4612-1.7775-.4417-3.2617.09C9.191 2.6686 2.171 5.422.9215 5.9101c-.6247.246-.93.4725-.918.7148v2.4255c0 .2422.3323.4957.969.801 1.2698.6097 8.3318 3.4612 9.4493 3.996 1.113.531 1.8982.5392 3.3127-.1995 1.41-.7343 8.0468-3.465 9.3285-4.1288.6488-.3397.9375-.6052.9375-.8437V6.2806l-.0082.0008ZM8.5933 8.5786l5.5627-.8512-1.68 2.4607-3.8827-1.6095ZM20.894 6.3594l-3.6442 1.4415-3.2888-1.3005 3.6405-1.4378 3.2925 1.2968Zm-9.6562-2.3828-.5393-.9922 1.68.6562 1.5818-.516-.4298 1.0238 1.6133.6052-2.0783.2145-.4687 1.1213-.75-1.2503-2.4023-.2145 1.7933-.648ZM7.0933 5.3791c1.6447 0 2.973.516 2.973 1.1483 0 .6367-1.332 1.152-2.973 1.152-1.641 0-2.973-.516-2.973-1.152 0-.633 1.332-1.1483 2.973-1.1483Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reeder5.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reeder5.jsx
new file mode 100755
index 0000000..7775050
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reeder5.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Reeder5(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M19.58 19.99A4.83 4.83 0 0024 15.1a4.9 4.9 0 00-3.17-4.62A6.73 6.73 0 0014.21 4c-2 0-3.81.93-5.03 2.39a4.79 4.79 0 00-5.64 3.97A4.87 4.87 0 000 15.1c0 2.6 1.95 4.72 4.42 4.89h.23a4.74 4.74 0 00.17 0h14.36l.03.01h.37v-.01zM14.99 9.75l-.78-2.49-.78 2.49h-2.52l2.04 1.53-.78 2.48 2.04-1.53 2.04 1.53-.78-2.48 2.04-1.53H15z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reminders.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reminders.jsx
new file mode 100755
index 0000000..a01348f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/reminders.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Reminders(props) {
4 return (
5 <Icon {...props}>
6 <path d="M4 22h-4v-4h4v4zm0-12h-4v4h4v-4zm0-8h-4v4h4v-4zm3 0v4h17v-4h-17zm0 12h17v-4h-17v4zm0 8h17v-4h-17v4z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remnote.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remnote.jsx
new file mode 100755
index 0000000..8783e44
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remnote.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Remnote(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8.5 15h7l2.95 4.213a.5.5 0 0 1-.41.787H5.96a.5.5 0 0 1-.41-.787L8.5 15Z" />
7 <path d="M.5 15a.5.5 0 0 1-.5-.5v-4a.5.5 0 0 1 .5-.5H12l-3.6 5H.5Z" />
8 <path d="M2.146 5.986a.525.525 0 0 1 0-.722l2.896-3.016a.476.476 0 0 1 .704.012L10 7l2 3H6L2.146 5.986Z" />
9 <path d="M23.5 15a.5.5 0 0 0 .5-.5v-4a.5.5 0 0 0-.5-.5H12l3.6 5h7.9Z" />
10 <path d="M21.854 5.986a.525.525 0 0 0 0-.722l-2.896-3.016a.476.476 0 0 0-.704.012L14 7l-2 3h6l3.854-4.014Z" />
11 <path d="M10 .5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5V10h-4V.5Z" />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remote-desktop.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remote-desktop.jsx
new file mode 100755
index 0000000..11a0758
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remote-desktop.jsx
@@ -0,0 +1,15 @@
1import Icon from "../icon.jsx";
2
3export default function RemoteDesktop(props) {
4 return (
5 <Icon {...props}>
6 <path d="M16.9 17.36c-.02-.26-.01-1 0-1.28.02-.92-.07-1.86.12-2.76.09-.43.37-.57.48-.96.08-.26-.05-.66.07-.93.02-.07.28-.21.36-.17-.05.07-.2.15-.28.2v.4c.6.65 2.77.5 3.6.43q.62-.02 1.14-.35a2 2 0 0 0-.54-.37c-.1-.05-.27-.13-.35-.2v-.02c.3-.04.94.49 1.16.7.15.15.37.51.51.62.12.32.25.6.37.93.38 1.1.45 2.28.46 3.43q.02.14-.07.25l-.23.13q-.25.15-.52.22c-.21.06-.52.1-.75.13-1.21.15-2.44.14-3.66.07a7 7 0 0 1-1.5-.23.7.7 0 0 1-.36-.24m-8.61.43c.77.77 3.9.62 4.98.59.37 0 .86-.09 1.24-.1v2.6c0 .66.06 1.57-.09 2.19-.23.3-.58.49-.92.63-1 .4-4.71.57-5.16-.63-.07-.78-.05-1.47-.05-2.25zm15.65.01-.01 3.23c0 .5.03 1.38-.03 1.85-.13 1.09-2.32 1.13-3.1 1.12-.97-.02-2.18-.11-2.9-.84l-.06-.07v-.04c-.18-.66-.1-1.56-.1-2.27v-2.5c.43 0 1.08.11 1.53.12 1.1 0 3.86.12 4.67-.6M8.12 23.19c-.33.1-2.8.01-3.28 0a5.3 5.3 0 0 1-3.62-1.8c-1.32-1.54-1.21-3-1.21-4.87V7.55c0-.92-.03-2.01.04-2.92A5.2 5.2 0 0 1 4.37.07C4.92-.03 6.1 0 6.7 0h9.25q1.2-.02 2.4 0a5.1 5.1 0 0 1 4.79 4c.17.82.12 1.7.12 2.54v4.75c0 .3.01.74-.01 1.02-.1-.06-.1-.09-.16-.18-.04-.47-.02-1.32-.02-1.82V6.98c0-.64.03-1.7-.03-2.31a5 5 0 0 0-1.74-3.32C19.75.05 18.4.21 16.53.22H7.47C6.69.22 5.44.18 4.7.24 3.4.36 2.22 1 1.39 1.98.04 3.58.18 5.1.18 7.06v8.7c0 2.43-.23 4.42 1.82 6.12 1.93 1.6 3.81 1.01 6.05 1.17.03 0 .06.11.07.14m6.53 0c.05-.1.03-.1.11-.16h.61c.72 0 1.45-.03 2.16 0 .06.06.05.08.08.17-.31.03-2.72.05-2.96-.01M5.1.85c.16-.02.37-.01.54-.01h11.2c.72 0 1.49-.04 2.2.1a4.3 4.3 0 0 1 3.25 3.08c.24.9.17 2.5.17 3.49v4.09a3 3 0 0 0-.91-.48V9.74c-.14-.23-.26-.24-.5-.33V6.47c0-.53.02-1.13-.05-1.66a3 3 0 0 0-1.1-1.92 3 3 0 0 0-1.95-.63H5.66c-1.18-.01-2.1.3-2.83 1.25a3.4 3.4 0 0 0-.58 1.87v11.38c0 .54-.03 1.13.04 1.65.14.92.7 1.72 1.52 2.17.75.4 1.55.37 2.39.37h1.84v1.41H5.47A4.33 4.33 0 0 1 .84 18.3V7.14c0-.85-.06-1.89.1-2.72A4.3 4.3 0 0 1 5.1.85m9.18 10.4c.2-.01.34.12.47.24.02.9-.16.72.35 1.44.32.46.27 1.7.27 2.3v2.14c-.54.51-2.6.5-3.37.52-.82 0-3.07-.04-3.63-.6-.15-.16-.11-.45-.1-.65.02-1.42.14-2.76.88-4.02.38-.65.92-1.17 1.67-1.36-.35.29-.58.25-1.02.69.82.5 2.3.42 3.24.37.54-.02 1.15-.06 1.57-.45l.02-.36c-.15-.12-.3-.12-.35-.26M10.84 9.9c.64.35 2.7.37 3.34-.02v1.67c-.45.23-1.08.28-1.59.27-.31 0-1.74.03-1.75-.45-.02-.44 0-1.03 0-1.48m7.22.01c.65.36 2.61.34 3.3.01v1.04l-.01.6c-.5.28-1.31.29-1.87.27-.33-.01-1.11-.04-1.35-.27-.14-.13-.07-1.45-.07-1.65" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M15.86 10.14c.23-.04 1.43.03 1.44.32.02.4 0 .9 0 1.31-.37.18-.51.18-.92.2-.6 0-.87.03-1.43-.19-.04-.3 0-.6 0-.9 0-.11-.05-.42.02-.49.19-.2.64-.22.9-.25m1.33.35c-.13-.25-.98-.27-1.22-.24-.2.01-.93.02-.94.29.14.25 1.01.25 1.28.25.2-.02.87-.03.88-.3"
11 />
12 <path d="M14.78 20.95c.25.02.64 0 .9 0h1.82c-.03.35 0 1-.01 1.39l-.01.01c-.18.06-2.36.02-2.7.02zm.53-8.23c.53.08 1.15.1 1.68-.01-.21.34-.3.76-.33 1.16l-.02.28c-.4.07-.63.05-1.03.01a3.4 3.4 0 0 0-.3-1.44m.31 1.56c.38.01.64.02 1.02 0v1.44c-.3.02-.73.03-1.02 0zm-.12 3.15c.35.18.93.2 1.28.01 0 .14-.02.55.06.67.02.03.1.03.14.12-.08.13-.25.11-.4.14-.48.08-.91 0-1.38-.1l.26-.16q.05-.34.04-.68m-.02-.03c.02-.08 0-.08.06-.12.19 0 .34.05.52.06.15.01.6-.1.72-.04q.02.04.01.1c-.06-.03-.55.02-.66.02-.18 0-.5-.05-.65-.02m.13-1.59c.22.07.8.04 1.03.03 0 .32-.03 1.05.04 1.32l-.02.03c-.2.04-.87.08-1.04-.01-.02-.05.01-1.17 0-1.34zm3.51-6.31c.53-.06 1.75-.03 2.2.27-.29.2-.7.21-1.05.24-.29.05-2.09.03-2.12-.28.13-.15.76-.21.97-.23m-7.19 0c.33-.02 2.05-.06 2.13.28-.1.16-.77.21-.97.23-.72.07-1.57.01-2.26-.23.39-.2.68-.24 1.1-.28M15 11.92a4 4 0 0 0 2.25.01c-.02.2 0 .32-.05.54-.22.24-1.83.26-2.13 0-.08-.07-.06-.44-.07-.55" />
13 </Icon>
14 );
15}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remove.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remove.jsx
new file mode 100755
index 0000000..d2ea86f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/remove.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Remove(props) {
4 return (
5 <Icon {...props}>
6 <path d="M3.85714 24H20.1429V5.33333H3.85714V24ZM21.5 1.33333H16.75L15.3929 0H8.60714L7.25 1.33333H2.5V4H21.5V1.33333Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/replit.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/replit.jsx
new file mode 100755
index 0000000..080e608
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/replit.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Replit(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.878 7.761H3.482A1.469 1.469 0 012 6.304V1.457C2 .644 2.67 0 3.482 0h6.913c.827 0 1.483.658 1.483 1.457v6.304zM20.882 16.215h-8.995V7.75h8.995c.87 0 1.588.717 1.588 1.586v5.294c0 .885-.717 1.586-1.588 1.586zM10.395 24H3.482C2.67 24 2 23.343 2 22.546v-4.853c0-.797.67-1.454 1.482-1.454h8.396v6.307c0 .797-.67 1.454-1.483 1.454z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rider.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rider.jsx
new file mode 100755
index 0000000..9ad3e3e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rider.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Rider(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3.0001 19.2001h9.6v1.8h-9.6v-1.8ZM6.8605 2.9953H2.9953v9.0036H4.751v-3.402H6.264l1.9411 3.4032h2.013L8.0847 8.4129a3.2494 3.2494 0 0 0 .4192-.1664c.486-.2334.8616-.5634 1.125-.9906.264-.426.396-.9228.396-1.476s-.1296-1.0392-.3888-1.4592c-.2598-.4206-.63-.7464-1.11-.978-.48-.2316-1.0356-.3474-1.6656-.3474Zm1.1706 3.5082c-.12.2034-.2904.36-.5118.4698H7.52c-.2208.1098-.4794.1638-.7752.1638H4.751v-2.682h1.9938c.2958 0 .5544.0546.7752.1638.2202.1092.3912.264.5112.4632.12.1998.18.441.18.711 0 .27-.06.5064-.18.7104Zm7.1646-3.5082h-3.4278v9.0036h3.4278c.8532 0 1.6182-.1926 2.2932-.5784a4.1339 4.1339 0 0 0 1.5852-1.6044c.381-.684.5718-1.4568.5718-2.319 0-.8622-.1908-1.6344-.5724-2.3184a4.1284 4.1284 0 0 0-1.5846-1.6044c-.6756-.3864-1.44-.579-2.2932-.579Zm2.322 6.0936c-.219.4482-.5298.792-.933 1.032s-.8724.36-1.4082.36h-1.653V4.5127h1.653c.5358 0 1.005.12 1.4082.36.4032.2406.714.5844.933 1.0326.2184.4476.3282.978.3282 1.5918 0 .6138-.1098 1.1436-.3282 1.5918Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rocket-chat.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rocket-chat.jsx
new file mode 100755
index 0000000..0d30073
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rocket-chat.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function RocketChat(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.58 8.45a8.93 8.93 0 0 0-2.63-2.6A14.5 14.5 0 0 0 12 3.62c-.98 0-1.96.08-2.93.26A7.88 7.88 0 0 0 .75 1.97a.59.59 0 0 0-.23.95c.85.9 2.27 2.66 1.92 4.25a6.9 6.9 0 0 0-2.08 4.81 6.92 6.92 0 0 0 2.08 4.85c.35 1.6-1.06 3.35-1.91 4.25a.59.59 0 0 0 .22.95 7.89 7.89 0 0 0 8.33-1.92c.96.18 1.94.26 2.92.26 2.81.05 5.58-.72 7.96-2.21a8.92 8.92 0 0 0 2.62-2.61 6.47 6.47 0 0 0 0-7.1Zm-10.7 9.86c-1.23 0-2.45-.15-3.64-.47l-.82.8a7.5 7.5 0 0 1-1.5 1.12c-.67.34-1.4.54-2.14.61l.12-.22a5.26 5.26 0 0 0 .66-4.1 5.07 5.07 0 0 1-2.15-3.91c0-3.4 4.24-6.17 9.47-6.17 5.22 0 9.46 2.76 9.46 6.17 0 3.4-4.24 6.17-9.46 6.17Z" />
7 <path d="M7.35 10.72a1.4 1.4 0 1 0-.01 2.8 1.4 1.4 0 0 0 0-2.8ZM11.84 10.72a1.4 1.4 0 1 0 0 2.8 1.4 1.4 0 0 0 0-2.8ZM16.33 10.72a1.4 1.4 0 1 0-.02 2.8 1.4 1.4 0 0 0 .02-2.8Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/roon.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/roon.jsx
new file mode 100755
index 0000000..a532846
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/roon.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Roon(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13.75 21C13.75 21 13.75 21 13.75 21C14.164 21 14.5 20.664 14.5 20.25C14.5 20.25 14.5 3.75 14.5 3.75C14.5 3.336 14.164 3 13.75 3C13.75 3 13.75 3 13.75 3C13.336 3 13 3.336 13 3.75C13 3.75 13 20.25 13 20.25C13 20.664 13.336 21 13.75 21C13.75 21 13.75 21 13.75 21ZM16.25 16C16.25 16 16.25 16 16.25 16C16.664 16 17 15.664 17 15.25C17 15.25 17 8.75 17 8.75C17 8.336 16.664 8 16.25 8C16.25 8 16.25 8 16.25 8C15.836 8 15.5 8.336 15.5 8.75C15.5 8.75 15.5 15.25 15.5 15.25C15.5 15.664 15.836 16 16.25 16C16.25 16 16.25 16 16.25 16ZM21.25 13.5C21.25 13.5 21.25 13.5 21.25 13.5C21.664 13.5 22 13.164 22 12.75C22 12.75 22 11.25 22 11.25C22 10.836 21.664 10.5 21.25 10.5C21.25 10.5 21.25 10.5 21.25 10.5C20.836 10.5 20.5 10.836 20.5 11.25C20.5 11.25 20.5 12.75 20.5 12.75C20.5 13.164 20.836 13.5 21.25 13.5C21.25 13.5 21.25 13.5 21.25 13.5ZM18.75 18.5C18.75 18.5 18.75 18.5 18.75 18.5C19.164 18.5 19.5 18.164 19.5 17.75C19.5 17.75 19.5 6.25 19.5 6.25C19.5 5.836 19.164 5.5 18.75 5.5C18.75 5.5 18.75 5.5 18.75 5.5C18.336 5.5 18 5.836 18 6.25C18 6.25 18 17.75 18 17.75C18 18.164 18.336 18.5 18.75 18.5C18.75 18.5 18.75 18.5 18.75 18.5ZM12 2.784C12 2.344 11.6225 1.9975 11.184 2.033C6.043 2.448 2 6.752 2 12C2 17.248 6.043 21.552 11.184 21.967C11.6225 22.0025 12 21.656 12 21.216C12 21.216 12 2.784 12 2.784C12 2.784 12 2.784 12 2.784Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/royal-tsx.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/royal-tsx.jsx
new file mode 100755
index 0000000..32b051f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/royal-tsx.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function RoyalTSX(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12 24C18.6274 24 24 18.6274 24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24ZM11.9671 6.84375L7.42146 15.973L14.4294 11.5032L11.9671 6.84375ZM3.02734 8.62415L5.86816 16.1625L8.29271 11.8819L3.02734 8.62415ZM17.8386 17.1474H8.29271L20.566 8.88941L17.8386 17.1474Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ruby-mine.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ruby-mine.jsx
new file mode 100755
index 0000000..7e00335
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/ruby-mine.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function RubyMine(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3 19.2001h9.6v1.8H3v-1.8ZM6.8724 2.9953H3.0072v9.0036h1.7556v-3.402h1.5128l1.9414 3.4032h2.013L8.0961 8.4129a3.2536 3.2536 0 0 0 .4191-.1664c.4866-.2334.8622-.5634 1.125-.9906.264-.426.396-.9228.396-1.476s-.1296-1.0392-.3888-1.4592c-.2598-.4206-.6294-.7464-1.1094-.978-.4806-.2316-1.0356-.3474-1.6656-.3474Zm1.17 3.5082c-.12.2034-.2904.36-.5112.4698-.2208.1098-.4788.1638-.7752.1638H4.7622v-2.682H6.756c.2964 0 .5544.0546.7752.1638.2208.1092.3912.264.5112.4632.12.1998.18.441.18.711 0 .27-.06.5064-.18.7104Zm6.1812-3.5082h-2.4432v9.0036h1.7298V5.5741l-.0258-.4242 2.0706 6.849h1.2738l2.0964-6.894-.0258.4692v6.4248h1.7364v-9.003H18.153l-1.788 5.91-.135.7716-.1542-.7722-1.8522-5.91Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rust-rover.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rust-rover.jsx
new file mode 100755
index 0000000..ea9423b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/rust-rover.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function RustRover(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 0h24v24H0V0Zm3.0001 19.2001h9.6v1.8h-9.6v-1.8ZM6.8605 2.9953H2.9953v9.0036H4.751v-3.402H6.264l1.9411 3.4032h2.013L8.0847 8.4129a3.2494 3.2494 0 0 0 .4192-.1664c.486-.2334.8616-.5634 1.125-.9906.264-.426.396-.9228.396-1.476s-.1296-1.0392-.3888-1.4592c-.2598-.4206-.63-.7464-1.11-.978-.48-.2316-1.0356-.3474-1.6656-.3474Zm1.1706 3.5082c-.12.2034-.2904.36-.5118.4698H7.52c-.2208.1098-.4794.1638-.7752.1638H4.751v-2.682h1.9938c.2958 0 .5544.0546.7752.1638.2202.1092.3912.264.5112.4632.12.1998.18.441.18.711 0 .27-.06.5064-.18.7104Zm7.602-3.5082h-3.8652v9.0036h1.7562v-3.402h1.5125l1.9411 3.4032h2.013l-2.1333-3.5872a3.2541 3.2541 0 0 0 .4191-.1664c.4866-.2334.8616-.5634 1.125-.9906.264-.426.396-.9228.396-1.476s-.1296-1.0392-.3888-1.4592c-.2598-.4206-.63-.7464-1.11-.978-.48-.2316-1.0356-.3474-1.6656-.3474Zm1.1706 3.5082c-.12.2034-.2904.36-.5118.4698-.2208.1098-.4788.1638-.7746.1638h-1.9938v-2.682h1.9938c.2958 0 .5544.0546.7752.1638.2202.1092.3912.264.5112.4632.12.1998.18.441.18.711 0 .27-.06.5064-.18.7104Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/safari.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/safari.jsx
new file mode 100755
index 0000000..8a238e1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/safari.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Safari(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0c6.623 0 12 5.377 12 12s-5.377 12-12 12-12-5.377-12-12 5.377-12 12-12zm1.476 14.955c.988-.405 1.757-1.211 2.116-2.216l2.408-6.739-6.672 2.387c-1.006.36-1.811 1.131-2.216 2.119l-3.065 7.494 7.429-3.045zm-.122-4.286c.551.551.551 1.446 0 1.996-.551.551-1.445.551-1.996 0-.551-.55-.551-1.445 0-1.996.551-.551 1.445-.551 1.996 0z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/screens4.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/screens4.jsx
new file mode 100755
index 0000000..a3d028c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/screens4.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Screens4(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M8.094 1.316a1.685 1.685 0 00-1.395 1.239l-.074.28-.348.032c-1.086.102-2.074.946-2.226 1.899l-.031.199-.262.031c-1.7.2-2.957 1.27-3.266 2.777-.258 1.27-.238 11.829.024 12.938.304 1.281 1.394 2.348 2.671 2.613 1.137.235 16.489.235 17.625 0 1.293-.27 2.434-1.406 2.696-2.691.242-1.184.242-11.676 0-12.86-.309-1.507-1.567-2.578-3.266-2.777l-.262-.031-.03-.2c-.153-.952-1.141-1.796-2.227-1.898l-.348-.031-.074-.281c-.192-.684-.711-1.137-1.438-1.243-.394-.054-7.375-.054-7.77.004M16 1.594c.54.203.91.703.957 1.281l.023.3.383.024c1.23.078 2.137 1.047 2.137 2.285v.223l.309.031c1.27.13 2.32 1.024 2.675 2.278.13.457.133 11.07.004 11.625-.074.324-.37 1.03-.433 1.03-.016 0-.004-.038.023-.089.067-.129.067-.133-.129-.125-.11 0-.207.04-.258.098-.046.05-.023-.012.055-.14.074-.13.188-.372.246-.54l.11-.305.011-5.386c.016-6.067.024-5.891-.312-6.567-.352-.715-1.04-1.215-1.863-1.36-.551-.1-15.329-.097-15.883 0-1.106.196-1.922 1.024-2.114 2.145-.058.328-.066 1.246-.054 5.782l.011 5.386.11.305c.058.168.172.41.25.54.137.226.137.23.02.105-.145-.149-.13-.145-.282-.075-.094.043-.11.07-.07.14.023.048.035.087.02.087-.063 0-.356-.695-.434-1.027-.13-.56-.13-11.165.004-11.63.355-1.253 1.406-2.148 2.675-2.277l.309-.031v-.223c0-1.238.906-2.207 2.137-2.285l.383-.023.023-.301a1.503 1.503 0 01.941-1.277c.383-.149 7.625-.149 8.016-.004m-7.734.14c-.567.118-.97.586-1.036 1.2l-.023.253h.75l.027-.195c.075-.57-.074-.55 4.016-.55s3.941-.02 4.016.55l.027.196h.75l-.023-.254c-.055-.504-.344-.922-.782-1.125-.23-.106-7.23-.172-7.722-.075m-1.844 1.79c-.934.148-1.64 1.019-1.64 2.015v.18h1.16l.019-.305c.031-.469.242-.695.719-.773.379-.063 10.261-.063 10.64 0 .477.078.688.304.72.773l.019.305h1.16v-.18c0-1.02-.707-1.867-1.688-2.023-.383-.059-10.738-.055-11.11.007m13.571 4.329c.215.109.313.195.422.37l.14.231.005 2.512c0 1.383-.004 2.39-.016 2.242l-.016-.27-.23.02c-.125.012-.235.004-.242-.012-.008-.02-.137-.023-.285-.015l-.27.015v.375c0 1.11-.637 2-1.629 2.274-.492.133-11.25.133-11.742 0-.973-.27-1.629-1.172-1.629-2.239 0-.418.023-.402-.574-.394-.2.004-.364-.012-.364-.031 0-.207-.093.039-.105.277-.008.176-.02-.805-.027-2.176l-.008-2.488.133-.25c.148-.29.422-.488.761-.555.114-.023 3.57-.039 7.805-.035l7.598.008.273.14M2.602 20.86c.101.102.171.188.16.188-.012 0-.106-.086-.207-.188-.102-.101-.172-.187-.16-.187.011 0 .105.086.207.187m19.007-.172c0 .008-.09.094-.199.2l-.2.183.185-.199c.175-.183.214-.223.214-.183"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-ace.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-ace.jsx
new file mode 100755
index 0000000..e2e5fb7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-ace.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function SequelAce(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M0 4.74C0 3.12 0 2.3.3 1.68A3 3 0 011.69.31C2.3 0 3.12 0 4.74 0h14.52c1.62 0 2.44 0 3.06.3a3 3 0 011.37 1.38c.31.62.31 1.44.31 3.06v14.52c0 1.62 0 2.44-.3 3.06a3 3 0 01-1.38 1.37c-.62.31-1.44.31-3.06.31H4.74c-1.62 0-2.44 0-3.06-.3a3 3 0 01-1.37-1.38C0 21.7 0 20.88 0 19.26V4.74zm3.4 12.22v-2.18c0 1.42 3.25 2.59 7.44 2.76a21.28 21.28 0 002.2 0c4.19-.17 7.43-1.34 7.43-2.76V17.7c0 1.41-3.24 2.58-7.44 2.76l-1.09.02c-.45 0-.81 0-1.1-.02-4.2-.18-7.44-1.35-7.44-2.76v-.74zm.01-6.44v2.91c0 1.42 3.25 2.59 7.44 2.76a21.28 21.28 0 002.2 0c4.19-.17 7.44-1.34 7.44-2.76v-.73-2.18c0 1.41-3.25 2.58-7.45 2.76l-1.09.02c-.45 0-.8 0-1.1-.02-4.2-.18-7.44-1.35-7.44-2.76zm0-4.32c0-1.5 3.82-2.7 8.54-2.7 4.71 0 8.54 1.2 8.54 2.7v3c0 1.42-3.25 2.59-7.45 2.76a21.3 21.3 0 01-2.2 0c-4.18-.17-7.43-1.34-7.43-2.76v-3z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-pro.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-pro.jsx
new file mode 100755
index 0000000..cc920ae
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sequel-pro.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function SequelPro(props) {
4 return (
5 <Icon {...props}>
6 <path d="M24 16.2c0 3.76-5.37 6.8-12 6.8S0 19.96 0 16.2c0-3.75 5.37-6.8 12-6.8s12 3.05 12 6.8z" />
7 <path d="M20.62 15.58c0 2.6-3.72 4.7-8.31 4.7-4.6 0-8.31-2.1-8.31-4.7s3.72-4.7 8.3-4.7c4.6 0 8.32 2.1 8.32 4.7z" />
8 <path d="M20.62 12.75c0 2.6-3.72 4.7-8.31 4.7-4.6 0-8.31-2.1-8.31-4.7s3.72-4.7 8.3-4.7c4.6 0 8.32 2.1 8.32 4.7z" />
9 <path d="M20.62 10.14c0 2.6-3.72 4.7-8.31 4.7-4.6 0-8.31-2.1-8.31-4.7s3.72-4.7 8.3-4.7c4.6 0 8.32 2.1 8.32 4.7z" />
10 <path d="M20.62 7.32c0 2.6-3.72 4.7-8.31 4.7-4.6 0-8.31-2.1-8.31-4.7s3.72-4.7 8.3-4.7c4.6 0 8.32 2.1 8.32 4.7z" />
11 <path d="M20.62 4.7c0 2.6-3.72 4.7-8.31 4.7C7.7 9.4 4 7.3 4 4.7S7.72 0 12.3 0c4.6 0 8.32 2.1 8.32 4.7z" />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/setapp.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/setapp.jsx
new file mode 100755
index 0000000..44aad58
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/setapp.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Setapp(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13.025,8.386l2.583,2.595c0.228,0.228 0.595,0.228 0.81,-0l2.583,-2.595c0.228,-0.228 0.228,-0.595 -0,-0.823l-2.583,-2.595c-0.228,-0.228 -0.595,-0.228 -0.81,-0l-2.583,2.607c-0.227,0.216 -0.227,0.583 0,0.811m-1.43,-1.431c0.228,0.228 0.595,0.228 0.81,0l2.583,-2.595c0.228,-0.228 0.228,-0.595 -0,-0.823l-2.583,-2.595c-0.228,-0.228 -0.595,-0.228 -0.81,-0l-2.583,2.595c-0.228,0.228 -0.228,0.595 0,0.823l2.583,2.595Zm-0,2.051l-2.583,2.595c-0.228,0.228 -0.228,0.595 0,0.823l2.583,2.595c0.228,0.228 0.595,0.228 0.81,0l2.583,-2.595c0.228,-0.228 0.228,-0.595 -0,-0.823l-2.583,-2.595c-0.215,-0.228 -0.582,-0.228 -0.81,0m-4.013,1.975c0.228,0.228 0.595,0.228 0.81,-0l2.583,-2.595c0.227,-0.228 0.227,-0.595 -0,-0.823l-2.583,-2.595c-0.228,-0.228 -0.595,-0.228 -0.81,-0l-2.583,2.595c-0.228,0.228 -0.228,0.595 0,0.823l2.583,2.595Zm8.836,2.051c-0.228,-0.228 -0.595,-0.228 -0.81,-0l-2.583,2.595c-0.227,0.228 -0.227,0.595 0,0.823l2.583,2.595c0.228,0.228 0.595,0.228 0.81,0l2.583,-2.595c0.228,-0.228 0.228,-0.595 -0,-0.823l-2.583,-2.595Zm-4.013,4.013c-0.228,-0.228 -0.595,-0.228 -0.81,-0l-2.583,2.595c-0.228,0.228 -0.228,0.595 0,0.823l2.583,2.595c0.228,0.228 0.595,0.228 0.81,0l2.583,-2.595c0.228,-0.228 0.228,-0.595 -0,-0.823l-2.583,-2.595Zm-1.418,-1.431l-2.582,-2.595c-0.228,-0.228 -0.595,-0.228 -0.811,0l-2.582,2.595c-0.228,0.228 -0.228,0.595 -0,0.823l2.582,2.595c0.228,0.228 0.595,0.228 0.811,0l2.582,-2.595c0.215,-0.228 0.215,-0.595 0,-0.823" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/signal.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/signal.jsx
new file mode 100755
index 0000000..c615f9c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/signal.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Signal(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.012 2.598c-5.22 0-9.452 3.9-9.452 8.709 0 3.016 1.219 5.301 3.155 6.774H5.71l.234 3.042v.004c0 .017 0 .031.004.046v.006a.306.306 0 00.445.22l.011-.008L9.3 19.717c.854.196 1.767.299 2.71.299 5.22 0 9.452-3.899 9.452-8.71 0-4.81-4.233-8.709-9.454-8.709zM10.39.72a13.058 13.058 0 011.605-.104c.38 0 .75.02 1.119.052l.057-.614a13.089 13.089 0 00-2.865.055l.083.612zm3.797.094c.915.165 1.785.436 2.61.795l.252-.567c-.132-.056-.263-.112-.397-.165-.762-.3-1.551-.524-2.355-.671zm9.169 10.556a9.97 9.97 0 01-.405 2.655l.59.175a10.55 10.55 0 00.431-2.831zM6.745 1.814A12.139 12.139 0 019.331.912L9.196.308a12.161 12.161 0 00-2.72.95zm13.65 1.399a12.005 12.005 0 00-2.329-1.673l-.311.541c.811.445 1.561.981 2.224 1.596l.416-.462zm-5.244 18.838c.945-.24 1.845-.591 2.686-1.03l-.315-.533c-.786.413-1.631.738-2.521.967zM3.677 4.005c.63-.638 1.347-1.2 2.13-1.675l-.327-.529c-.698.422-1.35.914-1.945 1.473-.102.094-.2.191-.3.289l.439.441zm19.48 11.28l-.568-.236a10.472 10.472 0 01-1.354 2.332l.495.369a11.035 11.035 0 001.424-2.465zM20.726 4.433a10.54 10.54 0 011.534 2.228l.555-.275a11.052 11.052 0 00-1.627-2.366l-.465.413zm2.554 3.003l-.568.244c.313.828.521 1.703.604 2.61l.615-.061a10.444 10.444 0 00-.651-2.793zM6.386 22.849l-.969.425-.332-1.025-.585.19.438 1.347a.33.33 0 00.167.188.305.305 0 00.249 0l1.283-.563zm3.823-1.193c-.078-.016-.157-.027-.237-.041l-.465-.079a.311.311 0 00-.172.023l-1.951.853.271.554 1.845-.803c.125.021.25.041.371.059.068.017.139.026.209.038zm3.728.02c-.633.104-1.281.156-1.942.156-.273 0-.525-.015-.772-.038l-.019.615c.251.024.511.04.791.04.698 0 1.383-.058 2.048-.166l-.104-.606zM1.517 7.116c.37-.825.852-1.598 1.425-2.302l-.47-.407A10.884 10.884 0 00.964 6.834l-.01.021zM20.532 18.21a11.497 11.497 0 01-2.07 1.728l.339.515a11.983 11.983 0 002.19-1.829zM.97 14.551c-.188-.796-.293-1.676-.323-2.671H.031c.03 1.071.145 2.005.345 2.843zM.538 7.925c-.297.91-.468 1.853-.51 2.813l.615.03a9.968 9.968 0 01.487-2.662zm4.199 13.26l-.59-1.815a.306.306 0 00-.105-.147 11.75 11.75 0 01-.66-.558l-.422.446c.194.184.408.362.629.541l.561 1.717zm-2.105-3.292a7.463 7.463 0 01-1.355-2.315l-.573.229a8.016 8.016 0 001.468 2.497z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch-up.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch-up.jsx
new file mode 100755
index 0000000..0acb2ed
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch-up.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function SketchUp(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M21.29 19.465 6.144 23.762 3.14 14.418 1.098 2.176 15.488.238l7.414 5.696Zm-14.927-1.61 4.617-1.183-1.18-2.254-4.296.965Zm-1.398-6.554 4.512-.965 1.183 2.144 5.047-1.07-3.117-3.867-8.485 1.504Zm10.203-9.664L2.602 3.247 3.46 5.18l9.02-1.29 3.332 3.329 5.261-.86Zm0 0"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch.jsx
new file mode 100755
index 0000000..c35cb07
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sketch.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Sketch(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 1.25l6.75 6.637V2L12 1.25zm0 0l-6.05 7h12.1l-6.05-7zm0 0L5.25 2v5.887L12 1.25zM5.25 2L0 9l4.416-.68L5.25 2zM0 9l11.959 13.703.008-.014L4.443 9H0zm18.75-7l.834 6.32L24 9l-5.25-7zM24 9h-4.506l-7.523 13.69.029.06L24 9zM12 22.75l-.031-.057-.008.012.039.045zM5.436 9l6.533 13.686L18.564 9H5.436Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/skype.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/skype.jsx
new file mode 100755
index 0000000..7d7a229
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/skype.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Skype(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.3 14.55C25.06 6.74 18.2-.35 10.18 1 5.81-1.7 0 1.36 0 6.55c0 1.2.33 2.33.91 3.3C-.7 17.69 6.2 24.69 14.22 23.23c.94.5 2 .78 3.14.78a6.55 6.55 0 0 0 5.95-9.45zm-11.2 5.33c-2.35 0-4.63-.57-5.99-2.5-2.02-2.85.64-4.28 1.95-3.2 1.1.93.75 3.15 3.95 3.15 1.41 0 3.15-.6 3.15-2 0-2.82-6.24-1.49-8.73-4.55a3.77 3.77 0 0 1 .04-4.55c1.95-2.51 7.68-2.67 10.14-.77 2.28 1.76 1.66 4.1-.17 4.1-2.2 0-1.05-2.89-4.61-2.89-2.58 0-3.6 1.84-1.78 2.73 2.42 1.2 8.75.83 8.75 5.6 0 3.36-3.25 4.88-6.7 4.88z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/slack.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/slack.jsx
new file mode 100755
index 0000000..163fdd9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/slack.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Slack(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8.8 12.7a2.5 2.5 0 0 0-2.5 2.5v6.3a2.5 2.5 0 0 0 5 0v-6.3c0-1.4-1-2.5-2.5-2.5zM0 15.2a2.5 2.5 0 0 0 5 0v-2.6H2.6A2.5 2.5 0 0 0 0 15.2zM8.8 0a2.5 2.5 0 0 0 0 5h2.6V2.5c0-1.4-1.2-2.5-2.6-2.5zM2.5 11.4h6.3a2.5 2.5 0 0 0 0-5H2.5a2.5 2.5 0 0 0 0 5zM21.5 6.3a2.5 2.5 0 0 0-2.6 2.5v2.6h2.6a2.5 2.5 0 0 0 0-5zM12.6 2.5v6.3a2.5 2.5 0 0 0 5 0V2.5a2.5 2.5 0 0 0-5 0zM17.7 21.5c0-1.4-1.1-2.5-2.5-2.5h-2.6v2.5a2.5 2.5 0 0 0 5 0zM21.5 12.6h-6.3a2.5 2.5 0 0 0 0 5.1h6.3a2.5 2.5 0 0 0 0-5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/snow.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/snow.jsx
new file mode 100755
index 0000000..1c55afa
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/snow.jsx
@@ -0,0 +1,18 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Snow(props) {
5 return (
6 <Icon {...props} className={Utils.classNames(props.className, "snow-icon")}>
7 <path d="M9.15317 1.01074C9.69604 1.10392 10.2482 1.15907 10.7799 1.29658C13.0159 1.87474 14.7392 3.18194 15.9577 5.16651C16.111 5.4162 16.251 5.46373 16.5266 5.42881C18.3198 5.20265 19.9297 5.68999 21.3102 6.85714C22.9519 8.24491 23.732 10.0534 23.646 12.226C23.5457 14.7636 21.8578 17.0988 19.5145 17.9749C19.4855 17.9857 19.4542 17.9904 19.4013 18.0037C19.3939 17.9343 19.3823 17.8751 19.3822 17.816C19.3809 17.1573 19.3846 16.4985 19.3787 15.8398C19.3774 15.7034 19.4186 15.6247 19.5338 15.5456C20.9551 14.5697 21.6462 13.2041 21.4857 11.4695C21.3341 9.82853 20.4756 8.62815 19.0004 7.93752C17.7032 7.33027 16.4063 7.41357 15.1486 8.10222C15.0855 8.13677 15.0238 8.17404 14.961 8.20952C14.9542 8.21328 14.9455 8.21357 14.9223 8.21912C14.8753 8.0579 14.8357 7.89281 14.7797 7.73375C13.88 5.17837 12.1253 3.62411 9.47279 3.25827C6.03382 2.78411 2.87392 5.20679 2.34996 8.68622C2.01707 10.8971 2.66554 12.8135 4.23448 14.3937C4.35156 14.5116 4.40709 14.6226 4.40521 14.7927C4.39637 15.5888 4.40126 16.3851 4.40126 17.2468C4.07166 17.0175 3.76653 16.8305 3.48879 16.6082C1.54488 15.0516 0.4198 13.0303 0.166906 10.5192C0.160506 10.4558 0.138012 10.3942 0.123047 10.3318V9.11173C0.169635 8.79973 0.212553 8.48698 0.26347 8.17573C0.810953 4.83399 3.45378 1.99069 6.70629 1.25855C7.19571 1.14834 7.69688 1.09197 8.19251 1.01074H9.15317Z" />
8 <g>
9 <path d="M6.55082 15.1352C6.55571 14.5367 7.03882 14.0541 7.62461 14.0626C8.21501 14.0713 8.68202 14.5576 8.67694 15.158C8.67185 15.7538 8.18592 16.2394 7.60202 16.2324C7.01557 16.2253 6.54593 15.7351 6.55082 15.1352Z" />
10 <path d="M17.2317 15.1576C17.2269 15.7554 16.7446 16.2387 16.159 16.2325C15.5742 16.2263 15.1014 15.7342 15.1055 15.136C15.1095 14.5397 15.5958 14.054 16.1802 14.0626C16.7713 14.0715 17.2365 14.5559 17.2317 15.1576Z" />
11 <path d="M12.9541 17.3224C12.9536 17.9238 12.481 18.4025 11.8891 18.4011C11.2964 18.3996 10.8274 17.9207 10.8281 17.3179C10.829 16.7182 11.3046 16.235 11.8932 16.2363C12.4816 16.2375 12.9545 16.7217 12.9541 17.3224Z" />
12 <path d="M6.55079 19.49C6.55352 18.8881 7.02684 18.4124 7.61922 18.416C8.21187 18.4197 8.67964 18.9 8.67682 19.5023C8.67418 20.0995 8.1939 20.5834 7.60726 20.5801C7.01978 20.5767 6.54816 20.0901 6.55079 19.49Z" />
13 <path d="M12.9542 21.6635C12.9557 22.2643 12.4842 22.7476 11.8944 22.75C11.3061 22.7524 10.8294 22.2694 10.8281 21.6696C10.827 21.0714 11.3027 20.583 11.8883 20.5811C12.4737 20.5792 12.9529 21.0658 12.9542 21.6635Z" />
14 <path d="M17.2315 19.5036C17.2285 20.103 16.7509 20.5838 16.1623 20.5801C15.5762 20.5763 15.1028 20.0876 15.1055 19.4889C15.1081 18.8897 15.586 18.4111 16.1766 18.4161C16.77 18.421 17.2346 18.9001 17.2315 19.5036Z" />
15 </g>
16 </Icon>
17 );
18}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spark.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spark.jsx
new file mode 100755
index 0000000..7655fae
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spark.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Spark(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0C18.6274 0 24 5.37258 24 12ZM12.218 3.25078L19.2492 17.8922C19.3453 18.0961 19.1555 18.2859 18.9539 18.1898L13.6664 15.7429C13.6242 15.7242 13.5773 15.7219 13.5375 15.7359C13.4883 15.7523 13.4484 15.7898 13.4297 15.8414L12.1055 19.6687C12.0857 19.7256 12.0361 19.7543 11.9859 19.7548L11.984 19.7549C11.9329 19.755 11.8817 19.7263 11.8617 19.6687L10.5375 15.8414C10.5188 15.7899 10.4767 15.7524 10.4299 15.736L10.4297 15.7383C10.3875 15.7242 10.343 15.7265 10.3008 15.7453L5.01328 18.1922C4.84717 18.2704 4.6904 18.1574 4.6912 18.0039C4.69101 17.9682 4.69931 17.9304 4.71797 17.8922L11.7492 3.25078C11.8453 3.05391 12.1242 3.05391 12.218 3.25078Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotify.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotify.jsx
new file mode 100755
index 0000000..718a4a8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotify.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Spotify(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M19.098 10.638c-3.868-2.297-10.248-2.508-13.941-1.387-.593.18-1.22-.155-1.399-.748-.18-.593.154-1.22.748-1.4 4.239-1.287 11.285-1.038 15.738 1.605.533.317.708 1.005.392 1.538-.316.533-1.005.709-1.538.392zm-.126 3.403c-.272.44-.847.578-1.287.308-3.225-1.982-8.142-2.557-11.958-1.399-.494.15-1.017-.129-1.167-.623-.149-.495.13-1.016.624-1.167 4.358-1.322 9.776-.682 13.48 1.595.44.27.578.847.308 1.286zm-1.469 3.267c-.215.354-.676.465-1.028.249-2.818-1.722-6.365-2.111-10.542-1.157-.402.092-.803-.16-.895-.562-.092-.403.159-.804.562-.896 4.571-1.045 8.492-.595 11.655 1.338.353.215.464.676.248 1.028zm-5.503-17.308c-6.627 0-12 5.373-12 12 0 6.628 5.373 12 12 12 6.628 0 12-5.372 12-12 0-6.627-5.372-12-12-12z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotlight.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotlight.jsx
new file mode 100755
index 0000000..4398b47
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotlight.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Spotlight(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.68 22.14l-7.44-7.44A9.1 9.1 0 1 0 0 9.1a9.1 9.1 0 0 0 14.7 7.14l7.44 7.44a1.09 1.09 0 0 0 1.54 0 1.1 1.1 0 0 0 0-1.54zM2.18 9.09a6.92 6.92 0 1 1 13.84.02 6.92 6.92 0 0 1-13.84-.02z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotube.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotube.jsx
new file mode 100755
index 0000000..f8c0e79
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/spotube.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Spotube(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0 13.9499v5.5153C.3957 20.8624.882 21.4377 2.3373 22h2.7933c.2813-.0719.3549-.1808.399-.4457v-9.3036c.2373-2.1299.667-3.221 2.2804-4.8747 1.3953-1.1068 2.3546-1.4557 4.4465-1.5041 1.5819.1382 2.4436.4463 3.9335 1.5041 1.8102 1.6983 2.1964 2.7943 2.3373 4.8747v9.3036c.1724.2837.3144.3954.7126.4457h2.2803c1.5544-.416 2.1092-.9652 2.4798-2.5348v-5.5153c-.1872-1.3355-.5502-1.8355-1.5677-2.3677-.2975-2.9706-1.0181-4.505-3.4774-6.9638C16.7502 2.9164 15.3386 2.2525 12.2565 2c-3.5312.2355-4.9837.9217-7.1259 2.6184-2.4024 2.3345-3.052 3.898-3.4489 6.9638C.713 12.2055.3416 12.7209 0 13.9499Z" />
7 <path d="M6.5273 13.1978v7.5766c.2982.6844.5735.8597 1.1972.9192.6761-.0645.948-.2817 1.2826-.9192v-7.5766c-.066-.9687-.271-1.3647-1.2826-1.5042-.9308.1907-1.1795.5294-1.1972 1.5042ZM15.1924 13.1978v7.5766c.2982.6844.5735.8597 1.1971.9192.6762-.0645.948-.2817 1.2827-.9192v-7.5766c-.0661-.9687-.271-1.3647-1.2827-1.5042-.9307.1907-1.1795.5294-1.1971 1.5042Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/statistics.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/statistics.jsx
new file mode 100755
index 0000000..5e5911f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/statistics.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Statistics(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6 9.4H.9c-.5 0-.9.4-.9.9V23c0 .5.4.9.9.9H6c.5 0 .9-.4.9-.9V10.3c0-.5-.4-.9-.9-.9zM14.6 0H9.4c-.4 0-.8.4-.8.9V23c0 .5.4.9.8.9h5.2c.4 0 .8-.4.8-.9V1c0-.5-.4-.9-.8-.9zM23.1 6.9H18c-.5 0-.9.3-.9.8v15.4c0 .5.4.9.9.9h5.1c.5 0 .9-.4.9-.9V7.7c0-.5-.4-.8-.9-.8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/stopped.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/stopped.jsx
new file mode 100755
index 0000000..05cb40c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/stopped.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Stopped(props) {
4 return (
5 <Icon {...props}>
6 <path d="M6 6h12v12H6z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/storm.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/storm.jsx
new file mode 100755
index 0000000..39fb1ad
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/storm.jsx
@@ -0,0 +1,18 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Storm(props) {
5 return (
6 <Icon
7 {...props}
8 className={Utils.classNames(props.className, "storm-icon")}
9 >
10 <path d="M9.21762 0.711914C9.76049 0.805091 10.3127 0.860338 10.8443 0.997749C13.0804 1.57591 14.8038 2.88311 16.0221 4.86768C16.1755 5.11737 16.3155 5.1649 16.5911 5.13008C18.3843 4.90382 19.9942 5.39116 21.3747 6.55831C23.0164 7.94608 23.7964 9.75455 23.7104 11.9272C23.6102 14.4649 21.9223 16.8001 19.5789 17.6761C19.5499 17.687 19.5186 17.6916 19.4657 17.7049C19.4585 17.6355 19.4468 17.5763 19.4466 17.5172C19.4454 16.8585 19.4491 16.1996 19.4431 15.5411C19.4418 15.4045 19.483 15.3258 19.5982 15.2468C21.0196 14.2709 21.7106 12.9052 21.55 11.1706C21.3985 9.5297 20.5401 8.32942 19.065 7.63869C17.7676 7.03144 16.4708 7.11483 15.2131 7.8034C15.1499 7.83803 15.0882 7.87521 15.0254 7.91069C15.0187 7.91446 15.01 7.91474 14.9867 7.92029C14.9398 7.75907 14.9002 7.59399 14.8442 7.43493C13.9445 4.87954 12.1898 3.32528 9.53724 2.95954C6.09828 2.48528 2.93837 4.90796 2.41442 8.3874C2.08152 10.5983 2.72999 12.5146 4.29894 14.095C4.41602 14.2128 4.47155 14.3238 4.46967 14.4938C4.46082 15.29 4.46571 16.0863 4.46571 16.948C4.13611 16.7187 3.83098 16.5317 3.55324 16.3095C1.60934 14.7528 0.484253 12.7315 0.231359 10.2204C0.224959 10.157 0.202465 10.0954 0.1875 10.033V8.8129C0.234088 8.5009 0.277006 8.18824 0.327924 7.8769C0.875406 4.53516 3.51823 1.69187 6.77075 0.959726C7.26016 0.849514 7.76134 0.793138 8.25696 0.711914H9.21762Z" />
11 <g>
12 <path d="M5.42578 20.6793L8.80799 17.9439L8.2366 16.6228L7.67199 15.3183H7.67651L7.68253 15.3214L8.23651 13.9587L8.79039 12.5889H6.53364L5.97976 13.9602L5.4382 15.285L5.42917 15.2896L5.43378 15.2999L5.42578 15.3183H5.44197L6.00065 16.623L6.56733 17.9451L6.55708 17.971L5.42578 20.6793Z" />
13 <path d="M10.1074 22.8359L13.4896 20.1004L12.9182 18.7836L12.3536 17.4833H12.3582L12.3642 17.4822L12.9182 16.1215L13.472 14.7539H11.2153L10.6614 16.121L10.1198 17.4435L10.1107 17.4473L10.1154 17.4613L10.1074 17.4833H10.1236L10.6823 18.7838L11.249 20.1037L11.2387 20.1285L10.1074 22.8359Z" />
14 <path d="M14.7979 20.6793L18.1802 17.9439L17.6087 16.6228L17.0441 15.3183H17.0487L17.0547 15.3214L17.6086 13.9587L18.1626 12.5889H15.9057L15.3518 13.9602L14.8103 15.285L14.8012 15.2896L14.8059 15.2999L14.7979 15.3183H14.814L15.3727 16.623L15.9395 17.9451L15.9292 17.971L14.7979 20.6793Z" />
15 </g>
16 </Icon>
17 );
18}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sublime-text.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sublime-text.jsx
new file mode 100755
index 0000000..80d2cea
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sublime-text.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function SublimeText(props) {
4 return (
5 <Icon {...props}>
6 <path d="M20.953.004a.397.397 0 0 0-.18.017L3.225 5.585c-.175.055-.323.214-.402.398a.42.42 0 0 0-.06.22v5.726a.42.42 0 0 0 .06.22c.079.183.227.341.402.397l7.454 2.364-7.454 2.363c-.255.08-.463.374-.463.655v5.688c0 .282.208.444.463.363l17.55-5.565c.237-.075.426-.336.452-.6.003-.022.013-.04.013-.065V12.06c0-.281-.208-.575-.463-.656L13.4 9.065l7.375-2.339c.255-.08.462-.375.462-.656V.384c0-.211-.117-.355-.283-.38z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sun.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sun.jsx
new file mode 100755
index 0000000..270a37f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/sun.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2import * as Utils from "../../../utils";
3
4export default function Sun(props) {
5 return (
6 <Icon {...props} className={Utils.classNames(props.className, "sun-icon")}>
7 <g>
8 <path d="M13.01 1.26c.03-.62-.2-1.06-.8-1.26h-.4c-.5.18-.8.5-.8 1.04v1.93c0 .18.05.35.12.5a.97.97 0 0 0 1.07.5.94.94 0 0 0 .79-.87l.01-.88.01-.96ZM1.27 11c-.63-.03-1.07.2-1.27.8v.4c.17.48.48.8 1.02.8h.29L3 12.99c.2-.01.4-.08.57-.18.36-.21.5-.66.39-1.08a.96.96 0 0 0-.89-.72H1.27ZM4.48 3.27l-.22-.1-.04.06c-.4 0-.75.22-.9.6-.17.38-.13.76.17 1.06.47.49.96.98 1.45 1.45a.98.98 0 0 0 1.09.22 1 1 0 0 0 .32-1.63c-.46-.47-.93-.96-1.43-1.4-.12-.12-.29-.19-.44-.26ZM4.36 20.78c-.53-.02-.85-.2-1.02-.56-.19-.38-.17-.76.1-1.06.52-.54 1.04-1.06 1.6-1.56.36-.36.96-.3 1.32.08.34.35.4.93.05 1.3-.5.54-1.03 1.07-1.57 1.57-.11.09-.24.15-.38.19l-.1.04ZM20.68 3.8c-.18-.38-.49-.55-1.02-.58l-.12.05c-.11.04-.29.11-.39.21-.53.48-1.04 1-1.53 1.52a.97.97 0 0 0 .05 1.34c.36.37.95.42 1.33.06.54-.5 1.05-1.02 1.55-1.55.29-.3.3-.67.13-1.05ZM20.8 19.67c-.03.53-.22.84-.6 1.02v-.01c-.36.17-.73.15-1.03-.12a38.4 38.4 0 0 1-1.57-1.58c-.33-.37-.28-.97.07-1.32.36-.36.95-.4 1.32-.06.54.5 1.06 1.02 1.56 1.56.1.12.17.26.2.4l.05.11ZM13 22.97v-1.93c-.02-.61-.45-1.05-1-1.04-.56.01-.98.44-.99 1.04v1.93c.01.6.43 1.03.98 1.03.57.01.99-.43 1.01-1.03ZM22.98 13H21.05c-.61-.01-1.04-.43-1.04-1 0-.55.43-.97 1.02-.98h1.94c.61 0 1.04.43 1.03 1 0 .56-.42.97-1.02.99Z" />
9 </g>
10 <path d="M11.87 8.01c2.15 0 3.93 1.8 3.93 3.99 0 2.19-1.78 4-3.93 3.98a3.97 3.97 0 0 1-3.92-4 3.97 3.97 0 0 1 3.92-3.97Zm-5.87 4a5.93 5.93 0 0 0 5.89 5.96A5.93 5.93 0 0 0 17.76 12c0-3.3-2.63-5.96-5.88-5.97-3.25 0-5.9 2.7-5.88 6v-.02Z" />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/super-productivity.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/super-productivity.jsx
new file mode 100755
index 0000000..93ec47a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/super-productivity.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function SuperProductivity(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.3814 17.75 0 12.5 12.3711 24 24 0 11.3814 17.75Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/table-plus.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/table-plus.jsx
new file mode 100755
index 0000000..0083b53
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/table-plus.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function TablePlus(props) {
4 return (
5 <Icon {...props}>
6 <path d="m1.125 16.438-.813-.188-.312.313 1.75.937.875-1.25 1.063 4.125h2.5l.25-.438h1l1.187-3.062 1.75.625 1.188 2.875h2.874l.063-.5h1l.625-4.313 1.438-3.812 4.5.625L24 9.062 23.062 8 20.75 9.875l-1.938-3.813L14.063 3l-4.624.5.687.875-2.063.188L6.875 9l-4.313 1.125-1.437 6.313Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tailscale.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tailscale.jsx
new file mode 100755
index 0000000..98987d7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tailscale.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Tailscale(props) {
4 return (
5 <Icon {...props}>
6 <path d="M24 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm-9 9a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm0-9a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm6-6a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zM3 24a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zm18 .5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zM6 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm9-9a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm-3 2.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zM6 3a3 3 0 1 1-6 0 3 3 0 0 1 6 0zM3 5.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z"/>
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/team-speak.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/team-speak.jsx
new file mode 100755
index 0000000..7942728
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/team-speak.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function TeamSpeak(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5.5 0A5.5 5.5 0 0 0 0 5.5v13A5.5 5.5 0 0 0 5.5 24h13a5.5 5.5 0 0 0 5.5-5.5v-13A5.5 5.5 0 0 0 18.5 0h-13Zm-.45 7.38V18h2.7V7.38h3.33V4.86H1.72v2.52h3.33Zm9.731 10.332c.684.312 1.488.468 2.412.468.924 0 1.722-.162 2.394-.486.684-.324 1.212-.78 1.584-1.368.384-.588.576-1.266.576-2.034 0-1.068-.3-1.944-.9-2.628-.6-.696-1.482-1.176-2.646-1.44L16.797 9.9c-.408-.096-.726-.276-.954-.54a1.558 1.558 0 0 1-.324-.99c0-.432.138-.762.414-.99.276-.24.672-.36 1.188-.36.552 0 .972.12 1.26.36.3.24.45.57.45.99h2.7c0-1.128-.396-2.022-1.188-2.682-.78-.672-1.842-1.008-3.186-1.008-.888 0-1.656.156-2.304.468a3.556 3.556 0 0 0-1.512 1.332c-.348.564-.522 1.23-.522 1.998 0 1.032.306 1.908.918 2.628.624.708 1.494 1.194 2.61 1.458l1.332.306c.432.096.768.282 1.008.558.24.276.36.606.36.99 0 .444-.162.792-.486 1.044-.312.252-.75.378-1.314.378-.588 0-1.056-.126-1.404-.378-.336-.264-.504-.618-.504-1.062h-2.7c0 .768.186 1.434.558 1.998.372.564.9 1.002 1.584 1.314Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/teams.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/teams.jsx
new file mode 100755
index 0000000..c1ea5a4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/teams.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Teams(props) {
4 return (
5 <Icon {...props}>
6 <path d="M20.248 9.83a1.983 1.983 0 0 1-1.05-1.062 2.027 2.027 0 0 1 0-1.55c.2-.478.577-.858 1.05-1.062a1.963 1.963 0 0 1 2.582 1.062 2.027 2.027 0 0 1 0 1.55c-.2.478-.577.858-1.05 1.062a1.963 1.963 0 0 1-1.532 0ZM19.044 17.25v-6h3.954v3.932c.014.354-.085.703-.282.995a2.145 2.145 0 0 1-.714.637c-.3.165-.622.279-.958.339a5.562 5.562 0 0 1-1.011.097h-.989ZM16.605 8.579a1.894 1.894 0 0 1-.765.156 1.867 1.867 0 0 1-.763-.156c-.087-.038-.145-.081-.21-.13-.069-.05-.145-.107-.272-.17V5.205c.127-.063.203-.12.272-.17a.982.982 0 0 1 .21-.13c.24-.105.5-.158.76-.156.264-.002.524.051.766.156.473.203.85.584 1.05 1.062a2.023 2.023 0 0 1 .002 1.55c-.2.478-.577.858-1.05 1.062ZM14.846 18.9a4.62 4.62 0 0 0-.251-.064V10h3.707v6.942c.013.349-.073.695-.248.995a1.953 1.953 0 0 1-.63.632c-.26.16-.547.273-.846.334a4.333 4.333 0 0 1-.891.097c-.194-.001-.388-.015-.58-.043a1.878 1.878 0 0 1-.261-.058Z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M13.853 23 1 20.75V3.25L13.853 1v22ZM4.461 8.115l5.932-.365v1.5l-2.225.1v6.563l-1.482-.088V9.409l-2.225.09V8.115Z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/telegram.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/telegram.jsx
new file mode 100755
index 0000000..798993b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/telegram.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Telegram(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1.47137906,10.7100602 L15.7673728,4.77371682 C17.1785653,4.15534771 21.9643487,2.17656658 21.9643487,2.17656658 C21.9643487,2.17656658 24.1731717,1.31084983 23.9891031,3.41330479 C23.9277469,4.27902153 23.4368974,7.30903014 22.9460478,10.5863864 L21.4121429,20.2947813 C21.4121429,20.2947813 21.2894305,21.7170303 20.2463752,21.9643779 C19.2033198,22.2117256 17.4853463,21.0986612 17.1785653,20.8513135 C16.9331406,20.6658028 12.5768506,17.8831418 10.9815895,16.5227298 C10.5520961,16.1517083 10.0612466,15.4096654 11.0429457,14.5439487 C13.2517688,12.5033306 15.8900852,9.96801729 17.4853463,8.36025762 C18.2216207,7.61821469 18.957895,5.8867812 15.8900852,7.98923616 L7.23886153,13.8637426 C7.23886153,13.8637426 6.25716238,14.4821118 4.41647649,13.9255796 C2.5757906,13.3690474 0.428323726,12.6270044 0.428323726,12.6270044 C0.428323726,12.6270044 -1.04422499,11.6994508 1.47137906,10.7100602 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/terminal.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/terminal.jsx
new file mode 100755
index 0000000..8a11afd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/terminal.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Terminal(props) {
4 return (
5 <Icon {...props}>
6 <path d="M9.67432 12.8243L2.38645 20.1121C2.03496 20.4636 1.46511 20.4636 1.11366 20.1121L0.263607 19.2621C-0.0872808 18.9112 -0.0879557 18.3425 0.262107 17.9908L6.03794 12.1878L0.262145 6.38491C-0.0879182 6.0332 -0.0872432 5.46451 0.263645 5.11363L1.11366 4.26362C1.46515 3.91213 2.035 3.91213 2.38645 4.26362L9.67432 11.5515C10.0258 11.9029 10.0258 12.4728 9.67432 12.8243ZM24 19.6878V18.4878C24 17.9908 23.5971 17.5878 23.1 17.5878H11.7C11.203 17.5878 10.8 17.9908 10.8 18.4878V19.6878C10.8 20.1849 11.203 20.5878 11.7 20.5878H23.1C23.5971 20.5878 24 20.1849 24 19.6878Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/text.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/text.jsx
new file mode 100755
index 0000000..6b2054d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/text.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Text(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M6 0a6 6 0 0 0-6 6v12a6 6 0 0 0 6 6h12a6 6 0 0 0 6-6V6a6 6 0 0 0-6-6H6Zm.5 7.5a1.5 1.5 0 1 1 0-3h11a1.5 1.5 0 0 1 0 3h-4V18a1.5 1.5 0 1 1-3 0V7.5h-4Z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thermostat.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thermostat.jsx
new file mode 100755
index 0000000..77a448a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thermostat.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Thermostat(props) {
4 return (
5 <Icon {...props}>
6 <path d="M15 13V5c0-1.66-1.34-3-3-3S9 3.34 9 5v8c-1.21.91-2 2.37-2 4 0 2.76 2.24 5 5 5s5-2.24 5-5c0-1.63-.79-3.09-2-4zm-4-8c0-.55.45-1 1-1s1 .45 1 1h-1v1h1v2h-1v1h1v2h-2V5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/things.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/things.jsx
new file mode 100755
index 0000000..0c8b288
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/things.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Things(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M18,0 C21.3137085,-6.08718376e-16 24,2.6862915 24,6 L24,18 C24,21.3137085 21.3137085,24 18,24 L6,24 C2.6862915,24 4.05812251e-16,21.3137085 0,18 L0,6 C-4.05812251e-16,2.6862915 2.6862915,6.08718376e-16 6,0 L18,0 Z M18.7086393,7.35298367 C18.3004026,6.90437204 17.6148815,6.88012726 17.1774851,7.29883146 L17.1774851,7.29883146 L9.81766548,14.3433337 L7.84936511,12.3254383 L7.74730719,12.2330066 C7.32232518,11.8940902 6.70782506,11.9249008 6.31730089,12.3254383 C5.89423304,12.759354 5.89423304,13.4628703 6.31730089,13.8967859 L6.31730089,13.8967859 L9.02563338,16.6745623 L9.12515791,16.7649541 C9.53941942,17.0972627 10.1368988,17.078281 10.5308434,16.7011717 L10.5308434,16.7011717 L18.6558409,8.9233979 L18.7494254,8.82197071 C19.0943185,8.39803056 19.0854731,7.76708672 18.7086393,7.35298367 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thunderbird.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thunderbird.jsx
new file mode 100755
index 0000000..020ace1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/thunderbird.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Thunderbird(props) {
4 return (
5 <Icon {...props}>
6 <path d="M23.7296 10.23c-.225-1.1996-.6936-2.3617-1.3308-3.4113-.1806-.3233-.4172-.6295-.6186-.9185-1.3495-1.8931-2.418-2.5304-2.6241-2.6429-.1874-.1312-.3749-.2624-.5623-.3748-1.7432-1.0872-2.8678-1.2371-2.8678-1.2371-.806-.3374-1.5932-.5248-2.1743-.6186-1.2558-.15-2.3055-.1312-3.2239 0 .15-.2624.2812-.356.3186-.3748.0232 0 .0166 0 0 0-.4498.0375-.9934.3374-1.4807.6373C9.503.6333 10.2153.2583 10.309.202h.0187C9.7655.1646 8.1723.5208 6.804 2.0391 2.549 3.8196 0 7.7183 0 11.973c0 3.224 1.2558 5.5482 2.6241 7.0852 1.2933 1.4058 2.7179 2.1555 3.3926 2.3617.0708.0279.225.0375.225.0375.0187-.0562-.8622-1.462-1.2559-3.149.7873.806 1.7245 1.4246 2.7741 1.537.1125.0188-.3749-.581-.8997-1.3682l.7123.2436 7.8161 2.6054c-.7685.7872-1.7994 1.5557-3.2052 2.2305 0 0 3.149-.2624 4.7047-2.0056-.6373 1.462-2.3805 2.2493-2.3805 2.2493 1.2746-.1875 4.6485-1.1809 6.7853-3.8612 2.4367-3.0365 3.1677-5.8856 2.4367-9.7093zm-6.223 7.1039c-.2436 1.1808-.7497 2.493-1.893 3.7487L1.7993 16.4904c-.3936-1.2558-.581-2.7178-.4686-4.4235.2437.4499.9747.8247 1.4245.8435-1.0496-2.343-.6373-3.955.15-5.0233a635.68 635.68 0 0 1 1.0309 1.5182v-.1125c.0187-.15.0375-.2624.075-.3748-.3562-.5249-.656-.9747-.881-1.2934.4311-.4873.9184-.8434 1.3496-1.0871.0187.2062.0562.3936.1124.6185.075.3187.0937.7873.0562 1.1622v-.0188c0 .075-.0187.15-.0374.225-.0188.075-.225.281-.2812.8247-.0562.581.15.8997.3561 1.1433.2437-.2249.6936-.7872 1.5183-1.1059.8247-.3373 1.3683-.8247 2.418-1.3495.6185-.3186 1.2745-.2812 2.0992-.2437 1.4808.2624 3.4301.7873 5.2483.881.4123.9747.581 2.3804.581 2.418 0 .1311.0188.2436.0188.356-3.224 1.2184-7.0102 2.6054-8.6034 3.0178-.1312.0375-1.5183-1.968-2.8116-3.88-.0187.0375-.0562.0563-.075.075-.0374.0375-.075.075-.0937.1125h-.1124c1.387 2.043 2.8678 4.161 3.0177 4.161 1.4058-.506 5.6044-1.9493 8.6596-2.9989-.0187 2.3055-.581 3.1677-.581 3.1677s.7685-.3 1.5557-1.0871c0 .6372-.1687 2.2867-1.4995 3.8799 0 0 .6935-.1874 1.4807-.5623Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tick-tick.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tick-tick.jsx
new file mode 100755
index 0000000..6efffcb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tick-tick.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function TickTick(props) {
4 return (
5 <Icon {...props}>
6 <path d="M8.948,9.516l-1.691,2.08m-0,-0l3.799,3.128m0,0c0.457,0.412 1.454,0.791 2.328,-0.3m-4.436,-4.908l2.968,2.437m0,0l6.368,-7.963m2.086,1.686l-2.086,-1.686m2.086,1.686l-6.986,8.748m4.9,-10.434l2.086,1.686l-2.086,-1.686Zm-6.368,7.963l8.454,-6.277l-2.086,-1.686l-6.368,7.963Zm8.454,-6.277l-6.986,8.748l-1.468,-2.471m0,0l-0.86,2.771l2.328,-0.3l-1.468,-2.471Zm0,0l-2.968,-2.437l-1.691,2.08l3.799,3.128l0.86,-2.771Zm-0.021,-10.147c-2.704,0.027 -5.286,1.128 -7.178,3.059c-3.939,4.02 -3.873,10.48 0.147,14.418c4.019,3.938 10.479,3.872 14.417,-0.147c1.893,-1.931 2.941,-4.535 2.913,-7.239l-2.549,0.026c0.021,2.028 -0.765,3.981 -2.184,5.429c-2.954,3.015 -7.799,3.064 -10.814,0.111c-3.014,-2.954 -3.063,-7.799 -0.11,-10.814c1.42,-1.448 3.356,-2.274 5.384,-2.294l-0.026,-2.549Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tidal.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tidal.jsx
new file mode 100755
index 0000000..ae8b104
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tidal.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Tidal(props) {
4 return (
5 <Icon {...props}>
6 <path d="M 8.000199 7.999472 L 3.9996765 3.999795 L 0 7.999472 L 3.9996765 11.999994 Z M 12.000882 11.99941 L 15.999887 7.999558 L 20.000323 11.999994 L 24 7.999472 L 20.000323 3.999795 L 16.000223 7.99905 L 12.000633 4.000305 L 8.00011 7.999136 L 12.000384 11.99941 L 8.00011 15.999683 L 12.000633 20.000205 L 16.00031 15.999683 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/todoist.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/todoist.jsx
new file mode 100755
index 0000000..c834873
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/todoist.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Todoist(props) {
4 return (
5 <Icon {...props}>
6 <path d="M0,8.6.68,9c1.19.69,2.38,1.37,3.57,2.07a1.17,1.17,0,0,0,1.28,0c2.07-1.21,4.15-2.4,6.22-3.6l3.32-1.88a.41.41,0,0,0,0-.76l-.71-.4a.82.82,0,0,0-.88,0L12,5.28,5.46,9A1.06,1.06,0,0,1,4.3,9Q2.23,7.82.13,6.61A.25.25,0,0,1,0,6.38,11.54,11.54,0,0,1,.27,3.76,4.76,4.76,0,0,1,4,.21,7.7,7.7,0,0,1,5.77,0C9.59,0,13.4,0,17.22,0a13.31,13.31,0,0,1,2.52.19A4.86,4.86,0,0,1,23.58,4a8.59,8.59,0,0,1,.17,1.59c0,4,0,8,0,11.94A8.81,8.81,0,0,1,23.53,20a4.79,4.79,0,0,1-3.87,3.59,10.15,10.15,0,0,1-2.13.17c-3.75,0-7.51,0-11.26,0a9.23,9.23,0,0,1-2.51-.25A4.8,4.8,0,0,1,.18,19.61,14,14,0,0,1,0,16.79s0,0,0-.06L.46,17c1.26.73,2.53,1.45,3.79,2.19a1.15,1.15,0,0,0,1.27,0l6.24-3.6,3.3-1.88a.4.4,0,0,0,0-.75l-.67-.39a.82.82,0,0,0-.91,0l-1.38.8L5.44,17.16a1.07,1.07,0,0,1-1.12,0L.12,14.71c-.07,0-.12-.07-.12-.17,0-.59,0-1.17,0-1.76,0,0,0-.06,0-.11l.15.08,4.12,2.37a1,1,0,0,0,.79.18,2.09,2.09,0,0,0,.41-.17l6.25-3.6,3.34-1.91a.41.41,0,0,0,.26-.36.4.4,0,0,0-.26-.38l-.71-.41a.79.79,0,0,0-.85,0L12,9.33,5.48,13.09a1.09,1.09,0,0,1-1.19,0L.14,10.67A.22.22,0,0,1,0,10.44c0-.55,0-1.11,0-1.66Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tor-browser.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tor-browser.jsx
new file mode 100755
index 0000000..93408a6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tor-browser.jsx
@@ -0,0 +1,15 @@
1import Icon from "../icon.jsx";
2
3export default function TorBrowser(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M12.02 21.82v-1.46a8.36 8.36 0 0 0 0-16.72V2.18a9.82 9.82 0 0 1 0 19.64Zm0-5.1a4.73 4.73 0 0 0 0-9.45V5.82a6.18 6.18 0 0 1 0 12.36v-1.45Zm0-7.26a2.54 2.54 0 0 1 0 5.08V9.46ZM0 12a12 12 0 1 0 24 0 12 12 0 0 0-24 0Z"
10 />
11 <path d="M12 1.36A10.8 10.8 0 0 0 1.17 12.14 10.8 10.8 0 0 0 12 22.92V1.36Z" />
12 <path d="M12 1.36A10.8 10.8 0 0 0 1.17 12.14 10.8 10.8 0 0 0 12 22.92V1.36Z" />
13 </Icon>
14 );
15}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tower.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tower.jsx
new file mode 100755
index 0000000..9ddfd43
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/tower.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function Tower(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M5.7 1H18v1h1.1l-.9 3.8H17v.9h.7V8h.7l.2 1.3h.7l.8 2.4-3 5.2H17V22h-1v.9H8v-1h-.8V17H7l-3-5.2.9-2.4h.5L5.5 8h.8V6.7h.6v-1H5.6L4.6 2h1V1zm3.2 4.8v.9h.6v-1h-.6zm2.6 0v.9h1v-1h-1zm3 0v.9h.5v-1h-.5zm-5.3 11v3.3h.3v-3.2h-.3zm2.3 0v3.3h1.2v-3.2h-1.2zm3.2 0v3.3h.2v-3.2h-.2zm-3.6-2h2l1.1-2.2H10L11 15zm-3.5-2.2L8.8 15H8l-1.3-2.3h1zm8.9 0L15.3 15h.7l1.3-2.3h-.8z"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/transmit.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/transmit.jsx
new file mode 100755
index 0000000..d9b3c53
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/transmit.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Transmit(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M21.3333333,4 C21.3333333,4 16.4844444,4 13.3333333,4 C10.6666667,4 10.6666667,6.61538462 10.6666667,6.61538462 L10.6666667,16.5538462 C10.6666667,16.5538462 10.6666667,17.0769231 11.2,17.0769231 C12.3479111,17.0769231 15.2590222,17.0769231 15.2590222,17.0769231 C15.7943111,15.7397641 17.1144889,14.7884615 18.6666667,14.7884615 C20.2188444,14.7884615 21.5390222,15.7397641 22.0743111,17.0769231 L23.4666667,17.0769231 C23.4666667,17.0769231 24,17.0769231 24,16.5622154 C24,14.8643077 24,9.39152821 24,6.61538462 C24,4 21.3333333,4 21.3333333,4 Z M6.66666667,15.7692308 C5.19395556,15.7692308 4,16.9402256 4,18.3846154 C4,19.8288308 5.19395556,21 6.66666667,21 C8.13937778,21 9.33333333,19.8288308 9.33333333,18.3846154 C9.33333333,16.9402256 8.13937778,15.7692308 6.66666667,15.7692308 Z M8,6.61538462 C8,6.61538462 3.46666667,6.61538462 3.2,6.61538462 C2.93333333,6.61538462 2.71751111,7.10794872 2.71751111,7.10794872 L0,11.8461538 L0.719644444,16.6009231 C0.719644444,16.6009231 0.8,17.0769231 1.33333333,17.0769231 C1.86666667,17.0769231 3.2592,17.0769231 3.2592,17.0769231 C3.7936,15.7397641 5.11324444,14.7884615 6.66666667,14.7884615 C7.56284444,14.7884615 8.37848889,15.1082359 9.01368889,15.6330564 C9.12604444,15.7258154 9.33333333,15.7692308 9.33333333,15.5076923 L9.33333333,7.88210256 C9.33333333,6.61538462 8,6.61538462 8,6.61538462 Z M6.66666667,11.8461538 L1.91662222,11.8461538 L4,8.18461538 L6.66666667,8.18461538 L6.66666667,11.8461538 Z M18.6666667,15.7692308 C17.1939556,15.7692308 16,16.9402256 16,18.3846154 C16,19.8288308 17.1939556,21 18.6666667,21 C20.1393778,21 21.3333333,19.8288308 21.3333333,18.3846154 C21.3333333,16.9402256 20.1393778,15.7692308 18.6666667,15.7692308 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/trello.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/trello.jsx
new file mode 100755
index 0000000..b999e0b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/trello.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Trello(props) {
4 return (
5 <Icon {...props}>
6 <path d="M 20.5 2 L 4.5 2 C 3.121094 2 2 3.121094 2 4.5 L 2 20.5 C 2 21.878906 3.121094 23 4.5 23 L 20.5 23 C 21.878906 23 23 21.878906 23 20.5 L 23 4.5 C 23 3.121094 21.878906 2 20.5 2 Z M 10.5 18 C 10.5 18.550781 10.050781 19 9.5 19 L 6 19 C 5.449219 19 5 18.550781 5 18 L 5 6 C 5 5.449219 5.449219 5 6 5 L 9.5 5 C 10.050781 5 10.5 5.449219 10.5 6 Z M 20 12 C 20 12.550781 19.550781 13 19 13 L 15.5 13 C 14.949219 13 14.5 12.550781 14.5 12 L 14.5 6 C 14.5 5.449219 14.949219 5 15.5 5 L 19 5 C 19.550781 5 20 5.449219 20 6 Z M 20 12 " />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/twitter.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/twitter.jsx
new file mode 100755
index 0000000..6a6e18b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/twitter.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Twitter(props) {
4 return (
5 <Icon {...props}>
6 <path d="M7.54752,22 C16.60416,22 21.55776,14.3048027 21.55776,7.63156222 C21.55776,7.41299342 21.55776,7.19540915 21.54336,6.97880943 C22.5070381,6.26394259 23.3389013,5.3788064 24,4.36484463 C23.1013239,4.7732353 22.1479961,5.04105778 21.17184,5.15937179 C22.1997542,4.5282613 22.9690786,3.53563394 23.33664,2.36621995 C22.3700712,2.9544411 21.3126203,3.36899003 20.20992,3.59197745 C18.6835995,1.92750143 16.2582906,1.52011507 14.2939673,2.59825725 C12.329644,3.67639943 11.314824,5.97194143 11.81856,8.19767513 C7.85941991,7.99412016 4.17069675,6.07630069 1.6704,2.92150286 C0.363477846,5.22892464 1.03102837,8.18079953 3.19488,9.66267687 C2.41127155,9.63885833 1.6447482,9.42206725 0.96,9.03059951 C0.96,9.05127493 0.96,9.07293491 0.96,9.09459488 C0.960641408,11.498451 2.61288143,13.5688905 4.9104,14.044883 C4.18547481,14.2476401 3.42487736,14.2772791 2.68704,14.1315229 C3.33211001,16.188652 5.18071158,17.5978902 7.28736,17.6384693 C5.54374564,19.0438391 3.38981713,19.8067582 1.17216,19.8044665 C0.780387426,19.8036951 0.388995903,19.779368 0,19.7316102 C2.25181051,21.2136215 4.87191687,21.9997213 7.54752,21.9960618" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/up-arrow.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/up-arrow.jsx
new file mode 100755
index 0000000..f17cb93
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/up-arrow.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function UpArrow(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fill="var(--green)"
8 d="M0 16.67l2.829 2.83 9.175-9.339 9.167 9.339 2.829-2.83-11.996-12.17z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/upload.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/upload.jsx
new file mode 100755
index 0000000..b3b23a1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/upload.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Upload(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11 22a1 1 0 1 1 2 0 1 1 0 0 1-2 0ZM11 16a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0v-3ZM11 4a1 1 0 1 1 2 0v9a1 1 0 1 1-2 0V4Z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M11.293 1.293a1 1 0 0 1 1.414 0l7 7a1 1 0 0 1-1.414 1.414L12 3.414 5.707 9.707a1 1 0 0 1-1.414-1.414l7-7Z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vim.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vim.jsx
new file mode 100755
index 0000000..29b4434
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vim.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Vim(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1 1L0 2v2h1v19h4L24 4V2l-1-1h-8l-1 1v2h1l-6 7V4h1V2L9 1H1z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vivaldi.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vivaldi.jsx
new file mode 100755
index 0000000..7baa302
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vivaldi.jsx
@@ -0,0 +1,14 @@
1import Icon from "../icon.jsx";
2
3export default function Vivaldi(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13.734 18.322c1.482-2.582 2.963-5.16 4.445-7.737.179-.312.253-.645.2-1-.106-.826-.95-1.424-1.761-1.244-.996.223-1.487 1.255-1.028 2.175.168.334.248.694.253 1.117l-.007.082a2.397 2.397 0 01-2.534 2.289c-.87-.053-1.524-.471-1.967-1.217a48.88 48.88 0 01-.58-1c-.106-.184-.21-.368-.316-.55l-.527-.915c-.238-.417-.477-.833-.718-1.245-.305-.524-.77-.804-1.37-.773-1.14.059-1.782 1.27-1.213 2.265.345.606.692 1.21 1.04 1.813a785.449 785.449 0 011.087 1.896c.785 1.37 1.571 2.743 2.365 4.108.311.53.796.788 1.408.746.548-.042.949-.328 1.223-.81z" />
7 <path
8 fillRule="evenodd"
9 clipRule="evenodd"
10 d="M12.4 24.8c-5.257 0-8.177 0-10.091-1.905C.4 20.985.4 18.063.4 12.803.4 7.543.4 4.62 2.309 2.71 4.223.8 7.143.8 12.4.8s8.178 0 10.091 1.905C24.4 4.615 24.4 7.537 24.4 12.797c0 5.26 0 8.182-1.909 10.093-1.913 1.91-4.834 1.91-10.091 1.91zM6.01 6.452c3.511-3.514 9.2-3.514 12.706 0 3.512 3.509 3.512 9.203 0 12.717-3.511 3.514-9.2 3.514-12.706 0-3.506-3.509-3.506-9.203 0-12.717z"
11 />
12 </Icon>
13 );
14}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vl-c.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vl-c.jsx
new file mode 100755
index 0000000..08be0f6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vl-c.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VLC(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.484,13.463 C15.241,13.463 16.338,12.116 16.549,11.789 L15.189,7.455 C14.829,7.795 13.862,8.392 11.509,8.392 C9.217,8.392 8.321,7.825 7.989,7.482 L6.599,11.904 C6.827,12.265 7.854,13.464 11.484,13.464 L11.484,13.463 Z M11.51,3.807 C12.3278545,3.79786067 13.1356496,3.62549025 13.886,3.3 L13.028,0.566 C12.9558148,0.37235421 12.8098209,0.215213036 12.622,0.129 C12.622,0.129 12.507,0 11.625,0 C10.743,0 10.57,0.136 10.57,0.136 C10.3787658,0.215037305 10.2298465,0.371220911 10.16,0.566 L9.276,3.381 C9.99131727,3.64795732 10.7466392,3.79198916 11.51,3.807 L11.51,3.807 Z M22.183,23.319 C22.1886935,23.2651338 22.1832473,23.2106722 22.167,23.159 L19.833,15.527 C19.7449724,15.2777167 19.5141374,15.1070651 19.25,15.096 L17.587,15.096 L17.787,15.736 C17.547,16.221 16.299,18.116 11.484,18.116 C6.884,18.116 5.656,16.386 5.374,15.808 L5.597,15.096 L3.936,15.096 C3.67186257,15.1070651 3.44102757,15.2777167 3.353,15.527 L1.019,23.16 C1.00381596,23.2084576 0.998045517,23.2593733 1.002,23.31 L1,23.33 C1.00334307,23.4057553 1.0113583,23.4812321 1.024,23.556 C1.06406965,23.8081189 1.27877691,23.9954615 1.534,24.001 L21.653,24.001 C21.9082231,23.9954615 22.1229303,23.8081189 22.163,23.556 C22.1753066,23.4812113 22.1829878,23.4057346 22.186,23.33 L22.183,23.319 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vmware-fusion.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vmware-fusion.jsx
new file mode 100755
index 0000000..3ac1b60
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vmware-fusion.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function VMwareFusion(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M14.7931034,0 C16.1505813,0 17.2536047,1.08944868 17.2755295,2.44170167 L17.2758621,2.48275862 L17.2758621,6.72413793 L21.5172414,6.72413793 C22.8884311,6.72413793 24,7.83570683 24,9.20689655 L24,21.5172414 C24,22.8884311 22.8884311,24 21.5172414,24 L9.20689655,24 C7.83570683,24 6.72413793,22.8884311 6.72413793,21.5172414 L6.72413793,17.2758621 L2.48275862,17.2758621 C1.12528079,17.2758621 0.02225734,16.1864134 0.000332618721,14.8341604 L0,14.7931034 L0,2.48275862 C0,1.12528079 1.08944868,0.02225734 2.44170167,0.000332618721 L2.48275862,0 L14.7931034,0 Z M12.4137931,4.24137931 L4.75862069,4.24137931 C4.42361411,4.24137931 4.15059602,4.50678361 4.13835915,4.83879949 L4.13793103,4.86206897 L4.13793103,12.5172414 L4.13835915,12.5405109 C4.15031145,12.8648054 4.41105663,13.1255506 4.73535121,13.1375029 L4.75862069,13.137931 L6.72413793,13.137931 L6.72413793,9.79301127 C6.72413793,9.62161255 6.86308404,9.48266644 7.03448276,9.48266644 C7.11682423,9.48266644 7.19579043,9.51538947 7.25399682,9.57363149 L14.4221152,16.7461375 C14.5432754,16.8673717 14.5432152,17.0638712 14.421981,17.1850313 C14.3637855,17.2431912 14.2848769,17.2758621 14.2026012,17.2758621 L10.862069,17.2758621 L10.862069,17.2758621 L10.862069,19.137931 C10.862069,19.4807285 11.1399612,19.7586207 11.4827586,19.7586207 L19.137931,19.7586207 C19.4729376,19.7586207 19.7459557,19.4932164 19.7581926,19.1612005 L19.7586207,19.137931 L19.7586207,11.4827586 C19.7586207,11.147752 19.4932164,10.874734 19.1612005,10.8624971 L19.137931,10.862069 L17.2758621,10.862069 L17.2758621,14.2986454 C17.2758621,14.4700441 17.136916,14.6089903 16.9655172,14.6089903 C16.8832922,14.6089903 16.8044278,14.5763594 16.7462408,14.5182627 L9.47078596,7.25410006 C9.34949467,7.13299703 9.34934206,6.93649761 9.47044509,6.81520633 C9.52865983,6.75690109 9.6076703,6.72413793 9.69006239,6.72413793 L13.0344828,6.72413793 L13.0344828,6.72413793 L13.0344828,4.86206897 L13.0340546,4.83879949 C13.0218178,4.50678361 12.7487997,4.24137931 12.4137931,4.24137931 Z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-high.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-high.jsx
new file mode 100755
index 0000000..b11c5e3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-high.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VolumeHigh(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.4332 4.0987A1 1 0 0 1 12 5v14a1 1 0 0 1-1.6247.7809L5.6493 16H2c-.5523 0-1-.4477-1-1V9c0-.5523.4477-1 1-1h3.6492l4.7261-3.7809a1 1 0 0 1 1.0579-.1204ZM10 7.0807 6.6247 9.7808A1 1 0 0 1 6 10H3v4h3c.227 0 .4474.0773.6247.2191L10 16.9194V7.0806ZM18.363 4.2227c.3906-.3904 1.0238-.3903 1.4143.0002a11.0003 11.0003 0 0 1 0 15.554c-.3905.3906-1.0237.3907-1.4143.0002-.3905-.3904-.3906-1.0236-.0002-1.4142a8.9996 8.9996 0 0 0 0-12.726c-.3904-.3906-.3903-1.0237.0002-1.4142Zm-3.53 3.53c.3906-.3904 1.0238-.3903 1.4143.0002a6 6 0 0 1 0 8.484c-.3905.3906-1.0237.3907-1.4143.0002-.3905-.3904-.3906-1.0236-.0002-1.4142a3.9999 3.9999 0 0 0 0-5.656c-.3904-.3905-.3903-1.0237.0002-1.4142Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-low.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-low.jsx
new file mode 100755
index 0000000..7da65d4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-low.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VolumeLow(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.4332 4.0987A1 1 0 0 1 12 5v14a1 1 0 0 1-1.6247.7809L5.6493 16H2c-.5523 0-1-.4477-1-1V9c0-.5523.4477-1 1-1h3.6492l4.7261-3.7809a1 1 0 0 1 1.0579-.1204ZM10 7.0807 6.6247 9.7808A1 1 0 0 1 6 10H3v4h3c.227 0 .4474.0773.6247.2191L10 16.9194V7.0806ZM14.833 7.7527c.3906-.3904 1.0238-.3903 1.4143.0003a6.0002 6.0002 0 0 1 0 8.484c-.3905.3905-1.0237.3906-1.4143.0002-.3905-.3905-.3906-1.0237-.0002-1.4142a4.0002 4.0002 0 0 0 0-5.656c-.3904-.3906-.3903-1.0238.0002-1.4143Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-muted.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-muted.jsx
new file mode 100755
index 0000000..b7ca410
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/volume-muted.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function VolumeMuted(props) {
4 return (
5 <Icon {...props}>
6 <path d="M11.4332 4.0987A1 1 0 0 1 12 5v14a1 1 0 0 1-1.6247.7809L5.6493 16H2c-.5523 0-1-.4477-1-1V9c0-.5523.4477-1 1-1h3.6492l4.7261-3.7809a1 1 0 0 1 1.0579-.1204ZM10 7.0807 6.6247 9.7808A1 1 0 0 1 6 10H3v4h3c.227 0 .4474.0773.6247.2191L10 16.9194V7.0806ZM23.7071 8.2929c.3905.3905.3905 1.0237 0 1.4142l-6 6c-.3905.3905-1.0237.3905-1.4142 0-.3905-.3905-.3905-1.0237 0-1.4142l6-6c.3905-.3905 1.0237-.3905 1.4142 0Z" />
7 <path d="M16.2929 8.2929c.3905-.3905 1.0237-.3905 1.4142 0l6 6c.3905.3905.3905 1.0237 0 1.4142-.3905.3905-1.0237.3905-1.4142 0l-6-6c-.3905-.3905-.3905-1.0237 0-1.4142Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n-off.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n-off.jsx
new file mode 100755
index 0000000..7c2ae8b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n-off.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VPNOff(props) {
4 return (
5 <Icon {...props}>
6 <path d="M18 1.5c2.481 0 4.5 2.019 4.5 4.5v4.5h-3v-4.5c0-0.827-0.673-1.5-1.5-1.5h-3c-0.827 0-1.5 0.673-1.5 1.5v4.5h0.375c0.619 0 1.125 0.506 1.125 1.125v11.25c0 0.619-0.506 1.125-1.125 1.125h-12.75c-0.619 0-1.125-0.506-1.125-1.125v-11.25c0-0.619 0.506-1.125 1.125-1.125h9.375v-4.5c0-2.481 2.019-4.5 4.5-4.5h3z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n.jsx
new file mode 100755
index 0000000..a73a27a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vp-n.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VPN(props) {
4 return (
5 <Icon {...props}>
6 <path d="M13.875 10.5h-0.375v-4.5c0-2.481-2.019-4.5-4.5-4.5h-3c-2.481 0-4.5 2.019-4.5 4.5v4.5h-0.375c-0.619 0-1.125 0.506-1.125 1.125v11.25c0 0.619 0.506 1.125 1.125 1.125h12.75c0.619 0 1.125-0.506 1.125-1.125v-11.25c0-0.619-0.506-1.125-1.125-1.125zM4.5 6c0-0.827 0.673-1.5 1.5-1.5h3c0.827 0 1.5 0.673 1.5 1.5v4.5h-6v-4.5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vs-codium.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vs-codium.jsx
new file mode 100755
index 0000000..26f51b4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/vs-codium.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function VSCodium(props) {
4 return (
5 <Icon {...props}>
6 <path d="M15.490073,0.41500893 C15.6570368,0.16641908 15.9559292,0.0010370577 16.2696021,0 C16.709182,-0.00103020955 17.1274126,0.23205506 17.3819638,0.563852738 C17.6217347,0.881179469 17.6956367,1.28223086 17.6961841,1.66519361 C17.6923522,2.20371881 17.5609709,2.73294127 17.4044082,3.24820961 C17.0130013,4.46428427 16.4814544,5.6353957 16.0845734,6.84991989 C15.6471832,8.22827568 15.4375205,9.76426117 16.0249044,11.1327974 C16.3320082,10.3234591 16.6358275,9.51257042 16.9418364,8.70219852 C17.0288766,8.48823553 17.1432878,8.24481385 17.3863432,8.15695465 C17.7246501,8.04325454 18.069526,8.37660265 18.0596724,8.68514351 C17.9671581,9.13477588 17.7876036,9.56321866 17.6463687,10.0004474 C16.5017091,13.2491704 15.2196465,16.4529302 13.9852096,19.6721946 C15.6269285,18.2550774 17.2735742,16.8431284 18.9174829,15.4285953 C19.3904556,15.0218589 19.9033901,14.5789452 20.048457,13.9644476 C20.1929764,13.3613201 19.9241921,12.7628439 19.619278,12.2449915 C19.2672856,11.6268761 18.817852,11.0392532 18.6525306,10.3436151 C18.5693224,9.98339233 18.5945038,9.56890366 18.8517922,9.27380011 C19.0373683,9.05156801 19.3751278,8.93683426 19.6603347,9.04536621 C19.9417096,9.14666268 20.1114105,9.40197117 20.2444341,9.64280875 C20.6911305,10.4888411 20.9697684,11.41343 21.0655672,12.354557 C21.3704814,11.7736527 21.6792274,11.1948156 21.984689,10.6144281 C22.1691702,10.272294 22.332302,9.90535271 22.6317419,9.63505648 C22.8123912,9.46657352 23.0757012,9.36062567 23.3308,9.41540848 C23.6504945,9.4820781 23.8749375,9.7565089 23.9608828,10.0417929 C24.058324,10.3446487 23.9554086,10.6599082 23.8519458,10.9477762 C23.5437472,11.7524631 23.059826,12.4806608 22.5934224,13.2093753 C21.9430849,14.174276 21.2522382,15.1159199 20.4984379,16.0115669 C20.9292591,15.7397202 21.3830721,15.4539194 21.910787,15.3970694 C22.410036,15.3340175 22.9618374,15.6099987 23.1271589,16.0699674 C23.2377382,16.3831596 23.0587312,16.7376974 22.7581964,16.8906757 C22.3175216,17.1227274 21.7958284,17.1196264 21.3058856,17.1402992 C19.528406,17.1862961 17.795815,18.0126894 16.6927594,19.3279932 C15.8223582,20.3771354 15.3778515,21.6805524 14.4943122,22.7209087 C13.9370365,23.3550454 13.1499268,24.1510553 12.2838217,23.975228 C11.1304033,23.7410734 11.1304033,22.0392247 10.8430067,21.1957764 C10.6946553,20.7704345 10.4165648,20.3817868 10.0306323,20.1166587 C9.69342023,19.8815062 9.28942271,19.7466164 8.88104583,19.6727114 C7.94385915,19.502678 6.97711171,19.5926045 6.04211471,19.4101674 C5.57406883,19.3202409 5.11313939,19.1429721 4.75567275,18.8375322 C4.41517619,18.5553491 4.17978471,18.1775546 4.01665291,17.7821882 C3.66411307,16.921168 3.59240075,15.9867596 3.27927531,15.1148863 C2.82600979,13.8595334 1.92933239,12.7499234 0.761133591,12.0129398 C0.514793631,11.8558269 0.247104231,11.7028485 0.0878043913,11.4578764 C-0.0419346487,11.2666534 -0.0304387687,10.9948067 0.139262071,10.8278743 C0.425563831,10.5338044 0.942877751,10.5095139 1.27352067,10.7529356 C1.95122927,11.2067025 2.04921783,12.0883953 2.68094295,12.5819573 C2.68203779,11.7674509 2.67765843,10.9534612 2.67601615,10.1394716 C2.67820583,9.90431908 2.65028731,9.65107786 2.77509955,9.43711486 C2.88841591,9.23452188 3.20208879,9.17973911 3.38438035,9.33168382 C3.63072031,9.52652453 3.70571715,9.8443681 3.74075215,10.1322362 C3.86337471,11.2542498 3.98161787,12.3767803 4.10478787,13.4993107 C4.72392227,12.9742228 5.00858179,12.1219886 4.80822527,11.3576135 C4.74746143,11.1136751 4.64892543,10.8625011 4.70476251,10.6092599 C4.75019855,10.3968474 4.98887459,10.2474868 5.21386507,10.2852145 C5.46677407,10.3177741 5.64742339,10.5224344 5.74212739,10.7327796 C5.89321591,11.0811155 5.89376335,11.4692464 5.86310771,11.8392887 C5.77333047,12.6822202 5.39560919,13.4605493 5.13503627,14.2626521 C4.88103243,14.9706938 4.70640475,15.7572921 4.96095607,16.4885907 C5.18758879,17.172342 5.76238203,17.7129345 6.43680607,18.019408 C7.26943511,18.4054717 8.20716919,18.5253736 9.12464867,18.5594836 C8.56682551,17.6379957 7.96028183,16.6627586 7.97068283,15.5665859 C7.98163127,14.462661 8.72503051,13.5329039 8.92593443,12.4677404 C9.26807323,10.70022 8.42340091,8.77920451 6.85065719,7.765206 C6.15214659,7.31195594 5.31349591,7.11039659 4.59582551,6.69022288 C3.94658287,6.31501243 3.36357831,5.64728254 3.46539883,4.88704209 C3.95862615,4.70667232 4.50933279,4.8219229 4.95438699,5.06379412 C5.82424071,5.50205643 6.37768447,6.33310108 7.25191759,6.7646448 C7.55902139,6.92279135 7.91101383,7.00083101 8.26081655,6.98067506 C8.45022459,6.55223228 8.26081655,6.07210759 7.95535503,5.73824264 C7.38056179,5.08446686 6.41052979,4.92580348 5.80946031,4.30096955 C5.50837815,3.97485688 5.34031959,3.5086863 5.46677407,3.08231079 C5.56968943,2.74534491 5.93919935,2.51587737 6.30706703,2.54120149 C6.85175203,2.57324425 7.32089279,2.89522239 7.69313983,3.24976008 C8.92538699,4.4126024 9.63429863,5.99406797 9.91238907,7.60137445 C10.2408424,9.49706584 9.98574363,11.4310018 9.58119871,13.2977514 C9.50565443,13.67813 9.36441955,14.0683282 9.46897715,14.4564591 C9.51386579,14.6363121 9.65126871,14.82185 9.86202623,14.8378714 C10.15216,14.8554432 10.3919308,14.6688717 10.6032358,14.5055569 C11.2639743,13.9959736 11.7889521,13.310155 12.0057312,12.5245904 C12.1748847,11.9519552 12.1798115,11.3524454 12.1677682,10.7627551 C12.1710527,10.4676516 12.148061,10.1420557 12.334732,9.88674723 C12.4683029,9.68932245 12.71738,9.5342768 12.9735736,9.59164368 C13.1744775,9.62782101 13.3168072,9.79216939 13.3781185,9.96840459 C13.4766545,10.2583399 13.4618741,10.5715321 13.4022051,10.8676693 C13.2133444,11.6842431 13.0425487,12.51167 12.7004099,13.2868982 C12.4589968,13.843512 12.1327332,14.3727345 11.6909635,14.8089295 C11.2037578,15.2962897 10.602141,15.6870047 10.2096393,16.2549886 C9.94194987,16.6431195 9.76896447,17.1253115 9.88501799,17.5888979 C9.96986839,17.9589402 10.2682135,18.2607624 10.6278698,18.4147744 C11.1517528,18.6406242 11.7878572,18.6292542 12.2986021,18.3749793 C12.7036944,18.1682518 12.9916385,17.8106132 13.2210084,17.443155 C13.6250059,16.7821438 13.8697036,16.0482611 14.0727972,15.3133447 C14.3853752,14.1267287 14.569309,12.9101373 14.6415687,11.6894112 C14.7242295,10.3854774 14.4735102,9.0370971 13.7771892,7.89802847 C13.4071319,7.28818225 12.8837963,6.76877937 12.2723258,6.37134567 C11.7216192,5.98476523 11.1161703,5.64986665 10.6694739,5.14906921 C10.2517908,4.6849659 9.96220447,4.05858151 10.1143878,3.44253349 C10.4001422,3.27301693 10.7608934,3.24355824 11.0773034,3.34950612 C11.6745409,3.54124589 12.1420394,3.99397916 12.443669,4.5061466 C12.8531407,5.10979098 13.1947321,5.82816911 13.9162344,6.15583225 C13.3293979,5.06586138 12.7239491,3.98519326 12.1299961,2.89884012 C11.9367561,2.53189875 11.7462532,2.13084736 11.796616,1.71119048 C11.8332933,1.39127965 12.148061,1.12873569 12.4880101,1.13028616 C12.7896397,1.13131979 13.072657,1.2915336 13.2522114,1.51479934 C13.4574947,1.76597329 13.5554832,2.07554775 13.6479976,2.37633631 C14.1215177,3.93196092 14.5944904,5.48706869 15.0696528,7.0421765 C15.6668904,5.96822701 15.919252,4.72372733 15.7495511,3.51850588 C15.6751017,2.87971781 15.4763874,2.26263615 15.3187299,1.63935266 C15.2114352,1.23158263 15.243733,0.774197993 15.490073,0.41500893 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/warp.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/warp.jsx
new file mode 100755
index 0000000..a3e83e5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/warp.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Warp(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.285,2.4 L21.345,2.4 C22.811,2.4 24,3.629 24,5.144 L24,15.798 C24,17.313 22.811,18.542 21.345,18.542 L8.379,18.542 L12.285,2.4 Z" />
7 <path d="M9.931,5.458 L2.633,5.458 C1.179,5.458 0,6.687 0,8.202 L0,18.856 C0,20.371 1.179,21.6 2.633,21.6 L11.616,21.6 L11.976,20.098 L6.42,20.098 L9.931,5.458 Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/web-storm.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/web-storm.jsx
new file mode 100755
index 0000000..3d75c80
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/web-storm.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function WebStorm(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1 1v22h22V1H1zm16.398 2.648c1.324 0 2.445.407 3.362 1.172L19.74 6.348c-.815-.56-1.578-.917-2.343-.917-.764 0-1.171.357-1.171.815v.051c0 .612.407.815 1.935 1.222 1.833.51 2.852 1.172 2.852 2.75v.052c0 1.833-1.375 2.851-3.31 2.851-1.376-.05-2.75-.56-3.82-1.528l1.171-1.426c.815.662 1.68 1.12 2.699 1.12.815 0 1.273-.305 1.273-.865v-.052c0-.51-.305-.763-1.833-1.171-1.833-.458-2.954-.968-2.954-2.801v-.052c0-1.68 1.324-2.75 3.157-2.75l.001.001zM2.63 3.852h2.088l1.375 5.296 1.579-5.296H9.2l1.528 5.296 1.375-5.296h2.138l-2.597 9.115H9.913L8.436 7.671l-1.528 5.296h-1.68L2.63 3.852H2.63zm.458 15.023h8.25v1.375h-8.25v-1.375z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wechat.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wechat.jsx
new file mode 100755
index 0000000..3f814e8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wechat.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Wechat(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.58 12.686c-.559-1.265-1.612-2.27-2.835-2.889-2.158-1.092-4.841-1.086-6.993.028-1.495.767-2.744 2.142-3.098 3.815-.291 1.232-.03 2.558.623 3.63.973 1.616 2.731 2.647 4.557 2.978 1.323.269 2.692.11 3.977-.261.772.299 1.46.783 2.207 1.142-.193-.648-.4-1.289-.62-1.927.84-.596 1.601-1.339 2.058-2.272.681-1.297.723-2.907.123-4.244zm-9.098-8.678c-2.287-1.287-5.135-1.48-7.595-.59-1.617.581-3.08 1.663-3.984 3.134-.82 1.33-1.128 2.987-.733 4.508.397 1.686 1.569 3.1 2.99 4.045-.274.779-.536 1.557-.783 2.342.894-.468 1.787-.956 2.682-1.431a9.955 9.955 0 003.355.475 5.645 5.645 0 01-.234-2.705c.207-1.257.894-2.407 1.828-3.258 1.582-1.48 3.824-2.105 5.955-1.954-.4-1.957-1.775-3.61-3.506-4.565h.025zm1.589 9.157c-.192.598-1.06.777-1.48.323-.464-.421-.284-1.3.325-1.488.673-.284 1.45.492 1.155 1.165zm4.395.084c-.235.538-1.046.663-1.445.248-.191-.175-.247-.44-.315-.67.096-.42.385-.854.853-.875.646-.09 1.224.709.893 1.298h.014zm-6.559-5.916c.008.881-1.168 1.431-1.828.833-.685-.49-.49-1.683.313-1.93.72-.289 1.57.315 1.514 1.086l.002.011zm-5.554.224c-.157.765-1.183 1.135-1.783.621-.696-.49-.501-1.706.316-1.953.8-.308 1.71.504 1.467 1.332z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/whats-app.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/whats-app.jsx
new file mode 100755
index 0000000..02bd081
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/whats-app.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function WhatsApp(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 0A12 12 0 001.6 18L0 24l6.3-1.5A12 12 0 1012 0zm0 2.4a9.5 9.5 0 019.6 9.6 9.6 9.6 0 01-14.2 8.4l-.8-.4-.9.2-2.3.5.5-2.1.3-1-.5-.8A9.6 9.6 0 0112 2.4zm-4.2 4c-.2 0-.6.1-.8.4-.3.3-1 1-1 2.5s1 3 1.1 3.1c.2.2 2.1 3.3 5.2 4.5 2.5 1 3 .8 3.6.8.5 0 1.7-.7 2-1.4.2-.7.2-1.3.2-1.5l-.6-.3-2-1c-.3 0-.5-.1-.7.2l-1 1.1c-.2.2-.3.3-.6.1-.3-.1-1.3-.5-2.4-1.5a9 9 0 01-1.7-2c-.2-.3 0-.5.1-.7.2 0 .3-.3.5-.5l.3-.5v-.5L9 7c-.2-.5-.4-.5-.7-.5h-.5z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/widget.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/widget.jsx
new file mode 100755
index 0000000..48611f5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/widget.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Widget(props) {
4 return (
5 <Icon {...props}>
6 <path d="M16.7 4.5l2.8 2.8-2.8 2.9-2.9-2.8 2.9-2.9M9 5v4H5V5h4m10 10v4h-4v-4h4M9 15v4H5v-4h4m7.7-13.3L11 7.3l5.7 5.7 5.6-5.7-5.6-5.6zM11 3H3v8h8V3zm10 10h-8v8h8v-8zm-10 0H3v8h8v-8z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi-off.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi-off.jsx
new file mode 100755
index 0000000..d2a4690
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi-off.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function WifiOff(props) {
4 return (
5 <Icon {...props}>
6 <path d="M21 11l2-2c-3.73-3.73-8.87-5.15-13.7-4.31l2.58 2.58c3.3-.02 6.61 1.22 9.12 3.73zM9 17l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm10-4c-1.08-1.08-2.36-1.85-3.72-2.33l3.02 3.02.7-.69zM3.41 1.64L2 3.05 5.05 6.1C3.59 6.83 2.22 7.79 1 9l2 2c1.23-1.23 2.65-2.16 4.17-2.78l2.24 2.24C7.79 10.89 6.27 11.74 5 13l2 2c1.35-1.35 3.11-2.04 4.89-2.06l7.08 7.08 1.41-1.41L3.41 1.64z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi.jsx
new file mode 100755
index 0000000..cbf2610
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/wifi.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Wifi(props) {
4 return (
5 <Icon {...props}>
6 <path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/windows.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/windows.jsx
new file mode 100755
index 0000000..b81d452
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/windows.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Windows(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12.428 12.428h9.851v9.851h-9.851Zm-10.714 0h9.851v9.851H1.714ZM12.428 1.714h9.851v9.851h-9.851zm-10.714 0h9.851v9.851H1.714z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/xcode.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/xcode.jsx
new file mode 100755
index 0000000..7c6185b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/xcode.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Xcode(props) {
4 return (
5 <Icon {...props}>
6 <path d="m17.14 9.72.12-.4c.4-1.5.81-3 1.37-4.44.25-.65.67-1.01 1.33-1.1.43-.04.9-.08 1.19.35a1.13 1.13 0 0 0 .73.48 2 2 0 0 1 .43.12c.2.07.27 0 .33-.2l.5-1.8c.2-.69.2-.68-.44-.92-.27-.1-.5-.14-.79-.01-.46.2-.87.12-1.23-.26a3.6 3.6 0 0 0-1.36-.91 9.3 9.3 0 0 0-4.7-.52c-.76.12-1.51.33-2.16.81-.1.07-.17.15-.26.24a11.7 11.7 0 0 1 2.6.03c.57.07 1.08.27 1.47.78.4.53.5 1.16.54 1.8.07.88-.09 1.74-.33 2.59l-.74 2.71c-.03.12-.06.23.1.26l1.3.4Zm-4.12 13.59c.42.04.76-.16.98-.55.13-.23.23-.48.3-.74l1.9-8.24.79-3.42c.05-.23 0-.31-.21-.36l-.85-.24c-.52-.16-.41-.14-.57.3l-3.8 11.17c-.06.15-.1.32-.12.48-.03.94.6 1.6 1.58 1.6ZM.02 6.73l.08.6.58 3.99.57 4.01.96 6.6c.03.18.09.26.3.22l3.65-.6 5.22-.84c.07-.01.12-.1.18-.14-.07-.04-.16-.13-.23-.12l-2.84.45-5.77.93c-.2.04-.27-.02-.29-.21l-.36-2.59L.33 7.09c-.04-.22.03-.33.26-.36l1.16-.18 4.74-.8 8-1.35 1.8-.32c.08-.02.14-.12.2-.19l-.25-.1-.07.02-2.25.39L.22 6.5c-.17.03-.26.08-.2.23Zm19.1-2.3H19c-.02.17-.08.35-.06.52l.27 1.68.72 4.5 1.2 7.4c.03.13 0 .24-.17.27l-3.87.62-1.83.3c-.05.02-.1.1-.14.16.06.04.12.1.18.1l.57-.07 5.6-.93-2.35-14.54Zm-5.1 8.71c.17-.16.14-.27.03-.4L9.27 6.78a1 1 0 0 1-.2-.43c-.04-.3.15-.56.43-.68.3-.12.57-.04.82.28l3.47 4.27.84 1.03c.14-.16.13-.28.02-.4l-1.39-1.72-2.8-3.42a.93.93 0 0 0-.65-.36.9.9 0 0 0-.7.25c-.41.37-.43.89-.05 1.35l4.34 5.42.63.77Zm-4.6-2.91-.17-.11-1.39-.53c-.15-.05-.22 0-.27.13l-2.54 6.42c-.06.16-.01.24.12.3l1.3.55c.24.11.33.05.42-.19l2.51-6.57h.01Zm4.4 2.97-.9-1.18c-.22-.37-.48-.55-.9-.37-.1.04-.22.04-.32.06L9 12.2c-.13.02-.25.06-.31.23l-.55 1.53c-.02.05-.02.12-.03.23l5.7-.97.02-.01Zm-7.53-.61-3.22.53.2 1.5c.03.22.12.25.3.22l1.67-.23c.17-.02.27-.1.34-.25l.62-1.5c.04-.08.05-.14.1-.28Z" />
7 <path d="m18.07 16.9-2.02-1.27c.03.13.02.28.08.36.13.15.29.27.46.36.22.13.47.22.7.34.34.17.59.42.59.85 0 .07.03.14.06.21l.06-.04a2.4 2.4 0 0 0 .3-2.05c-.19-.77-.54-1.44-1.27-1.82-.2-.1-.32-.02-.47.09-.16.11-.24.24-.2.47.1-.07.2-.11.27-.18.16-.18.32-.14.5-.02.74.53 1.2 1.88.94 2.69ZM4.6 19.8l.08.03 2-2.6-.22-.12-1.28-.53c-.2-.09-.26-.03-.27.19l-.19 1.75-.12 1.27ZM8.92 7.87c-.4.03-.65.2-.8.56l-.3.76c-.07.15-.05.23.11.29l1.35.5c.15.07.22.02.28-.13l.32-.79c.14-.35.08-.65-.23-.85-.21-.15-.48-.23-.73-.34Zm7.86 4.76 1.67-.24c.05 0 .11-.13.1-.18l-.24-1.37c-.01-.07-.12-.17-.2-.17-.27.02-.56.06-.84.12-.14.01-.24.08-.16.29l.78-.1c.06 0 .18.05.18.1l.2 1.06-1.25.18c-.15.02-.28.05-.24.31Zm.36-2.92-1.3-.39c-.15-.04-.13-.14-.1-.26l.75-2.7c.24-.86.4-1.72.33-2.6a3.27 3.27 0 0 0-.55-1.8c-.38-.5-.9-.7-1.47-.78-.86-.1-1.72-.12-2.59-.03.1-.08.16-.17.26-.24.65-.44 1.4-.72 2.17-.8a9.32 9.32 0 0 1 4.68.52c.52.19.98.5 1.36.9a1.02 1.02 0 0 0 1.24.26c.28-.12.52-.08.79.02.64.24.64.22.45.91l-.52 1.81c-.05.19-.12.26-.32.2-.14-.06-.29-.1-.44-.12a1 1 0 0 1-.72-.5c-.3-.41-.76-.38-1.2-.33-.65.08-1.07.44-1.32 1.1a44.38 44.38 0 0 0-1.37 4.43l-.12.4Zm-4.12 13.6c-.97-.01-1.6-.66-1.58-1.61.01-.16.06-.32.11-.48l3.81-11.16c.15-.44.06-.45.57-.3l.85.24c.2.05.26.14.2.36l-.77 3.42-1.92 8.24c-.06.26-.16.51-.29.74-.09.18-.23.33-.4.43a.99.99 0 0 1-.58.12ZM.02 6.72c-.06-.14.03-.2.2-.22l13.71-2.32 2.24-.39c.03 0 .06-.02.08-.01l.24.1c-.06.06-.11.17-.19.18l-1.8.32-3.85.65-4.15.7-4.75.8-1.16.18c-.22.03-.29.14-.26.36l1.74 11.95.37 2.58c.02.2.08.25.29.21l5.76-.93 2.85-.44c.06 0 .15.07.22.11-.05.05-.1.14-.18.15l-5.2.84-3.67.6c-.2.04-.27-.05-.29-.23l-.37-2.56-.59-4.03L.7 11.3.02 6.74Zm19.1-2.3L21.48 19l-1.32.23-4.27.7-.57.07c-.06.01-.13-.05-.19-.09.05-.05.1-.14.15-.15l1.83-.31 3.86-.63c.17-.02.19-.13.17-.27l-.47-2.88-1.72-10.69c-.02-.17.03-.34.06-.52l.1-.01h.01Z" />
8 <path d="m14.03 13.14-.63-.77-4.34-5.4c-.38-.47-.37-.98.05-1.36.42-.38.99-.35 1.36.1l4.18 5.14c.1.13.13.25-.02.4l-.84-1.02-3.47-4.28c-.25-.31-.52-.4-.82-.28-.29.12-.47.4-.43.69.02.15.1.31.2.43l4.78 5.94c.11.13.15.25-.02.41Zm-4.62-2.91-.08.24-2.44 6.35c-.1.24-.18.3-.41.18l-1.3-.55c-.15-.06-.2-.13-.13-.3L7.6 9.75c.05-.14.12-.2.27-.13l1.38.52c.07.02.11.07.16.1Zm-1.58-.34-.32.82-2.08 5.24c-.08.2-.04.3.14.36l.8.33c.2.1.28.07.36-.15l2.35-6.14-1.25-.46Zm6 3.31-5.71.96c.01-.09.01-.15.04-.22l.54-1.53c.06-.17.18-.21.32-.23l2.69-.48c.1-.02.22-.01.32-.05.42-.18.67 0 .9.36.26.4.56.75.9 1.18v.01Zm-5.34.63 4.84-.83-.8-1.03c-.04-.05-.15-.08-.23-.07l-.69.1-2.38.44c-.1.02-.25.08-.28.16-.17.39-.3.79-.46 1.23Zm-2.2-1.24-.09.26-.62 1.5c-.07.16-.17.22-.34.25l-1.66.23c-.2.03-.28 0-.3-.22l-.21-1.5 3.22-.52Zm-.41.34-2.28.39c-.08 0-.2.13-.2.2.02.3.08.6.14.89a.24.24 0 0 0 .18.12l1.36-.2c.09 0 .22-.05.25-.12l.54-1.28Zm12.2 3.96c.25-.81-.2-2.15-.95-2.67-.18-.13-.33-.17-.5.01-.07.07-.16.12-.27.2-.04-.25.04-.38.2-.48.15-.12.27-.2.47-.1.73.4 1.08 1.06 1.28 1.84a2.4 2.4 0 0 1-.26 1.98l-.05.07-.06.03c-.02-.07-.06-.14-.06-.21 0-.43-.25-.68-.6-.85l-.7-.34c-.16-.1-.32-.21-.45-.36-.06-.08-.05-.23-.08-.36l2.02 1.25ZM4.6 19.8l.12-1.27.18-1.75c.02-.21.07-.28.27-.2l1.28.54.23.13-2.01 2.59a.6.6 0 0 1-.07-.04Zm.34-.8.05.02 1.28-1.68-1.11-.45L4.94 19ZM8.92 7.88c.25.1.52.19.73.34.31.21.38.5.23.86l-.32.79c-.05.14-.13.2-.29.14L7.93 9.5c-.16-.06-.17-.15-.11-.3l.3-.75c.15-.36.4-.53.8-.57ZM8.1 9.25l1.12.43c.04 0 .14-.05.16-.11l.26-.61c.1-.2.05-.38-.11-.48-.2-.12-.4-.2-.61-.26-.24-.05-.43.06-.52.3l-.3.73Zm8.68 3.4c-.05-.27.09-.3.23-.32l1.25-.18-.2-1.06c0-.04-.11-.1-.18-.1l-.77.1c-.07-.21.02-.28.16-.3l.84-.11c.07 0 .18.1.2.17l.24 1.37c0 .05-.06.18-.1.18l-1.68.24Z" />
9 <path d="m7.83 9.9 1.25.46-2.35 6.14c-.08.21-.17.25-.37.15a6.65 6.65 0 0 0-.79-.33c-.18-.07-.22-.15-.14-.36l2.07-5.25.33-.82Zm.66 3.93.45-1.23c.03-.08.18-.14.28-.16l2.39-.43.69-.11c.07 0 .18.02.23.07l.8 1.04-4.84.82Zm-2.61-.9-.55 1.27c-.04.07-.16.12-.25.13l-1.36.2c-.06 0-.17-.07-.18-.13a6.45 6.45 0 0 1-.13-.89c-.01-.06.11-.19.19-.2l2.28-.38ZM4.94 19l.23-2.1 1.1.44L5 19.01l-.06-.02ZM8.1 9.25l.3-.73c.1-.24.28-.34.52-.29.21.05.42.14.6.26.16.1.2.28.12.47l-.27.62c-.02.05-.12.11-.16.1L8.1 9.25Z" />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/youtube-music.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/youtube-music.jsx
new file mode 100755
index 0000000..fe7e130
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/youtube-music.jsx
@@ -0,0 +1,13 @@
1import Icon from "../icon.jsx";
2
3export default function YoutubeMusic(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M12 24c6.627 0 12-5.373 12-12S18.627 0 12 0 0 5.373 0 12s5.373 12 12 12Zm0-17.727A5.735 5.735 0 0 1 17.727 12 5.727 5.727 0 0 1 12 17.727 5.727 5.727 0 0 1 6.273 12 5.735 5.735 0 0 1 12 6.273Zm0-.546a6.274 6.274 0 0 0 0 12.546 6.274 6.274 0 0 0 0-12.546Zm3.136 6.137-5.318 3.272V8.864l5.318 3Z"
9 clipRule="evenodd"
10 />
11 </Icon>
12 );
13}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zed.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zed.jsx
new file mode 100755
index 0000000..95e4415
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zed.jsx
@@ -0,0 +1,10 @@
1import Icon from "../icon.jsx";
2
3export default function Zed(props) {
4 return (
5 <Icon {...props}>
6 <path d="M.3711 2.407v16.0398h1.4265V2.2836c.0697-.289.193-.3793.4962-.4319l18.8542.0617-2.5428 2.5294H5.3328c-.5379.237-.7383.4637-.9303 1.0487v9.4389h1.3644V5.8h11.4118l-2.5428 2.591H9.116c-.4555.1505-.5859.3412-.7442.7403v2.0976h1.4885V9.8716h3.2251L.9294 22.025c-.2067.8577-.0354 1.179.6822 1.5423l20.2807.0617c1.1526-.533 1.4894-.9714 1.7366-1.9125V6.7254l-1.4885 1.2955v13.6955l-.3722.3702H2.852l2.4808-2.4677H18.419c.8553-.2822 1.1666-.5779 1.2404-1.4806V8.8846l-1.4885 1.5423v7.7114H6.8833l2.4808-2.4677h5.5819c.3855-.1615.5174-.3076.6822-.6169v-2.3442h-1.4265v1.4189h-3.2871L23.1947 1.79c.0618-.79-.166-1.108-1.0543-1.4189H2.2317C.9463.6967.5801 1.1812.3711 2.407Z" />
7 <path d="M0 18.8179V2.3755l.0053-.031C.1128 1.7143.2706 1.2009.6197.8058c.3515-.3979.851-.6247 1.521-.7943L2.1854 0h20.018l.0595.0208c.4565.1598.8287.3472 1.0594.6597.2402.3253.2756.7133.2423 1.1385l-.0106.136-11.7465 11.8022h2.023v-1.4189h2.1687v2.8081l-.0436.0819c-.0893.1675-.1862.3234-.332.4601-.1462.137-.3197.2346-.5343.3245l-.0688.0289H9.5173l-1.7346 1.7254h10.0172V10.277l2.2308-2.3114v10.1879l-.0013.0151c-.0396.4848-.1476.8779-.4175 1.1869-.263.301-.6365.4707-1.0765.6159l-.0566.0186H5.4859l-1.7346 1.7254h17.8638l.1541-.1533V7.8519L24 5.9103v15.854l-.0122.0464c-.1303.4962-.2954.9046-.6093 1.2605-.3095.3508-.7364.6198-1.3304.8945l-.0747.0345-20.451-.0622-.0785-.0397c-.3736-.1892-.6954-.4085-.8575-.7623-.1611-.3518-.1254-.7518-.0179-1.198l.0245-.1017 11.5962-11.5935h-1.9578V11.6H8.0007V9.0604l.0261-.0659c.0818-.2061.1748-.41.3352-.5807.1663-.177.3755-.2886.6376-.3752l.0567-.0187h5.4238l1.8144-1.8488H6.1381v9.1304H4.0313V5.4322l.0186-.0564c.1023-.3118.2198-.5705.4103-.7853.192-.2165.4315-.359.723-.4873l.0714-.0316H18.452l1.7996-1.79L2.3269 2.223a.6643.6643 0 0 0-.1004.026.1748.1748 0 0 0-.0282.0131l-.0008.0005-.0003.0004a.0694.0694 0 0 0-.0064.0105.332.332 0 0 0-.022.0583v16.4861H0ZM1.7976 2.2836c.0697-.289.193-.3793.4962-.4319l18.8542.0617-2.5428 2.5294H5.3328c-.5379.237-.7383.4637-.9303 1.0487v9.4389h1.3644V5.8h11.4118l-2.5428 2.591H9.116c-.4555.1505-.5859.3412-.7442.7403v2.0976h1.4885V9.8716h3.2251L.9294 22.025c-.2067.8577-.0354 1.179.6822 1.5423l20.2807.0617c1.1526-.533 1.4894-.9714 1.7366-1.9125V6.7254l-1.4885 1.2955v13.6955l-.3722.3702H2.852l2.4808-2.4677H18.419c.8553-.2822 1.1666-.5779 1.2404-1.4806V8.8846l-1.4885 1.5423v7.7114H6.8833l2.4808-2.4677h5.5819c.3855-.1615.5174-.3076.6822-.6169v-2.3442h-1.4265v1.4189h-3.2871L23.1947 1.79c.0618-.79-.166-1.108-1.0543-1.4189H2.2317C.9463.6967.5801 1.1812.3711 2.407v16.0398h1.4265V2.2836Z" />
8 </Icon>
9 );
10}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zen-browser.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zen-browser.jsx
new file mode 100755
index 0000000..b417df7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zen-browser.jsx
@@ -0,0 +1,11 @@
1import Icon from "../icon.jsx";
2
3export default function ZenBrowser(props) {
4 return (
5 <Icon {...props}>
6 <path d="M12 16.615a4.615 4.615 0 1 0 0-9.23 4.615 4.615 0 0 0 0 9.23ZM15.692 12a3.692 3.692 0 1 1-7.384 0 3.692 3.692 0 0 1 7.384 0Z" />
7 <path d="M20 12a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-8 6.462a6.461 6.461 0 1 0 0-12.923 6.461 6.461 0 0 0 0 12.923Z" />
8 <path d="M24 12c0 6.627-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0s12 5.373 12 12Zm-12 9.846c5.438 0 9.846-4.408 9.846-9.846S17.438 2.154 12 2.154 2.154 6.562 2.154 12 6.562 21.846 12 21.846Z" />
9 </Icon>
10 );
11}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zeplin.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zeplin.jsx
new file mode 100755
index 0000000..bf45e51
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zeplin.jsx
@@ -0,0 +1,43 @@
1import Icon from "../icon.jsx";
2
3export default function Zeplin(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 clipRule="evenodd"
9 d="M3.7 15.23l-1.26.46-.06 3.73 4.34-1.59c-1.49-.5-2.58-1.38-3.02-2.6zM4.36 11.28L0 12.87l2.44 2.82 1.26-.46c-.44-1.22-.17-2.6.66-3.95z"
10 />
11 <path
12 fillRule="evenodd"
13 clipRule="evenodd"
14 d="M11.69 5.89c-5.55 2.02-9.13 6.2-8 9.34l20.1-7.34c-1.14-3.13-6.56-4.03-12.1-2z"
15 />
16 <path
17 fillRule="evenodd"
18 clipRule="evenodd"
19 d="M15.8 17.23c5.55-2.03 9.13-6.2 7.99-9.34l-20.1 7.34c1.15 3.15 6.56 4.02 12.11 2z"
20 />
21 <path
22 fillRule="evenodd"
23 clipRule="evenodd"
24 d="M23.79 7.89l-20.1 7.34c.4 1.08 1.9 1.62 4 1.62 2.06 0 4.69-.51 7.42-1.51 5.55-2.03 9.45-5.3 8.68-7.45z"
25 />
26 <path
27 fillRule="evenodd"
28 clipRule="evenodd"
29 d="M19.79 6.27c-2.05 0-4.68.5-7.42 1.5-5.54 2.03-9.45 5.31-8.67 7.46l20.09-7.34c-.4-1.09-1.9-1.62-4-1.62z"
30 />
31 <path
32 fillRule="evenodd"
33 clipRule="evenodd"
34 d="M18.68 19.62c-.6 0-1.46-.54-2.6-1.59a33.48 33.48 0 0 1-4.3-5.14 33.54 33.54 0 0 1-3.34-5.81c-.77-1.84-.88-2.97-.32-3.36a.74.74 0 0 1 .43-.13c.46 0 1.34.34 2.96 1.94l.04.03v.05l-.03.35-.02.23-.16-.16C9.58 4.26 8.8 4.07 8.56 4.07a.3.3 0 0 0-.17.04c-.24.17-.26 1 .5 2.78.69 1.65 1.86 3.69 3.28 5.73a33 33 0 0 0 4.24 5.06c1.42 1.32 2.05 1.46 2.26 1.46a.3.3 0 0 0 .18-.04c.25-.18.25-1.07-.59-2.99l-.03-.08.08-.05.24-.13.1-.06.05.1c.6 1.36 1.15 3.09.42 3.6a.75.75 0 0 1-.44.13zm0-.21v.1-.1z"
35 />
36 <path
37 fillRule="evenodd"
38 clipRule="evenodd"
39 d="M15.93 17.17v.1c-.14 1.74-.51 3.83-1.48 3.91h-.06c-.65 0-1.27-.93-1.83-2.78-.54-1.75-.96-4.1-1.18-6.61-.21-2.52-.21-4.9.01-6.72.25-1.97.72-3 1.4-3.07h.05c.48 0 1.2.54 1.92 3.04l-.47.1a9.78 9.78 0 0 0-.78-2c-.24-.42-.48-.66-.67-.66h-.02c-.29.02-.72.74-.95 2.65a33.14 33.14 0 0 0-.01 6.62c.21 2.48.62 4.8 1.15 6.5.24.78.5 1.41.75 1.84.23.4.46.62.63.62h.02c.28-.03.81-.77 1.03-3.37l.5-.17z"
40 />
41 </Icon>
42 );
43}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zoom.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zoom.jsx
new file mode 100755
index 0000000..d0e9610
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zoom.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Zoom(props) {
4 return (
5 <Icon {...props}>
6 <path d="M17.2536,8.02493913 L17.2536,18.4441739 L3.92128696,18.4441739 C3.92128696,18.4441739 0.111965217,18.8923478 0,14.9711652 L0,5 L13.780487,5 C13.780487,5 17.1415304,5.33610435 17.2536,8.02493913 Z M23.9755826,5 L23.9755826,18.4598261 L18.0381913,14.5230957 L18.0381913,9.03335652 L23.9755826,5 Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zotero.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zotero.jsx
new file mode 100755
index 0000000..1223d35
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zotero.jsx
@@ -0,0 +1,12 @@
1import Icon from "../icon.jsx";
2
3export default function Zotero(props) {
4 return (
5 <Icon {...props}>
6 <path
7 fillRule="evenodd"
8 d="M8.6 16.2L17 7.4s.6-.8.4-1.4c-.2-.5-1.3-.5-1.3-.5H4.5v2.3h8.8l-8.1 8.4s-1 .7-.7 1.5c.2.8 1.3.8 1.3.8h11.6v-2.3zm12-11.4L12.4.4S11.6 0 11 0 9.5.4 9.5.4l-8 4.4s-.7.5-1 1C0 6.6 0 7.3 0 7.3v9.6s0 .7.4 1.3c.4.6.9.8.9.8l8.2 4.7s1 .4 1.5.4c.4 0 1.5-.4 1.5-.4l8.2-4.7s.5-.2.9-.8c.4-.6.4-1.3.4-1.3V7.2s0-.6-.4-1.3c-.4-.7-1-1-1-1z"
9 />
10 </Icon>
11 );
12}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zulip.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zulip.jsx
new file mode 100755
index 0000000..8b94751
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/icons/library/zulip.jsx
@@ -0,0 +1,9 @@
1import Icon from "../icon.jsx";
2
3export default function Zulip(props) {
4 return (
5 <Icon {...props}>
6 <path d="M22.77 3.59c0 1.2-.55 2.28-1.37 2.93l-8.04 7.18c-.15.13-.34-.08-.23-.25l2.94-5.9c.09-.17-.02-.37-.19-.37H4.45c-1.77 0-3.22-1.62-3.22-3.59C1.23 1.61 2.68 0 4.45 0h15.1c1.77 0 3.22 1.61 3.22 3.59ZM4.45 24h15.1c1.77 0 3.22-1.62 3.22-3.59 0-1.97-1.45-3.59-3.22-3.59H8.12c-.17 0-.28-.2-.2-.37l2.95-5.9c.11-.17-.08-.38-.23-.25L2.6 17.48a3.73 3.73 0 0 0-1.37 2.93c0 1.97 1.45 3.59 3.22 3.59Z" />
7 </Icon>
8 );
9}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missive.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missive.jsx
new file mode 100755
index 0000000..eec0ace
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missive.jsx
@@ -0,0 +1,48 @@
1import * as Uebersicht from "uebersicht";
2import { SuspenseIcon } from "../icons/icon.jsx";
3import * as Icons from "../icons/icons.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils.js";
6
7const { React } = Uebersicht;
8
9/**
10 * Missive component to display a notification.
11 * @param {Object} props - The properties object.
12 * @param {string} props.id - The unique identifier for the missive.
13 * @param {string} props.side - The side where the missive should appear ('left' or 'right').
14 * @param {string} props.content - The content of the missive.
15 * @param {number} [props.timeout] - The timeout for the missive to auto-close.
16 * @returns {JSX.Element} The Missive component.
17 */
18export default function Missive({ id, side, content, timeout }) {
19 // Get the setMissives function from the context
20 const { setMissives } = useSimpleBarContext();
21
22 // Generate class names based on the side prop
23 const classes = Utils.classNames("missive", {
24 "missive--left": side === "left",
25 "missive--right": side === "right",
26 });
27
28 // Close the missive by removing it from the context and clearing the timeout.
29 const closeMissive = () => {
30 setMissives((current) => {
31 return current.filter((m) => m.id !== id);
32 });
33 if (timeout) {
34 clearTimeout(timeout);
35 }
36 };
37
38 return (
39 <div key={id} className={classes}>
40 <div className="missive__text">{content}</div>
41 <button className="missive__close" onClick={closeMissive}>
42 <SuspenseIcon>
43 <Icons.Close className="missive__close-icon" />
44 </SuspenseIcon>
45 </button>
46 </div>
47 );
48}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missives.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missives.jsx
new file mode 100755
index 0000000..3563937
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/missives/missives.jsx
@@ -0,0 +1,40 @@
1import * as Uebersicht from "uebersicht";
2import { useSimpleBarContext } from "../simple-bar-context.jsx";
3import Missive from "./missive.jsx";
4import useServerSocket from "../../hooks/use-server-socket.js";
5
6export { missivesStyles as styles } from "../../styles/components/missives";
7
8const { React } = Uebersicht;
9
10/**
11 * Component to display a list of missives.
12 * It uses the simple-bar context to get settings and missives data.
13 * It also sets up a server socket to receive new missives.
14 *
15 * @returns {JSX.Element} The rendered component.
16 */
17export function Component() {
18 // Destructure settings, missives, and pushMissive function from the context
19 const { settings, missives, pushMissive } = useSimpleBarContext();
20 const { enableServer } = settings.global;
21
22 // Set up a server socket to listen for "missive" events and push new missives
23 useServerSocket("missive", enableServer, pushMissive);
24
25 return (
26 <div className="missives">
27 {missives.map(({ id, side, content, timeout }) => {
28 return (
29 <Missive
30 key={id}
31 id={id}
32 side={side}
33 content={content}
34 timeout={timeout}
35 />
36 );
37 })}
38 </div>
39 );
40}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/aerospace-display-manager.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/aerospace-display-manager.jsx
new file mode 100755
index 0000000..8c4fa98
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/aerospace-display-manager.jsx
@@ -0,0 +1,83 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils";
3import * as Icons from "../icons/icons.jsx";
4
5const { React } = Uebersicht;
6
7/**
8 * UserWidgetsCreator component allows users to create and manage custom widgets.
9 * @param {Object} props - The component props.
10 * @param {Object} props.defaultValue - The default value for the widgets.
11 * @param {Function} props.onChange - The function to call when the widgets change.
12 * @returns {JSX.Element} The UserWidgetsCreator component.
13 */
14export default function AerospaceDisplayManager({ defaultValue, onChange }) {
15 const [indexes, setIndexes] = React.useState(defaultValue || {});
16 const [displays, setDisplays] = React.useState(Object.keys(defaultValue));
17
18 const addDisplay = () => {
19 setDisplays((current) => {
20 const highest = Math.max(...current, 0);
21 const newIndex = highest + 1;
22 setIndexes((current) => {
23 return { ...current, [newIndex]: Number(current[newIndex]) || 1 };
24 });
25 return [...current, newIndex];
26 });
27 };
28
29 const removeDisplay = (index) => {
30 setDisplays((current) => {
31 const newDisplays = current.filter((display) => display !== index);
32 setIndexes((current) => {
33 const newIndexes = { ...current };
34 delete newIndexes[index];
35 return newIndexes;
36 });
37 return newDisplays;
38 });
39 };
40
41 React.useEffect(() => {
42 const diffs = Utils.compareObjects(defaultValue, indexes);
43 const hasDiffs = Object.keys(diffs).length > 0;
44 if (hasDiffs) onChange({ target: { value: indexes } });
45 }, [defaultValue, onChange, indexes]);
46
47 return (
48 <div className="aerospace-display-manager">
49 <div className="aerospace-display-manager__label">
50 <em>AeroSpace</em> Custom display indexes
51 </div>
52 <div className="aerospace-display-manager__displays">
53 {displays.map((display) => {
54 const index = indexes[display] || 1;
55
56 const updateIndex = (e) => {
57 const value = e.target.value;
58 setIndexes((current) => {
59 return { ...current, [display]: Number(value) };
60 });
61 };
62
63 return (
64 <div key={display} className="aerospace-display-manager__display">
65 <span>{display}</span>:
66 <input type="number" value={index} onChange={updateIndex} />
67 <button
68 className="aerospace-display-manager__remove-display"
69 onClick={() => removeDisplay(display)}
70 >
71 <Icons.Close />
72 </button>
73 </div>
74 );
75 })}
76 </div>
77 <button className="aerospace-display-manager__add" onClick={addDisplay}>
78 <Icons.Add />
79 Add a display
80 </button>
81 </div>
82 );
83}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/color-picker.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/color-picker.jsx
new file mode 100755
index 0000000..dbff879
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/color-picker.jsx
@@ -0,0 +1,109 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "../../settings";
3
4const { React } = Uebersicht;
5
6/**
7 * ColorPicker component allows users to select a color from predefined options or input a custom color.
8 * @param {Object} props - The component props.
9 * @param {Function} props.callback - The callback function to handle color selection.
10 * @param {number} props.index - The index of the color picker.
11 * @param {string} props.selectedColor - The initially selected color.
12 * @returns {JSX.Element} The ColorPicker component.
13 */
14export default function ColorPicker({ callback, index, selectedColor }) {
15 // Determine if the selected color is a custom color
16 const isSelectedCustom = !Settings.userWidgetColors.includes(selectedColor);
17 // State to manage the open/close status of the color picker
18 const [open, setOpen] = React.useState(false);
19 // State to manage the currently selected color
20 const [selected, setSelected] = React.useState(selectedColor);
21 // State to manage the custom color input
22 const [customColor, setCustomColor] = React.useState(
23 isSelectedCustom ? selectedColor : undefined,
24 );
25
26 // Toggle the color picker open/close status
27 const onClick = () => setOpen(!open);
28
29 /**
30 * Handle custom color input change.
31 * @param {Object} e - The event object.
32 */
33 const onCustomColorChange = (e) => {
34 const value = e.target.value;
35 setCustomColor(value);
36 callback?.(index, "backgroundColor", value);
37 };
38
39 /**
40 * Handle custom color submission.
41 */
42 const onCustomColorSubmit = () => {
43 setSelected(customColor);
44 setOpen(false);
45 };
46
47 return (
48 <div className="color-picker">
49 <button
50 className="color-picker__button"
51 style={{
52 backgroundColor: isSelectedCustom ? customColor : `var(${selected})`,
53 }}
54 onClick={onClick}
55 />
56 {open && (
57 <div className="color-picker__colors" onClick={() => setOpen(false)}>
58 {Settings.userWidgetColors.map((color) => {
59 /**
60 * Handle predefined color selection.
61 * @param {Object} e - The event object.
62 */
63 const onClick = (e) => {
64 e.stopPropagation();
65 setCustomColor(undefined);
66 setSelected(color);
67 callback?.(index, "backgroundColor", color);
68 setOpen(false);
69 };
70 return (
71 <button
72 key={color}
73 onClick={onClick}
74 style={{ backgroundColor: `var(${color})` }}
75 />
76 );
77 })}
78 <div
79 className="color-picker__custom-color"
80 onClick={(e) => e.stopPropagation()}
81 >
82 <div
83 className="color-picker__custom-color-preview"
84 style={{ backgroundColor: customColor }}
85 />
86 <input
87 type="text"
88 className="color-picker__custom-color-input"
89 placeholder="Or any valid css color value (hex, rgb-a, hsl)"
90 onChange={onCustomColorChange}
91 defaultValue={customColor}
92 autoCapitalize="false"
93 autoComplete="false"
94 autoCorrect="false"
95 spellCheck={false}
96 />
97 <button
98 className="color-picker__custom-color-submit"
99 disabled={!customColor}
100 onClick={onCustomColorSubmit}
101 >
102 Ok
103 </button>
104 </div>
105 </div>
106 )}
107 </div>
108 );
109}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/icon-picker.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/icon-picker.jsx
new file mode 100755
index 0000000..ca3bdab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/icon-picker.jsx
@@ -0,0 +1,130 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import { SuspenseIcon } from "../icons/icon.jsx";
4
5const { React } = Uebersicht;
6
7/**
8 * IconPicker component allows users to select an icon from a list of available icons.
9 *
10 * @param {Object} props - The component props.
11 * @param {Function} props.callback - The callback function to be called when an icon is selected.
12 * @param {number} props.index - The index of the icon picker.
13 * @param {string} props.selectedIcon - The initially selected icon.
14 * @returns {JSX.Element} The IconPicker component.
15 */
16export default function IconPicker({ callback, index, selectedIcon }) {
17 // State to manage the open/close state of the icon picker dropdown
18 const [open, setOpen] = React.useState(false);
19 // State to manage the currently selected icon
20 const [selected, setSelected] = React.useState(selectedIcon);
21 // State to manage the search term for filtering icons
22 const [searchTerm, setSearchTerm] = React.useState("");
23
24 // Get the selected icon component
25 const Icon = Icons[selected];
26 // Get the list of all available icon keys
27 const keys = Object.keys(Icons);
28
29 // Filter icons based on search term
30 const filteredKeys = React.useMemo(() => {
31 if (!searchTerm.trim()) {
32 return keys;
33 }
34 return keys.filter((key) =>
35 key.toLowerCase().includes(searchTerm.toLowerCase()),
36 );
37 }, [keys, searchTerm]);
38
39 /**
40 * Toggles the open state of the icon picker dropdown.
41 */
42 const onClick = () => setOpen(!open);
43
44 /**
45 * Handles search input changes.
46 *
47 * @param {React.ChangeEvent<HTMLInputElement>} e - The input change event.
48 */
49 const onSearchChange = (e) => {
50 setSearchTerm(e.target.value);
51 };
52
53 /**
54 * Clears the search term.
55 */
56 const clearSearch = () => {
57 setSearchTerm("");
58 };
59
60 return (
61 <div className="icon-picker">
62 <button className="icon-picker__button" onClick={onClick}>
63 <SuspenseIcon>
64 <Icon />
65 </SuspenseIcon>
66 </button>
67 {open && (
68 <div className="icon-picker__dropdown">
69 <div
70 className="icon-picker__search"
71 onClick={(e) => e.stopPropagation()}
72 >
73 <button
74 className="icon-picker__back"
75 onClick={() => setOpen(false)}
76 type="button"
77 >
78 <Icons.ChevronLeft />
79 Back
80 </button>
81 <input
82 type="text"
83 placeholder="Search icons..."
84 value={searchTerm}
85 onChange={onSearchChange}
86 className="icon-picker__search-input"
87 autoFocus
88 />
89 {searchTerm && (
90 <button
91 className="icon-picker__search-clear"
92 onClick={clearSearch}
93 type="button"
94 >
95 ✕
96 </button>
97 )}
98 </div>
99 <div className="icon-picker__icons" onClick={() => setOpen(false)}>
100 {filteredKeys.length > 0 ? (
101 filteredKeys.map((key) => {
102 /**
103 * Handles the icon selection.
104 *
105 * @param {React.MouseEvent} e - The click event.
106 */
107 const onClick = (e) => {
108 e.stopPropagation();
109 setSelected(key);
110 callback?.(index, "icon", key);
111 setOpen(false);
112 };
113 const Icon = Icons[key];
114 return (
115 <button key={key} onClick={onClick} title={key}>
116 <Icon />
117 </button>
118 );
119 })
120 ) : (
121 <div className="icon-picker__no-results">
122 No icons found for "{searchTerm}"
123 </div>
124 )}
125 </div>
126 </div>
127 )}
128 </div>
129 );
130}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-component.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-component.jsx
new file mode 100755
index 0000000..8e48b66
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-component.jsx
@@ -0,0 +1,159 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils";
3import SettingsInner from "./settings-inner.jsx";
4import SettingsWidgets from "./settings-widgets.jsx";
5import * as Settings from "../../settings";
6
7const { React } = Uebersicht;
8
9const TABS_STORAGE_KEY = "simple-bar-last-current-settings-tab";
10const TABS = [
11 "global",
12 "themes",
13 "process",
14 "spacesDisplay",
15 "widgets",
16 "customStyles",
17];
18
19/**
20 * Main settings component.
21 * @param {Object} props - Component properties.
22 * @param {Function} props.closeSettings - Function to close the settings.
23 */
24export default function Component({ closeSettings }) {
25 // State to keep track of the current tab
26 const [currentTab, setCurrentTab] = React.useState(getLastCurrentTab());
27 // State to keep track of pending changes
28 const [pendingChanges, setPendingChanges] = React.useState(0);
29 // Get current settings
30 const settings = Settings.get();
31 // State to keep track of new settings
32 const [newSettings, setNewSettings] = React.useState(settings);
33
34 /**
35 * Update the current tab and store it in session storage.
36 * @param {number} tab - The index of the tab to switch to.
37 */
38 const updateTab = (tab) => {
39 setCurrentTab(tab);
40 window.sessionStorage.setItem(TABS_STORAGE_KEY, tab);
41 };
42
43 /**
44 * Refresh the simple-bar with new settings.
45 * @param {Event} e - The event object.
46 */
47 const refreshSimpleBar = async (e) => {
48 Utils.clickEffect(e);
49 setPendingChanges(0);
50 await Settings.set(newSettings);
51 Utils.hardRefresh();
52 };
53
54 // Effect to calculate the number of pending changes
55 React.useEffect(() => {
56 const diffs = Utils.compareObjects(settings, newSettings);
57 const deepDiffs = Object.keys(diffs).reduce(
58 (acc, key) => [...acc, ...Object.keys(diffs[key])],
59 [],
60 );
61 setPendingChanges(deepDiffs.length);
62 }, [newSettings, settings]);
63
64 return (
65 <div className="settings">
66 <div className="settings__overlay" onClick={closeSettings} />
67 <div className="settings__outer">
68 <div className="settings__header">
69 <button
70 className="settings__header-dot settings__header-dot--close"
71 onClick={closeSettings}
72 />
73 <span className="settings__header-dot settings__header-dot--disabled" />
74 <span className="settings__header-dot settings__header-dot--disabled" />
75 Settings
76 </div>
77 <div className="settings__tabs">
78 {Object.keys(Settings.defaultSettings).map((key) => {
79 const setting = Settings.data[key];
80 const hideTab = !TABS.includes(key);
81
82 if (!setting || hideTab) return null;
83
84 const { label } = setting;
85 const i = TABS.indexOf(key);
86 const classes = Utils.classNames("settings__tab", {
87 "settings__tab--current": i === currentTab,
88 });
89 return (
90 <button key={i} className={classes} onClick={() => updateTab(i)}>
91 {label}
92 </button>
93 );
94 })}
95 </div>
96 <div className="settings__inner">
97 {Object.keys(Settings.defaultSettings).map((key) => {
98 const setting = Settings.data[key];
99 const hideContent = !TABS.includes(key);
100
101 if (!setting || hideContent) return null;
102
103 const isWidgetsTab = key === "widgets";
104
105 const { label } = setting;
106 return (
107 <div
108 key={key}
109 className="settings__category"
110 style={{ transform: `translateX(-${100 * currentTab}%)` }}
111 >
112 {isWidgetsTab ? (
113 <SettingsWidgets
114 newSettings={newSettings}
115 setNewSettings={setNewSettings}
116 />
117 ) : (
118 <React.Fragment>
119 <div className="settings__inner-title">{label}</div>
120 <SettingsInner
121 settingKey={key}
122 setting={setting}
123 newSettings={newSettings}
124 setNewSettings={setNewSettings}
125 />
126 </React.Fragment>
127 )}
128 </div>
129 );
130 })}
131 </div>
132 <div className="settings__bottom">
133 {pendingChanges !== 0 && (
134 <div className="settings__pending-changes">
135 <b>{pendingChanges}</b> pending change{pendingChanges > 1 && "s"}
136 </div>
137 )}
138 <button
139 className="settings__refresh-button"
140 onClick={refreshSimpleBar}
141 disabled={!pendingChanges}
142 >
143 Confirm changes and refresh simple-bar
144 </button>
145 </div>
146 </div>
147 </div>
148 );
149}
150
151/**
152 * Get the last current tab from session storage.
153 * @returns {number} The index of the last current tab.
154 */
155function getLastCurrentTab() {
156 const storedLastCurrentTab = window.sessionStorage.getItem(TABS_STORAGE_KEY);
157 if (storedLastCurrentTab) return parseInt(storedLastCurrentTab, 10);
158 return 0;
159}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-inner.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-inner.jsx
new file mode 100755
index 0000000..e318b25
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-inner.jsx
@@ -0,0 +1,123 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import SettingsItem from "./settings-item.jsx";
4import * as Utils from "../../utils";
5import * as Settings from "../../settings";
6
7const { React } = Uebersicht;
8
9/**
10 * SettingsInner component to render each setting category.
11 * @param {Object} props - Component properties.
12 * @param {string} props.settingKey - Key of current setting.
13 * @param {Object} props.setting - Contains infos & documentation data.
14 * @param {string[]} props.setting.infos - Current settings information.
15 * @param {string} props.setting.documentation - Current setting documentation link.
16 * @param {Object} props.newSettings - Object containing current modified settings.
17 * @param {Function} props.setNewSettings - Function allowing to save newly modified settings.
18 */
19export default function SettingsInner({
20 settingKey,
21 setting,
22 newSettings,
23 setNewSettings,
24}) {
25 const { infos, documentation } = setting;
26 return (
27 <>
28 {Object.keys(Settings.defaultSettings[settingKey]).map((subKey) => {
29 const subSetting = Settings.data[subKey];
30 if (!subSetting) return null;
31 const {
32 Component,
33 fullWidth,
34 label,
35 options,
36 placeholder,
37 title,
38 type,
39 minHeight,
40 } = subSetting;
41
42 const code = settingKey + subKey;
43 const defaultValue = newSettings[settingKey][subKey];
44
45 const classes = Utils.classNames("settings__item", {
46 "settings__item--radio": type === "radio",
47 "settings__item--text":
48 type === "text" || type === "number" || type === "color",
49 "settings__item--textarea": type === "textarea",
50 "settings__item--color": type === "color",
51 "settings__item--full-width": fullWidth,
52 });
53
54 const onChange = (e) => {
55 let value = e.target.value;
56 if (type === "checkbox") {
57 value = e.target.checked;
58 }
59 if (type === "number") {
60 value = parseFloat(value);
61 if (isNaN(value)) {
62 value = 0;
63 }
64 }
65
66 const updatedSettings = {
67 ...newSettings,
68 [settingKey]: { ...newSettings[settingKey], [subKey]: value },
69 };
70 setNewSettings(updatedSettings);
71 };
72
73 return (
74 <React.Fragment key={code}>
75 {title && <div className="settings__item-title">{title}</div>}
76 <div
77 className={classes}
78 onChange={type === "radio" ? onChange : undefined}
79 >
80 <SettingsItem
81 code={code}
82 Component={Component}
83 defaultValue={defaultValue}
84 label={label}
85 onChange={onChange}
86 options={options}
87 placeholder={placeholder}
88 type={type}
89 minHeight={minHeight}
90 />
91 </div>
92 </React.Fragment>
93 );
94 })}
95 {documentation && (
96 <div className="settings__documentation">
97 <Icons.OpenBook className="settings__documentation-icon" />
98 <span className="settings__documentation-title">
99 You{"'"}ll find all the information about these settings{" "}
100 <a
101 href={`https://www.jeantinland.com/toolbox/simple-bar/documentation${documentation}`}
102 >
103 here on the documentation
104 </a>{" "}
105 hosted on jeantinland.com.
106 </span>
107 </div>
108 )}
109 {infos && infos.length && (
110 <div className="settings__infos">
111 <div className="settings__infos-title">Tips</div>
112 {infos.map((info, i) => (
113 <div
114 key={i}
115 className="settings__info"
116 dangerouslySetInnerHTML={{ __html: info }}
117 />
118 ))}
119 </div>
120 )}
121 </>
122 );
123}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-item.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-item.jsx
new file mode 100755
index 0000000..91c6f54
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-item.jsx
@@ -0,0 +1,143 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils";
3
4const { React } = Uebersicht;
5
6/**
7 * Item component to render different types of settings inputs.
8 * @param {Object} props - Component properties.
9 * @param {string} props.code - Unique code for the setting.
10 * @param {React.Component} props.Component - Custom component for the setting.
11 * @param {any} props.defaultValue - Default value of the setting.
12 * @param {string} props.label - Label for the setting.
13 * @param {string} props.type - Type of the setting input.
14 * @param {Array} [props.options] - Options for select or radio inputs.
15 * @param {string} [props.placeholder] - Placeholder for text inputs.
16 * @param {number} [props.minHeight] - Minimum height for textarea inputs.
17 * @param {Function} props.onChange - Change handler for the setting input.
18 */
19export default function SettingsItem({
20 code,
21 Component,
22 defaultValue,
23 label,
24 type,
25 options,
26 placeholder,
27 minHeight,
28 onChange,
29}) {
30 const onClick = (e) => Utils.clickEffect(e);
31 if (type === "component") {
32 return <Component defaultValue={defaultValue} onChange={onChange} />;
33 }
34 if (type === "select") {
35 return (
36 <React.Fragment>
37 <label htmlFor={code} dangerouslySetInnerHTML={{ __html: label }} />
38 <select
39 id={code}
40 className="settings__select"
41 onChange={onChange}
42 defaultValue={defaultValue}
43 >
44 {options.map((option) => (
45 <option key={option.code} value={option.code}>
46 {option.name}
47 </option>
48 ))}
49 </select>
50 </React.Fragment>
51 );
52 }
53 if (type === "radio") {
54 return options.map((option) => (
55 <div className="settings__item-option" key={option} onClick={onClick}>
56 <input
57 name={code}
58 id={option}
59 value={option}
60 type="radio"
61 defaultChecked={option === defaultValue}
62 />
63 <label
64 htmlFor={option}
65 dangerouslySetInnerHTML={{ __html: `${option} ${label}` }}
66 />
67 </div>
68 ));
69 }
70 if (type === "text" || type === "color") {
71 return (
72 <React.Fragment>
73 <label htmlFor={code} dangerouslySetInnerHTML={{ __html: label }} />
74 {type === "color" && (
75 <div
76 className="settings__item-color-pill"
77 style={{ backgroundColor: defaultValue || "transparent" }}
78 />
79 )}
80 <input
81 id={code}
82 type="text"
83 defaultValue={defaultValue}
84 placeholder={placeholder}
85 onChange={onChange}
86 autoComplete="off"
87 autoCorrect="off"
88 autoCapitalize="off"
89 spellCheck={false}
90 />
91 </React.Fragment>
92 );
93 }
94 if (type === "number") {
95 return (
96 <React.Fragment>
97 <label htmlFor={code} dangerouslySetInnerHTML={{ __html: label }} />
98 <input
99 id={code}
100 type="number"
101 value={defaultValue}
102 placeholder={placeholder}
103 onChange={onChange}
104 autoComplete="off"
105 />
106 </React.Fragment>
107 );
108 }
109 if (type === "textarea") {
110 return (
111 <React.Fragment>
112 <label htmlFor={code} dangerouslySetInnerHTML={{ __html: label }} />
113 <textarea
114 id={code}
115 defaultValue={defaultValue}
116 placeholder={placeholder}
117 onChange={onChange}
118 autoComplete="off"
119 autoCorrect="off"
120 autoCapitalize="off"
121 spellCheck={false}
122 style={{ minHeight }}
123 />
124 </React.Fragment>
125 );
126 }
127 return (
128 <React.Fragment>
129 <input
130 id={code}
131 type="checkbox"
132 defaultChecked={defaultValue}
133 onChange={onChange}
134 onClick={onClick}
135 />
136 <label
137 htmlFor={code}
138 onClick={onClick}
139 dangerouslySetInnerHTML={{ __html: label }}
140 />
141 </React.Fragment>
142 );
143}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-widgets.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-widgets.jsx
new file mode 100755
index 0000000..736e4bb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings-widgets.jsx
@@ -0,0 +1,180 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import * as Utils from "../../utils";
4import * as Settings from "../../settings";
5import SettingsInner from "./settings-inner.jsx";
6
7const { React } = Uebersicht;
8
9const settingsKeys = {
10 batteryWidget: "batteryWidgetOptions",
11 browserTrackWidget: "browserTrackWidgetOptions",
12 cpuWidget: "cpuWidgetOptions",
13 cryptoWidget: "cryptoWidgetOptions",
14 dateWidget: "dateWidgetOptions",
15 gpuWidget: "gpuWidgetOptions",
16 memoryWidget: "memoryWidgetOptions",
17 keyboardWidget: "keyboardWidgetOptions",
18 micWidget: "micWidgetOptions",
19 mpdWidget: "mpdWidgetOptions",
20 musicWidget: "musicWidgetOptions",
21 netstatsWidget: "netstatsWidgetOptions",
22 nextMeetingWidget: "nextMeetingWidgetOptions",
23 notificationsWidget: "notificationsWidgetOptions",
24 soundWidget: "soundWidgetOptions",
25 spotifyWidget: "spotifyWidgetOptions",
26 stockWidget: "stockWidgetOptions",
27 timeWidget: "timeWidgetOptions",
28 vpnWidget: "vpnWidgetOptions",
29 githubWidget: "githubWidgetOptions",
30 weatherWidget: "weatherWidgetOptions",
31 wifiWidget: "networkWidgetOptions",
32 youtubeMusicWidget: "youtubeMusicWidgetOptions",
33 zoomWidget: "zoomWidgetOptions",
34 userWidgets: "userWidgets",
35};
36
37/**
38 * SettingsWidgets component to render widgets setting category.
39 * @param {Object} props - Component properties.
40 * @param {Object} props.newSettings - Object containing current modified settings.
41 * @param {Function} props.setNewSettings - Function allowing to save newly modified settings.
42 */
43export default function SettingsWidgets({ newSettings, setNewSettings }) {
44 const [currentWidget, setCurrentWidget] = React.useState(null);
45 const currentSetting = Settings.data[currentWidget];
46
47 /**
48 * Removes the current widget setting,
49 */
50 const removeCurrentWidget = () => {
51 setCurrentWidget(null);
52 };
53
54 /**
55 * Prevent checkbox click from propagating to the parent element,
56 * allowing to avoid triggering the widget selection.
57 */
58 const handleCheckboxClick = (e) => {
59 e.stopPropagation();
60 Utils.clickEffect(e);
61 };
62
63 /**
64 * Updates the current widget based on the clicked element.
65 * @param {string} widget - The key of the widget to update.
66 */
67 const updateCurrentWidget = (widget) => (e) => {
68 if (widget === "processWidget") return;
69
70 Utils.clickEffect(e);
71 const widgetKey = settingsKeys[widget];
72 setCurrentWidget(currentWidget === widgetKey ? null : widgetKey);
73 };
74
75 return (
76 <div className="settings__widgets">
77 <Breadcrumb
78 currentSetting={currentSetting}
79 removeCurrentWidget={removeCurrentWidget}
80 />
81 {!currentWidget ? (
82 <div className="settings__widgets-list">
83 <div
84 className="settings__widgets-item"
85 onClick={updateCurrentWidget("userWidgets")}
86 >
87 Custom widgets
88 <Icons.ChevronRight className="settings__widgets-item-icon" />
89 </div>
90 {Object.keys(Settings.defaultSettings.widgets).map((subKey) => {
91 const subSetting = Settings.data[subKey];
92 if (!subSetting) return null;
93 const { label } = subSetting;
94 const defaultValue = newSettings.widgets[subKey];
95 const isProcess = subKey === "processWidget";
96
97 const classes = Utils.classNames("settings__widgets-item", {
98 "settings__widgets-item--process": isProcess,
99 });
100
101 const onChange = (e) => {
102 const value = e.target.checked;
103
104 const updatedSettings = {
105 ...newSettings,
106 widgets: { ...newSettings.widgets, [subKey]: value },
107 };
108 setNewSettings(updatedSettings);
109 };
110
111 return (
112 <div
113 key={subKey}
114 className={classes}
115 onClick={updateCurrentWidget(subKey)}
116 >
117 <input
118 type="checkbox"
119 defaultChecked={defaultValue}
120 onChange={onChange}
121 onClick={handleCheckboxClick}
122 />
123 {label}
124 {!isProcess && (
125 <Icons.ChevronRight className="settings__widgets-item-icon" />
126 )}
127 </div>
128 );
129 })}
130 </div>
131 ) : (
132 <div className="settings__widget-settings">
133 <SettingsInner
134 settingKey={currentWidget}
135 setting={currentSetting}
136 newSettings={newSettings}
137 setNewSettings={setNewSettings}
138 />
139 </div>
140 )}
141 </div>
142 );
143}
144
145/**
146 * SettingsWidgets component to render widgets setting category.
147 * @param {Object} props - Component properties.
148 * @param {Object} props.currentSetting - Object containing the current setting.
149 * @param {Function} props.removeCurrentWidget - Function removing the current setting allowing to go back to widget list.
150 */
151function Breadcrumb({ currentSetting, removeCurrentWidget }) {
152 if (!currentSetting) {
153 return (
154 <div className="settings__widgets-breadcrumb">
155 <div className="settings__widgets-breadcrumb-title">Widgets</div>
156 </div>
157 );
158 }
159 const { label } = currentSetting;
160 return (
161 <div className="settings__widgets-breadcrumb">
162 <button
163 className="settings__widgets-breadcrumb-title"
164 onClick={removeCurrentWidget}
165 >
166 Widgets
167 </button>
168 <span className="settings__widgets-breadcrumb-current">
169 {">"} {label}
170 </span>
171 <button
172 className="settings__widgets-breadcrumb-back"
173 onClick={removeCurrentWidget}
174 >
175 <Icons.ChevronLeft className="settings__widgets-breadcrumb-back-icon" />
176 Back
177 </button>
178 </div>
179 );
180}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings.jsx
new file mode 100755
index 0000000..c63f853
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/settings.jsx
@@ -0,0 +1,94 @@
1import * as Uebersicht from "uebersicht";
2import * as Utils from "../../utils";
3import * as Settings from "../../settings";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5
6export { settingsStyles as styles } from "../../styles/components/settings/settings";
7
8const { React } = Uebersicht;
9
10// Settings component is lazy loaded. That way,
11// it isn't loaded everytime simple-bar is refreshed
12const Component = React.lazy(() => import("./settings-component.jsx"));
13
14/**
15 * Wrapper component that handles keyboard shortcuts for various actions
16 * and manages the visibility of the settings component.
17 *
18 * @component
19 * @returns {React.Fragment} A fragment containing the settings component if visible.
20 */
21export function Wrapper() {
22 const { pushMissive } = useSimpleBarContext();
23 const [visible, setVisible] = React.useState(false);
24
25 const closeSettings = () => {
26 setVisible(false);
27 Utils.blurBar();
28 };
29
30 // Actions handled by this function are
31 // > Hard refresh simple-bar with cmd/ctrl + r
32 // > Open settings with cmd/ctrl + ,
33 // > Toggle dark theme with cmd/ctrl + t
34 const handleKeydown = React.useCallback(
35 (e) => {
36 const { ctrlKey, key, metaKey } = e;
37 if ((ctrlKey || metaKey) && key === "r") {
38 e.preventDefault();
39 Utils.hardRefresh();
40 }
41 if ((ctrlKey || metaKey) && key === ",") {
42 e.preventDefault();
43 setVisible(true);
44 }
45 if ((ctrlKey || metaKey) && key === "t") {
46 e.preventDefault();
47 // We retrieve the latest version of settings
48 const settings = Settings.get();
49 const AUTO = "auto";
50 // If current value is auto, it is stored as is
51 // otherwise, it is toggled
52 let newValue = AUTO;
53 if (settings.global.theme !== AUTO) {
54 newValue = settings.global.theme;
55 }
56 // OS is instructed to toggle dark theme
57 Uebersicht.run(
58 `osascript -e 'tell app "System Events" to tell appearance preferences to set dark mode to not dark mode'`,
59 );
60 // A notification is pushed either in Macos notification center or via internal missives system
61 Utils.notification("Toggling dark theme...", pushMissive);
62 if (newValue !== AUTO) {
63 // Only theme value is updated
64 const updatedSettings = {
65 ...settings,
66 global: { ...settings.global, theme: newValue },
67 };
68 // Settings are updated and simple-bar is hard refreshed
69 Settings.set(updatedSettings);
70 Utils.hardRefresh();
71 }
72 }
73 },
74 [pushMissive],
75 );
76
77 React.useEffect(() => {
78 // We bind keydown event on Übersicht document when <Settings /> component is mounted
79 // Event listener is removed on unmount
80 document.addEventListener("keydown", handleKeydown);
81 return () => document.removeEventListener("keydown", handleKeydown);
82 }, [handleKeydown]);
83
84 // Only a fragment is returned if <Settings /> component is not visible
85 return (
86 <React.Fragment>
87 {visible && (
88 <React.Suspense fallback={<React.Fragment />}>
89 <Component visible={visible} closeSettings={closeSettings} />
90 </React.Suspense>
91 )}
92 </React.Fragment>
93 );
94}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx
new file mode 100755
index 0000000..a026047
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/settings/user-widgets-creator.jsx
@@ -0,0 +1,297 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import * as Settings from "../../settings";
4import * as Utils from "../../utils";
5import ColorPicker from "./color-picker.jsx";
6import IconPicker from "./icon-picker.jsx";
7
8const { React } = Uebersicht;
9
10/**
11 * UserWidgetsCreator component allows users to create and manage custom widgets.
12 * @param {Object} props - The component props.
13 * @param {Object} props.defaultValue - The default value for the widgets.
14 * @param {Function} props.onChange - The function to call when the widgets change.
15 * @returns {JSX.Element} The UserWidgetsCreator component.
16 */
17export default function UserWidgetsCreator({ defaultValue, onChange }) {
18 const [widgets, setWidgets] = React.useState(defaultValue || {});
19 const keys = Object.keys(widgets);
20
21 // Determine the highest widget ID and calculate the new ID for a new widget
22 const highestId = keys.reduce((acc, key) => {
23 const keyAsNumber = parseInt(key, 10);
24 return keyAsNumber > acc ? keyAsNumber : acc;
25 }, 1);
26 const newId = highestId + 1;
27
28 // Function to add a new widget
29 const onClick = () =>
30 setWidgets((widgets) => ({
31 ...widgets,
32 [newId]: { ...Settings.userWidgetDefault },
33 }));
34
35 // Function to handle changes to a widget
36 const onWidgetChange = (index, field, value) => {
37 const newWidgets = { ...widgets };
38 const newKeys = Object.keys(newWidgets);
39 const updatedWidgets = newKeys.reduce((acc, key, i) => {
40 const widget = newWidgets[key];
41 return {
42 ...acc,
43 [i + 1]: key === index ? { ...widget, [field]: value } : widget,
44 };
45 }, {});
46 setWidgets(updatedWidgets);
47 };
48
49 // Effect to detect changes in widgets and call onChange prop
50 React.useEffect(() => {
51 const diffs = Utils.compareObjects(defaultValue, widgets);
52 const hasDiffs = Object.keys(diffs).length > 0;
53 if (hasDiffs) onChange({ target: { value: widgets } });
54 }, [defaultValue, onChange, widgets]);
55
56 return (
57 <div className="user-widgets-creator">
58 {keys.map((key, i) => (
59 <UserWidgetCreator
60 key={`${key}-${widgets[key].backgroundColor}`}
61 index={key}
62 onWidgetChange={onWidgetChange}
63 setWidgets={setWidgets}
64 widget={widgets[key]}
65 isFirst={i === 0}
66 isLast={i === keys.length - 1}
67 />
68 ))}
69 <button className="user-widgets-creator__add" onClick={onClick}>
70 <Icons.Add />
71 Add a custom widget
72 </button>
73 </div>
74 );
75}
76
77/**
78 * UserWidgetCreator component allows users to configure individual widgets.
79 * @param {Object} props - The component props.
80 * @param {string} props.index - The index of the widget.
81 * @param {boolean} props.isFirst - Whether the widget is the first in the list.
82 * @param {boolean} props.isLast - Whether the widget is the last in the list.
83 * @param {Function} props.onWidgetChange - The function to call when the widget changes.
84 * @param {Function} props.setWidgets - The function to set the widgets state.
85 * @param {Object} props.widget - The widget data.
86 * @returns {JSX.Element} The UserWidgetCreator component.
87 */
88function UserWidgetCreator({
89 index,
90 isFirst,
91 isLast,
92 onWidgetChange,
93 setWidgets,
94 widget,
95}) {
96 const {
97 title,
98 icon,
99 backgroundColor,
100 output,
101 onClickAction,
102 onRightClickAction,
103 onMiddleClickAction,
104 refreshFrequency,
105 active = true,
106 noIcon = false,
107 hideWhenNoOutput = true,
108 showOnDisplay = "",
109 } = widget;
110
111 const indexAsNumber = parseInt(index, 10);
112
113 // Function to remove a widget
114 const onRemoveClick = () => {
115 setWidgets((widgets) => {
116 const keys = Object.keys(widgets);
117 return keys.reduce(
118 (acc, key) => (key === index ? acc : { ...acc, [key]: widgets[key] }),
119 {},
120 );
121 });
122 };
123
124 // Function to handle changes to widget fields
125 const onChange = (field, chexbox = false) => {
126 return (e) => {
127 const value = (chexbox ? e?.target?.checked : e?.target?.value) ?? "";
128 onWidgetChange(index, field, value);
129 };
130 };
131
132 // Function to move the widget up in the list
133 const onBeforeClick = () => {
134 setWidgets((widgets) => {
135 const swapedWidget = widgets[indexAsNumber - 1];
136 return {
137 ...widgets,
138 [indexAsNumber - 1]: widget,
139 [indexAsNumber]: swapedWidget,
140 };
141 });
142 };
143
144 // Function to move the widget down in the list
145 const onAfterClick = () => {
146 setWidgets((widgets) => {
147 const swapedWidget = widgets[indexAsNumber + 1];
148 return {
149 ...widgets,
150 [indexAsNumber + 1]: widget,
151 [indexAsNumber]: swapedWidget,
152 };
153 });
154 };
155
156 return (
157 <div key={indexAsNumber} className="user-widget-creator">
158 <div className="user-widget-creator__sort-buttons">
159 {!isFirst && (
160 <button
161 className="user-widget-creator__sort-button user-widget-creator__sort-button--before"
162 onClick={onBeforeClick}
163 >
164 <Icons.ChevronTop />
165 </button>
166 )}
167 {!isLast && (
168 <button
169 className="user-widget-creator__sort-button user-widget-creator__sort-button--after"
170 onClick={onAfterClick}
171 >
172 <Icons.ChevronBottom />
173 </button>
174 )}
175 </div>
176 <button className="user-widget-creator__remove" onClick={onRemoveClick}>
177 <Icons.Remove />
178 </button>
179 <div className="user-widget-creator__index">
180 n°<b>{index}</b>
181 </div>
182 <IconPicker callback={onWidgetChange} index={index} selectedIcon={icon} />
183 <div className="user-widget-creator__right">
184 <div className="user-widget-creator__right-top">
185 <ColorPicker
186 callback={onWidgetChange}
187 index={index}
188 selectedColor={backgroundColor}
189 />
190 <input
191 className="user-widget-creator__title"
192 onChange={onChange("title")}
193 type="text"
194 defaultValue={title}
195 />
196 <label htmlFor={`refresh-frequency-${index}`}>
197 Refresh frequency (ms):
198 </label>
199 <input
200 className="user-widget-creator__refresh-frequency"
201 onChange={onChange("refreshFrequency")}
202 id={`refresh-frequency-${index}`}
203 type="text"
204 defaultValue={refreshFrequency}
205 />
206 </div>
207 <div className="user-widget-creator__input-group">
208 <label htmlFor={`show-on-display-${index}`}>Show on display: </label>
209 <input
210 className="user-widget-creator__show-on-display"
211 onChange={onChange("showOnDisplay")}
212 id={`show-on-display-${index}`}
213 type="text"
214 defaultValue={showOnDisplay}
215 placeholder="example: 1,2 (leave blank to show on all displays)"
216 spellCheck={false}
217 />
218 </div>
219 <div className="user-widget-creator__input-group">
220 <label htmlFor={`output-${index}`}>Command/script path: </label>
221 <input
222 className="user-widget-creator__output"
223 onChange={onChange("output")}
224 id={`output-${index}`}
225 type="text"
226 defaultValue={output}
227 spellCheck={false}
228 />
229 </div>
230 <div className="user-widget-creator__input-group">
231 <label htmlFor={`on-click-action-${index}`}>
232 On click command/script path:{" "}
233 </label>
234 <input
235 className="user-widget-creator__on-click-action"
236 onChange={onChange("onClickAction")}
237 id={`on-click-action-${index}`}
238 type="text"
239 defaultValue={onClickAction}
240 spellCheck={false}
241 />
242 </div>
243 <div className="user-widget-creator__input-group">
244 <label htmlFor={`on-right-click-action-${index}`}>
245 On right click command/script path:{" "}
246 </label>
247 <input
248 className="user-widget-creator__on-right-click-action"
249 onChange={onChange("onRightClickAction")}
250 id={`on-right-click-action-${index}`}
251 type="text"
252 defaultValue={onRightClickAction}
253 spellCheck={false}
254 />
255 </div>
256 <div className="user-widget-creator__input-group">
257 <label htmlFor={`on-middle-click-action-${index}`}>
258 On middle click command/script path:{" "}
259 </label>
260 <input
261 className="user-widget-creator__on-middle-click-action"
262 onChange={onChange("onMiddleClickAction")}
263 id={`on-middle-click-action-${index}`}
264 type="text"
265 defaultValue={onMiddleClickAction}
266 spellCheck={false}
267 />
268 </div>
269 <div className="user-widget-creator__input-group">
270 <input
271 id={`active-${index}`}
272 type="checkbox"
273 defaultChecked={active}
274 onChange={onChange("active", true)}
275 />
276 <label htmlFor={`active-${index}`}>Active</label>
277 <input
278 id={`no-icon-${index}`}
279 type="checkbox"
280 defaultChecked={noIcon}
281 onChange={onChange("noIcon", true)}
282 />
283 <label htmlFor={`no-icon-${index}`}>No icon</label>
284 <input
285 id={`hide-when-no-output-${index}`}
286 type="checkbox"
287 defaultChecked={hideWhenNoOutput}
288 onChange={onChange("hideWhenNoOutput", true)}
289 />
290 <label htmlFor={`hide-when-no-output-${index}`}>
291 Hide when no script output
292 </label>
293 </div>
294 </div>
295 </div>
296 );
297}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/side-icon.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/side-icon.jsx
new file mode 100755
index 0000000..893241d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/side-icon.jsx
@@ -0,0 +1,32 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "./icons/icons.jsx";
3import { SuspenseIcon } from "./icons/icon.jsx";
4import { useSimpleBarContext } from "./simple-bar-context.jsx";
5
6const { React } = Uebersicht;
7
8export { sideIconStyles as styles } from "../../lib/styles/components/side-icon";
9
10/**
11 * Component to render the side icon based on the settings.
12 *
13 * @returns {JSX.Element|null} The side icon component or null if sideDecoration is disabled.
14 */
15export function Component() {
16 // Using context to get settings
17 const { settings } = useSimpleBarContext();
18 // Destructuring sideDecoration from global settings
19 const { sideDecoration } = settings.global;
20
21 // If sideDecoration is disabled, return null
22 if (!sideDecoration) return null;
23
24 // Render the side icon component
25 return (
26 <div className="side-icon">
27 <SuspenseIcon>
28 <Icons.Apple className="side-icon__svg" />
29 </SuspenseIcon>
30 </div>
31 );
32}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/simple-bar-context.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/simple-bar-context.jsx
new file mode 100755
index 0000000..7cab27a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/simple-bar-context.jsx
@@ -0,0 +1,131 @@
1import * as Uebersicht from "uebersicht";
2import * as Aerospace from "../aerospace.js";
3
4const { React } = Uebersicht;
5
6// Create a context with default values
7const SimpleBarContext = React.createContext({
8 display: 1,
9 SIPDisabled: false,
10 settings: {},
11 setSettings: () => {},
12});
13
14/**
15 * Custom hook to use the SimpleBarContext
16 * @returns {Object} The context value
17 */
18export function useSimpleBarContext() {
19 return React.useContext(SimpleBarContext);
20}
21
22/**
23 * Provides context for simple-bar.
24 *
25 * @param {Object} props - The properties object.
26 * @param {Object} props.initialSettings - The initial settings for the application.
27 * @param {Array} props.displays - The initial displays configuration.
28 * @param {boolean} props.SIPDisabled - Indicates if SIP (System Integrity Protection) is disabled.
29 * @param {React.ReactNode} props.children - The child components to be wrapped by the provider.
30 *
31 * @returns {JSX.Element} The context provider component.
32 */
33export default function SimpleBarContextProvider({
34 initialSettings,
35 displays,
36 SIPDisabled,
37 children,
38}) {
39 const [settings, setSettings] = React.useState(initialSettings);
40 const [_displays, setDisplays] = React.useState(displays);
41 const [missives, setMissives] = React.useState([]);
42 const [ubersichtScreens, setUbersichtScreens] = React.useState([]);
43
44 const { windowManager, enableServer, yabaiServerRefresh } = settings.global;
45 const serverEnabled = enableServer && yabaiServerRefresh;
46 const isYabai = windowManager === "yabai";
47
48 const currentDisplays = serverEnabled && isYabai ? _displays : displays;
49
50 const ubersichtDisplayId = parseInt(
51 window.location.pathname.replace("/", ""),
52 10,
53 );
54
55 // Fetch Übersicht's active screen list from /state/
56 React.useEffect(() => {
57 if (isYabai) return undefined;
58
59 const controller = new AbortController();
60
61 const loadScreens = async () => {
62 try {
63 const response = await fetch("/state/", { signal: controller.signal });
64 if (!response.ok) throw new Error("Failed to load /state/");
65 const state = await response.json();
66 setUbersichtScreens(Array.isArray(state?.screens) ? state.screens : []);
67 } catch (error) {
68 if (error?.name !== "AbortError") {
69 setUbersichtScreens([]);
70 }
71 }
72 };
73
74 loadScreens();
75 return () => controller.abort();
76 }, [displays, isYabai]);
77
78 // Derive the current display rank from the active Übersicht screen order.
79 // This handles phantom displays (closed lid, previously connected monitors)
80 // that Übersicht still counts but AeroSpace doesn't report.
81 const currentScreenRank = ubersichtScreens.indexOf(ubersichtDisplayId) + 1;
82
83 // Match the current display using either the yabai display ID or AeroSpace's custom display index logic.
84 const currentDisplay =
85 currentDisplays?.find((display) =>
86 isYabai
87 ? display.id === ubersichtDisplayId
88 : Aerospace.getDisplayIndex(display) === currentScreenRank,
89 ) || {};
90
91 // Determine the display index for context value
92 // currentDisplay.index is from yabai
93 // Aerospace.getDisplayIndex is from AeroSpace with custom logic
94 // Fallback to AeroSpace monitor-appkit-nsscreen-screens-id or default to 1
95 const displayIndex =
96 currentDisplay.index ?? Aerospace.getDisplayIndex(currentDisplay) ?? 1;
97
98 const pushMissive = (newMissive) => {
99 const now = Date.now();
100 const { content, side = "right", delay = 5000 } = newMissive;
101 const timeout =
102 typeof delay === "number" && delay !== 0
103 ? setTimeout(() => {
104 setMissives((current) => {
105 return current.filter((m) => m.id !== now);
106 });
107 }, delay)
108 : undefined;
109 setMissives((current) => {
110 return [...current, { id: now, content, side, timeout }];
111 });
112 };
113
114 return (
115 <SimpleBarContext.Provider
116 value={{
117 displayIndex,
118 SIPDisabled,
119 settings,
120 setSettings,
121 displays: currentDisplays,
122 setDisplays,
123 missives,
124 setMissives,
125 pushMissive,
126 }}
127 >
128 {children}
129 </SimpleBarContext.Provider>
130 );
131}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai-context.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai-context.jsx
new file mode 100755
index 0000000..245977b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai-context.jsx
@@ -0,0 +1,112 @@
1import * as Uebersicht from "uebersicht";
2import { useSimpleBarContext } from "./simple-bar-context.jsx";
3import useServerSocket from "../hooks/use-server-socket.js";
4import * as Yabai from "../yabai.js";
5import * as Skhd from "../skhd.js";
6
7const { React } = Uebersicht;
8
9// Create a context with default values
10const YabaiContext = React.createContext({
11 spaces: [],
12 windows: [],
13 skhdMode: "",
14});
15
16/**
17 * Custom hook to use the YabaiContext
18 * @returns {Object} The context value
19 */
20export function useYabaiContext() {
21 return React.useContext(YabaiContext);
22}
23
24export default React.memo(YabaiContextProvider);
25
26/**
27 * YabaiContextProvider component provides context for Yabai spaces, windows, and skhd mode.
28 * It uses server sockets to fetch and update the context values.
29 *
30 * @param {Object} props - The component props.
31 * @param {Array} props.spaces - Initial spaces data.
32 * @param {Array} props.windows - Initial windows data.
33 * @param {Object} props.skhdMode - Initial skhd mode data.
34 * @param {React.ReactNode} props.children - The child components to be wrapped by the provider.
35 * @returns {JSX.Element} The YabaiContext provider component.
36 */
37function YabaiContextProvider({ spaces, windows, skhdMode, children }) {
38 const { settings, setDisplays } = useSimpleBarContext();
39 const { enableServer, yabaiServerRefresh } = settings.global;
40 const { displaySkhdMode } = settings.process;
41 const serverEnabled = enableServer && yabaiServerRefresh;
42
43 const [yabaiSpaces, setYabaiSpaces] = React.useState(spaces);
44 const [yabaiWindows, setYabaiWindows] = React.useState(windows);
45 const [currentSkhdMode, setCurrentSkhdMode] = React.useState(skhdMode);
46
47 // Resets the spaces state to an empty array.
48 const resetSpaces = () => {
49 setYabaiSpaces([]);
50 };
51
52 // Resets the windows state to an empty array.
53 const resetWindows = () => {
54 setYabaiWindows([]);
55 };
56
57 // Resets the displays state to an empty array.
58 const resetDisplays = () => {
59 setDisplays([]);
60 };
61
62 // Resets the skhd mode state to an empty object.
63 const resetSkhdMode = () => {
64 setCurrentSkhdMode({});
65 };
66
67 // Fetches the current spaces from Yabai and updates the state.
68 const getSpaces = async () => {
69 const newSpaces = await Yabai.getSpaces();
70 setYabaiSpaces(newSpaces);
71 };
72
73 // Fetches the current windows from Yabai and updates the state.
74 const getWindows = async () => {
75 const newWindows = await Yabai.getWindows();
76 setYabaiWindows(newWindows);
77 };
78
79 // Fetches the current displays from Yabai and updates the state.
80 const getDisplays = async () => {
81 const newDisplays = await Yabai.getDisplays();
82 setDisplays(newDisplays);
83 };
84
85 // Fetches the current skhd mode from Skhd and updates the state.
86 const getSkhdMode = async () => {
87 const newSkhdMode = await Skhd.getMode();
88 setCurrentSkhdMode(newSkhdMode);
89 };
90
91 useServerSocket("spaces", serverEnabled, getSpaces, resetSpaces);
92 useServerSocket("windows", serverEnabled, getWindows, resetWindows);
93 useServerSocket("displays", serverEnabled, getDisplays, resetDisplays);
94 useServerSocket("mode", displaySkhdMode, getSkhdMode, resetSkhdMode);
95
96 const usedWindows = serverEnabled ? yabaiWindows : windows;
97 // Windows with an empty subrole should not be displayed in the UI
98 // See https://github.com/Jean-Tinland/simple-bar/issues/495 for reference
99 const filteredWindows = usedWindows.filter((window) => window.subrole);
100
101 return (
102 <YabaiContext.Provider
103 value={{
104 spaces: serverEnabled ? yabaiSpaces : spaces,
105 windows: filteredWindows,
106 skhdMode: serverEnabled ? currentSkhdMode : skhdMode,
107 }}
108 >
109 {children}
110 </YabaiContext.Provider>
111 );
112}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/opened-apps.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/opened-apps.jsx
new file mode 100755
index 0000000..744867e
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/opened-apps.jsx
@@ -0,0 +1,55 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons.js";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import * as Utils from "../../utils.js";
5
6const { React } = Uebersicht;
7
8/**
9 * OpenedApps component to display a list of opened applications.
10 * @param {Object} props - Component properties.
11 * @param {Array} props.apps - The list of opened applications.
12 * @returns {JSX.Element|null} The rendered component or null if no applications are present.
13 */
14export default function OpenedApps({ apps }) {
15 // Return null if no applications are present
16 if (!apps.length) return null;
17
18 // Sort and map the applications to JSX elements
19 return Utils.sortWindows(apps).map((app, i) => {
20 const {
21 "is-minimized": isMinimized,
22 minimized: __legacyIsMinimized,
23 "has-focus": hasFocus,
24 focused: __legacyHasFocus,
25 "has-parent-zoom": hasParentZoom,
26 "zoom-parent": __legacyHasParentZoom,
27 "has-fullscreen-zoom": hasFullscreenZoom,
28 "zoom-fullscreen": __legacyHasFullscreenZoom,
29 "is-topmost": isTopmost,
30 } = app;
31 const appName = Utils.normalizeAppName(app.app);
32
33 // Skip minimized applications
34 if (isMinimized ?? __legacyIsMinimized) return null;
35
36 // Get the application icon or default icon
37 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
38
39 // Determine the CSS classes for the icon
40 const classes = Utils.classNames("space__icon", {
41 "space__icon--focused": hasFocus ?? __legacyHasFocus,
42 "space__icon--fullscreen":
43 (hasParentZoom ?? __legacyHasParentZoom) ||
44 (hasFullscreenZoom ?? __legacyHasFullscreenZoom),
45 "space__icon--topmost": isTopmost,
46 });
47
48 // Render the application icon
49 return (
50 <SuspenseIcon key={i}>
51 <Icon className={classes} />
52 </SuspenseIcon>
53 );
54 });
55}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/process.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/process.jsx
new file mode 100755
index 0000000..96a0b7c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/process.jsx
@@ -0,0 +1,102 @@
1import * as Uebersicht from "uebersicht";
2import Window from "./window.jsx";
3import * as Utils from "../../utils";
4import { useYabaiContext } from "../yabai-context.jsx";
5import { useSimpleBarContext } from "../simple-bar-context.jsx";
6
7export { processStyles as styles } from "../../styles/components/process";
8
9const { React } = Uebersicht;
10
11/**
12 * Process component that displays the current windows and spaces information.
13 * @returns {JSX.Element|null} The rendered component or null if not visible.
14 */
15const Component = React.memo(() => {
16 // Get context values from yabai and simple-bar
17 const { spaces, windows, skhdMode } = useYabaiContext();
18 const { displayIndex, settings } = useSimpleBarContext();
19 const { process, spacesDisplay, widgets } = settings;
20 const { processWidget } = widgets;
21 const { exclusionsAsRegex } = spacesDisplay;
22 const { displayForFocusedSpace, centered, showCurrentSpaceMode, displaySkhdMode, showOnDisplay } =
23 process;
24
25 // Determine if the process widget should be visible
26 const visible =
27 processWidget &&
28 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) &&
29 windows;
30
31 if (!visible) return null;
32
33 // Parse exclusions based on settings
34 const exclusions = exclusionsAsRegex
35 ? spacesDisplay.exclusions
36 : spacesDisplay.exclusions.split(", ");
37
38 const titleExclusions = exclusionsAsRegex
39 ? spacesDisplay.titleExclusions
40 : spacesDisplay.titleExclusions.split(", ");
41
42 // Find the current space based on visibility and display index
43 const currentSpace = spaces.find((space) => {
44 const {
45 "is-visible": isVisible,
46 "has-focus" : hasFocus,
47 visible: __legacyIsVisible,
48 display,
49 } = space;
50 return (isVisible ?? __legacyIsVisible) && (displayForFocusedSpace ? hasFocus : display === displayIndex);
51 });
52
53 // Get sticky and non-sticky windows using a utility function
54 const { stickyWindows, nonStickyWindows } = Utils.stickyWindowWorkaround({
55 windows,
56 uniqueApps: false,
57 currentDisplay: displayIndex,
58 currentSpace: currentSpace?.index,
59 exclusions,
60 titleExclusions,
61 exclusionsAsRegex,
62 });
63
64 // Combine sticky and non-sticky windows
65 const apps = [...stickyWindows, ...nonStickyWindows];
66
67 // Determine CSS classes for the component
68 const classes = Utils.classNames("process", {
69 "process--centered": centered,
70 });
71
72 // Determine the current skhd mode and its color
73 const currentSkhdMode = skhdMode.mode === "default" ? null : skhdMode.mode;
74 const skhdModeColor = "var(--" + skhdMode.color + ")";
75
76 return (
77 <div className={classes}>
78 <div className="process__container">
79 {showCurrentSpaceMode && currentSpace && (
80 <div key={currentSpace.index} className="process__layout">
81 {currentSpace.type}
82 </div>
83 )}
84 {displaySkhdMode && currentSkhdMode && (
85 <div
86 className="process__skhd-mode"
87 style={{ backgroundColor: skhdModeColor }}
88 >
89 {currentSkhdMode}
90 </div>
91 )}
92 {Utils.sortWindows(apps).map((window, i) => (
93 <Window key={i} window={window} />
94 ))}
95 </div>
96 </div>
97 );
98});
99
100Component.displayName = "Process";
101
102export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space-options.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space-options.jsx
new file mode 100755
index 0000000..9c54d8b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space-options.jsx
@@ -0,0 +1,84 @@
1import * as Uebersicht from "uebersicht";
2import * as Icons from "../icons/icons.jsx";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils.js";
6import * as Yabai from "../../yabai.js";
7
8const { React } = Uebersicht;
9
10/**
11 * SpaceOptions component provides options to manipulate spaces (move left, move right, remove).
12 * @param {Object} props - The component props.
13 * @param {number} props.index - The index of the space.
14 * @param {Function} props.setHovered - Function to set the hovered state.
15 * @returns {JSX.Element} The SpaceOptions component.
16 */
17export default function SpaceOptions({ index, setHovered }) {
18 // Get displayIndex from the context
19 const { displayIndex } = useSimpleBarContext();
20
21 /**
22 * Handles the click event to remove a space.
23 * @param {Event} e - The click event.
24 */
25 const remove = async (e) => {
26 e.stopPropagation();
27 Utils.clickEffect(e);
28 setHovered(false);
29 await Yabai.removeSpace(index, displayIndex);
30 };
31
32 /**
33 * Returns a function to handle the click event to swap a space.
34 * @param {string} direction - The direction to swap the space ("left" or "right").
35 * @returns {Function} The click event handler.
36 */
37 const moveTo = (direction) => async (e) => {
38 Utils.clickEffect(e);
39 setHovered(false);
40 await Yabai.swapSpace(index, direction);
41 };
42
43 /**
44 * Prevents the default behavior of the mouse down event.
45 * @param {Event} e - The mouse down event.
46 */
47 const onMouseDown = (e) => e.preventDefault();
48
49 /**
50 * Handles the mouse leave event to unset the hovered state.
51 */
52 const onMouseLeave = () => setHovered(false);
53
54 return (
55 <span className="space-options" onMouseLeave={onMouseLeave}>
56 <div
57 className="space-options__option space-options__option--move-prev"
58 onMouseDown={onMouseDown}
59 onClick={moveTo("left")}
60 >
61 <SuspenseIcon>
62 <Icons.ChevronLeft />
63 </SuspenseIcon>
64 </div>
65 <div
66 className="space-options__option space-options__option--move-next"
67 onMouseDown={onMouseDown}
68 onClick={moveTo("right")}
69 >
70 <SuspenseIcon>
71 <Icons.ChevronRight />
72 </SuspenseIcon>
73 </div>
74 <div
75 className="space-options__option space-options__option--remove"
76 onClick={remove}
77 >
78 <SuspenseIcon>
79 <Icons.Remove />
80 </SuspenseIcon>
81 </div>
82 </span>
83 );
84}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space.jsx
new file mode 100755
index 0000000..3b5e761
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/space.jsx
@@ -0,0 +1,194 @@
1import * as Uebersicht from "uebersicht";
2import OpenedApps from "./opened-apps.jsx";
3import SpaceOptions from "./space-options.jsx";
4import { useYabaiContext } from "../yabai-context.jsx";
5import { useSimpleBarContext } from "../simple-bar-context.jsx";
6import * as Utils from "../../utils.js";
7import * as Yabai from "../../yabai.js";
8
9const { React } = Uebersicht;
10
11/**
12 * Component representing a space in yabai window manager.
13 * @param {Object} props - The component props.
14 * @param {Object} props.space - The space object.
15 * @param {number} props.display - The display index.
16 * @param {number} props.currentSpaceIndex - The current space index.
17 * @param {boolean} props.lastOfSpace - Whether this is the last space.
18 * @returns {JSX.Element|null} The rendered component.
19 */
20export default function Space({
21 space,
22 display,
23 currentSpaceIndex,
24 lastOfSpace,
25}) {
26 const { windows } = useYabaiContext();
27 const { SIPDisabled, settings } = useSimpleBarContext();
28 const { spacesDisplay } = settings;
29 const {
30 displayAllSpacesOnAllScreens,
31 exclusionsAsRegex,
32 displayStickyWindowsSeparately,
33 hideDuplicateAppsInSpaces,
34 showOptionsOnHover,
35 } = spacesDisplay;
36
37 const labelRef = React.useRef();
38 const [hovered, setHovered] = React.useState(false);
39 const [noDelay, setNoDelay] = React.useState(false);
40 const [editable, setEditable] = React.useState(false);
41 const {
42 index,
43 label,
44 "has-focus": hasFocus,
45 focused: __legacyHasFocus,
46 "is-visible": isVisible,
47 visible: __legacyIsVisible,
48 "is-native-fullscreen": isNativeFullscreen,
49 "native-fullscreen": __legacyIsNativeFullscreen,
50 type,
51 } = space;
52 const [spaceLabel, setSpaceLabel] = React.useState(
53 label?.length ? label : index,
54 );
55
56 // Return null if the space should not be displayed on the current screen
57 if (!displayAllSpacesOnAllScreens && display.index !== space.display)
58 return null;
59
60 const exclusions = exclusionsAsRegex
61 ? spacesDisplay.exclusions
62 : spacesDisplay.exclusions.split(", ");
63 const titleExclusions = exclusionsAsRegex
64 ? spacesDisplay.titleExclusions
65 : spacesDisplay.titleExclusions.split(", ");
66
67 /**
68 * Handle mouse enter event.
69 * @param {MouseEvent} e - The mouse event.
70 */
71 const onMouseEnter = (e) => {
72 if (!showOptionsOnHover) return;
73 const { altKey, metaKey } = e;
74 if (altKey) return;
75 setHovered(true);
76 if (metaKey) setNoDelay(true);
77 };
78
79 /**
80 * Handle mouse leave event.
81 */
82 const onMouseLeave = () => {
83 setHovered(false);
84 setNoDelay(false);
85 setEditable(false);
86 window.getSelection().removeAllRanges();
87 };
88
89 /**
90 * Handle click event.
91 * @param {MouseEvent} e - The mouse event.
92 */
93 const onClick = (e) => {
94 onMouseLeave(e);
95 if (e.altKey) {
96 setEditable(true);
97 labelRef.current?.select();
98 return;
99 }
100 if (hasFocus || __legacyHasFocus) return;
101 if (SIPDisabled && !spacesDisplay.switchSpacesWithoutYabai) {
102 Yabai.goToSpace(index);
103 Utils.clickEffect(e);
104 return;
105 }
106 Utils.switchSpace(currentSpaceIndex, index);
107 Utils.clickEffect(e);
108 };
109
110 /**
111 * Handle right-click event.
112 */
113 const onRightClick = () => {
114 setHovered(true);
115 setNoDelay(true);
116 };
117
118 /**
119 * Handle change event for the space label input.
120 * @param {Event} e - The change event.
121 */
122 const onChange = (e) => {
123 if (!editable) return;
124 const newLabel = e.target.value;
125 setSpaceLabel(newLabel);
126 Yabai.renameSpace(index, newLabel);
127 };
128
129 const { nonStickyWindows: apps, stickyWindows } =
130 Utils.stickyWindowWorkaround({
131 windows,
132 uniqueApps: hideDuplicateAppsInSpaces,
133 currentDisplay: display,
134 currentSpace: index,
135 exclusions,
136 titleExclusions,
137 exclusionsAsRegex,
138 });
139 const allApps = [...apps, ...stickyWindows];
140
141 // Determine if the space should be hidden
142 const hidden =
143 !(hasFocus ?? __legacyHasFocus) &&
144 !(isVisible ?? __legacyHasFocus) &&
145 !allApps.length &&
146 spacesDisplay.hideEmptySpaces;
147
148 if (hidden) return null;
149
150 const classes = Utils.classNames(`space space--${type}`, {
151 "space--focused": hasFocus ?? __legacyHasFocus,
152 "space--visible": isVisible ?? __legacyIsVisible,
153 "space--fullscreen": isNativeFullscreen ?? __legacyIsNativeFullscreen,
154 "space--hovered": hovered,
155 "space--no-delay": noDelay,
156 "space--empty": allApps.length,
157 "space--editable": editable,
158 });
159
160 const labelSize = (
161 typeof spaceLabel === "number" ? spaceLabel.toString() : spaceLabel
162 ).length;
163
164 return (
165 <React.Fragment>
166 {displayAllSpacesOnAllScreens && lastOfSpace && (
167 <div className="spaces__separator" />
168 )}
169 <div
170 className={classes}
171 onMouseLeave={onMouseLeave}
172 onMouseEnter={onMouseEnter}
173 >
174 <button
175 className="space__inner"
176 onClick={onClick}
177 onContextMenu={onRightClick}
178 >
179 <input
180 ref={labelRef}
181 type="text"
182 className="space__label"
183 onChange={onChange}
184 value={spaceLabel}
185 style={{ width: `${labelSize}ch` }}
186 readOnly={!editable}
187 />
188 <OpenedApps apps={displayStickyWindowsSeparately ? apps : allApps} />
189 </button>
190 {SIPDisabled && <SpaceOptions index={index} setHovered={setHovered} />}
191 </div>
192 </React.Fragment>
193 );
194}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/spaces.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/spaces.jsx
new file mode 100755
index 0000000..e3a69d0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/spaces.jsx
@@ -0,0 +1,109 @@
1import * as Uebersicht from "uebersicht";
2import Space from "./space.jsx";
3import Stickies from "./stickies.jsx";
4import * as Icons from "../icons/icons.jsx";
5import { SuspenseIcon } from "../icons/icon.jsx";
6import { useYabaiContext } from "../yabai-context.jsx";
7import { useSimpleBarContext } from "../simple-bar-context.jsx";
8import * as Utils from "../../utils";
9import * as Yabai from "../../yabai";
10
11export { spacesStyles as styles } from "../../styles/components/spaces/spaces";
12
13const { React } = Uebersicht;
14
15/**
16 * Spaces component to display spaces and manage space-related actions.
17 * @returns {JSX.Element|null} The rendered component.
18 */
19const Component = React.memo(() => {
20 // Get spaces and windows data from Yabai context
21 const { spaces, windows } = useYabaiContext();
22 // Get various settings and display information from simple-bar context
23 const { SIPDisabled, displayIndex, displays, settings } =
24 useSimpleBarContext();
25 const { spacesDisplay, process } = settings;
26 const {
27 displayStickyWindowsSeparately,
28 spacesExclusions,
29 exclusionsAsRegex,
30 hideCreateSpaceButton,
31 showOnDisplay,
32 } = spacesDisplay;
33 // Determine if the component should be visible on the current display
34 const visible = Utils.isVisibleOnDisplay(displayIndex, showOnDisplay);
35 const isProcessVisible = Utils.isVisibleOnDisplay(
36 displayIndex,
37 process.showOnDisplay,
38 );
39
40 if (!visible) return null;
41
42 if (!spaces && !windows) {
43 return <div className="spaces spaces--empty" />;
44 }
45
46 // Find the current space index
47 const { index: currentSpaceIndex } =
48 spaces.find((space) => {
49 const { "has-focus": hasFocus, focused: __legacyHasFocus } = space;
50 return hasFocus ?? __legacyHasFocus;
51 }) || {};
52
53 return displays.map((display, i) => {
54 if (display.index !== displayIndex) return null;
55
56 /**
57 * Handle click event to create a new space.
58 * @param {Event} e - The click event.
59 */
60 const onClick = async (e) => {
61 Utils.clickEffect(e);
62 await Yabai.createSpace(displayIndex);
63 };
64
65 return (
66 <div key={i} className="spaces">
67 {displayStickyWindowsSeparately && <Stickies display={display} />}
68 {spaces.map((space, i) => {
69 const { label, index } = space;
70 const lastOfSpace =
71 i !== 0 && space.display !== spaces[i - 1].display;
72
73 const key = label?.length ? label : index;
74 const spacesExclusionsList = spacesExclusions.replace(/ /g, "").split(",");
75 const isExcluded = Utils.isSpaceExcluded(
76 key,
77 spacesExclusionsList,
78 exclusionsAsRegex,
79 );
80
81 if (isExcluded) return null;
82
83 return (
84 <Space
85 key={key}
86 display={display}
87 space={space}
88 currentSpaceIndex={currentSpaceIndex}
89 lastOfSpace={lastOfSpace}
90 />
91 );
92 })}
93 {SIPDisabled && !hideCreateSpaceButton ? (
94 <button className="spaces__add" onClick={onClick}>
95 <SuspenseIcon>
96 <Icons.Add />
97 </SuspenseIcon>
98 </button>
99 ) : (
100 isProcessVisible && <div className="spaces__end-separator" />
101 )}
102 </div>
103 );
104 });
105});
106
107Component.displayName = "Spaces";
108
109export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/stickies.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/stickies.jsx
new file mode 100755
index 0000000..703bf68
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/stickies.jsx
@@ -0,0 +1,56 @@
1import OpenedApps from "./opened-apps.jsx";
2import { useYabaiContext } from "../yabai-context.jsx";
3import { useSimpleBarContext } from "../simple-bar-context.jsx";
4import * as Utils from "../../utils";
5
6/**
7 * Stickies component to display sticky windows.
8 * @param {Object} props - Component properties.
9 * @param {Object} props.display - The current display information.
10 * @returns {JSX.Element|null} The rendered component or null if no sticky windows are present.
11 */
12export default function Stickies({ display }) {
13 // Get windows from yabai context
14 const { windows } = useYabaiContext();
15 // Get settings from simple-bar context
16 const { settings } = useSimpleBarContext();
17 const { spacesDisplay } = settings;
18 const { exclusionsAsRegex, hideDuplicateAppsInSpaces } = spacesDisplay;
19
20 // Determine exclusions based on settings
21 const exclusions = exclusionsAsRegex
22 ? spacesDisplay.exclusions
23 : spacesDisplay.exclusions.split(", ");
24 const titleExclusions = exclusionsAsRegex
25 ? spacesDisplay.titleExclusions
26 : spacesDisplay.titleExclusions.split(", ");
27
28 // Get sticky windows using a utility function
29 const { stickyWindows: apps } = Utils.stickyWindowWorkaround({
30 windows,
31 uniqueApps: hideDuplicateAppsInSpaces,
32 currentDisplay: display,
33 currentSpace: undefined,
34 exclusions,
35 titleExclusions,
36 exclusionsAsRegex,
37 });
38
39 // Filter out minimized sticky windows
40 const notMinimizedStikies = apps.filter((app) => {
41 const { "is-minimized": isMinimized, minimized: __legacyIsMinimized } = app;
42 return !(isMinimized || __legacyIsMinimized);
43 });
44
45 // Return null if no non-minimized sticky windows are present
46 if (!notMinimizedStikies?.length) return null;
47
48 // Render the sticky windows
49 return (
50 <div className="stickies">
51 <div className="stickies__inner">
52 <OpenedApps apps={apps} />
53 </div>
54 </div>
55 );
56}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/window.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/window.jsx
new file mode 100755
index 0000000..2b47878
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/yabai/window.jsx
@@ -0,0 +1,119 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils";
6import * as Yabai from "../../yabai";
7
8const { React } = Uebersicht;
9
10/**
11 * Window component to display a window in simple-bar.
12 * @param {Object} props - The component props.
13 * @param {Object} props.window - The window object containing window details.
14 * @returns {JSX.Element|null} The rendered window component or null if the window is minimized or not focused.
15 */
16export default function Window({ window }) {
17 const { settings } = useSimpleBarContext();
18 const ref = React.useRef();
19
20 // Destructure settings for process display options
21 const {
22 displayOnlyCurrent,
23 hideWindowTitle,
24 displayOnlyIcon,
25 expandAllProcesses,
26 displayStackIndex,
27 displayOnlyCurrentStack,
28 } = settings.process;
29
30 // Destructure window properties
31 const {
32 "stack-index": stackIndex,
33 "is-minimized": isMinimized,
34 minimized: __legacyIsMinimized,
35 "has-focus": hasFocus,
36 focused: __legacyHasFocus,
37 app: appName,
38 title,
39 id,
40 } = window;
41
42 // Determine if the window is focused
43 const isFocused = hasFocus ?? __legacyHasFocus;
44
45 // Return null if the window is minimized or not focused when displayOnlyCurrent is true
46 if (
47 (isMinimized ?? __legacyIsMinimized) ||
48 (displayOnlyCurrent && !isFocused)
49 ) {
50 return null;
51 }
52
53 // Get the icon for the application or use the default icon
54 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
55
56 /**
57 * Handle click event on the window button.
58 * @param {Event} e - The click event.
59 */
60 const onClick = (e) => {
61 !displayOnlyCurrent && Utils.clickEffect(e);
62 Yabai.focusWindow(id);
63 };
64
65 /**
66 * Handle mouse enter event to start sliding animation.
67 */
68 const onMouseEnter = () => {
69 Utils.startSliding(ref.current, ".process__inner", ".process__name");
70 };
71
72 /**
73 * Handle mouse leave event to stop sliding animation.
74 */
75 const onMouseLeave = () => {
76 Utils.stopSliding(ref.current, ".process__name");
77 };
78
79 // Generate class names for the window button
80 const classes = Utils.classNames("process__window", {
81 "process__window--expanded": expandAllProcesses,
82 "process__window--focused": !displayOnlyCurrent && isFocused,
83 "process__window--only-current": displayOnlyCurrent,
84 "process__window--only-icon": displayOnlyIcon,
85 });
86
87 // Clean up the window name for display
88 const cleanedUpName =
89 appName !== title && title.length ? `${appName} / ${title}` : appName;
90 const processName = hideWindowTitle ? appName : cleanedUpName;
91
92 // Determine if the stack index should be displayed
93 const showStackIndex =
94 displayStackIndex &&
95 (!displayOnlyCurrentStack || isFocused) &&
96 stackIndex > 0;
97
98 return (
99 <button
100 ref={ref}
101 className={classes}
102 onClick={onClick}
103 onMouseEnter={displayOnlyIcon ? undefined : onMouseEnter}
104 onMouseLeave={displayOnlyIcon ? undefined : onMouseLeave}
105 >
106 <SuspenseIcon>
107 <Icon className="process__icon" />
108 </SuspenseIcon>
109 {!displayOnlyIcon && (
110 <span className="process__inner">
111 <span className="process__name">{processName}</span>
112 </span>
113 )}
114 {showStackIndex && (
115 <span className="process__stack-index">{stackIndex}</span>
116 )}
117 </button>
118 );
119}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-server-socket.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-server-socket.js
new file mode 100755
index 0000000..962c2be
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-server-socket.js
@@ -0,0 +1,221 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "../settings";
3import { useSimpleBarContext } from "../components/simple-bar-context.jsx";
4
5const { React } = Uebersicht;
6
7/**
8 * Custom hook to manage server socket connections and handle incoming messages.
9 *
10 * @param {string} target - The target widget to manage.
11 * @param {boolean} visible - Visibility state of the widget.
12 * @param {function} getter - Function to handle data retrieval.
13 * @param {function} resetWidget - Function to reset the widget state.
14 * @param {function} setLoading - Function to set the loading state.
15 * @param {number} [userWidgetIndex] - Index of the user widget (if applicable).
16 *
17 * @returns {void}
18 */
19export default function useServerSocket(
20 target,
21 visible,
22 getter,
23 resetWidget,
24 setLoading,
25 userWidgetIndex,
26) {
27 const { settings, setSettings } = useSimpleBarContext();
28 const { enableServer, serverSocketPort } = settings.global;
29 const socket = React.useRef(null);
30
31 const isUserWidget = target === "user-widget";
32
33 /**
34 * Handles incoming WebSocket messages and performs actions based on the message content.
35 * @param {Object} e - The event object containing the message data.
36 * @param {string} e.data - The JSON string containing the action and data.
37 * @param {string} e.data.action - The action to perform (e.g., "push", "refresh", "disable", "enable", "toggle").
38 * @param {Object} e.data.data - The data associated with the action.
39 */
40 const handleMessage = React.useCallback(
41 (e) => {
42 const { action, data } = JSON.parse(e.data);
43
44 if (action === "push" || (visible && action === "refresh")) {
45 getter(data);
46 }
47
48 if (action === "disable" || action === "enable") {
49 const state = action === "enable";
50
51 if (isUserWidget) {
52 toggleUserWidget(
53 userWidgetIndex,
54 resetWidget,
55 setSettings,
56 state,
57 setLoading,
58 );
59 } else {
60 toggleWidget(target, resetWidget, setSettings, state, setLoading);
61 }
62 }
63
64 if (action === "toggle") {
65 if (isUserWidget) {
66 toggleUserWidget(
67 userWidgetIndex,
68 resetWidget,
69 setSettings,
70 undefined,
71 setLoading,
72 );
73 } else {
74 toggleWidget(target, resetWidget, setSettings, undefined, setLoading);
75 }
76 }
77 },
78 [
79 getter,
80 isUserWidget,
81 resetWidget,
82 setLoading,
83 setSettings,
84 target,
85 userWidgetIndex,
86 visible,
87 ],
88 );
89
90 React.useEffect(() => {
91 // If the server is enabled, create a new WebSocket connection
92 if (enableServer) {
93 // If the socket is not already created, create a new one
94 if (socket.current === null) {
95 let queryParams = `target=${target}`;
96
97 if (userWidgetIndex !== undefined) {
98 queryParams = queryParams.concat(
99 `&userWidgetIndex=${userWidgetIndex}`,
100 );
101 }
102
103 const newSocket = new WebSocket(
104 `ws://localhost:${serverSocketPort}/?${queryParams}`,
105 );
106
107 newSocket.onmessage = handleMessage;
108 socket.current = newSocket;
109 }
110 } else {
111 // If the server is disabled, close the socket if it exists
112 if (socket.current) {
113 socket.current.close();
114 socket.current = null;
115 }
116 }
117 }, [enableServer, handleMessage, serverSocketPort, target, userWidgetIndex]);
118}
119
120const settingsKeys = {
121 battery: "batteryWidget",
122 "browser-track": "browserTrackWidget",
123 cpu: "cpuWidget",
124 crypto: "cryptoWidget",
125 "date-display": "dateWidget",
126 gpu: "gpuWidget",
127 keyboard: "keyboardWidget",
128 mic: "micWidget",
129 mpd: "mpdWidget",
130 music: "musicWidget",
131 netstats: "netstatsWidget",
132 "next-meeting": "nextMeetingWidget",
133 notifications: "notificationsWidget",
134 sound: "soundWidget",
135 spotify: "spotifyWidget",
136 stock: "stockWidget",
137 time: "timeWidget",
138 "viscosity-vpn": "vpnWidget",
139 weather: "weatherWidget",
140 wifi: "wifiWidget",
141 memory: "memoryWidget",
142 "youtube-music": "youtubeMusicWidget",
143 zoom: "zoomWidget",
144};
145
146/**
147 * Toggles the state of a widget and updates the settings accordingly.
148 *
149 * @param {string} widget - The name of the widget to toggle.
150 * @param {Function} resetWidget - A function to reset the widget state, if needed.
151 * @param {Function} setSettings - A function to update the settings state.
152 * @param {boolean} [forcedState] - An optional parameter to force the widget state.
153 * @param {Function} setLoading - A function to set the loading state.
154 * @returns {Promise<void>} - A promise that resolves when the widget state is toggled.
155 */
156async function toggleWidget(
157 widget,
158 resetWidget,
159 setSettings,
160 forcedState,
161 setLoading,
162) {
163 const key = settingsKeys[widget];
164 setSettings((settings) => {
165 const { widgets } = settings;
166 const active = forcedState ?? !widgets[key];
167 if (!active) {
168 resetWidget?.();
169 } else {
170 setLoading?.(true);
171 }
172 const newSettings = {
173 ...settings,
174 widgets: { ...widgets, [key]: active },
175 };
176 Settings.set(newSettings);
177 return newSettings;
178 });
179}
180
181/**
182 * Toggles the active state of a user widget.
183 *
184 * @param {number} index - The index of the user widget to toggle.
185 * @param {Function} resetWidget - A function to reset the widget, called when the widget is deactivated.
186 * @param {Function} setSettings - A function to update the settings state.
187 * @param {boolean} [forcedState] - An optional boolean to force the widget's active state.
188 * @param {Function} setLoading - A function to set the loading state, called when the widget is activated.
189 * @returns {Promise<void>} A promise that resolves when the settings have been updated.
190 */
191async function toggleUserWidget(
192 index,
193 resetWidget,
194 setSettings,
195 forcedState,
196 setLoading,
197) {
198 setSettings((settings) => {
199 const { userWidgetsList = {} } = settings.userWidgets;
200 const active = forcedState ?? !userWidgetsList[index].active;
201 if (!active) {
202 resetWidget?.();
203 } else {
204 setLoading?.(true);
205 }
206 const newUserWidgetsList = {
207 ...userWidgetsList,
208 [index]: { ...userWidgetsList[index], active },
209 };
210
211 const newSettings = {
212 ...settings,
213 userWidgets: {
214 ...settings.userWidgets,
215 userWidgetsList: newUserWidgetsList,
216 },
217 };
218 Settings.set(newSettings);
219 return newSettings;
220 });
221}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-widget-refresh.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-widget-refresh.js
new file mode 100755
index 0000000..cf79515
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/hooks/use-widget-refresh.js
@@ -0,0 +1,37 @@
1import * as Uebersicht from "uebersicht";
2
3const { React } = Uebersicht;
4
5/**
6 * Custom hook to refresh a widget at a specified frequency.
7 *
8 * @param {boolean} active - Flag indicating whether the widget is active.
9 * @param {Function} getter - Function to fetch or update the widget data.
10 * @param {number} refreshFrequency - Frequency in milliseconds to refresh the widget.
11 */
12export default function useWidgetRefresh(active, getter, refreshFrequency) {
13 const abortableGetter = React.useCallback(
14 (signal) => {
15 if (!active || signal.aborted) return;
16 getter();
17 },
18 [active, getter],
19 );
20
21 React.useEffect(() => {
22 const controller = new AbortController();
23 if (active) {
24 abortableGetter(controller.signal);
25 const interval = setInterval(
26 () => abortableGetter(controller.signal),
27 refreshFrequency,
28 );
29 return () => {
30 controller.abort();
31 clearInterval(interval);
32 };
33 } else {
34 controller.abort();
35 }
36 }, [active, abortableGetter, refreshFrequency]);
37}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/schemas/config.json b/users/ryan/modules/simple-bar/simple-bar-source/lib/schemas/config.json
new file mode 100755
index 0000000..e10efa2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/schemas/config.json
@@ -0,0 +1,1159 @@
1{
2 "$schema": "http://json-schema.org/draft-07/schema#",
3 "$id": "config.json",
4 "title": "simple-bar config JSON schema",
5 "type": "object",
6 "additionalProperties": false,
7 "properties": {
8 "$schema": { "type": "string" },
9 "global": {
10 "type": "object",
11 "additionalProperties": false,
12 "properties": {
13 "theme": {
14 "type": "string",
15 "enum": ["auto", "dark", "light"],
16 "description": "Theme to use"
17 },
18 "floatingBar": {
19 "type": "boolean",
20 "description": "Make simple-bar floating by adding padding around it"
21 },
22 "noBarBg": {
23 "type": "boolean",
24 "description": "Remove the background of the bar"
25 },
26 "noColorInData": {
27 "type": "boolean",
28 "description": "Remove colors from all data widgets"
29 },
30 "bottomBar": {
31 "type": "boolean",
32 "description": "Place simple-bar at the bottom of the screen"
33 },
34 "sideDecoration": {
35 "type": "boolean",
36 "description": "Add an Apple logo on the left side of simple-bar"
37 },
38 "inlineSpacesOptions": {
39 "type": "boolean",
40 "description": "Show spaces options inline"
41 },
42 "disableAnimations": {
43 "type": "boolean",
44 "description": "Disable all persistent animations in simple-bar"
45 },
46 "disableNotifications": {
47 "type": "boolean",
48 "description": "Disable notifications"
49 },
50 "enableMissives": {
51 "type": "boolean",
52 "description": "Enable missives (internal notification system)"
53 },
54 "compactMode": {
55 "type": "boolean",
56 "description": "Enable compact mode"
57 },
58 "widgetMaxWidth": {
59 "type": "string",
60 "description": "Max width for widgets. Overflowing text while be shown with a sliding effect"
61 },
62 "spacesBackgroundColorAsForeground": {
63 "type": "boolean",
64 "description": "Use spaces background color as foreground color"
65 },
66 "widgetsBackgroundColorAsForeground": {
67 "type": "boolean",
68 "description": "Use widgets background color as foreground color"
69 },
70 "font": {
71 "type": "string",
72 "description": "Define the font used by simple-bar"
73 },
74 "fontSize": {
75 "type": "string",
76 "description": "Define the font size for all the widgets. You can use any css unit. It can particulary be usefull if you have displays with different pixel density and different scaling factor in which case you can set a value with a relative viewport unit like 1vh. Be careful to not set a value too high as it could break all simple-bar interface as this setting is used for every texts"
77 },
78 "yabaiPath": {
79 "type": "string",
80 "description": "Determine the path to the yabai binary"
81 },
82 "aerospacePath": {
83 "type": "string",
84 "description": "Determine the path to the aerospace binary"
85 },
86 "windowManager": {
87 "type": "string",
88 "enum": ["yabai", "aerospace"],
89 "description": "Determine the window manager used by simple-bar to display spaces & processes: yabai or aerospace"
90 },
91 "shell": {
92 "type": "string",
93 "enum": ["sh", "bash", "dash"],
94 "description": "Depending on your preference you can choose between these 3 shell for all simple-bar scripts execution: sh, bash, dash"
95 },
96 "terminal": {
97 "type": "string",
98 "enum": ["Terminal", "iTerm2"],
99 "description": "Define the terminal used by simple-bar to run commands"
100 },
101 "slidingAnimationPace": {
102 "type": "number",
103 "description": "Determine the speed of the sliding animation for widgets with overflowing text. Default is \"4\". The higher slidingAnimationPace value, the faster the texts slides (must be > 0)"
104 },
105 "enableServer": {
106 "type": "boolean",
107 "description": "Enable websocket connection to the server in each data widget. You must install and launch simple-bar-server before activating this setting"
108 },
109 "serverSocketPort": {
110 "type": "number",
111 "description": "Determine the port on which the websockets will be opened. Check you simple-bar-server config file to get the right port if you changed it"
112 },
113 "yabaiServerRefresh": {
114 "type": "boolean",
115 "description": "Enable websocket connection to the server in yabai spaces & process widgets. You must install and launch simple-bar-server before activating this setting"
116 },
117 "aerospaceServerRefresh": {
118 "type": "boolean",
119 "description": "Enable websocket connection to the server in AeroSpace spaces widgets. You must install and launch simple-bar-server before activating this setting"
120 }
121 }
122 },
123 "themes": {
124 "type": "object",
125 "additionalProperties": false,
126 "properties": {
127 "lightTheme": {
128 "type": "string",
129 "description": "Light theme to use"
130 },
131 "darkTheme": {
132 "type": "string",
133 "description": "Dark theme to use"
134 },
135 "colorMain": {
136 "type": "string",
137 "description": "Override the main color of the theme. Must be a valid CSS color."
138 },
139 "colorMainAlt": {
140 "type": "string",
141 "description": "Override the main alternative color of the theme. Must be a valid CSS color."
142 },
143 "colorMinor": {
144 "type": "string",
145 "description": "Override the minor color of the theme. Must be a valid CSS color."
146 },
147 "colorAccent": {
148 "type": "string",
149 "description": "Override the accent color of the theme. Must be a valid CSS color."
150 },
151 "colorRed": {
152 "type": "string",
153 "description": "Override the red color of the theme. Must be a valid CSS color."
154 },
155 "colorGreen": {
156 "type": "string",
157 "description": "Override the green color of the theme. Must be a valid CSS color."
158 },
159 "colorYellow": {
160 "type": "string",
161 "description": "Override the yellow color of the theme. Must be a valid CSS color."
162 },
163 "colorOrange": {
164 "type": "string",
165 "description": "Override the orange color of the theme. Must be a valid CSS color."
166 },
167 "colorBlue": {
168 "type": "string",
169 "description": "Override the blue color of the theme. Must be a valid CSS color."
170 },
171 "colorMagenta": {
172 "type": "string",
173 "description": "Override the magenta color of the theme. Must be a valid CSS color."
174 },
175 "colorCyan": {
176 "type": "string",
177 "description": "Override the cya color of the theme. Must be a valid CSS color."
178 },
179 "colorBlack": {
180 "type": "string",
181 "description": "Override the black color of the theme. Must be a valid CSS color."
182 },
183 "colorWhite": {
184 "type": "string",
185 "description": "Override the white color of the theme. Must be a valid CSS color."
186 },
187 "colorForeground": {
188 "type": "string",
189 "description": "Override the foreground color of the theme. Must be a valid CSS color."
190 },
191 "colorBackground": {
192 "type": "string",
193 "description": "Override the background color of the theme. Must be a valid CSS color."
194 }
195 }
196 },
197 "process": {
198 "type": "object",
199 "additionalProperties": false,
200 "properties": {
201 "showOnDisplay": {
202 "type": "string",
203 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
204 },
205 "displayOnlyCurrent": {
206 "type": "boolean",
207 "description": "Insead of showing all processes of the current space, simple-bar will only show the current one"
208 },
209 "centered": {
210 "type": "boolean",
211 "description": "The process widget will be centered. Do not activate it if you run simple-bar on a mac with a notch"
212 },
213 "showCurrentSpaceMode": {
214 "type": "boolean",
215 "description": "[yabai] Show the current space yabai mode on the left of the processes"
216 },
217 "hideWindowTitle": {
218 "type": "boolean",
219 "description": "Hide window titles"
220 },
221 "displayOnlyIcon": {
222 "type": "boolean",
223 "description": "Show only the process icon"
224 },
225 "expandAllProcesses": {
226 "type": "boolean",
227 "description": "All processes are revealed"
228 },
229 "displaySkhdMode": {
230 "type": "boolean",
231 "description": "[yabai] If the current space is in stack mode, each process will have its stack index displayed"
232 },
233 "displayStackIndex": {
234 "type": "boolean",
235 "description": "[yabai] Show stack index only on focused process"
236 },
237 "displayOnlyCurrentStack": {
238 "type": "boolean",
239 "description": "[yabai] Show stack-index only for focused process"
240 }
241 }
242 },
243 "spacesDisplay": {
244 "type": "object",
245 "additionalProperties": false,
246 "properties": {
247 "showOnDisplay": {
248 "type": "string",
249 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
250 },
251 "exclusions": {
252 "type": "string",
253 "description": "You can exclude some process with their app name. Simply add the wanted app name and separate multiple app names with a comma"
254 },
255 "titleExclusions": {
256 "type": "string",
257 "description": "Same as previous settings but with the window title name"
258 },
259 "spacesExclusions": {
260 "type": "string",
261 "description": "Whole space(s) can be excluded for the spaces display by their name here separated by a comma"
262 },
263 "exclusionsAsRegex": {
264 "type": "boolean",
265 "description": "Instead of using comma in the exclusions fields, you can use the regex syntax"
266 },
267 "displayAllSpacesOnAllScreens": {
268 "type": "boolean",
269 "description": "By default, only spaces attached to the current display are displayed on all displays. This can be changed with this setting"
270 },
271 "hideDuplicateAppsInSpaces": {
272 "type": "boolean",
273 "description": "Each instance of an app is displayed separately in their respective space. You can merge all duplicates with this setting"
274 },
275 "displayStickyWindowsSeparately": {
276 "type": "boolean",
277 "description": "[yabai] Sticky windows are displayed on each screens by default. You can choose to displayed only in one place thanks to this settings (at the left of all the spaces)"
278 },
279 "hideCreateSpaceButton": {
280 "type": "boolean",
281 "description": "[yabai] Simply hide the \"+\" button (which is only visible if you have SIP disabled)"
282 },
283 "hideEmptySpaces": {
284 "type": "boolean",
285 "description": "Hide spaces with no opened apps"
286 },
287 "showOptionsOnHover": {
288 "type": "boolean",
289 "description": "Space options are opened on right click if this setting is set to false"
290 },
291 "switchSpacesWithoutYabai": {
292 "type": "boolean",
293 "description": "Instead of relying on yabai to switch to a specific space (on space click), simple-bar will trigger the \"switch to prev/next\" space shortcut which need to be enabled in macos settings to be working"
294 },
295 "customAeroSpaceDisplayIndexes": {
296 "type": "object",
297 "description": "[AeroSpace] Allow display numbering override in case of monitor numbering mismatch between AeroSpace and Übersicht",
298 "patternProperties": {
299 "^\\d+$": {
300 "type": "number",
301 "description": "Override the display index for the monitor with the given ID"
302 }
303 }
304 }
305 }
306 },
307 "widgets": {
308 "type": "object",
309 "additionalProperties": false,
310 "properties": {
311 "processWidget": {
312 "type": "boolean",
313 "description": "Hide or show the process widget"
314 },
315 "githubWidget": {
316 "type": "boolean",
317 "description": "Hide or show the GitHub widget"
318 },
319 "weatherWidget": {
320 "type": "boolean",
321 "description": "Hide or show the weather widget"
322 },
323 "netstatsWidget": {
324 "type": "boolean",
325 "description": "Hide or show the netstats widget"
326 },
327 "cpuWidget": {
328 "type": "boolean",
329 "description": "Hide or show the CPU widget"
330 },
331 "gpuWidget": {
332 "type": "boolean",
333 "description": "Hide or show the GPU widget"
334 },
335 "memoryWidget": {
336 "type": "boolean",
337 "description": "Hide or show the memory widget"
338 },
339 "batteryWidget": {
340 "type": "boolean",
341 "description": "Hide or show the battery widget"
342 },
343 "wifiWidget": {
344 "type": "boolean",
345 "description": "Hide or show the wifi widget"
346 },
347 "vpnWidget": {
348 "type": "boolean",
349 "description": "Hide or show the VPN widget"
350 },
351 "zoomWidget": {
352 "type": "boolean",
353 "description": "Hide or show the Zoom widget"
354 },
355 "soundWidget": {
356 "type": "boolean",
357 "description": "Hide or show the sound widget"
358 },
359 "micWidget": {
360 "type": "boolean",
361 "description": "Hide or show the microphone widget"
362 },
363 "dateWidget": {
364 "type": "boolean",
365 "description": "Hide or show the date widget"
366 },
367 "timeWidget": {
368 "type": "boolean",
369 "description": "Hide or show the time widget"
370 },
371 "keyboardWidget": {
372 "type": "boolean",
373 "description": "Hide or show the keyboard widget"
374 },
375 "spotifyWidget": {
376 "type": "boolean",
377 "description": "Hide or show the Spotify widget"
378 },
379 "cryptoWidget": {
380 "type": "boolean",
381 "description": "Hide or show the Crypto widget"
382 },
383 "stockWidget": {
384 "type": "boolean",
385 "description": "Hide or show the stocks widget"
386 },
387 "youtubeMusicWidget": {
388 "type": "boolean",
389 "description": "Hide or show the Youtube widget"
390 },
391 "musicWidget": {
392 "type": "boolean",
393 "description": "Hide or show the Music widget"
394 },
395 "mpdWidget": {
396 "type": "boolean",
397 "description": "Hide or show the MPD widget"
398 },
399 "browserTrackWidget": {
400 "type": "boolean",
401 "description": "Hide or show the browser track widget"
402 },
403 "notificationsWidget": {
404 "type": "boolean",
405 "description": "Hide or show the notification badges widget"
406 },
407 "nextMeetingWidget": {
408 "type": "boolean",
409 "description": "Hide or show the next meeting widget"
410 }
411 }
412 },
413 "githubWidgetOptions": {
414 "type": "object",
415 "additionalProperties": false,
416 "properties": {
417 "refreshFrequency": {
418 "type": "number",
419 "description": "The refresh frequency of this widget in milliseconds"
420 },
421 "showOnDisplay": {
422 "type": "string",
423 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
424 },
425 "showIcon": {
426 "type": "boolean",
427 "description": "Show or hide the widget icon"
428 },
429 "hideWhenNoNotification": {
430 "type": "boolean",
431 "description": "Hide the widget when there is no notification"
432 },
433 "notificationUrl": {
434 "type": "string",
435 "description": "The URL opened on click. Default is \"https://github.com/notifications\""
436 },
437 "ghBinaryPath": {
438 "type": "string",
439 "description": "The binary path required to get GitHub notifications count in the widget"
440 }
441 }
442 },
443 "weatherWidgetOptions": {
444 "type": "object",
445 "additionalProperties": false,
446 "properties": {
447 "refreshFrequency": {
448 "type": "number",
449 "description": "The refresh frequency of this widget in milliseconds"
450 },
451 "showOnDisplay": {
452 "type": "string",
453 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
454 },
455 "showIcon": {
456 "type": "boolean",
457 "description": "Show or hide the widget icon"
458 },
459 "unit": {
460 "type": "string",
461 "enum": ["C", "F"],
462 "description": "The temperature unit to use (C or F)"
463 },
464 "hideLocation": {
465 "type": "boolean",
466 "description": "Hide the location in the widget"
467 },
468 "hideGradient": {
469 "type": "boolean",
470 "description": "Hide the sunset/sunrise gradient in the widget"
471 },
472 "customLocation": {
473 "type": "string",
474 "description": "Set your location. If empty, the location is determined by the location API"
475 }
476 }
477 },
478 "netstatsWidgetOptions": {
479 "type": "object",
480 "additionalProperties": false,
481 "properties": {
482 "refreshFrequency": {
483 "type": "number",
484 "description": "The refresh frequency of this widget in milliseconds"
485 },
486 "showOnDisplay": {
487 "type": "string",
488 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
489 },
490 "showIcon": {
491 "type": "boolean",
492 "description": "Show or hide the widget icon"
493 },
494 "displayAsGraph": {
495 "type": "boolean",
496 "description": "Instead of show current network information, the widget will display a graphic showing the latest 60 seconds (it can change depending of the refresh frequency of the widget) of network activity. All drawn points are relative to the highest value"
497 },
498 "netstatsThreshold": {
499 "type": "number",
500 "description": "Hide the widget when download and upload are below this value in kb/s (0 to always show)"
501 }
502 }
503 },
504 "cpuWidgetOptions": {
505 "type": "object",
506 "additionalProperties": false,
507 "properties": {
508 "refreshFrequency": {
509 "type": "number",
510 "description": "The refresh frequency of this widget in milliseconds"
511 },
512 "showOnDisplay": {
513 "type": "string",
514 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
515 },
516 "showIcon": {
517 "type": "boolean",
518 "description": "Show or hide the widget icon"
519 },
520 "displayAsGraph": {
521 "type": "boolean",
522 "description": "Instead of show current CPU information, the widget will display a graphic showing the latest 100 seconds (it can change depending of the refresh frequency of the widget) of CPU activity. All drawn points are relative to the highest value"
523 },
524 "cpuUsageThreshold": {
525 "type": "number",
526 "description": "Hide the widget when CPU usage is below this percentage (0 to always show)"
527 },
528 "cpuMonitorApp": {
529 "type": "string",
530 "enum": ["Activity Monitor", "Top", "None"],
531 "description": "Define the opened app on widget click: Activity Monitor, Top or None"
532 }
533 }
534 },
535 "gpuWidgetOptions": {
536 "type": "object",
537 "additionalProperties": false,
538 "properties": {
539 "refreshFrequency": {
540 "type": "number",
541 "description": "The refresh frequency of this widget in milliseconds"
542 },
543 "showOnDisplay": {
544 "type": "string",
545 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
546 },
547 "showIcon": {
548 "type": "boolean",
549 "description": "Show or hide the widget icon"
550 },
551 "displayAsGraph": {
552 "type": "boolean",
553 "description": "Instead of show current CPU information, the widget will display a graphic showing the latest 100 seconds (it can change depending of the refresh frequency of the widget) of CPU activity. All drawn points are relative to the highest value"
554 },
555 "gpuMacmonBinaryPath": {
556 "type": "string",
557 "description": "The binary path required to get GPU usage in the widget"
558 }
559 }
560 },
561 "memoryWidgetOptions": {
562 "type": "object",
563 "additionalProperties": false,
564 "properties": {
565 "refreshFrequency": { "type": "number" },
566 "showOnDisplay": {
567 "type": "string",
568 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
569 },
570 "showIcon": {
571 "type": "boolean",
572 "description": "Show or hide the widget icon"
573 },
574 "memoryUsageThreshold": {
575 "type": "number",
576 "description": "Hide the widget when used memory is below this percentage (0 to always show)"
577 },
578 "memoryMonitorApp": {
579 "type": "string",
580 "enum": ["Activity Monitor", "Top", "None"],
581 "description": "Define the opened app on widget click: Activity Monitor, Top or None"
582 }
583 }
584 },
585 "batteryWidgetOptions": {
586 "type": "object",
587 "additionalProperties": false,
588 "properties": {
589 "refreshFrequency": {
590 "type": "number",
591 "description": "The refresh frequency of this widget in milliseconds"
592 },
593 "showOnDisplay": {
594 "type": "string",
595 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
596 },
597 "showIcon": {
598 "type": "boolean",
599 "description": "Show or hide the widget icon"
600 },
601 "toggleCaffeinateOnClick": {
602 "type": "boolean",
603 "description": "Enable the toggle of caffeinate mode on click"
604 },
605 "caffeinateOption": {
606 "type": "string",
607 "description": "The options to pass to caffeinate when toggling it"
608 }
609 }
610 },
611 "networkWidgetOptions": {
612 "type": "object",
613 "additionalProperties": false,
614 "properties": {
615 "refreshFrequency": {
616 "type": "number",
617 "description": "The refresh frequency of this widget in milliseconds"
618 },
619 "showOnDisplay": {
620 "type": "string",
621 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
622 },
623 "showIcon": {
624 "type": "boolean",
625 "description": "Show or hide the widget icon"
626 },
627 "networkDevice": {
628 "type": "string",
629 "description": "The network device source name"
630 },
631 "hideWifiIfDisabled": {
632 "type": "boolean",
633 "description": "Hide the widget if the network is disabled"
634 },
635 "toggleWifiOnClick": {
636 "type": "boolean",
637 "description": "Toggle wifi on click"
638 },
639 "hideNetworkName": {
640 "type": "boolean",
641 "description": "Hide the network name"
642 }
643 }
644 },
645 "vpnWidgetOptions": {
646 "type": "object",
647 "additionalProperties": false,
648 "properties": {
649 "refreshFrequency": {
650 "type": "number",
651 "description": "The refresh frequency of this widget in milliseconds"
652 },
653 "showOnDisplay": {
654 "type": "string",
655 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
656 },
657 "showIcon": {
658 "type": "boolean",
659 "description": "Show or hide the widget icon"
660 },
661 "vpnConnectionName": {
662 "type": "string",
663 "description": "The name of the connection you want to display"
664 },
665 "vpnShowConnectionName": {
666 "type": "boolean",
667 "description": "Display the connection name in the widget"
668 }
669 }
670 },
671 "zoomWidgetOptions": {
672 "type": "object",
673 "additionalProperties": false,
674 "properties": {
675 "refreshFrequency": {
676 "type": "number",
677 "description": "The refresh frequency of this widget in milliseconds"
678 },
679 "showOnDisplay": {
680 "type": "string",
681 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
682 },
683 "showVideo": {
684 "type": "boolean",
685 "description": "Displays your current call video status"
686 },
687 "showMic": {
688 "type": "boolean",
689 "description": "Displays your current call microphone status"
690 }
691 }
692 },
693 "soundWidgetOptions": {
694 "type": "object",
695 "additionalProperties": false,
696 "properties": {
697 "refreshFrequency": {
698 "type": "number",
699 "description": "The refresh frequency of this widget in milliseconds"
700 },
701 "showOnDisplay": {
702 "type": "string",
703 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
704 },
705 "showIcon": {
706 "type": "boolean",
707 "description": "Show or hide the widget icon"
708 },
709 "keyboardMaxLength": {
710 "type": "number",
711 "description": "Maximum number of characters to display for the keyboard layout (0 to show full name)"
712 }
713 }
714 },
715 "micWidgetOptions": {
716 "type": "object",
717 "additionalProperties": false,
718 "properties": {
719 "refreshFrequency": {
720 "type": "number",
721 "description": "The refresh frequency of this widget in milliseconds"
722 },
723 "showOnDisplay": {
724 "type": "string",
725 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
726 },
727 "showIcon": {
728 "type": "boolean",
729 "description": "Show or hide the widget icon"
730 }
731 }
732 },
733 "dateWidgetOptions": {
734 "type": "object",
735 "additionalProperties": false,
736 "properties": {
737 "refreshFrequency": {
738 "type": "number",
739 "description": "The refresh frequency of this widget in milliseconds"
740 },
741 "showOnDisplay": {
742 "type": "string",
743 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
744 },
745 "showIcon": {
746 "type": "boolean",
747 "description": "Show or hide the widget icon"
748 },
749 "shortDateFormat": {
750 "type": "boolean",
751 "description": "If true, the date will be displayed in short format"
752 },
753 "locale": {
754 "type": "string",
755 "description": "The locale to use for the date"
756 },
757 "calendarApp": {
758 "type": "string",
759 "description": "The calendar app to open when clicking on the date"
760 }
761 }
762 },
763 "timeWidgetOptions": {
764 "type": "object",
765 "additionalProperties": false,
766 "properties": {
767 "refreshFrequency": {
768 "type": "number",
769 "description": "The refresh frequency of this widget in milliseconds"
770 },
771 "showOnDisplay": {
772 "type": "string",
773 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
774 },
775 "showIcon": {
776 "type": "boolean",
777 "description": "Show or hide the widget icon"
778 },
779 "hour12": {
780 "type": "boolean",
781 "description": "Display time in 12h format"
782 },
783 "dayProgress": {
784 "type": "boolean",
785 "description": "Display day progress"
786 },
787 "showSeconds": {
788 "type": "boolean",
789 "description": "Display seconds"
790 }
791 }
792 },
793 "keyboardWidgetOptions": {
794 "type": "object",
795 "additionalProperties": false,
796 "properties": {
797 "refreshFrequency": {
798 "type": "number",
799 "description": "The refresh frequency of this widget in milliseconds"
800 },
801 "showOnDisplay": {
802 "type": "string",
803 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
804 },
805 "showIcon": {
806 "type": "boolean",
807 "description": "Show or hide the widget icon"
808 }
809 }
810 },
811 "cryptoWidgetOptions": {
812 "type": "object",
813 "additionalProperties": false,
814 "properties": {
815 "refreshFrequency": {
816 "type": "number",
817 "description": "The refresh frequency of this widget in milliseconds"
818 },
819 "showOnDisplay": {
820 "type": "string",
821 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
822 },
823 "showIcon": {
824 "type": "boolean",
825 "description": "Show or hide the widget icon"
826 },
827 "denomination": {
828 "type": "string",
829 "enum": ["usd", "eur"],
830 "description": "The displayed denomination, usd or eur"
831 },
832 "identifiers": {
833 "type": "string",
834 "description": "You can set a list of denomination Default is \"bitcoin,ethereum,celo\". Only theses 3 identifiers have a personalized icon"
835 },
836 "precision": {
837 "type": "number",
838 "description": "The number of decimals to display"
839 }
840 }
841 },
842 "stockWidgetOptions": {
843 "type": "object",
844 "additionalProperties": false,
845 "properties": {
846 "refreshFrequency": {
847 "type": "number",
848 "description": "The refresh frequency of this widget in milliseconds"
849 },
850 "showOnDisplay": {
851 "type": "string",
852 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
853 },
854 "showIcon": {
855 "type": "boolean",
856 "description": "Show or hide the widget icon"
857 },
858 "yahooFinanceApiKey": {
859 "type": "string",
860 "description": "Your API key for Yahoo Finance"
861 },
862 "symbols": {
863 "type": "string",
864 "description": "The symbols for your stocks, ETFs, mutual funds,..."
865 },
866 "showSymbol": {
867 "type": "boolean",
868 "description": "Show the symbol of the currency"
869 },
870 "showCurrency": {
871 "type": "boolean",
872 "description": "Show the currency of the currency"
873 },
874 "showMarketPrice": {
875 "type": "boolean",
876 "description": "Show the market price of the currency"
877 },
878 "showMarketChange": {
879 "type": "boolean",
880 "description": "Show the change of the currency"
881 },
882 "showMarketPercent": {
883 "type": "boolean",
884 "description": "Show the change of the currency percent"
885 },
886 "showColor": {
887 "type": "boolean",
888 "description": "Show the market change in red or green"
889 }
890 }
891 },
892 "spotifyWidgetOptions": {
893 "type": "object",
894 "additionalProperties": false,
895 "properties": {
896 "refreshFrequency": {
897 "type": "number",
898 "description": "The refresh frequency of this widget in milliseconds"
899 },
900 "showOnDisplay": {
901 "type": "string",
902 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
903 },
904 "showIcon": {
905 "type": "boolean",
906 "description": "Show or hide the widget icon"
907 },
908 "showSpotifyMetadata": {
909 "type": "boolean",
910 "description": "Show or hide Spotify metadata (author name, song name)."
911 },
912 "showSpecter": {
913 "type": "boolean",
914 "description": "Show the specter animation when a song is playing"
915 }
916 }
917 },
918 "youtubeMusicWidgetOptions": {
919 "type": "object",
920 "additionalProperties": false,
921 "properties": {
922 "refreshFrequency": {
923 "type": "number",
924 "description": "The refresh frequency of this widget in milliseconds"
925 },
926 "showOnDisplay": {
927 "type": "string",
928 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
929 },
930 "showIcon": {
931 "type": "boolean",
932 "description": "Show or hide the widget icon"
933 },
934 "showSpecter": {
935 "type": "boolean",
936 "description": "Show the specter animation when a song is playing"
937 },
938 "youtubeMusicPort": {
939 "type": "number",
940 "description": "The port on which the YoutubeMusic server is running"
941 }
942 }
943 },
944 "musicWidgetOptions": {
945 "type": "object",
946 "additionalProperties": false,
947 "properties": {
948 "refreshFrequency": {
949 "type": "number",
950 "description": "The refresh frequency of this widget in milliseconds"
951 },
952 "showOnDisplay": {
953 "type": "string",
954 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
955 },
956 "showIcon": {
957 "type": "boolean",
958 "description": "Show or hide the widget icon"
959 },
960 "showSpecter": {
961 "type": "boolean",
962 "description": "Show the specter animation when a song is playing"
963 }
964 }
965 },
966 "mpdWidgetOptions": {
967 "type": "object",
968 "additionalProperties": false,
969 "properties": {
970 "refreshFrequency": {
971 "type": "number",
972 "description": "The refresh frequency of this widget in milliseconds"
973 },
974 "showOnDisplay": {
975 "type": "string",
976 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
977 },
978 "showIcon": {
979 "type": "boolean",
980 "description": "Show or hide the widget icon"
981 },
982 "showSpecter": {
983 "type": "boolean",
984 "description": "Show the specter animation when a song is playing"
985 },
986 "mpdBinaryPath": {
987 "type": "string",
988 "description": "The binary path required to run mpc commands from the widget"
989 },
990 "mpdPort": { "type": "string", "description": "The port used by MPD" },
991 "mpdHost": { "type": "string", "description": "The host used by MPD" },
992 "mpdFormatString": {
993 "type": "string",
994 "description": "The format string used by MPC"
995 }
996 }
997 },
998 "browserTrackWidgetOptions": {
999 "type": "object",
1000 "additionalProperties": false,
1001 "properties": {
1002 "refreshFrequency": {
1003 "type": "number",
1004 "description": "The refresh frequency of this widget in milliseconds"
1005 },
1006 "showOnDisplay": {
1007 "type": "string",
1008 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
1009 },
1010 "showIcon": {
1011 "type": "boolean",
1012 "description": "Show or hide the widget icon"
1013 },
1014 "showSpecter": {
1015 "type": "boolean",
1016 "description": "Show the specter animation when a song is playing"
1017 }
1018 }
1019 },
1020 "notificationsWidgetOptions": {
1021 "type": "object",
1022 "additionalProperties": false,
1023 "properties": {
1024 "refreshFrequency": {
1025 "type": "number",
1026 "description": "The refresh frequency of this widget in milliseconds"
1027 },
1028 "showOnDisplay": {
1029 "type": "string",
1030 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
1031 },
1032 "excludedApps": {
1033 "type": "string",
1034 "description": "Comma-separated list of app names to exclude from the notifications widget (e.g. \"BetterTouchTool, Xcode\")"
1035 }
1036 }
1037 },
1038 "nextMeetingWidgetOptions": {
1039 "type": "object",
1040 "additionalProperties": false,
1041 "properties": {
1042 "refreshFrequency": {
1043 "type": "number",
1044 "description": "The refresh frequency of this widget in milliseconds"
1045 },
1046 "showOnDisplay": {
1047 "type": "string",
1048 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
1049 },
1050 "showJoinButton": {
1051 "type": "boolean",
1052 "description": "Show or hide the join button"
1053 },
1054 "showTimeOnly": {
1055 "type": "boolean",
1056 "description": "Hide the meeting title and show only time"
1057 },
1058 "icalBuddyPath": {
1059 "type": "string",
1060 "description": "Optional path to the icalBuddy binary"
1061 },
1062 "lookAheadHours": {
1063 "type": "number",
1064 "description": "Number of hours to look ahead for upcoming meetings"
1065 }
1066 }
1067 },
1068 "userWidgets": {
1069 "type": "object",
1070 "properties": {
1071 "userWidgetsList": {
1072 "type": "object",
1073 "description": "List of your custom widgets",
1074 "additionalProperties": false,
1075 "patternProperties": {
1076 "^[0-9]+$": {
1077 "type": "object",
1078 "properties": {
1079 "title": {
1080 "type": "string",
1081 "description": "The title of the widget"
1082 },
1083 "icon": {
1084 "type": "string",
1085 "description": "The icon of the widget"
1086 },
1087 "backgroundColor": {
1088 "type": "string",
1089 "description": "Any valid CSS color"
1090 },
1091 "output": {
1092 "type": "string",
1093 "description": "The command to get the output, can be a shell script"
1094 },
1095 "onClickAction": {
1096 "type": "string",
1097 "description": "The action on click, can be a shell script"
1098 },
1099 "onRightClickAction": {
1100 "type": "string",
1101 "description": "The action on right click, can be a shell script"
1102 },
1103 "onMiddleClickAction": {
1104 "type": "string",
1105 "description": "The action on middle click, can be a shell script"
1106 },
1107 "showOnDisplay": {
1108 "type": "string",
1109 "description": "The displays on which the process will be displayed. Add a list of indexes (for example: \"1,2\"). Leave blank to display the widget on every spaces"
1110 },
1111 "refreshFrequency": {
1112 "type": "number",
1113 "description": "The refresh frequency of this widget in milliseconds"
1114 },
1115 "active": {
1116 "type": "boolean",
1117 "description": "Enable or disable this specific user widget"
1118 },
1119 "noIcon": {
1120 "type": "boolean",
1121 "description": "Hide the icon"
1122 },
1123 "hideWhenNoOutput": {
1124 "type": "boolean",
1125 "description": "Hide the widget when script returns empty output"
1126 }
1127 },
1128 "additionalProperties": false,
1129 "required": [
1130 "title",
1131 "icon",
1132 "backgroundColor",
1133 "output",
1134 "onClickAction",
1135 "onRightClickAction",
1136 "onMiddleClickAction",
1137 "showOnDisplay",
1138 "refreshFrequency",
1139 "active",
1140 "noIcon",
1141 "hideWhenNoOutput"
1142 ]
1143 }
1144 }
1145 }
1146 }
1147 },
1148 "customStyles": {
1149 "type": "object",
1150 "additionalProperties": false,
1151 "properties": {
1152 "styles": {
1153 "type": "string",
1154 "description": "Your custom css styles here"
1155 }
1156 }
1157 }
1158 }
1159}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/browser-audio.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/browser-audio.applescript
new file mode 100755
index 0000000..e6b64cf
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/browser-audio.applescript
@@ -0,0 +1,91 @@
1set browser to ""
2set title_string to ""
3set active_tab to 0
4
5to replace_chars(this_text, search_string, replacement_string)
6 set AppleScript's text item delimiters to the search_string
7 set the item_list to every text item of this_text
8 set AppleScript's text item delimiters to the replacement_string
9 set this_text to the item_list as string
10 set AppleScript's text item delimiters to ""
11 return this_text
12end replace_chars
13
14try
15 do shell script "osascript -e 'id of application \"Google Chrome\"'"
16 if application "Google Chrome" is running then
17 tell application "Google Chrome"
18 set window_list to every window
19
20 repeat with the_window in window_list
21 set tab_list to every tab in the_window
22
23 repeat with the_tab in tab_list
24 set the_title to the title of the_tab
25 set the_url to the URL of the_tab
26 if "- YouTube" is in the_title then
27 if active_tab is 0 then set title_string to " " & text 1 thru -11 of the_title
28 set browser to "chrome"
29 set active_tab to 1
30 end if
31 if "open.spotify.com" is in the_url then
32 if active_tab is 0 then set title_string to " " & text of the_title
33 set browser to "chrome"
34 set active_tab to 1
35 if "Spotify" is in the_title then set title_string to ""
36 end if
37 end repeat
38 end repeat
39 end tell
40 end if
41end try
42
43try
44 do shell script "osascript -e 'id of application \"Brave Browser\"'"
45 if application "Brave Browser" is running then
46 tell application "Brave Browser"
47 set window_list to every window
48
49 repeat with the_window in window_list
50 set tab_list to every tab in the_window
51
52 repeat with the_tab in tab_list
53 set the_url to the URL of the_tab
54 set the_title to the title of the_tab
55 if "- YouTube" is in the_title then
56 if active_tab is 0 then set title_string to " " & text 1 thru -11 of the_title
57 set browser to "brave"
58 set active_tab to 1
59 end if
60 if "open.spotify.com" is in the_url then
61 if active_tab is 0 then set title_string to " " & text of the_title
62 set browser to "brave"
63 set active_tab to 1
64 if "Spotify" is in the_title then set title_string to ""
65 end if
66 end repeat
67 end repeat
68 end tell
69 end if
70end try
71
72if application "Safari" is running then
73 tell application "Safari"
74 set window_list to every window
75
76 repeat with the_window in window_list
77 set tab_list to every tab in the_window
78
79 repeat with the_tab in tab_list
80 set the_title to the name of the_tab
81 if "- YouTube" is in the_title then
82 if active_tab is 0 then set title_string to " " & text 1 thru -11 of the_title
83 set browser to "safari"
84 set active_tab to 1
85 end if
86 end repeat
87 end repeat
88 end tell
89end if
90
91return "{ \"browser\": \"" & browser & "\", \"title\": \"" & replace_chars(title_string, "\"", "Ò") & "\" }"
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-audio.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-audio.applescript
new file mode 100755
index 0000000..23c408a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-audio.applescript
@@ -0,0 +1,24 @@
1set browser to ""
2set title_string to ""
3set active_tab to 0
4
5to replace_chars(this_text, search_string, replacement_string)
6 set AppleScript's text item delimiters to the search_string
7 set the item_list to every text item of this_text
8 set AppleScript's text item delimiters to the replacement_string
9 set this_text to the item_list as string
10 set AppleScript's text item delimiters to ""
11 return this_text
12end replace_chars
13
14tell application "Firefox"
15 set the_title to (name of windows whose name contains "- YouTube") as text
16
17 if "- YouTube" is in the_title then
18 if active_tab is 0 then set title_string to " " & text 1 thru -11 of the_title
19 set browser to "firefox"
20 set active_tab to 1
21 end if
22end tell
23
24return "{ \"browser\": \"" & browser & "\", \"title\": \"" & replace_chars(title_string, "\"", "Ò") & "\" }"
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-dev-audio.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-dev-audio.applescript
new file mode 100755
index 0000000..6618fec
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/firefox-dev-audio.applescript
@@ -0,0 +1,24 @@
1set browser to ""
2set title_string to ""
3set active_tab to 0
4
5to replace_chars(this_text, search_string, replacement_string)
6 set AppleScript's text item delimiters to the search_string
7 set the item_list to every text item of this_text
8 set AppleScript's text item delimiters to the replacement_string
9 set this_text to the item_list as string
10 set AppleScript's text item delimiters to ""
11 return this_text
12end replace_chars
13
14tell application "Firefox Developer Edition"
15 set the_title to (name of windows whose name contains "- YouTube") as text
16
17 if "- YouTube" is in the_title then
18 if active_tab is 0 then set title_string to " " & text 1 thru -11 of the_title
19 set browser to "firefox"
20 set active_tab to 1
21 end if
22end tell
23
24return "{ \"browser\": \"" & browser & "\", \"title\": \"" & replace_chars(title_string, "\"", "Ò") & "\" }"
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-aerospace.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-aerospace.sh
new file mode 100755
index 0000000..0e9c140
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-aerospace.sh
@@ -0,0 +1,26 @@
1# Store the first argument passed to the script in the variable aerospace_path
2aerospace_path=$1
3
4# Get the status of System Integrity Protection (SIP) and store it in the variable SIP
5SIP=$(csrutil status)
6
7# List monitors using the aerospace tool, format the output as JSON, and store it in the variable displays
8# Redirect any error output to /dev/null
9displays=$($aerospace_path list-monitors --json --format "%{monitor-id} %{monitor-name} %{monitor-appkit-nsscreen-screens-id}" 2> /dev/null)
10
11# Check if the previous command failed (exit status 1)
12if [ $? -eq 1 ]; then
13 # Print "aerospaceError" and exit the script with status 0
14 echo "aerospaceError"
15 exit 0
16fi
17
18# Print a JSON object containing the displays information, SIP status, and a shadow property set to true
19echo $(cat <<-EOF
20 {
21 "displays": $displays,
22 "SIP": "$SIP",
23 "shadow": true
24 }
25EOF
26) \ No newline at end of file
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-yabai.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-yabai.sh
new file mode 100755
index 0000000..5dbbfe3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/init-yabai.sh
@@ -0,0 +1,102 @@
1# Assign input arguments to variables
2yabai_path=$1
3display_skhd_mode=$2
4disable_signals=$3
5enable_window_title_changed_signal=$4
6
7# Check if yabai is running
8pgrep -x yabai > /dev/null
9
10# If yabai is not running, output an error message and exit
11if [ $? -eq 1 ]; then
12 echo "yabaiError"
13 exit 0
14fi
15
16# Get the System Integrity Protection (SIP) status
17SIP=$(csrutil status)
18# Get the current window shadow configuration from yabai
19shadow_enabled=$($yabai_path -m config window_shadow)
20
21# Query yabai for spaces, windows, and displays information
22spaces=$($yabai_path -m query --spaces)
23windows=$($yabai_path -m query --windows)
24displays=$($yabai_path -m query --displays)
25
26# Retry querying spaces if the initial query was empty
27if [ -z "$spaces" ]; then
28 spaces=$($yabai_path -m query --spaces)
29fi
30
31# Retry querying windows if the initial query was empty and remove backslashes
32if [ -z "$windows" ]; then
33 windows=$($yabai_path -m query --windows | sed 's/\\.//g;')
34fi
35
36# Retry querying displays if the initial query was empty
37if [ -z "$displays" ]; then
38 displays=$($yabai_path -m query --displays)
39fi
40
41# Add or remove signals based on the disable_signals flag
42if [ $disable_signals = "false" ]; then
43 # Add signals to refresh the simple-bar widget on various yabai events
44 $yabai_path -m signal --add event=window_focused action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar when focused application changes"
45 $yabai_path -m signal --add event=window_minimized action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar when a window is minimized"
46 $yabai_path -m signal --add event=window_resized action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar when a window is resized"
47 $yabai_path -m signal --add event=window_destroyed action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar when an application window is closed"
48 $yabai_path -m signal --add event=space_changed action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar on space change"
49 $yabai_path -m signal --add event=display_changed action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar on display focus change"
50
51 # Add signal for window title change if enabled
52 if [ $enable_window_title_changed_signal = "true" ]; then
53 $yabai_path -m signal --add event=window_title_changed action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar when current window title changes"
54 fi
55
56 # Add signals for space creation and destruction if yabai version is 6 or higher
57 yabai_major_version=$($yabai_path -v | awk -F '.' '{print $1}' | sed 's/yabai-v//')
58 if [ $yabai_major_version -ge 6 ]; then
59 $yabai_path -m signal --add event=space_destroyed action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar on space removal"
60 $yabai_path -m signal --add event=space_created action="osascript -e 'tell application id \"tracesOf.Uebersicht\" to refresh widget id \"simple-bar-index-jsx\"'" label="Refresh simple-bar on space creation"
61 fi
62else
63 # Remove signals if disable_signals is true
64 $yabai_path -m signal --remove label="Refresh simple-bar when focused application changes" >/dev/null 2>&1 || true
65 $yabai_path -m signal --remove label="Refresh simple-bar when a window is minimized" >/dev/null 2>&1 || true
66 $yabai_path -m signal --remove label="Refresh simple-bar when a window is resized" >/dev/null 2>&1 || true
67 $yabai_path -m signal --remove label="Refresh simple-bar when an application window is closed" >/dev/null 2>&1 || true
68 $yabai_path -m signal --remove label="Refresh simple-bar on space change" >/dev/null 2>&1 || true
69 $yabai_path -m signal --remove label="Refresh simple-bar on display focus change" >/dev/null 2>&1 || true
70 $yabai_path -m signal --remove label="Refresh simple-bar when current window title changes" >/dev/null 2>&1 || true
71 $yabai_path -m signal --remove label="Refresh simple-bar on space removal" >/dev/null 2>&1 || true
72 $yabai_path -m signal --remove label="Refresh simple-bar on space creation" >/dev/null 2>&1 || true
73fi
74
75# Determine skhd mode based on the display_skhd_mode flag and disable_signals flag
76if [ $display_skhd_mode = "true" ]; then
77 SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
78 if [ $disable_signals = "false" ]; then
79 skhd_mode=$(cat "$("${SCRIPT_DIR}"/yabai-set-mode.sh --query)")
80 else
81 skhd_mode=$(cat "$("${SCRIPT_DIR}"/yabai-set-mode-server.sh --query)")
82 fi
83else
84 skhd_mode="{}"
85fi
86
87# Output the collected information as a JSON object
88echo $(cat <<-EOF
89 {
90 "spaces": $spaces,
91 "windows": $windows,
92 "displays": $displays,
93 "SIP": "$SIP",
94 "shadow": "$shadow_enabled",
95 "skhdMode": $skhd_mode
96 }
97EOF
98) | \
99 # Remove invisible U+200E Left-To-Right Mark character
100 sed "s/\xe2\x80\x8e//g" | \
101 # Remove newlines from output (handling Google Chrome JSON parse error caused by "search in page")
102 tr -d '\n'
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/netstats.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/netstats.sh
new file mode 100755
index 0000000..66447ec
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/netstats.sh
@@ -0,0 +1,5 @@
1#!/bin/bash
2
3# Optimized: Single netstat call with direct output processing
4netstat -w1 2>&1 | awk 'NR==3 {printf "{ \"download\": %s, \"upload\": %s}", $4, $6; exit}'
5
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh
new file mode 100755
index 0000000..b8e13e5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/next-meeting.sh
@@ -0,0 +1,101 @@
1#!/bin/bash
2# Get next meeting using icalBuddy (much faster than AppleScript, handles recurring events)
3# Usage: next-meeting.sh [icalBuddyPath] [lookAheadHours]
4
5# Configuration
6MAX_IN_PROGRESS_MINUTES=15 # Stop showing "now" after meeting is 15 min in progress
7LOOKAHEAD="${2:-12}" # How many hours ahead to look for meetings (default: 12)
8MAX_EVENTS=10 # Fetch multiple events to skip stale in-progress ones
9
10# Calculate end time (icalBuddy doesn't support now+Xh syntax)
11END_TIME=$(date -v+${LOOKAHEAD}H "+%Y-%m-%d %H:%M")
12
13# Use custom path if provided, otherwise auto-detect
14CUSTOM_PATH="$1"
15if [ -n "$CUSTOM_PATH" ] && [ -x "$CUSTOM_PATH" ]; then
16 ICALBUDDY="$CUSTOM_PATH"
17else
18 ICALBUDDY=$(which icalBuddy 2>/dev/null)
19 if [ -z "$ICALBUDDY" ]; then
20 if [ -x "/opt/homebrew/bin/icalBuddy" ]; then
21 ICALBUDDY="/opt/homebrew/bin/icalBuddy"
22 elif [ -x "/usr/local/bin/icalBuddy" ]; then
23 ICALBUDDY="/usr/local/bin/icalBuddy"
24 else
25 echo ""
26 exit 0
27 fi
28 fi
29fi
30
31now_epoch=$(date +%s)
32
33# Fetch multiple events - each event bullet starts with <<<E>>>
34# Using a unique prefix that won't appear in notes content
35output=$("$ICALBUDDY" -n -nc -nrd -ea -eed -li "$MAX_EVENTS" \
36 -b "<<<E>>>" -ss "" \
37 -df "%Y-%m-%d" -tf "%H:%M" \
38 -iep "title,datetime,notes" \
39 eventsFrom:"now" to:"$END_TIME" 2>/dev/null)
40
41if [ -z "$output" ]; then
42 echo ""
43 exit 0
44fi
45
46# Write events to temp file for processing
47tmpfile=$(mktemp)
48echo "$output" > "$tmpfile"
49
50# Extract individual events by splitting on <<<E>>> prefix
51event_num=0
52while IFS= read -r line; do
53 if [[ "$line" == "<<<E>>>"* ]]; then
54 # Process previous event if we have one
55 if [ "$event_num" -gt 0 ] && [ -n "$cur_title" ] && [ -n "$cur_start_time" ] && [ -n "$cur_iso_date" ]; then
56 meeting_epoch=$(date -j -f "%Y-%m-%d %H:%M" "$cur_iso_date $cur_start_time" +%s 2>/dev/null)
57 if [ -n "$meeting_epoch" ]; then
58 minutes_until=$(( (meeting_epoch - now_epoch) / 60 ))
59 if [ "$minutes_until" -ge "-$MAX_IN_PROGRESS_MINUTES" ]; then
60 echo "${cur_title}|${cur_iso_date}T${cur_start_time}||${cur_notes}|${minutes_until}"
61 rm -f "$tmpfile"
62 exit 0
63 fi
64 fi
65 fi
66
67 # Start new event
68 event_num=$((event_num + 1))
69 cur_title="${line#<<<E>>>}"
70 cur_title=$(echo "$cur_title" | sed 's/ (Calendar)$//')
71 cur_iso_date=""
72 cur_start_time=""
73 cur_notes=""
74 in_notes=0
75 elif [[ "$line" =~ ^[[:space:]]+[0-9]{4}-[0-9]{2}-[0-9]{2}" at "[0-9]{2}:[0-9]{2} ]]; then
76 cur_iso_date=$(echo "$line" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}')
77 cur_start_time=$(echo "$line" | grep -oE 'at [0-9]{2}:[0-9]{2}' | head -1 | sed 's/at //')
78 in_notes=0
79 elif [[ "$line" == *"notes:"* ]]; then
80 in_notes=1
81 cur_notes="$line"
82 elif [ "$in_notes" -eq 1 ]; then
83 cur_notes="${cur_notes} $(echo "$line" | sed 's/|/¦/g')"
84 fi
85done < "$tmpfile"
86
87# Process the last event
88if [ "$event_num" -gt 0 ] && [ -n "$cur_title" ] && [ -n "$cur_start_time" ] && [ -n "$cur_iso_date" ]; then
89 meeting_epoch=$(date -j -f "%Y-%m-%d %H:%M" "$cur_iso_date $cur_start_time" +%s 2>/dev/null)
90 if [ -n "$meeting_epoch" ]; then
91 minutes_until=$(( (meeting_epoch - now_epoch) / 60 ))
92 if [ "$minutes_until" -ge "-$MAX_IN_PROGRESS_MINUTES" ]; then
93 echo "${cur_title}|${cur_iso_date}T${cur_start_time}||${cur_notes}|${minutes_until}"
94 rm -f "$tmpfile"
95 exit 0
96 fi
97 fi
98fi
99
100rm -f "$tmpfile"
101echo ""
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-iterm2.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-iterm2.applescript
new file mode 100755
index 0000000..ab00115
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-iterm2.applescript
@@ -0,0 +1,9 @@
1on run argv
2 set commandToRun to item 1 of argv
3 tell application "iTerm"
4 set newWindow to (create window with default profile)
5 tell current session of newWindow
6 write text commandToRun
7 end tell
8 end tell
9end run \ No newline at end of file
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-terminal.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-terminal.applescript
new file mode 100755
index 0000000..898ec7a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/run-command-in-terminal.applescript
@@ -0,0 +1,7 @@
1on run argv
2 set commandToRun to item 1 of argv
3 tell application "Terminal"
4 do script commandToRun
5 activate
6 end tell
7end run \ No newline at end of file
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode-server.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode-server.sh
new file mode 100755
index 0000000..f5fc782
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode-server.sh
@@ -0,0 +1,38 @@
1#! /usr/bin/env sh
2
3# make sure to fix permissions!
4# Privacy & Security > Automation > skhd > Ubersicht
5
6# Write information regarding skhd mode to a cache file for widgets to read from.
7# Usage:
8# $0 --query print location of cache file
9# $0 mode_name [color] write mode_name (and optionally, a color) to a cache file
10# default color is white.
11# by default, a mode named "default" will not be shown.
12
13CACHE_FILE="$HOME/Library/Caches/uebersicht-simple-bar-index/yabai-mode"
14
15mkdir -p "$(dirname "$CACHE_FILE")"
16touch "$CACHE_FILE"
17
18main() {
19 # optional second argument color
20 color="$2"
21 if [ -z "$color" ]; then
22 color="white"
23 fi
24
25 # update cache file
26 echo \
27 "{\"mode\": \"$1\", \"color\": \"$color\"}" \
28 > "$CACHE_FILE"
29}
30
31case "$1" in
32 --query)
33 echo "$CACHE_FILE"
34 ;;
35 *)
36 main "$@"
37 ;;
38esac
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode.sh
new file mode 100755
index 0000000..6f580db
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/yabai-set-mode.sh
@@ -0,0 +1,40 @@
1#! /usr/bin/env sh
2
3# make sure to fix permissions!
4# Privacy & Security > Automation > skhd > Ubersicht
5
6# Write information regarding skhd mode to a cache file for widgets to read from.
7# Usage:
8# $0 --query print location of cache file
9# $0 mode_name [color] write mode_name (and optionally, a color) to a cache file
10# default color is white.
11# by default, a mode named "default" will not be shown.
12
13CACHE_FILE="$HOME/Library/Caches/uebersicht-simple-bar-index/yabai-mode"
14
15mkdir -p "$(dirname "$CACHE_FILE")"
16touch "$CACHE_FILE"
17
18main() {
19 # optional second argument color
20 color="$2"
21 if [ -z "$color" ]; then
22 color="white"
23 fi
24
25 # update cache file
26 echo \
27 "{\"mode\": \"$1\", \"color\": \"$color\"}" \
28 > "$CACHE_FILE"
29
30 osascript -e 'tell application id "tracesOf.Uebersicht" to refresh widget id "simple-bar-index-jsx"'
31}
32
33case "$1" in
34 --query)
35 echo "$CACHE_FILE"
36 ;;
37 *)
38 main "$@"
39 ;;
40esac
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-mute-status.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-mute-status.applescript
new file mode 100755
index 0000000..71288a7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-mute-status.applescript
@@ -0,0 +1,17 @@
1property btnTitle : "Mute audio"
2
3if application "zoom.us" is running then
4 tell application "System Events"
5 tell application process "zoom.us"
6 if exists (menu item btnTitle of menu 1 of menu bar item "Meeting" of menu bar 1) then
7 set returnValue to "on"
8 else
9 set returnValue to "off"
10 end if
11 end tell
12 end tell
13else
14 set returnValue to ""
15end if
16
17return returnValue \ No newline at end of file
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-video-status.applescript b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-video-status.applescript
new file mode 100755
index 0000000..367821f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/scripts/zoom-video-status.applescript
@@ -0,0 +1,17 @@
1property btnTitle : "Stop video"
2
3if application "zoom.us" is running then
4 tell application "System Events"
5 tell application process "zoom.us"
6 if exists (menu item btnTitle of menu 1 of menu bar item "Meeting" of menu bar 1) then
7 set returnValue to "on"
8 else
9 set returnValue to "off"
10 end if
11 end tell
12 end tell
13else
14 set returnValue to ""
15end if
16
17return returnValue \ No newline at end of file
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/settings.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/settings.js
new file mode 100755
index 0000000..55c53ff
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/settings.js
@@ -0,0 +1,1184 @@
1import * as Uebersicht from "uebersicht";
2import * as Themes from "./styles/themes";
3import * as Utils from "./utils";
4import UserWidgetsCreator from "./components/settings/user-widgets-creator.jsx";
5import AerospaceDisplayManager from "./components/settings/aerospace-display-manager.jsx";
6
7export { Component, styles, Wrapper } from "./components/settings/settings.jsx";
8
9const SETTINGS_STORAGE_KEY = "simple-bar-settings";
10
11// The available themes are retrieved from the Themes collection
12// They are then split into dark and light themes
13const availableThemes = Object.keys(Themes.collection).map((key) => {
14 const theme = Themes.collection[key];
15 return { code: key, name: theme.name, kind: theme.kind };
16});
17const darkThemes = availableThemes.filter((theme) => theme.kind === "dark");
18const lightThemes = availableThemes.filter((theme) => theme.kind === "light");
19
20// These are all the information displayed in the settings module
21export const data = {
22 global: {
23 label: "Global",
24 documentation: "/global-settings/",
25 infos: [
26 '- "<b>No bar background</b>" is visually better with the "Floating bar" option activated',
27 '- The higher the "<b>Sliding animation pace</b>" value, the faster the texts slides (must be > 0, default is set to 4)',
28 "<br/>",
29 '<b>"Use background color as foreground"</b>:',
30 "This setting will remove all background colors and use the removed color for all the foreground texts",
31 ],
32 },
33 theme: {
34 label: "theme",
35 type: "radio",
36 options: ["auto", "dark", "light"],
37 title: "Appearance & tweaks",
38 },
39 floatingBar: { label: "Floating bar", type: "checkbox" },
40 noBarBg: { label: "No bar background", type: "checkbox" },
41 noColorInData: { label: "No colors in data", type: "checkbox" },
42 bottomBar: { label: "Bottom bar", type: "checkbox" },
43 sideDecoration: { label: "Apple logo", type: "checkbox" },
44 inlineSpacesOptions: { label: "Inline spaces options", type: "checkbox" },
45 disableAnimations: {
46 label: "Disable persistent animations",
47 type: "checkbox",
48 },
49 enableMissives: {
50 label: "Use internal notification system (missives)",
51 type: "checkbox",
52 fullWidth: true,
53 },
54 disableNotifications: { label: "Disable notifications", type: "checkbox" },
55 compactMode: { label: "Compact mode", type: "checkbox" },
56 widgetMaxWidth: { label: "Widget max width", type: "text" },
57 widgetsBackgroundColorAsForeground: {
58 label: "Use background color as foreground for widgets",
59 type: "checkbox",
60 fullWidth: true,
61 },
62 spacesBackgroundColorAsForeground: {
63 label: "Use background color as foreground for spaces & process",
64 type: "checkbox",
65 fullWidth: true,
66 },
67 font: {
68 label: "Global font",
69 type: "text",
70 placeholder: "default: JetBrains Mono",
71 fullWidth: false,
72 },
73 fontSize: {
74 label: "Font size",
75 type: "text",
76 placeholder: "default: 11px",
77 fullWidth: false,
78 },
79 yabaiPath: {
80 label: "yabai path",
81 type: "text",
82 placeholder: "default: $(which yabai)",
83 fullWidth: true,
84 title: "Configuration",
85 },
86 aerospacePath: {
87 label: "Aerospace path",
88 type: "text",
89 placeholder: "default: $(which aerospace)",
90 fullWidth: true,
91 },
92 windowManager: {
93 title: "Which window or space manager are you using?",
94 label: "",
95 type: "radio",
96 options: ["yabai", "aerospace"],
97 },
98 shell: {
99 title: "With which shell do you want to execute simple-bar scripts?",
100 label: "",
101 type: "radio",
102 options: ["sh", "bash", "dash"],
103 },
104 terminal: {
105 title: "Which terminal should user facing commands be run in?",
106 label: "",
107 type: "radio",
108 options: ["Terminal", "iTerm2"],
109 },
110 slidingAnimationPace: {
111 label: "Sliding animation speed",
112 type: "number",
113 placeholder: "Default: 4",
114 fullWidth: true,
115 },
116 enableServer: {
117 label: "Enable simple-bar-server connection",
118 type: "checkbox",
119 fullWidth: true,
120 title: "simple-bar-server",
121 },
122 serverHttpPort: {
123 label: "simple-bar-server http port",
124 type: "number",
125 placeholder: "Default: 7776",
126 fullWidth: true,
127 },
128 serverSocketPort: {
129 label: "simple-bar-server socket port",
130 type: "number",
131 placeholder: "Default: 7777",
132 fullWidth: true,
133 },
134 yabaiServerRefresh: {
135 label: "Refresh yabai spaces & process with simple-bar-server",
136 type: "checkbox",
137 fullWidth: true,
138 },
139 aerospaceServerRefresh: {
140 label: "Refresh AeroSpace spaces with simple-bar-server",
141 type: "checkbox",
142 fullWidth: true,
143 },
144
145 themes: {
146 label: "Themes",
147 documentation: "/themes-settings/",
148 infos: [
149 "Colors defined here will override the selected theme. Leave it empty to use the theme colors.",
150 "<br/>",
151 "<b>You can use any valid CSS color:</b>",
152 "- named-color",
153 "- hex-color",
154 "- rgb()",
155 "- hsl()",
156 "- hwb()",
157 "<br/>",
158 "<b>Styles are applied in this order:</b>",
159 "- Theme",
160 "- Color overrides",
161 "- Custom styles",
162 "<br/>",
163 "The last one overrides the previous ones.",
164 ],
165 },
166 darkTheme: { label: "Dark theme", type: "select", options: darkThemes },
167 lightTheme: { label: "Light theme", type: "select", options: lightThemes },
168 colorMain: { label: "Main", type: "color", title: "Color overrides" },
169 colorMainAlt: { label: "Main alternative", type: "color" },
170 colorMinor: { label: "Minor", type: "color" },
171 colorAccent: { label: "Accent", type: "color" },
172 colorRed: { label: "Red", type: "color" },
173 colorGreen: { label: "Green", type: "color" },
174 colorYellow: { label: "Yellow", type: "color" },
175 colorOrange: { label: "Orange", type: "color" },
176 colorBlue: { label: "Blue", type: "color" },
177 colorMagenta: { label: "Magenta", type: "color" },
178 colorCyan: { label: "Cyan", type: "color" },
179 colorBlack: { label: "Black", type: "color" },
180 colorWhite: { label: "White", type: "color" },
181 colorForeground: { label: "Foreground", type: "color" },
182 colorBackground: { label: "Background", type: "color" },
183
184 process: {
185 label: "Process",
186 documentation: "/process-settings/",
187 },
188 displayForFocusedSpace: {
189 label:
190 "<em>yabai</em> Display for focused space instead of current display space (usefull when you have simple-bar on one display in multi-monitor setup)",
191 type: "checkbox",
192 fullWidth: true,
193 },
194 displayOnlyCurrent: {
195 label:
196 "<em>yabai</em> <em>AeroSpace</em> Display only current process name",
197 type: "checkbox",
198 fullWidth: true,
199 },
200 centered: {
201 label: "<em>yabai</em> <em>AeroSpace</em> Center process widget",
202 type: "checkbox",
203 },
204 showCurrentSpaceMode: {
205 label: "<em>yabai</em> Show current space mode (BSP, Stack, Float)",
206 type: "checkbox",
207 fullWidth: true,
208 },
209 hideWindowTitle: {
210 label:
211 "<em>yabai</em> <em>AeroSpace</em> Hide window titles (show only app name for each process)",
212 type: "checkbox",
213 fullWidth: true,
214 },
215 displayOnlyIcon: {
216 label: "<em>yabai</em> <em>AeroSpace</em> Display only process icon",
217 type: "checkbox",
218 fullWidth: true,
219 },
220 expandAllProcesses: {
221 label: "<em>yabai</em> <em>AeroSpace</em> Expand all processes",
222 type: "checkbox",
223 fullWidth: true,
224 },
225 displaySkhdMode: {
226 label:
227 "<em>yabai</em> Display current skhd mode (requires some configuration, see readme file)",
228 type: "checkbox",
229 fullWidth: true,
230 },
231 displayStackIndex: {
232 label:
233 "<em>yabai</em> Display stack-index for all processes in space (if greater than 0)",
234 type: "checkbox",
235 fullWidth: true,
236 },
237 displayOnlyCurrentStack: {
238 label: "<em>yabai</em> Display stack-index only for focused process",
239 type: "checkbox",
240 fullWidth: true,
241 },
242
243 spacesDisplay: {
244 label: "Spaces",
245 documentation: "/spaces-settings/",
246 infos: [
247 "You can declare here which apps to exclude from the spaces display",
248 'Each exclusion must be separated by a comma and a space ", "',
249 "These exclusions will also be applied on the process name display",
250 ],
251 },
252 exclusions: {
253 label: "<em>yabai</em> <em>AeroSpace</em> Exclusions by app name",
254 type: "text",
255 placeholder: "example: Finder, iTerm2",
256 fullWidth: true,
257 },
258 titleExclusions: {
259 label: "<em>yabai</em> <em>AeroSpace</em> Exclusions by window title name",
260 type: "text",
261 placeholder: "example: Preferences",
262 fullWidth: true,
263 },
264 spacesExclusions: {
265 label: "<em>yabai</em> <em>AeroSpace</em> Exclude spaces by space name",
266 type: "text",
267 placeholder: "example: Preferences",
268 fullWidth: true,
269 },
270 exclusionsAsRegex: {
271 label:
272 "<em>yabai</em> <em>AeroSpace</em> Use regex syntax in all exclusions fields",
273 type: "checkbox",
274 fullWidth: true,
275 },
276 displayAllSpacesOnAllScreens: {
277 label:
278 "<em>yabai</em> <em>AeroSpace</em> Display all spaces on all screens",
279 type: "checkbox",
280 fullWidth: true,
281 },
282 hideEmptySpaces: {
283 label: "<em>yabai</em> <em>AeroSpace</em> Hide empty spaces",
284 type: "checkbox",
285 },
286 showOptionsOnHover: {
287 label: "<em>yabai</em> Show space options on hover",
288 type: "checkbox",
289 fullWidth: true,
290 },
291 switchSpacesWithoutYabai: {
292 label: "<em>yabai</em> Switch spaces with ^â­ /^â­¢ instead of yabai",
293 type: "checkbox",
294 fullWidth: true,
295 },
296 hideDuplicateAppsInSpaces: {
297 label:
298 "<em>yabai</em> <em>AeroSpace</em> Hide duplicate app icons in same space",
299 type: "checkbox",
300 fullWidth: true,
301 },
302 displayStickyWindowsSeparately: {
303 label: "<em>yabai</em> Display sticky windows separately",
304 type: "checkbox",
305 fullWidth: true,
306 },
307 hideCreateSpaceButton: {
308 label: "<em>yabai</em> Hide create space button",
309 type: "checkbox",
310 fullWidth: true,
311 },
312 customAeroSpaceDisplayIndexes: {
313 label: "<em>AeroSpace</em> Custom AeroSpace display indexes",
314 type: "component",
315 Component: AerospaceDisplayManager,
316 },
317
318 widgets: {
319 label: "Widgets",
320 documentation: "/widgets/",
321 },
322 processWidget: { label: "Process name", type: "checkbox" },
323 zoomWidget: { label: "Zoom", type: "checkbox" },
324 timeWidget: { label: "Time", type: "checkbox" },
325 dateWidget: { label: "Date", type: "checkbox" },
326 wifiWidget: { label: "Network", type: "checkbox" },
327 vpnWidget: { label: "Viscosity VPN", type: "checkbox" },
328 micWidget: { label: "Microphone", type: "checkbox" },
329 soundWidget: { label: "Sound", type: "checkbox" },
330 githubWidget: { label: "GitHub", type: "checkbox" },
331 weatherWidget: { label: "Weather", type: "checkbox" },
332 netstatsWidget: { label: "Network stats", type: "checkbox" },
333 cpuWidget: { label: "CPU", type: "checkbox" },
334 gpuWidget: { label: "GPU", type: "checkbox" },
335 memoryWidget: { label: "Memory", type: "checkbox" },
336 batteryWidget: { label: "Battery", type: "checkbox" },
337 keyboardWidget: { label: "Keyboard", type: "checkbox" },
338 spotifyWidget: { label: "Spotify", type: "checkbox" },
339 youtubeMusicWidget: { label: "YouTube Music", type: "checkbox" },
340 cryptoWidget: { label: "Crypto", type: "checkbox" },
341 stockWidget: { label: "Stock", type: "checkbox" },
342 musicWidget: { label: "Music/iTunes", type: "checkbox" },
343 mpdWidget: { label: "MPD state via mpc", type: "checkbox" },
344 browserTrackWidget: { label: "Browser track", type: "checkbox" },
345 notificationsWidget: { label: "Notification badges", type: "checkbox" },
346 nextMeetingWidget: { label: "Next meeting", type: "checkbox" },
347
348 showOnDisplay: {
349 label: "Show on display n°",
350 type: "text",
351 placeholder: "example: 1,2 (leave blank to show on all displays)",
352 fullWidth: true,
353 },
354
355 githubWidgetOptions: {
356 label: "GitHub",
357 documentation: "/github/",
358 },
359 hideWhenNoNotification: {
360 label: "Hide widget when no notification",
361 type: "checkbox",
362 },
363 notificationUrl: {
364 label: "The URL opened on click",
365 type: "text",
366 placeholder: "example: https://github.com/notifications",
367 fullWidth: true,
368 },
369 ghBinaryPath: {
370 label: "Path to gh binary",
371 type: "text",
372 placeholder: "example: /opt/homebrew/bin/gh",
373 fullWidth: true,
374 },
375
376 weatherWidgetOptions: {
377 label: "Weather",
378 documentation: "/weather/",
379 infos: [
380 'Leave "Your location" blank in order to let simple-bar use your geolocation.',
381 "Doing so, you need to allow Übersicht access to your location: a popup should appear on first use.",
382 ],
383 },
384 showIcon: { label: "Show icon", type: "checkbox" },
385 unit: {
386 title: "Temperature unit",
387 label: "",
388 type: "radio",
389 options: ["C", "F"],
390 },
391 hideLocation: { label: "Hide location", type: "checkbox" },
392 hideGradient: { label: "Hide gradient", type: "checkbox" },
393 customLocation: {
394 label: "Your location",
395 type: "text",
396 placeholder: "example: Paris",
397 fullWidth: true,
398 },
399
400 netstatsWidgetOptions: {
401 label: "Network stats",
402 documentation: "/network-stats/",
403 infos: [
404 "Here you can set the refresh frequency of the widget.",
405 "The default value is set to 2000 ms (2 seconds).",
406 ],
407 },
408 netstatsThreshold: {
409 label: "Hide below (kb/s)",
410 type: "number",
411 placeholder: "0 to always show",
412 },
413
414 cpuWidgetOptions: {
415 label: "CPU usage",
416 documentation: "/cpu/",
417 infos: [
418 "Here you can set the refresh frequency of the widget.",
419 "The default value is set to 2000 ms (2 seconds).",
420 ],
421 },
422 cpuUsageThreshold: {
423 label: "Hide below (%)",
424 type: "number",
425 placeholder: "0 to always show",
426 },
427
428 gpuWidgetOptions: {
429 label: "GPU usage",
430 documentation: "/gpu/",
431 infos: [
432 "Here you can set the refresh frequency of the widget.",
433 "The default value is set to 2000 ms (2 seconds).",
434 ],
435 },
436
437 gpuMacmonBinaryPath: {
438 label: "Path to macmon binary",
439 type: "text",
440 placeholder: "example: /opt/homebrew/bin/macmon",
441 fullWidth: true,
442 },
443
444 memoryWidgetOptions: {
445 label: "Memory pressure",
446 documentation: "/memory-pressure/",
447 infos: [
448 "Here you can set the refresh frequency of the widget.",
449 "The default value is set to 4000 ms (4 seconds).",
450 ],
451 },
452 memoryUsageThreshold: {
453 label: "Hide below (%)",
454 type: "number",
455 placeholder: "0 to always show",
456 },
457
458 displayAsGraph: {
459 label: "Display as graph",
460 type: "checkbox",
461 fullWidth: true,
462 },
463
464 cpuMonitorApp: {
465 title: "Cpu monitor app",
466 label: "",
467 type: "radio",
468 options: ["Top", "Activity Monitor", "None"],
469 },
470
471 memoryMonitorApp: {
472 title: " app",
473 label: "",
474 type: "radio",
475 options: ["Top", "Activity Monitor", "None"],
476 },
477
478 batteryWidgetOptions: {
479 label: "Battery",
480 documentation: "/battery/",
481 infos: [
482 "no option (default) — Prevent the system from sleeping, not the display",
483 "-d — Prevent the display from sleeping.",
484 "-i — Prevent the system from idle sleeping.",
485 "-s — Prevent the system from sleeping. This is valid only when system is running on AC power.",
486 "-u — Declare that a user is active. If the display is off, this option turns the display on and prevents the display from going into idle sleep.",
487 "-t 60 — Specifies the timeout value in seconds for which the command is valid.",
488 ],
489 },
490
491 toggleCaffeinateOnClick: {
492 label: "Toggle caffeinate on click",
493 type: "checkbox",
494 fullWidth: true,
495 },
496 disableCaffeinateInvertedBackground: {
497 label: "Disable caffeinate inverted background",
498 type: "checkbox",
499 fullWidth: true,
500 },
501 caffeinateOption: {
502 label: "Caffeinate options",
503 type: "text",
504 placeholder: "example: -d",
505 },
506
507 networkWidgetOptions: {
508 label: "Network",
509 documentation: "/network/",
510 infos: [
511 "Here you can override the default displayed network source.",
512 "And also turn Wifi on / off when clicking the Wifi icon.",
513 "Additionally, you can choose to hide the network name for privacy.",
514 ],
515 },
516
517 networkDevice: {
518 label: "Network device source name",
519 type: "text",
520 placeholder: "example: en0",
521 },
522 hideWifiIfDisabled: { label: "Hide if disabled", type: "checkbox" },
523 toggleWifiOnClick: { label: "Toggle Wifi onclick", type: "checkbox" },
524 hideNetworkName: { label: "Hide network name", type: "checkbox" },
525
526 vpnWidgetOptions: {
527 label: "Viscosity VPN",
528 documentation: "/viscosity-vpn/",
529 infos: ["Here you can set your Viscosity vpn connection name."],
530 },
531
532 vpnConnectionName: {
533 label: "Viscosity connection name",
534 type: "text",
535 fullWidth: true,
536 },
537 vpnShowConnectionName: {
538 label: "Display the connection name in the widget",
539 type: "checkbox",
540 fullWidth: true,
541 },
542
543 zoomWidgetOptions: {
544 label: "Zoom status",
545 documentation: "/zoom/",
546 },
547
548 showVideo: { label: "Show video status", type: "checkbox" },
549 showMic: { label: "Show mic status", type: "checkbox" },
550
551 soundWidgetOptions: {
552 label: "Sound",
553 documentation: "/sound/",
554 },
555
556 micWidgetOptions: {
557 label: "Mic",
558 documentation: "/microphone/",
559 },
560
561 keyboardWidgetOptions: {
562 label: "Keyboard",
563 documentation: "/keyboard/",
564 },
565 keyboardMaxLength: {
566 label: "Characters to display",
567 type: "number",
568 placeholder: "0 to show full name",
569 },
570
571 timeWidgetOptions: {
572 label: "Time",
573 documentation: "/time/",
574 },
575
576 hour12: { label: "12h time format", type: "checkbox" },
577 dayProgress: { label: "Day progress", type: "checkbox" },
578 showSeconds: { label: "Show seconds", type: "checkbox" },
579
580 dateWidgetOptions: {
581 label: "Date",
582 documentation: "/date/",
583 },
584
585 shortDateFormat: { label: "Short format", type: "checkbox" },
586 locale: { label: "Locale", type: "text", placeholder: "example: en-UK" },
587 calendarApp: {
588 label: "Calendar App",
589 type: "text",
590 placeholder: "example: Fantastical",
591 fullWidth: true,
592 },
593
594 youtubeMusicWidgetOptions: {
595 label: "YouTube Music",
596 },
597
598 spotifyWidgetOptions: {
599 label: "Spotify",
600 documentation: "/spotify/",
601 },
602
603 cryptoWidgetOptions: {
604 label: "Crypto",
605 documentation: "/crypto/",
606 },
607
608 stockWidgetOptions: {
609 label: "Stock",
610 documentation: "/stocks/",
611 infos: [
612 "Here you can configure your API key for the Yahoo Finance API.",
613 "If you haven't gotten one yet, go to https://www.yahoofinanceapi.com/.",
614 "You can register for free and use the Basic tier (100 requests/day).",
615 ],
616 },
617
618 musicWidgetOptions: {
619 label: "Music/iTunes",
620 documentation: "/music-itunes/",
621 },
622
623 mpdWidgetOptions: {
624 label: "MPD via mpc",
625 documentation: "/mpd-state-via-mpc/",
626 },
627
628 mpdBinaryPath: {
629 label: "Path to mpc binary",
630 type: "text",
631 placeholder: "example: /opt/homebrew/bin/mpc",
632 fullWidth: true,
633 },
634 mpdHost: {
635 label: "Host",
636 type: "text",
637 placeholder: "example: 127.0.0.1",
638 },
639 mpdPort: {
640 label: "Port",
641 type: "text",
642 placeholder: "example: 6600",
643 },
644 mpdFormatString: {
645 label: "Format String (see `man mpc`)",
646 type: "text",
647 placeholder: "example: %title%[ - %artist%]|[%file%]",
648 fullWidth: true,
649 },
650
651 browserTrackWidgetOptions: {
652 label: "Browser",
653 documentation: "/browser-track/",
654 },
655 excludedApps: {
656 label: "Excluded apps (comma-separated app names)",
657 type: "text",
658 placeholder: "example: BetterTouchTool, Xcode",
659 fullWidth: true,
660 },
661 notificationsWidgetOptions: {
662 label: "Notification badges",
663 documentation: "/notifications/",
664 infos: [
665 "Shows notification badge counts from running macOS apps.",
666 "Click any badge to open that application.",
667 'Each app exclusion must be separated by a comma and a space ", "',
668 ],
669 },
670 nextMeetingWidgetOptions: {
671 label: "Next meeting",
672 documentation: "/next-meeting/",
673 infos: [
674 "Shows your next upcoming calendar event with time until start.",
675 "Supports one-click join for Zoom, Teams, Google Meet, and Webex.",
676 "Handles Microsoft SafeLinks (Outlook URL protection) automatically.",
677 "<br/>",
678 "<b>Requires icalBuddy:</b> brew install ical-buddy",
679 "Grant calendar access when prompted.",
680 ],
681 },
682 icalBuddyPath: {
683 label: "Path to icalBuddy binary",
684 type: "text",
685 placeholder: "default: auto-detect (Homebrew)",
686 fullWidth: true,
687 },
688 lookAheadHours: {
689 label: "Look ahead (hours)",
690 type: "number",
691 placeholder: "default: 12",
692 },
693 showJoinButton: { label: "Show join button", type: "checkbox" },
694 showTimeOnly: { label: "Show time only (hide title)", type: "checkbox" },
695 showSpecter: { label: "Show animated specter", type: "checkbox" },
696 showSpotifyMetadata: { label: "Show Spotify metadata", type: "checkbox" },
697 youtubeMusicPort: { label: "Port", type: "text", placeholder: "26538" },
698
699 denomination: { label: "Denomination", type: "text", placeholder: "usd" },
700 identifiers: {
701 label: "Identifiers",
702 type: "text",
703 placeholder: "celo,bitcoin,ethereum",
704 },
705 precision: { label: "Decimals rounding", type: "text", placeholder: 5 },
706
707 symbols: {
708 label: "Symbols for your stocks, ETFs, mutual funds, ...",
709 type: "text",
710 placeholder: "AAPL,TSLA",
711 fullWidth: true,
712 },
713 yahooFinanceApiKey: {
714 label: "Your API key for Yahoo Finance",
715 type: "text",
716 placeholder: "YOUR_API_KEY",
717 fullWidth: true,
718 },
719 showSymbol: { label: "Show symbol", type: "checkbox" },
720 showCurrency: { label: "Show currency", type: "checkbox" },
721 showMarketPrice: { label: "Show market price", type: "checkbox" },
722 showMarketChange: { label: "Show market change", type: "checkbox" },
723 showMarketPercent: { label: "Show market change percent", type: "checkbox" },
724 showColor: {
725 label: "Show colored output for market change",
726 type: "checkbox",
727 },
728
729 userWidgets: {
730 label: "User widgets",
731 documentation: "/custom-widgets/",
732 },
733 userWidgetsList: { type: "component", Component: UserWidgetsCreator },
734
735 refreshFrequency: { label: "Refresh frequency (in ms)", type: "number" },
736
737 customStyles: {
738 label: "Custom styles",
739 documentation: "/custom-styles/",
740 },
741 styles: {
742 label: "Styles",
743 type: "textarea",
744 fullWidth: true,
745 minHeight: 240,
746 },
747};
748
749// Default settings are defined here
750export const defaultSettings = {
751 global: {
752 theme: "auto",
753 compactMode: false,
754 floatingBar: false,
755 noBarBg: false,
756 noColorInData: false,
757 bottomBar: false,
758 sideDecoration: false,
759 inlineSpacesOptions: false,
760 disableAnimations: false,
761 spacesBackgroundColorAsForeground: false,
762 widgetsBackgroundColorAsForeground: false,
763 widgetMaxWidth: "160px",
764 slidingAnimationPace: 4,
765 font: "JetBrains Mono, Monaco, Menlo, monospace",
766 fontSize: "11px",
767 yabaiPath: "$(which yabai)",
768 aerospacePath: "$(which aerospace)",
769 windowManager: "yabai",
770 shell: "sh",
771 terminal: "Terminal",
772 disableNotifications: false,
773 enableMissives: false,
774 enableServer: false,
775 serverSocketPort: 7777,
776 yabaiServerRefresh: false,
777 aerospaceServerRefresh: false,
778 },
779 themes: {
780 lightTheme: "NightShiftLight",
781 darkTheme: "NightShiftDark",
782 colorMain: "",
783 colorMainAlt: "",
784 colorMinor: "",
785 colorAccent: "",
786 colorRed: "",
787 colorGreen: "",
788 colorYellow: "",
789 colorOrange: "",
790 colorBlue: "",
791 colorMagenta: "",
792 colorCyan: "",
793 colorBlack: "",
794 colorWhite: "",
795 colorForeground: "",
796 colorBackground: "",
797 },
798 process: {
799 showOnDisplay: "",
800 displayForFocusedSpace: false,
801 displayOnlyCurrent: false,
802 centered: false,
803 showCurrentSpaceMode: false,
804 hideWindowTitle: false,
805 displayOnlyIcon: false,
806 expandAllProcesses: false,
807 displaySkhdMode: false,
808 displayStackIndex: true,
809 displayOnlyCurrentStack: false,
810 },
811 spacesDisplay: {
812 showOnDisplay: "",
813 exclusions: "",
814 titleExclusions: "",
815 spacesExclusions: "",
816 exclusionsAsRegex: false,
817 displayAllSpacesOnAllScreens: false,
818 hideDuplicateAppsInSpaces: false,
819 displayStickyWindowsSeparately: false,
820 hideCreateSpaceButton: false,
821 hideEmptySpaces: false,
822 showOptionsOnHover: true,
823 switchSpacesWithoutYabai: false,
824 customAeroSpaceDisplayIndexes: {},
825 },
826 widgets: {
827 processWidget: true,
828 githubWidget: false,
829 weatherWidget: false,
830 netstatsWidget: false,
831 cpuWidget: false,
832 gpuWidget: false,
833 memoryWidget: false,
834 batteryWidget: true,
835 wifiWidget: true,
836 vpnWidget: false,
837 zoomWidget: false,
838 soundWidget: true,
839 micWidget: false,
840 dateWidget: true,
841 timeWidget: true,
842 keyboardWidget: false,
843 spotifyWidget: true,
844 cryptoWidget: false,
845 stockWidget: false,
846 youtubeMusicWidget: false,
847 musicWidget: true,
848 mpdWidget: false,
849 browserTrackWidget: false,
850 notificationsWidget: false,
851 nextMeetingWidget: false,
852 },
853 githubWidgetOptions: {
854 refreshFrequency: 1000 * 60 * 10,
855 showOnDisplay: "",
856 showIcon: true,
857 hideWhenNoNotification: false,
858 notificationUrl: "https://github.com/notifications",
859 ghBinaryPath: "/opt/homebrew/bin/gh",
860 },
861 weatherWidgetOptions: {
862 refreshFrequency: 1000 * 60 * 30,
863 showOnDisplay: "",
864 showIcon: true,
865 unit: "C",
866 hideLocation: false,
867 hideGradient: false,
868 customLocation: "",
869 },
870 netstatsWidgetOptions: {
871 refreshFrequency: 2000,
872 showOnDisplay: "",
873 showIcon: true,
874 displayAsGraph: false,
875 netstatsThreshold: 0,
876 },
877 cpuWidgetOptions: {
878 refreshFrequency: 2000,
879 showOnDisplay: "",
880 showIcon: true,
881 displayAsGraph: false,
882 cpuUsageThreshold: 0,
883 cpuMonitorApp: "Activity Monitor",
884 },
885 gpuWidgetOptions: {
886 refreshFrequency: 3000,
887 showOnDisplay: "",
888 showIcon: true,
889 displayAsGraph: false,
890 gpuMacmonBinaryPath: "/opt/homebrew/bin/macmon",
891 },
892 memoryWidgetOptions: {
893 refreshFrequency: 4000,
894 showOnDisplay: "",
895 showIcon: true,
896 memoryUsageThreshold: 0,
897 memoryMonitorApp: "Activity Monitor",
898 },
899 batteryWidgetOptions: {
900 refreshFrequency: 10000,
901 showOnDisplay: "",
902 showIcon: true,
903 toggleCaffeinateOnClick: true,
904 disableCaffeinateInvertedBackground: false,
905 caffeinateOption: "",
906 },
907 networkWidgetOptions: {
908 refreshFrequency: 20000,
909 showOnDisplay: "",
910 showIcon: true,
911 networkDevice: "en0",
912 hideWifiIfDisabled: false,
913 toggleWifiOnClick: false,
914 hideNetworkName: false,
915 },
916 vpnWidgetOptions: {
917 refreshFrequency: 8000,
918 showOnDisplay: "",
919 showIcon: true,
920 vpnConnectionName: "",
921 vpnShowConnectionName: false,
922 },
923 zoomWidgetOptions: {
924 refreshFrequency: 5000,
925 showOnDisplay: "",
926 showVideo: true,
927 showMic: true,
928 },
929 soundWidgetOptions: {
930 refreshFrequency: 20000,
931 showOnDisplay: "",
932 showIcon: true,
933 },
934 micWidgetOptions: {
935 refreshFrequency: 20000,
936 showOnDisplay: "",
937 showIcon: true,
938 },
939 dateWidgetOptions: {
940 refreshFrequency: 30000,
941 showOnDisplay: "",
942 showIcon: true,
943 shortDateFormat: true,
944 locale: "en-UK",
945 calendarApp: "",
946 },
947 timeWidgetOptions: {
948 refreshFrequency: 1000,
949 showOnDisplay: "",
950 showIcon: true,
951 hour12: false,
952 dayProgress: true,
953 showSeconds: false,
954 },
955 keyboardWidgetOptions: {
956 refreshFrequency: 20000,
957 showOnDisplay: "",
958 showIcon: true,
959 keyboardMaxLength: 0,
960 },
961 cryptoWidgetOptions: {
962 refreshFrequency: 5 * 60 * 1000,
963 showOnDisplay: "",
964 showIcon: true,
965 denomination: "usd",
966 identifiers: "bitcoin,ethereum,celo",
967 precision: 5,
968 },
969 stockWidgetOptions: {
970 refreshFrequency: 15 * 60 * 1000,
971 showOnDisplay: "",
972 showIcon: true,
973 yahooFinanceApiKey: "YOUR_API_KEY",
974 symbols: "AAPL,TSLA",
975 showSymbol: true,
976 showCurrency: true,
977 showMarketPrice: true,
978 showMarketChange: false,
979 showMarketPercent: true,
980 showColor: true,
981 },
982 spotifyWidgetOptions: {
983 refreshFrequency: 10000,
984 showOnDisplay: "",
985 showIcon: true,
986 showSpecter: true,
987 showSpotifyMetadata: true,
988 },
989 youtubeMusicWidgetOptions: {
990 refreshFrequency: 10000,
991 showOnDisplay: "",
992 showIcon: true,
993 showSpecter: true,
994 youtubeMusicPort: 26538,
995 },
996 musicWidgetOptions: {
997 refreshFrequency: 10000,
998 showOnDisplay: "",
999 showIcon: true,
1000 showSpecter: true,
1001 },
1002 mpdWidgetOptions: {
1003 refreshFrequency: 10000,
1004 showOnDisplay: "",
1005 showIcon: true,
1006 showSpecter: true,
1007 mpdBinaryPath: "/opt/homebrew/bin/mpc",
1008 mpdPort: "6600",
1009 mpdHost: "127.0.0.1",
1010 mpdFormatString: "%title%[ - %artist%]|[%file%]",
1011 },
1012 browserTrackWidgetOptions: {
1013 refreshFrequency: 10000,
1014 showOnDisplay: "",
1015 showIcon: true,
1016 showSpecter: true,
1017 },
1018 notificationsWidgetOptions: {
1019 refreshFrequency: 10000,
1020 showOnDisplay: "",
1021 excludedApps: "",
1022 },
1023 nextMeetingWidgetOptions: {
1024 refreshFrequency: 60000,
1025 showOnDisplay: "",
1026 showJoinButton: true,
1027 showTimeOnly: false,
1028 icalBuddyPath: "",
1029 lookAheadHours: 12,
1030 },
1031 userWidgets: {
1032 userWidgetsList: {},
1033 },
1034 customStyles: {
1035 styles: "/* your custom css styles here */",
1036 },
1037};
1038
1039// User widget default settings
1040export const userWidgetDefault = {
1041 title: "Your widget name",
1042 icon: "Widget",
1043 backgroundColor: "--main-alt",
1044 output: 'echo "Hello world!"',
1045 onClickAction: "",
1046 onRightClickAction: "",
1047 onMiddleClickAction: "",
1048 refreshFrequency: 10000,
1049 showOnDisplay: "",
1050 active: true,
1051 noIcon: false,
1052 hideWhenNoOutput: true,
1053};
1054
1055// Colors available for user widgets
1056export const userWidgetColors = [
1057 "--main",
1058 "--main-alt",
1059 "--minor",
1060 "--accent",
1061 "--red",
1062 "--green",
1063 "--yellow",
1064 "--orange",
1065 "--blue",
1066 "--magenta",
1067 "--cyan",
1068];
1069
1070/**
1071 * Retrieves the application settings from local storage.
1072 * If no settings are found, the default settings are used.
1073 * The settings schema is removed before returning the settings.
1074 *
1075 * @returns {Object} The application settings.
1076 */
1077export function get() {
1078 const storedSettings = window.localStorage.getItem(SETTINGS_STORAGE_KEY);
1079 const settings = storedSettings
1080 ? Utils.mergeDeep(defaultSettings, JSON.parse(storedSettings))
1081 : defaultSettings;
1082 delete settings.$schema;
1083 return settings;
1084}
1085
1086/**
1087 * Updates the settings by merging them with the schema, saving them to a config file,
1088 * and storing them in the local storage.
1089 *
1090 * @param {Object} newSettings - The new settings to be applied.
1091 * @returns {Promise<void>} A promise that resolves when the settings have been saved.
1092 */
1093export async function set(newSettings) {
1094 pruneObsoleteSettings(newSettings);
1095 const settingsWithSchema = {
1096 $schema:
1097 "https://raw.githubusercontent.com/Jean-Tinland/simple-bar/refs/heads/master/lib/schemas/config.json",
1098 ...newSettings,
1099 };
1100 await saveToConfigFile(settingsWithSchema);
1101 window.localStorage.setItem(
1102 SETTINGS_STORAGE_KEY,
1103 JSON.stringify(settingsWithSchema),
1104 );
1105}
1106
1107/**
1108 * Saves the provided settings to the configuration file.
1109 *
1110 * @param {Object} newSettings - The new settings to be saved.
1111 * @returns {Promise<void>} A promise that resolves when the settings have been saved.
1112 * @throws Will throw an error if the settings cannot be saved.
1113 */
1114async function saveToConfigFile(newSettings) {
1115 try {
1116 const settings = JSON.stringify(newSettings, undefined, 2);
1117 const cleanSettings = settings.replace(/'/g, "'\"'\"'");
1118 await Uebersicht.run(`echo '${cleanSettings}' | tee ~/.simplebarrc`);
1119 } catch (e) {
1120 // eslint-disable-next-line no-console
1121 console.error(e);
1122 }
1123}
1124
1125/**
1126 * Checks if the configuration file for simple-bar exists.
1127 *
1128 * This function runs a shell command to check for the presence of the
1129 * configuration file located at `~/.simplebarrc`. If the file exists,
1130 * the function returns `true`; otherwise, it returns `false`.
1131 *
1132 * @returns {Promise<boolean>} A promise that resolves to `true` if the
1133 * configuration file exists, and `false` otherwise.
1134 */
1135export async function checkIfConfigFileExists() {
1136 let exists = false;
1137 try {
1138 exists = Boolean(await Uebersicht.run(`ls ~/.simplebarrc`));
1139 } catch (e) {
1140 // eslint-disable-next-line no-console
1141 console.error(e);
1142 }
1143 return exists;
1144}
1145
1146/**
1147 * Removes obsolete settings from the provided settings object.
1148 *
1149 * @param {Object} settings - The settings object to prune.
1150 * @param {Object} settings.global - The global settings object.
1151 * @param {string} settings.global.externalConfigFile - The external configuration file setting to be removed.
1152 * @param {Object} settings.widgets - The widgets settings object.
1153 * @param {Object} settings.widgets.dndWidget - The dndWidget setting to be removed.
1154 * @param {Object} settings.widgets.undefined - The undefined widget setting to be removed.
1155 */
1156function pruneObsoleteSettings(settings) {
1157 delete settings.global.externalConfigFile;
1158 delete settings.widgets.dndWidget;
1159 delete settings.widgets.undefined;
1160}
1161
1162/**
1163 * Loads the external configuration file for simple-bar.
1164 */
1165export async function loadExternalConfig() {
1166 const configFileExists = await checkIfConfigFileExists();
1167 if (!configFileExists) return;
1168 try {
1169 const config = JSON.parse(await Uebersicht.run(`cat ~/.simplebarrc`));
1170 const settings = Utils.mergeDeep(defaultSettings, config);
1171 return settings;
1172 } catch (e) {
1173 // eslint-disable-next-line no-console
1174 console.error("Error loading external config:", e);
1175 }
1176}
1177
1178/** */
1179export async function init() {
1180 const externalConfig = await loadExternalConfig();
1181 if (externalConfig) {
1182 set(externalConfig);
1183 }
1184}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/skhd.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/skhd.js
new file mode 100755
index 0000000..e2923d1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/skhd.js
@@ -0,0 +1,17 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "./settings";
3import * as Utils from "./utils";
4
5/**
6 * Retrieves the current mode by executing a shell script and parsing its output.
7 *
8 * @returns {Promise<Object> | undefined} A promise that resolves to the parsed JSON object representing the mode.
9 */
10export async function getMode() {
11 const settings = Settings.get();
12 const { shell } = settings.global;
13 const mode = await Uebersicht.run(
14 `cat $(${shell} ./simple-bar/lib/scripts/yabai-set-mode-server.sh --query 2>&1)`,
15 );
16 return Utils.parseJson(mode);
17}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/battery.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/battery.js
new file mode 100755
index 0000000..5c0c413
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/battery.js
@@ -0,0 +1,134 @@
1// Styles for /lib/components/data/battery.jsx component
2export const batteryStyles = /* css */ `
3.battery {
4 position: relative;
5 background-color: var(--magenta);
6 overflow: hidden;
7}
8.battery--caffeinate,
9.simple-bar--no-color-in-data .battery--caffeinate {
10 color: var(--black);
11 background-color: var(--white);
12}
13.simple-bar--widgets-background-color-as-foreground .battery {
14 color: var(--magenta);
15 background-color: transparent;
16}
17.simple-bar--widgets-background-color-as-foreground .battery--caffeinate {
18 color: var(--foreground);
19}
20.battery__icon {
21 position: relative;
22 width: 16px;
23 height: 9px;
24 margin-top: -2px;
25 margin-right: 10px;
26}
27.battery__icon::after {
28 content: '';
29 position: absolute;
30 top: calc(10% + 1px);
31 left: calc(100% + 2px);
32 width: 2px;
33 height: 80%;
34 border-radius: 0 3px 3px 0;
35 background-color: currentColor;
36}
37.simple-bar--no-color-in-data .battery__icon::after {
38 background-color: currentColor;
39}
40.battery__icon-inner {
41 position: relative;
42 width: 100%;
43 height: 100%;
44 border-radius: 3px;
45 border: 1px solid currentColor;
46 overflow: hidden;
47}
48.battery__charging-icon {
49 position: absolute;
50 top: -1px;
51 left: calc(50% - 6px);
52 width: 11px;
53 height: 11px;
54 fill: currentColor;
55 stroke: var(--magenta);
56 stroke-width: 2;
57}
58.simple-bar--no-color-in-data .battery__charging-icon {
59 stroke: var(--minor);
60}
61.battery--caffeinate .battery__charging-icon {
62 stroke: var(--white);
63}
64.simple-bar--widgets-background-color-as-foreground .battery__charging-icon {
65 stroke: var(--background);
66}
67.simple-bar--no-color-in-data .battery__icon-inner {
68 fill: currentColor;
69 border: 1px solid currentColor;
70}
71.battery__icon-filler {
72 position: absolute;
73 top: 1px;
74 left: 1px;
75 width: calc(100% - 2px);
76 height: calc(100% - 2px);
77 background-color: currentColor;
78 border-radius: 2px;
79 transform: scaleX(0);
80 transform-origin: left center;
81 transition: transform 160ms var(--transition-easing);
82 z-index: 0;
83}
84.simple-bar--no-color-in-data .battery__icon-filler {
85 background-color: currentColor;
86 opacity: 0.8;
87}
88.simple-bar--no-color-in-data .battery--caffeinate .battery__icon::after,
89.simple-bar--no-color-in-data .battery--caffeinate .battery__icon-filler {
90 background-color: currentColor;
91}
92.battery--low .battery__icon-filler {
93 background-color: var(--red);
94}
95.battery--low-power-mode .battery__icon-filler {
96 background-color: var(--yellow);
97}
98.battery__caffeinate-icon {
99 position: absolute;
100 top: calc(50% - 12px);
101 right: -4px;
102 width: 26px !important;
103 height: 26px !important;
104 opacity: 0.15;
105}
106.battery__caffeinate-icon g path {
107 animation: coffee-spur-sliding-up 1600ms var(--transition-easing) infinite;
108}
109.simple-bar--animations-disabled .battery__caffeinate-icon g path {
110 animation: none;
111}
112.battery__caffeinate-icon g path:nth-child(2) {
113 animation-delay: -600ms;
114}
115.battery__caffeinate-icon g path:nth-child(3) {
116 animation-delay: -280ms;
117}
118@keyframes coffee-spur-sliding-up {
119 0% {
120 opacity: 0;
121 transform: translateY(3px);
122 }
123 20% {
124 opacity: 0.7;
125 }
126 80% {
127 opacity: 0.7;
128 }
129 100% {
130 opacity: 0;
131 transform: translateY(-4px);
132 }
133}
134`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/browser-track.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/browser-track.js
new file mode 100755
index 0000000..c70a1ee
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/browser-track.js
@@ -0,0 +1,40 @@
1// Styles for /lib/components/data/browser-track.jsx
2export const browserTrackStyles = /* css */ `
3.browser-track {
4 position: relative;
5 background-color: var(--green);
6}
7.simple-bar--widgets-background-color-as-foreground .browser-track {
8 color: var(--green);
9 background-color: transparent;
10}
11.browser-track__icons {
12 position: relative;
13}
14.browser-track__icons > svg:nth-of-type(1),
15.browser-track__icons > svg:nth-of-type(2) {
16 width: 10px;
17 height: 10px;
18 fill: currentColor;
19}
20.browser-track__icons > svg:nth-of-type(1) {
21 margin-right: 7px;
22}
23.simple-bar--no-color-in-data .browser-track__icons > svg:nth-of-type(1) {
24 fill: currentColor;
25}
26.browser-track__icons > svg:nth-of-type(2) {
27 position: absolute;
28 bottom: -1px;
29 right: 2px;
30 stroke: var(--green);
31 stroke-width: 3px;
32}
33.simple-bar--widgets-background-color-as-foreground .browser-track__icons > svg:nth-of-type(2) {
34 stroke: var(--background);
35}
36.simple-bar--no-color-in-data .browser-track__icons > svg:nth-of-type(2) {
37 fill: currentColor;
38 stroke: var(--minor);
39}
40`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/cpu.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/cpu.js
new file mode 100755
index 0000000..672c246
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/cpu.js
@@ -0,0 +1,16 @@
1// Styles for /lib/components/data/cpu.jsx component
2export const cpuStyles = /* css */ `
3.cpu {
4 color: var(--foreground);
5 background-color: var(--minor);
6}
7.cpu--graph {
8 min-width: 90px;
9 padding: 0;
10}
11.cpu__usage {
12 width: 4ch;
13 padding: 3px;
14 text-align: right;
15}
16`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/crypto.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/crypto.js
new file mode 100755
index 0000000..3c9b0ae
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/crypto.js
@@ -0,0 +1,9 @@
1// Styles for /lib/components/data/crypto.jsx component
2export const cryptoStyles = /* css */ `
3.crypto {
4 color: var(--foreground);
5 background-color: var(--minor);
6}
7.simple-bar--widgets-background-color-as-foreground .crypto {
8 background-color: transparent;
9}`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget-loader.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget-loader.js
new file mode 100755
index 0000000..62710aa
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget-loader.js
@@ -0,0 +1,32 @@
1// Styles for /lib/components/data/data-widget-loader.jsx component
2export const dataWidgetLoaderStyles = /* css */ `
3.data-widget-loader {
4 animation: data-widget-loader-appearance 320ms var(--transition-easing);
5}
6@keyframes data-widget-loader-appearance {
7 0% {
8 opacity: 0;
9 }
10}
11.data-widget-loader::before {
12 content: "";
13 width: 10px;
14 height: 10px;
15 margin-right: 7px;
16 background-color: currentColor;
17 border-radius: 50%;
18 opacity: 0.75;
19}
20.data-widget-loader__inner {
21 border: 2px solid transparent;
22 border-bottom-color: currentColor;
23 box-sizing: border-box;
24 border-radius: 50%;
25 animation: data-widget-loader-spining 640ms ease infinite;
26}
27@keyframes data-widget-loader-spining {
28 100% {
29 transform: rotate(360deg);
30 }
31}
32`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget.js
new file mode 100755
index 0000000..f0b5cf1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/data-widget.js
@@ -0,0 +1,65 @@
1// Styles for /lib/components/data/data-widget.jsx component
2export const dataWidgetStyles = /* css */ `
3.data-widget {
4 display: flex;
5 align-items: center;
6 margin: var(--item-outer-margin);
7 padding: var(--item-inner-margin);
8 color: var(--background);
9 font-family: var(--font);
10 font-size: inherit;
11 background-color: var(--minor);
12 text-decoration: none;
13 white-space: nowrap;
14 border-radius: var(--item-radius);
15 border: 0;
16 outline: none;
17 cursor: default;
18 user-select: none;
19 -webkit-user-select: none;
20 box-shadow: var(--light-shadow);
21 transition: all 160ms var(--transition-easing);
22}
23.simple-bar--no-shadow .data-widget {
24 box-shadow: none;
25}
26.simple-bar--no-color-in-data .data-widget {
27 color: var(--foreground);
28 background-color: var(--minor);
29}
30.simple-bar--widgets-background-color-as-foreground .data-widget {
31 background-color: transparent;
32 box-shadow: none;
33}
34.simple-bar--widgets-background-color-as-foreground.simple-bar--no-color-in-data .data-widget {
35 color: var(--foreground) !important;
36 background-color: transparent;
37}
38.data-widget--clickable {
39 cursor: pointer;
40}
41.data-widget--clickable:hover {
42 box-shadow: var(--light-shadow), var(--hover-ring);
43}
44.data-widget--clickable:active {
45 box-shadow: var(--light-shadow), var(--focus-ring);
46}
47.data-widget > svg {
48 width: 14px;
49 height: 14px;
50 margin-right: 7px;
51 fill: currentColor;
52}
53.data-widget__inner {
54 max-width: var(--item-max-width);
55 display: flex;
56 flew-wrap: nowrap;
57 overflow: hidden;
58}
59.data-widget__slider {
60 display: flex;
61 align-items: center;
62 white-space: nowrap;
63 transition: transform 160ms var(--transition-easing);
64}
65`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/date-display.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/date-display.js
new file mode 100755
index 0000000..c152449
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/date-display.js
@@ -0,0 +1,10 @@
1// Styles for /lib/components/data/date-display.jsx component
2export const dateStyles = /* css */ `
3.date-display {
4 background-color: var(--cyan);
5}
6.simple-bar--widgets-background-color-as-foreground .date-display {
7 color: var(--cyan);
8 background-color: transparent;
9}
10`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/github.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/github.js
new file mode 100755
index 0000000..f451ddc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/github.js
@@ -0,0 +1,10 @@
1// Styles for /lib/components/data/github.jsx component
2export const githubStyles = /* css */ `
3.github {
4 position: relative;
5 color: var(--foreground);
6 background-color: var(--minor);
7 overflow: hidden;
8 z-index: 0;
9}
10`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/gpu.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/gpu.js
new file mode 100755
index 0000000..c3f4b78
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/gpu.js
@@ -0,0 +1,15 @@
1// Styles for /lib/components/data/gpu.jsx component
2export const gpuStyles = /* css */ `
3.gpu {
4 color: var(--foreground);
5 background-color: var(--minor);
6}
7.gpu--graph {
8 min-width: 70px;
9 padding: 0;
10}
11.gpu__usage {
12 width: 4ch;
13 text-align: right;
14}
15`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/graph.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/graph.js
new file mode 100755
index 0000000..0bf3609
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/graph.js
@@ -0,0 +1,49 @@
1// Styles for /lib/components/data/graph.jsx component
2export const graphStyles = /* css */ `
3.graph {
4 position: relative;
5 width: 100%;
6 height: 100%;
7 display: flex;
8 align-items: flex-end;
9 gap: 4px;
10 overflow: hidden;
11 border-radius: inherit;
12}
13.graph__bars {
14 flex: 1 1 100%;
15 height: 75%;
16 display: flex;
17 align-items: flex-end;
18 justify-content: flex-end;
19 pointer-events: none;
20}
21.graph__bar {
22 min-height: 1px;
23 opacity: 0.75;
24}
25.graph__data {
26 position: absolute;
27 top: 3px;
28 left: 3px;
29 width: calc(100% - 6px);
30 flex: 0 0 auto;
31 display: flex;
32 justify-content: space-between;
33 gap: 2px;
34}
35.graph__data-item {
36 display: flex;
37 align-items: center;
38 gap: 3px;
39}
40.graph__data-item-icon {
41 flex: 0 0 10px;
42 width: 10px;
43 height: 10px;
44 fill: currentColor;
45}
46.graph__data-item-value {
47 font-size: calc(var(--font-size) - 2px);
48}
49`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/keyboard.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/keyboard.js
new file mode 100755
index 0000000..dfc4f70
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/keyboard.js
@@ -0,0 +1,10 @@
1// Styles for /lib/components/data/keyboard.jsx component
2export const keyboardStyles = /* css */ `
3.keyboard {
4 background-color: var(--main-alt);
5}
6.simple-bar--widgets-background-color-as-foreground .keyboard {
7 color: var(--main-alt);
8 background-color: transparent;
9}
10`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/memory.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/memory.js
new file mode 100755
index 0000000..d0239bb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/memory.js
@@ -0,0 +1,30 @@
1// Styles for /lib/components/data/memory.jsx component
2export const memoryStyles = /* css */ `
3.memory {
4 color: var(--foreground);
5 background-color: var(--minor);
6}
7.memory--low {
8 --pie-color: var(--green);
9}
10.memory--medium {
11 --pie-color: var(--yellow);
12}
13.memory--high {
14 --pie-color: var(--red);
15}
16.memory__pie {
17 flex: 0 0 21px;
18 width: 21px;
19 height: 21px;
20 border-radius: 50%;
21}
22.memory__content {
23 display: flex;
24 gap: 4px;
25 padding-left: 5px;
26}
27.memory--high .memory__content {
28 color: var(--red);
29}
30`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mic.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mic.js
new file mode 100755
index 0000000..7a58f10
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mic.js
@@ -0,0 +1,83 @@
1// Styles for /lib/components/data/mic.jsx component
2export const micStyles = /* css */ `
3.mic {
4font-variant-numeric: tabular-nums;
5 background-color: var(--orange);
6 transform: translateZ(0);
7}
8.simple-bar--widgets-background-color-as-foreground .mic {
9 color: var(--orange);
10 background-color: transparent;
11}
12.mic__slider-container {
13 --slider-size: 10px;
14
15 position: relative;
16 max-width: 0;
17 height: 100%;
18 display: flex;
19 align-items: center;
20 padding: 0;
21 overflow: hidden;
22 opacity: 0.7;
23 border-radius: var(--item-radius);
24 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
25 opacity 320ms var(--transition-easing),
26 clip-path 0ms var(--transition-easing);
27}
28.mic:hover .mic__slider-container,
29.mic--dragging .mic__slider-container {
30 max-width: 100px;
31 clip-path: inset(-100vh -100vw);
32 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
33 opacity 320ms var(--transition-easing),
34 clip-path 320ms 320ms var(--transition-easing)
35}
36.mic__slider-container:hover {
37 opacity: 1;
38}
39.mic__slider {
40 width: 100px;
41 height: var(--slider-size);
42 appearance: none;
43 background-color: var(--background);
44 border-radius: var(--item-radius);
45 outline: none;
46 -webkit-appearance: none;
47}
48.simple-bar--widgets-background-color-as-foreground .mic__slider {
49 background-color: var(--foreground);
50}
51.mic__slider::-webkit-slider-thumb {
52 width: var(--slider-size);
53 height: var(--slider-size);
54 background-color: var(--foreground);
55 border-radius: var(--item-radius);
56 cursor: pointer;
57 -webkit-appearance: none;
58 transform-origin: center;
59 transition: transform 160ms var(--transition-easing);
60}
61.simple-bar--widgets-background-color-as-foreground .mic__slider::-webkit-slider-thumb {
62 background-color: var(--orange);
63}
64.mic__slider::-webkit-slider-thumb:hover {
65 transform: scale(1.5);
66}
67.mic__display {
68 display: flex;
69 align-items: center;
70 margin-right: 4px;
71 overflow: hidden;
72}
73.mic__display:active {
74 color: currentColor;
75}
76.mic__display > svg {
77 flex-shrink: 0;
78 width: 14px;
79 height: 14px;
80 margin-right: 3px;
81 fill: currentColor;
82}
83`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mpd.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mpd.js
new file mode 100755
index 0000000..da159ab
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/mpd.js
@@ -0,0 +1,80 @@
1// Styles for /lib/components/data/mpd.jsx component
2export const mpdStyles = /* css */ `
3.mpd {
4 position: relative;
5 background-color: var(--cyan);
6}
7.simple-bar--widgets-background-color-as-foreground .mpd {
8 color: var(--cyan);
9 background-color: transparent;
10}
11.mpd__outer {
12 display: flex;
13 gap: 4px;
14}
15.mpd__inner {
16 max-width: 140px;
17 display: flex;
18 flew-wrap: nowrap;
19 overflow: hidden;
20}
21.mpd__info {
22 white-space: nowrap;
23 transition: transform 160ms var(--transition-easing);
24}
25.mpd__slider-container {
26 --slider-size: 10px;
27
28 position: relative;
29 max-width: 0;
30 height: 100%;
31 display: flex;
32 align-items: center;
33 padding: 0;
34 clip-path: inset(0);
35 opacity: 0.7;
36 border-radius: var(--item-radius);
37 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
38 opacity 320ms var(--transition-easing),
39 clip-path 0ms var(--transition-easing);
40}
41.mpd:hover .mpd__slider-container,
42.mpd--dragging .mpd__slider-container {
43 max-width: 100px;
44 clip-path: inset(-100vh -100vw);
45 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
46 opacity 320ms var(--transition-easing),
47 clip-path 320ms 320ms var(--transition-easing)
48}
49.mpd__slider-container:hover {
50 opacity: 1;
51}
52.mpd__slider {
53 width: 100px;
54 height: var(--slider-size);
55 appearance: none;
56 background-color: var(--background);
57 border-radius: var(--item-radius);
58 outline: none;
59 -webkit-appearance: none;
60}
61.simple-bar--widgets-background-color-as-foreground .mpd__slider {
62 background-color: var(--foreground);
63}
64.mpd__slider::-webkit-slider-thumb {
65 width: var(--slider-size);
66 height: var(--slider-size);
67 background-color: var(--foreground);
68 border-radius: var(--item-radius);
69 cursor: pointer;
70 -webkit-appearance: none;
71 transform-origin: center;
72 transition: transform 160ms var(--transition-easing);
73}
74.simple-bar--widgets-background-color-as-foreground .mpd__slider::-webkit-slider-thumb {
75 background-color: var(--blue);
76}
77.mpd__slider::-webkit-slider-thumb:hover {
78 transform: scale(1.5);
79}
80`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/music.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/music.js
new file mode 100755
index 0000000..5de3b1f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/music.js
@@ -0,0 +1,11 @@
1// Styles for /lib/components/data/music.jsx component
2export const musicStyles = /* css */ `
3.music {
4 position: relative;
5 background-color: var(--green);
6}
7.simple-bar--widgets-background-color-as-foreground .music {
8 color: var(--green);
9 background-color: transparent;
10}
11`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/netstats.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/netstats.js
new file mode 100755
index 0000000..384d970
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/netstats.js
@@ -0,0 +1,48 @@
1// Styles for /lib/components/data/netstats.jsx component
2export const netstatsStyles = /* css */ `
3.netstats {
4 display: flex;
5 align-items: center;
6 justify-content: space-between;
7 gap: 6px;
8 color: var(--foreground);
9 background-color: var(--minor);
10 z-index: 0;
11}
12.netstats--graph {
13 min-width: 120px;
14 padding: 0;
15}
16.simple-bar--widgets-background-color-as-foreground .netstats {
17 background-color: transparent;
18}
19.netstats__item {
20 width: 9ch;
21 display: flex;
22 align-items: center;
23 justify-content: center;
24 gap: 4px;
25 padding: 0 4px;
26}
27.netstats__value {
28 display: flex;
29 align-items: baseline;
30 justify-content: flex-end;
31 margin: 0 auto;
32}
33.netstats__value > em {
34 font-size: 0.8em;
35 font-style: normal;
36}
37.netstats__icon {
38 flex: 0 0 12px;
39 width: 12px;
40 height: 12px;
41}
42.netstats__icon--download {
43 fill: var(--magenta);
44}
45.netstats__icon--upload {
46 fill: var(--blue);
47}
48`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/next-meeting.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/next-meeting.js
new file mode 100755
index 0000000..c4a0a0f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/next-meeting.js
@@ -0,0 +1,71 @@
1// Styles for /lib/components/data/next-meeting.jsx component
2export const nextMeetingStyles = /* css */ `
3.next-meeting {
4 background-color: var(--cyan);
5}
6.simple-bar--widgets-background-color-as-foreground .next-meeting {
7 color: var(--cyan);
8 background-color: transparent;
9}
10.simple-bar--no-color-in-data .next-meeting {
11 background-color: var(--minor);
12}
13.next-meeting--upcoming {
14 background-color: var(--yellow) !important;
15}
16.simple-bar--widgets-background-color-as-foreground .next-meeting--upcoming {
17 color: var(--yellow);
18 background-color: transparent !important;
19}
20.next-meeting--urgent {
21 background-color: var(--red) !important;
22 animation: next-meeting-pulse 1.5s ease-in-out infinite;
23}
24.simple-bar--widgets-background-color-as-foreground .next-meeting--urgent {
25 color: var(--red);
26 background-color: transparent !important;
27}
28@keyframes next-meeting-pulse {
29 0%, 100% { opacity: 1; }
30 50% { opacity: 0.7; }
31}
32.simple-bar--animations-disabled .next-meeting--urgent {
33 animation: none;
34}
35.next-meeting__title {
36 max-width: 120px;
37 overflow: hidden;
38 text-overflow: ellipsis;
39 white-space: nowrap;
40 margin-right: 6px;
41}
42.next-meeting__time {
43 font-weight: 600;
44 opacity: 0.9;
45}
46.next-meeting__join {
47 margin-left: 6px;
48 padding: 2px 6px;
49 background-color: rgba(255, 255, 255, 0.2);
50 border: none;
51 border-radius: 3px;
52 color: inherit;
53 font-family: inherit;
54 font-size: 10px;
55 font-weight: 600;
56 cursor: pointer;
57 transition: background-color 160ms var(--transition-easing),
58 transform 160ms var(--transition-easing);
59}
60.next-meeting__join:hover {
61 background-color: rgba(255, 255, 255, 0.35);
62 transform: translateY(-1px);
63}
64.next-meeting__join:active {
65 transform: translateY(0);
66}
67.next-meeting__join:focus {
68 outline: none;
69 box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5);
70}
71`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/notifications.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/notifications.js
new file mode 100755
index 0000000..a1008c8
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/notifications.js
@@ -0,0 +1,68 @@
1// Styles for /lib/components/data/notifications.jsx component
2export const notificationsStyles = /* css */ `
3.notifications {
4 display: flex;
5 align-items: center;
6 gap: 5px;
7 margin-left: 5px;
8}
9.notification-pill {
10 display: flex;
11 align-items: center;
12 gap: 5px;
13 padding: 7px 8px;
14 background-color: var(--red);
15 border: none;
16 border-radius: var(--item-radius);
17 color: var(--white);
18 font-family: inherit;
19 font-size: 11px;
20 cursor: pointer;
21 transition: background-color 160ms var(--transition-easing),
22 transform 160ms var(--transition-easing);
23}
24.notification-pill:hover {
25 filter: brightness(1.2);
26 transform: translateY(-1px);
27}
28.notification-pill:active {
29 transform: translateY(0);
30}
31.notification-pill:focus {
32 outline: none;
33 box-shadow: var(--focus-ring);
34}
35.simple-bar--no-color-in-data .notification-pill {
36 background-color: var(--minor);
37 color: var(--foreground);
38}
39.simple-bar--widgets-background-color-as-foreground .notification-pill {
40 background-color: transparent;
41 color: var(--red);
42 border: 1px solid var(--red);
43}
44.simple-bar--widgets-background-color-as-foreground .notification-pill:hover {
45 background-color: var(--red);
46 color: var(--white);
47}
48.notification-pill__icon {
49 width: 14px;
50 height: 14px;
51 fill: currentColor;
52 flex-shrink: 0;
53}
54.notification-pill__badge {
55 background-color: rgba(0, 0, 0, 0.3);
56 color: var(--white);
57 padding: 1px 5px;
58 border-radius: 6px;
59 font-size: 10px;
60 font-weight: 600;
61 min-width: 8px;
62 text-align: center;
63}
64.simple-bar--widgets-background-color-as-foreground .notification-pill__badge {
65 background-color: var(--red);
66 color: var(--white);
67}
68`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/sound.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/sound.js
new file mode 100755
index 0000000..a45a862
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/sound.js
@@ -0,0 +1,83 @@
1// Styles for /lib/components/data/sound.jsx component
2export const soundStyles = /* css */ `
3.sound {
4 font-variant-numeric: tabular-nums;
5 background-color: var(--blue);
6 transform: translateZ(0);
7}
8.simple-bar--widgets-background-color-as-foreground .sound {
9 color: var(--blue);
10 background-color: transparent;
11}
12.sound__slider-container {
13 --slider-size: 10px;
14
15 position: relative;
16 max-width: 0;
17 height: 100%;
18 display: flex;
19 align-items: center;
20 padding: 0;
21 clip-path: inset(0);
22 opacity: 0.7;
23 border-radius: var(--item-radius);
24 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
25 opacity 320ms var(--transition-easing),
26 clip-path 0ms var(--transition-easing);
27}
28.sound:hover .sound__slider-container,
29.sound--dragging .sound__slider-container {
30 max-width: 100px;
31 clip-path: inset(-100vh -100vw);
32 transition: max-width 320ms var(--transition-easing), padding 320ms var(--transition-easing),
33 opacity 320ms var(--transition-easing),
34 clip-path 320ms 320ms var(--transition-easing)
35}
36.sound__slider-container:hover {
37 opacity: 1;
38}
39.sound__slider {
40 width: 100px;
41 height: var(--slider-size);
42 appearance: none;
43 background-color: var(--background);
44 border-radius: var(--item-radius);
45 outline: none;
46 -webkit-appearance: none;
47}
48.simple-bar--widgets-background-color-as-foreground .sound__slider {
49 background-color: var(--foreground);
50}
51.sound__slider::-webkit-slider-thumb {
52 width: var(--slider-size);
53 height: var(--slider-size);
54 background-color: var(--foreground);
55 border-radius: var(--item-radius);
56 cursor: pointer;
57 -webkit-appearance: none;
58 transform-origin: center;
59 transition: transform 160ms var(--transition-easing);
60}
61.simple-bar--widgets-background-color-as-foreground .sound__slider::-webkit-slider-thumb {
62 background-color: var(--blue);
63}
64.sound__slider::-webkit-slider-thumb:hover {
65 transform: scale(1.5);
66}
67.sound__display {
68 display: flex;
69 align-items: center;
70 margin-right: 4px;
71 overflow: hidden;
72}
73.sound__display:active {
74 color: currentColor;
75}
76.sound__display > svg {
77 flex-shrink: 0;
78 width: 14px;
79 height: 14px;
80 margin-right: 3px;
81 fill: currentColor;
82}
83`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/specter.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/specter.js
new file mode 100755
index 0000000..03d97a3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/specter.js
@@ -0,0 +1,55 @@
1// Styles for /lib/components/data/specter.jsx component
2export const specterStyles = /* css */ `
3.specter {
4 position: absolute;
5 bottom: 0;
6 right: 30px;
7 display: flex;
8 align-items: flex-end;
9 z-index: 2;
10 pointer-events: none;
11 touch-action: none;
12}
13.simple-bar--animations-disabled .specter {
14 display: none;
15}
16.specter > span {
17 flex: 0 0 5px;
18 height: 15px;
19 max-height: 15px;
20 margin-left: 1px;
21 background-color: var(--main);
22 opacity: 0.1;
23 transform-origin: bottom;
24}
25.simple-bar--no-color-in-data .specter > span,
26.simple-bar--widgets-background-color-as-foreground .specter > span {
27 background-color: currentColor;
28}
29.specter > span {
30 animation: specter-waving 640ms var(--transition-easing) infinite;
31}
32.simple-bar--animations-disabled .specter > span {
33 animation: none;
34}
35.specter > span:nth-of-type(1) {
36 animation-delay: -460ms;
37}
38.specter > span:nth-of-type(2) {
39 animation-delay: -320ms;
40}
41.specter > span:nth-of-type(3) {
42 animation-delay: -200ms;
43}
44.specter > span:nth-of-type(4) {
45 animation-delay: -240ms;
46}
47.specter > span:nth-of-type(5) {
48 animation-delay: -150ms;
49}
50@keyframes specter-waving {
51 50% {
52 transform: scaleY(0.2);
53 }
54}
55`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/spotify.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/spotify.js
new file mode 100755
index 0000000..0f9db7a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/spotify.js
@@ -0,0 +1,15 @@
1// Styles for /lib/components/data/spotify.jsx component
2export const spotifyStyles = /* css */ `
3.spotify {
4 position: relative;
5 background-color: var(--green);
6}
7.simple-bar--widgets-background-color-as-foreground .spotify {
8 color: var(--green);
9 background-color: transparent;
10}
11
12.spotify--hidden-metadata > svg {
13 margin-right: 0;
14}
15`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/stock.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/stock.js
new file mode 100755
index 0000000..2c1eacd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/stock.js
@@ -0,0 +1,15 @@
1// Styles for /lib/components/data/stock.jsx component
2export const stockStyles = /* css */ `
3.stock {
4 color: var(--foreground);
5 background-color: var(--minor);
6}
7.simple-bar--widgets-background-color-as-foreground .stock {
8 background-color: transparent;
9}
10.stockUp {
11 color: var(--green);
12}
13.stockDown {
14 color: var(--red);
15}`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/time.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/time.js
new file mode 100755
index 0000000..ac04f90
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/time.js
@@ -0,0 +1,85 @@
1// Styles for /lib/components/data/time.jsx component
2export const timeStyles = /* css */ `
3.time {
4 position: relative;
5 font-variant-numeric: tabular-nums;
6 background-color: var(--yellow);
7 overflow: hidden;
8 z-index: 0;
9}
10.simple-bar--widgets-background-color-as-foreground .time {
11 color: var(--yellow);
12 background-color: transparent;
13}
14.time__filler {
15 position: absolute;
16 top: 0;
17 left: 0;
18 width: 100%;
19 height: 100%;
20 transform: scaleX(0);
21 background-color: rgba(0, 0, 0, 0.15);
22 transform-origin: left;
23 pointer-events: none;
24 touch-action: none;
25 z-index: -1;
26}
27.simple-bar--widgets-background-color-as-foreground .time__filler {
28 background-color: transparent;
29}
30.time__icon {
31 position: relative;
32 flex: 0 0 15px;
33 width: 15px;
34 height: 15px;
35 margin-right: 7px;
36 border: 1px solid var(--background);
37 border-radius: 50%;
38}
39.simple-bar--widgets-background-color-as-foreground .time__icon {
40 border: 1px solid var(--yellow);
41}
42.simple-bar--no-color-in-data .time__icon {
43 border: 1px solid var(--foreground);
44}
45.time__hours,
46.time__minutes {
47 position: absolute;
48 bottom: 50%;
49 width: 1px;
50 left: 50%;
51 margin-left: -1px;
52 background-color: var(--background);
53 transform-origin: bottom;
54 transition: transform 160ms var(--transition-easing);
55 will-change: transform;
56}
57.simple-bar--widgets-background-color-as-foreground .time__hours,
58.simple-bar--widgets-background-color-as-foreground .time__minutes {
59 background-color: var(--yellow);
60}
61.simple-bar--no-color-in-data .time__hours,
62.simple-bar--no-color-in-data .time__minutes {
63 background-color: var(--foreground);
64}
65.time__hours {
66 height: 28%;
67}
68.time__minutes {
69 height: 43%;
70}
71@media only screen and (-webkit-min-device-pixel-ratio: 2),
72 only screen and (min-device-pixel-ratio: 2),
73 only screen and (min-resolution: 192dpi),
74 only screen and (min-resolution: 2dppx) {
75 .time__icon {
76 flex: 0 0 16px;
77 width: 16px;
78 height: 16px;
79 }
80 .time__hours,
81 .time__minutes {
82 margin-left: 0;
83 }
84}
85`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/viscosity-vpn.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/viscosity-vpn.js
new file mode 100755
index 0000000..b486b18
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/viscosity-vpn.js
@@ -0,0 +1,17 @@
1// Styles for /lib/components/data/viscosity-vpn.jsx component
2export const viscosityVPNStyles = /* css */ `
3.viscosity-vpn {
4 background-color: var(--red);
5}
6.simple-bar--widgets-background-color-as-foreground .viscosity-vpn {
7 color: var(--red);
8 background-color: transparent;
9}
10.viscosity-vpn--disconnected {
11 background-color: var(--minor);
12}
13.simple-bar--widgets-background-color-as-foreground .viscosity-vpn--disconnected {
14 color: var(--minor);
15 background-color: transparent;
16}
17`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/weather.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/weather.js
new file mode 100755
index 0000000..0b48abe
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/weather.js
@@ -0,0 +1,163 @@
1// Styles for /lib/components/data/weather.jsx component
2export const weatherStyles = /* css */ `
3.weather {
4 position: relative;
5 color: var(--foreground);
6 background-color: var(--minor);
7 overflow: hidden;
8 z-index: 0;
9}
10.simple-bar--widgets-background-color-as-foreground .weather {
11 background-color: transparent;
12}
13.weather__gradient {
14 position: absolute;
15 top: 0;
16 left: 0;
17 width: 100%;
18 height: 100%;
19 opacity: 0.65;
20 z-index: -1;
21}
22.weather--sunrise .weather__gradient {
23 background: linear-gradient(to top right, var(--main), var(--red), var(--yellow), var(--blue));
24}
25.weather--sunset .weather__gradient {
26 background: linear-gradient(to bottom right, var(--blue), var(--yellow), var(--red), var(--magenta), var(--main));
27}
28.simple-bar--no-color-in-data .weather__gradient {
29 display: none;
30}
31.sun-icon,
32.moon-icon {
33 transform-origin: 50% 50%;
34 animation: sunny-and-moon-scale-and-rotate 2560ms ease infinite;
35}
36.simple-bar--animations-disabled .sun-icon,
37.simple-bar--animations-disabled .moon-icon {
38 animation: none;
39}
40@keyframes sunny-and-moon-scale-and-rotate {
41 50% {
42 transform: rotate(14deg);
43 }
44}
45.cloud-icon {
46 transform: translateY(-1%) rotate(5deg);
47 animation: cloud-levitating 2560ms ease-in-out infinite;
48}
49.simple-bar--animations-disabled .cloud-icon {
50 animation: none;
51}
52@keyframes cloud-levitating {
53 50% {
54 transform: translateY(10%) rotate(-3deg);
55 }
56}
57.rain-icon > g > path {
58 animation: rain-translate 2560ms ease-in-out infinite;
59}
60.simple-bar--animations-disabled .rain-icon > g > path {
61 animation: none;
62}
63.rain-icon > g > path:nth-child(2) {
64 animation-delay: 320ms;
65}
66.rain-icon > g > path:nth-child(1) {
67 animation-delay: 640ms;
68}
69@keyframes rain-translate {
70 0% {
71 opacity: 0;
72 transform: translateY(-10%);
73 }
74 50% {
75 opacity: 0.5;
76 }
77 100% {
78 opacity: 0;
79 transform: translateY(10%);
80 }
81}
82.snow-icon > g > path {
83 animation: snow-translate 2560ms ease-in-out infinite;
84}
85.simple-bar--animations-disabled .snow-icon > g > path {
86 animation: none;
87}
88.snow-icon > g > path:nth-child(5) {
89 animation-delay: 320ms;
90}
91.snow-icon > g > path:nth-child(4) {
92 animation-delay: 640ms;
93}
94.snow-icon > g > path:nth-child(3) {
95 animation-delay: 960ms;
96}
97.snow-icon > g > path:nth-child(2) {
98 animation-delay: 1280ms;
99}
100.snow-icon > g > path:nth-child(1) {
101 animation-delay: 1600ms;
102}
103@keyframes phasing-snow {
104 50% {
105 opacity: 0.1;
106 }
107}
108.fog-icon > g > path {
109 animation: fog-phasing 2560ms ease-in-out infinite;
110}
111.simple-bar--animations-disabled .fog-icon > g > path {
112 animation: none;
113}
114.fog-icon > g > path:nth-child(8) {
115 animation-delay: -640ms;
116}
117.fog-icon > g > path:nth-child(7) {
118 animation-delay: -320ms;
119}
120.fog-icon > g > path:nth-child(5) {
121 animation-delay: 320ms;
122}
123.fog-icon > g > path:nth-child(4) {
124 animation-delay: 640ms;
125}
126.fog-icon > g > path:nth-child(3) {
127 animation-delay: 960ms;
128}
129.fog-icon > g > path:nth-child(2) {
130 animation-delay: 1280ms;
131}
132.fog-icon > g > path:nth-child(1) {
133 animation-delay: 1600ms;
134}
135@keyframes fog-phasing {
136 50% {
137 opacity: 0.2;
138 }
139}
140.storm-icon > g > path {
141 animation: flashing-storm 2560ms ease-in-out infinite;
142}
143.simple-bar--animations-disabled .storm-icon > g > path {
144 animation: none;
145}
146.storm-icon > g > path:nth-child(2) {
147 animation-delay: 320ms;
148}
149.storm-icon > g > path:nth-child(1) {
150 animation-delay: 640ms;
151}
152@keyframes flashing-storm {
153 15%,
154 30%,
155 34% {
156 opacity: 1;
157 }
158 16%,
159 31% {
160 opacity: 0;
161 }
162}
163`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/wifi.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/wifi.js
new file mode 100755
index 0000000..8d2cc97
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/wifi.js
@@ -0,0 +1,13 @@
1// Styles for /lib/components/data/wifi.jsx component
2export const wifiStyles = /* css */ `
3.wifi {
4 background-color: var(--red);
5}
6.simple-bar--widgets-background-color-as-foreground .wifi {
7 color: var(--red);
8 background-color: transparent;
9}
10.wifi--hidden-name > svg {
11 margin-right: 0;
12}
13`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/youtube-music.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/youtube-music.js
new file mode 100755
index 0000000..703be21
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/youtube-music.js
@@ -0,0 +1,11 @@
1// Styles for /lib/components/data/youtube-music.jsx component
2export const youtubeMusicStyles = /* css */ `
3.youtube-music {
4 position: relative;
5 background-color: var(--red);
6}
7.simple-bar--widgets-background-color-as-foreground .youtube-music {
8 color: var(--red);
9 background-color: transparent;
10}
11`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/zoom.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/zoom.js
new file mode 100755
index 0000000..55b125c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/data/zoom.js
@@ -0,0 +1,26 @@
1// Styles for /lib/components/data/zoom.jsx component
2export const zoomStyles = /* css */ `
3.zoom {
4 position: relative;
5 display: flex;
6 align-items: center;
7 background-color: var(--minor);
8}
9.simple-bar--widgets-background-color-as-foreground .zoom {
10 color: var(--minor);
11 background-color: transparent;
12}
13.simple-bar--no-color-in-data .zoom {
14 background-color: var(--minor);
15}
16.zoom__icon {
17 width: 14px;
18 height: 14px;
19 fill: var(--red);
20 margin: 0 1px 0 4px;
21 transform: translateZ(0);
22}
23.zoom__icon--on {
24 fill: var(--green);
25}
26`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/missives.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/missives.js
new file mode 100755
index 0000000..18e7b17
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/missives.js
@@ -0,0 +1,89 @@
1// Styles for /lib/components/missives/{missive|missives}.jsx components
2export const missivesStyles = /* css */ `
3.missives {
4 position: absolute;
5 top: 0;
6 left: 0;
7 width: 100%;
8 height: 100%;
9 pointer-events: none;
10 overflow: hidden;
11}
12.missive {
13 --gradient-size: 100px;
14
15 position: absolute;
16 top: 0;
17 width: fit-content;
18 height: 100%;
19 display: flex;
20 align-items: center;
21 gap: 10px;
22 padding: 0 16px;
23 box-sizing: border-box;
24 background-color: var(--background);
25 pointer-events: auto;
26 transition: transform 160ms var(--transition-easing);
27}
28.missive::after {
29 content: "";
30 position: absolute;
31 top: 0;
32 height: 100%;
33 width: var(--gradient-size);
34 pointer-events: none;
35}
36.missive--left {
37 left: 0;
38 animation: left-missive-appearance 320ms var(--transition-easing);
39}
40@keyframes left-missive-appearance {
41 0% {
42 transform: translateX(-100%);
43 }
44}
45.missive--left::after {
46 left: 100%;
47 background: linear-gradient(to right, var(--background) 0%, transparent 100%);
48}
49.missive--right {
50 right: 0;
51 flex-direction: row-reverse;
52 animation: right-missive-appearance 320ms var(--transition-easing);
53}
54@keyframes right-missive-appearance {
55 0% {
56 transform: translateX(100%);
57 }
58}
59.missive--right::after {
60 right: 100%;
61 background: linear-gradient(to left, var(--background) 0%, transparent 100%);
62}
63.missive__text {
64 max-width: calc(100vw - var(--gradient-size));
65 overflow: hidden;
66}
67.missive__close {
68 width: 24px;
69 height: 24px;
70 display: flex;
71 align-items: center;
72 justify-content: center;
73 fill: var(--foreground);
74 background-color: transparent;
75 border: 0;
76 cursor: pointer;
77 user-select: none;
78 border-radius: var(--item-radius);
79 transition: box-shadow 160ms var(--transition-easing);
80}
81.missive__close:hover {
82 box-shadow: var(--light-shadow), var(--hover-ring);
83}
84.missive__close-icon {
85 flex: 0 0 10px;
86 width: 10px;
87 height: 10px;
88}
89`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/process.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/process.js
new file mode 100755
index 0000000..f674ac2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/process.js
@@ -0,0 +1,161 @@
1// Styles for /lib/components/{yabai|aerospace}/process.jsx components
2export const styles = /* css */ `
3.process {
4 display: flex;
5 pointer-events: none;
6 touch-action: none;
7}
8.process--centered {
9 position: absolute;
10 top: 0;
11 left: 0;
12 width: 100%;
13 height: 100%;
14}
15.process:empty {
16 display: none;
17}
18.process__container {
19 display: flex;
20 align-items: stretch;
21 box-sizing: border-box;
22 pointer-events: auto;
23 touch-action: auto;
24}
25.process--centered .process__container {
26 height: var(--bar-height);
27 margin: 0 auto;
28 padding: var(--bar-inner-margin);
29}
30.simple-bar--no-bar-background .process__container:not(:empty) {
31 padding: 4px 5px;
32 background-color: var(--background);
33 box-shadow: var(--light-shadow);
34 border-radius: var(--bar-radius);
35}
36.process__layout {
37 display: flex;
38 align-items: center;
39 padding: var(--item-inner-margin);
40 color: var(--white);
41 font-family: var(--font);
42 font-size: var(--font-size);
43 background-color: var(--main-alt);
44 border-radius: var(--item-radius);
45 box-shadow: var(--light-shadow);
46}
47.simple-bar--spaces-background-color-as-foreground .process__layout {
48 color: var(--foreground);
49 font-weight: 700;
50 background-color: transparent;
51 box-shadow: none;
52}
53.process__skhd-mode {
54 display: flex;
55 align-items: center;
56 padding: var(--item-inner-margin);
57 color: var(--foreground);
58 background-color: var(--minor);
59 font-family: var(--font);
60 font-size: var(--font-size);
61 border-radius: var(--item-radius);
62 box-shadow: var(--light-shadow);
63 font-style: italic;
64 text-transform: uppercase;
65}
66.process__window {
67 display: flex;
68 align-items: center;
69 gap: 3px;
70 margin: var(--item-outer-margin);
71 padding: var(--item-inner-margin);
72 color: currentColor;
73 font-family: var(--font);
74 font-size: var(--font-size);
75 background-color: var(--minor);
76 border-radius: var(--item-radius);
77 border: 0;
78 outline: none;
79 box-shadow: var(--light-shadow);
80 cursor: pointer;
81 user-select: none;
82 -webkit-user-select: none;
83 transition: color 160ms var(--transition-easing), background-color 160ms var(--transition-easing),
84 border 160ms var(--transition-easing), box-shadow 160ms var(--transition-easing);
85 z-index: 0;
86}
87.simple-bar--spaces-background-color-as-foreground .process__window {
88 background-color: transparent;
89 box-shadow: none;
90}
91.simple-bar--no-shadow .process__container,
92.simple-bar--no-bar-background.simple-bar--no-shadow .process__container,
93.simple-bar--no-shadow .process__layout,
94.simple-bar--no-shadow .process__skhd-mode,
95.simple-bar--no-shadow .process__window {
96 box-shadow: none;
97}
98.process__window:only-child {
99 margin: 0;
100}
101.process__window--only-current {
102 background-color: var(--minor);
103}
104.process__window--focused {
105 color: var(--minor);
106 background-color: var(--foreground);
107}
108.process__stack-index {
109 padding: 2px 5px;
110 color: var(--foreground);
111 background-color: var(--background);
112 font-size: calc(var(--font-size) - 1px);
113 border-radius: var(--item-radius);
114}
115.process__window--focused .process__stack-index {
116 color: var(--white);
117 background-color: var(--main-alt);
118}
119.simple-bar--spaces-background-color-as-foreground .process__window--focused {
120 color: var(--foreground);
121 background-color: transparent;
122 box-shadow: var(--light-shadow), 0 0 0 1px var(--foreground);
123}
124.process__window:not(.process__window--only-current):not(.process__window--focused):is(:hover, :active) {
125 box-shadow: var(--light-shadow), var(--hover-ring);
126}
127.process__icon {
128 flex: 0 0 11px;
129 width: 11px;
130 height: 11px;
131 fill: currentColor;
132 transition: margin-right 160ms var(--transition-easing);
133}
134.process__window--only-current .process__icon,
135.process__window--focused .process__icon,
136.process__window--expanded .process__icon {
137 margin-right: 6px;
138}
139.process__window--only-icon .process__icon {
140 margin-right: 0;
141}
142.process__inner {
143 max-width: 0;
144 display: flex;
145 flex-wrap: nowrap;
146 overflow: hidden;
147 transition: max-width 160ms var(--transition-easing);
148}
149.process__window--focused .process__inner,
150.process__window--expanded .process__inner {
151 max-width: var(--item-max-width);
152}
153.process__window--only-current .process__inner {
154 max-width: 400px;
155}
156.process__name {
157 margin-top: 2px;
158 white-space: nowrap;
159 transition: transform 160ms var(--transition-easing);
160}
161`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/aerospace-display-manager.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/aerospace-display-manager.js
new file mode 100755
index 0000000..fb0dba6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/aerospace-display-manager.js
@@ -0,0 +1,101 @@
1export const aerospaceDisplayManagerStyles = /* css */ `
2.aerospace-display-manager {
3 flex: 1 1 100%;
4 position: relative;
5 display: flex;
6 flex-direction: column;
7 gap: 10px;
8 padding: 10px;
9}
10.aerospace-display-manager::before {
11 content: '';
12 position: absolute;
13 top: 0;
14 left: 0;
15 width: 100%;
16 height: 100%;
17 background-color: var(--main-alt);
18 border-radius: var(--item-radius);
19 opacity: 0.1;
20 z-index: -1;
21}
22.aerospace-display-manager__label > em {
23 padding: 2px 3px;
24 font-size: calc(var(--font-size) - 2px);
25 color: var(--foreground);
26 background-color: var(--minor);
27 border-radius: 2px;
28}
29.aerospace-display-manager__displays {
30 display: flex;
31 flex-direction: column;
32 gap: 6px;
33}
34.aerospace-display-manager__display {
35 display: flex;
36 align-items: center;
37 gap: 2px;
38}
39.aerospace-display-manager__display > input {
40 width: 8ch;
41 padding: 2px 4px;
42 box-sizing: border-box;
43 font-family: var(--font);
44 font-size: calc(var(--font-size) * 0.9);
45 background-color: var(--white);
46 border: 0;
47 outline: none;
48 border-radius: 4px;
49 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
50}
51.aerospace-display-manager__display > input:hover {
52 box-shadow: var(--hover-ring);
53}
54.aerospace-display-manager__display > input:focus {
55 box-shadow: var(--focus-ring);
56}
57.aerospace-display-manager__remove-display {
58 padding: 3px 6px;
59 box-sizing: border-box;
60 background-color: var(--red);
61 border-radius: var(--item-radius);
62 border: 0;
63 box-shadow: var(--light-shadow);
64 cursor: pointer;
65 user-select: none;
66 -webkit-user-select: none;
67 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
68}
69.aerospace-display-manager__remove-display:hover {
70 box-shadow: var(--light-shadow), var(--focus-ring);
71}
72.aerospace-display-manager__remove-display > svg {
73 width: 8px;
74 height: 8px;
75 fill: var(--white);
76}
77.aerospace-display-manager__add {
78 width: fit-content;
79 display: flex;
80 align-items: center;
81 padding: 7px 10px;
82 font-family: var(--font);
83 font-size: calc(var(--font-size) * 0.9);
84 background-color: var(--green);
85 border-radius: var(--item-radius);
86 border: 0;
87 box-shadow: var(--light-shadow);
88 cursor: pointer;
89 user-select: none;
90 -webkit-user-select: none;
91 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
92}
93.aerospace-display-manager__add:hover {
94 box-shadow: var(--light-shadow), var(--focus-ring);
95}
96.aerospace-display-manager__add > svg {
97 width: 10px;
98 height: 10px;
99 margin-right: 1ch;
100}
101`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/color-picker.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/color-picker.js
new file mode 100755
index 0000000..4064efd
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/color-picker.js
@@ -0,0 +1,83 @@
1export const colorPickerStyles = /* css */ `
2.color-picker {
3 margin-right: 1ch;
4}
5.color-picker__button {
6 width: 20px;
7 height: 20px;
8 border-radius: 50%;
9 border: 0;
10 cursor: pointer;
11}
12.color-picker__colors {
13 position: absolute;
14 top: 0;
15 left: 0;
16 width: 100%;
17 height: 100%;
18 display: flex;
19 align-items: center;
20 justify-content: center;
21 padding-bottom: 35px;
22 box-sizing: border-box;
23 -webkit-backdrop-filter: blur(5px);
24 border-radius: var(--item-radius);
25 z-index: 1;
26}
27.color-picker__colors > button,
28.color-picker__custom-color-preview {
29 width: 20px;
30 height: 20px;
31 margin: 0 10px;
32 border-radius: 50%;
33 border: 0;
34 cursor: pointer;
35 box-shadow: var(--light-shadow);
36}
37.color-picker__custom-color {
38 position: absolute;
39 bottom: 10px;
40 left: 0;
41 width: 100%;
42 height: 25px;
43 display: flex;
44 align-items: center;
45 justify-content: center;
46 z-index: 2;
47 pointer-events: none;
48 touch-action: none;
49}
50.color-picker__custom-color > * {
51 pointer-events: auto;
52 touch-action: auto;
53}
54.color-picker__custom-color-preview {
55 cursor: default;
56}
57input.color-picker__custom-color-input {
58 width: 48ch;
59}
60.color-picker__custom-color-submit {
61 margin-left: 8px;
62 padding: 7px 10px;
63 font-family: var(--font);
64 font-size: calc(var(--font-size) * 0.9);
65 background-color: var(--green);
66 border-radius: var(--item-radius);
67 border: 0;
68 cursor: pointer;
69 user-select: none;
70 -webkit-user-select: none;
71 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
72}
73.color-picker__custom-color-submit:not(:disabled) {
74 box-shadow: var(--light-shadow);
75}
76.color-picker__custom-color-submit:not(:disabled):hover {
77 box-shadow: var(--light-shadow), var(--focus-ring);
78}
79.color-picker__custom-color-submit:disabled {
80 opacity: 0.5;
81 cursor: not-allowed;
82}
83`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/icon-picker.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/icon-picker.js
new file mode 100755
index 0000000..0c853d5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/icon-picker.js
@@ -0,0 +1,155 @@
1export const iconPickerStyles = /* css */ `
2.icon-picker {
3 margin-right: 1ch;
4}
5.icon-picker__button {
6 width: 50px;
7 height: 50px;
8 display: flex;
9 align-items: center;
10 justify-content: center;
11 fill: var(--foreground);
12 background-color: transparent;
13 border: 0;
14 cursor: pointer;
15 user-select: none;
16}
17.icon-picker__button > svg {
18 width: 24px;
19 height: 24px;
20}
21.icon-picker__dropdown {
22 position: absolute;
23 top: 0;
24 left: 0;
25 width: 100%;
26 height: 100%;
27 display: flex;
28 flex-direction: column;
29 -webkit-backdrop-filter: blur(5px);
30 border-radius: var(--item-radius);
31 overflow: hidden;
32 z-index: 1;
33}
34.icon-picker__search {
35 position: relative;
36 padding: 8px;
37 background-color: var(--main-alt);
38 border-bottom: 1px solid var(--foreground-alt);
39 display: flex;
40 align-items: center;
41 gap: 12px;
42}
43.icon-picker__back {
44 display: flex;
45 align-items: center;
46 padding: 10px 14px;
47 height: 28px;
48 background-color: var(--background);
49 border: 1px solid var(--foreground-alt);
50 border-radius: var(--item-radius);
51 color: var(--foreground);
52 font-family: var(--font);
53 font-size: 13px;
54 font-weight: 500;
55 cursor: pointer;
56 white-space: nowrap;
57 box-sizing: border-box;
58 transition: color 160ms var(--transition-easing),
59 background-color 160ms var(--transition-easing),
60 box-shadow 160ms var(--transition-easing);
61}
62.icon-picker__back:hover {
63 color: var(--background);
64 background-color: var(--foreground);
65 box-shadow: var(--hover-ring);
66}
67.icon-picker__back > svg {
68 width: 10px;
69 height: 10px;
70 margin-right: 6px;
71 fill: currentColor;
72}
73.icon-picker__search-input {
74 flex: 1;
75 height: 28px;
76 padding: 0 35px 0 14px;
77 border: 1px solid var(--foreground-alt);
78 border-radius: var(--item-radius);
79 background-color: var(--background);
80 color: var(--foreground);
81 font-size: 14px;
82 font-family: var(--font);
83 outline: none;
84 box-sizing: border-box;
85 position: relative;
86 transition: border 160ms var(--transition-easing),
87 box-shadow 160ms var(--transition-easing);
88}
89.icon-picker__search-input:focus {
90 border-color: var(--foreground);
91 box-shadow: var(--focus-ring);
92}
93.icon-picker__search-input::placeholder {
94 color: var(--foreground-alt);
95 opacity: 0.7;
96}
97.icon-picker__search-clear {
98 position: absolute;
99 right: 24px;
100 top: 50%;
101 transform: translateY(-50%);
102 background: none;
103 border: none;
104 color: var(--foreground-alt);
105 cursor: pointer;
106 font-size: 16px;
107 padding: 6px;
108 display: flex;
109 align-items: center;
110 justify-content: center;
111 border-radius: 50%;
112 transition: color 160ms var(--transition-easing),
113 background-color 160ms var(--transition-easing);
114}
115.icon-picker__search-clear:hover {
116 color: var(--foreground);
117 background-color: var(--main-alt);
118}
119.icon-picker__icons {
120 flex: 1;
121 display: flex;
122 align-items: flex-start;
123 justify-content: flex-start;
124 flex-wrap: wrap;
125 padding: 10px;
126 box-sizing: border-box;
127 overflow: auto;
128}
129.icon-picker__icons > button {
130 width: 30px;
131 height: 30px;
132 display: flex;
133 align-items: center;
134 justify-content: center;
135 margin: 5px;
136 border: 0;
137 background-color: var(--main-alt);
138 border-radius: var(--item-radius);
139 box-shadow: var(--light-shadow);
140 cursor: pointer;
141 user-select: none;
142}
143.icon-picker__icons > button > svg {
144 width: 24px;
145 height: 24px;
146 fill: var(--background);
147}
148.icon-picker__no-results {
149 width: 100%;
150 text-align: center;
151 color: var(--foreground-alt);
152 font-style: italic;
153 padding: 20px;
154}
155`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/settings.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/settings.js
new file mode 100755
index 0000000..2fa37b0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/settings.js
@@ -0,0 +1,408 @@
1// Styles for /lib/components/settings/settings.jsx component
2import { userWidgetsCreatorStyles } from "./user-widgets-creator";
3import { aerospaceDisplayManagerStyles } from "./aerospace-display-manager";
4
5export const settingsStyles = /* css */ `
6.settings {
7 z-index: 1;
8}
9.settings__overlay {
10 position: fixed;
11 top: 0;
12 left: 0;
13 width: 100%;
14 height: 100%;
15 z-index: 0;
16}
17.simple-bar--floating .settings__overlay,
18.simple-bar--no-bar-background .settings__overlay {
19 display: none;
20}
21.simple-bar--on-bottom .settings__overlay {
22 top: unset;
23 bottom: 28px;
24}
25.settings__outer {
26 --settings-width: 620px;
27 position: fixed;
28 left: calc(50% - (var(--settings-width) / 2));
29 top: calc(var(--bar-height) + 10px);
30 width: var(--settings-width);
31 display: flex;
32 flex-direction: column;
33 align-items: stretch;
34 padding: 20px;
35 background-color: var(--main);
36 border-radius: var(--item-radius);
37 box-shadow: var(--light-shadow);
38 z-index: 1;
39}
40.simple-bar--floating .settings__outer {
41 top: calc(var(--bar-height) + 20px);
42}
43.simple-bar--on-bottom .settings__outer {
44 top: unset;
45 bottom: calc(var(--bar-height) + 10px);
46}
47.settings__header {
48 display: flex;
49 align-items: center;
50 margin-bottom: 14px;
51 font-size: calc(var(--font-size) * 1.4);
52 font-weight: 700;
53}
54.settings__header-dot {
55 flex: 0 0 12px;
56 width: 12px;
57 height: 12px;
58 border-radius: 50%;
59 margin-right: 9px;
60}
61.settings__header-dot--close {
62 padding: 0;
63 background-color: var(--red);
64 cursor: pointer;
65 user-select: none;
66 border: 0;
67 -webkit-user-select: none;
68}
69.settings__header-dot--disabled {
70 background-color: grey;
71 opacity: 0.3;
72}
73.settings__tabs {
74 width: fit-content;
75 display: flex;
76 gap: 10px;
77 margin-bottom: 10px;
78 padding: 5px;
79 background-color: var(--minor);
80 border-radius: var(--item-radius);
81}
82.settings__tab {
83 flex: 0 0 auto;
84 display: flex;
85 align-items: center;
86 padding: 5px;
87 font-family: var(--font);
88 font-size: var(--font-size);
89 color: var(--foreground);
90 text-align: center;
91 background-color: transparent;
92 border-radius: var(--item-radius);
93 border: 0;
94 outline: none;
95 cursor: pointer;
96 user-select: none;
97 -webkit-user-select: none;
98 transition: color 160ms var(--transition-easing), background-color 160ms var(--transition-easing),
99 box-shadow 160ms var(--transition-easing);
100}
101.settings__tab:hover {
102 box-shadow: var(--hover-ring);
103}
104.settings__tab:active {
105 box-shadow: var(--focus-ring);
106}
107.settings__tab--current {
108 color: var(--background);
109 background-color: var(--foreground);
110}
111.settings__inner {
112 display: flex;
113 align-items: flex-start;
114 flex-wrap: nowrap;
115 overflow: clip;
116}
117.settings__category {
118 flex: 0 0 100%;
119 max-height: 70vh;
120 display: flex;
121 flex-wrap: wrap;
122 gap: 6px;
123 padding: 0 10px 25px 0;
124 box-sizing: border-box;
125 overflow: auto;
126 transition: transform 160ms var(--transition-easing);
127}
128.settings__category::-webkit-scrollbar {
129 width: 5px;
130 height: 5px;
131}
132.settings__category::-webkit-scrollbar-track {
133 background-color: var(--main-alt);
134 opacity: 0.1;
135 border-radius: var(--item-radius);
136}
137.settings__category::-webkit-scrollbar-thumb {
138 background: var(--foreground);
139 border-radius: var(--item-radius);
140}
141.settings__inner-title {
142 flex: 0 0 100%;
143 font-size: calc(var(--font-size) * 1.2);
144 font-weight: 700;
145}
146.settings__item-title {
147 flex: 0 0 100%;
148 margin: 8px 0;
149 font-weight: 700;
150}
151.settings__item,
152.settings__item-option {
153 position: relative;
154 flex: 1 0 32%;
155 display: flex;
156 align-items: center;
157 gap: 4px;
158}
159.settings__item--full-width {
160 flex: 1 1 100%;
161}
162.settings__item--color {
163 flex: 0 0 32%;
164 flex-direction: column;
165 align-items: stretch;
166}
167.settings__item--radio {
168 flex: 0 0 100%;
169 display: flex;
170 flex-wrap: wrap;
171}
172.settings__item--textarea {
173 flex-direction: column;
174 align-items: stretch;
175 padding: 5px;
176}
177.settings__item--color > label,
178.settings__item--full-width.settings__item--text > label,
179.settings__item--full-width.settings__item--textarea > label {
180 flex: 0 0 auto;
181 white-space: nowrap;
182}
183.settings__item--text > input,
184.settings__item--textarea > textarea {
185 flex: 1 1 auto;
186 width: auto;
187 padding: 2px 4px;
188 box-sizing: border-box;
189 font-family: var(--font);
190 font-size: calc(var(--font-size) * 0.9);
191 background-color: var(--white);
192 border: 0;
193 outline: none;
194 border-radius: 4px;
195 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
196}
197.settings__item--textarea > textarea {
198 resize: vertical;
199}
200.settings__item--color > input,
201.settings__item--full-width.settings__item--text > input,
202.settings__item--full-width.settings__item--textarea > textarea {
203 flex: 1 1 100%;
204}
205.settings__item--text > input:hover,
206.settings__item--textarea > textarea:hover {
207 box-shadow: var(--hover-ring);
208}
209.settings__item--text > input:focus,
210.settings__item--textarea > textarea:focus {
211 box-shadow: var(--focus-ring);
212}
213.settings__item--color > input {
214 padding-left: 24px;
215}
216.settings__item-color-pill {
217 position: absolute;
218 bottom: 1px;
219 left: 2px;
220 height: 14px;
221 width: 14px;
222 border-radius: 2px;
223 border: 1px solid gray;
224}
225.settings__item > label > em {
226 padding: 2px 3px;
227 font-size: calc(var(--font-size) - 2px);
228 color: var(--foreground);
229 background-color: var(--minor);
230 border-radius: 2px;
231}
232.settings__documentation {
233 width: 100%;
234 margin-top: 5px;
235 padding: 10px;
236 color: var(--white);
237 background-color: var(--main-alt);
238 font-weight: 700;
239 border-radius: 5px;
240}
241.settings__documentation-icon {
242 display: inline-block;
243 width: 18px;
244 height: 18px;
245 margin-right: 8px;
246 margin-top: -2px;
247 vertical-align: middle;
248 fill: currentColor;
249}
250.settings__documentation a {
251 color: currentColor;
252}
253.settings__infos {
254 width: 100%;
255 margin-top: 5px;
256 padding: 10px;
257 color: var(--foreground);
258 background-color: var(--minor);
259 border-radius: 5px;
260}
261.settings__infos-title {
262 margin-bottom: 7px;
263 font-size: calc(var(--font-size) * 1.1);
264 font-weight: 700;
265}
266.settings__info {
267 font-style: italic;
268}
269.settings__bottom {
270 display: flex;
271 align-items: center;
272 justify-content: flex-end;
273 margin-top: 10px;
274}
275.settings__pending-changes {
276 margin: 0 10px;
277}
278.settings__refresh-button,
279.settings__import-button,
280.settings__export-button {
281 padding: 7px 10px;
282 font-family: var(--font);
283 font-size: calc(var(--font-size) * 0.9);
284 border-radius: var(--item-radius);
285 border: 0;
286 cursor: pointer;
287 user-select: none;
288 -webkit-user-select: none;
289 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
290}
291.settings__import-button,
292.settings__export-button {
293 margin-right: 10px;
294 color: var(--foreground);
295 background-color: var(--minor);
296}
297.settings__export-button {
298 margin-left: 10px;
299}
300.settings__refresh-button {
301 background-color: var(--green);
302}
303.settings__refresh-button:not(:disabled),
304.settings__import-button:not(:disabled),
305.settings__export-button:not(:disabled) {
306 box-shadow: var(--light-shadow);
307}
308.settings__refresh-button:not(:disabled):hover,
309.settings__import-button:not(:disabled):hover,
310.settings__export-button:not(:disabled):hover {
311 box-shadow: var(--light-shadow), var(--focus-ring);
312}
313.settings__refresh-button:disabled,
314.settings__import-button:disabled,
315.settings__export-button:disabled {
316 opacity: 0.5;
317 cursor: not-allowed;
318}
319.settings__import-export-label {
320 margin-right: auto;
321}
322.settings__widgets {
323 width: 100%;
324}
325.settings__widgets-breadcrumb {
326 height: 28px;
327 display: flex;
328 align-items: center;
329 gap: 6px;
330 padding: 2px 0 5px;
331 margin-bottom: 5px;
332}
333.settings__widgets-breadcrumb-title {
334 font-size: calc(var(--font-size) * 1.2);
335 font-weight: 700;
336}
337button.settings__widgets-breadcrumb-title {
338 padding: 0;
339 color: inherit;
340 font-family: inherit;
341 background-color: transparent;
342 text-decoration: underline;
343 cursor: pointer;
344 border: 0;
345}
346.settings__widgets-breadcrumb-current {
347 margin-bottom: -2px;
348}
349.settings__widgets-breadcrumb-back {
350 display: flex;
351 align-items: center;
352 margin-left: auto;
353 padding: 2px 10px;
354 background-color: var(--minor);
355 border: 1px solid var(--foreground-alt);
356 border-radius: var(--item-radius);
357 color: var(--foreground);
358 font-family: var(--font);
359 font-size: 13px;
360 font-weight: 500;
361 cursor: pointer;
362 white-space: nowrap;
363 box-sizing: border-box;
364 transition: color 160ms var(--transition-easing),
365 background-color 160ms var(--transition-easing),
366 box-shadow 160ms var(--transition-easing);
367}
368.settings__widgets-breadcrumb-back:hover {
369 box-shadow: var(--hover-ring);
370}
371.settings__widgets-breadcrumb-back-icon {
372 flex: 0 0 8px;
373 width: 8px;
374 height: 8px;
375 margin-right: 6px;
376 fill: currentColor;
377}
378.settings__widgets-list {
379 display: flex;
380 flex-direction: column;
381 gap: 6px;
382}
383.settings__widgets-item {
384 display: flex;
385 align-items: center;
386 gap: 10px;
387 padding: 10px;
388 background-color: var(--minor);
389 border-radius: var(--item-radius);
390}
391.settings__widgets-item:not(.settings__widgets-item--process) {
392 cursor: pointer;
393}
394.settings__widgets-item-icon {
395 flex: 0 0 10px;
396 width: 10px;
397 height: 10px;
398 margin-left: auto;
399 fill: currentcolor;
400}
401.settings__widget-settings {
402 display: flex;
403 flex-wrap: wrap;
404 gap: 6px;
405}
406${userWidgetsCreatorStyles}
407${aerospaceDisplayManagerStyles}
408`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/user-widgets-creator.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/user-widgets-creator.js
new file mode 100755
index 0000000..417826a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/settings/user-widgets-creator.js
@@ -0,0 +1,170 @@
1import { colorPickerStyles } from "./color-picker";
2import { iconPickerStyles } from "./icon-picker";
3
4export const userWidgetsCreatorStyles = /* css */ `
5 .user-widgets-creator {
6 position: relative;
7 width: 100%;
8 display: flex;
9 flex-direction: column;
10 padding-bottom: 25px;
11 border-radius: var(--item-radius);
12 }
13 .user-widgets-creator__add {
14 position: sticky;
15 bottom: 0;
16 display: flex;
17 align-items: center;
18 margin: 0 auto;
19 padding: 7px 10px;
20 font-family: var(--font);
21 font-size: calc(var(--font-size) * 0.9);
22 background-color: var(--green);
23 border-radius: var(--item-radius);
24 border: 0;
25 box-shadow: var(--light-shadow);
26 cursor: pointer;
27 user-select: none;
28 -webkit-user-select: none;
29 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
30 }
31 .user-widgets-creator__add:hover {
32 box-shadow: var(--light-shadow), var(--focus-ring);
33 }
34 .user-widgets-creator__add > svg {
35 width: 10px;
36 height: 10px;
37 margin-right: 1ch;
38 }
39 .user-widget-creator {
40 position: relative;
41 display: flex;
42 align-items: center;
43 margin-bottom: 15px;
44 padding: 5px;
45 z-index: 0;
46 }
47 .user-widget-creator::before {
48 content: '';
49 position: absolute;
50 top: 0;
51 left: 0;
52 width: 100%;
53 height: 100%;
54 background-color: var(--main-alt);
55 border-radius: var(--item-radius);
56 opacity: 0.1;
57 z-index: -1;
58 }
59 .user-widget-creator__sort-buttons {
60 position: absolute;
61 top: 0;
62 left: 17px;
63 height: 100%;
64 display: flex;
65 flex-direction: column;
66 pointer-events: none;
67 touch-action: none;
68 }
69 .user-widget-creator__sort-button {
70 width: 26px;
71 height: 26px;
72 display: flex;
73 align-items: center;
74 justify-content: center;
75 padding: 0;
76 background-color: transparent;
77 border: 0;
78 cursor: pointer;
79 pointer-events: auto;
80 touch-action: auto;
81 }
82 .user-widget-creator__sort-button--before {
83 margin-bottom: 5px;
84 }
85 .user-widget-creator__sort-button--after {
86 margin-top: auto;
87 }
88 .user-widget-creator__sort-button > svg {
89 width: 22px;
90 height: 22px;
91 fill: var(--foreground);
92 }
93 .user-widget-creator__remove {
94 position: absolute;
95 top: 2px;
96 right: 2px;
97 padding: 5px;
98 background-color: var(--red);
99 border-radius: var(--item-radius);
100 border: 0;
101 box-shadow: var(--light-shadow);
102 cursor: pointer;
103 user-select: none;
104 -webkit-user-select: none;
105 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
106 }
107 .user-widget-creator__remove:hover {
108 box-shadow: var(--light-shadow), var(--focus-ring);
109 }
110 .user-widget-creator__remove > svg {
111 width: 10px;
112 height: 10px;
113 fill: var(--white);
114 }
115 .user-widget-creator__index {
116 position: absolute;
117 top: calc(50% - 40px);
118 left: 20px;
119 }
120 .user-widget-creator__right {
121 flex: 1 1 100%;
122 display: flex;
123 flex-direction: column;
124 }
125 .user-widget-creator__right-top {
126 display: flex;
127 align-items: center;
128 }
129 .user-widget-creator__right-top > label {
130 margin: 0 1ch 0 2ch;
131 }
132 .user-widget-creator__input-group {
133 display: flex;
134 align-items: center;
135 margin: 2px 0;
136 }
137 .user-widget-creator input[type="text"] {
138 width: auto;
139 margin: 3px 0;
140 padding: 2px 4px;
141 box-sizing: border-box;
142 font-family: var(--font);
143 font-size: calc(var(--font-size) * 0.9);
144 border: 0;
145 outline: none;
146 border-radius: 4px;
147 transition: box-shadow 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
148 }
149 .user-widget-creator input[type="text"]:hover {
150 box-shadow: var(--hover-ring);
151 }
152 .user-widget-creator input[type="text"]:focus {
153 box-shadow: var(--focus-ring);
154 }
155 .user-widget-creator__input-group label {
156 white-space: nowrap;
157 }
158 .user-widget-creator__input-group input[type="text"] {
159 flex: 1 1 100%;
160 margin-left: 1ch;
161 }
162 .user-widget-creator__input-group input[type="checkbox"]:not(:first-child) {
163 margin-left: 16px;
164 }
165 .user-widget-creator__input-group input[type="checkbox"] {
166 margin-right: 6px;
167 }
168 ${colorPickerStyles}
169 ${iconPickerStyles}
170`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/side-icon.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/side-icon.js
new file mode 100755
index 0000000..9d4535d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/side-icon.js
@@ -0,0 +1,15 @@
1// Styles for /lib/components/side-icon.jsx component
2export const sideIconStyles = /* css */ `
3.side-icon {
4 display: flex;
5 align-items: center;
6 margin: 0 5px;
7 color: #fff;
8}
9
10.side-icon__svg {
11 width: 14px;
12 height: 14px;
13 fill: currentColor;
14}
15`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space-options.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space-options.js
new file mode 100755
index 0000000..1f43895
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space-options.js
@@ -0,0 +1,137 @@
1export const spaceOptionsStyles = /* css */ `
2.space-options {
3 position: absolute;
4 top: calc(100% + 3px);
5 left: calc(50% - 22px);
6 height: 90%;
7 width: 50px;
8 height: 18px;
9 display: flex;
10 align-items: stretch;
11 background-color: var(--white);
12 opacity: 0;
13 pointer-events: none;
14 touch-action: none;
15 border-radius: 3px;
16 box-shadow: var(--light-shadow);
17 transform-origin: top center;
18 transform: translateZ(0) scale(0);
19 transition: opacity 160ms var(--transition-easing), transform 160ms var(--transition-easing);
20 z-index: 1;
21}
22.simple-bar--on-bottom .space-options {
23 top: unset;
24 bottom: calc(100% + 3px);
25 transform-origin: bottom center;
26}
27.simple-bar--inline-spaces-options .space-options {
28 height: 100%;
29 top: 0;
30 left: 100%;
31 border-radius: 3px;
32 transform-origin: center;
33}
34.space--hovered .space-options {
35 opacity: 1;
36 transform: translateZ(0);
37 pointer-events: auto;
38 touch-action: auto;
39 transition: opacity 160ms 1s var(--transition-easing), transform 160ms 1s var(--transition-easing);
40}
41.space--hovered.space--no-delay .space-options {
42 transition: opacity 160ms var(--transition-easing), transform 160ms var(--transition-easing);
43}
44.space-options::before {
45 content: "";
46 position: absolute;
47 bottom: 100%;
48 left: 0;
49 width: 100%;
50 height: 3px;
51 z-index: 2;
52}
53.space-options::after {
54 content: '';
55 position: absolute;
56 top: -3px;
57 left: calc(50% - 4px);
58 width: 0;
59 height: 0;
60 border-left: 4px solid transparent;
61 border-right: 4px solid transparent;
62 border-bottom: 3px solid var(--white);
63}
64.simple-bar--on-bottom .space-options::after {
65 top: unset;
66 bottom: -3px;
67 border-left: 4px solid transparent;
68 border-right: 4px solid transparent;
69 border-top: 3px solid var(--white);
70 border-bottom: none;
71}
72.simple-bar--inline-spaces-options .space-options::after {
73 top: calc(50% - 4px);
74 left: -3px;
75 border-top: 4px solid transparent;
76 border-bottom: 4px solid transparent;
77 border-right: 3px solid var(--white);
78 border-left: none;
79}
80.space-options__option {
81 position: relative;
82 flex: 1 1 100%;
83 display: flex;
84 align-items: center;
85 justify-content: center;
86 cursor: pointer;
87 user-select: none;
88 -webkit-user-select: none;
89 transform: translateZ(0);
90 transition: background-color 160ms var(--transition-easing), opacity 160ms var(--transition-easing);
91}
92.space-options__option:last-child {
93 opacity: 0.8;
94 background-color: var(--red);
95}
96.space--fullscreen .space-options__option:last-child,
97.space:first-of-type:only-of-type .space-options__option:last-child,
98.space:first-of-type:nth-last-of-type(2) .space-options__option:last-child {
99 pointer-events: none;
100 touch-action: none;
101 opacity: 0.5;
102 filter: grayscale(100%);
103}
104.space:first-of-type .space-options__option--move-prev,
105.space:nth-last-of-type(1) .space-options__option--move-next,
106.space:first-of-type:only-of-type .space-options__option--move-prev,
107.space:first-of-type:only-of-type .space-options__option--move-next,
108.space:first-of-type:nth-last-of-type(1) .space-options__option--move-prev,
109.space:first-of-type:nth-last-of-type(1) .space-options__option--move-next {
110 opacity: 0.2;
111 pointer-events: none;
112 touch-action: none;
113}
114.space .space-options__option:first-of-type {
115 border-radius: 3px 0 0 3px;
116}
117.space-options__option:last-of-type {
118 border-radius: 0 3px 3px 0;
119}
120.space-options__option:not(:last-child):hover {
121 background-color: var(--transparent-dark);
122}
123.space-options__option:last-child:hover {
124 opacity: 1;
125}
126.space-options__option > svg {
127 width: 8px;
128 height: 8px;
129 fill: var(--black);
130 curor: pointer;
131 user-select: none;
132 -webkit-user-select: none;
133}
134.space-options__option:last-child > svg {
135 fill: var(--white);
136}
137`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space.js
new file mode 100755
index 0000000..0e6d1cb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/space.js
@@ -0,0 +1,152 @@
1export const spaceStyles = /* css */ `
2.space, .stickies {
3 position: relative;
4 display: flex;
5 align-items: center;
6 animation: space-appearance 320ms var(--transition-easing);
7}
8
9@keyframes space-appearance {
10 0% {
11 opacity: 0;
12 }
13}
14.space__inner,
15.spaces__add,
16.stickies__inner {
17 height: 100%;
18 display: flex;
19 align-items: center;
20 margin: var(--item-outer-margin);
21 padding: var(--item-inner-margin);
22 color: currentColor;
23 font-family: var(--font);
24 background-color: var(--minor);
25 border-radius: var(--item-radius);
26 border: 0;
27 outline: none;
28 box-shadow: var(--light-shadow);
29 cursor: pointer;
30 user-select: none;
31 -webkit-user-select: none;
32 transition: color 160ms var(--transition-easing), background-color 160ms var(--transition-easing),
33 border 160ms var(--transition-easing), box-shadow 160ms var(--transition-easing);
34 z-index: 0;
35}
36.space__inner:disabled {
37 cursor: default;
38}
39.stickies__inner {
40 padding-block: 0;
41 background-color: var(--background);
42 box-shadow: none;
43 cursor: default;
44}
45.simple-bar--spaces-background-color-as-foreground .space__inner,
46.simple-bar--spaces-background-color-as-foreground .spaces__add,
47.simple-bar--spaces-background-color-as-foreground .stickies__inner {
48 background-color: transparent;
49 box-shadow: none;
50}
51.simple-bar--no-shadow .space__inner,
52.simple-bar--no-shadow .spaces__add,
53.simple-bar--no-shadow .stickies__inner {
54 box-shadow: none;
55}
56.space:first-of-type .space__inner {
57 margin-left: 0;
58}
59.space:hover .space__inner {
60 z-index: 1;
61}
62.spaces__add {
63 height: auto;
64 background-color: transparent;
65 box-shadow: none;
66}
67.spaces__add:hover {
68 background-color: var(--minor);
69}
70.space--fullscreen .space__inner {
71 color: var(--minor);
72 background-color: var(--yellow);
73}
74.simple-bar--spaces-background-color-as-foreground .space--fullscreen .space__inner {
75 color: var(--yellow);
76 background-color: transparent;
77}
78.space--focused .space__inner {
79 color: var(--minor);
80 background-color: var(--foreground);
81}
82.simple-bar--spaces-background-color-as-foreground .space--focused .space__inner {
83 color: var(--foreground);
84 background-color: transparent;
85}
86.space--visible .space__inner {
87 box-shadow: var(--light-shadow), var(--foreground-shadow);
88}
89.simple-bar--no-shadow .space--visible .space__inner {
90 box-shadow: none;
91}
92.space:not(.space--focused) .space__inner:not(:disabled):hover,
93.spaces__add:hover {
94 box-shadow: var(--light-shadow), var(--hover-ring);
95}
96.space:not(.space--focused) .space__inner:not(:disabled):active,
97.spaces__add:active {
98 box-shadow: var(--light-shadow), var(--focus-ring);
99}
100.simple-bar--no-shadow .space:not(.space--focused) .space__inner:not(:disabled):hover,
101.simple-bar--no-shadow .spaces__add:hover {
102 box-shadow: var(--hover-ring);
103}
104.simple-bar--no-shadow .space:not(.space--focused) .space__inner:not(:disabled):active,
105.simple-bar--no-shadow .spaces__add:active {
106box-shadow: var(--focus-ring);
107}
108.space__label {
109 display: block;
110 margin: 0;
111 color: currentColor;
112 font-family: inherit;
113 font-size: var(--font-size);
114 line-height: 1;
115 text-align: center;
116 background-color: transparent;
117 border: 0;
118 border-radius: 2px;
119 outline: none;
120}
121.space__label:not(:read-only):focus {
122 box-shadow: var(--focus-ring);
123}
124.simple-bar--spaces-background-color-as-foreground .space--focused .space__label {
125 font-weight: 700;
126}
127.space__icon {
128 flex: 0 0 11px;
129 width: 11px;
130 height: 11px;
131 margin-left: 6px;
132 fill: currentColor;
133 opacity: 0.5;
134 transform: translateZ(0);
135}
136.stickies__inner .space__icon:first-child {
137 margin: 0;
138}
139.space__icon--focused {
140 opacity: 1;
141}
142.space__icon--fullscreen {
143 fill: var(--yellow);
144}
145.space__icon--topmost {
146 fill: var(--orange);
147}
148.space--focused .space__icon--fullscreen {
149 stroke: rgba(0, 0, 0, 0.3);
150 stroke-width: 2px;
151}
152`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/spaces.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/spaces.js
new file mode 100755
index 0000000..8657b9c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/components/spaces/spaces.js
@@ -0,0 +1,50 @@
1// Styles for /lib/components/{yabai|aerospace}/*.jsx components
2import { spaceStyles } from "./space";
3import { spaceOptionsStyles } from "./space-options";
4
5export const styles = /* css */ `
6.spaces {
7 flex: 0 0 auto;
8 display: flex;
9 align-items: stretch;
10}
11.simple-bar--no-bar-background .spaces {
12 padding: 4px 5px;
13 background-color: var(--background);
14 box-shadow: var(--light-shadow);
15 border-radius: var(--bar-radius);
16}
17.simple-bar--no-bar-background.simple-bar--no-shadow .spaces {
18 box-shadow: none;
19}
20.simple-bar--process-aligned-to-left .spaces {
21 margin-right: 4px;
22}
23.spaces__separator {
24 align-self: center;
25 flex: 0 0 5px;
26 width: 5px;
27 height: 5px;
28 margin: var(--item-outer-margin);
29 background-color: var(--foreground);
30 border-radius: 50%;
31 opacity: 0.35;
32}
33${spaceStyles}
34${spaceOptionsStyles}
35.spaces__add > svg {
36 width: 10px;
37 height: 10px;
38 fill: currentColor;
39}
40.spaces__end-separator {
41 align-self: center;
42 flex: 0 0 4px;
43 width: 4px;
44 height: 4px;
45 margin: var(--item-outer-margin);
46 background-color: var(--main-alt);
47 border-radius: 50%;
48 opacity: 0.35;
49}
50`;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/base.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/base.js
new file mode 100755
index 0000000..041c848
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/base.js
@@ -0,0 +1,120 @@
1// simple-bar' global styles
2const baseStyles = /* css */ `
3.simple-bar {
4 position: fixed;
5 top: 0;
6 left: 0;
7 width: 100%;
8 z-index: 0;
9 height: var(--bar-height);
10 display: flex;
11 align-items: stretch;
12 padding: var(--bar-inner-margin);
13 box-sizing: border-box;
14 color: var(--foreground);
15 font-size: var(--font-size);
16 font-family: var(--font);
17 background-color: var(--background);
18 border: var(--bar-border);
19 box-shadow: var(--light-shadow);
20}
21@media only screen and (-webkit-min-device-pixel-ratio: 2),
22 only screen and (min-device-pixel-ratio: 2),
23 only screen and (min-resolution: 192dpi),
24 only screen and (min-resolution: 2dppx) {
25 .simple-bar {
26 -webkit-font-smoothing: antialiased;
27 }
28}
29.simple-bar--floating {
30 top: var(--bar-outer-margin, 5px);
31 left: var(--bar-outer-margin, 5px);
32 width: calc(100% - (var(--bar-outer-margin, 5px) * 2));
33 border-radius: var(--bar-radius);
34}
35.simple-bar--no-bar-background {
36 padding: 0;
37}
38.simple-bar--on-bottom {
39 top: unset;
40 bottom: 0;
41}
42.simple-bar--floating.simple-bar--on-bottom {
43 bottom: var(--bar-outer-margin, 5px);
44}
45.simple-bar--no-bar-background,
46.simple-bar--no-shadow {
47 box-shadow: none;
48}
49.simple-bar--focused,
50.simple-bar--no-shadow.simple-bar--focused {
51 box-shadow: inset 0 0 0 1px var(--red);
52}
53.simple-bar--no-bar-background {
54 background-color: transparent;
55}
56.simple-bar--empty {
57 height: var(--bar-height);
58 display: flex;
59 align-items: center;
60}
61.simple-bar--empty {
62 z-index: 2;
63}
64.simple-bar--empty > span {
65 position: relative;
66 display: flex;
67 align-items: center;
68 color: var(--foreground);
69}
70.simple-bar--empty > span::before {
71 content: "";
72 width: 6px;
73 height: 6px;
74 margin-right: 7px;
75 background-color: var(--red);
76 border-radius: 50%;
77}
78.simple-bar--empty.simple-bar--loading > span::before {
79 background-color: var(--green);
80}
81.simple-bar__data {
82 position: relative;
83 display: flex;
84 align-items: stretch;
85 margin-left: auto;
86}
87.simple-bar__data:empty {
88 display: none;
89}
90.simple-bar--no-color-in-data .simple-bar__data {
91 color: var(--white);
92}
93.simple-bar--no-bar-background .simple-bar__data {
94 padding: 4px 5px 4px 0;
95 background-color: var(--background);
96 box-shadow: var(--light-shadow);
97 border-radius: var(--bar-radius);
98}
99.simple-bar--no-bar-background.simple-bar--no-shadow .simple-bar__data {
100 box-shadow: none;
101}
102.simple-bar-icon-loader {
103 flex: 0 0 10px;
104 width: 10px;
105 height: 10px;
106 margin-right: 7px;
107 background-color: currentColor;
108 border-radius: 50%;
109}
110#simple-bar-click-effect {
111 position: absolute;
112 border-radius: 50%;
113 pointer-events: none;
114 touch-action: none;
115 background-color: var(--click-effect);
116 z-index: 2147483647;
117}
118`;
119
120export { baseStyles as styles };
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/variables.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/variables.js
new file mode 100755
index 0000000..19a7aad
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/core/variables.js
@@ -0,0 +1,107 @@
1import * as Theme from "../theme";
2import * as Settings from "../../settings";
3
4/**
5 * Generates CSS variables based on the provided theme scheme.
6 *
7 * @param {string} scheme - The theme scheme to use for generating CSS variables.
8 * @returns {string} The generated CSS variables as a string.
9 */
10const themedVariables = (scheme) => {
11 const settings = Settings.get();
12 const { themes } = settings;
13 const {
14 colorMain,
15 colorMainAlt,
16 colorMinor,
17 colorAccent,
18 colorRed,
19 colorGreen,
20 colorYellow,
21 colorOrange,
22 colorBlue,
23 colorMagenta,
24 colorCyan,
25 colorBlack,
26 colorWhite,
27 colorForeground,
28 colorBackground,
29 } = themes;
30 const { widgetMaxWidth, compactMode, font, fontSize } = settings.global;
31
32 return /* css */ `
33:root {
34 --main: ${colorMain?.trim() || Theme.colors(themes)[scheme].main};
35 --main-alt: ${colorMainAlt?.trim() || Theme.colors(themes)[scheme].mainAlt};
36 --minor: ${colorMinor?.trim() || Theme.colors(themes)[scheme].minor};
37 --accent: ${colorAccent?.trim() || Theme.colors(themes)[scheme].yellow};
38 --red: ${colorRed?.trim() || Theme.colors(themes)[scheme].red};
39 --green: ${colorGreen?.trim() || Theme.colors(themes)[scheme].green};
40 --yellow: ${colorYellow?.trim() || Theme.colors(themes)[scheme].yellow};
41 --orange: ${colorOrange?.trim() || Theme.colors(themes)[scheme].orange};
42 --blue: ${colorBlue?.trim() || Theme.colors(themes)[scheme].blue};
43 --magenta: ${colorMagenta?.trim() || Theme.colors(themes)[scheme].magenta};
44 --cyan: ${colorCyan?.trim() || Theme.colors(themes)[scheme].cyan};
45 --black: ${colorBlack?.trim() || Theme.colors(themes)[scheme].black};
46 --white: ${colorWhite?.trim() || Theme.colors(themes)[scheme].white};
47 --foreground: ${
48 colorForeground?.trim() || Theme.colors(themes)[scheme].foreground
49 };
50 --background: ${colorBackground?.trim() || Theme.colors(themes)[scheme].main};
51 --transparent-dark: ${Theme.colors(themes)[scheme].transparentDark};
52 --font: ${font?.trim() || Theme.colors(themes)[scheme].defaultFont};
53 --font-size: ${fontSize.trim().length ? fontSize : "11px"};
54 --bar-height: ${
55 compactMode
56 ? Theme.colors(themes)[scheme].compactBarHeight
57 : Theme.colors(themes)[scheme].barHeight
58 };
59 --bar-radius: ${Theme.colors(themes)[scheme].barRadius};
60 --bar-border: ${Theme.colors(themes)[scheme].barBorder};
61 --bar-inner-margin: ${Theme.colors(themes)[scheme].barInnerMargin};
62 --item-max-width: ${widgetMaxWidth.trim().length ? widgetMaxWidth : "160px"};
63 --item-radius: ${Theme.colors(themes)[scheme].itemRadius};
64 --item-inner-margin: ${Theme.colors(themes)[scheme].itemInnerMargin};
65 --item-outer-margin: ${Theme.colors(themes)[scheme].itemOuterMargin};
66 --hover-ring: ${Theme.colors(themes)[scheme].hoverRing};
67 --focus-ring: ${Theme.colors(themes)[scheme].focusRing};
68 --light-shadow: ${Theme.colors(themes)[scheme].lightShadow};
69 --foreground-shadow: ${
70 Theme.colors(themes)[scheme].foregroundShadow
71 ? Theme.colors(themes)[scheme].foregroundShadow
72 : "0 0 0 1px var(--foreground)"
73 };
74 --transition-easing: ${Theme.colors(themes)[scheme].transitionEasing};
75 --click-effect: ${Theme.colors(themes)[scheme].clickEffect};
76}
77`;
78};
79
80const darkVariables = themedVariables("dark");
81const lightVariables = themedVariables("light");
82
83/**
84 * Builds CSS variables based on the user's theme settings.
85 *
86 * @returns {string} The CSS variables for the selected theme.
87 */
88const buildVariables = () => {
89 const settings = Settings.get();
90 const { theme } = settings.global;
91 if (theme === "auto") {
92 return /* css */ `
93 @media (prefers-color-scheme: light) {
94 ${lightVariables}
95 }
96 @media (prefers-color-scheme: dark) {
97 ${darkVariables}
98 }
99 `;
100 }
101 if (theme === "light") {
102 return lightVariables;
103 }
104 return darkVariables;
105};
106
107export const styles = buildVariables();
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-colors.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-colors.js
new file mode 100755
index 0000000..88b7d43
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-colors.js
@@ -0,0 +1,15 @@
1import * as Pywal from "./pywal";
2
3export const colors = {
4 main: Pywal.variables.background,
5 mainAlt: Pywal.variables.function,
6 minor: Pywal.variables.function,
7 accent: Pywal.variables.result,
8 red: Pywal.variables.operator,
9 green: Pywal.variables.result,
10 yellow: Pywal.variables.cursor,
11 orange: Pywal.variables.scrollbar,
12 blue: Pywal.variables.matched,
13 magenta: Pywal.variables.variable,
14 cyan: Pywal.variables.function,
15};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-from-desktop.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-from-desktop.sh
new file mode 100755
index 0000000..cd99142
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-from-desktop.sh
@@ -0,0 +1,9 @@
1#! /usr/bin/env bash
2
3wal -n -s -i $(sqlite3 -readonly ~/Library/Application\ Support/Dock/desktoppicture.db 'SELECT * FROM data ORDER BY rowID DESC LIMIT 1;' | sed -e "s|~|$HOME|g")
4
5{
6 echo -n 'export const variables = '
7 cat "$HOME/.cache/wal/colors-speedcrunch.json"
8 echo ';'
9} > pywal.js
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-gen.sh b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-gen.sh
new file mode 100755
index 0000000..7cbc8ee
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal-gen.sh
@@ -0,0 +1,7 @@
1#! /usr/bin/env bash
2
3{
4 echo -n 'export const variables = '
5 cat "$HOME/.cache/wal/colors-speedcrunch.json"
6 echo ';'
7} > pywal.js
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal.js
new file mode 100755
index 0000000..3ce4a64
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/pywal/pywal.js
@@ -0,0 +1,15 @@
1export const variables = {
2 cursor: "#d1dbe0",
3 number: "#d1dbe0",
4 parens: "#BFC3B9",
5 result: "#94A4A8",
6 comment: "#92999c",
7 matched: "#94A4A8",
8 function: "#376089",
9 operator: "#708C9F",
10 variable: "#507495",
11 scrollbar: "#708C9F",
12 separator: "#708C9F",
13 background: "#0a0e0d",
14 editorbackground: "#0a0e0d",
15};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/theme.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/theme.js
new file mode 100755
index 0000000..51985a5
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/theme.js
@@ -0,0 +1,21 @@
1import * as Themes from "./themes";
2import * as Pywal from "./pywal/pywal-colors";
3
4const WITH_PYWAL = false;
5
6const overrideColors = WITH_PYWAL ? Pywal.colors : {};
7
8/**
9 * Generates color themes by merging the specified themes with override colors.
10 *
11 * @param {Object} themes - An object containing the light and dark theme names.
12 * @param {string} themes.lightTheme - The name of the light theme.
13 * @param {string} themes.darkTheme - The name of the dark theme.
14 * @returns {Object} An object containing the light and dark color themes.
15 */
16export function colors(themes) {
17 return {
18 light: { ...Themes.collection[themes.lightTheme], ...overrideColors },
19 dark: { ...Themes.collection[themes.darkTheme], ...overrideColors },
20 };
21}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes.js
new file mode 100755
index 0000000..ff5a24c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes.js
@@ -0,0 +1,72 @@
1import * as NightShiftDark from "./themes/night-shift-dark";
2import * as NightShiftLight from "./themes/night-shift-light";
3import * as MacOSDark from "./themes/mac-os-dark";
4import * as MacOSLight from "./themes/mac-os-light";
5import * as OneDark from "./themes/one-dark";
6import * as OneLight from "./themes/one-light";
7import * as GruvboxDark from "./themes/gruvbox-dark";
8import * as GruvboxLight from "./themes/gruvbox-light";
9import * as GruvboxMaterial from "./themes/gruvbox-material";
10import * as Dracula from "./themes/dracula";
11import * as Nord from "./themes/nord";
12import * as Amarena from "./themes/amarena";
13import * as SolarizedLight from "./themes/solarized-light";
14import * as SolarizedDark from "./themes/solarized-dark";
15import * as Cisco from "./themes/cisco";
16import * as Sylens from "./themes/sylens";
17import * as SpaceDuck from "./themes/spaceduck";
18import * as MidsummerNightDark from "./themes/midsummer-night-dark";
19import * as CatppuccinOld from "./themes/catppuccin";
20import * as CatppuccinLatte from "./themes/catppuccin-latte.js";
21import * as CatppuccinFrappe from "./themes/catppuccin-frappe.js";
22import * as CatppuccinMacchiato from "./themes/catppuccin-macchiato.js";
23import * as CatppuccinMocha from "./themes/catppuccin-mocha.js";
24import * as TokyoNight from "./themes/tokyo-night";
25import * as MaterialOcean from "./themes/material-ocean";
26import * as NightOwl from "./themes/night-owl";
27import * as NightfoxDark from "./themes/nightfox-dark";
28import * as NightfoxLight from "./themes/nightfox-light";
29import * as VscodeDarkModern from "./themes/vscode-dark-modern";
30import * as RosePine from "./themes/rose-pine";
31import * as RosePineMoon from "./themes/rose-pine-moon";
32import * as RosePineDawn from "./themes/rose-pine-dawn";
33import * as CyberdreamLight from "./themes/cyberdream-light.js";
34import * as CyberdreamDark from "./themes/cyberdream-dark.js";
35
36// Entire collection of themes available in simple-bar
37export const collection = {
38 NightShiftDark: NightShiftDark.theme,
39 NightShiftLight: NightShiftLight.theme,
40 MacOSDark: MacOSDark.theme,
41 MacOSLight: MacOSLight.theme,
42 OneDark: OneDark.theme,
43 OneLight: OneLight.theme,
44 GruvboxDark: GruvboxDark.theme,
45 GruvboxLight: GruvboxLight.theme,
46 GruvboxMaterial: GruvboxMaterial.theme,
47 Dracula: Dracula.theme,
48 Nord: Nord.theme,
49 Amarena: Amarena.theme,
50 SolarizedLight: SolarizedLight.theme,
51 SolarizedDark: SolarizedDark.theme,
52 Cisco: Cisco.theme,
53 Sylens: Sylens.theme,
54 SpaceDuck: SpaceDuck.theme,
55 MidsummerNightDark: MidsummerNightDark.theme,
56 Catppuccin: CatppuccinOld.theme,
57 CatppuccinLatte: CatppuccinLatte.theme,
58 CatppuccinFrappe: CatppuccinFrappe.theme,
59 CatppuccinMacchiato: CatppuccinMacchiato.theme,
60 CatppuccinMocha: CatppuccinMocha.theme,
61 TokyoNight: TokyoNight.theme,
62 MaterialOcean: MaterialOcean.theme,
63 NightOwl: NightOwl.theme,
64 NightfoxDark: NightfoxDark.theme,
65 NightfoxLight: NightfoxLight.theme,
66 VscodeDarkModern: VscodeDarkModern.theme,
67 RosePine: RosePine.theme,
68 RosePineMoon: RosePineMoon.theme,
69 RosePineDawn: RosePineDawn.theme,
70 CyberdreamLight: CyberdreamLight.theme,
71 CyberdreamDark: CyberdreamDark.theme,
72};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/amarena.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/amarena.js
new file mode 100755
index 0000000..91561c1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/amarena.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Amarena",
3 kind: "dark",
4 main: "#1a2026",
5 mainAlt: "#526170",
6 minor: "#242d35",
7 red: "#f26190",
8 green: "#fb6396",
9 yellow: "#f92d72",
10 orange: "#c269bc",
11 blue: "#4cb9d6",
12 magenta: "#58d6bf",
13 cyan: "#6ccb6e",
14 black: "#1a2026",
15 white: "#f4f5f2",
16 foreground: "#f4f5f2",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "MesloLGS NF, JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "3px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 4px",
27 hoverRing: "0 0 0 1px rgba(249, 45, 114, 0.75)",
28 focusRing: "0 0 0 1px rgb(249, 45, 114)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-frappe.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-frappe.js
new file mode 100755
index 0000000..7f6ab49
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-frappe.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Catppuccin Frappe",
3 kind: "dark",
4 main: "#303446", // Base
5 mainAlt: "#292c3c", // Mantle
6 minor: "#232634", // Crust
7 red: "#e78284", // Red
8 green: "#a6d189", // Green
9 yellow: "#e5c890", // Yellow
10 orange: "#ef9f76", // Peach
11 blue: "#8caaee", // Blue
12 magenta: "#ca9ee6", // Mauve
13 cyan: "#99d1db", // Sky
14 black: "#303446", // Base
15 white: "#c6d0f5", // Text
16 foreground: "#c6d0f5", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-latte.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-latte.js
new file mode 100755
index 0000000..dd53fec
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-latte.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Catppuccin Latte",
3 kind: "light",
4 main: "#eff1f5", // Base
5 mainAlt: "#e6e9ef", // Mantle
6 minor: "#dce0e8", // Crust
7 red: "#d20f39", // Red
8 green: "#40a02b", // Green
9 yellow: "#df8e1d", // Yellow
10 orange: "#fe640b", // Peach
11 blue: "#1e66f5", // Blue
12 magenta: "#8839ef", // Mauve
13 cyan: "#04a5e5", // Sky
14 black: "#4c4f69", // Text
15 white: "#eff1f5", // Base
16 foreground: "#4c4f69", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-macchiato.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-macchiato.js
new file mode 100755
index 0000000..f1db514
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-macchiato.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Catppuccin Macchiato",
3 kind: "dark",
4 main: "#24273a", // Base
5 mainAlt: "#1e2030", // Mantle
6 minor: "#181926", // Crust
7 red: "#ed8796", // Red
8 green: "#a6da95", // Green
9 yellow: "#eed49f", // Yellow
10 orange: "#f5a97f", // Peach
11 blue: "#8aadf4", // Blue
12 magenta: "#c6a0f6", // Mauve
13 cyan: "#91d7e3", // Sky
14 black: "#24273a", // Base
15 white: "#cad3f5", // Text
16 foreground: "#cad3f5", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-mocha.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-mocha.js
new file mode 100755
index 0000000..64b1cc2
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin-mocha.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Catppuccin Mocha",
3 kind: "dark",
4 main: "#1e1e2e", // Base
5 mainAlt: "#181825", // Mantle
6 minor: "#11111b", // Crust
7 red: "#f38ba8", // Red
8 green: "#a6e3a1", // Green
9 yellow: "#f9e2af", // Yellow
10 orange: "#fab387", // Peach
11 blue: "#89b4fa", // Blue
12 magenta: "#cba6f7", // Mauve
13 cyan: "#89dceb", // Sky
14 black: "#1e1e2e", // Base
15 white: "#cdd6f4", // Text
16 foreground: "#cdd6f4", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin.js
new file mode 100755
index 0000000..2ac8520
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/catppuccin.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Catppuccin (old)",
3 kind: "dark",
4 main: "#1E1E2E",
5 mainAlt: "#302D41",
6 minor: "#575268",
7 red: "#F28FAD",
8 green: "#ABE9B3",
9 yellow: "#FAE3B0",
10 orange: "#F8BD96",
11 blue: "#96CDFB",
12 magenta: "#DDB6F2",
13 cyan: "#89DCEB",
14 black: "#161320",
15 white: "#D9E0EE",
16 foreground: "#D9E0EE",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cisco.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cisco.js
new file mode 100755
index 0000000..a4d84f3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cisco.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Cisco",
3 kind: "dark",
4 main: "#282a36",
5 mainAlt: "#8E2F91",
6 minor: "#543185",
7 red: "#8E2F91",
8 green: "#8E2F91",
9 yellow: "#BE3161",
10 orange: "#008CD1",
11 blue: "#6E5BC2",
12 magenta: "#8E2F91",
13 cyan: "#CC60CB",
14 black: "#292a2b",
15 white: "#f5f5f5",
16 foreground: "#9E70B5",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-dark.js
new file mode 100755
index 0000000..a192d37
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Cyberdream Dark",
3 kind: "dark",
4 main: "rgba(22, 24, 26, 0.6)", // Base - with 40% transparency
5 mainAlt: "rgba(30, 33, 36, 0.6)", // Mantle - with 40% transparency
6 minor: "rgba(60, 64, 72, 0.6)", // Crust - with 40% transparency
7 red: "#ff6e5e", // Red
8 green: "#5eff6c", // Neon Green
9 yellow: "#f1ff5e", // Yellow
10 orange: "#ffbd5e", // Orange
11 blue: "#5ea1ff", // Blue
12 magenta: "#ff5ef1", // Magenta
13 cyan: "#5ef1ff", // Cyan
14 black: "#16181a", // Base
15 white: "#ffffff", // Text
16 foreground: "#ffffff", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-light.js
new file mode 100755
index 0000000..4403ec4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/cyberdream-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Cyberdream Light",
3 kind: "light",
4 main: "rgba(255, 255, 255, 0.6)", // Base - with 40% transparency
5 mainAlt: "rgba(234, 234, 234, 0.6)", // Mantle - with 40% transparency
6 minor: "rgba(172, 172, 172, 0.6)", // Crust - with 40% transparency
7 red: "#d11500", // Red
8 green: "#008b0c", // Green
9 yellow: "#997b00", // Bronze
10 orange: "#d17c00", // Orange
11 blue: "#0057d1", // Indigo
12 magenta: "#d100bf", // Magenta
13 cyan: "#008c99", // Aqua
14 black: "#16181a", // Text
15 white: "#ffffff", // Base
16 foreground: "#16181a", // Text
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/dracula.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/dracula.js
new file mode 100755
index 0000000..8eb6b28
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/dracula.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Dracula",
3 kind: "dark",
4 main: "#282a36",
5 mainAlt: "#ff79c6",
6 minor: "#44475a",
7 red: "#ff5555",
8 green: "#50fa7b",
9 yellow: "#f1fa8c",
10 orange: "#ffb86c",
11 blue: "#bd93f9",
12 magenta: "#ff79c6",
13 cyan: "#8be9fd",
14 black: "#282a36",
15 white: "#f8f8f2",
16 foreground: "#f8f8f2",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-dark.js
new file mode 100755
index 0000000..e61884c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Gruvbox Dark",
3 kind: "dark",
4 main: "#282828",
5 mainAlt: "#ff0000",
6 minor: "#3c3836",
7 red: "#cc241d",
8 green: "#98971a",
9 yellow: "#d79921",
10 orange: "#d65d0e",
11 blue: "#458588",
12 magenta: "#b16286",
13 cyan: "#689d6a",
14 black: "#282828",
15 white: "#ebdbb2",
16 foreground: "#ebdbb2",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-light.js
new file mode 100755
index 0000000..153a38d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Gruvbox Light",
3 kind: "light",
4 main: "#fbf1c7",
5 mainAlt: "#7c6f64",
6 minor: "#ebdbb2",
7 red: "#cc241d",
8 green: "#98971a",
9 yellow: "#d79921",
10 orange: "#d65d0e",
11 blue: "#458588",
12 magenta: "#b16286",
13 cyan: "#689d6a",
14 black: "#fbf1c7",
15 white: "#3c3836",
16 foreground: "#3c3836",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-material.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-material.js
new file mode 100755
index 0000000..1de9fff
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/gruvbox-material.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Gruvbox Material",
3 kind: "dark",
4 main: "#282828",
5 mainAlt: "#ea6962",
6 minor: "#32302f",
7 red: "#ea6962",
8 green: "#a9b665",
9 yellow: "#e3a84e",
10 orange: "#e78a4e",
11 blue: "#7daea3",
12 magenta: "#d3869b",
13 cyan: "#89b482",
14 black: "#282828",
15 white: "#928374",
16 foreground: "#dfbf8e",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "8px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "6px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-dark.js
new file mode 100755
index 0000000..f658960
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Mac OS Dark",
3 kind: "dark",
4 main: "#292a2b",
5 mainAlt: "#5f5f60",
6 minor: "#3c3d3e",
7 red: "#ee5f5c",
8 green: "#77b756",
9 yellow: "#f8c644",
10 orange: "#ca8739",
11 blue: "#2b7bf7",
12 magenta: "#9b57a2",
13 cyan: "#e65d9c",
14 black: "#292a2b",
15 white: "#f5f5f5",
16 foreground: "#fff",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "14px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-light.js
new file mode 100755
index 0000000..61229f9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/mac-os-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Mac OS Light",
3 kind: "light",
4 main: "#ececed",
5 mainAlt: "#5f5f60",
6 minor: "#fff",
7 red: "#ee5f5c",
8 green: "#77b756",
9 yellow: "#f8c644",
10 orange: "#ca8739",
11 blue: "#2b7bf7",
12 magenta: "#9b57a2",
13 cyan: "#e65d9c",
14 black: "#292a2b",
15 white: "#f5f5f5",
16 foreground: "#292a2b",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "14px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/material-ocean.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/material-ocean.js
new file mode 100755
index 0000000..ad521b1
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/material-ocean.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Material Theme - Ocean",
3 kind: "dark",
4 main: "rgb(15, 17, 26)",
5 mainAlt: "#0F111A",
6 minor: "#3c3d3e",
7 red: "#f07178",
8 green: "#C3E88D",
9 yellow: "#FFCB6B",
10 orange: "#F78C6C",
11 blue: "#82AAFF",
12 magenta: "#C792EA",
13 cyan: "#89DDFF",
14 black: "#000000",
15 white: "#ffffff",
16 foreground: "#A6ACCD",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "Roboto Mono, monospace",
19 barHeight: "30px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "14px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/midsummer-night-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/midsummer-night-dark.js
new file mode 100755
index 0000000..d5358e4
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/midsummer-night-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Midsummer Night Dark",
3 kind: "dark",
4 main: "#1c1e27",
5 mainAlt: "#212831",
6 minor: "#212831",
7 red: "#e43d6a",
8 green: "#0af29d",
9 yellow: "#eea585",
10 orange: "#e88376",
11 blue: "#56c2ea",
12 magenta: "#b468d0",
13 cyan: "#00ccbb",
14 black: "#1b222d",
15 white: "#fff",
16 foreground: "#fff",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-owl.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-owl.js
new file mode 100755
index 0000000..b883b9c
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-owl.js
@@ -0,0 +1,33 @@
1export const theme = {
2 name: "NightOwl",
3 kind: "dark",
4 main: "#011627",
5 mainAlt: "#0b253a",
6 minor: "#084d8180",
7 red: "#ef5350",
8 green: "#22da6e",
9 yellow: "#FFCA28",
10 orange: "#F78C6C",
11 blue: "#82AAFF",
12 magenta: "#C792EA",
13 cyan: "#7fdbca",
14 black: "#011627",
15 white: "#ffffff",
16 foreground: "#d2dee7",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(214, 222, 235, 0.5)",
28 focusRing: "0 0 0 2px rgb(214, 222, 235, 0.2)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 foregroundShadow: "0 0 0 rgba(0, 0, 0, 0)",
31 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
32 clickEffect: "rgba(214, 222, 235, 0.3)",
33};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-dark.js
new file mode 100755
index 0000000..dd3e3b3
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Night Shift Dark",
3 kind: "dark",
4 main: "#1b222d",
5 mainAlt: "#98a8c5",
6 minor: "#39465e",
7 red: "#e78482",
8 green: "#8fc8BB",
9 yellow: "#ffd484",
10 orange: "#ffb374",
11 blue: "#6db3cE",
12 magenta: "#ad82cB",
13 cyan: "#7eddde",
14 black: "#1b222d",
15 white: "#fff",
16 foreground: "#fff",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "6px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "5px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-light.js
new file mode 100755
index 0000000..92e7038
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/night-shift-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Night Shift Light",
3 kind: "light",
4 main: "#fff",
5 mainAlt: "#98a8c5",
6 minor: "#f5f5f5",
7 red: "#e78482",
8 green: "#8fc8bb",
9 yellow: "#d1ab66",
10 orange: "#ffb374",
11 blue: "#6db3ce",
12 magenta: "#ad82cb",
13 cyan: "#2fc2c3",
14 black: "#1b222d",
15 white: "#f5f5f5",
16 foreground: "#1b222d",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "6px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "5px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-dark.js
new file mode 100755
index 0000000..0e8fd6a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Nightfox Dark",
3 kind: "dark",
4 main: "#192330",
5 mainAlt: "#131a24",
6 minor: "#29394f",
7 red: "#c94f6d",
8 green: "#81b29a",
9 yellow: "#dbc074",
10 orange: "#f4a261",
11 blue: "#719cd6",
12 magenta: "#9d79d6",
13 cyan: "#63cdcf",
14 black: "#192330",
15 white: "#dfdfe0",
16 foreground: "#cdcecf",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "7px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "5px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(205, 206, 207, 0.75)",
28 focusRing: "0 0 0 2px rgb(205, 206, 207)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(214, 222, 235, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-light.js
new file mode 100755
index 0000000..72d885f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nightfox-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Nightfox Light",
3 kind: "light",
4 main: "#f6f2ee",
5 mainAlt: "#e4dcd4",
6 minor: "#d3c7bb",
7 red: "#a5222f",
8 green: "#396847",
9 yellow: "#AC5402",
10 orange: "#955f61",
11 blue: "#2848a9",
12 magenta: "#6e33ce",
13 cyan: "#287980",
14 black: "#352c24",
15 white: "#f2e9e1",
16 foreground: "#3d2b5a",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "7px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "5px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(61, 43, 90, 0.75)",
28 focusRing: "0 0 0 2px rgb(61, 43, 90)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(214, 222, 235, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nord.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nord.js
new file mode 100755
index 0000000..0bdf1a7
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/nord.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Nord",
3 kind: "dark",
4 main: "#3b4252",
5 mainAlt: "#eceef4",
6 minor: "#4c566a",
7 red: "#bf616a",
8 green: "#a3be8c",
9 yellow: "#ebcb8b",
10 orange: "#d08770",
11 blue: "#81a1c1",
12 magenta: "#b48ead",
13 cyan: "#88c0d0",
14 black: "#2e3440",
15 white: "#eceff4",
16 foreground: "#d8dee9",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "Source Code Pro",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "14px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-dark.js
new file mode 100755
index 0000000..e73da4f
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "One Dark",
3 kind: "dark",
4 main: "#21252b",
5 mainAlt: "#e6e6e6",
6 minor: "#323842",
7 red: "#e05561",
8 green: "#8cc265",
9 yellow: "#d18f52",
10 orange: "#ffb374",
11 blue: "#6db3ce",
12 magenta: "#c162de",
13 cyan: "#42b3c2",
14 black: "#21252b",
15 white: "#fff",
16 foreground: "#abb2bf",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "20px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-light.js
new file mode 100755
index 0000000..64fbb4a
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/one-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "One Light",
3 kind: "light",
4 main: "#f5f5f5",
5 mainAlt: "#21252b",
6 minor: "#fff",
7 red: "#e05561",
8 green: "#8cc265",
9 yellow: "#d18f52",
10 orange: "#FFB374",
11 blue: "#6DB3CE",
12 magenta: "#c162de",
13 cyan: "#42b3c2",
14 black: "#21252b",
15 white: "#fff",
16 foreground: "#21252b",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "20px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-dawn.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-dawn.js
new file mode 100755
index 0000000..50b6b49
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-dawn.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Rosé Pine Dawn",
3 kind: "light",
4 main: "#faf4ed",
5 mainAlt: "#fffaf3",
6 minor: "#f2e9e1",
7 red: "#b4637a",
8 green: "#286983",
9 yellow: "#ea9d34",
10 orange: "#d7827e",
11 blue: "#56949f",
12 magenta: "#907aa9",
13 cyan: "#d7827e",
14 black: "#575279",
15 white: "#faf4ed",
16 foreground: "#575279",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-moon.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-moon.js
new file mode 100755
index 0000000..d0d3e2b
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine-moon.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Rosé Pine Moon",
3 kind: "dark",
4 main: "#232136",
5 mainAlt: "#2a273f",
6 minor: "#393552",
7 red: "#eb6f92",
8 green: "#3e8fb0",
9 yellow: "#f6c177",
10 orange: "#ea9a97",
11 blue: "#9ccfd8",
12 magenta: "#c4a7e7",
13 cyan: "#ea9a97",
14 black: "#232136",
15 white: "#e0def4",
16 foreground: "#e0def4",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine.js
new file mode 100755
index 0000000..1c20f58
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/rose-pine.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Rosé Pine",
3 kind: "dark",
4 main: "#191724",
5 mainAlt: "#1f1d2e",
6 minor: "#26233a",
7 red: "#eb6f92",
8 green: "#31748f",
9 yellow: "#f6c177",
10 orange: "#ebbcba",
11 blue: "#9ccfd8",
12 magenta: "#c4a7e7",
13 cyan: "#ebbcba",
14 black: "#191724",
15 white: "#e0def4",
16 foreground: "#e0def4",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-dark.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-dark.js
new file mode 100755
index 0000000..1beef76
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-dark.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Solarized Dark",
3 kind: "dark",
4 main: "#002b36",
5 mainAlt: "#002b36",
6 minor: "#073642",
7 red: "#dc322f",
8 green: "#859900",
9 yellow: "#b58900",
10 orange: "#cb4b16",
11 blue: "#0087ff",
12 magenta: "#d33682",
13 cyan: "#2aa198",
14 black: "#262626",
15 white: "#e4e4e4",
16 foreground: "#93a1a1",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "20px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-light.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-light.js
new file mode 100755
index 0000000..b90aa81
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/solarized-light.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Solarized Light",
3 kind: "light",
4 main: "#fdf6e3",
5 mainAlt: "#fdf6e3",
6 minor: "#eee8d5",
7 red: "#dc322f",
8 green: "#859900",
9 yellow: "#b58900",
10 orange: "#cb4b16",
11 blue: "#0087ff",
12 magenta: "#d33682",
13 cyan: "#2aa198",
14 black: "#262626",
15 white: "#e4e4e4",
16 foreground: "#657b83",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "16px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "20px",
25 itemInnerMargin: "3px 9px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
28 focusRing: "0 0 0 2px rgba(152, 168, 198, 0.5)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(0, 0, 0, 0.15)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/spaceduck.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/spaceduck.js
new file mode 100755
index 0000000..45d4ca9
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/spaceduck.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "SpaceDuck",
3 kind: "dark",
4 main: "#0f111b",
5 mainAlt: "#b3a1e6",
6 minor: "#1b1c36",
7 red: "#e33400",
8 green: "#5ccc96",
9 yellow: "#f2ce00",
10 orange: "#e39400",
11 blue: "#686f9a",
12 magenta: "#ce6f8f",
13 cyan: "#00a3cc",
14 black: "#000000",
15 white: "#FFF",
16 foreground: "#ecf0c1",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "5px",
24 itemRadius: "3px",
25 itemInnerMargin: "5px 10px",
26 itemOuterMargin: "0 0 0 4px",
27 hoverRing: "0 0 0 2px rgba(92, 204, 150, 0.75)",
28 focusRing: "0 0 0 2px rgb(92, 204, 150)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 0)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/sylens.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/sylens.js
new file mode 100755
index 0000000..1d3f8ec
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/sylens.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Sylens",
3 kind: "dark",
4 main: "#1B2229",
5 mainAlt: "#7d5a15",
6 minor: "#1b2229",
7 red: "#7d5a15",
8 green: "#BF6832",
9 yellow: "#d65d0e",
10 orange: "#475090",
11 blue: "#33736A",
12 magenta: "#814b42",
13 cyan: "#346a97",
14 black: "#a77822",
15 white: "#1b2229",
16 foreground: "#a77822",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "MonoLisa",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "2px",
25 itemInnerMargin: "3px 7px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(167, 120, 34, 0.75)",
28 focusRing: "0 0 0 2px rgb(167, 120, 34)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(167, 120, 34, H0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/tokyo-night.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/tokyo-night.js
new file mode 100755
index 0000000..9982420
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/tokyo-night.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Tokyo Night",
3 kind: "dark",
4 main: "#15161E",
5 mainAlt: "#302D41",
6 minor: "#15161E",
7 red: "#F7768E",
8 green: "#9ECE6A",
9 yellow: "#E0AF68",
10 orange: "#F8BD96",
11 blue: "#7AA2F7",
12 magenta: "#BB9AF7",
13 cyan: "#7DCFFF",
14 black: "#15161E",
15 white: "#A9B1D6",
16 foreground: "#A9B1D6",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "9px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "0px",
24 itemRadius: "5px",
25 itemInnerMargin: "0px 9px",
26 itemOuterMargin: "0 0 0 4px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/vscode-dark-modern.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/vscode-dark-modern.js
new file mode 100755
index 0000000..d997e77
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/styles/themes/vscode-dark-modern.js
@@ -0,0 +1,32 @@
1export const theme = {
2 name: "Vscode Dark Modern",
3 kind: "dark",
4 main: "#181818",
5 mainAlt: "#1f1f1f",
6 minor: "#2a2a2a",
7 red: "#e78482",
8 green: "#4ec6ae",
9 yellow: "#dcdcaa",
10 orange: "#ffb374",
11 blue: "#4fc1ff",
12 magenta: "#c586c0",
13 cyan: "#9cdcfe",
14 black: "#181818",
15 white: "#fff",
16 foreground: "#fff",
17 transparentDark: "rgba(0, 0, 0, 0.05)",
18 defaultFont: "JetBrains Mono, Monaco, Menlo, monospace",
19 barHeight: "34px",
20 compactBarHeight: "28px",
21 barRadius: "3px",
22 barBorder: "0px solid transparent",
23 barInnerMargin: "3px",
24 itemRadius: "7px",
25 itemInnerMargin: "2px 6px",
26 itemOuterMargin: "0 0 0 5px",
27 hoverRing: "0 0 0 2px rgba(255, 255, 255, 0.75)",
28 focusRing: "0 0 0 2px rgb(255, 255, 255)",
29 lightShadow: "0 5px 10px rgba(0, 0, 0, 0.24)",
30 transitionEasing: "cubic-bezier(0.4, 0, 0.2, 1)",
31 clickEffect: "rgba(255, 255, 255, 0.3)",
32};
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/utils.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/utils.js
new file mode 100755
index 0000000..f9d0460
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/utils.js
@@ -0,0 +1,828 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "./settings";
3
4/**
5 * Parses a JSON string and returns the corresponding JavaScript object.
6 * Cleans up JSON that contains escape sequences, such as `\\` or `\"`.
7 *
8 * @param {string} json - The JSON string to parse.
9 * @returns {Object|undefined} The parsed JavaScript object, or undefined if parsing fails.
10 */
11export function parseJson(json) {
12 try {
13 // clean up JSON with escape sequences, (i.e.)
14 // empty arrays: [,] -> []
15 // escape sequences: \\" -> "
16 let cleanedJson = json
17 .replace(/\[,+/g, "[")
18 .replace(/,+\]/g, "]")
19 .replace(/,+,/g, ",")
20 .replace(/\[,/g, "[")
21 .replace(/,\]/g, "]")
22 .replace(/\\/g, "\\\\")
23 .replace(/\\"/g, '"');
24 return JSON.parse(cleanedJson);
25 } catch (error) {
26 // eslint-disable-next-line no-console
27 console.error(error, json);
28 return undefined;
29 }
30}
31
32/*!
33 Copyright (c) 2017 Jed Watson.
34 Licensed under the MIT License (MIT), see
35 http://jedwatson.github.io/classnames
36*/
37const hasOwn = {}.hasOwnProperty;
38
39/**
40 * Combines multiple class names into a single string.
41 *
42 * @param {...(string|boolean|undefined|null)} arguments - The class names to combine.
43 * Each argument can be a string, boolean, undefined, or null. Only truthy values will be included.
44 * @returns {string} The combined class names.
45 */
46export function classNames() {
47 let classes = "";
48
49 for (let i = 0; i < arguments.length; i++) {
50 const arg = arguments[i];
51 if (arg) {
52 classes = appendClass(classes, parseValue(arg));
53 }
54 }
55
56 return classes;
57}
58
59function parseValue(arg) {
60 if (typeof arg === "string" || typeof arg === "number") {
61 return arg;
62 }
63 if (typeof arg !== "object") {
64 return "";
65 }
66 if (Array.isArray(arg)) {
67 return classNames.apply(null, arg);
68 }
69 if (
70 arg.toString !== Object.prototype.toString &&
71 !arg.toString.toString().includes("[native code]")
72 ) {
73 return arg.toString();
74 }
75
76 let classes = "";
77 for (let key in arg) {
78 if (hasOwn.call(arg, key) && arg[key]) {
79 classes = appendClass(classes, key);
80 }
81 }
82 return classes;
83}
84
85function appendClass(value, newClass) {
86 if (!newClass) {
87 return value;
88 }
89 if (value) {
90 return value + " " + newClass;
91 }
92 return value + newClass;
93}
94/*!
95 End of Jed Watson's classNames
96*/
97
98const WIDTH = 20;
99const DURATION = 320;
100
101const CACHE_PREFIX = "sb_cmd_";
102const CACHE_CLEANUP_INTERVAL = 300000; // Clean up every 5 minutes
103let _lastCleanup = 0;
104
105/**
106 * Simple string hash for generating cache keys from command strings.
107 * @param {string} str - The string to hash.
108 * @returns {string} A base-36 hash string.
109 */
110function hashString(str) {
111 let hash = 0;
112 for (let i = 0; i < str.length; i++) {
113 const char = str.charCodeAt(i);
114 hash = (hash << 5) - hash + char;
115 hash |= 0;
116 }
117 return Math.abs(hash).toString(36);
118}
119
120/**
121 * Removes expired cache entries from localStorage to prevent unbounded growth.
122 * Uses a conservative 60-second grace period beyond the longest widget refresh.
123 */
124function cleanupExpiredCache() {
125 const now = Date.now();
126 if (now - _lastCleanup < CACHE_CLEANUP_INTERVAL) return;
127 _lastCleanup = now;
128
129 try {
130 const keysToRemove = [];
131 for (let i = 0; i < localStorage.length; i++) {
132 const key = localStorage.key(i);
133 if (key && key.startsWith(CACHE_PREFIX)) {
134 try {
135 const cached = localStorage.getItem(key);
136 if (cached) {
137 const parsed = JSON.parse(cached);
138 // Remove if older than 60 seconds (well beyond any widget refresh)
139 if (now - parsed.t > 60000) {
140 keysToRemove.push(key);
141 }
142 }
143 } catch {
144 // Remove malformed entries
145 keysToRemove.push(key);
146 }
147 }
148 }
149 keysToRemove.forEach((key) => localStorage.removeItem(key));
150 } catch {
151 // Ignore cleanup errors
152 }
153}
154
155/**
156 * Runs a shell command via Uebersicht.run() with cross-display caching.
157 *
158 * In multi-display setups, each display runs its own simple-bar instance.
159 * System-wide data (CPU, memory, battery, etc.) is identical across displays,
160 * so this function uses localStorage (shared across all Übersicht WebViews)
161 * to cache command results and prevent redundant execution.
162 *
163 * Expired cache entries are automatically cleaned up every 5 minutes.
164 *
165 * @param {string} command - The shell command to execute.
166 * @param {number} cacheTimeout - How long (ms) the cached result remains valid.
167 * Typically set to the widget's refresh frequency so that within one refresh
168 * cycle, only one display actually executes the command.
169 * @returns {Promise<string>} The command output (from cache or fresh execution).
170 */
171export async function cachedRun(command, cacheTimeout) {
172 if (!cacheTimeout || cacheTimeout <= 0) {
173 return Uebersicht.run(command);
174 }
175
176 cleanupExpiredCache();
177
178 const cacheKey = CACHE_PREFIX + hashString(command);
179 const now = Date.now();
180
181 try {
182 const cached = localStorage.getItem(cacheKey);
183 if (cached) {
184 const parsed = JSON.parse(cached);
185 if (now - parsed.t < cacheTimeout) {
186 return parsed.r;
187 }
188 }
189 } catch {
190 // Ignore cache read errors
191 }
192
193 const result = await Uebersicht.run(command);
194 try {
195 localStorage.setItem(cacheKey, JSON.stringify({ r: result, t: now }));
196 } catch {
197 // Ignore cache write errors (e.g., storage full)
198 }
199 return result;
200}
201
202/**
203 * Creates a click effect animation at the location of the mouse click event.
204 *
205 * @param {MouseEvent} e - The mouse event object containing the click coordinates.
206 */
207export function clickEffect(e) {
208 const { body } = document;
209 const { clientX, clientY } = e;
210 const cursor = Object.assign(document.createElement("div"), {
211 id: "simple-bar-click-effect",
212 });
213 Object.assign(cursor.style, {
214 top: `${clientY - WIDTH / 2}px`,
215 left: `${clientX - WIDTH / 2}px`,
216 width: `${WIDTH}px`,
217 height: `${WIDTH}px`,
218 transition: `transform ${DURATION} ease`,
219 });
220 if (cursor && "animate" in cursor) {
221 body.appendChild(cursor);
222 cursor.animate(
223 [
224 { opacity: 0, transform: "scale(0)" },
225 { opacity: 1, transform: "scale(2)" },
226 { opacity: 0, transform: "scale(1.6)" },
227 ],
228 { duration: DURATION },
229 );
230 }
231 setTimeout(() => cursor && body.removeChild(cursor), DURATION);
232}
233
234function isObject(item) {
235 return item && typeof item === "object" && !Array.isArray(item);
236}
237
238/**
239 * Deeply merges multiple source objects into a target object.
240 *
241 * @param {Object} target - The target object to merge properties into.
242 * @param {...Object} sources - One or more source objects to merge properties from.
243 * @returns {Object} - The target object after merging.
244 */
245export function mergeDeep(target, ...sources) {
246 if (!sources.length) return target;
247 const source = sources.shift();
248 if (isObject(target) && isObject(source)) {
249 for (const key in source) {
250 if (isObject(source[key])) {
251 if (!target[key]) Object.assign(target, { [key]: {} });
252 mergeDeep(target[key], source[key]);
253 } else {
254 Object.assign(target, { [key]: source[key] });
255 }
256 }
257 }
258 return mergeDeep(target, ...sources);
259}
260
261/*!
262 * (c) 2019 Chris Ferdinandi & Jascha Brinkmann, MIT License, https://gomakethings.com & https://twitter.com/jaschaio
263 */
264/**
265 * Compares two objects and returns the differences.
266 *
267 * @param {Object} obj1 - The first object to compare.
268 * @param {Object} obj2 - The second object to compare.
269 * @returns {Object} An object containing the differences between obj1 and obj2.
270 *
271 * @example
272 * const obj1 = { a: 1, b: 2, c: 3 };
273 * const obj2 = { a: 1, b: 4, d: 5 };
274 * const diffs = compareObjects(obj1, obj2);
275 * // diffs = { b: 4, c: null, d: 5 }
276 */
277export function compareObjects(obj1, obj2) {
278 if (!obj2 || Object.prototype.toString.call(obj2) !== "[object Object]") {
279 return obj1;
280 }
281 const diffs = {};
282 let key;
283 const arraysMatch = (arr1, arr2) => {
284 if (arr1.length !== arr2.length) return false;
285 for (let i = 0; i < arr1.length; i++) {
286 if (arr1[i] !== arr2[i]) return false;
287 }
288 return true;
289 };
290 const compare = (item1, item2, key) => {
291 const type1 = Object.prototype.toString.call(item1);
292 const type2 = Object.prototype.toString.call(item2);
293 if (type2 === "[object Undefined]") {
294 diffs[key] = null;
295 return;
296 }
297 if (type1 !== type2) {
298 diffs[key] = item2;
299 return;
300 }
301 if (type1 === "[object Object]") {
302 const objDiff = compareObjects(item1, item2);
303 if (Object.keys(objDiff).length > 0) {
304 diffs[key] = objDiff;
305 }
306 return;
307 }
308 if (type1 === "[object Array]") {
309 if (!arraysMatch(item1, item2)) {
310 diffs[key] = item2;
311 }
312 return;
313 }
314 if (type1 === "[object Function]") {
315 if (item1.toString() !== item2.toString()) {
316 diffs[key] = item2;
317 }
318 } else {
319 if (item1 !== item2) {
320 diffs[key] = item2;
321 }
322 }
323 };
324 for (key in obj1) {
325 if (Object.prototype.hasOwnProperty.call(obj1, key)) {
326 compare(obj1[key], obj2[key], key);
327 }
328 }
329 for (key in obj2) {
330 if (Object.prototype.hasOwnProperty.call(obj2, key)) {
331 if (!obj1[key] && obj1[key] !== obj2[key]) {
332 diffs[key] = obj2[key];
333 }
334 }
335 }
336 return diffs;
337}
338
339/**
340 * Filters applications based on provided exclusions and title exclusions.
341 *
342 * @param {Object} app - The application object to be filtered.
343 * @param {Array<string>} exclusions - List of application names to be excluded.
344 * @param {Array<string>} titleExclusions - List of application titles to be excluded.
345 * @param {boolean} exclusionsAsRegex - Flag indicating if exclusions should be treated as regular expressions.
346 * @returns {boolean} - Returns true if the application should be included, false otherwise.
347 */
348export function filterApps(
349 app,
350 exclusions,
351 titleExclusions,
352 exclusionsAsRegex,
353) {
354 const fullscreen = app.isNativeFullscreen ?? app.__legacyIsNativeFullscreen;
355 const appName = app.app || app["app-name"];
356 const appTitle = app.title || app["window-title"];
357
358 const isAppNameExcluded = exclusionsAsRegex
359 ? exclusions.length !== 0 && new RegExp(exclusions).test(appName)
360 : exclusions.includes(appName);
361
362 const isAppTitleExcluded = exclusionsAsRegex
363 ? titleExclusions.length !== 0 && new RegExp(titleExclusions).test(appTitle)
364 : titleExclusions.includes(appTitle);
365
366 return (
367 fullscreen ||
368 (!isAppNameExcluded && !appTitle?.length) ||
369 (!isAppNameExcluded && !isAppTitleExcluded)
370 );
371}
372
373export function isSpaceExcluded(id, exclusions /*list*/, exclusionsAsRegex) {
374 const isSpaceNameExcluded = exclusionsAsRegex
375 ? exclusions.some(
376 (rx) =>
377 rx.length !== 0 &&
378 (rx instanceof RegExp ? rx : new RegExp(rx)).test(id),
379 )
380 : exclusions.includes(id);
381
382 return exclusions && isSpaceNameExcluded;
383}
384
385/**
386 * Filters and categorizes windows into sticky and non-sticky based on various criteria.
387 *
388 * @param {Object} params - The parameters for the function.
389 * @param {Array} params.windows - The list of windows to filter.
390 * @param {boolean} params.uniqueApps - Whether to treat apps as unique.
391 * @param {number} params.currentDisplay - The current display identifier.
392 * @param {number} params.currentSpace - The current space identifier.
393 * @param {Array} params.exclusions - The list of app names to exclude.
394 * @param {Array} params.titleExclusions - The list of window titles to exclude.
395 * @param {boolean} params.exclusionsAsRegex - Whether exclusions are regex patterns.
396 * @returns {Object} An object containing two arrays: `nonStickyWindows` and `stickyWindows`.
397 */
398export function stickyWindowWorkaround({
399 windows = [],
400 uniqueApps,
401 currentDisplay,
402 currentSpace,
403 exclusions,
404 titleExclusions,
405 exclusionsAsRegex,
406}) {
407 const stickySet = new Set();
408 const stickyWindows = windows.filter((app) => {
409 const {
410 "is-sticky": isSticky,
411 sticky: __legacyIsSticky,
412 "is-native-fullscreen": isNativeFullscreen,
413 "native-fullscreen": __legacyIsNativeFullscreen,
414 display,
415 app: appName,
416 id,
417 } = app;
418 return (
419 (isSticky ?? __legacyIsSticky) &&
420 !(isNativeFullscreen ?? __legacyIsNativeFullscreen) &&
421 display === currentDisplay &&
422 filterApps(app, exclusions, titleExclusions, exclusionsAsRegex) &&
423 !stickySet.has(uniqueApps ? appName : id) &&
424 stickySet.add(uniqueApps ? appName : id)
425 );
426 });
427 const nonStickySet = new Set();
428 const nonStickyWindows = windows.filter((app) => {
429 const {
430 "is-sticky": isSticky,
431 sticky: __legacyIsSticky,
432 "is-native-fullscreen": isNativeFullscreen,
433 "native-fullscreen": __legacyIsNativeFullscreen,
434 space,
435 app: appName,
436 id,
437 } = app;
438 return (
439 (!(isSticky ?? __legacyIsSticky) ||
440 (isNativeFullscreen ?? __legacyIsNativeFullscreen)) &&
441 space === currentSpace &&
442 filterApps(app, exclusions, titleExclusions, exclusionsAsRegex) &&
443 !nonStickySet.has(uniqueApps ? appName : id) &&
444 nonStickySet.add(uniqueApps ? appName : id)
445 );
446 });
447 return { nonStickyWindows, stickyWindows };
448}
449
450/**
451 * Sorts an array of window objects based on their frame coordinates and stack index.
452 *
453 * The sorting priority is as follows:
454 * 1. `frame.x` - Windows are sorted by their x-coordinate.
455 * 2. `frame.y` - If x-coordinates are equal, windows are sorted by their y-coordinate.
456 * 3. `stack-index` - If both x and y coordinates are equal, windows are sorted by their stack index.
457 * 4. `id` - If all previous criteria are equal, windows are sorted by their id.
458 *
459 * @param {Array} windows - The array of window objects to be sorted.
460 * @param {Object} windows[].frame - The frame object containing x and y coordinates.
461 * @param {number} windows[].frame.x - The x-coordinate of the window.
462 * @param {number} windows[].frame.y - The y-coordinate of the window.
463 * @param {number} windows[].stack-index - The stack index of the window.
464 * @param {number} windows[].id - The unique identifier of the window.
465 * @returns {Array} The sorted array of window objects.
466 */
467export function sortWindows(windows) {
468 return windows.sort((a, b) => {
469 if (a.frame.x !== b.frame.x) {
470 return a.frame.x > b.frame.x;
471 }
472 if (a.frame.y !== b.frame.y) {
473 return a.frame.y > b.frame.y;
474 }
475 if (a["stack-index"] !== b["stack-index"]) {
476 return a["stack-index"] > b["stack-index"];
477 }
478 return a.id > b.id;
479 });
480}
481
482/**
483 * Softly refreshes the Uebersicht widget with the specified ID.
484 *
485 * This function runs an AppleScript command to refresh the widget with the ID "simple-bar-index-jsx"
486 * in the Uebersicht application.
487 *
488 * @async
489 * @function softRefresh
490 * @returns {Promise<void>} A promise that resolves when the refresh command has been executed.
491 */
492export async function softRefresh() {
493 await Uebersicht.run(
494 `osascript -e 'tell application id "tracesOf.Uebersicht" to refresh widget id "simple-bar-index-jsx"'`,
495 );
496}
497
498/**
499 * Triggers a hard refresh of the Uebersicht application by running an AppleScript command.
500 *
501 * @async
502 * @function hardRefresh
503 * @returns {Promise<void>} A promise that resolves when the refresh command has been executed.
504 */
505export async function hardRefresh() {
506 await Uebersicht.run(
507 `osascript -e 'tell application id "tracesOf.Uebersicht" to refresh'`,
508 );
509}
510
511/**
512 * Displays a notification using either the pushMissive function or the system notification.
513 *
514 * @param {string} content - The content of the notification.
515 * @param {Function} pushMissive - A function to push a missive notification.
516 * @param {Object} [options] - Optional settings for the notification.
517 * @param {string} [options.side="right"] - The side where the notification should appear.
518 * @param {number} [options.delay=5000] - The delay before the notification disappears.
519 */
520export function notification(
521 content,
522 pushMissive,
523 { side = "right", delay = 5000 } = {},
524) {
525 const settings = Settings.get();
526 const { disableNotifications, enableMissives } = settings.global;
527 if (disableNotifications) return;
528 if (enableMissives && typeof pushMissive === "function") {
529 pushMissive({ side, content, delay });
530 } else {
531 Uebersicht.run(
532 `osascript -e 'tell app "System Events" to display notification "${content}" with title "simple-bar"'`,
533 );
534 }
535}
536
537/**
538 * Injects styles into the document head. If styles with the given ID already exist, it updates them.
539 * Otherwise, it creates a new style element and appends it to the document head.
540 *
541 * @param {string} id - The ID to assign to the style element.
542 * @param {string[]} [styles=[]] - An array of CSS styles to inject.
543 */
544export function injectStyles(id, styles = []) {
545 const existingStyles = document.getElementById(id);
546 // Merge all styles and minify them
547 const stylesToInject = styles.join("").replace(/\s+/g, " ");
548 if (existingStyles) {
549 existingStyles.innerHTML = stylesToInject;
550 return;
551 }
552 document.head.appendChild(
553 Object.assign(document.createElement("style"), {
554 id,
555 innerHTML: stylesToInject,
556 }),
557 );
558}
559
560const DEFAULT_PACE = 4;
561
562/**
563 * Starts the sliding animation for a given container.
564 *
565 * @param {HTMLElement} container - The container element that holds the inner and slider elements.
566 * @param {string} innerSelector - The CSS selector for the inner element.
567 * @param {string} sliderSelector - The CSS selector for the slider element.
568 */
569export function startSliding(container, innerSelector, sliderSelector) {
570 if (!container) return;
571 const settings = Settings.get();
572 const { slidingAnimationPace = DEFAULT_PACE } = settings.global;
573 const pace =
574 !slidingAnimationPace || slidingAnimationPace < 1
575 ? DEFAULT_PACE
576 : parseInt(slidingAnimationPace);
577 const inner = container.querySelector(innerSelector);
578 const slider = container.querySelector(sliderSelector);
579 const delta = inner.clientWidth - slider.clientWidth;
580 if (delta > 0) return;
581 const timing = Math.round((Math.abs(delta) * 100) / pace);
582 Object.assign(slider.style, {
583 transform: `translateX(${delta}px)`,
584 transition: `transform ${timing}ms linear`,
585 });
586}
587
588/**
589 * Stops the sliding effect by removing the inline style of the slider element.
590 *
591 * @param {HTMLElement} container - The container element that holds the slider.
592 * @param {string} sliderSelector - The CSS selector for the slider element.
593 */
594export function stopSliding(container, sliderSelector) {
595 if (!container) return;
596 container.querySelector(sliderSelector).removeAttribute("style");
597}
598
599/**
600 * Cleans up the given output by trimming whitespace and removing all newline characters.
601 *
602 * @param {string} output - The string output to be cleaned.
603 * @returns {string} - The cleaned output string.
604 */
605export function cleanupOutput(output) {
606 return output?.trim().replace(/(\r\n|\n|\r)/gm, "");
607}
608
609/**
610 * Returns a promise that resolves after a specified number of milliseconds.
611 *
612 * @param {number} ms - The number of milliseconds to wait before the promise resolves.
613 * @returns {Promise<void>} An empty promise that resolves after the specified delay.
614 */
615export function timeout(ms) {
616 return new Promise((resolve) => setTimeout(resolve, ms));
617}
618
619/**
620 * Switches the space (virtual desktop) on macOS.
621 *
622 * @param {number} currentIndex - The current space index.
623 * @param {number} desiredIndex - The desired space index to switch to.
624 * @returns {Promise<void>} A promise that resolves when the space switch is complete.
625 */
626export async function switchSpace(currentIndex, desiredIndex) {
627 const repeats = Math.abs(currentIndex - desiredIndex);
628 const left = currentIndex > desiredIndex;
629 for (let i = 0; i < repeats; i++) {
630 await Uebersicht.run(
631 `osascript -e 'tell app "System Events" to key code ${
632 left ? "123" : "124"
633 } using control down'`,
634 );
635 }
636}
637
638/**
639 * Adds event listeners to handle focus and blur events on the bar element.
640 *
641 * This function selects the element with the class "simple-bar" and adds
642 * event listeners for "click" and "mouseleave" events. When the bar is clicked,
643 * it checks if the click target is the bar itself and then calls the `focusBar` function.
644 * When the mouse leaves the bar, it calls the `blurBar` function.
645 */
646export function handleBarFocus() {
647 const bar = document.querySelector(".simple-bar");
648 if (!bar) return;
649 bar.addEventListener("click", (e) => {
650 if (e.target !== bar) return;
651 focusBar();
652 });
653 bar.addEventListener("mouseleave", blurBar);
654}
655
656/**
657 * Focuses the bar element by adding the "simple-bar--focused" class to it.
658 * If the bar element is not found, the function does nothing.
659 */
660function focusBar() {
661 const bar = document.querySelector(".simple-bar");
662 if (!bar) return;
663 bar.classList.add("simple-bar--focused");
664}
665
666/**
667 * Removes the "simple-bar--focused" class from the element with the class "simple-bar".
668 * If the element is not found, the function does nothing.
669 */
670export function blurBar() {
671 const bar = document.querySelector(".simple-bar");
672 if (!bar) return;
673 bar.classList.remove("simple-bar--focused");
674}
675
676/**
677 * Retrieves the system architecture.
678 *
679 * This function runs two shell commands using Uebersicht to get the system's
680 * architecture and system type. It then processes the output to determine
681 * if the system is using an ARM64 architecture or x86_64.
682 *
683 * The result is cached permanently (in memory and localStorage) since
684 * system architecture never changes at runtime.
685 *
686 * @returns {Promise<"arm64" | "x86_64">} A promise that resolves to a string indicating the system architecture ("arm64" or "x86_64").
687 */
688let _cachedSystem = null;
689
690export async function getSystem() {
691 if (_cachedSystem) return _cachedSystem;
692 try {
693 const stored = localStorage.getItem("sb_system_arch");
694 if (stored) {
695 _cachedSystem = stored;
696 return _cachedSystem;
697 }
698 } catch {
699 // Ignore localStorage errors
700 }
701 const [bareArchitecture, bareSystem] = await Promise.all([
702 Uebersicht.run("uname -a"),
703 Uebersicht.run("uname -m"),
704 ]);
705 const architecture = cleanupOutput(bareArchitecture);
706 const system = cleanupOutput(bareSystem);
707 if (
708 system.startsWith("arm64") ||
709 (system.startsWith("x86_64") && architecture.includes("ARM64"))
710 ) {
711 _cachedSystem = "arm64";
712 } else {
713 _cachedSystem = "x86_64";
714 }
715 try {
716 localStorage.setItem("sb_system_arch", _cachedSystem);
717 } catch {
718 // Ignore localStorage errors
719 }
720 return _cachedSystem;
721}
722
723/**
724 * Checks if a display is visible based on the provided setting.
725 *
726 * @param {number} display - The display number to check.
727 * @param {string} setting - A comma-separated string of display numbers.
728 * @returns {boolean} - Returns true if the display is visible, otherwise false.
729 */
730export function isVisibleOnDisplay(display, setting) {
731 try {
732 if (!setting?.trim()) return true;
733 const displays = setting.split(",").map((d) => parseInt(d, 10));
734 return displays.includes(display);
735 } catch {
736 return true;
737 }
738}
739
740/**
741 * Adds a value to the graph history and ensures the graph does not exceed the specified maximum length.
742 *
743 * @param {any} value - The value to add to the graph history.
744 * @param {function} setGraph - The state setter function for updating the graph.
745 * @param {number} maxLength - The maximum length of the graph history.
746 */
747export function addToGraphHistory(value, setGraph, maxLength) {
748 setGraph((graph) => {
749 const newGraph = [...graph, value];
750 if (newGraph.length > maxLength) {
751 newGraph.shift();
752 }
753 return newGraph;
754 });
755}
756
757/**
758 * Parses a string value into an integer and returns it if valid, otherwise returns a default value.
759 *
760 * @param {string} value - The string value to parse.
761 * @param {number} defaultValue - The default value to return if parsing fails.
762 * @returns {number} - The parsed integer or the default value if parsing fails.
763 */
764export function getRefreshFrequency(value, defaultValue) {
765 const parsedValue = parseInt(value, 10);
766 return isNaN(parsedValue) ? defaultValue : parsedValue;
767}
768
769/**
770 * Executes a given command in the user's preferred terminal application.
771 *
772 * The terminal application is determined by the global settings.
773 * Supported terminals are "Terminal" and "iTerm2".
774 *
775 * @param {string} command - The command to be executed in the terminal.
776 */
777export function runInUserTerminal(command) {
778 const settings = Settings.get();
779 const { terminal } = settings.global;
780 switch (terminal) {
781 case "Terminal":
782 Uebersicht.run(
783 `osascript ./simple-bar/lib/scripts/run-command-in-terminal.applescript` +
784 ` "${command}"`,
785 );
786 break;
787 case "iTerm2":
788 Uebersicht.run(
789 `osascript ./simple-bar/lib/scripts/run-command-in-iterm2.applescript` +
790 ` "${command}"`,
791 );
792 break;
793 default:
794 break;
795 }
796}
797
798/**
799 * Formats a given number of bytes into a more readable string with appropriate units.
800 *
801 * @param {number} bytes - The number of bytes to format.
802 * @param {number} [decimals=1] - The number of decimal places to include in the formatted string.
803 * @returns {string} The formatted string with the appropriate unit.
804 */
805export function formatBytes(bytes, decimals = 1) {
806 if (!+bytes) return "0b";
807
808 const k = 1024;
809 const dm = decimals < 0 ? 0 : decimals;
810 const sizes = ["b", "kb", "mb", "gb", "tb", "pb", "eb", "zb", "yb"];
811
812 const i = Math.floor(Math.log(bytes) / Math.log(k));
813
814 return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}<em>${
815 sizes[i]
816 }</em>`;
817}
818
819/**
820 * Normalizes an application name by removing any left-to-right mark characters (U+200E).
821 *
822 * @param {string} name - The application name to normalize.
823 * @returns {string} The normalized application name without left-to-right mark characters.
824 */
825export function normalizeAppName(name) {
826 if (!name) return "";
827 return name.replace(/[\u200E]/g, "");
828}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/yabai.js b/users/ryan/modules/simple-bar/simple-bar-source/lib/yabai.js
new file mode 100755
index 0000000..1a56068
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/yabai.js
@@ -0,0 +1,128 @@
1import * as Uebersicht from "uebersicht";
2import * as Settings from "./settings";
3import * as Utils from "./utils";
4
5/**
6 * Focuses on the specified space.
7 * @param {number} index - The index of the space to focus on.
8 */
9export async function goToSpace(index) {
10 const settings = Settings.get();
11 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
12 await Uebersicht.run(`${yabaiPath} -m space --focus ${index}`);
13}
14
15/**
16 * Renames the specified space.
17 * @param {number} index - The index of the space to rename.
18 * @param {string} label - The new label for the space.
19 */
20export async function renameSpace(index, label) {
21 const settings = Settings.get();
22 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
23 await Uebersicht.run(`${yabaiPath} -m space ${index} --label "${label}"`);
24}
25
26/**
27 * Creates a new space on the specified display.
28 * @param {number} displayId - The ID of the display to create the space on.
29 */
30export async function createSpace(displayId) {
31 const settings = Settings.get();
32 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
33 await focusDisplay(displayId);
34 await Uebersicht.run(`${yabaiPath} -m space --create`);
35 await Utils.softRefresh();
36}
37
38/**
39 * Removes the specified space from the specified display.
40 * @param {number} index - The index of the space to remove.
41 * @param {number} displayId - The ID of the display to remove the space from.
42 */
43export async function removeSpace(index, displayId) {
44 const settings = Settings.get();
45 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
46 await focusDisplay(displayId);
47 await Uebersicht.run(`${yabaiPath} -m space ${index} --destroy`);
48 await Utils.softRefresh();
49}
50
51/**
52 * Swaps the specified space with the space in the given direction.
53 * @param {number} index - The index of the space to swap.
54 * @param {string} direction - The direction to swap the space ("left" or "right").
55 */
56export async function swapSpace(index, direction) {
57 const settings = Settings.get();
58 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
59 const action = direction === "left" ? index - 1 : index + 1;
60 await Uebersicht.run(`${yabaiPath} -m space ${index} --swap ${action}`);
61 await Utils.softRefresh();
62}
63
64/**
65 * Focuses on the specified window.
66 * @param {number} id - The ID of the window to focus on.
67 */
68export async function focusWindow(id) {
69 const settings = Settings.get();
70 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
71 await Uebersicht.run(`${yabaiPath} -m window --focus ${id}`);
72}
73
74/**
75 * Retrieves the list of spaces.
76 * @returns {Promise<Object[]>} A promise that resolves to the list of spaces.
77 */
78export async function getSpaces() {
79 const settings = Settings.get();
80 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
81 const json = await Uebersicht.run(`${yabaiPath} -m query --spaces`);
82 return Utils.parseJson(json);
83}
84
85/**
86 * Retrieves the list of windows.
87 * @returns {Promise<Object[]>} A promise that resolves to the list of windows.
88 */
89export async function getWindows() {
90 const settings = Settings.get();
91 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
92 const json = await Uebersicht.run(`${yabaiPath} -m query --windows`);
93 const cleanedJson = json.replace(/\\\n/g, "").replace(/00000/g, "0");
94 return Utils.parseJson(cleanedJson);
95}
96
97/**
98 * Retrieves the list of displays.
99 * @returns {Promise<Object[]>} A promise that resolves to the list of displays.
100 */
101export async function getDisplays() {
102 const settings = Settings.get();
103 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
104 const json = await Uebersicht.run(`${yabaiPath} -m query --displays`);
105 return Utils.parseJson(json);
106}
107
108/**
109 * Focus the given display.
110 *
111 * Silently ignores the error thrown when the display is already focused,
112 * which is a known and harmless yabai behavior.
113 *
114 * @param {number|string} displayId - The ID of the display to focus.
115 */
116async function focusDisplay(displayId) {
117 const settings = Settings.get();
118 const { yabaiPath = "/opt/homebrew/bin/yabai" } = settings.global;
119 try {
120 await Uebersicht.run(`${yabaiPath} -m display --focus ${displayId}`);
121 } catch (e) {
122 const message = e?.toString?.() || "";
123 if (!message.includes("cannot focus an already focused display")) {
124 // eslint-disable-next-line no-console
125 console.warn("Failed to focus display:", message);
126 }
127 }
128}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/package-lock.json b/users/ryan/modules/simple-bar/simple-bar-source/package-lock.json
new file mode 100755
index 0000000..3682fa0
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/package-lock.json
@@ -0,0 +1,3267 @@
1{
2 "name": "simple-bar",
3 "version": "1.0.0",
4 "lockfileVersion": 3,
5 "requires": true,
6 "packages": {
7 "": {
8 "name": "simple-bar",
9 "version": "1.0.0",
10 "devDependencies": {
11 "@eslint/js": "^9",
12 "eslint": "^9",
13 "eslint-plugin-react": "^7",
14 "eslint-plugin-react-hooks": "^7",
15 "globals": "^16"
16 }
17 },
18 "node_modules/@aashutoshrathi/word-wrap": {
19 "version": "1.2.6",
20 "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
21 "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
22 "dev": true,
23 "license": "MIT",
24 "engines": {
25 "node": ">=0.10.0"
26 }
27 },
28 "node_modules/@babel/code-frame": {
29 "version": "7.27.1",
30 "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
31 "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
32 "dev": true,
33 "license": "MIT",
34 "dependencies": {
35 "@babel/helper-validator-identifier": "^7.27.1",
36 "js-tokens": "^4.0.0",
37 "picocolors": "^1.1.1"
38 },
39 "engines": {
40 "node": ">=6.9.0"
41 }
42 },
43 "node_modules/@babel/compat-data": {
44 "version": "7.28.5",
45 "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
46 "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
47 "dev": true,
48 "license": "MIT",
49 "engines": {
50 "node": ">=6.9.0"
51 }
52 },
53 "node_modules/@babel/core": {
54 "version": "7.28.5",
55 "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
56 "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
57 "dev": true,
58 "license": "MIT",
59 "dependencies": {
60 "@babel/code-frame": "^7.27.1",
61 "@babel/generator": "^7.28.5",
62 "@babel/helper-compilation-targets": "^7.27.2",
63 "@babel/helper-module-transforms": "^7.28.3",
64 "@babel/helpers": "^7.28.4",
65 "@babel/parser": "^7.28.5",
66 "@babel/template": "^7.27.2",
67 "@babel/traverse": "^7.28.5",
68 "@babel/types": "^7.28.5",
69 "@jridgewell/remapping": "^2.3.5",
70 "convert-source-map": "^2.0.0",
71 "debug": "^4.1.0",
72 "gensync": "^1.0.0-beta.2",
73 "json5": "^2.2.3",
74 "semver": "^6.3.1"
75 },
76 "engines": {
77 "node": ">=6.9.0"
78 },
79 "funding": {
80 "type": "opencollective",
81 "url": "https://opencollective.com/babel"
82 }
83 },
84 "node_modules/@babel/generator": {
85 "version": "7.28.5",
86 "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
87 "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
88 "dev": true,
89 "license": "MIT",
90 "dependencies": {
91 "@babel/parser": "^7.28.5",
92 "@babel/types": "^7.28.5",
93 "@jridgewell/gen-mapping": "^0.3.12",
94 "@jridgewell/trace-mapping": "^0.3.28",
95 "jsesc": "^3.0.2"
96 },
97 "engines": {
98 "node": ">=6.9.0"
99 }
100 },
101 "node_modules/@babel/helper-compilation-targets": {
102 "version": "7.27.2",
103 "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
104 "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
105 "dev": true,
106 "license": "MIT",
107 "dependencies": {
108 "@babel/compat-data": "^7.27.2",
109 "@babel/helper-validator-option": "^7.27.1",
110 "browserslist": "^4.24.0",
111 "lru-cache": "^5.1.1",
112 "semver": "^6.3.1"
113 },
114 "engines": {
115 "node": ">=6.9.0"
116 }
117 },
118 "node_modules/@babel/helper-globals": {
119 "version": "7.28.0",
120 "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
121 "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
122 "dev": true,
123 "license": "MIT",
124 "engines": {
125 "node": ">=6.9.0"
126 }
127 },
128 "node_modules/@babel/helper-module-imports": {
129 "version": "7.27.1",
130 "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
131 "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
132 "dev": true,
133 "license": "MIT",
134 "dependencies": {
135 "@babel/traverse": "^7.27.1",
136 "@babel/types": "^7.27.1"
137 },
138 "engines": {
139 "node": ">=6.9.0"
140 }
141 },
142 "node_modules/@babel/helper-module-transforms": {
143 "version": "7.28.3",
144 "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
145 "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
146 "dev": true,
147 "license": "MIT",
148 "dependencies": {
149 "@babel/helper-module-imports": "^7.27.1",
150 "@babel/helper-validator-identifier": "^7.27.1",
151 "@babel/traverse": "^7.28.3"
152 },
153 "engines": {
154 "node": ">=6.9.0"
155 },
156 "peerDependencies": {
157 "@babel/core": "^7.0.0"
158 }
159 },
160 "node_modules/@babel/helper-string-parser": {
161 "version": "7.27.1",
162 "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
163 "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
164 "dev": true,
165 "license": "MIT",
166 "engines": {
167 "node": ">=6.9.0"
168 }
169 },
170 "node_modules/@babel/helper-validator-identifier": {
171 "version": "7.28.5",
172 "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
173 "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
174 "dev": true,
175 "license": "MIT",
176 "engines": {
177 "node": ">=6.9.0"
178 }
179 },
180 "node_modules/@babel/helper-validator-option": {
181 "version": "7.27.1",
182 "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
183 "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
184 "dev": true,
185 "license": "MIT",
186 "engines": {
187 "node": ">=6.9.0"
188 }
189 },
190 "node_modules/@babel/helpers": {
191 "version": "7.28.4",
192 "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
193 "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
194 "dev": true,
195 "license": "MIT",
196 "dependencies": {
197 "@babel/template": "^7.27.2",
198 "@babel/types": "^7.28.4"
199 },
200 "engines": {
201 "node": ">=6.9.0"
202 }
203 },
204 "node_modules/@babel/parser": {
205 "version": "7.28.5",
206 "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
207 "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
208 "dev": true,
209 "license": "MIT",
210 "dependencies": {
211 "@babel/types": "^7.28.5"
212 },
213 "bin": {
214 "parser": "bin/babel-parser.js"
215 },
216 "engines": {
217 "node": ">=6.0.0"
218 }
219 },
220 "node_modules/@babel/template": {
221 "version": "7.27.2",
222 "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
223 "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
224 "dev": true,
225 "license": "MIT",
226 "dependencies": {
227 "@babel/code-frame": "^7.27.1",
228 "@babel/parser": "^7.27.2",
229 "@babel/types": "^7.27.1"
230 },
231 "engines": {
232 "node": ">=6.9.0"
233 }
234 },
235 "node_modules/@babel/traverse": {
236 "version": "7.28.5",
237 "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
238 "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
239 "dev": true,
240 "license": "MIT",
241 "dependencies": {
242 "@babel/code-frame": "^7.27.1",
243 "@babel/generator": "^7.28.5",
244 "@babel/helper-globals": "^7.28.0",
245 "@babel/parser": "^7.28.5",
246 "@babel/template": "^7.27.2",
247 "@babel/types": "^7.28.5",
248 "debug": "^4.3.1"
249 },
250 "engines": {
251 "node": ">=6.9.0"
252 }
253 },
254 "node_modules/@babel/types": {
255 "version": "7.28.5",
256 "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
257 "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
258 "dev": true,
259 "license": "MIT",
260 "dependencies": {
261 "@babel/helper-string-parser": "^7.27.1",
262 "@babel/helper-validator-identifier": "^7.28.5"
263 },
264 "engines": {
265 "node": ">=6.9.0"
266 }
267 },
268 "node_modules/@eslint-community/eslint-utils": {
269 "version": "4.9.0",
270 "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
271 "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
272 "dev": true,
273 "license": "MIT",
274 "dependencies": {
275 "eslint-visitor-keys": "^3.4.3"
276 },
277 "engines": {
278 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
279 },
280 "funding": {
281 "url": "https://opencollective.com/eslint"
282 },
283 "peerDependencies": {
284 "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
285 }
286 },
287 "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
288 "version": "3.4.3",
289 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
290 "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
291 "dev": true,
292 "license": "Apache-2.0",
293 "engines": {
294 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
295 },
296 "funding": {
297 "url": "https://opencollective.com/eslint"
298 }
299 },
300 "node_modules/@eslint-community/regexpp": {
301 "version": "4.12.2",
302 "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
303 "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
304 "dev": true,
305 "license": "MIT",
306 "engines": {
307 "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
308 }
309 },
310 "node_modules/@eslint/config-array": {
311 "version": "0.21.1",
312 "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
313 "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
314 "dev": true,
315 "license": "Apache-2.0",
316 "dependencies": {
317 "@eslint/object-schema": "^2.1.7",
318 "debug": "^4.3.1",
319 "minimatch": "^3.1.2"
320 },
321 "engines": {
322 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
323 }
324 },
325 "node_modules/@eslint/config-helpers": {
326 "version": "0.4.2",
327 "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
328 "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
329 "dev": true,
330 "license": "Apache-2.0",
331 "dependencies": {
332 "@eslint/core": "^0.17.0"
333 },
334 "engines": {
335 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
336 }
337 },
338 "node_modules/@eslint/core": {
339 "version": "0.17.0",
340 "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
341 "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
342 "dev": true,
343 "license": "Apache-2.0",
344 "dependencies": {
345 "@types/json-schema": "^7.0.15"
346 },
347 "engines": {
348 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
349 }
350 },
351 "node_modules/@eslint/eslintrc": {
352 "version": "3.3.1",
353 "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
354 "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
355 "dev": true,
356 "license": "MIT",
357 "dependencies": {
358 "ajv": "^6.12.4",
359 "debug": "^4.3.2",
360 "espree": "^10.0.1",
361 "globals": "^14.0.0",
362 "ignore": "^5.2.0",
363 "import-fresh": "^3.2.1",
364 "js-yaml": "^4.1.0",
365 "minimatch": "^3.1.2",
366 "strip-json-comments": "^3.1.1"
367 },
368 "engines": {
369 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
370 },
371 "funding": {
372 "url": "https://opencollective.com/eslint"
373 }
374 },
375 "node_modules/@eslint/eslintrc/node_modules/globals": {
376 "version": "14.0.0",
377 "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
378 "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
379 "dev": true,
380 "license": "MIT",
381 "engines": {
382 "node": ">=18"
383 },
384 "funding": {
385 "url": "https://github.com/sponsors/sindresorhus"
386 }
387 },
388 "node_modules/@eslint/js": {
389 "version": "9.39.1",
390 "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
391 "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
392 "dev": true,
393 "license": "MIT",
394 "engines": {
395 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
396 },
397 "funding": {
398 "url": "https://eslint.org/donate"
399 }
400 },
401 "node_modules/@eslint/object-schema": {
402 "version": "2.1.7",
403 "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
404 "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
405 "dev": true,
406 "license": "Apache-2.0",
407 "engines": {
408 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
409 }
410 },
411 "node_modules/@eslint/plugin-kit": {
412 "version": "0.4.1",
413 "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
414 "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
415 "dev": true,
416 "license": "Apache-2.0",
417 "dependencies": {
418 "@eslint/core": "^0.17.0",
419 "levn": "^0.4.1"
420 },
421 "engines": {
422 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
423 }
424 },
425 "node_modules/@humanfs/core": {
426 "version": "0.19.1",
427 "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
428 "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
429 "dev": true,
430 "license": "Apache-2.0",
431 "engines": {
432 "node": ">=18.18.0"
433 }
434 },
435 "node_modules/@humanfs/node": {
436 "version": "0.16.7",
437 "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
438 "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
439 "dev": true,
440 "license": "Apache-2.0",
441 "dependencies": {
442 "@humanfs/core": "^0.19.1",
443 "@humanwhocodes/retry": "^0.4.0"
444 },
445 "engines": {
446 "node": ">=18.18.0"
447 }
448 },
449 "node_modules/@humanwhocodes/module-importer": {
450 "version": "1.0.1",
451 "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
452 "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
453 "dev": true,
454 "license": "Apache-2.0",
455 "engines": {
456 "node": ">=12.22"
457 },
458 "funding": {
459 "type": "github",
460 "url": "https://github.com/sponsors/nzakas"
461 }
462 },
463 "node_modules/@humanwhocodes/retry": {
464 "version": "0.4.3",
465 "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
466 "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
467 "dev": true,
468 "license": "Apache-2.0",
469 "engines": {
470 "node": ">=18.18"
471 },
472 "funding": {
473 "type": "github",
474 "url": "https://github.com/sponsors/nzakas"
475 }
476 },
477 "node_modules/@jridgewell/gen-mapping": {
478 "version": "0.3.13",
479 "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
480 "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
481 "dev": true,
482 "license": "MIT",
483 "dependencies": {
484 "@jridgewell/sourcemap-codec": "^1.5.0",
485 "@jridgewell/trace-mapping": "^0.3.24"
486 }
487 },
488 "node_modules/@jridgewell/remapping": {
489 "version": "2.3.5",
490 "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
491 "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
492 "dev": true,
493 "license": "MIT",
494 "dependencies": {
495 "@jridgewell/gen-mapping": "^0.3.5",
496 "@jridgewell/trace-mapping": "^0.3.24"
497 }
498 },
499 "node_modules/@jridgewell/resolve-uri": {
500 "version": "3.1.2",
501 "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
502 "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
503 "dev": true,
504 "license": "MIT",
505 "engines": {
506 "node": ">=6.0.0"
507 }
508 },
509 "node_modules/@jridgewell/sourcemap-codec": {
510 "version": "1.5.5",
511 "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
512 "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
513 "dev": true,
514 "license": "MIT"
515 },
516 "node_modules/@jridgewell/trace-mapping": {
517 "version": "0.3.31",
518 "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
519 "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
520 "dev": true,
521 "license": "MIT",
522 "dependencies": {
523 "@jridgewell/resolve-uri": "^3.1.0",
524 "@jridgewell/sourcemap-codec": "^1.4.14"
525 }
526 },
527 "node_modules/@types/estree": {
528 "version": "1.0.8",
529 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
530 "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
531 "dev": true,
532 "license": "MIT"
533 },
534 "node_modules/@types/json-schema": {
535 "version": "7.0.15",
536 "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
537 "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
538 "dev": true,
539 "license": "MIT"
540 },
541 "node_modules/acorn": {
542 "version": "8.15.0",
543 "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
544 "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
545 "dev": true,
546 "license": "MIT",
547 "bin": {
548 "acorn": "bin/acorn"
549 },
550 "engines": {
551 "node": ">=0.4.0"
552 }
553 },
554 "node_modules/acorn-jsx": {
555 "version": "5.3.2",
556 "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
557 "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
558 "dev": true,
559 "license": "MIT",
560 "peerDependencies": {
561 "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
562 }
563 },
564 "node_modules/ajv": {
565 "version": "6.12.6",
566 "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
567 "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
568 "dev": true,
569 "license": "MIT",
570 "dependencies": {
571 "fast-deep-equal": "^3.1.1",
572 "fast-json-stable-stringify": "^2.0.0",
573 "json-schema-traverse": "^0.4.1",
574 "uri-js": "^4.2.2"
575 },
576 "funding": {
577 "type": "github",
578 "url": "https://github.com/sponsors/epoberezkin"
579 }
580 },
581 "node_modules/ansi-styles": {
582 "version": "4.3.0",
583 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
584 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
585 "dev": true,
586 "license": "MIT",
587 "dependencies": {
588 "color-convert": "^2.0.1"
589 },
590 "engines": {
591 "node": ">=8"
592 },
593 "funding": {
594 "url": "https://github.com/chalk/ansi-styles?sponsor=1"
595 }
596 },
597 "node_modules/argparse": {
598 "version": "2.0.1",
599 "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
600 "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
601 "dev": true,
602 "license": "Python-2.0"
603 },
604 "node_modules/array-buffer-byte-length": {
605 "version": "1.0.1",
606 "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
607 "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
608 "dev": true,
609 "license": "MIT",
610 "dependencies": {
611 "call-bind": "^1.0.5",
612 "is-array-buffer": "^3.0.4"
613 },
614 "engines": {
615 "node": ">= 0.4"
616 },
617 "funding": {
618 "url": "https://github.com/sponsors/ljharb"
619 }
620 },
621 "node_modules/array-includes": {
622 "version": "3.1.8",
623 "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
624 "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
625 "dev": true,
626 "license": "MIT",
627 "dependencies": {
628 "call-bind": "^1.0.7",
629 "define-properties": "^1.2.1",
630 "es-abstract": "^1.23.2",
631 "es-object-atoms": "^1.0.0",
632 "get-intrinsic": "^1.2.4",
633 "is-string": "^1.0.7"
634 },
635 "engines": {
636 "node": ">= 0.4"
637 },
638 "funding": {
639 "url": "https://github.com/sponsors/ljharb"
640 }
641 },
642 "node_modules/array.prototype.findlast": {
643 "version": "1.2.5",
644 "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
645 "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
646 "dev": true,
647 "license": "MIT",
648 "dependencies": {
649 "call-bind": "^1.0.7",
650 "define-properties": "^1.2.1",
651 "es-abstract": "^1.23.2",
652 "es-errors": "^1.3.0",
653 "es-object-atoms": "^1.0.0",
654 "es-shim-unscopables": "^1.0.2"
655 },
656 "engines": {
657 "node": ">= 0.4"
658 },
659 "funding": {
660 "url": "https://github.com/sponsors/ljharb"
661 }
662 },
663 "node_modules/array.prototype.flat": {
664 "version": "1.3.2",
665 "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
666 "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
667 "dev": true,
668 "license": "MIT",
669 "dependencies": {
670 "call-bind": "^1.0.2",
671 "define-properties": "^1.2.0",
672 "es-abstract": "^1.22.1",
673 "es-shim-unscopables": "^1.0.0"
674 },
675 "engines": {
676 "node": ">= 0.4"
677 },
678 "funding": {
679 "url": "https://github.com/sponsors/ljharb"
680 }
681 },
682 "node_modules/array.prototype.flatmap": {
683 "version": "1.3.2",
684 "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
685 "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
686 "dev": true,
687 "license": "MIT",
688 "dependencies": {
689 "call-bind": "^1.0.2",
690 "define-properties": "^1.2.0",
691 "es-abstract": "^1.22.1",
692 "es-shim-unscopables": "^1.0.0"
693 },
694 "engines": {
695 "node": ">= 0.4"
696 },
697 "funding": {
698 "url": "https://github.com/sponsors/ljharb"
699 }
700 },
701 "node_modules/array.prototype.tosorted": {
702 "version": "1.1.4",
703 "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
704 "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
705 "dev": true,
706 "license": "MIT",
707 "dependencies": {
708 "call-bind": "^1.0.7",
709 "define-properties": "^1.2.1",
710 "es-abstract": "^1.23.3",
711 "es-errors": "^1.3.0",
712 "es-shim-unscopables": "^1.0.2"
713 },
714 "engines": {
715 "node": ">= 0.4"
716 }
717 },
718 "node_modules/arraybuffer.prototype.slice": {
719 "version": "1.0.3",
720 "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
721 "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
722 "dev": true,
723 "license": "MIT",
724 "dependencies": {
725 "array-buffer-byte-length": "^1.0.1",
726 "call-bind": "^1.0.5",
727 "define-properties": "^1.2.1",
728 "es-abstract": "^1.22.3",
729 "es-errors": "^1.2.1",
730 "get-intrinsic": "^1.2.3",
731 "is-array-buffer": "^3.0.4",
732 "is-shared-array-buffer": "^1.0.2"
733 },
734 "engines": {
735 "node": ">= 0.4"
736 },
737 "funding": {
738 "url": "https://github.com/sponsors/ljharb"
739 }
740 },
741 "node_modules/available-typed-arrays": {
742 "version": "1.0.7",
743 "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
744 "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
745 "dev": true,
746 "license": "MIT",
747 "dependencies": {
748 "possible-typed-array-names": "^1.0.0"
749 },
750 "engines": {
751 "node": ">= 0.4"
752 },
753 "funding": {
754 "url": "https://github.com/sponsors/ljharb"
755 }
756 },
757 "node_modules/balanced-match": {
758 "version": "1.0.2",
759 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
760 "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
761 "dev": true,
762 "license": "MIT"
763 },
764 "node_modules/baseline-browser-mapping": {
765 "version": "2.8.24",
766 "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.24.tgz",
767 "integrity": "sha512-uUhTRDPXamakPyghwrUcjaGvvBqGrWvBHReoiULMIpOJVM9IYzQh83Xk2Onx5HlGI2o10NNCzcs9TG/S3TkwrQ==",
768 "dev": true,
769 "license": "Apache-2.0",
770 "bin": {
771 "baseline-browser-mapping": "dist/cli.js"
772 }
773 },
774 "node_modules/brace-expansion": {
775 "version": "1.1.12",
776 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
777 "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
778 "dev": true,
779 "license": "MIT",
780 "dependencies": {
781 "balanced-match": "^1.0.0",
782 "concat-map": "0.0.1"
783 }
784 },
785 "node_modules/browserslist": {
786 "version": "4.27.0",
787 "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz",
788 "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==",
789 "dev": true,
790 "funding": [
791 {
792 "type": "opencollective",
793 "url": "https://opencollective.com/browserslist"
794 },
795 {
796 "type": "tidelift",
797 "url": "https://tidelift.com/funding/github/npm/browserslist"
798 },
799 {
800 "type": "github",
801 "url": "https://github.com/sponsors/ai"
802 }
803 ],
804 "license": "MIT",
805 "dependencies": {
806 "baseline-browser-mapping": "^2.8.19",
807 "caniuse-lite": "^1.0.30001751",
808 "electron-to-chromium": "^1.5.238",
809 "node-releases": "^2.0.26",
810 "update-browserslist-db": "^1.1.4"
811 },
812 "bin": {
813 "browserslist": "cli.js"
814 },
815 "engines": {
816 "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
817 }
818 },
819 "node_modules/call-bind": {
820 "version": "1.0.7",
821 "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
822 "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
823 "dev": true,
824 "license": "MIT",
825 "dependencies": {
826 "es-define-property": "^1.0.0",
827 "es-errors": "^1.3.0",
828 "function-bind": "^1.1.2",
829 "get-intrinsic": "^1.2.4",
830 "set-function-length": "^1.2.1"
831 },
832 "engines": {
833 "node": ">= 0.4"
834 },
835 "funding": {
836 "url": "https://github.com/sponsors/ljharb"
837 }
838 },
839 "node_modules/callsites": {
840 "version": "3.1.0",
841 "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
842 "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
843 "dev": true,
844 "license": "MIT",
845 "engines": {
846 "node": ">=6"
847 }
848 },
849 "node_modules/caniuse-lite": {
850 "version": "1.0.30001753",
851 "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz",
852 "integrity": "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw==",
853 "dev": true,
854 "funding": [
855 {
856 "type": "opencollective",
857 "url": "https://opencollective.com/browserslist"
858 },
859 {
860 "type": "tidelift",
861 "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
862 },
863 {
864 "type": "github",
865 "url": "https://github.com/sponsors/ai"
866 }
867 ],
868 "license": "CC-BY-4.0"
869 },
870 "node_modules/chalk": {
871 "version": "4.1.2",
872 "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
873 "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
874 "dev": true,
875 "license": "MIT",
876 "dependencies": {
877 "ansi-styles": "^4.1.0",
878 "supports-color": "^7.1.0"
879 },
880 "engines": {
881 "node": ">=10"
882 },
883 "funding": {
884 "url": "https://github.com/chalk/chalk?sponsor=1"
885 }
886 },
887 "node_modules/color-convert": {
888 "version": "2.0.1",
889 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
890 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
891 "dev": true,
892 "license": "MIT",
893 "dependencies": {
894 "color-name": "~1.1.4"
895 },
896 "engines": {
897 "node": ">=7.0.0"
898 }
899 },
900 "node_modules/color-name": {
901 "version": "1.1.4",
902 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
903 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
904 "dev": true,
905 "license": "MIT"
906 },
907 "node_modules/concat-map": {
908 "version": "0.0.1",
909 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
910 "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
911 "dev": true,
912 "license": "MIT"
913 },
914 "node_modules/convert-source-map": {
915 "version": "2.0.0",
916 "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
917 "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
918 "dev": true,
919 "license": "MIT"
920 },
921 "node_modules/cross-spawn": {
922 "version": "7.0.6",
923 "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
924 "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
925 "dev": true,
926 "license": "MIT",
927 "dependencies": {
928 "path-key": "^3.1.0",
929 "shebang-command": "^2.0.0",
930 "which": "^2.0.1"
931 },
932 "engines": {
933 "node": ">= 8"
934 }
935 },
936 "node_modules/data-view-buffer": {
937 "version": "1.0.1",
938 "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
939 "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
940 "dev": true,
941 "license": "MIT",
942 "dependencies": {
943 "call-bind": "^1.0.6",
944 "es-errors": "^1.3.0",
945 "is-data-view": "^1.0.1"
946 },
947 "engines": {
948 "node": ">= 0.4"
949 },
950 "funding": {
951 "url": "https://github.com/sponsors/ljharb"
952 }
953 },
954 "node_modules/data-view-byte-length": {
955 "version": "1.0.1",
956 "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
957 "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
958 "dev": true,
959 "license": "MIT",
960 "dependencies": {
961 "call-bind": "^1.0.7",
962 "es-errors": "^1.3.0",
963 "is-data-view": "^1.0.1"
964 },
965 "engines": {
966 "node": ">= 0.4"
967 },
968 "funding": {
969 "url": "https://github.com/sponsors/ljharb"
970 }
971 },
972 "node_modules/data-view-byte-offset": {
973 "version": "1.0.0",
974 "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
975 "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
976 "dev": true,
977 "license": "MIT",
978 "dependencies": {
979 "call-bind": "^1.0.6",
980 "es-errors": "^1.3.0",
981 "is-data-view": "^1.0.1"
982 },
983 "engines": {
984 "node": ">= 0.4"
985 },
986 "funding": {
987 "url": "https://github.com/sponsors/ljharb"
988 }
989 },
990 "node_modules/debug": {
991 "version": "4.4.3",
992 "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
993 "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
994 "dev": true,
995 "license": "MIT",
996 "dependencies": {
997 "ms": "^2.1.3"
998 },
999 "engines": {
1000 "node": ">=6.0"
1001 },
1002 "peerDependenciesMeta": {
1003 "supports-color": {
1004 "optional": true
1005 }
1006 }
1007 },
1008 "node_modules/deep-is": {
1009 "version": "0.1.4",
1010 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
1011 "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
1012 "dev": true,
1013 "license": "MIT"
1014 },
1015 "node_modules/define-data-property": {
1016 "version": "1.1.4",
1017 "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
1018 "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
1019 "dev": true,
1020 "license": "MIT",
1021 "dependencies": {
1022 "es-define-property": "^1.0.0",
1023 "es-errors": "^1.3.0",
1024 "gopd": "^1.0.1"
1025 },
1026 "engines": {
1027 "node": ">= 0.4"
1028 },
1029 "funding": {
1030 "url": "https://github.com/sponsors/ljharb"
1031 }
1032 },
1033 "node_modules/define-properties": {
1034 "version": "1.2.1",
1035 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
1036 "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
1037 "dev": true,
1038 "license": "MIT",
1039 "dependencies": {
1040 "define-data-property": "^1.0.1",
1041 "has-property-descriptors": "^1.0.0",
1042 "object-keys": "^1.1.1"
1043 },
1044 "engines": {
1045 "node": ">= 0.4"
1046 },
1047 "funding": {
1048 "url": "https://github.com/sponsors/ljharb"
1049 }
1050 },
1051 "node_modules/electron-to-chromium": {
1052 "version": "1.5.244",
1053 "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.244.tgz",
1054 "integrity": "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==",
1055 "dev": true,
1056 "license": "ISC"
1057 },
1058 "node_modules/es-abstract": {
1059 "version": "1.23.3",
1060 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
1061 "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
1062 "dev": true,
1063 "license": "MIT",
1064 "dependencies": {
1065 "array-buffer-byte-length": "^1.0.1",
1066 "arraybuffer.prototype.slice": "^1.0.3",
1067 "available-typed-arrays": "^1.0.7",
1068 "call-bind": "^1.0.7",
1069 "data-view-buffer": "^1.0.1",
1070 "data-view-byte-length": "^1.0.1",
1071 "data-view-byte-offset": "^1.0.0",
1072 "es-define-property": "^1.0.0",
1073 "es-errors": "^1.3.0",
1074 "es-object-atoms": "^1.0.0",
1075 "es-set-tostringtag": "^2.0.3",
1076 "es-to-primitive": "^1.2.1",
1077 "function.prototype.name": "^1.1.6",
1078 "get-intrinsic": "^1.2.4",
1079 "get-symbol-description": "^1.0.2",
1080 "globalthis": "^1.0.3",
1081 "gopd": "^1.0.1",
1082 "has-property-descriptors": "^1.0.2",
1083 "has-proto": "^1.0.3",
1084 "has-symbols": "^1.0.3",
1085 "hasown": "^2.0.2",
1086 "internal-slot": "^1.0.7",
1087 "is-array-buffer": "^3.0.4",
1088 "is-callable": "^1.2.7",
1089 "is-data-view": "^1.0.1",
1090 "is-negative-zero": "^2.0.3",
1091 "is-regex": "^1.1.4",
1092 "is-shared-array-buffer": "^1.0.3",
1093 "is-string": "^1.0.7",
1094 "is-typed-array": "^1.1.13",
1095 "is-weakref": "^1.0.2",
1096 "object-inspect": "^1.13.1",
1097 "object-keys": "^1.1.1",
1098 "object.assign": "^4.1.5",
1099 "regexp.prototype.flags": "^1.5.2",
1100 "safe-array-concat": "^1.1.2",
1101 "safe-regex-test": "^1.0.3",
1102 "string.prototype.trim": "^1.2.9",
1103 "string.prototype.trimend": "^1.0.8",
1104 "string.prototype.trimstart": "^1.0.8",
1105 "typed-array-buffer": "^1.0.2",
1106 "typed-array-byte-length": "^1.0.1",
1107 "typed-array-byte-offset": "^1.0.2",
1108 "typed-array-length": "^1.0.6",
1109 "unbox-primitive": "^1.0.2",
1110 "which-typed-array": "^1.1.15"
1111 },
1112 "engines": {
1113 "node": ">= 0.4"
1114 },
1115 "funding": {
1116 "url": "https://github.com/sponsors/ljharb"
1117 }
1118 },
1119 "node_modules/es-define-property": {
1120 "version": "1.0.0",
1121 "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
1122 "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
1123 "dev": true,
1124 "license": "MIT",
1125 "dependencies": {
1126 "get-intrinsic": "^1.2.4"
1127 },
1128 "engines": {
1129 "node": ">= 0.4"
1130 }
1131 },
1132 "node_modules/es-errors": {
1133 "version": "1.3.0",
1134 "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
1135 "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
1136 "dev": true,
1137 "license": "MIT",
1138 "engines": {
1139 "node": ">= 0.4"
1140 }
1141 },
1142 "node_modules/es-iterator-helpers": {
1143 "version": "1.0.19",
1144 "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz",
1145 "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==",
1146 "dev": true,
1147 "license": "MIT",
1148 "dependencies": {
1149 "call-bind": "^1.0.7",
1150 "define-properties": "^1.2.1",
1151 "es-abstract": "^1.23.3",
1152 "es-errors": "^1.3.0",
1153 "es-set-tostringtag": "^2.0.3",
1154 "function-bind": "^1.1.2",
1155 "get-intrinsic": "^1.2.4",
1156 "globalthis": "^1.0.3",
1157 "has-property-descriptors": "^1.0.2",
1158 "has-proto": "^1.0.3",
1159 "has-symbols": "^1.0.3",
1160 "internal-slot": "^1.0.7",
1161 "iterator.prototype": "^1.1.2",
1162 "safe-array-concat": "^1.1.2"
1163 },
1164 "engines": {
1165 "node": ">= 0.4"
1166 }
1167 },
1168 "node_modules/es-object-atoms": {
1169 "version": "1.0.0",
1170 "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
1171 "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
1172 "dev": true,
1173 "license": "MIT",
1174 "dependencies": {
1175 "es-errors": "^1.3.0"
1176 },
1177 "engines": {
1178 "node": ">= 0.4"
1179 }
1180 },
1181 "node_modules/es-set-tostringtag": {
1182 "version": "2.0.3",
1183 "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
1184 "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
1185 "dev": true,
1186 "license": "MIT",
1187 "dependencies": {
1188 "get-intrinsic": "^1.2.4",
1189 "has-tostringtag": "^1.0.2",
1190 "hasown": "^2.0.1"
1191 },
1192 "engines": {
1193 "node": ">= 0.4"
1194 }
1195 },
1196 "node_modules/es-shim-unscopables": {
1197 "version": "1.0.2",
1198 "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
1199 "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
1200 "dev": true,
1201 "license": "MIT",
1202 "dependencies": {
1203 "hasown": "^2.0.0"
1204 }
1205 },
1206 "node_modules/es-to-primitive": {
1207 "version": "1.2.1",
1208 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
1209 "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
1210 "dev": true,
1211 "license": "MIT",
1212 "dependencies": {
1213 "is-callable": "^1.1.4",
1214 "is-date-object": "^1.0.1",
1215 "is-symbol": "^1.0.2"
1216 },
1217 "engines": {
1218 "node": ">= 0.4"
1219 },
1220 "funding": {
1221 "url": "https://github.com/sponsors/ljharb"
1222 }
1223 },
1224 "node_modules/escalade": {
1225 "version": "3.2.0",
1226 "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
1227 "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
1228 "dev": true,
1229 "license": "MIT",
1230 "engines": {
1231 "node": ">=6"
1232 }
1233 },
1234 "node_modules/escape-string-regexp": {
1235 "version": "4.0.0",
1236 "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1237 "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1238 "dev": true,
1239 "license": "MIT",
1240 "engines": {
1241 "node": ">=10"
1242 },
1243 "funding": {
1244 "url": "https://github.com/sponsors/sindresorhus"
1245 }
1246 },
1247 "node_modules/eslint": {
1248 "version": "9.39.1",
1249 "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
1250 "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
1251 "dev": true,
1252 "license": "MIT",
1253 "dependencies": {
1254 "@eslint-community/eslint-utils": "^4.8.0",
1255 "@eslint-community/regexpp": "^4.12.1",
1256 "@eslint/config-array": "^0.21.1",
1257 "@eslint/config-helpers": "^0.4.2",
1258 "@eslint/core": "^0.17.0",
1259 "@eslint/eslintrc": "^3.3.1",
1260 "@eslint/js": "9.39.1",
1261 "@eslint/plugin-kit": "^0.4.1",
1262 "@humanfs/node": "^0.16.6",
1263 "@humanwhocodes/module-importer": "^1.0.1",
1264 "@humanwhocodes/retry": "^0.4.2",
1265 "@types/estree": "^1.0.6",
1266 "ajv": "^6.12.4",
1267 "chalk": "^4.0.0",
1268 "cross-spawn": "^7.0.6",
1269 "debug": "^4.3.2",
1270 "escape-string-regexp": "^4.0.0",
1271 "eslint-scope": "^8.4.0",
1272 "eslint-visitor-keys": "^4.2.1",
1273 "espree": "^10.4.0",
1274 "esquery": "^1.5.0",
1275 "esutils": "^2.0.2",
1276 "fast-deep-equal": "^3.1.3",
1277 "file-entry-cache": "^8.0.0",
1278 "find-up": "^5.0.0",
1279 "glob-parent": "^6.0.2",
1280 "ignore": "^5.2.0",
1281 "imurmurhash": "^0.1.4",
1282 "is-glob": "^4.0.0",
1283 "json-stable-stringify-without-jsonify": "^1.0.1",
1284 "lodash.merge": "^4.6.2",
1285 "minimatch": "^3.1.2",
1286 "natural-compare": "^1.4.0",
1287 "optionator": "^0.9.3"
1288 },
1289 "bin": {
1290 "eslint": "bin/eslint.js"
1291 },
1292 "engines": {
1293 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1294 },
1295 "funding": {
1296 "url": "https://eslint.org/donate"
1297 },
1298 "peerDependencies": {
1299 "jiti": "*"
1300 },
1301 "peerDependenciesMeta": {
1302 "jiti": {
1303 "optional": true
1304 }
1305 }
1306 },
1307 "node_modules/eslint-plugin-react": {
1308 "version": "7.35.0",
1309 "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
1310 "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
1311 "dev": true,
1312 "license": "MIT",
1313 "dependencies": {
1314 "array-includes": "^3.1.8",
1315 "array.prototype.findlast": "^1.2.5",
1316 "array.prototype.flatmap": "^1.3.2",
1317 "array.prototype.tosorted": "^1.1.4",
1318 "doctrine": "^2.1.0",
1319 "es-iterator-helpers": "^1.0.19",
1320 "estraverse": "^5.3.0",
1321 "hasown": "^2.0.2",
1322 "jsx-ast-utils": "^2.4.1 || ^3.0.0",
1323 "minimatch": "^3.1.2",
1324 "object.entries": "^1.1.8",
1325 "object.fromentries": "^2.0.8",
1326 "object.values": "^1.2.0",
1327 "prop-types": "^15.8.1",
1328 "resolve": "^2.0.0-next.5",
1329 "semver": "^6.3.1",
1330 "string.prototype.matchall": "^4.0.11",
1331 "string.prototype.repeat": "^1.0.0"
1332 },
1333 "engines": {
1334 "node": ">=4"
1335 },
1336 "peerDependencies": {
1337 "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
1338 }
1339 },
1340 "node_modules/eslint-plugin-react-hooks": {
1341 "version": "7.0.1",
1342 "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
1343 "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
1344 "dev": true,
1345 "license": "MIT",
1346 "dependencies": {
1347 "@babel/core": "^7.24.4",
1348 "@babel/parser": "^7.24.4",
1349 "hermes-parser": "^0.25.1",
1350 "zod": "^3.25.0 || ^4.0.0",
1351 "zod-validation-error": "^3.5.0 || ^4.0.0"
1352 },
1353 "engines": {
1354 "node": ">=18"
1355 },
1356 "peerDependencies": {
1357 "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
1358 }
1359 },
1360 "node_modules/eslint-plugin-react/node_modules/doctrine": {
1361 "version": "2.1.0",
1362 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
1363 "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
1364 "dev": true,
1365 "license": "Apache-2.0",
1366 "dependencies": {
1367 "esutils": "^2.0.2"
1368 },
1369 "engines": {
1370 "node": ">=0.10.0"
1371 }
1372 },
1373 "node_modules/eslint-scope": {
1374 "version": "8.4.0",
1375 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
1376 "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
1377 "dev": true,
1378 "license": "BSD-2-Clause",
1379 "dependencies": {
1380 "esrecurse": "^4.3.0",
1381 "estraverse": "^5.2.0"
1382 },
1383 "engines": {
1384 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1385 },
1386 "funding": {
1387 "url": "https://opencollective.com/eslint"
1388 }
1389 },
1390 "node_modules/eslint-visitor-keys": {
1391 "version": "4.2.1",
1392 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
1393 "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
1394 "dev": true,
1395 "license": "Apache-2.0",
1396 "engines": {
1397 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1398 },
1399 "funding": {
1400 "url": "https://opencollective.com/eslint"
1401 }
1402 },
1403 "node_modules/espree": {
1404 "version": "10.4.0",
1405 "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
1406 "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
1407 "dev": true,
1408 "license": "BSD-2-Clause",
1409 "dependencies": {
1410 "acorn": "^8.15.0",
1411 "acorn-jsx": "^5.3.2",
1412 "eslint-visitor-keys": "^4.2.1"
1413 },
1414 "engines": {
1415 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1416 },
1417 "funding": {
1418 "url": "https://opencollective.com/eslint"
1419 }
1420 },
1421 "node_modules/esquery": {
1422 "version": "1.5.0",
1423 "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
1424 "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
1425 "dev": true,
1426 "license": "BSD-3-Clause",
1427 "dependencies": {
1428 "estraverse": "^5.1.0"
1429 },
1430 "engines": {
1431 "node": ">=0.10"
1432 }
1433 },
1434 "node_modules/esrecurse": {
1435 "version": "4.3.0",
1436 "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
1437 "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
1438 "dev": true,
1439 "license": "BSD-2-Clause",
1440 "dependencies": {
1441 "estraverse": "^5.2.0"
1442 },
1443 "engines": {
1444 "node": ">=4.0"
1445 }
1446 },
1447 "node_modules/estraverse": {
1448 "version": "5.3.0",
1449 "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
1450 "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
1451 "dev": true,
1452 "license": "BSD-2-Clause",
1453 "engines": {
1454 "node": ">=4.0"
1455 }
1456 },
1457 "node_modules/esutils": {
1458 "version": "2.0.3",
1459 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1460 "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
1461 "dev": true,
1462 "license": "BSD-2-Clause",
1463 "engines": {
1464 "node": ">=0.10.0"
1465 }
1466 },
1467 "node_modules/fast-deep-equal": {
1468 "version": "3.1.3",
1469 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1470 "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
1471 "dev": true,
1472 "license": "MIT"
1473 },
1474 "node_modules/fast-json-stable-stringify": {
1475 "version": "2.1.0",
1476 "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
1477 "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
1478 "dev": true,
1479 "license": "MIT"
1480 },
1481 "node_modules/fast-levenshtein": {
1482 "version": "2.0.6",
1483 "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
1484 "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
1485 "dev": true,
1486 "license": "MIT"
1487 },
1488 "node_modules/file-entry-cache": {
1489 "version": "8.0.0",
1490 "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
1491 "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
1492 "dev": true,
1493 "license": "MIT",
1494 "dependencies": {
1495 "flat-cache": "^4.0.0"
1496 },
1497 "engines": {
1498 "node": ">=16.0.0"
1499 }
1500 },
1501 "node_modules/find-up": {
1502 "version": "5.0.0",
1503 "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1504 "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1505 "dev": true,
1506 "license": "MIT",
1507 "dependencies": {
1508 "locate-path": "^6.0.0",
1509 "path-exists": "^4.0.0"
1510 },
1511 "engines": {
1512 "node": ">=10"
1513 },
1514 "funding": {
1515 "url": "https://github.com/sponsors/sindresorhus"
1516 }
1517 },
1518 "node_modules/flat-cache": {
1519 "version": "4.0.1",
1520 "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
1521 "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
1522 "dev": true,
1523 "license": "MIT",
1524 "dependencies": {
1525 "flatted": "^3.2.9",
1526 "keyv": "^4.5.4"
1527 },
1528 "engines": {
1529 "node": ">=16"
1530 }
1531 },
1532 "node_modules/flatted": {
1533 "version": "3.4.2",
1534 "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
1535 "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
1536 "dev": true,
1537 "license": "ISC"
1538 },
1539 "node_modules/for-each": {
1540 "version": "0.3.3",
1541 "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
1542 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
1543 "dev": true,
1544 "license": "MIT",
1545 "dependencies": {
1546 "is-callable": "^1.1.3"
1547 }
1548 },
1549 "node_modules/function-bind": {
1550 "version": "1.1.2",
1551 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
1552 "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
1553 "dev": true,
1554 "license": "MIT",
1555 "funding": {
1556 "url": "https://github.com/sponsors/ljharb"
1557 }
1558 },
1559 "node_modules/function.prototype.name": {
1560 "version": "1.1.6",
1561 "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
1562 "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
1563 "dev": true,
1564 "license": "MIT",
1565 "dependencies": {
1566 "call-bind": "^1.0.2",
1567 "define-properties": "^1.2.0",
1568 "es-abstract": "^1.22.1",
1569 "functions-have-names": "^1.2.3"
1570 },
1571 "engines": {
1572 "node": ">= 0.4"
1573 },
1574 "funding": {
1575 "url": "https://github.com/sponsors/ljharb"
1576 }
1577 },
1578 "node_modules/functions-have-names": {
1579 "version": "1.2.3",
1580 "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
1581 "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
1582 "dev": true,
1583 "license": "MIT",
1584 "funding": {
1585 "url": "https://github.com/sponsors/ljharb"
1586 }
1587 },
1588 "node_modules/gensync": {
1589 "version": "1.0.0-beta.2",
1590 "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
1591 "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
1592 "dev": true,
1593 "license": "MIT",
1594 "engines": {
1595 "node": ">=6.9.0"
1596 }
1597 },
1598 "node_modules/get-intrinsic": {
1599 "version": "1.2.4",
1600 "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
1601 "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
1602 "dev": true,
1603 "license": "MIT",
1604 "dependencies": {
1605 "es-errors": "^1.3.0",
1606 "function-bind": "^1.1.2",
1607 "has-proto": "^1.0.1",
1608 "has-symbols": "^1.0.3",
1609 "hasown": "^2.0.0"
1610 },
1611 "engines": {
1612 "node": ">= 0.4"
1613 },
1614 "funding": {
1615 "url": "https://github.com/sponsors/ljharb"
1616 }
1617 },
1618 "node_modules/get-symbol-description": {
1619 "version": "1.0.2",
1620 "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
1621 "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
1622 "dev": true,
1623 "license": "MIT",
1624 "dependencies": {
1625 "call-bind": "^1.0.5",
1626 "es-errors": "^1.3.0",
1627 "get-intrinsic": "^1.2.4"
1628 },
1629 "engines": {
1630 "node": ">= 0.4"
1631 },
1632 "funding": {
1633 "url": "https://github.com/sponsors/ljharb"
1634 }
1635 },
1636 "node_modules/glob-parent": {
1637 "version": "6.0.2",
1638 "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
1639 "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
1640 "dev": true,
1641 "license": "ISC",
1642 "dependencies": {
1643 "is-glob": "^4.0.3"
1644 },
1645 "engines": {
1646 "node": ">=10.13.0"
1647 }
1648 },
1649 "node_modules/globals": {
1650 "version": "16.5.0",
1651 "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
1652 "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
1653 "dev": true,
1654 "license": "MIT",
1655 "engines": {
1656 "node": ">=18"
1657 },
1658 "funding": {
1659 "url": "https://github.com/sponsors/sindresorhus"
1660 }
1661 },
1662 "node_modules/globalthis": {
1663 "version": "1.0.3",
1664 "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
1665 "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
1666 "dev": true,
1667 "license": "MIT",
1668 "dependencies": {
1669 "define-properties": "^1.1.3"
1670 },
1671 "engines": {
1672 "node": ">= 0.4"
1673 },
1674 "funding": {
1675 "url": "https://github.com/sponsors/ljharb"
1676 }
1677 },
1678 "node_modules/gopd": {
1679 "version": "1.0.1",
1680 "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
1681 "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
1682 "dev": true,
1683 "license": "MIT",
1684 "dependencies": {
1685 "get-intrinsic": "^1.1.3"
1686 },
1687 "funding": {
1688 "url": "https://github.com/sponsors/ljharb"
1689 }
1690 },
1691 "node_modules/has-bigints": {
1692 "version": "1.0.2",
1693 "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
1694 "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
1695 "dev": true,
1696 "license": "MIT",
1697 "funding": {
1698 "url": "https://github.com/sponsors/ljharb"
1699 }
1700 },
1701 "node_modules/has-flag": {
1702 "version": "4.0.0",
1703 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1704 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1705 "dev": true,
1706 "license": "MIT",
1707 "engines": {
1708 "node": ">=8"
1709 }
1710 },
1711 "node_modules/has-property-descriptors": {
1712 "version": "1.0.2",
1713 "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
1714 "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
1715 "dev": true,
1716 "license": "MIT",
1717 "dependencies": {
1718 "es-define-property": "^1.0.0"
1719 },
1720 "funding": {
1721 "url": "https://github.com/sponsors/ljharb"
1722 }
1723 },
1724 "node_modules/has-proto": {
1725 "version": "1.0.3",
1726 "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
1727 "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
1728 "dev": true,
1729 "license": "MIT",
1730 "engines": {
1731 "node": ">= 0.4"
1732 },
1733 "funding": {
1734 "url": "https://github.com/sponsors/ljharb"
1735 }
1736 },
1737 "node_modules/has-symbols": {
1738 "version": "1.0.3",
1739 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1740 "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
1741 "dev": true,
1742 "license": "MIT",
1743 "engines": {
1744 "node": ">= 0.4"
1745 },
1746 "funding": {
1747 "url": "https://github.com/sponsors/ljharb"
1748 }
1749 },
1750 "node_modules/has-tostringtag": {
1751 "version": "1.0.2",
1752 "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
1753 "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
1754 "dev": true,
1755 "license": "MIT",
1756 "dependencies": {
1757 "has-symbols": "^1.0.3"
1758 },
1759 "engines": {
1760 "node": ">= 0.4"
1761 },
1762 "funding": {
1763 "url": "https://github.com/sponsors/ljharb"
1764 }
1765 },
1766 "node_modules/hasown": {
1767 "version": "2.0.2",
1768 "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
1769 "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
1770 "dev": true,
1771 "license": "MIT",
1772 "dependencies": {
1773 "function-bind": "^1.1.2"
1774 },
1775 "engines": {
1776 "node": ">= 0.4"
1777 }
1778 },
1779 "node_modules/hermes-estree": {
1780 "version": "0.25.1",
1781 "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
1782 "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
1783 "dev": true,
1784 "license": "MIT"
1785 },
1786 "node_modules/hermes-parser": {
1787 "version": "0.25.1",
1788 "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
1789 "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
1790 "dev": true,
1791 "license": "MIT",
1792 "dependencies": {
1793 "hermes-estree": "0.25.1"
1794 }
1795 },
1796 "node_modules/ignore": {
1797 "version": "5.3.2",
1798 "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
1799 "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
1800 "dev": true,
1801 "license": "MIT",
1802 "engines": {
1803 "node": ">= 4"
1804 }
1805 },
1806 "node_modules/import-fresh": {
1807 "version": "3.3.1",
1808 "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
1809 "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
1810 "dev": true,
1811 "license": "MIT",
1812 "dependencies": {
1813 "parent-module": "^1.0.0",
1814 "resolve-from": "^4.0.0"
1815 },
1816 "engines": {
1817 "node": ">=6"
1818 },
1819 "funding": {
1820 "url": "https://github.com/sponsors/sindresorhus"
1821 }
1822 },
1823 "node_modules/imurmurhash": {
1824 "version": "0.1.4",
1825 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1826 "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
1827 "dev": true,
1828 "license": "MIT",
1829 "engines": {
1830 "node": ">=0.8.19"
1831 }
1832 },
1833 "node_modules/internal-slot": {
1834 "version": "1.0.7",
1835 "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
1836 "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
1837 "dev": true,
1838 "license": "MIT",
1839 "dependencies": {
1840 "es-errors": "^1.3.0",
1841 "hasown": "^2.0.0",
1842 "side-channel": "^1.0.4"
1843 },
1844 "engines": {
1845 "node": ">= 0.4"
1846 }
1847 },
1848 "node_modules/is-array-buffer": {
1849 "version": "3.0.4",
1850 "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
1851 "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
1852 "dev": true,
1853 "license": "MIT",
1854 "dependencies": {
1855 "call-bind": "^1.0.2",
1856 "get-intrinsic": "^1.2.1"
1857 },
1858 "engines": {
1859 "node": ">= 0.4"
1860 },
1861 "funding": {
1862 "url": "https://github.com/sponsors/ljharb"
1863 }
1864 },
1865 "node_modules/is-async-function": {
1866 "version": "2.0.0",
1867 "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
1868 "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
1869 "dev": true,
1870 "license": "MIT",
1871 "dependencies": {
1872 "has-tostringtag": "^1.0.0"
1873 },
1874 "engines": {
1875 "node": ">= 0.4"
1876 },
1877 "funding": {
1878 "url": "https://github.com/sponsors/ljharb"
1879 }
1880 },
1881 "node_modules/is-bigint": {
1882 "version": "1.0.4",
1883 "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
1884 "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
1885 "dev": true,
1886 "license": "MIT",
1887 "dependencies": {
1888 "has-bigints": "^1.0.1"
1889 },
1890 "funding": {
1891 "url": "https://github.com/sponsors/ljharb"
1892 }
1893 },
1894 "node_modules/is-boolean-object": {
1895 "version": "1.1.2",
1896 "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
1897 "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
1898 "dev": true,
1899 "license": "MIT",
1900 "dependencies": {
1901 "call-bind": "^1.0.2",
1902 "has-tostringtag": "^1.0.0"
1903 },
1904 "engines": {
1905 "node": ">= 0.4"
1906 },
1907 "funding": {
1908 "url": "https://github.com/sponsors/ljharb"
1909 }
1910 },
1911 "node_modules/is-callable": {
1912 "version": "1.2.7",
1913 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
1914 "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
1915 "dev": true,
1916 "license": "MIT",
1917 "engines": {
1918 "node": ">= 0.4"
1919 },
1920 "funding": {
1921 "url": "https://github.com/sponsors/ljharb"
1922 }
1923 },
1924 "node_modules/is-core-module": {
1925 "version": "2.13.1",
1926 "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
1927 "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
1928 "dev": true,
1929 "license": "MIT",
1930 "dependencies": {
1931 "hasown": "^2.0.0"
1932 },
1933 "funding": {
1934 "url": "https://github.com/sponsors/ljharb"
1935 }
1936 },
1937 "node_modules/is-data-view": {
1938 "version": "1.0.1",
1939 "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
1940 "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
1941 "dev": true,
1942 "license": "MIT",
1943 "dependencies": {
1944 "is-typed-array": "^1.1.13"
1945 },
1946 "engines": {
1947 "node": ">= 0.4"
1948 },
1949 "funding": {
1950 "url": "https://github.com/sponsors/ljharb"
1951 }
1952 },
1953 "node_modules/is-date-object": {
1954 "version": "1.0.5",
1955 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
1956 "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
1957 "dev": true,
1958 "license": "MIT",
1959 "dependencies": {
1960 "has-tostringtag": "^1.0.0"
1961 },
1962 "engines": {
1963 "node": ">= 0.4"
1964 },
1965 "funding": {
1966 "url": "https://github.com/sponsors/ljharb"
1967 }
1968 },
1969 "node_modules/is-extglob": {
1970 "version": "2.1.1",
1971 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1972 "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1973 "dev": true,
1974 "license": "MIT",
1975 "engines": {
1976 "node": ">=0.10.0"
1977 }
1978 },
1979 "node_modules/is-finalizationregistry": {
1980 "version": "1.0.2",
1981 "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
1982 "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
1983 "dev": true,
1984 "license": "MIT",
1985 "dependencies": {
1986 "call-bind": "^1.0.2"
1987 },
1988 "funding": {
1989 "url": "https://github.com/sponsors/ljharb"
1990 }
1991 },
1992 "node_modules/is-generator-function": {
1993 "version": "1.0.10",
1994 "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
1995 "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
1996 "dev": true,
1997 "license": "MIT",
1998 "dependencies": {
1999 "has-tostringtag": "^1.0.0"
2000 },
2001 "engines": {
2002 "node": ">= 0.4"
2003 },
2004 "funding": {
2005 "url": "https://github.com/sponsors/ljharb"
2006 }
2007 },
2008 "node_modules/is-glob": {
2009 "version": "4.0.3",
2010 "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
2011 "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
2012 "dev": true,
2013 "license": "MIT",
2014 "dependencies": {
2015 "is-extglob": "^2.1.1"
2016 },
2017 "engines": {
2018 "node": ">=0.10.0"
2019 }
2020 },
2021 "node_modules/is-map": {
2022 "version": "2.0.2",
2023 "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
2024 "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
2025 "dev": true,
2026 "license": "MIT",
2027 "funding": {
2028 "url": "https://github.com/sponsors/ljharb"
2029 }
2030 },
2031 "node_modules/is-negative-zero": {
2032 "version": "2.0.3",
2033 "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
2034 "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
2035 "dev": true,
2036 "license": "MIT",
2037 "engines": {
2038 "node": ">= 0.4"
2039 },
2040 "funding": {
2041 "url": "https://github.com/sponsors/ljharb"
2042 }
2043 },
2044 "node_modules/is-number-object": {
2045 "version": "1.0.7",
2046 "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
2047 "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
2048 "dev": true,
2049 "license": "MIT",
2050 "dependencies": {
2051 "has-tostringtag": "^1.0.0"
2052 },
2053 "engines": {
2054 "node": ">= 0.4"
2055 },
2056 "funding": {
2057 "url": "https://github.com/sponsors/ljharb"
2058 }
2059 },
2060 "node_modules/is-regex": {
2061 "version": "1.1.4",
2062 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
2063 "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
2064 "dev": true,
2065 "license": "MIT",
2066 "dependencies": {
2067 "call-bind": "^1.0.2",
2068 "has-tostringtag": "^1.0.0"
2069 },
2070 "engines": {
2071 "node": ">= 0.4"
2072 },
2073 "funding": {
2074 "url": "https://github.com/sponsors/ljharb"
2075 }
2076 },
2077 "node_modules/is-set": {
2078 "version": "2.0.2",
2079 "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
2080 "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
2081 "dev": true,
2082 "license": "MIT",
2083 "funding": {
2084 "url": "https://github.com/sponsors/ljharb"
2085 }
2086 },
2087 "node_modules/is-shared-array-buffer": {
2088 "version": "1.0.3",
2089 "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
2090 "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
2091 "dev": true,
2092 "license": "MIT",
2093 "dependencies": {
2094 "call-bind": "^1.0.7"
2095 },
2096 "engines": {
2097 "node": ">= 0.4"
2098 },
2099 "funding": {
2100 "url": "https://github.com/sponsors/ljharb"
2101 }
2102 },
2103 "node_modules/is-string": {
2104 "version": "1.0.7",
2105 "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
2106 "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
2107 "dev": true,
2108 "license": "MIT",
2109 "dependencies": {
2110 "has-tostringtag": "^1.0.0"
2111 },
2112 "engines": {
2113 "node": ">= 0.4"
2114 },
2115 "funding": {
2116 "url": "https://github.com/sponsors/ljharb"
2117 }
2118 },
2119 "node_modules/is-symbol": {
2120 "version": "1.0.4",
2121 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
2122 "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
2123 "dev": true,
2124 "license": "MIT",
2125 "dependencies": {
2126 "has-symbols": "^1.0.2"
2127 },
2128 "engines": {
2129 "node": ">= 0.4"
2130 },
2131 "funding": {
2132 "url": "https://github.com/sponsors/ljharb"
2133 }
2134 },
2135 "node_modules/is-typed-array": {
2136 "version": "1.1.13",
2137 "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
2138 "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
2139 "dev": true,
2140 "license": "MIT",
2141 "dependencies": {
2142 "which-typed-array": "^1.1.14"
2143 },
2144 "engines": {
2145 "node": ">= 0.4"
2146 },
2147 "funding": {
2148 "url": "https://github.com/sponsors/ljharb"
2149 }
2150 },
2151 "node_modules/is-weakmap": {
2152 "version": "2.0.1",
2153 "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
2154 "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
2155 "dev": true,
2156 "license": "MIT",
2157 "funding": {
2158 "url": "https://github.com/sponsors/ljharb"
2159 }
2160 },
2161 "node_modules/is-weakref": {
2162 "version": "1.0.2",
2163 "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
2164 "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
2165 "dev": true,
2166 "license": "MIT",
2167 "dependencies": {
2168 "call-bind": "^1.0.2"
2169 },
2170 "funding": {
2171 "url": "https://github.com/sponsors/ljharb"
2172 }
2173 },
2174 "node_modules/is-weakset": {
2175 "version": "2.0.2",
2176 "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
2177 "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
2178 "dev": true,
2179 "license": "MIT",
2180 "dependencies": {
2181 "call-bind": "^1.0.2",
2182 "get-intrinsic": "^1.1.1"
2183 },
2184 "funding": {
2185 "url": "https://github.com/sponsors/ljharb"
2186 }
2187 },
2188 "node_modules/isarray": {
2189 "version": "2.0.5",
2190 "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
2191 "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
2192 "dev": true,
2193 "license": "MIT"
2194 },
2195 "node_modules/isexe": {
2196 "version": "2.0.0",
2197 "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
2198 "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
2199 "dev": true,
2200 "license": "ISC"
2201 },
2202 "node_modules/iterator.prototype": {
2203 "version": "1.1.2",
2204 "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
2205 "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
2206 "dev": true,
2207 "license": "MIT",
2208 "dependencies": {
2209 "define-properties": "^1.2.1",
2210 "get-intrinsic": "^1.2.1",
2211 "has-symbols": "^1.0.3",
2212 "reflect.getprototypeof": "^1.0.4",
2213 "set-function-name": "^2.0.1"
2214 }
2215 },
2216 "node_modules/js-tokens": {
2217 "version": "4.0.0",
2218 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
2219 "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
2220 "dev": true,
2221 "license": "MIT"
2222 },
2223 "node_modules/js-yaml": {
2224 "version": "4.3.0",
2225 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
2226 "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
2227 "dev": true,
2228 "funding": [
2229 {
2230 "type": "github",
2231 "url": "https://github.com/sponsors/puzrin"
2232 },
2233 {
2234 "type": "github",
2235 "url": "https://github.com/sponsors/nodeca"
2236 }
2237 ],
2238 "license": "MIT",
2239 "dependencies": {
2240 "argparse": "^2.0.1"
2241 },
2242 "bin": {
2243 "js-yaml": "bin/js-yaml.js"
2244 }
2245 },
2246 "node_modules/jsesc": {
2247 "version": "3.1.0",
2248 "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
2249 "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
2250 "dev": true,
2251 "license": "MIT",
2252 "bin": {
2253 "jsesc": "bin/jsesc"
2254 },
2255 "engines": {
2256 "node": ">=6"
2257 }
2258 },
2259 "node_modules/json-buffer": {
2260 "version": "3.0.1",
2261 "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
2262 "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
2263 "dev": true,
2264 "license": "MIT"
2265 },
2266 "node_modules/json-schema-traverse": {
2267 "version": "0.4.1",
2268 "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
2269 "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
2270 "dev": true,
2271 "license": "MIT"
2272 },
2273 "node_modules/json-stable-stringify-without-jsonify": {
2274 "version": "1.0.1",
2275 "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
2276 "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
2277 "dev": true,
2278 "license": "MIT"
2279 },
2280 "node_modules/json5": {
2281 "version": "2.2.3",
2282 "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
2283 "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
2284 "dev": true,
2285 "license": "MIT",
2286 "bin": {
2287 "json5": "lib/cli.js"
2288 },
2289 "engines": {
2290 "node": ">=6"
2291 }
2292 },
2293 "node_modules/jsx-ast-utils": {
2294 "version": "3.3.5",
2295 "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
2296 "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
2297 "dev": true,
2298 "license": "MIT",
2299 "dependencies": {
2300 "array-includes": "^3.1.6",
2301 "array.prototype.flat": "^1.3.1",
2302 "object.assign": "^4.1.4",
2303 "object.values": "^1.1.6"
2304 },
2305 "engines": {
2306 "node": ">=4.0"
2307 }
2308 },
2309 "node_modules/keyv": {
2310 "version": "4.5.4",
2311 "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
2312 "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
2313 "dev": true,
2314 "license": "MIT",
2315 "dependencies": {
2316 "json-buffer": "3.0.1"
2317 }
2318 },
2319 "node_modules/levn": {
2320 "version": "0.4.1",
2321 "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
2322 "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
2323 "dev": true,
2324 "license": "MIT",
2325 "dependencies": {
2326 "prelude-ls": "^1.2.1",
2327 "type-check": "~0.4.0"
2328 },
2329 "engines": {
2330 "node": ">= 0.8.0"
2331 }
2332 },
2333 "node_modules/locate-path": {
2334 "version": "6.0.0",
2335 "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
2336 "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
2337 "dev": true,
2338 "license": "MIT",
2339 "dependencies": {
2340 "p-locate": "^5.0.0"
2341 },
2342 "engines": {
2343 "node": ">=10"
2344 },
2345 "funding": {
2346 "url": "https://github.com/sponsors/sindresorhus"
2347 }
2348 },
2349 "node_modules/lodash.merge": {
2350 "version": "4.6.2",
2351 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
2352 "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
2353 "dev": true,
2354 "license": "MIT"
2355 },
2356 "node_modules/loose-envify": {
2357 "version": "1.4.0",
2358 "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
2359 "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
2360 "dev": true,
2361 "license": "MIT",
2362 "dependencies": {
2363 "js-tokens": "^3.0.0 || ^4.0.0"
2364 },
2365 "bin": {
2366 "loose-envify": "cli.js"
2367 }
2368 },
2369 "node_modules/lru-cache": {
2370 "version": "5.1.1",
2371 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
2372 "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
2373 "dev": true,
2374 "license": "ISC",
2375 "dependencies": {
2376 "yallist": "^3.0.2"
2377 }
2378 },
2379 "node_modules/minimatch": {
2380 "version": "3.1.5",
2381 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
2382 "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
2383 "dev": true,
2384 "license": "ISC",
2385 "dependencies": {
2386 "brace-expansion": "^1.1.7"
2387 },
2388 "engines": {
2389 "node": "*"
2390 }
2391 },
2392 "node_modules/ms": {
2393 "version": "2.1.3",
2394 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
2395 "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
2396 "dev": true,
2397 "license": "MIT"
2398 },
2399 "node_modules/natural-compare": {
2400 "version": "1.4.0",
2401 "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
2402 "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
2403 "dev": true,
2404 "license": "MIT"
2405 },
2406 "node_modules/node-releases": {
2407 "version": "2.0.27",
2408 "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
2409 "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
2410 "dev": true,
2411 "license": "MIT"
2412 },
2413 "node_modules/object-assign": {
2414 "version": "4.1.1",
2415 "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
2416 "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
2417 "dev": true,
2418 "license": "MIT",
2419 "engines": {
2420 "node": ">=0.10.0"
2421 }
2422 },
2423 "node_modules/object-inspect": {
2424 "version": "1.13.1",
2425 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
2426 "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
2427 "dev": true,
2428 "license": "MIT",
2429 "funding": {
2430 "url": "https://github.com/sponsors/ljharb"
2431 }
2432 },
2433 "node_modules/object-keys": {
2434 "version": "1.1.1",
2435 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
2436 "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
2437 "dev": true,
2438 "license": "MIT",
2439 "engines": {
2440 "node": ">= 0.4"
2441 }
2442 },
2443 "node_modules/object.assign": {
2444 "version": "4.1.5",
2445 "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
2446 "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
2447 "dev": true,
2448 "license": "MIT",
2449 "dependencies": {
2450 "call-bind": "^1.0.5",
2451 "define-properties": "^1.2.1",
2452 "has-symbols": "^1.0.3",
2453 "object-keys": "^1.1.1"
2454 },
2455 "engines": {
2456 "node": ">= 0.4"
2457 },
2458 "funding": {
2459 "url": "https://github.com/sponsors/ljharb"
2460 }
2461 },
2462 "node_modules/object.entries": {
2463 "version": "1.1.8",
2464 "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
2465 "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
2466 "dev": true,
2467 "license": "MIT",
2468 "dependencies": {
2469 "call-bind": "^1.0.7",
2470 "define-properties": "^1.2.1",
2471 "es-object-atoms": "^1.0.0"
2472 },
2473 "engines": {
2474 "node": ">= 0.4"
2475 }
2476 },
2477 "node_modules/object.fromentries": {
2478 "version": "2.0.8",
2479 "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
2480 "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
2481 "dev": true,
2482 "license": "MIT",
2483 "dependencies": {
2484 "call-bind": "^1.0.7",
2485 "define-properties": "^1.2.1",
2486 "es-abstract": "^1.23.2",
2487 "es-object-atoms": "^1.0.0"
2488 },
2489 "engines": {
2490 "node": ">= 0.4"
2491 },
2492 "funding": {
2493 "url": "https://github.com/sponsors/ljharb"
2494 }
2495 },
2496 "node_modules/object.values": {
2497 "version": "1.2.0",
2498 "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
2499 "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
2500 "dev": true,
2501 "license": "MIT",
2502 "dependencies": {
2503 "call-bind": "^1.0.7",
2504 "define-properties": "^1.2.1",
2505 "es-object-atoms": "^1.0.0"
2506 },
2507 "engines": {
2508 "node": ">= 0.4"
2509 },
2510 "funding": {
2511 "url": "https://github.com/sponsors/ljharb"
2512 }
2513 },
2514 "node_modules/optionator": {
2515 "version": "0.9.3",
2516 "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
2517 "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
2518 "dev": true,
2519 "license": "MIT",
2520 "dependencies": {
2521 "@aashutoshrathi/word-wrap": "^1.2.3",
2522 "deep-is": "^0.1.3",
2523 "fast-levenshtein": "^2.0.6",
2524 "levn": "^0.4.1",
2525 "prelude-ls": "^1.2.1",
2526 "type-check": "^0.4.0"
2527 },
2528 "engines": {
2529 "node": ">= 0.8.0"
2530 }
2531 },
2532 "node_modules/p-limit": {
2533 "version": "3.1.0",
2534 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
2535 "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
2536 "dev": true,
2537 "license": "MIT",
2538 "dependencies": {
2539 "yocto-queue": "^0.1.0"
2540 },
2541 "engines": {
2542 "node": ">=10"
2543 },
2544 "funding": {
2545 "url": "https://github.com/sponsors/sindresorhus"
2546 }
2547 },
2548 "node_modules/p-locate": {
2549 "version": "5.0.0",
2550 "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
2551 "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
2552 "dev": true,
2553 "license": "MIT",
2554 "dependencies": {
2555 "p-limit": "^3.0.2"
2556 },
2557 "engines": {
2558 "node": ">=10"
2559 },
2560 "funding": {
2561 "url": "https://github.com/sponsors/sindresorhus"
2562 }
2563 },
2564 "node_modules/parent-module": {
2565 "version": "1.0.1",
2566 "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
2567 "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
2568 "dev": true,
2569 "license": "MIT",
2570 "dependencies": {
2571 "callsites": "^3.0.0"
2572 },
2573 "engines": {
2574 "node": ">=6"
2575 }
2576 },
2577 "node_modules/path-exists": {
2578 "version": "4.0.0",
2579 "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
2580 "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
2581 "dev": true,
2582 "license": "MIT",
2583 "engines": {
2584 "node": ">=8"
2585 }
2586 },
2587 "node_modules/path-key": {
2588 "version": "3.1.1",
2589 "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
2590 "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
2591 "dev": true,
2592 "license": "MIT",
2593 "engines": {
2594 "node": ">=8"
2595 }
2596 },
2597 "node_modules/path-parse": {
2598 "version": "1.0.7",
2599 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
2600 "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
2601 "dev": true,
2602 "license": "MIT"
2603 },
2604 "node_modules/picocolors": {
2605 "version": "1.1.1",
2606 "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
2607 "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
2608 "dev": true,
2609 "license": "ISC"
2610 },
2611 "node_modules/possible-typed-array-names": {
2612 "version": "1.0.0",
2613 "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
2614 "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
2615 "dev": true,
2616 "license": "MIT",
2617 "engines": {
2618 "node": ">= 0.4"
2619 }
2620 },
2621 "node_modules/prelude-ls": {
2622 "version": "1.2.1",
2623 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
2624 "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
2625 "dev": true,
2626 "license": "MIT",
2627 "engines": {
2628 "node": ">= 0.8.0"
2629 }
2630 },
2631 "node_modules/prop-types": {
2632 "version": "15.8.1",
2633 "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
2634 "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
2635 "dev": true,
2636 "license": "MIT",
2637 "dependencies": {
2638 "loose-envify": "^1.4.0",
2639 "object-assign": "^4.1.1",
2640 "react-is": "^16.13.1"
2641 }
2642 },
2643 "node_modules/punycode": {
2644 "version": "2.3.1",
2645 "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
2646 "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
2647 "dev": true,
2648 "license": "MIT",
2649 "engines": {
2650 "node": ">=6"
2651 }
2652 },
2653 "node_modules/react-is": {
2654 "version": "16.13.1",
2655 "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
2656 "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
2657 "dev": true,
2658 "license": "MIT"
2659 },
2660 "node_modules/reflect.getprototypeof": {
2661 "version": "1.0.4",
2662 "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
2663 "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
2664 "dev": true,
2665 "license": "MIT",
2666 "dependencies": {
2667 "call-bind": "^1.0.2",
2668 "define-properties": "^1.2.0",
2669 "es-abstract": "^1.22.1",
2670 "get-intrinsic": "^1.2.1",
2671 "globalthis": "^1.0.3",
2672 "which-builtin-type": "^1.1.3"
2673 },
2674 "engines": {
2675 "node": ">= 0.4"
2676 },
2677 "funding": {
2678 "url": "https://github.com/sponsors/ljharb"
2679 }
2680 },
2681 "node_modules/regexp.prototype.flags": {
2682 "version": "1.5.2",
2683 "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
2684 "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
2685 "dev": true,
2686 "license": "MIT",
2687 "dependencies": {
2688 "call-bind": "^1.0.6",
2689 "define-properties": "^1.2.1",
2690 "es-errors": "^1.3.0",
2691 "set-function-name": "^2.0.1"
2692 },
2693 "engines": {
2694 "node": ">= 0.4"
2695 },
2696 "funding": {
2697 "url": "https://github.com/sponsors/ljharb"
2698 }
2699 },
2700 "node_modules/resolve": {
2701 "version": "2.0.0-next.5",
2702 "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
2703 "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
2704 "dev": true,
2705 "license": "MIT",
2706 "dependencies": {
2707 "is-core-module": "^2.13.0",
2708 "path-parse": "^1.0.7",
2709 "supports-preserve-symlinks-flag": "^1.0.0"
2710 },
2711 "bin": {
2712 "resolve": "bin/resolve"
2713 },
2714 "funding": {
2715 "url": "https://github.com/sponsors/ljharb"
2716 }
2717 },
2718 "node_modules/resolve-from": {
2719 "version": "4.0.0",
2720 "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2721 "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2722 "dev": true,
2723 "license": "MIT",
2724 "engines": {
2725 "node": ">=4"
2726 }
2727 },
2728 "node_modules/safe-array-concat": {
2729 "version": "1.1.2",
2730 "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
2731 "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
2732 "dev": true,
2733 "license": "MIT",
2734 "dependencies": {
2735 "call-bind": "^1.0.7",
2736 "get-intrinsic": "^1.2.4",
2737 "has-symbols": "^1.0.3",
2738 "isarray": "^2.0.5"
2739 },
2740 "engines": {
2741 "node": ">=0.4"
2742 },
2743 "funding": {
2744 "url": "https://github.com/sponsors/ljharb"
2745 }
2746 },
2747 "node_modules/safe-regex-test": {
2748 "version": "1.0.3",
2749 "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
2750 "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
2751 "dev": true,
2752 "license": "MIT",
2753 "dependencies": {
2754 "call-bind": "^1.0.6",
2755 "es-errors": "^1.3.0",
2756 "is-regex": "^1.1.4"
2757 },
2758 "engines": {
2759 "node": ">= 0.4"
2760 },
2761 "funding": {
2762 "url": "https://github.com/sponsors/ljharb"
2763 }
2764 },
2765 "node_modules/semver": {
2766 "version": "6.3.1",
2767 "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
2768 "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
2769 "dev": true,
2770 "license": "ISC",
2771 "bin": {
2772 "semver": "bin/semver.js"
2773 }
2774 },
2775 "node_modules/set-function-length": {
2776 "version": "1.2.2",
2777 "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
2778 "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
2779 "dev": true,
2780 "license": "MIT",
2781 "dependencies": {
2782 "define-data-property": "^1.1.4",
2783 "es-errors": "^1.3.0",
2784 "function-bind": "^1.1.2",
2785 "get-intrinsic": "^1.2.4",
2786 "gopd": "^1.0.1",
2787 "has-property-descriptors": "^1.0.2"
2788 },
2789 "engines": {
2790 "node": ">= 0.4"
2791 }
2792 },
2793 "node_modules/set-function-name": {
2794 "version": "2.0.2",
2795 "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
2796 "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
2797 "dev": true,
2798 "license": "MIT",
2799 "dependencies": {
2800 "define-data-property": "^1.1.4",
2801 "es-errors": "^1.3.0",
2802 "functions-have-names": "^1.2.3",
2803 "has-property-descriptors": "^1.0.2"
2804 },
2805 "engines": {
2806 "node": ">= 0.4"
2807 }
2808 },
2809 "node_modules/shebang-command": {
2810 "version": "2.0.0",
2811 "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
2812 "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
2813 "dev": true,
2814 "license": "MIT",
2815 "dependencies": {
2816 "shebang-regex": "^3.0.0"
2817 },
2818 "engines": {
2819 "node": ">=8"
2820 }
2821 },
2822 "node_modules/shebang-regex": {
2823 "version": "3.0.0",
2824 "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
2825 "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
2826 "dev": true,
2827 "license": "MIT",
2828 "engines": {
2829 "node": ">=8"
2830 }
2831 },
2832 "node_modules/side-channel": {
2833 "version": "1.0.6",
2834 "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
2835 "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
2836 "dev": true,
2837 "license": "MIT",
2838 "dependencies": {
2839 "call-bind": "^1.0.7",
2840 "es-errors": "^1.3.0",
2841 "get-intrinsic": "^1.2.4",
2842 "object-inspect": "^1.13.1"
2843 },
2844 "engines": {
2845 "node": ">= 0.4"
2846 },
2847 "funding": {
2848 "url": "https://github.com/sponsors/ljharb"
2849 }
2850 },
2851 "node_modules/string.prototype.matchall": {
2852 "version": "4.0.11",
2853 "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
2854 "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==",
2855 "dev": true,
2856 "license": "MIT",
2857 "dependencies": {
2858 "call-bind": "^1.0.7",
2859 "define-properties": "^1.2.1",
2860 "es-abstract": "^1.23.2",
2861 "es-errors": "^1.3.0",
2862 "es-object-atoms": "^1.0.0",
2863 "get-intrinsic": "^1.2.4",
2864 "gopd": "^1.0.1",
2865 "has-symbols": "^1.0.3",
2866 "internal-slot": "^1.0.7",
2867 "regexp.prototype.flags": "^1.5.2",
2868 "set-function-name": "^2.0.2",
2869 "side-channel": "^1.0.6"
2870 },
2871 "engines": {
2872 "node": ">= 0.4"
2873 },
2874 "funding": {
2875 "url": "https://github.com/sponsors/ljharb"
2876 }
2877 },
2878 "node_modules/string.prototype.repeat": {
2879 "version": "1.0.0",
2880 "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
2881 "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
2882 "dev": true,
2883 "license": "MIT",
2884 "dependencies": {
2885 "define-properties": "^1.1.3",
2886 "es-abstract": "^1.17.5"
2887 }
2888 },
2889 "node_modules/string.prototype.trim": {
2890 "version": "1.2.9",
2891 "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
2892 "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
2893 "dev": true,
2894 "license": "MIT",
2895 "dependencies": {
2896 "call-bind": "^1.0.7",
2897 "define-properties": "^1.2.1",
2898 "es-abstract": "^1.23.0",
2899 "es-object-atoms": "^1.0.0"
2900 },
2901 "engines": {
2902 "node": ">= 0.4"
2903 },
2904 "funding": {
2905 "url": "https://github.com/sponsors/ljharb"
2906 }
2907 },
2908 "node_modules/string.prototype.trimend": {
2909 "version": "1.0.8",
2910 "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
2911 "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
2912 "dev": true,
2913 "license": "MIT",
2914 "dependencies": {
2915 "call-bind": "^1.0.7",
2916 "define-properties": "^1.2.1",
2917 "es-object-atoms": "^1.0.0"
2918 },
2919 "funding": {
2920 "url": "https://github.com/sponsors/ljharb"
2921 }
2922 },
2923 "node_modules/string.prototype.trimstart": {
2924 "version": "1.0.8",
2925 "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
2926 "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
2927 "dev": true,
2928 "license": "MIT",
2929 "dependencies": {
2930 "call-bind": "^1.0.7",
2931 "define-properties": "^1.2.1",
2932 "es-object-atoms": "^1.0.0"
2933 },
2934 "engines": {
2935 "node": ">= 0.4"
2936 },
2937 "funding": {
2938 "url": "https://github.com/sponsors/ljharb"
2939 }
2940 },
2941 "node_modules/strip-json-comments": {
2942 "version": "3.1.1",
2943 "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
2944 "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
2945 "dev": true,
2946 "license": "MIT",
2947 "engines": {
2948 "node": ">=8"
2949 },
2950 "funding": {
2951 "url": "https://github.com/sponsors/sindresorhus"
2952 }
2953 },
2954 "node_modules/supports-color": {
2955 "version": "7.2.0",
2956 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
2957 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
2958 "dev": true,
2959 "license": "MIT",
2960 "dependencies": {
2961 "has-flag": "^4.0.0"
2962 },
2963 "engines": {
2964 "node": ">=8"
2965 }
2966 },
2967 "node_modules/supports-preserve-symlinks-flag": {
2968 "version": "1.0.0",
2969 "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
2970 "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
2971 "dev": true,
2972 "license": "MIT",
2973 "engines": {
2974 "node": ">= 0.4"
2975 },
2976 "funding": {
2977 "url": "https://github.com/sponsors/ljharb"
2978 }
2979 },
2980 "node_modules/type-check": {
2981 "version": "0.4.0",
2982 "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
2983 "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
2984 "dev": true,
2985 "license": "MIT",
2986 "dependencies": {
2987 "prelude-ls": "^1.2.1"
2988 },
2989 "engines": {
2990 "node": ">= 0.8.0"
2991 }
2992 },
2993 "node_modules/typed-array-buffer": {
2994 "version": "1.0.2",
2995 "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
2996 "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
2997 "dev": true,
2998 "license": "MIT",
2999 "dependencies": {
3000 "call-bind": "^1.0.7",
3001 "es-errors": "^1.3.0",
3002 "is-typed-array": "^1.1.13"
3003 },
3004 "engines": {
3005 "node": ">= 0.4"
3006 }
3007 },
3008 "node_modules/typed-array-byte-length": {
3009 "version": "1.0.1",
3010 "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
3011 "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
3012 "dev": true,
3013 "license": "MIT",
3014 "dependencies": {
3015 "call-bind": "^1.0.7",
3016 "for-each": "^0.3.3",
3017 "gopd": "^1.0.1",
3018 "has-proto": "^1.0.3",
3019 "is-typed-array": "^1.1.13"
3020 },
3021 "engines": {
3022 "node": ">= 0.4"
3023 },
3024 "funding": {
3025 "url": "https://github.com/sponsors/ljharb"
3026 }
3027 },
3028 "node_modules/typed-array-byte-offset": {
3029 "version": "1.0.2",
3030 "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
3031 "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
3032 "dev": true,
3033 "license": "MIT",
3034 "dependencies": {
3035 "available-typed-arrays": "^1.0.7",
3036 "call-bind": "^1.0.7",
3037 "for-each": "^0.3.3",
3038 "gopd": "^1.0.1",
3039 "has-proto": "^1.0.3",
3040 "is-typed-array": "^1.1.13"
3041 },
3042 "engines": {
3043 "node": ">= 0.4"
3044 },
3045 "funding": {
3046 "url": "https://github.com/sponsors/ljharb"
3047 }
3048 },
3049 "node_modules/typed-array-length": {
3050 "version": "1.0.6",
3051 "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
3052 "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
3053 "dev": true,
3054 "license": "MIT",
3055 "dependencies": {
3056 "call-bind": "^1.0.7",
3057 "for-each": "^0.3.3",
3058 "gopd": "^1.0.1",
3059 "has-proto": "^1.0.3",
3060 "is-typed-array": "^1.1.13",
3061 "possible-typed-array-names": "^1.0.0"
3062 },
3063 "engines": {
3064 "node": ">= 0.4"
3065 },
3066 "funding": {
3067 "url": "https://github.com/sponsors/ljharb"
3068 }
3069 },
3070 "node_modules/unbox-primitive": {
3071 "version": "1.0.2",
3072 "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
3073 "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
3074 "dev": true,
3075 "license": "MIT",
3076 "dependencies": {
3077 "call-bind": "^1.0.2",
3078 "has-bigints": "^1.0.2",
3079 "has-symbols": "^1.0.3",
3080 "which-boxed-primitive": "^1.0.2"
3081 },
3082 "funding": {
3083 "url": "https://github.com/sponsors/ljharb"
3084 }
3085 },
3086 "node_modules/update-browserslist-db": {
3087 "version": "1.1.4",
3088 "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
3089 "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
3090 "dev": true,
3091 "funding": [
3092 {
3093 "type": "opencollective",
3094 "url": "https://opencollective.com/browserslist"
3095 },
3096 {
3097 "type": "tidelift",
3098 "url": "https://tidelift.com/funding/github/npm/browserslist"
3099 },
3100 {
3101 "type": "github",
3102 "url": "https://github.com/sponsors/ai"
3103 }
3104 ],
3105 "license": "MIT",
3106 "dependencies": {
3107 "escalade": "^3.2.0",
3108 "picocolors": "^1.1.1"
3109 },
3110 "bin": {
3111 "update-browserslist-db": "cli.js"
3112 },
3113 "peerDependencies": {
3114 "browserslist": ">= 4.21.0"
3115 }
3116 },
3117 "node_modules/uri-js": {
3118 "version": "4.4.1",
3119 "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
3120 "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
3121 "dev": true,
3122 "license": "BSD-2-Clause",
3123 "dependencies": {
3124 "punycode": "^2.1.0"
3125 }
3126 },
3127 "node_modules/which": {
3128 "version": "2.0.2",
3129 "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
3130 "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
3131 "dev": true,
3132 "license": "ISC",
3133 "dependencies": {
3134 "isexe": "^2.0.0"
3135 },
3136 "bin": {
3137 "node-which": "bin/node-which"
3138 },
3139 "engines": {
3140 "node": ">= 8"
3141 }
3142 },
3143 "node_modules/which-boxed-primitive": {
3144 "version": "1.0.2",
3145 "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
3146 "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
3147 "dev": true,
3148 "license": "MIT",
3149 "dependencies": {
3150 "is-bigint": "^1.0.1",
3151 "is-boolean-object": "^1.1.0",
3152 "is-number-object": "^1.0.4",
3153 "is-string": "^1.0.5",
3154 "is-symbol": "^1.0.3"
3155 },
3156 "funding": {
3157 "url": "https://github.com/sponsors/ljharb"
3158 }
3159 },
3160 "node_modules/which-builtin-type": {
3161 "version": "1.1.3",
3162 "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
3163 "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
3164 "dev": true,
3165 "license": "MIT",
3166 "dependencies": {
3167 "function.prototype.name": "^1.1.5",
3168 "has-tostringtag": "^1.0.0",
3169 "is-async-function": "^2.0.0",
3170 "is-date-object": "^1.0.5",
3171 "is-finalizationregistry": "^1.0.2",
3172 "is-generator-function": "^1.0.10",
3173 "is-regex": "^1.1.4",
3174 "is-weakref": "^1.0.2",
3175 "isarray": "^2.0.5",
3176 "which-boxed-primitive": "^1.0.2",
3177 "which-collection": "^1.0.1",
3178 "which-typed-array": "^1.1.9"
3179 },
3180 "engines": {
3181 "node": ">= 0.4"
3182 },
3183 "funding": {
3184 "url": "https://github.com/sponsors/ljharb"
3185 }
3186 },
3187 "node_modules/which-collection": {
3188 "version": "1.0.1",
3189 "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
3190 "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
3191 "dev": true,
3192 "license": "MIT",
3193 "dependencies": {
3194 "is-map": "^2.0.1",
3195 "is-set": "^2.0.1",
3196 "is-weakmap": "^2.0.1",
3197 "is-weakset": "^2.0.1"
3198 },
3199 "funding": {
3200 "url": "https://github.com/sponsors/ljharb"
3201 }
3202 },
3203 "node_modules/which-typed-array": {
3204 "version": "1.1.15",
3205 "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
3206 "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
3207 "dev": true,
3208 "license": "MIT",
3209 "dependencies": {
3210 "available-typed-arrays": "^1.0.7",
3211 "call-bind": "^1.0.7",
3212 "for-each": "^0.3.3",
3213 "gopd": "^1.0.1",
3214 "has-tostringtag": "^1.0.2"
3215 },
3216 "engines": {
3217 "node": ">= 0.4"
3218 },
3219 "funding": {
3220 "url": "https://github.com/sponsors/ljharb"
3221 }
3222 },
3223 "node_modules/yallist": {
3224 "version": "3.1.1",
3225 "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
3226 "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
3227 "dev": true,
3228 "license": "ISC"
3229 },
3230 "node_modules/yocto-queue": {
3231 "version": "0.1.0",
3232 "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
3233 "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
3234 "dev": true,
3235 "license": "MIT",
3236 "engines": {
3237 "node": ">=10"
3238 },
3239 "funding": {
3240 "url": "https://github.com/sponsors/sindresorhus"
3241 }
3242 },
3243 "node_modules/zod": {
3244 "version": "4.1.12",
3245 "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz",
3246 "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
3247 "dev": true,
3248 "license": "MIT",
3249 "funding": {
3250 "url": "https://github.com/sponsors/colinhacks"
3251 }
3252 },
3253 "node_modules/zod-validation-error": {
3254 "version": "4.0.2",
3255 "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
3256 "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
3257 "dev": true,
3258 "license": "MIT",
3259 "engines": {
3260 "node": ">=18.0.0"
3261 },
3262 "peerDependencies": {
3263 "zod": "^3.25.0 || ^4.0.0"
3264 }
3265 }
3266 }
3267}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/package.json b/users/ryan/modules/simple-bar/simple-bar-source/package.json
new file mode 100755
index 0000000..b0cde0d
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/package.json
@@ -0,0 +1,17 @@
1{
2 "name": "simple-bar",
3 "licence": "MIT",
4 "version": "1.0.0",
5 "type": "module",
6 "description": "A yabai status bar widget for Übersicht.",
7 "scripts": {
8 "lint": "eslint . --ext .js,.jsx"
9 },
10 "devDependencies": {
11 "@eslint/js": "^9",
12 "eslint": "^9",
13 "eslint-plugin-react": "^7",
14 "eslint-plugin-react-hooks": "^7",
15 "globals": "^16"
16 }
17}
diff --git a/users/ryan/modules/taskwarrior-ubersicht/default.nix b/users/ryan/modules/taskwarrior-ubersicht/default.nix
index 1f16c24..665af89 100644..100755
--- a/users/ryan/modules/taskwarrior-ubersicht/default.nix
+++ b/users/ryan/modules/taskwarrior-ubersicht/default.nix
@@ -4,12 +4,7 @@ with lib;
4 4
5let 5let
6 cfg = config.ryan.simple-bar; 6 cfg = config.ryan.simple-bar;
7 # Fetch the git repo at a specific rev 7 "taskwarrior-ubersicht-upstream" = ./taskwarrior-widget-source
8 "taskwarrior-ubersicht-upstream" = builtins.fetchGit {
9 url = "https://github.com/nstanger/taskwarrior.widget";
10 rev = "30428166fc84491eec36d91248df65f95064c97c";
11 shallow = true;
12 };
13in 8in
14{ 9{
15 options.ryan.taskwarrior-widget.enable = mkEnableOption "taskwarrior-widget"; 10 options.ryan.taskwarrior-widget.enable = mkEnableOption "taskwarrior-widget";
diff --git a/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/README.md b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/README.md
new file mode 100755
index 0000000..bf20fb7
--- /dev/null
+++ b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/README.md
@@ -0,0 +1,7 @@
1# Taskwarrior widget for Übersicht
2
3Inspired by the original Taskwarrior Widget by Kevin Bockelandt (<https://github.com/KevinBockelandt/TaskwarriorWidget>), but enhanced and rewritten from scratch for Übersicht’s more recent React + JSX framework.
4
5The widget displays a configurable number (default 20) of ready Taskwarrior tasks (i.e., those that have the `READY` virtual tag), sorted in descending order of urgency. The columns displayed are task ID, number of days/weeks/months/years (as appropriate) to due date, description, project, tags, urgency, and a configurable indicator (default 🟊) of whether you’ve started a task.
6
7Due and overdue tasks are highlighted using configurable colours.
diff --git a/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/style.css b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/style.css
new file mode 100755
index 0000000..2de4075
--- /dev/null
+++ b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/style.css
@@ -0,0 +1,43 @@
1#taskwarrior-widget-container strong.warning {
2 color: orange;
3}
4#taskwarrior-widget-container strong.error {
5 color: red;
6}
7
8#taskwarrior-widget-container table {
9 border-collapse: collapse;
10}
11
12#taskwarrior-widget-container tr.header {
13 font-size: 8pt;
14 font-weight: bold;
15}
16
17#taskwarrior-widget-container th, td {
18 padding-bottom: 4px;
19 padding-left: 0px;
20 padding-right: 12px;
21 padding-top: 4px;
22 text-align: left;
23}
24
25#taskwarrior-widget-container th:last-of-type, td:last-of-type {
26 padding-right: 8px;
27}
28
29#taskwarrior-widget-container th.num, td.num {
30 text-align: right;
31}
32
33#taskwarrior-widget-container .star {
34 font-family: Symbola, sans-serif;
35 font-size: 8pt;
36 padding-left: 4px;
37 padding-right: 1px;
38 text-align: center;
39}
40
41#taskwarrior-widget-container tbody tr:nth-child(odd) {
42 background-color: rgba(255, 255, 255, 0.1);
43}
diff --git a/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/taskwarrior.jsx b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/taskwarrior.jsx
new file mode 100755
index 0000000..14e23a5
--- /dev/null
+++ b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/taskwarrior.jsx
@@ -0,0 +1,203 @@
1// Originally inspired by Taskwarrior Widget by Kevin Bockelandt:
2// https://github.com/KevinBockelandt/TaskwarriorWidget
3// Rewritten from scratch using the new React + JSX framework.
4
5'use strict';
6
7export const command = "task +READY -PARENT export";
8
9export const refreshFrequency = 10000;
10
11// Ridiculously high number of days (in ms), used to indicate there is no due date
12export const maxDue = 100000 * 60 * 60 * 24 * 1000;
13
14export const className = `
15 left: 30px;
16 top: 45px;
17 font-family: Helvetica Neue;
18 font-size: 10pt;
19 font-weight: 400;
20 background: rgba(0, 0, 0, 0.5);
21 border-radius: 7px;
22 padding: 5px;
23`;
24
25// Configuration
26// Note date differences are in ms
27const millisecondsInDay = 24 * 60 * 60 * 1000;
28const millisecondsInWeek = millisecondsInDay * 7;
29const millisecondsInMonth = millisecondsInDay * 30.42; // on average
30const millisecondsInYear = millisecondsInDay * 365.25; // appproximately
31// Maximum number of entries to display
32const maxEntries = 20;
33// Indicator for tasks that are started
34const startedIndicator = "🟊";
35
36// Colours
37const headerColour = Object.freeze({ r: 255, g: 255, b: 255, a: 1 });
38// The opacity is determined dynamically for all the following
39const overDueColour = Object.freeze({ r: 255, g: 100, b: 100 });
40const dueColour = Object.freeze({ r: 255, g: 200, b: 0 });
41const normalColour = Object.freeze({ r: 255, g: 255, b: 255 });
42const tagsColour = Object.freeze({ r: 50, g: 225, b: 50 });
43
44// Tasks fade out towards the bottom of the table in steps of 1 / maxEntries
45const opacities = Object.freeze((() => {
46 let values = [];
47 for (let i = 0; i < maxEntries; i++) {
48 values.push(((i / maxEntries * -1) + 1).toFixed(2));
49 }
50 return values;
51})());
52
53// Reformat and compute task values ready for output
54const processTask = (task, index) => {
55 // Compute number of days to due date
56 if (task.due) {
57 let dueDateOffset = maxDue;
58 // Taskwarrior date strings aren't quite in ISO 8601 format
59 // e.g.: 20191007T110000Z, which should be 2019-10-07T11:00:00Z
60 let dateParts = [task.due.slice(0, 4), task.due.slice(4, 6), task.due.slice(6, 8)].join("-");
61 let timeParts = [task.due.slice(8, 11), task.due.slice(11, 13), task.due.slice(13)].join(":");
62 let dueDate = new Date(dateParts + timeParts);
63 let today = new Date();
64 // Truncate the offset between the due date and today to the nearest day
65 today.setHours(0);
66 today.setMinutes(0);
67 today.setSeconds(0);
68 today.setMilliseconds(0);
69 dueDate.setMinutes(0);
70 dueDate.setSeconds(0);
71 dueDate.setMilliseconds(0);
72
73 let difference = dueDate.getTime() - today.getTime();
74 if (Math.abs(difference) > millisecondsInYear) {
75 dueDateOffset = Math.floor(difference / millisecondsInYear);
76 task.units = dueDateOffset + "y";
77 } else if (Math.abs(difference) > millisecondsInMonth) {
78 dueDateOffset = Math.floor(difference / millisecondsInMonth);
79 task.units = dueDateOffset + "m";
80 } else if (Math.abs(difference) > millisecondsInWeek) {
81 dueDateOffset = Math.floor(difference / millisecondsInWeek);
82 task.units = dueDateOffset + "w";
83 } else {
84 dueDateOffset = Math.floor(difference / millisecondsInDay);
85 task.units = dueDateOffset + "d";
86 }
87 task.due = difference;
88 }
89
90 // If the task has tags, merge them into a single string
91 if (task.tags) {
92 task.tags = task.tags.map((tag) => { return "+" + tag; }).join(" ");
93 }
94
95 // Mark started tasks
96 if (task.start) {
97 task.start = startedIndicator;
98 }
99
100 // don't need to check for 0 here as it'll get set to 0.0 anyway
101 task.urgency = task.urgency ? parseFloat(task.urgency).toFixed(2) : 0.0;
102
103 return task;
104};
105
106// Colourise the tasks in the output list
107const colourTask = (task, index) => {
108 // Colour row text according to due date
109 if (task.due < 0) {
110 task.colour = Object.assign({}, overDueColour);
111 }
112 else if (task.due == 0) {
113 task.colour = Object.assign({}, dueColour);
114 }
115 else {
116 task.colour = Object.assign({}, normalColour);
117 }
118 task.colour.a = opacities[index];
119
120 return task;
121}
122
123const rgbaString = (colour, a) => {
124 if (colour.a) {
125 return "rgba(" + colour.r + ", " + colour.g + ", " + colour.b + ", " + colour.a + ")";
126 }
127 else {
128 return "rgba(" + colour.r + ", " + colour.g + ", " + colour.b + ", " + a + ")";
129 }
130};
131
132export const render = ({ output, error }) => {
133 // What if error is already set?
134 // Will the following give an exception anyway?
135 try {
136 // Get the JSON object containing all the tasks and process them.
137 let taskList = JSON.parse(output).map(processTask);
138 // Sort the tasks by due date ascending, then by urgency descending.
139 taskList.sort((a, b) => {
140 // Adjust for no due date
141 // CAUTION: 0 is "falsy" but valid, so needs to be explicitly checked for
142 let aDue = (a.due || a.due === 0) ? a.due : maxDue;
143 let bDue = (b.due || b.due === 0) ? b.due : maxDue;
144 // Need urgency as a fraction. Maximum possible urgency is 60.7
145 // with default settings, so let’s assume it’s less than 1000.
146 return (aDue - a.urgency/1000) - (bDue - b.urgency/1000);
147 });
148 // We have to colourise after the sort.
149 // Only display the first maxEntries tasks.
150 taskList = taskList.slice(0, maxEntries).map(colourTask);
151
152 return (
153 <div id="taskwarrior-widget-container">
154 <link rel="stylesheet" type="text/css" href="taskwarrior.widget/style.css" />
155 <table>
156 <thead>
157 <tr className="header" style={{ color: rgbaString(headerColour) }}>
158 <th className="star">{startedIndicator}</th>
159 <th className="num">ID</th>
160 <th className="num">DUE</th>
161 <th>DESCRIPTION</th>
162 <th>PROJECT</th>
163 <th style={{ color: rgbaString(tagsColour, 1) }}>TAGS</th>
164 <th className="num">URG</th>
165 </tr>
166 </thead>
167 <tbody>
168 {taskList.map((task, index) => {
169 return (
170 <tr style={{ color: rgbaString(task.colour) }} key={index}>
171 <td className="star">{task.start}</td>
172 <td className="num">{task.id}</td>
173 <td className="num">{task.units}</td>
174 <td>{task.description}</td>
175 <td>{task.project}</td>
176 <td style={{ color: rgbaString(tagsColour, task.colour.a) }}>{task.tags}</td>
177 <td className="num">{task.urgency}</td>
178 </tr>
179 );
180 })}
181 </tbody>
182 </table>
183 </div>
184 )
185 }
186 catch (e) {
187 if (!output) {
188 return (
189 <div id="taskwarrior-widget-container">
190 <p><strong>No tasks found.</strong></p>
191 </div>
192 )
193 }
194 else {
195 console.error(e)
196 return (
197 <div id="taskwarrior-widget-container">
198 <p><strong class="error">Error: {e}.</strong></p>
199 </div>
200 )
201 }
202 }
203};
diff --git a/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/widget.json b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/widget.json
new file mode 100755
index 0000000..9ceeaa8
--- /dev/null
+++ b/users/ryan/modules/taskwarrior-ubersicht/taskwarrior-widget-source/widget.json
@@ -0,0 +1,6 @@
1{
2 "name": "Taskwarrior Widget",
3 "description": "Displays a list of tasks from Taskwarrior",
4 "author": "Nigel Stanger",
5 "email": "nigel.stanger@gmail.com"
6}