@glowhop/core-tour 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,18 @@
1
- import type { ReadonlyStepProps, StepProps } from "./types";
1
+ import type { TourClassNames, TourControls } from "../types";
2
+ import type { DeepReadonly, ReadonlyStepProps, StepProps } from "./types";
2
3
  /**
3
4
  * Creates a shallow clone of step properties with deep clones of nested objects.
4
5
  * @param props The properties to clone.
5
6
  * @returns A mutable copy of the properties.
6
7
  */
7
8
  export declare function cloneStepProps<T>(props: ReadonlyStepProps<T>): StepProps<T>;
9
+ /** Copies `controls` into frozen records, with frozen copies of their `keys`. */
10
+ export declare function cloneControls(controls: DeepReadonly<TourControls> | undefined): TourControls | undefined;
11
+ /**
12
+ * Copies `classNames` into a frozen record. Its class arrays are shared rather than copied: they are
13
+ * typed readonly and nothing in the tour writes to them, and copying them costs bundle size.
14
+ */
15
+ export declare function cloneClassNames(classNames: TourClassNames | undefined): TourClassNames | undefined;
8
16
  /**
9
17
  * Creates a deep-frozen copy of step properties.
10
18
  * @param props The properties to freeze.
@@ -1,18 +1,21 @@
1
- import type { EventHandler, IndicatorOptions, OverlayOptions, PopoverOptions, PrimitiveValue, StartOptions, StepActionInstruction, StepBehavior, StepParameters, StepTransitionAction, TargetResolver } from "../types";
1
+ import type { IndicatorOptions, OverlayOptions, PopoverOptions, PrimitiveValue, StartOptions, StepActionInstruction, StepBehavior, StepHookAction, StepParameters, TargetEventHandler, TargetResolver, TourClassNames, TourControls } from "../types";
2
2
  /** Recursively makes all properties readonly at any depth. */
3
3
  export type DeepReadonly<T> = T extends (...arguments_: infer _Arguments) => infer _Return ? T : T extends readonly (infer TEntry)[] ? readonly DeepReadonly<TEntry>[] : T extends object ? {
4
4
  readonly [TKey in keyof T]: DeepReadonly<T[TKey]>;
5
5
  } : T;
6
- /** Step properties (title, content, and optional display options) excluding target and behavior. */
7
- export type StepProps<T> = Omit<StepParameters<T>, "id" | "target" | "resetPropsOnEnter" | "behavior">;
6
+ /** Step properties (title, content, behavior, and optional display options) excluding id and target. */
7
+ export type StepProps<T> = Omit<StepParameters<T>, "id" | "target">;
8
8
  /** Immutable step properties. */
9
9
  export type ReadonlyStepProps<T> = {
10
- readonly title: T;
10
+ readonly title?: T;
11
11
  readonly content: T;
12
12
  readonly data?: Readonly<Record<string, PrimitiveValue>>;
13
13
  readonly overlay?: DeepReadonly<OverlayOptions>;
14
14
  readonly popover?: DeepReadonly<PopoverOptions>;
15
15
  readonly indicator?: DeepReadonly<IndicatorOptions>;
16
+ readonly behavior?: DeepReadonly<StepBehavior>;
17
+ readonly controls?: DeepReadonly<TourControls>;
18
+ readonly classNames?: DeepReadonly<TourClassNames>;
16
19
  };
17
20
  /** Immutable tour start options. */
18
21
  export type ReadonlyStartOptions<T> = DeepReadonly<StartOptions<T>>;
@@ -21,14 +24,11 @@ export interface WorkflowStepDefinition<T> {
21
24
  /** Stable identifier, unique within the workflow. */
22
25
  readonly id: string;
23
26
  readonly target: TargetResolver;
24
- readonly resetPropsOnEnter?: boolean;
25
- readonly behavior?: DeepReadonly<StepBehavior>;
26
27
  readonly props: ReadonlyStepProps<T>;
27
28
  readonly actions: readonly StepActionInstruction<T>[];
28
- readonly eventHandlers: readonly EventHandler<T>[];
29
- readonly advanceAction: StepTransitionAction<T> | null;
30
- readonly previousAction: StepTransitionAction<T> | null;
31
- readonly cancelAction: StepTransitionAction<T> | null;
29
+ readonly targetEvents: readonly TargetEventHandler<T>[];
30
+ readonly beforeEnter: StepHookAction<T> | null;
31
+ readonly beforeLeave: StepHookAction<T> | null;
32
32
  }
