js-draw 0.9.2 → 0.9.3

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 (39) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/bundle.js +1 -1
  3. package/dist/src/Editor.d.ts +2 -2
  4. package/dist/src/EditorImage.d.ts +1 -1
  5. package/dist/src/EventDispatcher.d.ts +1 -1
  6. package/dist/src/SVGLoader.d.ts +2 -2
  7. package/dist/src/UndoRedoHistory.d.ts +2 -2
  8. package/dist/src/Viewport.d.ts +1 -1
  9. package/dist/src/commands/SerializableCommand.d.ts +1 -1
  10. package/dist/src/components/AbstractComponent.d.ts +3 -3
  11. package/dist/src/components/SVGGlobalAttributesObject.d.ts +1 -1
  12. package/dist/src/components/builders/FreehandLineBuilder.d.ts +2 -0
  13. package/dist/src/components/builders/FreehandLineBuilder.js +10 -2
  14. package/dist/src/components/builders/types.d.ts +1 -1
  15. package/dist/src/components/util/StrokeSmoother.d.ts +1 -1
  16. package/dist/src/math/Mat33.d.ts +1 -1
  17. package/dist/src/math/Path.d.ts +1 -1
  18. package/dist/src/math/Vec2.d.ts +2 -2
  19. package/dist/src/rendering/caching/testUtils.d.ts +1 -1
  20. package/dist/src/rendering/caching/types.d.ts +2 -2
  21. package/dist/src/rendering/renderers/SVGRenderer.js +1 -1
  22. package/dist/src/toolbar/IconProvider.d.ts +1 -1
  23. package/dist/src/toolbar/localization.d.ts +1 -0
  24. package/dist/src/toolbar/localization.js +1 -0
  25. package/dist/src/toolbar/makeColorInput.d.ts +2 -2
  26. package/dist/src/toolbar/widgets/BaseWidget.d.ts +1 -1
  27. package/dist/src/toolbar/widgets/TextToolWidget.js +23 -2
  28. package/dist/src/tools/BaseTool.js +4 -4
  29. package/dist/src/tools/PipetteTool.d.ts +1 -1
  30. package/dist/src/tools/SelectionTool/SelectionHandle.d.ts +3 -3
  31. package/dist/src/tools/TextTool.js +8 -2
  32. package/dist/src/tools/ToolbarShortcutHandler.d.ts +1 -1
  33. package/dist/src/types.d.ts +8 -8
  34. package/package.json +16 -16
  35. package/src/components/builders/FreehandLineBuilder.ts +12 -2
  36. package/src/rendering/renderers/SVGRenderer.ts +1 -1
  37. package/src/toolbar/localization.ts +2 -0
  38. package/src/toolbar/widgets/TextToolWidget.ts +29 -1
  39. package/src/tools/TextTool.ts +10 -2
@@ -29,8 +29,8 @@ import Pointer from './Pointer';
29
29
  import Rect2 from './math/Rect2';
30
30
  import { EditorLocalization } from './localization';
31
31
  import IconProvider from './toolbar/IconProvider';
