lapikit 0.7.9 → 0.8.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.
@@ -166,7 +166,7 @@ button.kit-list-item {
166
166
  color: var(--kit-list-item-pressed-fg, var(--kit-list-item-fg));
167
167
  }
168
168
 
169
- .kit-list-item:not([data-disabled=true]):focus-visible {
169
+ .kit-list-item:is(:not([data-disabled=true]), [data-disabled-focusable=true]):focus-visible {
170
170
  outline: 2px solid var(--kit-color-focus);
171
171
  outline-offset: 2px;
172
172
  }
@@ -175,4 +175,9 @@ button.kit-list-item {
175
175
  opacity: var(--kit-disabled-opacity, 0.55);
176
176
  pointer-events: none;
177
177
  user-select: none;
178
+ }
179
+
180
+ .kit-list-item[data-disabled-focusable=true] {
181
+ pointer-events: auto;
182
+ cursor: not-allowed;
178
183
  }</style>
@@ -1,11 +1,13 @@
1
1
  <script lang="ts">
2
+ import { DEV } from 'esm-env';
2
3
  import { clickOutside, floating, useComponentAttrs, useElevation } from '../../utils';
3
- import type { ModelPopoverProps, PopoverProps } from './popover.types.js';
4
+ import type { PopoverProps, PopoverTriggerProps } from './popover.types.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(),
7
8
  open = $bindable(false),
8
9
  children,
10
+ trigger,
9
11
  activator,
10
12
  rounded = 'md',
11
13
  position = 'bottom',
@@ -19,31 +21,73 @@
19
21
  ...rest
20
22
  }: PopoverProps = $props();
21
23
 
24
+ $effect(() => {
25
+ if (DEV && activator)
26
+ console.warn('[lapikit] kit:popover: activator is removed, use the trigger snippet');
27
+ });
28
+
29
+ const popoverId = $props.id();
30
+
22
31
  let attrs = $derived(
23
32
  useComponentAttrs('kit-popover-content', { className, sClass, styleAttr, sStyle, color }, rest)
24
33
  );
25
34
  let elevationState = $derived(useElevation(elevation));
26
35
 
27
36
  let contentRef = $state<HTMLElement | null>(null);
28
- let activatorRef = $state<HTMLElement | null>(null);
37
+ let triggerRef = $state<HTMLElement | null>(null);
29
38
 
