unit.gl 0.0.35 → 0.0.39

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 (72) hide show
  1. package/LICENSE +21 -201
  2. package/README.md +30 -74
  3. package/css/unit.gl.css +28 -65
  4. package/css/unit.gl.min.css +1 -1
  5. package/package.json +13 -8
  6. package/scss/_global.scss +5 -23
  7. package/scss/_reset.scss +13 -15
  8. package/scss/classes/_guide.scss +126 -0
  9. package/scss/classes/_index.scss +25 -11
  10. package/scss/classes/_ratio.scss +30 -0
  11. package/scss/dev/_banner.scss +30 -1
  12. package/scss/dev/_index.scss +0 -0
  13. package/scss/functions/_color.scss +40 -0
  14. package/scss/functions/_index.scss +39 -16
  15. package/scss/functions/_layer.scss +48 -0
  16. package/scss/functions/_ratio.scss +58 -157
  17. package/scss/functions/_scale.scss +55 -49
  18. package/scss/functions/_sequence.scss +154 -126
  19. package/scss/functions/_view.scss +40 -0
  20. package/scss/functions/math/_arithmetic.scss +102 -0
  21. package/scss/functions/math/_index.scss +30 -0
  22. package/scss/functions/unit/_index.scss +30 -0
  23. package/scss/functions/unit/_unit_conversion.scss +94 -0
  24. package/scss/functions/{_unit_functions.scss → unit/_unit_functions.scss} +70 -36
  25. package/scss/index.scss +2 -16
  26. package/scss/maps/_color.scss +43 -0
  27. package/scss/maps/_index.scss +1 -0
  28. package/scss/mixins/_device.scss +63 -25
  29. package/scss/mixins/_display.scss +106 -44
  30. package/scss/mixins/_guide.scss +191 -158
  31. package/scss/mixins/_helper.scss +287 -52
  32. package/scss/mixins/_index.scss +50 -17
  33. package/scss/mixins/_paper.scss +38 -17
  34. package/scss/mixins/_ratio.scss +30 -13
  35. package/scss/mixins/_unit.scss +94 -0
  36. package/scss/mixins/_view.scss +123 -44
  37. package/scss/tags/_index.scss +30 -0
  38. package/scss/tags/_unit.scss +40 -0
  39. package/scss/utilities/_guides.scss +103 -0
  40. package/scss/utilities/_index.scss +6 -0
  41. package/scss/variables/_color.scss +83 -0
  42. package/scss/variables/_device.scss +140 -50
  43. package/scss/variables/_index.scss +84 -16
  44. package/scss/variables/_layer.scss +148 -51
  45. package/scss/variables/_paper.scss +243 -17
  46. package/scss/variables/_ratio.scss +224 -0
  47. package/scss/variables/_scale.scss +230 -104
  48. package/scss/variables/_unit.scss +76 -72
  49. package/scss/variables/_view.scss +135 -39
  50. package/ts/AspectRatio.ts +29 -0
  51. package/ts/Border.ts +29 -0
  52. package/ts/BoxModel.ts +40 -0
  53. package/ts/FlexContainer.ts +48 -0
  54. package/ts/Grid.ts +21 -0
  55. package/ts/GridContainer.ts +33 -0
  56. package/ts/Layout.ts +34 -0
  57. package/ts/Position.ts +28 -0
  58. package/ts/Rectangle.ts +28 -0
  59. package/ts/ResponsiveImage.ts +28 -0
  60. package/ts/ResponsiveScale.ts +21 -0
  61. package/ts/Size.ts +32 -0
  62. package/ts/Spacing.ts +68 -0
  63. package/ts/Transform.ts +38 -0
  64. package/ts/Typography.ts +41 -0
  65. package/ts/Unit.ts +57 -0
  66. package/ts/Viewport.ts +24 -0
  67. package/js/index.d.ts +0 -1
  68. package/js/index.js +0 -3
  69. package/js/unit.gl.min.js +0 -1
  70. package/scss/classes/_paper.scss +0 -97
  71. package/scss/functions/_arithmetic.scss +0 -64
  72. package/scss/functions/_unit_conversion.scss +0 -77
