@feugene/granularity-media 0.2.1 → 0.4.0

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.
Files changed (45) hide show
  1. package/README.md +23 -6
  2. package/dist/chunks/{config-CZ4ZDG0_.js → config-DHLlFslI.js} +1 -1
  3. package/dist/chunks/config-DfJkKtIh.js +27 -0
  4. package/dist/chunks/{en-C-Wc5fTB.js → en-BugobSAO.js} +12 -4
  5. package/dist/chunks/{es-BUPtE9_0.js → es-B7iA-ExH.js} +12 -4
  6. package/dist/chunks/outputSize-D2FU4CbB.js +23 -0
  7. package/dist/chunks/ru-DSjpFh8N.js +4 -0
  8. package/dist/chunks/{ru-BqNILj54.js → ru-DpiW6Vax.js} +12 -4
  9. package/dist/chunks/useCameraStream-CPdm3r90.js +86 -0
  10. package/dist/components/GrCameraCapture/chunks/GrCameraCapture-t-uFTD9s.js +134 -0
  11. package/dist/components/GrCameraCapture/index.js +4 -3
  12. package/dist/components/GrCodeScanner/chunks/GrCodeScanner-BX147Gct.js +162 -0
  13. package/dist/components/GrCodeScanner/index.js +3 -0
  14. package/dist/components/GrImageCrop/chunks/{GrImageCrop-Fo2qrX2n.js → GrImageCrop-g1StRUis.js} +85 -84
  15. package/dist/components/GrImageCrop/index.js +1 -1
  16. package/dist/granular-provider.js +14 -12
  17. package/dist/i18n/all.js +1 -1
  18. package/dist/i18n/index.js +4 -4
  19. package/dist/index.js +8 -5
  20. package/dist/resolver.js +5 -1
  21. package/dist/types/componentNames.d.ts +1 -1
  22. package/dist/types/components/GrCameraCapture/GrCameraCapture.vue.d.ts +13 -9
  23. package/dist/types/components/GrCameraCapture/cameraState.d.ts +0 -17
  24. package/dist/types/components/GrCameraCapture/grCameraCaptureStyles.d.ts +6 -2
  25. package/dist/types/components/GrCameraCapture/index.d.ts +2 -2
  26. package/dist/types/components/GrCodeScanner/GrCodeScanner.vue.d.ts +121 -0
  27. package/dist/types/components/GrCodeScanner/__tests__/GrCodeScanner.test.d.ts +1 -0
  28. package/dist/types/components/GrCodeScanner/__tests__/codeDetection.test.d.ts +1 -0
  29. package/dist/types/components/GrCodeScanner/codeDetection.d.ts +42 -0
  30. package/dist/types/components/GrCodeScanner/config.d.ts +5 -0
  31. package/dist/types/components/GrCodeScanner/defaults.d.ts +16 -0
  32. package/dist/types/components/GrCodeScanner/grCodeScannerStyles.d.ts +19 -0
  33. package/dist/types/components/GrCodeScanner/index.d.ts +9 -0
  34. package/dist/types/granular-provider/shared.d.ts +1 -0
  35. package/dist/types/i18n/index.d.ts +21 -0
  36. package/dist/types/i18n/messages/en.d.ts +14 -0
  37. package/dist/types/i18n/messages/es.d.ts +14 -0
  38. package/dist/types/i18n/messages/ru.d.ts +14 -0
  39. package/dist/types/index.d.ts +1 -0
  40. package/dist/types/internal/__tests__/outputSize.test.d.ts +1 -0
  41. package/dist/types/internal/outputSize.d.ts +26 -0
  42. package/dist/types/internal/useCameraStream.d.ts +30 -0
  43. package/package.json +5 -1
  44. package/dist/chunks/ru-DN_wJDkP.js +0 -4
  45. package/dist/components/GrCameraCapture/chunks/GrCameraCapture-B9EPXm7r.js +0 -201
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Распознавание кодов: нативный путь и точка подключения для остальных.
3
+ *
4
+ * `BarcodeDetector` есть в Chrome и Edge, но его нет ни в Safari, ни в Firefox —
5
+ * то есть на iPhone его нет вовсе, а там сканируют чаще всего. Тащить декодер в
6
+ * пакет нельзя: у него нет ни одной зависимости, и ради одного компонента
7
+ * появилась бы самая тяжёлая. Поэтому компонент умеет нативный путь сам, а
8
+ * остальные браузеры закрывает детектором, который передаёт приложение.
9
+ */
10
+ /** Один распознанный код. */
11
+ export interface GrCodeResult {
12
+ /** Содержимое: адрес, номер товара, текст. */
13
+ value: string;
14
+ /** Символика: `qr_code`, `ean_13`, `code_128`, … */
15
+ format: string;
16
+ }
17
+ /**
18
+ * Детектор кадра. Ровно та форма, в которую заворачивается любая библиотека:
19
+ * на вход — то, что умеет рисовать canvas, на выход — список кодов.
20
+ */
21
+ export type GrCodeDetector = (source: CanvasImageSource) => Promise<GrCodeResult[]>;
22
+ /** Есть ли нативный `BarcodeDetector`. */
23
+ export declare function nativeDetectorSupported(scope?: typeof globalThis): boolean;
24
+ /**
25
+ * Нативный детектор в общей форме.
26
+ *
27
+ * Формат приводится к нашему типу здесь, а не в компоненте: спецификация зовёт
28
+ * содержимое `rawValue`, и это единственное место, где чужое имя видно.
29
+ */
30
+ export declare function createNativeDetector(formats: readonly string[] | undefined, scope?: typeof globalThis): GrCodeDetector | null;
31
+ /**
32
+ * Что сообщать наружу из очередного кадра.
33
+ *
34
+ * Камера отдаёт десятки кадров в секунду, и один и тот же код распознаётся в
35
+ * каждом. Без фильтра приложение получило бы поток одинаковых событий и
36
+ * оформило бы двадцать заказов вместо одного. Поэтому по умолчанию сообщается
37
+ * только то, чего не было в предыдущем кадре.
38
+ *
39
+ * `continuous` нужен там, где сканируют подряд (приёмка на складе): там повтор
40
+ * того же кода — законное второе событие.
41
+ */
42
+ export declare function freshCodes(previous: readonly GrCodeResult[], next: readonly GrCodeResult[], continuous: boolean): GrCodeResult[];
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Кнопки состояния и управления — `GrButton` ядра, и ребро объявлено: пресет
3
+ * подмешивает safelist и CSS только тем компонентам, что попали в селекцию.
4
+ */
5
+ export declare const grCodeScannerConfig: import("@feugene/unocss-preset-granular/contract").GranularComponentDescriptor<"GrCodeScanner">;
@@ -0,0 +1,16 @@
1
+ import type { GrCodeScannerSize } from './grCodeScannerStyles';
2
+ /**
3
+ * Настраиваемые через `GrConfigProvider` пропы.
4
+ *
5
+ * Аугментация реестра идёт по месту объявления — через
6
+ * `@feugene/granularity/composables/useGrComponentConfig`, а не через реэкспорт:
7
+ * иначе слияние отваливается молча.
8
+ */
9
+ export interface GrCodeScannerConfigurableProps {
10
+ size?: GrCodeScannerSize;
11
+ }
12
+ declare module '@feugene/granularity/composables/useGrComponentConfig' {
13
+ interface GrComponentDefaultsRegistry {
14
+ GrCodeScanner?: GrCodeScannerConfigurableProps;
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ export type GrCodeScannerSize = 'xs' | 'sm' | 'md' | 'lg';
2
+ export declare const rootClass = "grid gap-2";
3
+ export declare const frameClass = "relative w-full overflow-hidden rounded-[var(--gr-radius-md)] border border-[var(--gr-brd)] bg-[var(--gr-muted)]";
4
+ export declare const videoClass = "h-full w-full object-contain";
5
+ /**
6
+ * Прицел: показывает, куда наводить. Рамка, а не затемнение вокруг, — код
7
+ * распознаётся по всему кадру, и затемнение обещало бы обратное.
8
+ */
9
+ export declare const reticleClass = "pointer-events-none absolute inset-[15%] rounded-[var(--gr-radius-md)] border-2 border-[var(--gr-code-scanner-reticle,var(--gr-primary))]";
10
+ export declare const stateLayerClass = "absolute inset-0 grid place-content-center gap-3 p-4 text-center transition-opacity duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]";
11
+ export declare const stateTextClass = "text-[var(--gr-muted-fg)]";
12
+ export declare const controlsClass = "flex flex-wrap items-center gap-2";
13
+ export declare const sizeTextClass: {
14
+ readonly xs: "text-[length:var(--gr-control-text-xs)] leading-[var(--gr-control-leading-xs)]";
15
+ readonly sm: "text-[length:var(--gr-control-text-sm)] leading-[var(--gr-control-leading-sm)]";
16
+ readonly md: "text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)]";
17
+ readonly lg: "text-[length:var(--gr-control-text-lg)] leading-[var(--gr-control-leading-lg)]";
18
+ };
19
+ export declare const grCodeScannerSafelist: string[];
@@ -0,0 +1,9 @@
1
+ export { default } from './GrCodeScanner.vue';
2
+ export { default as GrCodeScanner } from './GrCodeScanner.vue';
3
+ export type { GrCodeDetector, GrCodeResult } from './codeDetection';
4
+ export { createNativeDetector, freshCodes, nativeDetectorSupported } from './codeDetection';
5
+ export { grCodeScannerConfig } from './config';
6
+ export type { GrCodeScannerConfigurableProps } from './defaults';
7
+ export type { GrCodeScannerEmits, GrCodeScannerProps } from './GrCodeScanner.vue';
8
+ export { grCodeScannerSafelist } from './grCodeScannerStyles';
9
+ export type { GrCodeScannerSize } from './grCodeScannerStyles';
@@ -9,6 +9,7 @@ export declare const GRANULARITY_MEDIA_PROVIDER_ID = "@feugene/granularity-media
9
9
  */
10
10
  export declare const granularityMediaComponentConfigs: {
11
11
  GrCameraCapture: GranularComponentDescriptor<"GrCameraCapture">;
12
+ GrCodeScanner: GranularComponentDescriptor<"GrCodeScanner">;
12
13
  GrImageCrop: GranularComponentDescriptor<"GrImageCrop">;
13
14
  };
14
15
  export type GranularityMediaComponentName = keyof typeof granularityMediaComponentConfigs;
@@ -22,6 +22,13 @@ export declare const grMediaMessages: {
22
22
  live: string;
23
23
  captured: string;
24
24
  };
25
+ scanner: {
26
+ label: string;
27
+ start: string;
28
+ stop: string;
29
+ unsupported: string;
30
+ detected: string;
31
+ };
25
32
  };
26
33
  readonly es: {
27
34
  imageCrop: {
@@ -46,6 +53,13 @@ export declare const grMediaMessages: {
46
53
  live: string;
47
54
  captured: string;
48
55
  };
56
+ scanner: {
57
+ label: string;
58
+ start: string;
59
+ stop: string;
60
+ unsupported: string;
61
+ detected: string;
62
+ };
49
63
  };
50
64
  readonly ru: {
51
65
  imageCrop: {
@@ -70,6 +84,13 @@ export declare const grMediaMessages: {
70
84
  live: string;
71
85
  captured: string;
72
86
  };
87
+ scanner: {
88
+ label: string;
89
+ start: string;
90
+ stop: string;
91
+ unsupported: string;
92
+ detected: string;
93
+ };
73
94
  };
74
95
  };
75
96
  export type GrMediaLocale = keyof typeof grMediaMessages;
@@ -24,6 +24,13 @@ export declare const en: {
24
24
  live: string;
25
25
  captured: string;
26
26
  };
27
+ scanner: {
28
+ label: string;
29
+ start: string;
30
+ stop: string;
31
+ unsupported: string;
32
+ detected: string;
33
+ };
27
34
  };
28
35
  imageCrop: {
29
36
  label: string;
@@ -47,6 +54,13 @@ export declare const en: {
47
54
  live: string;
48
55
  captured: string;
49
56
  };
57
+ scanner: {
58
+ label: string;
59
+ start: string;
60
+ stop: string;
61
+ unsupported: string;
62
+ detected: string;
63
+ };
50
64
  }>;
51
65
  };
52
66
  };
@@ -24,6 +24,13 @@ export declare const es: {
24
24
  live: string;
25
25
  captured: string;
26
26
  };
27
+ scanner: {
28
+ label: string;
29
+ start: string;
30
+ stop: string;
31
+ unsupported: string;
32
+ detected: string;
33
+ };
27
34
  };
28
35
  imageCrop: {
29
36
  label: string;
@@ -47,6 +54,13 @@ export declare const es: {
47
54
  live: string;
48
55
  captured: string;
49
56
  };
57
+ scanner: {
58
+ label: string;
59
+ start: string;
60
+ stop: string;
61
+ unsupported: string;
62
+ detected: string;
63
+ };
50
64
  }>;
51
65
  };
52
66
  };
@@ -24,6 +24,13 @@ export declare const ru: {
24
24
  live: string;
25
25
  captured: string;
26
26
  };
27
+ scanner: {
28
+ label: string;
29
+ start: string;
30
+ stop: string;
31
+ unsupported: string;
32
+ detected: string;
33
+ };
27
34
  };
28
35
  imageCrop: {
29
36
  label: string;
@@ -47,6 +54,13 @@ export declare const ru: {
47
54
  live: string;
48
55
  captured: string;
49
56
  };
57
+ scanner: {
58
+ label: string;
59
+ start: string;
60
+ stop: string;
61
+ unsupported: string;
62
+ detected: string;
63
+ };
50
64
  }>;
