@cntrl-site/sdk 1.25.1-0 → 1.25.1-2

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.
@@ -0,0 +1,34 @@
1
+ import { Left, RectCoordinates, RectObject, ScaleOrigin, Sides, Top } from "../types/article/Rect";
2
+ export declare class Rect {
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ static fromObject({ x, y, width, height }: RectObject): Rect;
8
+ static intersection(rect1: Rect, rect2: Rect): Rect;
9
+ static isSideBySide(rect1: Rect, rect2: Rect): boolean;
10
+ static isContained(rect1: Rect, rect2: Rect): boolean;
11
+ static isEqual(rect1: Rect, rect2: Rect): boolean;
12
+ static scale(rect: Rect, factor: number, origin: ScaleOrigin): Rect;
13
+ static scaleWithOrigin(rect: Rect, factor: number, kt: number, kl: number): Rect;
14
+ static getChildScaleOrigin(parentRect: Rect, childRect: Rect, parentOrigin: ScaleOrigin): Sides;
15
+ static getUnrotatedChildRect(parentRect: Rect, childRect: Rect, rotationAngle: number): Rect;
16
+ static getRotatedRectCoordinates(originalRect: Rect, newRect: Rect, angle: number): RectCoordinates;
17
+ static getUnRotatedPosition(coords: RectCoordinates, angle: number): [Top, Left];
18
+ static getOriginRectFromBoundary: (boundary: DOMRect, angle: number, ratio: number) => Rect;
19
+ static getRotatedBoundingBox(boundary: Rect, angle: number): Rect;
20
+ static getRelativeRect(src: Rect, origin: Rect): Rect;
21
+ static getDefault(): Rect;
22
+ static getHorizontallyIntersectingRects(selectedRect: Rect, unselectedRects: Rect[]): Rect[];
23
+ static getVerticallyIntersectingRects(selectedRect: Rect, unselectedRects: Rect[]): Rect[];
24
+ static roundRect(rect: Rect): Rect;
25
+ static roundRects(rects: Rect[]): Rect[];
26
+ constructor(x: number, y: number, width: number, height: number);
27
+ get left(): number;
28
+ get top(): number;
29
+ get right(): number;
30
+ get bottom(): number;
31
+ getScaled(xRatio: number, yRatio?: number): Rect;
32
+ getRelative(source: Rect): Rect;
33
+ private static getNewPosition;
34
+ }
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Rect = void 0;
5
+ const Rect_1 = require("../types/article/Rect");
6
+ class Rect {
7
+ static fromObject({ x, y, width, height }) {
8
+ return new _a(x, y, width, height);
9
+ }
10
+ static intersection(rect1, rect2) {
11
+ const left = Math.max(rect1.left, rect2.left);
12
+ const top = Math.max(rect1.top, rect2.top);
13
+ const width = Math.min(rect1.right, rect2.right) - left;
14
+ const height = Math.min(rect1.bottom, rect2.bottom) - top;
15
+ return new _a(left, top, Math.max(width, 0), Math.max(height, 0));
16
+ }
17
+ static isSideBySide(rect1, rect2) {
18
+ return Math.round(rect1.left) === Math.round(rect2.left)
19
+ || Math.round(rect1.top) === Math.round(rect2.top)
20
+ || Math.round(rect1.right) === Math.round(rect2.right)
21
+ || Math.round(rect1.bottom) === Math.round(rect2.bottom);
22
+ }
23
+ static isContained(rect1, rect2) {
24
+ return rect1.left <= rect2.left && rect1.top <= rect2.top && rect1.right >= rect2.right && rect1.bottom >= rect2.bottom;
25
+ }
26
+ static isEqual(rect1, rect2) {
27
+ return Math.round(rect1.left) === Math.round(rect2.left)
28
+ && Math.round(rect1.top) === Math.round(rect2.top)
29
+ && Math.round(rect1.right) === Math.round(rect2.right)
30
+ && Math.round(rect1.bottom) === Math.round(rect2.bottom);
31
+ }
32
+ static scale(rect, factor, origin) {
33
+ const width = rect.width * factor;
34
+ const height = rect.height * factor;
35
+ const dw = rect.width - width;
36
+ const dh = rect.height - height;
37
+ const [kt, kl] = Rect_1.scaleMatrix[origin];
38
+ const x = rect.left + (kl * dw);
39
+ const y = rect.top + (kt * dh);
40
+ return new _a(x, y, width, height);
41
+ }
42
+ static scaleWithOrigin(rect, factor, kt, kl) {
43
+ const width = rect.width * factor;
44
+ const height = rect.height * factor;
45
+ const dw = rect.width - width;
46
+ const dh = rect.height - height;
47
+ const x = rect.left + (kl * dw);
48
+ const y = rect.top + (kt * dh);
49
+ return new _a(x, y, width, height);
50
+ }
51
+ static getChildScaleOrigin(parentRect, childRect, parentOrigin) {
52
+ if (childRect.width === 0 || childRect.height === 0 || parentRect.width === 0 || parentRect.height === 0) {
53
+ return [0, 0]; // Default or fallback value
54
+ }
55
+ const [kt, kl] = Rect_1.scaleMatrix[parentOrigin];
56
+ const dw = childRect.width / parentRect.width;
57
+ const dh = childRect.height / parentRect.height;
58
+ const clNormalized = childRect.left / childRect.width;
59
+ const ctNormalized = childRect.top / childRect.height;
60
+ const pw = 1 / dw;
61
+ const ph = 1 / dh;
62
+ const pl = kl * pw;
63
+ const pt = kt * ph;
64
+ const originLeft = pl - clNormalized;
65
+ const originTop = pt - ctNormalized;
66
+ return [originTop, originLeft];
67
+ }
68
+ static getUnrotatedChildRect(parentRect, childRect, rotationAngle) {
69
+ const radians = -1 * rotationAngle * (Math.PI / 180);
70
+ const parentCenterX = parentRect.left + parentRect.width / 2;
71
+ const parentCenterY = parentRect.top + parentRect.height / 2;
72
+ const relativeX = childRect.left + childRect.width / 2 - parentCenterX;
73
+ const relativeY = childRect.top + childRect.height / 2 - parentCenterY;
74
+ const unrotatedX = relativeX * Math.cos(radians) - relativeY * Math.sin(radians);
75
+ const unrotatedY = relativeX * Math.sin(radians) + relativeY * Math.cos(radians);
76
+ const finalX = unrotatedX + parentCenterX;
77
+ const finalY = unrotatedY + parentCenterY;
78
+ const unrotatedWidth = childRect.width;
79
+ const unrotatedHeight = childRect.height;
80
+ return new _a(finalX - unrotatedWidth / 2, finalY - unrotatedHeight / 2, unrotatedWidth, unrotatedHeight);
81
+ }
82
+ static getRotatedRectCoordinates(originalRect, newRect, angle) {
83
+ if (angle === 0)
84
+ return [newRect.left, newRect.top, newRect.right, newRect.bottom];
85
+ const radians = (Math.PI * angle) / 180;
86
+ const cos = Math.cos(radians);
87
+ const sin = Math.sin(radians);
88
+ const centerX = originalRect.left + originalRect.width / 2;
89
+ const centerY = originalRect.top + originalRect.height / 2;
90
+ const { left, top, right, bottom } = newRect;
91
+ const rotatedLeft = left * cos - top * sin - centerX * cos + centerY * sin + centerX;
92
+ const rotatedTop = left * sin + top * cos - centerX * sin - centerY * cos + centerY;
93
+ const rotatedRight = right * cos - bottom * sin - centerX * cos + centerY * sin + centerX;
94
+ const rotatedBottom = right * sin + bottom * cos - centerX * sin - centerY * cos + centerY;
95
+ return [rotatedLeft, rotatedTop, rotatedRight, rotatedBottom];
96
+ }
97
+ static getUnRotatedPosition(coords, angle) {
98
+ const [left, top, right, bottom] = coords;
99
+ const centerX = (right + left) / 2;
100
+ const centerY = (bottom + top) / 2;
101
+ const radians = -1 * (Math.PI * angle) / 180;
102
+ const cos = Math.cos(radians);
103
+ const sin = Math.sin(radians);
104
+ const newLeft = left * cos - top * sin - cos * centerX + sin * centerY + centerX;
105
+ const newTop = left * sin + top * cos - sin * centerX - cos * centerY + centerY;
106
+ return [newLeft, newTop];
107
+ }
108
+ static getRotatedBoundingBox(boundary, angle) {
109
+ if (angle === 0)
110
+ return _a.fromObject(boundary);
111
+ const { x, y, width, height } = boundary;
112
+ const radian = (angle * Math.PI) / 180;
113
+ const cx = x + width / 2;
114
+ const cy = y + height / 2;
115
+ const corners = [
116
+ { x, y },
117
+ { x: x + width, y },
118
+ { x, y: y + height },
119
+ { x: x + width, y: y + height }
120
+ ];
121
+ const rotatedCorners = corners.map((corner) => {
122
+ const dx = corner.x - cx;
123
+ const dy = corner.y - cy;
124
+ return {
125
+ x: cx + (dx * Math.cos(radian) - dy * Math.sin(radian)),
126
+ y: cy + (dx * Math.sin(radian) + dy * Math.cos(radian))
127
+ };
128
+ });
129
+ const xValues = rotatedCorners.map(point => point.x);
130
+ const yValues = rotatedCorners.map(point => point.y);
131
+ const minX = Math.min(...xValues);
132
+ const maxX = Math.max(...xValues);
133
+ const minY = Math.min(...yValues);
134
+ const maxY = Math.max(...yValues);
135
+ return new _a(minX, minY, maxX - minX, maxY - minY);
136
+ }
137
+ static getRelativeRect(src, origin) {
138
+ return new _a(src.left - origin.left, src.top - origin.top, src.width, src.height);
139
+ }
140
+ static getDefault() {
141
+ return new _a(0, 0, 0, 0);
142
+ }
143
+ static getHorizontallyIntersectingRects(selectedRect, unselectedRects) {
144
+ return unselectedRects.filter(rect => selectedRect.bottom >= rect.top && selectedRect.top <= rect.bottom);
145
+ }
146
+ static getVerticallyIntersectingRects(selectedRect, unselectedRects) {
147
+ return unselectedRects.filter(rect => selectedRect.right >= rect.left && selectedRect.left <= rect.right);
148
+ }
149
+ static roundRect(rect) {
150
+ return new _a(Math.round(rect.x), Math.round(rect.y), Math.round(rect.width), Math.round(rect.height));
151
+ }
152
+ static roundRects(rects) {
153
+ return rects.map(r => _a.roundRect(r));
154
+ }
155
+ constructor(x, y, width, height) {
156
+ this.x = x;
157
+ this.y = y;
158
+ this.width = width;
159
+ this.height = height;
160
+ }
161
+ get left() {
162
+ return this.width >= 0 ? this.x : this.x + this.width;
163
+ }
164
+ get top() {
165
+ return this.height >= 0 ? this.y : this.y + this.height;
166
+ }
167
+ get right() {
168
+ return this.width >= 0 ? this.x + this.width : this.x;
169
+ }
170
+ get bottom() {
171
+ return this.height >= 0 ? this.y + this.height : this.y;
172
+ }
173
+ getScaled(xRatio, yRatio = xRatio) {
174
+ return new _a(this.x * xRatio, this.y * yRatio, this.width * xRatio, this.height * yRatio);
175
+ }
176
+ getRelative(source) {
177
+ return new _a(this.left - source.left, this.top - source.top, this.width, this.height);
178
+ }
179
+ static getNewPosition(rect, newDimensions) {
180
+ const x = rect.left + (rect.width - newDimensions.width) / 2;
181
+ const y = rect.top + (rect.height - newDimensions.height) / 2;
182
+ return { x, y };
183
+ }
184
+ }
185
+ exports.Rect = Rect;
186
+ _a = Rect;
187
+ Rect.getOriginRectFromBoundary = (boundary, angle, ratio) => {
188
+ const radians = angle * (Math.PI / 180);
189
+ const cos = Math.abs(Math.cos(radians));
190
+ const sin = Math.abs(Math.sin(radians));
191
+ const W = boundary.width;
192
+ const H = boundary.height;
193
+ if (Math.abs(angle % 180) === 90) {
194
+ const { x, y } = _a.getNewPosition(boundary, { width: H, height: W });
195
+ return new _a(x, y, H, W);
196
+ }
197
+ if (Math.abs(angle % 45) === 0) {
198
+ const w = W / (cos + sin / ratio);
199
+ const h = H / (cos + sin * ratio);
200
+ const { x, y } = _a.getNewPosition(boundary, { width: w, height: h });
201
+ return new _a(x, y, w, h);
202
+ }
203
+ const w = (W * cos - H * sin) / (cos * cos - sin * sin);
204
+ const h = (H - w * sin) / cos;
205
+ const { x, y } = _a.getNewPosition(boundary, { width: w, height: h });
206
+ return new _a(x, y, w, h);
207
+ };
package/lib/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { Client as CntrlClient } from './Client/Client';
2
2
  export { FontFaceGenerator } from './FontFaceGenerator/FontFaceGenerator';
