mirror of
https://github.com/nunocoracao/blowfish.git
synced 2026-01-30 16:31:52 +01:00
config redirect
This commit is contained in:
0
node_modules/typeit/dist/Cursor.d.ts
generated
vendored
Normal file
0
node_modules/typeit/dist/Cursor.d.ts
generated
vendored
Normal file
13
node_modules/typeit/dist/Queue.d.ts
generated
vendored
Normal file
13
node_modules/typeit/dist/Queue.d.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { QueueItem } from "./types";
|
||||
declare let Queue: (initialItems: QueueItem[]) => {
|
||||
add: (steps: QueueItem[] | QueueItem) => typeof Queue;
|
||||
set: (index: number, item: QueueItem) => void;
|
||||
wipe: () => void;
|
||||
reset: () => void;
|
||||
destroy: (key: Symbol) => boolean;
|
||||
done: (key: Symbol, shouldDestroy?: boolean) => boolean;
|
||||
getItems: (all?: boolean) => QueueItem[];
|
||||
getQueue: () => Map<any, any>;
|
||||
getTypeable: () => QueueItem[];
|
||||
};
|
||||
export default Queue;
|
||||
15
node_modules/typeit/dist/constants.d.ts
generated
vendored
Normal file
15
node_modules/typeit/dist/constants.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { CursorOptions, Options } from "./types";
|
||||
export declare const DATA_ATTRIBUTE = "data-typeit-id";
|
||||
export declare const CURSOR_CLASS = "ti-cursor";
|
||||
export declare const START = "START";
|
||||
export declare const END = "END";
|
||||
export declare const DEFAULT_STATUSES: {
|
||||
started: boolean;
|
||||
completed: boolean;
|
||||
frozen: boolean;
|
||||
destroyed: boolean;
|
||||
};
|
||||
export declare const DEFAULT_OPTIONS: Options & {
|
||||
cursor: Required<CursorOptions>;
|
||||
};
|
||||
export declare const PLACEHOLDER_CSS: string;
|
||||
2
node_modules/typeit/dist/helpers/appendStyleBlock.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/appendStyleBlock.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (styles: string, id?: string) => void;
|
||||
export default _default;
|
||||
5
node_modules/typeit/dist/helpers/asArray.d.ts
generated
vendored
Normal file
5
node_modules/typeit/dist/helpers/asArray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Converts value as within array, unless the value itself already is one.
|
||||
*/
|
||||
declare const _default: <T>(value: any) => T[];
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/beforePaint.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/beforePaint.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare let beforePaint: (cb: any) => Promise<any>;
|
||||
export default beforePaint;
|
||||
9
node_modules/typeit/dist/helpers/calculateDelay.d.ts
generated
vendored
Normal file
9
node_modules/typeit/dist/helpers/calculateDelay.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Given a delay value, form it into the type of object
|
||||
* that will be used by Instance().
|
||||
*
|
||||
* @param {integer | array}
|
||||
* @return {array}
|
||||
*/
|
||||
declare const _default: (delayArg: number | number[]) => number[];
|
||||
export default _default;
|
||||
5
node_modules/typeit/dist/helpers/calculatePace.d.ts
generated
vendored
Normal file
5
node_modules/typeit/dist/helpers/calculatePace.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Options } from "../types";
|
||||
/**
|
||||
* [typePace, deletePace]
|
||||
*/
|
||||
export default function (options: Options): number[];
|
||||
16
node_modules/typeit/dist/helpers/chunkStrings.d.ts
generated
vendored
Normal file
16
node_modules/typeit/dist/helpers/chunkStrings.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { El } from "../types";
|
||||
export declare function walkElementNodes(element: El | Node, shouldReverse?: boolean, shouldIncludeCursor?: boolean): El[];
|
||||
/**
|
||||
* Convert string to array of chunks that will be later
|
||||
* used to construct a TypeIt queue.
|
||||
*/
|
||||
export declare function chunkStringAsHtml(string: string): El[];
|
||||
/**
|
||||
* Given a string, chunk it into array items to be later
|
||||
* converted to queue items for typing.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {boolean} asHtml
|
||||
* @return {array}
|
||||
*/
|
||||
export declare function maybeChunkStringAsHtml(str: string, asHtml?: boolean): Partial<El>[];
|
||||
9
node_modules/typeit/dist/helpers/countStepsToSelector.d.ts
generated
vendored
Normal file
9
node_modules/typeit/dist/helpers/countStepsToSelector.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { QueueItem, Sides } from "../types";
|
||||
interface countStepsToSelectorArgs {
|
||||
queueItems: QueueItem[];
|
||||
selector: string | number;
|
||||
cursorPosition: number;
|
||||
to: Sides;
|
||||
}
|
||||
declare const countStepsToSelector: ({ queueItems, selector, cursorPosition, to, }: countStepsToSelectorArgs) => number;
|
||||
export default countStepsToSelector;
|
||||
3
node_modules/typeit/dist/helpers/createElement.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/createElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
declare const _default: (el: any) => El;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/createTextNode.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/createTextNode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (content: string) => Text;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/destroyTimeouts.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/destroyTimeouts.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (timeouts: number[]) => [];
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/duplicate.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/duplicate.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: <T>(value: T, times: number) => T[];
|
||||
export default _default;
|
||||
3
node_modules/typeit/dist/helpers/expandTextNodes.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/expandTextNodes.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
declare let expandTextNodes: (element: El) => El;
|
||||
export default expandTextNodes;
|
||||
10
node_modules/typeit/dist/helpers/fireItem.d.ts
generated
vendored
Normal file
10
node_modules/typeit/dist/helpers/fireItem.d.ts
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import { CursorOptions, El, QueueMapPair } from "../types";
|
||||
interface FireItemArgs {
|
||||
index: number;
|
||||
queueItems: QueueMapPair[];
|
||||
wait: (...args: any) => Promise<void>;
|
||||
cursor: El | undefined;
|
||||
cursorOptions: CursorOptions;
|
||||
}
|
||||
declare let fireItem: ({ index, queueItems, wait, cursor, cursorOptions, }: FireItemArgs) => Promise<number>;
|
||||
export default fireItem;
|
||||
2
node_modules/typeit/dist/helpers/fireWhenVisible.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/fireWhenVisible.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (element: HTMLElement, func: Function) => void;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/generateHash.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/generateHash.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: () => string;
|
||||
export default _default;
|
||||
7
node_modules/typeit/dist/helpers/getAllChars.d.ts
generated
vendored
Normal file
7
node_modules/typeit/dist/helpers/getAllChars.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { El } from "../types";
|
||||
/**
|
||||
* Get a flattened array of text nodes that have been typed.
|
||||
* This excludes any cursor character that might exist.
|
||||
*/
|
||||
declare let getAllChars: (element: El) => any[];
|
||||
export default getAllChars;
|
||||
3
node_modules/typeit/dist/helpers/getAnimationFromElement.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/getAnimationFromElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
declare let getAnimationFromElement: (element: El) => Animation | undefined;
|
||||
export default getAnimationFromElement;
|
||||
2
node_modules/typeit/dist/helpers/getComputedStyle.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/getComputedStyle.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (el: any) => CSSStyleDeclaration;
|
||||
export default _default;
|
||||
7
node_modules/typeit/dist/helpers/getParsedBody.d.ts
generated
vendored
Normal file
7
node_modules/typeit/dist/helpers/getParsedBody.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { El } from "../types";
|
||||
/**
|
||||
* Parse a string as HTML and return the body
|
||||
* of the parsed document, with all text nodes expanded.
|
||||
*/
|
||||
declare const _default: (content: any) => El;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/handleFunctionalArg.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/handleFunctionalArg.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare let handleFunctionalArg: <T>(arg: any) => T;
|
||||
export default handleFunctionalArg;
|
||||
6
node_modules/typeit/dist/helpers/insertIntoElement.d.ts
generated
vendored
Normal file
6
node_modules/typeit/dist/helpers/insertIntoElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { El } from "../types";
|
||||
/**
|
||||
* Inserts a set of content into the element. Intended for SINGLE characters.
|
||||
*/
|
||||
declare let insertIntoElement: (originalTarget: El, character: El) => void;
|
||||
export default insertIntoElement;
|
||||
2
node_modules/typeit/dist/helpers/isArray.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/isArray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (thing: any) => boolean;
|
||||
export default _default;
|
||||
3
node_modules/typeit/dist/helpers/isBodyElement.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/isBodyElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
declare let isBodyElement: (node: El) => boolean;
|
||||
export default isBodyElement;
|
||||
2
node_modules/typeit/dist/helpers/isInput.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/isInput.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (el: HTMLElement) => boolean;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/isNonVoidElement.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/isNonVoidElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (el: any) => boolean;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/isNumber.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/isNumber.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (value: any) => boolean;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/merge.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/merge.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (originalObj: any, newObj: any) => any;
|
||||
export default _default;
|
||||
3
node_modules/typeit/dist/helpers/processCursorOptions.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/processCursorOptions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { CursorOptions } from "../types";
|
||||
declare let processCursorOptions: (cursorOptions: boolean | CursorOptions) => boolean | CursorOptions;
|
||||
export default processCursorOptions;
|
||||
2
node_modules/typeit/dist/helpers/randomInRange.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/randomInRange.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (value: number, range: number) => number;
|
||||
export default _default;
|
||||
8
node_modules/typeit/dist/helpers/rebuildCursorAnimation.d.ts
generated
vendored
Normal file
8
node_modules/typeit/dist/helpers/rebuildCursorAnimation.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { El, CursorOptions } from "../types";
|
||||
interface rebuildCursorAnimationArgs {
|
||||
cursor: El | undefined;
|
||||
cursorOptions: CursorOptions;
|
||||
options: any;
|
||||
}
|
||||
declare let rebuildCursorAnimation: ({ cursor, options, cursorOptions, }: rebuildCursorAnimationArgs) => Animation;
|
||||
export default rebuildCursorAnimation;
|
||||
3
node_modules/typeit/dist/helpers/removeNode.d.ts
generated
vendored
Normal file
3
node_modules/typeit/dist/helpers/removeNode.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
declare const _default: (node: Node, rootElement: El) => void;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/repositionCursor.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/repositionCursor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (element: HTMLElement, allChars: any[], newCursorPosition: number) => void;
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/select.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/select.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare let select: (selector: string, element?: Node, all?: boolean) => Node | NodeList | null;
|
||||
export default select;
|
||||
2
node_modules/typeit/dist/helpers/selectorToElement.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/selectorToElement.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { El } from "../types";
|
||||
export default function (thing: string | El): El;
|
||||
11
node_modules/typeit/dist/helpers/setCursorAnimation.d.ts
generated
vendored
Normal file
11
node_modules/typeit/dist/helpers/setCursorAnimation.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/// <reference types="web-animations-js" />
|
||||
import { El } from "../types";
|
||||
/**
|
||||
* Create and return an animation for the cursor.
|
||||
*/
|
||||
declare let setCursorAnimation: ({ cursor, frames, options, }: {
|
||||
cursor: El;
|
||||
frames: AnimationKeyFrame[];
|
||||
options: Partial<AnimationEffectTiming>;
|
||||
}) => Animation;
|
||||
export default setCursorAnimation;
|
||||
11
node_modules/typeit/dist/helpers/setCursorStyles.d.ts
generated
vendored
Normal file
11
node_modules/typeit/dist/helpers/setCursorStyles.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { El } from "../types";
|
||||
export declare let cursorFontStyles: {
|
||||
readonly "font-family": "";
|
||||
readonly "font-weight": "";
|
||||
readonly "font-size": "";
|
||||
readonly "font-style": "";
|
||||
readonly "line-height": "";
|
||||
readonly color: "";
|
||||
readonly transform: "translateX(-.125em)";
|
||||
};
|
||||
export declare let setCursorStyles: (id: string, element: El) => void;
|
||||
9
node_modules/typeit/dist/helpers/toArray.d.ts
generated
vendored
Normal file
9
node_modules/typeit/dist/helpers/toArray.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Literally just wraps toArray() to save a few bytes
|
||||
* when it's repeatedly used.
|
||||
*
|
||||
* @param {any}
|
||||
* @return {array}
|
||||
*/
|
||||
declare const _default: (val: any) => any[];
|
||||
export default _default;
|
||||
2
node_modules/typeit/dist/helpers/updateCursorPosition.d.ts
generated
vendored
Normal file
2
node_modules/typeit/dist/helpers/updateCursorPosition.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare let updateCursorPosition: (steps: number, cursorPosition: number, printedCharacters: Element[]) => number;
|
||||
export default updateCursorPosition;
|
||||
5
node_modules/typeit/dist/helpers/wait.d.ts
generated
vendored
Normal file
5
node_modules/typeit/dist/helpers/wait.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Fire a callback after a delay, and add the timeout ID to a referenced array.
|
||||
*/
|
||||
declare let wait: (callback: Function, delay: number | undefined, timeouts: number[]) => Promise<void>;
|
||||
export default wait;
|
||||
4
node_modules/typeit/dist/index.d.ts
generated
vendored
Normal file
4
node_modules/typeit/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Options, TypeItInstance } from "./types";
|
||||
export declare type TypeItOptions = Options;
|
||||
declare const TypeIt: TypeItInstance;
|
||||
export default TypeIt;
|
||||
825
node_modules/typeit/dist/index.es.js
generated
vendored
Normal file
825
node_modules/typeit/dist/index.es.js
generated
vendored
Normal file
@@ -0,0 +1,825 @@
|
||||
// TypeIt by Alex MacArthur - https://typeitjs.com
|
||||
const isArray = (thing) => Array.isArray(thing);
|
||||
const asArray = (value) => {
|
||||
return isArray(value) ? value : [value];
|
||||
};
|
||||
let Queue = function(initialItems) {
|
||||
let add = function(steps) {
|
||||
asArray(steps).forEach((step) => {
|
||||
return _q.set(Symbol(step.char?.innerText), buildQueueItem({ ...step }));
|
||||
});
|
||||
return this;
|
||||
};
|
||||
let getTypeable = () => rawValues().filter((value) => value.typeable);
|
||||
let set = function(index, item) {
|
||||
let keys = [..._q.keys()];
|
||||
_q.set(keys[index], buildQueueItem(item));
|
||||
};
|
||||
let buildQueueItem = (queueItem) => {
|
||||
queueItem.shouldPauseCursor = function() {
|
||||
return Boolean(this.typeable || this.cursorable || this.deletable);
|
||||
};
|
||||
return queueItem;
|
||||
};
|
||||
let reset = function() {
|
||||
_q.forEach((item) => delete item.done);
|
||||
};
|
||||
let wipe = function() {
|
||||
_q = /* @__PURE__ */ new Map();
|
||||
add(initialItems);
|
||||
};
|
||||
let getQueue = () => _q;
|
||||
let rawValues = () => Array.from(_q.values());
|
||||
let destroy = (key) => _q.delete(key);
|
||||
let getItems = (all = false) => all ? rawValues() : rawValues().filter((i) => !i.done);
|
||||
let done = (key, shouldDestroy = false) => shouldDestroy ? _q.delete(key) : _q.get(key).done = true;
|
||||
let _q = /* @__PURE__ */ new Map();
|
||||
add(initialItems);
|
||||
return {
|
||||
add,
|
||||
set,
|
||||
wipe,
|
||||
reset,
|
||||
destroy,
|
||||
done,
|
||||
getItems,
|
||||
getQueue,
|
||||
getTypeable
|
||||
};
|
||||
};
|
||||
const toArray = (val) => Array.from(val);
|
||||
const createTextNode = (content) => document.createTextNode(content);
|
||||
let expandTextNodes = (element) => {
|
||||
[...element.childNodes].forEach((child) => {
|
||||
if (child.nodeValue) {
|
||||
[...child.nodeValue].forEach((c) => {
|
||||
child.parentNode.insertBefore(createTextNode(c), child);
|
||||
});
|
||||
child.remove();
|
||||
return;
|
||||
}
|
||||
expandTextNodes(child);
|
||||
});
|
||||
return element;
|
||||
};
|
||||
const getParsedBody = (content) => {
|
||||
let doc = document.implementation.createHTMLDocument();
|
||||
doc.body.innerHTML = content;
|
||||
return expandTextNodes(doc.body);
|
||||
};
|
||||
const DATA_ATTRIBUTE = "data-typeit-id";
|
||||
const CURSOR_CLASS = "ti-cursor";
|
||||
const END = "END";
|
||||
const DEFAULT_STATUSES = {
|
||||
started: false,
|
||||
completed: false,
|
||||
frozen: false,
|
||||
destroyed: false
|
||||
};
|
||||
const DEFAULT_OPTIONS = {
|
||||
breakLines: true,
|
||||
cursor: {
|
||||
autoPause: true,
|
||||
autoPauseDelay: 500,
|
||||
animation: {
|
||||
frames: [0, 0, 1].map((n) => {
|
||||
return { opacity: n };
|
||||
}),
|
||||
options: {
|
||||
iterations: Infinity,
|
||||
easing: "steps(2, start)",
|
||||
fill: "forwards"
|
||||
}
|
||||
}
|
||||
},
|
||||
cursorChar: "|",
|
||||
cursorSpeed: 1e3,
|
||||
deleteSpeed: null,
|
||||
html: true,
|
||||
lifeLike: true,
|
||||
loop: false,
|
||||
loopDelay: 750,
|
||||
nextStringDelay: 750,
|
||||
speed: 100,
|
||||
startDelay: 250,
|
||||
startDelete: false,
|
||||
strings: [],
|
||||
waitUntilVisible: false,
|
||||
beforeString: () => {
|
||||
},
|
||||
afterString: () => {
|
||||
},
|
||||
beforeStep: () => {
|
||||
},
|
||||
afterStep: () => {
|
||||
},
|
||||
afterComplete: () => {
|
||||
}
|
||||
};
|
||||
const PLACEHOLDER_CSS = `[${DATA_ATTRIBUTE}]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}`;
|
||||
function walkElementNodes(element, shouldReverse = false, shouldIncludeCursor = false) {
|
||||
let cursor = element.querySelector(`.${CURSOR_CLASS}`);
|
||||
let walker = document.createTreeWalker(element, NodeFilter.SHOW_ALL, {
|
||||
acceptNode: (node) => {
|
||||
if (cursor && shouldIncludeCursor) {
|
||||
if (node.classList?.contains(CURSOR_CLASS)) {
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
if (cursor.contains(node)) {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
}
|
||||
return node.classList?.contains(CURSOR_CLASS) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
});
|
||||
let nextNode;
|
||||
let nodes = [];
|
||||
while (nextNode = walker.nextNode()) {
|
||||
if (!nextNode.originalParent) {
|
||||
nextNode.originalParent = nextNode.parentNode;
|
||||
}
|
||||
nodes.push(nextNode);
|
||||
}
|
||||
return shouldReverse ? nodes.reverse() : nodes;
|
||||
}
|
||||
function chunkStringAsHtml(string) {
|
||||
return walkElementNodes(getParsedBody(string));
|
||||
}
|
||||
function maybeChunkStringAsHtml(str, asHtml = true) {
|
||||
return asHtml ? chunkStringAsHtml(str) : toArray(str).map(createTextNode);
|
||||
}
|
||||
const createElement = (el) => document.createElement(el);
|
||||
const appendStyleBlock = (styles, id = "") => {
|
||||
let styleBlock = createElement("style");
|
||||
styleBlock.id = id;
|
||||
styleBlock.appendChild(createTextNode(styles));
|
||||
document.head.appendChild(styleBlock);
|
||||
};
|
||||
const calculateDelay = (delayArg) => {
|
||||
if (!isArray(delayArg)) {
|
||||
delayArg = [delayArg / 2, delayArg / 2];
|
||||
}
|
||||
return delayArg;
|
||||
};
|
||||
const randomInRange = (value, range2) => {
|
||||
return Math.abs(
|
||||
Math.random() * (value + range2 - (value - range2)) + (value - range2)
|
||||
);
|
||||
};
|
||||
let range = (val) => val / 2;
|
||||
function calculatePace(options) {
|
||||
let { speed, deleteSpeed, lifeLike } = options;
|
||||
deleteSpeed = deleteSpeed !== null ? deleteSpeed : speed / 3;
|
||||
return lifeLike ? [
|
||||
randomInRange(speed, range(speed)),
|
||||
randomInRange(deleteSpeed, range(deleteSpeed))
|
||||
] : [speed, deleteSpeed];
|
||||
}
|
||||
const destroyTimeouts = (timeouts) => {
|
||||
timeouts.forEach(clearTimeout);
|
||||
return [];
|
||||
};
|
||||
const generateHash = () => Math.random().toString().substring(2, 9);
|
||||
const isInput = (el) => "value" in el;
|
||||
let getAllChars = (element) => {
|
||||
if (isInput(element)) {
|
||||
return toArray(element.value);
|
||||
}
|
||||
return walkElementNodes(element, true).filter(
|
||||
(c) => !(c.childNodes.length > 0)
|
||||
);
|
||||
};
|
||||
const fireWhenVisible = (element, func) => {
|
||||
let observer = new IntersectionObserver(
|
||||
(entries, observer2) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
func();
|
||||
observer2.unobserve(element);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 1 }
|
||||
);
|
||||
observer.observe(element);
|
||||
};
|
||||
let handleFunctionalArg = (arg) => {
|
||||
return typeof arg === "function" ? arg() : arg;
|
||||
};
|
||||
const isNumber = (value) => Number.isInteger(value);
|
||||
let select = (selector, element = document, all = false) => {
|
||||
return element[`querySelector${all ? "All" : ""}`](selector);
|
||||
};
|
||||
let isBodyElement = (node) => /body/i.test(node?.tagName);
|
||||
let insertIntoElement = (originalTarget, character) => {
|
||||
if (isInput(originalTarget)) {
|
||||
originalTarget.value = `${originalTarget.value}${character.textContent}`;
|
||||
return;
|
||||
}
|
||||
character.innerHTML = "";
|
||||
let target = isBodyElement(character.originalParent) ? originalTarget : character.originalParent || originalTarget;
|
||||
target.insertBefore(
|
||||
character,
|
||||
select("." + CURSOR_CLASS, target) || null
|
||||
);
|
||||
};
|
||||
let updateCursorPosition = (steps, cursorPosition, printedCharacters) => {
|
||||
return Math.min(
|
||||
Math.max(cursorPosition + steps, 0),
|
||||
printedCharacters.length
|
||||
);
|
||||
};
|
||||
const merge = (originalObj, newObj) => Object.assign({}, originalObj, newObj);
|
||||
const removeNode = (node, rootElement) => {
|
||||
if (!node)
|
||||
return;
|
||||
let nodeParent = node.parentNode;
|
||||
let nodeToRemove = nodeParent.childNodes.length > 1 || nodeParent.isSameNode(rootElement) ? node : nodeParent;
|
||||
nodeToRemove.remove();
|
||||
};
|
||||
const repositionCursor = (element, allChars, newCursorPosition) => {
|
||||
let nodeToInsertBefore = allChars[newCursorPosition - 1];
|
||||
let cursor = select(`.${CURSOR_CLASS}`, element);
|
||||
element = nodeToInsertBefore?.parentNode || element;
|
||||
element.insertBefore(cursor, nodeToInsertBefore || null);
|
||||
};
|
||||
function selectorToElement(thing) {
|
||||
return typeof thing === "string" ? select(thing) : thing;
|
||||
}
|
||||
const isNonVoidElement = (el) => /<(.+)>(.*?)<\/(.+)>/.test(el.outerHTML);
|
||||
let wait = (callback, delay, timeouts) => {
|
||||
return new Promise((resolve) => {
|
||||
let cb = async () => {
|
||||
await callback();
|
||||
resolve();
|
||||
};
|
||||
timeouts.push(setTimeout(cb, delay || 0));
|
||||
});
|
||||
};
|
||||
let cursorFontStyles = {
|
||||
"font-family": "",
|
||||
"font-weight": "",
|
||||
"font-size": "",
|
||||
"font-style": "",
|
||||
"line-height": "",
|
||||
color: "",
|
||||
transform: "translateX(-.125em)"
|
||||
};
|
||||
let setCursorStyles = (id, element) => {
|
||||
let rootSelector = `[${DATA_ATTRIBUTE}='${id}']`;
|
||||
let cursorSelector = `${rootSelector} .${CURSOR_CLASS}`;
|
||||
let computedStyles = getComputedStyle(element);
|
||||
let customProperties = Object.entries(cursorFontStyles).reduce(
|
||||
(accumulator, [item, value]) => {
|
||||
return `${accumulator} ${item}: var(--ti-cursor-${item}, ${value || computedStyles[item]});`;
|
||||
},
|
||||
""
|
||||
);
|
||||
appendStyleBlock(
|
||||
`${cursorSelector} { display: inline-block; width: 0; ${customProperties} }`,
|
||||
id
|
||||
);
|
||||
};
|
||||
const duplicate = (value, times) => new Array(times).fill(value);
|
||||
const countStepsToSelector = ({
|
||||
queueItems,
|
||||
selector,
|
||||
cursorPosition,
|
||||
to
|
||||
}) => {
|
||||
if (isNumber(selector)) {
|
||||
return selector * -1;
|
||||
}
|
||||
let isMovingToEnd = new RegExp(END, "i").test(to);
|
||||
let selectorIndex = selector ? [...queueItems].reverse().findIndex(({ char }) => {
|
||||
let parentElement = char.parentElement;
|
||||
let parentMatches = parentElement.matches(selector);
|
||||
if (isMovingToEnd && parentMatches) {
|
||||
return true;
|
||||
}
|
||||
return parentMatches && parentElement.firstChild.isSameNode(char);
|
||||
}) : -1;
|
||||
if (selectorIndex < 0) {
|
||||
selectorIndex = isMovingToEnd ? 0 : queueItems.length - 1;
|
||||
}
|
||||
let offset = isMovingToEnd ? 0 : 1;
|
||||
return selectorIndex - cursorPosition + offset;
|
||||
};
|
||||
let beforePaint = (cb) => {
|
||||
return new Promise((resolve) => {
|
||||
requestAnimationFrame(async () => {
|
||||
resolve(await cb());
|
||||
});
|
||||
});
|
||||
};
|
||||
let getAnimationFromElement = (element) => {
|
||||
return element?.getAnimations().find((animation) => {
|
||||
return animation.id === element.dataset.tiAnimationId;
|
||||
});
|
||||
};
|
||||
let setCursorAnimation = ({
|
||||
cursor,
|
||||
frames,
|
||||
options
|
||||
}) => {
|
||||
let animation = cursor.animate(frames, options);
|
||||
animation.pause();
|
||||
animation.id = cursor.dataset.tiAnimationId;
|
||||
beforePaint(() => {
|
||||
beforePaint(() => {
|
||||
animation.play();
|
||||
});
|
||||
});
|
||||
return animation;
|
||||
};
|
||||
let rebuildCursorAnimation = ({
|
||||
cursor,
|
||||
options,
|
||||
cursorOptions
|
||||
}) => {
|
||||
if (!cursor || !cursorOptions)
|
||||
return;
|
||||
let animation = getAnimationFromElement(cursor);
|
||||
let oldCurrentTime;
|
||||
if (animation) {
|
||||
options.delay = animation.effect.getComputedTiming().delay;
|
||||
oldCurrentTime = animation.currentTime;
|
||||
animation.cancel();
|
||||
}
|
||||
let newAnimation = setCursorAnimation({
|
||||
cursor,
|
||||
frames: cursorOptions.animation.frames,
|
||||
options
|
||||
});
|
||||
if (oldCurrentTime) {
|
||||
newAnimation.currentTime = oldCurrentTime;
|
||||
}
|
||||
return newAnimation;
|
||||
};
|
||||
let execute = (queueItem) => queueItem.func?.call(null);
|
||||
let fireItem = async ({
|
||||
index,
|
||||
queueItems,
|
||||
wait: wait2,
|
||||
cursor,
|
||||
cursorOptions
|
||||
}) => {
|
||||
let queueItem = queueItems[index][1];
|
||||
let instantQueue = [];
|
||||
let tempIndex = index;
|
||||
let futureItem = queueItem;
|
||||
let shouldBeGrouped = () => futureItem && !futureItem.delay;
|
||||
let shouldPauseCursor = queueItem.shouldPauseCursor() && cursorOptions.autoPause;
|
||||
while (shouldBeGrouped()) {
|
||||
instantQueue.push(futureItem);
|
||||
shouldBeGrouped() && tempIndex++;
|
||||
futureItem = queueItems[tempIndex] ? queueItems[tempIndex][1] : null;
|
||||
}
|
||||
if (instantQueue.length) {
|
||||
await beforePaint(async () => {
|
||||
for (let q of instantQueue) {
|
||||
await execute(q);
|
||||
}
|
||||
});
|
||||
return tempIndex - 1;
|
||||
}
|
||||
let animation = getAnimationFromElement(cursor);
|
||||
let options;
|
||||
if (animation) {
|
||||
options = {
|
||||
...animation.effect.getComputedTiming(),
|
||||
delay: shouldPauseCursor ? cursorOptions.autoPauseDelay : 0
|
||||
};
|
||||
}
|
||||
await wait2(async () => {
|
||||
if (animation && shouldPauseCursor) {
|
||||
animation.cancel();
|
||||
}
|
||||
await beforePaint(() => {
|
||||
execute(queueItem);
|
||||
});
|
||||
}, queueItem.delay);
|
||||
await rebuildCursorAnimation({
|
||||
cursor,
|
||||
options,
|
||||
cursorOptions
|
||||
});
|
||||
return index;
|
||||
};
|
||||
let processCursorOptions = (cursorOptions) => {
|
||||
if (typeof cursorOptions === "object") {
|
||||
let newOptions = {};
|
||||
let { frames: defaultFrames, options: defaultOptions } = DEFAULT_OPTIONS.cursor.animation;
|
||||
newOptions.animation = cursorOptions.animation || {};
|
||||
newOptions.animation.frames = cursorOptions.animation?.frames || defaultFrames;
|
||||
newOptions.animation.options = merge(
|
||||
defaultOptions,
|
||||
cursorOptions.animation?.options || {}
|
||||
);
|
||||
newOptions.autoPause = cursorOptions.autoPause ?? DEFAULT_OPTIONS.cursor.autoPause;
|
||||
newOptions.autoPauseDelay = cursorOptions.autoPauseDelay || DEFAULT_OPTIONS.cursor.autoPauseDelay;
|
||||
return newOptions;
|
||||
}
|
||||
if (cursorOptions === true) {
|
||||
return DEFAULT_OPTIONS.cursor;
|
||||
}
|
||||
return cursorOptions;
|
||||
};
|
||||
const TypeIt = function(element, options = {}) {
|
||||
let _wait = async (callback, delay, silent = false) => {
|
||||
if (_statuses.frozen) {
|
||||
await new Promise((resolve) => {
|
||||
this.unfreeze = () => {
|
||||
_statuses.frozen = false;
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
}
|
||||
silent || await _opts.beforeStep(this);
|
||||
await wait(callback, delay, _timeouts);
|
||||
silent || await _opts.afterStep(this);
|
||||
};
|
||||
let _fireItemWithContext = (index, queueItems) => {
|
||||
return fireItem({
|
||||
index,
|
||||
queueItems,
|
||||
wait: _wait,
|
||||
cursor: _cursor,
|
||||
cursorOptions: _opts.cursor
|
||||
});
|
||||
};
|
||||
let _removeNode = (node) => removeNode(node, _element);
|
||||
let _elementIsInput = () => isInput(_element);
|
||||
let _getPace = (index = 0) => calculatePace(_opts)[index];
|
||||
let _getAllChars = () => getAllChars(_element);
|
||||
let _maybeAppendPause = (opts = {}) => {
|
||||
let delay = opts.delay;
|
||||
delay && _queue.add({ delay });
|
||||
};
|
||||
let _queueAndReturn = (steps, opts) => {
|
||||
_queue.add(steps);
|
||||
_maybeAppendPause(opts);
|
||||
return this;
|
||||
};
|
||||
let _getDerivedCursorPosition = () => _predictedCursorPosition ?? _cursorPosition;
|
||||
let _generateTemporaryOptionQueueItems = (newOptions = {}) => {
|
||||
return [
|
||||
{ func: () => _options(newOptions) },
|
||||
{ func: () => _options(_opts) }
|
||||
];
|
||||
};
|
||||
let _addSplitPause = (items) => {
|
||||
let delay = _opts.nextStringDelay;
|
||||
_queue.add([{ delay: delay[0] }, ...items, { delay: delay[1] }]);
|
||||
};
|
||||
let _setUpCursor = () => {
|
||||
if (_elementIsInput()) {
|
||||
return;
|
||||
}
|
||||
let cursor = createElement("span");
|
||||
cursor.className = CURSOR_CLASS;
|
||||
if (!_shouldRenderCursor) {
|
||||
cursor.style.visibility = "hidden";
|
||||
return cursor;
|
||||
}
|
||||
cursor.innerHTML = getParsedBody(_opts.cursorChar).innerHTML;
|
||||
return cursor;
|
||||
};
|
||||
let _attachCursor = async () => {
|
||||
!_elementIsInput() && _cursor && _element.appendChild(_cursor);
|
||||
if (_shouldRenderCursor) {
|
||||
setCursorStyles(_id, _element);
|
||||
_cursor.dataset.tiAnimationId = _id;
|
||||
let { animation } = _opts.cursor;
|
||||
let { frames, options: options2 } = animation;
|
||||
setCursorAnimation({
|
||||
frames,
|
||||
cursor: _cursor,
|
||||
options: {
|
||||
duration: _opts.cursorSpeed,
|
||||
...options2
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
let _generateQueue = () => {
|
||||
let strings = _opts.strings.filter((string) => !!string);
|
||||
strings.forEach((string, index) => {
|
||||
this.type(string);
|
||||
if (index + 1 === strings.length) {
|
||||
return;
|
||||
}
|
||||
let splitItems = _opts.breakLines ? [{ func: () => _type(createElement("BR")), typeable: true }] : duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1)
|
||||
},
|
||||
_queue.getTypeable().length
|
||||
);
|
||||
_addSplitPause(splitItems);
|
||||
});
|
||||
};
|
||||
let _prepLoop = async (delay) => {
|
||||
let derivedCursorPosition = _getDerivedCursorPosition();
|
||||
derivedCursorPosition && await _move({ value: derivedCursorPosition });
|
||||
let queueItems = _getAllChars().map((c) => {
|
||||
return [
|
||||
Symbol(),
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1),
|
||||
deletable: true,
|
||||
shouldPauseCursor: () => true
|
||||
}
|
||||
];
|
||||
});
|
||||
for (let index = 0; index < queueItems.length; index++) {
|
||||
await _fireItemWithContext(index, queueItems);
|
||||
}
|
||||
_queue.reset();
|
||||
_queue.set(0, { delay });
|
||||
};
|
||||
let _maybePrependHardcodedStrings = (strings) => {
|
||||
let existingMarkup = _element.innerHTML;
|
||||
if (!existingMarkup) {
|
||||
return strings;
|
||||
}
|
||||
_element.innerHTML = "";
|
||||
if (_opts.startDelete) {
|
||||
_element.innerHTML = existingMarkup;
|
||||
expandTextNodes(_element);
|
||||
_addSplitPause(
|
||||
duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1),
|
||||
deletable: true
|
||||
},
|
||||
_getAllChars().length
|
||||
)
|
||||
);
|
||||
return strings;
|
||||
}
|
||||
let hardCodedStrings = existingMarkup.replace(/<!--(.+?)-->/g, "").trim().split(/<br(?:\s*?)(?:\/)?>/);
|
||||
return hardCodedStrings.concat(strings);
|
||||
};
|
||||
let _fire = async (remember = true) => {
|
||||
_statuses.started = true;
|
||||
let cleanUp = (qKey) => {
|
||||
_queue.done(qKey, !remember);
|
||||
};
|
||||
try {
|
||||
let queueItems = [..._queue.getQueue()];
|
||||
for (let index = 0; index < queueItems.length; index++) {
|
||||
let [queueKey, queueItem] = queueItems[index];
|
||||
if (queueItem.done)
|
||||
continue;
|
||||
if (!queueItem.deletable || queueItem.deletable && _getAllChars().length) {
|
||||
let newIndex = await _fireItemWithContext(index, queueItems);
|
||||
Array(newIndex - index).fill(index + 1).map((x, y) => x + y).forEach((i) => {
|
||||
let [key] = queueItems[i];
|
||||
cleanUp(key);
|
||||
});
|
||||
index = newIndex;
|
||||
}
|
||||
cleanUp(queueKey);
|
||||
}
|
||||
if (!remember) {
|
||||
return this;
|
||||
}
|
||||
_statuses.completed = true;
|
||||
await _opts.afterComplete(this);
|
||||
if (!_opts.loop) {
|
||||
throw "";
|
||||
}
|
||||
let delay = _opts.loopDelay;
|
||||
_wait(async () => {
|
||||
await _prepLoop(delay[0]);
|
||||
_fire();
|
||||
}, delay[1]);
|
||||
} catch (e) {
|
||||
}
|
||||
return this;
|
||||
};
|
||||
let _move = async (step) => {
|
||||
_cursorPosition = updateCursorPosition(
|
||||
step,
|
||||
_cursorPosition,
|
||||
_getAllChars()
|
||||
);
|
||||
repositionCursor(_element, _getAllChars(), _cursorPosition);
|
||||
};
|
||||
let _type = (char) => insertIntoElement(_element, char);
|
||||
let _options = async (opts) => _opts = merge(_opts, opts);
|
||||
let _empty = async () => {
|
||||
if (_elementIsInput()) {
|
||||
_element.value = "";
|
||||
return;
|
||||
}
|
||||
_getAllChars().forEach(_removeNode);
|
||||
return;
|
||||
};
|
||||
let _delete = () => {
|
||||
let allChars = _getAllChars();
|
||||
if (!allChars.length)
|
||||
return;
|
||||
if (_elementIsInput()) {
|
||||
_element.value = _element.value.slice(0, -1);
|
||||
} else {
|
||||
_removeNode(allChars[_cursorPosition]);
|
||||
}
|
||||
};
|
||||
this.break = function(actionOpts) {
|
||||
return _queueAndReturn(
|
||||
{
|
||||
func: () => _type(createElement("BR")),
|
||||
typeable: true
|
||||
},
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
this.delete = function(numCharacters = null, actionOpts = {}) {
|
||||
numCharacters = handleFunctionalArg(numCharacters);
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let num = numCharacters;
|
||||
let { instant, to } = actionOpts;
|
||||
let typeableQueueItems = _queue.getTypeable();
|
||||
let rounds = (() => {
|
||||
if (num === null) {
|
||||
return typeableQueueItems.length;
|
||||
}
|
||||
if (isNumber(num)) {
|
||||
return num;
|
||||
}
|
||||
return countStepsToSelector({
|
||||
queueItems: typeableQueueItems,
|
||||
selector: num,
|
||||
cursorPosition: _getDerivedCursorPosition(),
|
||||
to
|
||||
});
|
||||
})();
|
||||
return _queueAndReturn(
|
||||
[
|
||||
bookEndQueueItems[0],
|
||||
...duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: instant ? 0 : _getPace(1),
|
||||
deletable: true
|
||||
},
|
||||
rounds
|
||||
),
|
||||
bookEndQueueItems[1]
|
||||
],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
this.empty = function(actionOpts = {}) {
|
||||
return _queueAndReturn({ func: _empty }, actionOpts);
|
||||
};
|
||||
this.exec = function(func, actionOpts = {}) {
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
return _queueAndReturn(
|
||||
[bookEndQueueItems[0], { func: () => func(this) }, bookEndQueueItems[1]],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
this.move = function(movementArg, actionOpts = {}) {
|
||||
movementArg = handleFunctionalArg(movementArg);
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let { instant, to } = actionOpts;
|
||||
let numberOfSteps = countStepsToSelector({
|
||||
queueItems: _queue.getTypeable(),
|
||||
selector: movementArg === null ? "" : movementArg,
|
||||
to,
|
||||
cursorPosition: _getDerivedCursorPosition()
|
||||
});
|
||||
let directionalStep = numberOfSteps < 0 ? -1 : 1;
|
||||
_predictedCursorPosition = _getDerivedCursorPosition() + numberOfSteps;
|
||||
return _queueAndReturn(
|
||||
[
|
||||
bookEndQueueItems[0],
|
||||
...duplicate(
|
||||
{
|
||||
func: () => _move(directionalStep),
|
||||
delay: instant ? 0 : _getPace(),
|
||||
cursorable: true
|
||||
},
|
||||
Math.abs(numberOfSteps)
|
||||
),
|
||||
bookEndQueueItems[1]
|
||||
],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
this.options = function(opts, actionOpts = {}) {
|
||||
opts = handleFunctionalArg(opts);
|
||||
_options(opts);
|
||||
return _queueAndReturn({}, actionOpts);
|
||||
};
|
||||
this.pause = function(milliseconds, actionOpts = {}) {
|
||||
return _queueAndReturn(
|
||||
{ delay: handleFunctionalArg(milliseconds) },
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
this.type = function(string, actionOpts = {}) {
|
||||
string = handleFunctionalArg(string);
|
||||
let { instant } = actionOpts;
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let chars = maybeChunkStringAsHtml(string, _opts.html);
|
||||
let charsAsQueueItems = chars.map((char) => {
|
||||
return {
|
||||
func: () => _type(char),
|
||||
char,
|
||||
delay: instant || isNonVoidElement(char) ? 0 : _getPace(),
|
||||
typeable: char.nodeType === Node.TEXT_NODE
|
||||
};
|
||||
});
|
||||
let itemsToQueue = [
|
||||
bookEndQueueItems[0],
|
||||
{ func: async () => await _opts.beforeString(string, this) },
|
||||
...charsAsQueueItems,
|
||||
{ func: async () => await _opts.afterString(string, this) },
|
||||
bookEndQueueItems[1]
|
||||
];
|
||||
return _queueAndReturn(itemsToQueue, actionOpts);
|
||||
};
|
||||
this.is = function(key) {
|
||||
return _statuses[key];
|
||||
};
|
||||
this.destroy = function(shouldRemoveCursor = true) {
|
||||
_timeouts = destroyTimeouts(_timeouts);
|
||||
handleFunctionalArg(shouldRemoveCursor) && _cursor && _removeNode(_cursor);
|
||||
_statuses.destroyed = true;
|
||||
};
|
||||
this.freeze = function() {
|
||||
_statuses.frozen = true;
|
||||
};
|
||||
this.unfreeze = () => {
|
||||
};
|
||||
this.reset = function(rebuild) {
|
||||
!this.is("destroyed") && this.destroy();
|
||||
if (rebuild) {
|
||||
_queue.wipe();
|
||||
rebuild(this);
|
||||
} else {
|
||||
_queue.reset();
|
||||
}
|
||||
_cursorPosition = 0;
|
||||
for (let property in _statuses) {
|
||||
_statuses[property] = false;
|
||||
}
|
||||
_element[_elementIsInput() ? "value" : "innerHTML"] = "";
|
||||
return this;
|
||||
};
|
||||
this.go = function() {
|
||||
if (_statuses.started) {
|
||||
return this;
|
||||
}
|
||||
_attachCursor();
|
||||
if (!_opts.waitUntilVisible) {
|
||||
_fire();
|
||||
return this;
|
||||
}
|
||||
fireWhenVisible(_element, _fire.bind(this));
|
||||
return this;
|
||||
};
|
||||
this.flush = function(cb = () => {
|
||||
}) {
|
||||
_attachCursor();
|
||||
_fire(false).then(cb);
|
||||
return this;
|
||||
};
|
||||
this.getQueue = () => _queue;
|
||||
this.getOptions = () => _opts;
|
||||
this.updateOptions = (options2) => _options(options2);
|
||||
this.getElement = () => _element;
|
||||
let _element = selectorToElement(element);
|
||||
let _timeouts = [];
|
||||
let _cursorPosition = 0;
|
||||
let _predictedCursorPosition = null;
|
||||
let _statuses = merge({}, DEFAULT_STATUSES);
|
||||
options.cursor = processCursorOptions(
|
||||
options.cursor ?? DEFAULT_OPTIONS.cursor
|
||||
);
|
||||
let _opts = merge(DEFAULT_OPTIONS, options);
|
||||
_opts = merge(_opts, {
|
||||
html: !_elementIsInput() && _opts.html,
|
||||
nextStringDelay: calculateDelay(_opts.nextStringDelay),
|
||||
loopDelay: calculateDelay(_opts.loopDelay)
|
||||
});
|
||||
let _id = generateHash();
|
||||
let _queue = Queue([{ delay: _opts.startDelay }]);
|
||||
_element.dataset.typeitId = _id;
|
||||
appendStyleBlock(PLACEHOLDER_CSS);
|
||||
let _shouldRenderCursor = !!_opts.cursor && !_elementIsInput();
|
||||
let _cursor = _setUpCursor();
|
||||
_opts.strings = _maybePrependHardcodedStrings(asArray(_opts.strings));
|
||||
if (_opts.strings.length) {
|
||||
_generateQueue();
|
||||
}
|
||||
};
|
||||
export {
|
||||
TypeIt as default
|
||||
};
|
||||
2
node_modules/typeit/dist/index.umd.js
generated
vendored
Normal file
2
node_modules/typeit/dist/index.umd.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
58
node_modules/typeit/dist/types.d.ts
generated
vendored
Normal file
58
node_modules/typeit/dist/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/// <reference types="web-animations-js" />
|
||||
export type TypeItInstance = (element: El | string, options: Options) => void;
|
||||
export type Character = {
|
||||
node: El | null;
|
||||
content: string | Node;
|
||||
};
|
||||
export interface CursorAnimationOptions {
|
||||
frames?: AnimationKeyFrame[];
|
||||
options?: Partial<AnimationEffectTiming>;
|
||||
}
|
||||
export interface CursorOptions {
|
||||
autoPause?: boolean;
|
||||
autoPauseDelay?: number;
|
||||
animation?: CursorAnimationOptions;
|
||||
}
|
||||
export interface Options {
|
||||
breakLines?: boolean;
|
||||
cursorChar?: string;
|
||||
cursor?: CursorOptions | boolean;
|
||||
cursorSpeed?: number;
|
||||
deleteSpeed?: null | number;
|
||||
html?: boolean;
|
||||
lifeLike?: boolean;
|
||||
loop?: boolean;
|
||||
loopDelay?: number;
|
||||
nextStringDelay?: number;
|
||||
speed?: number;
|
||||
startDelay?: number;
|
||||
startDelete?: boolean;
|
||||
strings?: string[] | string;
|
||||
waitUntilVisible?: boolean;
|
||||
beforeString?: Function;
|
||||
afterString?: Function;
|
||||
beforeStep?: Function;
|
||||
afterStep?: Function;
|
||||
afterComplete?: Function;
|
||||
}
|
||||
export type ActionOpts = Options & {
|
||||
to?: Sides;
|
||||
instant?: boolean;
|
||||
delay?: number;
|
||||
};
|
||||
export type QueueItem = {
|
||||
done?: boolean;
|
||||
func?: () => any;
|
||||
delay?: number;
|
||||
char?: any;
|
||||
typeable?: boolean;
|
||||
deletable?: boolean;
|
||||
cursorable?: boolean;
|
||||
shouldPauseCursor?: () => boolean;
|
||||
};
|
||||
export type QueueMapPair = [Symbol, QueueItem];
|
||||
export interface El extends HTMLElement {
|
||||
value: string | number;
|
||||
originalParent?: HTMLElement;
|
||||
}
|
||||
export type Sides = "START" | "END";
|
||||
62
node_modules/typeit/package.json
generated
vendored
Normal file
62
node_modules/typeit/package.json
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "typeit",
|
||||
"version": "8.7.1",
|
||||
"description": "The most versatile animated typing utility on the planet.",
|
||||
"author": "Alex MacArthur <alex@macarthur.me> (https://macarthur.me)",
|
||||
"license": "GPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/alexmacarthur/typeit/issues"
|
||||
},
|
||||
"homepage": "https://typeitjs.com",
|
||||
"main": "dist/index.umd.js",
|
||||
"module": "dist/index.es.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist/",
|
||||
"src/",
|
||||
"scripts/"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "vite build && scripts/banner && tsc",
|
||||
"tsc": "tsc",
|
||||
"start": "vite serve examples --host 0.0.0.0",
|
||||
"test": "jest",
|
||||
"postinstall": "node ./scripts/notice.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"animated",
|
||||
"typing",
|
||||
"typing effect",
|
||||
"typewriter",
|
||||
"typewriter effect",
|
||||
"type effect",
|
||||
"text effects"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/alexmacarthur/typeit.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@types/web-animations-js": "^2.2.12",
|
||||
"jest": "^29.3.1",
|
||||
"jest-cli": "^29.3.1",
|
||||
"jest-environment-jsdom": "^29.3.1",
|
||||
"terser": "^5.16.1",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^4.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"clearMocks": true,
|
||||
"testPathIgnorePatterns": [
|
||||
"<rootDir>/__tests__/setup.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"./__tests__/setup.js"
|
||||
],
|
||||
"testEnvironment": "jsdom"
|
||||
}
|
||||
}
|
||||
9
node_modules/typeit/scripts/banner
generated
vendored
Executable file
9
node_modules/typeit/scripts/banner
generated
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIST_PATH="$(pwd)/dist"
|
||||
DIST_FILES=("index.umd.js" "index.es.js")
|
||||
|
||||
for f in "${DIST_FILES[@]}"
|
||||
do
|
||||
echo -e "// TypeIt by Alex MacArthur - https://typeitjs.com\n$(cat $DIST_PATH/$f)" > $DIST_PATH/$f
|
||||
done
|
||||
5
node_modules/typeit/scripts/notice.js
generated
vendored
Normal file
5
node_modules/typeit/scripts/notice.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const message = `Thanks for using TypeIt! If you're using this library commercially, please purchase a license:
|
||||
|
||||
https://typeitjs.com/licenses/purchase`;
|
||||
|
||||
console.log("\x1b[35m%s\x1b[0m", message);
|
||||
0
node_modules/typeit/src/Cursor.ts
generated
vendored
Normal file
0
node_modules/typeit/src/Cursor.ts
generated
vendored
Normal file
79
node_modules/typeit/src/Queue.ts
generated
vendored
Normal file
79
node_modules/typeit/src/Queue.ts
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import asArray from "./helpers/asArray";
|
||||
import { QueueItem } from "./types";
|
||||
|
||||
let Queue = function (initialItems: QueueItem[]) {
|
||||
/**
|
||||
* Add a single or several steps onto the `waiting` queue.
|
||||
*/
|
||||
let add = function (steps: QueueItem[] | QueueItem): typeof Queue {
|
||||
asArray<QueueItem>(steps).forEach((step) => {
|
||||
return _q.set(Symbol(step.char?.innerText), buildQueueItem({ ...step }));
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
let getTypeable = (): QueueItem[] =>
|
||||
rawValues().filter((value) => value.typeable);
|
||||
|
||||
/**
|
||||
* Given an index, set an item in the queue.
|
||||
*/
|
||||
let set = function (index: number, item: QueueItem): void {
|
||||
let keys = [..._q.keys()];
|
||||
|
||||
_q.set(keys[index], buildQueueItem(item));
|
||||
};
|
||||
|
||||
let buildQueueItem = (queueItem: QueueItem): QueueItem => {
|
||||
queueItem.shouldPauseCursor = function () {
|
||||
return Boolean(this.typeable || this.cursorable || this.deletable);
|
||||
};
|
||||
|
||||
return queueItem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Move all `executed` queue items to `waiting`.
|
||||
*/
|
||||
let reset = function (): void {
|
||||
_q.forEach((item) => delete item.done);
|
||||
};
|
||||
|
||||
let wipe = function (): void {
|
||||
_q = new Map();
|
||||
add(initialItems);
|
||||
};
|
||||
|
||||
let getQueue = () => _q;
|
||||
let rawValues = (): QueueItem[] => Array.from(_q.values());
|
||||
let destroy = (key: Symbol) => _q.delete(key);
|
||||
|
||||
/**
|
||||
* Retrieve all items that are still eligible to be executed. By default, only the
|
||||
* completed items will be retrieved.
|
||||
*/
|
||||
let getItems = (all: boolean = false): QueueItem[] =>
|
||||
all ? rawValues() : rawValues().filter((i) => !i.done);
|
||||
|
||||
let done = (key: Symbol, shouldDestroy: boolean = false) =>
|
||||
shouldDestroy ? _q.delete(key) : (_q.get(key).done = true);
|
||||
|
||||
let _q = new Map();
|
||||
|
||||
add(initialItems);
|
||||
|
||||
return {
|
||||
add,
|
||||
set,
|
||||
wipe,
|
||||
reset,
|
||||
destroy,
|
||||
done,
|
||||
getItems,
|
||||
getQueue,
|
||||
getTypeable,
|
||||
};
|
||||
};
|
||||
|
||||
export default Queue;
|
||||
51
node_modules/typeit/src/constants.ts
generated
vendored
Normal file
51
node_modules/typeit/src/constants.ts
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import { CursorOptions, Options } from "./types";
|
||||
|
||||
export const DATA_ATTRIBUTE = "data-typeit-id";
|
||||
export const CURSOR_CLASS = "ti-cursor";
|
||||
export const START = "START";
|
||||
export const END = "END";
|
||||
export const DEFAULT_STATUSES = {
|
||||
started: false,
|
||||
completed: false,
|
||||
frozen: false,
|
||||
destroyed: false,
|
||||
};
|
||||
|
||||
export const DEFAULT_OPTIONS: Options & {
|
||||
cursor: Required<CursorOptions>;
|
||||
} = {
|
||||
breakLines: true,
|
||||
cursor: {
|
||||
autoPause: true,
|
||||
autoPauseDelay: 500,
|
||||
animation: {
|
||||
frames: [0, 0, 1].map((n) => {
|
||||
return { opacity: n };
|
||||
}),
|
||||
options: {
|
||||
iterations: Infinity,
|
||||
easing: "steps(2, start)",
|
||||
fill: "forwards",
|
||||
},
|
||||
},
|
||||
},
|
||||
cursorChar: "|",
|
||||
cursorSpeed: 1000,
|
||||
deleteSpeed: null,
|
||||
html: true,
|
||||
lifeLike: true,
|
||||
loop: false,
|
||||
loopDelay: 750,
|
||||
nextStringDelay: 750,
|
||||
speed: 100,
|
||||
startDelay: 250,
|
||||
startDelete: false,
|
||||
strings: [],
|
||||
waitUntilVisible: false,
|
||||
beforeString: () => {},
|
||||
afterString: () => {},
|
||||
beforeStep: () => {},
|
||||
afterStep: () => {},
|
||||
afterComplete: () => {},
|
||||
};
|
||||
export const PLACEHOLDER_CSS = `[${DATA_ATTRIBUTE}]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}`;
|
||||
9
node_modules/typeit/src/helpers/appendStyleBlock.ts
generated
vendored
Normal file
9
node_modules/typeit/src/helpers/appendStyleBlock.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import createElement from "./createElement";
|
||||
import createTextNode from "./createTextNode";
|
||||
|
||||
export default (styles: string, id = ""): void => {
|
||||
let styleBlock: HTMLElement = createElement("style");
|
||||
styleBlock.id = id;
|
||||
styleBlock.appendChild(createTextNode(styles));
|
||||
document.head.appendChild(styleBlock);
|
||||
};
|
||||
8
node_modules/typeit/src/helpers/asArray.ts
generated
vendored
Normal file
8
node_modules/typeit/src/helpers/asArray.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import isArray from "./isArray";
|
||||
|
||||
/**
|
||||
* Converts value as within array, unless the value itself already is one.
|
||||
*/
|
||||
export default <T>(value): T[] => {
|
||||
return isArray(value) ? value : [value];
|
||||
};
|
||||
9
node_modules/typeit/src/helpers/beforePaint.ts
generated
vendored
Normal file
9
node_modules/typeit/src/helpers/beforePaint.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
let beforePaint = (cb): Promise<any> => {
|
||||
return new Promise((resolve) => {
|
||||
requestAnimationFrame(async () => {
|
||||
resolve(await cb());
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default beforePaint;
|
||||
16
node_modules/typeit/src/helpers/calculateDelay.ts
generated
vendored
Normal file
16
node_modules/typeit/src/helpers/calculateDelay.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import isArray from "./isArray";
|
||||
|
||||
/**
|
||||
* Given a delay value, form it into the type of object
|
||||
* that will be used by Instance().
|
||||
*
|
||||
* @param {integer | array}
|
||||
* @return {array}
|
||||
*/
|
||||
export default (delayArg: number | number[]): number[] => {
|
||||
if (!isArray(delayArg)) {
|
||||
delayArg = [(delayArg as number) / 2, (delayArg as number) / 2];
|
||||
}
|
||||
|
||||
return delayArg as number[];
|
||||
};
|
||||
20
node_modules/typeit/src/helpers/calculatePace.ts
generated
vendored
Normal file
20
node_modules/typeit/src/helpers/calculatePace.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Options } from "../types";
|
||||
import randomInRange from "./randomInRange";
|
||||
|
||||
let range = (val: number): number => val / 2;
|
||||
|
||||
/**
|
||||
* [typePace, deletePace]
|
||||
*/
|
||||
export default function (options: Options): number[] {
|
||||
let { speed, deleteSpeed, lifeLike } = options;
|
||||
|
||||
deleteSpeed = deleteSpeed !== null ? deleteSpeed : speed / 3;
|
||||
|
||||
return lifeLike
|
||||
? [
|
||||
randomInRange(speed, range(speed)),
|
||||
randomInRange(deleteSpeed, range(deleteSpeed)),
|
||||
]
|
||||
: [speed, deleteSpeed];
|
||||
}
|
||||
73
node_modules/typeit/src/helpers/chunkStrings.ts
generated
vendored
Normal file
73
node_modules/typeit/src/helpers/chunkStrings.ts
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
import { El } from "../types";
|
||||
import toArray from "./toArray";
|
||||
import getParsedBody from "./getParsedBody";
|
||||
import createTextNode from "./createTextNode";
|
||||
import { CURSOR_CLASS } from "../constants";
|
||||
|
||||
export function walkElementNodes(
|
||||
element: El | Node,
|
||||
shouldReverse: boolean = false,
|
||||
shouldIncludeCursor: boolean = false
|
||||
): El[] {
|
||||
let cursor = (element as HTMLElement).querySelector(`.${CURSOR_CLASS}`);
|
||||
|
||||
let walker = document.createTreeWalker(element, NodeFilter.SHOW_ALL, {
|
||||
acceptNode: (node: El) => {
|
||||
// Include the cursor node, but none of it's children.
|
||||
if (cursor && shouldIncludeCursor) {
|
||||
if (node.classList?.contains(CURSOR_CLASS)) {
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
}
|
||||
|
||||
// Do not include any of the cursor's child nodes.
|
||||
if (cursor.contains(node)) {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe exclude the cursor and its children.
|
||||
return node.classList?.contains(CURSOR_CLASS)
|
||||
? NodeFilter.FILTER_REJECT
|
||||
: NodeFilter.FILTER_ACCEPT;
|
||||
},
|
||||
});
|
||||
|
||||
let nextNode;
|
||||
let nodes = [];
|
||||
|
||||
while ((nextNode = walker.nextNode())) {
|
||||
// Necessary for preserving reference to parent nodes
|
||||
// as we empty elements during typing.
|
||||
// If this has already been set, don't do it again.
|
||||
if (!nextNode.originalParent) {
|
||||
nextNode.originalParent = nextNode.parentNode;
|
||||
}
|
||||
|
||||
nodes.push(nextNode);
|
||||
}
|
||||
|
||||
return shouldReverse ? nodes.reverse() : nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string to array of chunks that will be later
|
||||
* used to construct a TypeIt queue.
|
||||
*/
|
||||
export function chunkStringAsHtml(string: string): El[] {
|
||||
return walkElementNodes(getParsedBody(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, chunk it into array items to be later
|
||||
* converted to queue items for typing.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {boolean} asHtml
|
||||
* @return {array}
|
||||
*/
|
||||
export function maybeChunkStringAsHtml(
|
||||
str: string,
|
||||
asHtml = true
|
||||
): Partial<El>[] {
|
||||
return asHtml ? chunkStringAsHtml(str) : toArray(str).map(createTextNode);
|
||||
}
|
||||
49
node_modules/typeit/src/helpers/countStepsToSelector.ts
generated
vendored
Normal file
49
node_modules/typeit/src/helpers/countStepsToSelector.ts
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { END } from "../constants";
|
||||
import { QueueItem, Sides } from "../types";
|
||||
import isNumber from "./isNumber";
|
||||
|
||||
interface countStepsToSelectorArgs {
|
||||
queueItems: QueueItem[];
|
||||
selector: string | number;
|
||||
cursorPosition: number;
|
||||
to: Sides;
|
||||
}
|
||||
|
||||
const countStepsToSelector = ({
|
||||
queueItems,
|
||||
selector,
|
||||
cursorPosition,
|
||||
to,
|
||||
}: countStepsToSelectorArgs): number => {
|
||||
if (isNumber(selector)) {
|
||||
return (selector as number) * -1;
|
||||
}
|
||||
|
||||
let isMovingToEnd = new RegExp(END, "i").test(to);
|
||||
let selectorIndex = selector
|
||||
? [...queueItems].reverse().findIndex(({ char }) => {
|
||||
let parentElement = char.parentElement;
|
||||
let parentMatches = parentElement.matches(selector);
|
||||
|
||||
// We found the butt end of the selected element.
|
||||
if (isMovingToEnd && parentMatches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We found the very beginning of the selected element.
|
||||
return parentMatches && parentElement.firstChild.isSameNode(char);
|
||||
})
|
||||
: -1;
|
||||
|
||||
// Couldn't find it the selector, so determine if we
|
||||
// need to move either to the beginning or the end.
|
||||
if (selectorIndex < 0) {
|
||||
selectorIndex = isMovingToEnd ? 0 : queueItems.length - 1;
|
||||
}
|
||||
|
||||
let offset = isMovingToEnd ? 0 : 1;
|
||||
|
||||
return selectorIndex - cursorPosition + offset;
|
||||
};
|
||||
|
||||
export default countStepsToSelector;
|
||||
3
node_modules/typeit/src/helpers/createElement.ts
generated
vendored
Normal file
3
node_modules/typeit/src/helpers/createElement.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { El } from "../types";
|
||||
|
||||
export default (el): El => document.createElement(el);
|
||||
1
node_modules/typeit/src/helpers/createTextNode.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/createTextNode.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (content: string): Text => document.createTextNode(content);
|
||||
5
node_modules/typeit/src/helpers/destroyTimeouts.ts
generated
vendored
Normal file
5
node_modules/typeit/src/helpers/destroyTimeouts.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export default (timeouts: number[]): [] => {
|
||||
timeouts.forEach(clearTimeout);
|
||||
|
||||
return [];
|
||||
};
|
||||
2
node_modules/typeit/src/helpers/duplicate.ts
generated
vendored
Normal file
2
node_modules/typeit/src/helpers/duplicate.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export default <T>(value: T, times: number): T[] =>
|
||||
new Array(times).fill(value);
|
||||
21
node_modules/typeit/src/helpers/expandTextNodes.ts
generated
vendored
Normal file
21
node_modules/typeit/src/helpers/expandTextNodes.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import createTextNode from "./createTextNode";
|
||||
import { El } from "../types";
|
||||
|
||||
let expandTextNodes = (element: El): El => {
|
||||
[...element.childNodes].forEach((child) => {
|
||||
if (child.nodeValue) {
|
||||
[...child.nodeValue].forEach((c) => {
|
||||
child.parentNode.insertBefore(createTextNode(c), child);
|
||||
});
|
||||
|
||||
child.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
expandTextNodes(child as El);
|
||||
});
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
export default expandTextNodes;
|
||||
87
node_modules/typeit/src/helpers/fireItem.ts
generated
vendored
Normal file
87
node_modules/typeit/src/helpers/fireItem.ts
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
import { CursorOptions, El, QueueItem, QueueMapPair } from "../types";
|
||||
import beforePaint from "./beforePaint";
|
||||
import getAnimationFromElement from "./getAnimationFromElement";
|
||||
import rebuildCursorAnimation from "./rebuildCursorAnimation";
|
||||
|
||||
let execute = (queueItem: QueueItem) => queueItem.func?.call(null);
|
||||
|
||||
interface FireItemArgs {
|
||||
index: number;
|
||||
queueItems: QueueMapPair[];
|
||||
wait: (...args: any) => Promise<void>;
|
||||
cursor: El | undefined;
|
||||
cursorOptions: CursorOptions;
|
||||
}
|
||||
|
||||
let fireItem = async ({
|
||||
index,
|
||||
queueItems,
|
||||
wait,
|
||||
cursor,
|
||||
cursorOptions,
|
||||
}: FireItemArgs): Promise<number> => {
|
||||
let queueItem = queueItems[index][1];
|
||||
let instantQueue = [];
|
||||
let tempIndex = index;
|
||||
let futureItem = queueItem;
|
||||
let shouldBeGrouped = () => futureItem && !futureItem.delay;
|
||||
let shouldPauseCursor =
|
||||
queueItem.shouldPauseCursor() && cursorOptions.autoPause;
|
||||
|
||||
// Crawl through the queue and group together all items that
|
||||
// do not have have a delay and can be executed instantly.
|
||||
while (shouldBeGrouped()) {
|
||||
instantQueue.push(futureItem);
|
||||
|
||||
shouldBeGrouped() && tempIndex++;
|
||||
futureItem = queueItems[tempIndex] ? queueItems[tempIndex][1] : null;
|
||||
}
|
||||
|
||||
if (instantQueue.length) {
|
||||
// All are executed together before the browser has a chance to repaint.
|
||||
await beforePaint(async () => {
|
||||
for (let q of instantQueue) {
|
||||
await execute(q);
|
||||
}
|
||||
});
|
||||
|
||||
// Important! Because we moved into the future, the index
|
||||
// needs to be modified and returned for accurate remaining execution.
|
||||
return tempIndex - 1;
|
||||
}
|
||||
|
||||
// An animation is only registered on the cursor when it's made visible.
|
||||
// If the cursor has been disabled, there won't be one here.
|
||||
let animation = getAnimationFromElement(cursor);
|
||||
let options;
|
||||
|
||||
if (animation) {
|
||||
options = {
|
||||
...animation.effect.getComputedTiming(),
|
||||
delay: shouldPauseCursor ? cursorOptions.autoPauseDelay : 0,
|
||||
};
|
||||
}
|
||||
|
||||
await wait(async () => {
|
||||
// If it's a qualified queue item, pause the cursor at the
|
||||
// beginning of the item's execution by destroying the aniatmion.
|
||||
// Immediately after completing, the animation will be recreated (with a delay).
|
||||
if (animation && shouldPauseCursor) {
|
||||
animation.cancel();
|
||||
}
|
||||
|
||||
await beforePaint(() => {
|
||||
execute(queueItem);
|
||||
});
|
||||
}, queueItem.delay);
|
||||
|
||||
await rebuildCursorAnimation({
|
||||
cursor,
|
||||
options,
|
||||
cursorOptions,
|
||||
});
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
export default fireItem;
|
||||
15
node_modules/typeit/src/helpers/fireWhenVisible.ts
generated
vendored
Normal file
15
node_modules/typeit/src/helpers/fireWhenVisible.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export default (element: HTMLElement, func: Function): void => {
|
||||
let observer = new IntersectionObserver(
|
||||
(entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
func();
|
||||
observer.unobserve(element);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ threshold: 1.0 }
|
||||
);
|
||||
|
||||
observer.observe(element);
|
||||
};
|
||||
1
node_modules/typeit/src/helpers/generateHash.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/generateHash.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (): string => Math.random().toString().substring(2, 9);
|
||||
20
node_modules/typeit/src/helpers/getAllChars.ts
generated
vendored
Normal file
20
node_modules/typeit/src/helpers/getAllChars.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import isInput from "./isInput";
|
||||
import { El } from "../types";
|
||||
import toArray from "./toArray";
|
||||
import { walkElementNodes } from "./chunkStrings";
|
||||
|
||||
/**
|
||||
* Get a flattened array of text nodes that have been typed.
|
||||
* This excludes any cursor character that might exist.
|
||||
*/
|
||||
let getAllChars = (element: El) => {
|
||||
if (isInput(element)) {
|
||||
return toArray(element.value);
|
||||
}
|
||||
|
||||
return walkElementNodes(element, true).filter(
|
||||
(c) => !(c.childNodes.length > 0)
|
||||
);
|
||||
};
|
||||
|
||||
export default getAllChars;
|
||||
9
node_modules/typeit/src/helpers/getAnimationFromElement.ts
generated
vendored
Normal file
9
node_modules/typeit/src/helpers/getAnimationFromElement.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { El } from "../types";
|
||||
|
||||
let getAnimationFromElement = (element: El): Animation | undefined => {
|
||||
return element?.getAnimations().find((animation) => {
|
||||
return animation.id === element.dataset.tiAnimationId;
|
||||
});
|
||||
};
|
||||
|
||||
export default getAnimationFromElement;
|
||||
1
node_modules/typeit/src/helpers/getComputedStyle.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/getComputedStyle.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (el): CSSStyleDeclaration => window.getComputedStyle(el, null);
|
||||
13
node_modules/typeit/src/helpers/getParsedBody.ts
generated
vendored
Normal file
13
node_modules/typeit/src/helpers/getParsedBody.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { El } from "../types";
|
||||
import expandTextNodes from "./expandTextNodes";
|
||||
|
||||
/**
|
||||
* Parse a string as HTML and return the body
|
||||
* of the parsed document, with all text nodes expanded.
|
||||
*/
|
||||
export default (content): El => {
|
||||
let doc = document.implementation.createHTMLDocument();
|
||||
doc.body.innerHTML = content;
|
||||
|
||||
return expandTextNodes(doc.body as El);
|
||||
};
|
||||
5
node_modules/typeit/src/helpers/handleFunctionalArg.ts
generated
vendored
Normal file
5
node_modules/typeit/src/helpers/handleFunctionalArg.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
let handleFunctionalArg = <T>(arg: any | (() => T)): T => {
|
||||
return typeof arg === "function" ? arg() : arg;
|
||||
};
|
||||
|
||||
export default handleFunctionalArg;
|
||||
32
node_modules/typeit/src/helpers/insertIntoElement.ts
generated
vendored
Normal file
32
node_modules/typeit/src/helpers/insertIntoElement.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import isInput from "./isInput";
|
||||
import select from "./select";
|
||||
import { CURSOR_CLASS } from "../constants";
|
||||
import { El } from "../types";
|
||||
import isBodyElement from "./isBodyElement";
|
||||
|
||||
/**
|
||||
* Inserts a set of content into the element. Intended for SINGLE characters.
|
||||
*/
|
||||
let insertIntoElement = (originalTarget: El, character: El) => {
|
||||
if (isInput(originalTarget)) {
|
||||
originalTarget.value = `${originalTarget.value}${character.textContent}`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Necessary for creating *empty* elements that will
|
||||
// later be filled with actual characters.
|
||||
character.innerHTML = "";
|
||||
|
||||
let target = isBodyElement(character.originalParent as El)
|
||||
? originalTarget
|
||||
: // If we add one-off fresh elements, there will be no
|
||||
// "originalParent", so always fall back to the default target.
|
||||
character.originalParent || originalTarget;
|
||||
|
||||
target.insertBefore(
|
||||
character as El,
|
||||
(select("." + CURSOR_CLASS, target) as Node) || null
|
||||
);
|
||||
};
|
||||
|
||||
export default insertIntoElement;
|
||||
1
node_modules/typeit/src/helpers/isArray.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/isArray.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (thing: any): boolean => Array.isArray(thing);
|
||||
5
node_modules/typeit/src/helpers/isBodyElement.ts
generated
vendored
Normal file
5
node_modules/typeit/src/helpers/isBodyElement.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { El } from "../types";
|
||||
|
||||
let isBodyElement = (node: El): boolean => /body/i.test(node?.tagName);
|
||||
|
||||
export default isBodyElement;
|
||||
1
node_modules/typeit/src/helpers/isInput.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/isInput.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (el: HTMLElement): boolean => "value" in el;
|
||||
1
node_modules/typeit/src/helpers/isNonVoidElement.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/isNonVoidElement.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (el) => /<(.+)>(.*?)<\/(.+)>/.test(el.outerHTML);
|
||||
1
node_modules/typeit/src/helpers/isNumber.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/isNumber.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (value: any): boolean => Number.isInteger(value);
|
||||
1
node_modules/typeit/src/helpers/merge.ts
generated
vendored
Normal file
1
node_modules/typeit/src/helpers/merge.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (originalObj, newObj) => Object.assign({}, originalObj, newObj);
|
||||
35
node_modules/typeit/src/helpers/processCursorOptions.ts
generated
vendored
Normal file
35
node_modules/typeit/src/helpers/processCursorOptions.ts
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import { DEFAULT_OPTIONS } from "../constants";
|
||||
import { CursorOptions } from "../types";
|
||||
import merge from "./merge";
|
||||
|
||||
let processCursorOptions = (
|
||||
cursorOptions: boolean | CursorOptions
|
||||
): boolean | CursorOptions => {
|
||||
if (typeof cursorOptions === "object") {
|
||||
let newOptions: CursorOptions = {};
|
||||
let { frames: defaultFrames, options: defaultOptions } =
|
||||
DEFAULT_OPTIONS.cursor.animation;
|
||||
|
||||
newOptions.animation = cursorOptions.animation || {};
|
||||
newOptions.animation.frames =
|
||||
cursorOptions.animation?.frames || defaultFrames;
|
||||
newOptions.animation.options = merge(
|
||||
defaultOptions,
|
||||
cursorOptions.animation?.options || {}
|
||||
);
|
||||
newOptions.autoPause =
|
||||
cursorOptions.autoPause ?? DEFAULT_OPTIONS.cursor.autoPause;
|
||||
newOptions.autoPauseDelay =
|
||||
cursorOptions.autoPauseDelay || DEFAULT_OPTIONS.cursor.autoPauseDelay;
|
||||
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
if (cursorOptions === true) {
|
||||
return DEFAULT_OPTIONS.cursor;
|
||||
}
|
||||
|
||||
return cursorOptions;
|
||||
};
|
||||
|
||||
export default processCursorOptions;
|
||||
5
node_modules/typeit/src/helpers/randomInRange.ts
generated
vendored
Normal file
5
node_modules/typeit/src/helpers/randomInRange.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export default (value: number, range: number): number => {
|
||||
return Math.abs(
|
||||
Math.random() * (value + range - (value - range)) + (value - range)
|
||||
);
|
||||
};
|
||||
49
node_modules/typeit/src/helpers/rebuildCursorAnimation.ts
generated
vendored
Normal file
49
node_modules/typeit/src/helpers/rebuildCursorAnimation.ts
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { El, CursorOptions } from "../types";
|
||||
import getAnimationFromElement from "./getAnimationFromElement";
|
||||
import setCursorAnimation from "./setCursorAnimation";
|
||||
|
||||
interface rebuildCursorAnimationArgs {
|
||||
cursor: El | undefined;
|
||||
cursorOptions: CursorOptions;
|
||||
options: any;
|
||||
}
|
||||
|
||||
let rebuildCursorAnimation = ({
|
||||
cursor,
|
||||
options,
|
||||
cursorOptions,
|
||||
}: rebuildCursorAnimationArgs): Animation => {
|
||||
if (!cursor || !cursorOptions) return;
|
||||
|
||||
let animation = getAnimationFromElement(cursor);
|
||||
let oldCurrentTime: number;
|
||||
|
||||
// An existing animation is actively running...
|
||||
// so carry over the timing properties we care about.
|
||||
if (animation) {
|
||||
options.delay = animation.effect.getComputedTiming().delay;
|
||||
|
||||
// This needs to be set later, since there's no way to pass
|
||||
// the current time into the constructor.
|
||||
oldCurrentTime = animation.currentTime;
|
||||
animation.cancel();
|
||||
}
|
||||
|
||||
// Create a new animation using the same
|
||||
// configuration as the previous one.
|
||||
let newAnimation = setCursorAnimation({
|
||||
cursor,
|
||||
frames: cursorOptions.animation.frames,
|
||||
options,
|
||||
});
|
||||
|
||||
// By setting the currentTime, the animation will
|
||||
// be in sync with the previous one.
|
||||
if (oldCurrentTime) {
|
||||
newAnimation.currentTime = oldCurrentTime;
|
||||
}
|
||||
|
||||
return newAnimation;
|
||||
};
|
||||
|
||||
export default rebuildCursorAnimation;
|
||||
16
node_modules/typeit/src/helpers/removeNode.ts
generated
vendored
Normal file
16
node_modules/typeit/src/helpers/removeNode.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { El } from "../types";
|
||||
|
||||
export default (node: Node, rootElement: El): void => {
|
||||
if (!node) return;
|
||||
|
||||
let nodeParent = node.parentNode as HTMLElement;
|
||||
let nodeToRemove =
|
||||
nodeParent.childNodes.length > 1 || nodeParent.isSameNode(rootElement)
|
||||
? // This parent still needs to exist.
|
||||
node
|
||||
: // There's nothing else in there, so just delete the entire thing.
|
||||
// By doing this, we clean up markup as we go along.
|
||||
nodeParent;
|
||||
|
||||
(nodeToRemove as Element).remove();
|
||||
};
|
||||
15
node_modules/typeit/src/helpers/repositionCursor.ts
generated
vendored
Normal file
15
node_modules/typeit/src/helpers/repositionCursor.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { CURSOR_CLASS } from "../constants";
|
||||
import select from "./select";
|
||||
import { El } from "../types";
|
||||
|
||||
export default (
|
||||
element: HTMLElement,
|
||||
allChars: any[],
|
||||
newCursorPosition: number
|
||||
): void => {
|
||||
let nodeToInsertBefore = allChars[newCursorPosition - 1];
|
||||
let cursor = select(`.${CURSOR_CLASS}`, element) as El;
|
||||
element = nodeToInsertBefore?.parentNode || element;
|
||||
|
||||
element.insertBefore(cursor as any, nodeToInsertBefore || null);
|
||||
};
|
||||
9
node_modules/typeit/src/helpers/select.ts
generated
vendored
Normal file
9
node_modules/typeit/src/helpers/select.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
let select = (
|
||||
selector: string,
|
||||
element: Node = document,
|
||||
all: boolean = false
|
||||
): Node | NodeList | null => {
|
||||
return element[`querySelector${all ? "All" : ""}`](selector);
|
||||
};
|
||||
|
||||
export default select;
|
||||
6
node_modules/typeit/src/helpers/selectorToElement.ts
generated
vendored
Normal file
6
node_modules/typeit/src/helpers/selectorToElement.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { El } from "../types";
|
||||
import select from "./select";
|
||||
|
||||
export default function (thing: string | El): El {
|
||||
return typeof thing === "string" ? (select(thing as string) as El) : thing;
|
||||
}
|
||||
34
node_modules/typeit/src/helpers/setCursorAnimation.ts
generated
vendored
Normal file
34
node_modules/typeit/src/helpers/setCursorAnimation.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { El } from "../types";
|
||||
import beforePaint from "./beforePaint";
|
||||
|
||||
/**
|
||||
* Create and return an animation for the cursor.
|
||||
*/
|
||||
let setCursorAnimation = ({
|
||||
cursor,
|
||||
frames,
|
||||
options,
|
||||
}: {
|
||||
cursor: El;
|
||||
frames: AnimationKeyFrame[];
|
||||
options: Partial<AnimationEffectTiming>;
|
||||
}): Animation => {
|
||||
let animation = cursor.animate(frames, options);
|
||||
|
||||
animation.pause();
|
||||
|
||||
animation.id = cursor.dataset.tiAnimationId;
|
||||
|
||||
// Kicking back the animation until after the next repaint
|
||||
// prevents odd freezing issues when a new animation is
|
||||
// generated in place of an older one.
|
||||
beforePaint(() => {
|
||||
beforePaint(() => {
|
||||
animation.play();
|
||||
});
|
||||
});
|
||||
|
||||
return animation;
|
||||
};
|
||||
|
||||
export default setCursorAnimation;
|
||||
33
node_modules/typeit/src/helpers/setCursorStyles.ts
generated
vendored
Normal file
33
node_modules/typeit/src/helpers/setCursorStyles.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { CURSOR_CLASS, DATA_ATTRIBUTE } from "../constants";
|
||||
import { El } from "../types";
|
||||
import appendStyleBlock from "./appendStyleBlock";
|
||||
|
||||
export let cursorFontStyles = {
|
||||
"font-family": "",
|
||||
"font-weight": "",
|
||||
"font-size": "",
|
||||
"font-style": "",
|
||||
"line-height": "",
|
||||
color: "",
|
||||
transform: "translateX(-.125em)",
|
||||
} as const;
|
||||
|
||||
export let setCursorStyles = (id: string, element: El) => {
|
||||
let rootSelector = `[${DATA_ATTRIBUTE}='${id}']`;
|
||||
let cursorSelector = `${rootSelector} .${CURSOR_CLASS}`;
|
||||
let computedStyles = getComputedStyle(element);
|
||||
let customProperties: string = Object.entries(cursorFontStyles).reduce(
|
||||
(accumulator, [item, value]) => {
|
||||
return `${accumulator} ${item}: var(--ti-cursor-${item}, ${
|
||||
value || computedStyles[item]
|
||||
});`;
|
||||
},
|
||||
""
|
||||
);
|
||||
|
||||
// Set animation styles & custom properties.
|
||||
appendStyleBlock(
|
||||
`${cursorSelector} { display: inline-block; width: 0; ${customProperties} }`,
|
||||
id
|
||||
);
|
||||
};
|
||||
8
node_modules/typeit/src/helpers/toArray.ts
generated
vendored
Normal file
8
node_modules/typeit/src/helpers/toArray.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Literally just wraps toArray() to save a few bytes
|
||||
* when it's repeatedly used.
|
||||
*
|
||||
* @param {any}
|
||||
* @return {array}
|
||||
*/
|
||||
export default (val): any[] => Array.from(val);
|
||||
12
node_modules/typeit/src/helpers/updateCursorPosition.ts
generated
vendored
Normal file
12
node_modules/typeit/src/helpers/updateCursorPosition.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
let updateCursorPosition = (
|
||||
steps: number,
|
||||
cursorPosition: number,
|
||||
printedCharacters: Element[]
|
||||
) => {
|
||||
return Math.min(
|
||||
Math.max(cursorPosition + steps, 0),
|
||||
printedCharacters.length
|
||||
);
|
||||
};
|
||||
|
||||
export default updateCursorPosition;
|
||||
20
node_modules/typeit/src/helpers/wait.ts
generated
vendored
Normal file
20
node_modules/typeit/src/helpers/wait.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Fire a callback after a delay, and add the timeout ID to a referenced array.
|
||||
*/
|
||||
let wait = (
|
||||
callback: Function,
|
||||
delay: number | undefined,
|
||||
timeouts: number[]
|
||||
) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
let cb = async () => {
|
||||
await callback();
|
||||
|
||||
resolve();
|
||||
};
|
||||
|
||||
timeouts.push(setTimeout(cb, delay || 0) as unknown as number);
|
||||
});
|
||||
};
|
||||
|
||||
export default wait;
|
||||
682
node_modules/typeit/src/index.ts
generated
vendored
Normal file
682
node_modules/typeit/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,682 @@
|
||||
import Queue from "./Queue";
|
||||
import { maybeChunkStringAsHtml } from "./helpers/chunkStrings";
|
||||
import expandTextNodes from "./helpers/expandTextNodes";
|
||||
import appendStyleBlock from "./helpers/appendStyleBlock";
|
||||
import asArray from "./helpers/asArray";
|
||||
import calculateDelay from "./helpers/calculateDelay";
|
||||
import calculatePace from "./helpers/calculatePace";
|
||||
import createElement from "./helpers/createElement";
|
||||
import destroyTimeouts from "./helpers/destroyTimeouts";
|
||||
import generateHash from "./helpers/generateHash";
|
||||
import getAllChars from "./helpers/getAllChars";
|
||||
import fireWhenVisible from "./helpers/fireWhenVisible";
|
||||
import getParsedBody from "./helpers/getParsedBody";
|
||||
import handleFunctionalArg from "./helpers/handleFunctionalArg";
|
||||
import isNumber from "./helpers/isNumber";
|
||||
import insertIntoElement from "./helpers/insertIntoElement";
|
||||
import isInput from "./helpers/isInput";
|
||||
import updateCursorPosition from "./helpers/updateCursorPosition";
|
||||
import merge from "./helpers/merge";
|
||||
import removeNode from "./helpers/removeNode";
|
||||
import repositionCursor from "./helpers/repositionCursor";
|
||||
import selectorToElement from "./helpers/selectorToElement";
|
||||
import isNonVoidElement from "./helpers/isNonVoidElement";
|
||||
import wait from "./helpers/wait";
|
||||
import { setCursorStyles } from "./helpers/setCursorStyles";
|
||||
import {
|
||||
El,
|
||||
Options,
|
||||
QueueItem,
|
||||
ActionOpts,
|
||||
TypeItInstance,
|
||||
QueueMapPair,
|
||||
CursorOptions,
|
||||
} from "./types";
|
||||
import {
|
||||
CURSOR_CLASS,
|
||||
DEFAULT_STATUSES,
|
||||
DEFAULT_OPTIONS,
|
||||
PLACEHOLDER_CSS,
|
||||
} from "./constants";
|
||||
import duplicate from "./helpers/duplicate";
|
||||
import countStepsToSelector from "./helpers/countStepsToSelector";
|
||||
import fireItem from "./helpers/fireItem";
|
||||
import setCursorAnimation from "./helpers/setCursorAnimation";
|
||||
import processCursorOptions from "./helpers/processCursorOptions";
|
||||
|
||||
// Necessary for publicly exposing types.
|
||||
export declare type TypeItOptions = Options;
|
||||
|
||||
const TypeIt: TypeItInstance = function (element, options = {}) {
|
||||
let _wait = async (
|
||||
callback: Function,
|
||||
delay: number | undefined,
|
||||
silent: boolean = false
|
||||
): Promise<void> => {
|
||||
if (_statuses.frozen) {
|
||||
await new Promise<void>((resolve) => {
|
||||
this.unfreeze = () => {
|
||||
_statuses.frozen = false;
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
silent || (await _opts.beforeStep(this));
|
||||
|
||||
await wait(callback, delay, _timeouts);
|
||||
|
||||
silent || (await _opts.afterStep(this));
|
||||
};
|
||||
|
||||
let _fireItemWithContext = (
|
||||
index: number,
|
||||
queueItems: QueueMapPair[]
|
||||
): Promise<number> => {
|
||||
return fireItem({
|
||||
index,
|
||||
queueItems,
|
||||
wait: _wait,
|
||||
cursor: _cursor as El,
|
||||
cursorOptions: _opts.cursor as CursorOptions,
|
||||
});
|
||||
};
|
||||
|
||||
let _removeNode = (node) => removeNode(node, _element);
|
||||
|
||||
let _elementIsInput = () => isInput(_element);
|
||||
|
||||
let _getPace = (index: number = 0): number => calculatePace(_opts)[index];
|
||||
|
||||
let _getAllChars = (): El[] => getAllChars(_element);
|
||||
|
||||
let _maybeAppendPause = (opts: ActionOpts = {}) => {
|
||||
let delay = opts.delay;
|
||||
delay && _queue.add({ delay });
|
||||
};
|
||||
|
||||
let _queueAndReturn = (steps: QueueItem[] | QueueItem, opts: ActionOpts) => {
|
||||
_queue.add(steps);
|
||||
_maybeAppendPause(opts);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
let _getDerivedCursorPosition = () =>
|
||||
_predictedCursorPosition ?? _cursorPosition;
|
||||
|
||||
let _generateTemporaryOptionQueueItems = (
|
||||
newOptions: Options = {}
|
||||
): QueueItem[] => {
|
||||
return [
|
||||
{ func: () => _options(newOptions) },
|
||||
{ func: () => _options(_opts) },
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Add items to the queue with a split pause
|
||||
* wrapped around them.
|
||||
*/
|
||||
let _addSplitPause = (items: QueueItem[]) => {
|
||||
let delay = _opts.nextStringDelay;
|
||||
|
||||
_queue.add([{ delay: delay[0] }, ...items, { delay: delay[1] }]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provided it's a non-form element and the options is provided,
|
||||
* set up the cursor element for the
|
||||
*/
|
||||
let _setUpCursor = (): void | El => {
|
||||
if (_elementIsInput()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a cursor node from a previous instance (prior to a reset()),
|
||||
// there's no need to recreate one now.
|
||||
let cursor = createElement("span");
|
||||
cursor.className = CURSOR_CLASS;
|
||||
|
||||
// Don't bother touching up the cursor if we don't want it to visibly render anyway.
|
||||
if (!_shouldRenderCursor) {
|
||||
cursor.style.visibility = "hidden";
|
||||
|
||||
return cursor as El;
|
||||
}
|
||||
|
||||
cursor.innerHTML = getParsedBody(_opts.cursorChar).innerHTML;
|
||||
|
||||
return cursor as El;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attach it to the DOM so, along with the required CSS transition.
|
||||
*/
|
||||
let _attachCursor = async () => {
|
||||
!_elementIsInput() && _cursor && _element.appendChild(_cursor);
|
||||
|
||||
if (_shouldRenderCursor) {
|
||||
setCursorStyles(_id, _element);
|
||||
|
||||
(_cursor as El).dataset.tiAnimationId = _id;
|
||||
|
||||
let { animation } = _opts.cursor as CursorOptions;
|
||||
let { frames, options } = animation;
|
||||
|
||||
setCursorAnimation({
|
||||
frames,
|
||||
cursor: _cursor as El,
|
||||
options: {
|
||||
duration: _opts.cursorSpeed,
|
||||
...options,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Based on provided strings, generate a TypeIt queue
|
||||
* to be fired for each character in the string.
|
||||
*/
|
||||
let _generateQueue = () => {
|
||||
let strings = (_opts.strings as string[]).filter((string) => !!string);
|
||||
|
||||
strings.forEach((string, index) => {
|
||||
this.type(string);
|
||||
|
||||
// This is the last string. Get outta here.
|
||||
if (index + 1 === strings.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let splitItems: QueueItem[] = _opts.breakLines
|
||||
? [{ func: () => _type(createElement("BR")), typeable: true }]
|
||||
: duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1),
|
||||
},
|
||||
_queue.getTypeable().length
|
||||
);
|
||||
|
||||
_addSplitPause(splitItems);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 1. Reset queue.
|
||||
* 2. Reset initial pause.
|
||||
*/
|
||||
let _prepLoop = async (delay: number) => {
|
||||
let derivedCursorPosition = _getDerivedCursorPosition();
|
||||
derivedCursorPosition && (await _move({ value: derivedCursorPosition }));
|
||||
|
||||
// Grab all characters currently mounted to the DOM,
|
||||
// in order to wipe the slate clean before restarting.
|
||||
//
|
||||
// It's important to first convert each deletion to a
|
||||
// queue item, so that we can take advantage of the same
|
||||
// cursor-pausing logic (and anything else that might be
|
||||
// introduced in the future).
|
||||
let queueItems: QueueMapPair[] = _getAllChars().map((c) => {
|
||||
return [
|
||||
Symbol(),
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1),
|
||||
deletable: true,
|
||||
shouldPauseCursor: () => true,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
for (let index = 0; index < queueItems.length; index++) {
|
||||
await _fireItemWithContext(index, queueItems);
|
||||
}
|
||||
|
||||
_queue.reset();
|
||||
_queue.set(0, { delay });
|
||||
};
|
||||
|
||||
let _maybePrependHardcodedStrings = (strings): string[] => {
|
||||
let existingMarkup = _element.innerHTML;
|
||||
|
||||
if (!existingMarkup) {
|
||||
return strings;
|
||||
}
|
||||
|
||||
// Once we've saved the existing markup to a variable,
|
||||
// wipe the element clean to prepare for typing.
|
||||
_element.innerHTML = "";
|
||||
|
||||
if (_opts.startDelete) {
|
||||
_element.innerHTML = existingMarkup;
|
||||
|
||||
expandTextNodes(_element);
|
||||
|
||||
_addSplitPause(
|
||||
duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: _getPace(1),
|
||||
deletable: true,
|
||||
},
|
||||
_getAllChars().length
|
||||
)
|
||||
);
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
let hardCodedStrings = existingMarkup
|
||||
.replace(/<!--(.+?)-->/g, "")
|
||||
.trim()
|
||||
.split(/<br(?:\s*?)(?:\/)?>/);
|
||||
|
||||
return hardCodedStrings.concat(strings);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute items in the queue.
|
||||
*
|
||||
* @param remember If false, each queue item will be destroyed once executed.
|
||||
* @returns
|
||||
*/
|
||||
let _fire = async (remember = true): Promise<TypeItInstance> => {
|
||||
_statuses.started = true;
|
||||
|
||||
// @todo remove this eventually..
|
||||
// console.log(
|
||||
// "Total time:",
|
||||
// queueItems.reduce((total, step) => {
|
||||
// total = total + step.delay;
|
||||
|
||||
// return total;
|
||||
// }, 0)
|
||||
// );
|
||||
|
||||
let cleanUp = (qKey) => {
|
||||
_queue.done(qKey, !remember);
|
||||
};
|
||||
|
||||
try {
|
||||
let queueItems = [..._queue.getQueue()] as QueueMapPair[];
|
||||
|
||||
for (let index = 0; index < queueItems.length; index++) {
|
||||
let [queueKey, queueItem] = queueItems[index];
|
||||
|
||||
// Only execute items that aren't done yet.
|
||||
if (queueItem.done) continue;
|
||||
|
||||
// Because calling .delete() with no parameters will attempt to
|
||||
// delete all "typeable" characters, we may overfetch, since some characters
|
||||
// in the queue may already be deleted. This ensures that we do not attempt to
|
||||
// delete a character that isn't actually mounted to the DOM.
|
||||
if (
|
||||
!queueItem.deletable ||
|
||||
(queueItem.deletable && _getAllChars().length)
|
||||
) {
|
||||
let newIndex = await _fireItemWithContext(index, queueItems);
|
||||
|
||||
// Ensure each skipped item goes through the cleanup process,
|
||||
// so that methods like .flush() don't get messed up.
|
||||
Array(newIndex - index)
|
||||
.fill(index + 1)
|
||||
.map((x, y) => x + y)
|
||||
.forEach((i) => {
|
||||
let [key] = queueItems[i];
|
||||
|
||||
cleanUp(key);
|
||||
});
|
||||
|
||||
index = newIndex;
|
||||
}
|
||||
|
||||
cleanUp(queueKey);
|
||||
}
|
||||
|
||||
if (!remember) {
|
||||
return this;
|
||||
}
|
||||
|
||||
_statuses.completed = true;
|
||||
|
||||
await _opts.afterComplete(this);
|
||||
|
||||
if (!_opts.loop) {
|
||||
throw "";
|
||||
}
|
||||
|
||||
let delay = _opts.loopDelay;
|
||||
|
||||
_wait(async () => {
|
||||
await _prepLoop(delay[0]);
|
||||
_fire();
|
||||
}, delay[1]);
|
||||
} catch (e) {}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Move type cursor by a given number.
|
||||
*/
|
||||
let _move = async (step): Promise<void> => {
|
||||
_cursorPosition = updateCursorPosition(
|
||||
step,
|
||||
_cursorPosition,
|
||||
_getAllChars()
|
||||
);
|
||||
|
||||
repositionCursor(_element, _getAllChars(), _cursorPosition);
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert a single or many characters into the target element.
|
||||
*/
|
||||
let _type = (char): void => insertIntoElement(_element, char);
|
||||
|
||||
let _options = async (opts) => (_opts = merge(_opts, opts));
|
||||
|
||||
let _empty = async () => {
|
||||
if (_elementIsInput()) {
|
||||
_element.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
_getAllChars().forEach(_removeNode);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
let _delete = (): void => {
|
||||
let allChars = _getAllChars();
|
||||
|
||||
if (!allChars.length) return;
|
||||
|
||||
if (_elementIsInput()) {
|
||||
_element.value = (_element.value as string).slice(0, -1);
|
||||
} else {
|
||||
_removeNode(allChars[_cursorPosition]);
|
||||
}
|
||||
};
|
||||
|
||||
this.break = function (actionOpts: ActionOpts) {
|
||||
return _queueAndReturn(
|
||||
{
|
||||
func: () => _type(createElement("BR")),
|
||||
typeable: true,
|
||||
},
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
|
||||
this.delete = function (
|
||||
numCharacters: number | string | (() => number | null) = null,
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
numCharacters = handleFunctionalArg<number>(numCharacters);
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let num = numCharacters;
|
||||
let { instant, to } = actionOpts;
|
||||
let typeableQueueItems = _queue.getTypeable();
|
||||
|
||||
let rounds = (() => {
|
||||
if (num === null) {
|
||||
return typeableQueueItems.length;
|
||||
}
|
||||
|
||||
if (isNumber(num)) {
|
||||
return num;
|
||||
}
|
||||
|
||||
return countStepsToSelector({
|
||||
queueItems: typeableQueueItems,
|
||||
selector: num,
|
||||
cursorPosition: _getDerivedCursorPosition(),
|
||||
to,
|
||||
});
|
||||
})();
|
||||
|
||||
return _queueAndReturn(
|
||||
[
|
||||
bookEndQueueItems[0],
|
||||
...duplicate(
|
||||
{
|
||||
func: _delete,
|
||||
delay: instant ? 0 : _getPace(1),
|
||||
deletable: true,
|
||||
},
|
||||
rounds
|
||||
),
|
||||
bookEndQueueItems[1],
|
||||
],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
|
||||
this.empty = function (actionOpts: ActionOpts = {}) {
|
||||
return _queueAndReturn({ func: _empty }, actionOpts);
|
||||
};
|
||||
|
||||
this.exec = function (
|
||||
func: (instance: TypeItInstance) => any,
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
|
||||
return _queueAndReturn(
|
||||
[bookEndQueueItems[0], { func: () => func(this) }, bookEndQueueItems[1]],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
|
||||
this.move = function (
|
||||
movementArg: string | number | (() => string | number),
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
movementArg = handleFunctionalArg<string | number>(movementArg);
|
||||
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let { instant, to } = actionOpts;
|
||||
|
||||
let numberOfSteps = countStepsToSelector({
|
||||
queueItems: _queue.getTypeable(),
|
||||
selector: movementArg === null ? "" : movementArg,
|
||||
to,
|
||||
cursorPosition: _getDerivedCursorPosition(),
|
||||
});
|
||||
let directionalStep = numberOfSteps < 0 ? -1 : 1;
|
||||
|
||||
_predictedCursorPosition = _getDerivedCursorPosition() + numberOfSteps;
|
||||
|
||||
return _queueAndReturn(
|
||||
[
|
||||
bookEndQueueItems[0],
|
||||
...duplicate(
|
||||
{
|
||||
func: () => _move(directionalStep),
|
||||
delay: instant ? 0 : _getPace(),
|
||||
cursorable: true,
|
||||
},
|
||||
Math.abs(numberOfSteps)
|
||||
),
|
||||
bookEndQueueItems[1],
|
||||
],
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
|
||||
this.options = function (
|
||||
opts: Options | (() => Options),
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
opts = handleFunctionalArg<Options>(opts);
|
||||
|
||||
_options(opts);
|
||||
|
||||
return _queueAndReturn({}, actionOpts);
|
||||
};
|
||||
|
||||
this.pause = function (
|
||||
milliseconds: number | (() => number),
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
return _queueAndReturn(
|
||||
{ delay: handleFunctionalArg<number>(milliseconds) },
|
||||
actionOpts
|
||||
);
|
||||
};
|
||||
|
||||
this.type = function (
|
||||
string: string | (() => string),
|
||||
actionOpts: ActionOpts = {}
|
||||
) {
|
||||
string = handleFunctionalArg<string>(string);
|
||||
|
||||
let { instant } = actionOpts;
|
||||
let bookEndQueueItems = _generateTemporaryOptionQueueItems(actionOpts);
|
||||
let chars = maybeChunkStringAsHtml(string, _opts.html);
|
||||
|
||||
let charsAsQueueItems = chars.map((char): QueueItem => {
|
||||
return {
|
||||
func: () => _type(char),
|
||||
char,
|
||||
delay: instant || isNonVoidElement(char) ? 0 : _getPace(),
|
||||
typeable: char.nodeType === Node.TEXT_NODE,
|
||||
};
|
||||
});
|
||||
|
||||
let itemsToQueue = [
|
||||
bookEndQueueItems[0],
|
||||
{ func: async () => await _opts.beforeString(string, this) },
|
||||
...charsAsQueueItems,
|
||||
{ func: async () => await _opts.afterString(string, this) },
|
||||
bookEndQueueItems[1],
|
||||
];
|
||||
|
||||
return _queueAndReturn(itemsToQueue, actionOpts);
|
||||
};
|
||||
|
||||
this.is = function (key): boolean {
|
||||
return _statuses[key];
|
||||
};
|
||||
|
||||
this.destroy = function (shouldRemoveCursor = true) {
|
||||
_timeouts = destroyTimeouts(_timeouts);
|
||||
handleFunctionalArg<boolean>(shouldRemoveCursor) &&
|
||||
_cursor &&
|
||||
_removeNode(_cursor);
|
||||
_statuses.destroyed = true;
|
||||
};
|
||||
|
||||
this.freeze = function () {
|
||||
_statuses.frozen = true;
|
||||
};
|
||||
|
||||
this.unfreeze = () => {};
|
||||
|
||||
this.reset = function (rebuild: ((TypeIt) => typeof TypeIt) | undefined) {
|
||||
!this.is("destroyed") && this.destroy();
|
||||
|
||||
// If provided, the queue can be totally regenerated.
|
||||
if (rebuild) {
|
||||
_queue.wipe();
|
||||
rebuild(this);
|
||||
} else {
|
||||
_queue.reset();
|
||||
}
|
||||
|
||||
_cursorPosition = 0;
|
||||
|
||||
for (let property in _statuses) {
|
||||
_statuses[property] = false;
|
||||
}
|
||||
|
||||
_element[_elementIsInput() ? "value" : "innerHTML"] = "";
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Can only be called once.
|
||||
*/
|
||||
this.go = function () {
|
||||
if (_statuses.started) {
|
||||
return this;
|
||||
}
|
||||
|
||||
_attachCursor();
|
||||
|
||||
if (!_opts.waitUntilVisible) {
|
||||
_fire();
|
||||
return this;
|
||||
}
|
||||
|
||||
fireWhenVisible(_element, _fire.bind(this));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Like `.go()`, but more... "off the grid."
|
||||
*
|
||||
* - won't trigger `afterComplete` callback
|
||||
* - items won't be replayed after `.reset()`
|
||||
*
|
||||
* When called, all non-done items will be "flushed" --
|
||||
* that is, executed, but not remembered.
|
||||
*/
|
||||
this.flush = function (cb: () => any = () => {}) {
|
||||
_attachCursor();
|
||||
|
||||
_fire(false).then(cb);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
this.getQueue = () => _queue;
|
||||
this.getOptions = () => _opts;
|
||||
this.updateOptions = (options: Options) => _options(options);
|
||||
this.getElement = () => _element;
|
||||
|
||||
let _element = selectorToElement(element);
|
||||
let _timeouts: number[] = [];
|
||||
let _cursorPosition = 0;
|
||||
let _predictedCursorPosition = null;
|
||||
let _statuses = merge({}, DEFAULT_STATUSES);
|
||||
|
||||
options.cursor = processCursorOptions(
|
||||
options.cursor ?? DEFAULT_OPTIONS.cursor
|
||||
);
|
||||
|
||||
let _opts: Options = merge(DEFAULT_OPTIONS, options);
|
||||
_opts = merge(_opts, {
|
||||
html: !_elementIsInput() && _opts.html,
|
||||
nextStringDelay: calculateDelay(_opts.nextStringDelay),
|
||||
loopDelay: calculateDelay(_opts.loopDelay),
|
||||
});
|
||||
|
||||
let _id = generateHash();
|
||||
let _queue = Queue([{ delay: _opts.startDelay }]);
|
||||
|
||||
_element.dataset.typeitId = _id;
|
||||
|
||||
// Used to set a "placeholder" space in the element, so that it holds vertical sizing before anything's typed.
|
||||
appendStyleBlock(PLACEHOLDER_CSS);
|
||||
|
||||
let _shouldRenderCursor = !!_opts.cursor && !_elementIsInput();
|
||||
let _cursor = _setUpCursor();
|
||||
|
||||
_opts.strings = _maybePrependHardcodedStrings(asArray<string>(_opts.strings));
|
||||
|
||||
// Only generate a queue if we have strings
|
||||
// and this isn't a reset of a previous instance,
|
||||
// in which case we'd have a pre-defined queue.
|
||||
if (_opts.strings.length) {
|
||||
_generateQueue();
|
||||
}
|
||||
};
|
||||
|
||||
export default TypeIt;
|
||||
78
node_modules/typeit/src/types.ts
generated
vendored
Normal file
78
node_modules/typeit/src/types.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
export type TypeItInstance = (element: El | string, options: Options) => void;
|
||||
|
||||
export type Character = {
|
||||
node: El | null;
|
||||
content: string | Node;
|
||||
};
|
||||
|
||||
export interface CursorAnimationOptions {
|
||||
frames?: AnimationKeyFrame[];
|
||||
options?: Partial<AnimationEffectTiming>;
|
||||
}
|
||||
|
||||
export interface CursorOptions {
|
||||
autoPause?: boolean;
|
||||
autoPauseDelay?: number;
|
||||
animation?: CursorAnimationOptions;
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
breakLines?: boolean;
|
||||
cursorChar?: string;
|
||||
cursor?: CursorOptions | boolean;
|
||||
|
||||
// @todo: Remove in next major release.
|
||||
cursorSpeed?: number;
|
||||
deleteSpeed?: null | number;
|
||||
html?: boolean;
|
||||
lifeLike?: boolean;
|
||||
loop?: boolean;
|
||||
loopDelay?: number;
|
||||
nextStringDelay?: number;
|
||||
speed?: number;
|
||||
startDelay?: number;
|
||||
startDelete?: boolean;
|
||||
strings?: string[] | string;
|
||||
waitUntilVisible?: boolean;
|
||||
beforeString?: Function;
|
||||
afterString?: Function;
|
||||
beforeStep?: Function;
|
||||
afterStep?: Function;
|
||||
afterComplete?: Function;
|
||||
}
|
||||
|
||||
export type ActionOpts = Options & {
|
||||
to?: Sides;
|
||||
instant?: boolean;
|
||||
delay?: number;
|
||||
};
|
||||
|
||||
export type QueueItem = {
|
||||
done?: boolean;
|
||||
func?: () => any;
|
||||
delay?: number;
|
||||
char?: any;
|
||||
|
||||
// A queue item that can be visibly 'typed' to the
|
||||
// screen, including those queued with ".type()" and ".break()"
|
||||
typeable?: boolean;
|
||||
|
||||
deletable?: boolean;
|
||||
|
||||
// An explicit indicator that a queue item should pause
|
||||
// the cursor animation during execution.
|
||||
cursorable?: boolean;
|
||||
|
||||
// An item should pause the cursor of it's
|
||||
// EITHER "typeable," "cusorable," or "deleteable."
|
||||
shouldPauseCursor?: () => boolean;
|
||||
};
|
||||
|
||||
export type QueueMapPair = [Symbol, QueueItem];
|
||||
|
||||
export interface El extends HTMLElement {
|
||||
value: string | number;
|
||||
originalParent?: HTMLElement;
|
||||
}
|
||||
|
||||
export type Sides = "START" | "END";
|
||||
Reference in New Issue
Block a user