svelte-multiselect 11.5.1 → 11.6.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/CmdPalette.svelte.d.ts +2 -2
- package/dist/CodeExample.svelte +1 -1
- package/dist/MultiSelect.svelte +324 -161
- package/dist/MultiSelect.svelte.d.ts +2 -2
- package/dist/Nav.svelte +408 -172
- package/dist/Nav.svelte.d.ts +38 -37
- package/dist/Wiggle.svelte +9 -2
- package/dist/Wiggle.svelte.d.ts +7 -4
- package/dist/attachments.d.ts +7 -1
- package/dist/attachments.js +164 -108
- package/dist/heading-anchors.d.ts +14 -0
- package/dist/heading-anchors.js +114 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/live-examples/highlighter.js +62 -0
- package/dist/live-examples/index.d.ts +7 -0
- package/dist/live-examples/index.js +23 -0
- package/dist/live-examples/mdsvex-transform.d.ts +32 -0
- package/dist/live-examples/mdsvex-transform.js +184 -0
- package/dist/live-examples/vite-plugin.d.ts +6 -0
- package/dist/live-examples/vite-plugin.js +170 -0
- package/dist/types.d.ts +45 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +11 -0
- package/package.json +44 -20
- package/readme.md +25 -1
package/dist/Nav.svelte.d.ts
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
import type { Page } from '@sveltejs/kit';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
href: string;
|
|
14
|
-
label: string;
|
|
15
|
-
}]>;
|
|
16
|
-
menu_props?: HTMLAttributes<HTMLDivElement>;
|
|
17
|
-
link_props?: HTMLAttributes<HTMLAnchorElement>;
|
|
18
|
-
page?: Page;
|
|
19
|
-
labels?: Record<string, string>;
|
|
20
|
-
} & Omit<HTMLAttributes<HTMLElement>, "children">;
|
|
21
|
-
exports: {};
|
|
22
|
-
bindings: "";
|
|
23
|
-
slots: {};
|
|
24
|
-
events: {};
|
|
25
|
-
};
|
|
26
|
-
declare class __sveltets_Render<Route extends string | [string, string] | [string, string[]]> {
|
|
27
|
-
props(): ReturnType<typeof $$render<Route>>['props'];
|
|
28
|
-
events(): ReturnType<typeof $$render<Route>>['events'];
|
|
29
|
-
slots(): ReturnType<typeof $$render<Route>>['slots'];
|
|
30
|
-
bindings(): "";
|
|
31
|
-
exports(): {};
|
|
4
|
+
import type { TooltipOptions } from './attachments';
|
|
5
|
+
import type { NavRoute, NavRouteObject } from './types';
|
|
6
|
+
interface ItemSnippetParams {
|
|
7
|
+
route: NavRouteObject;
|
|
8
|
+
href: string;
|
|
9
|
+
label: string;
|
|
10
|
+
is_active: boolean;
|
|
11
|
+
is_dropdown: boolean;
|
|
12
|
+
render_default: Snippet;
|
|
32
13
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
14
|
+
type $$ComponentProps = {
|
|
15
|
+
routes: NavRoute[];
|
|
16
|
+
children?: Snippet<[{
|
|
17
|
+
is_open: boolean;
|
|
18
|
+
panel_id: string;
|
|
19
|
+
routes: NavRoute[];
|
|
20
|
+
}]>;
|
|
21
|
+
item?: Snippet<[ItemSnippetParams]>;
|
|
22
|
+
link?: Snippet<[{
|
|
23
|
+
href: string;
|
|
24
|
+
label: string;
|
|
25
|
+
}]>;
|
|
26
|
+
menu_props?: HTMLAttributes<HTMLDivElement>;
|
|
27
|
+
link_props?: HTMLAttributes<HTMLAnchorElement>;
|
|
28
|
+
page?: Page;
|
|
29
|
+
labels?: Record<string, string>;
|
|
30
|
+
tooltips?: Record<string, string | Omit<TooltipOptions, `disabled`>>;
|
|
31
|
+
tooltip_options?: Omit<TooltipOptions, `content`>;
|
|
32
|
+
breakpoint?: number;
|
|
33
|
+
onnavigate?: (data: {
|
|
34
|
+
href: string;
|
|
35
|
+
event: MouseEvent;
|
|
36
|
+
route: NavRouteObject;
|
|
37
|
+
}) => void | false;
|
|
38
|
+
onopen?: () => void;
|
|
39
|
+
onclose?: () => void;
|
|
40
|
+
} & Omit<HTMLAttributes<HTMLElementTagNameMap[`nav`]>, `children`>;
|
|
41
|
+
declare const Nav: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
42
|
+
type Nav = ReturnType<typeof Nav>;
|
|
42
43
|
export default Nav;
|
package/dist/Wiggle.svelte
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<script lang="ts">import { Spring } from 'svelte/motion';
|
|
2
|
-
let { wiggle = $bindable(false), angle = 0, scale = 1, dx = 0, dy = 0, duration = 200,
|
|
3
|
-
const store = Spring.of(() => (wiggle ? { scale, angle, dx, dy } : { angle: 0, scale: 1, dx: 0, dy: 0 }),
|
|
2
|
+
let { wiggle = $bindable(false), angle = 0, scale = 1, dx = 0, dy = 0, duration = 200, spring_options = $bindable({ stiffness: 0.05, damping: 0.1 }), children, ...rest } = $props();
|
|
3
|
+
const store = Spring.of(() => (wiggle ? { scale, angle, dx, dy } : { angle: 0, scale: 1, dx: 0, dy: 0 }), spring_options);
|
|
4
|
+
// update spring physics when options change
|
|
5
|
+
$effect(() => {
|
|
6
|
+
store.stiffness = spring_options.stiffness;
|
|
7
|
+
store.damping = spring_options.damping;
|
|
8
|
+
});
|
|
4
9
|
$effect.pre(() => {
|
|
5
10
|
if (wiggle)
|
|
6
11
|
setTimeout(() => (wiggle = false), duration);
|
|
@@ -8,6 +13,8 @@ $effect.pre(() => {
|
|
|
8
13
|
</script>
|
|
9
14
|
|
|
10
15
|
<span
|
|
16
|
+
{...rest}
|
|
17
|
+
style:display="inline-block"
|
|
11
18
|
style:transform="rotate({store.current.angle}deg) scale({store.current.scale})
|
|
12
19
|
translate({store.current.dx}px, {store.current.dy}px)"
|
|
13
20
|
>
|
package/dist/Wiggle.svelte.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
type
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = HTMLAttributes<HTMLSpanElement> & {
|
|
3
4
|
wiggle?: boolean;
|
|
4
5
|
angle?: number;
|
|
5
6
|
scale?: number;
|
|
6
7
|
dx?: number;
|
|
7
8
|
dy?: number;
|
|
8
9
|
duration?: number;
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
spring_options?: {
|
|
11
|
+
stiffness: number;
|
|
12
|
+
damping: number;
|
|
13
|
+
};
|
|
11
14
|
children?: Snippet;
|
|
12
15
|
};
|
|
13
|
-
declare const Wiggle: import("svelte").Component<$$ComponentProps, {}, "wiggle">;
|
|
16
|
+
declare const Wiggle: import("svelte").Component<$$ComponentProps, {}, "wiggle" | "spring_options">;
|
|
14
17
|
type Wiggle = ReturnType<typeof Wiggle>;
|
|
15
18
|
export default Wiggle;
|
package/dist/attachments.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type Attachment } from 'svelte/attachments';
|
|
2
|
+
import { get_uuid } from './utils';
|
|
3
|
+
export { get_uuid };
|
|
2
4
|
declare global {
|
|
3
5
|
interface CSS {
|
|
4
6
|
highlights: HighlightRegistry;
|
|
@@ -56,8 +58,12 @@ export interface TooltipOptions {
|
|
|
56
58
|
content?: string;
|
|
57
59
|
placement?: `top` | `bottom` | `left` | `right`;
|
|
58
60
|
delay?: number;
|
|
59
|
-
|
|
61
|
+
hide_delay?: number;
|
|
62
|
+
disabled?: boolean | `touch-devices`;
|
|
60
63
|
style?: string;
|
|
64
|
+
show_arrow?: boolean;
|
|
65
|
+
offset?: number;
|
|
66
|
+
allow_html?: boolean;
|
|
61
67
|
}
|
|
62
68
|
export declare const tooltip: (options?: TooltipOptions) => Attachment;
|
|
63
69
|
export type ClickOutsideConfig<T extends HTMLElement> = {
|
package/dist/attachments.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import {} from 'svelte/attachments';
|
|
2
|
+
import { get_uuid } from './utils';
|
|
3
|
+
// Re-export get_uuid for backwards compatibility
|
|
4
|
+
export { get_uuid };
|
|
2
5
|
// Svelte 5 attachment factory to make an element draggable
|
|
3
6
|
// @param options - Configuration options for dragging behavior
|
|
4
7
|
// @returns Attachment function that sets up dragging on an element
|
|
@@ -358,35 +361,46 @@ function clear_tooltip() {
|
|
|
358
361
|
if (hide_timeout)
|
|
359
362
|
clearTimeout(hide_timeout);
|
|
360
363
|
if (current_tooltip) {
|
|
364
|
+
// Remove aria-describedby from the trigger element
|
|
365
|
+
current_tooltip._owner?.removeAttribute(`aria-describedby`);
|
|
361
366
|
current_tooltip.remove();
|
|
362
367
|
current_tooltip = null;
|
|
363
368
|
}
|
|
364
369
|
}
|
|
365
370
|
export const tooltip = (options = {}) => (node) => {
|
|
366
|
-
//
|
|
367
|
-
if (
|
|
371
|
+
// SSR guard + element validation
|
|
372
|
+
if (typeof document === `undefined` || !(node instanceof HTMLElement))
|
|
368
373
|
return;
|
|
369
|
-
// Handle null/undefined options
|
|
370
|
-
const safe_options = options || {};
|
|
371
374
|
const cleanup_functions = [];
|
|
375
|
+
// Handle disabled option
|
|
376
|
+
if (options.disabled === true)
|
|
377
|
+
return;
|
|
378
|
+
// Track current input method for 'touch-devices' option (runtime detection, not capability sniffing)
|
|
379
|
+
// This allows tooltips on hybrid devices (Surface, iPad with mouse) when using mouse/stylus
|
|
380
|
+
let last_pointer_type = `mouse`;
|
|
381
|
+
const track_pointer = (event) => {
|
|
382
|
+
last_pointer_type = event.pointerType;
|
|
383
|
+
};
|
|
384
|
+
if (options.disabled === `touch-devices`) {
|
|
385
|
+
document.addEventListener(`pointerdown`, track_pointer, true);
|
|
386
|
+
cleanup_functions.push(() => document.removeEventListener(`pointerdown`, track_pointer, true));
|
|
387
|
+
}
|
|
372
388
|
function setup_tooltip(element) {
|
|
373
|
-
if (!element || safe_options.disabled)
|
|
374
|
-
return;
|
|
375
389
|
// Use let so content can be updated reactively
|
|
376
|
-
let content =
|
|
390
|
+
let content = options.content || element.title ||
|
|
377
391
|
element.getAttribute(`aria-label`) || element.getAttribute(`data-title`);
|
|
378
392
|
if (!content)
|
|
379
393
|
return;
|
|
380
394
|
// Store original title and remove it to prevent default tooltip
|
|
381
395
|
// Only store title if we're not using custom content
|
|
382
|
-
if (element.title && !
|
|
396
|
+
if (element.title && !options.content) {
|
|
383
397
|
element.setAttribute(`data-original-title`, element.title);
|
|
384
398
|
element.removeAttribute(`title`);
|
|
385
399
|
}
|
|
386
400
|
// Reactively update content when tooltip attributes change
|
|
387
401
|
const tooltip_attrs = [`title`, `aria-label`, `data-title`];
|
|
388
402
|
const observer = new MutationObserver((mutations) => {
|
|
389
|
-
if (
|
|
403
|
+
if (options.content)
|
|
390
404
|
return; // custom content takes precedence
|
|
391
405
|
for (const { type, attributeName } of mutations) {
|
|
392
406
|
if (type !== `attributes` || !attributeName)
|
|
@@ -408,20 +422,33 @@ export const tooltip = (options = {}) => (node) => {
|
|
|
408
422
|
content = new_content;
|
|
409
423
|
// Only update tooltip if this element owns it
|
|
410
424
|
if (current_tooltip?._owner === element) {
|
|
411
|
-
|
|
425
|
+
if (options.allow_html !== false) {
|
|
426
|
+
current_tooltip.innerHTML = content.replace(/\r/g, `<br/>`);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
current_tooltip.textContent = content;
|
|
430
|
+
}
|
|
412
431
|
}
|
|
413
432
|
}
|
|
414
433
|
});
|
|
415
434
|
observer.observe(element, { attributes: true, attributeFilter: tooltip_attrs });
|
|
416
435
|
function show_tooltip() {
|
|
436
|
+
// Skip tooltip on touch input when 'touch-devices' option is set
|
|
437
|
+
if (options.disabled === `touch-devices` && last_pointer_type === `touch`)
|
|
438
|
+
return;
|
|
417
439
|
clear_tooltip();
|
|
418
440
|
show_timeout = setTimeout(() => {
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
const placement =
|
|
422
|
-
|
|
441
|
+
const tooltip_el = document.createElement(`div`);
|
|
442
|
+
tooltip_el.className = `custom-tooltip`;
|
|
443
|
+
const placement = options.placement || `bottom`;
|
|
444
|
+
tooltip_el.setAttribute(`data-placement`, placement);
|
|
445
|
+
// Accessibility: link tooltip to trigger element
|
|
446
|
+
const tooltip_id = `tooltip-${get_uuid()}`;
|
|
447
|
+
tooltip_el.id = tooltip_id;
|
|
448
|
+
tooltip_el.setAttribute(`role`, `tooltip`);
|
|
449
|
+
element.setAttribute(`aria-describedby`, tooltip_id);
|
|
423
450
|
// Apply base styles
|
|
424
|
-
|
|
451
|
+
tooltip_el.style.cssText = `
|
|
425
452
|
position: absolute; z-index: 9999; opacity: 0;
|
|
426
453
|
background: var(--tooltip-bg, #333); color: var(--text-color, white); border: var(--tooltip-border, none);
|
|
427
454
|
padding: var(--tooltip-padding, 6px 10px); border-radius: var(--tooltip-radius, 6px); font-size: var(--tooltip-font-size, 13px); line-height: 1.4;
|
|
@@ -429,16 +456,22 @@ export const tooltip = (options = {}) => (node) => {
|
|
|
429
456
|
filter: var(--tooltip-shadow, drop-shadow(0 2px 8px rgba(0,0,0,0.25))); transition: opacity 0.15s ease-out;
|
|
430
457
|
`;
|
|
431
458
|
// Apply custom styles if provided (these will override base styles due to CSS specificity)
|
|
432
|
-
if (
|
|
459
|
+
if (options.style) {
|
|
433
460
|
// Parse and apply custom styles as individual properties for better control
|
|
434
|
-
const custom_styles =
|
|
461
|
+
const custom_styles = options.style.split(`;`).filter((style) => style.trim());
|
|
435
462
|
custom_styles.forEach((style) => {
|
|
436
463
|
const [property, value] = style.split(`:`).map((s) => s.trim());
|
|
437
464
|
if (property && value)
|
|
438
|
-
|
|
465
|
+
tooltip_el.style.setProperty(property, value);
|
|
439
466
|
});
|
|
440
467
|
}
|
|
441
|
-
|
|
468
|
+
// Security: allow_html defaults to true; set to false for plain text rendering
|
|
469
|
+
if (options.allow_html !== false) {
|
|
470
|
+
tooltip_el.innerHTML = content?.replace(/\r/g, `<br/>`) ?? ``;
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
tooltip_el.textContent = content ?? ``;
|
|
474
|
+
}
|
|
442
475
|
// Mirror CSS custom properties from the trigger node onto the tooltip element
|
|
443
476
|
const trigger_styles = getComputedStyle(element);
|
|
444
477
|
[
|
|
@@ -455,97 +488,100 @@ export const tooltip = (options = {}) => (node) => {
|
|
|
455
488
|
].forEach((name) => {
|
|
456
489
|
const value = trigger_styles.getPropertyValue(name).trim();
|
|
457
490
|
if (value)
|
|
458
|
-
|
|
491
|
+
tooltip_el.style.setProperty(name, value);
|
|
459
492
|
});
|
|
460
493
|
// Append early so we can read computed border styles for arrow border
|
|
461
|
-
document.body.appendChild(
|
|
462
|
-
//
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const arrow_size_raw = trigger_styles.getPropertyValue(`--tooltip-arrow-size`)
|
|
469
|
-
.trim();
|
|
470
|
-
const arrow_size_num = Number.parseInt(arrow_size_raw || ``, 10);
|
|
471
|
-
const arrow_px = Number.isFinite(arrow_size_num) ? arrow_size_num : 6;
|
|
472
|
-
const border_color = tooltip_styles.borderTopColor;
|
|
473
|
-
const border_width_num = Number.parseFloat(tooltip_styles.borderTopWidth || `0`);
|
|
474
|
-
const has_border = !!border_color && border_color !== `rgba(0, 0, 0, 0)` &&
|
|
475
|
-
border_width_num > 0;
|
|
476
|
-
const maybe_append_border_arrow = () => {
|
|
477
|
-
if (!has_border)
|
|
478
|
-
return;
|
|
479
|
-
const border_arrow = document.createElement(`div`);
|
|
480
|
-
border_arrow.className = `custom-tooltip-arrow-border`;
|
|
481
|
-
border_arrow.style.cssText =
|
|
494
|
+
document.body.appendChild(tooltip_el);
|
|
495
|
+
// Create arrow elements only if show_arrow is not false
|
|
496
|
+
if (options.show_arrow !== false) {
|
|
497
|
+
const tooltip_styles = getComputedStyle(tooltip_el);
|
|
498
|
+
const arrow = document.createElement(`div`);
|
|
499
|
+
arrow.className = `custom-tooltip-arrow`;
|
|
500
|
+
arrow.style.cssText =
|
|
482
501
|
`position: absolute; width: 0; height: 0; pointer-events: none;`;
|
|
483
|
-
const
|
|
502
|
+
const arrow_size_raw = trigger_styles.getPropertyValue(`--tooltip-arrow-size`)
|
|
503
|
+
.trim();
|
|
504
|
+
const arrow_size_num = Number.parseInt(arrow_size_raw || ``, 10);
|
|
505
|
+
const arrow_px = Number.isFinite(arrow_size_num) ? arrow_size_num : 6;
|
|
506
|
+
const border_color = tooltip_styles.borderTopColor;
|
|
507
|
+
const border_width_num = Number.parseFloat(tooltip_styles.borderTopWidth || `0`);
|
|
508
|
+
const has_border = !!border_color && border_color !== `rgba(0, 0, 0, 0)` &&
|
|
509
|
+
border_width_num > 0;
|
|
510
|
+
// Helper to create border arrow behind fill arrow
|
|
511
|
+
const append_border_arrow = () => {
|
|
512
|
+
if (!has_border)
|
|
513
|
+
return;
|
|
514
|
+
const border_arrow = document.createElement(`div`);
|
|
515
|
+
border_arrow.className = `custom-tooltip-arrow-border`;
|
|
516
|
+
border_arrow.style.cssText =
|
|
517
|
+
`position: absolute; width: 0; height: 0; pointer-events: none;`;
|
|
518
|
+
const border_size = arrow_px + (border_width_num * 1.4);
|
|
519
|
+
if (placement === `top`) {
|
|
520
|
+
border_arrow.style.left = `calc(50% - ${border_size}px)`;
|
|
521
|
+
border_arrow.style.bottom = `-${border_size}px`;
|
|
522
|
+
border_arrow.style.borderLeft = `${border_size}px solid transparent`;
|
|
523
|
+
border_arrow.style.borderRight = `${border_size}px solid transparent`;
|
|
524
|
+
border_arrow.style.borderTop = `${border_size}px solid ${border_color}`;
|
|
525
|
+
}
|
|
526
|
+
else if (placement === `left`) {
|
|
527
|
+
border_arrow.style.top = `calc(50% - ${border_size}px)`;
|
|
528
|
+
border_arrow.style.right = `-${border_size}px`;
|
|
529
|
+
border_arrow.style.borderTop = `${border_size}px solid transparent`;
|
|
530
|
+
border_arrow.style.borderBottom = `${border_size}px solid transparent`;
|
|
531
|
+
border_arrow.style.borderLeft = `${border_size}px solid ${border_color}`;
|
|
532
|
+
}
|
|
533
|
+
else if (placement === `right`) {
|
|
534
|
+
border_arrow.style.top = `calc(50% - ${border_size}px)`;
|
|
535
|
+
border_arrow.style.left = `-${border_size}px`;
|
|
536
|
+
border_arrow.style.borderTop = `${border_size}px solid transparent`;
|
|
537
|
+
border_arrow.style.borderBottom = `${border_size}px solid transparent`;
|
|
538
|
+
border_arrow.style.borderRight = `${border_size}px solid ${border_color}`;
|
|
539
|
+
}
|
|
540
|
+
else { // bottom
|
|
541
|
+
border_arrow.style.left = `calc(50% - ${border_size}px)`;
|
|
542
|
+
border_arrow.style.top = `-${border_size}px`;
|
|
543
|
+
border_arrow.style.borderLeft = `${border_size}px solid transparent`;
|
|
544
|
+
border_arrow.style.borderRight = `${border_size}px solid transparent`;
|
|
545
|
+
border_arrow.style.borderBottom = `${border_size}px solid ${border_color}`;
|
|
546
|
+
}
|
|
547
|
+
tooltip_el.appendChild(border_arrow);
|
|
548
|
+
};
|
|
549
|
+
// Style and position fill arrow
|
|
484
550
|
if (placement === `top`) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
551
|
+
arrow.style.left = `calc(50% - ${arrow_px}px)`;
|
|
552
|
+
arrow.style.bottom = `-${arrow_px}px`;
|
|
553
|
+
arrow.style.borderLeft = `${arrow_px}px solid transparent`;
|
|
554
|
+
arrow.style.borderRight = `${arrow_px}px solid transparent`;
|
|
555
|
+
arrow.style.borderTop = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
490
556
|
}
|
|
491
557
|
else if (placement === `left`) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
558
|
+
arrow.style.top = `calc(50% - ${arrow_px}px)`;
|
|
559
|
+
arrow.style.right = `-${arrow_px}px`;
|
|
560
|
+
arrow.style.borderTop = `${arrow_px}px solid transparent`;
|
|
561
|
+
arrow.style.borderBottom = `${arrow_px}px solid transparent`;
|
|
562
|
+
arrow.style.borderLeft = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
497
563
|
}
|
|
498
564
|
else if (placement === `right`) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
565
|
+
arrow.style.top = `calc(50% - ${arrow_px}px)`;
|
|
566
|
+
arrow.style.left = `-${arrow_px}px`;
|
|
567
|
+
arrow.style.borderTop = `${arrow_px}px solid transparent`;
|
|
568
|
+
arrow.style.borderBottom = `${arrow_px}px solid transparent`;
|
|
569
|
+
arrow.style.borderRight = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
504
570
|
}
|
|
505
571
|
else { // bottom
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
572
|
+
arrow.style.left = `calc(50% - ${arrow_px}px)`;
|
|
573
|
+
arrow.style.top = `-${arrow_px}px`;
|
|
574
|
+
arrow.style.borderLeft = `${arrow_px}px solid transparent`;
|
|
575
|
+
arrow.style.borderRight = `${arrow_px}px solid transparent`;
|
|
576
|
+
arrow.style.borderBottom = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
511
577
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// Create the fill arrow on top
|
|
515
|
-
if (placement === `top`) {
|
|
516
|
-
arrow.style.left = `calc(50% - ${arrow_px}px)`;
|
|
517
|
-
arrow.style.bottom = `-${arrow_px}px`;
|
|
518
|
-
arrow.style.borderLeft = `${arrow_px}px solid transparent`;
|
|
519
|
-
arrow.style.borderRight = `${arrow_px}px solid transparent`;
|
|
520
|
-
arrow.style.borderTop = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
578
|
+
append_border_arrow();
|
|
579
|
+
tooltip_el.appendChild(arrow);
|
|
521
580
|
}
|
|
522
|
-
else if (placement === `left`) {
|
|
523
|
-
arrow.style.top = `calc(50% - ${arrow_px}px)`;
|
|
524
|
-
arrow.style.right = `-${arrow_px}px`;
|
|
525
|
-
arrow.style.borderTop = `${arrow_px}px solid transparent`;
|
|
526
|
-
arrow.style.borderBottom = `${arrow_px}px solid transparent`;
|
|
527
|
-
arrow.style.borderLeft = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
528
|
-
}
|
|
529
|
-
else if (placement === `right`) {
|
|
530
|
-
arrow.style.top = `calc(50% - ${arrow_px}px)`;
|
|
531
|
-
arrow.style.left = `-${arrow_px}px`;
|
|
532
|
-
arrow.style.borderTop = `${arrow_px}px solid transparent`;
|
|
533
|
-
arrow.style.borderBottom = `${arrow_px}px solid transparent`;
|
|
534
|
-
arrow.style.borderRight = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
535
|
-
}
|
|
536
|
-
else { // bottom
|
|
537
|
-
arrow.style.left = `calc(50% - ${arrow_px}px)`;
|
|
538
|
-
arrow.style.top = `-${arrow_px}px`;
|
|
539
|
-
arrow.style.borderLeft = `${arrow_px}px solid transparent`;
|
|
540
|
-
arrow.style.borderRight = `${arrow_px}px solid transparent`;
|
|
541
|
-
arrow.style.borderBottom = `${arrow_px}px solid var(--tooltip-bg, #333)`;
|
|
542
|
-
}
|
|
543
|
-
maybe_append_border_arrow();
|
|
544
|
-
tooltip.appendChild(arrow);
|
|
545
581
|
// Position tooltip
|
|
546
582
|
const rect = element.getBoundingClientRect();
|
|
547
|
-
const tooltip_rect =
|
|
548
|
-
const margin = 12;
|
|
583
|
+
const tooltip_rect = tooltip_el.getBoundingClientRect();
|
|
584
|
+
const margin = options.offset ?? 12;
|
|
549
585
|
let top = 0, left = 0;
|
|
550
586
|
if (placement === `top`) {
|
|
551
587
|
top = rect.top - tooltip_rect.height - margin;
|
|
@@ -566,22 +602,26 @@ export const tooltip = (options = {}) => (node) => {
|
|
|
566
602
|
// Keep in viewport
|
|
567
603
|
left = Math.max(8, Math.min(left, globalThis.innerWidth - tooltip_rect.width - 8));
|
|
568
604
|
top = Math.max(8, Math.min(top, globalThis.innerHeight - tooltip_rect.height - 8));
|
|
569
|
-
|
|
570
|
-
|
|
605
|
+
tooltip_el.style.left = `${left + globalThis.scrollX}px`;
|
|
606
|
+
tooltip_el.style.top = `${top + globalThis.scrollY}px`;
|
|
571
607
|
const custom_opacity = trigger_styles.getPropertyValue(`--tooltip-opacity`).trim();
|
|
572
|
-
|
|
573
|
-
current_tooltip = Object.assign(
|
|
574
|
-
},
|
|
608
|
+
tooltip_el.style.opacity = custom_opacity || `1`;
|
|
609
|
+
current_tooltip = Object.assign(tooltip_el, { _owner: element });
|
|
610
|
+
}, options.delay || 100);
|
|
611
|
+
}
|
|
612
|
+
function handle_keydown(event) {
|
|
613
|
+
if (event.key === `Escape` && current_tooltip?._owner === element)
|
|
614
|
+
clear_tooltip();
|
|
575
615
|
}
|
|
576
616
|
function hide_tooltip() {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
current_tooltip = null;
|
|
583
|
-
}
|
|
617
|
+
if (show_timeout)
|
|
618
|
+
clearTimeout(show_timeout);
|
|
619
|
+
const delay = options.hide_delay ?? 0;
|
|
620
|
+
if (delay > 0) {
|
|
621
|
+
hide_timeout = setTimeout(() => clear_tooltip(), delay);
|
|
584
622
|
}
|
|
623
|
+
else
|
|
624
|
+
clear_tooltip();
|
|
585
625
|
}
|
|
586
626
|
function handle_scroll(event) {
|
|
587
627
|
// Hide if document or any ancestor scrolls (would move element). Skip internal element scrolls.
|
|
@@ -595,10 +635,26 @@ export const tooltip = (options = {}) => (node) => {
|
|
|
595
635
|
events.forEach((event, idx) => element.addEventListener(event, handlers[idx]));
|
|
596
636
|
// Hide tooltip when user scrolls the page (not element-level scrolls like input fields)
|
|
597
637
|
globalThis.addEventListener(`scroll`, handle_scroll, true);
|
|
638
|
+
// Add Escape key listener to dismiss tooltip
|
|
639
|
+
document.addEventListener(`keydown`, handle_keydown);
|
|
640
|
+
// Watch for element removal from DOM to prevent orphaned tooltips
|
|
641
|
+
const removal_observer = new MutationObserver((mutations) => {
|
|
642
|
+
const was_removed = mutations.some((mut) => Array.from(mut.removedNodes).some((node) => node === element || (node instanceof Element && node.contains(element))));
|
|
643
|
+
if (was_removed && current_tooltip?._owner === element)
|
|
644
|
+
clear_tooltip();
|
|
645
|
+
});
|
|
646
|
+
if (element.parentElement) {
|
|
647
|
+
removal_observer.observe(element.parentElement, { childList: true, subtree: true });
|
|
648
|
+
}
|
|
598
649
|
return () => {
|
|
599
650
|
observer.disconnect();
|
|
651
|
+
removal_observer.disconnect();
|
|
600
652
|
events.forEach((event, idx) => element.removeEventListener(event, handlers[idx]));
|
|
601
653
|
globalThis.removeEventListener(`scroll`, handle_scroll, true);
|
|
654
|
+
document.removeEventListener(`keydown`, handle_keydown);
|
|
655
|
+
// Clear tooltip if this element owns it (also removes aria-describedby)
|
|
656
|
+
if (current_tooltip?._owner === element)
|
|
657
|
+
clear_tooltip();
|
|
602
658
|
const original_title = element.getAttribute(`data-original-title`);
|
|
603
659
|
if (original_title) {
|
|
604
660
|
element.setAttribute(`title`, original_title);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @type {() => import('svelte/compiler').PreprocessorGroup} */
|
|
2
|
+
export declare function heading_ids(): {
|
|
3
|
+
name: string;
|
|
4
|
+
markup({ content }: {
|
|
5
|
+
content: string;
|
|
6
|
+
}): {
|
|
7
|
+
code: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export interface HeadingAnchorsOptions {
|
|
11
|
+
selector?: string;
|
|
12
|
+
icon_svg?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const heading_anchors: (options?: HeadingAnchorsOptions) => (node: Element) => (() => void) | undefined;
|