@@ -1,66 +1,162 @@
1
- // Copyright 2024 Scape Agency BV
2
-
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
-
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
-
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // ============================================================================
2
+ // Poster
3
+ // ============================================================================
14
4
 
5
+ ////
6
+ ///
7
+ /// View Variables Module
8
+ /// ===========================================================================
9
+ ///
10
+ /// This module defines the breakpoints for responsive design, categorized by
11
+ /// device types. It leverages a base unit to calculate breakpoint values for
12
+ /// consistency across various screen sizes.
13
+ ///
14
+ /// Breakpoint Categories:
15
+ /// - xs: Extra small devices (e.g., Mobile phones)
16
+ /// - sm: Small devices (e.g., Tablets)
17
+ /// - md: Medium devices (e.g., Laptops)
18
+ /// - lg: Large devices (e.g., Desktops)
19
+ /// - xl: Extra large devices (e.g., TVs)
20
+ /// - sl: Super large devices (e.g., Large TVs)
21
+ ///
22
+ /// Base Unit:
23
+ /// - The base screen unit is set to 16px, which serves as the foundation for
24
+ /// calculating breakpoints.
25
+ ///
26
+ /// Example Usage:
27
+ /// @media (min-width: map-get($breakpoints, md)) {
28
+ /// // Styles for medium devices and up
29
+ /// }
30
+ ///
31
+ /// @group View
32
+ /// @author Scape Agency
33
+ /// @link https://unit.gl
34
+ /// @since 0.1.0 initial release
35
+ /// @todo None
36
+ /// @access public
37
+ ///
38
+ ////
15
39
 
16
40
 
17
41
  // ============================================================================
18
- // Media | Screen
42
+ // Use
19
43
  // ============================================================================
20
44
 
21
- // 320px — 480px: Mobile devices
22
- // 481px — 768px: iPads, Tablets
23
- // 769px — 1024px: Small screens, laptops
24
- // 1025px — 1200px: Desktops, large screens
25
- // 1201px and more —  Extra large screens, TV
26
-
27
-
28
- $base_screen_unit: 16px !default; // Base unit size (16px)
29
45
 
46
+ // ============================================================================
47
+ // Variables
48
+ // ============================================================================
30
49
 
31
- @function calc_breakpoint($multiplier) {
32
- @return $base_screen_unit * $multiplier;
33
- }
34
50
 
51
+ ///
52
+ /// Base unit size used for calculating breakpoints. Defaults to 16px.
53
+ ///
54
+ /// @name $base_screen_unit
55
+ /// @type Length
56
+ ///
57
+ $base_screen_unit: 16px !default;
58
+
59
+
60
+
61
+ ///
62
+ /// A map defining the breakpoints for responsive design. Each key represents
63
+ /// a different device category, with the value calculated using the base
64
+ /// screen unit.
65
+ ///
66
+ /// - **xs**: 320px (Extra small devices like mobile phones)
67
+ /// - **sm**: 480px (Small devices like tablets)
68
+ /// - **md**: 768px (Medium devices like laptops)
69
+ /// - **lg**: 1024px (Large devices like desktops)
70
+ /// - **xl**: 1280px (Extra large devices like TVs)
71
+ /// - **sl**: 1440px (Super large devices like large TVs)
72
+ ///
73
+ /// @name $breakpoints
74
+ /// @type Map
75
+ ///
76
+ // $breakpoints: (
77
+ // xs: calc_breakpoint($base_screen_unit, 20), // 320px - Extra small devices (Mobile)
78
+ // sm: calc_breakpoint($base_screen_unit, 30), // 480px - Small devices (Tablets)
79
+ // md: calc_breakpoint($base_screen_unit, 48), // 768px - Medium devices (Laptops)
80
+ // lg: calc_breakpoint($base_screen_unit, 64), // 1024px - Large devices (Desktops)
81
+ // xl: calc_breakpoint($base_screen_unit, 80), // 1280px - Extra large devices (TV)
82
+ // sl: calc_breakpoint($base_screen_unit, 90), // 1440px - Super large devices (Large TV)
83
+ // ) !default;
35
84
 
