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; +}