51
65
  };
52
66
  };
@@ -1,2 +1,3 @@
1
1
  export * from './components/GrCameraCapture';
2
+ export * from './components/GrCodeScanner';
2
3
  export * from './components/GrImageCrop';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Размер результата по заданной части `output`.
3
+ *
4
+ * Ловушка, ради которой это отдельная функция: задать **одну** сторону —
5
+ * обычное дело («аватар шириной 256»), и вторая обязана считаться из
6
+ * соотношения захваченной области. Взятая из исходника, она даёт растянутую
7
+ * картинку: кадр камеры 640×480 при `output.width = 800` превращался в холст
8
+ * 800×480, то есть в изображение, растянутое по горизонтали на четверть.
9
+ *
10
+ * Обе стороны заданы — это **габарит**, а не точный размер: кадр вписывается в
11
+ * него, сохраняя свои пропорции. Взять их буквально значило бы растянуть
12
+ * картинку, когда соотношения не совпали, — а пропорции съёмки в этом пакете
13
+ * не искажаются никогда.
14
+ */
15
+ export interface GrOutputRequest {
16
+ width?: number;
17
+ height?: number;
18
+ }
19
+ export interface GrOutputSize {
20
+ width: number;
21
+ height: number;
22
+ }
23
+ export declare function outputSize(area: {
24
+ sw: number;
25
+ sh: number;
26
+ }, output?: GrOutputRequest): GrOutputSize;
@@ -0,0 +1,30 @@
1
+ import type { Ref } from 'vue';
2
+ import type { GrCameraStatus } from '../components/GrCameraCapture/cameraState';
3
+ /**
4
+ * Поток камеры: запрос, состояния отказа, размеры кадра, остановка.
5
+ *
6
+ * Общий для съёмки и сканирования — у обоих одна и та же половина работы, и
7
+ * дважды написанная она разъехалась бы на первом же исправлении: отказ, забытая
8
+ * остановка дорожек, соотношение сторон до `loadedmetadata`. Компоненту
9
+ * остаётся то, ради чего он существует: снять кадр или распознать код.
10
+ */
11
+ export interface UseCameraStreamOptions {
12
+ video: Ref<HTMLVideoElement | null>;
13
+ disabled: () => boolean;
14
+ facing: () => 'user' | 'environment';
15
+ deviceId: () => string | undefined;
16
+ /** Пожелание камере, а не требование: см. `exact` ниже. */
17
+ aspectRatio?: () => number | undefined;
18
+ onStatus?: (status: GrCameraStatus) => void;
19
+ onStart?: () => void;
20
+ onStop?: () => void;
21
+ }
22
+ export declare function useCameraStream(options: UseCameraStreamOptions): {
23
+ status: Ref<GrCameraStatus, GrCameraStatus>;
24
+ streamRatio: Ref<number | null, number | null>;
25
+ frameRatio: import("vue").ComputedRef<number>;
26
+ isLive: import("vue").ComputedRef<boolean>;
27
+ message: import("vue").ComputedRef<string>;
28
+ start: () => Promise<void>;
29
+ stop: () => void;
30
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@feugene/granularity-media",
3
3
  "description": "Media components for @feugene/granularity: image cropping, camera capture, code scanning and video playback.",
4
- "version": "0.2.1",
4
+ "version": "0.4.0",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
7
7
  "name": "Evgeniy Fureev",
@@ -51,6 +51,10 @@
51
51
  "types": "./dist/types/components/GrCameraCapture/index.d.ts",
52
52
  "import": "./dist/components/GrCameraCapture/index.js"
53
53
  },