30
- const model: ModelPopoverProps = {
31
- toggle: (element) => {
32
- if (element === null) return;
33
- activatorRef = element;
39
+ const focusableSelector =
40
+ 'a[href], button:not(:disabled), input:not(:disabled), select:not(:disabled), textarea:not(:disabled), [tabindex]:not([tabindex="-1"])';
41
+
42
+ const close = (restoreFocus = false) => {
43
+ open = false;
44
+ if (restoreFocus) triggerRef?.focus();
45
+ };
46
+
47
+ let triggerProps: PopoverTriggerProps = $derived({
48
+ 'aria-haspopup': 'dialog',
49
+ 'aria-expanded': open,
50
+ 'aria-controls': popoverId,
51
+ onclick: (event: MouseEvent) => {
52
+ triggerRef = event.currentTarget as HTMLElement;
34
53
  open = !open;
35
54
  }
55
+ });
56
+
57
+ // focus leaves the popover for another element of the page
58
+ const onFocusOut = (event: FocusEvent) => {
59
+ const next = event.relatedTarget as Node | null;
60
+ if (!next || contentRef?.contains(next) || triggerRef?.contains(next)) return;
61
+ close();
36
62
  };
37
63
 
38
64
  $effect(() => {
39
65
  ref = contentRef;
40
66
  });
41
67
 
68
+ $effect(() => {
69
+ if (open && !triggerRef?.isConnected) {
70
+ triggerRef = document.querySelector<HTMLElement>(
71
+ `[aria-controls="${CSS.escape(popoverId)}"]`
72
+ );
73
+ }
74
+ });
75
+
76
+ $effect(() => {
77
+ if (!open || !contentRef) return;
78
+ const content = contentRef;
79
+ const frame = requestAnimationFrame(() => {
80
+ const first = content.querySelector<HTMLElement>(focusableSelector);
81
+ (first ?? content).focus();
82
+ });
83
+ return () => cancelAnimationFrame(frame);
84
+ });
85
+
42
86
  $effect(() => {
43
87
  if (!open) return;
44
88
 
45
89
  const onKeydown = (event: KeyboardEvent) => {
46
- if (event.key === 'Escape') open = false;
90
+ if (event.key === 'Escape') close(true);
47
91
  };
48
92
 
49
93
  document.addEventListener('keydown', onKeydown);
@@ -51,22 +95,25 @@
51
95
  });
52
96
  </script>
53
97
 
54
- {@render activator?.(model)}
98
+ {@render trigger?.(triggerProps)}
55
99
 
56
100
  {#if open}
57
101
  <div
58
102
  bind:this={contentRef}
103
+ id={popoverId}
59
104
  popover="manual"
60
105
  class={attrs.class}
61
106
  style={attrs.style}
62
107
  role="dialog"
108
+ tabindex="-1"
63
109
  data-rounded={rounded}
64
110
  data-density={density}
65
111
  data-elevation={elevationState.base}
66
112
  data-elevation-hover={elevationState.hover}
67
113
  data-elevation-active={elevationState.active}
68
- use:floating={{ anchor: activatorRef, side: position, offset: 6 }}
69
- use:clickOutside={{ exclude: [contentRef, activatorRef], onClose: () => (open = false) }}
114
+ onfocusout={onFocusOut}
115
+ use:floating={{ anchor: triggerRef, side: position, offset: 6 }}
116
+ use:clickOutside={{ exclude: [contentRef, triggerRef], onClose: () => close() }}
70
117
  {...attrs.rest}
71
118
  >
72
119
  {@render children?.()}
@@ -1,15 +1,21 @@
1
1
  import type { ColorProps, Component, ElevationProps, RoundedType } from '../../@types';
2
2
  import type { Snippet } from 'svelte';
3
- export type ModelPopoverProps = {
4
- toggle: (element: HTMLElement | null) => void;
5
- };
3
+ /** The attributes to spread on the element that opens the popover */
4
+ export interface PopoverTriggerProps {
5
+ 'aria-haspopup': 'dialog';
6
+ 'aria-expanded': boolean;
7
+ 'aria-controls': string;
8
+ onclick: (event: MouseEvent) => void;
9
+ }
6
10
  export interface PopoverProps extends Component {
7
11
  ref?: HTMLElement | null;
8
12
  open?: boolean;
9
13
  rounded?: RoundedType | 'full';
10
14
  position?: 'top' | 'bottom' | 'left' | 'right';
11
15
  color?: ColorProps;
12
- activator?: Snippet<[ModelPopoverProps]>;
16
+ trigger?: Snippet<[PopoverTriggerProps]>;
13
17
  elevation?: ElevationProps;
14
18
  density?: 'dense' | 'compact' | 'default' | 'comfortable' | 'spacious';
19
+ /** removed in 0.8.0: use the trigger snippet */
20
+ activator?: never;
15
21
  }
@@ -6,8 +6,7 @@
6
6
  ref = $bindable(),
7
7
  value = $bindable(),
8
8
  type = 'text',
9
- min,
10
- max,
9
+ maxlength,
11
10
  counter = false,
12
11
  hideSpinButtons = false,
13
12
  class: className,
@@ -21,6 +20,7 @@
21
20
  rounded,
22
21
  color,
23
22
  elevation,
23
+ label,
24
24
  disabled = false,
25
25
  readonly = false,
26
26
  error = false,
@@ -44,13 +44,6 @@
44
44
  let inputRef = $state<HTMLInputElement | null>(null);
45
45
  let text = $derived(`${value ?? ''}`);
46
46
 
47
- $effect(() => {
48
- if (typeof max === 'number' && max > 0 && text.length > max) {
49
- const truncated = text.slice(0, max);
50
- value = typeof value === 'number' ? Number(truncated) || 0 : truncated;
51
- }
52
- });
53
-
54
47
  function clear() {
55
48
  value = '';
56
49
  inputRef?.focus();
@@ -70,6 +63,7 @@
70
63
  {rounded}
71
64
  {color}
72
65
  {elevation}
66
+ {label}
73
67
  {disabled}
74
68
  {readonly}
75
69
  {error}
@@ -88,7 +82,7 @@
88
82
  {prependInner}
89
83
  {appendInner}
90
84
  dirty={text.length > 0}
91
- counter={counter ? `${text.length}${max ? `/${max}` : ''}` : undefined}
85
+ counter={counter ? `${text.length}${maxlength ? `/${maxlength}` : ''}` : undefined}
92
86
  onclear={clear}
93
87
  data-hide-spin-buttons={type === 'number' && hideSpinButtons}
94
88
  >
@@ -101,8 +95,7 @@
101
95
  class="kit-textfield__input"
102
96
  {type}
103
97
  size="1"
104
- minlength={min}
105
- maxlength={max}
98
+ {maxlength}
106
99
  />
107
100
  {/snippet}
108
101
  </Field>
@@ -1,7 +1,7 @@
1
1
  import type { HTMLInputAttributes } from 'svelte/elements';
2
2
  import type { ClassNameType, KitClassNameType, KitStylePropertiesType, StylePropertiesType } from '../../@types';
3
3
  import type { FieldBaseProps } from '../field/field.types';
4
- type FieldOwnedAttributes = keyof FieldBaseProps | 'size' | 'type' | 'value' | 'min' | 'max';
4
+ type FieldOwnedAttributes = keyof FieldBaseProps | 'size' | 'type' | 'value';
5
5
  export interface TextfieldProps extends FieldBaseProps, Omit<HTMLInputAttributes, FieldOwnedAttributes | 'class' | 'style' | 'children'> {
6
6
  ref?: HTMLElement | null;
7
7
  class?: ClassNameType;
@@ -10,10 +10,6 @@ export interface TextfieldProps extends FieldBaseProps, Omit<HTMLInputAttributes
10
10
  's-style'?: KitStylePropertiesType;
11
11
  value?: string | number;
12
12
  type?: 'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url';
13
- /** minimal length of the value */
14
- min?: number;
15
- /** maximal length of the value, also used by the counter */
16
- max?: number;
17
13
  counter?: boolean;
18
14
  hideSpinButtons?: boolean;
19
15
  }
@@ -0,0 +1,9 @@
1
+ import type { TooltipValue } from './tooltip.types.ts';
2
+ /**
3
+ * tooltip - Shows the shared tooltip on hover and keyboard focus of the node.
4
+ * A node without an accessible name gets the label as aria-label, the others get it as a description.
5
+ */
6
+ export declare function tooltip(node: HTMLElement, value: TooltipValue): {
7
+ update(next: TooltipValue): void;
8
+ destroy(): void;
9
+ };
@@ -0,0 +1,159 @@
1
+ import { mount } from 'svelte';
2
+ const sharedId = 'kit-tooltip-shared';
3
+ // one tooltip for every kit:btn, kit:chip and kit:icon, mounted on the first hover or focus
4
+ const shared = $state({
5
+ id: sharedId,
6
+ open: false,
7
+ label: '',
8
+ location: 'bottom',
9
+ variant: undefined,
10
+ density: 'default',
11
+ rounded: 'xs',
12
+ delayDuration: 850,
13
+ closeDelay: 100
14
+ });
15
+ let loading = null;
16
+ let owner = null;
17
+ function load() {
18
+ loading ??= import('./tooltip.svelte').then(({ default: Tooltip }) => {
19
+ const instance = mount(Tooltip, { target: document.body, props: shared });
20
+ return instance.triggerHandlers;
21
+ });
22
+ return loading;
23
+ }
24
+ function normalize(value) {
25
+ if (!value)
26
+ return null;
27
+ return typeof value === 'string' ? { label: value } : value.label ? value : null;
28
+ }
29
+ /**
30
+ * tooltip - Shows the shared tooltip on hover and keyboard focus of the node.
31
+ * A node without an accessible name gets the label as aria-label, the others get it as a description.
32
+ */
33
+ export function tooltip(node, value) {
34
+ let options = normalize(value);
35
+ let named = false;
36
+ let hovered = false;
37
+ let listening = false;
38
+ function syncName() {
39
+ if (named)
40
+ node.removeAttribute('aria-label');
41
+ named = false;
42
+ if (!options)
43
+ return;
44
+ const hasName = node.hasAttribute('aria-label') ||
45
+ node.hasAttribute('aria-labelledby') ||
46
+ !!node.textContent?.trim();
47
+ if (hasName)
48
+ return;
49
+ node.setAttribute('aria-label', options.label);
50
+ named = true;
51
+ }
52
+ function describe(on) {
53
+ if (named)
54
+ return;
55
+ const ids = (node.getAttribute('aria-describedby') ?? '').split(' ').filter(Boolean);
56
+ const others = ids.filter((id) => id !== sharedId);
57
+ const next = on ? [...others, sharedId] : others;
58
+ if (next.length)
59
+ node.setAttribute('aria-describedby', next.join(' '));
60
+ else
61
+ node.removeAttribute('aria-describedby');
62
+ }
63
+ function activate() {
64
+ if (!options)
65
+ return;
66
+ owner = node;
67
+ Object.assign(shared, {
68
+ label: options.label,
69
+ location: options.location ?? 'bottom',
70
+ variant: options.variant,
71
+ density: options.density ?? 'default',
72
+ rounded: options.rounded ?? 'xs',
73
+ delayDuration: options.delayDuration ?? 850,
74
+ closeDelay: options.closeDelay ?? 100
75
+ });
76
+ }
77
+ // the handlers read currentTarget and target, gone once the event is dispatched
78
+ const as = (event, target = event.target) => ({ currentTarget: node, target, pointerType: event.pointerType });
79
+ const onPointerEnter = (event) => {
80
+ hovered = true;
81
+ if (event.pointerType === 'touch')
82
+ return;
83
+ const fake = as(event);
84
+ load().then((handlers) => {
85
+ if (!hovered)
86
+ return;
87
+ activate();
88
+ handlers().onpointerenter(fake);
89
+ });
90
+ };
91
+ const onPointerLeave = (event) => {
92
+ hovered = false;
93
+ if (owner === node)
94
+ loading?.then((handlers) => handlers().onpointerleave(event));
95
+ };
96
+ const onPointerDown = (event) => {
97
+ if (owner === node)
98
+ loading?.then((handlers) => handlers().onpointerdown(event));
99
+ };
100
+ const onFocusIn = (event) => {
101
+ if (node.contains(event.relatedTarget))
102
+ return;
103
+ describe(true);
104
+ const fake = as(event);
105
+ load().then((handlers) => {
106
+ if (!node.contains(document.activeElement))
107
+ return;
108
+ activate();
109
+ handlers().onfocus(fake);
110
+ });
111
+ };
112
+ const onFocusOut = (event) => {
113
+ if (node.contains(event.relatedTarget))
114
+ return;
115
+ describe(false);
116
+ if (owner === node)
117
+ loading?.then((handlers) => handlers().onblur(event));
118
+ };
119
+ function listen(on) {
120
+ if (on === listening)
121
+ return;
122
+ listening = on;
123
+ const method = on ? 'addEventListener' : 'removeEventListener';
124
+ node[method]('pointerenter', onPointerEnter);
125
+ node[method]('pointerleave', onPointerLeave);
126
+ node[method]('pointerdown', onPointerDown);
127
+ node[method]('focusin', onFocusIn);
128
+ node[method]('focusout', onFocusOut);
129
+ }
130
+ function release() {
131
+ if (owner !== node)
132
+ return;
133
+ owner = null;
134
+ shared.open = false;
135
+ }
136
+ listen(!!options);
137
+ syncName();
138
+ return {
139
+ update(next) {
140
+ options = normalize(next);
141
+ listen(!!options);
142
+ syncName();
143
+ if (!options) {
144
+ describe(false);
145
+ release();
146
+ }
147
+ else if (owner === node) {
148
+ activate();
149
+ }
150
+ },
151
+ destroy() {
152
+ listen(false);
153
+ if (named)
154
+ node.removeAttribute('aria-label');
155
+ describe(false);
156
+ release();
157
+ }
158
+ };
159
+ }
@@ -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
- const tooltipId = $props.id();
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 triggerRef = $state<HTMLElement | null>(null);
44
+ let anchor = $state<HTMLElement | null>(null);
35
45
  let timer: ReturnType<typeof setTimeout> | null = null;
36
46
  let focused = false;
37
- let mounted = $derived(open || forceMount || !!tooltip);
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 handleHoverOpen = () => {
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 handleClose = () => {
59
+ const hide = () => {
62
60
  clearTimer();
63
61
  open = false;
64
62
  };
65
63
 
66
- const handleHoverClose = () => {
64
+ const scheduleHide = () => {
67
65
  clearTimer();
68
66
  if (focused) return;
69
- timer = setTimeout(handleClose, 100);
67
+ timer = setTimeout(hide, closeDelay);
70
68
  };
71
69
 
72
- const handleFocusClose = () => {
73
- focused = false;
74
- handleClose();
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
- ref = triggerRef;
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') handleClose();
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
- <!-- svelte-ignore a11y_no_static_element_interactions -->
98
- <span
99
- bind:this={triggerRef}
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: triggerRef,
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={handleHoverClose}
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, {}, "ref" | "open">;
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
- export interface TooltipProps extends Component {
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;