32
- declare type HTMLPointerEventType = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
33
- declare type HTMLPointerEventFilter = (eventName: HTMLPointerEventType, event: PointerEvent) => boolean;
32
+ type HTMLPointerEventType = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
33
+ type HTMLPointerEventFilter = (eventName: HTMLPointerEventType, event: PointerEvent) => boolean;
34
34
  export interface EditorSettings {
35
35
  /** Defaults to `RenderingMode.CanvasRenderer` */
36
36
  renderingMode: RenderingMode;
@@ -27,7 +27,7 @@ export default class EditorImage {
27
27
  static addElement(elem: AbstractComponent, applyByFlattening?: boolean): SerializableCommand;
28
28
  private static AddElementCommand;
29
29
  }
30
- declare type TooSmallToRenderCheck = (rect: Rect2) => boolean;
30
+ type TooSmallToRenderCheck = (rect: Rect2) => boolean;
31
31
  /** Part of the Editor's image. @internal */
32
32
  export declare class ImageNode {
33
33
  private parent;
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * @packageDocumentation
17
17
  */
18
- declare type CallbackHandler<EventType> = (data: EventType) => void;
18
+ type CallbackHandler<EventType> = (data: EventType) => void;
19
19
  export default class EventDispatcher<EventKeyType extends string | symbol | number, EventMessageType> {
20
20
  private listeners;
21
21
  constructor();
@@ -3,8 +3,8 @@ import { ComponentAddedListener, ImageLoader, OnDetermineExportRectListener, OnP
3
3
  export declare const defaultSVGViewRect: Rect2;
4
4
  export declare const svgAttributesDataKey = "svgAttrs";
5
5
  export declare const svgStyleAttributesDataKey = "svgStyleAttrs";
6
- export declare type SVGLoaderUnknownAttribute = [string, string];
7
- export declare type SVGLoaderUnknownStyleAttribute = {
6
+ export type SVGLoaderUnknownAttribute = [string, string];
7
+ export type SVGLoaderUnknownStyleAttribute = {
8
8
  key: string;
9
9
  value: string;
10
10
  priority?: string;
@@ -1,7 +1,7 @@
1
1
  import Editor from './Editor';
2
2
  import Command from './commands/Command';
3
- declare type AnnounceRedoCallback = (command: Command) => void;
4
- declare type AnnounceUndoCallback = (command: Command) => void;
3
+ type AnnounceRedoCallback = (command: Command) => void;
4
+ type AnnounceUndoCallback = (command: Command) => void;
5
5
  declare class UndoRedoHistory {
6
6
  private readonly editor;
7
7
  private announceRedoCallback;
@@ -4,7 +4,7 @@ import Rect2 from './math/Rect2';
4
4
  import { Point2, Vec2 } from './math/Vec2';
5
5
  import { StrokeDataPoint } from './types';
6
6
  import { EditorNotifier } from './types';
7
- declare type PointDataType<T extends Point2 | StrokeDataPoint | number> = T extends Point2 ? Point2 : number;
7
+ type PointDataType<T extends Point2 | StrokeDataPoint | number> = T extends Point2 ? Point2 : number;
8
8
  export declare abstract class ViewportTransform extends Command {
9
9
  abstract readonly transform: Mat33;
10
10
  }
@@ -1,6 +1,6 @@
1
1
  import Editor from '../Editor';
2
2
  import Command from './Command';
3
- export declare type DeserializationCallback = (data: Record<string, any> | any[], editor: Editor) => SerializableCommand;
3
+ export type DeserializationCallback = (data: Record<string, any> | any[], editor: Editor) => SerializableCommand;
4
4
  export default abstract class SerializableCommand extends Command {
5
5
  private commandTypeId;
6
6
  constructor(commandTypeId: string);
@@ -4,9 +4,9 @@ import Mat33 from '../math/Mat33';
4
4
  import Rect2 from '../math/Rect2';
5
5
  import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
6
6
  import { ImageComponentLocalization } from './localization';
7
- export declare type LoadSaveData = (string[] | Record<symbol, string | number>);
8
- export declare type LoadSaveDataTable = Record<string, Array<LoadSaveData>>;
9
- export declare type DeserializeCallback = (data: string) => AbstractComponent;
7
+ export type LoadSaveData = (string[] | Record<symbol, string | number>);
8
+ export type LoadSaveDataTable = Record<string, Array<LoadSaveData>>;
9
+ export type DeserializeCallback = (data: string) => AbstractComponent;
10
10
  export default abstract class AbstractComponent {
11
11
  private readonly componentKind;
12
12
  protected lastChangedTime: number;
@@ -4,7 +4,7 @@ import Rect2 from '../math/Rect2';
4
4
  import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
5
5
  import AbstractComponent from './AbstractComponent';
6
6
  import { ImageComponentLocalization } from './localization';
7
- declare type GlobalAttrsList = Array<[string, string | null]>;
7
+ type GlobalAttrsList = Array<[string, string | null]>;
8
8
  export default class SVGGlobalAttributesObject extends AbstractComponent {
9
9
  private readonly attrs;
10
10
  protected contentBBox: Rect2;
@@ -24,7 +24,9 @@ export default class FreehandLineBuilder implements ComponentBuilder {
24
24
  private previewStroke;
25
25
  preview(renderer: AbstractRenderer): void;
26
26
  build(): Stroke;
27
+ private getMinFit;
27
28
  private roundPoint;
29
+ private roundDistance;
28
30
  private curveToPathCommands;
29
31
  private addCurve;
30
32
  addPoint(newPoint: StrokeDataPoint): void;
@@ -33,7 +33,7 @@ export default class FreehandLineBuilder {
33
33
  fill: Color4.transparent,
34
34
  stroke: {
35
35
  color: this.startPoint.color,
36
- width: this.averageWidth,
36
+ width: this.roundDistance(this.averageWidth),
37
37
  }
38
38
  };
39
39
  }
@@ -76,13 +76,21 @@ export default class FreehandLineBuilder {
76
76
  this.curveFitter.finalizeCurrentCurve();
77
77
  return this.previewStroke();
78
78
  }
79
- roundPoint(point) {
79
+ getMinFit() {
80
80
  let minFit = Math.min(this.minFitAllowed, this.averageWidth / 2);
81
81
  if (minFit < 1e-10) {
82
82
  minFit = this.minFitAllowed;
83
83
  }
84
+ return minFit;
85
+ }
86
+ roundPoint(point) {
87
+ const minFit = this.getMinFit();
84
88
  return Viewport.roundPoint(point, minFit);
85
89
  }
90
+ roundDistance(dist) {
91
+ const minFit = this.getMinFit();
92
+ return Viewport.roundPoint(dist, minFit);
93
+ }
86
94
  curveToPathCommands(curve) {
87
95
  // Case where no points have been added
88
96
  if (!curve) {
@@ -9,4 +9,4 @@ export interface ComponentBuilder {
9
9
  preview(renderer: AbstractRenderer): void;
10
10
  addPoint(point: StrokeDataPoint): void;
11
11
  }
12
- export declare type ComponentBuilderFactory = (startPoint: StrokeDataPoint, viewport: Viewport) => ComponentBuilder;
12
+ export type ComponentBuilderFactory = (startPoint: StrokeDataPoint, viewport: Viewport) => ComponentBuilder;
@@ -8,7 +8,7 @@ export interface Curve {
8
8
  endWidth: number;
9
9
  endPoint: Vec2;
10
10
  }
11
- declare type OnCurveAddedCallback = (curve: Curve | null) => void;
11
+ type OnCurveAddedCallback = (curve: Curve | null) => void;
12
12
  export declare class StrokeSmoother {
13
13
  private startPoint;
14
14
  private minFitAllowed;
@@ -1,6 +1,6 @@
1
1
  import { Point2, Vec2 } from './Vec2';
2
2
  import Vec3 from './Vec3';
3
- export declare type Mat33Array = [
3
+ export type Mat33Array = [
4
4
  number,
5
5
  number,
6
6
  number,
@@ -30,7 +30,7 @@ export interface MoveToPathCommand {
30
30
  kind: PathCommandType.MoveTo;
31
31
  point: Point2;
32
32
  }
33
- export declare type PathCommand = CubicBezierPathCommand | LinePathCommand | QuadraticBezierPathCommand | MoveToPathCommand;
33
+ export type PathCommand = CubicBezierPathCommand | LinePathCommand | QuadraticBezierPathCommand | MoveToPathCommand;
34
34
  interface IntersectionResult {
35
35
  curve: LineSegment2 | Bezier;
36
36
  parameterValue: number;
@@ -9,5 +9,5 @@ export declare namespace Vec2 {
9
9
  const unitY: Vec3;
10
10
  const zero: Vec3;
11
11
  }
12
- export declare type Point2 = Vec3;
13
- export declare type Vec2 = Vec3;
12
+ export type Point2 = Vec3;
13
+ export type Vec2 = Vec3;
@@ -1,7 +1,7 @@
1
1
  import DummyRenderer from '../renderers/DummyRenderer';
2
2
  import RenderingCache from './RenderingCache';
3
3
  import { CacheProps } from './types';
4
- declare type RenderAllocCallback = (renderer: DummyRenderer) => void;
4
+ type RenderAllocCallback = (renderer: DummyRenderer) => void;
5
5
  export declare const createCache: (onRenderAlloc?: RenderAllocCallback, cacheOptions?: Partial<CacheProps>) => {
6
6
  cache: RenderingCache;
7
7
  editor: import("../../Editor").Editor;
@@ -1,8 +1,8 @@
1
1
  import { Vec2 } from '../../math/Vec2';
2
2
  import AbstractRenderer from '../renderers/AbstractRenderer';
3
3
  import { CacheRecordManager } from './CacheRecordManager';
4
- export declare type CacheAddress = number;
5
- export declare type BeforeDeallocCallback = () => void;
4
+ export type CacheAddress = number;
5
+ export type BeforeDeallocCallback = () => void;
6
6
  export interface CacheProps {
7
7
  createRenderer(): AbstractRenderer;
8
8
  isOfCorrectType(renderer: AbstractRenderer): boolean;
@@ -87,7 +87,7 @@ export default class SVGRenderer extends AbstractRenderer {
87
87
  }
88
88
  if (style.stroke) {
89
89
  pathElem.setAttribute('stroke', style.stroke.color.toHexString());
90
- pathElem.setAttribute('stroke-width', style.stroke.width.toString());
90
+ pathElem.setAttribute('stroke-width', toRoundedString(style.stroke.width));
91
91
  }
92
92
  this.elem.appendChild(pathElem);
93
93
  (_a = this.objectElems) === null || _a === void 0 ? void 0 : _a.push(pathElem);
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
2
2
  import { ComponentBuilderFactory } from '../components/builders/types';
3
3
  import { TextStyle } from '../components/TextComponent';
4
4
  import Pen from '../tools/Pen';
5
- declare type IconType = SVGSVGElement | HTMLImageElement;
5
+ type IconType = SVGSVGElement | HTMLImageElement;
6
6
  export default class IconProvider {
7
7
  makeUndoIcon(): IconType;
8
8
  makeRedoIcon(mirror?: boolean): IconType;
@@ -1,5 +1,6 @@
1
1
  export interface ToolbarLocalization {
2
2
  fontLabel: string;
3
+ textSize: string;
3
4
  touchPanning: string;
4
5
  lockRotation: string;
5
6
  outlinedRectanglePen: string;
@@ -8,6 +8,7 @@ export const defaultToolbarLocalization = {
8
8
  thicknessLabel: 'Thickness: ',
9
9
  colorLabel: 'Color: ',
10
10
  fontLabel: 'Font: ',
11
+ textSize: 'Size: ',
11
12
  resizeImageToSelection: 'Resize image to selection',
12
13
  deleteSelection: 'Delete selection',
13
14
  duplicateSelection: 'Duplicate selection',
@@ -1,6 +1,6 @@
1
1
  import Color4 from '../Color4';
2
2
  import Editor from '../Editor';
3
- declare type OnColorChangeListener = (color: Color4) => void;
4
- declare type SetColorCallback = (color: Color4 | string) => void;
3
+ type OnColorChangeListener = (color: Color4) => void;
4
+ type SetColorCallback = (color: Color4 | string) => void;
5
5
  export declare const makeColorInput: (editor: Editor, onColorChange: OnColorChangeListener) => [HTMLInputElement, HTMLElement, SetColorCallback];
6
6
  export default makeColorInput;
@@ -1,7 +1,7 @@
1
1
  import Editor from '../../Editor';
2
2
  import { KeyPressEvent } from '../../types';
3
3
  import { ToolbarLocalization } from '../localization';
4
- export declare type SavedToolbuttonState = Record<string, any>;
4
+ export type SavedToolbuttonState = Record<string, any>;
5
5
  export default abstract class BaseWidget {
6
6
  #private;
7
7
  protected editor: Editor;
@@ -26,8 +26,11 @@ export default class TextToolWidget extends BaseToolWidget {
26
26
  fillDropdown(dropdown) {
27
27
  const fontRow = document.createElement('div');
28
28
  const colorRow = document.createElement('div');
29
+ const sizeRow = document.createElement('div');
29
30
  const fontInput = document.createElement('select');
30
31
  const fontLabel = document.createElement('label');
32
+ const sizeInput = document.createElement('input');
33
+ const sizeLabel = document.createElement('label');
31
34
  const [colorInput, colorInputContainer, setColorInputValue] = makeColorInput(this.editor, color => {
32
35
  this.tool.setColor(color);
33
36
  });
@@ -40,10 +43,16 @@ export default class TextToolWidget extends BaseToolWidget {
40
43
  fontInput.appendChild(option);
41
44
  fontsInInput.add(fontName);
42
45
  };
46
+ sizeInput.setAttribute('type', 'number');
47
+ sizeInput.min = '1';
48
+ sizeInput.max = '128';
43
49
  fontLabel.innerText = this.localizationTable.fontLabel;
44
50
  colorLabel.innerText = this.localizationTable.colorLabel;
51
+ sizeLabel.innerText = this.localizationTable.textSize;
45
52
  colorInput.id = `${toolbarCSSPrefix}-text-color-input-${TextToolWidget.idCounter++}`;
46
53
  colorLabel.setAttribute('for', colorInput.id);
54
+ sizeInput.id = `${toolbarCSSPrefix}-text-size-input-${TextToolWidget.idCounter++}`;
55
+ sizeLabel.setAttribute('for', sizeInput.id);
47
56
  addFontToInput('monospace');
48
57
  addFontToInput('serif');
49
58
  addFontToInput('sans-serif');
@@ -52,10 +61,18 @@ export default class TextToolWidget extends BaseToolWidget {
52
61
  fontInput.onchange = () => {
53
62
  this.tool.setFontFamily(fontInput.value);
54
63
  };
64
+ sizeInput.onchange = () => {
65
+ const size = parseInt(sizeInput.value);
66
+ if (!isNaN(size) && size > 0) {
67
+ this.tool.setFontSize(size);
68
+ }
69
+ };
55
70
  colorRow.appendChild(colorLabel);
56
71
  colorRow.appendChild(colorInputContainer);
57
72
  fontRow.appendChild(fontLabel);
58
73
  fontRow.appendChild(fontInput);
74
+ sizeRow.appendChild(sizeLabel);
75
+ sizeRow.appendChild(sizeInput);
59
76
  this.updateDropdownInputs = () => {
60
77
  const style = this.tool.getTextStyle();
61
78
  setColorInputValue(style.renderingStyle.fill);
@@ -63,14 +80,15 @@ export default class TextToolWidget extends BaseToolWidget {
63
80
  addFontToInput(style.fontFamily);
64
81
  }
65
82
  fontInput.value = style.fontFamily;
83
+ sizeInput.value = `${style.size}`;
66
84
  };
67
85
  this.updateDropdownInputs();
68
- dropdown.replaceChildren(colorRow, fontRow);
86
+ dropdown.replaceChildren(colorRow, sizeRow, fontRow);
69
87
  return true;
70
88
  }
71
89
  serializeState() {
72
90
  const textStyle = this.tool.getTextStyle();
73
- return Object.assign(Object.assign({}, super.serializeState()), { fontFamily: textStyle.fontFamily, color: textStyle.renderingStyle.fill.toHexString() });
91
+ return Object.assign(Object.assign({}, super.serializeState()), { fontFamily: textStyle.fontFamily, textSize: textStyle.size, color: textStyle.renderingStyle.fill.toHexString() });
74
92
  }
75
93
  deserializeFrom(state) {
76
94
  if (state.fontFamily && typeof (state.fontFamily) === 'string') {
@@ -79,6 +97,9 @@ export default class TextToolWidget extends BaseToolWidget {
79
97
  if (state.color && typeof (state.color) === 'string') {
80
98
  this.tool.setColor(Color4.fromHex(state.color));
81
99
  }
100
+ if (state.textSize && typeof (state.textSize) === 'number') {
101
+ this.tool.setFontSize(state.textSize);
102
+ }
82
103
  super.deserializeFrom(state);
83
104
  }
84
105
  }
@@ -1,15 +1,15 @@
1
1
  import { EditorEventType } from '../types';
2
2
  export default class BaseTool {
3
+ onPointerDown(_event) { return false; }
4
+ onPointerMove(_event) { }
5
+ onPointerUp(_event) { }
6
+ onGestureCancel() { }
3
7
  constructor(notifier, description) {
4
8
  this.notifier = notifier;
5
9
  this.description = description;
6
10
  this.enabled = true;
7
11
  this.group = null;
8
12
  }
9
- onPointerDown(_event) { return false; }
10
- onPointerMove(_event) { }
11
- onPointerUp(_event) { }
12
- onGestureCancel() { }
13
13
  onWheel(_event) {
14
14
  return false;
15
15
  }
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
2
2
  import Editor from '../Editor';
3
3
  import { PointerEvt } from '../types';
4
4
  import BaseTool from './BaseTool';
5
- declare type ColorListener = (color: Color4 | null) => void;
5
+ type ColorListener = (color: Color4 | null) => void;
6
6
  export default class PipetteTool extends BaseTool {
7
7
  private editor;
8
8
  private colorPreviewListener;
@@ -6,9 +6,9 @@ export declare enum HandleShape {
6
6
  Square = 1
7
7
  }
8
8
  export declare const handleSize = 30;
9
- export declare type DragStartCallback = (startPoint: Point2) => void;
10
- export declare type DragUpdateCallback = (canvasPoint: Point2) => void;
11
- export declare type DragEndCallback = () => void;
9
+ export type DragStartCallback = (startPoint: Point2) => void;
10
+ export type DragUpdateCallback = (canvasPoint: Point2) => void;
11
+ export type DragEndCallback = () => void;
12
12
  export default class SelectionHandle {
13
13
  readonly shape: HandleShape;
14
14
  private readonly parentSide;
@@ -108,8 +108,10 @@ export default class TextTool extends BaseTool {
108
108
  this.textInputElem.style.margin = '0';
109
109
  this.textInputElem.style.width = `${this.textInputElem.scrollWidth}px`;
110
110
  this.textInputElem.style.height = `${this.textInputElem.scrollHeight}px`;
111
+ // Get the ascent based on the font, using a character that is tall in most fonts.
112
+ const tallCharacter = '⎢';
113
+ const ascent = this.getTextAscent(tallCharacter, this.textStyle);
111
114
  const rotation = this.textRotation + viewport.getRotationAngle();
112
- const ascent = this.getTextAscent(this.textInputElem.value || 'W', this.textStyle);
113
115
  const scale = this.getTextScaleMatrix();
114
116
  this.textInputElem.style.transform = `${scale.toCSSMatrix()} rotate(${rotation * 180 / Math.PI}deg) translate(0, ${-ascent}px)`;
115
117
  this.textInputElem.style.transformOrigin = 'top left';
@@ -171,7 +173,11 @@ export default class TextTool extends BaseTool {
171
173
  const halfTestRegionSize = Vec2.of(2.5, 2.5).times(this.editor.viewport.getSizeOfPixelOnCanvas());
172
174
  const testRegion = Rect2.fromCorners(canvasPos.minus(halfTestRegionSize), canvasPos.plus(halfTestRegionSize));
173
175
  const targetNodes = this.editor.image.getElementsIntersectingRegion(testRegion);
174
- const targetTextNodes = targetNodes.filter(node => node instanceof TextComponent);
176
+ let targetTextNodes = targetNodes.filter(node => node instanceof TextComponent);
177
+ // Don't try to edit text nodes that contain the viewport (this allows us
178
+ // to zoom in on text nodes and add text on top of them.)
179
+ const visibleRect = this.editor.viewport.visibleRect;
180
+ targetTextNodes = targetTextNodes.filter(node => !node.getBBox().containsRect(visibleRect));
175
181
  // End any TextNodes we're currently editing.
176
182
  this.flushInput();
177
183
  if (targetTextNodes.length > 0) {
@@ -1,7 +1,7 @@
1
1
  import Editor from '../Editor';
2
2
  import { KeyPressEvent } from '../types';
3
3
  import BaseTool from './BaseTool';
4
- declare type KeyPressListener = (event: KeyPressEvent) => boolean;
4
+ type KeyPressListener = (event: KeyPressEvent) => boolean;
5
5
  export default class ToolbarShortcutHandler extends BaseTool {
6
6
  private listeners;
7
7
  constructor(editor: Editor);
@@ -68,9 +68,9 @@ export interface PointerMoveEvt extends PointerEvtBase {
68
68
  export interface PointerUpEvt extends PointerEvtBase {
69
69
  readonly kind: InputEvtType.PointerUpEvt;
70
70
  }
71
- export declare type PointerEvt = PointerDownEvt | PointerMoveEvt | PointerUpEvt;
72
- export declare type InputEvt = KeyPressEvent | KeyUpEvent | WheelEvt | GestureCancelEvt | PointerEvt | CopyEvent | PasteEvent;
73
- export declare type EditorNotifier = EventDispatcher<EditorEventType, EditorEventDataType>;
71
+ export type PointerEvt = PointerDownEvt | PointerMoveEvt | PointerUpEvt;
72
+ export type InputEvt = KeyPressEvent | KeyUpEvent | WheelEvt | GestureCancelEvt | PointerEvt | CopyEvent | PasteEvent;
73
+ export type EditorNotifier = EventDispatcher<EditorEventType, EditorEventDataType>;
74
74
  export declare enum EditorEventType {
75
75
  ToolEnabled = 0,
76
76
  ToolDisabled = 1,
@@ -85,7 +85,7 @@ export declare enum EditorEventType {
85
85
  ColorPickerColorSelected = 10,
86
86
  ToolbarDropdownShown = 11
87
87
  }
88
- declare type EditorToolEventType = EditorEventType.ToolEnabled | EditorEventType.ToolDisabled | EditorEventType.ToolUpdated;
88
+ type EditorToolEventType = EditorEventType.ToolEnabled | EditorEventType.ToolDisabled | EditorEventType.ToolUpdated;
89
89
  export interface EditorToolEvent {
90
90
  readonly kind: EditorToolEventType;
91
91
  readonly tool: BaseTool;
@@ -128,10 +128,10 @@ export interface ToolbarDropdownShownEvent {
128
128
  readonly kind: EditorEventType.ToolbarDropdownShown;
129
129
  readonly parentWidget: BaseWidget;
130
130
  }
131
- export declare type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
132
- export declare type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null;
133
- export declare type ComponentAddedListener = (component: AbstractComponent) => void;
134
- export declare type OnDetermineExportRectListener = (exportRect: Rect2) => void;
131
+ export type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
132
+ export type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null;
133
+ export type ComponentAddedListener = (component: AbstractComponent) => void;
134
+ export type OnDetermineExportRectListener = (exportRect: Rect2) => void;
135
135
  export interface ImageLoader {
136
136
  start(onAddComponent: ComponentAddedListener, onProgressListener: OnProgressListener, onDetermineExportRect?: OnDetermineExportRectListener): Promise<void>;
137
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-draw",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
5
5
  "main": "./dist/src/lib.d.ts",
6
6
  "types": "./dist/src/lib.js",
@@ -83,27 +83,27 @@
83
83
  },
84
84
  "devDependencies": {
85
85
  "@types/bezier-js": "^4.1.0",
86
- "@types/jest": "^29.0.3",
87
- "@types/jsdom": "^20.0.0",
88
- "@types/node": "^18.7.23",
89
- "@typescript-eslint/eslint-plugin": "^5.38.1",
90
- "@typescript-eslint/parser": "^5.38.1",
91
- "css-loader": "^6.7.1",
92
- "eslint": "^8.24.0",
93
- "husky": "^8.0.1",
94
- "jest": "^29.0.3",
95
- "jest-environment-jsdom": "^29.0.3",
96
- "jsdom": "^20.0.0",
86
+ "@types/jest": "^29.2.3",
87
+ "@types/jsdom": "^20.0.1",
88
+ "@types/node": "^18.11.9",
89
+ "@typescript-eslint/eslint-plugin": "^5.44.0",
90
+ "@typescript-eslint/parser": "^5.44.0",
91
+ "css-loader": "^6.7.2",
92
+ "eslint": "^8.28.0",
93
+ "husky": "^8.0.2",
94
+ "jest": "^29.2.3",
95
+ "jest-environment-jsdom": "^29.3.1",
96
+ "jsdom": "^20.0.3",
97
97
  "lint-staged": "^13.0.3",
98
98
  "pinst": "^3.0.0",
99
99
  "style-loader": "^3.3.1",
100
100
  "terser-webpack-plugin": "^5.3.6",
101
- "ts-jest": "^29.0.2",
101
+ "ts-jest": "^29.0.3",
102
102
  "ts-loader": "^9.4.1",
103
103
  "ts-node": "^10.9.1",
104
- "typedoc": "^0.23.15",
105
- "typescript": "^4.8.3",
106
- "webpack": "^5.74.0"
104
+ "typedoc": "^0.23.21",
105
+ "typescript": "^4.9.3",
106
+ "webpack": "^5.75.0"
107
107
  },
108
108
  "bugs": {
109
109
  "url": "https://github.com/personalizedrefrigerator/js-draw/issues"
@@ -55,7 +55,7 @@ export default class FreehandLineBuilder implements ComponentBuilder {
55
55
  fill: Color4.transparent,
56
56
  stroke: {
57
57
  color: this.startPoint.color,
58
- width: this.averageWidth,
58
+ width: this.roundDistance(this.averageWidth),
59
59
  }
60
60
  };
61
61
  }
@@ -107,16 +107,26 @@ export default class FreehandLineBuilder implements ComponentBuilder {
107
107
  return this.previewStroke()!;
108
108
  }
109
109
 
110
- private roundPoint(point: Point2): Point2 {
110
+ private getMinFit(): number {
111
111
  let minFit = Math.min(this.minFitAllowed, this.averageWidth / 2);
112
112
 
113
113
  if (minFit < 1e-10) {
114
114
  minFit = this.minFitAllowed;
115
115
  }
116
+
117
+ return minFit;
118
+ }
116
119
 
120
+ private roundPoint(point: Point2): Point2 {
121
+ const minFit = this.getMinFit();
117
122
  return Viewport.roundPoint(point, minFit);
118
123
  }
119
124
 
125
+ private roundDistance(dist: number): number {
126
+ const minFit = this.getMinFit();
127
+ return Viewport.roundPoint(dist, minFit);
128
+ }
129
+
120
130
  private curveToPathCommands(curve: Curve|null): PathCommand[] {
121
131
  // Case where no points have been added
122
132
  if (!curve) {
@@ -102,7 +102,7 @@ export default class SVGRenderer extends AbstractRenderer {
102
102
 
103
103
  if (style.stroke) {
104
104
  pathElem.setAttribute('stroke', style.stroke.color.toHexString());
105
- pathElem.setAttribute('stroke-width', style.stroke.width.toString());
105
+ pathElem.setAttribute('stroke-width', toRoundedString(style.stroke.width));
106
106
  }
107
107
 
108
108
  this.elem.appendChild(pathElem);
@@ -2,6 +2,7 @@
2
2
 
3
3
  export interface ToolbarLocalization {
4
4
  fontLabel: string;
5
+ textSize: string;
5
6
  touchPanning: string;
6
7
  lockRotation: string;
7
8
  outlinedRectanglePen: string;
@@ -44,6 +45,7 @@ export const defaultToolbarLocalization: ToolbarLocalization = {
44
45
  thicknessLabel: 'Thickness: ',
45
46
  colorLabel: 'Color: ',
46
47
  fontLabel: 'Font: ',
48
+ textSize: 'Size: ',
47
49
  resizeImageToSelection: 'Resize image to selection',
48
50
  deleteSelection: 'Delete selection',
49
51
  duplicateSelection: 'Duplicate selection',