UNPKG

@dvcol/neo-svelte

Version:

Neomorphic ui library for svelte 5

215 lines (214 loc) 6.26 kB
import type { HTMLAttributes } from 'svelte/elements'; import type { NeoHandlePlacements, NeoHandleProps } from '../common/neo-handle.model.js'; import type { NeoDialogPlacement } from '../common/neo-placement.model.js'; export interface NeoMovableSnapTranslate { /** * Translate duration (in ms). * * @default 600 */ duration?: number; /** * Easing function. * * @default 'var(--neo-easing-spring, ease-in-out)' */ easing?: string; } export interface NeoMovableSnap { /** * Whether the movable should snap to the viewport edges & center. */ enabled?: boolean; /** * Whether the element should only snap to the corners of the viewport. */ corner?: boolean; /** * Whether snapping to a corner should change the element placement. */ placement?: boolean; /** * Whether the element can be snapped outside the viewport (with handles peeking in). * * @default true */ outside?: boolean; /** * How much of the element should be visible when snapped outside the viewport. * * @default 25 */ offset?: number; /** * Translate css to apply when snapping to a position */ translate?: NeoMovableSnapTranslate; } export type NeoMovableHandle = Pick<NeoHandleProps, 'visible' | 'handle' | 'position' | 'minSize'> & { /** * Whether the whole element should act as a handle. */ full?: boolean; }; export interface NeoMovableLimit { min?: number; max?: number; } export interface NeoMovableLimits { x?: NeoMovableLimit; y?: NeoMovableLimit; } export interface NeoMovableThreshold { x?: number; y?: number; top?: number; right?: number; bottom?: number; left?: number; outside?: boolean; } export type NeoMovable<Parsed extends boolean = false> = Pick<NeoHandleProps, 'enabled' | 'placement' | 'axis' | 'outside'> & { /** * The step size for dragging the element with arrow keys. * * @default 4 */ step?: number; /** * The margin around the element when snapping to the viewport edges. * * @default 16px */ margin?: number; /** * Whether the element should be contained within to the viewport edges. */ contain?: boolean; /** * Boundaries for the element movement. */ limits?: NeoMovableLimits; /** * Whether the element's offset should be reset when it is closed. * * @default true */ resetOnClose?: boolean; /** * The threshold offset over which the element should be closed. * * If falsy, the element will not be closed no matter how far it is dragged. * * All thresholds are absolute values. * * @default 0 */ closeThreshold?: number | NeoMovableThreshold; /** * Whether to show a handle for dragging the element. * If 'true', the handle will be visible whenever most appropriate. * * @default true */ handle?: Parsed extends true ? NeoMovableHandle : boolean | NeoMovableHandle; /** * Whether the element should snap to the viewport edges. * If 'corner', the element will snap to the closest corner. * * @default false */ snap?: Parsed extends true ? NeoMovableSnap : boolean | 'corner' | NeoMovableSnap; }; export interface NeoMoved { x: number; y: number; } export type NeoMovableOutside = false | NeoHandlePlacements; export type NeoMovableHandlers<Element extends HTMLElement> = Pick<HTMLAttributes<Element>, 'onpointerdown' | 'onkeydown' | 'onkeyup' | 'onblur'>; export interface NeoMovableUseOptions<Element extends HTMLElement, Handle extends HTMLElement> { /** * The element's offset from its original position if any (applied transform). */ offset: NeoMoved; /** * Whether the element is outside the viewport, and in which direction. */ outside: NeoMovableOutside; /** * The element original placement. */ placement: NeoDialogPlacement; /** * Movable options. */ movable?: Partial<NeoMovable>; /** * Reference to the element to move. */ element?: Element; /** * Callback to close the element. */ close?: () => unknown | Promise<unknown>; /** * Event handlers to attach to the handle. */ handlers?: Partial<NeoMovableHandlers<Handle>>; } export interface NeoMovableOffsetOptions { contain?: boolean; outside?: NeoMovableOutside; limits?: NeoMovableLimits; } export type NeoMovableResetOptions = NeoMovableOffsetOptions & { x?: number; y?: number; translate?: boolean | NeoMovableSnapTranslate; }; export interface NeoMovableUseResult<Element extends HTMLElement, Handle extends HTMLElement> { /** * The element's offset from its original position if any (applied transform). */ offset: NeoMoved; /** * Whether the element is outside the viewport, and in which direction. */ outside: NeoMovableOutside; /** * The element original placement. */ placement: NeoDialogPlacement; /** * Original movable options. */ movable: NeoMovable; /** * Reference to the element to move. */ element?: Element; /** * The css translate value to apply to the element. */ translate: CSSStyleDeclaration['translate']; /** * If the element is currently being translated programmatically (snap or arrow keys). */ translating: number; /** * If the element is currently being moved by the user (drag). */ moving: boolean; /** * Event handlers to attach to the handle. */ handlers: NeoMovableHandlers<Handle>; /** * Reset the element's offset to its original position. */ reset: (options?: NeoMovableResetOptions) => Promise<boolean>; } export declare const defaultSnap: Required<NeoMovableSnap>; export declare const defaultHandle: NeoMovableHandle; export declare const defaultMovable: NeoMovable; export declare function useMovable<Element extends HTMLElement, Handle extends HTMLElement>(options: NeoMovableUseOptions<Element, Handle>): NeoMovableUseResult<Element, Handle>;