@colixsystems/widget-sdk 0.142.0 → 0.143.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 +22 -2
- package/dist/contract.cjs +45 -1
- package/dist/contract.js +45 -1
- package/dist/filepicker.native.js +8 -9
- package/dist/hooks.js +37 -8
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.native.js +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ The data layer lives in **four separate domain-client packages**, each instantia
|
|
|
32
32
|
| **CORE** | `useContainerWidth()` | `[width, onLayout]` | No context slice, no scope. Measures the width the widget's OWN box has, so it can lay itself out for the space it is in rather than for the screen. Spread the handler onto your outermost primitive. Use it for any widget with a wide form and a narrow one (a table, a toolbar, a row of tiles) — never switch on the device or window width, because a widget in a one-of-three grid cell on desktop has phone-width room and a widget filling a phone page does not. Width is 0 until the first layout: render the WIDE form then. One implementation covers web (react-native-web) and the native export. |
|
|
33
33
|
| **CORE** | `isNarrowWidth(width)` | `boolean` | No context slice, no scope. True when a MEASURED width is below `NARROW_WIDTH_PX` (480) — the one threshold every widget switches at, so a page reflows together rather than raggedly. An unmeasured width (0) is NOT narrow, so nothing flashes through the narrow form on first paint. |
|
|
34
34
|
| **CORE** | `useSectionEmpty(isEmpty)` | `void` | `ctx.section.reportEmpty` — no scope. Declares that the widget has NO content to show, so the host drops its layout slot instead of reserving space (and its parent's `gap`) for it. Returning `null` is not enough: the host wraps every widget in an entrance element, so a widget rendering nothing still leaves an empty box the parent stack gaps around. For a CONDITIONALLY ABSENT section (a per-record child collection with no rows for this record), never to suppress a genuine empty state. Stays mounted while collapsed, so passing `false` brings it back. Authoring surfaces never collapse. No-op on a host that doesn't implement it. |
|
|
35
|
+
| **CORE** | `useScreenTitle(title)` | `void` | `ctx.screen.reportTitle` — no scope. Names the screen the widget is on, so the host paints that name in the app header beside the back control instead of the app brand. The page's own name is the default; only the widget knows the screen is really "Order #1423" rather than "Orders". The MOST RECENT call wins — with several widgets on one screen the last to report owns the title, and on unmount (or an empty title) the host falls back to the most recent surviving report and finally to the page name. Only a screen showing the back control paints a title; a root page keeps the brand. No-op on a host that doesn't implement it. |
|
|
35
36
|
| **CORE** | `useRefresh(handler)` | `void` | `ctx.refresh.subscribe` — no scope. Subscribes the handler to the page-level refresh tick (pull-to-refresh on mobile). Handler may return a Promise — the host waits for `allSettled` before clearing the spinner. The three datastore hooks auto-subscribe their own `refetch`; widgets only call this directly to re-run non-datastore work. No-op on a host that doesn't implement refresh. |
|
|
36
37
|
| **CORE** | `useClipboard()` | `{ copy, paste, hasContent }` | platform clipboard (web `navigator.clipboard` / native `expo-clipboard`); rejects with `ClipboardError` — no scope |
|
|
37
38
|
| **CORE** | `useToast()` | `{ showToast }` | `ctx.toast.showToast` — wired by the Player and the Expo export; an authoring preview omits it and the call is a no-op — no scope |
|
|
@@ -70,7 +71,26 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
70
71
|
|
|
71
72
|
## Status
|
|
72
73
|
|
|
73
|
-
`v0.
|
|
74
|
+
`v0.143.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**.
|
|
75
|
+
|
|
76
|
+
### What's new in 0.143.0 (contract 1.111.0)
|
|
77
|
+
|
|
78
|
+
**A widget can name the screen it is on — `useScreenTitle(title)` + the optional `ctx.screen` slice (sc-7955).** The app header now shows the PAGE title beside the back control on a sub-page, instead of repeating the app brand on every screen. The page's own name is the default, but a page is often about one record, and only the widget has it:
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
const { data: order } = useDatastoreRecord(tableId, recordId);
|
|
82
|
+
useScreenTitle(order ? `Order #${order.reference}` : null);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- The header reads "Order #1423" rather than "Orders" as soon as the record lands; before it does, the blank title leaves the page name standing (only a non-empty string registers).
|
|
86
|
+
- `reportTitle` returns a release function, so the title reverts cleanly when the widget unmounts or its title empties.
|
|
87
|
+
- **The most recent call wins.** With two title-setting widgets on one screen the last to report owns the header; when it goes, the host falls back to the most recent surviving report, then to the page name.
|
|
88
|
+
- Only a screen that shows the back control paints a title — a root/menu page keeps the app brand or logo untouched.
|
|
89
|
+
- Optional slice: on the Studio canvas and the Agent Mode edit preview there is no app header, so the hook is a no-op rather than an error.
|
|
90
|
+
|
|
91
|
+
### What's new in 0.142.1
|
|
92
|
+
|
|
93
|
+
**A native file upload no longer crashes the app (sc-7906).** Making the part a `File` let the upload through, and then the app died on any real file: Expo's `fetch` builds a multipart body by reading the WHOLE file into the JS heap — `convertFormDataAsync` awaits `part.bytes()` and concatenates — so a send costs about three times the file's size on the JS thread. The native host now streams the file off disk through expo-file-system's upload task instead. `<FilePicker>`, `useCamera()` and `useImageEditor()` are unchanged for a widget author — the picked file stays where the picker put it, so `asset.uri` still renders, and the name the user chose travels to the backend as an explicit `file_name` field.
|
|
74
94
|
|
|
75
95
|
### What's new in 0.142.0 (contract 1.110.0)
|
|
76
96
|
|
|
@@ -526,7 +546,7 @@ When you take the `useCanWrite`-only route, omit the USER column for a guest (`i
|
|
|
526
546
|
|
|
527
547
|
**Dismissing the picker resolves `null`, not an error.** Backing out is the most common outcome, so it is deliberately not a rejection — your happy path needs no `try/catch`. A genuine failure (permission refused, no host broker) rejects with a structured `CameraError` (new named export) carrying a stable `.code` (`PERMISSION_DENIED` / `UNSUPPORTED` / `INTERNAL`).
|
|
528
548
|
|
|
529
|
-
**One upload path on both hosts.** The resolved asset is normalised to `{ uri, name, mimeType, width, height, size, file }`, where `uri` is directly displayable (`<Image source={{ uri }} />`) and `file` is already the right upload part for the platform — a
|
|
549
|
+
**One upload path on both hosts.** The resolved asset is normalised to `{ uri, name, mimeType, width, height, size, file }`, where `uri` is directly displayable (`<Image source={{ uri }} />`) and `file` is already the right upload part for the platform — a browser `File` on web, expo-file-system's `File` on native. (Never React Native's legacy `{ uri, name, type }` part: the native host streams the file off disk, and Expo's fetch rejects that part outright anyway. Do not branch on the part's type — an expo-file-system `File` is NOT `instanceof Blob` at runtime.) So the same three lines work everywhere:
|
|
530
550
|
|
|
531
551
|
```js
|
|
532
552
|
const fd = new FormData();
|
package/dist/contract.cjs
CHANGED
|
@@ -718,6 +718,26 @@ const HOOKS = [
|
|
|
718
718
|
requiredContextSlice: ["section.reportEmpty"],
|
|
719
719
|
scopes: null,
|
|
720
720
|
},
|
|
721
|
+
{
|
|
722
|
+
name: "useScreenTitle",
|
|
723
|
+
signature: "useScreenTitle(title)",
|
|
724
|
+
description:
|
|
725
|
+
"Name the screen this widget is on, so the host paints that name in the " +
|
|
726
|
+
"app header beside the back control. The page's own name is the default; " +
|
|
727
|
+
"only the widget knows when the screen is really \"Order #1423\" rather " +
|
|
728
|
+
"than \"Orders\". The MOST RECENT call wins: with several widgets on one " +
|
|
729
|
+
"screen the last to report owns the title, and when that widget unmounts " +
|
|
730
|
+
"(or passes an empty title) the host falls back to the most recent " +
|
|
731
|
+
"surviving report and finally to the page name. Only a screen that shows " +
|
|
732
|
+
"the back control paints a title — a root page keeps the app brand, so a " +
|
|
733
|
+
"title reported there is held but not shown. Safe on a host that does not " +
|
|
734
|
+
"implement it (Studio canvas, Agent Mode edit preview) — a no-op there.",
|
|
735
|
+
returnShape: {
|
|
736
|
+
"(returns)": "void",
|
|
737
|
+
},
|
|
738
|
+
requiredContextSlice: ["screen.reportTitle"],
|
|
739
|
+
scopes: null,
|
|
740
|
+
},
|
|
721
741
|
{
|
|
722
742
|
name: "useNavigation",
|
|
723
743
|
signature: "useNavigation()",
|
|
@@ -2321,6 +2341,22 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
2321
2341
|
required: false,
|
|
2322
2342
|
fields: { subscribe: "function" },
|
|
2323
2343
|
},
|
|
2344
|
+
// sc-7955 — widget -> host screen-chrome signal. The widget owns the knowledge
|
|
2345
|
+
// (it has the record), the host owns the chrome (the header title slot).
|
|
2346
|
+
// Optional so an AUTHORING host can omit it: with no slice the hook is a
|
|
2347
|
+
// no-op on the Studio canvas and the Agent Mode edit preview, neither of
|
|
2348
|
+
// which paints an app header at all.
|
|
2349
|
+
screen: {
|
|
2350
|
+
description:
|
|
2351
|
+
"Optional screen-chrome slot. { reportTitle(title) -> release }. " +
|
|
2352
|
+
"Registers this widget's title for the screen it is on and returns a " +
|
|
2353
|
+
"release function that withdraws it; the host paints the most recently " +
|
|
2354
|
+
"registered title in the header beside the back control and falls back " +
|
|
2355
|
+
"to the page name once every registration is released. Backs " +
|
|
2356
|
+
"useScreenTitle().",
|
|
2357
|
+
required: false,
|
|
2358
|
+
fields: { reportTitle: "function" },
|
|
2359
|
+
},
|
|
2324
2360
|
// sc-4416 — widget -> host emptiness signal. The widget owns the knowledge
|
|
2325
2361
|
// (it has the rows); the host owns the spacing (the slot and its gap).
|
|
2326
2362
|
// Optional so an AUTHORING host can omit it on purpose: with no slice the
|
|
@@ -3983,6 +4019,14 @@ const CONTRACT = deepFreeze({
|
|
|
3983
4019
|
// and the sc-7352 backfill deletes the stored key (a bottom-tabs app's
|
|
3984
4020
|
// strip becomes the sidebar's quick bar) BEFORE this ships.
|
|
3985
4021
|
// `menuItemCap` / `quickBarCap` keep their signatures.
|
|
4022
|
+
// 1.111.0: additive (sc-7955) -- `screen` joins `widgetContextShape` and
|
|
4023
|
+
// `useScreenTitle(title)` joins `hooks`: a widget names the screen it is
|
|
4024
|
+
// on, and the host paints that name in the header beside the back control
|
|
4025
|
+
// instead of the app brand. `reportTitle` returns a release function; the
|
|
4026
|
+
// MOST RECENT registration wins and the host falls back to the most recent
|
|
4027
|
+
// surviving one, then to the page name. The slice is OPTIONAL, so an
|
|
4028
|
+
// authoring host (Studio canvas, Agent Mode edit preview) omits it and the
|
|
4029
|
+
// hook is a no-op there rather than an error.
|
|
3986
4030
|
// 1.110.0: additive (sc-7885) — `triggeredBy` joins `actionScriptGlobals`:
|
|
3987
4031
|
// WHO initiated this run, as `{ type, id, name, email, role }`, or `null`
|
|
3988
4032
|
// on `schedule` / `record_*` where nothing did. `type` is `"app_user"` (an
|
|
@@ -3992,7 +4036,7 @@ const CONTRACT = deepFreeze({
|
|
|
3992
4036
|
// integration identity; this describes the caller, it does not grant
|
|
3993
4037
|
// anything. The same commit adds `properties` to this list, which the
|
|
3994
4038
|
// action-sdk copy had carried since 1.50.0 while this one had not.
|
|
3995
|
-
version: "1.
|
|
4039
|
+
version: "1.111.0",
|
|
3996
4040
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3997
4041
|
hooks: HOOKS,
|
|
3998
4042
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -718,6 +718,26 @@ const HOOKS = [
|
|
|
718
718
|
requiredContextSlice: ["section.reportEmpty"],
|
|
719
719
|
scopes: null,
|
|
720
720
|
},
|
|
721
|
+
{
|
|
722
|
+
name: "useScreenTitle",
|
|
723
|
+
signature: "useScreenTitle(title)",
|
|
724
|
+
description:
|
|
725
|
+
"Name the screen this widget is on, so the host paints that name in the " +
|
|
726
|
+
"app header beside the back control. The page's own name is the default; " +
|
|
727
|
+
"only the widget knows when the screen is really \"Order #1423\" rather " +
|
|
728
|
+
"than \"Orders\". The MOST RECENT call wins: with several widgets on one " +
|
|
729
|
+
"screen the last to report owns the title, and when that widget unmounts " +
|
|
730
|
+
"(or passes an empty title) the host falls back to the most recent " +
|
|
731
|
+
"surviving report and finally to the page name. Only a screen that shows " +
|
|
732
|
+
"the back control paints a title — a root page keeps the app brand, so a " +
|
|
733
|
+
"title reported there is held but not shown. Safe on a host that does not " +
|
|
734
|
+
"implement it (Studio canvas, Agent Mode edit preview) — a no-op there.",
|
|
735
|
+
returnShape: {
|
|
736
|
+
"(returns)": "void",
|
|
737
|
+
},
|
|
738
|
+
requiredContextSlice: ["screen.reportTitle"],
|
|
739
|
+
scopes: null,
|
|
740
|
+
},
|
|
721
741
|
{
|
|
722
742
|
name: "useNavigation",
|
|
723
743
|
signature: "useNavigation()",
|
|
@@ -2317,6 +2337,22 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
2317
2337
|
required: false,
|
|
2318
2338
|
fields: { subscribe: "function" },
|
|
2319
2339
|
},
|
|
2340
|
+
// sc-7955 — widget -> host screen-chrome signal. The widget owns the knowledge
|
|
2341
|
+
// (it has the record), the host owns the chrome (the header title slot).
|
|
2342
|
+
// Optional so an AUTHORING host can omit it: with no slice the hook is a
|
|
2343
|
+
// no-op on the Studio canvas and the Agent Mode edit preview, neither of
|
|
2344
|
+
// which paints an app header at all.
|
|
2345
|
+
screen: {
|
|
2346
|
+
description:
|
|
2347
|
+
"Optional screen-chrome slot. { reportTitle(title) -> release }. " +
|
|
2348
|
+
"Registers this widget's title for the screen it is on and returns a " +
|
|
2349
|
+
"release function that withdraws it; the host paints the most recently " +
|
|
2350
|
+
"registered title in the header beside the back control and falls back " +
|
|
2351
|
+
"to the page name once every registration is released. Backs " +
|
|
2352
|
+
"useScreenTitle().",
|
|
2353
|
+
required: false,
|
|
2354
|
+
fields: { reportTitle: "function" },
|
|
2355
|
+
},
|
|
2320
2356
|
// sc-4416 — widget -> host emptiness signal. The widget owns the knowledge
|
|
2321
2357
|
// (it has the rows); the host owns the spacing (the slot and its gap).
|
|
2322
2358
|
// Optional so an AUTHORING host can omit it on purpose: with no slice the
|
|
@@ -3979,6 +4015,14 @@ const CONTRACT = deepFreeze({
|
|
|
3979
4015
|
// and the sc-7352 backfill deletes the stored key (a bottom-tabs app's
|
|
3980
4016
|
// strip becomes the sidebar's quick bar) BEFORE this ships.
|
|
3981
4017
|
// `menuItemCap` / `quickBarCap` keep their signatures.
|
|
4018
|
+
// 1.111.0: additive (sc-7955) -- `screen` joins `widgetContextShape` and
|
|
4019
|
+
// `useScreenTitle(title)` joins `hooks`: a widget names the screen it is
|
|
4020
|
+
// on, and the host paints that name in the header beside the back control
|
|
4021
|
+
// instead of the app brand. `reportTitle` returns a release function; the
|
|
4022
|
+
// MOST RECENT registration wins and the host falls back to the most recent
|
|
4023
|
+
// surviving one, then to the page name. The slice is OPTIONAL, so an
|
|
4024
|
+
// authoring host (Studio canvas, Agent Mode edit preview) omits it and the
|
|
4025
|
+
// hook is a no-op there rather than an error.
|
|
3982
4026
|
// 1.110.0: additive (sc-7885) — `triggeredBy` joins `actionScriptGlobals`:
|
|
3983
4027
|
// WHO initiated this run, as `{ type, id, name, email, role }`, or `null`
|
|
3984
4028
|
// on `schedule` / `record_*` where nothing did. `type` is `"app_user"` (an
|
|
@@ -3988,7 +4032,7 @@ const CONTRACT = deepFreeze({
|
|
|
3988
4032
|
// integration identity; this describes the caller, it does not grant
|
|
3989
4033
|
// anything. The same commit adds `properties` to this list, which the
|
|
3990
4034
|
// action-sdk copy had carried since 1.50.0 while this one had not.
|
|
3991
|
-
version: "1.
|
|
4035
|
+
version: "1.111.0",
|
|
3992
4036
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3993
4037
|
hooks: HOOKS,
|
|
3994
4038
|
primitives: PRIMITIVES,
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
//
|
|
11
11
|
// `onPick` receives the same shape on both platforms:
|
|
12
12
|
// - web → the browser's `File` object (a `Blob` with name + type).
|
|
13
|
-
// - native → expo-file-system's `File
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
13
|
+
// - native → expo-file-system's `File`, carrying the same `uri` / `name` /
|
|
14
|
+
// `type` / `size` the old React Native `{ uri, name, type, size }` part
|
|
15
|
+
// did, so a widget reading those is unaffected. It must be a file on
|
|
16
|
+
// disk: the host uploads it by streaming it off disk (sc-7906), and
|
|
17
|
+
// Expo's fetch rejects the RN triple outright anyway ("Unsupported
|
|
18
18
|
// FormDataPart implementation"), which failed every native upload.
|
|
19
19
|
// `useFilestoreUpload` appends whichever verbatim into the multipart body.
|
|
20
20
|
|
|
@@ -49,10 +49,9 @@ function _mapAccept(accept) {
|
|
|
49
49
|
// keeping it as a fallback would only defer the failure.
|
|
50
50
|
function _asset(picked) {
|
|
51
51
|
const file = new FsFile(picked.uri);
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// the
|
|
55
|
-
// The picker's own values are the ones the user and the backend expect.
|
|
52
|
+
// The File derives both from the cache URI, which may be renamed,
|
|
53
|
+
// percent-encoded or extensionless. The upload sends the part's `name` as
|
|
54
|
+
// the stored name (sc-7906), so the picker's values are the ones that win.
|
|
56
55
|
_shadow(file, "name", picked.name || "upload");
|
|
57
56
|
_shadow(file, "type", picked.mimeType || "application/octet-stream");
|
|
58
57
|
return file;
|
package/dist/hooks.js
CHANGED
|
@@ -386,6 +386,36 @@ export function useSectionEmpty(isEmpty) {
|
|
|
386
386
|
}, [empty]);
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
+
/**
|
|
390
|
+
* sc-7955 — name the screen this widget is on, so the host paints that name in
|
|
391
|
+
* the header beside the back control. The page name is the default; only the
|
|
392
|
+
* widget knows when the screen is really "Order #1423" rather than "Orders".
|
|
393
|
+
*
|
|
394
|
+
* The MOST RECENT call wins: with several widgets on one screen the last to
|
|
395
|
+
* report owns the title, and when that widget unmounts (or passes an empty
|
|
396
|
+
* title) the host falls back to the most recent surviving report, then to the
|
|
397
|
+
* page name. Pass a blank or non-string title to bow out without unmounting
|
|
398
|
+
* (only a non-empty string registers, so a numeric id registers nothing).
|
|
399
|
+
*
|
|
400
|
+
* Keep it short — roughly 25 characters. The slot is one line and truncates
|
|
401
|
+
* with an ellipsis, sharing the row with back and the bell/identity cluster.
|
|
402
|
+
*
|
|
403
|
+
* Only a screen that shows the back control paints a title — a root page keeps
|
|
404
|
+
* the app brand, so a title reported there is held but not shown.
|
|
405
|
+
*
|
|
406
|
+
* Safe to call on a host that does not implement it: the hook is a no-op on the
|
|
407
|
+
* Studio canvas and the Agent Mode edit preview, which paint no app header.
|
|
408
|
+
*/
|
|
409
|
+
export function useScreenTitle(title) {
|
|
410
|
+
const ctx = useWidgetContextOrThrow("useScreenTitle");
|
|
411
|
+
const report = ctx.screen && ctx.screen.reportTitle;
|
|
412
|
+
const text = typeof title === "string" ? title.trim() : "";
|
|
413
|
+
useEffect(() => {
|
|
414
|
+
if (typeof report !== "function" || !text) return undefined;
|
|
415
|
+
return report(text);
|
|
416
|
+
}, [report, text]);
|
|
417
|
+
}
|
|
418
|
+
|
|
389
419
|
/**
|
|
390
420
|
* sc-4399 — measure the width the widget's own box actually has, so it can lay
|
|
391
421
|
* itself out for the space it is in rather than for the screen. A widget in a
|
|
@@ -3571,14 +3601,13 @@ export function useFilestoreFile(fileId) {
|
|
|
3571
3601
|
* same way the read hooks do (tenant for PROJECT, app user for PERSONAL)
|
|
3572
3602
|
* and posts a multipart FormData to `ctx.filestore.files.upload`.
|
|
3573
3603
|
*
|
|
3574
|
-
* `upload(file, { folderId?, fileName? })` takes a
|
|
3575
|
-
*
|
|
3576
|
-
*
|
|
3577
|
-
*
|
|
3578
|
-
*
|
|
3579
|
-
* "Unsupported FormDataPart implementation"
|
|
3580
|
-
*
|
|
3581
|
-
* the Blob's own `.name`.
|
|
3604
|
+
* `upload(file, { folderId?, fileName? })` takes a browser `File` on the web
|
|
3605
|
+
* Player and expo-file-system's `File` on the Expo export, as `<FilePicker>`,
|
|
3606
|
+
* `useCamera()` and `useImageEditor()` all hand back. Never React Native's
|
|
3607
|
+
* legacy `{ uri, name, type }` part: the native host streams the file off
|
|
3608
|
+
* disk (sc-7906), and Expo's fetch rejects that part outright anyway with
|
|
3609
|
+
* "Unsupported FormDataPart implementation". `fileName` overrides the stored
|
|
3610
|
+
* name, which otherwise comes from the part's own `.name`.
|
|
3582
3611
|
*
|
|
3583
3612
|
* The destination can refuse the add two ways (sc-6977). BRANCH ON
|
|
3584
3613
|
* `err.status`: 403 means the caller may know why — most often a public space
|
package/dist/index.d.ts
CHANGED
|
@@ -1473,6 +1473,8 @@ export function useRefresh(
|
|
|
1473
1473
|
* collapse. Safe on a host that does not implement it — a no-op there.
|
|
1474
1474
|
*/
|
|
1475
1475
|
export function useSectionEmpty(isEmpty: boolean): void;
|
|
1476
|
+
/** sc-7955 — name this screen for the header title slot; most recent call wins. */
|
|
1477
|
+
export function useScreenTitle(title: string | null | undefined): void;
|
|
1476
1478
|
|
|
1477
1479
|
/** The layout event a react-native primitive passes to `onLayout`. */
|
|
1478
1480
|
export interface WidgetLayoutEvent {
|
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.143.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
],
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "node scripts/build.js",
|
|
52
|
-
"test": "node --test src/__tests__/contract.test.js src/__tests__/theme-token-refs.test.js src/__tests__/vetted-imports-audit.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-invites.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-filestore-file.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-payments.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-section-empty.test.js src/__tests__/hooks-widget-event.test.js src/__tests__/hooks-widget-input.test.js src/__tests__/hooks-identification.test.js src/__tests__/hooks-subscription.test.js src/__tests__/hooks-volatile-query-key.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/linter-translation-api.test.js src/__tests__/linter-page-url.test.js src/__tests__/linter-image-height.test.js src/__tests__/linter-flex-basis-percent.test.js src/__tests__/linter-hardcoded-design.test.js src/__tests__/linter-editability.test.js src/__tests__/linter-measured-padding.test.js src/__tests__/linter-payment-error.test.js src/__tests__/linter-platform.test.js src/__tests__/linter-react-import.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/lucideIconName.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/hooks-translate.test.js src/__tests__/devserver.test.js src/__tests__/flatten-entry.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js src/__tests__/property-schema-resolve.test.js src/__tests__/corner-radius.test.js src/__tests__/theme-components-parity.test.js src/__tests__/navigation-parity.test.js src/__tests__/theme-depth-tokens.test.js src/__tests__/interaction-lift.test.js src/__tests__/toast-host.test.js src/__tests__/overlay-tokens.test.js src/__tests__/hooks-domain-error-mapping.test.js src/__tests__/linter-datastore-error.test.js src/__tests__/linter-write-gating.test.js src/__tests__/hooks-speech-to-text.test.js src/__tests__/hooks-camera.test.js src/__tests__/hooks-barcode.test.js src/__tests__/hooks-image-editor.test.js src/__tests__/hooks-bound-columns.test.js src/__tests__/hooks-stable-query.test.js src/__tests__/hooks-can-write.test.js src/__tests__/widget-route.test.js src/__tests__/linter-html-in-content.test.js src/__tests__/markdown.test.js src/__tests__/markdown-edit.test.js src/__tests__/richtext-tokens.test.js src/__tests__/style-group.test.js"
|
|
52
|
+
"test": "node --test src/__tests__/contract.test.js src/__tests__/theme-token-refs.test.js src/__tests__/vetted-imports-audit.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-invites.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-filestore-file.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-payments.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-section-empty.test.js src/__tests__/hooks-screen-title.test.js src/__tests__/hooks-widget-event.test.js src/__tests__/hooks-widget-input.test.js src/__tests__/hooks-identification.test.js src/__tests__/hooks-subscription.test.js src/__tests__/hooks-volatile-query-key.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/linter-translation-api.test.js src/__tests__/linter-page-url.test.js src/__tests__/linter-image-height.test.js src/__tests__/linter-flex-basis-percent.test.js src/__tests__/linter-hardcoded-design.test.js src/__tests__/linter-editability.test.js src/__tests__/linter-measured-padding.test.js src/__tests__/linter-payment-error.test.js src/__tests__/linter-platform.test.js src/__tests__/linter-react-import.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/lucideIconName.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/hooks-translate.test.js src/__tests__/devserver.test.js src/__tests__/flatten-entry.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js src/__tests__/property-schema-resolve.test.js src/__tests__/corner-radius.test.js src/__tests__/theme-components-parity.test.js src/__tests__/navigation-parity.test.js src/__tests__/theme-depth-tokens.test.js src/__tests__/interaction-lift.test.js src/__tests__/toast-host.test.js src/__tests__/overlay-tokens.test.js src/__tests__/hooks-domain-error-mapping.test.js src/__tests__/linter-datastore-error.test.js src/__tests__/linter-write-gating.test.js src/__tests__/hooks-speech-to-text.test.js src/__tests__/hooks-camera.test.js src/__tests__/hooks-barcode.test.js src/__tests__/hooks-image-editor.test.js src/__tests__/hooks-bound-columns.test.js src/__tests__/hooks-stable-query.test.js src/__tests__/hooks-can-write.test.js src/__tests__/widget-route.test.js src/__tests__/linter-html-in-content.test.js src/__tests__/markdown.test.js src/__tests__/markdown-edit.test.js src/__tests__/richtext-tokens.test.js src/__tests__/style-group.test.js"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=18"
|