@vingy/vueltip 1.3.1 → 2.0.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 CHANGED
@@ -13,13 +13,16 @@ A headless tooltip component for Vue.js.
13
13
  To install Vueltip, use npm or yarn:
14
14
 
15
15
  ```bash
16
- pnpm add vueltip
16
+ pnpm add @vingy/vueltip
17
17
  ```
18
18
 
19
19
  Register the tooltip in your app:
20
20
 
21
21
  ```ts
22
- import { vueltipPlugin, vueltipDirective } from 'vueltip'
22
+ import {
23
+ vueltipPlugin,
24
+ vueltipDirective,
25
+ } from '@vingy/vueltip'
23
26
 
24
27
  createApp(App)
25
28
  .use(vueltipPlugin, { component: Tooltip })
@@ -52,7 +55,7 @@ First, create a tooltip component using the \`useTooltip\` composable:
52
55
 
53
56
  <script setup>
54
57
  import { useTemplateRef } from 'vue'
55
- import { useVueltip } from 'vueltip'
58
+ import { useVueltip } from '@vingy/vueltip'
56
59
 
57
60
  const tooltipElement = useTemplateRef('tooltipElement')
58
61
  const arrowElement = useTemplateRef('arrowElement')
@@ -90,7 +93,10 @@ Import and register the tooltip component and plugin in your app's entry point:
90
93
  // main.ts
91
94
  import { createApp } from 'vue'
92
95
  import App from './App.vue'
93
- import { vueltipPlugin, vueltipDirective } from 'vueltip'
96
+ import {
97
+ vueltipPlugin,
98
+ vueltipDirective,
99
+ } from '@vingy/vueltip'
94
100
  import Tooltip from './components/Tooltip.vue'
95
101
 
96
102
  const app = createApp(App)
@@ -121,7 +127,7 @@ Now you can use the `v-tooltip` directive on any element:
121
127
 
122
128
  <span
123
129
  v-tooltip="{
124
- content: 'This is a helpful tooltip',
130
+ text: 'This is a helpful tooltip',
125
131
  placement: 'right',
126
132
  }"
127
133
  >
@@ -139,17 +145,17 @@ See the demo app in [demo/](../../demo/).
139
145
 
140
146
  The `vueltipPlugin` accepts the following options:
141
147
 
142
- | Option | Type | Default | Description |
143
- | -------------------------- | -------------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------- |
144
- | `component` | `Component` | Required | The Vue component to render as the tooltip |
145
- | `showDelay` | `number` | `0` | Delay in milliseconds before the tooltip appears on hover |
146
- | `hideDelay` | `number` | `200` | Delay in milliseconds before the tooltip disappears when the cursor leaves |
147
- | `defaultPlacement` | `Placement` | `'top'` | Default tooltip placement: `'top'`, `'bottom'`, `'left'`, `'right'`, etc. |
148
- | `defaultTruncateDetection` | `'x' \| 'y' \| 'both' \| 'none'` | `'both'` | Direction(s) to check for text truncation (`'x'` for horizontal, `'y'` for vertical, `'both'`, or `'none'` to disable) |
149
- | `handleDialogModals` | `boolean` | `false` | Whether to handle tooltips within HTML `<dialog>` elements with the `open` attribute (modal dialogs) |
150
- | `placementAttribute` | `string` | `'vueltip-placement'` | HTML attribute name for tooltip placement overrides |
151
- | `keyAttribute` | `string` | `'vueltip-key'` | HTML attribute name for tooltip identification |
152
- | `truncateAttribute` | `string` | `'vueltip-truncate'` | HTML attribute name for truncate detection overrides |
148
+ | Option | Type | Default | Description |
149
+ | -------------------------- | -------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
150
+ | `component` | `Component` | Required | The Vue component to render as the tooltip |
151
+ | `showDelay` | `number` | `0` | Delay in milliseconds before the tooltip appears on hover |
152
+ | `hideDelay` | `number` | `200` | Delay in milliseconds before the tooltip disappears when the cursor leaves |
153
+ | `defaultPlacement` | `Placement` | `'top'` | Default tooltip placement: `'top'`, `'bottom'`, `'left'`, `'right'`, etc. |
154
+ | `defaultTruncateDetection` | `'x' \| 'y' \| 'both' \| 'none'` | `'both'` | Direction(s) to check for text truncation (`'x'` for horizontal, `'y'` for vertical, `'both'`, or `'none'` to disable) |
155
+ | `handleDialogModals` | `boolean` | `false` | Whether to handle tooltips within HTML `<dialog>` elements with the `open` attribute (modal dialogs) |
156
+ | `placementAttribute` | `string` | `'data-vueltip-placement'` | HTML attribute name for tooltip placement overrides |
157
+ | `keyAttribute` | `string` | `'data-vueltip-key'` | HTML attribute name for tooltip identification |
158
+ | `truncateAttribute` | `string` | `'data-vueltip-truncate'` | HTML attribute name for truncate detection overrides |
153
159
 
154
160
  ### useVueltip Composable Options
155
161
 
@@ -178,7 +184,64 @@ v-tooltip="'Tooltip text'"
178
184
 
179
185
  ```ts
