vue3-flashcards
Version:
Tinder-like flashcards component with dragging and flipping
442 lines (405 loc) • 15.4 kB
TypeScript
import { AllowedComponentProps } from 'vue';
import { App } from 'vue';
import { ComponentCustomProps } from 'vue';
import { ComponentOptionsMixin } from 'vue';
import { ComponentProvideOptions } from 'vue';
import { ComputedRef } from 'vue';
import { DefineComponent } from 'vue';
import { InjectionKey } from 'vue';
import { PublicProps } from 'vue';
import { ShallowUnwrapRef } from 'vue';
import { VNode } from 'vue';
import { VNodeProps } from 'vue';
declare const __VLS_component: DefineComponent<FlipCardProps, {
flip: typeof flip;
}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
flip: (isFlipped: boolean) => any;
}, string, PublicProps, Readonly<FlipCardProps> & Readonly<{
onFlip?: ((isFlipped: boolean) => any) | undefined;
}>, {
waitAnimationEnd: boolean;
disabled: boolean;
flipAxis: "x" | "y";
}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
declare type __VLS_PrettifyLocal<T> = {
[K in keyof T]: T[K];
} & {};
declare function __VLS_template(): {
attrs: Partial<{}>;
slots: Readonly<{
front: (props: {
flip: () => void;
}) => any;
back?: (props: {
flip: () => void;
}) => any;
}> & {
front: (props: {
flip: () => void;
}) => any;
back?: (props: {
flip: () => void;
}) => any;
};
refs: {};
rootEl: HTMLDivElement;
};
declare type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
declare type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
$slots: S;
};
};
export declare interface A11yAnnounceEvent {
type: A11yAnnounceEventType;
/** For a swipe, the direction / skip action that occurred. */
action?: SwipeAction;
/** Cards left in the deck after this event. */
remaining: number;
/** Resolved labels (already merged with user overrides). */
labels: A11yLabels;
}
/** The kind of event being announced to assistive technology. */
export declare type A11yAnnounceEventType = 'swipe' | 'restore' | 'empty';
/**
* Accessibility defaults. The `a11y` prop is on by default — these are the
* fallbacks used when it's omitted or only partially specified. Labels are the
* English defaults; pass an `a11y.labels` object to localize them.
*
* `announce` receives the deck event and the labels and returns the string read
* out by the live region (or `null`/`''` to stay silent for that event).
*/
declare const a11yDefaults: {
readonly enabled: true;
readonly keyboard: true;
readonly confirmOnKey: false;
readonly manageFocus: true;
readonly liveMode: "polite" | "assertive";
readonly labels: {
readonly deck: "Card deck";
readonly card: "Card";
readonly top: "up";
readonly left: "left";
readonly right: "right";
readonly bottom: "down";
readonly skip: "skipped";
readonly restore: "restored";
readonly empty: "No more cards";
readonly instructions: "Use arrow keys to swipe the card, Enter to confirm.";
};
};
declare type A11yLabels = typeof a11yDefaults.labels;
/**
* Public, user-facing accessibility options (the grouped `a11y` prop).
*
* Accessibility is ON by default — every field here is optional and falls back
* to {@link a11yDefaults}. Pass `a11y: false` (or `{ enabled: false }`) to opt
* out of all built-in a11y wiring and supply your own.
*/
export declare interface A11yOptions {
/** Master switch. `false` disables roles, live region, keyboard and focus. */
enabled?: boolean;
/** Arrow / Enter / Space / restore keyboard navigation. Default `true`. */
keyboard?: boolean;
/**
* Two-step keyboard swipe: an arrow key peeks the card to its full pre-swipe
* pose and waits for Enter/Space to confirm (Escape cancels). Default `false`
* — arrow keys swipe immediately.
*/
confirmOnKey?: boolean;
/** Move focus to the next card after a keyboard swipe. Default `true`. */
manageFocus?: boolean;
/** aria-live politeness of the announcement region. Default `'polite'`. */
liveMode?: 'polite' | 'assertive';
/** Override any of the built-in English labels for localization. */
labels?: Partial<A11yLabels>;
/**
* Build the live-region announcement for a deck event. Return `null`/`''` to
* stay silent. Defaults to e.g. `"Card swiped right, 4 remaining"`.
*/
announce?: (event: A11yAnnounceEvent) => string | null;
}
/** The `a11y` prop accepts the options object, or a plain boolean shorthand. */
export declare type A11yProp = A11yOptions | boolean;
/**
* Context handed to an `animationKeyframes` callback. Everything the callback
* needs to build a fly-out keyframe set is here — no DOM access, no component
* internals.
*
* Note there is NO release-point and NO `isRestoring` here, on purpose:
* - Starting a manual swipe from where the finger let go is the LIBRARY's job
* (FlashCard prepends the release frame), not the callback's.
* - The restore animation is the swipe REVERSED, also built by the library. The
* callback describes ONE thing: how the card flies OUT, from center.
*/
export declare interface AnimationContext {
/** The action that produced this flight: 'left' | 'right' | 'top' | 'bottom' | 'skip'. */
type: SwipeAction;
/** Directions enabled on the card. */
direction: Direction[];
/** Max rotation (deg) configured on the card. */
maxRotation: number;
}
/**
* Signature of the user-overridable animation prop. Describes how the card flies
* OUT (from center) — either the single off-screen end frame, or a list of
* frames for a multi-step exit. That's all the user writes:
*
* (ctx) => ({ transform: `translateX(320px)`, opacity: 0 })
*
* The library derives the rest:
* - swipe-out: starts the card at the drag-release point (or center) → your frames.
* - restore: plays your frames in REVERSE, ending at center.
*/
export declare type AnimationKeyframes = (ctx: AnimationContext) => Keyframe | Keyframe[];
/**
* Default fly-out generator — a WAAPI port of the CSS keyframes it replaces.
* Returns just the off-screen end frame; the library handles the start (release
* point) and the restore (this, reversed).
*/
export declare const defaultAnimationKeyframes: AnimationKeyframes;
declare type Direction = 'top' | 'left' | 'right' | 'bottom';
declare interface DragPosition {
x: number;
y: number;
delta: number;
type?: SwipeAction | null;
}
declare interface DragSetupParams {
swipeThreshold?: number;
dragThreshold?: number;
maxDragY?: number | null;
maxDragX?: number | null;
direction?: Direction[];
disableDrag?: boolean;
initialPosition?: DragPosition;
resistance?: ResistanceOptions | null;
velocity?: VelocityOptions | null;
}
declare interface FlashCardProps extends DragSetupParams {
disableDrag?: boolean;
maxRotation?: number;
transformStyle?: (position: DragPosition) => string;
flight?: {
type: SwipeAction;
isRestoring: boolean;
initialPosition?: DragPosition;
};
animation?: {
keyframes?: AnimationKeyframes;
duration?: number;
easing?: string;
};
}
export declare const FlashCards: <T extends Record<string, unknown>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{
readonly onSkip?: ((item: T) => any) | undefined;
readonly onDragend?: ((item: T) => any) | undefined;
readonly onDragstart?: ((item: T) => any) | undefined;
readonly onDragmove?: ((item: T, type: SwipeAction | null, delta: number) => any) | undefined;
readonly onRestore?: ((item: T) => any) | undefined;
readonly onLoop?: (() => any) | undefined;
readonly onSwipeTop?: ((item: T) => any) | undefined;
readonly onSwipeLeft?: ((item: T) => any) | undefined;
readonly onSwipeRight?: ((item: T) => any) | undefined;
readonly onSwipeBottom?: ((item: T) => any) | undefined;
} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>, "onDragend" | "onDragstart" | "onDragmove" | "onLoop" | "onSkip" | "onRestore" | "onSwipeTop" | "onSwipeLeft" | "onSwipeRight" | "onSwipeBottom"> & FlashCardsProps<T> & Partial<{}>> & PublicProps;
expose(exposed: ShallowUnwrapRef< {
swipe: (direction: Direction) => void;
swipeTop: () => void;
swipeLeft: () => void;
swipeRight: () => void;
swipeBottom: () => void;
skip: () => void;
restore: () => T | undefined;
reset: (resetOptions?: ResetOptions) => Promise<void>;
peek: (percent: number, direction: Direction) => void;
canRestore: ComputedRef<boolean>;
isEnd: ComputedRef<boolean>;
isStart: ComputedRef<boolean>;
}>): void;
attrs: any;
slots: Readonly<{
default: (props: {
item: T;
activeItemKey: string | number;
}) => any;
top?: (props: {
item: T;
delta: number;
}) => any;
left?: (props: {
item: T;
delta: number;
}) => any;
right?: (props: {
item: T;
delta: number;
}) => any;
bottom?: (props: {
item: T;
delta: number;
}) => any;
empty?: (props: {
reset: (options?: ResetOptions) => void;
}) => any;
actions?: (props: {
restore: () => void;
skip: () => void;
reset: (options?: ResetOptions) => void;
swipeTop: () => void;
swipeLeft: () => void;
swipeRight: () => void;
swipeBottom: () => void;
isEnd: boolean;
isStart: boolean;
canRestore: boolean;
}) => any;
}> & {
default: (props: {
item: T;
activeItemKey: string | number;
}) => any;
top?: (props: {
item: T;
delta: number;
}) => any;
left?: (props: {
item: T;
delta: number;
}) => any;
right?: (props: {
item: T;
delta: number;
}) => any;
bottom?: (props: {
item: T;
delta: number;
}) => any;
empty?: (props: {
reset: (options?: ResetOptions) => void;
}) => any;
actions?: (props: {
restore: () => void;
skip: () => void;
reset: (options?: ResetOptions) => void;
swipeTop: () => void;
swipeLeft: () => void;
swipeRight: () => void;
swipeBottom: () => void;
isEnd: boolean;
isStart: boolean;
canRestore: boolean;
}) => any;
};
emit: ((evt: "skip", item: T) => void) & ((evt: "dragend", item: T) => void) & ((evt: "dragstart", item: T) => void) & ((evt: "dragmove", item: T, type: SwipeAction | null, delta: number) => void) & ((evt: "restore", item: T) => void) & ((evt: "loop") => void) & ((evt: "swipeTop", item: T) => void) & ((evt: "swipeLeft", item: T) => void) & ((evt: "swipeRight", item: T) => void) & ((evt: "swipeBottom", item: T) => void);
}>) => VNode & {
__ctx?: Awaited<typeof __VLS_setup>;
};
/**
* Typed injection keys for configs
*/
export declare const FlashCardsConfigKey: InjectionKey<FlashCardsProps<Record<string, unknown>>>;
export declare function FlashCardsPlugin(app: App, options?: FlashCardsPluginOptions): void;
export declare interface FlashCardsPluginOptions<T = any> {
flashCards?: FlashCardsProps<T>;
flipCard?: FlipCardProps;
registerComponents?: boolean;
}
declare interface FlashCardsProps<Item> extends Omit<FlashCardProps, 'direction'> {
/**
* Array of items to display as cards
*/
items?: Item[];
/**
* Direction of swiping: horizontal (left/right), vertical (up/down),
* or array of specific directions for custom combinations
*/
swipeDirection?: Direction[] | 'horizontal' | 'vertical';
/**
* Enable loop swiping mode
*/
loop?: boolean;
/**
* Number of cards to render in dom, cant be less than 1. If stack is greater it will override this value
*/
renderLimit?: number;
/**
* Number of cards to stack
*/
stack?: number;
/**
* Offset for stack
*/
stackOffset?: number;
/**
* Scale factor for stack
*/
stackScale?: number;
/**
* Direction for stack
*/
stackDirection?: StackDirection;
/**
* Key to track items by — a field on your item holding a stable, unique value.
* Required if you are going to modify the `items` array at runtime or use
* `loop`. Defaults to `'id'` at runtime; if your items use a differently named
* key, set this (e.g. `itemKey="uuid"`). When omitted and there's no `id`
* field, cards fall back to array-index tracking — a dev-only warning fires.
*/
itemKey?: keyof Item;
/**
* Wait for animation to end before performing next action
*/
waitAnimationEnd?: boolean;
/**
* Accessibility options. ON by default — keyboard navigation, ARIA roles, a
* live-region announcer and focus management all work out of the box. Pass an
* object to tune labels / behavior, or `false` to opt out entirely and supply
* your own a11y. See `A11yOptions`.
*/
a11y?: A11yProp;
}
/**
* Flips card
*/
declare function flip(): void;
export declare const FlipCard: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
export declare interface FlipCardConfig {
disabled?: boolean;
waitAnimationEnd?: boolean;
flipAxis?: 'x' | 'y';
}
export declare const FlipCardConfigKey: InjectionKey<FlipCardProps>;
declare interface FlipCardProps {
disabled?: boolean;
waitAnimationEnd?: boolean;
flipAxis?: 'x' | 'y';
}
declare interface ResetOptions {
animate?: boolean;
delay?: number;
}
declare interface ResistanceOptions {
threshold?: number;
strength?: number;
}
declare const StackDirection: {
readonly TOP: "top";
readonly BOTTOM: "bottom";
readonly LEFT: "left";
readonly RIGHT: "right";
};
declare type StackDirection = typeof StackDirection[keyof typeof StackDirection];
declare const SwipeAction: {
readonly TOP: "top";
readonly LEFT: "left";
readonly RIGHT: "right";
readonly BOTTOM: "bottom";
readonly SKIP: "skip";
};
declare type SwipeAction = typeof SwipeAction[keyof typeof SwipeAction];
declare interface VelocityOptions {
threshold?: number;
}
export { }