@opendaw/lib-dom 0.0.6

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 (56) hide show
  1. package/README.md +1 -0
  2. package/dist/browser.d.ts +10 -0
  3. package/dist/browser.d.ts.map +1 -0
  4. package/dist/browser.js +19 -0
  5. package/dist/compression.d.ts +5 -0
  6. package/dist/compression.d.ts.map +1 -0
  7. package/dist/compression.js +17 -0
  8. package/dist/console-commands.d.ts +8 -0
  9. package/dist/console-commands.d.ts.map +1 -0
  10. package/dist/console-commands.js +55 -0
  11. package/dist/context-2d.d.ts +7 -0
  12. package/dist/context-2d.d.ts.map +1 -0
  13. package/dist/context-2d.js +31 -0
  14. package/dist/css-utils.d.ts +7 -0
  15. package/dist/css-utils.d.ts.map +1 -0
  16. package/dist/css-utils.js +36 -0
  17. package/dist/dragging.d.ts +25 -0
  18. package/dist/dragging.d.ts.map +1 -0
  19. package/dist/dragging.js +105 -0
  20. package/dist/errors.d.ts +5 -0
  21. package/dist/errors.d.ts.map +1 -0
  22. package/dist/errors.js +6 -0
  23. package/dist/events.d.ts +15 -0
  24. package/dist/events.d.ts.map +1 -0
  25. package/dist/events.js +26 -0
  26. package/dist/files.d.ts +5 -0
  27. package/dist/files.d.ts.map +1 -0
  28. package/dist/files.js +62 -0
  29. package/dist/fonts.d.ts +8 -0
  30. package/dist/fonts.d.ts.map +1 -0
  31. package/dist/fonts.js +17 -0
  32. package/dist/frames.d.ts +17 -0
  33. package/dist/frames.d.ts.map +1 -0
  34. package/dist/frames.js +63 -0
  35. package/dist/html.d.ts +21 -0
  36. package/dist/html.d.ts.map +1 -0
  37. package/dist/html.js +121 -0
  38. package/dist/index.d.ts +18 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +25 -0
  41. package/dist/keyboard.d.ts +15 -0
  42. package/dist/keyboard.d.ts.map +1 -0
  43. package/dist/keyboard.js +12 -0
  44. package/dist/modfier-keys.d.ts +18 -0
  45. package/dist/modfier-keys.d.ts.map +1 -0
  46. package/dist/modfier-keys.js +6 -0
  47. package/dist/stream.d.ts +4 -0
  48. package/dist/stream.d.ts.map +1 -0
  49. package/dist/stream.js +21 -0
  50. package/dist/svg.d.ts +15 -0
  51. package/dist/svg.d.ts.map +1 -0
  52. package/dist/svg.js +45 -0
  53. package/dist/terminable.d.ts +13 -0
  54. package/dist/terminable.d.ts.map +1 -0
  55. package/dist/terminable.js +38 -0
  56. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ This package is part of the openDAW SDK