180
186
  v-tooltip="{
181
- content: 'Tooltip text',
187
+ text: 'Tooltip text',
182
188
  placement: 'right' // Placement: 'top', 'bottom', 'left', 'right', etc.
183
189
  }"
184
190
  ```
191
+
192
+ ## Custom Data
193
+
194
+ You can extend the tooltip content with custom typed data for use in your tooltip component:
195
+
196
+ **1. Create a type declaration file (e.g., `vueltip.d.ts`):**
197
+
198
+ ```ts
199
+ declare module '@vingy/vueltip' {
200
+ interface CustomVueltipData {
201
+ userId?: number
202
+ userName?: string
203
+ severity?: 'info' | 'warning' | 'error'
204
+ metadata?: Record<string, unknown>
205
+ }
206
+ }
207
+ ```
208
+
209
+ **2. Use custom data in your directive:**
210
+
211
+ ```vue
212
+ <button
213
+ v-tooltip="{
214
+ text: 'User profile',
215
+ custom: {
216
+ userId: 123,
217
+ userName: 'John Doe',
218
+ severity: 'info',
219
+ },
220
+ }"
221
+ >
222
+ View Profile
223
+ </button>
224
+ ```
225
+
226
+ **3. Access custom data in your Tooltip component:**
227
+
228
+ ```vue
229
+ <script setup>
230
+ import { useVueltip } from '@vingy/vueltip'
231
+
232
+ const { content, show } = useVueltip({
233
+ /* ... */
234
+ })
235
+ </script>
236
+
237
+ <template>
238
+ <div v-if="show">
239
+ {{ content?.text }}
240
+
241
+ <!-- Access your custom data -->
242
+ <span v-if="content?.custom?.userId">
243
+ User ID: {{ content.custom.userId }}
244
+ </span>
245
+ </div>
246
+ </template>
247
+ ```
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- import { n as __reExport, t as __exportAll } from "./chunk-CtajNgzt.mjs";
2
1
  import * as Vue from "vue";
3
2
  import { App, Component, Directive, DirectiveBinding, ShallowRef, StyleValue } from "vue";
4
3
 
@@ -249,18 +248,19 @@ declare type UseFloatingOptions<T extends ReferenceElement = ReferenceElement> =
249
248
  type Maybe<T> = T | null | undefined; //#endregion
250
249
  //#endregion
251
250
  //#region src/types.d.ts
251
+ interface CustomVueltipData {}
252
252
  interface Content {
253
253
  text: Maybe<string>;
254
+ custom?: CustomVueltipData;
254
255
  }
255
- type Binding = Maybe<string> | {
256
- content: Maybe<string | Content>;
257
- placement: Placement;
258
- };
256
+ type Value = Maybe<string> | (Content & {
257
+ placement?: Placement;
258
+ });
259
259
  type Modifier = 'x' | 'y' | 'none' | 'both';
260
- type TooltipDirective = Directive<HTMLElement, Binding, Modifier, Placement>;
260
+ type TooltipDirective = Directive<HTMLElement, Value, Modifier, Placement>;
261
261
  type Options = {
262
- /** @default 'vueltip-placement' */placementAttribute: string; /** @default 'vueltip-key' */
263
- keyAttribute: string; /** @default 'vueltip-truncate' */
262
+ /** @default 'data-vueltip-placement' */placementAttribute: string; /** @default 'data-vueltip-key' */
263
+ keyAttribute: string; /** @default 'data-vueltip-truncate' */
264
264
  truncateAttribute: string; /** @default 0 */
265
265
  showDelay: number; /** @default 200 */
266
266
  hideDelay: number; /** @default false */
@@ -311,8 +311,8 @@ declare const useVueltip: ({
311
311
  //#endregion
312
312
  //#region src/directive.d.ts
313
313
  declare const vueltipDirective: {
314
- updated: (el: HTMLElement, binding: DirectiveBinding<Binding, Modifier, Placement>) => void;
315
- created: (el: HTMLElement, binding: DirectiveBinding<Binding, Modifier, Placement>) => void;
314
+ updated: (el: HTMLElement, binding: DirectiveBinding<Value, Modifier, Placement>) => void;
315
+ created: (el: HTMLElement, binding: DirectiveBinding<Value, Modifier, Placement>) => void;
316
316
  beforeUnmount: (el: HTMLElement) => void;
317
317
  };
318
318
  //#endregion
@@ -326,4 +326,4 @@ declare const vueltipPlugin: {
326
326
  }>) => void;
327
327
  };
328
328
  //#endregion
329
- export { type Content, setOptions, useVueltip, vueltipDirective, vueltipPlugin };
329
+ export { type Content, type CustomVueltipData, setOptions, useVueltip, vueltipDirective, vueltipPlugin };
package/dist/index.mjs CHANGED
@@ -1390,9 +1390,9 @@ function useFloating(reference, floating, options) {
1390
1390
  //#endregion
1391
1391
  //#region src/options.ts
1392
1392
  let options = {
1393
- placementAttribute: "vueltip-placement",
1394
- keyAttribute: "vueltip-key",
1395
- truncateAttribute: "vueltip-truncate",
1393
+ placementAttribute: "data-vueltip-placement",
1394
+ keyAttribute: "data-vueltip-key",
1395
+ truncateAttribute: "data-vueltip-truncate",
1396
1396
  showDelay: 0,
1397
1397
  hideDelay: 200,
1398
1398
  handleDialogModals: false,
@@ -1409,10 +1409,17 @@ const getOption = (key) => options[key];
1409
1409
 
1410
1410
  //#endregion
1411
1411
  //#region src/state.ts
1412
+ let timerId;
1412
1413
  const tooltipPlacement = ref("top");
1413
1414
  const debouncedTooltipPlacement = ref("top");
1414
1415
  const hoveredElement = ref();
1415
1416
  const debouncedHoveredElement = ref();
1417
+ const forceClearHoveredElement = (el) => {
1418
+ if (el !== debouncedHoveredElement.value && el !== hoveredElement.value) return;
1419
+ hoveredElement.value = void 0;
1420
+ debouncedHoveredElement.value = void 0;
1421
+ if (timerId) clearTimeout(timerId);
1422
+ };
1416
1423
  const contentMap = ref(/* @__PURE__ */ new Map());
1417
1424
  const getContent = (key) => contentMap.value.get(key);
1418
1425
  const setContent = (key, value) => contentMap.value.set(key, value);
@@ -1420,7 +1427,6 @@ const deleteContent = (key) => contentMap.value.delete(key);
1420
1427
  const generateKey = () => crypto.randomUUID();
1421
1428
  const tooltipKey = ref();
1422
1429
  const tooltipContent = ref();
1423
- let timerId;
1424
1430
  watch([
1425
1431
  tooltipKey,
1426
1432
  hoveredElement,
@@ -1573,13 +1579,12 @@ const onMouseout = ensureEventTarget((target) => {
1573
1579
  const toContent = (value) => {
1574
1580
  if (value == null) return { text: value };
1575
1581
  if (typeof value === "string") return { text: value };
1576
- if (value.content == null) return { text: value.content };
1577
- if (typeof value.content === "string") return { text: value.content };
1578
- return value.content;
1582
+ const { placement: _, ...rest } = value;
1583
+ return rest;
1579
1584
  };
1580
1585
  const extractPlacement = (binding) => {
1581
1586
  const { value, arg } = binding;
1582
- if (value && typeof value !== "string" && "placement" in value) return value.placement;
1587
+ if (value && typeof value !== "string" && "placement" in value && value.placement != null) return value.placement;
1583
1588
  if (!arg) return getOption("defaultPlacement");
1584
1589
  return arg;
1585
1590
  };
@@ -1612,6 +1617,7 @@ const vueltipDirective = {
1612
1617
  },
1613
1618
  beforeUnmount: (el) => {
1614
1619
  ensureKey(el, (key) => deleteContent(key));
1620
+ forceClearHoveredElement(el);
1615
1621
  el.removeEventListener("mouseenter", onMouseover);
1616
1622
  el.removeEventListener("focus", onMouseover);
1617
1623
  el.removeEventListener("mouseleave", onMouseout);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vingy/vueltip",
3
- "version": "1.3.1",
3
+ "version": "2.0.1",
4
4
  "description": "Headless tooltip which only shows when necessary.",
5
5
  "keywords": [
6
6
  "composition-api",