Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-joyride

Package Overview
Dependencies
Maintainers
1
Versions
137
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-joyride - npm Package Compare versions

Comparing version 3.0.0-4 to 3.0.0-5

src/modules/useJoyrideData.ts

54

dist/index.d.ts

@@ -17,2 +17,3 @@ import * as react_jsx_runtime from 'react/jsx-runtime';

readonly UPDATE: "update";
readonly COMPLETE: "complete";
};

@@ -102,2 +103,3 @@ declare const EVENTS: {

type Placement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end';
type SpotlightCSSProperties = Omit<CSSProperties, 'height' | 'width' | 'bottom' | 'left' | 'right' | 'top'>;
interface Styles {

@@ -115,4 +117,4 @@ beacon: CSSProperties;

overlayLegacyCenter: CSSProperties;
spotlight: CSSProperties;
spotlightLegacy: CSSProperties;
spotlight: SpotlightCSSProperties;
spotlightLegacy: SpotlightCSSProperties;
tooltip: CSSProperties;

@@ -126,3 +128,3 @@ tooltipContainer: CSSProperties;

interface StylesWithFloaterStyles extends Styles {
floaterStyles: Styles$1;
floaterStyles: PartialDeep<Styles$1>;
}

@@ -141,37 +143,2 @@ interface StylesOptions {

type Listener = (state: State) => void;
type PopperData = Parameters<NonNullable<Props$1['getPopper']>>[0];
declare class Store {
private beaconPopper;
private tooltipPopper;
private data;
private listener;
private store;
constructor(options?: StoreOptions);
getState(): State;
private getNextState;
private getSteps;
private hasUpdatedState;
private setState;
addListener: (listener: Listener) => void;
setSteps: (steps: Array<Step>) => void;
getHelpers(): StoreHelpers;
getPopper: (name: "beacon" | "tooltip") => PopperData | null;
setPopper: (name: "beacon" | "tooltip", popper: PopperData) => void;
cleanupPoppers: () => void;
close: (origin?: Origin | null) => void;
go: (nextIndex: number) => void;
info: () => State;
next: () => void;
open: () => void;
prev: () => void;
reset: (restart?: boolean) => void;
skip: () => void;
start: (nextIndex?: number) => void;
stop: (advance?: boolean) => void;
update: (state: Partial<State>) => void;
}
type StoreInstance = ReturnType<typeof createStore>;
declare function createStore(options?: StoreOptions): Store;
type FloaterProps = Omit<Props$1, 'content' | 'component'>;

@@ -439,3 +406,3 @@ type SelectorOrElement = string | null | HTMLElement;

type StepProps = Simplify<State & {
callback?: Callback;
cleanupPoppers: () => void;
continuous: boolean;

@@ -445,5 +412,6 @@ debug: boolean;

nonce?: string;
setPopper: NonNullable<FloaterProps['getPopper']>;
shouldScroll: boolean;
step: StepMerged;
store: StoreInstance;
updateState: (state: Partial<State>) => void;
}>;

@@ -460,5 +428,2 @@ type StoreHelpers = {

};
type StoreOptions = Simplify<Props & {
controlled: boolean;
}>;
type TooltipProps = {

@@ -509,4 +474,5 @@ continuous: boolean;

declare function Joyride(props: Props): react_jsx_runtime.JSX.Element | null;
declare function ReactJoyride(props: Props): react_jsx_runtime.JSX.Element | null;
export { ACTIONS, type Actions, type AnyObject, type BaseProps, type BeaconProps, type BeaconRenderProps, type CallBackProps, type Callback, EVENTS, type Events, type FloaterProps, LIFECYCLE, type Lifecycle, type Locale, type NarrowPlainObject, ORIGIN, type Origin, type OverlayProps, PORTAL_ELEMENT_ID, type Placement, type Props, STATUS, type SelectorOrElement, type State, type Status, type Step, type StepMerged, type StepProps, type StoreHelpers, type StoreOptions, type Styles, type StylesOptions, type StylesWithFloaterStyles, type TooltipProps, type TooltipRenderProps, ReactJoyride as default };
export { ACTIONS, type Actions, type AnyObject, type BaseProps, type BeaconProps, type BeaconRenderProps, type CallBackProps, type Callback, EVENTS, type Events, type FloaterProps, Joyride, LIFECYCLE, type Lifecycle, type Locale, type NarrowPlainObject, ORIGIN, type Origin, type OverlayProps, PORTAL_ELEMENT_ID, type Placement, type Props, STATUS, type SelectorOrElement, type SpotlightCSSProperties, type State, type Status, type Step, type StepMerged, type StepProps, type StoreHelpers, type Styles, type StylesOptions, type StylesWithFloaterStyles, type TooltipProps, type TooltipRenderProps, ReactJoyride as default };
{
"name": "react-joyride",
"version": "3.0.0-4",
"version": "3.0.0-5",
"description": "Create guided tours for your apps",

@@ -42,3 +42,2 @@ "author": "Gil Barbara <gilbarbara@gmail.com>",

"@gilbarbara/hooks": "^0.8.2",
"deep-diff": "^1.0.2",
"deepmerge": "^4.3.1",

@@ -50,3 +49,3 @@ "is-lite": "^1.2.1",

"scrollparent": "^2.1.0",
"tree-changes": "^0.11.2"
"tree-changes-hook": "^0.11.2"
},

@@ -76,2 +75,3 @@ "devDependencies": {

"caniuse-lite": "^1.0.30001659",
"chalk": "^5.3.0",
"cross-env": "^7.0.3",

@@ -138,2 +138,10 @@ "csstype": "^3.1.3",

}
],
"no-restricted-syntax": [
"warn",
{
"message": "Don't forget to remove calls to logger before committing.",
"selector":
"CallExpression[callee.name='logger']"
}
]

@@ -140,0 +148,0 @@ },

import { noop } from '~/modules/helpers';
import { LIFECYCLE, STATUS } from '~/literals';
import { ACTIONS, LIFECYCLE, STATUS } from '~/literals';

@@ -74,3 +74,3 @@ import { FloaterProps, Locale, Props, State, Step } from '~/types';

export const defaultState: State = {
action: 'init',
action: ACTIONS.INIT,
controlled: false,

@@ -77,0 +77,0 @@ index: 0,

@@ -12,2 +12,3 @@ export const ACTIONS = {

UPDATE: 'update',
COMPLETE: 'complete',
} as const;

@@ -14,0 +15,0 @@

@@ -58,3 +58,7 @@ import scroll from 'scroll';

*/
export function getElement(element: string | HTMLElement): HTMLElement | null {
export function getElement(element?: string | HTMLElement): HTMLElement | null {
if (!element) {
return null;
}
if (typeof element === 'string') {

@@ -61,0 +65,0 @@ try {

@@ -119,10 +119,2 @@ import { isValidElement, ReactNode } from 'react';

export function hasValidKeys(object: Record<string, unknown>, keys?: Array<string>): boolean {
if (!is.plainObject(object) || !is.array(keys)) {
return false;
}
return Object.keys(object).every(d => keys.includes(d));
}
/**

@@ -146,4 +138,3 @@ * Convert hex to RGB

const withContinuous =
continuous && ([ACTIONS.PREV, ACTIONS.NEXT, ACTIONS.UPDATE] as Actions[]).includes(action);
const withContinuous = continuous && ([ACTIONS.PREV, ACTIONS.NEXT] as Actions[]).includes(action);

@@ -167,3 +158,3 @@ return step.disableBeacon || step.placement === 'center' || withContinuous;

/* eslint-disable no-console */
const logFn = warn ? console.warn || console.error : console.log;
const logFn = warn ? console.warn ?? console.error : console.log;

@@ -170,0 +161,0 @@ if (debug) {

@@ -35,3 +35,7 @@ import { Props as FloaterProps } from 'react-floater';

export function getMergedStep(props: Props, currentStep?: Step): StepMerged {
export function getMergedStep(props: Props, currentStep?: Step): StepMerged | null {
if (!currentStep) {
return null;
}
const step = currentStep ?? {};

@@ -38,0 +42,0 @@ const mergedStep = deepmerge.all([defaultStep, getTourProps(props), step], {

import { Props as FloaterProps } from 'react-floater';
import deepEqual from '@gilbarbara/deep-equal';
import is from 'is-lite';
import { getMergedStep } from '~/modules/step';
import { ACTIONS, LIFECYCLE, STATUS } from '~/literals';
import { Origin, State, Status, Step, StoreHelpers, StoreOptions } from '~/types';
import { Origin, Props, State, Status, Step, StoreHelpers } from '~/types';
import { hasValidKeys, objectKeys, omit } from './helpers';
type StateWithContinuous = State & { continuous: boolean };

@@ -23,3 +24,2 @@ type Listener = (state: State) => void;

};
const validKeys = objectKeys(omit(defaultState, 'controlled', 'size'));

@@ -29,7 +29,8 @@ class Store {

private tooltipPopper: PopperData | null;
private data: Map<string, any> = new Map();
private readonly data: Map<string, any> = new Map();
private listener: Listener | null;
private store: Map<string, any> = new Map();
private readonly props: Props;
private readonly store: Map<string, any> = new Map();
constructor(options?: StoreOptions) {
constructor(options?: Props) {
const { continuous = false, stepIndex, steps = [] } = options ?? {};

@@ -50,54 +51,42 @@

this.setSteps(steps);
this.beaconPopper = null;
this.tooltipPopper = null;
this.listener = null;
this.setSteps(steps);
this.props = options ?? { steps: [] };
}
public getState(): State {
if (!this.store.size) {
return { ...defaultState };
}
private getStep(nextIndex?: number): Step | null {
const steps = this.data.get('steps');
const { index } = this.getState();
return {
action: this.store.get('action') || '',
controlled: this.store.get('controlled') || false,
index: parseInt(this.store.get('index'), 10),
lifecycle: this.store.get('lifecycle') || '',
origin: this.store.get('origin') || null,
size: this.store.get('size') || 0,
status: (this.store.get('status') as Status) || '',
};
return getMergedStep(this.props, steps[nextIndex ?? index]);
}
private getNextState(state: Partial<State>, force: boolean = false): State {
const { action, controlled, index, size, status } = this.getState();
const newIndex = is.number(state.index) ? state.index : index;
const nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
private getUpdatedIndex(nextIndex: number): number {
const { size } = this.getState();
return {
action: state.action ?? action,
controlled,
index: nextIndex,
lifecycle: state.lifecycle ?? LIFECYCLE.INIT,
origin: state.origin ?? null,
size: state.size ?? size,
status: nextIndex === size ? STATUS.FINISHED : state.status ?? status,
};
return Math.min(Math.max(nextIndex, 0), size);
}
private getSteps(): Array<Step> {
const steps = this.data.get('steps');
return Array.isArray(steps) ? steps : [];
private hasUpdatedState(oldState: State): boolean {
return !deepEqual(oldState, this.getState());
}
private hasUpdatedState(oldState: State): boolean {
const before = JSON.stringify(oldState);
const after = JSON.stringify(this.getState());
private prepareState(patch: Partial<State>, forceIndex: boolean = false): State {
const { action, controlled, index, size, status } = this.getState();
const newIndex = patch.index ?? index;
return before !== after;
return {
action: patch.action ?? action,
controlled,
index: controlled && !forceIndex ? index : newIndex,
lifecycle: patch.lifecycle ?? LIFECYCLE.INIT,
origin: patch.origin ?? null,
size: patch.size ?? size,
status: patch.status ?? status,
};
}
private setState(nextState: Partial<StateWithContinuous>, initial: boolean = false) {
private setState(patch: Partial<StateWithContinuous>, initial: boolean = false) {
const state = this.getState();

@@ -114,3 +103,3 @@

...state,
...nextState,
...patch,
};

@@ -126,4 +115,4 @@

if (initial) {
this.store.set('controlled', nextState.controlled);
this.store.set('continuous', nextState.continuous);
this.store.set('controlled', patch.controlled);
this.store.set('continuous', patch.continuous);
}

@@ -136,2 +125,43 @@

public updateState = (patch: Partial<State>, forceIndex = false) => {
this.setState({
...this.getState(),
...this.prepareState(patch, forceIndex),
});
};
public cleanupPoppers = () => {
this.beaconPopper = null;
this.tooltipPopper = null;
};
public getPopper = (name: 'beacon' | 'tooltip'): PopperData | null => {
if (name === 'beacon') {
return this.beaconPopper;
}
return this.tooltipPopper;
};
public setPopper: NonNullable<FloaterProps['getPopper']> = (popper, type) => {
if (type === 'wrapper') {
this.beaconPopper = popper;
} else {
this.tooltipPopper = popper;
}
if (popper && this.store.get('lifecycle') === LIFECYCLE.COMPLETE) {
this.updateState({
action: ACTIONS.UPDATE,
lifecycle: LIFECYCLE.INIT,
});
}
const getPopper = this.getStep()?.floaterProps?.getPopper;
if (getPopper) {
getPopper(popper, type);
}
};
public addListener = (listener: Listener) => {

@@ -141,2 +171,18 @@ this.listener = listener;

public getState(): State {
if (!this?.store?.size) {
return { ...defaultState };
}
return {
action: this.store.get('action') || '',
controlled: this.store.get('controlled') || false,
index: parseInt(this.store.get('index'), 10),
lifecycle: this.store.get('lifecycle') || '',
origin: this.store.get('origin') || null,
size: this.store.get('size') || 0,
status: (this.store.get('status') as Status) || '',
};
}
public setSteps = (steps: Array<Step>) => {

@@ -155,3 +201,3 @@ const { size, status } = this.getState();

this.setState(state);
this.updateState(state);
};

@@ -172,23 +218,2 @@

public getPopper = (name: 'beacon' | 'tooltip'): PopperData | null => {
if (name === 'beacon') {
return this.beaconPopper;
}
return this.tooltipPopper;
};
public setPopper = (name: 'beacon' | 'tooltip', popper: PopperData) => {
if (name === 'beacon') {
this.beaconPopper = popper;
} else {
this.tooltipPopper = popper;
}
};
public cleanupPoppers = () => {
this.beaconPopper = null;
this.tooltipPopper = null;
};
public close = (origin: Origin | null = null) => {

@@ -201,4 +226,7 @@ const { index, status } = this.getState();

this.setState({
...this.getNextState({ action: ACTIONS.CLOSE, index: index + 1, origin }),
this.updateState({
action: ACTIONS.CLOSE,
index: index + 1,
origin,
lifecycle: LIFECYCLE.COMPLETE,
});

@@ -214,6 +242,8 @@ };

const step = this.getSteps()[nextIndex];
const step = this.getStep(nextIndex);
this.setState({
...this.getNextState({ action: ACTIONS.GO, index: nextIndex }),
this.updateState({
action: ACTIONS.GO,
index: nextIndex,
lifecycle: LIFECYCLE.COMPLETE,
status: step ? status : STATUS.FINISHED,

@@ -232,3 +262,7 @@ });

this.setState(this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
this.updateState({
action: ACTIONS.NEXT,
index: this.getUpdatedIndex(index + 1),
lifecycle: LIFECYCLE.COMPLETE,
});
};

@@ -243,5 +277,3 @@

this.setState({
...this.getNextState({ action: ACTIONS.UPDATE, lifecycle: LIFECYCLE.TOOLTIP }),
});
this.updateState({ action: ACTIONS.UPDATE, lifecycle: LIFECYCLE.TOOLTIP });
};

@@ -256,4 +288,6 @@

this.setState({
...this.getNextState({ action: ACTIONS.PREV, index: index - 1 }),
this.updateState({
action: ACTIONS.PREV,
index: this.getUpdatedIndex(index - 1),
lifecycle: LIFECYCLE.COMPLETE,
});

@@ -269,4 +303,6 @@ };

this.setState({
...this.getNextState({ action: ACTIONS.RESET, index: 0 }),
this.updateState({
action: ACTIONS.RESET,
index: 0,
lifecycle: LIFECYCLE.COMPLETE,
status: restart ? STATUS.RUNNING : STATUS.READY,

@@ -283,5 +319,5 @@ });

this.setState({
this.updateState({
action: ACTIONS.SKIP,
lifecycle: LIFECYCLE.INIT,
lifecycle: LIFECYCLE.COMPLETE,
status: STATUS.SKIPPED,

@@ -294,12 +330,10 @@ });

this.setState({
...this.getNextState(
{
action: ACTIONS.START,
index: is.number(nextIndex) ? nextIndex : index,
},
true,
),
status: size ? STATUS.RUNNING : STATUS.WAITING,
});
this.updateState(
{
action: ACTIONS.START,
index: is.number(nextIndex) ? nextIndex : index,
status: size ? STATUS.RUNNING : STATUS.WAITING,
},
true,
);
};

@@ -314,25 +348,9 @@

this.setState({
...this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }),
this.updateState({
action: ACTIONS.STOP,
index: index + (advance ? 1 : 0),
lifecycle: LIFECYCLE.COMPLETE,
status: STATUS.PAUSED,
});
};
public update = (state: Partial<State>) => {
if (!hasValidKeys(state, validKeys)) {
throw new Error(`State is not valid. Valid keys: ${validKeys.join(', ')}`);
}
this.setState({
...this.getNextState(
{
...this.getState(),
...state,
action: state.action ?? ACTIONS.UPDATE,
origin: state.origin ?? null,
},
true,
),
});
};
}

@@ -342,4 +360,4 @@

export default function createStore(options?: StoreOptions) {
export default function createStore(options?: Props) {
return new Store(options);
}
import { useMount, useSetState, useUnmount } from '@gilbarbara/hooks';
import is from 'is-lite';
import { canUseDOM } from '~/modules/dom';
import { PORTAL_ELEMENT_ID } from '~/literals';

@@ -22,6 +20,2 @@

useMount(() => {
if (!canUseDOM()) {
return;
}
if (portalElement) {

@@ -50,3 +44,3 @@ if (is.domElement(portalElement)) {

useUnmount(() => {
if (!canUseDOM() || !element || useExternalPortal) {
if (!element || useExternalPortal) {
return;

@@ -53,0 +47,0 @@ }

import { CSSProperties, ReactNode } from 'react';
import { Styles as FloaterStyles } from 'react-floater';
import { ValueOf } from '@gilbarbara/types';
import { PartialDeep, ValueOf } from '@gilbarbara/types';

@@ -74,2 +74,7 @@ import { ACTIONS, EVENTS, LIFECYCLE, ORIGIN, STATUS } from '~/literals';

export type SpotlightCSSProperties = Omit<
CSSProperties,
'height' | 'width' | 'bottom' | 'left' | 'right' | 'top'
>;
export interface Styles {

@@ -87,4 +92,4 @@ beacon: CSSProperties;

overlayLegacyCenter: CSSProperties;
spotlight: CSSProperties;
spotlightLegacy: CSSProperties;
spotlight: SpotlightCSSProperties;
spotlightLegacy: SpotlightCSSProperties;
tooltip: CSSProperties;

@@ -99,3 +104,3 @@ tooltipContainer: CSSProperties;

export interface StylesWithFloaterStyles extends Styles {
floaterStyles: FloaterStyles;
floaterStyles: PartialDeep<FloaterStyles>;
}

@@ -102,0 +107,0 @@

@@ -5,4 +5,2 @@ import { ElementType, MouseEventHandler, ReactNode, RefCallback } from 'react';

import type { StoreInstance } from '~/modules/store';
import { Actions, Events, Lifecycle, Locale, Origin, Placement, Status, Styles } from './common';

@@ -316,3 +314,3 @@

State & {
callback?: Callback;
cleanupPoppers: () => void;
continuous: boolean;

@@ -322,5 +320,6 @@ debug: boolean;

nonce?: string;
setPopper: NonNullable<FloaterProps['getPopper']>;
shouldScroll: boolean;
step: StepMerged;
store: StoreInstance;
updateState: (state: Partial<State>) => void;
}

@@ -340,8 +339,2 @@ >;

export type StoreOptions = Simplify<
Props & {
controlled: boolean;
}
>;
export type TooltipProps = {

@@ -348,0 +341,0 @@ continuous: boolean;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc