browser-haptic 1.0.10 → 1.0.12

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/dist/haptic.d.ts CHANGED
@@ -1,4 +1,12 @@
1
- export type VibrationPattern = number | number[];
1
+ export type VibrationPattern = number | number[] | readonly number[];
2
+ export declare enum HapticPreset {
3
+ Light = "light",
4
+ Medium = "medium",
5
+ Heavy = "heavy",
6
+ Success = "success",
7
+ Warning = "warning",
8
+ Error = "error"
9
+ }
2
10
  export interface Haptic {
3
11
  hasVibration(): boolean;
4
12
  isSupported(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"haptic.d.ts","sourceRoot":"","sources":["../src/haptic.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAUjD,MAAM,WAAW,MAAM;IACrB,YAAY,IAAI,OAAO,CAAC;IACxB,WAAW,IAAI,OAAO,CAAC;IACvB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACzC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;IAChB,OAAO,IAAI,IAAI,CAAC;IAChB,KAAK,IAAI,IAAI,CAAC;CACf;AA6ED,eAAO,MAAM,YAAY,QAAO,OAA4B,CAAC;AAmB7D,eAAO,MAAM,WAAW,QAAO,OAG9B,CAAC;AAoBF,eAAO,MAAM,OAAO,GAAI,SAAS,gBAAgB,KAAG,IAAwB,CAAC;AAQ7E,eAAO,MAAM,KAAK,QAAO,IAA8B,CAAC;AAQxD,eAAO,MAAM,MAAM,QAAO,IAA+B,CAAC;AAQ1D,eAAO,MAAM,KAAK,QAAO,IAA8B,CAAC;AAQxD,eAAO,MAAM,OAAO,QAAO,IAAqC,CAAC;AASjE,eAAO,MAAM,OAAO,QAAO,IAAqC,CAAC;AAQjE,eAAO,MAAM,KAAK,QAAO,IAAmC,CAAC;AAE7D,QAAA,MAAM,MAAM,EAAE,MAUb,CAAC;AAiBF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"haptic.d.ts","sourceRoot":"","sources":["../src/haptic.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAAC;AAGrE,oBAAY,YAAY;IACtB,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAUD,MAAM,WAAW,MAAM;IACrB,YAAY,IAAI,OAAO,CAAC;IACxB,WAAW,IAAI,OAAO,CAAC;IACvB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACzC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;IAChB,OAAO,IAAI,IAAI,CAAC;IAChB,KAAK,IAAI,IAAI,CAAC;CACf;AA0HD,eAAO,MAAM,YAAY,QAAO,OAA4B,CAAC;AAmB7D,eAAO,MAAM,WAAW,QAAO,OAG9B,CAAC;AAoBF,eAAO,MAAM,OAAO,GAAI,SAAS,gBAAgB,KAAG,IAAwB,CAAC;AAQ7E,eAAO,MAAM,KAAK,QAAO,IAA8C,CAAC;AAQxE,eAAO,MAAM,MAAM,QAAO,IAA+C,CAAC;AAQ1E,eAAO,MAAM,KAAK,QAAO,IAA8C,CAAC;AAQxE,eAAO,MAAM,OAAO,QAAO,IAAgD,CAAC;AAQ5E,eAAO,MAAM,OAAO,QAAO,IAAgD,CAAC;AAQ5E,eAAO,MAAM,KAAK,QAAO,IAA8C,CAAC;AAExE,QAAA,MAAM,MAAM,EAAE,MAUb,CAAC;AAiBF,eAAe,MAAM,CAAC"}
package/dist/haptic.js CHANGED
@@ -1,10 +1,44 @@
1
- const PRESETS = {
2
- light: 10,
3
- medium: 20,
4
- heavy: 40,
5
- success: [10, 50, 10],
6
- warning: [30, 30, 30],
7
- error: [50, 30, 50, 30, 50],
1
+ export var HapticPreset;
2
+ (function (HapticPreset) {
3
+ HapticPreset["Light"] = "light";
4
+ HapticPreset["Medium"] = "medium";
5
+ HapticPreset["Heavy"] = "heavy";
6
+ HapticPreset["Success"] = "success";
7
+ HapticPreset["Warning"] = "warning";
8
+ HapticPreset["Error"] = "error";
9
+ })(HapticPreset || (HapticPreset = {}));
10
+ const ANDROID_MIN_VIBRATION_MS = 1001;
11
+ const VIBRATION_PRESETS = new Map([
12
+ [HapticPreset.Light, 30],
13
+ [HapticPreset.Medium, 50],
14
+ [HapticPreset.Heavy, 80],
15
+ [HapticPreset.Success, [20, 50, 20]],
16
+ [HapticPreset.Warning, [40, 30, 40]],
17
+ [HapticPreset.Error, [50, 30, 50, 30, 50]],
18
+ ]);
19
+ const ANDROID_VIBRATION_PRESETS = new Map([
20
+ [HapticPreset.Light, ANDROID_MIN_VIBRATION_MS],
21
+ [HapticPreset.Medium, ANDROID_MIN_VIBRATION_MS],
22
+ [HapticPreset.Heavy, ANDROID_MIN_VIBRATION_MS],
23
+ [HapticPreset.Success, [ANDROID_MIN_VIBRATION_MS, 150, ANDROID_MIN_VIBRATION_MS]],
24
+ [HapticPreset.Warning, [ANDROID_MIN_VIBRATION_MS, 100, ANDROID_MIN_VIBRATION_MS, 100, ANDROID_MIN_VIBRATION_MS]],
25
+ [HapticPreset.Error, [ANDROID_MIN_VIBRATION_MS, 80, ANDROID_MIN_VIBRATION_MS, 80, ANDROID_MIN_VIBRATION_MS, 80, ANDROID_MIN_VIBRATION_MS]],
26
+ ]);
27
+ const IOS_PRESETS = new Map([
28
+ [HapticPreset.Light, [15, 40, 15]],
29
+ [HapticPreset.Medium, [15, 35, 15, 35, 15]],
30
+ [HapticPreset.Heavy, [15, 30, 15, 30, 15, 30, 15]],
31
+ [HapticPreset.Success, [20, 50, 20]],
32
+ [HapticPreset.Warning, [40, 30, 40]],
33
+ [HapticPreset.Error, [50, 30, 50, 30, 50]],
34
+ ]);
35
+ const isAndroid = () => typeof navigator !== "undefined" &&
36
+ /Android/i.test(navigator.userAgent ?? "");
37
+ const getPreset = (variant) => {
38
+ if (!hasVibrationAPI())
39
+ return IOS_PRESETS.get(variant);
40
+ const presets = isAndroid() ? ANDROID_VIBRATION_PRESETS : VIBRATION_PRESETS;
41
+ return presets.get(variant);
8
42
  };
9
43
  const hasVibrationAPI = () => typeof navigator !== "undefined" && typeof navigator.vibrate === "function";
10
44
  const hasDOM = () => typeof document !== "undefined" && !!document.body;
@@ -27,22 +61,22 @@ const fireIOSSwitch = () => {
27
61
  catch {
28
62
  }
29
63
  };
30
- const toPatternArray = (pattern) => Array.isArray(pattern) ? [...pattern] : [pattern];
64
+ const toPatternArray = (pattern) => (Array.isArray(pattern) ? [...pattern] : [pattern]);
31
65
  const trigger = (pattern) => {
32
66
  if (hasVibrationAPI()) {
33
67
  try {
34
- const p = Array.isArray(pattern) ? [...pattern] : pattern;
35
- navigator.vibrate(p);
68
+ const normalized = toPatternArray(pattern);
69
+ const payload = normalized.length === 1 ? normalized[0] : normalized;
70
+ navigator.vibrate(payload);
36
71
  }
37
72
  catch {
38
73
  }
39
74
  return;
40
75
  }
41
76
  const arr = toPatternArray(pattern);
77
+ const pairs = Array.from({ length: Math.ceil(arr.length / 2) }, (_, i) => [arr[i * 2] ?? 0, arr[i * 2 + 1] ?? 0]);
42
78
  let delay = 0;
43
- for (let i = 0; i < arr.length; i += 2) {
44
- const vibrateMs = arr[i] ?? 0;
45
- const pauseMs = arr[i + 1] ?? 0;
79
+ for (const [vibrateMs, pauseMs] of pairs) {
46
80
  if (vibrateMs > 0)
47
81
  setTimeout(fireIOSSwitch, delay);
48
82
  delay += vibrateMs + pauseMs;
@@ -55,12 +89,12 @@ export const isSupported = () => {
55
89
  return hasVibrationAPI() || hasDOM();
56
90
  };
57
91
  export const vibrate = (pattern) => trigger(pattern);
58
- export const light = () => trigger(PRESETS.light);
59
- export const medium = () => trigger(PRESETS.medium);
60
- export const heavy = () => trigger(PRESETS.heavy);
61
- export const success = () => trigger([...PRESETS.success]);
62
- export const warning = () => trigger([...PRESETS.warning]);
63
- export const error = () => trigger([...PRESETS.error]);
92
+ export const light = () => trigger(getPreset(HapticPreset.Light));
93
+ export const medium = () => trigger(getPreset(HapticPreset.Medium));
94
+ export const heavy = () => trigger(getPreset(HapticPreset.Heavy));
95
+ export const success = () => trigger(getPreset(HapticPreset.Success));
96
+ export const warning = () => trigger(getPreset(HapticPreset.Warning));
97
+ export const error = () => trigger(getPreset(HapticPreset.Error));
64
98
  const Haptic = {
65
99
  hasVibration,
66
100
  isSupported,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-haptic",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "Lightweight haptic feedback for web apps. Vibration API (Android) + iOS Safari 17.4+ switch fallback. Zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",