36
- // Define breakpoints using the function
37
85
  $breakpoints: (
38
- xs: calc_breakpoint(20), // 320px - Extra small devices (Mobile)
39
- sm: calc_breakpoint(30), // 480px - Small devices (Tablets)
40
- md: calc_breakpoint(48), // 768px - Medium devices (Laptops)
41
- lg: calc_breakpoint(64), // 1024px - Large devices (Desktops)
42
- xl: calc_breakpoint(80), // 1280px - Extra large devices (TV)
43
- sl: calc_breakpoint(90), // 1440px - Super large devices (Large TV)
86
+ xs: 320px, // 320px - Extra small devices (Mobile)
87
+ sm: 480px, // 480px - Small devices (Tablets)
88
+ md: 768px, // 768px - Medium devices (Laptops)
89
+ lg: 1024px, // 1024px - Large devices (Desktops)
90
+ xl: 1280px, // 1280px - Extra large devices (TV)
91
+ sl: 1440px, // 1440px - Super large devices (Large TV)
44
92
  ) !default;
45
93
 
46
94
 
47
- // Expose individual breakpoints for easier direct access
95
+ ///
96
+ /// Exposes the value of the `xs` breakpoint for direct access.
97
+ ///
98
+ /// @name $media_xs
99
+ /// @type Length
100
+ ///
48
101
  $media_xs: map-get($breakpoints, xs) !default;
102
+
103
+
104
+ ///
105
+ /// Exposes the value of the `sm` breakpoint for direct access.
106
+ ///
107
+ /// @name $media_sm
108
+ /// @type Length
109
+ ///
49
110
  $media_sm: map-get($breakpoints, sm) !default;
111
+
112
+
113
+ ///
114
+ /// Exposes the value of the `md` breakpoint for direct access.
115
+ ///
116
+ /// @name $media_md
117
+ /// @type Length
118
+ ///
50
119
  $media_md: map-get($breakpoints, md) !default;
120
+
121
+
122
+ ///
123
+ /// Exposes the value of the `lg` breakpoint for direct access.
124
+ ///
125
+ /// @name $media_lg
126
+ /// @type Length
127
+ ///
51
128
  $media_lg: map-get($breakpoints, lg) !default;
129
+
130
+
131
+ ///
132
+ /// Exposes the value of the `xl` breakpoint for direct access.
133
+ ///
134
+ /// @name $media_xl
135
+ /// @type Length
136
+ ///
52
137
  $media_xl: map-get($breakpoints, xl) !default;
138
+
139
+
140
+ ///
141
+ /// Exposes the value of the `sl` breakpoint for direct access.
142
+ ///
143
+ /// @name $media_sl
144
+ /// @type Length
145
+ ///
53
146
  $media_sl: map-get($breakpoints, sl) !default;
54
147
 
55
- // $media_xs: 320px !default;
56
- // $media_sm: 480px !default;
57
- // $media_md: 768px !default;
58
- // $media_lg: 1024px !default;
59
- // $media_xl: 1280px !default;
60
- // $media_sl: 1440px !default;
61
148
 
149
+ ///
150
+ /// Calculates the difference between the `sl` and `xs` breakpoints.
151
+ ///
152
+ /// @name $media_dif
153
+ /// @type Length
154
+ ///
62
155
  $media_dif: calc($media_sl - $media_xs);
63
156
 
157
+
158
+ // Uncomment below if you want to use the following predefined breakpoints for various devices:
159
+
64
160
  // $media_min: 320px !default; // Mobile
65
161
  // $media_med: 640px !default; // Tablet
66
162
  // $media_max: 960px !default; // Screen
