@vingy/vueltip 1.0.0 → 1.2.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/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { n as __reExport, t as __exportAll } from "./chunk-CtajNgzt.mjs";
2
2
  import * as Vue from "vue";
3
- import { App, Component, Directive, ShallowRef, StyleValue } from "vue";
3
+ import { App, Component, Directive, DirectiveBinding, ShallowRef, StyleValue } from "vue";
4
4
 
5
5
  //#region ../../node_modules/.pnpm/@floating-ui+utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.d.mts
6
6
  declare type AlignedPlacement = `${Side}-${Alignment}`;
@@ -252,13 +252,17 @@ type Binding = string | {
252
252
  content: string | Content;
253
253
  placement: Placement;
254
254
  };
255
- type TooltipDirective = Directive<HTMLElement, Binding>;
255
+ type Modifier = 'x' | 'y' | 'none' | 'both';
256
+ type TooltipDirective = Directive<HTMLElement, Binding, Modifier, Placement>;
256
257
  type Options = {
257
- /** @default 'tooltip-placement' */placementAttribute: string; /** @default 'tooltip-key' */
258
- keyAttribute: string; /** @default 0 */
258
+ /** @default 'vueltip-placement' */placementAttribute: string; /** @default 'vueltip-key' */
259
+ keyAttribute: string; /** @default 'vueltip-truncate' */
260
+ truncateAttribute: string; /** @default 0 */
259
261
  showDelay: number; /** @default 200 */
260
262
  hideDelay: number; /** @default false */
261
- handleDialogModals: boolean;
263
+ handleDialogModals: boolean; /** @default 'both' */
264
+ defaultTruncateDetection: Modifier; /** @default 'top' */
265
+ defaultPlacement: Placement;
262
266
  };
