### Initialize Gtk and Run Main Loop Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gtk.md Initializes the Gtk toolkit and starts a GLib main loop. This is the fundamental setup required before creating any widgets or running a Gtk application. ```typescript import GLib from "gi://GLib" import Gtk from "gi://Gtk?version=4.0" Gtk.init() const loop = GLib.MainLoop.new(null, false) // create widgets here loop.runAsync() ``` -------------------------------- ### Creating and Using Gio.Settings Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md Instantiate Gio.Settings with a schema ID and use the createSettings helper to get and set application settings. This example shows how to interact with 'simple-string' and 'string-dictionary'. ```ts const settings = new Gio.Settings({ schemaId: "my.awesome.app" }) const { simpleString, setSimpleString } = createSettings(settings, { "simple-string": "s", "string-dictionary": "a{ss}", }) console.log(simpleString.get()) setSimpleString("new value") ``` -------------------------------- ### Install Gnim and Dependencies Source: https://context7.com/aylur/gnim/llms.txt Install Gnim and necessary development dependencies for a Gtk4 project using npm. ```sh mkdir gnim-app && cd gnim-app npm install gnim npm install typescript esbuild @girs/gtk-4.0 @girs/gjs -D ``` -------------------------------- ### Initialize Gnim Project and Install Dependencies Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Creates a new Gnim project directory, installs Gnim, TypeScript, esbuild, and GTK4/GJS type definitions. ```sh mkdir gnim-app cd gnim-app npm install gnim npm install typescript esbuild @girs/gtk-4.0 @girs/gjs -D ``` -------------------------------- ### Install Gnim Dependencies on Ubuntu Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Installs necessary packages for Gnim development on Ubuntu using apt. ```sh sudo apt install libgjs-dev libgtk-3-dev npm ``` -------------------------------- ### Gnim Project Structure Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Illustrates the expected file and directory layout for a Gnim project after setup. ```txt . ├── node_modules ├── package-lock.json ├── package.json ├── scripts │ └── build.sh ├── src │ ├── env.d.ts │ └── main.ts └── tsconfig.json ``` -------------------------------- ### Transpiled GObject Class Example Source: https://github.com/aylur/gnim/blob/main/docs/gobject.md Shows the JavaScript output generated from the GObject decorator example. It includes constructor logic for properties and the GObject.registerClass call. ```javascript const priv = Symbol("private props") class MyObj extends GObject.Object { [priv] = { "my-prop": "" } constructors() { super() Object.defineProperty(this, "myProp", { enumerable: true, configurable: false, set(value) { if (this[priv]["my-prop"] !== value) { this[priv]["my-prop"] = v this.notify("my-prop") } }, get() { return this[priv]["my-prop"] }, }) } mySignal(a, b) { return this.emit("my-signal", a, b) } on_my_signal(a, b) { // default handler } } GObject.registerClass( { GTypeName: "MyObj", Properties: { "my-prop": GObject.ParamSpec.string( "my-prop", "", "", GObject.ParamFlags.READWRITE, "", ), }, Signals: { "my-signal": { param_types: [String.$gtype, GObject.TYPE_UINT], }, }, }, MyObj, ) ``` -------------------------------- ### Example GObject Class with Decorators Source: https://github.com/aylur/gnim/blob/main/docs/gobject.md Demonstrates registering a GObject class with a property and a signal using decorators. Imports from 'gnim/gobject' are required. ```typescript import GObject, { register, property, signal } from "gnim/gobject" @register({ GTypeName: "MyObj" }) class MyObj extends GObject.Object { @property(String) myProp = "" @signal(String, GObject.TYPE_UINT) mySignal(a: string, b: number) { // default handler } } ``` -------------------------------- ### Example Usage of GObject Decorators Source: https://github.com/aylur/gnim/blob/main/docs/gobject.md Demonstrates the basic usage of @register, @property, and @signal decorators to define a GObject class with a property and a signal. ```APIDOC ## Example Usage ```ts import GObject, { register, property, signal } from "gnim/gobject" @register({ GTypeName: "MyObj" }) class MyObj extends GObject.Object { @property(String) myProp = "" @signal(String, GObject.TYPE_UINT) mySignal(a: string, b: number) { // default handler } } ``` ``` -------------------------------- ### Initializing Widget Relations with Setup Function Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md The '$' prop can be used to set up inter-widget relationships, like configuring a search bar's key capture widget within a window. ```tsx function MyWidget() { let searchbar: Gtk.SearchBar function init(win: Gtk.Window) { searchbar.set_key_capture_widget(win) } return ( (searchbar = self)}> ) } ``` -------------------------------- ### Install Gnim Dependencies on Fedora Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Installs necessary packages for Gnim development on Fedora using dnf. ```sh sudo dnf install gjs-devel gtk4-devel npm ``` -------------------------------- ### DBus method Decorator Examples Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Examples of using the 'method' decorator for DBus methods, including methods with and without return values. ```typescript class { @method("s", "i") Simple(arg0: string, arg1: number): void {} @method(["s", "i"], ["s"]) SimpleReturn(arg0: string, arg1: number): [string] { return ["return valule"] } } ``` -------------------------------- ### Install Gnim Dependencies on Arch Linux Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Installs necessary packages for Gnim development on Arch Linux using pacman. ```sh sudo pacman -Syu gjs gtk4 npm ``` -------------------------------- ### State Management with createBinding and GObject Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gnim.md Integrate GObject properties with Gnim's reactive system using createBinding. This example shows how to bind to a GObject's 'counter' property and display it. ```tsx import GObject, { register, property } from "gnim/gobject" import { createBinding } from "gnim" @register() class CountStore extends GObject.Object { @property(Number) counter = 0 } function Counter() { const count = new CountStore() function increment() { count.counter += 1 } const counter = createBinding(count, "counter") const label = counter((num) => num.toString()) return ( ) } ``` -------------------------------- ### DBus methodAsync Decorator Examples Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Examples of using the 'methodAsync' decorator for asynchronous DBus methods, including methods with and without return values. ```typescript class { @methodAsync("s", "i") async Simple(arg0: string, arg1: number): Promise {} @methodAsync(["s", "i"], ["s"]) async SimpleReturn(arg0: string, arg1: number): Promise<[string]> { return ["return valule"] } } ``` -------------------------------- ### Imperative Setup Function in JSX Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Use the '$' prop to define an arbitrary function that runs after properties are set and before the jsx function returns. This is useful for acquiring widget references or initializing relations. ```tsx print(self, "is about to be returned")} /> ``` -------------------------------- ### Create Settings Accessors Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Wrap a `Gio.Settings` object with `createSettings` to get a collection of setters and accessors for managing application settings. ```typescript function createSettings>( settings: Gio.Settings, keys: T, ): Settings ``` ```typescript const s = createSettings(settings, { "complex-key": "a{sa{ss}}", "simple-key": "s", }) s.complexKey.subscribe(() => { print(s.complexKey.get()) }) s.setComplexKey((prev) => ({ ...prev, neyKey: { nested: "" }, })) ``` -------------------------------- ### Function Component Setup with '$' Prop Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Function components can also utilize the '$' prop for imperative setup, similar to class components. Ensure FCProps is used for TypeScript to recognize the '$' prop. ```tsx import { FCProps } from "gnim" type MyComponentProps = FCProps< Gtk.Button, { prop?: string } > function MyComponent({ prop }: MyComponentProps) { return } return print(self, "is a Button")} prop="hello" /> ``` -------------------------------- ### Gnim Counter Example Source: https://github.com/aylur/gnim/blob/main/docs/index.md Demonstrates a basic counter component using Gnim's JSX and reactivity features. It utilizes `createState` for managing component state and `createEffect` for side effects, along with Gtk widgets for UI elements. ```tsx function Counter() { const [count, setCount] = createState(0) function increment() { setCount((v) => v + 1) } createEffect(() => { console.log("count is", count()) }) return ( c.toString())} /> Increment ) } ``` -------------------------------- ### DBus Proxy Method Example Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Example of defining a method in a class intended to be used as a DBus proxy. Note that the method implementation is not invoked when used as a proxy. ```typescript @iface("some.dbus.interface") class MyProxy extends Service { @method() Method() { console.log("this is never invoked when working as a proxy") } } const proxy = await new MyProxy().proxy() proxy.Method() ``` -------------------------------- ### DBus property Decorator Example Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Example of using the 'property' decorator to define a DBus property with a string type. ```typescript class { @property("s") Value = "value" } ``` -------------------------------- ### DBus getter Decorator Example Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Example of using the 'getter' decorator to define a read-only DBus property. ```typescript class { @getter("s") get Value() { return "" } } ``` -------------------------------- ### Create and Run an Effect Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gnim.md Use `createEffect` to run a function that tracks reactive values and re-runs when dependencies change. This example logs state changes to the console. ```ts const [count, setCount] = createState(0) const [message, setMessage] = createState("Hello") createEffect(() => { console.log(count(), message()) }) setCount(1) // Output: 1, "Hello" setMessage("World") // Output: 1, "World" ``` -------------------------------- ### createExternal Source: https://context7.com/aylur/gnim/llms.txt Creates a reactive value from an external push-based source. The producer is started on first subscriber and torn down on last unsubscribe. ```APIDOC ## `createExternal` Creates a reactive value from an external push-based source (timers, streams, IPC). The producer is started on first subscriber and torn down on last unsubscribe. ```ts import { createExternal } from "gnim" // Tick every second const seconds = createExternal(0, (set) => { const id = setInterval(() => set((v) => v + 1), 1000) return () => clearInterval(id) }) // Current time string const clock = createExternal("", (set) => { function tick() { set(new Date().toLocaleTimeString()) } tick() const id = setInterval(tick, 1000) return () => clearInterval(id) }) return ``` ``` -------------------------------- ### Fetch API Implementation in GJS Source: https://github.com/aylur/gnim/blob/main/docs/polyfills.md Use this snippet to make HTTP requests in GJS. Ensure you import `fetch` and `URL` from `gnim/fetch`. This example demonstrates a POST request with a JSON body. ```ts import { fetch, URL } from "gnim/fetch" const url = new URL("https://some-site.com/api") url.searchParams.set("hello", "world") const res = await fetch(url, { method: "POST", body: JSON.stringify({ hello: "world" }), headers: { "Content-Type": "application/json", }, }) const json = await res.json() ``` -------------------------------- ### Gnim Function Components with FCProps Source: https://context7.com/aylur/gnim/llms.txt Define function components using `FCProps` to include the `$` setup prop and typed props for GObject instances. ```tsx import { FCProps, createState } from "gnim" type CounterProps = FCProps< Gtk.Box, { initial?: number label?: string } > function Counter({ initial = 0, label = "Count" }: CounterProps) { const [count, setCount] = createState(initial) const display = count((n) => `${label}: ${n}`) return ( setCount((v) => v + 1)} /> setCount((v) => v - 1)} /> ) } // Usage — `$` gives a typed ref to the returned Gtk.Box return self.set_margin_top(8)} /> ``` -------------------------------- ### Acquiring Widget References with Setup Function Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md A common use case for the '$' prop is to capture a reference to the widget within the component's scope for later use, such as in event handlers. ```tsx function MyWidget() { let box: Gtk.Box function someHandler() { console.log(box) } return (box = self)} /> } ``` -------------------------------- ### Create External Reactive Source with `createExternal` Source: https://context7.com/aylur/gnim/llms.txt Use `createExternal` to create reactive values from push-based sources like timers or streams. The producer starts on the first subscriber and cleans up on the last unsubscribe. ```typescript import { createExternal } from "gnim" // Tick every second const seconds = createExternal(0, (set) => { const id = setInterval(() => set((v) => v + 1), 1000) return () => clearInterval(id) }) // Current time string const clock = createExternal("", (set) => { function tick() { set(new Date().toLocaleTimeString()) } tick() const id = setInterval(tick, 1000) return () => clearInterval(id) }) return ``` -------------------------------- ### Gtk CenterBox Layout Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gtk.md Illustrates using Gtk CenterBox to position widgets in start, center, and end sections. This is useful for creating layouts with distinct areas. ```typescript const centerBox = new Gtk.CenterBox({ orientation: Gtk.Orientation.HORIZONTAL, }) centerBox.set_start_widget(Gtk.Label.new("start")) centerBox.set_center_widget(Gtk.Label.new("center")) centerBox.set_end_widget(Gtk.Label.new("end")) ``` -------------------------------- ### Gnim Application Entry Point Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md A basic entry point for a Gnim application that logs 'hello world' to the console. ```ts console.log("hello world") ``` -------------------------------- ### DBus setter Decorator Example Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Example of using the 'setter' decorator to define a write-only DBus property. ```typescript class { @setter("s") set Value(value: string) { } } ``` -------------------------------- ### Presenting Window on Activation Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md This snippet demonstrates how to present an existing window or create a new one when the application is activated. It ensures that if a window already exists, it's brought to the front. ```tsx class MyApp extends Gtk.Application { declare window?: Gtk.Window vfunc_activate(): void { if (this.window) { return this.window.present() } createRoot((dispose) => { this.connect("shutdown", dispose) return (this.window = self).present()} /> }) } } ``` -------------------------------- ### createSettings Source: https://context7.com/aylur/gnim/llms.txt Wraps `Gio.Settings` into typed accessors and setters, converting kebab-case keys to camelCase. ```APIDOC ## createSettings Wraps `Gio.Settings` into typed accessors and setters, converting kebab-case keys to camelCase. ```ts import Gio from "gi://Gio" import { createSettings } from "gnim" const settings = new Gio.Settings({ schemaId: "org.example.App" }) const s = createSettings(settings, { "window-width": "i", "window-height": "i", "theme": "s", "recent-files": "as", }) // Read console.log(s.theme()) // e.g. "dark" console.log(s.windowWidth()) // e.g. 800 // Write s.setTheme("light") s.setRecentFiles((prev) => [...prev, "/home/user/doc.txt"]) // Subscribe s.theme.subscribe(() => { console.log("theme changed to", s.theme()) }) ``` ``` -------------------------------- ### Nix Development Shell for Gnim Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Sets up a development shell using Nix flakes, including GObject introspection, GLib, npm, GTK4, and GJS. ```nix { inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; outputs = { self, nixpkgs }; in let forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"]; in { devShells = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { # enter this shell using `nix develop` default = pkgs.mkShell { packages = with pkgs; [ gobject-introspection glib nodePackages.npm gtk4 gjs ]; }; }); }; } ``` -------------------------------- ### Create a Connection with Initial Value Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Use `createConnection` to set up `GObject.Object` signal connections. It takes an initial value and a list of signal handlers, returning an accessor that holds the current value. ```typescript function createConnection( init: T, handler: [ object: O, signal: S, callback: ( ...args: [...Parameters, currentValue: T] ) => T, ], ): Accessor ``` ```typescript const value: Accessor = createConnection( "initial value", [obj1, "notify", (pspec, currentValue) => currentValue + pspec.name], [obj2, "sig-name", (sigArg1, sigArg2, currentValue) => "str"], ) ``` -------------------------------- ### Service.serve Method Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md The `serve` method is used to export a service object onto the DBus. ```APIDOC ## `Service.serve` Attempt to own `name` and export this object at `objectPath` on `busType`. ```ts class Service { async serve(props: { busType?: Gio.BusType name?: string objectPath?: string flags?: Gio.BusNameOwnerFlags timeout?: number }): Promise } ``` This method allows a service to be registered on the DBus. It accepts optional parameters to configure the bus type, service name, object path, and ownership flags. It returns a promise that resolves with the service instance. ``` -------------------------------- ### Contexts Source: https://context7.com/aylur/gnim/llms.txt Dependency injection without prop drilling. `createContext` accepts a default value used when no provider is found. ```APIDOC ## Contexts Dependency injection without prop drilling. `createContext` accepts a default value used when no provider is found. ```tsx import { createContext, createRoot } from "gnim" const ThemeContext = createContext<"light" | "dark">("light") function ThemedLabel() { const theme = ThemeContext.use() return } function App() { return ( {() => } {/* logs "Theme: dark" */} {/* logs "Theme: light" (default) */} ) } createRoot(() => App()) ``` ``` -------------------------------- ### Create a Basic Gtk Window Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gtk.md Creates a simple Gtk window with a title bar and a label. It also sets up a 'close-request' signal to quit the main loop when the window is closed. ```typescript const win = new Gtk.Window({ defaultWidth: 300, defaultHeight: 200, title: "My App", }) const titlebar = new Gtk.HeaderBar() const label = new Gtk.Label({ label: "Hello World", }) win.set_titlebar(titlebar) win.set_child(label) win.connect("close-request", () => loop.quit()) win.present() ``` -------------------------------- ### Using a DBus Proxy Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Demonstrates how to create a proxy to interact with a remote DBus service. ```APIDOC ## Using a DBus Proxy ```ts const proxy = await new MyService().proxy() proxy.MyProperty = "new value" const value = await proxy.MyMethod("hello") console.log(value) // "hello" ``` This example shows how to create a proxy for the `MyService` DBus interface. It then demonstrates setting a property (`MyProperty`) and calling an asynchronous method (`MyMethod`) on the remote service. ``` -------------------------------- ### Using Gtk.Application Without Subclassing Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md Instantiate Gtk.Application directly and connect signal handlers. This is a simpler approach for applications that don't require extensive custom logic within the application class itself. ```ts import Gtk from "gi://Gtk" import Gio from "gi://Gio" import { createRoot } from "./jsx/scope" import { programInvocationName, programArgs } from "system" export const app = new Gtk.Application({ applicationId: "my.awesome.app", flags: Gio.ApplicationFlags.NON_UNIQUE, }) app.connect("activate", () => { createRoot((dispose) => { app.connect("shutdown", dispose) // show windows here }) }) app.runAsync([programInvocationName, ...programArgs]) ``` -------------------------------- ### Basic Gtk.Box Component in TypeScript Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Illustrates a basic Gtk.Box component created using traditional TypeScript, showing manual widget creation and connection of signals. ```ts function Box() { let counter = 0 const button = new Gtk.Button() const icon = new Gtk.Image({ iconName: "system-search-symbolic", }) const label = new Gtk.Label({ label: `clicked ${counter} times`, }) const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, }) function onClicked() { label.label = `clicked ${counter} times` } button.set_child(icon) box.append(button) box.append(label) button.connect("clicked", onClicked) return box } ``` -------------------------------- ### Gtk Grid Layout Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gtk.md Demonstrates creating a Gtk Grid for arranging widgets in a table-like structure. Use attach to specify position and span. ```typescript const grid = new Gtk.Grid() grid.attach(Gtk.Label.new("0x0"), 0, 0, 1, 1) grid.attach(Gtk.Label.new("0x1"), 0, 1, 1, 1) ``` -------------------------------- ### Gnim Class Component Special Props Source: https://context7.com/aylur/gnim/llms.txt Class components in Gnim accept special JSX-only props for constructor, child placement, signal handling, and setup. ```tsx // $constructor — use a static factory instead of `new` Gtk.DropDown.new_from_strings(["Alpha", "Beta", "Gamma"])} /> // $type — pass to Gtk.Buildable.add_child (Gtk4 only) // Signal handlers: `on` and `onNotify` print("revealed:", self.childRevealed)} onDestroy={(self) => print(self, "destroyed")} /> // $= setup function — runs after props/signals/children are applied function MyWidget() { let box!: Gtk.Box function handleKey() { console.log("box ref:", box) } return ( (box = self)} onKeyPressed={handleKey}> ) } // class and css props ``` -------------------------------- ### Fetch Polyfill Source: https://context7.com/aylur/gnim/llms.txt A basic implementation of the web `fetch` API and `URL` for GJS, built on `Soup`. ```APIDOC ## `fetch` polyfill A basic implementation of the web `fetch` API and `URL` for GJS, built on `Soup`. ```ts import { fetch, URL } from "gnim/fetch" // GET with query params const url = new URL("https://api.example.com/users") url.searchParams.set("page", "1") url.searchParams.set("limit", "20") const res = await fetch(url) if (!res.ok) throw new Error(`HTTP ${res.status}`) const users = await res.json() console.log(users) // POST with JSON body const created = await fetch("https://api.example.com/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Alice", role: "admin" }), }) const newUser = await created.json() console.log(newUser) ``` ``` -------------------------------- ### Custom ParamSpec Declaration with @property Source: https://github.com/aylur/gnim/blob/main/docs/gobject.md Defines a custom property type using a function that returns a GObject.ParamSpec. This example creates a 'Percent' property for a double between 0 and 1. ```typescript const Percent = (name: string, flags: ParamFlags) => GObject.ParamSpec.double(name, "", "", flags, 0, 1, 0) @register() class MyObj extends GObject.Object { @property(Percent) percent = 0 } ``` -------------------------------- ### createSettings Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Wraps a Gio.Settings into a collection of setters and accessors for managing application settings. ```APIDOC ## `createSettings` ### Description Wraps a `Gio.Settings` into a collection of setters and accessors. ### Signature ```ts function createSettings>( settings: Gio.Settings, keys: T, ): Settings ``` ### Example ```ts const s = createSettings(settings, { "complex-key": "a{sa{ss}}", "simple-key": "s", }) s.complexKey.subscribe(() => { print(s.complexKey.get()) }) s.setComplexKey((prev) => ({ ...prev, neyKey: { nested: "" }, })) ``` ``` -------------------------------- ### createConnection Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Creates an Accessor by setting up GObject.Object signal connections with an initial value and a list of signal handlers. ```APIDOC ## `createConnection` ### Signature ```ts function createConnection( init: T, handler: [ object: O, signal: S, callback: ( ...args: [...Parameters, currentValue: T] ) => T, ], ): Accessor ``` ### Description Creates an `Accessor` which sets up a list of `GObject.Object` signal connections. It expects an initial value and a list of `[object, signal, callback]` tuples where the callback is called with the arguments passed by the signal and the current value as the last parameter. ### Example ```ts const value: Accessor = createConnection( "initial value", [obj1, "notify", (pspec, currentValue) => currentValue + pspec.name], [obj2, "sig-name", (sigArg1, sigArg2, currentValue) => "str"], ) ``` ### Important The connection will only get attached when the first subscriber appears, and is dropped when the last one disappears. ``` -------------------------------- ### Build and Run Gnim Application Source: https://context7.com/aylur/gnim/llms.txt Build the TypeScript project using esbuild and run the resulting JavaScript file with gjs. ```sh # scripts/build.sh esbuild --bundle src/main.ts \ --outdir=dist \ --external:gi://* \ --external:resource://* \ --external:system \ --external:gettext \ --format=esm \ --sourcemap=inline # run gjs -m dist/main.js ``` -------------------------------- ### Gtk Overlay Layout Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gtk.md Shows how to use Gtk Overlay to stack widgets on top of each other. The main child defines the size, and other children are overlaid. ```typescript const overlay = new Gtk.Overlay() overlay.set_child(Gtk.Label.new("main child")) overlay.add_overlay(Gtk.Label.new("overlay")) ``` -------------------------------- ### Compiling GSchema Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md Commands to copy the GSchema XML file and compile it. This is a necessary step before settings can be read or written. ```sh cp my.awesome.app.gschema.xml /usr/share/glib-2.0/schemas glib-compile-schemas /usr/share/glib-2.0/schemas ``` -------------------------------- ### Create Root Scope with createRoot Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Use `createRoot` to establish a root scope for your application. This is typically done once at the entry point. Components like `` and `` manage their own scopes internally. ```typescript function createRoot(fn: (dispose: () => void) => T) ``` ```tsx createRoot((dipose) => { return }) ``` -------------------------------- ### Implement Context with createContext Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Define and use contexts for dependency injection, avoiding prop drilling. `createContext` sets up a context, `use` consumes it, and a Provider component wraps children to supply the value. ```tsx const MyContext = createContext("fallback-value") function ConsumerComponent() { const value = MyContext.use() return } function ProviderComponent() { return ( {() => } ) } ``` -------------------------------- ### Gnim Build Script using esbuild Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Configures esbuild to bundle the Gnim application, externalize GJS/GTK modules, and generate source maps. ```sh esbuild --bundle src/main.ts \ --outdir=dist \ --external:gi://* \ --external:resource://* \ --external:system \ --external:gettext \ --format=esm \ --sourcemap=inline ``` -------------------------------- ### Construct GObject Instance with Properties Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gobject.md Use the `new` operator to create a GObject instance and initialize its properties using a dictionary. ```typescript const labelWidget = new Gtk.Label({ label: "Text", useMarkup: true, }) ``` -------------------------------- ### Use DBus Service as a Server Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Instantiate and serve a DBus service. Connect to signals and property changes to react to external events. ```typescript const service = await new MyService().serve() service.connect("my-signal", (_, str: string) => { console.log(`MySignal invoked with argument: "${str}"`) }) service.connect("notify::my-property", () => { console.log(`MyProperty set to ${service.MyProperty}`) }) ``` -------------------------------- ### Wrap Gio.Settings with createSettings Source: https://context7.com/aylur/gnim/llms.txt Use `createSettings` to wrap `Gio.Settings` into typed accessors and setters, converting kebab-case keys to camelCase. Supports subscribing to changes. ```typescript import Gio from "gi://Gio" import { createSettings } from "gnim" const settings = new Gio.Settings({ schemaId: "org.example.App" }) const s = createSettings(settings, { "window-width": "i", "window-height": "i", "theme": "s", "recent-files": "as", }) // Read console.log(s.theme()) // e.g. "dark" console.log(s.windowWidth()) // e.g. 800 // Write s.setTheme("light") s.setRecentFiles((prev) => [...prev, "/home/user/doc.txt"]) // Subscribe s.theme.subscribe(() => { console.log("theme changed to", s.theme()) }) ``` -------------------------------- ### Instantiate and export a D-Bus service Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md Instantiate your D-Bus service and export it when the application activates. Ensure the service is stopped when the application shuts down. ```typescript @register() class MyApp extends Gtk.Application { private service: MyService constructor() { super({ applicationId: "my.awesome.app" }) this.service = new MyService() } vfunc_shutdown(): void { super.vfunc_shutdown() this.service.stop() } vfunc_activate(): void { this.service.serve({ name: "my.awesome.app", objectPath: "/my/awesome/app/MyService", }) } } ``` -------------------------------- ### createRoot Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Creates a root scope for the application. This is typically used once at the entry point to manage the lifecycle of the entire application or a significant part of it. ```APIDOC ## `createRoot` ### Description Creates a root scope. Other than wrapping the main entry function in this, you likely won't need this elsewhere. `` and `` components run their children in their own scopes, for example. ### Signature ```ts function createRoot(fn: (dispose: () => void) => T) ``` ### Example ```tsx createRoot((dipose) => { return }) ``` ``` -------------------------------- ### Basic Gtk.Box Component in JSX Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Demonstrates the same Gtk.Box component rewritten using JSX syntax, showcasing a more declarative and concise approach with state management. ```tsx function Box() { const [counter, setCounter] = createState(0) const label = createComputed(() => `clicked ${counter()} times`) function onClicked() { setCounter((c) => c + 1) } return ( ) } ``` -------------------------------- ### Create Gnim Source Directory Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Creates the 'src' directory where your Gnim application's source files will reside. ```sh mkdir src ``` -------------------------------- ### DBus Service serve() Method Signature Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Signature for the 'serve' method, used to own a DBus name and export an object. ```typescript class Service { async serve(props: { busType?: Gio.BusType name?: string objectPath?: string flags?: Gio.BusNameOwnerFlags timeout?: number }): Promise } ``` -------------------------------- ### Fetch and URL Polyfills for GJS Source: https://context7.com/aylur/gnim/llms.txt Provides basic implementations of the web `fetch` API and `URL` class for GJS, leveraging the `Soup` library. Useful for making HTTP requests and parsing URLs. ```typescript import { fetch, URL } from "gnim/fetch" // GET with query params const url = new URL("https://api.example.com/users") url.searchParams.set("page", "1") url.searchParams.set("limit", "20") const res = await fetch(url) if (!res.ok) throw new Error(`HTTP ${res.status}`) const users = await res.json() console.log(users) // POST with JSON body const created = await fetch("https://api.example.com/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Alice", role: "admin" }), }) const newUser = await created.json() console.log(newUser) ``` -------------------------------- ### Subclassing Gtk.Application Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/app.md Use this approach to create a custom application class by extending Gtk.Application. It's suitable for complex applications requiring custom logic within the application lifecycle. ```ts import Gtk from "gi://Gtk" import Gio from "gi://Gio" import { register } from "./gobject" import { createRoot } from "./jsx/scope" import { programInvocationName, programArgs } from "system" @register() class MyApp extends Gtk.Application { constructor() { super({ applicationId: "my.awesome.app", flags: Gio.ApplicationFlags.FLAGS_NONE, }) } vfunc_activate(): void { createRoot((dispose) => { this.connect("shutdown", dispose) // show windows here }) } } export const app = new MyApp() app.runAsync([programInvocationName, ...programArgs]) ``` -------------------------------- ### Dependency Injection with `createContext` Source: https://context7.com/aylur/gnim/llms.txt Use `createContext` for dependency injection without prop drilling. A default value is used if no provider is found. Consumers use the `.use()` hook to access the context value. ```tsx import { createContext, createRoot } from "gnim" const ThemeContext = createContext<"light" | "dark">("light") function ThemedLabel() { const theme = ThemeContext.use() return } function App() { return ( {() => } {/* logs "Theme: dark" */} {/* logs "Theme: light" (default) */} ) } createRoot(() => App()) ``` -------------------------------- ### Construct GObject Instance with Static Method Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gobject.md Utilize static constructor methods provided by GObject classes for direct instance creation. ```typescript const labelWidget = Gtk.Label.new("Text") ``` -------------------------------- ### Run Gnim Application Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/intro.md Executes the 'dev' script defined in package.json to build and run the Gnim application. ```sh npm run dev ``` -------------------------------- ### Using $constructor for custom class instantiation Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Illustrates how to use the `$constructor` property within JSX to specify a static constructor function for creating class instances, noting limitations for construct-only properties. ```tsx Gtk.DropDown.new_from_strings(["item1", "item2"])} /> ``` -------------------------------- ### Contexts Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Context provides a mechanism for dependency injection, allowing data to be passed down the component tree without explicit prop drilling. It defines how to create, provide, and consume context values. ```APIDOC ## Contexts ### Description Context provides a form of dependency injection. It lets you avoid the need to pass data as props through intermediate components (a.k.a. prop drilling). The default value is used when no Provider is found above in the hierarchy. ### `createContext` Creates a new context object. ### `useContext` Consumes the value of the nearest Context Provider for the given context. ### Example ```tsx const MyContext = createContext("fallback-value") function ConsumerComponent() { const value = MyContext.use() return } function ProviderComponent() { return ( {() => } ) } ``` ``` -------------------------------- ### Creating a Root Scope Tied to a Window Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gnim.md Use `createRoot` to establish a root scope for your Gnim application, typically tied to a window's lifecycle. The provided dispose function should be connected to the window's 'close-request' signal. ```ts import { createRoot } from "gnim" const win = createRoot((dispose) => { const win = new Gtk.Window() win.connect("close-request", dispose) return win }) ``` -------------------------------- ### Creating a Root Scope Tied to the Application Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gnim.md Establishes a root scope for a Gtk.Application, ensuring cleanup occurs when the application shuts down. The dispose function is connected to the application's 'shutdown' signal. ```ts import { createRoot } from "gnim" class App extends Gtk.Application { vfunc_activate() { createRoot((dispose) => { this.connect("shutdown", dispose) new Gtk.Window() }) } } ``` -------------------------------- ### With — dynamic rendering Source: https://context7.com/aylur/gnim/llms.txt Renders content conditionally based on a reactive value. Wrap in a container since replaced widgets are appended, not inserted in order. ```APIDOC ## `` — dynamic rendering Renders content conditionally based on a reactive value. Wrap in a container since replaced widgets are appended, not inserted in order. ```tsx import { With, createState } from "gnim" function UserPanel() { const [user, setUser] = createState<{ name: string; email: string } | null>(null) return ( setUser({ name: "Alice", email: "alice@example.com" })} /> {/* wrapper keeps order stable */} {(u) => u && ( ) } ) } ``` ``` -------------------------------- ### createMemo Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Creates a derived reactive value that tracks dependencies and notifies subscribers only when the computed value changes. ```APIDOC ## `createMemo` ### Description Create a derived reactive value which tracks its dependencies and re-runs the computation whenever a dependency changes. The resulting `Accessor` will only notify subscribers when the computed value has changed. ### Signature ```ts function createMemo(compute: () => T): Accessor ``` ### Use Case It is useful to memoize values that are dependencies of expensive computations. ### Example ```ts const value = createBinding(gobject, "field") createEffect(() => { console.log("effect1", value()) }) const memoValue = createMemo(() => value()) createEffect(() => { console.log("effect2", memoValue()) }) value.notify("field") // triggers effect1 but not effect2 ``` ``` -------------------------------- ### Defining signal handlers with 'on' and 'onNotify' prefixes Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Demonstrates how to define signal handlers for GObject signals using the `on` prefix for standard signals and `onNotify` for `notify::` signals directly within JSX attributes. ```tsx print(self, "child-revealed")} onDestroy={(self) => print(self, "destroyed")} /> ``` -------------------------------- ### Exporting a DBus Service Source: https://github.com/aylur/gnim/blob/main/docs/dbus.md Shows how to export a defined DBus service and connect to its signals and property changes. ```APIDOC ## Exporting a DBus Service ```ts const service = await new MyService().serve() service.connect("my-signal", (_, str: string) => { console.log(`MySignal invoked with argument: "${str}"`) }) service.connect("notify::my-property", () => { console.log(`MyProperty set to ${service.MyProperty}`) }) ``` This code snippet illustrates how to instantiate and export a `MyService` instance to the DBus system. It then sets up listeners for the `my-signal` signal and property change notifications for `my-property`. ``` -------------------------------- ### Create reactive bindings to GObject properties with createBinding Source: https://context7.com/aylur/gnim/llms.txt Use `createBinding` to track GObject properties reactively via `notify::`. Supports nested properties and transformations. ```typescript import Adw from "gi://Adw" import { createBinding, createComputed } from "gnim" // Simple binding const styleManager = Adw.StyleManager.get_default() const colorScheme = createBinding(styleManager, "colorScheme") const isDark = colorScheme( (scheme) => scheme === Adw.ColorScheme.FORCE_DARK || scheme === Adw.ColorScheme.PREFER_DARK, ) // Nested binding — outer.nested?.field interface Outer extends GObject.Object { nested: Inner | null } interface Inner extends GObject.Object { title: string } declare const outer: Outer const title: Accessor = createBinding(outer, "nested", "title") // Use in JSX return v ?? "Untitled")} /> ``` -------------------------------- ### createBinding Source: https://context7.com/aylur/gnim/llms.txt Creates an `Accessor` that reactively tracks a GObject property via `notify::`. Supports nested (chained) bindings. ```APIDOC ## createBinding Creates an `Accessor` that reactively tracks a GObject property via `notify::`. Supports nested (chained) bindings. ```ts import Adw from "gi://Adw" import { createBinding, createComputed } from "gnim" // Simple binding const styleManager = Adw.StyleManager.get_default() const colorScheme = createBinding(styleManager, "colorScheme") const isDark = colorScheme( (scheme) => scheme === Adw.ColorScheme.FORCE_DARK || scheme === Adw.ColorScheme.PREFER_DARK, ) // Nested binding — outer.nested?.field interface Outer extends GObject.Object { nested: Inner | null } interface Inner extends GObject.Object { title: string } declare const outer: Outer const title: Accessor = createBinding(outer, "nested", "title") // Use in JSX return v ?? "Untitled")} /> ``` ``` -------------------------------- ### Run Function on Mount with onMount Source: https://github.com/aylur/gnim/blob/main/docs/jsx.md Employ `onMount` to schedule a function to run when the farthest non-mounted scope is returned. This is useful for performing actions after the component has been initialized. ```tsx function MyComponent() { onMount(() => { console.log("root scope returned") }) return <> } ``` -------------------------------- ### Nesting Custom Gnim Components Source: https://github.com/aylur/gnim/blob/main/docs/tutorial/gnim.md Demonstrates how to nest the `MyButton` component within another component, `MyWindow`, which also contains a `Gtk.Box`. ```tsx function MyWindow() { return ( Click The button ) } ```