@apotech-os/ui-sdk 0.2.0 → 0.5.0-rc.1

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.
package/dist/index.d.cts CHANGED
@@ -36,6 +36,42 @@ interface AppApiClient {
36
36
  * Perform a POST request to a platform-data endpoint.
37
37
  */
38
38
  post<T>(path: string, body?: unknown): Promise<T>;
39
+ /**
40
+ * Perform a PATCH request to a platform-data endpoint (e.g. update a record).
41
+ */
42
+ patch<T>(path: string, body?: unknown): Promise<T>;
43
+ /**
44
+ * Perform a DELETE request to a platform-data endpoint (e.g. delete a record).
45
+ */
46
+ delete<T>(path: string): Promise<T>;
47
+ /**
48
+ * Run one of this app's `uiInvoke` functions and get its return value back.
49
+ *
50
+ * This is the ONLY way a page can reach an integration: the action endpoint
51
+ * requires an app token and refuses a browser session. The platform mints the
52
+ * token server-side and runs the handler in-process.
53
+ *
54
+ * The function must be declared `trigger: { type: 'uiInvoke' }` in the
55
+ * manifest, and the caller must hold its `minRole` (default EDITOR).
56
+ *
57
+ * Pass `idempotencyKey` for anything that must not run twice on a double
58
+ * click — a concurrent duplicate is rejected with 409 INVOCATION_IN_FLIGHT.
59
+ *
60
+ * Throws AppInvokeError. `code === 'FUNCTION_REJECTED'` carries an app-authored
61
+ * message that is safe to show the user; every other failure is generic on
62
+ * purpose (raw provider errors can leak tokens or PII).
63
+ */
64
+ invoke<TResult, TInput = Record<string, unknown>>(functionName: string, input?: TInput, opts?: {
65
+ idempotencyKey?: string;
66
+ signal?: AbortSignal;
67
+ }): Promise<TResult>;
68
+ }
69
+ /** Thrown by AppApiClient.invoke. */
70
+ declare class AppInvokeError extends Error {
71
+ readonly status: number;
72
+ readonly code?: string | undefined;
73
+ readonly invocationId?: string | undefined;
74
+ constructor(status: number, message: string, code?: string | undefined, invocationId?: string | undefined);
39
75
  }
40
76
  declare const AppApiProvider: React.Provider<AppApiClient | null>;
41
77
  /**
@@ -80,7 +116,7 @@ interface TabsProps {
80
116
  children: React.ReactNode;
81
117
  }
82
118
  declare function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps): React.JSX.Element;
83
- declare function TabsList({ className, children }: {
119
+ declare function TabsList({ className, children, }: {
84
120
  className?: string;
85
121
  children: React.ReactNode;
86
122
  }): React.JSX.Element;
@@ -131,5 +167,101 @@ interface DateRangePickerProps {
131
167
  }
132
168
  /** Minimal controlled date-range picker using two native date inputs. */
133
169
  declare function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps): React.JSX.Element;
