@redocly/theme 0.55.0-next.2 → 0.55.0-next.3
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/lib/components/Marker/Marker.d.ts +10 -0
- package/lib/components/Marker/Marker.js +62 -0
- package/lib/core/contexts/CodeWalkthrough/CodeWalkthroughStepsContext.d.ts +1 -1
- package/lib/core/contexts/CodeWalkthrough/CodeWalkthroughStepsContext.js +5 -2
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.d.ts +17 -9
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.js +242 -47
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough.d.ts +9 -2
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough.js +2 -2
- package/lib/core/hooks/index.d.ts +1 -1
- package/lib/core/hooks/index.js +1 -1
- package/lib/core/hooks/use-active-page-version.d.ts +1 -0
- package/lib/core/hooks/{use-page-active-version.js → use-active-page-version.js} +3 -3
- package/lib/core/types/code-walkthrough.d.ts +13 -0
- package/lib/core/types/code-walkthrough.js +3 -0
- package/lib/core/types/index.d.ts +2 -0
- package/lib/core/types/index.js +2 -0
- package/lib/core/types/marker.d.ts +4 -0
- package/lib/core/types/marker.js +3 -0
- package/lib/core/utils/js-utils.d.ts +18 -0
- package/lib/core/utils/js-utils.js +31 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/markdoc/components/CodeWalkthrough/CodeStep.d.ts +1 -2
- package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +26 -20
- package/lib/markdoc/components/CodeWalkthrough/CodeWalkthrough.js +32 -3
- package/lib/markdoc/tags/code-step.js +0 -3
- package/lib/markdoc/tags/code-walkthrough.js +0 -1
- package/package.json +1 -1
- package/src/components/Marker/Marker.tsx +53 -0
- package/src/core/contexts/CodeWalkthrough/CodeWalkthroughStepsContext.tsx +6 -3
- package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +326 -65
- package/src/core/hooks/code-walkthrough/use-code-walkthrough.ts +9 -6
- package/src/core/hooks/index.ts +1 -1
- package/src/core/hooks/{use-page-active-version.ts → use-active-page-version.ts} +1 -1
- package/src/core/types/code-walkthrough.ts +15 -0
- package/src/core/types/index.ts +2 -0
- package/src/core/types/marker.ts +4 -0
- package/src/core/utils/js-utils.ts +31 -0
- package/src/index.ts +1 -0
- package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +76 -36
- package/src/markdoc/components/CodeWalkthrough/CodeWalkthrough.tsx +8 -3
- package/src/markdoc/tags/code-step.ts +0 -3
- package/src/markdoc/tags/code-walkthrough.ts +0 -1
- package/lib/core/hooks/use-page-active-version.d.ts +0 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { MarkerArea } from '../../core/types';
|
|
3
|
+
type MarkerProps = {
|
|
4
|
+
marker: MarkerArea;
|
|
5
|
+
registerMarker: (element: HTMLElement) => void;
|
|
6
|
+
removeMarker: (element: HTMLElement) => void;
|
|
7
|
+
dataAttribures?: Record<string, string | boolean | number>;
|
|
8
|
+
};
|
|
9
|
+
export declare const Marker: React.ForwardRefExoticComponent<MarkerProps & React.RefAttributes<HTMLDivElement>>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Marker = void 0;
|
|
30
|
+
const react_1 = __importStar(require("react"));
|
|
31
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
|
+
exports.Marker = (0, react_1.forwardRef)(({ marker, dataAttribures, registerMarker, removeMarker }, forwardedRef) => {
|
|
33
|
+
const internalRef = (0, react_1.useRef)(null);
|
|
34
|
+
// Reference should be available before paint
|
|
35
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
36
|
+
if (!forwardedRef)
|
|
37
|
+
return;
|
|
38
|
+
if (typeof forwardedRef === 'function') {
|
|
39
|
+
forwardedRef(internalRef.current);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
forwardedRef.current = internalRef.current;
|
|
43
|
+
}
|
|
44
|
+
}, [forwardedRef]);
|
|
45
|
+
(0, react_1.useEffect)(() => {
|
|
46
|
+
const currentElement = internalRef.current;
|
|
47
|
+
if (!currentElement)
|
|
48
|
+
return;
|
|
49
|
+
registerMarker(currentElement);
|
|
50
|
+
return () => removeMarker(currentElement);
|
|
51
|
+
}, [registerMarker, removeMarker, marker]);
|
|
52
|
+
return (react_1.default.createElement(StyledMarker, Object.assign({ "data-component-name": "Marker/Marker", ref: internalRef, marker: marker }, (dataAttribures !== null && dataAttribures !== void 0 ? dataAttribures : {}))));
|
|
53
|
+
});
|
|
54
|
+
const StyledMarker = styled_components_1.default.div `
|
|
55
|
+
position: absolute;
|
|
56
|
+
z-index: -1;
|
|
57
|
+
top: ${({ marker }) => marker.offset}px;
|
|
58
|
+
height: ${({ marker }) => marker.height}px;
|
|
59
|
+
width: 100%;
|
|
60
|
+
left: 0;
|
|
61
|
+
`;
|
|
62
|
+
//# sourceMappingURL=Marker.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { WalkthroughStepsState } from '../../../core/
|
|
1
|
+
import type { WalkthroughStepsState } from '../../../core/types';
|
|
2
2
|
export declare const CodeWalkthroughStepsContext: import("react").Context<WalkthroughStepsState>;
|
|
@@ -3,9 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CodeWalkthroughStepsContext = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
exports.CodeWalkthroughStepsContext = (0, react_1.createContext)({
|
|
6
|
+
markers: {},
|
|
6
7
|
activeStep: null,
|
|
7
8
|
setActiveStep: () => { },
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
registerStep: () => { },
|
|
10
|
+
registerMarker: () => { },
|
|
11
|
+
removeMarker: () => { },
|
|
12
|
+
removeStep: () => { },
|
|
10
13
|
});
|
|
11
14
|
//# sourceMappingURL=CodeWalkthroughStepsContext.js.map
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import type { CodeWalkthroughStepAttr } from '@redocly/config';
|
|
2
|
-
type
|
|
2
|
+
import type { WalkthroughStepsState } from '../../../core/types';
|
|
3
3
|
type CodeWalkthroughStep = CodeWalkthroughStepAttr & {
|
|
4
4
|
compRef?: HTMLElement;
|
|
5
|
+
markerRef?: HTMLElement;
|
|
5
6
|
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
unregister: (element: HTMLElement) => void;
|
|
11
|
-
lockObserver?: React.RefObject<boolean>;
|
|
12
|
-
filtersElementRef?: React.RefObject<HTMLDivElement | null>;
|
|
7
|
+
type Params = {
|
|
8
|
+
steps: CodeWalkthroughStep[];
|
|
9
|
+
enableDeepLink: boolean;
|
|
10
|
+
root: React.RefObject<HTMLDivElement | null>;
|
|
13
11
|
};
|
|
14
|
-
export declare function useCodeWalkthroughSteps(steps
|
|
12
|
+
export declare function useCodeWalkthroughSteps({ steps, enableDeepLink, root, }: Params): WalkthroughStepsState;
|
|
13
|
+
type StepsGroup = {
|
|
14
|
+
freeSpace: number;
|
|
15
|
+
usedSpace: number;
|
|
16
|
+
offset: number;
|
|
17
|
+
steps: {
|
|
18
|
+
offset: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}[];
|
|
21
|
+
};
|
|
22
|
+
export declare function getGroupMarkers(group: StepsGroup): number[];
|
|
15
23
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useCodeWalkthroughSteps = useCodeWalkthroughSteps;
|
|
4
|
+
exports.getGroupMarkers = getGroupMarkers;
|
|
4
5
|
const react_1 = require("react");
|
|
5
6
|
const react_router_dom_1 = require("react-router-dom");
|
|
6
7
|
const utils_1 = require("../../../core/utils");
|
|
7
8
|
const constants_1 = require("../../../core/constants");
|
|
8
|
-
function useCodeWalkthroughSteps(steps, enableDeepLink) {
|
|
9
|
+
function useCodeWalkthroughSteps({ steps, enableDeepLink, root, }) {
|
|
9
10
|
const location = (0, react_router_dom_1.useLocation)();
|
|
10
11
|
const navigate = (0, react_router_dom_1.useNavigate)();
|
|
11
12
|
const searchParams = (0, react_1.useMemo)(() => new URLSearchParams(location.search), [location.search]);
|
|
@@ -15,56 +16,122 @@ function useCodeWalkthroughSteps(steps, enableDeepLink) {
|
|
|
15
16
|
// Track observed elements in case new observer needs to be created
|
|
16
17
|
const observedElementsRef = (0, react_1.useRef)(new Set());
|
|
17
18
|
const [activeStep, setActiveStep] = (0, react_1.useState)(enableDeepLink ? searchParams.get(constants_1.ACTIVE_STEP_QUERY_PARAM) : null);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
const stepsMap = (0, react_1.useMemo)(() => {
|
|
20
|
+
const map = new Map();
|
|
21
|
+
steps.forEach((step, index) => {
|
|
22
|
+
map.set(step.id, Object.assign(Object.assign({}, step), { index }));
|
|
23
|
+
});
|
|
24
|
+
return map;
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
}, [JSON.stringify(steps)]);
|
|
27
|
+
const options = (0, react_1.useMemo)(() => {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
if (!(0, utils_1.isBrowser)()) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const filtersElementHeight = ((_a = filtersElementRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight) || 0;
|
|
33
|
+
const navbarHeight = ((_b = document.querySelector('nav')) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().height) || 0;
|
|
34
|
+
return {
|
|
35
|
+
filtersElementHeight,
|
|
36
|
+
navbarHeight,
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
const [visibleSteps, setVisibleSteps] = (0, react_1.useState)([]);
|
|
40
|
+
const [markers, setMarkers] = (0, react_1.useState)({});
|
|
41
|
+
(0, react_1.useEffect)(() => {
|
|
42
|
+
var _a, _b, _c, _d, _e;
|
|
43
|
+
if (!root.current || !visibleSteps.length || !options) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const markersMinTopOffset = options.filtersElementHeight + options.navbarHeight;
|
|
47
|
+
const rootHeight = (_b = (_a = root.current) === null || _a === void 0 ? void 0 : _a.clientHeight) !== null && _b !== void 0 ? _b : 0;
|
|
48
|
+
const lastStepOffset = (_e = (_d = (_c = visibleSteps[visibleSteps.length - 1]) === null || _c === void 0 ? void 0 : _c.compRef) === null || _d === void 0 ? void 0 : _d.offsetTop) !== null && _e !== void 0 ? _e : 0;
|
|
49
|
+
const deficit = Math.max(lastStepOffset - (rootHeight - window.innerHeight), 0);
|
|
50
|
+
const groups = getGroups(visibleSteps);
|
|
51
|
+
let markers = groups.flatMap((group) => getGroupMarkers(group));
|
|
52
|
+
if (deficit) {
|
|
53
|
+
const startOffset = markersMinTopOffset;
|
|
54
|
+
const endOffset = Math.max(rootHeight - window.innerHeight, 0);
|
|
55
|
+
markers = distributeMarkers({
|
|
56
|
+
endOffset,
|
|
57
|
+
markers,
|
|
58
|
+
startOffset: markersMinTopOffset < endOffset ? startOffset : 0,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
setMarkers(markers.reduce((acc, marker, index) => {
|
|
62
|
+
var _a;
|
|
63
|
+
const step = visibleSteps[index];
|
|
64
|
+
acc[step.id] = {
|
|
65
|
+
offset: marker,
|
|
66
|
+
height: markers[index + 1] || !step.compRef
|
|
67
|
+
? ((_a = markers[index + 1]) !== null && _a !== void 0 ? _a : rootHeight) - marker
|
|
68
|
+
: step.compRef.clientHeight,
|
|
69
|
+
};
|
|
70
|
+
return acc;
|
|
71
|
+
}, {}));
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [visibleSteps, root.current, options]);
|
|
74
|
+
const registerMarker = (0, react_1.useCallback)((stepId, element) => {
|
|
75
|
+
if (observerRef.current) {
|
|
76
|
+
const step = stepsMap.get(stepId);
|
|
77
|
+
if (step) {
|
|
78
|
+
step.markerRef = element;
|
|
30
79
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
80
|
+
observerRef.current.observe(element);
|
|
81
|
+
observedElementsRef.current.add(element);
|
|
82
|
+
}
|
|
83
|
+
}, [stepsMap]);
|
|
84
|
+
const removeMarker = (0, react_1.useCallback)((stepId, element) => {
|
|
34
85
|
if (observerRef.current) {
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
|
|
86
|
+
const step = stepsMap.get(stepId);
|
|
87
|
+
if (step) {
|
|
88
|
+
step.markerRef = undefined;
|
|
38
89
|
}
|
|
39
90
|
observerRef.current.unobserve(element);
|
|
40
91
|
observedElementsRef.current.delete(element);
|
|
41
92
|
}
|
|
42
|
-
}, [
|
|
93
|
+
}, [stepsMap]);
|
|
94
|
+
const registerStep = (0, react_1.useCallback)((stepId, element) => {
|
|
95
|
+
const step = stepsMap.get(stepId);
|
|
96
|
+
if (!step) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
step.compRef = element;
|
|
100
|
+
setVisibleSteps((prevSteps) => (0, utils_1.insertAt)(prevSteps, step.index, step));
|
|
101
|
+
}, [stepsMap]);
|
|
102
|
+
const removeStep = (0, react_1.useCallback)((stepId) => {
|
|
103
|
+
const step = stepsMap.get(stepId);
|
|
104
|
+
if (!step) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
step.compRef = undefined;
|
|
108
|
+
setVisibleSteps((prevSteps) => (0, utils_1.removeElement)(prevSteps, step));
|
|
109
|
+
setActiveStep((prevStep) => (prevStep === stepId ? null : prevStep));
|
|
110
|
+
}, [stepsMap]);
|
|
43
111
|
const observerCallback = (0, react_1.useCallback)((entries) => {
|
|
44
112
|
var _a, _b, _c;
|
|
45
|
-
if (lockObserver.current) {
|
|
113
|
+
if (lockObserver.current || !visibleSteps.length) {
|
|
46
114
|
return;
|
|
47
115
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
setActiveStep(((_a = renderedSteps[0]) === null || _a === void 0 ? void 0 : _a.id) || null);
|
|
116
|
+
if (visibleSteps.length < 2) {
|
|
117
|
+
setActiveStep(((_a = visibleSteps[0]) === null || _a === void 0 ? void 0 : _a.id) || null);
|
|
51
118
|
return;
|
|
52
119
|
}
|
|
53
120
|
for (const entry of entries) {
|
|
54
|
-
const
|
|
55
|
-
if (!
|
|
121
|
+
const stepId = (_c = (_b = entry.target) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.stepId;
|
|
122
|
+
if (!stepId) {
|
|
56
123
|
continue;
|
|
57
124
|
}
|
|
58
125
|
const { intersectionRatio, boundingClientRect, rootBounds, isIntersecting } = entry;
|
|
59
|
-
const step =
|
|
60
|
-
|
|
61
|
-
|
|
126
|
+
const step = stepsMap.get(stepId);
|
|
127
|
+
if (!step) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const stepIndex = visibleSteps.findIndex((renderedStep) => renderedStep.id === stepId);
|
|
131
|
+
const { next } = (0, utils_1.getAdjacentValues)(visibleSteps, stepIndex);
|
|
62
132
|
const intersectionAtTop = (rootBounds === null || rootBounds === void 0 ? void 0 : rootBounds.bottom) !== undefined && boundingClientRect.top < rootBounds.top;
|
|
63
133
|
const stepGoesIn = isIntersecting;
|
|
64
|
-
if (intersectionRatio > 0.8 &&
|
|
65
|
-
intersectionRatio < 1 &&
|
|
66
|
-
intersectionAtTop &&
|
|
67
|
-
activeStep === null) {
|
|
134
|
+
if (intersectionRatio > 0.8 && intersectionRatio < 1 && intersectionAtTop) {
|
|
68
135
|
setActiveStep(step.id);
|
|
69
136
|
break;
|
|
70
137
|
}
|
|
@@ -76,28 +143,37 @@ function useCodeWalkthroughSteps(steps, enableDeepLink) {
|
|
|
76
143
|
else if (next) {
|
|
77
144
|
newStep = next.id;
|
|
78
145
|
}
|
|
79
|
-
|
|
80
|
-
setActiveStep(newStep);
|
|
81
|
-
}
|
|
146
|
+
setActiveStep((prevStep) => newStep || prevStep);
|
|
82
147
|
break;
|
|
83
148
|
}
|
|
84
149
|
}
|
|
85
|
-
}, [
|
|
150
|
+
}, [stepsMap, visibleSteps]);
|
|
86
151
|
(0, react_1.useEffect)(() => {
|
|
87
|
-
var _a
|
|
88
|
-
|
|
89
|
-
|
|
152
|
+
var _a;
|
|
153
|
+
if (!options) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
90
156
|
const newObserver = new IntersectionObserver(observerCallback, {
|
|
91
|
-
threshold: [0.
|
|
92
|
-
rootMargin: `-${filtersElementHeight + navbarHeight}px 0px 0px 0px`,
|
|
157
|
+
threshold: [0.3, 0.8, 0.9, 0.95],
|
|
158
|
+
rootMargin: `-${options.filtersElementHeight + options.navbarHeight}px 0px 0px 0px`,
|
|
93
159
|
});
|
|
94
|
-
for (const observedElement of observedElementsRef.current) {
|
|
160
|
+
for (const observedElement of observedElementsRef.current.values()) {
|
|
95
161
|
newObserver.observe(observedElement);
|
|
96
162
|
}
|
|
97
|
-
|
|
98
|
-
(_c = observerRef.current) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
163
|
+
(_a = observerRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
99
164
|
observerRef.current = newObserver;
|
|
100
|
-
}, [observerCallback]);
|
|
165
|
+
}, [observerCallback, markers, options]);
|
|
166
|
+
(0, react_1.useEffect)(() => {
|
|
167
|
+
var _a, _b, _c;
|
|
168
|
+
if (!options) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const rootTopOffset = (_b = (_a = root.current) === null || _a === void 0 ? void 0 : _a.offsetTop) !== null && _b !== void 0 ? _b : 0;
|
|
172
|
+
if (!activeStep && rootTopOffset <= options.navbarHeight) {
|
|
173
|
+
setActiveStep(((_c = visibleSteps[0]) === null || _c === void 0 ? void 0 : _c.id) || null);
|
|
174
|
+
}
|
|
175
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
176
|
+
}, [activeStep, root.current, options, visibleSteps]);
|
|
101
177
|
/**
|
|
102
178
|
* Update the URL search params with the current state of the filters and inputs
|
|
103
179
|
*/
|
|
@@ -118,6 +194,125 @@ function useCodeWalkthroughSteps(steps, enableDeepLink) {
|
|
|
118
194
|
navigate({ search: newSearch }, { replace: true });
|
|
119
195
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
120
196
|
}, [activeStep]);
|
|
121
|
-
return {
|
|
197
|
+
return {
|
|
198
|
+
registerStep,
|
|
199
|
+
removeStep,
|
|
200
|
+
markers,
|
|
201
|
+
registerMarker,
|
|
202
|
+
removeMarker,
|
|
203
|
+
lockObserver,
|
|
204
|
+
filtersElementRef,
|
|
205
|
+
activeStep,
|
|
206
|
+
setActiveStep,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* This function analyzes the offset and height of each step to determine
|
|
211
|
+
* when a new group should be created. A new group is started when there is a free space
|
|
212
|
+
* between the two steps, treating it as the content of the next group header.
|
|
213
|
+
*
|
|
214
|
+
* @param steps - An array of `CodeWalkthroughStep` objects
|
|
215
|
+
*
|
|
216
|
+
* @returns An array of `StepsGroup` objects, each containing the offset from the top of the relative
|
|
217
|
+
* block, the free space at the top of the group, the total space used by the steps within the group
|
|
218
|
+
* and the steps themselves with relative offset and height.
|
|
219
|
+
*/
|
|
220
|
+
function getGroups(steps) {
|
|
221
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
222
|
+
if (!steps.length) {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
const firstStepOffset = (_c = (_b = (_a = steps[0]) === null || _a === void 0 ? void 0 : _a.compRef) === null || _b === void 0 ? void 0 : _b.offsetTop) !== null && _c !== void 0 ? _c : 0;
|
|
226
|
+
const firstStepHeight = (_f = (_e = (_d = steps[0]) === null || _d === void 0 ? void 0 : _d.compRef) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 0;
|
|
227
|
+
const secondStepOffset = (_j = (_h = (_g = steps[1]) === null || _g === void 0 ? void 0 : _g.compRef) === null || _h === void 0 ? void 0 : _h.offsetTop) !== null && _j !== void 0 ? _j : 0;
|
|
228
|
+
const margin = Math.max(secondStepOffset - firstStepOffset - firstStepHeight, 0);
|
|
229
|
+
let groupIndex = 0;
|
|
230
|
+
const groups = [
|
|
231
|
+
{
|
|
232
|
+
offset: 0,
|
|
233
|
+
freeSpace: firstStepOffset,
|
|
234
|
+
usedSpace: 0,
|
|
235
|
+
steps: [],
|
|
236
|
+
},
|
|
237
|
+
];
|
|
238
|
+
for (let i = 0; i < steps.length; i++) {
|
|
239
|
+
let currentGroup = groups[groupIndex];
|
|
240
|
+
const step = steps[i];
|
|
241
|
+
const stepHeight = (_l = (_k = step.compRef) === null || _k === void 0 ? void 0 : _k.clientHeight) !== null && _l !== void 0 ? _l : 0;
|
|
242
|
+
const stepOffset = (_o = (_m = step.compRef) === null || _m === void 0 ? void 0 : _m.offsetTop) !== null && _o !== void 0 ? _o : 0;
|
|
243
|
+
const prevStepOffset = currentGroup.freeSpace + currentGroup.usedSpace;
|
|
244
|
+
if (prevStepOffset !== Math.max(stepOffset - currentGroup.offset, 0)) {
|
|
245
|
+
const offset = currentGroup.offset + currentGroup.freeSpace + currentGroup.usedSpace;
|
|
246
|
+
groupIndex++;
|
|
247
|
+
groups[groupIndex] = {
|
|
248
|
+
offset,
|
|
249
|
+
freeSpace: Math.max(stepOffset - offset, 0),
|
|
250
|
+
usedSpace: 0,
|
|
251
|
+
steps: [],
|
|
252
|
+
};
|
|
253
|
+
currentGroup = groups[groupIndex];
|
|
254
|
+
}
|
|
255
|
+
currentGroup.steps.push({
|
|
256
|
+
offset: stepOffset - currentGroup.offset,
|
|
257
|
+
height: stepHeight,
|
|
258
|
+
ref: step.compRef,
|
|
259
|
+
});
|
|
260
|
+
currentGroup.usedSpace += stepHeight + margin;
|
|
261
|
+
}
|
|
262
|
+
return groups;
|
|
263
|
+
}
|
|
264
|
+
function getGroupMarkers(group) {
|
|
265
|
+
if (!group.steps.length) {
|
|
266
|
+
return [];
|
|
267
|
+
}
|
|
268
|
+
if (group.steps.length === 1) {
|
|
269
|
+
return [group.offset + group.steps[0].offset - group.freeSpace];
|
|
270
|
+
}
|
|
271
|
+
const availableFreeSpace = group.freeSpace > 0.3 * window.innerHeight ? 0.3 * window.innerHeight : group.freeSpace;
|
|
272
|
+
const unusedFreeSpace = group.freeSpace - availableFreeSpace;
|
|
273
|
+
const lastStepOffset = group.steps[group.steps.length - 1].offset;
|
|
274
|
+
// distribute group free space between steps
|
|
275
|
+
return distributeMarkers({
|
|
276
|
+
startOffset: 0,
|
|
277
|
+
endOffset: lastStepOffset - unusedFreeSpace,
|
|
278
|
+
markers: group.steps.map((step) => step.offset),
|
|
279
|
+
additionalSteps: [(marker) => group.offset + unusedFreeSpace + marker],
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Distribute markers preserving the relationship throughout the available space
|
|
284
|
+
* @param startOffset - the starting point of the available space
|
|
285
|
+
* @param endOffset - the end point of the available space
|
|
286
|
+
* @param markers - the markers to distribute
|
|
287
|
+
* @param additionalSteps - additional steps to apply to the markers
|
|
288
|
+
*
|
|
289
|
+
* @returns array of markers positions
|
|
290
|
+
*/
|
|
291
|
+
function distributeMarkers({ endOffset, markers, startOffset, additionalSteps = [], }) {
|
|
292
|
+
return markers.map((marker) => {
|
|
293
|
+
const normalizedOffset = getNormalizedNumber({
|
|
294
|
+
min: markers[0],
|
|
295
|
+
max: markers[markers.length - 1],
|
|
296
|
+
value: marker,
|
|
297
|
+
});
|
|
298
|
+
const availableSpace = endOffset - startOffset;
|
|
299
|
+
let result = startOffset + normalizedOffset * availableSpace;
|
|
300
|
+
for (const additionalStep of additionalSteps) {
|
|
301
|
+
result = additionalStep(result);
|
|
302
|
+
}
|
|
303
|
+
return result;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Normalize a number between a min and max value
|
|
308
|
+
* @param min - the minimum value of the distribution
|
|
309
|
+
* @param max - the maximum value of the distribution
|
|
310
|
+
* @param value - the value to normalize
|
|
311
|
+
*
|
|
312
|
+
* @returns normalized number between 0 and 1
|
|
313
|
+
*/
|
|
314
|
+
function getNormalizedNumber(options) {
|
|
315
|
+
const { min, max, value } = options;
|
|
316
|
+
return (value - min) / (max - min);
|
|
122
317
|
}
|
|
123
318
|
//# sourceMappingURL=use-code-walkthrough-steps.js.map
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import type { CodeWalkthroughFile, CodeWalkthroughStepAttr, CodeWalkthroughAttr } from '@redocly/config';
|
|
2
|
-
import
|
|
2
|
+
import type { WalkthroughStepsState } from '../../../core/types';
|
|
3
|
+
import { type WalkthroughControlsState } from '../../../core/hooks';
|
|
3
4
|
export type WalkthroughState = {
|
|
4
5
|
stepsState: WalkthroughStepsState;
|
|
5
6
|
controlsState: WalkthroughControlsState;
|
|
6
7
|
downloadAssociatedFiles: CodeWalkthroughFile[];
|
|
7
8
|
files: CodeWalkthroughFile[];
|
|
8
9
|
};
|
|
9
|
-
|
|
10
|
+
type Params = {
|
|
11
|
+
steps: CodeWalkthroughStepAttr[];
|
|
12
|
+
attributes: Omit<CodeWalkthroughAttr, 'steps' | 'preview'>;
|
|
13
|
+
root: React.RefObject<HTMLDivElement | null>;
|
|
14
|
+
};
|
|
15
|
+
export declare function useCodeWalkthrough({ steps, attributes, root }: Params): WalkthroughState;
|
|
16
|
+
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useCodeWalkthrough = useCodeWalkthrough;
|
|
4
4
|
const hooks_1 = require("../../../core/hooks");
|
|
5
|
-
function useCodeWalkthrough(steps, attributes) {
|
|
5
|
+
function useCodeWalkthrough({ steps, attributes, root }) {
|
|
6
6
|
const { filters, filesets, inputs, toggles, __idx } = attributes;
|
|
7
7
|
/*
|
|
8
8
|
We only enable deep linking for the first CodeWalkthrough,
|
|
@@ -11,7 +11,7 @@ function useCodeWalkthrough(steps, attributes) {
|
|
|
11
11
|
collisions/conflicts in the URL.
|
|
12
12
|
*/
|
|
13
13
|
const enableDeepLink = __idx === 1;
|
|
14
|
-
const stepsState = (0, hooks_1.useCodeWalkthroughSteps)(steps, enableDeepLink);
|
|
14
|
+
const stepsState = (0, hooks_1.useCodeWalkthroughSteps)({ steps, enableDeepLink, root });
|
|
15
15
|
const controlsState = (0, hooks_1.useCodeWalkthroughControls)(filters, inputs, toggles, enableDeepLink);
|
|
16
16
|
const files = filesets
|
|
17
17
|
.filter((fileset) => controlsState.areConditionsMet(fileset))
|
|
@@ -36,5 +36,5 @@ export * from '../../core/hooks/code-walkthrough/use-renderable-files';
|
|
|
36
36
|
export * from '../../core/hooks/use-element-size';
|
|
37
37
|
export * from '../../core/hooks/use-time-ago';
|
|
38
38
|
export * from '../../core/hooks/use-input-key-commands';
|
|
39
|
-
export * from '../../core/hooks/use-page-
|
|
39
|
+
export * from '../../core/hooks/use-active-page-version';
|
|
40
40
|
export * from '../../core/hooks/use-page-versions';
|
package/lib/core/hooks/index.js
CHANGED
|
@@ -52,6 +52,6 @@ __exportStar(require("../../core/hooks/code-walkthrough/use-renderable-files"),
|
|
|
52
52
|
__exportStar(require("../../core/hooks/use-element-size"), exports);
|
|
53
53
|
__exportStar(require("../../core/hooks/use-time-ago"), exports);
|
|
54
54
|
__exportStar(require("../../core/hooks/use-input-key-commands"), exports);
|
|
55
|
-
__exportStar(require("../../core/hooks/use-page-
|
|
55
|
+
__exportStar(require("../../core/hooks/use-active-page-version"), exports);
|
|
56
56
|
__exportStar(require("../../core/hooks/use-page-versions"), exports);
|
|
57
57
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useActivePageVersion(): string | undefined;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.useActivePageVersion = useActivePageVersion;
|
|
4
4
|
const hooks_1 = require("../../core/hooks");
|
|
5
|
-
function
|
|
5
|
+
function useActivePageVersion() {
|
|
6
6
|
const { usePageVersions } = (0, hooks_1.useThemeHooks)();
|
|
7
7
|
const { versions } = usePageVersions();
|
|
8
8
|
const activeVersion = versions.find((version) => version.active);
|
|
9
9
|
return activeVersion === null || activeVersion === void 0 ? void 0 : activeVersion.version;
|
|
10
10
|
}
|
|
11
|
-
//# sourceMappingURL=use-page-
|
|
11
|
+
//# sourceMappingURL=use-active-page-version.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MarkerArea } from '../../core/types';
|
|
2
|
+
export type ActiveStep = string | null;
|
|
3
|
+
export type WalkthroughStepsState = {
|
|
4
|
+
activeStep: ActiveStep;
|
|
5
|
+
setActiveStep: (stepId: ActiveStep) => void;
|
|
6
|
+
markers: Record<string, MarkerArea>;
|
|
7
|
+
registerMarker: (stepId: string, element: HTMLElement) => void;
|
|
8
|
+
removeMarker: (stepId: string, element: HTMLElement) => void;
|
|
9
|
+
registerStep: (stepId: string, element: HTMLElement) => void;
|
|
10
|
+
removeStep: (stepId: string) => void;
|
|
11
|
+
lockObserver?: React.RefObject<boolean>;
|
|
12
|
+
filtersElementRef?: React.RefObject<HTMLDivElement | null>;
|
|
13
|
+
};
|
|
@@ -13,3 +13,5 @@ export * from '../../core/types/user-menu';
|
|
|
13
13
|
export * from '../../core/types/user-claims';
|
|
14
14
|
export * from '../../core/types/common';
|
|
15
15
|
export * from '../../core/types/open-api-server';
|
|
16
|
+
export * from '../../core/types/marker';
|
|
17
|
+
export * from '../../core/types/code-walkthrough';
|
package/lib/core/types/index.js
CHANGED
|
@@ -29,4 +29,6 @@ __exportStar(require("../../core/types/user-menu"), exports);
|
|
|
29
29
|
__exportStar(require("../../core/types/user-claims"), exports);
|
|
30
30
|
__exportStar(require("../../core/types/common"), exports);
|
|
31
31
|
__exportStar(require("../../core/types/open-api-server"), exports);
|
|
32
|
+
__exportStar(require("../../core/types/marker"), exports);
|
|
33
|
+
__exportStar(require("../../core/types/code-walkthrough"), exports);
|
|
32
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -36,3 +36,21 @@ export declare function getAdjacentValues<T>(array: T[], index: number): {
|
|
|
36
36
|
prev: T | null;
|
|
37
37
|
next: T | null;
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Inserts an element at a given index in an array. Returns a new array with the element inserted.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const array = [10, 20, 30, 40];
|
|
44
|
+
* insertAt(array, 2, 25);
|
|
45
|
+
* // returns: [10, 20, 25, 30, 40]
|
|
46
|
+
*/
|
|
47
|
+
export declare function insertAt<T>(array: T[], index: number, newElement: T): T[];
|
|
48
|
+
/**
|
|
49
|
+
* Removes an element from an array. Returns a new array with the element removed.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const array = [10, 20, 30, 40];
|
|
53
|
+
* removeElement(array, 20);
|
|
54
|
+
* // returns: [10, 30, 40]
|
|
55
|
+
*/
|
|
56
|
+
export declare function removeElement<T>(array: T[], item: T): T[];
|