@garretapp/sdk 0.1.3 → 0.2.0

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.
@@ -111,7 +111,11 @@ interface GarretPlatform {
111
111
  /** Pack-shared store — present only when the pack declares `shared`; otherwise its calls reject. */
112
112
  shared: SharedApi;
113
113
  service<T extends ServiceClient = ServiceClient>(id: string): T;
114
- notify(title: string, body?: string): void;
114
+ /** Show a system notification. `opts.url` makes it clickable → opens the link (requires the
115
+ * `openExternal` capability; ignored otherwise). */
116
+ notify(title: string, body?: string, opts?: {
117
+ url?: string;
118
+ }): void;
115
119
  openExternal(url: string): Promise<boolean>;
116
120
  clipboard: {
117
121
  readText(): Promise<string>;
@@ -111,7 +111,11 @@ interface GarretPlatform {
111
111
  /** Pack-shared store — present only when the pack declares `shared`; otherwise its calls reject. */
112
112
  shared: SharedApi;
113
113
  service<T extends ServiceClient = ServiceClient>(id: string): T;
114
- notify(title: string, body?: string): void;
114
+ /** Show a system notification. `opts.url` makes it clickable → opens the link (requires the
115
+ * `openExternal` capability; ignored otherwise). */
116
+ notify(title: string, body?: string, opts?: {
117
+ url?: string;
118
+ }): void;
115
119
  openExternal(url: string): Promise<boolean>;
116
120
  clipboard: {
117
121
  readText(): Promise<string>;
package/dist/react.cjs CHANGED
@@ -293,6 +293,26 @@ function Accordion({
293
293
  open && /* @__PURE__ */ jsxRuntime.jsx("div", { children })
294
294
  ] });
295
295
  }
296
+ function StatusStrip({
297
+ error,
298
+ loading,
299
+ onRetry
300
+ }) {
301
+ if (error) {
302
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gx-status gx-status--error", children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 1l22 22M16.72 11.06A10.94 10.94 0 0 1 19 12.55M5 12.55a10.94 10.94 0 0 1 5.17-2.39M10.71 5.05A16 16 0 0 1 22.58 9M1.42 9a15.91 15.91 0 0 1 4.7-2.88M8.53 16.11a6 6 0 0 1 6.95 0M12 20h.01" }) }),
304
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Couldn\u2019t refresh \u2014 showing last update" }),
305
+ onRetry && /* @__PURE__ */ jsxRuntime.jsx("button", { className: "gx-status-retry", onClick: onRetry, children: "Retry" })
306
+ ] });
307
+ }
308
+ if (loading) {
309
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gx-status", children: [
310
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "gx-status-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }),
311
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Refreshing\u2026" })
312
+ ] });
313
+ }
314
+ return null;
315
+ }
296
316
  function Badge({ tone = "neutral", children }) {
297
317
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: `gx-badge gx-badge--${tone}`, children });
298
318
  }
@@ -359,6 +379,21 @@ function Select({
359
379
  function Switch({ on, onChange }) {
360
380
  return /* @__PURE__ */ jsxRuntime.jsx("button", { className: `gx-switch${on ? " gx-switch--on" : ""}`, role: "switch", "aria-checked": on, onClick: () => onChange(!on), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "gx-switch-knob" }) });
361
381
  }
382
+ function AutoForm({
383
+ schema,
384
+ value,
385
+ onChange
386
+ }) {
387
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldGroup, { children: schema.map((f) => /* @__PURE__ */ jsxRuntime.jsx(Field, { label: f.label, children: f.type === "select" ? /* @__PURE__ */ jsxRuntime.jsx(Select, { value: String(value[f.key] ?? ""), options: f.options, onChange: (v) => onChange({ [f.key]: v }) }) : f.type === "switch" ? /* @__PURE__ */ jsxRuntime.jsx(Switch, { on: Boolean(value[f.key]), onChange: (v) => onChange({ [f.key]: v }) }) : f.type === "number" ? /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { value: value[f.key], onCommit: (v) => onChange({ [f.key]: v }) }) : /* @__PURE__ */ jsxRuntime.jsx(
388
+ TextInput,
389
+ {
390
+ value: value[f.key],
391
+ placeholder: f.placeholder,
392
+ secret: f.type === "secret",
393
+ onCommit: (v) => onChange({ [f.key]: v })
394
+ }
395
+ ) }, f.key)) });
396
+ }
362
397
 
