vanilla-jui 1.4.8 → 1.5.1
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/README.md +10 -4
- package/dist/index.d.ts +402 -977
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/components/accordion.ts +467 -349
- package/src/components/flow.ts +779 -1133
- package/src/components/form.ts +666 -509
- package/src/components/menu.ts +199 -326
- package/src/components/modal.ts +510 -747
- package/src/components/offcanvas.ts +281 -361
- package/src/components/pagination.ts +207 -374
- package/src/components/swiper.ts +688 -1168
- package/src/components/tabs.ts +468 -788
- package/src/components/toc.ts +191 -244
- package/src/core/component.ts +332 -0
- package/src/core/motion.ts +298 -0
- package/src/core/presence.ts +233 -0
- package/src/core/scheduler.ts +91 -0
- package/src/core/view.ts +31 -0
- package/src/css/accordion.css +94 -3
- package/src/css/content.css +18 -24
- package/src/css/drop.css +4 -1
- package/src/css/form.css +8 -0
- package/src/css/menu.css +10 -5
- package/src/css/modal.css +2 -1
- package/src/css/offcanvas.css +5 -17
- package/src/css/swiper.css +2 -1
- package/src/css/tabs.css +8 -17
- package/src/css/themes/default/accordion.css +0 -48
- package/src/css/themes/default/swiper.css +1 -1
- package/src/css/themes/default/tabs.css +4 -6
- package/src/css/toast.css +1 -17
- package/src/css/tooltip.css +2 -1
- package/src/index.ts +8 -3
- package/src/locales/index.ts +3 -0
- package/src/primitives/drop.ts +253 -262
- package/src/primitives/loading.ts +22 -4
- package/src/primitives/parabola.ts +123 -164
- package/src/primitives/sticky.ts +297 -0
- package/src/primitives/theme.ts +164 -222
- package/src/primitives/toast.ts +309 -284
- package/src/primitives/tooltip.ts +65 -66
- package/src/utilities/browser.ts +38 -0
- package/src/utilities/dom.ts +0 -54
- package/src/utilities/refs.ts +61 -0
- package/src/utilities/state.ts +73 -0
- package/src/utilities/timer.ts +11 -31
- package/src/validation/validator.ts +289 -389
- package/src/components/sticky.ts +0 -297
- package/src/core/Component.ts +0 -377
- package/src/utilities/scheduler.ts +0 -156
package/src/components/toc.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {
|
|
2
|
+
For,
|
|
3
|
+
createMemo,
|
|
4
|
+
createDeepStore,
|
|
5
|
+
flushSync,
|
|
6
|
+
jsx,
|
|
7
|
+
} from 'vanilla-signal';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
type FunctionalComponent,
|
|
11
|
+
defineComponent,
|
|
12
|
+
} from '../core/component.ts';
|
|
7
13
|
import { joinClasses } from '../utilities/class-name.ts';
|
|
8
14
|
import { type DOMReference, all, requireContainer } from '../utilities/dom.ts';
|
|
15
|
+
import { createEventManager } from '../utilities/events.ts';
|
|
9
16
|
import { randomId } from '../utilities/id.ts';
|
|
10
17
|
import { type ResolveSchema, resolveProps } from '../utilities/types.ts';
|
|
11
18
|
|
|
@@ -19,14 +26,13 @@ interface TocClassNames {
|
|
|
19
26
|
|
|
20
27
|
type TocClassNameConfig = Partial<TocClassNames>;
|
|
21
28
|
|
|
22
|
-
interface TocItem {
|
|
29
|
+
export interface TocItem {
|
|
23
30
|
id: string;
|
|
24
31
|
text: string;
|
|
25
32
|
level: number;
|
|
26
|
-
element: HTMLHeadingElement;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
interface TocCurrent {
|
|
35
|
+
export interface TocCurrent {
|
|
30
36
|
index: number;
|
|
31
37
|
item: TocItem | null;
|
|
32
38
|
}
|
|
@@ -35,6 +41,7 @@ interface TocProps extends Record<string, unknown> {
|
|
|
35
41
|
target?: DOMReference;
|
|
36
42
|
headings?: string;
|
|
37
43
|
offset?: number;
|
|
44
|
+
reactive?: boolean;
|
|
38
45
|
className?: TocClassNameConfig;
|
|
39
46
|
onChange?:
|
|
40
47
|
| ((item: TocItem | null, index: number, toc: TocInstance) => void)
|
|
@@ -45,6 +52,7 @@ interface ResolvedTocProps extends Record<string, unknown> {
|
|
|
45
52
|
target: DOMReference;
|
|
46
53
|
headings: string;
|
|
47
54
|
offset: number;
|
|
55
|
+
reactive: boolean;
|
|
48
56
|
className: TocClassNames;
|
|
49
57
|
onChange:
|
|
50
58
|
| ((item: TocItem | null, index: number, toc: TocInstance) => void)
|
|
@@ -56,17 +64,11 @@ interface TocState extends Record<string, unknown> {
|
|
|
56
64
|
current: TocCurrent;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
interface
|
|
60
|
-
root: HTMLElement | null;
|
|
61
|
-
target: Element | null;
|
|
62
|
-
list: HTMLElement | null;
|
|
63
|
-
headings: HTMLHeadingElement[];
|
|
64
|
-
links: HTMLAnchorElement[];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
interface TocRuntime extends ComponentRuntime {
|
|
68
|
-
built: boolean;
|
|
67
|
+
interface TocRuntimeExtras {
|
|
69
68
|
ticking: boolean;
|
|
69
|
+
frameId: number;
|
|
70
|
+
refreshing: boolean;
|
|
71
|
+
refreshFrameId: number;
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
interface TocScrollOptions {
|
|
@@ -74,12 +76,16 @@ interface TocScrollOptions {
|
|
|
74
76
|
updateHash?: boolean;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
runtime: TocRuntime;
|
|
79
|
-
build(): TocInstance;
|
|
80
|
-
refresh(): TocInstance;
|
|
79
|
+
interface TocActions {
|
|
81
80
|
activate(index: number): TocInstance;
|
|
82
|
-
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type TocInstance = FunctionalComponent<
|
|
84
|
+
ResolvedTocProps,
|
|
85
|
+
TocState,
|
|
86
|
+
HTMLElement,
|
|
87
|
+
TocActions
|
|
88
|
+
>;
|
|
83
89
|
|
|
84
90
|
const DEFAULT_CLASS_NAMES: TocClassNames = {
|
|
85
91
|
toc: 'j-toc',
|
|
@@ -97,6 +103,7 @@ const TOC_PROPS_SCHEMA = {
|
|
|
97
103
|
type: 'number',
|
|
98
104
|
min: 0,
|
|
99
105
|
},
|
|
106
|
+
reactive: { default: false, type: 'boolean' },
|
|
100
107
|
className: {
|
|
101
108
|
default: DEFAULT_CLASS_NAMES,
|
|
102
109
|
type: 'object',
|
|
@@ -116,6 +123,7 @@ function normalizeProps(input: TocProps): ResolvedTocProps {
|
|
|
116
123
|
target: props.target as DOMReference,
|
|
117
124
|
headings: props.headings as string,
|
|
118
125
|
offset: props.offset as number,
|
|
126
|
+
reactive: props.reactive as boolean,
|
|
119
127
|
className: props.className as TocClassNames,
|
|
120
128
|
onChange: props.onChange as ResolvedTocProps['onChange'],
|
|
121
129
|
};
|
|
@@ -132,250 +140,189 @@ function normalizeHeading(element: HTMLHeadingElement, index: number): TocItem {
|
|
|
132
140
|
id: element.id,
|
|
133
141
|
text: element.textContent || '',
|
|
134
142
|
level: resolveHeadingLevel(element),
|
|
135
|
-
element,
|
|
136
143
|
};
|
|
137
144
|
}
|
|
138
145
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this.state = createDeepStore({
|
|
164
|
-
items: [],
|
|
165
|
-
current: {
|
|
166
|
-
index: -1,
|
|
167
|
-
item: null,
|
|
168
|
-
},
|
|
146
|
+
export function createToc(props: TocProps = {}): TocInstance {
|
|
147
|
+
const settings = normalizeProps(props);
|
|
148
|
+
const state = createDeepStore({
|
|
149
|
+
items: [],
|
|
150
|
+
current: { index: -1, item: null },
|
|
151
|
+
}) as TocState;
|
|
152
|
+
const runtime: TocRuntimeExtras = {
|
|
153
|
+
ticking: false,
|
|
154
|
+
frameId: 0,
|
|
155
|
+
refreshing: false,
|
|
156
|
+
refreshFrameId: 0,
|
|
157
|
+
};
|
|
158
|
+
const events = createEventManager();
|
|
159
|
+
let target: Element | null = null;
|
|
160
|
+
let headings: HTMLHeadingElement[] = [];
|
|
161
|
+
let observer: MutationObserver | null = null;
|
|
162
|
+
let toc: TocInstance;
|
|
163
|
+
const renderableItems = createMemo(() => state.items);
|
|
164
|
+
|
|
165
|
+
const setActive = (index: number): void => {
|
|
166
|
+
if (index === state.current.index) return;
|
|
167
|
+
const current = state.items[index] || null;
|
|
168
|
+
flushSync(() => {
|
|
169
|
+
state.current = { index, item: current };
|
|
169
170
|
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* 构建 Toc DOM 和滚动监听。
|
|
174
|
-
* @returns {Toc} 当前实例。
|
|
175
|
-
*/
|
|
176
|
-
build(): this {
|
|
177
|
-
if (this.runtime.destroyed)
|
|
178
|
-
throw new Error('Toc.build: instance destroyed');
|
|
179
|
-
if (this.runtime.built) return this;
|
|
180
|
-
|
|
181
|
-
this.init(this.props);
|
|
182
|
-
this.dom.target = requireContainer(this.props.target, 'Toc.target');
|
|
183
|
-
this.dom.list = jsx('div', {
|
|
184
|
-
className: this.props.className.list,
|
|
185
|
-
'data-toc-list': 'root',
|
|
186
|
-
}) as HTMLElement;
|
|
187
|
-
this.dom.root = jsx('nav', {
|
|
188
|
-
className: this.props.className.toc,
|
|
189
|
-
'data-toc': 'root',
|
|
190
|
-
children: this.dom.list,
|
|
191
|
-
}) as HTMLElement;
|
|
171
|
+
settings.onChange?.(current, index, toc);
|
|
172
|
+
};
|
|
192
173
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
174
|
+
const updateActive = (): void => {
|
|
175
|
+
if (!toc.runtime.built) return;
|
|
176
|
+
let index = -1;
|
|
177
|
+
const activeOffset = settings.offset + ACTIVE_OFFSET_TOLERANCE;
|
|
178
|
+
for (let current = headings.length - 1; current >= 0; current--) {
|
|
179
|
+
if (headings[current].getBoundingClientRect().top <= activeOffset) {
|
|
180
|
+
index = current;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
setActive(index);
|
|
185
|
+
};
|
|
197
186
|
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
187
|
+
const onScroll = (): void => {
|
|
188
|
+
if (runtime.ticking) return;
|
|
189
|
+
runtime.ticking = true;
|
|
190
|
+
runtime.frameId = requestAnimationFrame(() => {
|
|
191
|
+
runtime.ticking = false;
|
|
192
|
+
runtime.frameId = 0;
|
|
193
|
+
updateActive();
|
|
202
194
|
});
|
|
203
|
-
|
|
204
|
-
this.onClick(event)
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private onScroll(): void {
|
|
209
|
-
if (this.runtime.ticking) return;
|
|
195
|
+
};
|
|
210
196
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
197
|
+
const scheduleRefresh = (): void => {
|
|
198
|
+
if (runtime.refreshing) return;
|
|
199
|
+
runtime.refreshing = true;
|
|
200
|
+
runtime.refreshFrameId = requestAnimationFrame(() => {
|
|
201
|
+
runtime.refreshing = false;
|
|
202
|
+
runtime.refreshFrameId = 0;
|
|
203
|
+
syncFromTarget();
|
|
214
204
|
});
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
private onClick(event: Event): void {
|
|
219
|
-
if (!(event.target instanceof Element) || !this.dom.list) return;
|
|
220
|
-
const link = event.target.closest<HTMLElement>('[data-toc-index]');
|
|
221
|
-
if (!link || !this.dom.list.contains(link)) return;
|
|
222
|
-
|
|
223
|
-
const index = Number(link.dataset.tocIndex);
|
|
224
|
-
const item = this.state?.items[index];
|
|
225
|
-
if (!item) return;
|
|
226
|
-
|
|
227
|
-
event.preventDefault();
|
|
228
|
-
this.scrollToItem(item, { activeIndex: index, updateHash: true });
|
|
229
|
-
}
|
|
205
|
+
};
|
|
230
206
|
|
|
231
|
-
|
|
207
|
+
const scrollToItem = (
|
|
232
208
|
item: TocItem,
|
|
233
209
|
{ activeIndex = -1, updateHash = false }: TocScrollOptions = {}
|
|
234
|
-
): void {
|
|
210
|
+
): void => {
|
|
211
|
+
const heading = headings.find((element) => element.id === item.id);
|
|
212
|
+
if (!heading) return;
|
|
235
213
|
const scrollY = window.scrollY || window.pageYOffset || 0;
|
|
236
214
|
const top = Math.max(
|
|
237
215
|
0,
|
|
238
|
-
|
|
216
|
+
heading.getBoundingClientRect().top + scrollY - settings.offset
|
|
239
217
|
);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
top,
|
|
243
|
-
behavior: 'smooth',
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
if (activeIndex >= 0) this.setActive(activeIndex);
|
|
247
|
-
|
|
218
|
+
window.scrollTo({ top, behavior: 'smooth' });
|
|
219
|
+
if (activeIndex >= 0) setActive(activeIndex);
|
|
248
220
|
if (updateHash && window.history?.pushState) {
|
|
249
221
|
window.history.pushState(null, '', `#${item.id}`);
|
|
250
222
|
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
private linkClassName(item: TocItem, active = false): string {
|
|
254
|
-
const classes = [
|
|
255
|
-
this.props.className.link,
|
|
256
|
-
`${this.props.className.levelPrefix}${item.level}`,
|
|
257
|
-
];
|
|
258
|
-
if (active) classes.push(this.props.className.active);
|
|
259
|
-
return joinClasses(...classes);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
private buildLink(item: TocItem, index: number): HTMLAnchorElement {
|
|
263
|
-
return jsx('a', {
|
|
264
|
-
className: this.linkClassName(item),
|
|
265
|
-
href: `#${item.id}`,
|
|
266
|
-
'data-toc-index': String(index),
|
|
267
|
-
'data-toc-target': item.id,
|
|
268
|
-
children: item.text,
|
|
269
|
-
}) as HTMLAnchorElement;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
private updateActive(): void {
|
|
273
|
-
if (!this.runtime.built) return;
|
|
274
|
-
|
|
275
|
-
let index = -1;
|
|
276
|
-
const activeOffset = this.props.offset + ACTIVE_OFFSET_TOLERANCE;
|
|
277
|
-
for (let i = this.dom.headings.length - 1; i >= 0; i--) {
|
|
278
|
-
if (this.dom.headings[i].getBoundingClientRect().top <= activeOffset) {
|
|
279
|
-
index = i;
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
this.setActive(index);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private setActive(index: number): void {
|
|
288
|
-
if (!this.state || index === this.state.current.index) return;
|
|
289
|
-
|
|
290
|
-
const current = this.state.items[index] || null;
|
|
291
|
-
this.setState({
|
|
292
|
-
current: { index, item: current },
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
const items = this.state.items;
|
|
296
|
-
this.dom.links.forEach((link, i) => {
|
|
297
|
-
const active = i === index;
|
|
298
|
-
link.dataset.active = active ? '1' : '0';
|
|
299
|
-
link.className = this.linkClassName(items[i], active);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
if (typeof this.props.onChange === 'function') {
|
|
303
|
-
this.props.onChange(current, index, this);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 重新扫描标题并重建目录列表。
|
|
309
|
-
* @returns {Toc} 当前实例。
|
|
310
|
-
*/
|
|
311
|
-
refresh(): this {
|
|
312
|
-
if (
|
|
313
|
-
this.runtime.destroyed ||
|
|
314
|
-
!this.runtime.built ||
|
|
315
|
-
!this.dom.target ||
|
|
316
|
-
!this.dom.list
|
|
317
|
-
) {
|
|
318
|
-
return this;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
this.cleanup.events.clear();
|
|
322
|
-
|
|
323
|
-
this.dom.headings = all<HTMLHeadingElement>(
|
|
324
|
-
this.props.headings,
|
|
325
|
-
this.dom.target
|
|
326
|
-
);
|
|
327
|
-
const items = this.dom.headings.map(normalizeHeading);
|
|
328
|
-
this.dom.links = items.map((item, index) => this.buildLink(item, index));
|
|
329
|
-
|
|
330
|
-
this.dom.list.innerHTML = '';
|
|
331
|
-
for (const link of this.dom.links) this.dom.list.appendChild(link);
|
|
223
|
+
};
|
|
332
224
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
225
|
+
const syncFromTarget = (): void => {
|
|
226
|
+
if (toc.runtime.destroyed || !toc.runtime.built || !target) return;
|
|
227
|
+
headings = all<HTMLHeadingElement>(settings.headings, target);
|
|
228
|
+
const items = headings.map(normalizeHeading);
|
|
229
|
+
flushSync(() => {
|
|
230
|
+
state.items = items;
|
|
231
|
+
state.current = { index: -1, item: null };
|
|
336
232
|
});
|
|
233
|
+
updateActive();
|
|
234
|
+
};
|
|
337
235
|
|
|
338
|
-
|
|
339
|
-
this.updateActive();
|
|
340
|
-
return this;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* 激活并滚动到指定目录项。
|
|
345
|
-
* @param {number} index 目录项索引。
|
|
346
|
-
* @returns {Toc} 当前实例。
|
|
347
|
-
*/
|
|
348
|
-
activate(index: number): this {
|
|
349
|
-
if (!this.runtime.built || !this.state) return this;
|
|
236
|
+
const activate = (index: number): TocInstance => {
|
|
350
237
|
if (
|
|
351
|
-
|
|
352
|
-
index
|
|
353
|
-
index >=
|
|
238
|
+
toc.runtime.built &&
|
|
239
|
+
Number.isInteger(index) &&
|
|
240
|
+
index >= 0 &&
|
|
241
|
+
index < state.items.length
|
|
354
242
|
) {
|
|
355
|
-
|
|
243
|
+
scrollToItem(state.items[index]);
|
|
356
244
|
}
|
|
245
|
+
return toc;
|
|
246
|
+
};
|
|
357
247
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
248
|
+
toc = defineComponent({
|
|
249
|
+
name: 'Toc',
|
|
250
|
+
props: settings,
|
|
251
|
+
state,
|
|
252
|
+
actions: { activate },
|
|
253
|
+
view: () =>
|
|
254
|
+
jsx('nav', {
|
|
255
|
+
className: settings.className.toc,
|
|
256
|
+
'data-toc': 'root',
|
|
257
|
+
children: jsx('div', {
|
|
258
|
+
className: settings.className.list,
|
|
259
|
+
'data-toc-list': 'root',
|
|
260
|
+
children: For({
|
|
261
|
+
each: renderableItems,
|
|
262
|
+
key: (item: TocItem) => item.id,
|
|
263
|
+
children: (
|
|
264
|
+
itemAccessor: () => TocItem,
|
|
265
|
+
indexAccessor: () => number
|
|
266
|
+
) =>
|
|
267
|
+
jsx('a', {
|
|
268
|
+
className: () => {
|
|
269
|
+
const item = itemAccessor();
|
|
270
|
+
return joinClasses(
|
|
271
|
+
settings.className.link,
|
|
272
|
+
`${settings.className.levelPrefix}${item.level}`,
|
|
273
|
+
state.current.index === indexAccessor()
|
|
274
|
+
? settings.className.active
|
|
275
|
+
: ''
|
|
276
|
+
);
|
|
277
|
+
},
|
|
278
|
+
href: () => `#${itemAccessor().id}`,
|
|
279
|
+
'data-toc-index': () => String(indexAccessor()),
|
|
280
|
+
'data-toc-target': () => itemAccessor().id,
|
|
281
|
+
'data-active': () =>
|
|
282
|
+
state.current.index === indexAccessor() ? '1' : '0',
|
|
283
|
+
onClick: (event: Event) => {
|
|
284
|
+
event.preventDefault();
|
|
285
|
+
scrollToItem(itemAccessor(), {
|
|
286
|
+
activeIndex: indexAccessor(),
|
|
287
|
+
updateHash: true,
|
|
288
|
+
});
|
|
289
|
+
},
|
|
290
|
+
children: () => itemAccessor().text,
|
|
291
|
+
}),
|
|
292
|
+
}),
|
|
293
|
+
}),
|
|
294
|
+
}) as HTMLElement,
|
|
295
|
+
onBuild(context) {
|
|
296
|
+
target = requireContainer(settings.target, 'Toc.target');
|
|
297
|
+
events.on('scroll', window, 'scroll', onScroll, { passive: true });
|
|
298
|
+
context.own(() => events.clear());
|
|
299
|
+
syncFromTarget();
|
|
300
|
+
if (settings.reactive) {
|
|
301
|
+
observer = new MutationObserver(scheduleRefresh);
|
|
302
|
+
observer.observe(target, {
|
|
303
|
+
childList: true,
|
|
304
|
+
subtree: true,
|
|
305
|
+
characterData: true,
|
|
306
|
+
});
|
|
307
|
+
context.own(() => {
|
|
308
|
+
observer?.disconnect();
|
|
309
|
+
observer = null;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
onDestroy() {
|
|
314
|
+
if (runtime.frameId) cancelAnimationFrame(runtime.frameId);
|
|
315
|
+
if (runtime.refreshFrameId) cancelAnimationFrame(runtime.refreshFrameId);
|
|
316
|
+
runtime.frameId = 0;
|
|
317
|
+
runtime.refreshFrameId = 0;
|
|
318
|
+
runtime.ticking = false;
|
|
319
|
+
runtime.refreshing = false;
|
|
320
|
+
observer?.disconnect();
|
|
321
|
+
observer = null;
|
|
322
|
+
target = null;
|
|
323
|
+
headings = [];
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
return toc;
|
|
381
328
|
}
|