@colixsystems/widget-sdk 0.277.3 → 0.278.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 +9 -1
- package/dist/contract.cjs +53 -2
- package/dist/contract.js +53 -2
- package/dist/index.d.ts +56 -0
- package/dist/index.js +2 -0
- package/dist/index.native.js +2 -0
- package/dist/markdown-editor-bundle.js +158 -0
- package/dist/markdown-editor-field.js +6 -4
- package/dist/purchases.js +143 -0
- package/package.json +1 -57
- package/src/contract.js +53 -2
package/README.md
CHANGED
|
@@ -87,7 +87,15 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
87
87
|
|
|
88
88
|
## Status
|
|
89
89
|
|
|
90
|
-
`v0.
|
|
90
|
+
`v0.278.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**.
|
|
91
|
+
|
|
92
|
+
### What's new in 0.278.0 (contract 1.227.0)
|
|
93
|
+
|
|
94
|
+
**New `usePurchases()` hook: sell digital goods in the native app through the App Store and Google Play.** It runs on the workspace's own RevenueCat project and returns `{ supported, loading, offering, entitlements, error, purchase, restore, refresh }`. `offering` is the current offering (`{ id, packages: [{ id, title, description, priceString, currencyCode }] }`), `entitlements` the signed-in user's active entitlement identifiers, and `purchase(packageId)` / `restore()` resolve the updated entitlements or reject with a `PurchasesError` (`UNSUPPORTED`, `SIGN_IN_REQUIRED`, `CANCELLED`, `NOT_FOUND`, `PURCHASE_FAILED`, `INTERNAL`). It is native-only: a browser has no store billing, so on the web Player `supported` is `false` and the widget must show a visible "available in the app" state. `react-native-purchases` is now a vetted native-only import; prefer the hook, and never configure or log in Purchases yourself.
|
|
95
|
+
|
|
96
|
+
### What's new in 0.277.4
|
|
97
|
+
|
|
98
|
+
**`<MarkdownInput>` brings its own editor on web.** The web field loads a build of the editor with Tiptap inlined, so the SDK no longer lists any `@tiptap/*` package as a peer and an app that renders `<MarkdownInput>` on web installs nothing extra.
|
|
91
99
|
|
|
92
100
|
### What's new in 0.277.3
|
|
93
101
|
|
package/dist/contract.cjs
CHANGED
|
@@ -3130,6 +3130,37 @@ const HOOKS = [
|
|
|
3130
3130
|
requiredContextSlice: [],
|
|
3131
3131
|
scopes: null,
|
|
3132
3132
|
},
|
|
3133
|
+
// sc-15163 — native-only in-app purchase. Optional slice; the hook reports
|
|
3134
|
+
// supported:false on the web Player rather than throwing at render.
|
|
3135
|
+
{
|
|
3136
|
+
name: "usePurchases",
|
|
3137
|
+
signature: "usePurchases()",
|
|
3138
|
+
description:
|
|
3139
|
+
"Sell digital goods (a subscription, premium content, credits) in the native app through the App Store and Google " +
|
|
3140
|
+
"Play, on the workspace's own RevenueCat project. Returns { supported, loading, offering, entitlements, error, " +
|
|
3141
|
+
"purchase, restore, refresh }. `offering` is the current offering set up in RevenueCat — { id, packages: [{ id, " +
|
|
3142
|
+
"title, description, priceString, currencyCode }] } or null; show priceString as-is, the store localises it. " +
|
|
3143
|
+
"`entitlements` lists the signed-in user's ACTIVE entitlement identifiers — unlock content by checking it. " +
|
|
3144
|
+
"purchase(packageId) opens the store's own sheet and resolves the updated entitlements; restore() re-reads purchases " +
|
|
3145
|
+
"made on another device (offer it: the stores require a way to restore). Both reject with a PurchasesError whose " +
|
|
3146
|
+
".code is one of UNSUPPORTED | SIGN_IN_REQUIRED | CANCELLED | NOT_FOUND | PURCHASE_FAILED | INTERNAL; CANCELLED means " +
|
|
3147
|
+
"the buyer closed the sheet, so do not show it as a failure. A purchase needs a signed-in app user. NATIVE-ONLY: a " +
|
|
3148
|
+
"browser has no App Store or Google Play billing, so the web Player (and the Studio canvas) report supported:false " +
|
|
3149
|
+
"— ALWAYS render a visible 'available in the app' state there, never a blank or a dead button. The Expo export also " +
|
|
3150
|
+
"reports supported:false until the workspace connects RevenueCat in Payments and rebuilds the app.",
|
|
3151
|
+
returnShape: {
|
|
3152
|
+
supported: "boolean // false on the web Player and in an app built without RevenueCat",
|
|
3153
|
+
loading: "boolean",
|
|
3154
|
+
offering: "{ id, packages: [{ id, title, description, priceString, currencyCode }] } | null",
|
|
3155
|
+
entitlements: "string[] // active entitlement identifiers",
|
|
3156
|
+
error: "PurchasesError | null",
|
|
3157
|
+
purchase: "(packageId: string) => Promise<string[]> // rejects with PurchasesError",
|
|
3158
|
+
restore: "() => Promise<string[]> // rejects with PurchasesError",
|
|
3159
|
+
refresh: "() => Promise<void>",
|
|
3160
|
+
},
|
|
3161
|
+
requiredContextSlice: [],
|
|
3162
|
+
scopes: null,
|
|
3163
|
+
},
|
|
3133
3164
|
{
|
|
3134
3165
|
name: "useAudioPlayer",
|
|
3135
3166
|
signature: "useAudioPlayer(uri)",
|
|
@@ -4432,7 +4463,11 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
4432
4463
|
"audioRecorder: { isSupported() -> boolean, getPermission() -> Promise<'granted' | 'denied' | 'undetermined'>, " +
|
|
4433
4464
|
"start() -> Promise<{ getStatus() -> { durationMs, levelDb, ended }, stop() -> Promise<{ file, uri, durationMs, mime, release? }>, cancel() }> }, " +
|
|
4434
4465
|
"audioPlayer: { isSupported() -> boolean, load(uri, onStatus({ loaded, playing, positionMs, durationMs, error? })) -> " +
|
|
4435
|
-
"{ play() -> Promise<void>, pause(), seek(ms) -> Promise<void>, release() } }
|
|
4466
|
+
"{ play() -> Promise<void>, pause(), seek(ms) -> Promise<void>, release() } }, " +
|
|
4467
|
+
"purchases: { isSupported() -> boolean, getOffering() -> Promise<offering | null>, getEntitlements() -> Promise<string[]>, " +
|
|
4468
|
+
"purchase(packageId) -> Promise<string[]>, restore() -> Promise<string[]> } }. " +
|
|
4469
|
+
"purchases backs usePurchases() and is NATIVE-ONLY: the Expo export brokers it through react-native-purchases when the " +
|
|
4470
|
+
"workspace connected RevenueCat; the web Player never does, because a browser has no store billing. " +
|
|
4436
4471
|
"Backs useGeolocation(), useSpeechToText(), useCamera(), useImageEditor(), useBarcodeScanner(), usePdfExport().openPdf, useAudioRecorder() and useAudioPlayer(). The web Player brokers them via " +
|
|
4437
4472
|
"navigator.geolocation, window.SpeechRecognition, a getUserMedia camera preview, a host-side canvas, BarcodeDetector, a new browser tab, MediaRecorder and an <audio> element; the Expo export via " +
|
|
4438
4473
|
"expo-location, expo-speech-recognition, expo-image-picker, expo-image-manipulator, expo-camera, expo-print and expo-audio. " +
|
|
@@ -4472,6 +4507,7 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
4472
4507
|
pdfViewer: "object",
|
|
4473
4508
|
audioRecorder: "object",
|
|
4474
4509
|
audioPlayer: "object",
|
|
4510
|
+
purchases: "object",
|
|
4475
4511
|
},
|
|
4476
4512
|
},
|
|
4477
4513
|
};
|
|
@@ -4702,6 +4738,18 @@ const VETTED_IMPORTS = [
|
|
|
4702
4738
|
description:
|
|
4703
4739
|
"Native clipboard. The SDK's useClipboard() hook already wraps this; reach for it directly only if you need RN-specific options.",
|
|
4704
4740
|
},
|
|
4741
|
+
// sc-15163 — native-only: a browser has no App Store / Google Play billing.
|
|
4742
|
+
{
|
|
4743
|
+
specifier: "react-native-purchases",
|
|
4744
|
+
platforms: ["native"],
|
|
4745
|
+
category: "payments",
|
|
4746
|
+
description:
|
|
4747
|
+
"RevenueCat in-app purchase (StoreKit / Play Billing). PREFER usePurchases() from the SDK, which already runs on the " +
|
|
4748
|
+
"app's configured, signed-in customer. Import this directly only for what the hook does not cover, and NEVER call " +
|
|
4749
|
+
"Purchases.configure, logIn or logOut — the app owns them, and it configures Purchases only when the workspace " +
|
|
4750
|
+
"connected RevenueCat. Native-only because no browser offers store billing: author it in widget.native.jsx and give " +
|
|
4751
|
+
"widget.web.jsx a visible 'available in the app' state.",
|
|
4752
|
+
},
|
|
4705
4753
|
{
|
|
4706
4754
|
specifier: "expo-haptics",
|
|
4707
4755
|
platforms: ["native"],
|
|
@@ -6577,7 +6625,10 @@ const CONTRACT = deepFreeze({
|
|
|
6577
6625
|
// 1.226.0: behaviour (sc-15080) — `<MarkdownInput>` is a rich-text editor
|
|
6578
6626
|
// showing the formatted result; `showPreview`, `previewLabel` and
|
|
6579
6627
|
// `renderImage` are accepted and ignored.
|
|
6580
|
-
|
|
6628
|
+
// 1.227.0: additive (sc-15163) — new native-only `usePurchases()` hook and
|
|
6629
|
+
// `PurchasesError`, a `device.purchases` slice, and the vetted
|
|
6630
|
+
// `react-native-purchases` import.
|
|
6631
|
+
version: "1.227.0",
|
|
6581
6632
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
6582
6633
|
hooks: HOOKS,
|
|
6583
6634
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -3126,6 +3126,37 @@ const HOOKS = [
|
|
|
3126
3126
|
requiredContextSlice: [],
|
|
3127
3127
|
scopes: null,
|
|
3128
3128
|
},
|
|
3129
|
+
// sc-15163 — native-only in-app purchase. Optional slice; the hook reports
|
|
3130
|
+
// supported:false on the web Player rather than throwing at render.
|
|
3131
|
+
{
|
|
3132
|
+
name: "usePurchases",
|
|
3133
|
+
signature: "usePurchases()",
|
|
3134
|
+
description:
|
|
3135
|
+
"Sell digital goods (a subscription, premium content, credits) in the native app through the App Store and Google " +
|
|
3136
|
+
"Play, on the workspace's own RevenueCat project. Returns { supported, loading, offering, entitlements, error, " +
|
|
3137
|
+
"purchase, restore, refresh }. `offering` is the current offering set up in RevenueCat — { id, packages: [{ id, " +
|
|
3138
|
+
"title, description, priceString, currencyCode }] } or null; show priceString as-is, the store localises it. " +
|
|
3139
|
+
"`entitlements` lists the signed-in user's ACTIVE entitlement identifiers — unlock content by checking it. " +
|
|
3140
|
+
"purchase(packageId) opens the store's own sheet and resolves the updated entitlements; restore() re-reads purchases " +
|
|
3141
|
+
"made on another device (offer it: the stores require a way to restore). Both reject with a PurchasesError whose " +
|
|
3142
|
+
".code is one of UNSUPPORTED | SIGN_IN_REQUIRED | CANCELLED | NOT_FOUND | PURCHASE_FAILED | INTERNAL; CANCELLED means " +
|
|
3143
|
+
"the buyer closed the sheet, so do not show it as a failure. A purchase needs a signed-in app user. NATIVE-ONLY: a " +
|
|
3144
|
+
"browser has no App Store or Google Play billing, so the web Player (and the Studio canvas) report supported:false " +
|
|
3145
|
+
"— ALWAYS render a visible 'available in the app' state there, never a blank or a dead button. The Expo export also " +
|
|
3146
|
+
"reports supported:false until the workspace connects RevenueCat in Payments and rebuilds the app.",
|
|
3147
|
+
returnShape: {
|
|
3148
|
+
supported: "boolean // false on the web Player and in an app built without RevenueCat",
|
|
3149
|
+
loading: "boolean",
|
|
3150
|
+
offering: "{ id, packages: [{ id, title, description, priceString, currencyCode }] } | null",
|
|
3151
|
+
entitlements: "string[] // active entitlement identifiers",
|
|
3152
|
+
error: "PurchasesError | null",
|
|
3153
|
+
purchase: "(packageId: string) => Promise<string[]> // rejects with PurchasesError",
|
|
3154
|
+
restore: "() => Promise<string[]> // rejects with PurchasesError",
|
|
3155
|
+
refresh: "() => Promise<void>",
|
|
3156
|
+
},
|
|
3157
|
+
requiredContextSlice: [],
|
|
3158
|
+
scopes: null,
|
|
3159
|
+
},
|
|
3129
3160
|
{
|
|
3130
3161
|
name: "useAudioPlayer",
|
|
3131
3162
|
signature: "useAudioPlayer(uri)",
|
|
@@ -4428,7 +4459,11 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
4428
4459
|
"audioRecorder: { isSupported() -> boolean, getPermission() -> Promise<'granted' | 'denied' | 'undetermined'>, " +
|
|
4429
4460
|
"start() -> Promise<{ getStatus() -> { durationMs, levelDb, ended }, stop() -> Promise<{ file, uri, durationMs, mime, release? }>, cancel() }> }, " +
|
|
4430
4461
|
"audioPlayer: { isSupported() -> boolean, load(uri, onStatus({ loaded, playing, positionMs, durationMs, error? })) -> " +
|
|
4431
|
-
"{ play() -> Promise<void>, pause(), seek(ms) -> Promise<void>, release() } }
|
|
4462
|
+
"{ play() -> Promise<void>, pause(), seek(ms) -> Promise<void>, release() } }, " +
|
|
4463
|
+
"purchases: { isSupported() -> boolean, getOffering() -> Promise<offering | null>, getEntitlements() -> Promise<string[]>, " +
|
|
4464
|
+
"purchase(packageId) -> Promise<string[]>, restore() -> Promise<string[]> } }. " +
|
|
4465
|
+
"purchases backs usePurchases() and is NATIVE-ONLY: the Expo export brokers it through react-native-purchases when the " +
|
|
4466
|
+
"workspace connected RevenueCat; the web Player never does, because a browser has no store billing. " +
|
|
4432
4467
|
"Backs useGeolocation(), useSpeechToText(), useCamera(), useImageEditor(), useBarcodeScanner(), usePdfExport().openPdf, useAudioRecorder() and useAudioPlayer(). The web Player brokers them via " +
|
|
4433
4468
|
"navigator.geolocation, window.SpeechRecognition, a getUserMedia camera preview, a host-side canvas, BarcodeDetector, a new browser tab, MediaRecorder and an <audio> element; the Expo export via " +
|
|
4434
4469
|
"expo-location, expo-speech-recognition, expo-image-picker, expo-image-manipulator, expo-camera, expo-print and expo-audio. " +
|
|
@@ -4468,6 +4503,7 @@ const WIDGET_CONTEXT_SHAPE = {
|
|
|
4468
4503
|
pdfViewer: "object",
|
|
4469
4504
|
audioRecorder: "object",
|
|
4470
4505
|
audioPlayer: "object",
|
|
4506
|
+
purchases: "object",
|
|
4471
4507
|
},
|
|
4472
4508
|
},
|
|
4473
4509
|
};
|
|
@@ -4698,6 +4734,18 @@ const VETTED_IMPORTS = [
|
|
|
4698
4734
|
description:
|
|
4699
4735
|
"Native clipboard. The SDK's useClipboard() hook already wraps this; reach for it directly only if you need RN-specific options.",
|
|
4700
4736
|
},
|
|
4737
|
+
// sc-15163 — native-only: a browser has no App Store / Google Play billing.
|
|
4738
|
+
{
|
|
4739
|
+
specifier: "react-native-purchases",
|
|
4740
|
+
platforms: ["native"],
|
|
4741
|
+
category: "payments",
|
|
4742
|
+
description:
|
|
4743
|
+
"RevenueCat in-app purchase (StoreKit / Play Billing). PREFER usePurchases() from the SDK, which already runs on the " +
|
|
4744
|
+
"app's configured, signed-in customer. Import this directly only for what the hook does not cover, and NEVER call " +
|
|
4745
|
+
"Purchases.configure, logIn or logOut — the app owns them, and it configures Purchases only when the workspace " +
|
|
4746
|
+
"connected RevenueCat. Native-only because no browser offers store billing: author it in widget.native.jsx and give " +
|
|
4747
|
+
"widget.web.jsx a visible 'available in the app' state.",
|
|
4748
|
+
},
|
|
4701
4749
|
{
|
|
4702
4750
|
specifier: "expo-haptics",
|
|
4703
4751
|
platforms: ["native"],
|
|
@@ -6573,7 +6621,10 @@ const CONTRACT = deepFreeze({
|
|
|
6573
6621
|
// 1.226.0: behaviour (sc-15080) — `<MarkdownInput>` is a rich-text editor
|
|
6574
6622
|
// showing the formatted result; `showPreview`, `previewLabel` and
|
|
6575
6623
|
// `renderImage` are accepted and ignored.
|
|
6576
|
-
|
|
6624
|
+
// 1.227.0: additive (sc-15163) — new native-only `usePurchases()` hook and
|
|
6625
|
+
// `PurchasesError`, a `device.purchases` slice, and the vetted
|
|
6626
|
+
// `react-native-purchases` import.
|
|
6627
|
+
version: "1.227.0",
|
|
6577
6628
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
6578
6629
|
hooks: HOOKS,
|
|
6579
6630
|
primitives: PRIMITIVES,
|
package/dist/index.d.ts
CHANGED
|
@@ -946,6 +946,14 @@ export interface WidgetContext<TProps = unknown> {
|
|
|
946
946
|
release(): void;
|
|
947
947
|
};
|
|
948
948
|
};
|
|
949
|
+
/** sc-15163 — backs usePurchases. Brokered by the Expo export only. */
|
|
950
|
+
purchases?: {
|
|
951
|
+
isSupported?(): boolean;
|
|
952
|
+
getOffering(): Promise<PurchaseOffering | null>;
|
|
953
|
+
getEntitlements(): Promise<string[]>;
|
|
954
|
+
purchase(packageId: string): Promise<string[]>;
|
|
955
|
+
restore(): Promise<string[]>;
|
|
956
|
+
};
|
|
949
957
|
speech?: {
|
|
950
958
|
isSupported?(): boolean;
|
|
951
959
|
start(
|
|
@@ -2895,6 +2903,54 @@ export interface AudioPlayerResult {
|
|
|
2895
2903
|
*/
|
|
2896
2904
|
export function useAudioPlayer(uri: string | null | undefined): AudioPlayerResult;
|
|
2897
2905
|
|
|
2906
|
+
/** One package of the current offering, as the store prices it. */
|
|
2907
|
+
export interface PurchasePackage {
|
|
2908
|
+
id: string;
|
|
2909
|
+
title: string;
|
|
2910
|
+
description: string;
|
|
2911
|
+
priceString: string;
|
|
2912
|
+
currencyCode: string;
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/** The current offering the workspace set up in RevenueCat. */
|
|
2916
|
+
export interface PurchaseOffering {
|
|
2917
|
+
id: string;
|
|
2918
|
+
packages: PurchasePackage[];
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2921
|
+
/** What `usePurchases()` returns. */
|
|
2922
|
+
export interface PurchasesResult {
|
|
2923
|
+
/** False on the web Player: store billing needs the native app. */
|
|
2924
|
+
supported: boolean;
|
|
2925
|
+
loading: boolean;
|
|
2926
|
+
offering: PurchaseOffering | null;
|
|
2927
|
+
/** The signed-in user's active entitlement identifiers. */
|
|
2928
|
+
entitlements: string[];
|
|
2929
|
+
error: PurchasesError | null;
|
|
2930
|
+
purchase(packageId: string): Promise<string[]>;
|
|
2931
|
+
restore(): Promise<string[]>;
|
|
2932
|
+
refresh(): Promise<void>;
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
/**
|
|
2936
|
+
* Sell digital goods through the App Store and Google Play, on the
|
|
2937
|
+
* workspace's own RevenueCat project. Native-only: on the web Player
|
|
2938
|
+
* `supported` is false — render a visible "not available on the web" state.
|
|
2939
|
+
*/
|
|
2940
|
+
export function usePurchases(): PurchasesResult;
|
|
2941
|
+
|
|
2942
|
+
/** Error surfaced by `usePurchases()`. */
|
|
2943
|
+
export class PurchasesError extends Error {
|
|
2944
|
+
code:
|
|
2945
|
+
| "UNSUPPORTED"
|
|
2946
|
+
| "SIGN_IN_REQUIRED"
|
|
2947
|
+
| "CANCELLED"
|
|
2948
|
+
| "NOT_FOUND"
|
|
2949
|
+
| "PURCHASE_FAILED"
|
|
2950
|
+
| "INTERNAL";
|
|
2951
|
+
constructor(code: PurchasesError["code"], message: string, opts?: { cause?: unknown });
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2898
2954
|
/** Error surfaced by `useAudioPlayer()`. */
|
|
2899
2955
|
export class AudioPlayerError extends Error {
|
|
2900
2956
|
code: "UNSUPPORTED" | "LOAD_FAILED" | "BLOCKED" | "INTERNAL";
|
package/dist/index.js
CHANGED
|
@@ -132,6 +132,8 @@ export {
|
|
|
132
132
|
useAudioPlayer,
|
|
133
133
|
AudioPlayerError,
|
|
134
134
|
} from "./audio.js";
|
|
135
|
+
// sc-15163 — native-only in-app purchase; the web Player brokers none.
|
|
136
|
+
export { usePurchases, PurchasesError } from "./purchases.js";
|
|
135
137
|
export { useDatastoreFigure } from "./datastore-figure.js";
|
|
136
138
|
export {
|
|
137
139
|
useDatastoreAggregate,
|
package/dist/index.native.js
CHANGED
|
@@ -130,6 +130,8 @@ export {
|
|
|
130
130
|
useAudioPlayer,
|
|
131
131
|
AudioPlayerError,
|
|
132
132
|
} from "./audio.js";
|
|
133
|
+
// sc-15163 — native-only in-app purchase; the web Player brokers none.
|
|
134
|
+
export { usePurchases, PurchasesError } from "./purchases.js";
|
|
133
135
|
export { useDatastoreFigure } from "./datastore-figure.js";
|
|
134
136
|
export {
|
|
135
137
|
useDatastoreAggregate,
|