60 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { Binding, Variable } from "astal";
 | |
| import { Gtk } from "astal/gtk4";
 | |
| import AstalApps from "gi://AstalApps";
 | |
| import Pango from "gi://Pango?version=1.0";
 | |
| 
 | |
| const MAX_ITEMS = 8;
 | |
| 
 | |
| const AppList = ({ hide, query, visible }: { hide: () => void, query: Variable<string>, visible: Binding<Boolean> }) => {
 | |
|     const apps = new AstalApps.Apps();
 | |
|     const list = query((text) => apps.fuzzy_query(text).slice(0, MAX_ITEMS));
 | |
|     return <box>
 | |
|         <box
 | |
|             spacing={6}
 | |
|             vertical
 | |
|             cssClasses={["app-list"]}
 | |
|             visible={list.as(l => l.length > 0)}
 | |
|         >
 | |
|             {list.as(l => l.map(app => <AppButton app={app} hide={hide}></AppButton>))}
 | |
|         </box>
 | |
|         <box
 | |
|             halign={Gtk.Align.CENTER}
 | |
|             cssClasses={["list-empty"]}
 | |
|             vertical
 | |
|             visible={list.as(l => l.length === 0)}
 | |
|         >
 | |
|             <image iconName={"system-search-symbolic"}></image>
 | |
|             <label label={"No match found"}></label>
 | |
|         </box>
 | |
|     </box>
 | |
| }
 | |
| 
 | |
| const AppButton = ({ app, hide }: { app: AstalApps.Application, hide: () => void }) => {
 | |
|     return <button
 | |
|         onClicked={() => {
 | |
|             hide();
 | |
|             app.launch();
 | |
|         }}
 | |
|         child={
 | |
|             <box>
 | |
|                 <image iconName={app.iconName}></image>
 | |
|                 <box valign={Gtk.Align.CENTER} vertical>
 | |
|                     <label
 | |
|                         cssClasses={["title-2"]}
 | |
|                         ellipsize={Pango.EllipsizeMode.END}
 | |
|                         maxWidthChars={40}
 | |
|                         xalign={0}
 | |
|                         label={app.name}
 | |
|                     ></label>
 | |
|                     <label
 | |
|                         wrap xalign={0}
 | |
|                         label={app.description}
 | |
|                     ></label>
 | |
|                 </box>
 | |
|             </box>
 | |
|         }>
 | |
|     </button>
 | |
| }
 | |
| 
 | |
| export default AppList;
 |