diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 275238f..0000000 --- a/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "env": { - "test": { - "plugins": [ - "transform-class-properties", - "transform-object-rest-spread", - "transform-es2015-modules-commonjs", - "transform-es2015-classes" - ] - } - } -} diff --git a/.eslintrc.js b/.eslintrc.js index c115e53..eee4482 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,15 +1,27 @@ +const path = require('path'); + module.exports = { - extends: ['plugin:@shopify/esnext', 'plugin:@shopify/jest', 'plugin:@shopify/prettier'], + extends: [ + 'plugin:@shopify/typescript', + 'plugin:@shopify/jest', + 'plugin:@shopify/prettier', + ], + parser: '@typescript-eslint/parser', env: { browser: true, node: true, }, rules: { - 'import/no-unresolved': 'off', - 'import/no-extraneous-dependencies': 'off', - 'class-methods-use-this': 'off', - 'line-comment-position': 0, - 'lines-around-comment': 'off', 'jest/valid-title': 'off', }, + settings: { + 'import/resolver': { + node: { + paths: [ + path.resolve(__dirname, 'src'), + path.resolve(__dirname, 'test'), + ], + }, + }, + }, }; diff --git a/.github/workflows/tests.yml b/.github/workflows/ci.yml similarity index 77% rename from .github/workflows/tests.yml rename to .github/workflows/ci.yml index 965bc00..eae5027 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/ci.yml @@ -25,5 +25,11 @@ jobs: - name: Lint run: yarn lint + - name: Library typecheck + run: yarn type-check + + - name: Scripts typecheck + run: yarn type-check:scripts + - name: Test run: yarn test diff --git a/.prettierrc b/.prettierrc index 87e22d8..12e07af 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1 @@ -{ - "trailingComma": "all", - "printWidth": 120, - "singleQuote": true, - "bracketSpacing": false, - "arrowParens": "always" -} +"@shopify/prettier-config" diff --git a/.vscode/launch.json b/.vscode/launch.json index 8734b85..43a7c9f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,21 +1,16 @@ { - "version": "0.2.0", + "version": "1.0.0", "configurations": [ { "type": "node", "request": "launch", "name": "Jest Tests", - "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", + "program": "${workspaceRoot}/node_modules/.bin/jest", + "console": "integratedTerminal", "args": [ - "--config", - "config.json", "-i", "--watchAll" ], - "internalConsoleOptions": "openOnSessionStart", - "outFiles": [ - "${workspaceRoot}/dist/**/*" - ], } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c3c9f2..d735395 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,9 @@ "**/node_modules": true, "lib": true }, + "[typescript]": { + "editor.formatOnSave": false, + }, "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 291a1e3..53c1300 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,21 +14,21 @@ orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or +- The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 826ef61..94ba0dd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,10 +7,10 @@ appreciated and encouraged. 1. [Code of Conduct](#code-of-conduct) 2. [How to contribute](#how-to-contribute) - 1. [Creating issues](#creating-issues) - 2. [Opening pull requests](#opening-pull-requests) - 3. [JS Docblocks](#js-docblocks) -4. [How to run locally](#how-to-run-locally) + 1. [Creating issues](#creating-issues) + 2. [Opening pull requests](#opening-pull-requests) + 3. [JS Docblocks](#js-docblocks) +3. [How to run locally](#how-to-run-locally) ## Code of Conduct diff --git a/config.json b/config.json deleted file mode 100644 index a2d4725..0000000 --- a/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "testEnvironment": "jsdom", - "testMatch": ["/src/**/*.test.js"], - "setupFiles": ["/scripts/test/environment.js"], - "setupFilesAfterEnv": ["/scripts/test/setup.js"], - "transform": {".*": "/node_modules/babel-jest"}, - "moduleFileExtensions": ["js"], - "collectCoverageFrom": [ - "src/**/*.js", - "!src/**/*/index.js", - "!src/index.js", - "!src/index.legacy.js" - ], - "coverageDirectory": "./coverage/", - "collectCoverage": true, - "moduleDirectories": ["node_modules", "src", "scripts/test"] -} diff --git a/index.d.ts b/index.d.ts index 2245854..1fc1dd3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,560 +1,585 @@ declare module '@shopify/draggable/lib/draggable.bundle.legacy' { - export * from '@shopify/draggable'; + export * from '@shopify/draggable'; } declare module '@shopify/draggable/lib/es5/draggable.bundle' { - export * from '@shopify/draggable'; + export * from '@shopify/draggable'; } declare module '@shopify/draggable/lib/es5/draggable.bundle.legacy' { - export * from '@shopify/draggable'; + export * from '@shopify/draggable'; } declare module '@shopify/draggable' { - abstract class AbstractEvent { - constructor(data: DataT); - static readonly type: string; // Abstract, waiting on https://github.com/Microsoft/TypeScript/issues/14600 - static readonly cancelable: boolean; // Abstract, waiting on https://github.com/Microsoft/TypeScript/issues/14600 - readonly type: string; - readonly cancelable: boolean; - cancel(): void; - canceled(): boolean; - clone(): AbstractEvent; - } - - export { AbstractEvent as BaseEvent }; - - type GetEventByEventName = eventName extends 'draggable:initialize' - ? DraggableInitializedEvent - : eventName extends 'draggable:destroy' - ? DraggableDestroyEvent - : eventName extends 'drag:start' - ? DragStartEvent - : eventName extends 'drag:move' - ? DragMoveEvent - : eventName extends 'drag:over' - ? DragOverEvent - : eventName extends 'drag:over:container' - ? DragOverContainerEvent - : eventName extends 'drag:out' - ? DragOutEvent - : eventName extends 'drag:out:container' - ? DragOutContainerEvent - : eventName extends 'drag:stop' - ? DragStopEvent - : eventName extends 'drag:stopped' - ? DragStoppedEvent - : eventName extends 'drag:pressure' - ? DragPressureEvent - : eventName extends 'mirror:create' - ? MirrorCreateEvent - : eventName extends 'mirror:created' - ? MirrorCreatedEvent - : eventName extends 'mirror:attached' - ? MirrorAttachedEvent - : eventName extends 'mirror:move' - ? MirrorMoveEvent - : eventName extends 'mirror:moved' - ? MirrorMovedEvent - : eventName extends 'mirror:destroy' - ? MirrorDestroyEvent - : eventName extends 'droppable:start' - ? DroppableStartEvent - : eventName extends 'droppable:dropped' - ? DroppableDroppedEvent - : eventName extends 'droppable:returned' - ? DroppableReturnedEvent - : eventName extends 'droppable:stop' - ? DroppableStopEvent - : eventName extends 'sortable:start' - ? SortableStartEvent - : eventName extends 'sortable:sort' - ? SortableSortEvent - : eventName extends 'sortable:sorted' - ? SortableSortedEvent - : eventName extends 'sortable:stop' - ? SortableStopEvent - : eventName extends 'swappable:start' - ? SwappableStartEvent - : eventName extends 'swappable:swap' - ? SwappableSwapEvent - : eventName extends 'swappable:swapped' - ? SwappableSwappedEvent - : eventName extends 'swappable:stop' - ? SwappableStopEvent - : eventName extends 'collidable:in' - ? CollidableInEvent - : eventName extends 'collidable:out' - ? CollidableOutEvent - : eventName extends 'snap:in' - ? SnapInEvent - : eventName extends 'snap:out' - ? SnapOutEvent - : AbstractEvent; - - export interface DelayOptions { - mouse?: number; - drag?: number; - touch?: number; - } - - /** - * DragEvent - */ - export class DragEvent extends AbstractEvent { - readonly source: HTMLElement; - readonly originalSource: HTMLElement; - readonly mirror: HTMLElement; - readonly sourceContainer: HTMLElement; - readonly sensorEvent: SensorEvent; - readonly originalEvent: Event; - } - - export class DragStartEvent extends DragEvent { } - - export class DragMoveEvent extends DragEvent { } - - export class DragOverEvent extends DragEvent { - readonly overContainer: HTMLElement; - readonly over: HTMLElement; - } - - export class DragOutEvent extends DragEvent { - readonly overContainer: HTMLElement; - readonly over: HTMLElement; - } - - export class DragOverContainerEvent extends DragEvent { - readonly overContainer: HTMLElement; - } - - export class DragOutContainerEvent extends DragEvent { - readonly overContainer: HTMLElement; - } - - export class DragPressureEvent extends DragEvent { - readonly pressure: number; - } - - export class DragStopEvent extends DragEvent { } - - export class DragStoppedEvent extends DragEvent { } - - /** - * DraggableEvent - */ - export type DraggableEventNames = - 'draggable:initialize' | - 'draggable:destroy' | - 'drag:start' | - 'drag:move' | - 'drag:over' | - 'drag:over:container' | - 'drag:out' | - 'drag:out:container' | - 'drag:stop' | - 'drag:pressure' | - MirrorEventNames; - - export class DraggableEvent extends AbstractEvent { - readonly draggable: Draggable; - } - export class DraggableInitializedEvent extends DraggableEvent { } - export class DraggableDestroyEvent extends DraggableEvent { } - - export type DraggableClassNames = - 'body:dragging' | - 'container:dragging' | - 'source:dragging' | - 'source:placed' | - 'container:placed' | - 'draggable:over' | - 'container:over' | - 'source:original' | - 'mirror'; - - export type DraggableContainer = HTMLElement | HTMLElement[] | NodeList; - - export interface DraggableOptions { - draggable?: string; - distance?: number; - handle?: string | NodeList | HTMLElement[] | HTMLElement | ((currentElement: HTMLElement) => HTMLElement); - delay?: number | DelayOptions; - plugins?: Array; - sensors?: Sensor[]; - classes?: { [key in DraggableClassNames]: string | string[] }; - announcements?: AnnouncementOptions; - collidables?: Collidables; - mirror?: MirrorOptions; - scrollable?: ScrollableOptions; - swapAnimation?: SwapAnimationOptions; - sortAnimation?: SortAnimationOptions; - } - - export class Draggable { - static Plugins: { - Announcement: typeof Announcement, - Focusable: typeof Focusable, - Mirror: typeof Mirror, - Scrollable: typeof Scrollable - }; - constructor(containers: DraggableContainer, options?: DraggableOptions); - destroy(): void; - on(eventName: T, callback: (event: GetEventByEventName) => void): this; - off(eventName: T, callback: (event: GetEventByEventName) => void): this; - trigger(event: AbstractEvent): void; - addPlugin(...plugins: Array): this; - removePlugin(...plugins: Array): this; - addSensor(...sensors: Array): this; - removeSensor(...sensors: Array): this; - addContainer(...containers: HTMLElement[]): this; - removeContainer(...containers: HTMLElement[]): this; - getClassNameFor(name: DraggableClassNames): string; - getClassNamesFor(name: DraggableClassNames): string[]; - isDragging(): boolean; - getDraggableElementsForContainer(container: HTMLElement): HTMLElement[]; - } - - export abstract class AbstractPlugin { - protected draggable: Draggable; - constructor(draggable: Draggable); - protected abstract attach(): void; - protected abstract detach(): void; - } - - export { AbstractPlugin as BasePlugin }; - - /** - * Announcement Plugin - */ - export interface AnnouncementOptions { - expire: number; - [key: string]: string | (() => string) | number; - } - - class Announcement extends AbstractPlugin { - options: AnnouncementOptions; - protected attach(): void; - protected detach(): void; - } - - /** - * Focusable Plugin - */ - class Focusable extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - getElements(): HTMLElement[]; - } - - /** - * Mirror Plugin - */ - export type MirrorEventNames = - 'mirror:create' | - 'mirror:created' | - 'mirror:attached' | - 'mirror:move' | - 'mirror:destroy'; - - export class MirrorEvent extends AbstractEvent { - readonly source: HTMLElement; - readonly originalSource: HTMLElement; - readonly sourceContainer: HTMLElement; - readonly sensorEvent: SensorEvent; - readonly originalEvent: Event; - } - export class MirrorCreateEvent extends MirrorEvent { } - export class MirrorCreatedEvent extends MirrorEvent { - readonly mirror: HTMLElement; - } - export class MirrorAttachedEvent extends MirrorEvent { - readonly mirror: HTMLElement; - } - export class MirrorMoveEvent extends MirrorEvent { - readonly mirror: HTMLElement; - readonly passedThreshX: boolean; - readonly passedThreshY: boolean; - } - export class MirrorMovedEvent extends MirrorEvent { - readonly mirror: HTMLElement; - readonly passedThreshX: boolean; - readonly passedThreshY: boolean; - } - export class MirrorDestroyEvent extends MirrorEvent { - readonly mirror: HTMLElement; - } - - export interface MirrorOptions { - xAxis?: boolean; - yAxis?: boolean; - constrainDimensions?: boolean; - cursorOffsetX?: number; - cursorOffsetY?: number; - appendTo?: string | HTMLElement | ((source: HTMLElement) => HTMLElement); - } - - class Mirror extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - getElements(): HTMLElement[]; - } - - /** - * Scrollable Plugin - */ - export interface ScrollableOptions { - speed?: number; - sensitivity?: number; - scrollableElements?: HTMLElement[]; - } - - class Scrollable extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - /** - * Sensors - */ - export class SensorEvent extends AbstractEvent { - readonly originalEvent: Event; - readonly clientX: number; - readonly clientY: number; - readonly target: HTMLElement; - readonly container: HTMLElement; - readonly pressure: number; - } - - export class DragStartSensorEvent extends SensorEvent { } - - export class DragMoveSensorEvent extends SensorEvent { } - - export class DragStopSensorEvent extends SensorEvent { } - - export class DragPressureSensorEvent extends SensorEvent { } - - export interface SensorOptions { - delay?: number | DelayOptions; - } - - export class Sensor { - constructor(containers: HTMLElement | HTMLElement[] | NodeList, options?: SensorOptions); - attach(): this; - detach(): this; - addContainer(...containers: HTMLElement[]): void; - removeContainer(...containers: HTMLElement[]): void; - trigger(element: HTMLElement, sensorEvent: SensorEvent): SensorEvent; - } - - export interface Sensors { - DragSensor: typeof DragSensor; - } - - export class DragSensor extends Sensor { } - - export class ForceTouchSensor extends Sensor { } - - export class MouseSensor extends Sensor { } - - export class TouchSensor extends Sensor { } - - /** - * Droppable - */ - export type DroppableEventNames = - 'droppable:start' | - 'droppable:dropped' | - 'droppable:returned' | - 'droppable:stop' | - DraggableEventNames; - - export class DroppableEvent extends AbstractEvent { - readonly dragEvent: DragEvent; - } - - export class DroppableStartEvent extends DroppableEvent { - dropzone: HTMLElement; - } - - export class DroppableDroppedEvent extends DroppableEvent { - dropzone: HTMLElement; - } - - export class DroppableReturnedEvent extends DroppableEvent { - dropzone: HTMLElement; - } - - export class DroppableStopEvent extends DroppableEvent { - dropzone: HTMLElement; - } - - export type DroppableClassNames = - DraggableClassNames | - 'droppable:active' | - 'droppable:occupied'; - - export interface DroppableOptions extends DraggableOptions { - dropzone: string | NodeList | HTMLElement[] | (() => NodeList | HTMLElement[]); - classes?: { [key in DroppableClassNames]: string }; - } - - export class Droppable extends Draggable { - constructor(containers: DraggableContainer, options: DroppableOptions); - getClassNameFor(name: DroppableClassNames): string; - } - - /** - * Sortable - */ - export type SortableEventNames = - 'sortable:start' | - 'sortable:sort' | - 'sortable:sorted' | - 'sortable:stop' | - DraggableEventNames; - - export class SortableEvent extends AbstractEvent { - readonly dragEvent: DragEvent; - } - - export class SortableStartEvent extends SortableEvent { - readonly startIndex: number; - readonly startContainer: HTMLElement; - } - - export class SortableSortEvent extends SortableEvent { - readonly oldIndex: number; - readonly newIndex: number; - readonly oldContainer: HTMLElement; - readonly newContainer: HTMLElement; - } - - export class SortableSortedEvent extends SortableEvent { - readonly oldIndex: number; - readonly newIndex: number; - readonly oldContainer: HTMLElement; - readonly newContainer: HTMLElement; - } - - export class SortableStopEvent extends SortableEvent { - readonly oldIndex: number; - readonly newIndex: number; - readonly oldContainer: HTMLElement; - readonly newContainer: HTMLElement; - } - - export class Sortable extends Draggable { } - - /** - * Swappable - */ - export type SwappableEventNames = - 'swappable:start' | - 'swappable:swap' | - 'swappable:swapped' | - 'swappable:stop' | - DraggableEventNames; - - export class SwappableEvent extends AbstractEvent { - readonly dragEvent: DragEvent; - } - - export class SwappableStartEvent extends SwappableEvent { } - - export class SwappableSwapEvent extends SwappableEvent { - readonly over: HTMLElement; - readonly overContainer: HTMLElement; - } - - export class SwappableSwappedEvent extends SwappableEvent { - readonly swappedElement: HTMLElement; - } - - export class SwappableStopEvent extends SwappableEvent { } - - export class Swappable extends Draggable { } - - /** - * Collidable Plugin - */ - export type CollidableEventNames = - 'collidable:in' | - 'collidable:out'; - - export class CollidableEvent extends AbstractEvent { - readonly dragEvent: DragEvent; - readonly collidingElement: HTMLElement; - } - export class CollidableInEvent extends CollidableEvent { } - export class CollidableOutEvent extends CollidableEvent { } - - export type Collidables = string | NodeList | HTMLElement[] | (() => NodeList | HTMLElement[]); - - class Collidable extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - /** - * ResizeMirror Plugin - */ - class ResizeMirror extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - /** - * Snappable Plugin - */ - export type SnappableEventNames = - 'snap:in' | - 'snap:out'; - - export class SnapEvent extends AbstractEvent { - readonly dragEvent: DragEvent; - readonly snappable: HTMLElement; - } - export class SnapInEvent extends SnapEvent { } - export class SnapOutEvent extends SnapEvent { } - - class Snappable extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - /** - * SwapAnimation Plugin - */ - export interface SwapAnimationOptions { - duration: number; - easingFunction: string; - horizontal: boolean; - } - - class SwapAnimation extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - /** - * SortAnimation - */ - export interface SortAnimationOptions { - duration?: number; - easingFunction?: string; - } - - class SortAnimation extends AbstractPlugin { - protected attach(): void; - protected detach(): void; - } - - export const Plugins: { - Collidable: typeof Collidable, - SwapAnimation: typeof SwapAnimation, - SortAnimation: typeof SortAnimation, - ResizeMirror: typeof ResizeMirror, - Snappable: typeof Snappable, + abstract class AbstractEvent { + // Abstract, waiting on https://github.com/Microsoft/TypeScript/issues/14600 + static readonly type: string; + // Abstract, waiting on https://github.com/Microsoft/TypeScript/issues/14600 + static readonly cancelable: boolean; + readonly type: string; + readonly cancelable: boolean; + constructor(data: TData); + cancel(): void; + canceled(): boolean; + clone(): AbstractEvent; + } + + export {AbstractEvent as BaseEvent}; + + type GetEventByEventName = + TEventName extends 'draggable:initialize' + ? DraggableInitializedEvent + : TEventName extends 'draggable:destroy' + ? DraggableDestroyEvent + : TEventName extends 'drag:start' + ? DragStartEvent + : TEventName extends 'drag:move' + ? DragMoveEvent + : TEventName extends 'drag:over' + ? DragOverEvent + : TEventName extends 'drag:over:container' + ? DragOverContainerEvent + : TEventName extends 'drag:out' + ? DragOutEvent + : TEventName extends 'drag:out:container' + ? DragOutContainerEvent + : TEventName extends 'drag:stop' + ? DragStopEvent + : TEventName extends 'drag:stopped' + ? DragStoppedEvent + : TEventName extends 'drag:pressure' + ? DragPressureEvent + : TEventName extends 'mirror:create' + ? MirrorCreateEvent + : TEventName extends 'mirror:created' + ? MirrorCreatedEvent + : TEventName extends 'mirror:attached' + ? MirrorAttachedEvent + : TEventName extends 'mirror:move' + ? MirrorMoveEvent + : TEventName extends 'mirror:moved' + ? MirrorMovedEvent + : TEventName extends 'mirror:destroy' + ? MirrorDestroyEvent + : TEventName extends 'droppable:start' + ? DroppableStartEvent + : TEventName extends 'droppable:dropped' + ? DroppableDroppedEvent + : TEventName extends 'droppable:returned' + ? DroppableReturnedEvent + : TEventName extends 'droppable:stop' + ? DroppableStopEvent + : TEventName extends 'sortable:start' + ? SortableStartEvent + : TEventName extends 'sortable:sort' + ? SortableSortEvent + : TEventName extends 'sortable:sorted' + ? SortableSortedEvent + : TEventName extends 'sortable:stop' + ? SortableStopEvent + : TEventName extends 'swappable:start' + ? SwappableStartEvent + : TEventName extends 'swappable:swap' + ? SwappableSwapEvent + : TEventName extends 'swappable:swapped' + ? SwappableSwappedEvent + : TEventName extends 'swappable:stop' + ? SwappableStopEvent + : TEventName extends 'collidable:in' + ? CollidableInEvent + : TEventName extends 'collidable:out' + ? CollidableOutEvent + : TEventName extends 'snap:in' + ? SnapInEvent + : TEventName extends 'snap:out' + ? SnapOutEvent + : AbstractEvent; + + export interface DelayOptions { + mouse?: number; + drag?: number; + touch?: number; + } + + /** + * DragEvent + */ + export class DragEvent extends AbstractEvent { + readonly source: HTMLElement; + readonly originalSource: HTMLElement; + readonly mirror: HTMLElement; + readonly sourceContainer: HTMLElement; + readonly sensorEvent: SensorEvent; + readonly originalEvent: Event; + } + + export class DragStartEvent extends DragEvent {} + + export class DragMoveEvent extends DragEvent {} + + export class DragOverEvent extends DragEvent { + readonly overContainer: HTMLElement; + readonly over: HTMLElement; + } + + export class DragOutEvent extends DragEvent { + readonly overContainer: HTMLElement; + readonly over: HTMLElement; + } + + export class DragOverContainerEvent extends DragEvent { + readonly overContainer: HTMLElement; + } + + export class DragOutContainerEvent extends DragEvent { + readonly overContainer: HTMLElement; + } + + export class DragPressureEvent extends DragEvent { + readonly pressure: number; + } + + export class DragStopEvent extends DragEvent {} + + export class DragStoppedEvent extends DragEvent {} + + /** + * DraggableEvent + */ + export type DraggableEventNames = + | 'draggable:initialize' + | 'draggable:destroy' + | 'drag:start' + | 'drag:move' + | 'drag:over' + | 'drag:over:container' + | 'drag:out' + | 'drag:out:container' + | 'drag:stop' + | 'drag:pressure' + | MirrorEventNames; + + export class DraggableEvent extends AbstractEvent { + readonly draggable: Draggable; + } + export class DraggableInitializedEvent extends DraggableEvent {} + export class DraggableDestroyEvent extends DraggableEvent {} + + export type DraggableClassNames = + | 'body:dragging' + | 'container:dragging' + | 'source:dragging' + | 'source:placed' + | 'container:placed' + | 'draggable:over' + | 'container:over' + | 'source:original' + | 'mirror'; + + export type DraggableContainer = HTMLElement | HTMLElement[] | NodeList; + + export interface DraggableOptions { + draggable?: string; + distance?: number; + handle?: + | string + | NodeList + | HTMLElement[] + | HTMLElement + | ((currentElement: HTMLElement) => HTMLElement); + delay?: number | DelayOptions; + plugins?: (typeof AbstractPlugin)[]; + sensors?: Sensor[]; + classes?: {[key in DraggableClassNames]: string | string[]}; + announcements?: AnnouncementOptions; + collidables?: Collidables; + mirror?: MirrorOptions; + scrollable?: ScrollableOptions; + swapAnimation?: SwapAnimationOptions; + sortAnimation?: SortAnimationOptions; + } + + export class Draggable { + static Plugins: { + Announcement: typeof Announcement; + Focusable: typeof Focusable; + Mirror: typeof Mirror; + Scrollable: typeof Scrollable; }; + + constructor(containers: DraggableContainer, options?: DraggableOptions); + destroy(): void; + on( + eventName: T, + callback: (event: GetEventByEventName) => void, + ): this; + + off( + eventName: T, + callback: (event: GetEventByEventName) => void, + ): this; + + trigger(event: AbstractEvent): void; + addPlugin(...plugins: (typeof AbstractPlugin)[]): this; + removePlugin(...plugins: (typeof AbstractPlugin)[]): this; + addSensor(...sensors: (typeof Sensor)[]): this; + removeSensor(...sensors: (typeof Sensor)[]): this; + addContainer(...containers: HTMLElement[]): this; + removeContainer(...containers: HTMLElement[]): this; + getClassNameFor(name: DraggableClassNames): string; + getClassNamesFor(name: DraggableClassNames): string[]; + isDragging(): boolean; + getDraggableElementsForContainer(container: HTMLElement): HTMLElement[]; + } + + export abstract class AbstractPlugin { + protected draggable: Draggable; + constructor(draggable: Draggable); + protected abstract attach(): void; + protected abstract detach(): void; + } + + export {AbstractPlugin as BasePlugin}; + + /** + * Announcement Plugin + */ + export interface AnnouncementOptions { + expire: number; + [key: string]: string | (() => string) | number; + } + + class Announcement extends AbstractPlugin { + options: AnnouncementOptions; + protected attach(): void; + protected detach(): void; + } + + /** + * Focusable Plugin + */ + class Focusable extends AbstractPlugin { + getElements(): HTMLElement[]; + protected attach(): void; + protected detach(): void; + } + + /** + * Mirror Plugin + */ + export type MirrorEventNames = + | 'mirror:create' + | 'mirror:created' + | 'mirror:attached' + | 'mirror:move' + | 'mirror:destroy'; + + export class MirrorEvent extends AbstractEvent { + readonly source: HTMLElement; + readonly originalSource: HTMLElement; + readonly sourceContainer: HTMLElement; + readonly sensorEvent: SensorEvent; + readonly originalEvent: Event; + } + export class MirrorCreateEvent extends MirrorEvent {} + export class MirrorCreatedEvent extends MirrorEvent { + readonly mirror: HTMLElement; + } + export class MirrorAttachedEvent extends MirrorEvent { + readonly mirror: HTMLElement; + } + export class MirrorMoveEvent extends MirrorEvent { + readonly mirror: HTMLElement; + readonly passedThreshX: boolean; + readonly passedThreshY: boolean; + } + export class MirrorMovedEvent extends MirrorEvent { + readonly mirror: HTMLElement; + readonly passedThreshX: boolean; + readonly passedThreshY: boolean; + } + export class MirrorDestroyEvent extends MirrorEvent { + readonly mirror: HTMLElement; + } + + export interface MirrorOptions { + xAxis?: boolean; + yAxis?: boolean; + constrainDimensions?: boolean; + cursorOffsetX?: number; + cursorOffsetY?: number; + appendTo?: string | HTMLElement | ((source: HTMLElement) => HTMLElement); + } + + class Mirror extends AbstractPlugin { + getElements(): HTMLElement[]; + protected attach(): void; + protected detach(): void; + } + + /** + * Scrollable Plugin + */ + export interface ScrollableOptions { + speed?: number; + sensitivity?: number; + scrollableElements?: HTMLElement[]; + } + + class Scrollable extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + /** + * Sensors + */ + export class SensorEvent extends AbstractEvent { + readonly originalEvent: Event; + readonly clientX: number; + readonly clientY: number; + readonly target: HTMLElement; + readonly container: HTMLElement; + readonly pressure: number; + } + + export class DragStartSensorEvent extends SensorEvent {} + + export class DragMoveSensorEvent extends SensorEvent {} + + export class DragStopSensorEvent extends SensorEvent {} + + export class DragPressureSensorEvent extends SensorEvent {} + + export interface SensorOptions { + delay?: number | DelayOptions; + } + + export class Sensor { + constructor( + containers: HTMLElement | HTMLElement[] | NodeList, + options?: SensorOptions, + ); + + attach(): this; + detach(): this; + addContainer(...containers: HTMLElement[]): void; + removeContainer(...containers: HTMLElement[]): void; + trigger(element: HTMLElement, sensorEvent: SensorEvent): SensorEvent; + } + + export interface Sensors { + DragSensor: typeof DragSensor; + } + + export class DragSensor extends Sensor {} + + export class ForceTouchSensor extends Sensor {} + + export class MouseSensor extends Sensor {} + + export class TouchSensor extends Sensor {} + + /** + * Droppable + */ + export type DroppableEventNames = + | 'droppable:start' + | 'droppable:dropped' + | 'droppable:returned' + | 'droppable:stop' + | DraggableEventNames; + + export class DroppableEvent extends AbstractEvent { + readonly dragEvent: DragEvent; + } + + export class DroppableStartEvent extends DroppableEvent { + dropzone: HTMLElement; + } + + export class DroppableDroppedEvent extends DroppableEvent { + dropzone: HTMLElement; + } + + export class DroppableReturnedEvent extends DroppableEvent { + dropzone: HTMLElement; + } + + export class DroppableStopEvent extends DroppableEvent { + dropzone: HTMLElement; + } + + export type DroppableClassNames = + | DraggableClassNames + | 'droppable:active' + | 'droppable:occupied'; + + export interface DroppableOptions extends DraggableOptions { + dropzone: + | string + | NodeList + | HTMLElement[] + | (() => NodeList | HTMLElement[]); + classes?: {[key in DroppableClassNames]: string}; + } + + export class Droppable extends Draggable { + constructor(containers: DraggableContainer, options: DroppableOptions); + getClassNameFor(name: DroppableClassNames): string; + } + + /** + * Sortable + */ + export type SortableEventNames = + | 'sortable:start' + | 'sortable:sort' + | 'sortable:sorted' + | 'sortable:stop' + | DraggableEventNames; + + export class SortableEvent extends AbstractEvent { + readonly dragEvent: DragEvent; + } + + export class SortableStartEvent extends SortableEvent { + readonly startIndex: number; + readonly startContainer: HTMLElement; + } + + export class SortableSortEvent extends SortableEvent { + readonly oldIndex: number; + readonly newIndex: number; + readonly oldContainer: HTMLElement; + readonly newContainer: HTMLElement; + } + + export class SortableSortedEvent extends SortableEvent { + readonly oldIndex: number; + readonly newIndex: number; + readonly oldContainer: HTMLElement; + readonly newContainer: HTMLElement; + } + + export class SortableStopEvent extends SortableEvent { + readonly oldIndex: number; + readonly newIndex: number; + readonly oldContainer: HTMLElement; + readonly newContainer: HTMLElement; + } + + export class Sortable extends Draggable {} + + /** + * Swappable + */ + export type SwappableEventNames = + | 'swappable:start' + | 'swappable:swap' + | 'swappable:swapped' + | 'swappable:stop' + | DraggableEventNames; + + export class SwappableEvent extends AbstractEvent { + readonly dragEvent: DragEvent; + } + + export class SwappableStartEvent extends SwappableEvent {} + + export class SwappableSwapEvent extends SwappableEvent { + readonly over: HTMLElement; + readonly overContainer: HTMLElement; + } + + export class SwappableSwappedEvent extends SwappableEvent { + readonly swappedElement: HTMLElement; + } + + export class SwappableStopEvent extends SwappableEvent {} + + export class Swappable extends Draggable {} + + /** + * Collidable Plugin + */ + export type CollidableEventNames = 'collidable:in' | 'collidable:out'; + + export class CollidableEvent extends AbstractEvent { + readonly dragEvent: DragEvent; + readonly collidingElement: HTMLElement; + } + export class CollidableInEvent extends CollidableEvent {} + export class CollidableOutEvent extends CollidableEvent {} + + export type Collidables = + | string + | NodeList + | HTMLElement[] + | (() => NodeList | HTMLElement[]); + + class Collidable extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + /** + * ResizeMirror Plugin + */ + class ResizeMirror extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + /** + * Snappable Plugin + */ + export type SnappableEventNames = 'snap:in' | 'snap:out'; + + export class SnapEvent extends AbstractEvent { + readonly dragEvent: DragEvent; + readonly snappable: HTMLElement; + } + export class SnapInEvent extends SnapEvent {} + export class SnapOutEvent extends SnapEvent {} + + class Snappable extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + /** + * SwapAnimation Plugin + */ + export interface SwapAnimationOptions { + duration: number; + easingFunction: string; + horizontal: boolean; + } + + class SwapAnimation extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + /** + * SortAnimation + */ + export interface SortAnimationOptions { + duration?: number; + easingFunction?: string; + } + + class SortAnimation extends AbstractPlugin { + protected attach(): void; + protected detach(): void; + } + + export const Plugins: { + Collidable: typeof Collidable; + SwapAnimation: typeof SwapAnimation; + SortAnimation: typeof SortAnimation; + ResizeMirror: typeof ResizeMirror; + Snappable: typeof Snappable; + }; } diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..e16b087 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,31 @@ +module.exports = { + testEnvironment: 'jsdom', + testMatch: ['/src/**/*.test.(js|ts)'], + setupFiles: ['/test/environment.ts'], + setupFilesAfterEnv: ['/test/setup.ts'], + transform: { + '\\.(ts|js)': [ + 'babel-jest', + { + babelrc: false, + presets: [ + ['@shopify/babel-preset', {typescript: true, isWebpack5: true}], + ], + sourceMaps: 'inline', + }, + ], + }, + moduleFileExtensions: ['js', 'ts'], + collectCoverageFrom: [ + 'src/**/*.js', + '!src/**/*/index.js', + '!src/index.js', + '!src/index.legacy.js', + ], + moduleNameMapper: { + 'shared/(.*)': '/src/shared/$1', + }, + coverageDirectory: './coverage/', + collectCoverage: true, + moduleDirectories: ['node_modules', 'src', 'test'], +}; diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 6fc92ba..0000000 --- a/jsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "./src/" - } -} diff --git a/package.json b/package.json index a6e936c..eaa53b2 100644 --- a/package.json +++ b/package.json @@ -27,15 +27,18 @@ "scripts": { "start": "concurrently \"yarn watch\" \"cd examples && yarn && yarn start\"", "build": "yarn build:production", - "watch": "node scripts/watch.js", + "watch": "ts-node --project='./scripts/tsconfig.json' ./scripts/watch.ts", "prepare": "yarn build:development", "prepublishOnly": "yarn build:production", - "lint": "eslint ./src ./scripts --max-warnings 0", + "lint": "eslint ./src ./scripts ./test --max-warnings 0", + "type-check": "tsc --noEmit", + "type-check:scripts": "tsc --noEmit --project scripts", "esdoc": "esdoc -c esdoc.json", - "test": "jest --config config.json", - "test-ci": "jest --config config.json --coverage && codecov", - "build:development": "node scripts/build.js", - "build:production": "node scripts/build.js --production" + "test": "jest", + "test-ci": "jest --coverage && codecov", + "build:development": "ts-node --project='./scripts/tsconfig.json' ./scripts/build.ts", + "build:production": "ts-node --project='./scripts/tsconfig.json' ./scripts/build.ts --production", + "verify": "yarn lint && yarn type-check && yarn type-check:scripts && yarn build && yarn test" }, "files": [ "lib/**/*.js", @@ -43,14 +46,17 @@ ], "devDependencies": { "@babel/core": "^7.22.20", + "@microsoft/tsdoc": "^0.14.2", "@shopify/babel-preset": "^25.0.0", "@shopify/eslint-plugin": "^43.0.0", + "@shopify/prettier-config": "^1.1.2", + "@shopify/typescript-configs": "^5.1.0", + "@types/jest": "^29.5.5", + "@types/node": "^20.6.3", + "@types/webpack": "^5.28.2", + "@types/webpack-bundle-analyzer": "^4.6.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", - "babel-plugin-transform-class-properties": "^7.0.0-beta.3", - "babel-plugin-transform-es2015-classes": "^7.0.0-beta.3", - "babel-plugin-transform-es2015-modules-commonjs": "^7.0.0-beta.3", - "babel-plugin-transform-object-rest-spread": "^7.0.0-beta.3", "babel-preset-shopify": "^21.0.0", "codecov": "^3.0.2", "concurrently": "^3.5.1", @@ -59,10 +65,15 @@ "esdoc-ecmascript-proposal-plugin": "^1.0.0", "esdoc-standard-plugin": "^1.0.0", "eslint": "^8.49.0", + "eslint-plugin-tsdoc": "^0.2.17", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "prettier": "^3.0.3", "timers": "^0.1.1", + "ts-jest": "^29.1.1", + "ts-loader": "^9.4.4", + "ts-node": "^10.9.1", + "typescript": "^5.2.2", "webpack": "^5.88.2", "webpack-bundle-analyzer": "^4.9.1", "webpack-cli": "^5.1.4" diff --git a/scripts/build/.eslintrc.js b/scripts/.eslintrc.js similarity index 100% rename from scripts/build/.eslintrc.js rename to scripts/.eslintrc.js diff --git a/scripts/build.js b/scripts/build.js deleted file mode 100644 index 7d194e6..0000000 --- a/scripts/build.js +++ /dev/null @@ -1,16 +0,0 @@ -const webpack = require('webpack'); - -const {isProd, useAnalyser} = require('./build/config'); -const {createConfig: createDevelopmentConfig} = require('./build/development'); -const {createConfig: createProductionConfig} = require('./build/production'); -const {runner} = require('./build/utils'); - -let compiler; - -if (isProd) { - compiler = webpack(createProductionConfig({analyser: useAnalyser})); -} else { - compiler = webpack(createDevelopmentConfig({analyser: useAnalyser})); -} - -compiler.run(runner); diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..c945cfa --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,16 @@ +import webpack from 'webpack'; + +import {isProd, useAnalyser} from './build/config'; +import {createConfig as createDevelopmentConfig} from './build/development'; +import {createConfig as createProductionConfig} from './build/production'; +import {runner} from './build/runner'; + +let compiler; + +if (isProd) { + compiler = webpack(createProductionConfig({analyser: useAnalyser})); +} else { + compiler = webpack(createDevelopmentConfig({analyser: useAnalyser})); +} + +compiler.run(runner); diff --git a/scripts/build/bundles.js b/scripts/build/bundles.ts similarity index 90% rename from scripts/build/bundles.js rename to scripts/build/bundles.ts index 0c9838a..400db92 100644 --- a/scripts/build/bundles.js +++ b/scripts/build/bundles.ts @@ -1,4 +1,11 @@ -const bundles = [ +export interface Bundle { + name: string; + filename: string; + source: string; + path?: string; +} + +export const bundles: Bundle[] = [ { name: 'Draggable', filename: 'draggable.bundle', @@ -76,5 +83,3 @@ const bundles = [ path: 'plugins/', }, ]; - -module.exports = {bundles}; diff --git a/scripts/build/config.js b/scripts/build/config.js deleted file mode 100644 index a6cae51..0000000 --- a/scripts/build/config.js +++ /dev/null @@ -1,15 +0,0 @@ -const args = process.argv.filter((value, index) => index >= 2); -const useAnalyser = args.find((value) => value === '--analyser'); -const isProd = args.find((value) => value === '--production'); - -const rootPath = `${__dirname}/../../`; -const targetPath = isProd ? `${rootPath}lib/` : `${rootPath}examples/packages/@shopify/draggable`; -const resolveModules = ['node_modules', 'src/']; - -module.exports = { - isProd, - rootPath, - targetPath, - resolveModules, - useAnalyser, -}; diff --git a/scripts/build/config.ts b/scripts/build/config.ts new file mode 100644 index 0000000..053f136 --- /dev/null +++ b/scripts/build/config.ts @@ -0,0 +1,9 @@ +const args = process.argv.filter((_, index) => index >= 2); + +export const useAnalyser = args.some((value) => value === '--analyser'); +export const isProd = args.find((value) => value === '--production'); +export const rootPath = `${__dirname}/../../`; +export const targetPath = isProd + ? `${rootPath}lib/` + : `${rootPath}examples/packages/@shopify/draggable`; +export const resolveModules = ['node_modules', 'src/']; diff --git a/scripts/build/development.js b/scripts/build/development.js deleted file mode 100644 index 3855ecb..0000000 --- a/scripts/build/development.js +++ /dev/null @@ -1,49 +0,0 @@ -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; - -const {targetPath, resolveModules} = require('./config'); - -function createConfig({analyser}) { - const plugins = []; - const minimize = Boolean(analyser); - - if (analyser) { - plugins.push(new BundleAnalyzerPlugin({analyzerMode: 'static', openAnalyzer: false})); - } - - return { - mode: 'development', - entry: `./src/index.js`, - output: { - path: targetPath, - filename: `index.js`, - library: 'Draggable', - libraryTarget: 'umd', - umdNamedDefine: true, - }, - optimization: { - minimize, - }, - resolve: { - modules: resolveModules, - }, - plugins, - module: { - rules: [ - { - test: /(\.js)$/, - loader: 'babel-loader', - exclude: /node_modules/, - options: { - plugins: [ - 'transform-class-properties', - 'transform-object-rest-spread', - 'transform-es2015-modules-commonjs', - ], - }, - }, - ], - }, - }; -} - -module.exports = {createConfig}; diff --git a/scripts/build/development.ts b/scripts/build/development.ts new file mode 100644 index 0000000..b10d539 --- /dev/null +++ b/scripts/build/development.ts @@ -0,0 +1,56 @@ +import type {Configuration} from 'webpack'; +import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; + +import {targetPath, resolveModules} from './config'; + +interface Options { + analyser?: boolean; +} + +export function createConfig({analyser}: Options): Configuration { + const plugins: Configuration['plugins'] = []; + const minimize = Boolean(analyser); + + if (analyser) { + plugins.push( + new BundleAnalyzerPlugin({analyzerMode: 'static', openAnalyzer: false}), + ); + } + + return { + mode: 'development', + entry: `./src/index.js`, + output: { + path: targetPath, + filename: `index.js`, + library: 'Draggable', + libraryTarget: 'umd', + umdNamedDefine: true, + }, + optimization: { + minimize, + }, + resolve: { + extensions: ['.js', '.ts'], + modules: resolveModules, + }, + plugins, + module: { + rules: [ + { + test: /(\.js)$/, + loader: 'babel-loader', + exclude: /node_modules/, + }, + { + test: /(\.ts)$/, + loader: 'ts-loader', + exclude: /node_modules/, + options: { + transpileOnly: true, + }, + }, + ], + }, + }; +} diff --git a/scripts/build/production.js b/scripts/build/production.ts similarity index 58% rename from scripts/build/production.js rename to scripts/build/production.ts index def4feb..fac9e3d 100644 --- a/scripts/build/production.js +++ b/scripts/build/production.ts @@ -1,13 +1,19 @@ -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; +import type {Configuration} from 'webpack'; +import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; -const {targetPath, resolveModules} = require('./config'); -const {bundles} = require('./bundles'); +import {targetPath, resolveModules} from './config'; +import {bundles} from './bundles'; +import type {Bundle} from './bundles'; -function createBundleConfig(bundle, {analyser}) { +interface Options { + analyser?: boolean; +} + +function createBundleConfig(bundle: Bundle, {analyser}: Options) { const outputPath = bundle.path || ''; const minimize = Boolean(analyser); - const plugins = []; - const es5Plugins = []; + const plugins: Configuration['plugins'] = []; + const es5Plugins: Configuration['plugins'] = []; if (analyser) { plugins.push( @@ -19,7 +25,7 @@ function createBundleConfig(bundle, {analyser}) { ); } - const config = { + const config: Configuration = { mode: 'production', entry: `./src/${bundle.source}.js`, output: { @@ -33,6 +39,7 @@ function createBundleConfig(bundle, {analyser}) { minimize, }, resolve: { + extensions: ['.js', '.ts'], modules: resolveModules, }, plugins, @@ -42,12 +49,13 @@ function createBundleConfig(bundle, {analyser}) { test: /(\.js)$/, loader: 'babel-loader', exclude: /node_modules/, + }, + { + test: /(\.ts)$/, + loader: 'ts-loader', + exclude: /node_modules/, options: { - plugins: [ - 'transform-class-properties', - 'transform-object-rest-spread', - 'transform-es2015-modules-commonjs', - ], + transpileOnly: true, }, }, ], @@ -81,6 +89,14 @@ function createBundleConfig(bundle, {analyser}) { presets: [['@shopify/babel-preset']], }, }, + { + test: /(\.ts)$/, + loader: 'ts-loader', + exclude: /node_modules/, + options: { + transpileOnly: true, + }, + }, ], }, }; @@ -88,8 +104,9 @@ function createBundleConfig(bundle, {analyser}) { return [config, es5Config]; } -function createConfig(options) { - return bundles.reduce((configs, bundle) => [...configs, ...createBundleConfig(bundle, options)], []); +export function createConfig(options: Options): Configuration[] { + return bundles.reduce( + (configs, bundle) => [...configs, ...createBundleConfig(bundle, options)], + [], + ); } - -module.exports = {createConfig}; diff --git a/scripts/build/utils.js b/scripts/build/runner.ts similarity index 58% rename from scripts/build/utils.js rename to scripts/build/runner.ts index c8241d1..c4fce57 100644 --- a/scripts/build/utils.js +++ b/scripts/build/runner.ts @@ -1,10 +1,16 @@ -function runner(error, stats) { +import type {Stats, MultiStats} from 'webpack'; + +export function runner(error?: Error | null, stats?: Stats | MultiStats) { /* eslint-disable no-console */ if (error) { console.error(error); return; } + if (!stats) { + return; + } + console.log( stats.toString({ chunks: false, @@ -13,5 +19,3 @@ function runner(error, stats) { ); /* eslint-enable no-console */ } - -module.exports = {runner}; diff --git a/scripts/test/helpers/plugin.js b/scripts/test/helpers/plugin.js deleted file mode 100644 index 1cbfa1d..0000000 --- a/scripts/test/helpers/plugin.js +++ /dev/null @@ -1,23 +0,0 @@ -import AbstractPlugin from 'shared/AbstractPlugin'; - -export class TestPlugin extends AbstractPlugin { - constructor(draggable) { - super(draggable); - - jest.spyOn(this, 'attachFunction').mockImplementation(); - jest.spyOn(this, 'detachFunction').mockImplementation(); - } - - attach() { - this.attachFunction(); - } - - detach() { - this.detachFunction(); - } - - /* eslint-disable no-empty-function */ - attachFunction() {} - detachFunction() {} - /* eslint-enable no-empty-function */ -} diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 0000000..646b56b --- /dev/null +++ b/scripts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@shopify/typescript-configs/base.json", + "compilerOptions": { + "baseUrl": ".", + "rootDir": "../", + "module": "commonjs", + "target": "es2022", + "esModuleInterop": true, + "useUnknownInCatchVariables": false + }, + "include": ["../config/**/*", "./**/*"] +} diff --git a/scripts/watch.js b/scripts/watch.js deleted file mode 100644 index 29fafb3..0000000 --- a/scripts/watch.js +++ /dev/null @@ -1,14 +0,0 @@ -const webpack = require('webpack'); - -const {createConfig: createDevelopmentConfig} = require('./build/development'); -const {runner} = require('./build/utils'); - -const compiler = webpack(createDevelopmentConfig({analyser: false})); - -compiler.watch( - { - aggregateTimeout: 300, - poll: 1000, - }, - runner, -); diff --git a/scripts/watch.ts b/scripts/watch.ts new file mode 100644 index 0000000..97c5c59 --- /dev/null +++ b/scripts/watch.ts @@ -0,0 +1,14 @@ +import webpack from 'webpack'; + +import {createConfig as createDevelopmentConfig} from './build/development'; +import {runner} from './build/runner'; + +const compiler = webpack(createDevelopmentConfig({analyser: false})); + +compiler.watch( + { + aggregateTimeout: 300, + poll: 1000, + }, + runner, +); diff --git a/src/Draggable/DragEvent/DragEvent.js b/src/Draggable/DragEvent/DragEvent.ts similarity index 66% rename from src/Draggable/DragEvent/DragEvent.js rename to src/Draggable/DragEvent/DragEvent.ts index 899ca23..22724d4 100644 --- a/src/Draggable/DragEvent/DragEvent.js +++ b/src/Draggable/DragEvent/DragEvent.ts @@ -1,14 +1,37 @@ import AbstractEvent from 'shared/AbstractEvent'; +/** + * DragEventData + * @interface DragEventData + */ +interface DragEventData { + source: HTMLElement; + originalSource: HTMLElement; + mirror: HTMLElement; + sourceContainer: HTMLElement; + sensorEvent: any; +} + /** * Base drag event * @class DragEvent * @module DragEvent * @extends AbstractEvent */ -export class DragEvent extends AbstractEvent { +export class DragEvent< + T extends DragEventData, +> extends AbstractEvent { static type = 'drag'; + /** + * DragEvent constructor. + * @constructs DragEvent + * @param {DragEventData} data - Event data + */ + constructor(public data: T) { + super(data); + } + /** * Draggables source element * @property source @@ -80,7 +103,7 @@ export class DragEvent extends AbstractEvent { * @module DragStartEvent * @extends DragEvent */ -export class DragStartEvent extends DragEvent { +export class DragStartEvent extends DragEvent { static type = 'drag:start'; static cancelable = true; } @@ -91,17 +114,26 @@ export class DragStartEvent extends DragEvent { * @module DragMoveEvent * @extends DragEvent */ -export class DragMoveEvent extends DragEvent { +export class DragMoveEvent extends DragEvent { static type = 'drag:move'; } +/** + * DragOverEventData + * @interface DragOverEventData + */ +interface DragOverEventData extends DragEventData { + overContainer: HTMLElement; + over: HTMLElement; +} + /** * Drag over event * @class DragOverEvent * @module DragOverEvent * @extends DragEvent */ -export class DragOverEvent extends DragEvent { +export class DragOverEvent extends DragEvent { static type = 'drag:over'; static cancelable = true; @@ -126,13 +158,22 @@ export class DragOverEvent extends DragEvent { } } +/** + * DragOutEventData + * @interface DragOutEventData + */ +interface DragOutEventData extends DragEventData { + overContainer: HTMLElement; + over: HTMLElement; +} + /** * Drag out event * @class DragOutEvent * @module DragOutEvent * @extends DragEvent */ -export class DragOutEvent extends DragEvent { +export class DragOutEvent extends DragEvent { static type = 'drag:out'; /** @@ -156,13 +197,22 @@ export class DragOutEvent extends DragEvent { } } +/** + * DragOverContainerEventData + * @interface DragOverContainerEventData + */ +interface DragOverContainerEventData extends DragEventData { + overContainer: HTMLElement; + over: HTMLElement; +} + /** * Drag over container event * @class DragOverContainerEvent * @module DragOverContainerEvent * @extends DragEvent */ -export class DragOverContainerEvent extends DragEvent { +export class DragOverContainerEvent extends DragEvent { static type = 'drag:over:container'; /** @@ -176,13 +226,21 @@ export class DragOverContainerEvent extends DragEvent { } } +/** + * DragOutContainerEventData + * @interface DragOutContainerEventData + */ +interface DragOutContainerEventData extends DragEventData { + overContainer: HTMLElement; +} + /** * Drag out container event * @class DragOutContainerEvent * @module DragOutContainerEvent * @extends DragEvent */ -export class DragOutContainerEvent extends DragEvent { +export class DragOutContainerEvent extends DragEvent { static type = 'drag:out:container'; /** @@ -196,13 +254,21 @@ export class DragOutContainerEvent extends DragEvent { } } +/** + * DragPressureEventData + * @interface DragPressureEventData + */ +interface DragPressureEventData extends DragEventData { + pressure: number; +} + /** * Drag pressure event * @class DragPressureEvent * @module DragPressureEvent * @extends DragEvent */ -export class DragPressureEvent extends DragEvent { +export class DragPressureEvent extends DragEvent { static type = 'drag:pressure'; /** @@ -222,7 +288,7 @@ export class DragPressureEvent extends DragEvent { * @module DragStopEvent * @extends DragEvent */ -export class DragStopEvent extends DragEvent { +export class DragStopEvent extends DragEvent { static type = 'drag:stop'; static cancelable = true; } @@ -235,6 +301,6 @@ export class DragStopEvent extends DragEvent { * @module DragStoppedEvent * @extends DragEvent */ -export class DragStoppedEvent extends DragEvent { +export class DragStoppedEvent extends DragEvent { static type = 'drag:stopped'; } diff --git a/src/Draggable/Draggable.js b/src/Draggable/Draggable.js index 4a5fa49..4dc4436 100644 --- a/src/Draggable/Draggable.js +++ b/src/Draggable/Draggable.js @@ -3,7 +3,10 @@ import {closest} from 'shared/utils'; import {Announcement, Focusable, Mirror, Scrollable} from './Plugins'; import Emitter from './Emitter'; import {MouseSensor, TouchSensor} from './Sensors'; -import {DraggableInitializedEvent, DraggableDestroyEvent} from './DraggableEvent'; +import { + DraggableInitializedEvent, + DraggableDestroyEvent, +} from './DraggableEvent'; import { DragStartEvent, DragMoveEvent, @@ -28,8 +31,14 @@ const dragStop = Symbol('dragStop'); * @const {Function} defaultAnnouncements['drag:stop'] */ const defaultAnnouncements = { - 'drag:start': (event) => `Picked up ${event.source.textContent.trim() || event.source.id || 'draggable element'}`, - 'drag:stop': (event) => `Released ${event.source.textContent.trim() || event.source.id || 'draggable element'}`, + 'drag:start': (event) => + `Picked up ${ + event.source.textContent.trim() || event.source.id || 'draggable element' + }`, + 'drag:stop': (event) => + `Released ${ + event.source.textContent.trim() || event.source.id || 'draggable element' + }`, }; const defaultClasses = { @@ -103,7 +112,9 @@ export default class Draggable { } else if (containers instanceof HTMLElement) { this.containers = [containers]; } else { - throw new Error('Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`'); + throw new Error( + 'Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`', + ); } this.options = { @@ -225,10 +236,14 @@ export default class Draggable { * @example draggable.removePlugin(MirrorPlugin, CustomMirrorPlugin) */ removePlugin(...plugins) { - const removedPlugins = this.plugins.filter((plugin) => plugins.includes(plugin.constructor)); + const removedPlugins = this.plugins.filter((plugin) => + plugins.includes(plugin.constructor), + ); removedPlugins.forEach((plugin) => plugin.detach()); - this.plugins = this.plugins.filter((plugin) => !plugins.includes(plugin.constructor)); + this.plugins = this.plugins.filter( + (plugin) => !plugins.includes(plugin.constructor), + ); return this; } @@ -240,7 +255,9 @@ export default class Draggable { * @example draggable.addSensor(ForceTouchSensor, CustomSensor) */ addSensor(...sensors) { - const activeSensors = sensors.map((Sensor) => new Sensor(this.containers, this.options)); + const activeSensors = sensors.map( + (Sensor) => new Sensor(this.containers, this.options), + ); activeSensors.forEach((sensor) => sensor.attach()); this.sensors = [...this.sensors, ...activeSensors]; @@ -256,10 +273,14 @@ export default class Draggable { * @example draggable.removeSensor(TouchSensor, DragSensor) */ removeSensor(...sensors) { - const removedSensors = this.sensors.filter((sensor) => sensors.includes(sensor.constructor)); + const removedSensors = this.sensors.filter((sensor) => + sensors.includes(sensor.constructor), + ); removedSensors.forEach((sensor) => sensor.detach()); - this.sensors = this.sensors.filter((sensor) => !sensors.includes(sensor.constructor)); + this.sensors = this.sensors.filter( + (sensor) => !sensors.includes(sensor.constructor), + ); return this; } @@ -283,7 +304,9 @@ export default class Draggable { * @example draggable.removeContainer(document.body) */ removeContainer(...containers) { - this.containers = this.containers.filter((container) => !containers.includes(container)); + this.containers = this.containers.filter( + (container) => !containers.includes(container), + ); this.sensors.forEach((sensor) => sensor.removeContainer(...containers)); return this; } @@ -373,10 +396,14 @@ export default class Draggable { * @return {HTMLElement[]} */ getDraggableElementsForContainer(container) { - const allDraggableElements = container.querySelectorAll(this.options.draggable); + const allDraggableElements = container.querySelectorAll( + this.options.draggable, + ); return [...allDraggableElements].filter((childElement) => { - return childElement !== this.originalSource && childElement !== this.mirror; + return ( + childElement !== this.originalSource && childElement !== this.mirror + ); }); } @@ -400,7 +427,11 @@ export default class Draggable { return; } - if (this.options.handle && target && !closest(target, this.options.handle)) { + if ( + this.options.handle && + target && + !closest(target, this.options.handle) + ) { sensorEvent.cancel(); return; } @@ -410,12 +441,19 @@ export default class Draggable { if (this.lastPlacedSource && this.lastPlacedContainer) { clearTimeout(this.placedTimeoutID); - this.lastPlacedSource.classList.remove(...this.getClassNamesFor('source:placed')); - this.lastPlacedContainer.classList.remove(...this.getClassNamesFor('container:placed')); + this.lastPlacedSource.classList.remove( + ...this.getClassNamesFor('source:placed'), + ); + this.lastPlacedContainer.classList.remove( + ...this.getClassNamesFor('container:placed'), + ); } this.source = this.originalSource.cloneNode(true); - this.originalSource.parentNode.insertBefore(this.source, this.originalSource); + this.originalSource.parentNode.insertBefore( + this.source, + this.originalSource, + ); this.originalSource.style.display = 'none'; const dragStartEvent = new DragStartEvent({ @@ -435,9 +473,13 @@ export default class Draggable { return; } - this.originalSource.classList.add(...this.getClassNamesFor('source:original')); + this.originalSource.classList.add( + ...this.getClassNamesFor('source:original'), + ); this.source.classList.add(...this.getClassNamesFor('source:dragging')); - this.sourceContainer.classList.add(...this.getClassNamesFor('container:dragging')); + this.sourceContainer.classList.add( + ...this.getClassNamesFor('container:dragging'), + ); document.body.classList.add(...this.getClassNamesFor('body:dragging')); applyUserSelect(document.body, 'none'); @@ -482,10 +524,13 @@ export default class Draggable { target = closest(target, this.options.draggable); const withinCorrectContainer = closest(sensorEvent.target, this.containers); const overContainer = sensorEvent.overContainer || withinCorrectContainer; - const isLeavingContainer = this.currentOverContainer && overContainer !== this.currentOverContainer; + const isLeavingContainer = + this.currentOverContainer && overContainer !== this.currentOverContainer; const isLeavingDraggable = this.currentOver && target !== this.currentOver; - const isOverContainer = overContainer && this.currentOverContainer !== overContainer; - const isOverDraggable = withinCorrectContainer && target && this.currentOver !== target; + const isOverContainer = + overContainer && this.currentOverContainer !== overContainer; + const isOverDraggable = + withinCorrectContainer && target && this.currentOver !== target; if (isLeavingDraggable) { const dragOutEvent = new DragOutEvent({ @@ -497,7 +542,9 @@ export default class Draggable { overContainer: this.currentOverContainer, }); - this.currentOver.classList.remove(...this.getClassNamesFor('draggable:over')); + this.currentOver.classList.remove( + ...this.getClassNamesFor('draggable:over'), + ); this.currentOver = null; this.trigger(dragOutEvent); @@ -512,7 +559,9 @@ export default class Draggable { overContainer: this.currentOverContainer, }); - this.currentOverContainer.classList.remove(...this.getClassNamesFor('container:over')); + this.currentOverContainer.classList.remove( + ...this.getClassNamesFor('container:over'), + ); this.currentOverContainer = null; this.trigger(dragOutContainerEvent); @@ -573,24 +622,37 @@ export default class Draggable { this.trigger(dragStopEvent); - if (!dragStopEvent.canceled()) this.source.parentNode.insertBefore(this.originalSource, this.source); + if (!dragStopEvent.canceled()) + this.source.parentNode.insertBefore(this.originalSource, this.source); this.source.remove(); this.originalSource.style.display = ''; this.source.classList.remove(...this.getClassNamesFor('source:dragging')); - this.originalSource.classList.remove(...this.getClassNamesFor('source:original')); - this.originalSource.classList.add(...this.getClassNamesFor('source:placed')); - this.sourceContainer.classList.add(...this.getClassNamesFor('container:placed')); - this.sourceContainer.classList.remove(...this.getClassNamesFor('container:dragging')); + this.originalSource.classList.remove( + ...this.getClassNamesFor('source:original'), + ); + this.originalSource.classList.add( + ...this.getClassNamesFor('source:placed'), + ); + this.sourceContainer.classList.add( + ...this.getClassNamesFor('container:placed'), + ); + this.sourceContainer.classList.remove( + ...this.getClassNamesFor('container:dragging'), + ); document.body.classList.remove(...this.getClassNamesFor('body:dragging')); applyUserSelect(document.body, ''); if (this.currentOver) { - this.currentOver.classList.remove(...this.getClassNamesFor('draggable:over')); + this.currentOver.classList.remove( + ...this.getClassNamesFor('draggable:over'), + ); } if (this.currentOverContainer) { - this.currentOverContainer.classList.remove(...this.getClassNamesFor('container:over')); + this.currentOverContainer.classList.remove( + ...this.getClassNamesFor('container:over'), + ); } this.lastPlacedSource = this.originalSource; @@ -598,11 +660,15 @@ export default class Draggable { this.placedTimeoutID = setTimeout(() => { if (this.lastPlacedSource) { - this.lastPlacedSource.classList.remove(...this.getClassNamesFor('source:placed')); + this.lastPlacedSource.classList.remove( + ...this.getClassNamesFor('source:placed'), + ); } if (this.lastPlacedContainer) { - this.lastPlacedContainer.classList.remove(...this.getClassNamesFor('container:placed')); + this.lastPlacedContainer.classList.remove( + ...this.getClassNamesFor('container:placed'), + ); } this.lastPlacedSource = null; @@ -643,7 +709,9 @@ export default class Draggable { } const sensorEvent = getSensorEvent(event); - const source = this.source || closest(sensorEvent.originalEvent.target, this.options.draggable); + const source = + this.source || + closest(sensorEvent.originalEvent.target, this.options.draggable); const dragPressureEvent = new DragPressureEvent({ sensorEvent, diff --git a/src/Draggable/Emitter/Emitter.js b/src/Draggable/Emitter/Emitter.js index c6e2945..11ff3fc 100644 --- a/src/Draggable/Emitter/Emitter.js +++ b/src/Draggable/Emitter/Emitter.js @@ -68,7 +68,10 @@ export default class Emitter { if (caughtErrors.length) { /* eslint-disable no-console */ - console.error(`Draggable caught errors while triggering '${event.type}'`, caughtErrors); + console.error( + `Draggable caught errors while triggering '${event.type}'`, + caughtErrors, + ); /* eslint-enable no-console */ } diff --git a/src/Draggable/Emitter/tests/Emitter.test.js b/src/Draggable/Emitter/tests/Emitter.test.js index ac4a1e2..d1cc92e 100644 --- a/src/Draggable/Emitter/tests/Emitter.test.js +++ b/src/Draggable/Emitter/tests/Emitter.test.js @@ -78,7 +78,10 @@ describe('Emitter', () => { emitter.trigger(testEvent); expect(consoleErrorSpy).toHaveBeenCalled(); - expect(consoleErrorSpy).toHaveBeenCalledWith("Draggable caught errors while triggering 'event'", [error]); + expect(consoleErrorSpy).toHaveBeenCalledWith( + "Draggable caught errors while triggering 'event'", + [error], + ); expect(callbacks[0]).toHaveBeenCalled(); expect(callbacks[2]).toHaveBeenCalled(); diff --git a/src/Draggable/Plugins/Focusable/Focusable.js b/src/Draggable/Plugins/Focusable/Focusable.js index 8f3432a..8137548 100644 --- a/src/Draggable/Plugins/Focusable/Focusable.js +++ b/src/Draggable/Plugins/Focusable/Focusable.js @@ -43,14 +43,18 @@ export default class Focusable extends AbstractPlugin { * Attaches listeners to draggable */ attach() { - this.draggable.on('draggable:initialize', this[onInitialize]).on('draggable:destroy', this[onDestroy]); + this.draggable + .on('draggable:initialize', this[onInitialize]) + .on('draggable:destroy', this[onDestroy]); } /** * Detaches listeners from draggable */ detach() { - this.draggable.off('draggable:initialize', this[onInitialize]).off('draggable:destroy', this[onDestroy]); + this.draggable + .off('draggable:initialize', this[onInitialize]) + .off('draggable:destroy', this[onDestroy]); // Remove modified elements when detach this[onDestroy](); @@ -69,7 +73,10 @@ export default class Focusable extends AbstractPlugin { * @return {HTMLElement[]} */ getElements() { - return [...this.draggable.containers, ...this.draggable.getDraggableElements()]; + return [ + ...this.draggable.containers, + ...this.draggable.getDraggableElements(), + ]; } /** @@ -109,7 +116,9 @@ const elementsWithMissingTabIndex = []; * @private */ function decorateElement(element) { - const hasMissingTabIndex = Boolean(!element.getAttribute('tabindex') && element.tabIndex === -1); + const hasMissingTabIndex = Boolean( + !element.getAttribute('tabindex') && element.tabIndex === -1, + ); if (hasMissingTabIndex) { elementsWithMissingTabIndex.push(element); diff --git a/src/Draggable/Plugins/Focusable/tests/Focusable.test.js b/src/Draggable/Plugins/Focusable/tests/Focusable.test.js index 14d0f75..69c6fb2 100644 --- a/src/Draggable/Plugins/Focusable/tests/Focusable.test.js +++ b/src/Draggable/Plugins/Focusable/tests/Focusable.test.js @@ -36,7 +36,9 @@ describe('Focusable', () => { draggable: 'li', }); - const focusablePlugin = draggable.plugins.find((plugin) => plugin.constructor === Focusable); + const focusablePlugin = draggable.plugins.find( + (plugin) => plugin.constructor === Focusable, + ); expect(focusablePlugin).toBeInstanceOf(Focusable); }); @@ -46,7 +48,10 @@ describe('Focusable', () => { draggable: 'li', }); - const elements = [...draggable.containers, ...draggable.getDraggableElements()]; + const elements = [ + ...draggable.containers, + ...draggable.getDraggableElements(), + ]; waitForRequestAnimationFrame(); @@ -60,7 +65,10 @@ describe('Focusable', () => { draggable: 'li', }); - const elements = [...draggable.containers, ...draggable.getDraggableElements()]; + const elements = [ + ...draggable.containers, + ...draggable.getDraggableElements(), + ]; waitForRequestAnimationFrame(); @@ -103,6 +111,8 @@ describe('Focusable', () => { waitForRequestAnimationFrame(); - expect(elementWithTabIndexAttribute.tabIndex).toStrictEqual(originalTabIndex); + expect(elementWithTabIndexAttribute.tabIndex).toStrictEqual( + originalTabIndex, + ); }); }); diff --git a/src/Draggable/Plugins/Mirror/Mirror.js b/src/Draggable/Plugins/Mirror/Mirror.js index 1809f5e..2cb1f1b 100644 --- a/src/Draggable/Plugins/Mirror/Mirror.js +++ b/src/Draggable/Plugins/Mirror/Mirror.js @@ -163,7 +163,8 @@ export default class Mirror extends AbstractPlugin { return; } - const appendableContainer = this[getAppendableContainer](source) || sourceContainer; + const appendableContainer = + this[getAppendableContainer](source) || sourceContainer; this.mirror = source.cloneNode(true); const mirrorCreatedEvent = new MirrorCreatedEvent({ @@ -415,8 +416,14 @@ function computeMirrorDimensions({source, ...args}) { */ function calculateMirrorOffset({sensorEvent, sourceRect, options, ...args}) { return withPromise((resolve) => { - const top = options.cursorOffsetY === null ? sensorEvent.clientY - sourceRect.top : options.cursorOffsetY; - const left = options.cursorOffsetX === null ? sensorEvent.clientX - sourceRect.left : options.cursorOffsetX; + const top = + options.cursorOffsetY === null + ? sensorEvent.clientY - sourceRect.top + : options.cursorOffsetY; + const left = + options.cursorOffsetX === null + ? sensorEvent.clientX - sourceRect.left + : options.cursorOffsetX; const mirrorOffset = {top, left}; @@ -529,12 +536,16 @@ function positionMirror({withFrame = false, initial = false} = {}) { if (mirrorOffset) { const x = passedThreshX - ? Math.round((sensorEvent.clientX - mirrorOffset.left - scrollOffset.x) / (options.thresholdX || 1)) * - (options.thresholdX || 1) + ? Math.round( + (sensorEvent.clientX - mirrorOffset.left - scrollOffset.x) / + (options.thresholdX || 1), + ) * (options.thresholdX || 1) : Math.round(lastMovedX); const y = passedThreshY - ? Math.round((sensorEvent.clientY - mirrorOffset.top - scrollOffset.y) / (options.thresholdY || 1)) * - (options.thresholdY || 1) + ? Math.round( + (sensorEvent.clientY - mirrorOffset.top - scrollOffset.y) / + (options.thresholdY || 1), + ) * (options.thresholdY || 1) : Math.round(lastMovedY); if ((options.xAxis && options.yAxis) || initial) { diff --git a/src/Draggable/Plugins/Mirror/tests/Mirror.test.js b/src/Draggable/Plugins/Mirror/tests/Mirror.test.js index 9b7f35b..63a87f1 100644 --- a/src/Draggable/Plugins/Mirror/tests/Mirror.test.js +++ b/src/Draggable/Plugins/Mirror/tests/Mirror.test.js @@ -69,7 +69,10 @@ describe('Mirror', () => { let dragEvent; draggable.on('mirror:create', mirrorCreateHandler); - draggable.on('drag:start', (dragStartEvent) => (dragEvent = dragStartEvent)); + draggable.on( + 'drag:start', + (dragStartEvent) => (dragEvent = dragStartEvent), + ); clickMouse(draggableElement); waitForDragDelay(); @@ -128,7 +131,10 @@ describe('Mirror', () => { let dragEvent; draggable.on('mirror:created', mirrorCreatedHandler); - draggable.on('drag:start', (dragStartEvent) => (dragEvent = dragStartEvent)); + draggable.on( + 'drag:start', + (dragStartEvent) => (dragEvent = dragStartEvent), + ); clickMouse(draggableElement); waitForDragDelay(); @@ -158,7 +164,10 @@ describe('Mirror', () => { let dragEvent; draggable.on('mirror:attached', mirrorAttachedHandler); - draggable.on('drag:start', (dragStartEvent) => (dragEvent = dragStartEvent)); + draggable.on( + 'drag:start', + (dragStartEvent) => (dragEvent = dragStartEvent), + ); clickMouse(draggableElement); waitForDragDelay(); @@ -167,7 +176,9 @@ describe('Mirror', () => { const mirrorElement = document.querySelector('.draggable-mirror'); - expect(mirrorAttachedHandler).toHaveBeenCalledWithEvent(MirrorAttachedEvent); + expect(mirrorAttachedHandler).toHaveBeenCalledWithEvent( + MirrorAttachedEvent, + ); expect(mirrorAttachedHandler).toHaveBeenCalledWithEventProperties({ dragEvent, mirror: mirrorElement, diff --git a/src/Draggable/Plugins/Scrollable/Scrollable.js b/src/Draggable/Plugins/Scrollable/Scrollable.js index 8af279d..cb79530 100644 --- a/src/Draggable/Plugins/Scrollable/Scrollable.js +++ b/src/Draggable/Plugins/Scrollable/Scrollable.js @@ -119,7 +119,10 @@ export default class Scrollable extends AbstractPlugin { */ getScrollableElement(target) { if (this.hasDefinedScrollableElements()) { - return closest(target, this.options.scrollableElements) || document.documentElement; + return ( + closest(target, this.options.scrollableElements) || + document.documentElement + ); } else { return closestScrollableElement(target); } @@ -152,7 +155,9 @@ export default class Scrollable extends AbstractPlugin { */ [onDragMove](dragEvent) { this.findScrollableElementFrame = requestAnimationFrame(() => { - this.scrollableElement = this.getScrollableElement(dragEvent.sensorEvent.target); + this.scrollableElement = this.getScrollableElement( + dragEvent.sensorEvent.target, + ); }); if (!this.scrollableElement) { @@ -163,8 +168,16 @@ export default class Scrollable extends AbstractPlugin { const scrollOffset = {x: 0, y: 0}; if ('ontouchstart' in window) { - scrollOffset.y = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - scrollOffset.x = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; + scrollOffset.y = + window.pageYOffset || + document.documentElement.scrollTop || + document.body.scrollTop || + 0; + scrollOffset.x = + window.pageXOffset || + document.documentElement.scrollLeft || + document.body.scrollLeft || + 0; } this.currentMousePosition = { @@ -212,7 +225,11 @@ export default class Scrollable extends AbstractPlugin { const clientX = this.currentMousePosition.clientX; const clientY = this.currentMousePosition.clientY; - if (scrollableElement !== document.body && scrollableElement !== document.documentElement && !cutOff) { + if ( + scrollableElement !== document.body && + scrollableElement !== document.documentElement && + !cutOff + ) { const {offsetHeight, offsetWidth} = scrollableElement; if (rect.top + offsetHeight - clientY < sensitivity) { diff --git a/src/Draggable/Plugins/index.js b/src/Draggable/Plugins/index.js index a912332..51c3ff3 100644 --- a/src/Draggable/Plugins/index.js +++ b/src/Draggable/Plugins/index.js @@ -1,4 +1,13 @@ -export {default as Announcement, defaultOptions as defaultAnnouncementOptions} from './Announcement'; +export { + default as Announcement, + defaultOptions as defaultAnnouncementOptions, +} from './Announcement'; export {default as Focusable} from './Focusable'; -export {default as Mirror, defaultOptions as defaultMirrorOptions} from './Mirror'; -export {default as Scrollable, defaultOptions as defaultScrollableOptions} from './Scrollable'; +export { + default as Mirror, + defaultOptions as defaultMirrorOptions, +} from './Mirror'; +export { + default as Scrollable, + defaultOptions as defaultScrollableOptions, +} from './Scrollable'; diff --git a/src/Draggable/Sensors/DragSensor/DragSensor.js b/src/Draggable/Sensors/DragSensor/DragSensor.js index 7d0f12a..322fc62 100644 --- a/src/Draggable/Sensors/DragSensor/DragSensor.js +++ b/src/Draggable/Sensors/DragSensor/DragSensor.js @@ -1,7 +1,11 @@ import {closest} from 'shared/utils'; import Sensor from '../Sensor'; -import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent} from '../SensorEvent'; +import { + DragStartSensorEvent, + DragMoveSensorEvent, + DragStopSensorEvent, +} from '../SensorEvent'; const onMouseDown = Symbol('onMouseDown'); const onMouseUp = Symbol('onMouseUp'); @@ -195,7 +199,11 @@ export default class DragSensor extends Sensor { return; } - if (this.options.handle && target && !closest(target, this.options.handle)) { + if ( + this.options.handle && + target && + !closest(target, this.options.handle) + ) { return; } @@ -205,7 +213,10 @@ export default class DragSensor extends Sensor { return; } - const nativeDraggableElement = closest(event.target, (element) => element.draggable); + const nativeDraggableElement = closest( + event.target, + (element) => element.draggable, + ); if (nativeDraggableElement) { nativeDraggableElement.draggable = false; diff --git a/src/Draggable/Sensors/DragSensor/tests/DragSensor.test.js b/src/Draggable/Sensors/DragSensor/tests/DragSensor.test.js index 5a6cdd8..675523c 100644 --- a/src/Draggable/Sensors/DragSensor/tests/DragSensor.test.js +++ b/src/Draggable/Sensors/DragSensor/tests/DragSensor.test.js @@ -47,7 +47,9 @@ describe('DragSensor', () => { } describe('common', () => { - beforeEach(setup); + beforeEach(() => { + setup(); + }); afterEach(teardown); diff --git a/src/Draggable/Sensors/ForceTouchSensor/ForceTouchSensor.js b/src/Draggable/Sensors/ForceTouchSensor/ForceTouchSensor.js index aeb1234..84a8407 100644 --- a/src/Draggable/Sensors/ForceTouchSensor/ForceTouchSensor.js +++ b/src/Draggable/Sensors/ForceTouchSensor/ForceTouchSensor.js @@ -1,7 +1,12 @@ import {closest} from 'shared/utils'; import Sensor from '../Sensor'; -import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent, DragPressureSensorEvent} from '../SensorEvent'; +import { + DragStartSensorEvent, + DragMoveSensorEvent, + DragStopSensorEvent, + DragPressureSensorEvent, +} from '../SensorEvent'; const onMouseForceWillBegin = Symbol('onMouseForceWillBegin'); const onMouseForceDown = Symbol('onMouseForceDown'); @@ -47,10 +52,22 @@ export default class ForceTouchSensor extends Sensor { */ attach() { for (const container of this.containers) { - container.addEventListener('webkitmouseforcewillbegin', this[onMouseForceWillBegin], false); - container.addEventListener('webkitmouseforcedown', this[onMouseForceDown], false); + container.addEventListener( + 'webkitmouseforcewillbegin', + this[onMouseForceWillBegin], + false, + ); + container.addEventListener( + 'webkitmouseforcedown', + this[onMouseForceDown], + false, + ); container.addEventListener('mousedown', this[onMouseDown], true); - container.addEventListener('webkitmouseforcechanged', this[onMouseForceChange], false); + container.addEventListener( + 'webkitmouseforcechanged', + this[onMouseForceChange], + false, + ); } document.addEventListener('mousemove', this[onMouseMove]); @@ -62,10 +79,22 @@ export default class ForceTouchSensor extends Sensor { */ detach() { for (const container of this.containers) { - container.removeEventListener('webkitmouseforcewillbegin', this[onMouseForceWillBegin], false); - container.removeEventListener('webkitmouseforcedown', this[onMouseForceDown], false); + container.removeEventListener( + 'webkitmouseforcewillbegin', + this[onMouseForceWillBegin], + false, + ); + container.removeEventListener( + 'webkitmouseforcedown', + this[onMouseForceDown], + false, + ); container.removeEventListener('mousedown', this[onMouseDown], true); - container.removeEventListener('webkitmouseforcechanged', this[onMouseForceChange], false); + container.removeEventListener( + 'webkitmouseforcechanged', + this[onMouseForceChange], + false, + ); } document.removeEventListener('mousemove', this[onMouseMove]); @@ -95,7 +124,11 @@ export default class ForceTouchSensor extends Sensor { const target = document.elementFromPoint(event.clientX, event.clientY); const container = event.currentTarget; - if (this.options.handle && target && !closest(target, this.options.handle)) { + if ( + this.options.handle && + target && + !closest(target, this.options.handle) + ) { return; } diff --git a/src/Draggable/Sensors/MouseSensor/MouseSensor.js b/src/Draggable/Sensors/MouseSensor/MouseSensor.js index 21d8c17..f8e5d42 100644 --- a/src/Draggable/Sensors/MouseSensor/MouseSensor.js +++ b/src/Draggable/Sensors/MouseSensor/MouseSensor.js @@ -1,7 +1,11 @@ import {closest, distance as euclideanDistance} from 'shared/utils'; import Sensor from '../Sensor'; -import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent} from '../SensorEvent'; +import { + DragStartSensorEvent, + DragMoveSensorEvent, + DragStopSensorEvent, +} from '../SensorEvent'; const onContextMenuWhileDragging = Symbol('onContextMenuWhileDragging'); const onMouseDown = Symbol('onMouseDown'); @@ -47,7 +51,8 @@ export default class MouseSensor extends Sensor { */ this.pageY = null; - this[onContextMenuWhileDragging] = this[onContextMenuWhileDragging].bind(this); + this[onContextMenuWhileDragging] = + this[onContextMenuWhileDragging].bind(this); this[onMouseDown] = this[onMouseDown].bind(this); this[onMouseMove] = this[onMouseMove].bind(this); this[onMouseUp] = this[onMouseUp].bind(this); @@ -84,7 +89,11 @@ export default class MouseSensor extends Sensor { return; } - if (this.options.handle && event.target && !closest(event.target, this.options.handle)) { + if ( + this.options.handle && + event.target && + !closest(event.target, this.options.handle) + ) { return; } @@ -135,7 +144,11 @@ export default class MouseSensor extends Sensor { this.dragging = !dragStartEvent.canceled(); if (this.dragging) { - document.addEventListener('contextmenu', this[onContextMenuWhileDragging], true); + document.addEventListener( + 'contextmenu', + this[onContextMenuWhileDragging], + true, + ); document.addEventListener('mousemove', this[onMouseMove]); } } @@ -158,7 +171,8 @@ export default class MouseSensor extends Sensor { } const timeElapsed = Date.now() - this.onMouseDownAt; - const distanceTravelled = euclideanDistance(startEvent.pageX, startEvent.pageY, pageX, pageY) || 0; + const distanceTravelled = + euclideanDistance(startEvent.pageX, startEvent.pageY, pageX, pageY) || 0; clearTimeout(this.mouseDownTimeout); @@ -226,7 +240,11 @@ export default class MouseSensor extends Sensor { this.trigger(this.currentContainer, dragStopEvent); - document.removeEventListener('contextmenu', this[onContextMenuWhileDragging], true); + document.removeEventListener( + 'contextmenu', + this[onContextMenuWhileDragging], + true, + ); document.removeEventListener('mousemove', this[onMouseMove]); this.currentContainer = null; diff --git a/src/Draggable/Sensors/MouseSensor/tests/MouseSensor.test.js b/src/Draggable/Sensors/MouseSensor/tests/MouseSensor.test.js index 364e9ea..d917524 100644 --- a/src/Draggable/Sensors/MouseSensor/tests/MouseSensor.test.js +++ b/src/Draggable/Sensors/MouseSensor/tests/MouseSensor.test.js @@ -1,4 +1,12 @@ -import {createSandbox, triggerEvent, waitForDragDelay, DRAG_DELAY, clickMouse, moveMouse, releaseMouse} from 'helper'; +import { + createSandbox, + triggerEvent, + waitForDragDelay, + DRAG_DELAY, + clickMouse, + moveMouse, + releaseMouse, +} from 'helper'; import MouseSensor from '..'; @@ -47,7 +55,9 @@ describe('MouseSensor', () => { } describe('common', () => { - beforeEach(setup); + beforeEach(() => { + setup(); + }); afterEach(teardown); @@ -138,7 +148,11 @@ describe('MouseSensor', () => { releaseMouse(document.body); } - [dragFlowWithRightClick, dragFlowWithCtrlKey, dragFlowWithMetaKey].forEach((dragFlow) => { + [ + dragFlowWithRightClick, + dragFlowWithCtrlKey, + dragFlowWithMetaKey, + ].forEach((dragFlow) => { expect(dragFlow).not.toHaveTriggeredSensorEvent('drag:start'); }); }); @@ -165,7 +179,9 @@ describe('MouseSensor', () => { beforeEach(() => { setup({handle: '.handle'}); handleInDraggableElement = sandbox.querySelector('.draggable .handle'); - handleInNonDraggableElement = sandbox.querySelector('.non-draggable .handle'); + handleInNonDraggableElement = sandbox.querySelector( + '.non-draggable .handle', + ); }); afterEach(teardown); @@ -173,7 +189,10 @@ describe('MouseSensor', () => { it('does not prevent `dragstart` event when attempting to drag handle in non draggable element', () => { clickMouse(handleInNonDraggableElement); moveMouse(document, {pageX: 1, pageY: 1}); - const nativeDragEvent = triggerEvent(handleInNonDraggableElement, 'dragstart'); + const nativeDragEvent = triggerEvent( + handleInNonDraggableElement, + 'dragstart', + ); expect(nativeDragEvent).not.toHaveDefaultPrevented(); @@ -183,7 +202,10 @@ describe('MouseSensor', () => { it('prevent `dragstart` event when attempting to drag handle in draggable element', () => { clickMouse(handleInDraggableElement); moveMouse(document, {pageX: 1, pageY: 1}); - const nativeDragEvent = triggerEvent(handleInDraggableElement, 'dragstart'); + const nativeDragEvent = triggerEvent( + handleInDraggableElement, + 'dragstart', + ); expect(nativeDragEvent).toHaveDefaultPrevented(); diff --git a/src/Draggable/Sensors/Sensor/Sensor.js b/src/Draggable/Sensors/Sensor/Sensor.js index 0949157..43f5f9b 100644 --- a/src/Draggable/Sensors/Sensor/Sensor.js +++ b/src/Draggable/Sensors/Sensor/Sensor.js @@ -98,7 +98,9 @@ export default class Sensor { * @example draggable.removeContainer(document.body) */ removeContainer(...containers) { - this.containers = this.containers.filter((container) => !containers.includes(container)); + this.containers = this.containers.filter( + (container) => !containers.includes(container), + ); } /** diff --git a/src/Draggable/Sensors/TouchSensor/TouchSensor.js b/src/Draggable/Sensors/TouchSensor/TouchSensor.js index 7bdd080..4856388 100644 --- a/src/Draggable/Sensors/TouchSensor/TouchSensor.js +++ b/src/Draggable/Sensors/TouchSensor/TouchSensor.js @@ -1,7 +1,15 @@ -import {closest, distance as euclideanDistance, touchCoords} from 'shared/utils'; +import { + closest, + distance as euclideanDistance, + touchCoords, +} from 'shared/utils'; import Sensor from '../Sensor'; -import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent} from '../SensorEvent'; +import { + DragStartSensorEvent, + DragMoveSensorEvent, + DragStopSensorEvent, +} from '../SensorEvent'; const onTouchStart = Symbol('onTouchStart'); const onTouchEnd = Symbol('onTouchEnd'); @@ -113,7 +121,11 @@ export default class TouchSensor extends Sensor { return; } - if (this.options.handle && event.target && !closest(event.target, this.options.handle)) { + if ( + this.options.handle && + event.target && + !closest(event.target, this.options.handle) + ) { return; } @@ -143,7 +155,9 @@ export default class TouchSensor extends Sensor { } this.tapTimeout = window.setTimeout(() => { - this[onDistanceChange]({touches: [{pageX: this.pageX, pageY: this.pageY}]}); + this[onDistanceChange]({ + touches: [{pageX: this.pageX, pageY: this.pageY}], + }); }, delay.touch); } @@ -187,7 +201,12 @@ export default class TouchSensor extends Sensor { const start = touchCoords(startEvent); const current = touchCoords(event); const timeElapsed = Date.now() - this.onTouchStartAt; - const distanceTravelled = euclideanDistance(start.pageX, start.pageY, current.pageX, current.pageY); + const distanceTravelled = euclideanDistance( + start.pageX, + start.pageY, + current.pageX, + current.pageY, + ); Object.assign(this, current); @@ -212,7 +231,10 @@ export default class TouchSensor extends Sensor { return; } const {pageX, pageY} = touchCoords(event); - const target = document.elementFromPoint(pageX - window.scrollX, pageY - window.scrollY); + const target = document.elementFromPoint( + pageX - window.scrollX, + pageY - window.scrollY, + ); const dragMoveEvent = new DragMoveSensorEvent({ clientX: pageX, @@ -249,7 +271,10 @@ export default class TouchSensor extends Sensor { document.removeEventListener('touchmove', this[onTouchMove]); const {pageX, pageY} = touchCoords(event); - const target = document.elementFromPoint(pageX - window.scrollX, pageY - window.scrollY); + const target = document.elementFromPoint( + pageX - window.scrollX, + pageY - window.scrollY, + ); event.preventDefault(); diff --git a/src/Draggable/Sensors/TouchSensor/tests/TouchSensor.test.js b/src/Draggable/Sensors/TouchSensor/tests/TouchSensor.test.js index e7028e0..be29156 100644 --- a/src/Draggable/Sensors/TouchSensor/tests/TouchSensor.test.js +++ b/src/Draggable/Sensors/TouchSensor/tests/TouchSensor.test.js @@ -1,4 +1,12 @@ -import {createSandbox, triggerEvent, waitForDragDelay, DRAG_DELAY, touchStart, touchMove, touchRelease} from 'helper'; +import { + createSandbox, + triggerEvent, + waitForDragDelay, + DRAG_DELAY, + touchStart, + touchMove, + touchRelease, +} from 'helper'; import TouchSensor from '..'; @@ -38,7 +46,9 @@ describe('TouchSensor', () => { } describe('common', () => { - beforeEach(setup); + beforeEach(() => { + setup(); + }); afterEach(teardown); diff --git a/src/Draggable/tests/Draggable.test.js b/src/Draggable/tests/Draggable.test.js index 57cfa63..4769176 100644 --- a/src/Draggable/tests/Draggable.test.js +++ b/src/Draggable/tests/Draggable.test.js @@ -10,8 +10,16 @@ import { } from 'helper'; import Draggable, {defaultOptions} from '../Draggable'; -import {DragStartEvent, DragMoveEvent, DragStopEvent, DragStoppedEvent} from '../DragEvent'; -import {DraggableInitializedEvent, DraggableDestroyEvent} from '../DraggableEvent'; +import { + DragStartEvent, + DragMoveEvent, + DragStopEvent, + DragStoppedEvent, +} from '../DragEvent'; +import { + DraggableInitializedEvent, + DraggableDestroyEvent, +} from '../DraggableEvent'; import {Focusable, Mirror, Scrollable, Announcement} from '../Plugins'; import {MouseSensor, TouchSensor} from '../Sensors'; @@ -72,7 +80,9 @@ describe('Draggable', () => { it.skip('should set containers', () => { const newInstance = new Draggable(containers); - expect(newInstance.containers).toMatchObject(Array.prototype.slice.call(containers)); + expect(newInstance.containers).toMatchObject( + Array.prototype.slice.call(containers), + ); }); it.skip('should set single container if a list is not passed', () => { @@ -85,11 +95,15 @@ describe('Draggable', () => { it('should throw error if `containers` argument is wrong type', () => { expect(() => { return new Draggable({}); - }).toThrow('Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`'); + }).toThrow( + 'Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`', + ); expect(() => { return new Draggable('.li'); - }).toThrow('Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`'); + }).toThrow( + 'Draggable containers are expected to be of type `NodeList`, `HTMLElement[]` or `HTMLElement`', + ); }); it('should attach default plugins', () => { @@ -131,9 +145,9 @@ describe('Draggable', () => { expect(customPlugin.draggable).toBe(newInstance); - expect(customPlugin.attachFunction).toHaveBeenCalled(); + expect(customPlugin.attach).toHaveBeenCalled(); - expect(customPlugin.detachFunction).not.toHaveBeenCalled(); + expect(customPlugin.detach).not.toHaveBeenCalled(); }); it('should attach sensors', () => { @@ -204,17 +218,17 @@ describe('Draggable', () => { newInstance.destroy(); - expect(expectedPlugins[4].detachFunction).toHaveBeenCalled(); + expect(expectedPlugins[4].detach).toHaveBeenCalled(); - expect(expectedPlugins[4].detachFunction).toHaveBeenCalledTimes(1); + expect(expectedPlugins[4].detach).toHaveBeenCalledTimes(1); - expect(expectedPlugins[5].detachFunction).toHaveBeenCalled(); + expect(expectedPlugins[5].detach).toHaveBeenCalled(); - expect(expectedPlugins[5].detachFunction).toHaveBeenCalledTimes(1); + expect(expectedPlugins[5].detach).toHaveBeenCalledTimes(1); - expect(expectedPlugins[6].detachFunction).toHaveBeenCalled(); + expect(expectedPlugins[6].detach).toHaveBeenCalled(); - expect(expectedPlugins[6].detachFunction).toHaveBeenCalledTimes(1); + expect(expectedPlugins[6].detach).toHaveBeenCalledTimes(1); }); it('should remove all sensor event listeners', () => { @@ -248,7 +262,9 @@ describe('Draggable', () => { expect('my:event' in newInstance.emitter.callbacks).toBe(true); - expect(newInstance.emitter.callbacks['my:event']).toMatchObject([stubHandler]); + expect(newInstance.emitter.callbacks['my:event']).toMatchObject([ + stubHandler, + ]); }); it('should return draggable instance', () => { @@ -329,7 +345,9 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - const containerChildren = newInstance.getDraggableElementsForContainer(draggableElement.parentNode); + const containerChildren = newInstance.getDraggableElementsForContainer( + draggableElement.parentNode, + ); expect(containerChildren).toHaveLength(2); @@ -360,7 +378,10 @@ describe('Draggable', () => { newInstance.addContainer(dynamicContainer); - expect(newInstance.containers).toStrictEqual([...containers, dynamicContainer]); + expect(newInstance.containers).toStrictEqual([ + ...containers, + dynamicContainer, + ]); clickMouse(draggableElement); waitForDragDelay(); @@ -374,7 +395,9 @@ describe('Draggable', () => { describe('#removeContainer', () => { it('removes single container dynamically', () => { let dragOverContainerHandler = jest.fn(); - const allContainers = document.querySelectorAll('.Container, .DynamicContainer'); + const allContainers = document.querySelectorAll( + '.Container, .DynamicContainer', + ); const newInstance = new Draggable(allContainers, { draggable: 'li', }); @@ -415,7 +438,9 @@ describe('Draggable', () => { draggable: 'li', }); - expect(draggable.getDraggableElements()).toStrictEqual([...document.querySelectorAll('.Container li')]); + expect(draggable.getDraggableElements()).toStrictEqual([ + ...document.querySelectorAll('.Container li'), + ]); }); it('returns draggable elements after adding a container', () => { @@ -424,15 +449,21 @@ describe('Draggable', () => { draggable: 'li', }); - expect(draggable.getDraggableElements()).toStrictEqual([...document.querySelectorAll('.Container li')]); + expect(draggable.getDraggableElements()).toStrictEqual([ + ...document.querySelectorAll('.Container li'), + ]); draggable.addContainer(dynamicContainer); - expect(draggable.getDraggableElements()).toStrictEqual([...document.querySelectorAll('li')]); + expect(draggable.getDraggableElements()).toStrictEqual([ + ...document.querySelectorAll('li'), + ]); draggable.removeContainer(dynamicContainer); - expect(draggable.getDraggableElements()).toStrictEqual([...document.querySelectorAll('.Container li')]); + expect(draggable.getDraggableElements()).toStrictEqual([ + ...document.querySelectorAll('.Container li'), + ]); }); }); @@ -694,7 +725,9 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(newInstance.source.classList).toContain('draggable-source--is-dragging'); + expect(newInstance.source.classList).toContain( + 'draggable-source--is-dragging', + ); triggerEvent(draggableElement, 'mouseup', {button: 0}); }); @@ -839,7 +872,9 @@ describe('Draggable', () => { // Wait for default draggable.options.placedTimeout delay jest.advanceTimersByTime(800); - expect(containers[0].classList).not.toContain('draggable-container--placed'); + expect(containers[0].classList).not.toContain( + 'draggable-container--placed', + ); }); it('adds `container:dragging` classname to draggable container element on mousedown', () => { @@ -855,7 +890,9 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(containers[0].classList).toContain('draggable-container--is-dragging'); + expect(containers[0].classList).toContain( + 'draggable-container--is-dragging', + ); triggerEvent(draggableElement, 'mouseup', {button: 0}); }); @@ -873,11 +910,15 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(containers[0].classList).toContain('draggable-container--is-dragging'); + expect(containers[0].classList).toContain( + 'draggable-container--is-dragging', + ); triggerEvent(document.body, 'mouseup', {button: 0}); - expect(containers[0].classList).not.toContain('draggable-container--is-dragging'); + expect(containers[0].classList).not.toContain( + 'draggable-container--is-dragging', + ); }); it('removes `container:dragging` classname from draggable container element on dragEvent.cancel()', () => { @@ -895,7 +936,9 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(containers[0].classList).not.toContain('draggable-container--is-dragging'); + expect(containers[0].classList).not.toContain( + 'draggable-container--is-dragging', + ); triggerEvent(draggableElement, 'mouseup', {button: 0}); }); @@ -912,11 +955,19 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(draggableElement.classList.contains(newInstance.getClassNameFor('source:original'))).toBe(true); + expect( + draggableElement.classList.contains( + newInstance.getClassNameFor('source:original'), + ), + ).toBe(true); triggerEvent(document.body, 'mouseup', {button: 0}); - expect(draggableElement.classList.contains(newInstance.getClassNameFor('source:original'))).toBe(false); + expect( + draggableElement.classList.contains( + newInstance.getClassNameFor('source:original'), + ), + ).toBe(false); }); it('should have multiple classes for `source:original` on start', () => { @@ -935,7 +986,9 @@ describe('Draggable', () => { // Wait for delay waitForDragDelay(); - expect(newInstance.getClassNamesFor('source:original')).toStrictEqual(sourceOriginalClasses); + expect(newInstance.getClassNamesFor('source:original')).toStrictEqual( + sourceOriginalClasses, + ); triggerEvent(document.body, 'mouseup', {button: 0}); }); diff --git a/src/Droppable/Droppable.js b/src/Droppable/Droppable.js index 9cd17cf..713ddbf 100644 --- a/src/Droppable/Droppable.js +++ b/src/Droppable/Droppable.js @@ -2,7 +2,12 @@ import {closest} from 'shared/utils'; import Draggable from '../Draggable'; -import {DroppableStartEvent, DroppableDroppedEvent, DroppableReturnedEvent, DroppableStopEvent} from './DroppableEvent'; +import { + DroppableStartEvent, + DroppableDroppedEvent, + DroppableReturnedEvent, + DroppableStopEvent, +} from './DroppableEvent'; const onDragStart = Symbol('onDragStart'); const onDragMove = Symbol('onDragMove'); @@ -18,8 +23,12 @@ const getDropzones = Symbol('getDropzones'); * @return {String} */ function onDroppableDroppedDefaultAnnouncement({dragEvent, dropzone}) { - const sourceText = dragEvent.source.textContent.trim() || dragEvent.source.id || 'draggable element'; - const dropzoneText = dropzone.textContent.trim() || dropzone.id || 'droppable element'; + const sourceText = + dragEvent.source.textContent.trim() || + dragEvent.source.id || + 'draggable element'; + const dropzoneText = + dropzone.textContent.trim() || dropzone.id || 'droppable element'; return `Dropped ${sourceText} into ${dropzoneText}`; } @@ -30,8 +39,12 @@ function onDroppableDroppedDefaultAnnouncement({dragEvent, dropzone}) { * @return {String} */ function onDroppableReturnedDefaultAnnouncement({dragEvent, dropzone}) { - const sourceText = dragEvent.source.textContent.trim() || dragEvent.source.id || 'draggable element'; - const dropzoneText = dropzone.textContent.trim() || dropzone.id || 'droppable element'; + const sourceText = + dragEvent.source.textContent.trim() || + dragEvent.source.id || + 'draggable element'; + const dropzoneText = + dropzone.textContent.trim() || dropzone.id || 'droppable element'; return `Returned ${sourceText} from ${dropzoneText}`; } @@ -108,7 +121,9 @@ export default class Droppable extends Draggable { this[onDragMove] = this[onDragMove].bind(this); this[onDragStop] = this[onDragStop].bind(this); - this.on('drag:start', this[onDragStart]).on('drag:move', this[onDragMove]).on('drag:stop', this[onDragStop]); + this.on('drag:start', this[onDragStart]) + .on('drag:move', this[onDragMove]) + .on('drag:stop', this[onDragStop]); } /** @@ -117,7 +132,9 @@ export default class Droppable extends Draggable { destroy() { super.destroy(); - this.off('drag:start', this[onDragStart]).off('drag:move', this[onDragMove]).off('drag:stop', this[onDragStop]); + this.off('drag:start', this[onDragStart]) + .off('drag:move', this[onDragMove]) + .off('drag:stop', this[onDragStop]); } /** @@ -153,11 +170,17 @@ export default class Droppable extends Draggable { this.initialDropzone = dropzone; for (const dropzoneElement of this.dropzones) { - if (dropzoneElement.classList.contains(this.getClassNameFor('droppable:occupied'))) { + if ( + dropzoneElement.classList.contains( + this.getClassNameFor('droppable:occupied'), + ) + ) { continue; } - dropzoneElement.classList.add(...this.getClassNamesFor('droppable:active')); + dropzoneElement.classList.add( + ...this.getClassNamesFor('droppable:active'), + ); } } @@ -172,11 +195,16 @@ export default class Droppable extends Draggable { } const dropzone = this[closestDropzone](event.sensorEvent.target); - const overEmptyDropzone = dropzone && !dropzone.classList.contains(this.getClassNameFor('droppable:occupied')); + const overEmptyDropzone = + dropzone && + !dropzone.classList.contains(this.getClassNameFor('droppable:occupied')); if (overEmptyDropzone && this[dropInDropzone](event, dropzone)) { this.lastDropzone = dropzone; - } else if ((!dropzone || dropzone === this.initialDropzone) && this.lastDropzone) { + } else if ( + (!dropzone || dropzone === this.initialDropzone) && + this.lastDropzone + ) { this[returnToOriginalDropzone](event); this.lastDropzone = null; } @@ -258,7 +286,9 @@ export default class Droppable extends Draggable { } this.initialDropzone.appendChild(event.source); - this.lastDropzone.classList.remove(...this.getClassNamesFor('droppable:occupied')); + this.lastDropzone.classList.remove( + ...this.getClassNamesFor('droppable:occupied'), + ); } /** diff --git a/src/Droppable/tests/Droppable.test.js b/src/Droppable/tests/Droppable.test.js index 0f84c38..80aecc7 100644 --- a/src/Droppable/tests/Droppable.test.js +++ b/src/Droppable/tests/Droppable.test.js @@ -1,6 +1,18 @@ -import {createSandbox, clickMouse, moveMouse, releaseMouse, waitForDragDelay, DRAG_DELAY} from 'helper'; +import { + createSandbox, + clickMouse, + moveMouse, + releaseMouse, + waitForDragDelay, + DRAG_DELAY, +} from 'helper'; -import Droppable, {DroppableStartEvent, DroppableDroppedEvent, DroppableReturnedEvent, DroppableStopEvent} from '..'; +import Droppable, { + DroppableStartEvent, + DroppableDroppedEvent, + DroppableReturnedEvent, + DroppableStopEvent, +} from '..'; const sampleMarkup = `
@@ -60,7 +72,9 @@ describe('Droppable', () => { }); it('droppable:start event', () => { - droppable.on('drag:start', (dragEvent) => originalDragEvents.push(dragEvent)); + droppable.on('drag:start', (dragEvent) => + originalDragEvents.push(dragEvent), + ); droppable.on('droppable:start', eventHandler); move(); @@ -74,7 +88,9 @@ describe('Droppable', () => { }); it('droppable:dropped event', () => { - droppable.on('drag:move', (dragEvent) => originalDragEvents.push(dragEvent)); + droppable.on('drag:move', (dragEvent) => + originalDragEvents.push(dragEvent), + ); droppable.on('droppable:dropped', eventHandler); move(); @@ -88,7 +104,9 @@ describe('Droppable', () => { }); it('droppable:returned event', () => { - droppable.on('drag:move', (dragEvent) => originalDragEvents.push(dragEvent)); + droppable.on('drag:move', (dragEvent) => + originalDragEvents.push(dragEvent), + ); droppable.on('droppable:returned', eventHandler); move(() => { @@ -105,7 +123,9 @@ describe('Droppable', () => { }); it('droppable:stop event', () => { - droppable.on('drag:stop', (dragEvent) => originalDragEvents.push(dragEvent)); + droppable.on('drag:stop', (dragEvent) => + originalDragEvents.push(dragEvent), + ); droppable.on('droppable:stop', eventHandler); move(); diff --git a/src/Plugins/Collidable/Collidable.js b/src/Plugins/Collidable/Collidable.js index 87c4da7..85714ef 100644 --- a/src/Plugins/Collidable/Collidable.js +++ b/src/Plugins/Collidable/Collidable.js @@ -52,14 +52,18 @@ export default class Collidable extends AbstractPlugin { * Attaches plugins event listeners */ attach() { - this.draggable.on('drag:move', this[onDragMove]).on('drag:stop', this[onDragStop]); + this.draggable + .on('drag:move', this[onDragMove]) + .on('drag:stop', this[onDragStop]); } /** * Detaches plugins event listeners */ detach() { - this.draggable.off('drag:move', this[onDragMove]).off('drag:stop', this[onDragStop]); + this.draggable + .off('drag:move', this[onDragMove]) + .off('drag:stop', this[onDragStop]); } /** @@ -71,7 +75,10 @@ export default class Collidable extends AbstractPlugin { if (typeof collidables === 'string') { return Array.prototype.slice.call(document.querySelectorAll(collidables)); - } else if (collidables instanceof NodeList || collidables instanceof Array) { + } else if ( + collidables instanceof NodeList || + collidables instanceof Array + ) { return Array.prototype.slice.call(collidables); } else if (collidables instanceof HTMLElement) { return [collidables]; @@ -90,7 +97,9 @@ export default class Collidable extends AbstractPlugin { [onDragMove](event) { const target = event.sensorEvent.target; - this.currentAnimationFrame = requestAnimationFrame(this[onRequestAnimationFrame](target)); + this.currentAnimationFrame = requestAnimationFrame( + this[onRequestAnimationFrame](target), + ); if (this.currentlyCollidingElement) { event.cancel(); @@ -107,9 +116,12 @@ export default class Collidable extends AbstractPlugin { }); const enteringCollidable = Boolean( - this.currentlyCollidingElement && this.lastCollidingElement !== this.currentlyCollidingElement, + this.currentlyCollidingElement && + this.lastCollidingElement !== this.currentlyCollidingElement, + ); + const leavingCollidable = Boolean( + !this.currentlyCollidingElement && this.lastCollidingElement, ); - const leavingCollidable = Boolean(!this.currentlyCollidingElement && this.lastCollidingElement); if (enteringCollidable) { if (this.lastCollidingElement) { @@ -130,7 +142,8 @@ export default class Collidable extends AbstractPlugin { * @param {DragStopEvent} event - Drag stop event */ [onDragStop](event) { - const lastCollidingElement = this.currentlyCollidingElement || this.lastCollidingElement; + const lastCollidingElement = + this.currentlyCollidingElement || this.lastCollidingElement; const collidableOutEvent = new CollidableOutEvent({ dragEvent: event, collidingElement: lastCollidingElement, @@ -153,7 +166,9 @@ export default class Collidable extends AbstractPlugin { [onRequestAnimationFrame](target) { return () => { const collidables = this.getCollidables(); - this.currentlyCollidingElement = closest(target, (element) => collidables.includes(element)); + this.currentlyCollidingElement = closest(target, (element) => + collidables.includes(element), + ); }; } } diff --git a/src/Plugins/ResizeMirror/ResizeMirror.js b/src/Plugins/ResizeMirror/ResizeMirror.js index da83892..4ff6e81 100644 --- a/src/Plugins/ResizeMirror/ResizeMirror.js +++ b/src/Plugins/ResizeMirror/ResizeMirror.js @@ -134,7 +134,9 @@ export default class ResizeMirror extends AbstractPlugin { overContainer.appendChild(this.mirror); } - const overElement = over || this.draggable.getDraggableElementsForContainer(overContainer)[0]; + const overElement = + over || + this.draggable.getDraggableElementsForContainer(overContainer)[0]; if (!overElement) { return; @@ -143,7 +145,10 @@ export default class ResizeMirror extends AbstractPlugin { requestNextAnimationFrame(() => { const overRect = overElement.getBoundingClientRect(); - if (this.lastHeight === overRect.height && this.lastWidth === overRect.width) { + if ( + this.lastHeight === overRect.height && + this.lastWidth === overRect.width + ) { return; } diff --git a/src/Plugins/Snappable/Snappable.js b/src/Plugins/Snappable/Snappable.js index 19d6bc5..de142e0 100644 --- a/src/Plugins/Snappable/Snappable.js +++ b/src/Plugins/Snappable/Snappable.js @@ -128,12 +128,16 @@ export default class Snappable extends AbstractPlugin { this.mirror.style.display = 'none'; } - source.classList.remove(...this.draggable.getClassNamesFor('source:dragging')); + source.classList.remove( + ...this.draggable.getClassNamesFor('source:dragging'), + ); source.classList.add(...this.draggable.getClassNamesFor('source:placed')); // Need to cancel this in drag out setTimeout(() => { - source.classList.remove(...this.draggable.getClassNamesFor('source:placed')); + source.classList.remove( + ...this.draggable.getClassNamesFor('source:placed'), + ); }, this.draggable.options.placedTimeout); } diff --git a/src/Plugins/SortAnimation/SortAnimation.js b/src/Plugins/SortAnimation/SortAnimation.js index e861eb7..d260aa5 100644 --- a/src/Plugins/SortAnimation/SortAnimation.js +++ b/src/Plugins/SortAnimation/SortAnimation.js @@ -87,7 +87,8 @@ export default class SortAnimation extends AbstractPlugin { */ [onSortableSort]({dragEvent}) { const {sourceContainer} = dragEvent; - const elements = this.draggable.getDraggableElementsForContainer(sourceContainer); + const elements = + this.draggable.getDraggableElementsForContainer(sourceContainer); this.lastElements = Array.from(elements).map((el) => { return { domEl: el, @@ -168,5 +169,8 @@ function animate({from, to}, {duration, easingFunction}) { function resetElementOnTransitionEnd(event) { event.target.style.transition = ''; event.target.style.pointerEvents = ''; - event.target.removeEventListener('transitionend', resetElementOnTransitionEnd); + event.target.removeEventListener( + 'transitionend', + resetElementOnTransitionEnd, + ); } diff --git a/src/Plugins/SwapAnimation/SwapAnimation.js b/src/Plugins/SwapAnimation/SwapAnimation.ts similarity index 74% rename from src/Plugins/SwapAnimation/SwapAnimation.js rename to src/Plugins/SwapAnimation/SwapAnimation.ts index d890027..89ab99b 100644 --- a/src/Plugins/SwapAnimation/SwapAnimation.js +++ b/src/Plugins/SwapAnimation/SwapAnimation.ts @@ -1,6 +1,10 @@ import AbstractPlugin from 'shared/AbstractPlugin'; -const onSortableSorted = Symbol('onSortableSorted'); +interface Options { + duration: number; + easingFunction: string; + horizontal: boolean; +} /** * SwapAnimation default options @@ -10,7 +14,7 @@ const onSortableSorted = Symbol('onSortableSorted'); * @property {Boolean} defaultOptions.horizontal * @type {Object} */ -export const defaultOptions = { +export const defaultOptions: Options = { duration: 150, easingFunction: 'ease-in-out', horizontal: false, @@ -23,12 +27,14 @@ export const defaultOptions = { * @extends AbstractPlugin */ export default class SwapAnimation extends AbstractPlugin { + private options: Options; + private lastAnimationFrame: number | null; /** * SwapAnimation constructor. * @constructs SwapAnimation * @param {Draggable} draggable - Draggable instance */ - constructor(draggable) { + constructor(draggable: any) { super(draggable); /** @@ -50,21 +56,21 @@ export default class SwapAnimation extends AbstractPlugin { */ this.lastAnimationFrame = null; - this[onSortableSorted] = this[onSortableSorted].bind(this); + this.onSortableSorted = this.onSortableSorted.bind(this); } /** * Attaches plugins event listeners */ attach() { - this.draggable.on('sortable:sorted', this[onSortableSorted]); + this.draggable.on('sortable:sorted', this.onSortableSorted); } /** * Detaches plugins event listeners */ detach() { - this.draggable.off('sortable:sorted', this[onSortableSorted]); + this.draggable.off('sortable:sorted', this.onSortableSorted); } /** @@ -80,10 +86,12 @@ export default class SwapAnimation extends AbstractPlugin { * @param {SortableSortedEvent} sortableEvent * @private */ - [onSortableSorted]({oldIndex, newIndex, dragEvent}) { + onSortableSorted({oldIndex, newIndex, dragEvent}: any) { const {source, over} = dragEvent; - cancelAnimationFrame(this.lastAnimationFrame); + if (this.lastAnimationFrame) { + cancelAnimationFrame(this.lastAnimationFrame); + } // Can be done in a separate frame this.lastAnimationFrame = requestAnimationFrame(() => { @@ -106,7 +114,11 @@ export default class SwapAnimation extends AbstractPlugin { * @param {String} options.horizontal * @private */ -function animate(from, to, {duration, easingFunction, horizontal}) { +function animate( + from: HTMLElement, + to: HTMLElement, + {duration, easingFunction, horizontal}: any, +) { for (const element of [from, to]) { element.style.pointerEvents = 'none'; } @@ -135,8 +147,19 @@ function animate(from, to, {duration, easingFunction, horizontal}) { * @param {Event} event * @private */ -function resetElementOnTransitionEnd(event) { +function resetElementOnTransitionEnd(event: Event) { + if (event.target == null || !isHTMLElement(event.target)) { + return; + } + event.target.style.transition = ''; event.target.style.pointerEvents = ''; - event.target.removeEventListener('transitionend', resetElementOnTransitionEnd); + event.target.removeEventListener( + 'transitionend', + resetElementOnTransitionEnd, + ); +} + +function isHTMLElement(eventTarget: EventTarget): eventTarget is HTMLElement { + return Boolean('style' in eventTarget); } diff --git a/src/Plugins/index.js b/src/Plugins/index.js index 30da0fb..593a08a 100644 --- a/src/Plugins/index.js +++ b/src/Plugins/index.js @@ -1,5 +1,14 @@ export {default as Collidable} from './Collidable'; -export {default as ResizeMirror, defaultOptions as defaultResizeMirrorOptions} from './ResizeMirror'; +export { + default as ResizeMirror, + defaultOptions as defaultResizeMirrorOptions, +} from './ResizeMirror'; export {default as Snappable} from './Snappable'; -export {default as SwapAnimation, defaultOptions as defaultSwapAnimationOptions} from './SwapAnimation'; -export {default as SortAnimation, defaultOptions as defaultSortAnimationOptions} from './SortAnimation'; +export { + default as SwapAnimation, + defaultOptions as defaultSwapAnimationOptions, +} from './SwapAnimation'; +export { + default as SortAnimation, + defaultOptions as defaultSortAnimationOptions, +} from './SortAnimation'; diff --git a/src/Sortable/Sortable.js b/src/Sortable/Sortable.js index c413e9c..691515a 100644 --- a/src/Sortable/Sortable.js +++ b/src/Sortable/Sortable.js @@ -1,6 +1,11 @@ import Draggable from '../Draggable'; -import {SortableStartEvent, SortableSortEvent, SortableSortedEvent, SortableStopEvent} from './SortableEvent'; +import { + SortableStartEvent, + SortableSortEvent, + SortableSortedEvent, + SortableStopEvent, +} from './SortableEvent'; const onDragStart = Symbol('onDragStart'); const onDragOverContainer = Symbol('onDragOverContainer'); @@ -14,11 +19,19 @@ const onDragStop = Symbol('onDragStop'); * @return {String} */ function onSortableSortedDefaultAnnouncement({dragEvent}) { - const sourceText = dragEvent.source.textContent.trim() || dragEvent.source.id || 'sortable element'; + const sourceText = + dragEvent.source.textContent.trim() || + dragEvent.source.id || + 'sortable element'; if (dragEvent.over) { - const overText = dragEvent.over.textContent.trim() || dragEvent.over.id || 'sortable element'; - const isFollowing = dragEvent.source.compareDocumentPosition(dragEvent.over) & Node.DOCUMENT_POSITION_FOLLOWING; + const overText = + dragEvent.over.textContent.trim() || + dragEvent.over.id || + 'sortable element'; + const isFollowing = + dragEvent.source.compareDocumentPosition(dragEvent.over) & + Node.DOCUMENT_POSITION_FOLLOWING; if (isFollowing) { return `Placed ${sourceText} after ${overText}`; @@ -106,7 +119,9 @@ export default class Sortable extends Draggable { * @return {Number} */ index(element) { - return this.getSortableElementsForContainer(element.parentNode).indexOf(element); + return this.getSortableElementsForContainer(element.parentNode).indexOf( + element, + ); } /** @@ -116,11 +131,15 @@ export default class Sortable extends Draggable { * @return {HTMLElement[]} */ getSortableElementsForContainer(container) { - const allSortableElements = container.querySelectorAll(this.options.draggable); + const allSortableElements = container.querySelectorAll( + this.options.draggable, + ); return [...allSortableElements].filter((childElement) => { return ( - childElement !== this.originalSource && childElement !== this.mirror && childElement.parentNode === container + childElement !== this.originalSource && + childElement !== this.mirror && + childElement.parentNode === container ); }); } diff --git a/src/Sortable/tests/Sortable.test.js b/src/Sortable/tests/Sortable.test.js index 0d7cf79..33643b9 100644 --- a/src/Sortable/tests/Sortable.test.js +++ b/src/Sortable/tests/Sortable.test.js @@ -1,4 +1,11 @@ -import {createSandbox, clickMouse, moveMouse, releaseMouse, waitForDragDelay, DRAG_DELAY} from 'helper'; +import { + createSandbox, + clickMouse, + moveMouse, + releaseMouse, + waitForDragDelay, + DRAG_DELAY, +} from 'helper'; import Sortable from '..'; @@ -119,14 +126,22 @@ describe('Sortable', () => { }); it('sorts elements as you drag within a single container', () => { - draggableElements = sortable.getDraggableElementsForContainer(containers[0]); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = sortable.getDraggableElementsForContainer( + containers[0], + ); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); clickMouse(firstItem); waitForDragDelay(); moveMouse(secondItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ secondItem, // original firstItem @@ -137,7 +152,8 @@ describe('Sortable', () => { moveMouse(thirdItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ secondItem, thirdItem, @@ -148,7 +164,8 @@ describe('Sortable', () => { moveMouse(forthItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ secondItem, thirdItem, @@ -159,25 +176,45 @@ describe('Sortable', () => { releaseMouse(sortable.source); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([secondItem, thirdItem, forthItem, firstItem]); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + secondItem, + thirdItem, + forthItem, + firstItem, + ]); }); it('sorts elements as you drag between multiple containers', () => { - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); - expect(draggableElements).toHaveOrder([fifthItem, sixthItem, seventhItem, eighthItem]); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); + expect(draggableElements).toHaveOrder([ + fifthItem, + sixthItem, + seventhItem, + eighthItem, + ]); clickMouse(firstItem); waitForDragDelay(); moveMouse(fifthItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([secondItem, thirdItem, forthItem]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([ // original firstItem sortable.source, @@ -189,10 +226,12 @@ describe('Sortable', () => { moveMouse(eighthItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([secondItem, thirdItem, forthItem]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([ fifthItem, sixthItem, @@ -204,11 +243,19 @@ describe('Sortable', () => { releaseMouse(sortable.source); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([secondItem, thirdItem, forthItem]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); - expect(draggableElements).toHaveOrder([fifthItem, sixthItem, seventhItem, eighthItem, firstItem]); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); + expect(draggableElements).toHaveOrder([ + fifthItem, + sixthItem, + seventhItem, + eighthItem, + firstItem, + ]); }); it('prevents sorting when sortable:sort event gets canceled', () => { @@ -220,13 +267,25 @@ describe('Sortable', () => { waitForDragDelay(); moveMouse(secondItem); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([sortable.source, secondItem, thirdItem, forthItem]); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + sortable.source, + secondItem, + thirdItem, + forthItem, + ]); releaseMouse(sortable.source); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); }); it('sorts elements into empty container', () => { @@ -237,7 +296,8 @@ describe('Sortable', () => { releaseMouse(sortable.source); }); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ fifthItem, sixthItem, @@ -249,14 +309,16 @@ describe('Sortable', () => { forthItem, ]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([]); clickMouse(firstItem); waitForDragDelay(); moveMouse(secondContainer); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ fifthItem, sixthItem, @@ -267,12 +329,14 @@ describe('Sortable', () => { forthItem, ]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([sortable.source]); releaseMouse(sortable.source); - draggableElements = sortable.getDraggableElementsForContainer(firstContainer); + draggableElements = + sortable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ fifthItem, sixthItem, @@ -283,7 +347,8 @@ describe('Sortable', () => { forthItem, ]); - draggableElements = sortable.getDraggableElementsForContainer(secondContainer); + draggableElements = + sortable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([firstItem]); }); }); diff --git a/src/Swappable/Swappable.js b/src/Swappable/Swappable.js index 4da8a4e..db97783 100644 --- a/src/Swappable/Swappable.js +++ b/src/Swappable/Swappable.js @@ -1,6 +1,11 @@ import Draggable from '../Draggable'; -import {SwappableStartEvent, SwappableSwapEvent, SwappableSwappedEvent, SwappableStopEvent} from './SwappableEvent'; +import { + SwappableStartEvent, + SwappableSwapEvent, + SwappableSwappedEvent, + SwappableStopEvent, +} from './SwappableEvent'; const onDragStart = Symbol('onDragStart'); const onDragOver = Symbol('onDragOver'); @@ -12,8 +17,14 @@ const onDragStop = Symbol('onDragStop'); * @return {String} */ function onSwappableSwappedDefaultAnnouncement({dragEvent, swappedElement}) { - const sourceText = dragEvent.source.textContent.trim() || dragEvent.source.id || 'swappable element'; - const overText = swappedElement.textContent.trim() || swappedElement.id || 'swappable element'; + const sourceText = + dragEvent.source.textContent.trim() || + dragEvent.source.id || + 'swappable element'; + const overText = + swappedElement.textContent.trim() || + swappedElement.id || + 'swappable element'; return `Swapped ${sourceText} with ${overText}`; } @@ -60,7 +71,9 @@ export default class Swappable extends Draggable { this[onDragOver] = this[onDragOver].bind(this); this[onDragStop] = this[onDragStop].bind(this); - this.on('drag:start', this[onDragStart]).on('drag:over', this[onDragOver]).on('drag:stop', this[onDragStop]); + this.on('drag:start', this[onDragStart]) + .on('drag:over', this[onDragOver]) + .on('drag:stop', this[onDragStop]); } /** @@ -69,7 +82,9 @@ export default class Swappable extends Draggable { destroy() { super.destroy(); - this.off('drag:start', this._onDragStart).off('drag:over', this._onDragOver).off('drag:stop', this._onDragStop); + this.off('drag:start', this._onDragStart) + .off('drag:over', this._onDragOver) + .off('drag:stop', this._onDragStop); } /** @@ -95,7 +110,11 @@ export default class Swappable extends Draggable { * @param {DragOverEvent} event - Drag over event */ [onDragOver](event) { - if (event.over === event.originalSource || event.over === event.source || event.canceled()) { + if ( + event.over === event.originalSource || + event.over === event.source || + event.canceled() + ) { return; } diff --git a/src/Swappable/tests/Swappable.test.js b/src/Swappable/tests/Swappable.test.js index 082da89..1447c0b 100644 --- a/src/Swappable/tests/Swappable.test.js +++ b/src/Swappable/tests/Swappable.test.js @@ -1,4 +1,11 @@ -import {createSandbox, clickMouse, moveMouse, releaseMouse, waitForDragDelay, DRAG_DELAY} from 'helper'; +import { + createSandbox, + clickMouse, + moveMouse, + releaseMouse, + waitForDragDelay, + DRAG_DELAY, +} from 'helper'; import Swappable from '..'; @@ -119,14 +126,22 @@ describe('Swappable', () => { }); it('swaps elements as you drag within a single container', () => { - draggableElements = swappable.getDraggableElementsForContainer(containers[0]); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = swappable.getDraggableElementsForContainer( + containers[0], + ); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); clickMouse(firstItem); waitForDragDelay(); moveMouse(secondItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ secondItem, // original firstItem @@ -137,7 +152,8 @@ describe('Swappable', () => { moveMouse(thirdItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ thirdItem, secondItem, @@ -148,7 +164,8 @@ describe('Swappable', () => { moveMouse(forthItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); expect(draggableElements).toHaveOrder([ forthItem, secondItem, @@ -159,25 +176,50 @@ describe('Swappable', () => { releaseMouse(swappable.source); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([forthItem, secondItem, thirdItem, firstItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + forthItem, + secondItem, + thirdItem, + firstItem, + ]); }); it('sorts elements as you drag between multiple containers', () => { - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); - draggableElements = swappable.getDraggableElementsForContainer(secondContainer); - expect(draggableElements).toHaveOrder([fifthItem, sixthItem, seventhItem, eighthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(secondContainer); + expect(draggableElements).toHaveOrder([ + fifthItem, + sixthItem, + seventhItem, + eighthItem, + ]); clickMouse(firstItem); waitForDragDelay(); moveMouse(fifthItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([fifthItem, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + fifthItem, + secondItem, + thirdItem, + forthItem, + ]); - draggableElements = swappable.getDraggableElementsForContainer(secondContainer); + draggableElements = + swappable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([ // original firstItem swappable.source, @@ -188,10 +230,17 @@ describe('Swappable', () => { moveMouse(eighthItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([eighthItem, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + eighthItem, + secondItem, + thirdItem, + forthItem, + ]); - draggableElements = swappable.getDraggableElementsForContainer(secondContainer); + draggableElements = + swappable.getDraggableElementsForContainer(secondContainer); expect(draggableElements).toHaveOrder([ fifthItem, sixthItem, @@ -202,11 +251,23 @@ describe('Swappable', () => { releaseMouse(swappable.source); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([eighthItem, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + eighthItem, + secondItem, + thirdItem, + forthItem, + ]); - draggableElements = swappable.getDraggableElementsForContainer(secondContainer); - expect(draggableElements).toHaveOrder([fifthItem, sixthItem, seventhItem, firstItem]); + draggableElements = + swappable.getDraggableElementsForContainer(secondContainer); + expect(draggableElements).toHaveOrder([ + fifthItem, + sixthItem, + seventhItem, + firstItem, + ]); }); it('prevents sorting when sortable:sort event gets canceled', () => { @@ -218,12 +279,24 @@ describe('Swappable', () => { waitForDragDelay(); moveMouse(secondItem); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([swappable.source, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + swappable.source, + secondItem, + thirdItem, + forthItem, + ]); releaseMouse(swappable.source); - draggableElements = swappable.getDraggableElementsForContainer(firstContainer); - expect(draggableElements).toHaveOrder([firstItem, secondItem, thirdItem, forthItem]); + draggableElements = + swappable.getDraggableElementsForContainer(firstContainer); + expect(draggableElements).toHaveOrder([ + firstItem, + secondItem, + thirdItem, + forthItem, + ]); }); }); diff --git a/src/shared/AbstractEvent/AbstractEvent.js b/src/shared/AbstractEvent/AbstractEvent.ts similarity index 69% rename from src/shared/AbstractEvent/AbstractEvent.js rename to src/shared/AbstractEvent/AbstractEvent.ts index 96b0373..a0941ca 100644 --- a/src/shared/AbstractEvent/AbstractEvent.js +++ b/src/shared/AbstractEvent/AbstractEvent.ts @@ -1,5 +1,3 @@ -const canceled = Symbol('canceled'); - /** * All events fired by draggable inherit this class. You can call `cancel()` to * cancel a specific event or you can check if an event has been canceled by @@ -8,7 +6,7 @@ const canceled = Symbol('canceled'); * @class AbstractEvent * @module AbstractEvent */ -export default class AbstractEvent { +export class AbstractEvent { /** * Event type * @static @@ -17,7 +15,6 @@ export default class AbstractEvent { * @type {String} */ static type = 'event'; - /** * Event cancelable * @static @@ -27,15 +24,19 @@ export default class AbstractEvent { */ static cancelable = false; + /** + * Private instance variable to track canceled state + * @private + * @type {Boolean} + */ + private _canceled = false; + /** * AbstractEvent constructor. * @constructs AbstractEvent - * @param {object} data - Event data + * @param {T} data - Event data */ - constructor(data) { - this[canceled] = false; - this.data = data; - } + constructor(public data: T) {} /** * Read-only type @@ -43,7 +44,7 @@ export default class AbstractEvent { * @return {String} */ get type() { - return this.constructor.type; + return (this.constructor as typeof AbstractEvent).type; } /** @@ -52,7 +53,7 @@ export default class AbstractEvent { * @return {Boolean} */ get cancelable() { - return this.constructor.cancelable; + return (this.constructor as typeof AbstractEvent).cancelable; } /** @@ -60,7 +61,7 @@ export default class AbstractEvent { * @abstract */ cancel() { - this[canceled] = true; + this._canceled = true; } /** @@ -69,17 +70,17 @@ export default class AbstractEvent { * @return {Boolean} */ canceled() { - return Boolean(this[canceled]); + return this._canceled; } /** * Returns new event instance with existing event data. * This method allows for overriding of event data. - * @param {Object} data + * @param {T} data * @return {AbstractEvent} */ - clone(data) { - return new this.constructor({ + clone(data: T) { + return new (this.constructor as typeof AbstractEvent)({ ...this.data, ...data, }); diff --git a/src/shared/AbstractEvent/index.js b/src/shared/AbstractEvent/index.js deleted file mode 100644 index 6145770..0000000 --- a/src/shared/AbstractEvent/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import AbstractEvent from './AbstractEvent'; - -export default AbstractEvent; diff --git a/src/shared/AbstractEvent/index.ts b/src/shared/AbstractEvent/index.ts new file mode 100644 index 0000000..5b07b69 --- /dev/null +++ b/src/shared/AbstractEvent/index.ts @@ -0,0 +1 @@ +export {AbstractEvent as default} from './AbstractEvent'; diff --git a/src/shared/AbstractEvent/tests/AbstractEvent.test.js b/src/shared/AbstractEvent/tests/AbstractEvent.test.ts similarity index 75% rename from src/shared/AbstractEvent/tests/AbstractEvent.test.js rename to src/shared/AbstractEvent/tests/AbstractEvent.test.ts index ecd1589..5ed191e 100644 --- a/src/shared/AbstractEvent/tests/AbstractEvent.test.js +++ b/src/shared/AbstractEvent/tests/AbstractEvent.test.ts @@ -1,26 +1,26 @@ -import AbstractEvent from '../AbstractEvent'; +import {AbstractEvent} from '../AbstractEvent'; describe('AbstractEvent', () => { it('should be of type AbstractEvent', () => { - const event = new AbstractEvent(); + const event = new AbstractEvent({}); expect(event).toBeInstanceOf(AbstractEvent); }); it('should initialize with correct type', () => { - const event = new AbstractEvent(); + const event = new AbstractEvent({}); expect(event.type).toBe('event'); }); it('should initialize in uncancelable state', () => { - const event = new AbstractEvent(); + const event = new AbstractEvent({}); expect(event.cancelable).toBe(false); }); it('should initialize in uncancelled state', () => { - const event = new AbstractEvent(); + const event = new AbstractEvent({}); expect(event.canceled()).toBe(false); }); @@ -36,7 +36,7 @@ describe('AbstractEvent', () => { }); it('should cancel event', () => { - const event = new AbstractEvent(); + const event = new AbstractEvent({}); expect(event.canceled()).toBe(false); diff --git a/src/shared/AbstractPlugin/AbstractPlugin.js b/src/shared/AbstractPlugin/AbstractPlugin.ts similarity index 71% rename from src/shared/AbstractPlugin/AbstractPlugin.js rename to src/shared/AbstractPlugin/AbstractPlugin.ts index d689bb2..795bb61 100644 --- a/src/shared/AbstractPlugin/AbstractPlugin.js +++ b/src/shared/AbstractPlugin/AbstractPlugin.ts @@ -4,20 +4,13 @@ * @class AbstractPlugin * @module AbstractPlugin */ -export default class AbstractPlugin { +export abstract class AbstractPlugin { /** * AbstractPlugin constructor. * @constructs AbstractPlugin * @param {Draggable} draggable - Draggable instance */ - constructor(draggable) { - /** - * Draggable instance - * @property draggable - * @type {Draggable} - */ - this.draggable = draggable; - } + constructor(protected draggable: any) {} /** * Override to add listeners diff --git a/src/shared/AbstractPlugin/index.js b/src/shared/AbstractPlugin/index.js deleted file mode 100644 index f4acb63..0000000 --- a/src/shared/AbstractPlugin/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import AbstractPlugin from './AbstractPlugin'; - -export default AbstractPlugin; diff --git a/src/shared/AbstractPlugin/index.ts b/src/shared/AbstractPlugin/index.ts new file mode 100644 index 0000000..f501639 --- /dev/null +++ b/src/shared/AbstractPlugin/index.ts @@ -0,0 +1 @@ +export {AbstractPlugin as default} from './AbstractPlugin'; diff --git a/src/shared/utils/closest/closest.js b/src/shared/utils/closest/closest.js deleted file mode 100644 index b7273b0..0000000 --- a/src/shared/utils/closest/closest.js +++ /dev/null @@ -1,60 +0,0 @@ -const matchFunction = - Element.prototype.matches || - Element.prototype.webkitMatchesSelector || - Element.prototype.mozMatchesSelector || - Element.prototype.msMatchesSelector; - -/** - * Get the closest parent element of a given element that matches the given - * selector string or matching function - * - * @param {Element} element The child element to find a parent of - * @param {String|Function} selector The string or function to use to match - * the parent element - * @return {Element|null} - */ -export default function closest(element, value) { - if (!element) { - return null; - } - - const selector = value; - const callback = value; - const nodeList = value; - const singleElement = value; - - const isSelector = Boolean(typeof value === 'string'); - const isFunction = Boolean(typeof value === 'function'); - const isNodeList = Boolean(value instanceof NodeList || value instanceof Array); - const isElement = Boolean(value instanceof HTMLElement); - - function conditionFn(currentElement) { - if (!currentElement) { - return currentElement; - } else if (isSelector) { - return matchFunction.call(currentElement, selector); - } else if (isNodeList) { - return [...nodeList].includes(currentElement); - } else if (isElement) { - return singleElement === currentElement; - } else if (isFunction) { - return callback(currentElement); - } else { - return null; - } - } - - let current = element; - - do { - current = current.correspondingUseElement || current.correspondingElement || current; - - if (conditionFn(current)) { - return current; - } - - current = current.parentNode; - } while (current && current !== document.body && current !== document); - - return null; -} diff --git a/src/shared/utils/closest/closest.ts b/src/shared/utils/closest/closest.ts new file mode 100644 index 0000000..8954cb4 --- /dev/null +++ b/src/shared/utils/closest/closest.ts @@ -0,0 +1,77 @@ +declare global { + export interface Node { + correspondingUseElement: SVGUseElement; + correspondingElement: SVGElement; + } +} + +type CallbackFunction = (element: Node) => boolean; +type Value = string | CallbackFunction | NodeList | Node | Node[]; + +/** + * Get the closest parent element node of a given node that matches the given + * selector string or matching function + * + * @param {Node} node The child element to find a parent of + * @param {String|Function} selector The string or function to use to match + * the parent node + * @return {Node|null} + */ +export default function closest(node?: Node, value?: Value) { + if (node == null) { + return null; + } + + function conditionFn(currentNode: Node | null): boolean { + if (currentNode == null || value == null) { + return false; + } else if (isSelector(value)) { + return Element.prototype.matches.call(currentNode, value); + } else if (isNodeList(value)) { + return [...value].includes(currentNode); + } else if (isElement(value)) { + return value === currentNode; + } else if (isFunction(value)) { + return value(currentNode); + } else { + return false; + } + } + + let current: Node | null = node; + + do { + current = + current.correspondingUseElement || + current.correspondingElement || + current; + + if (conditionFn(current)) { + return current; + } + + current = current?.parentNode || null; + } while ( + current != null && + current !== document.body && + current !== document + ); + + return null; +} + +function isSelector(value: Value): value is string { + return Boolean(typeof value === 'string'); +} + +function isNodeList(value: Value): value is NodeList | Node[] { + return Boolean(value instanceof NodeList || value instanceof Array); +} + +function isElement(value: Value): value is Node { + return Boolean(value instanceof Node); +} + +function isFunction(value: Value): value is (element: Node) => boolean { + return Boolean(typeof value === 'function'); +} diff --git a/src/shared/utils/closest/index.js b/src/shared/utils/closest/index.ts similarity index 100% rename from src/shared/utils/closest/index.js rename to src/shared/utils/closest/index.ts diff --git a/src/shared/utils/closest/tests/closest.test.js b/src/shared/utils/closest/tests/closest.test.ts similarity index 70% rename from src/shared/utils/closest/tests/closest.test.js rename to src/shared/utils/closest/tests/closest.test.ts index 7b7dde1..f39b3c6 100644 --- a/src/shared/utils/closest/tests/closest.test.js +++ b/src/shared/utils/closest/tests/closest.test.ts @@ -13,7 +13,7 @@ const sampleMarkup = ` `; describe('utils', () => { - let sandbox; + let sandbox: HTMLDivElement; beforeEach(() => { sandbox = createSandbox(sampleMarkup); @@ -28,13 +28,13 @@ describe('utils', () => { }); it('should return null when string selector does not match', () => { - const element = sandbox.querySelector('.leaf'); + const element = sandbox.querySelector('.leaf')!; expect(closest(element, 'will-not-match')).toBeNull(); }); it('should return null when function selector does not match', () => { - const element = sandbox.querySelector('.leaf'); + const element = sandbox.querySelector('.leaf')!; function selector() { return false; } @@ -43,24 +43,33 @@ describe('utils', () => { }); it('should return null when selector targets child element', () => { - const element = sandbox.querySelector('.twig'); + const element = sandbox.querySelector('.twig')!; expect(closest(element, '.leaf')).toBeNull(); }); it('should match element via callback', () => { - const element = sandbox.querySelector('.leaf'); + const element = sandbox.querySelector('.leaf')!; - function callback(currentElement) { - return currentElement.classList.contains('leaf'); + function callback(currentElement: Node) { + return (currentElement as HTMLElement).classList.contains('leaf'); } expect(closest(element, callback)).toBe(element); }); - ['.twig', 'ul', '.branch', 'section', '.tree', 'div', 'body', 'document'].forEach((expectedMatchingSelector) => { + [ + '.twig', + 'ul', + '.branch', + 'section', + '.tree', + 'div', + 'body', + 'document', + ].forEach((expectedMatchingSelector) => { it(`should return matched element when selector targets parent element matching selector ${expectedMatchingSelector}`, () => { - const element = sandbox.querySelector('.leaf'); + const element = sandbox.querySelector('.leaf')!; const expected = sandbox.querySelector(expectedMatchingSelector); expect(closest(element, expectedMatchingSelector)).toBe(expected); diff --git a/src/shared/utils/distance/distance.js b/src/shared/utils/distance/distance.ts similarity index 79% rename from src/shared/utils/distance/distance.js rename to src/shared/utils/distance/distance.ts index f956146..9954b67 100644 --- a/src/shared/utils/distance/distance.js +++ b/src/shared/utils/distance/distance.ts @@ -6,6 +6,11 @@ * @param {Number} y2 The Y position of the second point * @return {Number} */ -export default function distance(x1, y1, x2, y2) { +export default function distance( + x1: number, + y1: number, + x2: number, + y2: number, +) { return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); } diff --git a/src/shared/utils/distance/index.js b/src/shared/utils/distance/index.ts similarity index 100% rename from src/shared/utils/distance/index.js rename to src/shared/utils/distance/index.ts diff --git a/src/shared/utils/index.js b/src/shared/utils/index.ts similarity index 100% rename from src/shared/utils/index.js rename to src/shared/utils/index.ts diff --git a/src/shared/utils/requestNextAnimationFrame/index.js b/src/shared/utils/requestNextAnimationFrame/index.ts similarity index 100% rename from src/shared/utils/requestNextAnimationFrame/index.js rename to src/shared/utils/requestNextAnimationFrame/index.ts diff --git a/src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.js b/src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.ts similarity index 53% rename from src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.js rename to src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.ts index 35196cc..74fe8ff 100644 --- a/src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.js +++ b/src/shared/utils/requestNextAnimationFrame/requestNextAnimationFrame.ts @@ -1,4 +1,4 @@ -export default function requestNextAnimationFrame(callback) { +export default function requestNextAnimationFrame(callback: () => void) { return requestAnimationFrame(() => { requestAnimationFrame(callback); }); diff --git a/src/shared/utils/touchCoords/index.js b/src/shared/utils/touchCoords/index.ts similarity index 100% rename from src/shared/utils/touchCoords/index.js rename to src/shared/utils/touchCoords/index.ts diff --git a/src/shared/utils/touchCoords/touchCoords.js b/src/shared/utils/touchCoords/touchCoords.ts similarity index 83% rename from src/shared/utils/touchCoords/touchCoords.js rename to src/shared/utils/touchCoords/touchCoords.ts index d09a673..d671f1d 100644 --- a/src/shared/utils/touchCoords/touchCoords.js +++ b/src/shared/utils/touchCoords/touchCoords.ts @@ -3,7 +3,7 @@ * @param {TouchEvent} event a touch event * @return {Touch} a touch object */ -export default function touchCoords(event = {}) { +export default function touchCoords(event: TouchEvent) { const {touches, changedTouches} = event; return (touches && touches[0]) || (changedTouches && changedTouches[0]); } diff --git a/scripts/test/environment.js b/test/environment.ts similarity index 69% rename from scripts/test/environment.js rename to test/environment.ts index 0994274..2f5255f 100644 --- a/scripts/test/environment.js +++ b/test/environment.ts @@ -1,5 +1,11 @@ import {REQUEST_ANIMATION_FRAME_TIMEOUT} from './helpers/environment'; +declare global { + export interface Event { + stoppedPropagation: boolean; + } +} + window.requestAnimationFrame = (callback) => { return setTimeout(callback, REQUEST_ANIMATION_FRAME_TIMEOUT); }; @@ -9,7 +15,10 @@ window.cancelAnimationFrame = (id) => { }; Event.prototype.stopPropagation = (function (_super) { - return function (...args) { + return function ( + this: Event, + ...args: Parameters + ) { const returnValue = _super.call(this, ...args); this.stoppedPropagation = true; return returnValue; @@ -17,7 +26,10 @@ Event.prototype.stopPropagation = (function (_super) { })(Event.prototype.stopPropagation); Event.prototype.stopImmediatePropagation = (function (_super) { - return function (...args) { + return function ( + this: Event, + ...args: Parameters + ) { const returnValue = _super.call(this, ...args); this.stoppedPropagation = true; return returnValue; diff --git a/scripts/test/helper.js b/test/helper.ts similarity index 100% rename from scripts/test/helper.js rename to test/helper.ts diff --git a/scripts/test/helpers/constants.js b/test/helpers/constants.ts similarity index 100% rename from scripts/test/helpers/constants.js rename to test/helpers/constants.ts diff --git a/scripts/test/helpers/environment.js b/test/helpers/environment.ts similarity index 69% rename from scripts/test/helpers/environment.js rename to test/helpers/environment.ts index 1b771b0..ab68056 100644 --- a/scripts/test/helpers/environment.js +++ b/test/helpers/environment.ts @@ -1,6 +1,6 @@ import {setImmediate} from 'timers'; -export function createSandbox(content) { +export function createSandbox(content: string) { const sandbox = document.createElement('div'); sandbox.innerHTML = content; document.body.appendChild(sandbox); @@ -8,7 +8,10 @@ export function createSandbox(content) { return sandbox; } -export function withElementFromPoint(elementFromPoint, callback) { +export function withElementFromPoint( + elementFromPoint: HTMLElement, + callback: () => void, +) { const originalElementFromPoint = document.elementFromPoint; document.elementFromPoint = () => elementFromPoint; callback(); @@ -17,7 +20,9 @@ export function withElementFromPoint(elementFromPoint, callback) { export const REQUEST_ANIMATION_FRAME_TIMEOUT = 15; -export function waitForRequestAnimationFrame(requestAnimationFrameTimeout = REQUEST_ANIMATION_FRAME_TIMEOUT) { +export function waitForRequestAnimationFrame( + requestAnimationFrameTimeout = REQUEST_ANIMATION_FRAME_TIMEOUT, +) { jest.advanceTimersByTime(requestAnimationFrameTimeout + 1); } diff --git a/scripts/test/helpers/event.js b/test/helpers/event.ts similarity index 79% rename from scripts/test/helpers/event.js rename to test/helpers/event.ts index 22001f6..292a258 100644 --- a/scripts/test/helpers/event.js +++ b/test/helpers/event.ts @@ -1,6 +1,10 @@ import {withElementFromPoint} from './environment'; -export function triggerEvent(element, type, data = {}) { +export function triggerEvent( + element: HTMLElement, + type: string, + data: {[key: string]: any} = {}, +) { const event = document.createEvent('Event'); event.initEvent(type, true, true); diff --git a/scripts/test/helpers/index.js b/test/helpers/index.ts similarity index 100% rename from scripts/test/helpers/index.js rename to test/helpers/index.ts diff --git a/scripts/test/helpers/module.js b/test/helpers/module.ts similarity index 80% rename from scripts/test/helpers/module.js rename to test/helpers/module.ts index 0975d33..a03ebd8 100644 --- a/scripts/test/helpers/module.js +++ b/test/helpers/module.ts @@ -12,7 +12,13 @@ import { dragStop, } from './sensor'; -export function drag({from, to, sensor = 'mouse'}) { +interface Options { + from: HTMLElement; + to: HTMLElement; + sensor: 'mouse' | 'touch' | 'drag'; +} + +export function drag({from, to, sensor = 'mouse'}: Options) { if (sensor === 'mouse') { clickMouse(from); waitForDragDelay(); diff --git a/test/helpers/plugin.ts b/test/helpers/plugin.ts new file mode 100644 index 0000000..d016110 --- /dev/null +++ b/test/helpers/plugin.ts @@ -0,0 +1,20 @@ +import AbstractPlugin from 'shared/AbstractPlugin'; + +export class TestPlugin extends AbstractPlugin { + constructor(draggable: any) { + super(draggable); + + /* eslint-disable jest/prefer-spy-on */ + this.attach = jest.fn(); + this.detach = jest.fn(); + /* eslint-enable jest/prefer-spy-on */ + } + + attach() { + return jest.fn(); + } + + detach() { + return jest.fn(); + } +} diff --git a/scripts/test/helpers/sensor.js b/test/helpers/sensor.ts similarity index 50% rename from scripts/test/helpers/sensor.js rename to test/helpers/sensor.ts index 4d4ec66..ccc0284 100644 --- a/scripts/test/helpers/sensor.js +++ b/test/helpers/sensor.ts @@ -1,7 +1,14 @@ -import {DRAG_DELAY, defaultTouchEventOptions, defaultMouseEventOptions} from './constants'; +import { + DRAG_DELAY, + defaultTouchEventOptions, + defaultMouseEventOptions, +} from './constants'; import {triggerEvent} from './event'; -export function waitForDragDelay({dragDelay = DRAG_DELAY, restoreDateMock = true} = {}) { +export function waitForDragDelay({ + dragDelay = DRAG_DELAY, + restoreDateMock = true, +} = {}) { const next = Date.now() + dragDelay + 1; const dateMock = jest.spyOn(Date, 'now').mockImplementation(() => { return next; @@ -13,61 +20,70 @@ export function waitForDragDelay({dragDelay = DRAG_DELAY, restoreDateMock = true return dateMock; } -export function clickMouse(element, options = {}) { - return triggerEvent(element, 'mousedown', {...defaultMouseEventOptions, ...options}); +export function clickMouse(element: HTMLElement, options = {}) { + return triggerEvent(element, 'mousedown', { + ...defaultMouseEventOptions, + ...options, + }); } -export function moveMouse(element, options = {}) { - return triggerEvent(element, 'mousemove', {...defaultMouseEventOptions, ...options}); +export function moveMouse(element: HTMLElement, options = {}) { + return triggerEvent(element, 'mousemove', { + ...defaultMouseEventOptions, + ...options, + }); } -export function releaseMouse(element, options = {}) { - return triggerEvent(element, 'mouseup', {...defaultMouseEventOptions, ...options}); +export function releaseMouse(element: HTMLElement, options = {}) { + return triggerEvent(element, 'mouseup', { + ...defaultMouseEventOptions, + ...options, + }); } -export function touchStart(element, options) { +export function touchStart(element: HTMLElement, options = {}) { return triggerEvent(element, 'touchstart', { ...defaultTouchEventOptions, ...options, }); } -export function touchMove(element, options) { +export function touchMove(element: HTMLElement, options = {}) { return triggerEvent(element, 'touchmove', { ...defaultTouchEventOptions, ...options, }); } -export function touchRelease(element, options) { +export function touchRelease(element: HTMLElement, options = {}) { return triggerEvent(element, 'touchend', { ...defaultTouchEventOptions, ...options, }); } -export function dragStart(element, options) { +export function dragStart(element: HTMLElement, options = {}) { return triggerEvent(element, 'dragstart', { dataTransfer: getDataTransferStub(), ...options, }); } -export function dragOver(element, options) { +export function dragOver(element: HTMLElement, options = {}) { return triggerEvent(element, 'dragover', { dataTransfer: getDataTransferStub(), ...options, }); } -export function dragDrop(element, options) { +export function dragDrop(element: HTMLElement, options = {}) { return triggerEvent(element, 'drop', { dataTransfer: getDataTransferStub(), ...options, }); } -export function dragStop(element, options) { +export function dragStop(element: HTMLElement, options = {}) { return triggerEvent(element, 'dragend', { dataTransfer: getDataTransferStub(), ...options, diff --git a/scripts/test/matchers/dom-event.js b/test/matchers/dom-event.ts similarity index 85% rename from scripts/test/matchers/dom-event.js rename to test/matchers/dom-event.ts index 73f4513..4f922be 100644 --- a/scripts/test/matchers/dom-event.js +++ b/test/matchers/dom-event.ts @@ -1,4 +1,4 @@ -function toHaveDefaultPrevented(event) { +function toHaveDefaultPrevented(event: Event) { const pass = Boolean(event.defaultPrevented); return { @@ -11,7 +11,7 @@ function toHaveDefaultPrevented(event) { }; } -function toHaveStoppedPropagation(event) { +function toHaveStoppedPropagation(event: Event) { const pass = Boolean(event.stoppedPropagation); return { diff --git a/scripts/test/matchers/event.js b/test/matchers/event.ts similarity index 64% rename from scripts/test/matchers/event.js rename to test/matchers/event.ts index ef6bfa4..48de1ed 100644 --- a/scripts/test/matchers/event.js +++ b/test/matchers/event.ts @@ -1,21 +1,32 @@ +import AbstractEvent from 'shared/AbstractEvent'; + import {expectation} from './utils'; -function toHaveBeenCalledWithEvent(jestFunction, expectedEventConstructor) { +function toHaveBeenCalledWithEvent( + this: any, + jestFunction: ReturnType, + expectedEventConstructor: typeof AbstractEvent, +) { const mockFunction = jestFunction.mock; const mockCalls = mockFunction.calls; - let pass; + let pass: boolean; let message; - // eslint-disable-next-line @babel/no-invalid-this pass = this.isNot && mockCalls.length === 0; if (pass) { - message = () => `Expected ${expectedEventConstructor.type} event ${expectation(!pass)} triggered`; + message = () => + `Expected ${expectedEventConstructor.type} event ${expectation( + !pass, + )} triggered`; return {pass: !pass, message}; } pass = !mockCalls.length; if (pass) { - message = () => `Expected ${expectedEventConstructor.type} event ${expectation(pass)} triggered`; + message = () => + `Expected ${expectedEventConstructor.type} event ${expectation( + pass, + )} triggered`; return {pass, message}; } @@ -24,7 +35,9 @@ function toHaveBeenCalledWithEvent(jestFunction, expectedEventConstructor) { pass = !event; if (pass) { message = () => - `Expected ${expectedEventConstructor.type} event ${expectation(pass)} triggered with an event instance`; + `Expected ${expectedEventConstructor.type} event ${expectation( + pass, + )} triggered with an event instance`; return {pass, message}; } @@ -33,11 +46,16 @@ function toHaveBeenCalledWithEvent(jestFunction, expectedEventConstructor) { return { pass, message: () => - `Expected ${event.type} event ${expectation(pass)} triggered with ${expectedEventConstructor.name} instance`, + `Expected ${event.type} event ${expectation(pass)} triggered with ${ + expectedEventConstructor.name + } instance`, }; } -function toHaveBeenCalledWithEventProperties(jestFunction, expectedProperties) { +function toHaveBeenCalledWithEventProperties( + jestFunction: ReturnType, + expectedProperties: {[key: string]: any}, +) { const mockFunction = jestFunction.mock; const mockCalls = mockFunction.calls; const event = mockCalls[0][0]; @@ -54,8 +72,12 @@ function toHaveBeenCalledWithEventProperties(jestFunction, expectedProperties) { return { pass, message: () => { - const listOfExpectedProperties = expectedPropertyEntries.map(([key, value]) => `${key}=${JSON.stringify(value)}`); - const listOfReceivedProperties = receivedPropertyEntries.map(([key, value]) => `${key}=${JSON.stringify(value)}`); + const listOfExpectedProperties = expectedPropertyEntries.map( + ([key, value]) => `${key}=${JSON.stringify(value)}`, + ); + const listOfReceivedProperties = receivedPropertyEntries.map( + ([key, value]) => `${key}=${JSON.stringify(value)}`, + ); return `Expected ${event.type} event ${expectation( pass, diff --git a/scripts/test/matchers/index.js b/test/matchers/index.ts similarity index 100% rename from scripts/test/matchers/index.js rename to test/matchers/index.ts diff --git a/scripts/test/matchers/order.js b/test/matchers/order.ts similarity index 77% rename from scripts/test/matchers/order.js rename to test/matchers/order.ts index e9d675c..0459d69 100644 --- a/scripts/test/matchers/order.js +++ b/test/matchers/order.ts @@ -1,4 +1,4 @@ -function toHaveOrder(actualOrder, expectedOrder) { +function toHaveOrder(actualOrder: HTMLElement[], expectedOrder: HTMLElement[]) { const incorrectPositions = expectedOrder .map((element, index) => actualOrder[index] === element) .filter((isCorrectOrder) => !isCorrectOrder); @@ -13,7 +13,7 @@ function toHaveOrder(actualOrder, expectedOrder) { message += expectedOrder .map((element) => { - return `${element.textContent.trim()}`; + return `${(element.textContent || '').trim()}`; }) .join('\n'); @@ -21,7 +21,7 @@ function toHaveOrder(actualOrder, expectedOrder) { message += actualOrder .map((element) => { - return `${element.textContent.trim()}`; + return `${(element.textContent || '').trim()}`; }) .join('\n'); diff --git a/scripts/test/matchers/sensor.js b/test/matchers/sensor.ts similarity index 77% rename from scripts/test/matchers/sensor.js rename to test/matchers/sensor.ts index 8548af3..2bdeba6 100644 --- a/scripts/test/matchers/sensor.js +++ b/test/matchers/sensor.ts @@ -1,4 +1,8 @@ -function toHaveTriggeredSensorEvent(received, expectedEventName, count) { +function toHaveTriggeredSensorEvent( + received: () => void, + expectedEventName: string, + count: number, +) { let triggered = false; let callCount = 0; function callback() { @@ -12,7 +16,8 @@ function toHaveTriggeredSensorEvent(received, expectedEventName, count) { received(); document.removeEventListener(expectedEventName, callback); - const pass = Boolean(triggered) && Boolean(count === undefined || callCount === count); + const pass = + Boolean(triggered) && Boolean(count === undefined || callCount === count); return { pass, @@ -25,10 +30,13 @@ function toHaveTriggeredSensorEvent(received, expectedEventName, count) { }; } -function toHaveCanceledSensorEvent(received, expectedEventName) { +function toHaveCanceledSensorEvent( + received: () => void, + expectedEventName: string, +) { let canceled = false; - function callback(event) { + function callback(event: any) { canceled = event.detail.canceled(); } diff --git a/scripts/test/matchers/utils.js b/test/matchers/utils.ts similarity index 50% rename from scripts/test/matchers/utils.js rename to test/matchers/utils.ts index 7c18788..32fa502 100644 --- a/scripts/test/matchers/utils.js +++ b/test/matchers/utils.ts @@ -1,3 +1,3 @@ -export function expectation(passed) { +export function expectation(passed: boolean) { return passed ? 'not to have' : 'to have'; } diff --git a/scripts/test/setup.js b/test/setup.ts similarity index 100% rename from scripts/test/setup.js rename to test/setup.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4fd4bb0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "@shopify/typescript-configs/library", + "compilerOptions": { + "baseUrl": ".", + "rootDir": ".", + "lib": ["es2023"], + "resolveJsonModule": false, + "verbatimModuleSyntax": true, + "useUnknownInCatchVariables": false, + "paths": { + "shared/*": ["./src/shared/*"], + "helper": ["./test/helper.ts"] + } + }, + "include": [ + "./src/**/*", + "./test/**/*" + ] +} diff --git a/yarn.lock b/yarn.lock index 4e4c6ed..99008cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1133,6 +1133,13 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -1406,7 +1413,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== @@ -1429,6 +1436,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": version "0.3.19" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" @@ -1437,6 +1452,21 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@microsoft/tsdoc-config@0.16.2": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz#b786bb4ead00d54f53839a458ce626c8548d3adf" + integrity sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw== + dependencies: + "@microsoft/tsdoc" "0.14.2" + ajv "~6.12.6" + jju "~1.4.0" + resolve "~1.19.0" + +"@microsoft/tsdoc@0.14.2", "@microsoft/tsdoc@^0.14.2": + version "0.14.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" + integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -1534,6 +1564,16 @@ pkg-dir "^5.0.0" pluralize "^8.0.0" +"@shopify/prettier-config@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@shopify/prettier-config/-/prettier-config-1.1.2.tgz#612f87c0cd1196e8b43c85425e587d0fa7f1172d" + integrity sha512-5ugCL9sPGzmOaZjeRGaWUWhHgAbemrS6z+R7v6gwiD+BiqSeoFhIY+imLpfdFCVpuOGalpHeCv6o3gv++EHs0A== + +"@shopify/typescript-configs@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@shopify/typescript-configs/-/typescript-configs-5.1.0.tgz#f6e8fdd3291bf0a406578b2c6eb21f8c542d3c0a" + integrity sha512-RywGBTR+nQyJLxcrUcihPkHPIG3pIQI6i0YwMrM5rs9nWJ0+9A5HKEcboyGPLH+8V08EXGfFQ6H820O9ajyk4A== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1563,6 +1603,26 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@types/babel__core@^7.1.14": version "7.20.2" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.2.tgz#215db4f4a35d710256579784a548907237728756" @@ -1643,6 +1703,14 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/jest@^29.5.5": + version "29.5.5" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.5.tgz#727204e06228fe24373df9bae76b90f3e8236a2a" + integrity sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/jsdom@^20.0.0": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" @@ -1667,6 +1735,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.2.tgz#a065925409f59657022e9063275cd0b9bd7e1b12" integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw== +"@types/node@^20.6.3": + version "20.6.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.3.tgz#5b763b321cd3b80f6b8dde7a37e1a77ff9358dd9" + integrity sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA== + "@types/semver@^7.3.12", "@types/semver@^7.5.0": version "7.5.2" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564" @@ -1682,6 +1755,24 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.3.tgz#3d06b6769518450871fbc40770b7586334bdfd90" integrity sha512-THo502dA5PzG/sfQH+42Lw3fvmYkceefOspdCwpHRul8ik2Jv1K8I5OZz1AT3/rs46kwgMCe9bSBmDLYkkOMGg== +"@types/webpack-bundle-analyzer@^4.6.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.0.tgz#8863d62d2432126c2b3a9239cafa469215981c24" + integrity sha512-XeQmQCCXdZdap+A/60UKmxW5Mz31Vp9uieGlHB3T4z/o2OLVLtTI3bvTuS6A2OWd/rbAAQiGGWIEFQACu16szA== + dependencies: + "@types/node" "*" + tapable "^2.2.0" + webpack "^5" + +"@types/webpack@^5.28.2": + version "5.28.2" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-5.28.2.tgz#a4db514f30b1b593278fbae6d6f9654c3d53c4c8" + integrity sha512-7tcxyrIOd7WGimZIcWU6pDsNh2edGGnwYExOvd3l/nMvuxqwVPrFXnnTbYCnplqV9BJoU7Mo2mfFtiH8CNFvYw== + dependencies: + "@types/node" "*" + tapable "^2.2.0" + webpack "^5" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -2008,7 +2099,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^8.0.0, acorn-walk@^8.0.2: +acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== @@ -2018,7 +2109,7 @@ acorn@^2.1.0, acorn@^2.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" integrity sha512-pXK8ez/pVjqFdAgBkF1YPVRacuLQ9EXBKaKWaeh58WNfMkCmZhOZzu+NtKSPD5PHmCCHheQ5cD29qM1K4QTxIg== -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.10.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== @@ -2049,7 +2140,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2118,6 +2209,11 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2277,15 +2373,6 @@ axobject-query@^3.1.1: dependencies: dequal "^2.0.3" -babel-code-frame@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-7.0.0-beta.3.tgz#1614a91b2ba0e3848559f410bbacd030726899c9" - integrity sha512-flMsJ9eSpShupt2Gwpka84DoMePvE4HlDObzdEc+1iNkacv3+NHlsJ7dMKmbnVA/AT22UhcGEBHwbJLoXWBO6Q== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -2321,84 +2408,6 @@ babel-generator@6.26.1: source-map "^0.5.7" trim-right "^1.0.1" -babel-helper-annotate-as-pure@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-annotate-as-pure/-/babel-helper-annotate-as-pure-7.0.0-beta.3.tgz#f86e3f15b48c1f8df1669d890548ad6f7ca252d6" - integrity sha512-C6uYc7RmuPDZmkwTaV/ya0BGuZJFyuU/mAyDDqSfyuUZavk04eKdEWxjaKRGd3UA/fpzLNKViYO4aQgY4TsxCQ== - dependencies: - babel-types "7.0.0-beta.3" - -babel-helper-define-map@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-7.0.0-beta.3.tgz#503db9efcac5308d8df70fef48936364ac8e4212" - integrity sha512-F2DrZDfS4EIFi5HTK3eaL8ojJwM6jjEM26D/i7h1YAwlm6PytiOXlhcXNbOoSBv6767WesNWpLVDQoX68SjDrQ== - dependencies: - babel-helper-function-name "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - lodash "^4.2.0" - -babel-helper-function-name@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-7.0.0-beta.3.tgz#e86dd2eb2c09e06e392e79e203fc02427b24c871" - integrity sha512-iMWYqwDarQOVlEGcK1MfbtK9vrFGs5Z4UQsdASJUHdhBp918EM5kndwriiIbhUX8gr2B/CEV/udJkFTrHsjdMQ== - dependencies: - babel-helper-get-function-arity "7.0.0-beta.3" - babel-template "7.0.0-beta.3" - babel-traverse "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - -babel-helper-get-function-arity@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-7.0.0-beta.3.tgz#61a47709318a31bc2db872f4be9b4c8447198be8" - integrity sha512-ZkYFRMWKx1c9fUW72YNM3eieBG701CMbLjmLLWmJTTPc0F0kddS9Fwok26EAmndUAgD6kFdh7ms3PH94MdGuGQ== - dependencies: - babel-types "7.0.0-beta.3" - -babel-helper-module-imports@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz#e15764e3af9c8e11810c09f78f498a2bdc71585a" - integrity sha512-bdPrIXbUTYfREhRhjbN8SstwQaj0S4+rW4PKi1f2Wc5fizSh0hGYkfXUdiSSOgyTydm956tAyz4FrG61bqdQyw== - dependencies: - babel-types "7.0.0-beta.3" - lodash "^4.2.0" - -babel-helper-module-transforms@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-module-transforms/-/babel-helper-module-transforms-7.0.0-beta.3.tgz#42ccfa323e2d3aaaf0f743e66c2e7a292dc064f7" - integrity sha512-mnCAqH2fpcYny6LMyCg/bMif/D8FxER/at9R3xNWvfAv2N5x5Yhai0g8tBQZuINqZkAxQ4Tl7x/8ImviwKBQSA== - dependencies: - babel-helper-module-imports "7.0.0-beta.3" - babel-helper-simple-access "7.0.0-beta.3" - babel-template "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - lodash "^4.2.0" - -babel-helper-optimise-call-expression@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-7.0.0-beta.3.tgz#8c533bf31f05a4aa893700916e6a7e2a5fde7b9c" - integrity sha512-X614MCHT+to5dnH4uecU63VUmOs+4Hn8DfH6vT2090HHE9/swOuNFKpeNeI3hebt59eAYyoWb2iPGv7FTpIh3Q== - dependencies: - babel-types "7.0.0-beta.3" - -babel-helper-replace-supers@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-7.0.0-beta.3.tgz#73598401b73feff5a6689a929b77496f15d673c3" - integrity sha512-ZkTdE7XBDW0PUQkKTeax+m1JpZqzo9ze3zbqjRxyt+x328NeGLD3edmNCIxmFt86njxIo3AFfZ00PKd4g/7jqg== - dependencies: - babel-helper-optimise-call-expression "7.0.0-beta.3" - babel-template "7.0.0-beta.3" - babel-traverse "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - -babel-helper-simple-access@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-helper-simple-access/-/babel-helper-simple-access-7.0.0-beta.3.tgz#dee94c31289fca79076f7ced2d751a06e430756c" - integrity sha512-4gaS4Eej6+qY35EWuwtkDQ47oKTRIBmGEGMzTigyDVjRfNltAlhN8lZPhNsIcKxG3zJ/UTOhtx7j8dmn757PUw== - dependencies: - babel-template "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - lodash "^4.2.0" - babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -2477,60 +2486,11 @@ babel-plugin-react-test-id@^1.0.2: resolved "https://registry.yarnpkg.com/babel-plugin-react-test-id/-/babel-plugin-react-test-id-1.0.2.tgz#90fb7ab91e9623bea47ad1f7eddd9a38e2dfc51b" integrity sha512-d1bBxX3UNOIaX6NUEsR6Ekfy1fvmCegY9lQodgg6DevjhaNBDnaUeDUHl6JbIh5tuw0EF7FGgt+61yiFLMWwMg== -babel-plugin-syntax-class-properties@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-7.0.0-beta.3.tgz#84480d42dc9ec49f5f8e1e62fb435151cbbe11a3" - integrity sha512-0tNuKFPtKtElgd29PAiOHfA+IMALb6vD+tX8XsgDuaWWtgarqdJ3ia1EfFsG5RL7sUNYzKZM4UguMKzKLuvdQQ== - -babel-plugin-syntax-object-rest-spread@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-7.0.0-beta.3.tgz#7f781c180899dafd88f132f69472397549be48e5" - integrity sha512-21/MnmUFduLr4JzxrKMm/MeF+Jjyi5UdZo38IqzrP0sLhmPbal5ZAUJ4HgWH4339SdjnYgENacbY5wfk/zxTGg== - -babel-plugin-transform-class-properties@^7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-7.0.0-beta.3.tgz#d7cf0e431512262499421d53582969503f24581a" - integrity sha512-12n5QjNKJlbhRmAfVcM5D+rGpxsDa0AP+ufa5Xylvwcgjpq4YjEQc8L5VBBFLFmByAcXKsknNsAVuSfOIGHNDw== - dependencies: - babel-helper-function-name "7.0.0-beta.3" - babel-plugin-syntax-class-properties "7.0.0-beta.3" - babel-template "7.0.0-beta.3" - -babel-plugin-transform-es2015-classes@^7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-7.0.0-beta.3.tgz#578b9604a3ace50a1a92944cb045088cd69474bf" - integrity sha512-4vH3pzhx3oZ6rphe3EDCkxFfMsWlJoEMSk8pIHnfXm4dOL+goij5mrxqoTAh7W/DcMzpakZOdKkgsgg+iujg8Q== - dependencies: - babel-helper-annotate-as-pure "7.0.0-beta.3" - babel-helper-define-map "7.0.0-beta.3" - babel-helper-function-name "7.0.0-beta.3" - babel-helper-optimise-call-expression "7.0.0-beta.3" - babel-helper-replace-supers "7.0.0-beta.3" - babel-template "7.0.0-beta.3" - babel-traverse "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - -babel-plugin-transform-es2015-modules-commonjs@^7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-7.0.0-beta.3.tgz#d53ae18f16e0b6a50ab65cdafbe3fa51a22f39b5" - integrity sha512-RcRIKOAerrm2M5+w8ITVoadLynjU4inaw+VtZwq1G10VBNn2bbik7hfXWdgnTUdHE8h3TGAafHX9Iw0Zxxuhrg== - dependencies: - babel-helper-module-transforms "7.0.0-beta.3" - babel-helper-simple-access "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - babel-plugin-transform-inline-environment-variables@^0.4.3: version "0.4.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-environment-variables/-/babel-plugin-transform-inline-environment-variables-0.4.4.tgz#974245008b3cbbd646bd81707af147aea3acca43" integrity sha512-bJILBtn5a11SmtR2j/3mBOjX4K3weC6cq+NNZ7hG22wCAqpc3qtj/iN7dSe9HDiS46lgp1nHsQgeYrea/RUe+g== -babel-plugin-transform-object-rest-spread@^7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-7.0.0-beta.3.tgz#5c409f3cd70819dbb3382d2056971c5ebe01393a" - integrity sha512-NOlhrq1CmxyuI94vNsqMhRPMuL5VG2EKUOIJQ0bwNiXBiwWRLdPoWyPT+Irrx5g4g0PkFgA46tnRj7Dc4ZGsxg== - dependencies: - babel-plugin-syntax-object-rest-spread "7.0.0-beta.3" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2589,17 +2549,6 @@ babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-template@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-7.0.0-beta.3.tgz#ebb877b6070ce9912b0d0c22fcad3372165913a8" - integrity sha512-urJduLja89kSDGqY8ryw8iIwQnMl30IvhMtMNmDD7vBX0l0oylaLgK+7df/9ODX9vR/PhXuif6HYl5HlzAKXMg== - dependencies: - babel-code-frame "7.0.0-beta.3" - babel-traverse "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - babylon "7.0.0-beta.27" - lodash "^4.2.0" - babel-traverse@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" @@ -2615,29 +2564,6 @@ babel-traverse@6.26.0: invariant "^2.2.2" lodash "^4.17.4" -babel-traverse@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-7.0.0-beta.3.tgz#3cf0a45d53d934d85275d8770775d7944fc7c199" - integrity sha512-xyh/aPYuedMAfQlSj2kjHjsEmY5/Dpxs576L05DySAVMrV+ADX6l4mTOLysAEGwJfkePJlDLhFuS6SKaxv1V7w== - dependencies: - babel-code-frame "7.0.0-beta.3" - babel-helper-function-name "7.0.0-beta.3" - babel-types "7.0.0-beta.3" - babylon "7.0.0-beta.27" - debug "^3.0.1" - globals "^10.0.0" - invariant "^2.2.0" - lodash "^4.2.0" - -babel-types@7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.3.tgz#cd927ca70e0ae8ab05f4aab83778cfb3e6eb20b4" - integrity sha512-36k8J+byAe181OmCMawGhw+DtKO7AwexPVtsPXoMfAkjtZgoCX3bEuHWfdE5sYxRM8dojvtG/+O08M0Z/YDC6w== - dependencies: - esutils "^2.0.2" - lodash "^4.2.0" - to-fast-properties "^2.0.0" - babel-types@^6.10.2, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" @@ -2653,11 +2579,6 @@ babylon@6.18.0, babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -babylon@7.0.0-beta.27: - version "7.0.0-beta.27" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.27.tgz#b6edd30ef30619e2f630eb52585fdda84e6542cd" - integrity sha512-ksRx+r8eFIfdt63MCgLc9VxGL7W3jcyveQvMpNMVHgW+eb9mq3Xbm45FLCNkw8h92RvoNp4uuiwzcCEwxjDBZg== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2717,6 +2638,13 @@ browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.9: node-releases "^2.0.13" update-browserslist-db "^1.0.11" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2797,7 +2725,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2806,7 +2734,7 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3093,6 +3021,11 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3181,7 +3114,7 @@ debug@^2.6.8: dependencies: ms "2.0.0" -debug@^3.0.1, debug@^3.2.7: +debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -3285,6 +3218,11 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3420,7 +3358,7 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -enhanced-resolve@^5.15.0: +enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0: version "5.15.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== @@ -3860,6 +3798,14 @@ eslint-plugin-sort-class-members@^1.18.0: resolved "https://registry.yarnpkg.com/eslint-plugin-sort-class-members/-/eslint-plugin-sort-class-members-1.18.0.tgz#561746eb30abc4e8bb8d582d359c652299e450d8" integrity sha512-y4r5OC3LJNHJZCWfVwFnnRiNrQ/LRf7Pb1wD6/CP8Y4qmUvjtmkwrLvyY755p8SFTOOXVd33HgFuF3XxVW1xbg== +eslint-plugin-tsdoc@^0.2.17: + version "0.2.17" + resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz#27789495bbd8778abbf92db1707fec2ed3dfe281" + integrity sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA== + dependencies: + "@microsoft/tsdoc" "0.14.2" + "@microsoft/tsdoc-config" "0.16.2" + eslint-rule-composer@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" @@ -4029,7 +3975,7 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.7.0: +expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== @@ -4076,7 +4022,7 @@ fast-glob@^3.2.9, fast-glob@^3.3.0: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -4339,11 +4285,6 @@ global@^4.3.0: min-document "^2.19.0" process "^0.11.10" -globals@^10.0.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-10.4.0.tgz#5c477388b128a9e4c5c5d01c7a2aca68c68b2da7" - integrity sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA== - globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -4650,7 +4591,7 @@ interpret@^3.1.1: resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== -invariant@^2.2.0, invariant@^2.2.2: +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -4698,7 +4639,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.9.0: +is-core-module@^2.1.0, is-core-module@^2.13.0, is-core-module@^2.9.0: version "2.13.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== @@ -5300,7 +5241,7 @@ jest-snapshot@^29.7.0: pretty-format "^29.7.0" semver "^7.5.3" -jest-util@^29.7.0: +jest-util@^29.0.0, jest-util@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== @@ -5367,16 +5308,21 @@ jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -js-tokens@^3.0.0, js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + js-yaml@3.14.1, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5708,6 +5654,11 @@ lodash.map@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + lodash.merge@^4.4.0, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -5783,6 +5734,11 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -5805,7 +5761,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -6235,7 +6191,7 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.7: +path-parse@^1.0.6, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -6325,7 +6281,7 @@ prettier@^3.0.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== -pretty-format@^29.7.0: +pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -6631,6 +6587,14 @@ resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@~1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6732,7 +6696,7 @@ semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: +semver@^7.3.4, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -7234,6 +7198,49 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== +ts-jest@^29.1.1: + version "29.1.1" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-loader@^9.4.4: + version "9.4.4" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.4.tgz#6ceaf4d58dcc6979f84125335904920884b7cee4" + integrity sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tsconfig-paths@^3.14.2: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" @@ -7341,6 +7348,11 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -7448,6 +7460,11 @@ uuid@^8.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-to-istanbul@^9.0.1: version "9.1.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz#1b83ed4e397f58c85c266a570fc2558b5feb9265" @@ -7566,7 +7583,7 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.88.2: +webpack@^5, webpack@^5.88.2: version "5.88.2" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== @@ -7760,7 +7777,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^21.1.1: +yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -7778,6 +7795,11 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"