@media-quest/engine 0.0.21 → 0.0.23

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 (51) hide show
  1. package/package.json +1 -1
  2. package/src/Delement/DElement.dto.ts +5 -5
  3. package/src/Delement/DElement.ts +88 -88
  4. package/src/Delement/DImg.ts +39 -39
  5. package/src/Delement/DStyle-utils.ts +616 -616
  6. package/src/Delement/DStyle.ts +165 -165
  7. package/src/Delement/DText.ts +13 -13
  8. package/src/Delement/Ddiv.ts +25 -25
  9. package/src/Delement/button-click-action.ts +35 -35
  10. package/src/Delement/css.spec.ts +36 -36
  11. package/src/Delement/css.ts +46 -46
  12. package/src/Delement/element-factory.ts +40 -40
  13. package/src/common/DMaybe.ts +46 -46
  14. package/src/common/DTimestamp.ts +20 -20
  15. package/src/common/DTmestamp.spec.ts +11 -11
  16. package/src/common/result.ts +41 -41
  17. package/src/engine/SchemaDto.ts +24 -24
  18. package/src/engine/SchemaEngine.ts +150 -150
  19. package/src/engine/SchemaResult.ts +10 -10
  20. package/src/engine/dplayer.spec.ts +91 -91
  21. package/src/engine/dplayer.ts +104 -104
  22. package/src/engine/history-que.spec.ts +67 -67
  23. package/src/engine/history-que.ts +17 -17
  24. package/src/engine/next-que.spec.ts +121 -121
  25. package/src/engine/next-que.ts +101 -101
  26. package/src/engine/page-que-ruleengine-action.ts +6 -6
  27. package/src/engine/scale.spec.ts +38 -38
  28. package/src/engine/scale.ts +70 -70
  29. package/src/events/mq-events.ts +63 -63
  30. package/src/page/Page.ts +182 -182
  31. package/src/page/media-player.ts +117 -117
  32. package/src/page/page-component.ts +113 -113
  33. package/src/page/page-result.ts +11 -11
  34. package/src/page/task-manager.ts +240 -240
  35. package/src/page/task-state.ts +55 -55
  36. package/src/page/task.ts +90 -90
  37. package/src/public-api.ts +26 -26
  38. package/src/rules/__test__/complex-condition.spec.ts +15 -15
  39. package/src/rules/__test__/conditon.spec.ts +124 -124
  40. package/src/rules/__test__/numeric-condition.spec.ts +84 -84
  41. package/src/rules/__test__/rule-engine.spec.ts +348 -348
  42. package/src/rules/__test__/rule-evaluation.spec.ts +140 -140
  43. package/src/rules/__test__/string-condition.spec.ts +41 -41
  44. package/src/rules/condition.ts +191 -191
  45. package/src/rules/fact.ts +18 -18
  46. package/src/rules/rule-engine.ts +45 -45
  47. package/src/rules/rule.ts +40 -40
  48. package/src/utils/DUtil.ts +116 -116
  49. package/src/utils/ID.spec.ts +39 -39
  50. package/src/utils/ID.ts +73 -73
  51. package/tsconfig.json +19 -19