170
+ type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
171
+ declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
172
+ interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange'> {
173
+ checked?: boolean;
174
+ /** Preferred over onChange — receives the boolean directly. */
175
+ onCheckedChange?: (checked: boolean) => void;
176
+ label?: React.ReactNode;
177
+ }
178
+ declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
179
+ interface SidePanelProps {
180
+ open: boolean;
181
+ onClose: () => void;
182
+ title?: React.ReactNode;
183
+ description?: React.ReactNode;
184
+ children: React.ReactNode;
185
+ className?: string;
186
+ }
187
+ /**
188
+ * Blocking slide-over — reach for it when a task has more fields than a `Modal`
189
+ * can show without an inner scrollbar. Full height, so the body scrolls once and
190
+ * a footer can stay pinned; `Modal` centres a box and does no height management.
191
+ *
192
+ * Children are laid out in a flex column filling the panel: put the scrollable
193
+ * region in a `min-h-0 flex-1 overflow-y-auto` child and the footer after it.
194
+ *
195
+ * NOTE: no focus management. Autofocus the primary action yourself.
196
+ */
197
+ declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element | null;
198
+ interface CopyButtonProps {
199
+ value: string;
200
+ label?: string;
201
+ copiedLabel?: string;
202
+ variant?: ButtonProps['variant'];
203
+ size?: ButtonProps['size'];
204
+ className?: string;
205
+ }
206
+ /**
207
+ * Copy-to-clipboard button with inline feedback. On failure it says so rather
208
+ * than silently doing nothing — keep the copyable text selectable so manual
209
+ * copy stays the fallback.
210
+ */
211
+ declare function CopyButton({ value, label, copiedLabel, variant, size, className, }: CopyButtonProps): React.JSX.Element;
212
+ interface PopoverProps {
213
+ open: boolean;
214
+ onOpenChange: (open: boolean) => void;
215
+ trigger: React.ReactNode;
216
+ children: React.ReactNode;
217
+ align?: 'start' | 'end';
218
+ className?: string;
219
+ }
220
+ /** Anchored panel. Controlled — the caller owns `open`. Closes on outside click
221
+ * and Escape, which is what a filter pill needs and a Modal is too heavy for. */
222
+ declare function Popover({ open, onOpenChange, trigger, children, align, className, }: PopoverProps): React.JSX.Element;
223
+ interface DropdownMenuItem {
224
+ label: React.ReactNode;
225
+ onSelect: () => void;
226
+ disabled?: boolean;
227
+ destructive?: boolean;
228
+ }
229
+ interface DropdownMenuProps {
230
+ trigger: React.ReactNode;
231
+ items: DropdownMenuItem[];
232
+ align?: 'start' | 'end';
233
+ className?: string;
234
+ }
235
+ /** Uncontrolled menu built on Popover. Selecting an item closes it. */
236
+ declare function DropdownMenu({ trigger, items, align, className }: DropdownMenuProps): React.JSX.Element;
237
+
238
+ /**
239
+ * Browser helpers for app pages.
240
+ *
241
+ * App bundles get react, react-dom and this SDK from the shell's import map and
242
+ * bundle everything else themselves — so without these here, every app would
243
+ * reimplement clipboard handling and CSV escaping, and get the edge cases wrong
244
+ * in its own way.
245
+ */
246
+ /**
247
+ * Copy text to the clipboard.
248
+ *
249
+ * Returns `false` instead of throwing when the clipboard is unavailable (non
250
+ * secure context, permission refused) so the caller can render inline feedback.
251
+ * No `document.execCommand('copy')` fallback: it is deprecated, and the shell
252
+ * only ever runs on https or localhost, both secure contexts.
253
+ */
254
+ declare function copyToClipboard(text: string): Promise<boolean>;
255
+ /** Trigger a browser download of a Blob via a throwaway object URL + `<a>` click. */
256
+ declare function downloadBlob(blob: Blob, filename: string): void;
257
+ /** Serialize rows (header included) into an RFC 4180 CSV string. */
258
+ declare function toCsv(rows: string[][]): string;
259
+ /**
260
+ * Serialize + download in one call.
261
+ *
262
+ * The BOM is the whole reason this helper exists: without it Excel on Windows
263
+ * reads the file as latin-1 and mangles every accented character.
264
+ */
265
+ declare function downloadCsv(rows: string[][], filename: string): void;
134
266
 
135
- export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type DateRange, DateRangePicker, type DateRangePickerProps, Input, Link, type LinkProps, Modal, type ModalProps, Select, type SelectProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, cn, useAppApi, useAppContext };
267
+ export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, AppInvokeError, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, Checkbox, type CheckboxProps, CopyButton, type CopyButtonProps, type DateRange, DateRangePicker, type DateRangePickerProps, DropdownMenu, type DropdownMenuItem, type DropdownMenuProps, Input, Link, type LinkProps, Modal, type ModalProps, Popover, type PopoverProps, Select, type SelectProps, SidePanel, type SidePanelProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, type TextareaProps, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext };
package/dist/index.d.ts CHANGED
@@ -36,6 +36,42 @@ interface AppApiClient {
36
36
  * Perform a POST request to a platform-data endpoint.
37
37
  */
38
38
  post<T>(path: string, body?: unknown): Promise<T>;
39
+ /**
40
+ * Perform a PATCH request to a platform-data endpoint (e.g. update a record).
41
+ */
42
+ patch<T>(path: string, body?: unknown): Promise<T>;
43
+ /**
44
+ * Perform a DELETE request to a platform-data endpoint (e.g. delete a record).
45
+ */
46
+ delete<T>(path: string): Promise<T>;
47
+ /**
48
+ * Run one of this app's `uiInvoke` functions and get its return value back.
49
+ *
50
+ * This is the ONLY way a page can reach an integration: the action endpoint
51
+ * requires an app token and refuses a browser session. The platform mints the
52
+ * token server-side and runs the handler in-process.
53
+ *
54
+ * The function must be declared `trigger: { type: 'uiInvoke' }` in the
55
+ * manifest, and the caller must hold its `minRole` (default EDITOR).
56
+ *
57
+ * Pass `idempotencyKey` for anything that must not run twice on a double
58
+ * click — a concurrent duplicate is rejected with 409 INVOCATION_IN_FLIGHT.
59
+ *
60
+ * Throws AppInvokeError. `code === 'FUNCTION_REJECTED'` carries an app-authored
61
+ * message that is safe to show the user; every other failure is generic on
62
+ * purpose (raw provider errors can leak tokens or PII).
63
+ */
64
+ invoke<TResult, TInput = Record<string, unknown>>(functionName: string, input?: TInput, opts?: {
65
+ idempotencyKey?: string;
66
+ signal?: AbortSignal;
67
+ }): Promise<TResult>;
68
+ }
69
+ /** Thrown by AppApiClient.invoke. */
70
+ declare class AppInvokeError extends Error {
71
+ readonly status: number;
72
+ readonly code?: string | undefined;
73
+ readonly invocationId?: string | undefined;
74
+ constructor(status: number, message: string, code?: string | undefined, invocationId?: string | undefined);
39
75
  }
40
76
  declare const AppApiProvider: React.Provider<AppApiClient | null>;
41
77
  /**
@@ -80,7 +116,7 @@ interface TabsProps {
80
116
  children: React.ReactNode;
81
117
  }
82
118
  declare function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps): React.JSX.Element;
83
- declare function TabsList({ className, children }: {
119
+ declare function TabsList({ className, children, }: {
84
120
  className?: string;
85
121
  children: React.ReactNode;
86
122
  }): React.JSX.Element;
@@ -131,5 +167,101 @@ interface DateRangePickerProps {
131
167
  }
132
168
  /** Minimal controlled date-range picker using two native date inputs. */
133
169
  declare function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps): React.JSX.Element;
