@zag-js/tooltip 0.10.5 → 0.11.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.
@@ -1,4 +1,4 @@
1
- import { createMachine, subscribe } from "@zag-js/core"
1
+ import { createMachine, subscribe, guards } from "@zag-js/core"
2
2
  import { addDomEvent } from "@zag-js/dom-event"
3
3
  import { getScrollParents, isHTMLElement, isSafari } from "@zag-js/dom-query"
4
4
  import { getPlacement } from "@zag-js/popper"
@@ -7,6 +7,8 @@ import { dom } from "./tooltip.dom"
7
7
  import { store } from "./tooltip.store"
8
8
  import type { MachineContext, MachineState, UserDefinedContext } from "./tooltip.types"
9
9
 
10
+ const { and, not } = guards
11
+
10
12
  export function machine(userContext: UserDefinedContext) {
11
13
  const ctx = compact(userContext)
12
14
  return createMachine<MachineContext, MachineState>(
@@ -22,6 +24,7 @@ export function machine(userContext: UserDefinedContext) {
22
24
  interactive: true,
23
25
  currentPlacement: undefined,
24
26
  ...ctx,
27
+ hasPointerMoveOpened: false,
25
28
  positioning: {
26
29
  placement: "bottom",
27
30
  ...ctx.positioning,
@@ -48,12 +51,19 @@ export function machine(userContext: UserDefinedContext) {
48
51
  entry: ["clearGlobalId", "invokeOnClose"],
49
52
  on: {
50
53
  FOCUS: "open",
51
- POINTER_ENTER: [
54
+ POINTER_LEAVE: {
55
+ actions: ["clearPointerMoveOpened"],
56
+ },
57
+ POINTER_MOVE: [
52
58
  {
53
- guard: "noVisibleTooltip",
59
+ guard: and("noVisibleTooltip", not("hasPointerMoveOpened")),
54
60
  target: "opening",
55
61
  },
56
- { target: "open" },
62
+ {
63
+ guard: not("hasPointerMoveOpened"),
64
+ target: "open",
65
+ actions: ["setPointerMoveOpened"],
66
+ },
57
67
  ],
58
68
  },
59
69
  },
@@ -62,10 +72,16 @@ export function machine(userContext: UserDefinedContext) {
62
72
  tags: ["closed"],
63
73
  activities: ["trackScroll", "trackPointerlockChange"],
64
74
  after: {
65
- OPEN_DELAY: "open",
75
+ OPEN_DELAY: {
76
+ target: "open",
77
+ actions: ["setPointerMoveOpened"],
78
+ },
66
79
  },
67
80
  on: {
68
- POINTER_LEAVE: "closed",
81
+ POINTER_LEAVE: {
82
+ target: "closed",
83
+ actions: ["clearPointerMoveOpened"],
84
+ },
69
85
  BLUR: "closed",
70
86
  SCROLL: "closed",
71
87
  POINTER_LOCK_CHANGE: "closed",
@@ -91,14 +107,18 @@ export function machine(userContext: UserDefinedContext) {
91
107
  {
92
108
  guard: "isVisible",
93
109
  target: "closing",
110
+ actions: ["clearPointerMoveOpened"],
111
+ },
112
+ {
113
+ target: "closed",
114
+ actions: ["clearPointerMoveOpened"],
94
115
  },
95
- { target: "closed" },
96
116
  ],
97
117
  BLUR: "closed",
98
118
  ESCAPE: "closed",
99
119
  SCROLL: "closed",
100
120
  POINTER_LOCK_CHANGE: "closed",
101
- TOOLTIP_POINTER_LEAVE: {
121
+ "CONTENT.POINTER_LEAVE": {
102
122
  guard: "isInteractive",
103
123
  target: "closing",
104
124
  },
@@ -121,8 +141,11 @@ export function machine(userContext: UserDefinedContext) {
121
141
  },
122
142
  on: {
123
143
  FORCE_CLOSE: "closed",
124
- POINTER_ENTER: "open",
125
- TOOLTIP_POINTER_ENTER: {
144
+ POINTER_MOVE: {
145
+ target: "open",
146
+ actions: ["setPointerMoveOpened"],
147
+ },
148
+ "CONTENT.POINTER_MOVE": {
126
149
  guard: "isInteractive",
127
150
  target: "open",
128
151
  },
@@ -197,7 +220,7 @@ export function machine(userContext: UserDefinedContext) {
197
220
  }
198
221
  },
199
222
  invokeOnOpen(ctx, evt) {
200
- const omit = ["TOOLTIP_POINTER_ENTER", "POINTER_ENTER"]
223
+ const omit = ["CONTENT.POINTER_MOVE", "POINTER_MOVE"]
201
224
  if (!omit.includes(evt.type)) {
202
225
  ctx.onOpen?.()
203
226
  }
@@ -206,9 +229,8 @@ export function machine(userContext: UserDefinedContext) {
206
229
  ctx.onClose?.()
207
230
  },
208
231
  closeIfDisabled(ctx, _evt, { send }) {
209
- if (ctx.disabled) {
210
- send("CLOSE")
211
- }
232
+ if (!ctx.disabled) return
233
+ send("CLOSE")
212
234
  },
213
235
  setPositioning(ctx, evt) {
214
236
  const getPositionerEl = () => dom.getPositionerEl(ctx)
@@ -222,12 +244,19 @@ export function machine(userContext: UserDefinedContext) {
222
244
  toggleVisibility(ctx, _evt, { send }) {
223
245
  send({ type: ctx.open ? "OPEN" : "CLOSE", src: "controlled" })
224
246
  },
247
+ setPointerMoveOpened(ctx) {
248
+ ctx.hasPointerMoveOpened = true
249
+ },
250
+ clearPointerMoveOpened(ctx) {
251
+ ctx.hasPointerMoveOpened = false
252
+ },
225
253
  },
226
254
  guards: {
227
255
  closeOnPointerDown: (ctx) => ctx.closeOnPointerDown,
228
256
  noVisibleTooltip: () => store.id === null,
229
257
  isVisible: (ctx) => ctx.id === store.id,
230
258
  isInteractive: (ctx) => ctx.interactive,
259
+ hasPointerMoveOpened: (ctx) => !!ctx.hasPointerMoveOpened,
231
260
  },
232
261
  delays: {
233
262
  OPEN_DELAY: (ctx) => ctx.openDelay,
@@ -81,6 +81,11 @@ type PrivateContext = RootProperties & {
81
81
  * The computed placement of the tooltip.
82
82
  */
83
83
  currentPlacement?: Placement
84
+ /**
85
+ * @internal
86
+ * Whether the pointermove already opened the tooltip.
87
+ */
88
+ hasPointerMoveOpened?: boolean
84
89
  }
85
90
 
86
91
  export type MachineContext = PublicContext & ComputedContext & PrivateContext
@@ -1,3 +0,0 @@
1
- import type { AnatomyInstance, AnatomyPart } from '@zag-js/anatomy';
2
- export declare const anatomy: AnatomyInstance<"content" | "label" | "trigger" | "arrow" | "arrowTip" | "positioner">;
3
- export declare const parts: Record<"content" | "label" | "trigger" | "arrow" | "arrowTip" | "positioner", AnatomyPart>;
@@ -1,11 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const anatomy$1 = require('@zag-js/anatomy');
6
-
7
- const anatomy = anatomy$1.createAnatomy("tooltip").parts("trigger", "arrow", "arrowTip", "positioner", "content", "label");
8
- const parts = anatomy.build();
9
-
10
- exports.anatomy = anatomy;
11
- exports.parts = parts;
@@ -1,6 +0,0 @@
1
- import { createAnatomy } from '@zag-js/anatomy';
2
-
3
- const anatomy = createAnatomy("tooltip").parts("trigger", "arrow", "arrowTip", "positioner", "content", "label");
4
- const parts = anatomy.build();
5
-
6
- export { anatomy, parts };
@@ -1,34 +0,0 @@
1
- import { PositioningOptions } from "@zag-js/popper";
2
- import type { NormalizeProps, PropTypes } from "@zag-js/types";
3
- import type { Send, State } from "./tooltip.types";
4
- export declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): {
5
- /**
6
- * Whether the tooltip is open.
7
- */
8
- isOpen: boolean;
9
- /**
10
- * Function to open the tooltip.
11
- */
12
- open(): void;
13
- /**
14
- * Function to close the tooltip.
15
- */
16
- close(): void;
17
- /**
18
- * Returns the animation state of the tooltip.
19
- */
20
- getAnimationState(): {
21
- enter: boolean;
22
- exit: boolean;
23
- };
24
- /**
25
- * Function to reposition the popover
26
- */
27
- setPositioning(options?: Partial<PositioningOptions>): void;
28
- triggerProps: T["button"];
29
- arrowProps: T["element"];
30
- arrowTipProps: T["element"];
31
- positionerProps: T["element"];
32
- contentProps: T["element"];
33
- labelProps: T["element"];
34
- };
@@ -1,133 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const domQuery = require('@zag-js/dom-query');
6
- const popper = require('@zag-js/popper');
7
- const visuallyHidden = require('@zag-js/visually-hidden');
8
- const tooltip_anatomy = require('./tooltip.anatomy.js');
9
- const tooltip_dom = require('./tooltip.dom.js');
10
- const tooltip_store = require('./tooltip.store.js');
11
-
12
- function connect(state, send, normalize) {
13
- const id = state.context.id;
14
- const hasAriaLabel = state.context.hasAriaLabel;
15
- const isOpen = state.hasTag("open");
16
- const triggerId = tooltip_dom.dom.getTriggerId(state.context);
17
- const contentId = tooltip_dom.dom.getContentId(state.context);
18
- const isDisabled = state.context.disabled;
19
- const popperStyles = popper.getPlacementStyles({
20
- placement: state.context.currentPlacement
21
- });
22
- return {
23
- /**
24
- * Whether the tooltip is open.
25
- */
26
- isOpen,
27
- /**
28
- * Function to open the tooltip.
29
- */
30
- open() {
31
- send("OPEN");
32
- },
33
- /**
34
- * Function to close the tooltip.
35
- */
36
- close() {
37
- send("CLOSE");
38
- },
39
- /**
40
- * Returns the animation state of the tooltip.
41
- */
42
- getAnimationState() {
43
- return {
44
- enter: tooltip_store.store.prevId === null && id === tooltip_store.store.id,
45
- exit: tooltip_store.store.id === null
46
- };
47
- },
48
- /**
49
- * Function to reposition the popover
50
- */
51
- setPositioning(options = {}) {
52
- send({ type: "SET_POSITIONING", options });
53
- },
54
- triggerProps: normalize.button({
55
- ...tooltip_anatomy.parts.trigger.attrs,
56
- id: triggerId,
57
- "data-expanded": domQuery.dataAttr(isOpen),
58
- "aria-describedby": isOpen ? contentId : void 0,
59
- onClick() {
60
- send("CLICK");
61
- },
62
- onFocus() {
63
- send("FOCUS");
64
- },
65
- onBlur() {
66
- if (id === tooltip_store.store.id) {
67
- send("BLUR");
68
- }
69
- },
70
- onPointerDown() {
71
- if (isDisabled)
72
- return;
73
- if (id === tooltip_store.store.id) {
74
- send("POINTER_DOWN");
75
- }
76
- },
77
- onPointerMove() {
78
- if (isDisabled)
79
- return;
80
- send("POINTER_ENTER");
81
- },
82
- onPointerLeave() {
83
- if (isDisabled)
84
- return;
85
- send("POINTER_LEAVE");
86
- },
87
- onPointerCancel() {
88
- if (isDisabled)
89
- return;
90
- send("POINTER_LEAVE");
91
- }
92
- }),
93
- arrowProps: normalize.element({
94
- id: tooltip_dom.dom.getArrowId(state.context),
95
- ...tooltip_anatomy.parts.arrow.attrs,
96
- style: popperStyles.arrow
97
- }),
98
- arrowTipProps: normalize.element({
99
- ...tooltip_anatomy.parts.arrowTip.attrs,
100
- style: popperStyles.arrowTip
101
- }),
102
- positionerProps: normalize.element({
103
- id: tooltip_dom.dom.getPositionerId(state.context),
104
- ...tooltip_anatomy.parts.positioner.attrs,
105
- style: popperStyles.floating
106
- }),
107
- contentProps: normalize.element({
108
- ...tooltip_anatomy.parts.content.attrs,
109
- hidden: !isOpen,
110
- role: hasAriaLabel ? void 0 : "tooltip",
111
- id: hasAriaLabel ? void 0 : contentId,
112
- "data-placement": state.context.currentPlacement,
113
- onPointerEnter() {
114
- send("TOOLTIP_POINTER_ENTER");
115
- },
116
- onPointerLeave() {
117
- send("TOOLTIP_POINTER_LEAVE");
118
- },
119
- style: {
120
- pointerEvents: state.context.interactive ? "auto" : "none"
121
- }
122
- }),
123
- labelProps: normalize.element({
124
- ...tooltip_anatomy.parts.label.attrs,
125
- id: contentId,
126
- role: "tooltip",
127
- style: visuallyHidden.visuallyHiddenStyle,
128
- children: state.context["aria-label"]
129
- })
130
- };
131
- }
132
-
133
- exports.connect = connect;
@@ -1,129 +0,0 @@
1
- import { dataAttr } from '@zag-js/dom-query';
2
- import { getPlacementStyles } from '@zag-js/popper';
3
- import { visuallyHiddenStyle } from '@zag-js/visually-hidden';
4
- import { parts } from './tooltip.anatomy.mjs';
5
- import { dom } from './tooltip.dom.mjs';
6
- import { store } from './tooltip.store.mjs';
7
-
8
- function connect(state, send, normalize) {
9
- const id = state.context.id;
10
- const hasAriaLabel = state.context.hasAriaLabel;
11
- const isOpen = state.hasTag("open");
12
- const triggerId = dom.getTriggerId(state.context);
13
- const contentId = dom.getContentId(state.context);
14
- const isDisabled = state.context.disabled;
15
- const popperStyles = getPlacementStyles({
16
- placement: state.context.currentPlacement
17
- });
18
- return {
19
- /**
20
- * Whether the tooltip is open.
21
- */
22
- isOpen,
23
- /**
24
- * Function to open the tooltip.
25
- */
26
- open() {
27
- send("OPEN");
28
- },
29
- /**
30
- * Function to close the tooltip.
31
- */
32
- close() {
33
- send("CLOSE");
34
- },
35
- /**
36
- * Returns the animation state of the tooltip.
37
- */
38
- getAnimationState() {
39
- return {
40
- enter: store.prevId === null && id === store.id,
41
- exit: store.id === null
42
- };
43
- },
44
- /**
45
- * Function to reposition the popover
46
- */
47
- setPositioning(options = {}) {
48
- send({ type: "SET_POSITIONING", options });
49
- },
50
- triggerProps: normalize.button({
51
- ...parts.trigger.attrs,
52
- id: triggerId,
53
- "data-expanded": dataAttr(isOpen),
54
- "aria-describedby": isOpen ? contentId : void 0,
55
- onClick() {
56
- send("CLICK");
57
- },
58
- onFocus() {
59
- send("FOCUS");
60
- },
61
- onBlur() {
62
- if (id === store.id) {
63
- send("BLUR");
64
- }
65
- },
66
- onPointerDown() {
67
- if (isDisabled)
68
- return;
69
- if (id === store.id) {
70
- send("POINTER_DOWN");
71
- }
72
- },
73
- onPointerMove() {
74
- if (isDisabled)
75
- return;
76
- send("POINTER_ENTER");
77
- },
78
- onPointerLeave() {
79
- if (isDisabled)
80
- return;
81
- send("POINTER_LEAVE");
82
- },
83
- onPointerCancel() {
84
- if (isDisabled)
85
- return;
86
- send("POINTER_LEAVE");
87
- }
88
- }),
89
- arrowProps: normalize.element({
90
- id: dom.getArrowId(state.context),
91
- ...parts.arrow.attrs,
92
- style: popperStyles.arrow
93
- }),
94
- arrowTipProps: normalize.element({
95
- ...parts.arrowTip.attrs,
96
- style: popperStyles.arrowTip
97
- }),
98
- positionerProps: normalize.element({
99
- id: dom.getPositionerId(state.context),
100
- ...parts.positioner.attrs,
101
- style: popperStyles.floating
102
- }),
103
- contentProps: normalize.element({
104
- ...parts.content.attrs,
105
- hidden: !isOpen,
106
- role: hasAriaLabel ? void 0 : "tooltip",
107
- id: hasAriaLabel ? void 0 : contentId,
108
- "data-placement": state.context.currentPlacement,
109
- onPointerEnter() {
110
- send("TOOLTIP_POINTER_ENTER");
111
- },
112
- onPointerLeave() {
113
- send("TOOLTIP_POINTER_LEAVE");
114
- },
115
- style: {
116
- pointerEvents: state.context.interactive ? "auto" : "none"
117
- }
118
- }),
119
- labelProps: normalize.element({
120
- ...parts.label.attrs,
121
- id: contentId,
122
- role: "tooltip",
123
- style: visuallyHiddenStyle,
124
- children: state.context["aria-label"]
125
- })
126
- };
127
- }
128
-
129
- export { connect };
@@ -1,31 +0,0 @@
1
- import type { MachineContext as Ctx } from "./tooltip.types";
2
- export declare const dom: {
3
- getRootNode: (ctx: {
4
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
5
- }) => ShadowRoot | Document;
6
- getDoc: (ctx: {
7
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
8
- }) => Document;
9
- getWin: (ctx: {
10
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
11
- }) => Window & typeof globalThis;
12
- getActiveElement: (ctx: {
13
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
14
- }) => HTMLElement | null;
15
- getById: <T extends HTMLElement = HTMLElement>(ctx: {
16
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
17
- }, id: string) => T | null;
18
- queryById: <T_1 extends HTMLElement = HTMLElement>(ctx: {
19
- getRootNode?: (() => Node | ShadowRoot | Document) | undefined;
20
- }, id: string) => T_1;
21
- } & {
22
- getTriggerId: (ctx: Ctx) => string;
23
- getContentId: (ctx: Ctx) => string;
24
- getArrowId: (ctx: Ctx) => string;
25
- getPositionerId: (ctx: Ctx) => string;
26
- getTriggerEl: (ctx: Ctx) => HTMLElement | null;
27
- getContentEl: (ctx: Ctx) => HTMLElement | null;
28
- getPositionerEl: (ctx: Ctx) => HTMLElement | null;
29
- getArrowEl: (ctx: Ctx) => HTMLElement | null;
30
- getScrollParent: (ctx: Ctx) => HTMLElement;
31
- };
@@ -1,19 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const domQuery = require('@zag-js/dom-query');
6
-
7
- const dom = domQuery.createScope({
8
- getTriggerId: (ctx) => ctx.ids?.trigger ?? `tooltip:${ctx.id}:trigger`,
9
- getContentId: (ctx) => ctx.ids?.content ?? `tooltip:${ctx.id}:content`,
10
- getArrowId: (ctx) => ctx.ids?.arrow ?? `tooltip:${ctx.id}:arrow`,
11
- getPositionerId: (ctx) => ctx.ids?.positioner ?? `tooltip:${ctx.id}:popper`,
12
- getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
13
- getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
14
- getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
15
- getArrowEl: (ctx) => dom.getById(ctx, dom.getArrowId(ctx)),
16
- getScrollParent: (ctx) => domQuery.getScrollParent(dom.getTriggerEl(ctx))
17
- });
18
-
19
- exports.dom = dom;
@@ -1,15 +0,0 @@
1
- import { createScope, getScrollParent } from '@zag-js/dom-query';
2
-
3
- const dom = createScope({
4
- getTriggerId: (ctx) => ctx.ids?.trigger ?? `tooltip:${ctx.id}:trigger`,
5
- getContentId: (ctx) => ctx.ids?.content ?? `tooltip:${ctx.id}:content`,
6
- getArrowId: (ctx) => ctx.ids?.arrow ?? `tooltip:${ctx.id}:arrow`,
7
- getPositionerId: (ctx) => ctx.ids?.positioner ?? `tooltip:${ctx.id}:popper`,
8
- getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
9
- getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
10
- getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
11
- getArrowEl: (ctx) => dom.getById(ctx, dom.getArrowId(ctx)),
12
- getScrollParent: (ctx) => getScrollParent(dom.getTriggerEl(ctx))
13
- });
14
-
15
- export { dom };
@@ -1,3 +0,0 @@
1
- import type { Machine, StateMachine } from '@zag-js/core';
2
- import type { MachineContext, MachineState, UserDefinedContext } from "./tooltip.types";
3
- export declare function machine(userContext: UserDefinedContext): Machine<MachineContext, MachineState, StateMachine.AnyEventObject>;