@colixsystems/widget-sdk 0.12.0 → 0.13.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.
- package/README.md +7 -2
- package/dist/contract.cjs +15 -0
- package/dist/contract.js +15 -0
- package/dist/hooks.js +40 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +2 -0
- package/dist/index.native.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
6
6
|
|
|
7
7
|
## Status
|
|
8
8
|
|
|
9
|
-
`v0.
|
|
9
|
+
`v0.13.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
10
|
+
|
|
11
|
+
### What's new in 0.13.0
|
|
12
|
+
|
|
13
|
+
- **`WidgetTree` component + `useChildRenderer()` hook** wired. Container widgets (Tabs, Card, …) can now render arbitrary author-authored child page-tree nodes through the SDK without importing the host renderer. The host pre-binds the surrounding render context (breakpoint, page ctx, parent) into a closure on `ctx.renderer.renderNode(node)` — the widget just passes the child node. Additive.
|
|
10
14
|
|
|
11
15
|
### What's new in 0.12.0
|
|
12
16
|
|
|
@@ -85,7 +89,8 @@ import { defineWidget, validateManifest, useDatastoreQuery, Text, View } from "@
|
|
|
85
89
|
|
|
86
90
|
- `defineWidget({ manifest, component })` — validates the manifest and produces a widget module the host can register.
|
|
87
91
|
- `validateManifest(m)` / `validatePropertySchema(s)` / `validateProps(schema, props)` — shape validation; no third-party deps.
|
|
88
|
-
- `useDatastoreQuery`, `useDatastoreRecord`, `useDatastoreMutation`, `useDirectory`, `useFile`, `useWidgetEvent`, `usePayments`, `useTheme`, `useI18n`, `useUser`, `useNavigation` — hooks that read from the host-provided `WidgetContext`. `useDirectory(query?)` returns `{ users, loading, error, refetch }` (each user `{ id, name, role }`) and requires the `directory.read:users` scope. `usePayments()` returns `{ requestPayment, getPayment }` and requires the `payments.charge:appUser` scope; `requestPayment(...)` rejects with a `PaymentError`. `useUser()` returns the active end-user identity `{ id, email, displayName, roles, groupIds }` (`id` is `null` for anonymous / preview). `useNavigation()` returns `{ goTo, goBack, push, replace, back, currentRoute }` for internal page navigation — for external URLs use the `Linking` primitive (`Linking.openURL(url)`). `useDatastoreRecord(tableId, recordId)` returns `{ data, loading, error, refetch }` for a single record (data is one row or null). `useFile(fileId)` returns `{ url, file, loading, error, refetch }` — the `url` is an absolute URL composed against the host's API base.
|
|
92
|
+
- `useDatastoreQuery`, `useDatastoreRecord`, `useDatastoreMutation`, `useDirectory`, `useFile`, `useWidgetEvent`, `usePayments`, `useTheme`, `useI18n`, `useUser`, `useNavigation`, `useChildRenderer` — hooks that read from the host-provided `WidgetContext`. `useDirectory(query?)` returns `{ users, loading, error, refetch }` (each user `{ id, name, role }`) and requires the `directory.read:users` scope. `usePayments()` returns `{ requestPayment, getPayment }` and requires the `payments.charge:appUser` scope; `requestPayment(...)` rejects with a `PaymentError`. `useUser()` returns the active end-user identity `{ id, email, displayName, roles, groupIds }` (`id` is `null` for anonymous / preview). `useNavigation()` returns `{ goTo, goBack, push, replace, back, currentRoute }` for internal page navigation — for external URLs use the `Linking` primitive (`Linking.openURL(url)`). `useDatastoreRecord(tableId, recordId)` returns `{ data, loading, error, refetch }` for a single record (data is one row or null). `useFile(fileId)` returns `{ url, file, loading, error, refetch }` — the `url` is an absolute URL composed against the host's API base. `useChildRenderer()` returns `{ renderNode(node) }` — container widgets call it to render arbitrary child page-tree nodes (prefer the `WidgetTree` component for the common case).
|
|
93
|
+
- `WidgetTree({ node })` — component that renders an author-authored child node through the host's renderer; used by Tabs / Card / custom containers to host arbitrary child widgets.
|
|
89
94
|
- `Text`, `View`, `Pressable`, `Image`, `ScrollView`, `TextInput`, `FlatList`, `SectionList`, `ActivityIndicator`, `Switch`, `StyleSheet` — re-exported from `react-native`. The web build aliases `react-native` to `react-native-web` so widgets render in the browser without any per-platform code; the exported Expo app's Metro bundler resolves the real `react-native` library. See https://reactnative.dev/docs/ for per-component props.
|
|
90
95
|
- `WidgetContextProvider` — React context provider that the host (Studio, Player, exported app) wraps widgets with.
|
|
91
96
|
|
package/dist/contract.cjs
CHANGED
|
@@ -68,6 +68,15 @@ const HOOKS = [
|
|
|
68
68
|
requiredContextSlice: ["user"],
|
|
69
69
|
scopes: null,
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: "useChildRenderer",
|
|
73
|
+
signature: "useChildRenderer()",
|
|
74
|
+
returnShape: {
|
|
75
|
+
renderNode: "(node) => ReactElement",
|
|
76
|
+
},
|
|
77
|
+
requiredContextSlice: ["renderer.renderNode"],
|
|
78
|
+
scopes: null,
|
|
79
|
+
},
|
|
71
80
|
{
|
|
72
81
|
name: "useNavigation",
|
|
73
82
|
signature: "useNavigation()",
|
|
@@ -407,6 +416,12 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
407
416
|
required: true,
|
|
408
417
|
fields: { get: "function" },
|
|
409
418
|
},
|
|
419
|
+
renderer: {
|
|
420
|
+
description:
|
|
421
|
+
"Host child-node renderer. { renderNode(node) -> ReactElement }. Backs WidgetTree / useChildRenderer; lets a container widget (Tabs, Card, …) render arbitrary author-authored child nodes without importing the host renderer. The closure pre-binds breakpoint + page ctx + parent so the widget passes only the child node.",
|
|
422
|
+
required: true,
|
|
423
|
+
fields: { renderNode: "function" },
|
|
424
|
+
},
|
|
410
425
|
events: {
|
|
411
426
|
description: "{ emit(name, payload) }.",
|
|
412
427
|
required: true,
|
package/dist/contract.js
CHANGED
|
@@ -68,6 +68,15 @@ const HOOKS = [
|
|
|
68
68
|
requiredContextSlice: ["user"],
|
|
69
69
|
scopes: null,
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: "useChildRenderer",
|
|
73
|
+
signature: "useChildRenderer()",
|
|
74
|
+
returnShape: {
|
|
75
|
+
renderNode: "(node) => ReactElement",
|
|
76
|
+
},
|
|
77
|
+
requiredContextSlice: ["renderer.renderNode"],
|
|
78
|
+
scopes: null,
|
|
79
|
+
},
|
|
71
80
|
{
|
|
72
81
|
name: "useNavigation",
|
|
73
82
|
signature: "useNavigation()",
|
|
@@ -401,6 +410,12 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
401
410
|
required: true,
|
|
402
411
|
fields: { get: "function" },
|
|
403
412
|
},
|
|
413
|
+
renderer: {
|
|
414
|
+
description:
|
|
415
|
+
"Host child-node renderer. { renderNode(node) -> ReactElement }. Backs WidgetTree / useChildRenderer; lets a container widget (Tabs, Card, …) render arbitrary author-authored child nodes without importing the host renderer. The closure pre-binds breakpoint + page ctx + parent so the widget passes only the child node.",
|
|
416
|
+
required: true,
|
|
417
|
+
fields: { renderNode: "function" },
|
|
418
|
+
},
|
|
404
419
|
events: {
|
|
405
420
|
description: "{ emit(name, payload) }.",
|
|
406
421
|
required: true,
|
package/dist/hooks.js
CHANGED
|
@@ -517,6 +517,46 @@ export function useUser() {
|
|
|
517
517
|
return ctx.user;
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
+
/**
|
|
521
|
+
* Returns the host's child-node renderer:
|
|
522
|
+
* { renderNode(node) }.
|
|
523
|
+
*
|
|
524
|
+
* Widgets like Tabs / Card / a custom container call `renderNode(child)`
|
|
525
|
+
* to render an author-authored page-tree node nested inside themselves.
|
|
526
|
+
* The renderer closes over the surrounding render context (breakpoint,
|
|
527
|
+
* page ctx, parent) that the host already knows, so the widget doesn't
|
|
528
|
+
* need to plumb any of that through.
|
|
529
|
+
*
|
|
530
|
+
* Prefer the `WidgetTree` component for the common case
|
|
531
|
+
* (`<WidgetTree node={child} />`); reach for the hook when you need to
|
|
532
|
+
* branch on the node's shape before rendering.
|
|
533
|
+
*/
|
|
534
|
+
export function useChildRenderer() {
|
|
535
|
+
const ctx = useWidgetContextOrThrow("useChildRenderer");
|
|
536
|
+
if (!ctx.renderer || typeof ctx.renderer.renderNode !== "function") {
|
|
537
|
+
throw new Error(
|
|
538
|
+
"useChildRenderer: host did not inject a child-node renderer",
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
return ctx.renderer;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Renders an author-authored page-tree node through the host's child
|
|
546
|
+
* renderer. The widget hands off a node (or null) and gets back a React
|
|
547
|
+
* element rendered with the same dispatch the top-level page uses, so
|
|
548
|
+
* Tabs / Card / custom container widgets can host arbitrary child
|
|
549
|
+
* widgets without importing the host.
|
|
550
|
+
*/
|
|
551
|
+
export function WidgetTree({ node }) {
|
|
552
|
+
const ctx = useWidgetContextOrThrow("WidgetTree");
|
|
553
|
+
if (!ctx.renderer || typeof ctx.renderer.renderNode !== "function") {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
if (!node) return null;
|
|
557
|
+
return ctx.renderer.renderNode(node);
|
|
558
|
+
}
|
|
559
|
+
|
|
520
560
|
/**
|
|
521
561
|
* Returns the host-provided navigation surface:
|
|
522
562
|
* `{ goTo, goBack, push, replace, back, currentRoute }`.
|
package/dist/index.d.ts
CHANGED
|
@@ -382,6 +382,22 @@ export function useDatastoreRecord(
|
|
|
382
382
|
* refetch }`. The `url` is an absolute URL composed against the host's API
|
|
383
383
|
* base; safe to pass straight to `<Image source>`.
|
|
384
384
|
*/
|
|
385
|
+
/**
|
|
386
|
+
* The host's child-node renderer surface. `renderNode(node)` returns a
|
|
387
|
+
* React element rendered with the same dispatch the top-level page uses;
|
|
388
|
+
* the closure pre-binds breakpoint / page ctx / parent.
|
|
389
|
+
*/
|
|
390
|
+
export function useChildRenderer(): {
|
|
391
|
+
renderNode(node: unknown): unknown;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Renders an author-authored page-tree node through the host's child
|
|
396
|
+
* renderer. Prefer this over `useChildRenderer()` for the common case
|
|
397
|
+
* (`<WidgetTree node={child} />`).
|
|
398
|
+
*/
|
|
399
|
+
export const WidgetTree: (props: { node: unknown }) => unknown;
|
|
400
|
+
|
|
385
401
|
export function useFile(fileId: string | null | undefined): {
|
|
386
402
|
url: string | null;
|
|
387
403
|
file: {
|
package/dist/index.js
CHANGED
package/dist/index.native.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|