@wix/himalaya-cli 0.1577.0 → 0.1578.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.
Files changed (23) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/clipboard/src/index.d.ts +32 -1
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/haptic/src/index.d.ts +69 -5
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -2
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/ui/src/index.d.ts +19 -2
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +6 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +2 -2
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +2 -2
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +2 -2
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/clipboard.mjs +58 -1
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +2 -2
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/haptic.mjs +73 -4
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +2 -2
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +2 -2
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +2 -2
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +2 -2
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +2 -2
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/ui.mjs +5 -0
  18. package/dist/cli.mjs +1053 -915
  19. package/dist/preview-assets.generated.bin +0 -0
  20. package/guides/qa-builds.md +14 -6
  21. package/guides/sdk-reference.json +116 -8
  22. package/guides/web-page-sdk-reference.md +2 -2
  23. package/package.json +2 -2
@@ -1,3 +1,5 @@
1
+ import type { FileHandle } from "@wix/himalaya/sdk-types";
2
+ export type { FileHandle } from "@wix/himalaya/sdk-types";
1
3
  /** Copy `text` to the clipboard. */
2
4
  export declare function writeText(text: string): Promise<void>;
3
5
  /** Read the clipboard's text, or null if empty / the read was blocked (no focus,
@@ -7,5 +9,34 @@ export declare function readText(): Promise<string | null>;
7
9
  * web this can't be known without reading, so it returns true pessimistically;
8
10
  * treat it as a hint, not a guarantee. */
9
11
  export declare function hasText(): Promise<boolean>;
12
+ /** Largest image writeImage accepts (20 MB). Hosts enforce it too. */
13
+ export declare const MAX_IMAGE_BYTES: number;
14
+ /** Image MIME types writeImage copies. HEIC is iOS/macOS only (Android and web
15
+ * reject it `unsupported_type`); web accepts PNG only. The host sniffs the file's
16
+ * bytes, so a handle is judged by its content, not its `mimeType` — the binding only
17
+ * refuses up front a handle whose type is plainly not an image (e.g. application/pdf). */
18
+ export declare const IMAGE_MIME_TYPES: readonly string[];
19
+ /** Why writeImage rejected. */
20
+ export type ClipboardImageErrorCode = "unsupported_type" | "too_large" | "not_allowed" | "not_found" | "unavailable";
21
+ /** A writeImage rejection: an `Error` named "ClipboardImageError" carrying a stable
22
+ * `code`. (A plain Error, not a subclass — Tier-5 bundles target an engine without
23
+ * class syntax.) Branch on `isClipboardImageError(e) && e.code === "too_large"`. */
24
+ export interface ClipboardImageError extends Error {
25
+ name: "ClipboardImageError";
26
+ code: ClipboardImageErrorCode;
27
+ }
28
+ /** Build a coded writeImage rejection. */
29
+ export declare function clipboardImageError(code: ClipboardImageErrorCode, message?: string): ClipboardImageError;
30
+ /** Whether `e` is a coded writeImage rejection. */
31
+ export declare function isClipboardImageError(e: unknown): e is ClipboardImageError;
32
+ /** Copy an image file the worker already holds to the clipboard. Accepts a
33
+ * `FileHandle` (from files / camera / photos) or its substrate `uri`. Rejects with a
34
+ * `ClipboardImageError` (see `isClipboardImageError`) whose `code` is `unsupported_type` (not PNG/JPEG/WebP/HEIC, or
35
+ * not supported on this host), `too_large` (over 20 MB), `not_allowed` (outside the
36
+ * app's files substrate), `not_found`, or `unavailable` (no image clipboard here). */
37
+ export declare function writeImage(file: FileHandle | string): Promise<void>;
38
+ /** Whether the clipboard currently holds an image — without reading it (no iOS paste
39
+ * banner). Web cannot know without a permission-gated read, so it answers false. */
40
+ export declare function hasImage(): Promise<boolean>;
10
41
  /** Capability version, for bundles that gate on min binary version. */
