@colixsystems/widget-sdk 0.106.0 → 0.108.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 +39 -3
- package/dist/contract.cjs +37 -5
- package/dist/contract.js +37 -5
- package/dist/dev-shims.js +7 -3
- package/package.json +2 -2
- package/src/dev-shims.js +7 -3
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ The data layer lives in **four separate domain-client packages**, each instantia
|
|
|
17
17
|
|
|
18
18
|
| Group | Hook (signature) | Returns | Reads / scope |
|
|
19
19
|
| ----- | ---------------- | ------- | ------------- |
|
|
20
|
-
| **CORE** | `useTheme()` | `{ colors, elevation, spacing, spacingScale, radii, typography, components, widgetStyles }` | `ctx.workspace.theme` — no scope. `elevation` is the shared depth scale (`none / sm / md / lg / xl`) you spread into a style; `colors` includes the accent's quiet tiers (`primarySoft` / `onPrimarySoft` / `primaryStrong`). `components` is HOST-OWNED (the theme's per-component style tokens); the host has already folded it into your `props.style`, so read `useWidgetStyle()` and ignore this slice. |
|
|
20
|
+
| **CORE** | `useTheme()` | `{ colors, elevation, spacing, spacingScale, radii, typography, components, widgetStyles }` | `ctx.workspace.theme` — no scope. `elevation` is the shared depth scale (`none / sm / md / lg / xl`) you spread into a style; `colors` includes the accent's quiet tiers (`primarySoft` / `onPrimarySoft` / `primaryStrong`) and `loader`, the spinner colour for your own loading state. `components` is HOST-OWNED (the theme's per-component style tokens); the host has already folded it into your `props.style`, so read `useWidgetStyle()` and ignore this slice. |
|
|
21
21
|
| **CORE** | `useWorkspaceCurrency()` | `{ currency, formatMoney }` | `ctx.workspace.currency` — no scope. The currency this workspace charges its app users in, resolved at RENDER time. Render every price as `formatMoney(minorUnits)` and never write a currency symbol or code into a widget: the owner can change it after the widget ships, and a baked label then contradicts the charge. |
|
|
22
22
|
| **CORE** | `useWidgetStyle()` | `{ [styleField]: value }` | `ctx.props.style` — no scope. The author-set per-widget style values declared in `manifest.styleSchema`; apply each onto whatever element you choose. |
|
|
23
23
|
| **CORE** | `useUser()` | `{ id, email, displayName, roles, groupIds }` | `ctx.user` (host-built context, **camelCase** — not a wire payload; `id` null when anonymous) — no scope |
|
|
@@ -68,7 +68,43 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
68
68
|
|
|
69
69
|
## Status
|
|
70
70
|
|
|
71
|
-
`v0.
|
|
71
|
+
`v0.108.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**.
|
|
72
|
+
|
|
73
|
+
### What's new in 0.108.0 (contract 1.82.0)
|
|
74
|
+
|
|
75
|
+
**`themeTokens.colors` gains `loader` — the surface's spinner colour (sc-6095).** A widget that drew its own loading state had no token for it, so it reached for a literal grey. On a dark theme that grey vanished into the background and the widget looked frozen rather than busy — the same bug the host's own loading holds had.
|
|
76
|
+
|
|
77
|
+
`loader` tracks `onSurfaceMuted`, which means it rides the existing REQ-THEME-SURFACE derivation: it flips light on a dark page background, and it re-derives for a container that paints its own dark fill, exactly like the text colours around it. So reading it is enough — there is nothing to branch on:
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
const t = useTheme();
|
|
81
|
+
if (loading) return <ActivityIndicator color={t.colors.loader} />;
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The workspace's *Design → Loading Indicator* panel can override it app-wide; unset, it stays derived. Additive — the full `colors` shape is now `{ primary, onPrimary, primarySoft, onPrimarySoft, primaryStrong, secondary, onSecondary, surface, onSurface, surfaceMuted, onSurfaceMuted, border, loader, danger, success, warning, info }`.
|
|
85
|
+
|
|
86
|
+
### What's new in 0.107.0 (contract 1.81.0)
|
|
87
|
+
|
|
88
|
+
**Widgets can render QR codes — `react-native-qrcode-svg` is now a vetted import (sc-6105).** There was no QR encoder on the allowlist, so a check-in code, an install link, a table-ordering code, or a payment hand-off could not be built at all. The only QR the platform produced was a PNG the backend renders for one specific BankID sign order, which encodes nothing else.
|
|
89
|
+
|
|
90
|
+
The package is vetted for **both platforms** and needs no split file: it draws with the already-vetted `react-native-svg`, so one component covers the web Player and the Expo export.
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import QRCode from "react-native-qrcode-svg";
|
|
94
|
+
import { View } from "@colixsystems/widget-sdk";
|
|
95
|
+
|
|
96
|
+
export default function TicketCode({ ticketUrl }) {
|
|
97
|
+
return (
|
|
98
|
+
<View>
|
|
99
|
+
<QRCode value={ticketUrl} size={180} ecl="M" />
|
|
100
|
+
</View>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`value` is the encoded string; `size`, `color`, `backgroundColor`, `quietZone`, `ecl` (`"L" | "M" | "Q" | "H"`) and the `logo*` props shape the render. Encoding happens on-device — no network call, so it works offline in both hosts.
|
|
106
|
+
|
|
107
|
+
One caveat carried over from the package: it documents a Metro transformer that injects a `TextEncoder` polyfill for React Native **below 0.75**. The export ships RN 0.85.3, which has `TextEncoder` as a global, so that transformer is intentionally not wired up — don't add it.
|
|
72
108
|
|
|
73
109
|
### What's new in 0.106.0 (contract 1.80.0)
|
|
74
110
|
|
|
@@ -365,7 +401,7 @@ Additive — one new hook, one new optional device capability, one new error cla
|
|
|
365
401
|
|
|
366
402
|
- **The workspace theme now reaches the elements an app is built from.** Three things that used to be unreachable are now themeable: an element inside YOUR widget, the structural card container a page is made of, and any style field whose name the platform does not know. For a widget author the practical change is that **your `styleSchema` is the contract**: every field you declare becomes a knob the workspace owner can set once for the whole app, so declare the fields that describe your widget's appearance and give them clear `label`s and `ui.group`s — those labels are what the owner reads.
|
|
367
403
|
- **A field name you invented is as reachable as a canonical one.** A theme may carry values keyed by your widget's manifest id and then by your own field names, so `panelFill` is adjustable app-wide exactly like `cardBackground`. Separately, the unambiguous card names (`cardBackground`, `cardBorderColor`, `cardRadius`, `cardPadding`, `cardGradient`) bind by NAME to any widget that declares them, so naming a genuine card surface canonically opts it into the workspace's Cards controls for free.
|
|
368
|
-
- **`useTheme().colors` describes the surface your widget SITS ON, not the page.** A layout container that paints its own background re-derives the surface roles for everything inside it, so reading `colors.onSurface` for your text is readable whether your widget lands on the page, in a dark hero, or in a light card nested inside that hero. Nothing to opt into.
|
|
404
|
+
- **`useTheme().colors` describes the surface your widget SITS ON, not the page.** A layout container that paints its own background re-derives the surface roles for everything inside it, so reading `colors.onSurface` for your text is readable whether your widget lands on the page, in a dark hero, or in a light card nested inside that hero. `colors.loader` is that same surface's spinner colour — paint your loading state with it rather than a literal grey. Nothing to opt into.
|
|
369
405
|
- **Precedence, unchanged in spirit.** Contract default → workspace palette → component scope → per-widget-type value → the app author's per-instance `props.style`. Most specific wins, and the Properties Panel is still the final word. Your widget reads `props.style` exactly as before and never learns which layer supplied a value.
|
|
370
406
|
- **A colour may carry OPACITY.** `isHexColor` accepts the 8-digit `#RRGGBBAA` form alongside 3 and 6 digits, so a theme colour with an alpha reaches `useTheme()` with its transparency intact. It used to be rejected and the host dropped the key outright, which is why a translucent page background never reached the dark-surface derivation and every panel fell back to white.
|
|
371
407
|
- **The colour maths ignores alpha, on purpose.** `hexChannels` reads the R/G/B pair and skips any alpha, so contrast, readable text and the derived accent tints reason about the opaque colour. None of them can composite without knowing the backdrop, which a token table does not have — so transparency lives in the VALUE your widget renders, not in the decision about whether that colour reads as light or dark.
|
package/dist/contract.cjs
CHANGED
|
@@ -64,6 +64,11 @@ const DEFAULT_THEME_TOKENS = Object.freeze({
|
|
|
64
64
|
onSurface: "#111827",
|
|
65
65
|
surfaceMuted: "#f8fafc",
|
|
66
66
|
onSurfaceMuted: "#475569",
|
|
67
|
+
// sc-6095: the colour a loading spinner is painted with. A spinner is a
|
|
68
|
+
// muted foreground mark on the surface it sits on, so it tracks
|
|
69
|
+
// `onSurfaceMuted`, which deriveSurfaceTokens already flips for a dark
|
|
70
|
+
// background — so a dark theme gets a visible spinner with no new maths.
|
|
71
|
+
loader: "#475569",
|
|
67
72
|
border: "#e2e8f0",
|
|
68
73
|
danger: "#dc2626",
|
|
69
74
|
success: "#059669",
|
|
@@ -457,12 +462,13 @@ const HOOKS = [
|
|
|
457
462
|
signature: "useTheme()",
|
|
458
463
|
returnShape: {
|
|
459
464
|
colors:
|
|
460
|
-
"{ primary, onPrimary, secondary, onSecondary, surface, onSurface, surfaceMuted, onSurfaceMuted, border, danger, success, warning, info } — " +
|
|
465
|
+
"{ primary, onPrimary, secondary, onSecondary, surface, onSurface, surfaceMuted, onSurfaceMuted, border, loader, danger, success, warning, info } — " +
|
|
461
466
|
"REQ-THEME-SURFACE: the surface group (surface / surfaceMuted / onSurface / " +
|
|
462
|
-
"onSurfaceMuted / border) describes the surface your widget SITS ON, not the " +
|
|
467
|
+
"onSurfaceMuted / border / loader) describes the surface your widget SITS ON, not the " +
|
|
463
468
|
"page: a container painting its own background re-derives them for its " +
|
|
464
469
|
"subtree. Read them and your text is readable wherever the widget lands; " +
|
|
465
|
-
"there is nothing to opt into."
|
|
470
|
+
"there is nothing to opt into. `loader` is that surface's spinner colour " +
|
|
471
|
+
"(sc-6095) — paint your own loading state with it rather than a literal grey.",
|
|
466
472
|
spacing: "{ xs, sm, md, lg, xl }",
|
|
467
473
|
spacingScale:
|
|
468
474
|
"number — the app-wide spacing multiplier (REQ-THEME-LOOK, default 1). " +
|
|
@@ -2457,6 +2463,13 @@ const VETTED_IMPORTS = [
|
|
|
2457
2463
|
description:
|
|
2458
2464
|
"Embeds web content in a native WebView. Native-only; on web render an <iframe> (or a View with the URL) in widget.web.jsx.",
|
|
2459
2465
|
},
|
|
2466
|
+
{
|
|
2467
|
+
specifier: "react-native-qrcode-svg",
|
|
2468
|
+
platforms: ["web", "native"],
|
|
2469
|
+
category: "drawing",
|
|
2470
|
+
description:
|
|
2471
|
+
"Renders a QR code, drawn as SVG through the vetted react-native-svg — so one `<QRCode value={…} size={…} />` covers both platforms with no split file. Pure JS with no native module of its own: the web host resolves it and the Expo export pins it, exactly like date-fns. Its `text-encoding` polyfill is opt-in for React Native < 0.75 only; the export ships RN 0.85.3, which has a global TextEncoder, so the Metro transformer that package documents is deliberately not wired up.",
|
|
2472
|
+
},
|
|
2460
2473
|
];
|
|
2461
2474
|
|
|
2462
2475
|
// sc-1064: CORE React infrastructure specifiers the host RESOLVES at runtime
|
|
@@ -3311,7 +3324,24 @@ const CONTRACT = deepFreeze({
|
|
|
3311
3324
|
// blocked every first-party publish for twelve days. The flag separates
|
|
3312
3325
|
// who PROVIDES the table from whether the author may skip it; `required`
|
|
3313
3326
|
// still means required.
|
|
3314
|
-
|
|
3327
|
+
// 1.81.0: additive (sc-6105) — `react-native-qrcode-svg` joins
|
|
3328
|
+
// VETTED_IMPORTS as a web+native `drawing` package. Widgets had no QR
|
|
3329
|
+
// encoder at all: the only QR the platform produced was the BankID PNG
|
|
3330
|
+
// the backend renders for a specific sign order, so a check-in code, an
|
|
3331
|
+
// install link, or a table-ordering code was unbuildable. It draws
|
|
3332
|
+
// through the already-vetted react-native-svg and carries no native
|
|
3333
|
+
// module of its own, so it is host-shimmed on web and pinned in the
|
|
3334
|
+
// export like date-fns. No existing entry changed shape.
|
|
3335
|
+
//
|
|
3336
|
+
// 1.82.0: additive (sc-6095) — `themeTokens.colors` gains `loader`, the
|
|
3337
|
+
// colour a loading spinner is painted with, and `deriveSurfaceTokens`
|
|
3338
|
+
// returns it alongside the surface/text/border set. A spinner is a muted
|
|
3339
|
+
// foreground mark on the surface it sits on, so it tracks `onSurfaceMuted`
|
|
3340
|
+
// and inherits that set's dark-background flip — which is what makes a
|
|
3341
|
+
// dark theme's spinner visible instead of grey-on-grey.
|
|
3342
|
+
// `useTheme().colors.loader` is the value a widget reads for its own
|
|
3343
|
+
// loading state; both hosts paint their chrome spinners from the same key.
|
|
3344
|
+
version: "1.82.0",
|
|
3315
3345
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3316
3346
|
hooks: HOOKS,
|
|
3317
3347
|
primitives: PRIMITIVES,
|
|
@@ -3496,7 +3526,7 @@ const DARK_SURFACE_TEXT = Object.freeze({
|
|
|
3496
3526
|
* page, which is in turn what lets a built app follow its theme instead of
|
|
3497
3527
|
* carrying a baked-in hex for every heading.
|
|
3498
3528
|
*
|
|
3499
|
-
* Returns all
|
|
3529
|
+
* Returns all six keys together, never a subset: layering a dark card's text
|
|
3500
3530
|
* colour over a light ancestor's surface is exactly how light-on-light happens.
|
|
3501
3531
|
* `null` only when the colour is unusable, letting the caller keep what it had.
|
|
3502
3532
|
*/
|
|
@@ -3513,6 +3543,7 @@ function deriveSurfaceTokens(backgroundColor) {
|
|
|
3513
3543
|
surfaceMuted: base.surfaceMuted,
|
|
3514
3544
|
onSurface: base.onSurface,
|
|
3515
3545
|
onSurfaceMuted: base.onSurfaceMuted,
|
|
3546
|
+
loader: base.loader,
|
|
3516
3547
|
border: base.border,
|
|
3517
3548
|
};
|
|
3518
3549
|
}
|
|
@@ -3521,6 +3552,7 @@ function deriveSurfaceTokens(backgroundColor) {
|
|
|
3521
3552
|
surfaceMuted: mixHex(backgroundColor, "#ffffff", SURFACE_LIFT.surfaceMuted),
|
|
3522
3553
|
onSurface: DARK_SURFACE_TEXT.onSurface,
|
|
3523
3554
|
onSurfaceMuted: DARK_SURFACE_TEXT.onSurfaceMuted,
|
|
3555
|
+
loader: DARK_SURFACE_TEXT.onSurfaceMuted,
|
|
3524
3556
|
border: mixHex(backgroundColor, "#ffffff", SURFACE_LIFT.border),
|
|
3525
3557
|
};
|
|
3526
3558
|
}
|
package/dist/contract.js
CHANGED
|
@@ -64,6 +64,11 @@ const DEFAULT_THEME_TOKENS = Object.freeze({
|
|
|
64
64
|
onSurface: "#111827",
|
|
65
65
|
surfaceMuted: "#f8fafc",
|
|
66
66
|
onSurfaceMuted: "#475569",
|
|
67
|
+
// sc-6095: the colour a loading spinner is painted with. A spinner is a
|
|
68
|
+
// muted foreground mark on the surface it sits on, so it tracks
|
|
69
|
+
// `onSurfaceMuted`, which deriveSurfaceTokens already flips for a dark
|
|
70
|
+
// background — so a dark theme gets a visible spinner with no new maths.
|
|
71
|
+
loader: "#475569",
|
|
67
72
|
border: "#e2e8f0",
|
|
68
73
|
danger: "#dc2626",
|
|
69
74
|
success: "#059669",
|
|
@@ -457,12 +462,13 @@ const HOOKS = [
|
|
|
457
462
|
signature: "useTheme()",
|
|
458
463
|
returnShape: {
|
|
459
464
|
colors:
|
|
460
|
-
"{ primary, onPrimary, secondary, onSecondary, surface, onSurface, surfaceMuted, onSurfaceMuted, border, danger, success, warning, info } — " +
|
|
465
|
+
"{ primary, onPrimary, secondary, onSecondary, surface, onSurface, surfaceMuted, onSurfaceMuted, border, loader, danger, success, warning, info } — " +
|
|
461
466
|
"REQ-THEME-SURFACE: the surface group (surface / surfaceMuted / onSurface / " +
|
|
462
|
-
"onSurfaceMuted / border) describes the surface your widget SITS ON, not the " +
|
|
467
|
+
"onSurfaceMuted / border / loader) describes the surface your widget SITS ON, not the " +
|
|
463
468
|
"page: a container painting its own background re-derives them for its " +
|
|
464
469
|
"subtree. Read them and your text is readable wherever the widget lands; " +
|
|
465
|
-
"there is nothing to opt into."
|
|
470
|
+
"there is nothing to opt into. `loader` is that surface's spinner colour " +
|
|
471
|
+
"(sc-6095) — paint your own loading state with it rather than a literal grey.",
|
|
466
472
|
spacing: "{ xs, sm, md, lg, xl }",
|
|
467
473
|
spacingScale:
|
|
468
474
|
"number — the app-wide spacing multiplier (REQ-THEME-LOOK, default 1). " +
|
|
@@ -2457,6 +2463,13 @@ const VETTED_IMPORTS = [
|
|
|
2457
2463
|
description:
|
|
2458
2464
|
"Embeds web content in a native WebView. Native-only; on web render an <iframe> (or a View with the URL) in widget.web.jsx.",
|
|
2459
2465
|
},
|
|
2466
|
+
{
|
|
2467
|
+
specifier: "react-native-qrcode-svg",
|
|
2468
|
+
platforms: ["web", "native"],
|
|
2469
|
+
category: "drawing",
|
|
2470
|
+
description:
|
|
2471
|
+
"Renders a QR code, drawn as SVG through the vetted react-native-svg — so one `<QRCode value={…} size={…} />` covers both platforms with no split file. Pure JS with no native module of its own: the web host resolves it and the Expo export pins it, exactly like date-fns. Its `text-encoding` polyfill is opt-in for React Native < 0.75 only; the export ships RN 0.85.3, which has a global TextEncoder, so the Metro transformer that package documents is deliberately not wired up.",
|
|
2472
|
+
},
|
|
2460
2473
|
];
|
|
2461
2474
|
|
|
2462
2475
|
// sc-1064: CORE React infrastructure specifiers the host RESOLVES at runtime
|
|
@@ -3311,7 +3324,24 @@ const CONTRACT = deepFreeze({
|
|
|
3311
3324
|
// blocked every first-party publish for twelve days. The flag separates
|
|
3312
3325
|
// who PROVIDES the table from whether the author may skip it; `required`
|
|
3313
3326
|
// still means required.
|
|
3314
|
-
|
|
3327
|
+
// 1.81.0: additive (sc-6105) — `react-native-qrcode-svg` joins
|
|
3328
|
+
// VETTED_IMPORTS as a web+native `drawing` package. Widgets had no QR
|
|
3329
|
+
// encoder at all: the only QR the platform produced was the BankID PNG
|
|
3330
|
+
// the backend renders for a specific sign order, so a check-in code, an
|
|
3331
|
+
// install link, or a table-ordering code was unbuildable. It draws
|
|
3332
|
+
// through the already-vetted react-native-svg and carries no native
|
|
3333
|
+
// module of its own, so it is host-shimmed on web and pinned in the
|
|
3334
|
+
// export like date-fns. No existing entry changed shape.
|
|
3335
|
+
//
|
|
3336
|
+
// 1.82.0: additive (sc-6095) — `themeTokens.colors` gains `loader`, the
|
|
3337
|
+
// colour a loading spinner is painted with, and `deriveSurfaceTokens`
|
|
3338
|
+
// returns it alongside the surface/text/border set. A spinner is a muted
|
|
3339
|
+
// foreground mark on the surface it sits on, so it tracks `onSurfaceMuted`
|
|
3340
|
+
// and inherits that set's dark-background flip — which is what makes a
|
|
3341
|
+
// dark theme's spinner visible instead of grey-on-grey.
|
|
3342
|
+
// `useTheme().colors.loader` is the value a widget reads for its own
|
|
3343
|
+
// loading state; both hosts paint their chrome spinners from the same key.
|
|
3344
|
+
version: "1.82.0",
|
|
3315
3345
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3316
3346
|
hooks: HOOKS,
|
|
3317
3347
|
primitives: PRIMITIVES,
|
|
@@ -3496,7 +3526,7 @@ const DARK_SURFACE_TEXT = Object.freeze({
|
|
|
3496
3526
|
* page, which is in turn what lets a built app follow its theme instead of
|
|
3497
3527
|
* carrying a baked-in hex for every heading.
|
|
3498
3528
|
*
|
|
3499
|
-
* Returns all
|
|
3529
|
+
* Returns all six keys together, never a subset: layering a dark card's text
|
|
3500
3530
|
* colour over a light ancestor's surface is exactly how light-on-light happens.
|
|
3501
3531
|
* `null` only when the colour is unusable, letting the caller keep what it had.
|
|
3502
3532
|
*/
|
|
@@ -3513,6 +3543,7 @@ function deriveSurfaceTokens(backgroundColor) {
|
|
|
3513
3543
|
surfaceMuted: base.surfaceMuted,
|
|
3514
3544
|
onSurface: base.onSurface,
|
|
3515
3545
|
onSurfaceMuted: base.onSurfaceMuted,
|
|
3546
|
+
loader: base.loader,
|
|
3516
3547
|
border: base.border,
|
|
3517
3548
|
};
|
|
3518
3549
|
}
|
|
@@ -3521,6 +3552,7 @@ function deriveSurfaceTokens(backgroundColor) {
|
|
|
3521
3552
|
surfaceMuted: mixHex(backgroundColor, "#ffffff", SURFACE_LIFT.surfaceMuted),
|
|
3522
3553
|
onSurface: DARK_SURFACE_TEXT.onSurface,
|
|
3523
3554
|
onSurfaceMuted: DARK_SURFACE_TEXT.onSurfaceMuted,
|
|
3555
|
+
loader: DARK_SURFACE_TEXT.onSurfaceMuted,
|
|
3524
3556
|
border: mixHex(backgroundColor, "#ffffff", SURFACE_LIFT.border),
|
|
3525
3557
|
};
|
|
3526
3558
|
}
|
package/dist/dev-shims.js
CHANGED
|
@@ -94,9 +94,12 @@ export const REACT_JSX_RUNTIME_EXPORTS = ["jsx", "jsxs", "Fragment", "jsxDEV"];
|
|
|
94
94
|
// host namespace (sc-1064).
|
|
95
95
|
// * `@colixsystems/widget-sdk` — the widget must route hooks through the SAME
|
|
96
96
|
// SDK instance the host built (datastore/theme/navigation live there).
|
|
97
|
-
// * `lucide-react-native`, `react-native-svg`, `date-fns
|
|
98
|
-
// the host already bundles +
|
|
99
|
-
// host copy keeps icons/SVG on
|
|
97
|
+
// * `lucide-react-native`, `react-native-svg`, `date-fns`,
|
|
98
|
+
// `react-native-qrcode-svg` — vetted packages the host already bundles +
|
|
99
|
+
// shims (`_hostVettedModules`); sharing the host copy keeps icons/SVG on
|
|
100
|
+
// the host's react-native-web instance. qrcode-svg draws through
|
|
101
|
+
// react-native-svg, so externalising it keeps the QR on that same
|
|
102
|
+
// instance instead of a bundle inlining a second one (sc-6105).
|
|
100
103
|
const HOST_EXTERNAL_SPECIFIERS = [
|
|
101
104
|
"react",
|
|
102
105
|
"react/jsx-runtime",
|
|
@@ -107,6 +110,7 @@ const HOST_EXTERNAL_SPECIFIERS = [
|
|
|
107
110
|
"lucide-react-native",
|
|
108
111
|
"react-native-svg",
|
|
109
112
|
"date-fns",
|
|
113
|
+
"react-native-qrcode-svg",
|
|
110
114
|
// sc-1265: a bundled widget (and any vetted RN package it inlines, e.g.
|
|
111
115
|
// react-native-gesture-handler) imports `react-native`; the host resolves it
|
|
112
116
|
// to its OWN single react-native-web instance through a blob shim, so the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.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",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
],
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "node scripts/build.js",
|
|
51
|
-
"test": "node --test src/__tests__/contract.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-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__/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__/toast-host.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-bound-columns.test.js src/__tests__/hooks-stable-query.test.js src/__tests__/hooks-can-write.test.js src/__tests__/widget-route.test.js"
|
|
51
|
+
"test": "node --test src/__tests__/contract.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-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__/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__/toast-host.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-bound-columns.test.js src/__tests__/hooks-stable-query.test.js src/__tests__/hooks-can-write.test.js src/__tests__/widget-route.test.js"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=18"
|
package/src/dev-shims.js
CHANGED
|
@@ -94,9 +94,12 @@ export const REACT_JSX_RUNTIME_EXPORTS = ["jsx", "jsxs", "Fragment", "jsxDEV"];
|
|
|
94
94
|
// host namespace (sc-1064).
|
|
95
95
|
// * `@colixsystems/widget-sdk` — the widget must route hooks through the SAME
|
|
96
96
|
// SDK instance the host built (datastore/theme/navigation live there).
|
|
97
|
-
// * `lucide-react-native`, `react-native-svg`, `date-fns
|
|
98
|
-
// the host already bundles +
|
|
99
|
-
// host copy keeps icons/SVG on
|
|
97
|
+
// * `lucide-react-native`, `react-native-svg`, `date-fns`,
|
|
98
|
+
// `react-native-qrcode-svg` — vetted packages the host already bundles +
|
|
99
|
+
// shims (`_hostVettedModules`); sharing the host copy keeps icons/SVG on
|
|
100
|
+
// the host's react-native-web instance. qrcode-svg draws through
|
|
101
|
+
// react-native-svg, so externalising it keeps the QR on that same
|
|
102
|
+
// instance instead of a bundle inlining a second one (sc-6105).
|
|
100
103
|
const HOST_EXTERNAL_SPECIFIERS = [
|
|
101
104
|
"react",
|
|
102
105
|
"react/jsx-runtime",
|
|
@@ -107,6 +110,7 @@ const HOST_EXTERNAL_SPECIFIERS = [
|
|
|
107
110
|
"lucide-react-native",
|
|
108
111
|
"react-native-svg",
|
|
109
112
|
"date-fns",
|
|
113
|
+
"react-native-qrcode-svg",
|
|
110
114
|
// sc-1265: a bundled widget (and any vetted RN package it inlines, e.g.
|
|
111
115
|
// react-native-gesture-handler) imports `react-native`; the host resolves it
|
|
112
116
|
// to its OWN single react-native-web instance through a blob shim, so the
|