363
398
  // src/react.ts
364
399
  var singleton;
@@ -471,6 +506,38 @@ function useInstanceConfig(defaults) {
471
506
  );
472
507
  return { cfg, set, loaded };
473
508
  }
509
+ function usePoll(fn, opts) {
510
+ const { intervalMs, deps = [], enabled = true, background = false, idleFloorMs = 3e5 } = opts;
511
+ const active = useActive();
512
+ const [data, setData] = react.useState(void 0);
513
+ const [error, setError] = react.useState("");
514
+ const [loading, setLoading] = react.useState(false);
515
+ const fnRef = react.useRef(fn);
516
+ fnRef.current = fn;
517
+ const run = react.useCallback(async () => {
518
+ setLoading(true);
519
+ try {
520
+ setData(await fnRef.current());
521
+ setError("");
522
+ } catch (e) {
523
+ setError(e?.message || "Request failed");
524
+ } finally {
525
+ setLoading(false);
526
+ }
527
+ }, []);
528
+ react.useEffect(() => {
529
+ if (enabled) void run();
530
+ }, [enabled, run, ...deps]);
531
+ react.useEffect(() => {
532
+ if (!enabled || !(intervalMs > 0)) return;
533
+ const period = active ? intervalMs : Math.max(intervalMs, idleFloorMs);
534
+ const t = setInterval(() => {
535
+ if (active || background) void run();
536
+ }, period);
537
+ return () => clearInterval(t);
538
+ }, [enabled, intervalMs, active, background, idleFloorMs, run]);
539
+ return { data, error, loading, refresh: run };
540
+ }
474
541
  function useProps() {
475
542
  const g = getGarret();
476
543
  const [props, setProps] = react.useState({});
@@ -479,6 +546,7 @@ function useProps() {
479
546
  }
480
547
 
481
548
  exports.Accordion = Accordion;
549
+ exports.AutoForm = AutoForm;
482
550
  exports.Badge = Badge;
483
551
  exports.Dot = Dot;
484
552
  exports.EmptyState = EmptyState;
@@ -491,6 +559,7 @@ exports.NumberInput = NumberInput;
491
559
  exports.Scroll = Scroll;
492
560
  exports.Select = Select;
493
561
  exports.SettingsPanel = SettingsPanel;
562
+ exports.StatusStrip = StatusStrip;
494
563
  exports.Switch = Switch;
495
564
  exports.TextInput = TextInput;
496
565
  exports.useActive = useActive;
@@ -499,6 +568,7 @@ exports.useGarret = useGarret;
499
568
  exports.useHost = useHost;
500
569
  exports.useHostEvent = useHostEvent;
501
570
  exports.useInstanceConfig = useInstanceConfig;
571
+ exports.usePoll = usePoll;
502
572
  exports.useProps = useProps;
503
573
  exports.useStream = useStream;
504
574
  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-qz2Ef0Rp.cjs';
3
- export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-qz2Ef0Rp.cjs';
2
+ import { G as GarretPlatform } from './platform-Byqljdn8.cjs';
3
+ export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-Byqljdn8.cjs';
4
4
  import { ReactNode } from 'react';
5
5
  import './protocol-Do0BJdeE.cjs';
6
6
 
@@ -40,6 +40,14 @@ declare function Accordion({ title, aside, defaultOpen, children }: {
40
40
  defaultOpen?: boolean;
41
41
  children: ReactNode;
42
42
  }): JSX.Element;
43
+ /** A thin status strip shown ABOVE content that already has data: a "couldn't refresh" notice
44
+ * (stale-while-error) or a subtle "refreshing" hint. Renders nothing when fresh + idle. Pair with
45
+ * `usePoll` — pass its `{ error, loading, refresh }`. */
46
+ declare function StatusStrip({ error, loading, onRetry }: {
47
+ error?: string;
48
+ loading?: boolean;
49
+ onRetry?: () => void;
50
+ }): JSX.Element | null;
43
51
  /** A small pill; `tone` sets the color. */
44
52
  declare function Badge({ tone, children }: {
45
53
  tone?: Tone;
@@ -85,6 +93,34 @@ declare function Switch({ on, onChange }: {
85
93
  on: boolean;
86
94
  onChange: (v: boolean) => void;
87
95
  }): JSX.Element;
96
+ /** One declarative settings field for `AutoForm`. */
97
+ type FieldSpec = {
98
+ key: string;
99
+ label: string;
100
+ type: 'text' | 'secret';
101
+ placeholder?: string;
102
+ } | {
103
+ key: string;
104
+ label: string;
105
+ type: 'number';
106
+ } | {
107
+ key: string;
108
+ label: string;
109
+ type: 'select';
110
+ options: [value: string, label: string][];
111
+ } | {
112
+ key: string;
113
+ label: string;
114
+ type: 'switch';
115
+ };
116
+ /** Render a settings form from a declarative schema — a convenience over hand-composing Field +
117
+ * inputs. `value` supplies current values by key; `onChange` gets a shallow patch. Compose freely
118
+ * with your own Fields (wrap in FieldGroup / SettingsPanel as you like). */
119
+ declare function AutoForm<T extends Record<string, unknown>>({ schema, value, onChange }: {
120
+ schema: FieldSpec[];
121
+ value: T;
122
+ onChange: (patch: Partial<T>) => void;
123
+ }): JSX.Element;
88
124
 
89
125
  /** Typed proxy of your host's methods. Stream-vs-Promise is inferred from each method's `Api` return
90
126
  * type — nothing to configure. */
@@ -126,10 +162,27 @@ declare function useInstanceConfig<T extends Record<string, unknown>>(defaults:
126
162
  set: (patch: Partial<T>) => void;
127
163
  loaded: boolean;
128
164
  };
165
+ /** Declarative polling: runs `fn` on mount + whenever `deps` change, then every `intervalMs`. Gated on
166
+ * board activity — pauses when the board is idle UNLESS `background` is set, in which case it keeps
167
+ * polling at a throttled floor (`idleFloorMs`, default 5 min) so alerts/data stay fresh while you're
168
+ * not looking (no extra process — the widget's own webview). Stale-while-error: keeps the last data on
169
+ * failure and surfaces `error`. Pair with `<StatusStrip error={error} loading={loading} onRetry={refresh} />`. */
170
+ declare function usePoll<T>(fn: () => Promise<T>, opts: {
171
+ intervalMs: number;
172
+ deps?: unknown[];
173
+ enabled?: boolean;
174
+ background?: boolean;
175
+ idleFloorMs?: number;
176
+ }): {
177
+ data: T | undefined;
178
+ error: string;
179
+ loading: boolean;
180
+ refresh: () => void;
181
+ };
129
182
 
130
183
  /** Launch props for a spawned surface window (`g.surfaces.open(..., { props })`). `{}` for the board
131
184
  * surface. Delivered via `onReady`'s callback (a contextBridge getter would be frozen at exposure
132
185
  * time), so this re-renders when the runtime binds. The `T` is an unchecked cast — validate it yourself. */
133
186
  declare function useProps<T = Record<string, unknown>>(): T;
134
187
 
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 };
188
+ export { Accordion, AutoForm, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, type FieldSpec, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, StatusStrip, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, usePoll, 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-Bbj2Vh3W.js';
3
- export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-Bbj2Vh3W.js';
2
+ import { G as GarretPlatform } from './platform-CRkiyy2a.js';
3
+ export { S as SurfaceApi, a as SurfaceHandle, b as SurfaceOpenOptions, W as WindowControls } from './platform-CRkiyy2a.js';
4
4
  import { ReactNode } from 'react';
5
5
  import './protocol-Do0BJdeE.js';
6
6
 
@@ -40,6 +40,14 @@ declare function Accordion({ title, aside, defaultOpen, children }: {
40
40
  defaultOpen?: boolean;
41
41
  children: ReactNode;
42
42
  }): JSX.Element;
43
+ /** A thin status strip shown ABOVE content that already has data: a "couldn't refresh" notice
44
+ * (stale-while-error) or a subtle "refreshing" hint. Renders nothing when fresh + idle. Pair with
45
+ * `usePoll` — pass its `{ error, loading, refresh }`. */
46
+ declare function StatusStrip({ error, loading, onRetry }: {
47
+ error?: string;
48
+ loading?: boolean;
49
+ onRetry?: () => void;
50
+ }): JSX.Element | null;
43
51
  /** A small pill; `tone` sets the color. */
44
52
  declare function Badge({ tone, children }: {
45
53
  tone?: Tone;
@@ -85,6 +93,34 @@ declare function Switch({ on, onChange }: {
85
93
  on: boolean;
86
94
  onChange: (v: boolean) => void;
87
95
  }): JSX.Element;
96
+ /** One declarative settings field for `AutoForm`. */
97
+ type FieldSpec = {
98
+ key: string;
99
+ label: string;
100
+ type: 'text' | 'secret';
101
+ placeholder?: string;
102
+ } | {
103
+ key: string;
104
+ label: string;
105
+ type: 'number';
106
+ } | {
107
+ key: string;
108
+ label: string;
109
+ type: 'select';
110
+ options: [value: string, label: string][];
111
+ } | {
112
+ key: string;
113
+ label: string;
114
+ type: 'switch';
115
+ };
116
+ /** Render a settings form from a declarative schema — a convenience over hand-composing Field +
117
+ * inputs. `value` supplies current values by key; `onChange` gets a shallow patch. Compose freely
118
+ * with your own Fields (wrap in FieldGroup / SettingsPanel as you like). */
119
+ declare function AutoForm<T extends Record<string, unknown>>({ schema, value, onChange }: {
120
+ schema: FieldSpec[];
121
+ value: T;
122
+ onChange: (patch: Partial<T>) => void;
123
+ }): JSX.Element;
88
124
 
89
125
  /** Typed proxy of your host's methods. Stream-vs-Promise is inferred from each method's `Api` return
90
126
  * type — nothing to configure. */
@@ -126,10 +162,27 @@ declare function useInstanceConfig<T extends Record<string, unknown>>(defaults:
126
162
  set: (patch: Partial<T>) => void;
127
163
  loaded: boolean;
128
164
  };
165
+ /** Declarative polling: runs `fn` on mount + whenever `deps` change, then every `intervalMs`. Gated on
166
+ * board activity — pauses when the board is idle UNLESS `background` is set, in which case it keeps
167
+ * polling at a throttled floor (`idleFloorMs`, default 5 min) so alerts/data stay fresh while you're
168
+ * not looking (no extra process — the widget's own webview). Stale-while-error: keeps the last data on
169
+ * failure and surfaces `error`. Pair with `<StatusStrip error={error} loading={loading} onRetry={refresh} />`. */
170
+ declare function usePoll<T>(fn: () => Promise<T>, opts: {
171
+ intervalMs: number;
172
+ deps?: unknown[];
173
+ enabled?: boolean;
174
+ background?: boolean;
175
+ idleFloorMs?: number;
176
+ }): {
177
+ data: T | undefined;
178
+ error: string;
179
+ loading: boolean;
180
+ refresh: () => void;
181
+ };
129
182
 
130
183
  /** Launch props for a spawned surface window (`g.surfaces.open(..., { props })`). `{}` for the board
131
184
  * surface. Delivered via `onReady`'s callback (a contextBridge getter would be frozen at exposure
132
185
  * time), so this re-renders when the runtime binds. The `T` is an unchecked cast — validate it yourself. */
133
186
  declare function useProps<T = Record<string, unknown>>(): T;
134
187
 
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 };
188
+ export { Accordion, AutoForm, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, type FieldSpec, GarretError, GarretPlatform, Item, NumberInput, Scroll, Select, SettingsPanel, StatusStrip, type StreamStatus, Switch, TextInput, type Tone, type UseStreamResult, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, usePoll, useProps, useStream, useWidgetMenu };
package/dist/react.js CHANGED
@@ -58,6 +58,26 @@ function Accordion({
58
58
  open && /* @__PURE__ */ jsx("div", { children })
59
59
  ] });
60
60
  }
61
+ function StatusStrip({
62
+ error,
63
+ loading,
64
+ onRetry
65
+ }) {
66
+ if (error) {
67
+ return /* @__PURE__ */ jsxs("div", { className: "gx-status gx-status--error", children: [
68
+ /* @__PURE__ */ jsx("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M1 1l22 22M16.72 11.06A10.94 10.94 0 0 1 19 12.55M5 12.55a10.94 10.94 0 0 1 5.17-2.39M10.71 5.05A16 16 0 0 1 22.58 9M1.42 9a15.91 15.91 0 0 1 4.7-2.88M8.53 16.11a6 6 0 0 1 6.95 0M12 20h.01" }) }),
69
+ /* @__PURE__ */ jsx("span", { children: "Couldn\u2019t refresh \u2014 showing last update" }),
70
+ onRetry && /* @__PURE__ */ jsx("button", { className: "gx-status-retry", onClick: onRetry, children: "Retry" })
71
+ ] });
72
+ }
73
+ if (loading) {
74
+ return /* @__PURE__ */ jsxs("div", { className: "gx-status", children: [
75
+ /* @__PURE__ */ jsx("svg", { className: "gx-status-spin", width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }),
76
+ /* @__PURE__ */ jsx("span", { children: "Refreshing\u2026" })
77
+ ] });
78
+ }
79
+ return null;
80
+ }
61
81
  function Badge({ tone = "neutral", children }) {
62
82
  return /* @__PURE__ */ jsx("span", { className: `gx-badge gx-badge--${tone}`, children });
63
83
  }