170
+ type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
171
+ declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
172
+ interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange'> {
173
+ checked?: boolean;
174
+ /** Preferred over onChange — receives the boolean directly. */
175
+ onCheckedChange?: (checked: boolean) => void;
176
+ label?: React.ReactNode;
177
+ }
178
+ declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
179
+ interface SidePanelProps {
180
+ open: boolean;
181
+ onClose: () => void;
182
+ title?: React.ReactNode;
183
+ description?: React.ReactNode;
184
+ children: React.ReactNode;
185
+ className?: string;
186
+ }
187
+ /**
188
+ * Blocking slide-over — reach for it when a task has more fields than a `Modal`
189
+ * can show without an inner scrollbar. Full height, so the body scrolls once and
190
+ * a footer can stay pinned; `Modal` centres a box and does no height management.
191
+ *
192
+ * Children are laid out in a flex column filling the panel: put the scrollable
193
+ * region in a `min-h-0 flex-1 overflow-y-auto` child and the footer after it.
194
+ *
195
+ * NOTE: no focus management. Autofocus the primary action yourself.
196
+ */
197
+ declare function SidePanel({ open, onClose, title, description, children, className, }: SidePanelProps): React.JSX.Element | null;
198
+ interface CopyButtonProps {
199
+ value: string;
200
+ label?: string;
201
+ copiedLabel?: string;
202
+ variant?: ButtonProps['variant'];
203
+ size?: ButtonProps['size'];
204
+ className?: string;
205
+ }
206
+ /**
207
+ * Copy-to-clipboard button with inline feedback. On failure it says so rather
208
+ * than silently doing nothing — keep the copyable text selectable so manual
209
+ * copy stays the fallback.
210
+ */
211
+ declare function CopyButton({ value, label, copiedLabel, variant, size, className, }: CopyButtonProps): React.JSX.Element;
212
+ interface PopoverProps {
213
+ open: boolean;
214
+ onOpenChange: (open: boolean) => void;
215
+ trigger: React.ReactNode;
216
+ children: React.ReactNode;
217
+ align?: 'start' | 'end';
218
+ className?: string;
219
+ }
220
+ /** Anchored panel. Controlled — the caller owns `open`. Closes on outside click
221
+ * and Escape, which is what a filter pill needs and a Modal is too heavy for. */
222
+ declare function Popover({ open, onOpenChange, trigger, children, align, className, }: PopoverProps): React.JSX.Element;
223
+ interface DropdownMenuItem {
224
+ label: React.ReactNode;
225
+ onSelect: () => void;
226
+ disabled?: boolean;
227
+ destructive?: boolean;
228
+ }
229
+ interface DropdownMenuProps {
230
+ trigger: React.ReactNode;
231
+ items: DropdownMenuItem[];
232
+ align?: 'start' | 'end';
233
+ className?: string;
234
+ }
235
+ /** Uncontrolled menu built on Popover. Selecting an item closes it. */
236
+ declare function DropdownMenu({ trigger, items, align, className }: DropdownMenuProps): React.JSX.Element;
237
+
238
+ /**
239
+ * Browser helpers for app pages.
240
+ *
241
+ * App bundles get react, react-dom and this SDK from the shell's import map and
242
+ * bundle everything else themselves — so without these here, every app would
243
+ * reimplement clipboard handling and CSV escaping, and get the edge cases wrong
244
+ * in its own way.
245
+ */
246
+ /**
247
+ * Copy text to the clipboard.
248
+ *
249
+ * Returns `false` instead of throwing when the clipboard is unavailable (non
250
+ * secure context, permission refused) so the caller can render inline feedback.
251
+ * No `document.execCommand('copy')` fallback: it is deprecated, and the shell
252
+ * only ever runs on https or localhost, both secure contexts.
253
+ */
254
+ declare function copyToClipboard(text: string): Promise<boolean>;
255
+ /** Trigger a browser download of a Blob via a throwaway object URL + `<a>` click. */
256
+ declare function downloadBlob(blob: Blob, filename: string): void;
257
+ /** Serialize rows (header included) into an RFC 4180 CSV string. */
258
+ declare function toCsv(rows: string[][]): string;
259
+ /**
260
+ * Serialize + download in one call.
261
+ *
262
+ * The BOM is the whole reason this helper exists: without it Excel on Windows
263
+ * reads the file as latin-1 and mangles every accented character.
264
+ */
265
+ declare function downloadCsv(rows: string[][], filename: string): void;
134
266
 
135
- export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type DateRange, DateRangePicker, type DateRangePickerProps, Input, Link, type LinkProps, Modal, type ModalProps, Select, type SelectProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, cn, useAppApi, useAppContext };
267
+ export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, AppInvokeError, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, Checkbox, type CheckboxProps, CopyButton, type CopyButtonProps, type DateRange, DateRangePicker, type DateRangePickerProps, DropdownMenu, type DropdownMenuItem, type DropdownMenuProps, Input, Link, type LinkProps, Modal, type ModalProps, Popover, type PopoverProps, Select, type SelectProps, SidePanel, type SidePanelProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, Textarea, type TextareaProps, cn, copyToClipboard, downloadBlob, downloadCsv, toCsv, useAppApi, useAppContext };