@@ -1,165 +1,165 @@
1
- import { DCss } from "./css";
2
- import { DUtil } from "../utils/DUtil";
3
-
4
- type DStyle2 = CSSStyleDeclaration;
5
- export type PStyle = Partial<DStyle>;
6
- export interface DStyle {
7
- opacity: number;
8
- backgroundColor: string;
9
- visibility: "visible" | "hidden";
10
- cursor:
11
- | "pointer"
12
- | "help"
13
- | "copy"
14
- | "wait"
15
- | "not-allowed"
16
- | "context-menu"
17
- | "move"
18
- | "grabbing"
19
- | "grab"
20
- | "zoom-in"
21
- | "zoom-out"
22
- | "none"
23
- | "auto"
24
- | "default";
25
-
26
- // POSITION
27
- h: number;
28
- w: number;
29
- x: number;
30
- y: number;
31
-
32
- // BORDERS
33
- borderStyle: "solid" | "none" | "dotted" | "dashed";
34
- borderRadius: DCss.Px | DCss.Percent;
35
- borderWidth: DCss.Px;
36
- borderColor: string;
37
-
38
- margin: DCss.Px | DCss.Percent;
39
- padding: DCss.Px | DCss.Percent;
40
-
41
- // Translate
42
- transform: string;
43
- translate: string;
44
-
45
- // TEXT
46
- fontSize: DCss.Px;
47
- textColor: string;
48
- fontWeight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
49
- textAlign: "right" | "left" | "center";
50
- letterSpacing: DCss.Px;
51
- }
52
-
53
- export namespace DStyle {
54
- export const normalize = <T extends HTMLElement>(el: T): T => {
55
- el.style.padding = "0";
56
- el.style.margin = "0";
57
- el.style.position = "absolute";
58
- el.style.boxSizing = "border-box";
59
- return el;
60
- };
61
-
62
- export const applyStyles = <T extends HTMLElement>(el: T, style: Partial<DStyle>, scale: number): T => {
63
- // const scalePx = DCss.toStringCre(this.scale);
64
- const {
65
- x,
66
- y,
67
- backgroundColor,
68
- borderColor,
69
- borderWidth,
70
- borderRadius,
71
- borderStyle,
72
- w,
73
- opacity,
74
- cursor,
75
- fontSize,
76
- fontWeight,
77
- textColor,
78
- textAlign,
79
- translate,
80
- margin,
81
- padding,
82
- letterSpacing,
83
- h,
84
- transform,
85
- visibility,
86
- } = style;
87
-
88
- // this.el.style.fontWeight = '900';
89
- if (backgroundColor) {
90
- el.style.backgroundColor = backgroundColor;
91
- }
92
-
93
- if (cursor) {
94
- el.style.cursor = cursor;
95
- }
96
-
97
- if (transform) {
98
- el.style.transform = transform;
99
- }
100
-
101
- if (textColor) {
102
- el.style.color = textColor;
103
- }
104
- if (textAlign) {
105
- el.style.textAlign = textAlign;
106
- }
107
-
108
- if (borderColor) {
109
- el.style.borderColor = borderColor;
110
- }
111
-
112
- if (borderWidth) {
113
- el.style.borderWidth = DCss.toString(borderWidth, scale);
114
- }
115
- if (fontWeight) {
116
- el.style.fontWeight = fontWeight + "";
117
- }
118
- if (borderStyle) {
119
- el.style.borderStyle = borderStyle;
120
- }
121
- if (fontSize) {
122
- el.style.fontSize = DCss.toString(fontSize, scale);
123
- }
124
-
125
- if (DUtil.isNumber(x)) {
126
- el.style.left = x + "%";
127
- }
128
- if (DUtil.isNumber(y)) {
129
- el.style.bottom = y + "%";
130
- }
131
-
132
- if (DUtil.isNumber(h)) {
133
- el.style.height = h + "%";
134
- }
135
- if (DUtil.isNumber(w)) {
136
- el.style.width = w + "%";
137
- }
138
-
139
- if (DCss.isLengthUnit(borderRadius)) {
140
- el.style.borderRadius = DCss.toString(borderRadius, scale);
141
- }
142
-
143
- if (letterSpacing) {
144
- el.style.letterSpacing = DCss.toString(letterSpacing, scale);
145
- }
146
- if (margin) {
147
- el.style.margin = DCss.toString(margin, scale);
148
- }
149
- if (padding) {
150
- el.style.padding = DCss.toString(padding, scale);
151
- }
152
-
153
- if (DUtil.isNumber(opacity)) {
154
- el.style.opacity = opacity + "";
155
- }
156
-
157
- if (visibility) {
158
- el.style.visibility = visibility;
159
- }
160
-
161
- return el;
162
- };
163
- // const propNames = new Set(...ElementKeyNames);
164
- // export const validKey = (keyName: string) => propNames.has(keyName);
165
- }
1
+ import { DCss } from "./css";
2
+ import { DUtil } from "../utils/DUtil";
3
+
4
+ type DStyle2 = CSSStyleDeclaration;
5
+ export type PStyle = Partial<DStyle>;
6
+ export interface DStyle {
7
+ opacity: number;
8
+ backgroundColor: string;
9
+ visibility: "visible" | "hidden";
10
+ cursor:
11
+ | "pointer"
12
+ | "help"
13
+ | "copy"
14
+ | "wait"
15
+ | "not-allowed"
16
+ | "context-menu"
17
+ | "move"
18
+ | "grabbing"
19
+ | "grab"
20
+ | "zoom-in"
21
+ | "zoom-out"
22
+ | "none"
23
+ | "auto"
24
+ | "default";
25
+
26
+ // POSITION
27
+ h: number;
28
+ w: number;
29
+ x: number;
30
+ y: number;
31
+
32
+ // BORDERS
33
+ borderStyle: "solid" | "none" | "dotted" | "dashed";
34
+ borderRadius: DCss.Px | DCss.Percent;
35
+ borderWidth: DCss.Px;
36
+ borderColor: string;
37
+
38
+ margin: DCss.Px | DCss.Percent;
39
+ padding: DCss.Px | DCss.Percent;
40
+
41
+ // Translate
42
+ transform: string;
43
+ translate: string;
44
+
45
+ // TEXT
46
+ fontSize: DCss.Px;
47
+ textColor: string;
48
+ fontWeight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
49
+ textAlign: "right" | "left" | "center";
50
+ letterSpacing: DCss.Px;
51
+ }
52
+
53
+ export namespace DStyle {
54
+ export const normalize = <T extends HTMLElement>(el: T): T => {
55
+ el.style.padding = "0";
56
+ el.style.margin = "0";
57
+ el.style.position = "absolute";
58
+ el.style.boxSizing = "border-box";
59
+ return el;
60
+ };
61
+
62
+ export const applyStyles = <T extends HTMLElement>(el: T, style: Partial<DStyle>, scale: number): T => {
63
+ // const scalePx = DCss.toStringCre(this.scale);
64
+ const {
65
+ x,
66
+ y,
67
+ backgroundColor,
68
+ borderColor,
69
+ borderWidth,
70
+ borderRadius,
71
+ borderStyle,
72
+ w,
73
+ opacity,
74
+ cursor,
75
+ fontSize,
76
+ fontWeight,
77
+ textColor,
78
+ textAlign,
79
+ translate,
80
+ margin,
81
+ padding,
82
+ letterSpacing,
83
+ h,
84
+ transform,
85
+ visibility,
86
+ } = style;
87
+
88
+ // this.el.style.fontWeight = '900';
89
+ if (backgroundColor) {
90
+ el.style.backgroundColor = backgroundColor;
91
+ }
92
+
93
+ if (cursor) {
94
+ el.style.cursor = cursor;
95
+ }
96
+
97
+ if (transform) {
98
+ el.style.transform = transform;
99
+ }
100
+
101
+ if (textColor) {
102
+ el.style.color = textColor;
103
+ }
104
+ if (textAlign) {
105
+ el.style.textAlign = textAlign;
106
+ }
107
+
108
+ if (borderColor) {
109
+ el.style.borderColor = borderColor;
110
+ }
111
+
112
+ if (borderWidth) {
113
+ el.style.borderWidth = DCss.toString(borderWidth, scale);
114
+ }
115
+ if (fontWeight) {
116
+ el.style.fontWeight = fontWeight + "";
117
+ }
118
+ if (borderStyle) {
119
+ el.style.borderStyle = borderStyle;
120
+ }
121
+ if (fontSize) {
122
+ el.style.fontSize = DCss.toString(fontSize, scale);
123
+ }
124
+
125
+ if (DUtil.isNumber(x)) {
126
+ el.style.left = x + "%";
127
+ }
128
+ if (DUtil.isNumber(y)) {
129
+ el.style.bottom = y + "%";
130
+ }
131
+
132
+ if (DUtil.isNumber(h)) {
133
+ el.style.height = h + "%";
134
+ }
135
+ if (DUtil.isNumber(w)) {
136
+ el.style.width = w + "%";
137
+ }
138
+
139
+ if (DCss.isLengthUnit(borderRadius)) {
140
+ el.style.borderRadius = DCss.toString(borderRadius, scale);
141
+ }
142
+
143
+ if (letterSpacing) {
144
+ el.style.letterSpacing = DCss.toString(letterSpacing, scale);
145
+ }
146
+ if (margin) {
147
+ el.style.margin = DCss.toString(margin, scale);
148
+ }
149
+ if (padding) {
150
+ el.style.padding = DCss.toString(padding, scale);
151
+ }
152
+
153
+ if (DUtil.isNumber(opacity)) {
154
+ el.style.opacity = opacity + "";
155
+ }
156
+
157
+ if (visibility) {
158
+ el.style.visibility = visibility;
159
+ }
160
+
161
+ return el;
162
+ };
163
+ // const propNames = new Set(...ElementKeyNames);
164
+ // export const validKey = (keyName: string) => propNames.has(keyName);
165
+ }
@@ -1,13 +1,13 @@
1
- import { DElement, DElementBaseDto } from "./DElement";
2
- import { ScaleService } from "../engine/scale";
3
-
4
- export interface DTextDto extends DElementBaseDto {
5
- readonly _tag: "p";
6
- readonly innerText: string;
7
- }
8
-
9
- export class DText extends DElement<HTMLParagraphElement> {
10
- constructor(dto: DTextDto, scale: ScaleService) {
11
- super(document.createElement("p"), dto, scale);
12
- }
13
- }
1
+ import { DElement, DElementBaseDto } from "./DElement";
2
+ import { ScaleService } from "../engine/scale";
3
+
4
+ export interface DTextDto extends DElementBaseDto {
5
+ readonly _tag: "p";
6
+ readonly innerText: string;
7
+ }
8
+
9
+ export class DText extends DElement<HTMLParagraphElement> {
10
+ constructor(dto: DTextDto, scale: ScaleService) {
11
+ super(document.createElement("p"), dto, scale);
12
+ }
13
+ }
@@ -1,25 +1,25 @@
1
- import { DElement, DElementBaseDto } from "./DElement";
2
- import { DText, DTextDto } from "./DText";
3
- import { DImg, DImgDto } from "./DImg";
4
- import { ScaleService } from "../engine/scale";
5
-
6
- export interface DDivDto extends DElementBaseDto {
7
- readonly _tag: "div";
8
- readonly children: Array<DTextDto | DImgDto>;
9
- }
10
-
11
- export class DDiv extends DElement<HTMLDivElement> {
12
- private readonly TAG = "[ DDiv ]: ";
13
- protected readonly defaultStyle = { x: 22, y: 4 };
14
- private children: Array<DText | DImg> = [];
15
-
16
- constructor(dto: DDivDto, scale: ScaleService, children: Array<DText | DImg>) {
17
- const d = document.createElement("div");
18
- super(d, dto, scale);
19
- this.children = children;
20
-
21
- this.children.forEach((child) => {
22
- child.appendYourself(this.el);
23
- });
24
- }
25
- }
1
+ import { DElement, DElementBaseDto } from "./DElement";
2
+ import { DText, DTextDto } from "./DText";
3
+ import { DImg, DImgDto } from "./DImg";
4
+ import { ScaleService } from "../engine/scale";
5
+
6
+ export interface DDivDto extends DElementBaseDto {
7
+ readonly _tag: "div";
8
+ readonly children: Array<DTextDto | DImgDto>;
9
+ }
10
+
11
+ export class DDiv extends DElement<HTMLDivElement> {
12
+ private readonly TAG = "[ DDiv ]: ";
13
+ protected readonly defaultStyle = { x: 22, y: 4 };
14
+ private children: Array<DText | DImg> = [];
15
+
16
+ constructor(dto: DDivDto, scale: ScaleService, children: Array<DText | DImg>) {
17
+ const d = document.createElement("div");
18
+ super(d, dto, scale);
19
+ this.children = children;
20
+
21
+ this.children.forEach((child) => {
22
+ child.appendYourself(this.el);
23
+ });
24
+ }
25
+ }
@@ -1,35 +1,35 @@
1
- import { PlayAudioTask, PlayVideoTask } from "../page/task";
2
- import { Fact } from "../rules/fact";
3
-
4
- export type ButtonClickAction =
5
- | { kind: "play-audio"; task: PlayAudioTask }
6
- | { kind: "pause-audio" }
7
- | { kind: "play-video"; task: PlayVideoTask }
8
- | { kind: "pause-video" }
9
- | { kind: "submit-fact"; fact: Fact }
10
- | { kind: "next-page" }
11
- | { kind: "submit-form" };
12
-
13
- export const ButtonClickAction = {
14
- describe: (a: ButtonClickAction): string => {
15
- switch (a.kind) {
16
- case "next-page":
17
- return "go to next page";
18
- case "play-video":
19
- return "VideoId = " + a.task.videoId;
20
- case "play-audio":
21
- return "AudioId = " + a.task.audioId;
22
- case "pause-video":
23
- return "";
24
- case "pause-audio":
25
- return "";
26
- case "submit-fact":
27
- return a.fact.label + " = " + a.fact.value;
28
- case "submit-form":
29
- return "";
30
- default:
31
- const _exhaustiveCheck: never = a;
32
- return "";
33
- }
34
- },
35
- };
1
+ import { PlayAudioTask, PlayVideoTask } from "../page/task";
2
+ import { Fact } from "../rules/fact";
3
+
4
+ export type ButtonClickAction =
5
+ | { kind: "play-audio"; task: PlayAudioTask }
6
+ | { kind: "pause-audio" }
7
+ | { kind: "play-video"; task: PlayVideoTask }
8
+ | { kind: "pause-video" }
9
+ | { kind: "submit-fact"; fact: Fact }
10
+ | { kind: "next-page" }
11
+ | { kind: "submit-form" };
12
+
13
+ export const ButtonClickAction = {
14
+ describe: (a: ButtonClickAction): string => {
15
+ switch (a.kind) {
16
+ case "next-page":
17
+ return "go to next page";
18
+ case "play-video":
19
+ return "VideoId = " + a.task.videoId;
20
+ case "play-audio":
21
+ return "AudioId = " + a.task.audioId;
22
+ case "pause-video":
23
+ return "";
24
+ case "pause-audio":
25
+ return "";
26
+ case "submit-fact":
27
+ return a.fact.label + " = " + a.fact.value;
28
+ case "submit-form":
29
+ return "";
30
+ default:
31
+ const _exhaustiveCheck: never = a;
32
+ return "";
33
+ }
34
+ },
35
+ };
@@ -1,36 +1,36 @@
1
- import { DCss } from "./css";
2
- import LengthUnit = DCss.LengthUnit;
3
- import { DStyle } from "./DStyle";
4
- describe("Css utils testing", () => {
5
- test("Clamp and round of px-units", () => {
6
- const px1300: DCss.Px = { _unit: "px", value: 1300 };
7
- const px555: DCss.Px = { _unit: "px", value: 555 };
8
- const px123: DCss.Px = { _unit: "px", value: 123 };
9
- const px10: DCss.Px = { _unit: "px", value: 10 };
10
- const px3: DCss.Px = { _unit: "px", value: 3 };
11
- const px0: DCss.Px = { _unit: "px", value: 0 };
12
- const px1: DCss.Px = { _unit: "px", value: 1 };
13
- const scale026 = DCss.toString;
14
- // const scale001 = DCss.toStringCreator(0.01);
15
-
16
- expect(DCss.toString(px1300, 0.26)).toBe("338px");
17
- expect(DCss.toString(px10, 0.26)).toBe("3px");
18
- expect(DCss.toString(px1, 0.26)).toBe("1px");
19
- expect(DCss.toString(px3, 0.26)).toBe("1px");
20
- expect(DCss.toString(px0, 0.26)).toBe("0px");
21
- expect(DCss.toString(px0, 0.26)).toBe("0px");
22
- expect(DCss.toString(px555, 0.26)).toBe("144px");
23
- expect(DCss.toString(px123, 0.01)).toBe("4px");
24
- expect(DCss.toString(px1300, 0.01)).toBe("39px");
25
- expect(DCss.isLengthUnit()).toBe(false);
26
- expect(DCss.isLengthUnit({} as LengthUnit)).toBe(false);
27
- expect(DCss.isLengthUnit(px123)).toBe(true);
28
- });
29
-
30
- test("Normalize div: ", () => {
31
- const div = document.createElement("div");
32
- const normalized = DStyle.normalize(div);
33
- expect(normalized.style.padding).toBe("0px");
34
- expect(normalized.style.boxSizing).toBe("border-box");
35
- });
36
- });
1
+ import { DCss } from "./css";
2
+ import LengthUnit = DCss.LengthUnit;
3
+ import { DStyle } from "./DStyle";
4
+ describe("Css utils testing", () => {
5
+ test("Clamp and round of px-units", () => {
6
+ const px1300: DCss.Px = { _unit: "px", value: 1300 };
7
+ const px555: DCss.Px = { _unit: "px", value: 555 };
8
+ const px123: DCss.Px = { _unit: "px", value: 123 };
9
+ const px10: DCss.Px = { _unit: "px", value: 10 };
10
+ const px3: DCss.Px = { _unit: "px", value: 3 };
11
+ const px0: DCss.Px = { _unit: "px", value: 0 };
12
+ const px1: DCss.Px = { _unit: "px", value: 1 };
13
+ const scale026 = DCss.toString;
14
+ // const scale001 = DCss.toStringCreator(0.01);
15
+
16
+ expect(DCss.toString(px1300, 0.26)).toBe("338px");
17
+ expect(DCss.toString(px10, 0.26)).toBe("3px");
18
+ expect(DCss.toString(px1, 0.26)).toBe("1px");
19
+ expect(DCss.toString(px3, 0.26)).toBe("1px");
20
+ expect(DCss.toString(px0, 0.26)).toBe("0px");
21
+ expect(DCss.toString(px0, 0.26)).toBe("0px");
22
+ expect(DCss.toString(px555, 0.26)).toBe("144px");
23
+ expect(DCss.toString(px123, 0.01)).toBe("4px");
24
+ expect(DCss.toString(px1300, 0.01)).toBe("39px");
25
+ expect(DCss.isLengthUnit()).toBe(false);
26
+ expect(DCss.isLengthUnit({} as LengthUnit)).toBe(false);
27
+ expect(DCss.isLengthUnit(px123)).toBe(true);
28
+ });
29
+
30
+ test("Normalize div: ", () => {
31
+ const div = document.createElement("div");
32
+ const normalized = DStyle.normalize(div);
33
+ expect(normalized.style.padding).toBe("0px");
34
+ expect(normalized.style.boxSizing).toBe("border-box");
35
+ });
36
+ });
@@ -1,46 +1,46 @@
1
- import { DUtil } from "../utils/DUtil";
2
-
3
- export namespace DCss {
4
- export interface Px {
5
- readonly _unit: "px";
6
- readonly value: number;
7
- }
8
-
9
- export type LengthString = `${number}px` | `${number}%`;
10
- export interface Percent {
11
- readonly _unit: "percent";
12
- readonly value: number;
13
- }
14
-
15
- export type LengthUnit = Px | Percent;
16
-
17
- /**
18
- * Will scale to 3% of baseScale
19
- * @param unit
20
- * @param scale
21
- */
22
- export const toString = (unit: Readonly<LengthUnit>, scale: number): LengthString => {
23
- const clampedScale = Math.max(scale, 0.03);
24
- if (unit._unit === "px") {
25
- if (unit.value < 0.1) {
26
- return "0px";
27
- }
28
-
29
- const rounded = Math.round(unit.value * clampedScale);
30
- const clamped = Math.max(rounded, 1);
31
- return (clamped + "px") as LengthString;
32
- }
33
- return (unit.value + "%") as LengthString;
34
- };
35
-
36
- export const isLengthUnit = (unit?: LengthUnit): unit is LengthUnit => {
37
- if (!unit) {
38
- return false;
39
- }
40
- const unitKey: keyof LengthUnit = "_unit";
41
- const valueKey: keyof LengthUnit = "value";
42
- const hasUnitKey = DUtil.hasKey(unit, unitKey);
43
- const hasValueKey = DUtil.hasKey(unit, valueKey);
44
- return hasUnitKey && hasValueKey;
45
- };
46
- }
1
+ import { DUtil } from "../utils/DUtil";
2
+
3
+ export namespace DCss {
4
+ export interface Px {
5
+ readonly _unit: "px";
6
+ readonly value: number;
7
+ }
8
+
9
+ export type LengthString = `${number}px` | `${number}%`;
10
+ export interface Percent {
11
+ readonly _unit: "percent";
12
+ readonly value: number;
13
+ }
14
+
15
+ export type LengthUnit = Px | Percent;
16
+
17
+ /**
18
+ * Will scale to 3% of baseScale
19
+ * @param unit
20
+ * @param scale
21
+ */
22
+ export const toString = (unit: Readonly<LengthUnit>, scale: number): LengthString => {
23
+ const clampedScale = Math.max(scale, 0.03);
24
+ if (unit._unit === "px") {
25
+ if (unit.value < 0.1) {
26
+ return "0px";
27
+ }
28
+
29
+ const rounded = Math.round(unit.value * clampedScale);
30
+ const clamped = Math.max(rounded, 1);
31
+ return (clamped + "px") as LengthString;
32
+ }
33
+ return (unit.value + "%") as LengthString;
34
+ };
35
+
36
+ export const isLengthUnit = (unit?: LengthUnit): unit is LengthUnit => {
37
+ if (!unit) {
38
+ return false;
39
+ }
40
+ const unitKey: keyof LengthUnit = "_unit";
41
+ const valueKey: keyof LengthUnit = "value";
42
+ const hasUnitKey = DUtil.hasKey(unit, unitKey);
43
+ const hasValueKey = DUtil.hasKey(unit, valueKey);
44
+ return hasUnitKey && hasValueKey;
45
+ };
46
+ }