diff --git a/README.md b/README.md
index bdf9a53..b409183 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ npm install tactus
## Usage
+React
```jsx
import { triggerHaptic } from "tactus";
@@ -17,6 +18,12 @@ export default function BuyButton() {
return ;
}
```
+HTML + Vanilla JS
+```html
+
+
+```
+
`triggerHaptic(duration?)` fires one haptic pulse.
- No argument → 100 ms by default
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..03bf118
--- /dev/null
+++ b/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Try Tactus (Haptic feedback)
+
+
+
+
+
+
+
diff --git a/src/constants.d.ts b/src/constants.d.ts
new file mode 100644
index 0000000..a6d2da0
--- /dev/null
+++ b/src/constants.d.ts
@@ -0,0 +1,2 @@
+export declare const HAPTIC_ID = "___haptic-switch___";
+export declare const HAPTIC_DURATION_MS = 10;
diff --git a/src/constants.js b/src/constants.js
new file mode 100644
index 0000000..42dd3ce
--- /dev/null
+++ b/src/constants.js
@@ -0,0 +1,2 @@
+export const HAPTIC_ID = "___haptic-switch___";
+export const HAPTIC_DURATION_MS = 10;
diff --git a/src/haptic.cjs b/src/haptic.cjs
new file mode 100644
index 0000000..a01215c
--- /dev/null
+++ b/src/haptic.cjs
@@ -0,0 +1,65 @@
+'use strict';
+
+const HAPTIC_ID = "___haptic-switch___";
+const HAPTIC_DURATION_MS = 10;
+
+function isIOS$1() {
+ if (typeof navigator === "undefined" || typeof window === "undefined") {
+ return false;
+ }
+ const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);
+ const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
+ return iOSDevice || iPadOS;
+}
+
+let inputElement = null;
+let labelElement = null;
+let isIOS = false;
+// must only be called once
+function mount() {
+ if (labelElement && inputElement)
+ return;
+ isIOS = isIOS$1();
+ inputElement = document.querySelector(`#${HAPTIC_ID}`);
+ labelElement = document.querySelector(`label[for="${HAPTIC_ID}"]`);
+ if (inputElement && labelElement)
+ return;
+ inputElement = document.createElement("input");
+ inputElement.type = "checkbox";
+ inputElement.id = HAPTIC_ID;
+ inputElement.setAttribute("switch", "");
+ inputElement.style.display = "none";
+ document.body.appendChild(inputElement);
+ labelElement = document.createElement("label");
+ labelElement.htmlFor = HAPTIC_ID;
+ labelElement.style.display = "none";
+ document.body.appendChild(labelElement);
+}
+if (typeof window !== "undefined") {
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", mount, {
+ once: true,
+ });
+ }
+ else {
+ mount();
+ }
+}
+function triggerHaptic(duration = HAPTIC_DURATION_MS) {
+ if (typeof window === "undefined")
+ return;
+ if (isIOS) {
+ if (!inputElement || !labelElement)
+ mount();
+ labelElement === null || labelElement === void 0 ? void 0 : labelElement.click();
+ }
+ else {
+ if (navigator === null || navigator === void 0 ? void 0 : navigator.vibrate)
+ navigator.vibrate(duration);
+ else
+ labelElement === null || labelElement === void 0 ? void 0 : labelElement.click();
+ }
+}
+
+exports.triggerHaptic = triggerHaptic;
+//# sourceMappingURL=haptic.cjs.map
diff --git a/src/haptic.cjs.map b/src/haptic.cjs.map
new file mode 100644
index 0000000..e9e463b
--- /dev/null
+++ b/src/haptic.cjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"haptic.cjs","sources":["../../constants.ts","../../utils.ts","../../haptic.ts"],"sourcesContent":["export const HAPTIC_ID = \"___haptic-switch___\";\nexport const HAPTIC_DURATION_MS = 10;\n","export function isIOS(): boolean {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n return false;\n }\n\n const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n const iPadOS =\n navigator.platform === \"MacIntel\" && navigator.maxTouchPoints > 1;\n\n return iOSDevice || iPadOS;\n}\n","import { HAPTIC_ID, HAPTIC_DURATION_MS } from \"./constants\";\nimport { isIOS as isIOSFunction } from \"./utils\";\n\nlet inputElement: HTMLInputElement | null = null;\nlet labelElement: HTMLLabelElement | null = null;\nlet isIOS = false;\n\n// must only be called once\nfunction mount() {\n if (labelElement && inputElement) return;\n\n isIOS = isIOSFunction();\n\n inputElement = document.querySelector(`#${HAPTIC_ID}`);\n labelElement = document.querySelector(\n `label[for=\"${HAPTIC_ID}\"]`\n );\n\n if (inputElement && labelElement) return;\n\n inputElement = document.createElement(\"input\");\n inputElement.type = \"checkbox\";\n inputElement.id = HAPTIC_ID;\n inputElement.setAttribute(\"switch\", \"\");\n inputElement.style.display = \"none\";\n document.body.appendChild(inputElement);\n\n labelElement = document.createElement(\"label\");\n labelElement.htmlFor = HAPTIC_ID;\n labelElement.style.display = \"none\";\n document.body.appendChild(labelElement);\n}\n\nif (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", mount, {\n once: true,\n });\n } else {\n mount();\n }\n}\n\nexport function triggerHaptic(duration = HAPTIC_DURATION_MS) {\n if (typeof window === \"undefined\") return;\n\n if (isIOS) {\n if (!inputElement || !labelElement) mount();\n labelElement?.click();\n } else {\n if (navigator?.vibrate) navigator.vibrate(duration);\n else labelElement?.click();\n }\n}\n"],"names":["isIOS","isIOSFunction"],"mappings":";;AAAO,MAAM,SAAS,GAAG,qBAAqB;AACvC,MAAM,kBAAkB,GAAG,EAAE;;SCDpBA,OAAK,GAAA;IACjB,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACnE,QAAA,OAAO,KAAK;IAChB;IAEA,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;AAE9D,IAAA,MAAM,MAAM,GACR,SAAS,CAAC,QAAQ,KAAK,UAAU,IAAI,SAAS,CAAC,cAAc,GAAG,CAAC;IAErE,OAAO,SAAS,IAAI,MAAM;AAC9B;;ACRA,IAAI,YAAY,GAA4B,IAAI;AAChD,IAAI,YAAY,GAA4B,IAAI;AAChD,IAAI,KAAK,GAAG,KAAK;AAEjB;AACA,SAAS,KAAK,GAAA;IACV,IAAI,YAAY,IAAI,YAAY;QAAE;IAElC,KAAK,GAAGC,OAAa,EAAE;IAEvB,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAmB,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAC;IACxE,YAAY,GAAG,QAAQ,CAAC,aAAa,CACjC,CAAA,WAAA,EAAc,SAAS,CAAA,EAAA,CAAI,CAC9B;IAED,IAAI,YAAY,IAAI,YAAY;QAAE;AAElC,IAAA,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9C,IAAA,YAAY,CAAC,IAAI,GAAG,UAAU;AAC9B,IAAA,YAAY,CAAC,EAAE,GAAG,SAAS;AAC3B,IAAA,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC;AACvC,IAAA,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AACnC,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;AAEvC,IAAA,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9C,IAAA,YAAY,CAAC,OAAO,GAAG,SAAS;AAChC,IAAA,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AACnC,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;AAC3C;AAEA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AAC/B,IAAA,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE;AACnC,QAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,KAAK,EAAE;AACjD,YAAA,IAAI,EAAE,IAAI;AACb,SAAA,CAAC;IACN;SAAO;AACH,QAAA,KAAK,EAAE;IACX;AACJ;AAEM,SAAU,aAAa,CAAC,QAAQ,GAAG,kBAAkB,EAAA;IACvD,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE;IAEnC,IAAI,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY;AAAE,YAAA,KAAK,EAAE;AAC3C,QAAA,YAAY,aAAZ,YAAY,KAAA,MAAA,GAAA,MAAA,GAAZ,YAAY,CAAE,KAAK,EAAE;IACzB;SAAO;AACH,QAAA,IAAI,SAAS,KAAA,IAAA,IAAT,SAAS,KAAA,MAAA,GAAA,MAAA,GAAT,SAAS,CAAE,OAAO;AAAE,YAAA,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;;AAC9C,YAAA,YAAY,aAAZ,YAAY,KAAA,MAAA,GAAA,MAAA,GAAZ,YAAY,CAAE,KAAK,EAAE;IAC9B;AACJ;;;;"}
\ No newline at end of file
diff --git a/src/haptic.d.ts b/src/haptic.d.ts
new file mode 100644
index 0000000..49bf07d
--- /dev/null
+++ b/src/haptic.d.ts
@@ -0,0 +1 @@
+export declare function triggerHaptic(duration?: number): void;
diff --git a/src/haptic.js b/src/haptic.js
new file mode 100644
index 0000000..df2dbcc
--- /dev/null
+++ b/src/haptic.js
@@ -0,0 +1,63 @@
+const HAPTIC_ID = "___haptic-switch___";
+const HAPTIC_DURATION_MS = 10;
+
+function isIOS$1() {
+ if (typeof navigator === "undefined" || typeof window === "undefined") {
+ return false;
+ }
+ const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);
+ const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
+ return iOSDevice || iPadOS;
+}
+
+let inputElement = null;
+let labelElement = null;
+let isIOS = false;
+// must only be called once
+function mount() {
+ if (labelElement && inputElement)
+ return;
+ isIOS = isIOS$1();
+ inputElement = document.querySelector(`#${HAPTIC_ID}`);
+ labelElement = document.querySelector(`label[for="${HAPTIC_ID}"]`);
+ if (inputElement && labelElement)
+ return;
+ inputElement = document.createElement("input");
+ inputElement.type = "checkbox";
+ inputElement.id = HAPTIC_ID;
+ inputElement.setAttribute("switch", "");
+ inputElement.style.display = "none";
+ document.body.appendChild(inputElement);
+ labelElement = document.createElement("label");
+ labelElement.htmlFor = HAPTIC_ID;
+ labelElement.style.display = "none";
+ document.body.appendChild(labelElement);
+}
+if (typeof window !== "undefined") {
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", mount, {
+ once: true,
+ });
+ }
+ else {
+ mount();
+ }
+}
+function triggerHaptic(duration = HAPTIC_DURATION_MS) {
+ if (typeof window === "undefined")
+ return;
+ if (isIOS) {
+ if (!inputElement || !labelElement)
+ mount();
+ labelElement === null || labelElement === void 0 ? void 0 : labelElement.click();
+ }
+ else {
+ if (navigator === null || navigator === void 0 ? void 0 : navigator.vibrate)
+ navigator.vibrate(duration);
+ else
+ labelElement === null || labelElement === void 0 ? void 0 : labelElement.click();
+ }
+}
+
+export { triggerHaptic };
+//# sourceMappingURL=haptic.js.map
diff --git a/src/haptic.js.map b/src/haptic.js.map
new file mode 100644
index 0000000..2a9a59e
--- /dev/null
+++ b/src/haptic.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"haptic.js","sources":["../../constants.ts","../../utils.ts","../../haptic.ts"],"sourcesContent":["export const HAPTIC_ID = \"___haptic-switch___\";\nexport const HAPTIC_DURATION_MS = 10;\n","export function isIOS(): boolean {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n return false;\n }\n\n const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n const iPadOS =\n navigator.platform === \"MacIntel\" && navigator.maxTouchPoints > 1;\n\n return iOSDevice || iPadOS;\n}\n","import { HAPTIC_ID, HAPTIC_DURATION_MS } from \"./constants\";\nimport { isIOS as isIOSFunction } from \"./utils\";\n\nlet inputElement: HTMLInputElement | null = null;\nlet labelElement: HTMLLabelElement | null = null;\nlet isIOS = false;\n\n// must only be called once\nfunction mount() {\n if (labelElement && inputElement) return;\n\n isIOS = isIOSFunction();\n\n inputElement = document.querySelector(`#${HAPTIC_ID}`);\n labelElement = document.querySelector(\n `label[for=\"${HAPTIC_ID}\"]`\n );\n\n if (inputElement && labelElement) return;\n\n inputElement = document.createElement(\"input\");\n inputElement.type = \"checkbox\";\n inputElement.id = HAPTIC_ID;\n inputElement.setAttribute(\"switch\", \"\");\n inputElement.style.display = \"none\";\n document.body.appendChild(inputElement);\n\n labelElement = document.createElement(\"label\");\n labelElement.htmlFor = HAPTIC_ID;\n labelElement.style.display = \"none\";\n document.body.appendChild(labelElement);\n}\n\nif (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", mount, {\n once: true,\n });\n } else {\n mount();\n }\n}\n\nexport function triggerHaptic(duration = HAPTIC_DURATION_MS) {\n if (typeof window === \"undefined\") return;\n\n if (isIOS) {\n if (!inputElement || !labelElement) mount();\n labelElement?.click();\n } else {\n if (navigator?.vibrate) navigator.vibrate(duration);\n else labelElement?.click();\n }\n}\n"],"names":["isIOS","isIOSFunction"],"mappings":"AAAO,MAAM,SAAS,GAAG,qBAAqB;AACvC,MAAM,kBAAkB,GAAG,EAAE;;SCDpBA,OAAK,GAAA;IACjB,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACnE,QAAA,OAAO,KAAK;IAChB;IAEA,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;AAE9D,IAAA,MAAM,MAAM,GACR,SAAS,CAAC,QAAQ,KAAK,UAAU,IAAI,SAAS,CAAC,cAAc,GAAG,CAAC;IAErE,OAAO,SAAS,IAAI,MAAM;AAC9B;;ACRA,IAAI,YAAY,GAA4B,IAAI;AAChD,IAAI,YAAY,GAA4B,IAAI;AAChD,IAAI,KAAK,GAAG,KAAK;AAEjB;AACA,SAAS,KAAK,GAAA;IACV,IAAI,YAAY,IAAI,YAAY;QAAE;IAElC,KAAK,GAAGC,OAAa,EAAE;IAEvB,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAmB,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAC;IACxE,YAAY,GAAG,QAAQ,CAAC,aAAa,CACjC,CAAA,WAAA,EAAc,SAAS,CAAA,EAAA,CAAI,CAC9B;IAED,IAAI,YAAY,IAAI,YAAY;QAAE;AAElC,IAAA,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9C,IAAA,YAAY,CAAC,IAAI,GAAG,UAAU;AAC9B,IAAA,YAAY,CAAC,EAAE,GAAG,SAAS;AAC3B,IAAA,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC;AACvC,IAAA,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AACnC,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;AAEvC,IAAA,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC9C,IAAA,YAAY,CAAC,OAAO,GAAG,SAAS;AAChC,IAAA,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AACnC,IAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;AAC3C;AAEA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AAC/B,IAAA,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE;AACnC,QAAA,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,KAAK,EAAE;AACjD,YAAA,IAAI,EAAE,IAAI;AACb,SAAA,CAAC;IACN;SAAO;AACH,QAAA,KAAK,EAAE;IACX;AACJ;AAEM,SAAU,aAAa,CAAC,QAAQ,GAAG,kBAAkB,EAAA;IACvD,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE;IAEnC,IAAI,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY;AAAE,YAAA,KAAK,EAAE;AAC3C,QAAA,YAAY,aAAZ,YAAY,KAAA,MAAA,GAAA,MAAA,GAAZ,YAAY,CAAE,KAAK,EAAE;IACzB;SAAO;AACH,QAAA,IAAI,SAAS,KAAA,IAAA,IAAT,SAAS,KAAA,MAAA,GAAA,MAAA,GAAT,SAAS,CAAE,OAAO;AAAE,YAAA,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;;AAC9C,YAAA,YAAY,aAAZ,YAAY,KAAA,MAAA,GAAA,MAAA,GAAZ,YAAY,CAAE,KAAK,EAAE;IAC9B;AACJ;;;;"}
\ No newline at end of file
diff --git a/src/index.d.ts b/src/index.d.ts
new file mode 100644
index 0000000..61549cb
--- /dev/null
+++ b/src/index.d.ts
@@ -0,0 +1 @@
+export { triggerHaptic } from "./haptic";
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..61549cb
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1 @@
+export { triggerHaptic } from "./haptic";
diff --git a/src/tactus.min.js b/src/tactus.min.js
new file mode 100644
index 0000000..1105b70
--- /dev/null
+++ b/src/tactus.min.js
@@ -0,0 +1,2 @@
+var Tactus=function(e){"use strict";const t="___haptic-switch___";let n=null,o=null,i=!1;function a(){o&&n||(i=function(){if("undefined"==typeof navigator||"undefined"==typeof window)return!1;const e=/iPad|iPhone|iPod/.test(navigator.userAgent),t="MacIntel"===navigator.platform&&navigator.maxTouchPoints>1;return e||t}(),n=document.querySelector(`#${t}`),o=document.querySelector(`label[for="${t}"]`),n&&o||(n=document.createElement("input"),n.type="checkbox",n.id=t,n.setAttribute("switch",""),n.style.display="none",document.body.appendChild(n),o=document.createElement("label"),o.htmlFor=t,o.style.display="none",document.body.appendChild(o)))}return"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",a,{once:!0}):a()),e.triggerHaptic=function(e=10){"undefined"!=typeof window&&(i?(n&&o||a(),null==o||o.click()):(null===navigator||void 0===navigator?void 0:navigator.vibrate)?navigator.vibrate(e):null==o||o.click())},Object.defineProperty(e,"__esModule",{value:!0}),e}({});
+//# sourceMappingURL=tactus.min.js.map
diff --git a/src/tactus.min.js.map b/src/tactus.min.js.map
new file mode 100644
index 0000000..a878f27
--- /dev/null
+++ b/src/tactus.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tactus.min.js","sources":["../../constants.ts","../../haptic.ts","../../utils.ts"],"sourcesContent":["export const HAPTIC_ID = \"___haptic-switch___\";\nexport const HAPTIC_DURATION_MS = 10;\n","import { HAPTIC_ID, HAPTIC_DURATION_MS } from \"./constants\";\nimport { isIOS as isIOSFunction } from \"./utils\";\n\nlet inputElement: HTMLInputElement | null = null;\nlet labelElement: HTMLLabelElement | null = null;\nlet isIOS = false;\n\n// must only be called once\nfunction mount() {\n if (labelElement && inputElement) return;\n\n isIOS = isIOSFunction();\n\n inputElement = document.querySelector(`#${HAPTIC_ID}`);\n labelElement = document.querySelector(\n `label[for=\"${HAPTIC_ID}\"]`\n );\n\n if (inputElement && labelElement) return;\n\n inputElement = document.createElement(\"input\");\n inputElement.type = \"checkbox\";\n inputElement.id = HAPTIC_ID;\n inputElement.setAttribute(\"switch\", \"\");\n inputElement.style.display = \"none\";\n document.body.appendChild(inputElement);\n\n labelElement = document.createElement(\"label\");\n labelElement.htmlFor = HAPTIC_ID;\n labelElement.style.display = \"none\";\n document.body.appendChild(labelElement);\n}\n\nif (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", mount, {\n once: true,\n });\n } else {\n mount();\n }\n}\n\nexport function triggerHaptic(duration = HAPTIC_DURATION_MS) {\n if (typeof window === \"undefined\") return;\n\n if (isIOS) {\n if (!inputElement || !labelElement) mount();\n labelElement?.click();\n } else {\n if (navigator?.vibrate) navigator.vibrate(duration);\n else labelElement?.click();\n }\n}\n","export function isIOS(): boolean {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n return false;\n }\n\n const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);\n\n const iPadOS =\n navigator.platform === \"MacIntel\" && navigator.maxTouchPoints > 1;\n\n return iOSDevice || iPadOS;\n}\n"],"names":["HAPTIC_ID","inputElement","labelElement","isIOS","mount","navigator","window","iOSDevice","test","userAgent","iPadOS","platform","maxTouchPoints","isIOSFunction","document","querySelector","createElement","type","id","setAttribute","style","display","body","appendChild","htmlFor","readyState","addEventListener","once","duration","click","vibrate"],"mappings":"oCAAO,MAAMA,EAAY,sBCGzB,IAAIC,EAAwC,KACxCC,EAAwC,KACxCC,GAAQ,EAGZ,SAASC,IACDF,GAAgBD,IAEpBE,aCVA,GAAyB,oBAAdE,WAA+C,oBAAXC,OAC3C,OAAO,EAGX,MAAMC,EAAY,mBAAmBC,KAAKH,UAAUI,WAE9CC,EACqB,aAAvBL,UAAUM,UAA2BN,UAAUO,eAAiB,EAEpE,OAAOL,GAAaG,CACxB,CDAYG,GAERZ,EAAea,SAASC,cAAgC,IAAIf,KAC5DE,EAAeY,SAASC,cACpB,cAAcf,OAGdC,GAAgBC,IAEpBD,EAAea,SAASE,cAAc,SACtCf,EAAagB,KAAO,WACpBhB,EAAaiB,GAAKlB,EAClBC,EAAakB,aAAa,SAAU,IACpClB,EAAamB,MAAMC,QAAU,OAC7BP,SAASQ,KAAKC,YAAYtB,GAE1BC,EAAeY,SAASE,cAAc,SACtCd,EAAasB,QAAUxB,EACvBE,EAAakB,MAAMC,QAAU,OAC7BP,SAASQ,KAAKC,YAAYrB,IAC9B,OAEsB,oBAAXI,SACqB,YAAxBQ,SAASW,WACTX,SAASY,iBAAiB,mBAAoBtB,EAAO,CACjDuB,MAAM,IAGVvB,qBAIQ,SAAcwB,ED1CI,IC2CR,oBAAXtB,SAEPH,GACKF,GAAiBC,GAAcE,IACpCF,SAAAA,EAAc2B,UAEV,OAAAxB,gBAAA,IAAAA,eAAA,EAAAA,UAAWyB,SAASzB,UAAUyB,QAAQF,GACrC1B,SAAAA,EAAc2B,QAE3B"}
\ No newline at end of file
diff --git a/src/utils.d.ts b/src/utils.d.ts
new file mode 100644
index 0000000..830daa0
--- /dev/null
+++ b/src/utils.d.ts
@@ -0,0 +1 @@
+export declare function isIOS(): boolean;
diff --git a/src/utils.js b/src/utils.js
new file mode 100644
index 0000000..a0b805a
--- /dev/null
+++ b/src/utils.js
@@ -0,0 +1,8 @@
+export function isIOS() {
+ if (typeof navigator === "undefined" || typeof window === "undefined") {
+ return false;
+ }
+ const iOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent);
+ const iPadOS = navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
+ return iOSDevice || iPadOS;
+}