@@ -0,0 +1,29 @@
1
+ class AspectRatio {
2
+ width: Unit;
3
+ height: Unit;
4
+
5
+ constructor(width: Unit, height: Unit) {
6
+ this.width = width;
7
+ this.height = height;
8
+ }
9
+
10
+ calculateRatio(): number {
11
+ return this.width.value / this.height.value;
12
+ }
13
+
14
+ scaleToWidth(newWidth: Unit): Unit {
15
+ const ratio = this.calculateRatio();
16
+ const newHeightValue = newWidth.value / ratio;
17
+ return new Unit(newHeightValue, newWidth.unit);
18
+ }
19
+
20
+ scaleToHeight(newHeight: Unit): Unit {
21
+ const ratio = this.calculateRatio();
22
+ const newWidthValue = newHeight.value * ratio;
23
+ return new Unit(newWidthValue, newHeight.unit);
24
+ }
25
+
26
+ toString(): string {
27
+ return `AspectRatio: width ${this.width.toString()}, height ${this.height.toString()}, ratio ${this.calculateRatio()}`;
28
+ }
29
+ }
package/ts/Border.ts ADDED
@@ -0,0 +1,29 @@
1
+ type BorderStyle = 'solid' | 'dashed' | 'dotted' | 'double' | 'none';
2
+
3
+ class Border {
4
+ width: Unit;
5
+ style: BorderStyle;
6
+ color: string;
7
+
8
+ constructor(width: Unit, style: BorderStyle, color: string) {
9
+ this.width = width;
10
+ this.style = style;
11
+ this.color = color;
12
+ }
13
+
14
+ setWidth(newWidth: Unit): void {
15
+ this.width = newWidth;
16
+ }
17
+
18
+ setStyle(newStyle: BorderStyle): void {
19
+ this.style = newStyle;
20
+ }
21
+
22
+ setColor(newColor: string): void {
23
+ this.color = newColor;
24
+ }
25
+
26
+ toString(): string {
27
+ return `Border: ${this.width.toString()} ${this.style} ${this.color}`;
28
+ }
29
+ }
package/ts/BoxModel.ts ADDED
@@ -0,0 +1,40 @@
1
+ class BoxModel {
2
+ margin: Margin;
3
+ padding: Padding;
4
+ border: Border;
5
+ size: Size;
6
+
7
+ constructor(margin: Margin, padding: Padding, border: Border, size: Size) {
8
+ if (
9
+ margin.top.unit !== size.width.unit ||
10
+ padding.top.unit !== size.width.unit ||
11
+ border.width.unit !== size.width.unit
12
+ ) {
13
+ throw new Error('All units in BoxModel must match');
14
+ }
15
+ this.margin = margin;
16
+ this.padding = padding;
17
+ this.border = border;
18
+ this.size = size;
19
+ }
20
+
21
+ setMargin(margin: Margin): void {
22
+ this.margin = margin;
23
+ }
24
+
25
+ setPadding(padding: Padding): void {
26
+ this.padding = padding;
27
+ }
28
+
29
+ setBorder(border: Border): void {
30
+ this.border = border;
31
+ }
32
+
33
+ setSize(size: Size): void {
34
+ this.size = size;
35
+ }
36
+
37
+ toString(): string {
38
+ return `BoxModel:\n Size: ${this.size.toString()}\n Margin: ${this.margin.toString()}\n Padding: ${this.padding.toString()}\n Border: ${this.border.toString()}`;
39
+ }
40
+ }
@@ -0,0 +1,48 @@
1
+ type FlexDirection = 'row' | 'row-reverse' | 'column' | 'column-reverse';
2
+ type FlexWrap = 'nowrap' | 'wrap' | 'wrap-reverse';
3
+
4
+ class FlexContainer {
5
+ flexDirection: FlexDirection;
6
+ flexWrap: FlexWrap;
7
+ justifyContent: Justify;
8
+ alignItems: Align;
9
+ alignContent: Align;
10
+
11
+ constructor(
12
+ flexDirection: FlexDirection = 'row',
13
+ flexWrap: FlexWrap = 'nowrap',
14
+ justifyContent: Justify = 'start',
15
+ alignItems: Align = 'stretch',
16
+ alignContent: Align = 'stretch'
17
+ ) {
18
+ this.flexDirection = flexDirection;
19
+ this.flexWrap = flexWrap;
20
+ this.justifyContent = justifyContent;
21
+ this.alignItems = alignItems;
22
+ this.alignContent = alignContent;
23
+ }
24
+
25
+ setDirection(direction: FlexDirection): void {
26
+ this.flexDirection = direction;
27
+ }
28
+
29
+ setWrap(wrap: FlexWrap): void {
30
+ this.flexWrap = wrap;
31
+ }
32
+
33
+ setJustifyContent(justify: Justify): void {
34
+ this.justifyContent = justify;
35
+ }
36
+
37
+ setAlignItems(align: Align): void {
38
+ this.alignItems = align;
39
+ }
40
+
41
+ setAlignContent(align: Align): void {
42
+ this.alignContent = align;
43
+ }
44
+
45
+ toString(): string {
46
+ return `FlexContainer: direction ${this.flexDirection}, wrap ${this.flexWrap}, justify ${this.justifyContent}, align-items ${this.alignItems}, align-content ${this.alignContent}`;
47
+ }
48
+ }
package/ts/Grid.ts ADDED
@@ -0,0 +1,21 @@
1
+ class Grid {
2
+ columns: number;
3
+ gutter: Unit;
4
+ rowHeight: Unit;
5
+
6
+ constructor(columns: number, gutter: Unit, rowHeight: Unit) {
7
+ this.columns = columns;
8
+ this.gutter = gutter;
9
+ this.rowHeight = rowHeight;
10
+ }
11
+
12
+ getColumnWidth(containerWidth: Unit): Unit {
13
+ const totalGutterWidth = this.gutter.value * (this.columns - 1);
14
+ const columnWidth = (containerWidth.value - totalGutterWidth) / this.columns;
15
+ return new Unit(columnWidth, containerWidth.unit);
16
+ }
17
+
18
+ toString(): string {
19
+ return `Grid: ${this.columns} columns, gutter ${this.gutter.toString()}, row height ${this.rowHeight.toString()}`;
20
+ }
21
+ }
@@ -0,0 +1,33 @@
1
+ class GridContainer {
2
+ rows: number;
3
+ columns: number;
4
+ rowGap: Unit;
5
+ columnGap: Unit;
6
+
7
+ constructor(rows: number, columns: number, rowGap: Unit, columnGap: Unit) {
8
+ this.rows = rows;
9
+ this.columns = columns;
10
+ this.rowGap = rowGap;
11
+ this.columnGap = columnGap;
12
+ }
13
+
14
+ setRows(rows: number): void {
15
+ this.rows = rows;
16
+ }
17
+
18
+ setColumns(columns: number): void {
19
+ this.columns = columns;
20
+ }
21
+
22
+ setRowGap(rowGap: Unit): void {
23
+ this.rowGap = rowGap;
24
+ }
25
+
26
+ setColumnGap(columnGap: Unit): void {
27
+ this.columnGap = columnGap;
28
+ }
29
+
30
+ toString(): string {
31
+ return `GridContainer: ${this.rows} rows, ${this.columns} columns, row-gap ${this.rowGap.toString()}, column-gap ${this.columnGap.toString()}`;
32
+ }
33
+ }
package/ts/Layout.ts ADDED
@@ -0,0 +1,34 @@
1
+ type Align = 'start' | 'center' | 'end' | 'stretch';
2
+ type Justify = 'start' | 'center' | 'end' | 'space-between' | 'space-around';
3
+
4
+ class Layout {
5
+ width: Unit;
6
+ height: Unit;
7
+ align: Align;
8
+ justify: Justify;
9
+ direction: 'row' | 'column';
10
+
11
+ constructor(width: Unit, height: Unit, align: Align = 'stretch', justify: Justify = 'start', direction: 'row' | 'column' = 'row') {
12
+ this.width = width;
13
+ this.height = height;
14
+ this.align = align;
15
+ this.justify = justify;
16
+ this.direction = direction;
17
+ }
18
+
19
+ setAlign(align: Align): void {
20
+ this.align = align;
21
+ }
22
+
23
+ setJustify(justify: Justify): void {
24
+ this.justify = justify;
25
+ }
26
+
27
+ setDirection(direction: 'row' | 'column'): void {
28
+ this.direction = direction;
29
+ }
30
+
31
+ toString(): string {
32
+ return `Layout: ${this.direction}, width ${this.width.toString()}, height ${this.height.toString()}, align ${this.align}, justify ${this.justify}`;
33
+ }
34
+ }
package/ts/Position.ts ADDED
@@ -0,0 +1,28 @@
1
+ class Position {
2
+ x: Unit;
3
+ y: Unit;
4
+
5
+ constructor(x: Unit, y: Unit) {
6
+ if (x.unit !== y.unit) {
7
+ throw new Error('X and Y must have the same unit');
8
+ }
9
+ this.x = x;
10
+ this.y = y;
11
+ }
12
+
13
+ add(other: Position): Position {
14
+ return new Position(this.x.add(other.x), this.y.add(other.y));
15
+ }
16
+
17
+ subtract(other: Position): Position {
18
+ return new Position(this.x.subtract(other.x), this.y.subtract(other.y));
19
+ }
20
+
21
+ convert(toUnit: UnitType): Position {
22
+ return new Position(this.x.convert(toUnit), this.y.convert(toUnit));
23
+ }
24
+
25
+ toString(): string {
26
+ return `Position: (${this.x.toString()}, ${this.y.toString()})`;
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ class Rectangle {
2
+ position: Position;
3
+ size: Size;
4
+
5
+ constructor(position: Position, size: Size) {
6
+ if (position.x.unit !== size.width.unit || position.y.unit !== size.height.unit) {
7
+ throw new Error('Position and Size units must match');
8
+ }
9
+ this.position = position;
10
+ this.size = size;
11
+ }
12
+
13
+ move(newPosition: Position): Rectangle {
14
+ return new Rectangle(newPosition, this.size);
15
+ }
16
+
17
+ resize(newSize: Size): Rectangle {
18
+ return new Rectangle(this.position, newSize);
19
+ }
20
+
21
+ scale(factor: number): Rectangle {
22
+ return new Rectangle(this.position, this.size.scale(factor));
23
+ }
24
+
25
+ toString(): string {
26
+ return `Rectangle: Position(${this.position.toString()}), Size(${this.size.toString()})`;
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ class ResponsiveImage {
2
+ sources: Map<number, string>; // Map of breakpoint to image URL
3
+ altText: string;
4
+
5
+ constructor(altText: string) {
6
+ this.sources = new Map<number, string>();
7
+ this.altText = altText;
8
+ }
9
+
10
+ addSource(breakpoint: number, url: string): void {
11
+ this.sources.set(breakpoint, url);
12
+ }
13
+
14
+ getSource(viewportWidth: number): string {
15
+ let selectedSource = '';
16
+ this.sources.forEach((url, breakpoint) => {
17
+ if (viewportWidth >= breakpoint) {
18
+ selectedSource = url;
19
+ }
20
+ });
21
+ return selectedSource;
22
+ }
23
+
24
+ toString(viewportWidth: number): string {
25
+ const source = this.getSource(viewportWidth);
26
+ return `<img src="${source}" alt="${this.altText}" />`;
27
+ }
28
+ }
@@ -0,0 +1,21 @@
1
+ class ResponsiveScale {
2
+ viewport: Viewport;
3
+ baseSize: Unit;
4
+ scaleFactor: number;
5
+
6
+ constructor(viewport: Viewport, baseSize: Unit, scaleFactor: number) {
7
+ this.viewport = viewport;
8
+ this.baseSize = baseSize;
9
+ this.scaleFactor = scaleFactor;
10
+ }
11
+
12
+ calculateResponsiveSize(): Unit {
13
+ const ratio = this.viewport.width.value / 1920; // Assuming 1920px is the base
14
+ const scaledValue = this.baseSize.value * Math.pow(this.scaleFactor, ratio);
15
+ return new Unit(scaledValue, this.baseSize.unit);
16
+ }
17
+
18
+ toString(): string {
19
+ return `ResponsiveScale: Base(${this.baseSize.toString()}) ScaleFactor(${this.scaleFactor}) Viewport(${this.viewport.toString()})`;
20
+ }
21
+ }
package/ts/Size.ts ADDED
@@ -0,0 +1,32 @@
1
+ class Size {
2
+ width: Unit;
3
+ height: Unit;
4
+
5
+ constructor(width: Unit, height: Unit) {
6
+ if (width.unit !== height.unit) {
7
+ throw new Error('Width and height must have the same unit');
8
+ }
9
+ this.width = width;
10
+ this.height = height;
11
+ }
12
+
13
+ add(other: Size): Size {
14
+ return new Size(this.width.add(other.width), this.height.add(other.height));
15
+ }
16
+
17
+ subtract(other: Size): Size {
18
+ return new Size(this.width.subtract(other.width), this.height.subtract(other.height));
19
+ }
20
+
21
+ scale(factor: number): Size {
22
+ return new Size(this.width.multiply(factor), this.height.multiply(factor));
23
+ }
24
+
25
+ convert(toUnit: UnitType): Size {
26
+ return new Size(this.width.convert(toUnit), this.height.convert(toUnit));
27
+ }
28
+
29
+ toString(): string {
30
+ return `Size: ${this.width.toString()} x ${this.height.toString()}`;
31
+ }
32
+ }
package/ts/Spacing.ts ADDED
@@ -0,0 +1,68 @@
1
+ class Spacing {
2
+ top: Unit;
3
+ right: Unit;
4
+ bottom: Unit;
5
+ left: Unit;
6
+
7
+ constructor(top: Unit, right: Unit, bottom: Unit, left: Unit) {
8
+ if (top.unit !== right.unit || top.unit !== bottom.unit || top.unit !== left.unit) {
9
+ throw new Error('All sides must have the same unit');
10
+ }
11
+ this.top = top;
12
+ this.right = right;
13
+ this.bottom = bottom;
14
+ this.left = left;
15
+ }
16
+
17
+ add(other: Spacing): Spacing {
18
+ return new Spacing(
19
+ this.top.add(other.top),
20
+ this.right.add(other.right),
21
+ this.bottom.add(other.bottom),
22
+ this.left.add(other.left)
23
+ );
24
+ }
25
+
26
+ subtract(other: Spacing): Spacing {
27
+ return new Spacing(
28
+ this.top.subtract(other.top),
29
+ this.right.subtract(other.right),
30
+ this.bottom.subtract(other.bottom),
31
+ this.left.subtract(other.left)
32
+ );
33
+ }
34
+
35
+ scale(factor: number): Spacing {
36
+ return new Spacing(
37
+ this.top.multiply(factor),
38
+ this.right.multiply(factor),
39
+ this.bottom.multiply(factor),
40
+ this.left.multiply(factor)
41
+ );
42
+ }
43
+
44
+ convert(toUnit: UnitType): Spacing {
45
+ return new Spacing(
46
+ this.top.convert(toUnit),
47
+ this.right.convert(toUnit),
48
+ this.bottom.convert(toUnit),
49
+ this.left.convert(toUnit)
50
+ );
51
+ }
52
+
53
+ toString(): string {
54
+ return `Spacing: ${this.top.toString()} ${this.right.toString()} ${this.bottom.toString()} ${this.left.toString()}`;
55
+ }
56
+ }
57
+
58
+ class Margin extends Spacing {
59
+ constructor(top: Unit, right: Unit, bottom: Unit, left: Unit) {
60
+ super(top, right, bottom, left);
61
+ }
62
+ }
63
+
64
+ class Padding extends Spacing {
65
+ constructor(top: Unit, right: Unit, bottom: Unit, left: Unit) {
66
+ super(top, right, bottom, left);
67
+ }
68
+ }
@@ -0,0 +1,38 @@
1
+ type AngleUnit = 'deg' | 'rad';
2
+
3
+ class Transform {
4
+ translateX: Unit;
5
+ translateY: Unit;
6
+ rotate: number;
7
+ rotateUnit: AngleUnit;
8
+ scaleX: number;
9
+ scaleY: number;
10
+
11
+ constructor(translateX: Unit, translateY: Unit, rotate: number, rotateUnit: AngleUnit, scaleX: number, scaleY: number) {
12
+ this.translateX = translateX;
13
+ this.translateY = translateY;
14
+ this.rotate = rotate;
15
+ this.rotateUnit = rotateUnit;
16
+ this.scaleX = scaleX;
17
+ this.scaleY = scaleY;
18
+ }
19
+
20
+ setTranslation(translateX: Unit, translateY: Unit): void {
21
+ this.translateX = translateX;
22
+ this.translateY = translateY;
23
+ }
24
+
25
+ setRotation(angle: number, unit: AngleUnit): void {
26
+ this.rotate = angle;
27
+ this.rotateUnit = unit;
28
+ }
29
+
30
+ setScale(scaleX: number, scaleY: number): void {
31
+ this.scaleX = scaleX;
32
+ this.scaleY = scaleY;
33
+ }
34
+
35
+ toString(): string {
36
+ return `Transform: translate(${this.translateX.toString()}, ${this.translateY.toString()}) rotate(${this.rotate}${this.rotateUnit}) scale(${this.scaleX}, ${this.scaleY})`;
37
+ }
38
+ }