3
- export { getLayoutStyles, getLayoutMediaQuery } from './utils';
3
+ export { getLayoutStyles, getLayoutMediaQuery, measureFont } from './utils';
4
4
  export { ScrollPlaybackVideoManager } from './ScrollPlaybackVideoManager/ScrollPlaybackVideoManager';
5
+ export { Rect } from './Rect/Rect';
5
6
  export { SectionHeightMode } from './types/article/Section';
6
7
  export { TextAlign, TextDecoration, TextTransform, VerticalAlign } from './types/article/RichText';
7
8
  export { ArticleItemType } from './types/article/ArticleItemType';
@@ -19,3 +20,4 @@ export type { Project } from './types/project/Project';
19
20
  export type { Meta } from './types/project/Meta';
20
21
  export type { KeyframeValueMap, KeyframeAny } from './types/keyframe/Keyframe';
21
22
  export type { CompoundSettings } from './types/article/CompoundSettings';
23
+ export type { Dimensions, Left, Position, RectCoordinates, RectObject, ScaleOrigin, Sides, Top } from './types/article/Rect';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KeyframeType = exports.PositionType = exports.DimensionMode = exports.AnchorSide = exports.AreaAnchor = exports.ArticleItemType = exports.VerticalAlign = exports.TextTransform = exports.TextDecoration = exports.TextAlign = exports.SectionHeightMode = exports.ScrollPlaybackVideoManager = exports.getLayoutMediaQuery = exports.getLayoutStyles = exports.FontFaceGenerator = exports.CntrlClient = void 0;
3
+ exports.KeyframeType = exports.PositionType = exports.DimensionMode = exports.AnchorSide = exports.AreaAnchor = exports.ArticleItemType = exports.VerticalAlign = exports.TextTransform = exports.TextDecoration = exports.TextAlign = exports.SectionHeightMode = exports.Rect = exports.ScrollPlaybackVideoManager = exports.measureFont = exports.getLayoutMediaQuery = exports.getLayoutStyles = exports.FontFaceGenerator = exports.CntrlClient = void 0;
4
4
  // logic