263
267
  type UseTooltipOptions = {
264
268
  tooltipElement: Readonly<ShallowRef<HTMLElement | null>>;
@@ -307,8 +311,8 @@ declare const useVueltip: ({
307
311
  //#endregion
308
312
  //#region src/directive.d.ts
309
313
  declare const vueltipDirective: {
310
- updated: (el: HTMLElement, binding: Vue.DirectiveBinding<Binding, string, any>) => void;
311
- created: (el: HTMLElement, binding: Vue.DirectiveBinding<Binding, string, any>) => void;
314
+ updated: (el: HTMLElement, binding: DirectiveBinding<Binding, Modifier, Placement>) => void;
315
+ created: (el: HTMLElement, binding: DirectiveBinding<Binding, Modifier, Placement>) => void;
312
316
  beforeUnmount: (el: HTMLElement) => void;
313
317
  };
314
318
  //#endregion
package/dist/index.mjs CHANGED
@@ -1392,9 +1392,12 @@ function useFloating(reference, floating, options) {
1392
1392
  let options = {
1393
1393
  placementAttribute: "vueltip-placement",
1394
1394
  keyAttribute: "vueltip-key",
1395
+ truncateAttribute: "vueltip-truncate",
1395
1396
  showDelay: 0,
1396
1397
  hideDelay: 200,
1397
- handleDialogModals: false
1398
+ handleDialogModals: false,
1399
+ defaultTruncateDetection: "both",
1400
+ defaultPlacement: "top"
1398
1401
  };
1399
1402
  const setOptions = (opts) => {
1400
1403
  options = {
@@ -1402,6 +1405,7 @@ const setOptions = (opts) => {
1402
1405
  ...opts
1403
1406
  };
1404
1407
  };
1408
+ const getOption = (key) => options[key];
1405
1409
 
1406
1410
  //#endregion
1407
1411
  //#region src/state.ts
@@ -1409,10 +1413,10 @@ const tooltipPlacement = ref("top");
1409
1413
  const debouncedTooltipPlacement = ref("top");
1410
1414
  const hoveredElement = ref();
1411
1415
  const debouncedHoveredElement = ref();
1412
- const contentMap = /* @__PURE__ */ new Map();
1413
- const getContent = (key) => contentMap.get(key);
1414
- const setContent = (key, value) => contentMap.set(key, value);
1415
- const deleteContent = (key) => contentMap.delete(key);
1416
+ const contentMap = ref(/* @__PURE__ */ new Map());
1417
+ const getContent = (key) => contentMap.value.get(key);
1418
+ const setContent = (key, value) => contentMap.value.set(key, value);
1419
+ const deleteContent = (key) => contentMap.value.delete(key);
1416
1420
  const generateKey = () => crypto.randomUUID();
1417
1421
  const tooltipKey = ref();
1418
1422
  const tooltipContent = ref();
@@ -1420,11 +1424,12 @@ let timerId;
1420
1424
  watch([
1421
1425
  tooltipKey,
1422
1426
  hoveredElement,
1423
- tooltipPlacement
1427
+ tooltipPlacement,
1428
+ () => getContent(tooltipKey.value ?? "")
1424
1429
  ], ([key, el, placement]) => {
1425
1430
  if (!key) return;
1426
1431
  if (timerId) clearTimeout(timerId);
1427
- const timeout = el ? options.showDelay : options.hideDelay;
1432
+ const timeout = el ? getOption("showDelay") : getOption("hideDelay");
1428
1433
  timerId = setTimeout(() => {
1429
1434
  tooltipContent.value = getContent(key);
1430
1435
  debouncedHoveredElement.value = el;
@@ -1477,7 +1482,7 @@ const useVueltip = ({ tooltipElement, arrowElement, offset: _offset, padding, ar
1477
1482
  };
1478
1483
  });
1479
1484
  const show = computed(() => !!debouncedHoveredElement.value);
1480
- if (options.handleDialogModals) watch(show, (value) => {
1485
+ if (getOption("handleDialogModals")) watch(show, (value) => {
1481
1486
  if (!value || !tooltipElement.value || !debouncedHoveredElement.value || !initialParent) return;
1482
1487
  const dialogEl = debouncedHoveredElement.value.closest("dialog");
1483
1488
  if (!dialogEl) {
@@ -1497,7 +1502,18 @@ const useVueltip = ({ tooltipElement, arrowElement, offset: _offset, padding, ar
1497
1502
  //#endregion
1498
1503
  //#region src/utils.ts
1499
1504
  function isTruncated(el) {
1500
- return el.offsetWidth < el.scrollWidth - 1 || el.offsetHeight < el.scrollHeight - 1;
1505
+ const direction = getTruncationDirection(el);
1506
+ const x = el.offsetWidth < el.scrollWidth - 1;
1507
+ const y = el.offsetHeight < el.scrollHeight - 1;
1508
+ switch (direction) {
1509
+ case "x": return x;
1510
+ case "y": return y;
1511
+ case "both": return x || y;
1512
+ case "none": return true;
1513
+ }
1514
+ }
1515
+ function getTruncationDirection(el) {
1516
+ return el.getAttribute(getOption("truncateAttribute")) ?? getOption("defaultTruncateDetection");
1501
1517
  }
1502
1518
  function elementContainsText(el, text) {
1503
1519
  if (isInputElement(el) || isTextAreaElement(el)) return getInputValue(el).includes(text);
@@ -1516,7 +1532,7 @@ function getInputValue(el) {
1516
1532
  return el.value;
1517
1533
  }
1518
1534
  const ensureKey = (el, fn) => {
1519
- const key = el.getAttribute(options.keyAttribute);
1535
+ const key = el.getAttribute(getOption("keyAttribute"));
1520
1536
  if (!key) return;
1521
1537
  return fn(key);
1522
1538
  };
@@ -1533,7 +1549,7 @@ const onMouseover = ensureEventTarget((target) => ensureKey(target, (key) => {
1533
1549
  if (!content) return;
1534
1550
  const { text } = content;
1535
1551
  if (elementContainsText(target, text) && !isTruncated(target)) return;
1536
- const placement = target.getAttribute(options.placementAttribute);
1552
+ const placement = target.getAttribute(getOption("placementAttribute"));
1537
1553
  tooltipKey.value = key;
1538
1554
  hoveredElement.value = target;
1539
1555
  tooltipPlacement.value = placement;
@@ -1546,16 +1562,34 @@ const onMouseout = ensureEventTarget((target) => {
1546
1562
  //#endregion
1547
1563
  //#region src/directive.ts
1548
1564
  const toContent = (value) => typeof value === "string" ? { text: value } : typeof value.content === "string" ? { text: value.content } : value.content;
1549
- const extractPlacement = (value) => typeof value === "string" ? "top" : value.placement;
1565
+ const extractPlacement = (binding) => {
1566
+ const { value, arg } = binding;
1567
+ if (typeof value !== "string" && "placement" in value) return value.placement;
1568
+ if (!arg) return getOption("defaultPlacement");
1569
+ return arg;
1570
+ };
1571
+ const truncationDirection = (modifiers) => {
1572
+ if (modifiers.none) return "none";
1573
+ if (modifiers.both) return "both";
1574
+ if (modifiers.x && modifiers.y) return "both";
1575
+ if (modifiers.x) return "x";
1576
+ if (modifiers.y) return "y";
1577
+ return getOption("defaultTruncateDetection");
1578
+ };
1550
1579
  const vueltipDirective = {
1551
1580
  updated: (el, binding) => {
1552
- ensureKey(el, (key) => setContent(key, toContent(binding.value)));
1581
+ ensureKey(el, (key) => {
1582
+ el.setAttribute(getOption("placementAttribute"), extractPlacement(binding));
1583
+ el.setAttribute(getOption("truncateAttribute"), truncationDirection(binding.modifiers ?? {}));
1584
+ setContent(key, toContent(binding.value));
1585
+ });
1553
1586
  },
1554
1587
  created: (el, binding) => {
1555
1588
  const key = generateKey();
1556
1589
  setContent(key, toContent(binding.value));
1557
- el.setAttribute(options.keyAttribute, key);
1558
- el.setAttribute(options.placementAttribute, extractPlacement(binding.value));
1590
+ el.setAttribute(getOption("keyAttribute"), key);
1591
+ el.setAttribute(getOption("placementAttribute"), extractPlacement(binding));
1592
+ el.setAttribute(getOption("truncateAttribute"), truncationDirection(binding.modifiers ?? {}));
1559
1593
  el.addEventListener("mouseenter", onMouseover);
1560
1594
  el.addEventListener("focus", onMouseover);
1561
1595
  el.addEventListener("mouseleave", onMouseout);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vingy/vueltip",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Headless tooltip which only shows when necessary.",
5
5
  "keywords": [
6
6
  "composition-api",