ablok-components 0.3.136 → 0.3.138

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.
@@ -1,5 +1,5 @@
1
- import { isAndroid as e, isIOS as t, supportsRVFC as n } from "./platform.js";
2
- import { buildFallbackChain as r, classifyFacingFromLabel as i, dedupeByFacing as a, isFatalGumError as o, isTransientGumError as s, normalizeFacing as c, pickSwitchTarget as l, toErrorCode as u } from "./constraints.js";
1
+ import { buildFallbackChain as e, classifyFacingFromLabel as t, dedupeByFacing as n, isFatalGumError as r, isTransientGumError as i, normalizeFacing as a, pickSwitchTarget as o, toErrorCode as s } from "./constraints.js";
2
+ import { isAndroid as c, isIOS as l, supportsRVFC as u } from "./platform.js";
3
3
  import { CameraError as d } from "./types.js";
4
4
  //#region src/utilities/camera/CameraManager.ts
5
5
  var f = 1500, p = 2, m = 300, h = [
@@ -23,6 +23,9 @@ var f = 1500, p = 2, m = 300, h = [
23
23
  zoom = 1;
24
24
  zoomCapability = null;
25
25
  desiredZoom = null;
26
+ torch = !1;
27
+ torchCapability = !1;
28
+ canLockExposure = !1;
26
29
  video = null;
27
30
  seq = 0;
28
31
  tearingDown = !1;
@@ -55,7 +58,10 @@ var f = 1500, p = 2, m = 300, h = [
55
58
  error: this.error,
56
59
  permission: this.permission,
57
60
  zoom: this.zoom,
58
- zoomCapability: this.zoomCapability
61
+ zoomCapability: this.zoomCapability,
62
+ torch: this.torch,
63
+ torchCapability: this.torchCapability,
64
+ canLockExposure: this.canLockExposure
59
65
  };
60
66
  }
61
67
  static isSupported() {
@@ -64,52 +70,52 @@ var f = 1500, p = 2, m = 300, h = [
64
70
  attachVideo(e) {
65
71
  this.video !== e && (this.clearWatchdog(), this.video && (this.video.srcObject = null), this.video = e, e && this.stream && this.state !== "paused" && this.bindStream());
66
72
  }
67
- async start(e = {}) {
73
+ async start(n = {}) {
68
74
  if (this.disposed) return !1;
69
75
  if (!S.isSupported()) return this.fail(new d("unsupported", "getUserMedia is not available in this browser")), !1;
70
- let t = ++this.seq;
76
+ let o = ++this.seq;
71
77
  this.cancelRecovery(), this.intent = "live", this.teardown(), this.error = null, this.setState("starting");
72
- let n = e.resolution ?? this.lastGood?.resolution ?? this.opts.resolution, a = !!(e.strictDevice && e.deviceId), l = a ? void 0 : e.facing ?? (e.deviceId ? void 0 : this.opts.preferredFacing), f = r({
73
- deviceId: e.deviceId,
74
- facing: l,
75
- resolution: n,
76
- strictDevice: a
78
+ let c = n.resolution ?? this.lastGood?.resolution ?? this.opts.resolution, l = !!(n.strictDevice && n.deviceId), u = l ? void 0 : n.facing ?? (n.deviceId ? void 0 : this.opts.preferredFacing), f = e({
79
+ deviceId: n.deviceId,
80
+ facing: u,
81
+ resolution: c,
82
+ strictDevice: l
77
83
  }), p = null, h = null;
78
84
  for (let e of f) {
79
- if (t !== this.seq) return !1;
85
+ if (o !== this.seq) return !1;
80
86
  try {
81
87
  p = await navigator.mediaDevices.getUserMedia(e.constraints);
82
88
  break;
83
- } catch (n) {
84
- if (h = n, o(n)) break;
85
- if (s(n)) {
86
- if (await x(m), t !== this.seq) return !1;
89
+ } catch (t) {
90
+ if (h = t, r(t)) break;
91
+ if (i(t)) {
92
+ if (await x(m), o !== this.seq) return !1;
87
93
  try {
88
94
  p = await navigator.mediaDevices.getUserMedia(e.constraints);
89
95
  break;
90
96
  } catch (e) {
91
- if (h = e, o(e)) break;
97
+ if (h = e, r(e)) break;
92
98
  }
93
99
  }
94
100
  }
95
101
  }
96
- if (t !== this.seq) return p?.getTracks().forEach((e) => e.stop()), !1;
102
+ if (o !== this.seq) return p?.getTracks().forEach((e) => e.stop()), !1;
97
103
  if (!p) {
98
- let e = u(h);
104
+ let e = s(h);
99
105
  return e === "not-allowed" && (this.permission = "denied"), this.fail(new d(e, C(h), h)), !1;
100
106
  }
101
107
  let g = p.getVideoTracks()[0];
102
108
  if (!g) return p.getTracks().forEach((e) => e.stop()), this.fail(new d("not-found", "Stream has no video track")), !1;
103
- let _ = g.getSettings(), v = _.deviceId ?? e.deviceId ?? null, y = v ? this.probeCache.get(v) : void 0, b = c(_.facingMode) ?? y ?? i(g.label);
109
+ let _ = g.getSettings(), v = _.deviceId ?? n.deviceId ?? null, y = v ? this.probeCache.get(v) : void 0, b = a(_.facingMode) ?? y ?? t(g.label);
104
110
  if (v && this.probeCache.set(v, b), this.stream = p, this.activeDeviceId = v, this.activeFacing = b, this.lastGood = {
105
111
  deviceId: v,
106
- resolution: n
107
- }, this.permission !== "granted" && (this.permission = "granted"), g.onended = this.onTrackEnded, this.readZoomCapability(g), this.setState("live"), this.armStableTimer(), this.bindStream(), this.desiredZoom !== null && this.setZoom(this.desiredZoom), await this.refreshDevices(), t !== this.seq) return !1;
108
- if (!e.deviceId && !this.autoCorrected && this.opts.preferredFacing && b && (this.autoCorrected = !0, b !== this.opts.preferredFacing)) {
112
+ resolution: c
113
+ }, this.permission !== "granted" && (this.permission = "granted"), g.onended = this.onTrackEnded, this.readZoomCapability(g), this.readTorchCapability(g), this.setState("live"), this.armStableTimer(), this.bindStream(), this.desiredZoom !== null && this.setZoom(this.desiredZoom), await this.refreshDevices(), o !== this.seq) return !1;
114
+ if (!n.deviceId && !this.autoCorrected && this.opts.preferredFacing && b && (this.autoCorrected = !0, b !== this.opts.preferredFacing)) {
109
115
  let e = this.devices.find((e) => e.facing === this.opts.preferredFacing && e.deviceId !== v);
110
116
  if (e) return this.start({
111
117
  deviceId: e.deviceId,
112
- resolution: n,
118
+ resolution: c,
113
119
  strictDevice: !0
114
120
  });
115
121
  }
@@ -137,7 +143,7 @@ var f = 1500, p = 2, m = 300, h = [
137
143
  async switchCamera() {
138
144
  if (this.state === "starting") return !1;
139
145
  this.devices.length === 0 && await this.refreshDevices();
140
- let e = l(this.devices, this.activeDeviceId, this.activeFacing);
146
+ let e = o(this.devices, this.activeDeviceId, this.activeFacing);
141
147
  return e ? this.selectDevice(e.deviceId) : !1;
142
148
  }
143
149
  async selectDevice(e) {
@@ -177,6 +183,26 @@ var f = 1500, p = 2, m = 300, h = [
177
183
  }
178
184
  return this.zoom = t.getSettings().zoom ?? r, this.emit(), !0;
179
185
  }
186
+ async setTorch(e) {
187
+ let t = this.stream?.getVideoTracks()[0];
188
+ if (!t || !this.torchCapability) return !1;
189
+ try {
190
+ await t.applyConstraints({ advanced: [{ torch: e }] });
191
+ } catch {
192
+ return !1;
193
+ }
194
+ return this.torch = t.getSettings().torch ?? e, this.emit(), !0;
195
+ }
196
+ async setExposureLocked(e) {
197
+ let t = this.stream?.getVideoTracks()[0];
198
+ if (!t || !this.canLockExposure) return !1;
199
+ try {
200
+ await t.applyConstraints({ advanced: [{ exposureMode: e ? "manual" : "continuous" }] });
201
+ } catch {
202
+ return !1;
203
+ }
204
+ return !0;
205
+ }
180
206
  async refreshDevices() {
181
207
  return this.refreshing ||= this.doRefreshDevices().finally(() => {
182
208
  this.refreshing = null;
@@ -189,7 +215,7 @@ var f = 1500, p = 2, m = 300, h = [
189
215
  this.tearingDown = !0, this.clearWatchdog(), this.stableTimer && clearTimeout(this.stableTimer), this.stableTimer = null;
190
216
  let e = this.stream;
191
217
  if (this.stream = null, e) for (let t of e.getTracks()) t.onended = null, t.onmute = null, t.onunmute = null, t.stop();
192
- this.video && (this.video.pause(), this.video.srcObject = null), this.zoomCapability = null, this.tearingDown = !1;
218
+ this.video && (this.video.pause(), this.video.srcObject = null), this.zoomCapability = null, this.torch = !1, this.torchCapability = !1, this.canLockExposure = !1, this.tearingDown = !1;
193
219
  }
194
220
  fail(e) {
195
221
  this.teardown(), this.error = e, this.setState("error");
@@ -202,23 +228,23 @@ var f = 1500, p = 2, m = 300, h = [
202
228
  for (let t of this.listeners) t(e);
203
229
  }
204
230
  bindStream(e = 0) {
205
- let t = this.video, r = this.stream;
206
- if (!t || !r) return;
207
- this.clearWatchdog(), t.muted = !0, t.playsInline = !0, t.setAttribute("playsinline", ""), t.autoplay = !0, t.srcObject = r, t.load(), t.play().catch(b);
208
- let i = !1, a = setTimeout(() => {
209
- if (!i && (s(), this.stream === r && this.state === "live")) {
231
+ let t = this.video, n = this.stream;
232
+ if (!t || !n) return;
233
+ this.clearWatchdog(), t.muted = !0, t.playsInline = !0, t.setAttribute("playsinline", ""), t.autoplay = !0, t.srcObject = n, t.load(), t.play().catch(b);
234
+ let r = !1, i = setTimeout(() => {
235
+ if (!r && (o(), this.stream === n && this.state === "live")) {
210
236
  if (e < p) {
211
237
  t.srcObject = null, t.offsetHeight, this.bindStream(e + 1);
212
238
  return;
213
239
  }
214
240
  t.readyState >= 2 && t.videoWidth > 0 || this.opts.onWarning?.(new d("first-frame", "Video did not render its first frame"));
215
241
  }
216
- }, f), o = () => {
217
- i || (i = !0, s());
218
- }, s = () => {
219
- clearTimeout(a), t.removeEventListener("loadeddata", o), t.removeEventListener("playing", o), this.watchdogCleanup = null;
242
+ }, f), a = () => {
243
+ r || (r = !0, o());
244
+ }, o = () => {
245
+ clearTimeout(i), t.removeEventListener("loadeddata", a), t.removeEventListener("playing", a), this.watchdogCleanup = null;
220
246
  };
221
- this.watchdogCleanup = s, n(t) ? t.requestVideoFrameCallback(() => o()) : (t.addEventListener("loadeddata", o), t.addEventListener("playing", o));
247
+ this.watchdogCleanup = o, u(t) ? t.requestVideoFrameCallback(() => a()) : (t.addEventListener("loadeddata", a), t.addEventListener("playing", a));
222
248
  }
223
249
  clearWatchdog() {
224
250
  this.watchdogCleanup?.(), this.watchdogCleanup = null;
@@ -276,32 +302,32 @@ var f = 1500, p = 2, m = 300, h = [
276
302
  };
277
303
  async doRefreshDevices() {
278
304
  if (this.disposed || !navigator.mediaDevices?.enumerateDevices || this.state === "starting") return;
279
- let n;
305
+ let e;
280
306
  try {
281
- n = await navigator.mediaDevices.enumerateDevices();
307
+ e = await navigator.mediaDevices.enumerateDevices();
282
308
  } catch {
283
309
  return;
284
310
  }
285
- let r = n.filter((e) => e.kind === "videoinput" && e.deviceId), o = new Set(r.map((e) => e.deviceId));
286
- for (let e of [...this.probeCache.keys()]) o.has(e) || this.probeCache.delete(e);
287
- let s = e() && !t() && this.permission !== "denied", c = [];
311
+ let r = e.filter((e) => e.kind === "videoinput" && e.deviceId), i = new Set(r.map((e) => e.deviceId));
312
+ for (let e of [...this.probeCache.keys()]) i.has(e) || this.probeCache.delete(e);
313
+ let a = c() && !l() && this.permission !== "denied", o = [];
288
314
  for (let e of r) {
289
315
  if (this.disposed) return;
290
- let t = this.probeCache.get(e.deviceId), n = t !== void 0;
291
- if (!n && s) {
292
- let r = await this.probeDevice(e.deviceId);
293
- if (r === void 0) continue;
294
- t = r, n = !0, this.probeCache.set(e.deviceId, r);
316
+ let n = this.probeCache.get(e.deviceId), r = n !== void 0;
317
+ if (!r && a) {
318
+ let t = await this.probeDevice(e.deviceId);
319
+ if (t === void 0) continue;
320
+ n = t, r = !0, this.probeCache.set(e.deviceId, t);
295
321
  }
296
- c.push({
322
+ o.push({
297
323
  deviceId: e.deviceId,
298
324
  label: e.label,
299
- facing: t ?? i(e.label),
300
- probed: n
325
+ facing: n ?? t(e.label),
326
+ probed: r
301
327
  });
302
328
  }
303
- let l = s ? a(c, this.activeDeviceId) : c;
304
- this.devices = l, this.emit();
329
+ let s = a ? n(o, this.activeDeviceId) : o;
330
+ this.devices = s, this.emit();
305
331
  }
306
332
  async probeDevice(e) {
307
333
  if (e === this.activeDeviceId && this.stream) return this.probeCache.get(e) ?? this.activeFacing;
@@ -312,7 +338,7 @@ var f = 1500, p = 2, m = 300, h = [
312
338
  ...y
313
339
  } });
314
340
  let n = t.getVideoTracks()[0];
315
- return c(n?.getSettings().facingMode) ?? null;
341
+ return a(n?.getSettings().facingMode) ?? null;
316
342
  } catch {
317
343
  return;
318
344
  } finally {
@@ -337,6 +363,10 @@ var f = 1500, p = 2, m = 300, h = [
337
363
  step: t.step && t.step > 0 ? t.step : .1
338
364
  }, this.zoom = e.getSettings().zoom ?? t.min) : (this.zoomCapability = null, this.zoom = 1);
339
365
  }
366
+ readTorchCapability(e) {
367
+ let t = e.getCapabilities?.();
368
+ this.torchCapability = t?.torch === !0, this.torch = this.torchCapability ? e.getSettings().torch ?? !1 : !1, this.canLockExposure = Array.isArray(t?.exposureMode) && t.exposureMode.includes("manual");
369
+ }
340
370
  };
341
371
  function C(e) {
342
372
  return e instanceof Error ? e.message || e.name : "Camera could not be started";
@@ -20,8 +20,6 @@ export interface TintPaint {
20
20
  opacity: number;
21
21
  }
22
22
  export declare function resolveTintPaint(color: string, intensity: number): TintPaint;
23
- /** Rotation the frame needs so that "up" in the image matches "up" on screen. */
24
- export declare function orientationAngle(): number;
25
23
  export declare function captureFrame(video: HTMLVideoElement, opts: CaptureOptions): HTMLCanvasElement;
26
24
  export declare function cssFilter(filter: Filter): string;
27
25
  /** Fallback for engines without ctx.filter (older Safari); matches CSS filter matrices. */
@@ -1,6 +1,5 @@
1
- import { isIOS as e } from "./platform.js";
2
1
  //#region src/utilities/camera/capture.ts
3
- function t(e, t, n, r) {
2
+ function e(e, t, n, r) {
4
3
  let i = Math.max(n / e, r / t), a = n / i, o = r / i;
5
4
  return {
6
5
  sx: (e - a) / 2,
@@ -9,7 +8,7 @@ function t(e, t, n, r) {
9
8
  sh: o
10
9
  };
11
10
  }
12
- function n(e, t) {
11
+ function t(e, t) {
13
12
  let n = Math.min(1, Math.max(0, t)), r = e.match(/^#([\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/i)?.[1];
14
13
  if (!r) return {
15
14
  color: e,
@@ -21,49 +20,33 @@ function n(e, t) {
21
20
  opacity: 1
22
21
  };
23
22
  }
24
- function r() {
25
- if (typeof window > "u") return 0;
26
- let e = window.screen?.orientation?.angle;
27
- if (typeof e == "number") return i(e);
28
- let t = window.orientation;
29
- return typeof t == "number" ? i(t) : 0;
23
+ function n(n, a) {
24
+ let o = n.videoWidth, s = n.videoHeight;
25
+ if (!o || !s) throw Error("Video has no frame to capture yet");
26
+ let c = document.createElement("canvas");
27
+ c.width = a.width, c.height = a.height;
28
+ let l = c.getContext("2d");
29
+ if (!l) throw Error("2D canvas context unavailable");
30
+ let u = "filter" in l;
31
+ l.save(), a.mirror && (l.translate(a.width, 0), l.scale(-1, 1)), u && a.filter && a.filter !== "none" && (l.filter = r(a.filter));
32
+ let d = e(o, s, a.width, a.height);
33
+ l.drawImage(n, d.sx, d.sy, d.sw, d.sh, 0, 0, a.width, a.height), l.restore(), !u && a.filter && a.filter !== "none" && i(l, a.filter);
34
+ let f = a.tintColor ? t(a.tintColor, a.tintIntensity ?? 0) : null;
35
+ return f && f.opacity > 0 && (l.save(), l.globalAlpha = f.opacity, l.fillStyle = f.color, l.fillRect(0, 0, a.width, a.height), l.restore()), c;
30
36
  }
31
- function i(e) {
32
- return (Math.round(e / 90) * 90 % 360 + 360) % 360;
33
- }
34
- function a(i, a) {
35
- let c = i.videoWidth, l = i.videoHeight;
36
- if (!c || !l) throw Error("Video has no frame to capture yet");
37
- let u = document.createElement("canvas");
38
- u.width = a.width, u.height = a.height;
39
- let d = u.getContext("2d");
40
- if (!d) throw Error("2D canvas context unavailable");
41
- let f = e() ? r() : 0, p = f === 90 || f === 270, m = "filter" in d;
42
- if (d.save(), a.mirror && (d.translate(a.width, 0), d.scale(-1, 1)), m && a.filter && a.filter !== "none" && (d.filter = o(a.filter)), p) {
43
- d.translate(a.width / 2, a.height / 2), d.rotate(-f * Math.PI / 180);
44
- let e = a.height, n = a.width, r = t(c, l, e, n);
45
- d.drawImage(i, r.sx, r.sy, r.sw, r.sh, -e / 2, -n / 2, e, n);
46
- } else {
47
- let e = t(c, l, a.width, a.height);
48
- d.drawImage(i, e.sx, e.sy, e.sw, e.sh, 0, 0, a.width, a.height);
49
- }
50
- d.restore(), !m && a.filter && a.filter !== "none" && s(d, a.filter);
51
- let h = a.tintColor ? n(a.tintColor, a.tintIntensity ?? 0) : null;
52
- return h && h.opacity > 0 && (d.save(), d.globalAlpha = h.opacity, d.fillStyle = h.color, d.fillRect(0, 0, a.width, a.height), d.restore()), u;
53
- }
54
- function o(e) {
37
+ function r(e) {
55
38
  switch (e) {
56
39
  case "grayscale": return "grayscale(1)";
57
40
  case "sepia": return "sepia(1)";
58
41
  default: return "none";
59
42
  }
60
43
  }
61
- function s(e, t) {
44
+ function i(e, t) {
62
45
  if (t === "none") return;
63
46
  let { width: n, height: r } = e.canvas, i = e.getImageData(0, 0, n, r);
64
- c(i.data, t), e.putImageData(i, 0, 0);
47
+ a(i.data, t), e.putImageData(i, 0, 0);
65
48
  }
66
- function c(e, t) {
49
+ function a(e, t) {
67
50
  for (let n = 0; n < e.length; n += 4) {
68
51
  let r = e[n] ?? 0, i = e[n + 1] ?? 0, a = e[n + 2] ?? 0;
69
52
  if (t === "grayscale") {
@@ -72,11 +55,11 @@ function c(e, t) {
72
55
  } else t === "sepia" && (e[n] = Math.min(255, .393 * r + .769 * i + .189 * a), e[n + 1] = Math.min(255, .349 * r + .686 * i + .168 * a), e[n + 2] = Math.min(255, .272 * r + .534 * i + .131 * a));
73
56
  }
74
57
  }
75
- function l(e, t = {}) {
58
+ function o(e, t = {}) {
76
59
  let n = t.type ?? "image/jpeg", r = t.quality ?? .92;
77
60
  return t.asBlob ? new Promise((t, i) => {
78
61
  e.toBlob((e) => e ? t(e) : i(/* @__PURE__ */ Error("canvas.toBlob returned null")), n, r);
79
62
  }) : Promise.resolve(e.toDataURL(n, r));
80
63
  }
81
64
  //#endregion
82
- export { s as applyPixelFilter, a as captureFrame, t as coverCrop, o as cssFilter, l as exportCanvas, c as filterPixels, r as orientationAngle, n as resolveTintPaint };
65
+ export { i as applyPixelFilter, n as captureFrame, e as coverCrop, r as cssFilter, o as exportCanvas, a as filterPixels, t as resolveTintPaint };
@@ -38,11 +38,17 @@ declare global {
38
38
  max: number;
39
39
  step?: number;
40
40
  };
41
+ torch?: boolean;
42
+ exposureMode?: string[];
41
43
  }
42
44
  interface MediaTrackConstraintSet {
43
45
  zoom?: ConstrainDouble;
46
+ torch?: boolean;
47
+ exposureMode?: ConstrainDOMString;
44
48
  }
45
49
  interface MediaTrackSettings {
46
50
  zoom?: number;
51
+ torch?: boolean;
52
+ exposureMode?: string;
47
53
  }
48
54
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ablok-components",
3
3
  "private": false,
4
- "version": "0.3.136",
4
+ "version": "0.3.138",
5
5
  "type": "module",
6
6
  "dependencies": {
7
7
  "@tiptap/core": "^3.30.0",