@myrasec/eu-captcha-vue 0.0.1 → 0.0.3

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 CHANGED
@@ -1,35 +1,88 @@
1
- This package provides an easy integration of Myra Security's EU Captcha for vuejs 3.
1
+ This package provides an easy integration of EU CAPTCHA from Myra Security for Vue 3 and Nuxt.
2
2
 
3
- Get your sitekey on [EU-Captcha.eu](https://www.eu-captcha.eu/).
3
+ For full documentation see **[docs.eu-captcha.eu](https://docs.eu-captcha.eu/)**. [Sign up for free](https://app.eu-captcha.eu/user-registration).
4
4
 
5
5
  ## Installation
6
6
 
7
- (0) npm i @myrasec/eu-captcha-vue
7
+ ```bash
8
+ npm i @myrasec/eu-captcha-vue
9
+ ```
8
10
 
9
- (1) In your code add:
11
+ ## Basic usage
10
12
 
11
- ```
13
+ ```vue
14
+ <script setup>
12
15
  import { EuCaptcha, isEuCaptchaDone } from "@myrasec/eu-captcha-vue";
13
16
 
14
- // use the public sitekey you find in the customer's backend here.
15
- const captchaSitekey = "YOUR-SITEKEY-HERE";
17
+ const captchaSitekey = "EUCAPTCHA_SITE_KEY";
18
+ </script>
19
+
20
+ <template>
21
+ <form @submit.prevent="handleSubmit">
22
+ <!-- your fields -->
23
+ <EuCaptcha :sitekey="captchaSitekey" />
24
+ <button type="submit">Submit</button>
25
+ </form>
26
+ </template>
16
27
  ```
17
28
 
18
- (2) And then render the widget using the following syntax:
29
+ You can test the integration using any fake sitekey. If a sitekey does not exist, the captcha runs with default parameters which allow traffic to pass.
30
+
31
+ ## Props
32
+
33
+ | Prop | Type | Default | Description |
34
+ |---|---|---|---|
35
+ | `sitekey` | `string` | — | Your public sitekey (required) |
36
+ | `theme` | `string` | `"light"` | Visual theme: `"light"` or `"dark"` |
37
+ | `width` | `number` | `330` | Widget width in pixels |
38
+ | `widgetId` | `string` | — | Custom widget ID. If omitted, an ID is auto-generated. Needed when calling `euCaptcha.execute()`. |
39
+ | `autostart` | `boolean` | `true` | Start the challenge automatically on mount. Set to `false` to defer until `euCaptcha.execute(widgetId)` is called. |
40
+ | `onComplete` | `(token: string) => void` | — | Called with the encoded token when the challenge completes. |
41
+ | `onExpired` | `() => void` | — | Called when the token expires (60 minutes after completion). |
42
+ | `onError` | `() => void` | — | Called when the challenge fails due to a network or server error. |
19
43
 
44
+ ## Dark theme
45
+
46
+ ```vue
47
+ <EuCaptcha :sitekey="captchaSitekey" theme="dark" />
20
48
  ```
21
- <EuCaptcha sitekey={captchaSitekey} />
49
+
50
+ ## Custom width
51
+
52
+ ```vue
53
+ <EuCaptcha :sitekey="captchaSitekey" :width="280" />
22
54
  ```
23
55
 
24
- You can test the integration using any fake sitekey. If a sitekey
25
- does not exist, then the captcha runs with default parameters which
26
- allow traffic to pass.
56
+ ## Deferred execution
27
57
 
28
- ## Querying state
58
+ Set `:autostart="false"` and provide a `widgetId`, then trigger the challenge manually:
29
59
 
30
- Before submitting a form to a server, please ensure that EuCaptcha is done.
60
+ ```vue
61
+ <EuCaptcha
62
+ :sitekey="captchaSitekey"
63
+ widget-id="my-captcha"
64
+ :autostart="false"
65
+ />
31
66
 
67
+ <button @click="euCaptcha.execute('my-captcha')">Verify</button>
32
68
  ```
69
+
70
+ ## Callbacks
71
+
72
+ ```vue
73
+ <EuCaptcha
74
+ :sitekey="captchaSitekey"
75
+ :on-complete="(token) => console.log('token:', token)"
76
+ :on-expired="() => console.log('token expired')"
77
+ :on-error="() => console.log('challenge error')"
78
+ />
79
+ ```
80
+
81
+ ## Querying state
82
+
83
+ Before submitting a form to a server, ensure EU CAPTCHA is done:
84
+
85
+ ```js
33
86
  import { isEuCaptchaDone } from "@myrasec/eu-captcha-vue";
34
87
 
35
88
  function onSubmit(e) {
@@ -37,7 +90,6 @@ function onSubmit(e) {
37
90
 
38
91
  if (!isEuCaptchaDone()) {
39
92
  // computation has not been completed
40
-
41
93
  return;
42
94
  }
43
95
  }
@@ -45,16 +97,17 @@ function onSubmit(e) {
45
97
 
46
98
  ## Listening to state change
47
99
 
48
- Additionally, a message will be posted to the main window with msg.data.type
49
- set to 'euCaptchaDone', in case you want to be informed actively to change
50
- e.g. the state of a button.
100
+ Listen for the `euCaptchaDone` window message to be notified when the challenge completes:
51
101
 
52
- ```
53
- function listenForCaptchaDone(msg: MessageEvent) {
54
- if (msg.data.type === 'euCaptchaDone') {
55
- // change the state of the form, etc.
102
+ ```js
103
+ import { onMounted, onUnmounted } from "vue";
104
+
105
+ function listenForCaptchaDone(msg) {
106
+ if (msg.data.type === "euCaptchaDone") {
107
+ // enable submit button, update reactive state, etc.
56
108
  }
57
109
  }
58
110
 
59
- window.addEventListener("message", listenForCaptchaDone, false);
111
+ onMounted(() => window.addEventListener("message", listenForCaptchaDone, false));
112
+ onUnmounted(() => window.removeEventListener("message", listenForCaptchaDone, false));
60
113
  ```
@@ -1,70 +1,83 @@
1
- import { ref as d, createElementBlock as f, openBlock as m } from "vue";
2
- let o = {
1
+ import { ref as E, createElementBlock as C, openBlock as p } from "vue";
2
+ let r = {
3
3
  sitekey: "-",
4
4
  locale: "",
5
- theme: "light"
6
- }, l = {
5
+ theme: "light",
6
+ width: 330
7
+ }, f = {
7
8
  done: !1,
8
9
  registered: !1
9
- }, i = null;
10
- function h(e) {
11
- return typeof window > "u" ? Promise.reject("Cannot load script on server") : i || (i = new Promise((t, r) => {
10
+ }, l = null;
11
+ function k(e) {
12
+ return typeof window > "u" ? Promise.reject("Cannot load script on server") : l || (l = new Promise((t, i) => {
12
13
  if (document.querySelector(`script[src="${e}"]`)) {
13
14
  t();
14
15
  return;
15
16
  }
16
17
  const n = document.createElement("script");
17
- n.src = e, n.async = !0, n.onload = () => t(), n.onerror = () => r(new Error(`Failed to load ${e}`)), document.head.appendChild(n);
18
- }), i);
18
+ n.src = e, n.async = !0, n.onload = () => t(), n.onerror = () => i(new Error(`Failed to load ${e}`)), document.head.appendChild(n);
19
+ }), l);
19
20
  }
20
- function p(e) {
21
- e.data.type === "euCaptchaCompleted" && (l.done = !0);
21
+ function _(e) {
22
+ e.data.type === "euCaptchaCompleted" && (f.done = !0);
22
23
  }
23
- function $() {
24
- return l.done;
24
+ function S() {
25
+ return f.done;
25
26
  }
26
- function y(e, t) {
27
- e = e || {}, typeof e.sitekey == "string" && (o.sitekey = e.sitekey), typeof e.locale == "string" && (o.locale = e.locale), typeof e.theme == "string" && (o.theme = e.theme), h("https://cdn.eu-captcha.eu/verify.js").then(() => {
28
- l.registered || (l.registered = !0, window.addEventListener("message", p, !1)), t && t();
29
- }).catch((r) => {
30
- console.error("error during load of eu captcha library: " + r);
27
+ function v(e, t) {
28
+ e = e || {}, typeof e.sitekey == "string" && (r.sitekey = e.sitekey), typeof e.locale == "string" && (r.locale = e.locale), typeof e.theme == "string" && (r.theme = e.theme), typeof e.width == "number" && (r.width = e.width), k("https://cdn.eu-captcha.eu/verify.js").then(() => {
29
+ f.registered || (f.registered = !0, window.addEventListener("message", _, !1)), t && t();
30
+ }).catch((i) => {
31
+ console.error("error during load of eu captcha library: " + i);
31
32
  });
32
33
  }
33
- let c = null, s = null;
34
- const u = d("");
35
- function g() {
36
- u.value = window.getEuCaptchaElement(
37
- c ?? o.sitekey,
38
- s ?? o.theme
34
+ let m = null, h = null, w = null, c = null, y = !0, a = null, d = null, u = null, o = null;
35
+ const g = E("");
36
+ function x() {
37
+ g.value = window.getEuCaptchaElement(
38
+ m ?? r.sitekey,
39
+ h ?? r.theme,
40
+ w ?? r.width,
41
+ c ?? void 0,
42
+ y
39
43
  );
40
44
  }
41
- const k = {
42
- props: ["sitekey", "theme"],
45
+ const b = {
46
+ props: ["sitekey", "theme", "width", "widgetId", "autostart", "onComplete", "onExpired", "onError"],
43
47
  setup(e) {
44
- e.sitekey && (c = e.sitekey), e.theme && (s = e.theme);
48
+ e.sitekey && (m = e.sitekey), e.theme && (h = e.theme), e.width && (w = e.width), e.widgetId && (c = e.widgetId), typeof e.autostart == "boolean" && (y = e.autostart), e.onComplete && (a = e.onComplete), e.onExpired && (d = e.onExpired), e.onError && (u = e.onError);
45
49
  },
46
50
  data() {
47
- return y(null, g), {
48
- htmlContent: u
51
+ return v(null, x), {
52
+ htmlContent: g
49
53
  };
54
+ },
55
+ mounted() {
56
+ !a && !d && !u || (o = (e) => {
57
+ const t = e.data ?? {};
58
+ c && t.widgetId !== c || (t.type === "euCaptchaCompleted" && a && a(t.payload ?? ""), t.type === "euCaptchaExpired" && d && d(), t.type === "euCaptchaError" && u && u());
59
+ }, window.addEventListener("message", o, !1));
60
+ },
61
+ unmounted() {
62
+ o && (window.removeEventListener("message", o, !1), o = null);
50
63
  }
51
- }, _ = (e, t) => {
52
- const r = e.__vccOpts || e;
53
- for (const [n, a] of t)
54
- r[n] = a;
55
- return r;
56
- }, C = ["innerHTML"];
57
- function E(e, t, r, n, a, v) {
58
- return m(), f("div", { innerHTML: a.htmlContent }, null, 8, C);
64
+ }, L = (e, t) => {
65
+ const i = e.__vccOpts || e;
66
+ for (const [n, s] of t)
67
+ i[n] = s;
68
+ return i;
69
+ }, I = ["innerHTML"];
70
+ function $(e, t, i, n, s, M) {
71
+ return p(), C("div", { innerHTML: s.htmlContent }, null, 8, I);
59
72
  }
60
- const w = /* @__PURE__ */ _(k, [["render", E]]), x = {
73
+ const H = /* @__PURE__ */ L(b, [["render", $]]), j = {
61
74
  install: (e) => {
62
- e.component("b-upload-files-modal", w);
75
+ e.component("b-upload-files-modal", H);
63
76
  }
64
77
  };
65
78
  export {
66
- w as EuCaptcha,
67
- x as default,
68
- $ as isEuCaptchaDone,
69
- y as loadEuCaptcha
79
+ H as EuCaptcha,
80
+ j as default,
81
+ S as isEuCaptchaDone,
82
+ v as loadEuCaptcha
70
83
  };
@@ -1 +1 @@
1
- (function(t,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],o):(t=typeof globalThis<"u"?globalThis:t||self,o(t["@myra/eu-captcha-vue"]={},t.Vue))})(this,(function(t,o){"use strict";let a={sitekey:"-",locale:"",theme:"light"},c={done:!1,registered:!1},l=null;function p(e){return typeof window>"u"?Promise.reject("Cannot load script on server"):l||(l=new Promise((n,r)=>{if(document.querySelector(`script[src="${e}"]`)){n();return}const i=document.createElement("script");i.src=e,i.async=!0,i.onload=()=>n(),i.onerror=()=>r(new Error(`Failed to load ${e}`)),document.head.appendChild(i)}),l)}function y(e){e.data.type==="euCaptchaCompleted"&&(c.done=!0)}function g(){return c.done}function s(e,n){e=e||{},typeof e.sitekey=="string"&&(a.sitekey=e.sitekey),typeof e.locale=="string"&&(a.locale=e.locale),typeof e.theme=="string"&&(a.theme=e.theme),p("https://cdn.eu-captcha.eu/verify.js").then(()=>{c.registered||(c.registered=!0,window.addEventListener("message",y,!1)),n&&n()}).catch(r=>{console.error("error during load of eu captcha library: "+r)})}let d=null,f=null;const h=o.ref("");function _(){h.value=window.getEuCaptchaElement(d??a.sitekey,f??a.theme)}const C={props:["sitekey","theme"],setup(e){e.sitekey&&(d=e.sitekey),e.theme&&(f=e.theme)},data(){return s(null,_),{htmlContent:h}}},E=(e,n)=>{const r=e.__vccOpts||e;for(const[i,u]of n)r[i]=u;return r},k=["innerHTML"];function v(e,n,r,i,u,b){return o.openBlock(),o.createElementBlock("div",{innerHTML:u.htmlContent},null,8,k)}const m=E(C,[["render",v]]),w={install:e=>{e.component("b-upload-files-modal",m)}};t.EuCaptcha=m,t.default=w,t.isEuCaptchaDone=g,t.loadEuCaptcha=s,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
1
+ (function(n,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],o):(n=typeof globalThis<"u"?globalThis:n||self,o(n["@myra/eu-captcha-vue"]={},n.Vue))})(this,(function(n,o){"use strict";let r={sitekey:"-",locale:"",theme:"light",width:330},d={done:!1,registered:!1},u=null;function _(e){return typeof window>"u"?Promise.reject("Cannot load script on server"):u||(u=new Promise((t,l)=>{if(document.querySelector(`script[src="${e}"]`)){t();return}const i=document.createElement("script");i.src=e,i.async=!0,i.onload=()=>t(),i.onerror=()=>l(new Error(`Failed to load ${e}`)),document.head.appendChild(i)}),u)}function k(e){e.data.type==="euCaptchaCompleted"&&(d.done=!0)}function b(){return d.done}function y(e,t){e=e||{},typeof e.sitekey=="string"&&(r.sitekey=e.sitekey),typeof e.locale=="string"&&(r.locale=e.locale),typeof e.theme=="string"&&(r.theme=e.theme),typeof e.width=="number"&&(r.width=e.width),_("https://cdn.eu-captcha.eu/verify.js").then(()=>{d.registered||(d.registered=!0,window.addEventListener("message",k,!1)),t&&t()}).catch(l=>{console.error("error during load of eu captcha library: "+l)})}let w=null,E=null,g=null,c=null,p=!0,f=null,s=null,h=null,a=null;const C=o.ref("");function x(){C.value=window.getEuCaptchaElement(w??r.sitekey,E??r.theme,g??r.width,c??void 0,p)}const L={props:["sitekey","theme","width","widgetId","autostart","onComplete","onExpired","onError"],setup(e){e.sitekey&&(w=e.sitekey),e.theme&&(E=e.theme),e.width&&(g=e.width),e.widgetId&&(c=e.widgetId),typeof e.autostart=="boolean"&&(p=e.autostart),e.onComplete&&(f=e.onComplete),e.onExpired&&(s=e.onExpired),e.onError&&(h=e.onError)},data(){return y(null,x),{htmlContent:C}},mounted(){!f&&!s&&!h||(a=e=>{const t=e.data??{};c&&t.widgetId!==c||(t.type==="euCaptchaCompleted"&&f&&f(t.payload??""),t.type==="euCaptchaExpired"&&s&&s(),t.type==="euCaptchaError"&&h&&h())},window.addEventListener("message",a,!1))},unmounted(){a&&(window.removeEventListener("message",a,!1),a=null)}},I=(e,t)=>{const l=e.__vccOpts||e;for(const[i,m]of t)l[i]=m;return l},M=["innerHTML"];function S(e,t,l,i,m,$){return o.openBlock(),o.createElementBlock("div",{innerHTML:m.htmlContent},null,8,M)}const v=I(L,[["render",S]]),T={install:e=>{e.component("b-upload-files-modal",v)}};n.EuCaptcha=v,n.default=T,n.isEuCaptchaDone=b,n.loadEuCaptcha=y,Object.defineProperties(n,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myrasec/eu-captcha-vue",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/eu-captcha-vue.umd.cjs",
package/publish.sh ADDED
@@ -0,0 +1,5 @@
1
+ #! /bin/sh
2
+
3
+ npm run build || exit 1
4
+
5
+ npm publish --public