lapikit 0.7.9 → 0.8.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/dist/components/btn/btn.svelte +25 -4
- package/dist/components/btn/btn.types.d.ts +3 -0
- package/dist/components/card/card.svelte +6 -1
- package/dist/components/chip/chip.svelte +25 -4
- package/dist/components/chip/chip.types.d.ts +3 -0
- package/dist/components/dropdown/dropdown.svelte +120 -41
- package/dist/components/dropdown/dropdown.svelte.d.ts +1 -1
- package/dist/components/dropdown/dropdown.types.d.ts +19 -8
- package/dist/components/field/field.svelte +22 -0
- package/dist/components/field/field.types.d.ts +1 -0
- package/dist/components/icon/icon.svelte +11 -3
- package/dist/components/icon/icon.types.d.ts +3 -0
- package/dist/components/index.d.ts +3 -3
- package/dist/components/list/list.context.d.ts +7 -0
- package/dist/components/list/list.context.js +4 -0
- package/dist/components/list/list.svelte +18 -4
- package/dist/components/list/modules/list-item.svelte +68 -33
- package/dist/components/popover/popover.svelte +57 -10
- package/dist/components/popover/popover.types.d.ts +10 -4
- package/dist/components/textfield/textfield.svelte +5 -12
- package/dist/components/textfield/textfield.types.d.ts +1 -5
- package/dist/components/tooltip/tooltip-action.svelte.d.ts +9 -0
- package/dist/components/tooltip/tooltip-action.svelte.js +159 -0
- package/dist/components/tooltip/tooltip.svelte +71 -56
- package/dist/components/tooltip/tooltip.svelte.d.ts +4 -2
- package/dist/components/tooltip/tooltip.types.d.ts +28 -2
- package/dist/labs/sheet/sheet.svelte +6 -1
- package/package.json +1 -1
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onDestroy } from 'svelte';
|
|
3
|
+
import { DEV } from 'esm-env';
|
|
3
4
|
import { floating, useComponentAttrs } from '../../utils';
|
|
4
|
-
import type { TooltipProps } from './tooltip.types.js';
|
|
5
|
+
import type { TooltipProps, TooltipTriggerProps } from './tooltip.types.js';
|
|
5
6
|
|
|
6
7
|
let {
|
|
7
8
|
ref = $bindable(),
|
|
9
|
+
id,
|
|
8
10
|
children,
|
|
11
|
+
trigger,
|
|
9
12
|
tooltip,
|
|
10
13
|
open = $bindable(false),
|
|
11
|
-
forceMount = false,
|
|
12
14
|
label,
|
|
15
|
+
asLabel = false,
|
|
13
16
|
rounded = 'xs',
|
|
14
17
|
color,
|
|
15
18
|
location = 'bottom',
|
|
16
19
|
delayDuration = 850,
|
|
20
|
+
closeDelay = 100,
|
|
17
21
|
density = 'default',
|
|
18
22
|
variant,
|
|
19
23
|
disabled = false,
|
|
@@ -25,67 +29,96 @@
|
|
|
25
29
|
...rest
|
|
26
30
|
}: TooltipProps = $props();
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
$effect(() => {
|
|
33
|
+
if (DEV && children)
|
|
34
|
+
console.warn('[lapikit] kit:tooltip: children is removed, use the trigger snippet');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const generatedId = $props.id();
|
|
38
|
+
let tooltipId = $derived(id || generatedId);
|
|
29
39
|
|
|
30
40
|
let attrs = $derived(
|
|
31
41
|
useComponentAttrs('kit-tooltip', { className, sClass, styleAttr, sStyle, color }, rest)
|
|
32
42
|
);
|
|
33
43
|
|
|
34
|
-
let
|
|
44
|
+
let anchor = $state<HTMLElement | null>(null);
|
|
35
45
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
36
46
|
let focused = false;
|
|
37
|
-
let
|
|
47
|
+
let ariaAttribute = $derived(asLabel ? 'aria-labelledby' : 'aria-describedby');
|
|
38
48
|
|
|
39
49
|
const clearTimer = () => {
|
|
40
50
|
if (timer) clearTimeout(timer);
|
|
41
51
|
timer = null;
|
|
42
52
|
};
|
|
43
53
|
|
|
44
|
-
const
|
|
45
|
-
if (disabled) return;
|
|
46
|
-
clearTimer();
|
|
47
|
-
if (open) return;
|
|
48
|
-
timer = setTimeout(() => {
|
|
49
|
-
open = true;
|
|
50
|
-
timer = null;
|
|
51
|
-
}, delayDuration);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const handleFocusOpen = () => {
|
|
55
|
-
if (disabled) return;
|
|
56
|
-
focused = true;
|
|
54
|
+
const show = () => {
|
|
57
55
|
clearTimer();
|
|
58
56
|
open = true;
|
|
59
57
|
};
|
|
60
58
|
|
|
61
|
-
const
|
|
59
|
+
const hide = () => {
|
|
62
60
|
clearTimer();
|
|
63
61
|
open = false;
|
|
64
62
|
};
|
|
65
63
|
|
|
66
|
-
const
|
|
64
|
+
const scheduleHide = () => {
|
|
67
65
|
clearTimer();
|
|
68
66
|
if (focused) return;
|
|
69
|
-
timer = setTimeout(
|
|
67
|
+
timer = setTimeout(hide, closeDelay);
|
|
70
68
|
};
|
|
71
69
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
const isFocusVisible = (element: HTMLElement) => {
|
|
71
|
+
try {
|
|
72
|
+
return element.matches(':focus-visible');
|
|
73
|
+
} catch {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
75
76
|
};
|
|
76
77
|
|
|
78
|
+
// the trigger, when open is set without a pointer or a focus event
|
|
79
|
+
const findAnchor = () =>
|
|
80
|
+
document.querySelector<HTMLElement>(`[${ariaAttribute}~="${CSS.escape(tooltipId)}"]`);
|
|
81
|
+
|
|
82
|
+
let triggerProps: TooltipTriggerProps = $derived({
|
|
83
|
+
[ariaAttribute]: tooltipId,
|
|
84
|
+
onpointerenter: (event: PointerEvent) => {
|
|
85
|
+
if (disabled || event.pointerType === 'touch') return;
|
|
86
|
+
anchor = event.currentTarget as HTMLElement;
|
|
87
|
+
clearTimer();
|
|
88
|
+
if (open) return;
|
|
89
|
+
timer = setTimeout(show, delayDuration);
|
|
90
|
+
},
|
|
91
|
+
onpointerleave: scheduleHide,
|
|
92
|
+
onpointerdown: hide,
|
|
93
|
+
onfocus: (event: FocusEvent) => {
|
|
94
|
+
if (disabled) return;
|
|
95
|
+
anchor = event.currentTarget as HTMLElement;
|
|
96
|
+
focused = true;
|
|
97
|
+
if (isFocusVisible(event.target as HTMLElement)) show();
|
|
98
|
+
},
|
|
99
|
+
onblur: () => {
|
|
100
|
+
focused = false;
|
|
101
|
+
hide();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/** the handlers of the trigger, for the tooltip prop of kit:btn, kit:chip and kit:icon */
|
|
106
|
+
export function triggerHandlers() {
|
|
107
|
+
return triggerProps;
|
|
108
|
+
}
|
|
109
|
+
|
|
77
110
|
$effect(() => {
|
|
78
111
|
if (disabled) open = false;
|
|
79
112
|
});
|
|
80
113
|
|
|
81
114
|
$effect(() => {
|
|
82
|
-
|
|
115
|
+
if (open && !anchor?.isConnected) anchor = findAnchor();
|
|
83
116
|
});
|
|
84
117
|
|
|
85
118
|
$effect(() => {
|
|
86
119
|
if (!open) return;
|
|
87
120
|
const onKeyDown = (event: KeyboardEvent) => {
|
|
88
|
-
if (event.key === 'Escape')
|
|
121
|
+
if (event.key === 'Escape') hide();
|
|
89
122
|
};
|
|
90
123
|
document.addEventListener('keydown', onKeyDown);
|
|
91
124
|
return () => document.removeEventListener('keydown', onKeyDown);
|
|
@@ -94,33 +127,22 @@
|
|
|
94
127
|
onDestroy(clearTimer);
|
|
95
128
|
</script>
|
|
96
129
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class="kit-tooltip-trigger"
|
|
101
|
-
aria-describedby={open ? tooltipId : undefined}
|
|
102
|
-
onmouseenter={handleHoverOpen}
|
|
103
|
-
onmouseleave={handleHoverClose}
|
|
104
|
-
onfocusin={handleFocusOpen}
|
|
105
|
-
onfocusout={handleFocusClose}
|
|
106
|
-
>
|
|
107
|
-
{@render children?.()}
|
|
108
|
-
</span>
|
|
109
|
-
|
|
110
|
-
{#if mounted}
|
|
130
|
+
{@render trigger?.(triggerProps)}
|
|
131
|
+
|
|
132
|
+
{#if label || tooltip}
|
|
111
133
|
<div
|
|
134
|
+
bind:this={ref}
|
|
112
135
|
id={tooltipId}
|
|
113
136
|
popover="manual"
|
|
114
137
|
role="tooltip"
|
|
115
|
-
aria-label={label}
|
|
116
138
|
class={attrs.class}
|
|
117
139
|
style={attrs.style}
|
|
118
140
|
data-density={density}
|
|
119
141
|
data-variant={variant}
|
|
120
142
|
data-rounded={rounded}
|
|
121
143
|
use:floating={{
|
|
122
|
-
anchor
|
|
123
|
-
open,
|
|
144
|
+
anchor,
|
|
145
|
+
open: open && !!anchor,
|
|
124
146
|
side: location,
|
|
125
147
|
align: 'center',
|
|
126
148
|
offset: 6,
|
|
@@ -128,7 +150,7 @@
|
|
|
128
150
|
}}
|
|
129
151
|
{...attrs.rest}
|
|
130
152
|
onmouseenter={clearTimer}
|
|
131
|
-
onmouseleave={
|
|
153
|
+
onmouseleave={scheduleHide}
|
|
132
154
|
>
|
|
133
155
|
{#if tooltip}
|
|
134
156
|
{@render tooltip()}
|
|
@@ -167,18 +189,6 @@
|
|
|
167
189
|
--kit-tooltip-arrow: 0.35rem;
|
|
168
190
|
}
|
|
169
191
|
|
|
170
|
-
.kit-tooltip-trigger {
|
|
171
|
-
display: inline-flex;
|
|
172
|
-
align-self: start;
|
|
173
|
-
justify-self: start;
|
|
174
|
-
width: fit-content;
|
|
175
|
-
max-width: max-content;
|
|
176
|
-
}
|
|
177
|
-
.kit-tooltip-trigger:focus-visible {
|
|
178
|
-
outline: 2px solid var(--kit-color-focus);
|
|
179
|
-
outline-offset: 2px;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
192
|
.kit-tooltip {
|
|
183
193
|
position: fixed;
|
|
184
194
|
inset: auto;
|
|
@@ -307,4 +317,9 @@
|
|
|
307
317
|
.kit-tooltip {
|
|
308
318
|
animation: none;
|
|
309
319
|
}
|
|
320
|
+
}
|
|
321
|
+
@media (forced-colors: active) {
|
|
322
|
+
.kit-tooltip {
|
|
323
|
+
border: 1px solid CanvasText;
|
|
324
|
+
}
|
|
310
325
|
}</style>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { TooltipProps } from './tooltip.types.ts';
|
|
2
|
-
declare const Tooltip: import("svelte").Component<TooltipProps, {
|
|
1
|
+
import type { TooltipProps, TooltipTriggerProps } from './tooltip.types.ts';
|
|
2
|
+
declare const Tooltip: import("svelte").Component<TooltipProps, {
|
|
3
|
+
triggerHandlers: () => TooltipTriggerProps;
|
|
4
|
+
}, "ref" | "open">;
|
|
3
5
|
type Tooltip = ReturnType<typeof Tooltip>;
|
|
4
6
|
export default Tooltip;
|
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
import type { ColorProps, Component, RoundedType } from '../../@types';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
3
|
+
/** The attributes to spread on the element that shows the tooltip */
|
|
4
|
+
export interface TooltipTriggerProps {
|
|
5
|
+
'aria-describedby'?: string;
|
|
6
|
+
'aria-labelledby'?: string;
|
|
7
|
+
onpointerenter: (event: PointerEvent) => void;
|
|
8
|
+
onpointerleave: (event: PointerEvent) => void;
|
|
9
|
+
onpointerdown: (event: PointerEvent) => void;
|
|
10
|
+
onfocus: (event: FocusEvent) => void;
|
|
11
|
+
onblur: (event: FocusEvent) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface TooltipProps extends Omit<Component, 'children'> {
|
|
4
14
|
ref?: HTMLElement | null;
|
|
5
15
|
open?: boolean;
|
|
6
|
-
forceMount?: boolean;
|
|
7
16
|
rounded?: RoundedType | 'full';
|
|
8
17
|
label?: string;
|
|
18
|
+
/** the tooltip names the trigger (aria-labelledby) instead of describing it */
|
|
19
|
+
asLabel?: boolean;
|
|
9
20
|
location?: 'top' | 'bottom' | 'left' | 'right';
|
|
10
21
|
color?: ColorProps;
|
|
11
22
|
delayDuration?: number;
|
|
23
|
+
closeDelay?: number;
|
|
12
24
|
variant?: 'arrow';
|
|
13
25
|
density?: 'dense' | 'compact' | 'default' | 'comfortable' | 'spacious';
|
|
14
26
|
disabled?: boolean;
|
|
15
27
|
avoidCollisions?: boolean;
|
|
28
|
+
trigger?: Snippet<[TooltipTriggerProps]>;
|
|
16
29
|
tooltip?: Snippet;
|
|
30
|
+
/** removed in 0.8.0: use the trigger snippet */
|
|
31
|
+
children?: never;
|
|
32
|
+
}
|
|
33
|
+
/** The tooltip prop of kit:btn, kit:chip and kit:icon */
|
|
34
|
+
export interface TooltipOptions {
|
|
35
|
+
label: string;
|
|
36
|
+
location?: TooltipProps['location'];
|
|
37
|
+
variant?: TooltipProps['variant'];
|
|
38
|
+
density?: TooltipProps['density'];
|
|
39
|
+
rounded?: TooltipProps['rounded'];
|
|
40
|
+
delayDuration?: number;
|
|
41
|
+
closeDelay?: number;
|
|
17
42
|
}
|
|
43
|
+
export type TooltipValue = string | TooltipOptions | null | undefined | false;
|
|
@@ -203,7 +203,7 @@ button.kit-sheet {
|
|
|
203
203
|
color: var(--kit-sheet-pressed-fg, var(--kit-sheet-fg));
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
.kit-sheet:not([data-disabled=true]):focus-visible {
|
|
206
|
+
.kit-sheet:is(:not([data-disabled=true]), [data-disabled-focusable=true]):focus-visible {
|
|
207
207
|
outline: 2px solid var(--kit-color-focus);
|
|
208
208
|
outline-offset: 2px;
|
|
209
209
|
}
|
|
@@ -214,6 +214,11 @@ button.kit-sheet {
|
|
|
214
214
|
user-select: none;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
.kit-sheet[data-disabled-focusable=true] {
|
|
218
|
+
pointer-events: auto;
|
|
219
|
+
cursor: not-allowed;
|
|
220
|
+
}
|
|
221
|
+
|
|
217
222
|
/**
|
|
218
223
|
* rounded
|
|
219
224
|
* @link https://lapikit.dev/docs/customize
|