Comparing version 8.6.1-alpha.0 to 8.6.1
import { Options } from "./types"; | ||
export declare const DATA_ATTRIBUTE = "data-typeit-id"; | ||
export declare const CURSOR_CLASS = "ti-cursor"; | ||
export declare const CURSOR_WRAPPER_CLASS = "ti-cursor-wrapper"; | ||
export declare const START = "START"; | ||
@@ -14,1 +15,2 @@ export declare const END = "END"; | ||
export declare const PLACEHOLDER_CSS: string; | ||
export declare const CURSOR_ANIMATION_RESTART_DELAY = 500; |
@@ -1,3 +0,3 @@ | ||
import { Element } from "../types"; | ||
export declare function walkElementNodes(element: Element | Node, shouldReverse?: boolean): Element[]; | ||
import { El } from "../types"; | ||
export declare function walkElementNodes(element: El | Node, shouldReverse?: boolean, shouldIncludeCursor?: boolean): El[]; | ||
/** | ||
@@ -7,3 +7,3 @@ * Convert string to array of chunks that will be later | ||
*/ | ||
export declare function chunkStringAsHtml(string: string): Element[]; | ||
export declare function chunkStringAsHtml(string: string): El[]; | ||
/** | ||
@@ -17,2 +17,2 @@ * Given a string, chunk it into array items to be later | ||
*/ | ||
export declare function maybeChunkStringAsHtml(str: string, asHtml?: boolean): Partial<Element>[]; | ||
export declare function maybeChunkStringAsHtml(str: string, asHtml?: boolean): Partial<El>[]; |
@@ -1,3 +0,3 @@ | ||
import { Element } from "../types"; | ||
declare const _default: (el: any) => Element; | ||
import { El } from "../types"; | ||
declare const _default: (el: any) => El; | ||
export default _default; |
@@ -1,3 +0,3 @@ | ||
import { Element } from "../types"; | ||
declare let expandTextNodes: (element: Element) => Element; | ||
import { El } from "../types"; | ||
declare let expandTextNodes: (element: El) => El; | ||
export default expandTextNodes; |
@@ -1,3 +0,9 @@ | ||
import { QueueMapPair } from "../types"; | ||
declare let fireItem: (index: number, queueItems: QueueMapPair[], wait: any) => Promise<number>; | ||
import { El, QueueMapPair } from "../types"; | ||
interface FireItemArgs { | ||
index: number; | ||
queueItems: QueueMapPair[]; | ||
wait: (...args: any) => Promise<void>; | ||
cursor: El | undefined; | ||
} | ||
declare let fireItem: ({ index, queueItems, wait, cursor, }: FireItemArgs) => Promise<number>; | ||
export default fireItem; |
@@ -1,2 +0,2 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
/** | ||
@@ -6,3 +6,3 @@ * Get a flattened array of text nodes that have been typed. | ||
*/ | ||
declare let getAllChars: (element: Element) => any[]; | ||
declare let getAllChars: (element: El) => any[]; | ||
export default getAllChars; |
@@ -1,2 +0,2 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
/** | ||
@@ -6,3 +6,3 @@ * Parse a string as HTML and return the body | ||
*/ | ||
declare const _default: (content: any) => Element; | ||
declare const _default: (content: any) => El; | ||
export default _default; |
@@ -1,6 +0,6 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
/** | ||
* Inserts a set of content into the element. Intended for SINGLE characters. | ||
*/ | ||
declare let insertIntoElement: (originalTarget: Element, character: Element) => void; | ||
declare let insertIntoElement: (originalTarget: El, character: El) => void; | ||
export default insertIntoElement; |
@@ -1,6 +0,2 @@ | ||
import { Element } from "../types"; | ||
/** | ||
* @param {object} HTML node | ||
*/ | ||
declare const _default: (node: Element | null) => void; | ||
declare const _default: (node: Node) => void; | ||
export default _default; |
@@ -1,2 +0,2 @@ | ||
declare const _default: (element: Node, allChars: any[], newCursorPosition: number) => void; | ||
declare const _default: (element: HTMLElement, allChars: any[], newCursorPosition: number) => void; | ||
export default _default; |
@@ -1,2 +0,2 @@ | ||
declare let select: <T>(selector: string, element?: Node, all?: boolean) => T; | ||
declare let select: (selector: string, element?: Node, all?: boolean) => Node | NodeList | null; | ||
export default select; |
@@ -1,2 +0,2 @@ | ||
import { Element } from "../types"; | ||
export default function (thing: string | Element): Element; | ||
import { El } from "../types"; | ||
export default function (thing: string | El): El; |
@@ -1,2 +0,2 @@ | ||
import { Element, Options } from "../types"; | ||
import { El } from "../types"; | ||
export declare let cursorFontStyles: { | ||
@@ -9,5 +9,4 @@ readonly "font-family": ""; | ||
readonly color: ""; | ||
readonly "margin-left": "-.125em"; | ||
readonly "margin-right": ".125em"; | ||
readonly transform: "translateX(-.125em)"; | ||
}; | ||
export declare let setCursorStyles: (id: string, options: Options, element: Element) => void; | ||
export declare let setCursorStyles: (id: string, element: El) => void; |
/** | ||
* Fire a callback after a delay, and add the timeout ID to a referenced array. | ||
*/ | ||
declare let wait: (callback: Function, delay: number | undefined, timeouts: any) => Promise<void>; | ||
declare let wait: (callback: Function, delay: number | undefined, timeouts: number[]) => Promise<void>; | ||
export default wait; |
@@ -10,3 +10,3 @@ // TypeIt by Alex MacArthur - https://typeitjs.com | ||
var _a; | ||
return _q.set(Symbol((_a = step.char) == null ? void 0 : _a.innerText), { ...step }); | ||
return _q.set(Symbol((_a = step.char) == null ? void 0 : _a.innerText), buildQueueItem({ ...step })); | ||
}); | ||
@@ -18,4 +18,10 @@ return this; | ||
let keys = [..._q.keys()]; | ||
_q.set(keys[index], item); | ||
_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() { | ||
@@ -69,2 +75,3 @@ _q.forEach((item) => delete item.done); | ||
const CURSOR_CLASS = "ti-cursor"; | ||
const CURSOR_WRAPPER_CLASS = "ti-cursor-wrapper"; | ||
const END = "END"; | ||
@@ -105,7 +112,17 @@ const DEFAULT_STATUSES = { | ||
const PLACEHOLDER_CSS = `[${DATA_ATTRIBUTE}]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}`; | ||
function walkElementNodes(element, shouldReverse = false) { | ||
const CURSOR_ANIMATION_RESTART_DELAY = 500; | ||
function walkElementNodes(element, shouldReverse = false, shouldIncludeCursor = false) { | ||
let cursor = element.querySelector(`.${CURSOR_CLASS}`); | ||
let walker = document.createTreeWalker(element, NodeFilter.SHOW_ALL, { | ||
acceptNode: (node) => { | ||
var _a; | ||
return ((_a = node.classList) == null ? void 0 : _a.contains(CURSOR_CLASS)) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT; | ||
var _a, _b; | ||
if (cursor && shouldIncludeCursor) { | ||
if ((_a = node.classList) == null ? void 0 : _a.contains(CURSOR_CLASS)) { | ||
return NodeFilter.FILTER_ACCEPT; | ||
} | ||
if (cursor.contains(node)) { | ||
return NodeFilter.FILTER_REJECT; | ||
} | ||
} | ||
return ((_b = node.classList) == null ? void 0 : _b.contains(CURSOR_CLASS)) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT; | ||
} | ||
@@ -116,3 +133,5 @@ }); | ||
while (nextNode = walker.nextNode()) { | ||
nextNode.originalParent = nextNode.parentNode; | ||
if (!nextNode.originalParent) { | ||
nextNode.originalParent = nextNode.parentNode; | ||
} | ||
nodes.push(nextNode); | ||
@@ -183,3 +202,3 @@ } | ||
}; | ||
let isBodyElement = (node) => (node == null ? void 0 : node.tagName) === "BODY"; | ||
let isBodyElement = (node) => /body/i.test(node == null ? void 0 : node.tagName); | ||
let insertIntoElement = (originalTarget, character) => { | ||
@@ -209,6 +228,3 @@ if (isInput(originalTarget)) { | ||
element = (nodeToInsertBefore == null ? void 0 : nodeToInsertBefore.parentNode) || element; | ||
if (nodeToInsertBefore) { | ||
return nodeToInsertBefore.before(cursor); | ||
} | ||
element.append(cursor); | ||
element.insertBefore(cursor, nodeToInsertBefore || null); | ||
}; | ||
@@ -219,3 +235,3 @@ function selectorToElement(thing) { | ||
var isNonVoidElement = (el) => /<(.+)>(.*?)<\/(.+)>/.test(el.outerHTML); | ||
let wait = async (callback, delay, timeouts) => { | ||
let wait = (callback, delay, timeouts) => { | ||
return new Promise((resolve) => { | ||
@@ -236,6 +252,5 @@ let cb = async () => { | ||
color: "", | ||
"margin-left": "-.125em", | ||
"margin-right": ".125em" | ||
transform: "translateX(-.125em)" | ||
}; | ||
let setCursorStyles = (id, options, element) => { | ||
let setCursorStyles = (id, element) => { | ||
let rootSelector = `[${DATA_ATTRIBUTE}='${id}']`; | ||
@@ -247,3 +262,3 @@ let cursorSelector = `${rootSelector} .${CURSOR_CLASS}`; | ||
}, ""); | ||
appendStyleBlock(`@keyframes blink-${id} { 0% {opacity: 0} 49% {opacity: 0} 50% {opacity: 1} } ${cursorSelector} { display: inline; letter-spacing: -1em; ${customProperties} animation: blink-${id} ${options.cursorSpeed / 1e3}s infinite; } ${cursorSelector}.with-delay { animation-delay: 500ms; } ${cursorSelector}.disabled { animation: none; }`, id); | ||
appendStyleBlock(`${cursorSelector} { display: inline-block; width: 0; ${customProperties} } .${CURSOR_WRAPPER_CLASS} { display: inline-block; font: inherit; color: inherit; }`, id); | ||
}; | ||
@@ -282,2 +297,46 @@ var duplicate = (value, times) => new Array(times).fill(value); | ||
}; | ||
const DEFAULT_TIMING_OPTIONS = { | ||
iterations: Infinity, | ||
easing: "steps(2, start)", | ||
fill: "forwards" | ||
}; | ||
const DEFAULT_FRAMES = [ | ||
{ opacity: 0 }, | ||
{ opacity: 0 }, | ||
{ opacity: 1 } | ||
]; | ||
let setCursorAnimation = ({ | ||
cursor, | ||
frames = null, | ||
timingOptions = {} | ||
}) => { | ||
return cursor.animate(frames || DEFAULT_FRAMES, { | ||
...DEFAULT_TIMING_OPTIONS, | ||
...timingOptions | ||
}); | ||
}; | ||
let rebuildCursorAnimation = ({ | ||
cursor, | ||
frames, | ||
timingOptions | ||
}) => { | ||
if (!cursor) | ||
return; | ||
let animation = cursor.getAnimations()[0]; | ||
let oldCurrentTime; | ||
if (animation && animation.playState !== "idle") { | ||
timingOptions.delay = animation.effect.getComputedTiming().delay; | ||
oldCurrentTime = animation.currentTime; | ||
animation.cancel(); | ||
} | ||
let newAnimation = setCursorAnimation({ | ||
cursor, | ||
frames, | ||
timingOptions | ||
}); | ||
if (oldCurrentTime) { | ||
newAnimation.currentTime = oldCurrentTime; | ||
} | ||
return newAnimation; | ||
}; | ||
let execute = (queueItem) => { | ||
@@ -287,3 +346,8 @@ var _a; | ||
}; | ||
let fireItem = async (index, queueItems, wait2) => { | ||
let fireItem = async ({ | ||
index, | ||
queueItems, | ||
wait: wait2, | ||
cursor | ||
}) => { | ||
let queueItem = queueItems[index][1]; | ||
@@ -307,3 +371,21 @@ let instantQueue = []; | ||
} | ||
await wait2(() => beforePaint(() => execute(queueItem)), queueItem.delay); | ||
let animation = cursor == null ? void 0 : cursor.getAnimations()[0]; | ||
let timingOptions = cursor ? { | ||
...animation.effect.getComputedTiming(), | ||
delay: queueItem.shouldPauseCursor() ? CURSOR_ANIMATION_RESTART_DELAY : 0 | ||
} : {}; | ||
let frames = cursor ? animation.effect.getKeyframes() : []; | ||
await wait2(async () => { | ||
if (queueItem.shouldPauseCursor()) { | ||
animation == null ? void 0 : animation.cancel(); | ||
} | ||
await beforePaint(() => { | ||
execute(queueItem); | ||
}); | ||
}, queueItem.delay); | ||
rebuildCursorAnimation({ | ||
cursor, | ||
frames, | ||
timingOptions | ||
}); | ||
return index; | ||
@@ -363,8 +445,10 @@ }; | ||
!_elementIsInput() && _cursor && _element.appendChild(_cursor); | ||
_shouldRenderCursor && setCursorStyles(_id, _opts, _element); | ||
}; | ||
let _disableCursorBlink = (shouldDisable) => { | ||
if (_shouldRenderCursor && _cursor) { | ||
_cursor.classList.toggle("disabled", shouldDisable); | ||
_cursor.classList.toggle("with-delay", !shouldDisable); | ||
if (_shouldRenderCursor) { | ||
setCursorStyles(_id, _element); | ||
setCursorAnimation({ | ||
cursor: _cursor, | ||
timingOptions: { | ||
duration: _opts.cursorSpeed | ||
} | ||
}); | ||
} | ||
@@ -417,3 +501,2 @@ }; | ||
let cleanUp = (qKey) => { | ||
_disableCursorBlink(false); | ||
_queue.done(qKey, !remember); | ||
@@ -427,6 +510,9 @@ }; | ||
continue; | ||
if (queueItem.typeable && !_statuses.frozen) | ||
_disableCursorBlink(true); | ||
if (!queueItem.deletable || queueItem.deletable && _getAllChars().length) { | ||
let newIndex = await fireItem(index, queueItems, _wait); | ||
let newIndex = await fireItem({ | ||
index, | ||
queueItems, | ||
wait: _wait, | ||
cursor: _cursor | ||
}); | ||
Array(newIndex - index).fill(index + 1).map((x, y) => x + y).forEach((i) => { | ||
@@ -540,3 +626,4 @@ let [key] = queueItems[i]; | ||
func: () => _move(directionalStep), | ||
delay: instant ? 0 : _getPace() | ||
delay: instant ? 0 : _getPace(), | ||
cursorable: true | ||
}, Math.abs(numberOfSteps)), | ||
@@ -543,0 +630,0 @@ bookEndQueueItems[1] |
// TypeIt by Alex MacArthur - https://typeitjs.com | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TypeIt=t()}(this,(function(){"use strict";var e=e=>Array.isArray(e),t=t=>e(t)?t:[t];var n=e=>Array.from(e),r=e=>document.createTextNode(e);let i=e=>([...e.childNodes].forEach((e=>{if(e.nodeValue)return[...e.nodeValue].forEach((t=>{e.parentNode.insertBefore(r(t),e)})),void e.remove();i(e)})),e);var a=e=>{let t=document.implementation.createHTMLDocument();return t.body.innerHTML=e,i(t.body)};const l="ti-cursor",o={started:!1,completed:!1,frozen:!1,destroyed:!1},s={breakLines:!0,cursor:!0,cursorChar:"|",cursorSpeed:1e3,deleteSpeed:null,html:!0,lifeLike:!0,loop:!1,loopDelay:750,nextStringDelay:750,speed:100,startDelay:250,startDelete:!1,strings:[],waitUntilVisible:!1,beforeString:()=>{},afterString:()=>{},beforeStep:()=>{},afterStep:()=>{},afterComplete:()=>{}};function u(e,t=!1){let n,r=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:e=>{var t;return(null==(t=e.classList)?void 0:t.contains(l))?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),i=[];for(;n=r.nextNode();)n.originalParent=n.parentNode,i.push(n);return t?i.reverse():i}function d(e,t=!0){return t?u(a(e)):n(e).map(r)}var c=e=>document.createElement(e),f=(e,t="")=>{let n=c("style");n.id=t,n.appendChild(r(e)),document.head.appendChild(n)},h=t=>(e(t)||(t=[t/2,t/2]),t),y=(e,t)=>Math.abs(Math.random()*(e+t-(e-t))+(e-t));let p=e=>e/2;var m=e=>"value"in e;let g=e=>"function"==typeof e?e():e;var b=e=>Number.isInteger(e);let v=(e,t=document,n=!1)=>t["querySelector"+(n?"All":"")](e);var w=(e,t)=>Object.assign({},e,t),T=e=>{if(!e)return;let t=e.parentNode;(t.childNodes.length>1?e:t).remove()};let S={"font-family":"","font-weight":"","font-size":"","font-style":"","line-height":"",color:"","margin-left":"-.125em","margin-right":".125em"};var E=(e,t)=>new Array(t).fill(e);const L=({queueItems:e,selector:t,cursorPosition:n,to:r})=>{if(b(t))return-1*t;let i=new RegExp("END","i").test(r),a=t?[...e].reverse().findIndex((({char:e})=>{let n=e.parentElement,r=n.matches(t);return!(!i||!r)||r&&n.firstChild.isSameNode(e)})):-1;return a<0&&(a=i?0:e.length-1),a-n+(i?0:1)};let N=e=>new Promise((t=>{requestAnimationFrame((async()=>{t(await e())}))})),M=e=>{var t;return null==(t=e.func)?void 0:t.call(globalThis)},D=async(e,t,n)=>{let r=t[e][1],i=[],a=e,l=r,o=()=>l&&!l.delay;for(;o();)i.push(l),o()&&a++,l=t[a]?t[a][1]:null;return i.length?(await N((async()=>{for(let e of i)await M(e)})),a-1):(await n((()=>N((()=>M(r)))),r.delay),e)};return function(e,r={}){let N=async(e,t,n=!1)=>{J.frozen&&await new Promise((e=>{this.unfreeze=()=>{J.frozen=!1,e()}})),n||await X.beforeStep(this),await(async(e,t,n)=>new Promise((r=>{n.push(setTimeout((async()=>{await e(),r()}),t||0))})))(e,t,Q),n||await X.afterStep(this)},M=()=>m(_),x=(e=0)=>function(e){let{speed:t,deleteSpeed:n,lifeLike:r}=e;return n=null!==n?n:t/3,r?[y(t,p(t)),y(n,p(n))]:[t,n]}(X)[e],$=()=>(e=>m(e)?n(e.value):u(e,!0).filter((e=>!(e.childNodes.length>0))))(_),C=(e,t)=>(G.add(e),((e={})=>{let t=e.delay;t&&G.add({delay:t})})(t),this),I=()=>null!=W?W:U,k=(e={})=>[{func:()=>q(e)},{func:()=>q(X)}],H=e=>{let t=X.nextStringDelay;G.add([{delay:t[0]},...e,{delay:t[1]}])},A=async()=>{!M()&&Z&&_.appendChild(Z),K&&((e,t,n)=>{let r=`[data-typeit-id='${e}'] .ti-cursor`,i=getComputedStyle(n),a=Object.entries(S).reduce(((e,[t,n])=>`${e} ${t}: var(--ti-cursor-${t}, ${n||i[t]});`),"");f(`@keyframes blink-${e} { 0% {opacity: 0} 49% {opacity: 0} 50% {opacity: 1} } ${r} { display: inline; letter-spacing: -1em; ${a} animation: blink-${e} ${t.cursorSpeed/1e3}s infinite; } ${r}.with-delay { animation-delay: 500ms; } ${r}.disabled { animation: none; }`,e)})(Y,X,_)},P=e=>{K&&Z&&(Z.classList.toggle("disabled",e),Z.classList.toggle("with-delay",!e))},z=()=>{let e=X.strings.filter((e=>!!e));e.forEach(((t,n)=>{if(this.type(t),n+1===e.length)return;let r=X.breakLines?[{func:()=>R(c("BR")),typeable:!0}]:E({func:V,delay:x(1)},G.getTypeable().length);H(r)}))},O=async(e=!0)=>{J.started=!0;let t=t=>{P(!1),G.done(t,!e)};try{let n=[...G.getQueue()];for(let e=0;e<n.length;e++){let[r,i]=n[e];if(!i.done){if(i.typeable&&!J.frozen&&P(!0),!i.deletable||i.deletable&&$().length){let r=await D(e,n,N);Array(r-e).fill(e+1).map(((e,t)=>e+t)).forEach((e=>{let[r]=n[e];t(r)})),e=r}t(r)}}if(!e)return this;if(J.completed=!0,await X.afterComplete(this),!X.loop)throw"";let r=X.loopDelay;N((async()=>{await(async e=>{let t=I();t&&await F({value:t});for(let n of $())await N(V,x(1));G.reset(),G.set(0,{delay:e})})(r[0]),O()}),r[1])}catch(n){}return this},F=async e=>{var t,n,r;t=e,n=U,r=$(),U=Math.min(Math.max(n+t,0),r.length),((e,t,n)=>{let r=t[n-1],i=v(".ti-cursor",e);if(e=(null==r?void 0:r.parentNode)||e,r)return r.before(i);e.append(i)})(_,$(),U)},R=e=>((e,t)=>{if(m(e))return void(e.value=`${e.value}${t.textContent}`);t.innerHTML="";let n="BODY"===(null==(r=t.originalParent)?void 0:r.tagName)?e:t.originalParent||e;var r;n.insertBefore(t,v(".ti-cursor",n)||null)})(_,e),q=async e=>X=w(X,e),B=async()=>{M()?_.value="":$().forEach(T)},V=()=>{let e=$();e.length&&(M()?_.value=_.value.slice(0,-1):T(e[U]))};this.break=function(e){return C({func:()=>R(c("BR")),typeable:!0},e)},this.delete=function(e=null,t={}){e=g(e);let n=k(t),r=e,{instant:i,to:a}=t,l=G.getTypeable(),o=null===r?l.length:b(r)?r:L({queueItems:l,selector:r,cursorPosition:I(),to:a});return C([n[0],...E({func:V,delay:i?0:x(1),deletable:!0},o),n[1]],t)},this.empty=function(e={}){return C({func:B},e)},this.exec=function(e,t={}){let n=k(t);return C([n[0],{func:()=>e(this)},n[1]],t)},this.move=function(e,t={}){e=g(e);let n=k(t),{instant:r,to:i}=t,a=L({queueItems:G.getTypeable(),selector:null===e?"":e,to:i,cursorPosition:I()}),l=a<0?-1:1;return W=I()+a,C([n[0],...E({func:()=>F(l),delay:r?0:x()},Math.abs(a)),n[1]],t)},this.options=function(e,t={}){return e=g(e),q(e),C({},t)},this.pause=function(e,t={}){return C({delay:g(e)},t)},this.type=function(e,t={}){e=g(e);let{instant:n}=t,r=k(t),i=d(e,X.html).map((e=>{return{func:()=>R(e),char:e,delay:n||(t=e,/<(.+)>(.*?)<\/(.+)>/.test(t.outerHTML))?0:x(),typeable:e.nodeType===Node.TEXT_NODE};var t})),a=[r[0],{func:async()=>await X.beforeString(e,this)},...i,{func:async()=>await X.afterString(e,this)},r[1]];return C(a,t)},this.is=function(e){return J[e]},this.destroy=function(e=!0){Q.forEach(clearTimeout),Q=[],g(e)&&Z&&T(Z),J.destroyed=!0},this.freeze=function(){J.frozen=!0},this.unfreeze=()=>{},this.reset=function(e){!this.is("destroyed")&&this.destroy(),e?(G.wipe(),e(this)):G.reset(),U=0;for(let t in J)J[t]=!1;return _[M()?"value":"innerHTML"]="",this},this.go=function(){return J.started?this:(A(),X.waitUntilVisible?(((e,t)=>{new IntersectionObserver(((n,r)=>{n.forEach((n=>{n.isIntersecting&&(t(),r.unobserve(e))}))}),{threshold:1}).observe(e)})(_,O.bind(this)),this):(O(),this))},this.flush=function(e=(()=>{})){return A(),O(!1).then(e),this},this.getQueue=()=>G,this.getOptions=()=>X,this.updateOptions=e=>q(e),this.getElement=()=>_;let _="string"==typeof(j=e)?v(j):j;var j;let Q=[],U=0,W=null,J=w({},o),X=w(s,r);X=w(X,{html:!M()&&X.html,nextStringDelay:h(X.nextStringDelay),loopDelay:h(X.loopDelay)});let Y=Math.random().toString().substring(2,9),G=function(e){let n=function(e){return t(e).forEach((e=>{var t;return i.set(Symbol(null==(t=e.char)?void 0:t.innerText),{...e})})),this},r=()=>Array.from(i.values()),i=new Map;return n(e),{add:n,set:function(e,t){let n=[...i.keys()];i.set(n[e],t)},wipe:function(){i=new Map,n(e)},reset:function(){i.forEach((e=>delete e.done))},destroy:e=>i.delete(e),done:(e,t=!1)=>t?i.delete(e):i.get(e).done=!0,getItems:(e=!1)=>e?r():r().filter((e=>!e.done)),getQueue:()=>i,getTypeable:()=>r().filter((e=>e.typeable))}}([{func:()=>{},delay:X.startDelay}]);_.dataset.typeitId=Y,f("[data-typeit-id]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}");let K=X.cursor&&!M(),Z=(()=>{if(M())return;let e=c("span");return e.className=l,K?(e.innerHTML=a(X.cursorChar).innerHTML,e):(e.style.visibility="hidden",e)})();X.strings=(e=>{let t=_.innerHTML;return t?(_.innerHTML="",X.startDelete?(_.innerHTML=t,i(_),H(E({func:V,delay:x(1),deletable:!0},$().length)),e):t.replace(/<!--(.+?)-->/g,"").trim().split(/<br(?:\s*?)(?:\/)?>/).concat(e)):e})(t(X.strings)),X.strings.length&&z()}})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).TypeIt=t()}(this,(function(){"use strict";var e=e=>Array.isArray(e),t=t=>e(t)?t:[t];var n=e=>Array.from(e),r=e=>document.createTextNode(e);let i=e=>([...e.childNodes].forEach((e=>{if(e.nodeValue)return[...e.nodeValue].forEach((t=>{e.parentNode.insertBefore(r(t),e)})),void e.remove();i(e)})),e);var l=e=>{let t=document.implementation.createHTMLDocument();return t.body.innerHTML=e,i(t.body)};const a="ti-cursor",o={started:!1,completed:!1,frozen:!1,destroyed:!1},s={breakLines:!0,cursor:!0,cursorChar:"|",cursorSpeed:1e3,deleteSpeed:null,html:!0,lifeLike:!0,loop:!1,loopDelay:750,nextStringDelay:750,speed:100,startDelay:250,startDelete:!1,strings:[],waitUntilVisible:!1,beforeString:()=>{},afterString:()=>{},beforeStep:()=>{},afterStep:()=>{},afterComplete:()=>{}};function u(e,t=!1,n=!1){let r,i=e.querySelector(".ti-cursor"),l=document.createTreeWalker(e,NodeFilter.SHOW_ALL,{acceptNode:e=>{var t,r;if(i&&n){if(null==(t=e.classList)?void 0:t.contains(a))return NodeFilter.FILTER_ACCEPT;if(i.contains(e))return NodeFilter.FILTER_REJECT}return(null==(r=e.classList)?void 0:r.contains(a))?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),o=[];for(;r=l.nextNode();)r.originalParent||(r.originalParent=r.parentNode),o.push(r);return t?o.reverse():o}function c(e,t=!0){return t?u(l(e)):n(e).map(r)}var d=e=>document.createElement(e),f=(e,t="")=>{let n=d("style");n.id=t,n.appendChild(r(e)),document.head.appendChild(n)},h=t=>(e(t)||(t=[t/2,t/2]),t),y=(e,t)=>Math.abs(Math.random()*(e+t-(e-t))+(e-t));let p=e=>e/2;var m=e=>"value"in e;let g=e=>"function"==typeof e?e():e;var b=e=>Number.isInteger(e);let v=(e,t=document,n=!1)=>t["querySelector"+(n?"All":"")](e);var T=(e,t)=>Object.assign({},e,t),w=e=>{if(!e)return;let t=e.parentNode;(t.childNodes.length>1?e:t).remove()};let E={"font-family":"","font-weight":"","font-size":"","font-style":"","line-height":"",color:"",transform:"translateX(-.125em)"};var S=(e,t)=>new Array(t).fill(e);const L=({queueItems:e,selector:t,cursorPosition:n,to:r})=>{if(b(t))return-1*t;let i=new RegExp("END","i").test(r),l=t?[...e].reverse().findIndex((({char:e})=>{let n=e.parentElement,r=n.matches(t);return!(!i||!r)||r&&n.firstChild.isSameNode(e)})):-1;return l<0&&(l=i?0:e.length-1),l-n+(i?0:1)};let N=e=>new Promise((t=>{requestAnimationFrame((async()=>{t(await e())}))}));const C={iterations:1/0,easing:"steps(2, start)",fill:"forwards"},M=[{opacity:0},{opacity:0},{opacity:1}];let x=({cursor:e,frames:t=null,timingOptions:n={}})=>e.animate(t||M,{...C,...n}),I=e=>{var t;return null==(t=e.func)?void 0:t.call(globalThis)},D=async({index:e,queueItems:t,wait:n,cursor:r})=>{let i=t[e][1],l=[],a=e,o=i,s=()=>o&&!o.delay;for(;s();)l.push(o),s()&&a++,o=t[a]?t[a][1]:null;if(l.length)return await N((async()=>{for(let e of l)await I(e)})),a-1;let u=null==r?void 0:r.getAnimations()[0],c=r?{...u.effect.getComputedTiming(),delay:i.shouldPauseCursor()?500:0}:{},d=r?u.effect.getKeyframes():[];return await n((async()=>{i.shouldPauseCursor()&&(null==u||u.cancel()),await N((()=>{I(i)}))}),i.delay),(({cursor:e,frames:t,timingOptions:n})=>{if(!e)return;let r,i=e.getAnimations()[0];i&&"idle"!==i.playState&&(n.delay=i.effect.getComputedTiming().delay,r=i.currentTime,i.cancel());let l=x({cursor:e,frames:t,timingOptions:n});r&&(l.currentTime=r)})({cursor:r,frames:d,timingOptions:c}),e};return function(e,r={}){let N=async(e,t,n=!1)=>{W.frozen&&await new Promise((e=>{this.unfreeze=()=>{W.frozen=!1,e()}})),n||await X.beforeStep(this),await((e,t,n)=>new Promise((r=>{n.push(setTimeout((async()=>{await e(),r()}),t||0))})))(e,t,Q),n||await X.afterStep(this)},C=()=>m(V),M=(e=0)=>function(e){let{speed:t,deleteSpeed:n,lifeLike:r}=e;return n=null!==n?n:t/3,r?[y(t,p(t)),y(n,p(n))]:[t,n]}(X)[e],I=()=>(e=>m(e)?n(e.value):u(e,!0).filter((e=>!(e.childNodes.length>0))))(V),P=(e,t)=>(G.add(e),((e={})=>{let t=e.delay;t&&G.add({delay:t})})(t),this),A=()=>null!=U?U:J,O=(e={})=>[{func:()=>z(e)},{func:()=>z(X)}],H=e=>{let t=X.nextStringDelay;G.add([{delay:t[0]},...e,{delay:t[1]}])},k=async()=>{!C()&&Z&&V.appendChild(Z),Y&&(((e,t)=>{let n=`[data-typeit-id='${e}'] .ti-cursor`,r=getComputedStyle(t),i=Object.entries(E).reduce(((e,[t,n])=>`${e} ${t}: var(--ti-cursor-${t}, ${n||r[t]});`),"");f(`${n} { display: inline-block; width: 0; ${i} } .ti-cursor-wrapper { display: inline-block; font: inherit; color: inherit; }`,e)})(K,V),x({cursor:Z,timingOptions:{duration:X.cursorSpeed}}))},F=()=>{let e=X.strings.filter((e=>!!e));e.forEach(((t,n)=>{if(this.type(t),n+1===e.length)return;let r=X.breakLines?[{func:()=>q(d("BR")),typeable:!0}]:S({func:_,delay:M(1)},G.getTypeable().length);H(r)}))},R=async(e=!0)=>{W.started=!0;let t=t=>{G.done(t,!e)};try{let n=[...G.getQueue()];for(let e=0;e<n.length;e++){let[r,i]=n[e];if(!i.done){if(!i.deletable||i.deletable&&I().length){let r=await D({index:e,queueItems:n,wait:N,cursor:Z});Array(r-e).fill(e+1).map(((e,t)=>e+t)).forEach((e=>{let[r]=n[e];t(r)})),e=r}t(r)}}if(!e)return this;if(W.completed=!0,await X.afterComplete(this),!X.loop)throw"";let r=X.loopDelay;N((async()=>{await(async e=>{let t=A();t&&await $({value:t});for(let n of I())await N(_,M(1));G.reset(),G.set(0,{delay:e})})(r[0]),R()}),r[1])}catch(n){}return this},$=async e=>{var t,n,r;t=e,n=J,r=I(),J=Math.min(Math.max(n+t,0),r.length),((e,t,n)=>{let r=t[n-1],i=v(".ti-cursor",e);(e=(null==r?void 0:r.parentNode)||e).insertBefore(i,r||null)})(V,I(),J)},q=e=>((e,t)=>{if(m(e))return void(e.value=`${e.value}${t.textContent}`);t.innerHTML="";let n=(r=t.originalParent,/body/i.test(null==r?void 0:r.tagName)?e:t.originalParent||e);var r;n.insertBefore(t,v(".ti-cursor",n)||null)})(V,e),z=async e=>X=T(X,e),B=async()=>{C()?V.value="":I().forEach(w)},_=()=>{let e=I();e.length&&(C()?V.value=V.value.slice(0,-1):w(e[J]))};this.break=function(e){return P({func:()=>q(d("BR")),typeable:!0},e)},this.delete=function(e=null,t={}){e=g(e);let n=O(t),r=e,{instant:i,to:l}=t,a=G.getTypeable(),o=null===r?a.length:b(r)?r:L({queueItems:a,selector:r,cursorPosition:A(),to:l});return P([n[0],...S({func:_,delay:i?0:M(1),deletable:!0},o),n[1]],t)},this.empty=function(e={}){return P({func:B},e)},this.exec=function(e,t={}){let n=O(t);return P([n[0],{func:()=>e(this)},n[1]],t)},this.move=function(e,t={}){e=g(e);let n=O(t),{instant:r,to:i}=t,l=L({queueItems:G.getTypeable(),selector:null===e?"":e,to:i,cursorPosition:A()}),a=l<0?-1:1;return U=A()+l,P([n[0],...S({func:()=>$(a),delay:r?0:M(),cursorable:!0},Math.abs(l)),n[1]],t)},this.options=function(e,t={}){return e=g(e),z(e),P({},t)},this.pause=function(e,t={}){return P({delay:g(e)},t)},this.type=function(e,t={}){e=g(e);let{instant:n}=t,r=O(t),i=c(e,X.html).map((e=>{return{func:()=>q(e),char:e,delay:n||(t=e,/<(.+)>(.*?)<\/(.+)>/.test(t.outerHTML))?0:M(),typeable:e.nodeType===Node.TEXT_NODE};var t})),l=[r[0],{func:async()=>await X.beforeString(e,this)},...i,{func:async()=>await X.afterString(e,this)},r[1]];return P(l,t)},this.is=function(e){return W[e]},this.destroy=function(e=!0){Q.forEach(clearTimeout),Q=[],g(e)&&Z&&w(Z),W.destroyed=!0},this.freeze=function(){W.frozen=!0},this.unfreeze=()=>{},this.reset=function(e){!this.is("destroyed")&&this.destroy(),e?(G.wipe(),e(this)):G.reset(),J=0;for(let t in W)W[t]=!1;return V[C()?"value":"innerHTML"]="",this},this.go=function(){return W.started?this:(k(),X.waitUntilVisible?(((e,t)=>{new IntersectionObserver(((n,r)=>{n.forEach((n=>{n.isIntersecting&&(t(),r.unobserve(e))}))}),{threshold:1}).observe(e)})(V,R.bind(this)),this):(R(),this))},this.flush=function(e=(()=>{})){return k(),R(!1).then(e),this},this.getQueue=()=>G,this.getOptions=()=>X,this.updateOptions=e=>z(e),this.getElement=()=>V;let V="string"==typeof(j=e)?v(j):j;var j;let Q=[],J=0,U=null,W=T({},o),X=T(s,r);X=T(X,{html:!C()&&X.html,nextStringDelay:h(X.nextStringDelay),loopDelay:h(X.loopDelay)});let K=Math.random().toString().substring(2,9),G=function(e){let n=function(e){return t(e).forEach((e=>{var t;return l.set(Symbol(null==(t=e.char)?void 0:t.innerText),r({...e}))})),this},r=e=>(e.shouldPauseCursor=function(){return Boolean(this.typeable||this.cursorable||this.deletable)},e),i=()=>Array.from(l.values()),l=new Map;return n(e),{add:n,set:function(e,t){let n=[...l.keys()];l.set(n[e],r(t))},wipe:function(){l=new Map,n(e)},reset:function(){l.forEach((e=>delete e.done))},destroy:e=>l.delete(e),done:(e,t=!1)=>t?l.delete(e):l.get(e).done=!0,getItems:(e=!1)=>e?i():i().filter((e=>!e.done)),getQueue:()=>l,getTypeable:()=>i().filter((e=>e.typeable))}}([{func:()=>{},delay:X.startDelay}]);V.dataset.typeitId=K,f("[data-typeit-id]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}");let Y=X.cursor&&!C(),Z=(()=>{if(C())return;let e=d("span");return e.className=a,Y?(e.innerHTML=l(X.cursorChar).innerHTML,e):(e.style.visibility="hidden",e)})();X.strings=(e=>{let t=V.innerHTML;return t?(V.innerHTML="",X.startDelete?(V.innerHTML=t,i(V),H(S({func:_,delay:M(1),deletable:!0},I().length)),e):t.replace(/<!--(.+?)-->/g,"").trim().split(/<br(?:\s*?)(?:\/)?>/).concat(e)):e})(t(X.strings)),X.strings.length&&F()}})); |
@@ -1,4 +0,4 @@ | ||
export declare type TypeItInstance = (element: Element | string, options: Options) => void; | ||
export declare type TypeItInstance = (element: El | string, options: Options) => void; | ||
export declare type Character = { | ||
node: Element | null; | ||
node: El | null; | ||
content: string | Node; | ||
@@ -40,8 +40,10 @@ }; | ||
deletable?: boolean; | ||
cursorable?: boolean; | ||
shouldPauseCursor?: () => boolean; | ||
}; | ||
export declare type QueueMapPair = [Symbol, QueueItem]; | ||
export declare type Element = HTMLElement & CharacterData & Node & ChildNode & { | ||
export interface El extends HTMLElement { | ||
value: string | number; | ||
originalParent?: HTMLElement; | ||
}; | ||
} | ||
export declare type Sides = "START" | "END"; |
{ | ||
"name": "typeit", | ||
"version": "8.6.1-alpha.0", | ||
"version": "8.6.1", | ||
"description": "The most versatile animated typing utility on the planet.", | ||
@@ -42,9 +42,10 @@ "author": "Alex MacArthur <alex@macarthur.me> (https://macarthur.me)", | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.18.2", | ||
"@babel/preset-typescript": "^7.17.12", | ||
"jest": "^28.1.1", | ||
"jest-cli": "^28.1.1", | ||
"jest-environment-jsdom": "^28.1.1", | ||
"typescript": "^4.7.3", | ||
"vite": "^2.9.12" | ||
"@babel/preset-env": "^7.18.6", | ||
"@babel/preset-typescript": "^7.18.6", | ||
"@types/web-animations-js": "^2.2.12", | ||
"jest": "^28.1.2", | ||
"jest-cli": "^28.1.2", | ||
"jest-environment-jsdom": "^28.1.2", | ||
"typescript": "^4.7.4", | ||
"vite": "^2.9.14" | ||
}, | ||
@@ -61,3 +62,3 @@ "jest": { | ||
}, | ||
"gitHead": "55d58a67ba5f12a5251a35f215ec12d7341c90bb" | ||
"gitHead": "3600a4d499c4792d0488f016f48d3c230087a78b" | ||
} |
@@ -5,2 +5,3 @@ import { Options } from "./types"; | ||
export const CURSOR_CLASS = "ti-cursor"; | ||
export const CURSOR_WRAPPER_CLASS = "ti-cursor-wrapper"; | ||
export const START = "START"; | ||
@@ -37,1 +38,2 @@ export const END = "END"; | ||
export const PLACEHOLDER_CSS = `[${DATA_ATTRIBUTE}]:before {content: '.'; display: inline-block; width: 0; visibility: hidden;}`; | ||
export const CURSOR_ANIMATION_RESTART_DELAY = 500; |
@@ -0,1 +1,2 @@ | ||
import { El } from "../types"; | ||
import toArray from "./toArray"; | ||
@@ -6,28 +7,41 @@ import getParsedBody from "./getParsedBody"; | ||
import { Element } from "../types"; | ||
export function walkElementNodes( | ||
element: Element | Node, | ||
shouldReverse: boolean = false | ||
): Element[] { | ||
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: Element) => { | ||
// Always exclude the cursor + its children. | ||
return node.classList?.contains(CURSOR_CLASS) | ||
? NodeFilter.FILTER_REJECT | ||
: NodeFilter.FILTER_ACCEPT; | ||
} | ||
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. | ||
nextNode.originalParent = nextNode.parentNode; | ||
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); | ||
@@ -43,3 +57,3 @@ } | ||
*/ | ||
export function chunkStringAsHtml(string: string): Element[] { | ||
export function chunkStringAsHtml(string: string): El[] { | ||
return walkElementNodes(getParsedBody(string)); | ||
@@ -59,6 +73,4 @@ } | ||
asHtml = true | ||
): Partial<Element>[] { | ||
return asHtml | ||
? chunkStringAsHtml(str) | ||
: toArray(str).map(createTextNode); | ||
): Partial<El>[] { | ||
return asHtml ? chunkStringAsHtml(str) : toArray(str).map(createTextNode); | ||
} |
@@ -1,3 +0,3 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
export default (el): Element => document.createElement(el); | ||
export default (el): El => document.createElement(el); |
import createTextNode from "./createTextNode"; | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
let expandTextNodes = (element: Element): Element => { | ||
let expandTextNodes = (element: El): El => { | ||
[...element.childNodes].forEach((child) => { | ||
@@ -15,3 +15,3 @@ if (child.nodeValue) { | ||
expandTextNodes(child as Element); | ||
expandTextNodes(child as El); | ||
}); | ||
@@ -18,0 +18,0 @@ |
@@ -1,11 +0,21 @@ | ||
import { QueueItem, QueueMapPair } from "../types"; | ||
import { CURSOR_ANIMATION_RESTART_DELAY } from "../constants"; | ||
import { El, QueueItem, QueueMapPair } from "../types"; | ||
import beforePaint from "./beforePaint"; | ||
import rebuildCursorAnimation from "./rebuildCursorAnimation"; | ||
let execute = (queueItem: QueueItem) => queueItem.func?.call(this); | ||
let fireItem = async ( | ||
index: number, | ||
queueItems: QueueMapPair[], | ||
wait | ||
): Promise<number> => { | ||
interface FireItemArgs { | ||
index: number; | ||
queueItems: QueueMapPair[]; | ||
wait: (...args: any) => Promise<void>; | ||
cursor: El | undefined; | ||
} | ||
let fireItem = async ({ | ||
index, | ||
queueItems, | ||
wait, | ||
cursor, | ||
}: FireItemArgs): Promise<number> => { | ||
let queueItem = queueItems[index][1]; | ||
@@ -21,7 +31,7 @@ let instantQueue = []; | ||
instantQueue.push(futureItem); | ||
shouldBeGrouped() && tempIndex++; | ||
futureItem = queueItems[tempIndex] ? queueItems[tempIndex][1] : null; | ||
} | ||
if (instantQueue.length) { | ||
@@ -34,3 +44,3 @@ // All are executed together before the browser has a chance to repaint. | ||
}); | ||
// Important! Because we moved into the future, the index | ||
@@ -41,4 +51,26 @@ // needs to be modified and returned for accurate remaining execution. | ||
await wait(() => beforePaint(() => execute(queueItem)), queueItem.delay); | ||
let animation = cursor?.getAnimations()[0]; | ||
let timingOptions = cursor ? { | ||
...animation.effect.getComputedTiming(), | ||
delay: queueItem.shouldPauseCursor() ? CURSOR_ANIMATION_RESTART_DELAY : 0 | ||
} : {}; | ||
let frames = cursor ? animation.effect.getKeyframes() : []; | ||
await wait(async () => { | ||
// Pause the cursor while stuff is happening. | ||
if(queueItem.shouldPauseCursor()) { | ||
animation?.cancel(); | ||
} | ||
await beforePaint(() => { | ||
execute(queueItem); | ||
}) | ||
}, queueItem.delay); | ||
rebuildCursorAnimation({ | ||
cursor, | ||
frames, | ||
timingOptions | ||
}); | ||
return index; | ||
@@ -45,0 +77,0 @@ }; |
import isInput from "./isInput"; | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
import toArray from "./toArray"; | ||
@@ -10,3 +10,3 @@ import { walkElementNodes } from "./chunkStrings"; | ||
*/ | ||
let getAllChars = (element: Element) => { | ||
let getAllChars = (element: El) => { | ||
if(isInput(element)) { | ||
@@ -13,0 +13,0 @@ return toArray(element.value); |
@@ -1,2 +0,2 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
import expandTextNodes from "./expandTextNodes"; | ||
@@ -8,7 +8,7 @@ | ||
*/ | ||
export default (content): Element => { | ||
export default (content): El => { | ||
let doc = document.implementation.createHTMLDocument(); | ||
doc.body.innerHTML = content; | ||
return expandTextNodes(doc.body as Element); | ||
return expandTextNodes(doc.body as El); | ||
}; |
import isInput from "./isInput"; | ||
import select from "./select"; | ||
import { CURSOR_CLASS } from "../constants"; | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
import isBodyElement from "./isBodyElement"; | ||
let isBodyElement = (node): boolean => node?.tagName === "BODY"; | ||
/** | ||
@@ -12,4 +11,4 @@ * Inserts a set of content into the element. Intended for SINGLE characters. | ||
let insertIntoElement = ( | ||
originalTarget: Element, | ||
character: Element | ||
originalTarget: El, | ||
character: El | ||
) => { | ||
@@ -25,3 +24,3 @@ if (isInput(originalTarget)) { | ||
let target = isBodyElement(character.originalParent) | ||
let target = isBodyElement(character.originalParent as El) | ||
? originalTarget | ||
@@ -34,3 +33,3 @@ | ||
target.insertBefore( | ||
character as Element, | ||
character as El, | ||
select("." + CURSOR_CLASS, target) as Node || null | ||
@@ -37,0 +36,0 @@ ); |
@@ -1,7 +0,2 @@ | ||
import { Element } from "../types"; | ||
/** | ||
* @param {object} HTML node | ||
*/ | ||
export default (node: Element | null) => { | ||
export default (node: Node): void => { | ||
if(!node) return; | ||
@@ -18,3 +13,3 @@ | ||
nodeToRemove.remove(); | ||
(nodeToRemove as Element).remove(); | ||
}; |
import { CURSOR_CLASS } from "../constants"; | ||
import select from "./select"; | ||
import { El } from "../types"; | ||
export default ( | ||
element: Node, | ||
element: HTMLElement, | ||
allChars: any[], | ||
newCursorPosition: number | ||
): void => { | ||
): void => { | ||
let nodeToInsertBefore = allChars[newCursorPosition - 1]; | ||
let cursor = select<Node>(`.${CURSOR_CLASS}`, element); | ||
let cursor = select(`.${CURSOR_CLASS}`, element) as El; | ||
element = nodeToInsertBefore?.parentNode || element; | ||
if(nodeToInsertBefore) { | ||
return nodeToInsertBefore.before(cursor); | ||
} | ||
(element as Element).append(cursor); | ||
element.insertBefore(cursor as any, nodeToInsertBefore || null); | ||
}; |
@@ -1,6 +0,6 @@ | ||
let select = <T>( | ||
let select = ( | ||
selector: string, | ||
element: Node = document, | ||
all: boolean = false | ||
): T | null => { | ||
): Node | NodeList | null => { | ||
return element[`querySelector${all ? "All" : ""}`](selector); | ||
@@ -7,0 +7,0 @@ }; |
@@ -1,8 +0,8 @@ | ||
import { Element } from "../types"; | ||
import { El } from "../types"; | ||
import select from "./select"; | ||
export default function (thing: string | Element): Element { | ||
export default function (thing: string | El): El { | ||
return typeof thing === "string" | ||
? (select(thing as string) as Element) | ||
? (select(thing as string) as El) | ||
: thing; | ||
} |
@@ -1,3 +0,3 @@ | ||
import { CURSOR_CLASS, DATA_ATTRIBUTE } from "../constants"; | ||
import { Element, Options } from "../types"; | ||
import { CURSOR_CLASS, CURSOR_WRAPPER_CLASS, DATA_ATTRIBUTE } from "../constants"; | ||
import { El } from "../types"; | ||
import appendStyleBlock from "./appendStyleBlock"; | ||
@@ -12,4 +12,3 @@ | ||
color: "", | ||
"margin-left": "-.125em", | ||
"margin-right": ".125em", | ||
transform: "translateX(-.125em)" | ||
} as const; | ||
@@ -19,4 +18,3 @@ | ||
id: string, | ||
options: Options, | ||
element: Element | ||
element: El | ||
) => { | ||
@@ -37,7 +35,5 @@ let rootSelector = `[${DATA_ATTRIBUTE}='${id}']`; | ||
appendStyleBlock( | ||
`@keyframes blink-${id} { 0% {opacity: 0} 49% {opacity: 0} 50% {opacity: 1} } ${cursorSelector} { display: inline; letter-spacing: -1em; ${customProperties} animation: blink-${id} ${ | ||
options.cursorSpeed / 1000 | ||
}s infinite; } ${cursorSelector}.with-delay { animation-delay: 500ms; } ${cursorSelector}.disabled { animation: none; }`, | ||
`${cursorSelector} { display: inline-block; width: 0; ${customProperties} } .${CURSOR_WRAPPER_CLASS} { display: inline-block; font: inherit; color: inherit; }`, | ||
id | ||
); | ||
}; |
/** | ||
* Fire a callback after a delay, and add the timeout ID to a referenced array. | ||
*/ | ||
let wait = async (callback: Function, delay: number | undefined, timeouts) => { | ||
let wait = (callback: Function, delay: number | undefined, timeouts: number[]) => { | ||
return new Promise<void>((resolve) => { | ||
@@ -6,0 +6,0 @@ let cb = async () => { |
@@ -27,3 +27,3 @@ import Queue from "./Queue"; | ||
import { | ||
Element, | ||
El, | ||
Options, | ||
@@ -44,2 +44,3 @@ QueueItem, | ||
import fireItem from "./helpers/fireItem"; | ||
import setCursorAnimation from "./helpers/setCursorAnimation"; | ||
@@ -54,3 +55,3 @@ // Necessary for publicly exposing types. | ||
silent: boolean = false | ||
) => { | ||
): Promise<void> => { | ||
if (_statuses.frozen) { | ||
@@ -76,3 +77,3 @@ await new Promise<void>((resolve) => { | ||
let _getAllChars = (): Element[] => getAllChars(_element); | ||
let _getAllChars = (): El[] => getAllChars(_element); | ||
@@ -117,3 +118,3 @@ let _maybeAppendPause = (opts: ActionOpts = {}) => { | ||
*/ | ||
let _setUpCursor = (): void | Element => { | ||
let _setUpCursor = (): void | El => { | ||
if (_elementIsInput()) { | ||
@@ -132,3 +133,3 @@ return; | ||
return cursor as Element; | ||
return cursor as El; | ||
} | ||
@@ -138,3 +139,3 @@ | ||
return cursor as Element; | ||
return cursor as El; | ||
}; | ||
@@ -148,9 +149,10 @@ | ||
_shouldRenderCursor && setCursorStyles(_id, _opts, _element); | ||
}; | ||
let _disableCursorBlink = (shouldDisable: boolean): void => { | ||
if (_shouldRenderCursor && _cursor) { | ||
_cursor.classList.toggle("disabled", shouldDisable); | ||
_cursor.classList.toggle("with-delay", !shouldDisable); | ||
if (_shouldRenderCursor) { | ||
setCursorStyles(_id, _element); | ||
setCursorAnimation({ | ||
cursor: _cursor as El, | ||
timingOptions: { | ||
duration: _opts.cursorSpeed, | ||
}, | ||
}); | ||
} | ||
@@ -264,3 +266,2 @@ }; | ||
let cleanUp = (qKey) => { | ||
_disableCursorBlink(false); | ||
_queue.done(qKey, !remember); | ||
@@ -278,4 +279,2 @@ }; | ||
if (queueItem.typeable && !_statuses.frozen) _disableCursorBlink(true); | ||
// Because calling .delete() with no parameters will attempt to | ||
@@ -289,4 +288,10 @@ // delete all "typeable" characters, we may overfetch, since some characters | ||
) { | ||
let newIndex = await fireItem(index, queueItems, _wait); | ||
let newIndex = await fireItem({ | ||
index, | ||
queueItems, | ||
wait: _wait, | ||
cursor: _cursor as El, | ||
}); | ||
// Ensure each skipped item goes through the cleanup process, | ||
@@ -471,2 +476,3 @@ // so that methods like .flush() don't get messed up. | ||
delay: instant ? 0 : _getPace(), | ||
cursorable: true | ||
}, | ||
@@ -473,0 +479,0 @@ Math.abs(numberOfSteps) |
@@ -9,5 +9,5 @@ import asArray from "./helpers/asArray"; | ||
let add = function (steps: QueueItem[] | QueueItem): typeof Queue { | ||
asArray<QueueItem>(steps).forEach((step) => | ||
_q.set(Symbol(step.char?.innerText), { ...step }) | ||
); | ||
asArray<QueueItem>(steps).forEach((step) => { | ||
return _q.set(Symbol(step.char?.innerText), buildQueueItem({ ...step })); | ||
}); | ||
@@ -26,5 +26,13 @@ return this; | ||
_q.set(keys[index], item); | ||
_q.set(keys[index], buildQueueItem(item)); | ||
}; | ||
let buildQueueItem = (queueItem: QueueItem): QueueItem => { | ||
queueItem.shouldPauseCursor = function () { | ||
return Boolean(this.typeable || this.cursorable || this.deletable); | ||
} | ||
return queueItem; | ||
} | ||
/** | ||
@@ -53,3 +61,3 @@ * Move all `executed` queue items to `waiting`. | ||
let done = (key: Symbol, shouldDestroy: boolean = false) => | ||
let done = (key: Symbol, shouldDestroy: boolean = false) => | ||
shouldDestroy ? _q.delete(key) : (_q.get(key).done = true); | ||
@@ -56,0 +64,0 @@ |
@@ -1,8 +0,5 @@ | ||
export type TypeItInstance = ( | ||
element: Element | string, | ||
options: Options | ||
) => void; | ||
export type TypeItInstance = (element: El | string, options: Options) => void; | ||
export type Character = { | ||
node: Element | null; | ||
node: El | null; | ||
content: string | Node; | ||
@@ -45,4 +42,16 @@ }; | ||
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 | ||
}; | ||
@@ -52,10 +61,7 @@ | ||
export type Element = HTMLElement & | ||
CharacterData & | ||
Node & | ||
ChildNode & { | ||
value: string | number; | ||
originalParent?: HTMLElement; | ||
}; | ||
export interface El extends HTMLElement { | ||
value: string | number; | ||
originalParent?: HTMLElement; | ||
} | ||
export type Sides = "START" | "END"; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
114500
90
2209
0
8