@@ -0,0 +1,10 @@
1
+ export declare namespace Browser {
2
+ const isLocalHost: () => boolean;
3
+ const isMacOS: () => boolean;
4
+ const isWindows: () => boolean;
5
+ const isFirefox: () => boolean;
6
+ const isWeb: () => boolean;
7
+ const isTauriApp: () => boolean;
8
+ const userAgent: string;
9
+ }
10
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA,yBAAiB,OAAO,CAAC;IAGd,MAAM,WAAW,eAA2D,CAAA;IAC5E,MAAM,OAAO,eAAiE,CAAA;IAC9E,MAAM,SAAS,eAAgE,CAAA;IAC/E,MAAM,SAAS,eAA8E,CAAA;IAC7F,MAAM,KAAK,eAAsB,CAAA;IACjC,MAAM,UAAU,eAA8B,CAAA;IAC9C,MAAM,SAAS,QAMH,CAAA;CACtB"}
@@ -0,0 +1,19 @@
1
+ // noinspection PlatformDetectionJS
2
+ export var Browser;
3
+ (function (Browser) {
4
+ const hasLocation = typeof self !== "undefined" && "location" in self && typeof self.location !== undefined;
5
+ const hasNavigator = typeof self !== "undefined" && "navigator" in self && typeof self.navigator !== undefined;
6
+ Browser.isLocalHost = () => hasLocation && location.host.includes("localhost");
7
+ Browser.isMacOS = () => hasNavigator && navigator.userAgent.includes("Mac OS X");
8
+ Browser.isWindows = () => hasNavigator && navigator.userAgent.includes("Windows");
9
+ Browser.isFirefox = () => hasNavigator && navigator.userAgent.toLowerCase().includes("firefox");
10
+ Browser.isWeb = () => !Browser.isTauriApp();
11
+ Browser.isTauriApp = () => "__TAURI__" in window;
12
+ Browser.userAgent = hasNavigator ? navigator.userAgent
13
+ .replace(/^Mozilla\/[\d.]+\s*/, "")
14
+ .replace(/\bAppleWebKit\/[\d.]+\s*/g, "")
15
+ .replace(/\(KHTML, like Gecko\)\s*/g, "")
16
+ .replace(/\bSafari\/[\d.]+\s*/g, "")
17
+ .replace(/\s+/g, " ")
18
+ .trim() : "N/A";
19
+ })(Browser || (Browser = {}));
@@ -0,0 +1,5 @@
1
+ export declare namespace Compression {
2
+ const encode: (buffer: ArrayBuffer, format?: CompressionFormat) => Promise<ArrayBuffer>;
3
+ const decode: (buffer: ArrayBuffer, format?: CompressionFormat) => Promise<ArrayBuffer>;
4
+ }
5
+ //# sourceMappingURL=compression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../src/compression.ts"],"names":[],"mappings":"AAAA,yBAAiB,WAAW,CAAC;IAClB,MAAM,MAAM,GAAU,QAAQ,WAAW,EAAE,SAAQ,iBAA0B,KAAG,OAAO,CAAC,WAAW,CAMzG,CAAA;IAEM,MAAM,MAAM,GAAU,QAAQ,WAAW,EAAE,SAAQ,iBAA0B,KAAG,OAAO,CAAC,WAAW,CAMzG,CAAA;CACJ"}
@@ -0,0 +1,17 @@
1
+ export var Compression;
2
+ (function (Compression) {
3
+ Compression.encode = async (buffer, format = "gzip") => {
4
+ const stream = new CompressionStream(format);
5
+ const writer = stream.writable.getWriter();
6
+ writer.write(new Uint8Array(buffer));
7
+ writer.close();
8
+ return new Response(stream.readable).arrayBuffer();
9
+ };
10
+ Compression.decode = async (buffer, format = "gzip") => {
11
+ const stream = new DecompressionStream(format);
12
+ const writer = stream.writable.getWriter();
13
+ writer.write(new Uint8Array(buffer));
14
+ writer.close();
15
+ return new Response(stream.readable).arrayBuffer();
16
+ };
17
+ })(Compression || (Compression = {}));
@@ -0,0 +1,8 @@
1
+ import { AnyFunc, ObservableValue, Procedure, Provider } from "@opendaw/lib-std";
2
+ export type DotPath = string;
3
+ export declare namespace ConsoleCommands {
4
+ const exportMethod: (path: DotPath, callback: AnyFunc) => void;
5
+ const exportBoolean: (path: DotPath, init?: boolean) => ObservableValue<boolean>;
6
+ const exportAccessor: (path: DotPath, getter: Provider<unknown>, setter?: Procedure<any>) => void;
7
+ }
8
+ //# sourceMappingURL=console-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console-commands.d.ts","sourceRoot":"","sources":["../src/console-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAA0C,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AAEtH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAA;AAE5B,yBAAiB,eAAe,CAAC;IACtB,MAAM,YAAY,GAAI,MAAM,OAAO,EAAE,UAAU,OAAO,KAAG,IAC9B,CAAA;IAE3B,MAAM,aAAa,GAAI,MAAM,OAAO,EAAE,OAAM,OAAe,KAAG,eAAe,CAAC,OAAO,CAQ3F,CAAA;IAEM,MAAM,cAAc,GAAI,MAAM,OAAO,EAAE,QAAQ,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAQ,SAAS,CAAC,GAAG,CAAkB,KAAG,IAsB7G,CAAA;CAcT"}
@@ -0,0 +1,55 @@
1
+ import { DefaultObservableValue, EmptyProcedure } from "@opendaw/lib-std";
2
+ export var ConsoleCommands;
3
+ (function (ConsoleCommands) {
4
+ ConsoleCommands.exportMethod = (path, callback) => store(path, { value: callback });
5
+ ConsoleCommands.exportBoolean = (path, init = false) => {
6
+ const observableValue = new DefaultObservableValue(init);
7
+ ConsoleCommands.exportAccessor(path, () => observableValue.getValue(), input => {
8
+ const value = Boolean(input);
9
+ console.debug(`set to ${value}`);
10
+ observableValue.setValue(value);
11
+ });
12
+ return observableValue;
13
+ };
14
+ ConsoleCommands.exportAccessor = (path, getter, setter = EmptyProcedure) => store(path, {
15
+ get: () => {
16
+ try {
17
+ console.debug(getter());
18
+ return 0;
19
+ }
20
+ catch (error) {
21
+ console.error(error);
22
+ return 1;
23
+ }
24
+ },
25
+ set: (value) => {
26
+ try {
27
+ setter(value);
28
+ return getter();
29
+ }
30
+ catch (error) {
31
+ console.error(error);
32
+ return 1;
33
+ }
34
+ },
35
+ enumerable: false,
36
+ configurable: false
37
+ });
38
+ const global = (() => { try {
39
+ return self;
40
+ }
41
+ catch (_) {
42
+ return {};
43
+ } })();
44
+ const scope = (global["opendaw"] ??= {});
45
+ const store = (path, attributes) => {
46
+ const levels = path.split(".");
47
+ const name = levels.splice(-1)[0];
48
+ let current = scope;
49
+ for (const level of levels) {
50
+ current = (current[level] ??= {});
51
+ }
52
+ Object.defineProperty(current, name, attributes);
53
+ console.debug(`Console command 'opendaw.${path}' exported`);
54
+ };
55
+ })(ConsoleCommands || (ConsoleCommands = {}));
@@ -0,0 +1,7 @@
1
+ export declare namespace Context2d {
2
+ const truncateText: (context: CanvasRenderingContext2D, text: string, maxWidth: number) => {
3
+ text: string;
4
+ width: number;
5
+ };
6
+ }
7
+ //# sourceMappingURL=context-2d.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-2d.d.ts","sourceRoot":"","sources":["../src/context-2d.ts"],"names":[],"mappings":"AAIA,yBAAiB,SAAS,CAAC;IAChB,MAAM,YAAY,GAAI,SAAS,wBAAwB,EAAE,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG;QAC7F,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAA;KAoBhB,CAAA;CACJ"}
@@ -0,0 +1,31 @@
1
+ const ellipsis = "…";
2
+ export var Context2d;
3
+ (function (Context2d) {
4
+ Context2d.truncateText = (context, text, maxWidth) => {
5
+ if (text.length === 0) {
6
+ return { text: "", width: 0 };
7
+ }
8
+ let width = context.measureText(text).width;
9
+ if (width <= maxWidth) {
10
+ return { text, width };
11
+ }
12
+ const ellipseWidth = context.measureText(ellipsis).width;
13
+ let l = 0 | 0;
14
+ let r = text.length | 0;
15
+ while (l < r) {
16
+ const mid = (r + l) >>> 1;
17
+ width = context.measureText(text.substring(0, mid + 1)).width + ellipseWidth;
18
+ if (width <= maxWidth) {
19
+ l = mid + 1;
20
+ }
21
+ else {
22
+ r = mid;
23
+ }
24
+ }
25
+ if (l === 0) {
26
+ return { text: "", width: 0 };
27
+ }
28
+ const result = text.substring(0, l);
29
+ return { text: result + ellipsis, width: context.measureText(result).width + ellipseWidth };
30
+ };
31
+ })(Context2d || (Context2d = {}));
@@ -0,0 +1,7 @@
1
+ export declare namespace CssUtils {
2
+ const calc: (term: string, size: number, em: number) => number;
3
+ const registerCustomCursor: (identifier: number, data: string) => Map<number, string>;
4
+ const setCursor: (identifier: CssUtils.Cursor | number, doc?: Document) => void;
5
+ type Cursor = "alias" | "all-scroll" | "auto" | "cell" | "context-menu" | "col-resize" | "copy" | "crosshair" | "default" | "e-resize" | "ew-resize" | "grab" | "grabbing" | "help" | "move" | "n-resize" | "ne-resize" | "nesw-resize" | "ns-resize" | "nw-resize" | "nwse-resize" | "no-drop" | "none" | "not-allowed" | "pointer" | "progress" | "row-resize" | "s-resize" | "se-resize" | "sw-resize" | "text" | "url" | "w-resize" | "wait" | "zoom-in" | "zoom-out";
6
+ }
7
+ //# sourceMappingURL=css-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-utils.d.ts","sourceRoot":"","sources":["../src/css-utils.ts"],"names":[],"mappings":"AAEA,yBAAiB,QAAQ,CAAC;IACf,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,MAAM,MAAM,EAAE,IAAI,MAAM,KAAG,MAmB7D,CAAA;IAIM,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,MAAM,MAAM,wBAAwC,CAAA;IAEtG,MAAM,SAAS,GAAI,YAAY,QAAQ,CAAC,MAAM,GAAG,MAAM,EAAE,MAAK,QAAmB,SAIvF,CAAA;IAED,KAAY,MAAM,GACZ,OAAO,GACP,YAAY,GACZ,MAAM,GACN,MAAM,GACN,cAAc,GACd,YAAY,GACZ,MAAM,GACN,WAAW,GACX,SAAS,GACT,UAAU,GACV,WAAW,GACX,MAAM,GACN,UAAU,GACV,MAAM,GACN,MAAM,GACN,UAAU,GACV,WAAW,GACX,aAAa,GACb,WAAW,GACX,WAAW,GACX,aAAa,GACb,SAAS,GACT,MAAM,GACN,aAAa,GACb,SAAS,GACT,UAAU,GACV,YAAY,GACZ,UAAU,GACV,WAAW,GACX,WAAW,GACX,MAAM,GACN,KAAK,GACL,UAAU,GACV,MAAM,GACN,SAAS,GACT,UAAU,CAAA;CACnB"}
@@ -0,0 +1,36 @@
1
+ import { panic } from "@opendaw/lib-std";
2
+ export var CssUtils;
3
+ (function (CssUtils) {
4
+ CssUtils.calc = (term, size, em) => {
5
+ const regex = /([0-9]*\.?[0-9]+)([a-zA-Z%]*)/g;
6
+ let result = term;
7
+ result.split(/\+|(?<!\d)-/)
8
+ .flatMap(result => Array.from(result.matchAll(regex)))
9
+ .forEach(([replace, digits, unit]) => {
10
+ const number = parseFloat(digits);
11
+ if (isNaN(number)) {
12
+ return panic(`${replace} does not contain a number`);
13
+ }
14
+ if (unit === "em") {
15
+ result = result.replaceAll(replace, `${number * em}`);
16
+ }
17
+ else if (unit === "%") {
18
+ result = result.replaceAll(replace, `${number / 100.0 * size}`);
19
+ }
20
+ else if (unit === "px") {
21
+ result = result.replaceAll(replace, `${number}`);
22
+ }
23
+ else {
24
+ return panic(`Unknown unit '${unit}'`);
25
+ }
26
+ });
27
+ return Function(`return ${result}`)();
28
+ };
29
+ const customCursors = new Map();
30
+ CssUtils.registerCustomCursor = (identifier, data) => customCursors.set(identifier, data);
31
+ CssUtils.setCursor = (identifier, doc = document) => {
32
+ doc.documentElement.style.cursor = typeof identifier === "number"
33
+ ? customCursors.get(identifier) ?? "auto"
34
+ : identifier;
35
+ };
36
+ })(CssUtils || (CssUtils = {}));
@@ -0,0 +1,25 @@
1
+ import { Func, Option, Terminable } from "@opendaw/lib-std";
2
+ import { PointerCaptureTarget } from "./events";
3
+ export declare namespace Dragging {
4
+ interface Process {
5
+ update(event: Event): void;
6
+ cancel?(): void;
7
+ approve?(): void;
8
+ finally?(): void;
9
+ abortSignal?: AbortSignal;
10
+ }
11
+ interface Event {
12
+ readonly clientX: number;
13
+ readonly clientY: number;
14
+ readonly altKey: boolean;
15
+ readonly shiftKey: boolean;
16
+ readonly ctrlKey: boolean;
17
+ }
18
+ interface ProcessOptions {
19
+ multiTouch?: boolean;
20
+ immediate?: boolean;
21
+ permanentUpdates?: boolean;
22
+ }
23
+ const attach: <T extends PointerCaptureTarget>(target: T, factory: Func<PointerEvent, Option<Process>>, options?: ProcessOptions) => Terminable;
24
+ }
25
+ //# sourceMappingURL=dragging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dragging.d.ts","sourceRoot":"","sources":["../src/dragging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAA;AAGrE,OAAO,EAAS,oBAAoB,EAAC,MAAM,UAAU,CAAA;AAGrD,yBAAiB,QAAQ,CAAC;IACtB,UAAiB,OAAO;QACpB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;QAC1B,MAAM,CAAC,IAAI,IAAI,CAAA;QACf,OAAO,CAAC,IAAI,IAAI,CAAA;QAChB,OAAO,CAAC,IAAI,IAAI,CAAA;QAChB,WAAW,CAAC,EAAE,WAAW,CAAA;KAC5B;IAED,UAAiB,KAAK;QAClB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;QACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;QAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAC5B;IAED,UAAiB,cAAc;QAC3B,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAC7B;IAEM,MAAM,MAAM,GAAI,CAAC,SAAS,oBAAoB,EAAE,QAAQ,CAAC,EACT,SAAS,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,EAC5C,UAAU,cAAc,KAAG,UA0FjF,CAAA;CACJ"}
@@ -0,0 +1,105 @@
1
+ import { Terminable, Terminator } from "@opendaw/lib-std";
2
+ import { Browser } from "./browser";
3
+ import { AnimationFrame } from "./frames";
4
+ import { Events } from "./events";
5
+ import { Keyboard } from "./keyboard";
6
+ export var Dragging;
7
+ (function (Dragging) {
8
+ Dragging.attach = (target, factory, options) => {
9
+ const processCycle = new Terminator();
10
+ return Terminable.many(processCycle, Events.subscribe(target, "pointerdown", (event) => {
11
+ if (options?.multiTouch !== true && !event.isPrimary) {
12
+ return;
13
+ }
14
+ if (event.buttons !== 1 || (Browser.isMacOS() && event.ctrlKey)) {
15
+ return;
16
+ }
17
+ const option = factory(event);
18
+ if (option.isEmpty()) {
19
+ return;
20
+ }
21
+ const process = option.unwrap();
22
+ const pointerId = event.pointerId;
23
+ event.stopPropagation();
24
+ event.stopImmediatePropagation();
25
+ target.setPointerCapture(pointerId);
26
+ const moveEvent = {
27
+ clientX: event.clientX,
28
+ clientY: event.clientY,
29
+ altKey: event.altKey,
30
+ shiftKey: event.shiftKey,
31
+ ctrlKey: Keyboard.isControlKey(event)
32
+ };
33
+ if (options?.immediate === true) {
34
+ process.update(moveEvent);
35
+ }
36
+ if (options?.permanentUpdates === true) {
37
+ processCycle.own(AnimationFrame.add(() => process.update(moveEvent)));
38
+ processCycle.own(Events.subscribe(target, "pointermove", (event) => {
39
+ if (event.pointerId === pointerId) {
40
+ moveEvent.clientX = event.clientX;
41
+ moveEvent.clientY = event.clientY;
42
+ moveEvent.altKey = event.altKey;
43
+ moveEvent.shiftKey = event.shiftKey;
44
+ moveEvent.ctrlKey = Keyboard.isControlKey(event);
45
+ }
46
+ }));
47
+ }
48
+ else {
49
+ processCycle.own(Events.subscribe(target, "pointermove", (event) => {
50
+ if (event.pointerId === pointerId) {
51
+ moveEvent.clientX = event.clientX;
52
+ moveEvent.clientY = event.clientY;
53
+ moveEvent.altKey = event.altKey;
54
+ moveEvent.shiftKey = event.shiftKey;
55
+ moveEvent.ctrlKey = Keyboard.isControlKey(event);
56
+ process.update(moveEvent);
57
+ }
58
+ }));
59
+ }
60
+ const cancel = () => {
61
+ process.cancel?.call(process);
62
+ process.finally?.call(process);
63
+ processCycle.terminate();
64
+ };
65
+ processCycle.ownAll(Events.subscribe(target, "pointerup", (event) => {
66
+ if (event.pointerId === pointerId) {
67
+ process.approve?.call(process);
68
+ process.finally?.call(process);
69
+ processCycle.terminate();
70
+ }
71
+ }, { capture: true }), Events.subscribe(target, "pointercancel", (event) => {
72
+ console.debug(event.type);
73
+ if (event.pointerId === pointerId) {
74
+ target.releasePointerCapture(pointerId);
75
+ cancel();
76
+ }
77
+ }, { capture: true }), Events.subscribe(self, "beforeunload", (_event) => {
78
+ // Workaround for Chrome (does not release or cancel pointer)
79
+ target.releasePointerCapture(pointerId);
80
+ cancel();
81
+ }, { capture: true }), Events.subscribe(window, "keydown", (event) => {
82
+ moveEvent.altKey = event.altKey;
83
+ moveEvent.shiftKey = event.shiftKey;
84
+ moveEvent.ctrlKey = Keyboard.isControlKey(event);
85
+ if (event.key === "Escape") {
86
+ cancel();
87
+ }
88
+ else {
89
+ process.update(moveEvent);
90
+ }
91
+ }), Events.subscribe(window, "keyup", (event) => {
92
+ moveEvent.altKey = event.altKey;
93
+ moveEvent.shiftKey = event.shiftKey;
94
+ moveEvent.ctrlKey = Keyboard.isControlKey(event);
95
+ process.update(moveEvent);
96
+ }));
97
+ if (process.abortSignal) {
98
+ processCycle.own(Events.subscribe(process.abortSignal, "abort", () => {
99
+ target.releasePointerCapture(pointerId);
100
+ cancel();
101
+ }));
102
+ }
103
+ }));
104
+ };
105
+ })(Dragging || (Dragging = {}));
@@ -0,0 +1,5 @@
1
+ export declare namespace Errors {
2
+ const AbortError: number | Readonly<DOMException>;
3
+ const isAbort: (error: unknown) => boolean;
4
+ }
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,yBAAiB,MAAM,CAAC;IACb,MAAM,UAAU,iCACkC,CAAA;IAElD,MAAM,OAAO,GAAI,OAAO,OAAO,YACoD,CAAA;CAC7F"}
package/dist/errors.js ADDED
@@ -0,0 +1,6 @@
1
+ export var Errors;
2
+ (function (Errors) {
3
+ Errors.AbortError = typeof DOMException === "undefined"
4
+ ? NaN : Object.freeze(new DOMException("AbortError"));
5
+ Errors.isAbort = (error) => error === Errors.AbortError || (error instanceof DOMException && error.name === "AbortError");
6
+ })(Errors || (Errors = {}));
@@ -0,0 +1,15 @@
1
+ import { Nullable, Procedure, Subscription } from "@opendaw/lib-std";
2
+ export declare class Events {
3
+ static subscribe<K extends keyof WindowEventMap>(eventTarget: EventTarget, type: K, listener: (ev: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): Subscription;
4
+ static subscribeAny<E extends Event>(eventTarget: EventTarget, type: string, listener: (event: E) => void, options?: boolean | AddEventListenerOptions): Subscription;
5
+ static DOUBLE_DOWN_THRESHOLD: 200;
6
+ static subscribeDblDwn: (eventTarget: EventTarget, listener: (event: PointerEvent) => void) => Subscription;
7
+ static readonly PreventDefault: Procedure<Event>;
8
+ static readonly isTextInput: (target: Nullable<EventTarget>) => boolean;
9
+ }
10
+ export interface PointerCaptureTarget extends EventTarget {
11
+ setPointerCapture(pointerId: number): void;
12
+ releasePointerCapture(pointerId: number): void;
13
+ hasPointerCapture(pointerId: number): boolean;
14
+ }
15
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAE7E,qBAAa,MAAM;IACf,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EACzC,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAAG,YAAY;IAK3G,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,KAAK,EAAE,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAAG,YAAY;IAK/F,MAAM,CAAC,qBAAqB,EAAG,GAAG,CAAS;IAE3C,MAAM,CAAC,eAAe,GAAI,aAAa,WAAW,EAAE,UAAU,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KAAG,YAAY,CASzG;IAED,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,KAAK,CAAC,CAAkC;IAElF,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAI,QAAQ,QAAQ,CAAC,WAAW,CAAC,KAAG,OAAO,CAEqB;CAC9F;AAED,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACrD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1C,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9C,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;CAChD"}
package/dist/events.js ADDED
@@ -0,0 +1,26 @@
1
+ import { isDefined } from "@opendaw/lib-std";
2
+ export class Events {
3
+ static subscribe(eventTarget, type, listener, options) {
4
+ eventTarget.addEventListener(type, listener, options);
5
+ return { terminate: () => eventTarget.removeEventListener(type, listener, options) };
6
+ }
7
+ static subscribeAny(eventTarget, type, listener, options) {
8
+ eventTarget.addEventListener(type, listener, options);
9
+ return { terminate: () => eventTarget.removeEventListener(type, listener, options) };
10
+ }
11
+ static DOUBLE_DOWN_THRESHOLD = 200;
12
+ static subscribeDblDwn = (eventTarget, listener) => {
13
+ let lastDownTime = 0.0;
14
+ return this.subscribe(eventTarget, "pointerdown", event => {
15
+ const now = performance.now();
16
+ if (now - lastDownTime < this.DOUBLE_DOWN_THRESHOLD) {
17
+ listener(event);
18
+ }
19
+ lastDownTime = now;
20
+ }, { capture: true });
21
+ };
22
+ static PreventDefault = event => event.preventDefault();
23
+ static isTextInput = (target) => target instanceof HTMLInputElement
24
+ || target instanceof HTMLTextAreaElement
25
+ || (target instanceof HTMLElement && isDefined(target.getAttribute("contenteditable")));
26
+ }
@@ -0,0 +1,5 @@
1
+ export declare namespace Files {
2
+ const save: (arrayBuffer: ArrayBuffer, options?: SaveFilePickerOptions) => Promise<string>;
3
+ const open: (options?: OpenFilePickerOptions) => Promise<ReadonlyArray<File>>;
4
+ }
5
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAGA,yBAAiB,KAAK,CAAC;IACZ,MAAM,IAAI,GAAU,aAAa,WAAW,EAAE,UAAU,qBAAqB,KAAG,OAAO,CAAC,MAAM,CAkBpG,CAAA;IAEM,MAAM,IAAI,GAAU,UAAU,qBAAqB,KAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAgCvF,CAAA;CACJ"}
package/dist/files.js ADDED
@@ -0,0 +1,62 @@
1
+ import { Arrays, asDefined, isDefined } from "@opendaw/lib-std";
2
+ import { Promises } from "@opendaw/lib-runtime";
3
+ export var Files;
4
+ (function (Files) {
5
+ Files.save = async (arrayBuffer, options) => {
6
+ if (isDefined(window.showSaveFilePicker)) {
7
+ const handle = await window.showSaveFilePicker(options);
8
+ const writable = await handle.createWritable();
9
+ await writable.truncate(0);
10
+ await writable.write(arrayBuffer);
11
+ await writable.close();
12
+ return handle.name ?? "unknown";
13
+ }
14
+ else {
15
+ const blob = new Blob([arrayBuffer]);
16
+ const url = URL.createObjectURL(blob);
17
+ const anchor = document.createElement("a");
18
+ anchor.href = url;
19
+ anchor.download = options?.suggestedName ?? `unknown`;
20
+ anchor.click();
21
+ URL.revokeObjectURL(url);
22
+ return options?.suggestedName ?? "Unknown";
23
+ }
24
+ };
25
+ Files.open = async (options) => {
26
+ if (isDefined(window.showOpenFilePicker)) {
27
+ const { status, value: fileHandles, error } = await Promises.tryCatch(window.showOpenFilePicker(options));
28
+ if (status === "rejected") {
29
+ return Promise.reject(error);
30
+ }
31
+ return Promise.all(fileHandles.map(fileHandle => fileHandle.getFile()));
32
+ }
33
+ else {
34
+ return new Promise((resolve, reject) => {
35
+ if (isDefined(options)) {
36
+ console.warn("FileApi.showOpenFilePicker is emulated in this browser. OpenFilePickerOptions are ignored.");
37
+ }
38
+ const fileInput = document.createElement("input");
39
+ fileInput.type = "file";
40
+ fileInput.multiple = options?.multiple ?? false;
41
+ fileInput.style.display = "none";
42
+ fileInput.addEventListener("cancel", async () => {
43
+ fileInput.remove();
44
+ reject(new DOMException("cancel", "AbortError"));
45
+ });
46
+ fileInput.addEventListener("change", async (event) => {
47
+ const target = event.target;
48
+ const files = target.files;
49
+ if (isDefined(files)) {
50
+ resolve(Arrays.create(index => asDefined(files.item(index), `No file at index ${index}`), files.length));
51
+ }
52
+ else {
53
+ reject(new DOMException("cancel", "AbortError"));
54
+ }
55
+ fileInput.remove();
56
+ });
57
+ document.body.appendChild(fileInput);
58
+ fileInput.click();
59
+ });
60
+ }
61
+ };
62
+ })(Files || (Files = {}));
@@ -0,0 +1,8 @@
1
+ export type FontFaceProperties = {
2
+ "font-family": string;
3
+ "font-style": "normal" | "italic" | "oblique";
4
+ "font-weight": 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | "normal" | "bold" | "bolder" | "lighter";
5
+ "src": string;
6
+ };
7
+ export declare const loadFont: (properties: FontFaceProperties) => Promise<void>;
8
+ //# sourceMappingURL=fonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;IAC7C,aAAa,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACpH,KAAK,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,QAAQ,GAAU,YAAY,kBAAkB,kBAe5D,CAAA"}
package/dist/fonts.js ADDED
@@ -0,0 +1,17 @@
1
+ export const loadFont = async (properties) => {
2
+ try {
3
+ const response = await fetch(properties.src, { credentials: "omit" });
4
+ const fontData = await response.arrayBuffer();
5
+ const fontFace = new FontFace(properties["font-family"], fontData, {
6
+ display: "block",
7
+ weight: String(properties["font-weight"]),
8
+ style: properties["font-style"]
9
+ });
10
+ await fontFace.load();
11
+ document.fonts.add(fontFace);
12
+ console.debug(`font-family: '${fontFace.family}'`);
13
+ }
14
+ catch (error) {
15
+ console.error(error);
16
+ }
17
+ };
@@ -0,0 +1,17 @@
1
+ import { Exec, Terminable } from "@opendaw/lib-std";
2
+ export declare namespace AnimationFrame {
3
+ const add: (exec: Exec) => Terminable;
4
+ const once: (exec: Exec) => void;
5
+ const start: () => void;
6
+ const terminate: () => void;
7
+ }
8
+ export declare const deferNextFrame: (exec: Exec) => DeferExec;
9
+ export declare class DeferExec implements Terminable {
10
+ #private;
11
+ constructor(exec: Exec);
12
+ readonly request: () => void;
13
+ readonly immediate: () => void;
14
+ cancel(): void;
15
+ terminate(): void;
16
+ }
17
+ //# sourceMappingURL=frames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAO,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAEtD,yBAAiB,cAAc,CAAC;IAOrB,MAAM,GAAG,GAAI,MAAM,IAAI,KAAG,UAGhC,CAAA;IAEM,MAAM,IAAI,GAAI,MAAM,IAAI,KAAG,IAAgC,CAAA;IAE3D,MAAM,KAAK,QAAO,IAaxB,CAAA;IAEM,MAAM,SAAS,QAAO,IAM5B,CAAA;CACJ;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,IAAI,KAAG,SAAgC,CAAA;AAE5E,qBAAa,SAAU,YAAW,UAAU;;gBAM5B,IAAI,EAAE,IAAI;IAEtB,QAAQ,CAAC,OAAO,QAAO,IAAI,CAI1B;IAED,QAAQ,CAAC,SAAS,QAAO,IAAI,CAI5B;IAED,MAAM,IAAI,IAAI;IACd,SAAS,IAAI,IAAI;CAOpB"}
package/dist/frames.js ADDED
@@ -0,0 +1,63 @@
1
+ export var AnimationFrame;
2
+ (function (AnimationFrame) {
3
+ const nonrecurring = new Set();
4
+ const recurring = new Set();
5
+ const queue = new Array();
6
+ let id = -1;
7
+ AnimationFrame.add = (exec) => {
8
+ recurring.add(exec);
9
+ return { terminate: () => recurring.delete(exec) };
10
+ };
11
+ AnimationFrame.once = (exec) => { nonrecurring.add(exec); };
12
+ AnimationFrame.start = () => {
13
+ console.debug("AnimationFrame start");
14
+ const exe = () => {
15
+ if (recurring.size > 0 || nonrecurring.size > 0) {
16
+ recurring.forEach((exec) => queue.push(exec));
17
+ nonrecurring.forEach((exec) => queue.push(exec));
18
+ nonrecurring.clear();
19
+ queue.forEach((exec) => exec());
20
+ queue.length = 0;
21
+ }
22
+ id = requestAnimationFrame(exe);
23
+ };
24
+ id = requestAnimationFrame(exe);
25
+ };
26
+ AnimationFrame.terminate = () => {
27
+ console.debug("AnimationFrame terminate");
28
+ nonrecurring.clear();
29
+ recurring.clear();
30
+ queue.length = 0;
31
+ cancelAnimationFrame(id);
32
+ };
33
+ })(AnimationFrame || (AnimationFrame = {}));
34
+ export const deferNextFrame = (exec) => new DeferExec(exec);
35
+ export class DeferExec {
36
+ #exec;
37
+ #requested = false;
38
+ #disabled = false;
39
+ constructor(exec) { this.#exec = exec; }
40
+ request = () => {
41
+ if (this.#requested || this.#disabled) {
42
+ return;
43
+ }
44
+ this.#requested = true;
45
+ AnimationFrame.once(this.#fire);
46
+ };
47
+ immediate = () => {
48
+ if (this.#disabled) {
49
+ return;
50
+ }
51
+ this.#requested = true;
52
+ this.#fire();
53
+ };
54
+ cancel() { this.#requested = false; }
55
+ terminate() { this.#disabled = true; }
56
+ #fire = () => {
57
+ if (this.#disabled || !this.#requested) {
58
+ return;
59
+ }
60
+ this.#requested = false;
61
+ this.#exec();
62
+ };
63
+ }
package/dist/html.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { Color, int, Subscription } from "@opendaw/lib-std";
2
+ export declare namespace Html {
3
+ const parse: (source: string) => HTMLOrSVGElement & Element;
4
+ const empty: (element: Element) => void;
5
+ const replace: (element: Element, ...elements: ReadonlyArray<string | Element>) => void;
6
+ const query: <E extends Element>(selectors: string, parent?: ParentNode) => E;
7
+ const queryAll: <E extends Element>(selectors: string, parent?: ParentNode) => ReadonlyArray<E>;
8
+ const nextID: () => string;
9
+ const adoptStyleSheet: (classDefinition: string, prefix?: string) => string;
10
+ const buildClassList: (...input: Array<string | false | undefined>) => string;
11
+ const readCssVarColor: (...cssValues: Array<string>) => Array<Color.RGBA>;
12
+ const watchResize: (target: Element, callback: (entry: ResizeObserverEntry, observer: ResizeObserver) => void, options?: ResizeObserverOptions) => Subscription;
13
+ const watchIntersection: (target: Element, callback: IntersectionObserverCallback, options?: IntersectionObserverInit) => Subscription;
14
+ const secureBoundingBox: (element: Element) => DOMRect;
15
+ const unfocus: (owner?: Window) => void;
16
+ const selectContent: (element: HTMLElement) => void;
17
+ const unselectContent: (element: HTMLElement) => void;
18
+ const limitChars: <T extends HTMLElement, K extends keyof T & string>(element: T, property: K, limit: int) => undefined;
19
+ const EmptyGif: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=";
20
+ }
21
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAE,GAAG,EAA0B,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAEpG,yBAAiB,IAAI,CAAC;IACX,MAAM,KAAK,GAAI,QAAQ,MAAM,KAAG,gBAAgB,GAAG,OAUzD,CAAA;IAEM,MAAM,KAAK,GAAI,SAAS,OAAO,KAAG,IAA2E,CAAA;IAE7G,MAAM,OAAO,GAAI,SAAS,OAAO,EAAE,GAAG,UAAU,aAAa,CAAC,MAAM,GAAG,OAAO,CAAC,KAAG,IAGxF,CAAA;IAEM,MAAM,KAAK,GAAI,CAAC,SAAS,OAAO,EAAE,WAAW,MAAM,EAAE,SAAQ,UAAqB,KAAG,CACzC,CAAA;IAE5C,MAAM,QAAQ,GAAI,CAAC,SAAS,OAAO,EAAE,WAAW,MAAM,EAAE,SAAQ,UAAqB,KAAG,aAAa,CAAC,CAAC,CAC5D,CAAA;IAE3C,MAAM,MAAM,QAEJ,MACX,CAAA;IAEG,MAAM,eAAe,GAAI,iBAAiB,MAAM,EAAE,SAAS,MAAM,KAAG,MAU1E,CAAA;IAGM,MAAM,cAAc,GAAI,GAAG,OAAO,KAAK,CAAC,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC,WACX,CAAA;IAExD,MAAM,eAAe,GAAI,GAAG,WAAW,KAAK,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAS7E,CAAA;IAEM,MAAM,WAAW,GAAI,QAAQ,OAAO,EACf,UAAU,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,cAAc,KAAK,IAAI,EACxE,UAAU,qBAAqB,KAAG,YAI7D,CAAA;IAEM,MAAM,iBAAiB,GAAI,QAAQ,OAAO,EACf,UAAU,4BAA4B,EACtC,UAAU,wBAAwB,KAAG,YAItE,CAAA;IAGM,MAAM,iBAAiB,GAAI,SAAS,OAAO,KAAG,OASpD,CAAA;IAEM,MAAM,OAAO,GAAI,QAAO,MAAa,SAK3C,CAAA;IAEM,MAAM,aAAa,GAAI,SAAS,WAAW,SAQjD,CAAA;IAEM,MAAM,eAAe,GAAI,SAAS,WAAW,SAMnD,CAAA;IAEM,MAAM,UAAU,GAAI,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,cAkBhH,CAAA;IAEM,MAAM,QAAQ,EAAG,oHAA6H,CAAA;CACxJ"}
package/dist/html.js ADDED
@@ -0,0 +1,121 @@
1
+ import { asDefined, assert, Color, isDefined, panic, Rect } from "@opendaw/lib-std";
2
+ export var Html;
3
+ (function (Html) {
4
+ Html.parse = (source) => {
5
+ const template = document.createElement("div");
6
+ template.innerHTML = source;
7
+ if (template.childElementCount !== 1) {
8
+ return panic(`Source html has more than one root elements: '${source}'`);
9
+ }
10
+ const child = template.firstChild;
11
+ return child instanceof HTMLElement || child instanceof SVGSVGElement
12
+ ? child
13
+ : panic(`Cannot parse to HTMLOrSVGElement from '${source}'`);
14
+ };
15
+ Html.empty = (element) => { while (element.firstChild !== null) {
16
+ element.firstChild.remove();
17
+ } };
18
+ Html.replace = (element, ...elements) => {
19
+ Html.empty(element);
20
+ element.append(...elements);
21
+ };
22
+ Html.query = (selectors, parent = document) => asDefined(parent.querySelector(selectors));
23
+ Html.queryAll = (selectors, parent = document) => Array.from(parent.querySelectorAll(selectors));
24
+ Html.nextID = (() => {
25
+ let id = 0 | 0;
26
+ return () => (++id).toString(16).padStart(4, "0");
27
+ })();
28
+ Html.adoptStyleSheet = (classDefinition, prefix) => {
29
+ assert(classDefinition.includes("component"), `No 'component' found in: ${classDefinition}`);
30
+ const className = `${prefix ?? "C"}${Html.nextID()}`;
31
+ const sheet = new CSSStyleSheet();
32
+ sheet.replaceSync(classDefinition.replaceAll("component", `.${className}`));
33
+ if (sheet.cssRules.length === 0) {
34
+ return panic(`No cssRules found in: ${classDefinition}`);
35
+ }
36
+ document.adoptedStyleSheets.push(sheet);
37
+ return className;
38
+ };
39
+ // Allows conditional accumulation of classNames
40
+ Html.buildClassList = (...input) => input.filter(x => x !== false && x !== undefined).join(" ");
41
+ Html.readCssVarColor = (...cssValues) => {
42
+ const element = document.createElement("div");
43
+ document.body.appendChild(element);
44
+ const colors = cssValues.map(value => {
45
+ element.style.color = value;
46
+ return Color.parseCssRgbOrRgba(getComputedStyle(element).color);
47
+ });
48
+ element.remove();
49
+ return colors;
50
+ };
51
+ Html.watchResize = (target, callback, options) => {
52
+ const observer = new ResizeObserver(([first], observer) => callback(first, observer));
53
+ observer.observe(target, options);
54
+ return { terminate: () => observer.disconnect() };
55
+ };
56
+ Html.watchIntersection = (target, callback, options) => {
57
+ const observer = new IntersectionObserver(callback, options);
58
+ observer.observe(target);
59
+ return { terminate: () => observer.disconnect() };
60
+ };
61
+ // handles cases like 'display: contents', where the bounding box is always empty, although the children have dimensions
62
+ Html.secureBoundingBox = (element) => {
63
+ let elemRect = element.getBoundingClientRect();
64
+ if (!Rect.isEmpty(elemRect)) {
65
+ return elemRect;
66
+ }
67
+ for (const child of element.children) {
68
+ Rect.union(elemRect, Html.secureBoundingBox(child));
69
+ }
70
+ return elemRect;
71
+ };
72
+ Html.unfocus = (owner = self) => {
73
+ const element = owner.document.activeElement;
74
+ if (element !== null && "blur" in element && typeof element.blur === "function") {
75
+ element.blur();
76
+ }
77
+ };
78
+ Html.selectContent = (element) => {
79
+ const range = document.createRange();
80
+ const selection = window.getSelection();
81
+ if (isDefined(selection)) {
82
+ range.selectNodeContents(element);
83
+ selection.removeAllRanges();
84
+ selection.addRange(range);
85
+ }
86
+ };
87
+ Html.unselectContent = (element) => {
88
+ const selection = window.getSelection();
89
+ if (!isDefined(selection) || selection.rangeCount === 0) {
90
+ return;
91
+ }
92
+ if (element.contains(selection.getRangeAt(0).commonAncestorContainer)) {
93
+ selection.removeAllRanges();
94
+ }
95
+ };
96
+ Html.limitChars = (element, property, limit) => {
97
+ if (!(property in element))
98
+ return panic(`${property} not found in ${element}`);
99
+ if (typeof element[property] !== "string")
100
+ return panic(`${property} in ${element} is not a string`);
101
+ if (element[property].length > limit) {
102
+ element[property] = element[property].substring(0, limit);
103
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
104
+ element.setSelectionRange(limit, limit);
105
+ }
106
+ else {
107
+ const document = element.ownerDocument;
108
+ const range = document.createRange();
109
+ const selection = document.defaultView?.getSelection();
110
+ if (!isDefined(selection)) {
111
+ return;
112
+ }
113
+ range.selectNodeContents(element);
114
+ range.collapse(false);
115
+ selection.removeAllRanges();
116
+ selection.addRange(range);
117
+ }
118
+ }
119
+ };
120
+ Html.EmptyGif = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=";
121
+ })(Html || (Html = {}));
@@ -0,0 +1,18 @@
1
+ export * from "./browser";
2
+ export * from "./compression";
3
+ export * from "./console-commands";
4
+ export * from "./context-2d";
5
+ export * from "./css-utils";
6
+ export * from "./dragging";
7
+ export * from "./events";
8
+ export * from "./errors";
9
+ export * from "./files";
10
+ export * from "./fonts";
11
+ export * from "./frames";
12
+ export * from "./html";
13
+ export * from "./keyboard";
14
+ export * from "./modfier-keys";
15
+ export * from "./stream";
16
+ export * from "./svg";
17
+ export * from "./terminable";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,oBAAoB,CAAA;AAClC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,cAAc,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ const key = Symbol.for("@openDAW/lib-dom");
2
+ if (globalThis[key]) {
3
+ console.debug(`%c${key.description}%c is already available in ${globalThis.constructor.name}.`, "color: hsl(10, 83%, 60%)", "color: inherit");
4
+ }
5
+ else {
6
+ globalThis[key] = true;
7
+ console.debug(`%c${key.description}%c is now available in ${globalThis.constructor.name}.`, "color: hsl(200, 83%, 60%)", "color: inherit");
8
+ }
9
+ export * from "./browser";
10
+ export * from "./compression";
11
+ export * from "./console-commands";
12
+ export * from "./context-2d";
13
+ export * from "./css-utils";
14
+ export * from "./dragging";
15
+ export * from "./events";
16
+ export * from "./errors";
17
+ export * from "./files";
18
+ export * from "./fonts";
19
+ export * from "./frames";
20
+ export * from "./html";
21
+ export * from "./keyboard";
22
+ export * from "./modfier-keys";
23
+ export * from "./stream";
24
+ export * from "./svg";
25
+ export * from "./terminable";
@@ -0,0 +1,15 @@
1
+ export declare namespace Keyboard {
2
+ const isControlKey: ({ ctrlKey, metaKey }: {
3
+ ctrlKey: boolean;
4
+ metaKey: boolean;
5
+ }) => boolean;
6
+ const isCopyKey: ({ altKey }: {
7
+ altKey: boolean;
8
+ }) => boolean;
9
+ const GlobalShortcut: Readonly<{
10
+ isDelete: (event: KeyboardEvent) => boolean;
11
+ isSelectAll: (event: KeyboardEvent) => boolean;
12
+ isDeselectAll: (event: KeyboardEvent) => boolean;
13
+ }>;
14
+ }
15
+ //# sourceMappingURL=keyboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAGA,yBAAiB,QAAQ,CAAC;IACf,MAAM,YAAY,GAAI,sBAAoB;QAC7C,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAA;KACnB,YAA0C,CAAA;IAEpC,MAAM,SAAS,GAAI,YAAU;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,YAAW,CAAA;IAE3D,MAAM,cAAc;0BACL,aAAa;6BACV,aAAa;+BACX,aAAa;MACtC,CAAA;CACL"}
@@ -0,0 +1,12 @@
1
+ import { Browser } from "./browser";
2
+ import { Events } from "./events";
3
+ export var Keyboard;
4
+ (function (Keyboard) {
5
+ Keyboard.isControlKey = ({ ctrlKey, metaKey }) => Browser.isMacOS() ? metaKey : ctrlKey;
6
+ Keyboard.isCopyKey = ({ altKey }) => altKey;
7
+ Keyboard.GlobalShortcut = Object.freeze({
8
+ isDelete: (event) => !Events.isTextInput(event.target) && (event.code === "Delete" || event.code === "Backspace"),
9
+ isSelectAll: (event) => Keyboard.isControlKey(event) && !event.shiftKey && event.code === "KeyA",
10
+ isDeselectAll: (event) => Keyboard.isControlKey(event) && event.shiftKey && event.code === "KeyA"
11
+ });
12
+ })(Keyboard || (Keyboard = {}));
@@ -0,0 +1,18 @@
1
+ export declare const ModfierKeys: Readonly<{
2
+ Mac: {
3
+ Cmd: string;
4
+ Opt: string;
5
+ Shift: string;
6
+ };
7
+ Win: {
8
+ Cmd: string;
9
+ Opt: string;
10
+ Shift: string;
11
+ };
12
+ System: {
13
+ Cmd: string;
14
+ Opt: string;
15
+ Shift: string;
16
+ };
17
+ }>;
18
+ //# sourceMappingURL=modfier-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modfier-keys.d.ts","sourceRoot":"","sources":["../src/modfier-keys.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;EAIpB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { Browser } from "./browser";
2
+ export const ModfierKeys = (() => {
3
+ const Mac = { Cmd: "⌘", Opt: "⌥", Shift: "⇧" };
4
+ const Win = { Cmd: "Ctrl", Opt: "Alt", Shift: "⇧" };
5
+ return Object.freeze({ Mac, Win, System: Browser.isMacOS() ? Mac : Win });
6
+ })();
@@ -0,0 +1,4 @@
1
+ export declare namespace Stream {
2
+ const read: (reader: ReadableStreamDefaultReader<Uint8Array>) => Promise<ArrayBuffer>;
3
+ }
4
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAEA,yBAAiB,MAAM,CAAC;IACb,MAAM,IAAI,GAAU,QAAQ,2BAA2B,CAAC,UAAU,CAAC,KAAG,OAAO,CAAC,WAAW,CAe/F,CAAA;CACJ"}
package/dist/stream.js ADDED
@@ -0,0 +1,21 @@
1
+ export var Stream;
2
+ (function (Stream) {
3
+ Stream.read = async (reader) => {
4
+ const chunks = [];
5
+ while (true) {
6
+ const { done, value } = await reader.read();
7
+ if (done) {
8
+ break;
9
+ }
10
+ chunks.push(value);
11
+ }
12
+ const length = chunks.reduce((acc, val) => acc + val.length, 0);
13
+ const output = new Uint8Array(length);
14
+ let position = 0 | 0;
15
+ for (let chunk of chunks) {
16
+ output.set(chunk, position);
17
+ position += chunk.length;
18
+ }
19
+ return output.buffer;
20
+ };
21
+ })(Stream || (Stream = {}));
package/dist/svg.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare namespace Svg {
2
+ interface PathBuilder {
3
+ moveTo(x: number, y: number): this;
4
+ lineTo(x: number, y: number): this;
5
+ quadratic(x1: number, y1: number, x: number, y: number): this;
6
+ quadraticTo(x: number, y: number): this;
7
+ cubic(x1: number, y1: number, x2: number, y2: number, x: number, y: number): this;
8
+ arc(rx: number, ry: number, deg: number, largeArc: boolean, sweep: boolean, x: number, y: number): this;
9
+ circleSegment(cx: number, cy: number, radius: number, a0: number, a1: number): this;
10
+ close(): this;
11
+ get(): string;
12
+ }
13
+ const pathBuilder: () => PathBuilder;
14
+ }
15
+ //# sourceMappingURL=svg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../src/svg.ts"],"names":[],"mappings":"AAAA,yBAAiB,GAAG,CAAC;IACjB,UAAiB,WAAW;QACxB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAClC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAClC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QAC7D,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACjF,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvG,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;QACnF,KAAK,IAAI,IAAI,CAAA;QACb,GAAG,IAAI,MAAM,CAAA;KAChB;IAEM,MAAM,WAAW,QAAO,WAkD9B,CAAA;CACJ"}
package/dist/svg.js ADDED
@@ -0,0 +1,45 @@
1
+ export var Svg;
2
+ (function (Svg) {
3
+ Svg.pathBuilder = () => new class {
4
+ #d = "";
5
+ moveTo(x, y) {
6
+ this.#d += `M${x.toFixed(3)} ${y.toFixed(3)}`;
7
+ return this;
8
+ }
9
+ lineTo(x, y) {
10
+ this.#d += `L${x.toFixed(3)} ${y.toFixed(3)}`;
11
+ return this;
12
+ }
13
+ quadratic(x1, y1, x, y) {
14
+ this.#d += `Q${x1.toFixed(3)} ${y1.toFixed(3)} ${x.toFixed(3)} ${y.toFixed(3)}`;
15
+ return this;
16
+ }
17
+ quadraticTo(x, y) {
18
+ this.#d += `T${x.toFixed(3)} ${y.toFixed(3)}`;
19
+ return this;
20
+ }
21
+ cubic(x1, y1, x2, y2, x, y) {
22
+ this.#d += `Q${x1.toFixed(3)} ${y1.toFixed(3)} ${x2.toFixed(3)} ${y2.toFixed(3)} ${x.toFixed(3)} ${y.toFixed(3)}`;
23
+ return this;
24
+ }
25
+ arc(rx, ry, deg, largeArc, sweep, x, y) {
26
+ this.#d += `A${rx} ${ry} ${deg} ${largeArc ? 1 : 0} ${sweep ? 1 : 0} ${x.toFixed(3)} ${y.toFixed(3)}`;
27
+ return this;
28
+ }
29
+ circleSegment(cx, cy, radius, a0, a1) {
30
+ const x0 = cx + Math.cos(a0) * radius;
31
+ const y0 = cy + Math.sin(a0) * radius;
32
+ const x1 = cx + Math.cos(a1) * radius;
33
+ const y1 = cy + Math.sin(a1) * radius;
34
+ let range = a1 - a0;
35
+ while (range < 0.0)
36
+ range += Math.PI * 2.0;
37
+ return this.moveTo(x0, y0).arc(radius, radius, 0, range > Math.PI, true, x1, y1);
38
+ }
39
+ close() {
40
+ this.#d += "Z";
41
+ return this;
42
+ }
43
+ get() { return this.#d; }
44
+ };
45
+ })(Svg || (Svg = {}));
@@ -0,0 +1,13 @@
1
+ import { Func, Terminable } from "@opendaw/lib-std";
2
+ export declare namespace TerminatorUtils {
3
+ /**
4
+ * Terminates if the key is no longer referenced to.
5
+ * Make sure that the Terminable does not include other references
6
+ * that would prevent the key from being gc collected.
7
+ * That means the key must not appear in the Terminable!
8
+ * @param key WeakKey
9
+ * @param subscribe Sends a WeakRef to be able to be gc collected
10
+ */
11
+ const watchWeak: <K extends WeakKey>(key: K, subscribe: Func<WeakRef<K>, Terminable>) => K;
12
+ }
13
+ //# sourceMappingURL=terminable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminable.d.ts","sourceRoot":"","sources":["../src/terminable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAEjD,yBAAiB,eAAe,CAAC;IAE7B;;;;;;;OAOG;IACI,MAAM,SAAS,GAAI,CAAC,SAAS,OAAO,EAAE,KAAK,CAAC,EAAE,WAAW,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,KAAG,CAQ9F,CAAA;CAmBJ"}
@@ -0,0 +1,38 @@
1
+ export var TerminatorUtils;
2
+ (function (TerminatorUtils) {
3
+ const weakRefs = new Array();
4
+ /**
5
+ * Terminates if the key is no longer referenced to.
6
+ * Make sure that the Terminable does not include other references
7
+ * that would prevent the key from being gc collected.
8
+ * That means the key must not appear in the Terminable!
9
+ * @param key WeakKey
10
+ * @param subscribe Sends a WeakRef to be able to be gc collected
11
+ */
12
+ TerminatorUtils.watchWeak = (key, subscribe) => {
13
+ const weakRef = new WeakRef(key);
14
+ const terminable = subscribe(weakRef);
15
+ weakRefs.push([weakRef, terminable]);
16
+ if (weakRefs.length === 1) {
17
+ startWatchWeak();
18
+ }
19
+ return key;
20
+ };
21
+ const startWatchWeak = () => {
22
+ console.debug("start weak watching");
23
+ const id = setInterval(() => {
24
+ let index = weakRefs.length;
25
+ while (--index >= 0) {
26
+ const entry = weakRefs[index];
27
+ if (entry[0].deref() === undefined) {
28
+ entry[1].terminate();
29
+ weakRefs.splice(index, 1);
30
+ if (weakRefs.length === 0) {
31
+ console.debug("stop weak watching");
32
+ clearInterval(id);
33
+ }
34
+ }
35
+ }
36
+ }, 1000);
37
+ };
38
+ })(TerminatorUtils || (TerminatorUtils = {}));
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@opendaw/lib-dom",
3
+ "version": "0.0.6",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "license": "LGPL-3.0-or-later",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist/**/*"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "lint": "eslint \"**/*.ts\"",
22
+ "test": "vitest run"
23
+ },
24
+ "dependencies": {
25
+ "@opendaw/lib-runtime": "^0.0.6",
26
+ "@opendaw/lib-std": "^0.0.6",
27
+ "@types/wicg-file-system-access": "^2023.10.6"
28
+ },
29
+ "devDependencies": {
30
+ "@opendaw/eslint-config": "^0.0.6",
31
+ "@opendaw/typescript-config": "^0.0.6"
32
+ },
33
+ "gitHead": "04e5363a9851c7e116a306c2e933c5f410980fbe"
34
+ }