5
5
  var Client_1 = require("./Client/Client");
6
6
  Object.defineProperty(exports, "CntrlClient", { enumerable: true, get: function () { return Client_1.Client; } });
@@ -9,8 +9,11 @@ Object.defineProperty(exports, "FontFaceGenerator", { enumerable: true, get: fun
9
9
  var utils_1 = require("./utils");
10
10
  Object.defineProperty(exports, "getLayoutStyles", { enumerable: true, get: function () { return utils_1.getLayoutStyles; } });
11
11
  Object.defineProperty(exports, "getLayoutMediaQuery", { enumerable: true, get: function () { return utils_1.getLayoutMediaQuery; } });
12
+ Object.defineProperty(exports, "measureFont", { enumerable: true, get: function () { return utils_1.measureFont; } });
12
13
  var ScrollPlaybackVideoManager_1 = require("./ScrollPlaybackVideoManager/ScrollPlaybackVideoManager");
13
14
  Object.defineProperty(exports, "ScrollPlaybackVideoManager", { enumerable: true, get: function () { return ScrollPlaybackVideoManager_1.ScrollPlaybackVideoManager; } });
15
+ var Rect_1 = require("./Rect/Rect");
16
+ Object.defineProperty(exports, "Rect", { enumerable: true, get: function () { return Rect_1.Rect; } });
14
17
  // enums
15
18
  var Section_1 = require("./types/article/Section");
16
19
  Object.defineProperty(exports, "SectionHeightMode", { enumerable: true, get: function () { return Section_1.SectionHeightMode; } });
@@ -0,0 +1,34 @@
1
+ export interface RectObject {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface Position {
8
+ x: number;
9
+ y: number;
10
+ }
11
+ export interface Dimensions {
12
+ width: number;
13
+ height: number;
14
+ }
15
+ export type Left = number;
16
+ export type Top = number;
17
+ export type Right = number;
18
+ export type Bottom = number;
19
+ export type RectCoordinates = [Left, Top, Right, Bottom];
20
+ declare const ScaleOrigins: {
21
+ readonly TopLeft: "top-left";
22
+ readonly TopCenter: "top-center";
23
+ readonly TopRight: "top-right";
24
+ readonly MiddleLeft: "middle-left";
25
+ readonly MiddleCenter: "middle-center";
26
+ readonly MiddleRight: "middle-right";
27
+ readonly BottomLeft: "bottom-left";
28
+ readonly BottomCenter: "bottom-center";
29
+ readonly BottomRight: "bottom-right";
30
+ };
31
+ export type Sides = [top: number, left: number];
32
+ export declare const scaleMatrix: Record<ScaleOrigin, Sides>;
33
+ export type ScaleOrigin = typeof ScaleOrigins[keyof typeof ScaleOrigins];
34
+ export {};
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scaleMatrix = void 0;
4
+ const ScaleOrigins = {
5
+ TopLeft: 'top-left',
6
+ TopCenter: 'top-center',
7
+ TopRight: 'top-right',
8
+ MiddleLeft: 'middle-left',
9
+ MiddleCenter: 'middle-center',
10
+ MiddleRight: 'middle-right',
11
+ BottomLeft: 'bottom-left',
12
+ BottomCenter: 'bottom-center',
13
+ BottomRight: 'bottom-right'
14
+ };
15
+ exports.scaleMatrix = {
16
+ [ScaleOrigins.TopLeft]: [0, 0],
17
+ [ScaleOrigins.TopCenter]: [0, 0.5],
18
+ [ScaleOrigins.TopRight]: [0, 1],
19
+ [ScaleOrigins.MiddleLeft]: [0.5, 0],
20
+ [ScaleOrigins.MiddleCenter]: [0.5, 0.5],
21
+ [ScaleOrigins.MiddleRight]: [0.5, 1],
22
+ [ScaleOrigins.BottomLeft]: [1, 0],
23
+ [ScaleOrigins.BottomCenter]: [1, 0.5],
24
+ [ScaleOrigins.BottomRight]: [1, 1]
25
+ };
package/lib/utils.d.ts CHANGED
@@ -1,3 +1,15 @@
1
1
  import { Layout } from './types/project/Layout';
2
2
  export declare function getLayoutStyles<V, M>(layouts: Layout[], layoutValues: Record<string, V>[], mapToStyles: (values: V[], exemplary: number) => M): string;
3
3
  export declare function getLayoutMediaQuery(layoutId: string, layouts: Layout[]): string;
4
+ export declare function measureFont(font: string, text: string, win?: Window): FontMetrics;
5
+ interface FontMetrics {
6
+ capHeight: number;
7
+ baseline: number;
8
+ fontBoxHeight: number;
9
+ xHeight: number;
10
+ leftMargin: number;
11
+ topMargin: number;
12
+ rightMargin: number;
13
+ bottomMargin: number;
14
+ }
15
+ export {};
package/lib/utils.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getLayoutStyles = getLayoutStyles;
4
4
  exports.getLayoutMediaQuery = getLayoutMediaQuery;
5
+ exports.measureFont = measureFont;
5
6
  function getLayoutStyles(layouts, layoutValues, mapToStyles) {
6
7
  const mediaQueries = layouts
7
8
  .sort((a, b) => a.startsWith - b.startsWith)
@@ -28,3 +29,50 @@ function getLayoutMediaQuery(layoutId, layouts) {
28
29
  }
29
30
  return `@media (min-width: ${current.startsWith}px) and (max-width: ${next.startsWith - 1}px)`;
30
31
  }
32
+ const canvases = new WeakMap();
33
+ if (typeof window !== 'undefined') {
34
+ canvases.set(window, window.document.createElement('canvas'));
35
+ }
36
+ function measureFont(font, text, win = window) {
37
+ const canvas = resolveCanvas(win);
38
+ const context = canvas.getContext('2d');
39
+ if (!context) {
40
+ throw new ReferenceError('Canvas context is not available');
41
+ }
42
+ context.textBaseline = 'top';
43
+ context.font = font;
44
+ // measure "H" for basic font metrics
45
+ const hMetrics = context.measureText('H');
46
+ const capHeight = hMetrics.actualBoundingBoxDescent + hMetrics.actualBoundingBoxAscent;
47
+ const baseline = hMetrics.actualBoundingBoxDescent;
48
+ const topMargin = hMetrics.actualBoundingBoxAscent - hMetrics.fontBoundingBoxAscent;
49
+ // measure "x" for small letters metrics
50
+ const xMetrics = context.measureText('x');
51
+ const xHeight = xMetrics.actualBoundingBoxDescent + xMetrics.actualBoundingBoxAscent;
52
+ // measure "p" for descendants
53
+ const pMetrics = context.measureText('Hp');
54
+ const bottomMargin = pMetrics.actualBoundingBoxDescent - pMetrics.fontBoundingBoxDescent;
55
+ // measure first and last letter to get horizontal margins
56
+ const horMetrics = context.measureText(`${text.charAt(0)}${text.charAt(text.length - 1)}`);
57
+ const leftMargin = -horMetrics.actualBoundingBoxLeft;
58
+ const rightMargin = horMetrics.width - horMetrics.actualBoundingBoxRight;
59
+ return {
60
+ capHeight,
61
+ baseline,
62
+ fontBoxHeight: hMetrics.fontBoundingBoxDescent - hMetrics.fontBoundingBoxAscent,
63
+ xHeight,
64
+ leftMargin,
65
+ topMargin,
66
+ rightMargin,
67
+ bottomMargin
68
+ };
69
+ }
70
+ function resolveCanvas(win) {
71
+ if (typeof window === 'undefined') {
72
+ throw new TypeError('resolveCanvas() called on server');
73
+ }
74
+ if (!canvases.has(win)) {
75
+ canvases.set(win, win.document.createElement('canvas'));
76
+ }
77
+ return canvases.get(win);
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk",
3
- "version": "1.25.1-0",
3
+ "version": "1.25.1-2",
4
4
  "description": "Generic SDK for use in public websites.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",