UNPKG

artboard-deluxe

Version:
1,501 lines (1,483 loc) 62.4 kB
type Size = { width: number; height: number; }; type Coord = { x: number; y: number; }; /** * Edges of a rectangle. */ type Edge = { top: number; right: number; bottom: number; left: number; }; type Rectangle = Size & Coord; type Boundaries = { xMin: number; xMax: number; yMin: number; yMax: number; }; /** * The 'origin', similar to how the CSS `transform-origin` property works: * - horizontal: 'left' | 'center' | 'right' * - vertical: 'top' | 'center' | 'bottom' */ type Origin = 'top-left' | 'center-left' | 'bottom-left' | 'top-center' | 'center-center' | 'bottom-center' | 'top-right' | 'center-right' | 'bottom-right'; declare function createOptions(initOptions?: ArtboardOptions): { setAllOptions: (newOptions?: ArtboardOptions) => void; set: <T extends keyof ArtboardOptions>(key: T, value: ArtboardOptions[T]) => void; readonly hasBlockingRects: boolean; readonly overscrollBounds: Edge; readonly minScale: number; readonly maxScale: number; readonly scrollStepAmount: number; readonly margin: number; readonly momentumDeceleration: number; readonly springDamping: number; readonly direction: Direction; readonly rootClientRectMaxStale: number; readonly blockingRects: Rectangle[]; }; type Options = ReturnType<typeof createOptions>; declare function easeOutQuad(x: number): number; declare function easeOutBack(x: number): number; declare function easeOutElastic(x: number): number; declare function easeOutCirc(x: number): number; declare function easeInOutExpo(x: number): number; declare function easeOutCubic(x: number): number; declare function easeInSine(x: number): number; declare function easeInOutSine(x: number): number; declare function easeInOutQuad(x: number): number; declare function easeInOutQuart(x: number): number; declare function easeInOutCirc(x: number): number; declare function easeInOutQuint(x: number): number; declare function linear(x: number): number; type EasingFunction = (x: number) => number; declare const EASINGS: { readonly easeInOutExpo: typeof easeInOutExpo; readonly easeOutCirc: typeof easeOutCirc; readonly easeOutElastic: typeof easeOutElastic; readonly easeOutQuad: typeof easeOutQuad; readonly easeOutBack: typeof easeOutBack; readonly easeOutCubic: typeof easeOutCubic; readonly easeInSine: typeof easeInSine; readonly easeInOutSine: typeof easeInOutSine; readonly easeInOutQuad: typeof easeInOutQuad; readonly easeInOutQuart: typeof easeInOutQuart; readonly easeInOutCirc: typeof easeInOutCirc; readonly easeInOutQuint: typeof easeInOutQuint; readonly linear: typeof linear; }; type AnimationEasing = keyof typeof EASINGS | EasingFunction; type ArtboardAnimation = Coord & { key: string; /** The target scale for the animation. */ scale: number; /** The offset X value when the animation started. */ startX: number; /** The offset Y value when the animation started. */ startY: number; /** The scale value when the animation started. */ startScale: number; /** The easing method to use for the animation. */ easing: AnimationEasing; /** The timestamp when the animation started. */ startTime: number; /** The duration of the animation. */ duration: number; }; type AnimationOptions = { /** * The easing function to use when animating. * * Can either be the name of one of the built in easing functions or a custom function. * If a custom function is provided, it will receive the current progress (a value from 0 to 1) as the only argument and should return the eased progress. */ easing?: AnimationEasing; /** The speed of the animation. */ duration?: number; }; type PluginOptions<T> = T extends ArtboardPluginDefinition<infer O, any> ? O : never; type PluginInstance<T> = T extends ArtboardPluginDefinition<infer O extends object, infer R extends object> ? ArtboardPluginInstance<O, R> : never; type ObserverSizeChangeCallback<T extends Element> = (entry: ResizeObserverEntry & { target: T; }) => void; type ObserverSizeChangeContext = { unobserve: () => void; }; /** * Defines possible scroll directions. */ type Direction = 'horizontal' | 'vertical' | 'both' | 'none'; /** * A possible return type for the getBlockingRects() method. * * You may either return an object compatible with `Rectangle` (such as the return value of `element.getBoundingClientRect()`) or an array of four numbers representing `[x, y, width, height]`. */ type PossibleBlockingRect = Rectangle | [number, number, number, number]; /** * A fully initialised plugin instance. */ type ArtboardPluginInstance<O extends object = object, R extends object = object> = { /** * The options helper. */ options: ArtboardPluginOptions<O>; /** * Remove event listeners and clean up. */ destroy?: () => void; /** * Called in the main animation loop. * * Receives the state of the artboard at the time of the animation loop as an argument. */ loop?: (ctx: ArtboardLoopContext) => void; } & R; type ArtboardPluginOptions<T extends object> = { /** * Get an option value. */ get<K extends keyof T>(key: K): T[K]; /** * Get a required option value. If the option is not set an error is thrown. */ getRequired<K extends keyof T>(key: K): T[K]; /** * Get an option that is either a DOM element or a selector. * * Throws an error if no element could be found. */ getElement<K extends keyof T>(key: K, fallbackSelector: string, parent: HTMLElement): HTMLElement; /** * Returns the boolean representation of an option. */ should<K extends keyof T>(key: K, defaultValue?: T[K]): boolean; /** * Get an option value with a default value. */ get<K extends keyof T>(key: K, defaultValue: T[K]): NonNullable<T[K]>; /** * Set an option. */ set<K extends keyof T>(key: K, value: T[K]): void; /** * Set all options at once. */ setAll(newOptions: T): void; /** * Set multiple options at once. */ setMultiple(newOptions: Partial<T>): void; /** * Compute and cache a value based on the current options. * * If any option is changed (via set or setAll), the cache is cleared. */ computed<R>(callback: (options: T) => R): { value: R; }; }; type ArtboardPluginInit<O extends object, R extends object = object> = (artboard: Artboard, options: ArtboardPluginOptions<O>) => ArtboardPluginInstance<O, R>; /** * Defines a plugin definition. * * This is the return value when you create a plugin, e.g. using `mouse()`. * The plugin definition can then be passed as the second argument in an array to `createArtboard` or by manually adding the plugin after the artboard has been initialised using `artboard.addPlugin()`. */ type ArtboardPluginDefinition<T extends object, R extends object> = { /** * The options instance. */ options: ArtboardPluginOptions<T>; /** * The method to initlise the plugin. * * @internal */ init: ArtboardPluginInit<T, R>; }; /** * Options for createArtboard(). */ type ArtboardOptions = { /** * The initial offset. * * @example * ```typescript * { * initTransform: { * x: 500, * y: 20, * scale: 1 * } * } * ``` */ initTransform?: Coord & { scale: number; }; /** * How much of the artboard should remain visible when overscrolling. * * A value of 0 means the artboard can be dragged right to every edge of the * root element. A value of e.g. 100 means that there is always at least 100px * of the artboard visible. A negative value means the artboard can be dragged * outside the root element. * * You can also provide an object with top, right, bottom and left properties * to define individual values per edge. * * @example * Initialise with same bounds on all edges. * ```typescript * { * overscrollBounds: 20 * } * ``` * * @example * Initialise with individual bounds per edge. * ```typescript * { * overscrollBounds: { * top: 50, * bottom: 50, * left: 100, * right: 70, * } * } * ``` */ overscrollBounds?: number | Edge; /** * The margin used when aligning the artboard, for example when calling the * `scaleToFit()` method. In this case, a value of `0` would scale the artboard to * fill all the available width or height. A value of `50` would scale it so that * there is at least 50px between the artboard and the root element. * * @example * ```typescript * Keeps at least 10px space between the artboard and the root element when aligning. * { * margin: 10, * } * ``` */ margin?: number; /** * The amount to scroll per step, in pixels. This is used by methods like * `artboard.scrollUp()`. * * @example * Scrolls by 200px when calling for example the scrollUp() method, e.g. when * pressing the ArrowUp key. * ```typescript * { * scrollStepAmount: 200, * } * ``` */ scrollStepAmount?: number; /** * The minimum amount the artboard can scale. * * @example * Prevents scaling below 0.1. * * ```typescript * { * minScale: 0.1, * } * ``` */ minScale?: number; /** * The maximum amount the artboard can scale. * * @example * Prevents scaling above 9. * ```typescript * { * maxScale: 9, * } * ``` */ maxScale?: number; /** * The deceleration of the momentum scrolling. The higher the value the longer the momentum scrolling is applied. * * @example * ```typescript * { * momentumDeceleration: 0.96 * } * ``` */ momentumDeceleration?: number; /** * Which directions can be scrolled. * * Possible values are `'none'`, `'horizontal'`, `'vertical'` or `'both'` (default). * * @example * Restrict scrolling to the Y axis on a mobile viewport. * ```typescript * { * direction: window.innerWidth < 768 ? 'vertical' : 'both' * } * ``` */ direction?: Direction; springDamping?: number; /** * A method that should return an array of rectangles (relative to viewport) * that in some way overlap the root element. * * This information is used to center the artboard so that it (ideally) * remains as visible as possible. * * @example * ```typescript * function getBlockingRects() { * const toolbar = document.getElementById('toolbar') * const rect = toolbar.getBoundingClientRect() * return [rect] * } * ``` */ getBlockingRects?: () => PossibleBlockingRect[]; /** * How often the getBoundingClientRect() method should be called on the * root element. * * Some calculations require knowing the exact location of the root element * relative to the viewport. For this it will call getBoundingClientRect() * on the root element. However, doing this too much can have a negative * impact on performance, which is why this is only done sporadically. * * If you anticipate that the root element regularly changes its position * relative to the viewport, you may set a lower value. If the position * rarely or never changes, you may set a high value. * * Note the position is always updated when the ResizeObserver callback is * triggered for the root element. * * @example * Only refresh the root rect every minute. * * ```typescript * { * rootClientRectMaxStale: 60 * 1000, * } * ``` */ rootClientRectMaxStale?: number; }; /** * Options for scrolling an area of the artboard into view. */ type ArtboardScrollIntoViewOptions = AnimationOptions & { /** * Define whether the artboard should be scaled. * * - None: Keeps the current artboard scale. * - Full: Scales the artboard so that the target element fully covers the * available space. * - Blocking: Scales the artboard so that the target element covers the * non-blocking area. */ scale?: 'none' | 'full' | 'blocking'; /** * The scroll behaviour. * * - Smooth: Always animates the transition. * - Instant: Directly apply the transform and scale. * - Auto: Uses smooth, but switches to instant if an animation is currently * running. */ behavior?: 'smooth' | 'instant' | 'auto'; /** Which axis to scroll. */ axis?: 'x' | 'y' | 'both'; /** * Vertical alignment of the target rect within the effective viewport area. * * - `start`: Align the top edge of the target with the top of the viewport. * - `center`: Center the target vertically (default). * - `end`: Align the bottom edge of the target with the bottom of the viewport. * - `nearest`: Scroll the minimum distance needed. No-op if already visible. * If larger than the viewport, aligns `start`. * - `auto`: Center if the target fits within the viewport, otherwise align * `start`. */ block?: 'start' | 'center' | 'end' | 'nearest' | 'auto'; /** * Horizontal alignment of the target rect within the effective viewport area. * * - `start`: Align the left edge of the target with the left of the viewport. * - `center`: Center the target horizontally (default). * - `end`: Align the right edge of the target with the right of the viewport. * - `nearest`: Scroll the minimum distance needed. No-op if already visible. * If larger than the viewport, aligns `start`. * - `auto`: Center if the target fits within the viewport, otherwise align * `start`. */ inline?: 'start' | 'center' | 'end' | 'nearest' | 'auto'; /** * Padding insets from the viewport edges defining the effective area * for both positioning and scaling. * * Accepts a uniform number or per-edge values using the `Edge` type. */ padding?: number | Partial<Edge>; /** * Defines the effective horizontal area used for positioning. * * - `viewport`: Use the full root element (minus padding). Default. * - `blocking`: Use the non-blocked area computed from blocking rects. * This positions the target within the available space without affecting * scaling. Implied automatically when `scale` is `'blocking'`. */ area?: 'viewport' | 'blocking'; }; /** * The animation-relevant state of the artboard at the time the animation frame * was issued. These values might differ to the ones obtained using * artboard.getOffset(), etc. */ type ArtboardLoopContext = { /** * The size of the root element. */ rootSize: Size; /** * The (unscaled) size of the artboard. * * When the artboard instance is initialised, the size of the artboard is null. * When using the dom plugin, the size is set automatically from the artboard DOM * element. * * When not using the dom plugin to render on a canvas, the size is available only * when calling `artboard.setArtboardSize()`. */ artboardSize: Size | null; /** * The current scale. * * During a pinch gesture the scale value can go below minScale or above maxScale. */ scale: number; /** * The current artboard offset. * * During overscrolling the offset values can go outside the defined boundaries. */ offset: Coord; /** * The min/max boundaries for the artboard offset. */ boundaries: Boundaries; /** * The current timestamp for this animation iteration. * * When using the raf() plugin, this is the timestamp provided by the browser to the requestAnimationFrame callback. * When manually calling `artboard.loop()` this will be the same value you pass as the argument to the loop method. */ currentTime: number; }; /** * The current interaction of the artboard. * * `'dragging'` - The artboard is being dragged using a mouse or finger. * `'scaling'` - The artboard is being scaled using a mouse or finger. * `'momentum'` - Momentum scrolling is being applied after a dragging interaction. * `'momentumScaling'` - Momentum scaling is being applied after a scaling interaction. * `'none'` - THe artboard is not being interacted with. */ type Interaction = 'dragging' | 'scaling' | 'momentum' | 'momentumScaling' | 'none'; /** * The artboard instance. */ type Artboard = { /** * Add a plugin. * * Use this method if you conditionally need to add or remove plugins. * * @example * ```typescript * import { createArtboard, mouse } from 'artboard-deluxe' * * const artboard = createArtboard(document.body) * const mousePlugin = mouse() * artboard.addPlugin(mousePlugin) * ``` * * @param plugin - The plugin to add. */ addPlugin<T extends ArtboardPluginDefinition<any, any>>(plugin: T): T extends ArtboardPluginDefinition<infer O, infer R> ? ArtboardPluginInstance<O, R> : never; /** * Removes a previously added plugin. * * @example * ```typescript * import { createArtboard, clickZoom } from 'artboard-deluxe' * * const artboard = createArtboard(document.body) * const plugin = clickZoom() * artboard.addPlugin(plugin) * * function disableClickZoom() { * artboard.removePlugin(plugin) * } * ``` * * @param plugin - The plugin to remove. Must be the same instance that has been added using addPlugin. */ removePlugin(plugin: ArtboardPluginInstance): void; /** * Get the current applied scale of the artboard. * * @returns The current applied scale of the artboard. */ getScale(): number; /** * If there is an animation running, it returns the target scale of the animation. * Else the current applied scale is returned. * * @returns The finale scale of the artboard. */ getFinalScale(): number; /** * Get the current applied offset of the artboard. * * @returns The offset. */ getOffset(): Coord; /** * Get the final offset. If there is currently an animation, the method will return the target offset of the animation. * * @returns The offset. */ getFinalOffset(): Coord; /** * Update all options. * * Note that this will reset option properties back to defaults if they are * missing from the provided options. * * @example * ```typescript * import { createArtboard, type ArtboardOptions } from 'artboard-deluxe' * * function getOptions(): ArtboardOptions { * const isMobile = window.innerWidth < 768 * const minScale = isMobile ? 1 : 0.1 * const maxScale = isMobile ? 5 : 10 * return { * minScale, * maxScale * } * } * * const artboard = createArtboard(document.body, [], getOptions()) * * function updateOptions() { * artboard.setOptions(getOptions()) * } * ``` * * @param options - The full options to update. */ setOptions(options: ArtboardOptions): void; /** * Update a single option. * * @example * Update the minScale option when the viewport changes. * * ```typescript * import { createArtboard } from 'artboard-deluxe' * * function getMinScale() { * const isMobile = window.innerWidth < 768 * return isMobile ? 1 : 0.1 * } * * const artboard = createArtboard(document.body, [], { * minScale: getMinScale(), * }) * * function onViewportChange() { * artboard.setOption('minScale', getMinScale()) * } * ``` * * @param key - The name of the option to set. * @param value - The value of the option to set. */ setOption<T extends keyof ArtboardOptions>(key: T, value: ArtboardOptions[T]): void; /** * Destroys the artboard instance, removes all event listeners, plugins and observers. */ destroy(): void; /** * Starts an animation if the current offset and scale of the artboard is * outside the possible boundaries. */ animateToBoundary(): void; /** * The main animation handler. * * This method should be called from within a requestAnimationFrame callback. * The method updates the internal state, applies momentum scrolling and * animations. * * The method returns a snapshot of the state at the time of the animation * frame. For the best experience you should use these values as the * "source of truth", for example when using a canvas for rendering. * * @example * ```typescript * import { createArtboard, dom } from 'artboard-deluxe' * * const artboard = createArtboard( * document.body, * [ * dom(document.getElementById('artboard'))) * ] * ) * * function loop(timestamp: number) { * artboard.loop(timestamp) * window.requestAnimationFrame(loop) * } * * loop() * ``` * * @param currentTime - The current time. * * @returns The loop context that contains a snapshot of the state that is applied. */ loop(currentTime: number): ArtboardLoopContext; /** * Returns the x offset that perfectly centers the artboard within the * possible bounds. * * If the getBlockingRects option is provided, the method will also take * blocking rects into account, if possible. * * @param targetScale - The target scale for which to calculate the offset. * * @returns The x offset. */ getCenterX(targetScale?: number): number; /** * Animate to the given state. * * If an animation is currently running, it will be overriden. * If momentum scrolling is currently applied, it will be stopped. * * @param key - The name of the animation. * @param x - The target x offset. * @param y - The target y offset. * @param targetScale - The target scale. * @param options - The animation options. */ animateTo(key: string, x: number, y: number, targetScale?: number, options?: AnimationOptions | null): void; /** * Returns the size of the artboard. * * When using "infinite mode" (without any artboard size) this value will be null. * * @returns The artboard size. */ getArtboardSize(): Size | null; /** * Returns the size of the root element. * * @returns The size of the root element. */ getRootSize(): Size; /** * Animate or jump by the given offset. * * If there is an animation running currently and it's last animation frame timestamp is less than 300ms ago, the animation will be stopped and the offset applied immediately. * * @param providedX - How much pixels on the X axis to jump. * @param providedY - How much pixels on the y axis to jump. * @param options - The animation options. */ animateOrJumpBy(providedX?: number | null, providedY?: number | null, options?: AnimationOptions): void; /** * Animate or scroll to the given offset. * * If there is an animation running currently and it's last animation frame timestamp is less than 300ms ago, the animation will be stopped and the offset applied immediately. * * @param providedX - The new offset on the x axis. * @param providedY - The new offset on the y axis. * @param options - The animation options. */ animateOrJumpTo(providedX?: number | null, providedY?: number | null, options?: AnimationOptions): void; /** * Scroll one page up. * * @param options - The animation options. */ scrollPageUp(options?: AnimationOptions): void; /** * Scroll up by one page. * * @param options - The animation options. */ scrollPageUp(options?: AnimationOptions): void; /** * Scroll down by one page. * * @param options - The animation options. */ scrollPageDown(options?: AnimationOptions): void; /** * Scroll left by one page. * * @param options - The animation options. */ scrollPageLeft(options?: AnimationOptions): void; /** * Scroll right by one page. * * @param options - The animation options. */ scrollPageRight(options?: AnimationOptions): void; /** * Scroll up one step. * * @param options - The animation options. */ scrollUp(amount?: number, options?: AnimationOptions): void; /** * Scroll down one step. * * @param options - The animation options. */ scrollDown(amount?: number, options?: AnimationOptions): void; /** * Scroll left one step. * * @param options - The animation options. */ scrollLeft(amount?: number, options?: AnimationOptions): void; /** * Scroll right one step. * * @param options - The animation options. */ scrollRight(amount?: number, options?: AnimationOptions): void; /** * Scroll to the top of the artboard. * * @param options - The animation options. */ scrollToTop(options?: AnimationOptions): void; /** * Scroll to the end of the artboard. * * @param options - The animation options. */ scrollToEnd(options?: AnimationOptions): void; /** * Scale the artboard so it fits within the height of the root element. * * @param options - Animation options. */ scaleToFit(options?: AnimationOptions): void; /** * Reset zoom and center artboard on the x axis. * * @param options - The animation options. */ resetZoom(options?: AnimationOptions): void; /** * Set the scale of the artboard. * * @param newScale - The new scale to set. * @param immediate - If true, the scale is applied immediately. */ setScale(newScale: number, immediate?: boolean): void; /** * Zoom in the artboard by the given amount. * * @param delta - The amount to zoom in. */ zoomIn(delta?: number): void; /** * Zoom out the artboard by the given amount. * * @param delta - The amount to zoom out. */ zoomOut(delta?: number): void; /** * Set the offset. * * @param providedX - The new x offset. * @param providedY - The new y offset. * @param immediate - If set the offset is applied immediately. */ setOffset(providedX?: number | null, providedY?: number | null, immediate?: boolean): void; /** * Cancels the current animation. */ cancelAnimation(): void; /** * Scale the artboard around the given point. * * @param pageX - The x coordinate relative to the page. * @param pageY - The y coordinate relative to the page. * @param targetScale - The target scale. * @param animation - If provided, the scale is animated. */ scaleAroundPoint(pageX: number, pageY: number, targetScale: number, animation?: AnimationOptions | boolean): void; /** * Scales around the given point and returns what the offset should be so that the point remains centered. * * @param pageX - The x coordinate relative to the page. * @param pageY - The y coordinate relative to the page. * @param targetScale - The target scale. */ calculateScaleAroundPoint(pageX: number, pageY: number, targetScale: number, providedOffset?: Coord, providedScale?: number): Coord & { scale: number; }; /** * Scrolls the given rectangle into view. * * The rectangle's coordinates and sizes should be relative to the artboard, * _not_ the result of getBoundingClientRect(). For example, if the artboard * is 1000x1000 big and it contains a 500x500 rectangle that is centered * horizontally with a 50px margin on top, the value for targetRect would be: * { x: 250 // Because (1000 - 500) / 2 = 250, y: 50, width: 500, height: 500, * } * * @param targetRect - The rectangle to scroll into view. The coordinates and size of the rectangle should be uncaled and relative to the artboard. * @param options - Options for the scroll behaviour and animation. */ scrollIntoView(targetRect: Rectangle, options?: ArtboardScrollIntoViewOptions): void; /** * Set the artboard size. * * When using the dom plugin, the artboard size is already set and updated automatically. * Without the plugin (e.g. when using a canvas) it's expected to set the size manually. */ setArtboardSize(width: number, height: number): void; /** * Observe the size of the given element. * * @param element - The element to observe. */ observeSizeChange<T extends HTMLElement = HTMLElement>(element: T, cb: ObserverSizeChangeCallback<T>): ObserverSizeChangeContext; /** * Returns the root element. * * @returns The root element. */ getRootElement(): HTMLElement; /** * Returns the current artboard interaction. * * @returns The current interaction. */ getInteraction(): Interaction; /** * Set the current interaction. * * @param interaction - The new interaction. */ setInteraction(interaction?: Interaction): void; /** * Get the current velocity. * * @returns The velocity. */ getMomentum(): Coord | null; /** * Update the current velocity. * * If an argument is null, the current velocity value for that axis is kept. * * @param x - The velocity on the x axis. * @param y - The velocity on the y axis. */ setMomentum(x: number, y: number, deceleration?: number): void; /** * Stop momentum. */ setMomentum(): void; /** * Get the current touch direction. * * @returns The touch direction. */ getTouchDirection(): Direction; /** * Set the current touch direction. * * @param direction - The new touch direction. Defaults to 'none'. */ setTouchDirection(direction?: Direction): void; /** * The artboard options. */ options: Options; /** * Apply the given momentum. * * @param velocity - The momentum to apply. If undefined, the velocity is reset and no momentum scrolling is applied. */ startMomentum(velocity?: Coord): void; /** * Updates the offset based on the current touchDirection. * * For example, if the current touchDirection is 'vertical', then only the Y offset is updated. * * @param x - The new x offset. * @param y - The new y offset. */ setDirectionOffset(x: number, y: number): void; /** * Scrolls the given element into view. * * Only elements that are either a direct child of the root element or elements that are anchored to the artboard's location can be scrolled into view. * * @param targetEl - The element to scroll into view. * @param options - Options for the scroll behaviour. */ scrollElementIntoView(targetEl: HTMLElement, options?: ArtboardScrollIntoViewOptions): void; /** * Get the current boundaries. * * @param providedTargetScale - Calculate the boundaries if the given scale were applied. * @returns The boundaries. */ getBoundaries(providedTargetScale?: number): Boundaries; /** * Get the current target scale. * * Returns null when there is no target scale. * * @returns The target scale. */ getScaleTarget(): ScaleTarget | null; /** * Set the scale target. * * @param x - The target x offset. * @param y - The target y offset. * @param scale - The target scale. */ setScaleTarget(x: number, y: number, scale: number): void; /** * Get the currently running animation. * * @returns The animation if it exists. */ getAnimation(): ArtboardAnimation | null; /** * Determine whether the interaction before the current was momentum scrolling. * * This is used by plugins such as the `mouse()` plugin to prevent clicking on an element of the artboard if the user was previously momentum scrolling and clicking to stop the animation. * * @returns True if the previous interaction was momentum scrolling. */ wasMomentumScrolling(): boolean; }; /** * The target of the scale interaction. */ type ScaleTarget = Coord & { scale: number; }; /** * The current momentum. */ type Momentum = Coord & { deceleration: number; }; type ArtboardState = { /** * The current arboard offset/translation. */ offset: Coord; /** * The current scale of the artboard. */ scale: number; /** * The target state for the current animation. */ animation: ArtboardAnimation | null; /** * The calculated velocity of a drag gesture. */ momentum: Momentum | null; /** * The timestamp when momentum was stopped. */ momentumStopTimestamp: number; /** * The native size of the artboard (without any scaling). */ artboardSize: Size | null; /** * The current interaction. */ interaction: Interaction; /** * The detected touch direction. */ touchDirection: Direction; /** * The timestamp of the last call to animateTo(). */ lastAnimateToTimestamp: number; /** * The timestamp of the last animation loop. */ lastLoopTimestamp: number; /** * The position of the root element relative to the viewport. */ rootRect: DOMRect; /** * The native size of the root element. */ rootSize: Size; /** * The current scaling velocity. */ scaleVelocity: ScaleTarget | null; }; /** * Create a new artboard instance. */ declare function createArtboard( /** * The root element. * * Must be an element that creates a new stacking context (e.g. `position: relative`) when using the dom() plugin. * When using canvas rendering, this should be the canvas. */ providedRootEl: HTMLElement | HTMLCanvasElement, /** * The plugins to initialise the artboard with. * * Plugins can also be added afterwards using the `artboard.addPlugin()` method. */ initPlugins?: ArtboardPluginDefinition<any, any>[], /** * The init options. * * To update options after the artboard is initialised, use the `artboard.setOption()` and `artboard.setOptions()` methods. */ initOptions?: ArtboardOptions): Artboard; type OnlyWritable<T> = { [P in keyof T as T[P] extends string ? P extends `set${string}` | `get${string}` ? never : P : never]: T[P]; }; type WritableStyleProperty = keyof OnlyWritable<CSSStyleDeclaration>; type CssProperty = `--${string}`; type InlineStyleOverrider = { /** * Sets the given style property value on the element. * * @param property - The style property to set. * @param value - The value to set. If a number, the value is applied as pixels. */ set(property: WritableStyleProperty, value: string | number): void; /** * Sets the given custom property value on the element. * * @param property - The name of the CSS property. * @param value - The value to set. If a number, the value is applied as pixels. */ setProperty(property: CssProperty, value: string | number): void; /** * Sets the transform value. */ setTransform(x: number, y: number, scale?: number, scaleY?: number): void; /** * Applies the provided overrides on the element. */ setMultiple(styles: Partial<Record<WritableStyleProperty, string | number>>): void; /** * Restores the original style values. */ restore(): void; }; /** * Override inline styles on an element and keep track of the original styles. */ declare function inlineStyleOverrider(element: HTMLElement): InlineStyleOverrider; /** * Implements a "click to zoom". * * Note this plugin only handles click events originating from mouse pointers. * For touch devices, use the doubleTapToZoom plugin. * * @example * ```typescript * import { createArtboard, clickZoom } from 'artboard-deluxe' * * const root = document.elementById('root') * const artboard = createArtboard(root, [clickZoom()]) * ``` */ declare const clickZoom: (options?: { animation?: Required<AnimationOptions>; } | undefined) => ArtboardPluginDefinition<{ animation?: Required<AnimationOptions>; }, object>; type Property = '--artboard-offset-x' | '--artboard-offset-y' | '--artboard-scale' | '--artboard-size-width' | '--artboard-size-height' | '--artboard-root-width' | '--artboard-root-height'; /** * Sets the artboard state as CSS custom properties/variables on the given element or root element. */ declare const cssProperties: (options: { /** * The element on which the CSS properties should be set. * Falls back to the root element. */ element?: HTMLElement; /** * How precise the set values should be. * * A value of 1 (default) means that only whole pixels are applied (e.g. 20px). * A value of 0.5 means the values are rounded to the next 0.5 increment (e.g. 20.5px or 21px). * A value of 10 would round to 20px, 30px, 0px, etc. */ precision?: number; /** * Adds unitless property values. * * If true, instead of `--artboard-offset-x: -582px` it will set `--artboard-offset-x: -582`. * Useful if you want to do CSS calculations with purely numeric values. */ unitless?: boolean; /** * Define which CSS properties to set. */ properties: Property[]; /** * Restore original CSS properties on destroy. * * If true, the plugin will restore the CSS properties to their value before the plugin was initialised. */ restoreProperties?: boolean; }) => ArtboardPluginDefinition<{ /** * The element on which the CSS properties should be set. * Falls back to the root element. */ element?: HTMLElement; /** * How precise the set values should be. * * A value of 1 (default) means that only whole pixels are applied (e.g. 20px). * A value of 0.5 means the values are rounded to the next 0.5 increment (e.g. 20.5px or 21px). * A value of 10 would round to 20px, 30px, 0px, etc. */ precision?: number; /** * Adds unitless property values. * * If true, instead of `--artboard-offset-x: -582px` it will set `--artboard-offset-x: -582`. * Useful if you want to do CSS calculations with purely numeric values. */ unitless?: boolean; /** * Define which CSS properties to set. */ properties: Property[]; /** * Restore original CSS properties on destroy. * * If true, the plugin will restore the CSS properties to their value before the plugin was initialised. */ restoreProperties?: boolean; }, object>; declare function defineArtboardPlugin<O extends object, R extends object = object, HasOptions = object extends O ? true : false>(init: ArtboardPluginInit<O, R>): HasOptions extends true ? (options?: O) => ArtboardPluginDefinition<O, R> : (options: O) => ArtboardPluginDefinition<O, R>; /** * The DOM plugin adds support for using a DOM element as the artboard. */ declare const dom: (options: { /** * The artboard element. */ element: HTMLElement; /** * If set, the initial offset and scale is set based on the current position * of the artboard element in the viewport, relative to the root element. * * Use this if you want to determine the initial position of the artboard * using CSS, such as grid, flex or using transform. The plugin will override * any applied transform styles when it's initialised. */ setInitTransformFromRect?: boolean; /** * How precise the translate3d() values should be. * * A value of 1 (default) means the only whole pixels are applied (e.g. 20px). * A value of 0.5 means the values are rounded to the next 0.5 increment (e.g. 20.5px or 21px). * A value of 10 would round to 20px, 30px, 0px, etc. * * Note that internally the offset is kept as a floating point number. The * precision only defines how the number is rounded when setting the transform style. */ precision?: number; /** * Calculate the applied scale so that the resulting scaled element's visible size is rounded to the target precision. */ applyScalePrecision?: boolean; /** * Whether to restore the original styles after destroying the plugin instance. */ restoreStyles?: boolean; }) => ArtboardPluginDefinition<{ /** * The artboard element. */ element: HTMLElement; /** * If set, the initial offset and scale is set based on the current position * of the artboard element in the viewport, relative to the root element. * * Use this if you want to determine the initial position of the artboard * using CSS, such as grid, flex or using transform. The plugin will override * any applied transform styles when it's initialised. */ setInitTransformFromRect?: boolean; /** * How precise the translate3d() values should be. * * A value of 1 (default) means the only whole pixels are applied (e.g. 20px). * A value of 0.5 means the values are rounded to the next 0.5 increment (e.g. 20.5px or 21px). * A value of 10 would round to 20px, 30px, 0px, etc. * * Note that internally the offset is kept as a floating point number. The * precision only defines how the number is rounded when setting the transform style. */ precision?: number; /** * Calculate the applied scale so that the resulting scaled element's visible size is rounded to the target precision. */ applyScalePrecision?: boolean; /** * Whether to restore the original styles after destroying the plugin instance. */ restoreStyles?: boolean; }, object>; /** * Zooms the artboard using a double tap gesture. * * Note that this plugin only handles touch events. For mouse support, use * the clickZoom plugin. */ declare const doubleTapZoom: (options?: { animation?: AnimationOptions; } | undefined) => ArtboardPluginDefinition<{ animation?: AnimationOptions; }, object>; type KeyboardModifier = 'ctrl' | 'meta' | 'alt' | 'ctrlmeta'; type PickMatching<T, V> = { [K in keyof T as T[K] extends V ? K : never]: T[K]; }; type ExtractMethods<T> = PickMatching<T, () => void>; type ArtboardMethods = ExtractMethods<Artboard>; type Keymap = Record<string, [keyof ArtboardMethods, boolean?]>; declare const keyboard: (options?: { /** * The modifier key to check. * * Defaults to 'ctrl'. */ modifier?: KeyboardModifier; /** * Override the default keymap. * * Should be an object whose properties are the keyboard code (according to * KeyboardEvent['code']) and the values is an array where the first item is * the name of the Artboard method to call and the second (optional value) is * whether a modifier key is required. */ keymap?: Keymap; } | undefined) => ArtboardPluginDefinition<{ /** * The modifier key to check. * * Defaults to 'ctrl'. */ modifier?: KeyboardModifier; /** * Override the default keymap. * * Should be an object whose properties are the keyboard code (according to * KeyboardEvent['code']) and the values is an array where the first item is * the name of the Artboard method to call and the second (optional value) is * whether a modifier key is required. */ keymap?: Keymap; }, object>; /** * Options for the velocity queue used to determine the velocity for momentum * scrolling. */ type VelocityQueueOptions = { /** * The time span to look at for calculating the velocity in milliseconds. * * A value of 400 means only positions registered in the last 400ms will * determine the velocity. */ maxTimeWindow: number; /** * The minimum velocity. */ minVelocity: number; /** * The maximum velocity to calculate before applying the multiplicator. */ maxVelocity: number; /** * The multiplicator to apply to the final velocity. */ multiplicator: number; }; declare const mouse: (options?: { /** * Whether to set the cursor on the root element to indicate when dragging. * * Note by default this is disabled because changing the cursor can trigger style recalculation, see https://gist.github.com/paulirish/5d52fb081b3570c81e3a/565c05680b27c9cfd9f5e971d295cd558c3e1843. */ setCursor?: boolean; /** * Only allow dragging while holding the spacebar. */ useSpacebar?: boolean; /** * Options for the velocity queue. */ velocity?: Partial<VelocityQueueOptions>; scrollDirectionThreshold?: number; } | undefined) => ArtboardPluginDefinition<{ /** * Whether to set the cursor on the root element to indicate when dragging. * * Note by default this is disabled because changing the cursor can trigger style recalculation, see https://gist.github.com/paulirish/5d52fb081b3570c81e3a/565c05680b27c9cfd9f5e971d295cd558c3e1843. */ setCursor?: boolean; /** * Only allow dragging while holding the spacebar. */ useSpacebar?: boolean; /** * Options for the velocity queue. */ velocity?: Partial<VelocityQueueOptions>; scrollDirectionThreshold?: number; }, object>; type OverviewOptions = { element: HTMLElement; /** The element or selector for the artboard element in the overview. */ artboardElement?: HTMLElement | string; /** The element or selector for the visible area element in the overview. */ visibleAreaElement?: HTMLElement | string; /** The padding to apply inside the overview element, in pixels. */ padding?: number; /** * Whether to restore the original styles after destroying the plugin instance. */ restoreStyles?: boolean; /** * If enabled the height of the overview element is adjusted automatically * to the size of the artboard. * * The element must have a width. The height is calculated based on the * aspect ratio of the artboard. */ autoHeight?: boolean; /** * The maximum height for the overview element when autoHeight is enabled. * * If the calculated height exceeds this value, the height will be capped * and the artboard will be scaled to fit within the constrained dimensions. * * This is useful for preventing the overview from exceeding the viewport height. */ maxHeight?: number; }; declare const overview: (options: OverviewOptions) => ArtboardPluginDefinition<OverviewOptions, object>; /** * Registers a requestAnimationFrame callback for the artboard. */ declare const raf: (options?: { /** * Cap the frame rate to the given value (e.g. 30, 60, 120). * * When set, artboard.loop() is only called when the elapsed time since the * last frame exceeds the target interval. Useful for debugging frame-rate * dependent behavior. * * When not set, artboard.loop() is called on every animation frame. */ fps?: number; } | undefined) => ArtboardPluginDefinition<{ /** * Cap the frame rate to the given value (e.g. 30, 60, 120). * * When set, artboard.loop() is only called when the elapsed time since the * last frame exceeds the target interval. Useful for debugging frame-rate * dependent behavior. * * When not set, artboard.loop() is called on every animation frame. */ fps?: number; }, object>; type ScrollbarOrientation = 'x' | 'y'; declare const scrollbar: (options: { /** The element representing the scrollbar. */ element: HTMLElement; /** The element or selector representing the scrollbar thumb. */ thumbElement?: string | HTMLElement; /** The orientation. */ orientation: ScrollbarOrientation; /** The minimum size of the thumb. */ minThumbSize?: number; /** * Whether to restore the original styles after destroying the plugin instance. */ restoreStyles?: boolean; }) => ArtboardPluginDefinition<{ /** The element representing the scrollbar. */ element: HTMLElement; /** The element or selector representing the scrollbar thumb. */ thumbElement?: string | HTMLElement; /** The orientation. */ orientation: ScrollbarOrientation; /** The minimum size of the thumb. */ minThumbSize?: number; /** * Whether to restore the original styles after destroying the plugin instance. */ restoreStyles?: boolean; }, object>; declare const touch: (options?: { /** * Whether to require two touch points to interact with the artboard. * * The default is false, which will scroll the artboard using a single touch * point. Set this to true to require two touch points, which will scale and * scroll the artboard at the same time. Useful if you have some sort of * draw