@garretapp/sdk 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -187,9 +187,9 @@ function getGarret() {
187
187
  active: true,
188
188
  onActiveChange: () => () => {
189
189
  },
190
- onOpenSettings: () => () => {
190
+ setCommands: () => {
191
191
  },
192
- onRefresh: () => () => {
192
+ onCommand: () => () => {
193
193
  },
194
194
  setTitle: () => {
195
195
  },
@@ -43,6 +43,11 @@ interface SharedApi {
43
43
  storage: StorageApi;
44
44
  secrets: SecretsApi;
45
45
  }
46
+ /** A frame ⋯-menu command a widget declares via `setCommands` (dispatched back through `onCommand`). */
47
+ interface WidgetCommand {
48
+ id: string;
49
+ label: string;
50
+ }
46
51
  /** Options for opening a floating sibling surface. All fields optional; sizes in px. */
47
52
  interface SurfaceOpenOptions {
48
53
  /** initial props delivered to the opened surface as `g.props`; structured-cloned, so each surface
@@ -115,10 +120,10 @@ interface GarretPlatform {
115
120
  /** false when the board is ambient/idle — pause rAF/animations, throttle polling. */
116
121
  active: boolean;
117
122
  onActiveChange(cb: (active: boolean) => void): () => void;
118
- /** The host (frame ⋯→Settings) asks this widget to open its own config UI. */
119
- onOpenSettings(cb: () => void): () => void;
120
- /** The host (frame ⋯→Refresh) asks this widget to reload its data. */
121
- onRefresh(cb: () => void): () => void;
123
+ /** Declare the commands this widget wants in the frame's menu. The host renders them and dispatches
124
+ * the chosen one to `onCommand` — one generic mechanism (settings, refresh, or anything you invent). */
125
+ setCommands(commands: WidgetCommand[]): void;
126
+ onCommand(cb: (id: string) => void): () => void;
122
127
  /** Set this placement's title in the board frame header (persisted in the board config). */
123
128
  setTitle(title: string): void;
124
129
  /** Open sibling surfaces (same package) as floating windows. Requires the `windows` capability. */
@@ -43,6 +43,11 @@ interface SharedApi {
43
43
  storage: StorageApi;
44
44
  secrets: SecretsApi;
45
45
  }
46
+ /** A frame ⋯-menu command a widget declares via `setCommands` (dispatched back through `onCommand`). */
47
+ interface WidgetCommand {
48
+ id: string;
49
+ label: string;
50
+ }
46
51
  /** Options for opening a floating sibling surface. All fields optional; sizes in px. */
47
52
  interface SurfaceOpenOptions {
48
53
  /** initial props delivered to the opened surface as `g.props`; structured-cloned, so each surface
@@ -115,10 +120,10 @@ interface GarretPlatform {
115
120
  /** false when the board is ambient/idle — pause rAF/animations, throttle polling. */
116
121
  active: boolean;
117
122
  onActiveChange(cb: (active: boolean) => void): () => void;
118
- /** The host (frame ⋯→Settings) asks this widget to open its own config UI. */
119
- onOpenSettings(cb: () => void): () => void;
120
- /** The host (frame ⋯→Refresh) asks this widget to reload its data. */
121
- onRefresh(cb: () => void): () => void;
123
+ /** Declare the commands this widget wants in the frame's menu. The host renders them and dispatches
124
+ * the chosen one to `onCommand` — one generic mechanism (settings, refresh, or anything you invent). */
125
+ setCommands(commands: WidgetCommand[]): void;
126
+ onCommand(cb: (id: string) => void): () => void;
122
127
  /** Set this placement's title in the board frame header (persisted in the board config). */
123
128
  setTitle(title: string): void;
124
129
  /** Open sibling surfaces (same package) as floating windows. Requires the `windows` capability. */
package/dist/react.cjs CHANGED
@@ -220,9 +220,9 @@ function getGarret() {
220
220
  active: true,
221
221
  onActiveChange: () => () => {
222
222
  },
223
- onOpenSettings: () => () => {
223
+ setCommands: () => {
224
224
  },
225
- onRefresh: () => () => {
225
+ onCommand: () => () => {
226
226
  },
227
227
  setTitle: () => {
228
228
  },
@@ -426,17 +426,15 @@ function useActive() {
426
426
  react.useEffect(() => g.onActiveChange(setActive), [g]);
427
427
  return active;
428
428
  }
429
- function useOpenSettings(cb) {
429
+ function useWidgetMenu(items) {
430
430
  const g = getGarret();
431
- const ref = react.useRef(cb);
432
- ref.current = cb;
433
- react.useEffect(() => g.onOpenSettings(() => ref.current()), [g]);
434
- }
435
- function useRefresh(cb) {
436
- const g = getGarret();
437
- const ref = react.useRef(cb);
438
- ref.current = cb;
439
- react.useEffect(() => g.onRefresh(() => ref.current()), [g]);
431
+ const ref = react.useRef(items);
432
+ ref.current = items;
433
+ const key = items.map((i) => `${i.id}:${i.label}`).join("|");
434
+ react.useEffect(() => {
435
+ g.setCommands(ref.current.map((i) => ({ id: i.id, label: i.label })));
436
+ return g.onCommand((id) => ref.current.find((i) => i.id === id)?.run());
437
+ }, [g, key]);
440
438
  }
441
439
  function useInstanceConfig(defaults) {
442
440
  const g = getGarret();
@@ -501,7 +499,6 @@ exports.useGarret = useGarret;
501
499
  exports.useHost = useHost;
502
500
  exports.useHostEvent = useHostEvent;
503
501
  exports.useInstanceConfig = useInstanceConfig;
504
- exports.useOpenSettings = useOpenSettings;
505
502
  exports.useProps = useProps;
506
- exports.useRefresh = useRefresh;
507
503
  exports.useStream = useStream;
504
+ exports.useWidgetMenu = useWidgetMenu;
package/dist/react.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { G as GarretError, E as EventMap, H as HostClient, f as StreamCall } from './types-BxSYAH_H.cjs';
2
- import { G as GarretPlatform } from './platform-DjRN9xTv.cjs';
3
- export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-DjRN9xTv.cjs';
2
+ import { G as GarretPlatform } from './platform-qz2Ef0Rp.cjs';
3
+ export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-qz2Ef0Rp.cjs';
4
4
  import { ReactNode } from 'react';
5
5
  import './protocol-Do0BJdeE.cjs';
6
6
 
@@ -110,10 +110,14 @@ declare function useStream<Chunk, Result = void>(factory: () => StreamCall<Chunk
110
110
  declare function useConfig<T>(): [T, (patch: Partial<T>) => void, (value: T) => void];
111
111
  /** Board activity — `false` when ambient/idle. Gate polling / rAF / animations on it. */
112
112
  declare function useActive(): boolean;
113
- /** Run `cb` when the host (frame ⋯→Settings) asks this widget to reveal its own config UI. */
114
- declare function useOpenSettings(cb: () => void): void;
115
- /** Run `cb` when the host (frame ⋯→Refresh) asks this widget to reload. */
116
- declare function useRefresh(cb: () => void): void;
113
+ /** Declarative frame ⋯-menu: pass items with inline handlers. Registers them with the host (id +
114
+ * label) and runs the matching `run` when the user picks one. One generic mechanism — no bespoke
115
+ * per-action hooks. Example: `useWidgetMenu([{ id: 'refresh', label: 'Refresh', run: reload }])`. */
116
+ declare function useWidgetMenu(items: {
117
+ id: string;
118
+ label: string;
119
+ run: () => void;
120
+ }[]): void;
117
121
  /** Per-placement config backed by `g.instanceStorage` (isolated per widget instance). Loads once the
118
122
  * runtime binds (calls before bind reject); `set` writes through to storage + state. `loaded` gates
119
123
  * the first data fetch so you don't fetch with defaults before the saved config arrives. */
@@ -128,4 +132,4 @@ declare function useInstanceConfig<T extends Record<string, unknown>>(defaults:
128
132
  * time), so this re-renders when the runtime binds. The `T` is an unchecked cast — validate it yourself. */
129
133
  declare function useProps<T = Record<string, unknown>>(): T;
130
134
 
131
- export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useOpenSettings, useProps, useRefresh, useStream };
135
+ export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useProps, useStream, useWidgetMenu };
package/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { G as GarretError, E as EventMap, H as HostClient, f as StreamCall } from './types-BxSYAH_H.js';
2
- import { G as GarretPlatform } from './platform-K2c4rKaG.js';
3
- export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-K2c4rKaG.js';
2
+ import { G as GarretPlatform } from './platform-Bbj2Vh3W.js';
3
+ export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-Bbj2Vh3W.js';
4
4
  import { ReactNode } from 'react';
5
5
  import './protocol-Do0BJdeE.js';
6
6
 
@@ -110,10 +110,14 @@ declare function useStream<Chunk, Result = void>(factory: () => StreamCall<Chunk
110
110
  declare function useConfig<T>(): [T, (patch: Partial<T>) => void, (value: T) => void];
111
111
  /** Board activity — `false` when ambient/idle. Gate polling / rAF / animations on it. */
112
112
  declare function useActive(): boolean;
113
- /** Run `cb` when the host (frame ⋯→Settings) asks this widget to reveal its own config UI. */
114
- declare function useOpenSettings(cb: () => void): void;
115
- /** Run `cb` when the host (frame ⋯→Refresh) asks this widget to reload. */
116
- declare function useRefresh(cb: () => void): void;
113
+ /** Declarative frame ⋯-menu: pass items with inline handlers. Registers them with the host (id +
114
+ * label) and runs the matching `run` when the user picks one. One generic mechanism — no bespoke
115
+ * per-action hooks. Example: `useWidgetMenu([{ id: 'refresh', label: 'Refresh', run: reload }])`. */
116
+ declare function useWidgetMenu(items: {
117
+ id: string;
118
+ label: string;
119
+ run: () => void;
120
+ }[]): void;
117
121
  /** Per-placement config backed by `g.instanceStorage` (isolated per widget instance). Loads once the
118
122
  * runtime binds (calls before bind reject); `set` writes through to storage + state. `loaded` gates
119
123
  * the first data fetch so you don't fetch with defaults before the saved config arrives. */
@@ -128,4 +132,4 @@ declare function useInstanceConfig<T extends Record<string, unknown>>(defaults:
128
132
  * time), so this re-renders when the runtime binds. The `T` is an unchecked cast — validate it yourself. */
129
133
  declare function useProps<T = Record<string, unknown>>(): T;
130
134
 
131
- export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useOpenSettings, useProps, useRefresh, useStream };
135
+ export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useProps, useStream, useWidgetMenu };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getGarret, getRuntime, getHostTransport, createHostClient, getInstanceId } from './chunk-YBYF7JQS.js';
1
+ import { getGarret, getRuntime, getHostTransport, createHostClient, getInstanceId } from './chunk-AIGAFJFB.js';
2
2
  import { GarretError } from './chunk-ENIDFSMM.js';
3
3
  export { GarretError } from './chunk-ENIDFSMM.js';
4
4
  import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
@@ -191,17 +191,15 @@ function useActive() {
191
191
  useEffect(() => g.onActiveChange(setActive), [g]);
192
192
  return active;
193
193
  }
194
- function useOpenSettings(cb) {
194
+ function useWidgetMenu(items) {
195
195
  const g = getGarret();
196
- const ref = useRef(cb);
197
- ref.current = cb;
198
- useEffect(() => g.onOpenSettings(() => ref.current()), [g]);
199
- }
200
- function useRefresh(cb) {
201
- const g = getGarret();
202
- const ref = useRef(cb);
203
- ref.current = cb;
204
- useEffect(() => g.onRefresh(() => ref.current()), [g]);
196
+ const ref = useRef(items);
197
+ ref.current = items;
198
+ const key = items.map((i) => `${i.id}:${i.label}`).join("|");
199
+ useEffect(() => {
200
+ g.setCommands(ref.current.map((i) => ({ id: i.id, label: i.label })));
201
+ return g.onCommand((id) => ref.current.find((i) => i.id === id)?.run());
202
+ }, [g, key]);
205
203
  }
206
204
  function useInstanceConfig(defaults) {
207
205
  const g = getGarret();
@@ -245,4 +243,4 @@ function useProps() {
245
243
  return props;
246
244
  }
247
245
 
248
- export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, Item, NumberInput, Scroll, Select, SettingsPanel, Switch, TextInput, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useOpenSettings, useProps, useRefresh, useStream };
246
+ export { Accordion, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, Item, NumberInput, Scroll, Select, SettingsPanel, Switch, TextInput, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, useProps, useStream, useWidgetMenu };
package/dist/ui.cjs CHANGED
@@ -215,9 +215,9 @@ function getGarret() {
215
215
  active: true,
216
216
  onActiveChange: () => () => {
217
217
  },
218
- onOpenSettings: () => () => {
218
+ setCommands: () => {
219
219
  },
220
- onRefresh: () => () => {
220
+ onCommand: () => () => {
221
221
  },
222
222
  setTitle: () => {
223
223
  },
package/dist/ui.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as Transport } from './protocol-Do0BJdeE.cjs';
2
2
  import { E as EventMap, H as HostClient } from './types-BxSYAH_H.cjs';
3
3
  export { C as Capability, G as GarretError, M as Manifest, S as Stream, f as StreamCall, g as defineConfig, h as defineManifest } from './types-BxSYAH_H.cjs';
4
- export { G as GarretPlatform, c as GarretRuntime, d as SecretsApi, e as ServiceClient, f as StorageApi, S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls, g as getGarret, h as getHostTransport, i as getInstanceId, j as getRuntime } from './platform-DjRN9xTv.cjs';
4
+ export { G as GarretPlatform, c as GarretRuntime, d as SecretsApi, e as ServiceClient, f as StorageApi, S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls, g as getGarret, h as getHostTransport, i as getInstanceId, j as getRuntime } from './platform-qz2Ef0Rp.cjs';
5
5
 
6
6
  /**
7
7
  * UI-side host client — a typed proxy over the wire (protocol.ts). Every call returns ONE handle
package/dist/ui.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { T as Transport } from './protocol-Do0BJdeE.js';
2
2
  import { E as EventMap, H as HostClient } from './types-BxSYAH_H.js';
3
3
  export { C as Capability, G as GarretError, M as Manifest, S as Stream, f as StreamCall, g as defineConfig, h as defineManifest } from './types-BxSYAH_H.js';
4
- export { G as GarretPlatform, c as GarretRuntime, d as SecretsApi, e as ServiceClient, f as StorageApi, S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls, g as getGarret, h as getHostTransport, i as getInstanceId, j as getRuntime } from './platform-K2c4rKaG.js';
4
+ export { G as GarretPlatform, c as GarretRuntime, d as SecretsApi, e as ServiceClient, f as StorageApi, S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls, g as getGarret, h as getHostTransport, i as getInstanceId, j as getRuntime } from './platform-Bbj2Vh3W.js';
5
5
 
6
6
  /**
7
7
  * UI-side host client — a typed proxy over the wire (protocol.ts). Every call returns ONE handle
package/dist/ui.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { defineConfig, defineManifest } from './chunk-RZJO3X6O.js';
2
- export { createHostClient, getGarret, getHostTransport, getInstanceId, getRuntime } from './chunk-YBYF7JQS.js';
2
+ export { createHostClient, getGarret, getHostTransport, getInstanceId, getRuntime } from './chunk-AIGAFJFB.js';
3
3
  export { GarretError } from './chunk-ENIDFSMM.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garretapp/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Build extensions for Garret — one SDK for both web widgets and full-access native extensions. Host runtime (defineHost), UI client + React hooks. See docs/garret.html.",
5
5
  "license": "MIT",
6
6
  "author": "Sudharsan Selvaraj",