UNPKG

@rently-team/shepherd.js

Version:

Guide your users through a tour of your app.

104 lines (91 loc) 2.95 kB
import { type Tour, type TourOptions } from '../tour.ts'; import { type StepOptionsAttachTo, type Step, type StepOptions } from '../step.ts'; import { isFunction, isString } from './type-check.ts'; export class StepNoOp { constructor(_options: StepOptions) {} } export class TourNoOp { constructor(_tour: Tour, _options: TourOptions) {} } /** * Ensure class prefix ends in `-` * @param prefix - The prefix to prepend to the class names generated by nano-css * @return The prefix ending in `-` */ export function normalizePrefix(prefix?: string) { if (!isString(prefix) || prefix === '') { return ''; } return prefix.charAt(prefix.length - 1) !== '-' ? `${prefix}-` : prefix; } /** * Resolves attachTo options, converting element option value to a qualified HTMLElement. * @param step - The step instance * @returns {{}|{element, on}} * `element` is a qualified HTML Element * `on` is a string position value */ export function parseAttachTo(step: Step) { const options = step.options.attachTo || {}; const returnOpts = Object.assign({}, options); if (isFunction(returnOpts.element)) { // Bind the callback to step so that it has access to the object, to enable running additional logic returnOpts.element = returnOpts.element.call(step); } if (isString(returnOpts.element)) { // Can't override the element in user opts reference because we can't // guarantee that the element will exist in the future. try { returnOpts.element = document.querySelector( returnOpts.element ) as HTMLElement; } catch (e) { // TODO } if (!returnOpts.element) { console.error( `The element for this Shepherd step was not found ${options.element}` ); } } return returnOpts; } /* * Resolves the step's `extraHighlights` option, converting any locator values to HTMLElements. */ export function parseExtraHighlights(step: Step): HTMLElement[] { if (step.options.extraHighlights) { return step.options.extraHighlights.flatMap((highlight) => { return Array.from(document.querySelectorAll(highlight)) as HTMLElement[]; }); } return []; } /** * Checks if the step should be centered or not. Does not trigger attachTo.element evaluation, making it a pure * alternative for the deprecated step.isCentered() method. */ export function shouldCenterStep(resolvedAttachToOptions: StepOptionsAttachTo) { if ( resolvedAttachToOptions === undefined || resolvedAttachToOptions === null ) { return true; } return !resolvedAttachToOptions.element || !resolvedAttachToOptions.on; } /** * Create a unique id for steps, tours, modals, etc */ export function uuid() { let d = Date.now(); return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16); }); }