@@ -124,6 +144,21 @@ function Select({
124
144
  function Switch({ on, onChange }) {
125
145
  return /* @__PURE__ */ jsx("button", { className: `gx-switch${on ? " gx-switch--on" : ""}`, role: "switch", "aria-checked": on, onClick: () => onChange(!on), children: /* @__PURE__ */ jsx("span", { className: "gx-switch-knob" }) });
126
146
  }
147
+ function AutoForm({
148
+ schema,
149
+ value,
150
+ onChange
151
+ }) {
152
+ return /* @__PURE__ */ jsx(FieldGroup, { children: schema.map((f) => /* @__PURE__ */ jsx(Field, { label: f.label, children: f.type === "select" ? /* @__PURE__ */ jsx(Select, { value: String(value[f.key] ?? ""), options: f.options, onChange: (v) => onChange({ [f.key]: v }) }) : f.type === "switch" ? /* @__PURE__ */ jsx(Switch, { on: Boolean(value[f.key]), onChange: (v) => onChange({ [f.key]: v }) }) : f.type === "number" ? /* @__PURE__ */ jsx(NumberInput, { value: value[f.key], onCommit: (v) => onChange({ [f.key]: v }) }) : /* @__PURE__ */ jsx(
153
+ TextInput,
154
+ {
155
+ value: value[f.key],
156
+ placeholder: f.placeholder,
157
+ secret: f.type === "secret",
158
+ onCommit: (v) => onChange({ [f.key]: v })
159
+ }
160
+ ) }, f.key)) });
161
+ }
127
162
 
128
163
  // src/react.ts
129
164
  var singleton;
@@ -236,6 +271,38 @@ function useInstanceConfig(defaults) {
236
271
  );
237
272
  return { cfg, set, loaded };
238
273
  }
274
+ function usePoll(fn, opts) {
275
+ const { intervalMs, deps = [], enabled = true, background = false, idleFloorMs = 3e5 } = opts;
276
+ const active = useActive();
277
+ const [data, setData] = useState(void 0);
278
+ const [error, setError] = useState("");
279
+ const [loading, setLoading] = useState(false);
280
+ const fnRef = useRef(fn);
281
+ fnRef.current = fn;
282
+ const run = useCallback(async () => {
283
+ setLoading(true);
284
+ try {
285
+ setData(await fnRef.current());
286
+ setError("");
287
+ } catch (e) {
288
+ setError(e?.message || "Request failed");
289
+ } finally {
290
+ setLoading(false);
291
+ }
292
+ }, []);
293
+ useEffect(() => {
294
+ if (enabled) void run();
295
+ }, [enabled, run, ...deps]);
296
+ useEffect(() => {
297
+ if (!enabled || !(intervalMs > 0)) return;
298
+ const period = active ? intervalMs : Math.max(intervalMs, idleFloorMs);
299
+ const t = setInterval(() => {
300
+ if (active || background) void run();
301
+ }, period);
302
+ return () => clearInterval(t);
303
+ }, [enabled, intervalMs, active, background, idleFloorMs, run]);
304
+ return { data, error, loading, refresh: run };
305
+ }
239
306
  function useProps() {
240
307
  const g = getGarret();
241
308
  const [props, setProps] = useState({});
@@ -243,4 +310,4 @@ function useProps() {
243
310
  return props;
244
311
  }
245
312
 
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 };
313
+ export { Accordion, AutoForm, Badge, Dot, EmptyState, ErrorState, Field, FieldGroup, Item, NumberInput, Scroll, Select, SettingsPanel, StatusStrip, Switch, TextInput, useActive, useConfig, useGarret, useHost, useHostEvent, useInstanceConfig, usePoll, useProps, useStream, useWidgetMenu };
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-qz2Ef0Rp.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-Byqljdn8.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-Bbj2Vh3W.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-CRkiyy2a.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garretapp/sdk",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
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",