js-draw 0.17.1 → 0.17.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.
- package/CHANGELOG.md +9 -1
- package/dist/bundle.js +1 -1
- package/dist/src/EditorImage.d.ts +6 -6
- package/dist/src/EditorImage.js +83 -42
- package/dist/src/components/TextComponent.d.ts +1 -1
- package/dist/src/components/TextComponent.js +12 -4
- package/dist/src/rendering/RenderingStyle.d.ts +7 -0
- package/dist/src/rendering/RenderingStyle.js +6 -0
- package/dist/src/rendering/TextRenderingStyle.d.ts +13 -0
- package/dist/src/rendering/TextRenderingStyle.js +4 -1
- package/dist/src/tools/FindTool.js +2 -1
- package/dist/src/util/assertions.d.ts +22 -0
- package/dist/src/util/assertions.js +42 -3
- package/package.json +16 -16
- package/src/EditorImage.test.ts +33 -0
- package/src/EditorImage.ts +87 -35
- package/src/components/TextComponent.test.ts +1 -1
- package/src/components/TextComponent.ts +11 -9
- package/src/rendering/RenderingStyle.ts +9 -0
- package/src/rendering/TextRenderingStyle.ts +8 -1
- package/src/tools/FindTool.ts +2 -1
- package/src/util/assertions.ts +51 -3
@@ -72,7 +72,7 @@ describe('TextComponent', () => {
|
|
72
72
|
expect(text.getStyle().color).objEq(Color4.green);
|
73
73
|
});
|
74
74
|
|
75
|
-
it('
|
75
|
+
it('calling forceStyle on the duplicate of a TextComponent should preserve the original\'s style', () => {
|
76
76
|
const originalStyle: TextStyle = {
|
77
77
|
size: 11,
|
78
78
|
fontFamily: 'sans-serif',
|
@@ -5,7 +5,7 @@ import Rect2 from '../math/Rect2';
|
|
5
5
|
import Editor from '../Editor';
|
6
6
|
import { Vec2 } from '../math/Vec2';
|
7
7
|
import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
|
8
|
-
import { TextStyle, textStyleFromJSON, textStyleToJSON } from '../rendering/TextRenderingStyle';
|
8
|
+
import { cloneTextStyle, TextStyle, textStyleFromJSON, textStyleToJSON } from '../rendering/TextRenderingStyle';
|
9
9
|
import AbstractComponent from './AbstractComponent';
|
10
10
|
import { ImageComponentLocalization } from './localization';
|
11
11
|
import RestyleableComponent, { ComponentStyle, createRestyleComponentCommand } from './RestylableComponent';
|
@@ -170,7 +170,7 @@ export default class TextComponent extends AbstractComponent implements Restylea
|
|
170
170
|
|
171
171
|
public forceStyle(style: ComponentStyle, editor: Editor|null): void {
|
172
172
|
if (style.textStyle) {
|
173
|
-
this.style = style.textStyle;
|
173
|
+
this.style = cloneTextStyle(style.textStyle);
|
174
174
|
} else if (style.color) {
|
175
175
|
this.style = {
|
176
176
|
...this.style,
|
@@ -197,12 +197,7 @@ export default class TextComponent extends AbstractComponent implements Restylea
|
|
197
197
|
|
198
198
|
// See this.getStyle
|
199
199
|
public getTextStyle() {
|
200
|
-
return
|
201
|
-
...this.style,
|
202
|
-
renderingStyle: {
|
203
|
-
...this.style.renderingStyle,
|
204
|
-
},
|
205
|
-
};
|
200
|
+
return cloneTextStyle(this.style);
|
206
201
|
}
|
207
202
|
|
208
203
|
public getBaselinePos() {
|
@@ -219,7 +214,14 @@ export default class TextComponent extends AbstractComponent implements Restylea
|
|
219
214
|
}
|
220
215
|
|
221
216
|
protected createClone(): AbstractComponent {
|
222
|
-
|
217
|
+
const clonedTextObjects = this.textObjects.map(obj => {
|
218
|
+
if (typeof obj === 'string') {
|
219
|
+
return obj;
|
220
|
+
} else {
|
221
|
+
return obj.createClone() as TextComponent;
|
222
|
+
}
|
223
|
+
});
|
224
|
+
return new TextComponent(clonedTextObjects, this.transform, this.style);
|
223
225
|
}
|
224
226
|
|
225
227
|
public getText() {
|
@@ -10,6 +10,15 @@ interface RenderingStyle {
|
|
10
10
|
|
11
11
|
export default RenderingStyle;
|
12
12
|
|
13
|
+
export const cloneStyle = (style: RenderingStyle) => {
|
14
|
+
return {
|
15
|
+
fill: style.fill,
|
16
|
+
stroke: style.stroke ? {
|
17
|
+
...style.stroke
|
18
|
+
} : undefined,
|
19
|
+
};
|
20
|
+
};
|
21
|
+
|
13
22
|
export const stylesEqual = (a: RenderingStyle, b: RenderingStyle): boolean => {
|
14
23
|
const result = a === b || (a.fill.eq(b.fill)
|
15
24
|
&& (a.stroke == undefined) === (b.stroke == undefined)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import RenderingStyle, { styleFromJSON, styleToJSON } from './RenderingStyle';
|
1
|
+
import RenderingStyle, { cloneStyle, styleFromJSON, styleToJSON } from './RenderingStyle';
|
2
2
|
|
3
3
|
export interface TextStyle {
|
4
4
|
size: number;
|
@@ -10,6 +10,13 @@ export interface TextStyle {
|
|
10
10
|
|
11
11
|
export default TextStyle;
|
12
12
|
|
13
|
+
export const cloneTextStyle = (style: TextStyle) => {
|
14
|
+
return {
|
15
|
+
...style,
|
16
|
+
renderingStyle: cloneStyle(style.renderingStyle),
|
17
|
+
};
|
18
|
+
};
|
19
|
+
|
13
20
|
export const textStyleFromJSON = (json: any) => {
|
14
21
|
if (typeof json === 'string') {
|
15
22
|
json = JSON.parse(json);
|
package/src/tools/FindTool.ts
CHANGED
@@ -49,7 +49,8 @@ export default class FindTool extends BaseTool {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
if (matchIdx < matches.length) {
|
52
|
-
|
52
|
+
const undoable = false;
|
53
|
+
this.editor.dispatch(this.editor.viewport.zoomTo(matches[matchIdx], true, true), undoable);
|
53
54
|
this.editor.announceForAccessibility(
|
54
55
|
this.editor.localization.focusedFoundText(matchIdx + 1, matches.length)
|
55
56
|
);
|
package/src/util/assertions.ts
CHANGED
@@ -1,7 +1,55 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
/**
|
3
|
+
* Compile-time assertion that a branch of code is unreachable.
|
4
|
+
* @internal
|
5
|
+
*/
|
5
6
|
export const assertUnreachable = (key: never): never => {
|
7
|
+
// See https://stackoverflow.com/a/39419171/17055750
|
6
8
|
throw new Error(`Should be unreachable. Key: ${key}.`);
|
7
9
|
};
|
10
|
+
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Throws an exception if the typeof given value is not a number or `value` is NaN.
|
14
|
+
*
|
15
|
+
* @example
|
16
|
+
* ```ts
|
17
|
+
* const foo: unknown = 3;
|
18
|
+
* assertIsNumber(foo);
|
19
|
+
*
|
20
|
+
* assertIsNumber('hello, world'); // throws an Error.
|
21
|
+
* ```
|
22
|
+
*
|
23
|
+
*
|
24
|
+
*/
|
25
|
+
export const assertIsNumber = (value: any, allowNaN: boolean = false): value is number => {
|
26
|
+
if (typeof value !== 'number' || (!allowNaN && isNaN(value))) {
|
27
|
+
throw new Error('Given value is not a number');
|
28
|
+
// return false;
|
29
|
+
}
|
30
|
+
|
31
|
+
return true;
|
32
|
+
};
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Throws if any of `values` is not of type number.
|
36
|
+
*/
|
37
|
+
export const assertIsNumberArray = (
|
38
|
+
values: any[], allowNaN: boolean = false
|
39
|
+
): values is number[] => {
|
40
|
+
if (typeof values !== 'object') {
|
41
|
+
throw new Error('Asserting isNumberArray: Given entity is not an array');
|
42
|
+
}
|
43
|
+
|
44
|
+
if (!assertIsNumber(values['length'])) {
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
|
48
|
+
for (const value of values) {
|
49
|
+
if (!assertIsNumber(value, allowNaN)) {
|
50
|
+
return false;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
return true;
|
55
|
+
};
|