diff options
| -rw-r--r-- | app.tsx | 5 | ||||
| -rw-r--r-- | modules/launcher.tsx | 230 | ||||
| -rw-r--r-- | package-lock.json | 494 | ||||
| -rw-r--r-- | package.json | 9 | ||||
| -rwxr-xr-x | run.fish | 11 | ||||
| -rw-r--r-- | scss/launcher.scss | 38 |
6 files changed, 735 insertions, 52 deletions
@@ -4,6 +4,7 @@ import AstalHyprland from "gi://AstalHyprland"; import Bar from "./modules/bar"; import Launcher from "./modules/launcher"; import NotifPopups from "./modules/notifpopups"; +import Players from "./services/players"; import { PopupWindow } from "./utils/widgets"; const loadStyleAsync = async () => { @@ -29,6 +30,10 @@ App.start({ let log = true; if (request === "reload css") loadStyleAsync().catch(console.error); + else if (request === "media play pause") Players.get_default().lastPlayer?.play_pause(); + else if (request === "media next") Players.get_default().lastPlayer?.next(); + else if (request === "media previous") Players.get_default().lastPlayer?.previous(); + else if (request === "media stop") Players.get_default().lastPlayer?.stop(); else if (request.startsWith("toggle")) { const window = App.get_window(request.slice(7)); if (window instanceof PopupWindow) window.toggle(); diff --git a/modules/launcher.tsx b/modules/launcher.tsx index 4cde7c4..8f01596 100644 --- a/modules/launcher.tsx +++ b/modules/launcher.tsx @@ -1,12 +1,23 @@ -import { bind, Gio, timeout, Variable } from "astal"; +import { bind, execAsync, Gio, register, timeout, Variable } from "astal"; import { Astal, Gtk, Widget } from "astal/gtk3"; +import fuzzysort from "fuzzysort"; import type AstalApps from "gi://AstalApps"; import AstalHyprland from "gi://AstalHyprland"; +import Mexp from "math-expression-evaluator"; import { Apps } from "../services/apps"; import { getAppCategoryIcon } from "../utils/icons"; import { launch } from "../utils/system"; import { PopupWindow, setupCustomTooltip, TransitionType } from "../utils/widgets"; +type Mode = "apps" | "files" | "math"; + +interface Subcommand { + icon: string; + name: string; + description: string; + command: (...args: string[]) => void; +} + const maxSearchResults = 15; const browser = [ @@ -23,6 +34,17 @@ const files = ["thunar", "nemo", "nautilus"]; const ide = ["codium", "code", "clion", "intellij-idea-ultimate-edition"]; const music = ["spotify-adblock", "spotify", "audacious", "elisa"]; +const getIconFromMode = (mode: Mode) => { + switch (mode) { + case "apps": + return "apps"; + case "files": + return "folder"; + case "math": + return "calculate"; + } +}; + const launchAndClose = (self: JSX.Element, astalApp: AstalApps.Application) => { const toplevel = self.get_toplevel(); if (toplevel instanceof Widget.Window) toplevel.hide(); @@ -45,7 +67,7 @@ const PinnedApp = ({ names }: { names: string[] }) => { return app ? ( <button - className="app" + className="pinned-app result" cursor="pointer" onClicked={self => launchAndClose(self, astalApp!)} setup={self => setupCustomTooltip(self, app.get_display_name())} @@ -56,7 +78,7 @@ const PinnedApp = ({ names }: { names: string[] }) => { }; const PinnedApps = () => ( - <box homogeneous className="pinned"> + <box homogeneous> <PinnedApp names={browser} /> <PinnedApp names={terminal} /> <PinnedApp names={files} /> @@ -82,21 +104,72 @@ const SearchEntry = ({ entry }: { entry: Widget.Entry }) => ( </stack> ); -const Result = ({ app }: { app: AstalApps.Application }) => ( - <button className="app" cursor="pointer" onClicked={self => launchAndClose(self, app)}> +// TODO: description field +const Result = ({ + icon, + materialIcon, + label, + sublabel, + onClicked, +}: { + icon?: string; + materialIcon?: string; + label: string; + sublabel?: string; + onClicked: (self: Widget.Button) => void; +}) => ( + <button className="result" cursor="pointer" onClicked={onClicked}> <box> - {Astal.Icon.lookup_icon(app.iconName) ? ( - <icon className="icon" icon={app.iconName} /> + {icon && Astal.Icon.lookup_icon(icon) ? ( + <icon className="icon" icon={icon} /> + ) : ( + <label className="icon" label={materialIcon} /> + )} + {sublabel ? ( + <box vertical valign={Gtk.Align.CENTER} className="has-sublabel"> + <label xalign={0} label={label} /> + <label hexpand truncate maxWidthChars={1} className="sublabel" xalign={0} label={sublabel} /> + </box> ) : ( - <label className="icon" label={getAppCategoryIcon(app)} /> + <label xalign={0} label={label} /> )} - <label xalign={0} label={app.name} /> </box> </button> ); -const Results = ({ entry }: { entry: Widget.Entry }) => { +const SubcommandResult = ({ + entry, + subcommand, + args, +}: { + entry: Widget.Entry; + subcommand: Subcommand; + args: string[]; +}) => ( + <Result + materialIcon={subcommand.icon} + label={subcommand.name} + sublabel={subcommand.description} + onClicked={() => { + subcommand.command(...args); + entry.set_text(""); + }} + /> +); + +const AppResult = ({ app }: { app: AstalApps.Application }) => ( + <Result + icon={app.iconName} + materialIcon={getAppCategoryIcon(app)} + label={app.name} + sublabel={app.description} + onClicked={self => launchAndClose(self, app)} + /> +); + +const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> }) => { const empty = Variable(true); + return ( <stack className="results" @@ -112,17 +185,82 @@ const Results = ({ entry }: { entry: Widget.Entry }) => { vertical name="list" setup={self => { - let apps: AstalApps.Application[] = []; - self.hook(entry, "activate", () => { - if (entry.text && apps[0]) launchAndClose(self, apps[0]); - }); + const subcommands: Record<string, Subcommand> = { + apps: { + icon: "apps", + name: "Apps", + description: "Search for apps", + command: () => mode.set("apps"), + }, + files: { + icon: "folder", + name: "Files", + description: "Search for files", + command: () => mode.set("files"), + }, + calc: { + icon: "calculate", + name: "Calculator", + description: "A calculator...", + command: () => mode.set("math"), + }, + todo: { + icon: "checklist", + name: "Todo", + description: "Create a todo in <INSERT_TODO_APP>", + command: (...args) => { + // TODO: todo service or maybe use external app + }, + }, + }; + const subcommandList = Object.keys(subcommands); + const mexp = new Mexp(); + + const appSearch = () => { + const apps = Apps.fuzzy_query(entry.text); + empty.set(apps.length === 0); + if (apps.length > maxSearchResults) apps.length = maxSearchResults; + for (const app of apps) self.add(<AppResult app={app} />); + }; + + const calculate = () => { + // TODO: allow defs, history + let math = null; + try { + math = mexp.eval(entry.text); + } catch (e) { + // Ignore + } + if (math !== null) + self.add( + <Result + materialIcon="calculate" + label={entry.text} + sublabel={String(math)} + onClicked={() => execAsync(`wl-copy -- ${math}`).catch(console.error)} + /> + ); + }; + + self.hook(entry, "activate", () => entry.text && self.get_children()[0].activate()); self.hook(entry, "changed", () => { if (!entry.text) return; self.foreach(ch => ch.destroy()); - apps = Apps.fuzzy_query(entry.text); - empty.set(apps.length === 0); - if (apps.length > maxSearchResults) apps.length = maxSearchResults; - for (const app of apps) self.add(<Result app={app} />); + + if (entry.text.startsWith(">")) { + const args = entry.text.split(" "); + for (const { target } of fuzzysort.go(args[0].slice(1), subcommandList, { all: true })) + self.add( + <SubcommandResult + entry={entry} + subcommand={subcommands[target]} + args={args.slice(1)} + /> + ); + } else if (mode.get() === "apps") appSearch(); + else if (mode.get() === "math") calculate(); + + empty.set(self.get_children().length === 0); }); }} /> @@ -130,16 +268,16 @@ const Results = ({ entry }: { entry: Widget.Entry }) => { ); }; -const Launcher = ({ entry }: { entry: Widget.Entry }) => ( +const LauncherContent = ({ mode, entry }: { mode: Variable<Mode>; entry: Widget.Entry }) => ( <box vertical - className="launcher" + className={bind(mode).as(m => `launcher ${m}`)} css={bind(AstalHyprland.get_default(), "focusedMonitor").as(m => `margin-top: ${m.height / 4}px;`)} > <box className="search-bar"> <label className="icon" label="search" /> <SearchEntry entry={entry} /> - <label className="icon" label="apps" /> + <label className="icon" label={bind(mode).as(getIconFromMode)} /> </box> <revealer revealChild={bind(entry, "textLength").as(t => t === 0)} @@ -153,20 +291,24 @@ const Launcher = ({ entry }: { entry: Widget.Entry }) => ( transitionType={Gtk.RevealerTransitionType.SLIDE_UP} transitionDuration={150} > - <Results entry={entry} /> + <Results entry={entry} mode={mode} /> </revealer> </box> ); -export default () => { - const entry = (<entry name="entry" />) as Widget.Entry; +@register() +export default class Launcher extends PopupWindow { + readonly mode: Variable<Mode>; - return ( - <PopupWindow - name="launcher" - keymode={Astal.Keymode.EXCLUSIVE} - exclusivity={Astal.Exclusivity.IGNORE} - onKeyPressEvent={(_, event) => { + constructor() { + const entry = (<entry name="entry" />) as Widget.Entry; + const mode = Variable<Mode>("apps"); + + super({ + name: "launcher", + keymode: Astal.Keymode.EXCLUSIVE, + exclusivity: Astal.Exclusivity.IGNORE, + onKeyPressEvent(_, event) { const keyval = event.get_keyval()[1]; // Focus entry on typing if (!entry.isFocus && keyval >= 32 && keyval <= 126) { @@ -177,14 +319,20 @@ export default () => { // Consume event, if not consumed it will duplicate character in entry return true; } - }} - // Clear entry text on hide - setup={self => self.connect("hide", () => entry.set_text(""))} - transitionType={TransitionType.SLIDE_DOWN} - halign={Gtk.Align.CENTER} - valign={Gtk.Align.START} - > - <Launcher entry={entry} /> - </PopupWindow> - ); -}; + }, + transitionType: TransitionType.SLIDE_DOWN, + halign: Gtk.Align.CENTER, + valign: Gtk.Align.START, + child: <LauncherContent mode={mode} entry={entry} />, + }); + + this.mode = mode; + + this.connect("hide", () => entry.set_text("")); + } + + open(mode: Mode) { + this.mode.set(mode); + this.show(); + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c5de752 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,494 @@ +{ + "name": "caelestia", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "fuzzysort": "^3.1.0", + "math-expression-evaluator": "^2.0.6" + }, + "devDependencies": { + "esbuild": "0.24.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" + } + }, + "node_modules/fuzzysort": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz", + "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==", + "license": "MIT" + }, + "node_modules/math-expression-evaluator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-2.0.6.tgz", + "integrity": "sha512-DRung1qNcKbgkhFeQ0fBPUFB6voRUMY7KyRyp1TRQ2v95Rp2egC823xLRooM1mDx1rmbkY7ym6ZWmpaE/VimOA==", + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f0cb26d --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "fuzzysort": "^3.1.0", + "math-expression-evaluator": "^2.0.6" + }, + "devDependencies": { + "esbuild": "0.24.2" + } +} diff --git a/run.fish b/run.fish new file mode 100755 index 0000000..66e23ef --- /dev/null +++ b/run.fish @@ -0,0 +1,11 @@ +#!/bin/fish + +cd (dirname (status filename)) || exit 1 + +set -q XDG_RUNTIME_DIR && set bundle_dir $XDG_RUNTIME_DIR || set bundle_dir /tmp + +./node_modules/.bin/esbuild app.tsx --bundle --outfile=$bundle_dir/caelestia.js \ + --external:console --external:system --external:cairo --external:gettext --external:'file://*' --external:'gi://*' --external:'resource://*' \ + --define:SRC=\"(pwd)\" --format=esm --platform=neutral --main-fields=module,main + +gjs -m $bundle_dir/caelestia.js diff --git a/scss/launcher.scss b/scss/launcher.scss index 44b135d..8e710e9 100644 --- a/scss/launcher.scss +++ b/scss/launcher.scss @@ -29,7 +29,6 @@ .icon { font-size: lib.s(18); - color: scheme.$sapphire; } .placeholder { @@ -37,7 +36,7 @@ } } - .app { + .result { @include lib.element-decel; padding: lib.s(5) lib.s(10); @@ -52,35 +51,52 @@ } } - .pinned .app { + .pinned-app { @include lib.rounded(5); font-size: lib.s(64); } .results { + .icon { + font-size: lib.s(32); + } + .empty { color: scheme.$subtext0; @include lib.spacing; - - .icon { - font-size: lib.s(32); - } } - .app { + .result { @include lib.rounded(10); font-size: lib.s(18); & > * { - @include lib.spacing; + @include lib.spacing(8); } - .icon { - font-size: lib.s(32); + .has-sublabel { + font-size: lib.s(16); + + .sublabel { + color: scheme.$subtext0; + font-size: lib.s(14); + } } } } + + &.apps label.icon { + color: scheme.$sapphire; + } + + &.files label.icon { + color: scheme.$peach; + } + + &.math label.icon { + color: scheme.$green; + } } |