54
+ "./components/GrCodeScanner": {
55
+ "types": "./dist/types/components/GrCodeScanner/index.d.ts",
56
+ "import": "./dist/components/GrCodeScanner/index.js"
57
+ },
54
58
  "./components/GrImageCrop": {
55
59
  "types": "./dist/types/components/GrImageCrop/index.d.ts",
56
60
  "import": "./dist/components/GrImageCrop/index.js"
@@ -1,4 +0,0 @@
1
- //#region src/i18n/messages/const.ts
2
- var e = "grMedia", t = { en: { [e]: async () => import("./en-C-Wc5fTB.js").then((e) => e.n) } }, n = { es: { [e]: async () => import("./es-BUPtE9_0.js").then((e) => e.n) } }, r = { ru: { [e]: async () => import("./ru-BqNILj54.js").then((e) => e.n) } };
3
- //#endregion
4
- export { e as i, n, t as r, r as t };
@@ -1,201 +0,0 @@
1
- import { a as e, c as t, l as n, n as r, o as i, r as a, s as o, u as s } from "../../../chunks/config-CZ4ZDG0_.js";
2
- import { computed as c, createBlock as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, createTextVNode as p, createVNode as m, defineComponent as h, normalizeClass as g, normalizeStyle as _, onBeforeUnmount as v, onMounted as y, openBlock as b, ref as x, renderSlot as S, shallowRef as C, toDisplayString as w, unref as T, withCtx as E } from "vue";
3
- import D from "@feugene/granularity/components/GrButton";
4
- import { useAnnouncer as ee } from "@feugene/granularity/composables/useAnnouncer";
5
- import { useGrComponentSize as te } from "@feugene/granularity/composables/useGrComponentConfig";
6
- import { useGranularityTranslations as ne } from "@feugene/granularity/composables/useGranularityTranslations";
7
- //#region src/components/GrCameraCapture/cameraState.ts
8
- function O(e) {
9
- switch (e instanceof Error ? e.name : "") {
10
- case "NotAllowedError":
11
- case "SecurityError":
12
- case "PermissionDeniedError": return "denied";
13
- case "NotFoundError":
14
- case "DevicesNotFoundError":
15
- case "OverconstrainedError": return "missing";
16
- case "NotReadableError":
17
- case "TrackStartError":
18
- case "AbortError": return "busy";
19
- default: return "error";
20
- }
21
- }
22
- function k(e) {
23
- return typeof e?.mediaDevices?.getUserMedia == "function";
24
- }
25
- function A(e, t) {
26
- return t ?? e === "user";
27
- }
28
- function j(e, t) {
29
- let n = t > 0 ? t : 1;
30
- if (e.width <= 0 || e.height <= 0) return {
31
- sx: 0,
32
- sy: 0,
33
- sw: 0,
34
- sh: 0
35
- };
36
- if (e.width / e.height > n) {
37
- let t = e.height * n;
38
- return {
39
- sx: (e.width - t) / 2,
40
- sy: 0,
41
- sw: t,
42
- sh: e.height
43
- };
44
- }
45
- let r = e.width / n;
46
- return {
47
- sx: 0,
48
- sy: (e.height - r) / 2,
49
- sw: e.width,
50
- sh: r
51
- };
52
- }
53
- //#endregion
54
- //#region src/components/GrCameraCapture/GrCameraCapture.vue?vue&type=script&setup=true&lang.ts
55
- var M = ["aria-label"], N = /* @__PURE__ */ h({
56
- __name: "GrCameraCapture",
57
- props: {
58
- facing: { default: "user" },
59
- deviceId: { default: void 0 },
60
- aspectRatio: { default: void 0 },
61
- autoStart: {
62
- type: Boolean,
63
- default: !1
64
- },
65
- mirror: {
66
- type: Boolean,
67
- default: void 0
68
- },
69
- output: { default: void 0 },
70
- size: { default: void 0 },
71
- disabled: {
72
- type: Boolean,
73
- default: !1
74
- },
75
- ariaLabel: { default: void 0 }
76
- },
77
- emits: [
78
- "capture",
79
- "start",
80
- "stop",
81
- "statusChange"
82
- ],
83
- setup(h, { expose: N, emit: P }) {
84
- let F = h, I = P, { t: L } = ne(), { announce: R } = ee(), z = te(() => F.size, { component: "GrCameraCapture" }), B = x(null), V = C(null), H = x("idle"), U = x(null), W = c(() => F.aspectRatio ?? U.value ?? 4 / 3), G = c(() => A(F.facing, F.mirror)), K = c(() => H.value === "live"), q = c(() => {
85
- switch (H.value) {
86
- case "starting": return L("grMedia.camera.starting", "Requesting camera access…");
87
- case "denied": return L("grMedia.camera.denied", "Camera access is blocked. Allow it in the browser settings for this site.");
88
- case "missing": return L("grMedia.camera.missing", "No camera found on this device.");
89
- case "busy": return L("grMedia.camera.busy", "The camera is busy in another application.");
90
- case "insecure": return L("grMedia.camera.insecure", "The camera works only over HTTPS.");
91
- case "error": return L("grMedia.camera.error", "The camera could not be started.");
92
- default: return L("grMedia.camera.idle", "The camera is off.");
93
- }
94
- });
95
- function J(e) {
96
- H.value !== e && (H.value = e, I("statusChange", e));
97
- }
98
- function Y() {
99
- let e = B.value;
100
- !e || e.videoWidth <= 0 || e.videoHeight <= 0 || (U.value = e.videoWidth / e.videoHeight);
101
- }
102
- function X() {
103
- V.value?.getTracks().forEach((e) => e.stop()), V.value = null, U.value = null, B.value && (B.value.srcObject = null);
104
- }
105
- async function Z() {
106
- if (!(F.disabled || H.value === "starting" || H.value === "live")) {
107
- if (!k(navigator)) {
108
- J("insecure");
109
- return;
110
- }
111
- J("starting");
112
- try {
113
- let e = await navigator.mediaDevices.getUserMedia({
114
- video: F.deviceId ? { deviceId: { exact: F.deviceId } } : { facingMode: F.facing },
115
- audio: !1
116
- });
117
- V.value = e, B.value && (B.value.srcObject = e, B.value.addEventListener("loadedmetadata", Y, { once: !0 }), await B.value.play().catch(() => void 0), Y()), J("live"), I("start"), R(L("grMedia.camera.live", "Camera is on"));
118
- } catch (e) {
119
- X(), J(O(e)), R(q.value, { politeness: "assertive" });
120
- }
121
- }
122
- }
123
- function Q() {
124
- V.value && (X(), J("idle"), I("stop"));
125
- }
126
- async function $() {
127
- let e = B.value;
128
- if (!e || !K.value) return null;
129
- let t = j({
130
- width: e.videoWidth,
131
- height: e.videoHeight
132
- }, W.value);
133
- if (t.sw <= 0) return null;
134
- let n = document.createElement("canvas");
135
- n.width = Math.max(1, Math.round(F.output?.width ?? t.sw)), n.height = Math.max(1, Math.round(F.output?.height ?? t.sh));
136
- let r = n.getContext("2d");
137
- if (!r) return null;
138
- r.drawImage(e, t.sx, t.sy, t.sw, t.sh, 0, 0, n.width, n.height);
139
- let i = await new Promise((e) => {
140
- n.toBlob(e, F.output?.type ?? "image/jpeg", F.output?.quality ?? .92);
141
- });
142
- return i && (I("capture", i), R(L("grMedia.camera.captured", "Photo taken"))), i;
143
- }
144
- return y(() => {
145
- F.autoStart && Z();
146
- }), v(X), N({
147
- start: Z,
148
- stop: Q,
149
- capture: $,
150
- status: H
151
- }), (c, v) => (b(), d("div", {
152
- class: g(T(i)),
153
- role: "group",
154
- "aria-label": h.ariaLabel ?? T(L)("grMedia.camera.label", "Camera")
155
- }, [f("div", {
156
- class: g(T(a)),
157
- style: _({ aspectRatio: String(W.value) })
158
- }, [f("video", {
159
- ref_key: "videoEl",
160
- ref: B,
161
- class: g([T(s), G.value ? T(e) : ""]),
162
- playsinline: "",
163
- muted: "",
164
- autoplay: ""
165
- }, null, 2), K.value ? u("", !0) : (b(), d("div", {
166
- key: 0,
167
- class: g(T(t))
168
- }, [f("p", { class: g([T(n), T(o)[T(z)]]) }, w(q.value), 3), H.value !== "starting" && H.value !== "insecure" && H.value !== "missing" ? (b(), l(T(D), {
169
- key: 0,
170
- size: T(z),
171
- disabled: h.disabled,
172
- onClick: Z
173
- }, {
174
- default: E(() => [p(w(H.value === "idle" ? T(L)("grMedia.camera.start", "Turn on camera") : T(L)("grMedia.camera.retry", "Try again")), 1)]),
175
- _: 1
176
- }, 8, ["size", "disabled"])) : u("", !0)], 2))], 6), f("div", { class: g(T(r)) }, [S(c.$slots, "controls", {
177
- status: H.value,
178
- start: Z,
179
- stop: Q,
180
- capture: $
181
- }, () => [m(T(D), {
182
- size: T(z),
183
- disabled: h.disabled || !K.value,
184
- onClick: $
185
- }, {
186
- default: E(() => [p(w(T(L)("grMedia.camera.capture", "Take photo")), 1)]),
187
- _: 1
188
- }, 8, ["size", "disabled"]), K.value ? (b(), l(T(D), {
189
- key: 0,
190
- variant: "outline",
191
- size: T(z),
192
- disabled: h.disabled,
193
- onClick: Q
194
- }, {
195
- default: E(() => [p(w(T(L)("grMedia.camera.stop", "Turn off")), 1)]),
196
- _: 1
197
- }, 8, ["size", "disabled"])) : u("", !0)])], 2)], 10, M));
198
- }
199
- });
200
- //#endregion
201
- export { A as a, k as i, j as n, O as r, N as t };