ablok-components 0.3.124 → 0.3.127

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.
@@ -44,6 +44,7 @@ declare const __VLS_export: import('../../../../vue/dist/vue.esm-bundler.js').De
44
44
  mailto: boolean;
45
45
  clipboard: boolean;
46
46
  bluesky: boolean;
47
+ os: boolean;
47
48
  };
48
49
  };
49
50
  }>, {}, {}, {}, {}, import('../../../../vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../../../vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {}, string, import('../../../../vue/dist/vue.esm-bundler.js').PublicProps, Readonly<import('../../../../vue/dist/vue.esm-bundler.js').ExtractPropTypes<{
@@ -89,6 +90,7 @@ declare const __VLS_export: import('../../../../vue/dist/vue.esm-bundler.js').De
89
90
  mailto: boolean;
90
91
  clipboard: boolean;
91
92
  bluesky: boolean;
93
+ os: boolean;
92
94
  };
93
95
  };
94
96
  }>> & Readonly<{}>, {
@@ -26,9 +26,12 @@ var f = { class: "link-sharing" }, p = {
26
26
  key: 6,
27
27
  class: "col-12 col-md-6"
28
28
  }, M = ["href"], N = { class: "caption" }, P = {
29
+ key: 7,
30
+ class: "col-12 col-md-6"
31
+ }, F = { class: "caption" }, I = {
29
32
  key: 1,
30
33
  class: "link-sharing__instructions pt-5"
31
- }, F = { class: "row" }, I = { class: "col-12 text-center py-0" }, L = { class: "mb-5" }, R = (e) => e.replace(/<(?:.|\n)*?>/gm, ""), z = /*@__PURE__*/ s({
34
+ }, L = { class: "row" }, R = { class: "col-12 text-center py-0" }, z = { class: "mb-5" }, B = (e) => e.replace(/<(?:.|\n)*?>/gm, ""), V = /*@__PURE__*/ s({
32
35
  __name: "link-sharing",
33
36
  props: {
34
37
  url: {
@@ -57,69 +60,87 @@ var f = { class: "link-sharing" }, p = {
57
60
  whatsapp: !0,
58
61
  mailto: !0,
59
62
  clipboard: !0,
60
- bluesky: !0
63
+ bluesky: !0,
64
+ os: !0
61
65
  }
62
66
  }
63
67
  },
64
68
  setup(s) {
65
- let z = s, B = l(!1), V = t(() => encodeURIComponent(z.url));
66
- t(() => encodeURIComponent(z.media));
67
- let H = t(() => R(z.text)), U = t(() => !!(navigator && navigator.userAgent && /Mobi|Android/i.test(navigator.userAgent)));
68
- async function W() {
69
+ let V = s, H = l(!1), U = t(() => encodeURIComponent(V.url));
70
+ t(() => encodeURIComponent(V.media));
71
+ let W = t(() => B(V.text)), G = t(() => !!(navigator && navigator.userAgent && /Mobi|Android/i.test(navigator.userAgent))), K = t(() => !!(navigator && navigator.canShare));
72
+ async function q() {
69
73
  let e = document.createElement("textarea");
70
- document.body.appendChild(e), e.value = z.url, e.select(), e.setSelectionRange(0, 99999), navigator.clipboard.writeText(e.value), document.body.removeChild(e);
74
+ document.body.appendChild(e), e.value = V.url, e.select(), e.setSelectionRange(0, 99999), navigator.clipboard.writeText(e.value), document.body.removeChild(e);
75
+ }
76
+ async function J() {
77
+ if (K.value) {
78
+ let e = {
79
+ title: V.subject,
80
+ text: W.value,
81
+ url: V.url
82
+ };
83
+ await navigator.canShare(e) && await navigator.share(e).catch((e) => {
84
+ console.log("shareError", e);
85
+ });
86
+ }
71
87
  }
72
- return (t, l) => (c(), r("div", f, [B.value ? (c(), r("div", P, [i("div", F, [i("div", I, [i("div", L, [
88
+ return (t, l) => (c(), r("div", f, [H.value ? (c(), r("div", I, [i("div", L, [i("div", R, [i("div", z, [
73
89
  i("p", null, u(t.$t("sharing.instructions", { service: "Instagram" })), 1),
74
90
  i("p", null, [i("strong", null, u(Array.isArray(s.hashtags) ? s.hashtags.join(", ") : s.hashtags), 1)]),
75
91
  i("button", {
76
92
  type: "button",
77
93
  class: "btn btn-text",
78
- onClick: l[1] ||= d((e) => B.value = !B.value, ["prevent"])
94
+ onClick: l[1] ||= d((e) => H.value = !H.value, ["prevent"])
79
95
  }, [o(e, { symbol: "arrow-left" }), a(" " + u(t.$t("common.back")), 1)])
80
96
  ])])])])) : (c(), r("div", p, [i("div", m, [
81
97
  s.services.facebook ? (c(), r("div", h, [i("a", {
82
98
  class: "link-sharing__link btn btn-primary",
83
- href: `https://www.facebook.com/sharer/sharer.php?u=${V.value}`,
99
+ href: `https://www.facebook.com/sharer/sharer.php?u=${U.value}`,
84
100
  target: "_blank",
85
101
  rel: "noopener"
86
102
  }, [o(e, { symbol: "facebook" }), i("span", _, u(t.$t("sharing.facebook")), 1)], 8, g)])) : n("", !0),
87
103
  s.services.bluesky ? (c(), r("div", v, [i("a", {
88
104
  class: "link-sharing__link btn btn-primary",
89
- href: `https://bsky.app/intent/compose?text=${H.value}${H.value ? "%20" : ""}${s.url}`,
105
+ href: `https://bsky.app/intent/compose?text=${W.value}${W.value ? "%20" : ""}${s.url}`,
90
106
  target: "_blank",
91
107
  rel: "noopener"
92
108
  }, [o(e, { symbol: "bluesky-logo" }), i("span", b, u(t.$t("sharing.bluesky")), 1)], 8, y)])) : n("", !0),
93
109
  s.services.instagram ? (c(), r("div", x, [i("button", {
94
110
  type: "button",
95
111
  class: "link-sharing__link btn btn-primary",
96
- onClick: l[0] ||= d((e) => B.value = !B.value, ["prevent"])
112
+ onClick: l[0] ||= d((e) => H.value = !H.value, ["prevent"])
97
113
  }, [o(e, { symbol: "instagram" }), i("span", S, u(t.$t("sharing.instagram")), 1)])])) : n("", !0),
98
114
  s.services.linkedin ? (c(), r("div", C, [i("a", {
99
115
  class: "link-sharing__link btn btn-primary",
100
- href: `https://www.linkedin.com/shareArticle?mini=true&url=${V.value}&title=${s.subject}`,
116
+ href: `https://www.linkedin.com/shareArticle?mini=true&url=${U.value}&title=${s.subject}`,
101
117
  target: "_blank",
102
118
  rel: "noopener"
103
119
  }, [o(e, { symbol: "linkedin" }), i("span", T, u(t.$t("sharing.linkedin")), 1)], 8, w)])) : n("", !0),
104
- s.services.whatsapp && U.value ? (c(), r("div", E, [i("a", {
120
+ s.services.whatsapp && G.value ? (c(), r("div", E, [i("a", {
105
121
  class: "link-sharing__link btn btn-primary",
106
- href: `whatsapp://send?text=${V.value}`,
122
+ href: `whatsapp://send?text=${U.value}`,
107
123
  target: "_blank",
108
124
  rel: "noopener"
109
125
  }, [o(e, { symbol: "whatsapp" }), i("span", O, u(t.$t("sharing.whatsapp")), 1)], 8, D)])) : n("", !0),
110
126
  s.services.clipboard ? (c(), r("div", k, [i("button", {
111
127
  type: "button",
112
128
  class: "link-sharing__link btn btn-primary",
113
- onClick: d(W, ["prevent", "stop"])
129
+ onClick: d(q, ["prevent", "stop"])
114
130
  }, [o(e, { symbol: "copy" }), i("span", A, u(t.$t("sharing.clipboard")), 1)])])) : n("", !0),
115
131
  s.services.mailto ? (c(), r("div", j, [i("a", {
116
132
  class: "link-sharing__link btn btn-primary",
117
- href: `mailto:?subject=${s.subject}&body=${H.value}%0D%0A${s.url}`,
133
+ href: `mailto:?subject=${s.subject}&body=${W.value}%0D%0A${s.url}`,
118
134
  target: "_blank",
119
135
  rel: "noopener"
120
- }, [o(e, { symbol: "mail" }), i("span", N, u(t.$t("sharing.mailto")), 1)], 8, M)])) : n("", !0)
136
+ }, [o(e, { symbol: "mail" }), i("span", N, u(t.$t("sharing.mailto")), 1)], 8, M)])) : n("", !0),
137
+ s.services.os && K.value ? (c(), r("div", P, [i("button", {
138
+ type: "button",
139
+ class: "link-sharing__link btn btn-primary",
140
+ onClick: d(J, ["prevent"])
141
+ }, [o(e, { symbol: "share" }), i("span", F, u(t.$t("sharing.os")), 1)])])) : n("", !0)
121
142
  ])]))]));
122
143
  }
123
144
  });
124
145
  //#endregion
125
- export { z as default, R as stripHtml };
146
+ export { V as default, B as stripHtml };
@@ -0,0 +1,34 @@
1
+ export interface CaptureOptions {
2
+ /** Target canvas dimensions; falls back to the source video dimensions. */
3
+ targetResolution?: {
4
+ width: number;
5
+ height: number;
6
+ } | undefined;
7
+ /** True when the target ratio was explicitly requested (else derive height from source ratio). */
8
+ hasExplicitRatio: boolean;
9
+ /** Crop to the target ratio (cover) instead of letterboxing (contain). */
10
+ enableCropImage: boolean;
11
+ /** Digital zoom factor (1 = none). */
12
+ zoom: number;
13
+ /** Front-camera mirroring — flip horizontally. */
14
+ mirror: boolean;
15
+ /** Portrait-upright correction rotation (0/90/180/270), from useOrientationCorrection. */
16
+ captureRotation: number;
17
+ /** Called with the resulting PNG data URL. */
18
+ onSave: (dataUrl: string) => void;
19
+ }
20
+ /**
21
+ * Captures the current video frame onto the canvas, honouring ratio cropping,
22
+ * zoom, mirroring and device-orientation rotation. Pure drawing logic — no
23
+ * reactivity, trivially unit-testable.
24
+ */
25
+ export declare function captureFrame(canvas: HTMLCanvasElement, image: HTMLVideoElement, options: CaptureOptions): void;
26
+ /** Runs the canvas-capture pipeline (drawing + optional post-filter) and returns the PNG data URL. */
27
+ export declare function captureToDataUrl(canvas: HTMLCanvasElement, image: HTMLVideoElement, options: CaptureOptions, applyFilter?: (context: CanvasRenderingContext2D, width: number, height: number) => void): string;
28
+ /** Converts a captured data URL into the emitted photo payload. */
29
+ export declare function toPhotoPayload(dataUrl: string): {
30
+ name: string;
31
+ id: string;
32
+ blob: Blob;
33
+ size: number;
34
+ };
@@ -0,0 +1,53 @@
1
+ import { dataURItoBlob as e } from "../utilities/helpers.js";
2
+ //#region src/composables/useCameraCapture.ts
3
+ function t(e, t, n, r, i, a, o) {
4
+ let s = e.canvas.width, c = e.canvas.height;
5
+ e.translate(s / 2, c / 2), o && e.scale(-1, 1), e.rotate(n * Math.PI / 180);
6
+ let l = c, u = s, d = Math.max(l / r, u / i) * (a && a > 0 ? a : 1), f = r * d, p = i * d;
7
+ e.drawImage(t, -f / 2, -p / 2, f, p);
8
+ }
9
+ function n(e, n, r) {
10
+ let i = e.getContext("2d");
11
+ if (!i) return;
12
+ let a = n.srcObject instanceof MediaStream ? n.srcObject.getTracks() : [], { aspectRatio: o, width: s, height: c } = a.length ? a[0].getSettings() : {}, l = n?.videoWidth || s || 0, u = n?.videoHeight || c || 0, d = l && u ? l / u : o, f = r.targetResolution || {
13
+ width: l,
14
+ height: u
15
+ }, p = f?.width || l, m = r.hasExplicitRatio ? f?.height || u : Math.round(p / (d || 1)), h = p / m;
16
+ if (e.width = p, e.height = m, !l || !u || !d) return;
17
+ let g = r.zoom, _ = r.mirror;
18
+ if (i.save(), r.captureRotation === 90 || r.captureRotation === 270) {
19
+ t(i, n, r.captureRotation, l, u, g, _), i.restore();
20
+ return;
21
+ }
22
+ if (r.captureRotation === 180 && (i.translate(e.width, e.height), i.scale(-1, -1)), _ && (i.translate(e.width, 0), i.scale(-1, 1)), r.enableCropImage) {
23
+ let t = 0, r = 0, a = l, o = u;
24
+ if (d > h ? (a = u * h, t = (l - a) / 2) : d < h && (o = l / h, r = (u - o) / 2), g && g !== 1) {
25
+ let e = a / g, n = o / g;
26
+ t += (a - e) / 2, r += (o - n) / 2, a = e, o = n;
27
+ }
28
+ i.drawImage(n, t, r, a, o, 0, 0, e.width, e.height);
29
+ } else {
30
+ let t = e.width, r = e.height, a = 0, o = 0;
31
+ if (d > h ? (r = e.width / d, o = (e.height - r) / 2) : d < h && (t = e.height * d, a = (e.width - t) / 2), g && g !== 1) {
32
+ let s = l / g, c = u / g, d = (l - s) / 2, f = (u - c) / 2;
33
+ _ && (a = e.width - a - t), i.drawImage(n, d, f, s, c, a, o, t, r);
34
+ } else _ && (a = e.width - a - t), i.drawImage(n, 0, 0, l, u, a, o, t, r);
35
+ }
36
+ i.restore();
37
+ }
38
+ function r(e, t, r, i) {
39
+ n(e, t, r);
40
+ let a = e.getContext("2d");
41
+ return a && i && i(a, e.width, e.height), e.toDataURL("image/png");
42
+ }
43
+ function i(t) {
44
+ let n = e(t), r = `cam-pic-${(/* @__PURE__ */ new Date()).toISOString()}`;
45
+ return {
46
+ name: r,
47
+ id: r,
48
+ blob: n,
49
+ size: n.size
50
+ };
51
+ }
52
+ //#endregion
53
+ export { n as captureFrame, r as captureToDataUrl, i as toPhotoPayload };
@@ -0,0 +1,27 @@
1
+ import { ComputedRef, Ref } from '../../vue/dist/vue.esm-bundler.js';
2
+ /**
3
+ * Device-orientation correction for rotation-locked pages.
4
+ *
5
+ * When the page is rotation-locked, the OS bakes a portrait-up OR portrait-down
6
+ * (0°/180°) orientation into the camera buffer based on gravity. That affects the
7
+ * preview AND the captured canvas identically. `orientationFlip` is true only while
8
+ * the device is actually held in landscape (in-plane gravity near ±90°), where the
9
+ * buffer arrives upside-down relative to the device frame; the preview counter-rotates
10
+ * with a 180° rotation. Portrait-up and portrait-down are left untouched. Hysteresis
11
+ * around the band edges prevents flicker.
12
+ *
13
+ * `previewReady` gates the preview until the correction is live (motion permission
14
+ * granted + first sensor reading applied). A safety timeout prevents the preview
15
+ * from being blocked forever if permission is denied or never granted.
16
+ */
17
+ export declare function useOrientationCorrection(enabled: () => boolean): {
18
+ motionEnabled: Ref<boolean, boolean>;
19
+ orientationFlip: Ref<boolean>;
20
+ lastGravityAngle: Ref<number | null, number | null>;
21
+ orientationReady: Ref<boolean, boolean>;
22
+ requiresGate: ComputedRef<boolean>;
23
+ enableMotion: () => Promise<void>;
24
+ armGate: () => void;
25
+ getCaptureRotation: () => number;
26
+ dispose: () => void;
27
+ };
@@ -0,0 +1,66 @@
1
+ import { computed as e, ref as t } from "vue";
2
+ //#region src/composables/useOrientationCorrection.ts
3
+ function n(n) {
4
+ let r = t(!1), i = t(!1), a = t(null), o = t(!1), s, c, l = typeof window < "u" && "DeviceMotionEvent" in window && (window.matchMedia?.("(pointer: coarse)")?.matches || "ontouchstart" in window), u = e(() => n() && l);
5
+ function d() {
6
+ c &&= (window.removeEventListener("pointerdown", c, !0), window.removeEventListener("touchend", c, !0), void 0);
7
+ }
8
+ function f() {
9
+ o.value = !0, s &&= (clearTimeout(s), void 0), d();
10
+ }
11
+ function p() {
12
+ c || (c = () => {
13
+ h();
14
+ }, window.addEventListener("pointerdown", c, !0), window.addEventListener("touchend", c, !0));
15
+ }
16
+ function m(e) {
17
+ let t = e.accelerationIncludingGravity;
18
+ if (!t || t.x == null || t.y == null) return;
19
+ let n = Math.round(Math.atan2(t.x, t.y) * 180 / Math.PI);
20
+ if (a.value = n, !(typeof screen < "u" && screen.orientation && screen.orientation.type || "portrait-primary").startsWith("portrait")) i.value = !1;
21
+ else {
22
+ let e = Math.abs(Math.abs(n) - 90);
23
+ !i.value && e < 40 ? i.value = !0 : i.value && e > 50 && (i.value = !1);
24
+ }
25
+ o.value || f();
26
+ }
27
+ async function h() {
28
+ if (!(!n() || r.value)) try {
29
+ let e = window.DeviceOrientationEvent, t = window.DeviceMotionEvent;
30
+ if (e && typeof e.requestPermission == "function" && await e.requestPermission() !== "granted") {
31
+ f();
32
+ return;
33
+ }
34
+ t && typeof t.requestPermission == "function" && await t.requestPermission().catch(() => {}), window.addEventListener("devicemotion", m, !0), r.value = !0, d();
35
+ } catch (e) {
36
+ console.error(e, "enableMotion: failed"), f();
37
+ }
38
+ }
39
+ function g() {
40
+ if (!u.value) return;
41
+ s = setTimeout(f, 3e3);
42
+ let e = window.DeviceOrientationEvent;
43
+ e && typeof e.requestPermission == "function" ? p() : h();
44
+ }
45
+ function _() {
46
+ if (!n() || a.value == null) return 0;
47
+ let e = ((a.value - 180) % 360 + 360) % 360;
48
+ return (-1 * (Math.round(e / 90) * 90 % 360) % 360 + 360) % 360;
49
+ }
50
+ function v() {
51
+ window.removeEventListener("devicemotion", m, !0), s && clearTimeout(s), d();
52
+ }
53
+ return {
54
+ motionEnabled: r,
55
+ orientationFlip: i,
56
+ lastGravityAngle: a,
57
+ orientationReady: o,
58
+ requiresGate: u,
59
+ enableMotion: h,
60
+ armGate: g,
61
+ getCaptureRotation: _,
62
+ dispose: v
63
+ };
64
+ }
65
+ //#endregion
66
+ export { n as useOrientationCorrection };
package/dist/i18n.d.ts CHANGED
@@ -135,6 +135,7 @@ declare const i18n: import('vue-i18n').I18n<{
135
135
  mailto: string;
136
136
  clipboard: string;
137
137
  instructions: string;
138
+ os: string;
138
139
  };
139
140
  testing: {
140
141
  headline: string;
@@ -134,6 +134,7 @@ export declare const messages: {
134
134
  mailto: string;
135
135
  clipboard: string;
136
136
  instructions: string;
137
+ os: string;
137
138
  };
138
139
  testing: {
139
140
  headline: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ablok-components",
3
3
  "private": false,
4
- "version": "0.3.124",
4
+ "version": "0.3.127",
5
5
  "type": "module",
6
6
  "dependencies": {
7
7
  "@tiptap/core": "^3.30.0",