@colixsystems/widget-sdk 0.56.0 → 0.58.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 +14 -5
- package/dist/contract.cjs +1 -1
- package/dist/contract.js +1 -1
- package/dist/hooks.js +8 -4
- package/dist/index.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,11 +52,19 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
52
52
|
|
|
53
53
|
## Status
|
|
54
54
|
|
|
55
|
-
`v0.
|
|
55
|
+
`v0.58.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**.
|
|
56
|
+
|
|
57
|
+
### What's new in 0.58.0
|
|
58
|
+
|
|
59
|
+
**Filter the directory by group (sc-2964).** `useDirectory(query?)` and `useUsers(query?)` gain an optional `group_id` on the query object (`{ q?, role?, is_active?, group_id?, limit?, offset? }`). Pass the `id` of a `useGroups()` row to list only that group's members — pair it with a group picker to build "members of group X". A `group_id` from another tenant or a non-existent one returns an empty roster, never a cross-tenant member. The `DirectoryQuery` / `UsersQuery` types add `group_id?: string`; existing callers pass no `group_id` and see the full roster. No scope, manifest field, import, or hook signature changed — `CONTRACT` is unchanged; the query flows verbatim through the injected `@colixsystems/directory-client` on both the web Player and the native Expo export.
|
|
60
|
+
|
|
61
|
+
### What's new in 0.57.0
|
|
62
|
+
|
|
63
|
+
**A `required: true` `tableRef` must ship a matching `datastoreTemplate` table (sc-2791).** A widget property that the author cannot skip — a `tableRef` you mark `required: true` — must have a table to bind on install, or the end user has nothing to pick and the widget can't load its data. The marketplace analyzer now enforces this at publish: the check `manifest.requiredTableRefsHaveTemplate` rejects a manifest whose `datastoreTemplate.tables` count is fewer than its `required` `tableRef` property count, naming the offending properties. Two ways to clear it: seed a `datastoreTemplate` table for each required `tableRef` (the default — the widget owns its data), OR make the property **optional** when it binds a table the app already owns (shared data the user names). This tightens the existing "always ship a `datastoreTemplate` for a data widget" guidance into an enforced rule for the `required` case. No export, type, or hook changed shape — additive publish-gate + documentation. `CONTRACT` is unchanged (no new field).
|
|
56
64
|
|
|
57
65
|
### What's new in 0.55.0
|
|
58
66
|
|
|
59
|
-
**Dynamic record selection for `valueRef` (sc-2327).** The `valueRef` binding gains an optional `mode` field: `"static"` (the default — pin a specific `recordId`, the only prior behaviour) or `"latest"` (resolve the most recently created row live, sorting on the host-managed `created_at` descending with `limit: 1`; `recordId` is ignored). The built-in
|
|
67
|
+
**Dynamic record selection for `valueRef` (sc-2327).** The `valueRef` binding gains an optional `mode` field: `"static"` (the default — pin a specific `recordId`, the only prior behaviour) or `"latest"` (resolve the most recently created row live, sorting on the host-managed `created_at` descending with `limit: 1`; `recordId` is ignored). The built-in Data Value widget reads it to offer a "Latest entry" that updates as records are added, with no per-host code — the same baked widget source and the same injected `@colixsystems/datastore-client` run on the web Player and the native Expo export. The `ValueRefBinding` type adds `mode?: "static" | "latest"`. Existing bindings carry no `mode` and read as static. `CONTRACT.version` → `1.39.0`. Additive — no existing field changed shape.
|
|
60
68
|
|
|
61
69
|
### What's new in 0.56.0
|
|
62
70
|
|
|
@@ -127,7 +135,7 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
127
135
|
|
|
128
136
|
### What's new in 0.42.0
|
|
129
137
|
|
|
130
|
-
**RELATION columns hydrate with a display label (sc-1181).** Record reads now return `{ id, label }` for ONE_TO_ONE / ONE_TO_MANY and `[{ id, label }, ...]` for MANY_TO_MANY (empty array when no links) — `label` is the value of the column pointed at by the new optional `display_column_id` on `DatastoreSchemaColumn`, or, when unset, the first STRING/TEXT column on the target table. Widgets should render `record.<rel>.label` (or `record.<rel>.map(r => r.label).join(", ")` for M:M) directly; `.id` is still there for the foreign-key case. The cell-formatting helpers in the built-in `DataList` and `
|
|
138
|
+
**RELATION columns hydrate with a display label (sc-1181).** Record reads now return `{ id, label }` for ONE_TO_ONE / ONE_TO_MANY and `[{ id, label }, ...]` for MANY_TO_MANY (empty array when no links) — `label` is the value of the column pointed at by the new optional `display_column_id` on `DatastoreSchemaColumn`, or, when unset, the first STRING/TEXT column on the target table. Widgets should render `record.<rel>.label` (or `record.<rel>.map(r => r.label).join(", ")` for M:M) directly; `.id` is still there for the foreign-key case. The cell-formatting helpers in the built-in `DataList` and `DataValue` widgets already walk arrays and prefer `label` over `name` / `id` — author widgets that need the same can copy that pattern. `CONTRACT.version` is unchanged.
|
|
131
139
|
|
|
132
140
|
### What's new in 0.41.0
|
|
133
141
|
|
|
@@ -254,10 +262,10 @@ Also: `useFileSignatures(fileIds)` is now **self-scoped** (the caller's own sign
|
|
|
254
262
|
|
|
255
263
|
**New `valueRef` propertySchema type — bind a widget to a single value in the datastore (REQ-WDG-VALUEREF).**
|
|
256
264
|
|
|
257
|
-
- **`valueRef`** is a composite picker: the Studio Properties Panel renders three cascading dropdowns — pick a **table**, then a **record**, then a **column** — and the bound widget resolves the one cell. It is the discoverable replacement for hand-typing a `tableRef` + a raw record-id `string` + a `columnRef` separately (the old
|
|
265
|
+
- **`valueRef`** is a composite picker: the Studio Properties Panel renders three cascading dropdowns — pick a **table**, then a **record**, then a **column** — and the bound widget resolves the one cell. It is the discoverable replacement for hand-typing a `tableRef` + a raw record-id `string` + a `columnRef` separately (the old Data Value shape).
|
|
258
266
|
- **Persisted value is an object** `{ tableId, recordId, column }` (new `ValueRefBinding` type), unlike every other ref type, which is a bare string. A widget reads it with `useDatastoreRecord(value.tableId, value.recordId)` then `record[value.column]`; any missing piece means "no value".
|
|
259
267
|
- **tenant-copy** remaps `tableId` to the copied table and **nulls `recordId`** (records are business data and are never copied), so a copied workspace shows the widget's fallback until the new operator re-picks a record. `column` (a name) is preserved verbatim.
|
|
260
|
-
- The built-in **
|
|
268
|
+
- The built-in **Data Value** widget now uses `valueRef` (back-compatible: already-saved Data Value widgets that stored `tableId`/`recordId`/`column` as separate props keep rendering).
|
|
261
269
|
- **`CONTRACT.version` → `1.12.0`** (additive: one new optional propertySchema type). No existing export or type changed signature.
|
|
262
270
|
|
|
263
271
|
### What's new in 0.21.1
|
|
@@ -450,6 +458,7 @@ A widget that works but looks unfinished is only half done. `useTheme()` is the
|
|
|
450
458
|
|
|
451
459
|
- **Pull spacing and corners from tokens.** Use `theme.spacing` (`xs / sm / md / lg / xl`) for a consistent padding and gap rhythm, and `theme.radii` (`sm / md / lg / pill`) for corners. Don't hardcode raw pixel values.
|
|
452
460
|
- **Build a hierarchy.** A clear title (large, bold, `colors.onSurface`), body text, and muted captions in `colors.onSurfaceMuted` — three weights, not one flat size. Reserve `colors.primary` (with `colors.onPrimary` for text on it) for the single most important action or metric.
|
|
461
|
+
- **Set the theme font on every `Text`.** React Native `Text` does not inherit `fontFamily` from a parent, so a text element that omits it falls back to the system font and ignores the workspace's configured font. Put `theme.typography.fontFamily` on every text style (a shared `StyleSheet` built from `theme` keeps it in one place) and size text with `theme.typography.sizes`.
|
|
453
462
|
- **Contain and elevate.** Wrap a logical unit in a surface: `colors.surface` + padding + `radii.md` + a `colors.border` hairline or a subtle shadow. Use the status roles (`danger / success / warning / info`) for state.
|
|
454
463
|
- **Respond to touch.** Give every `Pressable` a pressed state via the function-style `style={({ pressed }) => [base, pressed && { opacity: 0.7 }]}`.
|
|
455
464
|
- **Use icons for clarity.** Pair a `lucide-react-native` icon with its label at a consistent size, coloured from the theme.
|
package/dist/contract.cjs
CHANGED
|
@@ -1862,7 +1862,7 @@ const CONTRACT = deepFreeze({
|
|
|
1862
1862
|
// an optional `mode` field: "static" (a pinned recordId, the default and
|
|
1863
1863
|
// the only prior behaviour) or "latest" (the most recently created row,
|
|
1864
1864
|
// resolved live by `created_at` desc with limit 1; recordId ignored). The
|
|
1865
|
-
//
|
|
1865
|
+
// Data Value widget reads it to show a live "latest entry". Existing
|
|
1866
1866
|
// bindings have no `mode` and read as static — additive, minor bump.
|
|
1867
1867
|
version: "1.39.0",
|
|
1868
1868
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
package/dist/contract.js
CHANGED
|
@@ -1862,7 +1862,7 @@ const CONTRACT = deepFreeze({
|
|
|
1862
1862
|
// an optional `mode` field: "static" (a pinned recordId, the default and
|
|
1863
1863
|
// the only prior behaviour) or "latest" (the most recently created row,
|
|
1864
1864
|
// resolved live by `created_at` desc with limit 1; recordId ignored). The
|
|
1865
|
-
//
|
|
1865
|
+
// Data Value widget reads it to show a live "latest entry". Existing
|
|
1866
1866
|
// bindings have no `mode` and read as static — additive, minor bump.
|
|
1867
1867
|
version: "1.39.0",
|
|
1868
1868
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
package/dist/hooks.js
CHANGED
|
@@ -2221,8 +2221,10 @@ function toDirectoryError(err) {
|
|
|
2221
2221
|
* users is NOT part of this surface; the directory is read-only here (see
|
|
2222
2222
|
* useUsers for administration).
|
|
2223
2223
|
*
|
|
2224
|
-
* `query` is an optional `{ q?, role?, is_active?, limit?, offset? }`
|
|
2225
|
-
* object passed through verbatim.
|
|
2224
|
+
* `query` is an optional `{ q?, role?, is_active?, group_id?, limit?, offset? }`
|
|
2225
|
+
* object passed through verbatim. `group_id` (the `id` of a `useGroups()` row)
|
|
2226
|
+
* restricts the roster to that group's members — pair it with a group picker to
|
|
2227
|
+
* build "members of group X". The hook re-fetches whenever
|
|
2226
2228
|
* `JSON.stringify(query)` changes and exposes `refetch` for on-demand
|
|
2227
2229
|
* reloads (e.g. a chat roster refresh).
|
|
2228
2230
|
*
|
|
@@ -2300,8 +2302,10 @@ export function useDirectory(query) {
|
|
|
2300
2302
|
* invite, deactivate, reactivate}` — `list` resolves to the `{ data, meta }`
|
|
2301
2303
|
* envelope VERBATIM, so we unwrap `res.data` (default `[]`). User rows are
|
|
2302
2304
|
* snake_case (`id`, `name`, `email`, `role`, `is_active`, …) and bodies
|
|
2303
|
-
* (e.g. `{ email, name, group_ids? }`) pass through verbatim.
|
|
2304
|
-
*
|
|
2305
|
+
* (e.g. `{ email, name, group_ids? }`) pass through verbatim. `query` is an
|
|
2306
|
+
* optional `{ q?, role?, is_active?, group_id?, limit?, offset? }`; `group_id`
|
|
2307
|
+
* (the `id` of a `useGroups()` row) narrows the list to that group's members.
|
|
2308
|
+
* The list refetches whenever `JSON.stringify(query)` changes; the imperative methods
|
|
2305
2309
|
* reject with a `DirectoryError`. Reads require the `users.read:*` scope;
|
|
2306
2310
|
* mutations additionally require `users.write:*`. The host's signed
|
|
2307
2311
|
* `X-Widget-Scopes` header + a tenant-scoped SystemAcl `users.read` /
|
package/dist/index.d.ts
CHANGED
|
@@ -585,6 +585,11 @@ export interface DirectoryQuery {
|
|
|
585
585
|
role?: "USER" | "INTEGRATION" | "ALL";
|
|
586
586
|
/** Filter by active state (snake_case on the wire). */
|
|
587
587
|
is_active?: boolean;
|
|
588
|
+
/**
|
|
589
|
+
* Restrict the roster to members of one app-user group — the `id` of a
|
|
590
|
+
* `useGroups()` row. Pair with a group picker to build "members of group X".
|
|
591
|
+
*/
|
|
592
|
+
group_id?: string;
|
|
588
593
|
limit?: number;
|
|
589
594
|
offset?: number;
|
|
590
595
|
}
|
|
@@ -1082,6 +1087,8 @@ export interface UsersQuery {
|
|
|
1082
1087
|
q?: string;
|
|
1083
1088
|
role?: "USER" | "INTEGRATION" | "ALL";
|
|
1084
1089
|
is_active?: boolean;
|
|
1090
|
+
/** Restrict to members of one app-user group — the `id` of a `useGroups()` row. */
|
|
1091
|
+
group_id?: string;
|
|
1085
1092
|
limit?: number;
|
|
1086
1093
|
offset?: number;
|
|
1087
1094
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.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",
|