@docentjs/dom 0.5.2 → 0.7.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.
- package/dist/index.cjs +213 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -6
- package/dist/index.d.ts +40 -6
- package/dist/index.js +211 -5
- package/dist/index.js.map +1 -1
- package/dist/validate.cjs +9 -0
- package/dist/validate.d.cts +1 -0
- package/dist/validate.d.ts +1 -0
- package/dist/validate.js +1 -0
- package/package.json +12 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Alignment, ArrowStyle, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, OverlayOptions, Placement, RenderContext, Renderer, Side, SpotlightOptions, SpotlightShape, StorageAdapter, Target, TargetSpec, Theme, Tour, TourController, defineTour } from "@docentjs/core";
|
|
1
|
+
import { Alignment, Appearance, ArrowStyle, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, OverlayOptions, Placement, RenderContext, Renderer, Side, SpotlightOptions, SpotlightShape, StorageAdapter, Target, TargetSpec, Theme, ThemeSpec, Tour, TourController, defineTour } from "@docentjs/core";
|
|
2
2
|
//#region src/arrows.d.ts
|
|
3
3
|
export declare const CONNECTOR_STYLES: readonly ["line", "dashed", "dotted", "curve", "curve-dashed", "squiggle", "loop", "elbow", "sketch", "pin"];
|
|
4
4
|
type ConnectorStyle = (typeof CONNECTOR_STYLES)[number];
|
|
@@ -17,6 +17,15 @@ export declare const THEME_VARS: Record<keyof Theme, string>;
|
|
|
17
17
|
/** Write theme tokens as inline custom properties on an element. Clears unset ones. */
|
|
18
18
|
export declare function applyTheme(el: HTMLElement, theme: Theme | undefined): void;
|
|
19
19
|
export declare function mergeThemes(...themes: Array<Theme | undefined>): Theme;
|
|
20
|
+
/**
|
|
21
|
+
* Layer one theme over another when either may be a preset name. Used by the
|
|
22
|
+
* framework adapters to merge a provider's defaults with a local theme.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mergeThemeSpecs(base: ThemeSpec | undefined, override: ThemeSpec | undefined): ThemeSpec | undefined;
|
|
25
|
+
/** `{ theme }` when there is one, or nothing, for spreading into options. */
|
|
26
|
+
export declare function themeOption(theme: ThemeSpec | undefined): {
|
|
27
|
+
theme?: ThemeSpec;
|
|
28
|
+
};
|
|
20
29
|
/**
|
|
21
30
|
* Regions of the built-in popover that can be replaced. Custom content is
|
|
22
31
|
* projected through native Shadow DOM slots, so it lives in the page's DOM
|
|
@@ -39,7 +48,7 @@ type PopoverSlots = Partial<Record<SlotName, SlotRenderer>>;
|
|
|
39
48
|
* that defines the template stays in the app.
|
|
40
49
|
*/
|
|
41
50
|
interface PopoverTemplate {
|
|
42
|
-
theme?:
|
|
51
|
+
theme?: ThemeSpec;
|
|
43
52
|
slots?: PopoverSlots;
|
|
44
53
|
/** Arrow style for tours using this template. */
|
|
45
54
|
arrow?: ArrowStyle;
|
|
@@ -72,8 +81,10 @@ interface DomRendererOptions {
|
|
|
72
81
|
arrow?: ArrowStyle;
|
|
73
82
|
/** Overlay defaults when a tour sets none: style, color, opacity, blur. */
|
|
74
83
|
overlay?: OverlayOptions;
|
|
75
|
-
/** Base theme tokens. Tours and templates layer on top. */
|
|
76
|
-
theme?:
|
|
84
|
+
/** Base theme: a preset name, tokens, or both. Tours and templates layer on top. */
|
|
85
|
+
theme?: ThemeSpec;
|
|
86
|
+
/** Light (default), dark, or follow the reader's system setting. */
|
|
87
|
+
appearance?: Appearance;
|
|
77
88
|
/** Replace regions of the built-in popover. */
|
|
78
89
|
slots?: PopoverSlots;
|
|
79
90
|
/** Named templates that tours select with `options.template`. */
|
|
@@ -115,6 +126,11 @@ export declare class DomRenderer implements Renderer {
|
|
|
115
126
|
private connectorLoading;
|
|
116
127
|
/** Arrow, spotlight and overlay settings for the current step. */
|
|
117
128
|
private look;
|
|
129
|
+
/** Preset tokens, once loaded. */
|
|
130
|
+
private presets;
|
|
131
|
+
private presetLoad;
|
|
132
|
+
/** Set while `appearance: 'auto'` is following the system setting. */
|
|
133
|
+
private schemeQuery;
|
|
118
134
|
/** Until then the step's own transition runs; scroll updates may animate. */
|
|
119
135
|
private settleUntil;
|
|
120
136
|
/** Play the connector draw-in on its next render. */
|
|
@@ -124,7 +140,8 @@ export declare class DomRenderer implements Renderer {
|
|
|
124
140
|
hasTarget(target: Target): boolean;
|
|
125
141
|
waitForTarget(target: Target, timeoutMs: number, signal: AbortSignal): Promise<boolean>;
|
|
126
142
|
currentRoute(): string;
|
|
127
|
-
show(ctx: RenderContext): void
|
|
143
|
+
show(ctx: RenderContext): void | Promise<void>;
|
|
144
|
+
private showNow;
|
|
128
145
|
hide(): void;
|
|
129
146
|
/**
|
|
130
147
|
* Re-measure and re-position everything. Safe to call often. `tracking`
|
|
@@ -138,6 +155,18 @@ export declare class DomRenderer implements Renderer {
|
|
|
138
155
|
private loadConnector;
|
|
139
156
|
/** Add the connector layer and its styles, beneath any popover. */
|
|
140
157
|
private attachConnector;
|
|
158
|
+
/** Does anything here need the built-in presets? */
|
|
159
|
+
private usesPresets;
|
|
160
|
+
private loadPresets;
|
|
161
|
+
private appearance;
|
|
162
|
+
/** The surface tokens for the current appearance: dark, or nothing for light. */
|
|
163
|
+
private appearanceTheme;
|
|
164
|
+
private prefersDark;
|
|
165
|
+
/** Renderer, then the appearance surface, then template, then tour. */
|
|
166
|
+
private themeFor;
|
|
167
|
+
/** With `appearance: 'auto'`, follow the system setting while the tour runs. */
|
|
168
|
+
private watchAppearance;
|
|
169
|
+
private onSchemeChange;
|
|
141
170
|
private resolveLook;
|
|
142
171
|
/** Expose the look to the stylesheet as host attributes and variables. */
|
|
143
172
|
private applyLook;
|
|
@@ -161,6 +190,7 @@ export declare class DomRenderer implements Renderer {
|
|
|
161
190
|
* `scrollend` finishes early where supported; a cap keeps it bounded.
|
|
162
191
|
*/
|
|
163
192
|
private afterScroll;
|
|
193
|
+
/** The tour's template: one the app registered, or a built-in look. */
|
|
164
194
|
private template;
|
|
165
195
|
private buildDefault;
|
|
166
196
|
private buildHeadless;
|
|
@@ -222,6 +252,10 @@ export declare function createDocent(options?: CreateDocentOptions): Docent;
|
|
|
222
252
|
//#region src/environment.d.ts
|
|
223
253
|
export declare function createDomEnvironment(doc?: Document): DocentEnvironment;
|
|
224
254
|
//#endregion
|
|
255
|
+
//#region src/looks.d.ts
|
|
256
|
+
type LookName = 'spotlight' | 'hint' | 'announcement';
|
|
257
|
+
export declare const BUILT_IN_LOOKS: Record<LookName, PopoverTemplate>;
|
|
258
|
+
//#endregion
|
|
225
259
|
//#region src/position.d.ts
|
|
226
260
|
interface Rect {
|
|
227
261
|
x: number;
|
|
@@ -367,5 +401,5 @@ export declare function resolveTarget(target: Target, root?: QueryRoot): Element
|
|
|
367
401
|
*/
|
|
368
402
|
export declare function waitForTarget(target: Target, timeoutMs: number, signal?: AbortSignal, root?: QueryRoot): Promise<Element | null>;
|
|
369
403
|
//#endregion
|
|
370
|
-
export { type ConnectorStyle, type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
|
|
404
|
+
export { type ConnectorStyle, type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type LookName, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
|
|
371
405
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Alignment, ArrowStyle, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, OverlayOptions, Placement, RenderContext, Renderer, Side, SpotlightOptions, SpotlightShape, StorageAdapter, Target, TargetSpec, Theme, Tour, TourController, defineTour } from "@docentjs/core";
|
|
1
|
+
import { Alignment, Appearance, ArrowStyle, ControllerOptions, Docent, DocentEnvironment, DocentOptions, Labels, Media, OverlayOptions, Placement, RenderContext, Renderer, Side, SpotlightOptions, SpotlightShape, StorageAdapter, Target, TargetSpec, Theme, ThemeSpec, Tour, TourController, defineTour } from "@docentjs/core";
|
|
2
2
|
//#region src/arrows.d.ts
|
|
3
3
|
export declare const CONNECTOR_STYLES: readonly ["line", "dashed", "dotted", "curve", "curve-dashed", "squiggle", "loop", "elbow", "sketch", "pin"];
|
|
4
4
|
type ConnectorStyle = (typeof CONNECTOR_STYLES)[number];
|
|
@@ -17,6 +17,15 @@ export declare const THEME_VARS: Record<keyof Theme, string>;
|
|
|
17
17
|
/** Write theme tokens as inline custom properties on an element. Clears unset ones. */
|
|
18
18
|
export declare function applyTheme(el: HTMLElement, theme: Theme | undefined): void;
|
|
19
19
|
export declare function mergeThemes(...themes: Array<Theme | undefined>): Theme;
|
|
20
|
+
/**
|
|
21
|
+
* Layer one theme over another when either may be a preset name. Used by the
|
|
22
|
+
* framework adapters to merge a provider's defaults with a local theme.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mergeThemeSpecs(base: ThemeSpec | undefined, override: ThemeSpec | undefined): ThemeSpec | undefined;
|
|
25
|
+
/** `{ theme }` when there is one, or nothing, for spreading into options. */
|
|
26
|
+
export declare function themeOption(theme: ThemeSpec | undefined): {
|
|
27
|
+
theme?: ThemeSpec;
|
|
28
|
+
};
|
|
20
29
|
/**
|
|
21
30
|
* Regions of the built-in popover that can be replaced. Custom content is
|
|
22
31
|
* projected through native Shadow DOM slots, so it lives in the page's DOM
|
|
@@ -39,7 +48,7 @@ type PopoverSlots = Partial<Record<SlotName, SlotRenderer>>;
|
|
|
39
48
|
* that defines the template stays in the app.
|
|
40
49
|
*/
|
|
41
50
|
interface PopoverTemplate {
|
|
42
|
-
theme?:
|
|
51
|
+
theme?: ThemeSpec;
|
|
43
52
|
slots?: PopoverSlots;
|
|
44
53
|
/** Arrow style for tours using this template. */
|
|
45
54
|
arrow?: ArrowStyle;
|
|
@@ -72,8 +81,10 @@ interface DomRendererOptions {
|
|
|
72
81
|
arrow?: ArrowStyle;
|
|
73
82
|
/** Overlay defaults when a tour sets none: style, color, opacity, blur. */
|
|
74
83
|
overlay?: OverlayOptions;
|
|
75
|
-
/** Base theme tokens. Tours and templates layer on top. */
|
|
76
|
-
theme?:
|
|
84
|
+
/** Base theme: a preset name, tokens, or both. Tours and templates layer on top. */
|
|
85
|
+
theme?: ThemeSpec;
|
|
86
|
+
/** Light (default), dark, or follow the reader's system setting. */
|
|
87
|
+
appearance?: Appearance;
|
|
77
88
|
/** Replace regions of the built-in popover. */
|
|
78
89
|
slots?: PopoverSlots;
|
|
79
90
|
/** Named templates that tours select with `options.template`. */
|
|
@@ -115,6 +126,11 @@ export declare class DomRenderer implements Renderer {
|
|
|
115
126
|
private connectorLoading;
|
|
116
127
|
/** Arrow, spotlight and overlay settings for the current step. */
|
|
117
128
|
private look;
|
|
129
|
+
/** Preset tokens, once loaded. */
|
|
130
|
+
private presets;
|
|
131
|
+
private presetLoad;
|
|
132
|
+
/** Set while `appearance: 'auto'` is following the system setting. */
|
|
133
|
+
private schemeQuery;
|
|
118
134
|
/** Until then the step's own transition runs; scroll updates may animate. */
|
|
119
135
|
private settleUntil;
|
|
120
136
|
/** Play the connector draw-in on its next render. */
|
|
@@ -124,7 +140,8 @@ export declare class DomRenderer implements Renderer {
|
|
|
124
140
|
hasTarget(target: Target): boolean;
|
|
125
141
|
waitForTarget(target: Target, timeoutMs: number, signal: AbortSignal): Promise<boolean>;
|
|
126
142
|
currentRoute(): string;
|
|
127
|
-
show(ctx: RenderContext): void
|
|
143
|
+
show(ctx: RenderContext): void | Promise<void>;
|
|
144
|
+
private showNow;
|
|
128
145
|
hide(): void;
|
|
129
146
|
/**
|
|
130
147
|
* Re-measure and re-position everything. Safe to call often. `tracking`
|
|
@@ -138,6 +155,18 @@ export declare class DomRenderer implements Renderer {
|
|
|
138
155
|
private loadConnector;
|
|
139
156
|
/** Add the connector layer and its styles, beneath any popover. */
|
|
140
157
|
private attachConnector;
|
|
158
|
+
/** Does anything here need the built-in presets? */
|
|
159
|
+
private usesPresets;
|
|
160
|
+
private loadPresets;
|
|
161
|
+
private appearance;
|
|
162
|
+
/** The surface tokens for the current appearance: dark, or nothing for light. */
|
|
163
|
+
private appearanceTheme;
|
|
164
|
+
private prefersDark;
|
|
165
|
+
/** Renderer, then the appearance surface, then template, then tour. */
|
|
166
|
+
private themeFor;
|
|
167
|
+
/** With `appearance: 'auto'`, follow the system setting while the tour runs. */
|
|
168
|
+
private watchAppearance;
|
|
169
|
+
private onSchemeChange;
|
|
141
170
|
private resolveLook;
|
|
142
171
|
/** Expose the look to the stylesheet as host attributes and variables. */
|
|
143
172
|
private applyLook;
|
|
@@ -161,6 +190,7 @@ export declare class DomRenderer implements Renderer {
|
|
|
161
190
|
* `scrollend` finishes early where supported; a cap keeps it bounded.
|
|
162
191
|
*/
|
|
163
192
|
private afterScroll;
|
|
193
|
+
/** The tour's template: one the app registered, or a built-in look. */
|
|
164
194
|
private template;
|
|
165
195
|
private buildDefault;
|
|
166
196
|
private buildHeadless;
|
|
@@ -222,6 +252,10 @@ export declare function createDocent(options?: CreateDocentOptions): Docent;
|
|
|
222
252
|
//#region src/environment.d.ts
|
|
223
253
|
export declare function createDomEnvironment(doc?: Document): DocentEnvironment;
|
|
224
254
|
//#endregion
|
|
255
|
+
//#region src/looks.d.ts
|
|
256
|
+
type LookName = 'spotlight' | 'hint' | 'announcement';
|
|
257
|
+
export declare const BUILT_IN_LOOKS: Record<LookName, PopoverTemplate>;
|
|
258
|
+
//#endregion
|
|
225
259
|
//#region src/position.d.ts
|
|
226
260
|
interface Rect {
|
|
227
261
|
x: number;
|
|
@@ -367,5 +401,5 @@ export declare function resolveTarget(target: Target, root?: QueryRoot): Element
|
|
|
367
401
|
*/
|
|
368
402
|
export declare function waitForTarget(target: Target, timeoutMs: number, signal?: AbortSignal, root?: QueryRoot): Promise<Element | null>;
|
|
369
403
|
//#endregion
|
|
370
|
-
export { type ConnectorStyle, type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
|
|
404
|
+
export { type ConnectorStyle, type CreateDocentOptions, type CreateTourOptions, type DomRendererOptions, type HeadlessPopover, type LookName, type Occluder, type PopoverSlots, type PopoverTemplate, type PositionInput, type PositionResult, type QueryRoot, type Rect, type Size, type SlotContent, type SlotName, type SlotRenderer, defineTour };
|
|
371
405
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,80 @@ function renderMedia(doc, media) {
|
|
|
78
78
|
return video;
|
|
79
79
|
}
|
|
80
80
|
//#endregion
|
|
81
|
+
//#region src/dev.ts
|
|
82
|
+
const checked = /* @__PURE__ */ new WeakSet();
|
|
83
|
+
/**
|
|
84
|
+
* Written exactly like this on purpose: bundlers replace
|
|
85
|
+
* `process.env.NODE_ENV` literally, so a production build turns this into
|
|
86
|
+
* `false`, and the check plus its import are dropped. Without a bundler
|
|
87
|
+
* `process` is simply not defined, and the catch treats that as development.
|
|
88
|
+
*/
|
|
89
|
+
function isProduction() {
|
|
90
|
+
try {
|
|
91
|
+
return process.env.NODE_ENV === "production";
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check every tour the manager knows, as they load. Tours that never start
|
|
98
|
+
* still get checked, which is where a broken condition usually hides.
|
|
99
|
+
*/
|
|
100
|
+
function warnAboutTours(docent) {
|
|
101
|
+
if (isProduction()) return;
|
|
102
|
+
const check = () => {
|
|
103
|
+
for (const tour of docent.getTours()) warnIfInvalid(tour);
|
|
104
|
+
};
|
|
105
|
+
docent.subscribe(check);
|
|
106
|
+
check();
|
|
107
|
+
}
|
|
108
|
+
/** Warn about anything wrong with this tour, once per tour, in development. */
|
|
109
|
+
function warnIfInvalid(tour) {
|
|
110
|
+
if (!tour || isProduction() || checked.has(tour)) return;
|
|
111
|
+
checked.add(tour);
|
|
112
|
+
import("@docentjs/core/validate").then(({ formatIssues, validateTour }) => {
|
|
113
|
+
const issues = validateTour(tour);
|
|
114
|
+
if (issues.length === 0) return;
|
|
115
|
+
const label = issues.filter((issue) => issue.level === "error").length > 0 ? "error" : "warning";
|
|
116
|
+
console.warn(`[docent] Tour "${tour.id}" has ${issues.length} ${label}${issues.length === 1 ? "" : "s"}:\n${formatIssues(issues)}\nThis check runs in development only. See https://docentjs.dev/reference/schema/`);
|
|
117
|
+
}).catch(() => {});
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region src/looks.ts
|
|
121
|
+
const BUILT_IN_LOOKS = {
|
|
122
|
+
/** The default: a dimmed page, a soft cutout, a small caret. */
|
|
123
|
+
spotlight: {},
|
|
124
|
+
/**
|
|
125
|
+
* A light touch for tips beside a feature: the page stays usable and
|
|
126
|
+
* clickable, with a glowing ring and a drawn curve instead of a scrim.
|
|
127
|
+
*/
|
|
128
|
+
hint: {
|
|
129
|
+
overlay: { style: "none" },
|
|
130
|
+
spotlight: {
|
|
131
|
+
ring: "glow",
|
|
132
|
+
padding: 6
|
|
133
|
+
},
|
|
134
|
+
arrow: "curve",
|
|
135
|
+
theme: { width: 300 }
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* For something to read rather than something to do: the page blurs away,
|
|
139
|
+
* nothing points anywhere, and the card is wider.
|
|
140
|
+
*/
|
|
141
|
+
announcement: {
|
|
142
|
+
overlay: {
|
|
143
|
+
style: "blur",
|
|
144
|
+
blur: 6
|
|
145
|
+
},
|
|
146
|
+
spotlight: {
|
|
147
|
+
ring: "none",
|
|
148
|
+
padding: 10
|
|
149
|
+
},
|
|
150
|
+
arrow: "none",
|
|
151
|
+
theme: { width: 420 }
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
81
155
|
//#region src/occlusion.ts
|
|
82
156
|
function isPinned(el) {
|
|
83
157
|
const view = el.ownerDocument.defaultView;
|
|
@@ -677,18 +751,82 @@ const THEME_VARS = {
|
|
|
677
751
|
connector: "connector",
|
|
678
752
|
ring: "ring"
|
|
679
753
|
};
|
|
754
|
+
/** Tokens that take a unit when given as a number. */
|
|
755
|
+
const UNITS = {
|
|
756
|
+
radius: "px",
|
|
757
|
+
width: "px",
|
|
758
|
+
duration: "ms"
|
|
759
|
+
};
|
|
760
|
+
/** `12` becomes `12px`, `220` becomes `220ms`, strings are passed through. */
|
|
761
|
+
function cssValue(key, value) {
|
|
762
|
+
return typeof value === "number" ? `${value}${UNITS[key] ?? ""}` : value;
|
|
763
|
+
}
|
|
680
764
|
/** Write theme tokens as inline custom properties on an element. Clears unset ones. */
|
|
681
765
|
function applyTheme(el, theme) {
|
|
682
766
|
for (const key of Object.keys(THEME_VARS)) {
|
|
683
767
|
const value = theme?.[key];
|
|
684
768
|
const prop = `--docent-${THEME_VARS[key]}`;
|
|
685
769
|
if (value === void 0) el.style.removeProperty(prop);
|
|
686
|
-
else el.style.setProperty(prop, value);
|
|
770
|
+
else el.style.setProperty(prop, cssValue(key, value));
|
|
771
|
+
}
|
|
772
|
+
if (theme?.accent !== void 0 && theme.accentForeground === void 0) {
|
|
773
|
+
const light = isLightColor(el, cssValue("accent", theme.accent));
|
|
774
|
+
if (light !== void 0) el.style.setProperty("--docent-accent-fg", light ? "var(--docent-fg)" : "var(--docent-bg)");
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Is this colour light enough to need dark text on it? Resolves the colour
|
|
779
|
+
* through the browser, so any CSS colour works. Undefined when it cannot tell.
|
|
780
|
+
*/
|
|
781
|
+
function isLightColor(el, color) {
|
|
782
|
+
const view = el.ownerDocument.defaultView;
|
|
783
|
+
if (!view) return void 0;
|
|
784
|
+
const previous = el.style.color;
|
|
785
|
+
el.style.color = color;
|
|
786
|
+
const computed = view.getComputedStyle(el).color;
|
|
787
|
+
el.style.color = previous;
|
|
788
|
+
const rgb = computed.match(/^(?:rgba?|color\(srgb)[( ]([^)]+)\)?/);
|
|
789
|
+
if (rgb?.[1]) {
|
|
790
|
+
const [r = 0, g = 0, b = 0] = rgb[1].split(/[\s,/]+/).slice(0, 3).map((n) => n.endsWith("%") ? Number.parseFloat(n) / 100 * 255 : Number.parseFloat(n));
|
|
791
|
+
const scale = computed.startsWith("color(") ? 255 : 1;
|
|
792
|
+
return (.2126 * r * scale + .7152 * g * scale + .0722 * b * scale) / 255 > .55;
|
|
687
793
|
}
|
|
794
|
+
const ok = computed.match(/^oklch\(\s*([\d.]+)(%?)/);
|
|
795
|
+
if (ok?.[1]) return Number.parseFloat(ok[1]) / (ok[2] === "%" ? 100 : 1) > .62;
|
|
688
796
|
}
|
|
689
797
|
function mergeThemes(...themes) {
|
|
690
798
|
return Object.assign({}, ...themes.filter(Boolean));
|
|
691
799
|
}
|
|
800
|
+
/**
|
|
801
|
+
* Layer one theme over another when either may be a preset name. Used by the
|
|
802
|
+
* framework adapters to merge a provider's defaults with a local theme.
|
|
803
|
+
*/
|
|
804
|
+
function mergeThemeSpecs(base, override) {
|
|
805
|
+
if (base === void 0) return override;
|
|
806
|
+
if (override === void 0) return base;
|
|
807
|
+
const first = typeof base === "string" ? { preset: base } : base;
|
|
808
|
+
const second = typeof override === "string" ? { preset: override } : override;
|
|
809
|
+
return {
|
|
810
|
+
...first,
|
|
811
|
+
...second
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
/** `{ theme }` when there is one, or nothing, for spreading into options. */
|
|
815
|
+
function themeOption(theme) {
|
|
816
|
+
return theme === void 0 ? {} : { theme };
|
|
817
|
+
}
|
|
818
|
+
/** True when this theme cannot be resolved without the built-in presets. */
|
|
819
|
+
function needsPresets(spec) {
|
|
820
|
+
return typeof spec === "string" || !!spec && typeof spec === "object" && "preset" in spec;
|
|
821
|
+
}
|
|
822
|
+
/** A preset name, tokens, or a preset with tokens on top, flattened to tokens. */
|
|
823
|
+
function resolveTheme(spec, presets) {
|
|
824
|
+
if (spec === void 0) return void 0;
|
|
825
|
+
if (typeof spec === "string") return presets?.[spec];
|
|
826
|
+
const { preset, ...tokens } = spec;
|
|
827
|
+
if (preset === void 0) return tokens;
|
|
828
|
+
return mergeThemes(presets?.[preset], tokens);
|
|
829
|
+
}
|
|
692
830
|
//#endregion
|
|
693
831
|
//#region src/renderer.ts
|
|
694
832
|
const DEFAULT_LOOK = {
|
|
@@ -720,6 +858,11 @@ var DomRenderer = class {
|
|
|
720
858
|
connectorLoading;
|
|
721
859
|
/** Arrow, spotlight and overlay settings for the current step. */
|
|
722
860
|
look = DEFAULT_LOOK;
|
|
861
|
+
/** Preset tokens, once loaded. */
|
|
862
|
+
presets;
|
|
863
|
+
presetLoad;
|
|
864
|
+
/** Set while `appearance: 'auto'` is following the system setting. */
|
|
865
|
+
schemeQuery;
|
|
723
866
|
/** Until then the step's own transition runs; scroll updates may animate. */
|
|
724
867
|
settleUntil = 0;
|
|
725
868
|
/** Play the connector draw-in on its next render. */
|
|
@@ -743,6 +886,12 @@ var DomRenderer = class {
|
|
|
743
886
|
return `${pathname}${search}`;
|
|
744
887
|
}
|
|
745
888
|
show(ctx) {
|
|
889
|
+
if (this.presets === void 0 && this.usesPresets(ctx)) return this.loadPresets().then(() => {
|
|
890
|
+
this.showNow(ctx);
|
|
891
|
+
});
|
|
892
|
+
this.showNow(ctx);
|
|
893
|
+
}
|
|
894
|
+
showNow(ctx) {
|
|
746
895
|
const firstStep = !this.host;
|
|
747
896
|
const host = this.mount();
|
|
748
897
|
const from = this.popover?.style.transform || null;
|
|
@@ -750,7 +899,8 @@ var DomRenderer = class {
|
|
|
750
899
|
this.ctx = ctx;
|
|
751
900
|
this.target = ctx.step.target === void 0 ? null : resolveTarget(ctx.step.target, this.doc);
|
|
752
901
|
const template = this.template(ctx);
|
|
753
|
-
|
|
902
|
+
this.watchAppearance(ctx);
|
|
903
|
+
applyTheme(host, this.themeFor(ctx, template));
|
|
754
904
|
this.setTemplateCss(template?.css);
|
|
755
905
|
this.applyLook(host, this.resolveLook(ctx, template));
|
|
756
906
|
this.settleUntil = performance.now() + this.duration(host) * 1.5;
|
|
@@ -780,6 +930,8 @@ var DomRenderer = class {
|
|
|
780
930
|
}
|
|
781
931
|
hide() {
|
|
782
932
|
this.teardownStep();
|
|
933
|
+
this.schemeQuery?.removeEventListener("change", this.onSchemeChange);
|
|
934
|
+
this.schemeQuery = void 0;
|
|
783
935
|
if (this.host) {
|
|
784
936
|
this.host.remove();
|
|
785
937
|
this.host = void 0;
|
|
@@ -964,6 +1116,55 @@ var DomRenderer = class {
|
|
|
964
1116
|
shadow.insertBefore(style, before);
|
|
965
1117
|
shadow.insertBefore(this.connector.el, before);
|
|
966
1118
|
}
|
|
1119
|
+
/** Does anything here need the built-in presets? */
|
|
1120
|
+
usesPresets(ctx) {
|
|
1121
|
+
return this.appearance(ctx) !== "light" || needsPresets(this.options.theme) || needsPresets(ctx.tour.options?.theme) || needsPresets(this.template(ctx)?.theme);
|
|
1122
|
+
}
|
|
1123
|
+
loadPresets() {
|
|
1124
|
+
this.presetLoad ??= import("./themes.js").then((mod) => {
|
|
1125
|
+
this.presets = {
|
|
1126
|
+
light: mod.light,
|
|
1127
|
+
dark: mod.dark,
|
|
1128
|
+
minimal: mod.minimal,
|
|
1129
|
+
contrast: mod.contrast
|
|
1130
|
+
};
|
|
1131
|
+
});
|
|
1132
|
+
return this.presetLoad;
|
|
1133
|
+
}
|
|
1134
|
+
appearance(ctx) {
|
|
1135
|
+
return ctx.tour.options?.appearance ?? this.options.appearance ?? "light";
|
|
1136
|
+
}
|
|
1137
|
+
/** The surface tokens for the current appearance: dark, or nothing for light. */
|
|
1138
|
+
appearanceTheme(ctx) {
|
|
1139
|
+
const appearance = this.appearance(ctx);
|
|
1140
|
+
if (appearance === "dark") return this.presets?.dark;
|
|
1141
|
+
if (appearance !== "auto") return void 0;
|
|
1142
|
+
return this.prefersDark() ? this.presets?.dark : this.presets?.light;
|
|
1143
|
+
}
|
|
1144
|
+
prefersDark() {
|
|
1145
|
+
return this.doc.defaultView?.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
|
|
1146
|
+
}
|
|
1147
|
+
/** Renderer, then the appearance surface, then template, then tour. */
|
|
1148
|
+
themeFor(ctx, template) {
|
|
1149
|
+
const presets = this.presets;
|
|
1150
|
+
return mergeThemes(resolveTheme(this.options.theme, presets), this.appearanceTheme(ctx), resolveTheme(template?.theme, presets), resolveTheme(ctx.tour.options?.theme, presets));
|
|
1151
|
+
}
|
|
1152
|
+
/** With `appearance: 'auto'`, follow the system setting while the tour runs. */
|
|
1153
|
+
watchAppearance(ctx) {
|
|
1154
|
+
const wanted = this.appearance(ctx) === "auto";
|
|
1155
|
+
if (wanted === (this.schemeQuery !== void 0)) return;
|
|
1156
|
+
if (!wanted) {
|
|
1157
|
+
this.schemeQuery?.removeEventListener("change", this.onSchemeChange);
|
|
1158
|
+
this.schemeQuery = void 0;
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
this.schemeQuery = this.doc.defaultView?.matchMedia?.("(prefers-color-scheme: dark)");
|
|
1162
|
+
this.schemeQuery?.addEventListener("change", this.onSchemeChange);
|
|
1163
|
+
}
|
|
1164
|
+
onSchemeChange = () => {
|
|
1165
|
+
const ctx = this.ctx;
|
|
1166
|
+
if (ctx && this.host) applyTheme(this.host, this.themeFor(ctx, this.template(ctx)));
|
|
1167
|
+
};
|
|
967
1168
|
resolveLook(ctx, template) {
|
|
968
1169
|
const tour = ctx.tour.options ?? {};
|
|
969
1170
|
const step = ctx.step;
|
|
@@ -1087,9 +1288,11 @@ var DomRenderer = class {
|
|
|
1087
1288
|
win.addEventListener("scrollend", finish, { once: true });
|
|
1088
1289
|
this.cleanups.push(stop);
|
|
1089
1290
|
}
|
|
1291
|
+
/** The tour's template: one the app registered, or a built-in look. */
|
|
1090
1292
|
template(ctx) {
|
|
1091
1293
|
const name = ctx.tour.options?.template ?? this.options.template;
|
|
1092
|
-
|
|
1294
|
+
if (name === void 0) return void 0;
|
|
1295
|
+
return this.options.templates?.[name] ?? BUILT_IN_LOOKS[name];
|
|
1093
1296
|
}
|
|
1094
1297
|
buildDefault(ctx, host, template) {
|
|
1095
1298
|
const slots = {
|
|
@@ -1364,6 +1567,7 @@ var DomTourController = class extends TourController {
|
|
|
1364
1567
|
followRoutes;
|
|
1365
1568
|
constructor(tour, options = {}) {
|
|
1366
1569
|
const { renderer: rendererOptions, followRoutes, ...rest } = options;
|
|
1570
|
+
warnIfInvalid(tour);
|
|
1367
1571
|
const renderer = new DomRenderer(rendererOptions);
|
|
1368
1572
|
super({
|
|
1369
1573
|
...rest,
|
|
@@ -1469,7 +1673,7 @@ function createDocent(options = {}) {
|
|
|
1469
1673
|
...renderer,
|
|
1470
1674
|
document: doc
|
|
1471
1675
|
} : { ...renderer };
|
|
1472
|
-
|
|
1676
|
+
const docent = new Docent({
|
|
1473
1677
|
...rest,
|
|
1474
1678
|
storage: rest.storage ?? createLocalStorage(),
|
|
1475
1679
|
environment: createDomEnvironment(doc),
|
|
@@ -1478,8 +1682,10 @@ function createDocent(options = {}) {
|
|
|
1478
1682
|
renderer: rendererOptions
|
|
1479
1683
|
})
|
|
1480
1684
|
});
|
|
1685
|
+
warnAboutTours(docent);
|
|
1686
|
+
return docent;
|
|
1481
1687
|
}
|
|
1482
1688
|
//#endregion
|
|
1483
|
-
export { CONNECTOR_STYLES, DEFAULT_LABELS, DomRenderer, DomTourController, NAME_ATTRIBUTE, Overlay, THEME_VARS, applyTheme, arrowGap, availableSpace, buildHeadlessShell, buildPopover, candidateSelectors, centerPosition, computePosition, createDocent, createDomEnvironment, createLocalStorage, createTour, defineTour, findOccluder, formatProgress, holePath, inflate, isConnector, isSafeUrl, mergeThemes, parsePlacement, queryAllDeep, renderBody, renderMedia, resolveSlots, resolveTarget, toSpec, uncover, waitForTarget };
|
|
1689
|
+
export { BUILT_IN_LOOKS, CONNECTOR_STYLES, DEFAULT_LABELS, DomRenderer, DomTourController, NAME_ATTRIBUTE, Overlay, THEME_VARS, applyTheme, arrowGap, availableSpace, buildHeadlessShell, buildPopover, candidateSelectors, centerPosition, computePosition, createDocent, createDomEnvironment, createLocalStorage, createTour, defineTour, findOccluder, formatProgress, holePath, inflate, isConnector, isSafeUrl, mergeThemeSpecs, mergeThemes, parsePlacement, queryAllDeep, renderBody, renderMedia, resolveSlots, resolveTarget, themeOption, toSpec, uncover, waitForTarget };
|
|
1484
1690
|
|
|
1485
1691
|
//# sourceMappingURL=index.js.map
|