33
33
  /** A complete tour workflow definition (immutable). */
34
34
  export interface WorkflowDefinition<T> {
@@ -1,16 +1,13 @@
1
- import type { EventHandler, StartOptions, StepActionInstruction, StepParameters, StepTransitionAction } from "../types";
1
+ import type { StartOptions, StepActionInstruction, StepHookAction, StepParameters, TargetEventHandler } from "../types";
2
2
  import type { StepProps, WorkflowDefinition, WorkflowStepDefinition } from "./types";
3
3
  export interface WorkflowStepDraft<T> {
4
4
  id: string;
5
5
  target: StepParameters<T>["target"];
6
- resetPropsOnEnter?: boolean;
7
6
  props: StepProps<T>;
8
- behavior?: StepParameters<T>["behavior"];
9
7
  actions: StepActionInstruction<T>[];
10
- eventHandlers: EventHandler<T>[];
11
- advanceAction: StepTransitionAction<T> | null;
12
- previousAction: StepTransitionAction<T> | null;
13
- cancelAction: StepTransitionAction<T> | null;
8
+ targetEvents: TargetEventHandler<T>[];
9
+ beforeEnter: StepHookAction<T> | null;
10
+ beforeLeave: StepHookAction<T> | null;
14
11
  }
15
12
  /**
16
13
  * Creates a mutable copy of a workflow step definition.
@@ -5,6 +5,7 @@ export interface TourViewCommands {
5
5
  canAdvance(): boolean;
6
6
  canCancel(): boolean;
7
7
  canPrevious(): boolean;
8
+ goTo(id: string): Promise<void>;
8
9
  isAdvanceDisabled(): boolean;
9
10
  isCancelDisabled(): boolean;
10
11
  isPreviousDisabled(): boolean;
@@ -73,11 +74,26 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
73
74
  private modalDocument;
74
75
  private modalRoot;
75
76
  private overlay;
76
- private pendingKeyboardCommand;
77
+ /** A command asked for while a visible popover was replaced, run once the new step is presented. */
78
+ private pendingCommand;
77
79
  private pointer;
78
80
  private pendingFocusGeneration;
81
+ /**
82
+ * The last click a presented step's button handled. It bubbles on to the window after the
83
+ * command it ran started the next step, and must not be queued a second time there.
84
+ */
85
+ private handledTriggerClick;
79
86
  private popover;
80
87
  private presentationDirty;
88
+ /**
89
+ * The focus a clear gives back once the popover has faded out. Kept past a clear that a new show
90
+ * supersedes, so that tour returns focus there instead of to the fading popover.
91
+ */
92
+ private focusToRestore;
93
+ /** The `allowInteraction` value the overlay, the page modality and the focus guard reflect. */
94
+ private appliedAllowInteraction;
95
+ /** Set when a live `allowInteraction` change started the pointer fade; the next frame clears it. */
96
+ private pointerFading;
81
97
  private rafId;
82
98
  private rafCancel;
83
99
  private root;
@@ -96,6 +112,7 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
96
112
  private activateRegisteredElements;
97
113
  private initializeElements;
98
114
  private syncModality;
115
+ private claimModal;
99
116
  private releaseModality;
100
117
  private restoreInertBranches;
101
118
  /**
@@ -125,6 +142,8 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
125
142
  private presentStepUi;
126
143
  /** The popover and pointer entrance itself, started synchronously. */
127
144
  private enterStepUi;
145
+ /** Fades the pointer in on the target, or out when the step does not show it. */
146
+ private presentPointer;
128
147
  private attachStepResources;
129
148
  /**
130
149
  * Binds the step's custom event handlers to its target element. Split out
@@ -146,9 +165,20 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
146
165
  private trackStepUi;
147
166
  private observeDynamicOperation;
148
167
  private handleKeydown;
168
+ /**
169
+ * The keyboard shortcut a keydown asks for, if `available` allows it. `null` leaves the key to the
170
+ * browser, as Enter on a focused control is: on a tour button, the click it produces runs that
171
+ * button's own command after the consumer's click handlers, like a pointer click.
172
+ */
173
+ private keyboardCommand;
149
174
  private handleOverlayClick;
150
175
  private queueTransitionKeydown;
151
- private flushPendingKeyboardCommand;
176
+ /**
177
+ * Queues the command of a tour button clicked while a visible popover is replaced. Listening on
178
+ * the window runs after the consumer's own click handlers, so a prevented click queues nothing.
179
+ */
180
+ private queueTransitionClick;
181
+ private flushPendingCommand;
152
182
  private loopFocus;
153
183
  private activateFocus;
154
184
  private syncScrollLock;
@@ -167,6 +197,11 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
167
197
  private syncControl;
168
198
  private isConsumerDisabled;
169
199
  private isLiveDisabled;
200
+ /**
201
+ * The props the overlay and popover render: the step's own, flagged when the step is detached so
202
+ * the overlay drops its cutout and the popover centers itself.
203
+ */
204
+ private elementProps;
170
205
  private isPointerEnabled;
171
206
  private cleanupStepResources;
172
207
  private cleanupTargetResources;
@@ -192,6 +227,14 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
192
227
  * and to restore the step's own setting once retargeted.
193
228
  */
194
229
  private applyInteractionLock;
230
+ /** Applies the step's own interaction setting to the overlay, the page modality and the focus guard. */
231
+ private applyInteraction;
232
+ /**
233
+ * Applies a `behavior.allowInteraction` changed through the step props while the step is on
234
+ * screen. A step still entering reads the new value when it presents, and a frozen one keeps
235
+ * interaction off until `retarget()` restores it. The indicator fades in or out instead of snapping.
236
+ */
237
+ private syncInteraction;
195
238
  private isFocusInsideTarget;
196
239
  /**
197
240
  * Resumes a presentation frozen by `freezeForDisconnectedTarget` on its new
@@ -200,7 +243,7 @@ export declare class DomTourViewDriver<T> implements TourViewDriver<T> {
200
243
  * and popover to the new rect on the next frame. Deliberately skips
201
244
  * `appear()` (no re-entrance animation) and `activateFocus()` (focus stays
202
245
  * where the user left it), only reclaiming it if it was on the target that
203
- * just disappeared.
246
+ * just disappeared and the step auto focuses.
204
247
  */
205
248
  retarget(step: ActiveStep<T>, signal: AbortSignal): Promise<void>;
206
249
  /**
@@ -1,5 +1,7 @@
1
1
  import type { IndicatorOptions, OverlayOptions, PopoverOptions } from "../types";
2
2
  export interface TourElementStep {
3
+ /** No target: the popover is centered and the backdrop has no cutout. */
4
+ readonly detached?: boolean;
3
5
  readonly indicator?: IndicatorOptions;
4
6
  readonly overlay?: OverlayOptions;
5
7
  readonly popover?: PopoverOptions;
@@ -12,6 +14,13 @@ export default abstract class GlowTourElement {
12
14
  disabled?: boolean;
13
15
  } | undefined;
14
16
  private readonly animations;
17
+ /**
18
+ * Animations that ran to completion and whose `fill: "forwards"` still applies.
19
+ *
20
+ * They keep overriding the element's inline styles, so a presentation that writes its state
21
+ * without animating would be painted with the previous animation's last frame instead.
22
+ */
23
+ private readonly filledAnimations;
15
24
  private readonly cancelledAnimations;
16
25
  private released;
17
26
  constructor(element: HTMLElement | SVGSVGElement, options?: {
@@ -49,12 +58,25 @@ export default abstract class GlowTourElement {
49
58
  */
50
59
  private _finishWhileDocumentHidden;
51
60
  protected _waitForAnimation(animation: Animation): Promise<boolean>;
52
- protected abstract _disappear(): Promise<void>;
61
+ /**
62
+ * Drops what finished animations still impose on the element.
63
+ *
64
+ * Every animation is followed by the inline styles that record the state it landed on, so
65
+ * releasing the fill leaves the element exactly as it looks. Without this, a fade-out that
66
+ * finished keeps forcing `opacity: 0` over the inline `opacity: 1` of the next presentation,
67
+ * and an unanimated one never starts an animation of its own to take the fill over.
68
+ */
69
+ protected _releaseFilledAnimations(): void;
70
+ protected abstract _disappear(hideFromAssistiveTechnology?: boolean): Promise<void>;
53
71
  protected abstract _getNextStyles(position: DOMRect, step: TourElementStep): Keyframe;
54
72
  abstract updatePosition(nextPosition: DOMRect, step: TourElementStep): void;
55
73
  abstract initializeProps(): void;
56
74
  getElement(): HTMLElement | SVGSVGElement | null;
57
- disappear(): Promise<void>;
75
+ /**
76
+ * Fades the element out. The popover stays exposed to assistive technology when passed `false`,
77
+ * for a step change: its live region then announces the new step and focus stays in it.
78
+ */
79
+ disappear(hideFromAssistiveTechnology?: boolean): Promise<void>;
58
80
  release(): void;
59
81
  cancelAnimations(): void;
60
82
  protected _cancelAnimation(animation: Animation): void;
@@ -19,13 +19,19 @@ export default class PopoverElement extends GlowTourElement {
19
19
  /**
20
20
  * Fades the popover in at `nextPosition` and commits that placement.
21
21
  *
22
- * The outgoing half of a step change is {@link disappear}, deliberately kept
23
- * separate: between the two, the caller swaps the step's content while the
24
- * popover is off screen, and — when the step scrolls — waits for the scroll
25
- * to settle so this entrance reads a rect that will not move again.
22
+ * The outgoing half of a step change is `disappear(false)`, which keeps the
23
+ * popover exposed to assistive technology, deliberately kept separate: between the two, the caller swaps the step's
24
+ * content while the popover is faded out, and — when the step scrolls — waits
25
+ * for the scroll to settle so this entrance reads a rect that will not move
26
+ * again.
26
27
  */
27
28
  present(nextPosition: DOMRect, step: TourElementStep): Promise<void>;
28
- initializeProps(): void;
29
+ /**
30
+ * Resets the popover to its idle presentation. A step change that replaces a
31
+ * visible popover passes `false`: the popover stays exposed so its live
32
+ * region announces the new step and focus stays in it.
33
+ */
34
+ initializeProps(hideFromAssistiveTechnology?: boolean): void;
29
35
  updatePosition(nextPosition: DOMRect, step: TourElementStep, onReposition?: (reposition: Promise<void>) => void): ResolvedPlacement;
30
36
  cancelAnimations(): void;
31
37
  private _flushReposition;
@@ -34,8 +40,14 @@ export default class PopoverElement extends GlowTourElement {
34
40
  private _applyArrowStyles;
35
41
  private _applyArrowStyle;
36
42
  _appear(position: DOMRect, step: TourElementStep): Promise<void>;
37
- _disappear(): Promise<void>;
43
+ _disappear(hideFromAssistiveTechnology?: boolean): Promise<void>;
38
44
  protected _release(): void;
39
45
  private _applyVisibleState;
46
+ /**
47
+ * Out of sight but still exposed to assistive technology. Pointer input is blocked the way
48
+ * `inert` blocks it: the controller ignores commands mid-transition, so a click must not look
49
+ * accepted.
50
+ */
51
+ private _applyFadedState;
40
52
  private _applyHiddenState;
41
53
  }
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export type { EventName, WorkflowBuilder, WorkflowStepBuilder } from "./builder";
2
2
  export type { ReadonlyStartOptions, ReadonlyStepProps, WorkflowDefinition, WorkflowStepDefinition, } from "./definition";
3
3
  export { createGlowTour } from "./runtime/tour-controller";
4
- export type { AnimationOptions, BaseOptions, BeforeActionStepContext, EventHandler, GlowTour, GlowTourOptions, IndicatorOptions, LifecycleHookContext, OverlayOptions, PopoverArrowOptions, PopoverOptions, PrimitiveValue, ReadonlyTourState, ResolvedPlacement, ScrollOptions, StartOptions, StepAction, StepActionInstruction, StepActionResult, StepBehavior, StepContext, StepEventContext, StepParameters, StepPropsStore, StepPropsUpdate, StepTransitionAction, TargetResolver, TargetResolverContext, TourCurrentStep, TourDirection, TourEvent, TourEventListener, TourEventSource, TourEventType, TourState, TourStatus, TryOrderOptions, WaitUntilOptions, } from "./types";
4
+ export type { AnimationOptions, BaseOptions, ClassValue, GlowTour, GlowTourOptions, IndicatorOptions, LifecycleHookContext, MissingTargetOptions, OverlayOptions, PopoverArrowOptions, PopoverOptions, PrimitiveValue, ReadonlyTourState, ResolvedPlacement, ScrollOptions, StartOptions, StepAction, StepActionInstruction, StepActionResult, StepBehavior, StepContext, StepEventContext, StepHookAction, StepHookContext, StepParameters, StepPropsPatch, StepPropsStore, StepPropsUpdate, TargetEventHandler, TargetResolver, TargetResolverContext, TourClassNames, TourControl, TourControlState, TourControls, TourCurrentStep, TourDirection, TourEvent, TourEventListener, TourEventSource, TourEventType, TourState, TourStatus, TryOrderOptions, WaitUntilOptions, } from "./types";