11
- export declare const version = 1;
42
+ export declare const version = 2;
@@ -1,9 +1,73 @@
1
- /** Maps to a native impact/notification/selection generator. */
2
- export type HapticPattern = "selection" | "light" | "medium" | "heavy" | "success" | "warning" | "error";
1
+ /**
2
+ * Maps to a native impact/notification/selection generator.
3
+ *
4
+ * - `rigid` / `soft` — iOS `UIImpactFeedbackGenerator.FeedbackStyle.rigid` / `.soft`.
5
+ * Android: `rigid` is a short full-amplitude click (`VibrationEffect.EFFECT_CLICK`-like),
6
+ * `soft` a longer low-amplitude tick (`PRIMITIVE_LOW_TICK`-like); on a device without
7
+ * amplitude control both are plain one-shots of different length.
8
+ */
9
+ export type HapticPattern = "selection" | "light" | "medium" | "heavy" | "rigid" | "soft" | "success" | "warning" | "error";
10
+ export interface PlayOptions {
11
+ /**
12
+ * 0..1, clamped. Scales the strength of an IMPACT style (`light`, `medium`, `heavy`,
13
+ * `rigid`, `soft`): iOS `impactOccurred(intensity:)`, Android amplitude where the
14
+ * vibrator has amplitude control. Ignored for `selection` and the notification styles
15
+ * (`success`, `warning`, `error`) — those have a fixed system strength — and on web.
16
+ */
17
+ intensity?: number;
18
+ }
19
+ export interface HapticStep {
20
+ pattern: HapticPattern;
21
+ /** Milliseconds to wait BEFORE this step plays (≥ 0). */
22
+ delayMs: number;
23
+ /** Same meaning as {@link PlayOptions.intensity}. */
24
+ intensity?: number;
25
+ }
26
+ /**
27
+ * What a verb reports. `ok: false` is honest: `unavailable` (this surface has no haptic
28
+ * hardware/API — web without `navigator.vibrate`, macOS) or `unsupported_binary` (the
29
+ * native app predates the verb; nothing played, nothing broke).
30
+ */
31
+ export type HapticResult = {
32
+ ok: true;
33
+ } | {
34
+ ok: false;
35
+ reason: "unavailable" | "unsupported_binary";
36
+ };
37
+ /** Most steps one {@link sequence} may carry. */
38
+ export declare const MAX_SEQUENCE_STEPS = 32;
39
+ /** Longest a {@link sequence} or {@link vibrate} pattern may run, in milliseconds. */
40
+ export declare const MAX_DURATION_MS = 10000;
41
+ /** Clamp an intensity into 0..1; `undefined` / non-finite → `undefined` (system default). */
42
+ export declare function clampIntensity(intensity: number | undefined): number | undefined;
3
43
  /**
4
44
  * Play a haptic feedback pattern. Fire-and-forget; resolves once handed to the
5
- * platform. A no-op on web and for unknown patterns.
45
+ * platform. Unknown pattern names keep their historical behaviour (the platform's
46
+ * default tap). `intensity` applies to impact styles only — see {@link PlayOptions}.
47
+ */
48
+ export declare function play(pattern?: HapticPattern, options?: PlayOptions): Promise<HapticResult>;
49
+ /**
50
+ * Play `steps` in order, waiting each step's `delayMs` before it plays. Runs natively
51
+ * as ONE bridge call (the timing does not depend on the worker), so a drum roll or a
52
+ * countdown keeps its rhythm. A new `sequence` cancels one still running. Resolves once
53
+ * the sequence has been scheduled.
54
+ *
55
+ * Rejects (`RangeError`) with more than {@link MAX_SEQUENCE_STEPS} steps, a negative or
56
+ * non-finite delay, or delays totalling over {@link MAX_DURATION_MS}. An empty list just
57
+ * cancels a running sequence.
58
+ */
59
+ export declare function sequence(steps: HapticStep[]): Promise<HapticResult>;
60
+ /**
61
+ * Raw vibration: `patternMs` alternates OFF / ON durations in milliseconds, starting
62
+ * with an off gap (`[0, 200, 100, 400]` = buzz 200, pause 100, buzz 400).
63
+ *
64
+ * Android plays it as `VibrationEffect.createWaveform`. iOS approximates: with Core
65
+ * Haptics each ON span is a continuous event (a transient one under 30 ms); without it,
66
+ * each ON span becomes one `heavy` impact at its start. Web uses `navigator.vibrate`.
67
+ *
68
+ * Rejects (`RangeError`) on an empty list, a negative or non-finite duration, or a
69
+ * pattern totalling over {@link MAX_DURATION_MS}.
6
70
  */
7
- export declare function play(pattern?: HapticPattern): Promise<void>;
71
+ export declare function vibrate(patternMs: number[]): Promise<HapticResult>;
8
72
  /** Capability version, for bundles that gate on a min binary version. */
9
- export declare const version = 1;
73
+ export declare const version = 2;
@@ -8,12 +8,12 @@ export declare const CAPABILITY_REGISTRY: {
8
8
  readonly calendar: readonly ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"];
9
9
  readonly calls: readonly ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"];
10
10
  readonly camera: readonly ["capture", "pickDocument", "prepareImage", "scanQR"];
11
- readonly clipboard: readonly ["hasText", "readText", "writeText"];
11
+ readonly clipboard: readonly ["hasImage", "hasText", "readText", "writeImage", "writeText"];
12
12
  readonly contacts: readonly ["getPermissionStatus", "pick", "requestPermission", "search"];
13
13
  readonly file_picker: readonly ["pick", "pickDirectoryForExport"];
14
14
  readonly files: readonly ["list", "readText", "remove", "stat", "write"];
15
15
  readonly godot: readonly ["loadPack", "release", "send"];
16
- readonly haptic: readonly ["play"];
16
+ readonly haptic: readonly ["play", "sequence", "vibrate"];
17
17
  readonly health: readonly ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"];
18
18
  readonly himi_apps: readonly ["canOpen", "current", "hostInfo", "open"];
19
19
  readonly iap: readonly ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"];
@@ -6,8 +6,23 @@ export interface AlertOptions {
6
6
  confirmLabel?: string;
7
7
  /** Cancel button label. OMIT for a single-button alert (no cancel button). */
8
8
  cancelLabel?: string;
9
- /** Style the confirm button with the `danger` token. */
9
+ /** Style the confirm button with the `danger` token. A destructive confirm is not the
10
+ * affirmative button: its `confirm.actionId` still runs, but without gesture credit. */
10
11
  destructive?: boolean;
12
+ /** The affirmative button's ACTION. Pressing it runs `actionId` as a NEW invocation
13
+ * with user-gesture origin (so an app service's `app.<svc>.<action>` may return `_nav` and
14
+ * navigate — the "Ready — View" alert). `label` replaces `confirmLabel`. The id is checked when
15
+ * you set it, against this worker: a `capability.<id>.*` needs `<id>` allowed, an `app.*` from a
16
+ * screen worker needs `app_services` and an exported action, a `tier5.*` must be this worker's
17
+ * own; anything else rejects (`action_not_allowed`). Cancel and dismissal run nothing. */
18
+ confirm?: AlertConfirm;
19
+ }
20
+ /** The affirmative button of an `alert()`: its label and the action its press runs. */
21
+ export interface AlertConfirm {
22
+ label: string;
23
+ actionId: string;
24
+ /** Passed to the action (JSON types kept). */
25
+ args?: Record<string, unknown>;
11
26
  }
12
27
  export interface AlertResult {
13
28
  /** true ⇒ the user tapped confirm; false ⇒ cancel or the alert was dismissed
@@ -16,7 +31,9 @@ export interface AlertResult {
16
31
  }
17
32
  /** Present a modal alert on the current screen. Resolves when the user picks a
18
33
  * button. Rejects with `ui_busy` while another alert() is pending, and with
19
- * `no_ui_host` if the app has no presenter attached. */
34
+ * `no_ui_host` if the app has no presenter attached — or, from an APP SERVICE, when no
35
+ * shell is in the foreground (re-show it from `onForeground`). An app service's alert shows on
36
+ * whatever screen is open. */
20
37
  export declare function alert(options: AlertOptions): Promise<AlertResult>;
21
38
  /** Snackbar tone — maps to the app's tone background tokens (`info` → textPrimary, `success`,
22
39
  * `warning`, `danger`). Use `danger` for errors; the hosts also accept `error` as an alias of it. */
@@ -561,6 +561,12 @@ export interface RichTemplate {
561
561
  export interface PushConfig {
562
562
  /** Ping base family, without an APNs environment suffix. */
563
563
  pingAppName?: string;
564
+ /** Wix Ping registration scope (#4708). "site" (default) filters delivery to the
565
+ * session's metasite and refuses to register without one; "user" registers the
566
+ * device for the signed-in Wix user with NO metasite filter — for an
567
+ * account-level app that is not about any single site. Only the "wix-ping"
568
+ * registrar reads it. */
569
+ pingScope?: "site" | "user";
564
570
  /** Token registrar. "generic" ⇒ POST the token to `registerUrl`; "wix-ping"
565
571
  * ⇒ the native Wix Ping registrar. */
566
572
  registrar: PushRegistrar;
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -26,11 +26,68 @@ async function hasText() {
26
26
  const r = await dispatch("capability.clipboard.hasText");
27
27
  return r?.has === true;
28
28
  }
29
- var version = 1;
29
+ var MAX_IMAGE_BYTES = 20 * 1024 * 1024;
30
+ var IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/heic"];
31
+ var CODES = ["unsupported_type", "too_large", "not_allowed", "not_found", "unavailable"];
32
+ function clipboardImageError(code, message) {
33
+ const text = !message ? code : message.startsWith(code) ? message : `${code}: ${message}`;
34
+ const err = new Error(text);
35
+ err.name = "ClipboardImageError";
36
+ err.code = code;
37
+ return err;
38
+ }
39
+ function isClipboardImageError(e) {
40
+ return e instanceof Error && e.name === "ClipboardImageError" && CODES.includes(e.code);
41
+ }
42
+ function codeOf(err) {
43
+ const msg = err instanceof Error ? err.message : String(err ?? "");
44
+ let best = null;
45
+ for (const c of CODES) {
46
+ const m = new RegExp(`(^|[^a-z_])${c}([^a-z_]|$)`).exec(msg);
47
+ if (!m) continue;
48
+ const at = m.index + m[1].length;
49
+ if (!best || at < best.at) best = { code: c, at };
50
+ }
51
+ return best?.code ?? null;
52
+ }
53
+ function plainlyNotAnImage(mimeType) {
54
+ const mime = (mimeType ?? "").toLowerCase().trim();
55
+ return mime !== "" && mime !== "application/octet-stream" && !mime.startsWith("image/");
56
+ }
57
+ async function writeImage(file) {
58
+ const handle = typeof file === "string" ? null : file;
59
+ const uri = typeof file === "string" ? file : file?.uri;
60
+ if (typeof uri !== "string" || uri.length === 0) throw clipboardImageError("not_allowed", "no file uri");
61
+ if (handle) {
62
+ if (plainlyNotAnImage(handle.mimeType)) throw clipboardImageError("unsupported_type", String(handle.mimeType));
63
+ if (typeof handle.sizeBytes === "number" && handle.sizeBytes > MAX_IMAGE_BYTES) throw clipboardImageError("too_large", `${handle.sizeBytes} bytes`);
64
+ }
65
+ const params = { uri };
66
+ if (handle?.mimeType) params.mimeType = handle.mimeType;
67
+ if (handle?.ownerScope) params.ownerScope = handle.ownerScope;
68
+ try {
69
+ await dispatch("capability.clipboard.writeImage", params);
70
+ } catch (err) {
71
+ const code = codeOf(err);
72
+ if (code) throw clipboardImageError(code, err instanceof Error ? err.message : String(err));
73
+ throw err;
74
+ }
75
+ }
76
+ async function hasImage() {
77
+ const r = await dispatch("capability.clipboard.hasImage");
78
+ return r?.has === true;
79
+ }
80
+ var version = 2;
30
81
  export {
82
+ IMAGE_MIME_TYPES,
83
+ MAX_IMAGE_BYTES,
84
+ clipboardImageError,
85
+ hasImage,
31
86
  hasText,
87
+ isClipboardImageError,
32
88
  readText,
33
89
  version,
90
+ writeImage,
34
91
  writeText
35
92
  };
36
93
  //# sourceMappingURL=clipboard.mjs.map
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -14,12 +14,81 @@ function dispatch(handlerId, params, _options) {
14
14
  }
15
15
 
16
16
  // ../../core/sdk/haptic/src/index.ts
17
- async function play(pattern = "light") {
18
- await dispatch("capability.haptic.play", { pattern });
17
+ var MAX_SEQUENCE_STEPS = 32;
18
+ var MAX_DURATION_MS = 1e4;
19
+ function clampIntensity(intensity) {
20
+ if (intensity === void 0 || typeof intensity !== "number" || !Number.isFinite(intensity)) return void 0;
21
+ return Math.min(1, Math.max(0, intensity));
19
22
  }
20
- var version = 1;
23
+ var UNKNOWN_ACTION = /unknown[_ ]?(action|handler)|ActionError\.unknown|^unknown\(|no handler/i;
24
+ function toResult(payload) {
25
+ const p = payload;
26
+ if (p && p.ok === false) {
27
+ return { ok: false, reason: p.reason === "unsupported_binary" ? "unsupported_binary" : "unavailable" };
28
+ }
29
+ return { ok: true };
30
+ }
31
+ async function settle(pending) {
32
+ try {
33
+ return toResult(await pending);
34
+ } catch (e) {
35
+ if (UNKNOWN_ACTION.test(String(e?.message ?? e))) return { ok: false, reason: "unsupported_binary" };
36
+ throw e;
37
+ }
38
+ }
39
+ async function play(pattern = "light", options = {}) {
40
+ const params = { pattern };
41
+ const intensity = clampIntensity(options.intensity);
42
+ if (intensity !== void 0) params.intensity = intensity;
43
+ return toResult(await dispatch("capability.haptic.play", params));
44
+ }
45
+ async function sequence(steps) {
46
+ if (!Array.isArray(steps)) throw new TypeError("sequence: steps must be an array");
47
+ if (steps.length > MAX_SEQUENCE_STEPS) {
48
+ throw new RangeError(`sequence: at most ${MAX_SEQUENCE_STEPS} steps (got ${steps.length})`);
49
+ }
50
+ let total = 0;
51
+ const wire = steps.map((s, i) => {
52
+ const delayMs = Number(s?.delayMs ?? 0);
53
+ if (!Number.isFinite(delayMs) || delayMs < 0) throw new RangeError(`sequence: step ${i} has an invalid delayMs`);
54
+ total += delayMs;
55
+ const out = {
56
+ pattern: String(s?.pattern ?? "light"),
57
+ delayMs: Math.round(delayMs)
58
+ };
59
+ const intensity = clampIntensity(s?.intensity);
60
+ if (intensity !== void 0) out.intensity = intensity;
61
+ return out;
62
+ });
63
+ if (total > MAX_DURATION_MS) {
64
+ throw new RangeError(`sequence: total delay ${total}ms exceeds ${MAX_DURATION_MS}ms`);
65
+ }
66
+ return settle(dispatch("capability.haptic.sequence", { steps: JSON.stringify(wire) }));
67
+ }
68
+ async function vibrate(patternMs) {
69
+ if (!Array.isArray(patternMs) || patternMs.length === 0) {
70
+ throw new RangeError("vibrate: patternMs must be a non-empty array");
71
+ }
72
+ let total = 0;
73
+ const wire = patternMs.map((ms, i) => {
74
+ const n = Number(ms);
75
+ if (!Number.isFinite(n) || n < 0) throw new RangeError(`vibrate: duration ${i} is invalid`);
76
+ total += n;
77
+ return Math.round(n);
78
+ });
79
+ if (total > MAX_DURATION_MS) {
80
+ throw new RangeError(`vibrate: pattern totals ${total}ms, over ${MAX_DURATION_MS}ms`);
81
+ }
82
+ return settle(dispatch("capability.haptic.vibrate", { pattern: wire.join(",") }));
83
+ }
84
+ var version = 2;
21
85
  export {
86
+ MAX_DURATION_MS,
87
+ MAX_SEQUENCE_STEPS,
88
+ clampIntensity,
22
89
  play,
23
- version
90
+ sequence,
91
+ version,
92
+ vibrate
24
93
  };
25
94
  //# sourceMappingURL=haptic.mjs.map
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -8,12 +8,12 @@ var CAPABILITY_REGISTRY = {
8
8
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
9
9
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
10
10
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
11
- "clipboard": ["hasText", "readText", "writeText"],
11
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
12
12
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
13
13
  "file_picker": ["pick", "pickDirectoryForExport"],
14
14
  "files": ["list", "readText", "remove", "stat", "write"],
15
15
  "godot": ["loadPack", "release", "send"],
16
- "haptic": ["play"],
16
+ "haptic": ["play", "sequence", "vibrate"],
17
17
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
18
18
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
19
19
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -23,12 +23,12 @@ var CAPABILITY_REGISTRY = {
23
23
  "calendar": ["createEvent", "deleteEvent", "getPermissionStatus", "listEvents", "requestPermission", "updateEvent"],
24
24
  "calls": ["answer", "availability", "getPermissionStatus", "getState", "hangup", "listCalls", "offer", "receiveSignal", "reject", "requestPermission", "setMuted", "setRingback", "setSpeaker", "signalNext", "signalStart", "signalStop", "start", "subscribeEvents"],
25
25
  "camera": ["capture", "pickDocument", "prepareImage", "scanQR"],
26
- "clipboard": ["hasText", "readText", "writeText"],
26
+ "clipboard": ["hasImage", "hasText", "readText", "writeImage", "writeText"],
27
27
  "contacts": ["getPermissionStatus", "pick", "requestPermission", "search"],
28
28
  "file_picker": ["pick", "pickDirectoryForExport"],
29
29
  "files": ["list", "readText", "remove", "stat", "write"],
30
30
  "godot": ["loadPack", "release", "send"],
31
- "haptic": ["play"],
31
+ "haptic": ["play", "sequence", "vibrate"],
32
32
  "health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
33
33
  "himi_apps": ["canOpen", "current", "hostInfo", "open"],
34
34
  "iap": ["appBinding", "consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
@@ -20,6 +20,11 @@ async function alert(options) {
20
20
  if (options.confirmLabel) params.confirmLabel = options.confirmLabel;
21
21
  if (options.cancelLabel) params.cancelLabel = options.cancelLabel;
22
22
  if (options.destructive) params.destructive = true;
23
+ if (options.confirm) {
24
+ const { label, actionId, args } = options.confirm;
25
+ params.confirm = JSON.stringify(args === void 0 ? { label, actionId } : { label, actionId, args });
26
+ params.confirmLabel = label;
27
+ }
23
28
  const r = await dispatch("capability.ui.alert", params);
24
29
  return { confirmed: r?.confirmed === true || r?.confirmed === "true" };
25
30
  }