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.
- package/dist/ablok-components.css +1 -1
- package/dist/ablok-components.umd.js +2 -2
- package/dist/components/molecules/base-camera/base-camera.vue_vue_type_script_async_true_setup_true_lang.js +238 -277
- package/dist/components/molecules/link-sharing/link-sharing.vue.d.ts +2 -0
- package/dist/components/molecules/link-sharing/link-sharing.vue_vue_type_script_setup_true_lang.js +40 -19
- package/dist/composables/useCameraCapture.d.ts +34 -0
- package/dist/composables/useCameraCapture.js +53 -0
- package/dist/composables/useOrientationCorrection.d.ts +27 -0
- package/dist/composables/useOrientationCorrection.js +66 -0
- package/dist/i18n.d.ts +1 -0
- package/dist/locales/en.d.ts +1 -0
- package/package.json +1 -1
|
@@ -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<{}>, {
|
package/dist/components/molecules/link-sharing/link-sharing.vue_vue_type_script_setup_true_lang.js
CHANGED
|
@@ -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
|
-
},
|
|
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
|
|
66
|
-
t(() => encodeURIComponent(
|
|
67
|
-
let
|
|
68
|
-
async function
|
|
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 =
|
|
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, [
|
|
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) =>
|
|
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=${
|
|
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=${
|
|
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) =>
|
|
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=${
|
|
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 &&
|
|
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=${
|
|
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(
|
|
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=${
|
|
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 {
|
|
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
package/dist/locales/en.d.ts
CHANGED