@zag-js/popover 1.43.0 → 2.0.0-next.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/index.d.mts CHANGED
@@ -3,7 +3,7 @@ export { anatomy } from './popover.anatomy.mjs';
3
3
  export { connect } from './popover.connect.mjs';
4
4
  export { machine } from './popover.machine.mjs';
5
5
  export { props, splitProps } from './popover.props.mjs';
6
- export { PopoverApi as Api, ElementIds, IntlTranslations, PopoverMachine as Machine, OpenChangeDetails, PopoverProps as Props, PopoverService as Service, TriggerProps, TriggerValueChangeDetails } from './popover.types.mjs';
6
+ export { PopoverApi as Api, ContentState, ElementIds, IntlTranslations, PopoverMachine as Machine, OpenChangeDetails, PositionerState, PopoverProps as Props, PopoverService as Service, TriggerProps, TriggerState, TriggerValueChangeDetails } from './popover.types.mjs';
7
7
  export { Placement, PositioningOptions } from '@zag-js/popper';
8
8
  import '@zag-js/anatomy';
9
9
  import '@zag-js/types';
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { anatomy } from './popover.anatomy.js';
3
3
  export { connect } from './popover.connect.js';
4
4
  export { machine } from './popover.machine.js';
5
5
  export { props, splitProps } from './popover.props.js';
6
- export { PopoverApi as Api, ElementIds, IntlTranslations, PopoverMachine as Machine, OpenChangeDetails, PopoverProps as Props, PopoverService as Service, TriggerProps, TriggerValueChangeDetails } from './popover.types.js';
6
+ export { PopoverApi as Api, ContentState, ElementIds, IntlTranslations, PopoverMachine as Machine, OpenChangeDetails, PositionerState, PopoverProps as Props, PopoverService as Service, TriggerProps, TriggerState, TriggerValueChangeDetails } from './popover.types.js';
7
7
  export { Placement, PositioningOptions } from '@zag-js/popper';
8
8
  import '@zag-js/anatomy';
9
9
  import '@zag-js/types';
@@ -33,25 +33,43 @@ __export(popover_connect_exports, {
33
33
  connect: () => connect
34
34
  });
35
35
  module.exports = __toCommonJS(popover_connect_exports);
36
+ var import_dismissable = require("@zag-js/dismissable");
36
37
  var import_dom_query = require("@zag-js/dom-query");
37
38
  var import_popper = require("@zag-js/popper");
38
39
  var import_popover = require("./popover.anatomy.js");
39
40
  var dom = __toESM(require("./popover.dom.js"));
40
41
  function connect(service, normalize) {
41
- const { state, context, send, computed, prop, scope } = service;
42
+ const { state, context, send, prop, scope } = service;
43
+ const layer = context.get("layer");
42
44
  const translations = prop("translations");
43
45
  const open = state.matches("open");
44
46
  const currentPlacement = context.get("currentPlacement");
45
47
  const currentPlacementSide = currentPlacement ? (0, import_popper.getPlacementSide)(currentPlacement) : void 0;
46
- const portalled = computed("currentPortalled");
47
48
  const rendered = context.get("renderedElements");
48
49
  const triggerValue = context.get("triggerValue");
49
50
  const popperStyles = (0, import_popper.getPlacementStyles)({
50
51
  ...prop("positioning"),
51
52
  placement: currentPlacement
52
53
  });
54
+ function getTriggerState(props = {}) {
55
+ const { value } = props;
56
+ const current = value == null ? false : triggerValue === value;
57
+ return { value, current, open: value == null ? open : open && current };
58
+ }
59
+ function getPositionerState() {
60
+ return { nested: !!layer?.nested, hasNested: !!layer?.hasNested };
61
+ }
62
+ function getContentState() {
63
+ return {
64
+ open,
65
+ modal: !!prop("modal"),
66
+ nested: !!layer?.nested,
67
+ hasNested: !!layer?.hasNested,
68
+ placement: currentPlacement,
69
+ side: currentPlacementSide
70
+ };
71
+ }
53
72
  return {
54
- portalled,
55
73
  open,
56
74
  setOpen(nextOpen) {
57
75
  const open2 = state.matches("open");
@@ -67,41 +85,39 @@ function connect(service, normalize) {
67
85
  },
68
86
  getArrowProps() {
69
87
  return normalize.element({
70
- id: dom.getArrowId(scope),
71
- ...import_popover.parts.arrow.attrs,
88
+ ...import_popover.parts.arrow.attrs(scope.id),
72
89
  dir: prop("dir"),
73
90
  style: popperStyles.arrow
74
91
  });
75
92
  },
76
93
  getArrowTipProps() {
77
94
  return normalize.element({
78
- ...import_popover.parts.arrowTip.attrs,
95
+ ...import_popover.parts.arrowTip.attrs(scope.id),
79
96
  dir: prop("dir"),
80
97
  style: popperStyles.arrowTip
81
98
  });
82
99
  },
83
100
  getAnchorProps() {
84
101
  return normalize.element({
85
- ...import_popover.parts.anchor.attrs,
86
- dir: prop("dir"),
87
- id: dom.getAnchorId(scope)
102
+ ...import_popover.parts.anchor.attrs(scope.id),
103
+ dir: prop("dir")
88
104
  });
89
105
  },
106
+ getTriggerState,
90
107
  getTriggerProps(props = {}) {
91
108
  const { value } = props;
92
- const current = value == null ? false : triggerValue === value;
109
+ const triggerState = getTriggerState(props);
110
+ const { current } = triggerState;
93
111
  return normalize.button({
94
- ...import_popover.parts.trigger.attrs,
112
+ ...import_popover.parts.trigger.attrs(scope.id),
95
113
  dir: prop("dir"),
96
114
  type: "button",
97
115
  "data-placement": currentPlacement,
98
116
  "data-side": currentPlacementSide,
99
- id: dom.getTriggerId(scope, value),
100
- "data-ownedby": scope.id,
101
117
  "data-value": value,
102
118
  "data-current": (0, import_dom_query.dataAttr)(current),
103
119
  "aria-haspopup": "dialog",
104
- "aria-expanded": value == null ? open : open && current,
120
+ "aria-expanded": triggerState.open,
105
121
  "data-state": open ? "open" : "closed",
106
122
  "aria-controls": dom.getContentId(scope),
107
123
  onPointerDown(event) {
@@ -122,55 +138,62 @@ function connect(service, normalize) {
122
138
  },
123
139
  getIndicatorProps() {
124
140
  return normalize.element({
125
- ...import_popover.parts.indicator.attrs,
141
+ ...import_popover.parts.indicator.attrs(scope.id),
126
142
  dir: prop("dir"),
127
143
  "data-state": open ? "open" : "closed"
128
144
  });
129
145
  },
146
+ getPositionerState,
130
147
  getPositionerProps() {
131
148
  return normalize.element({
132
- id: dom.getPositionerId(scope),
133
- ...import_popover.parts.positioner.attrs,
149
+ ...import_popover.parts.positioner.attrs(scope.id),
134
150
  dir: prop("dir"),
135
- style: popperStyles.floating
151
+ ...(0, import_dismissable.getDismissableLayerAttrs)(layer),
152
+ style: {
153
+ ...popperStyles.floating,
154
+ ...(0, import_dismissable.getDismissableLayerStyle)(layer, { zIndex: true })
155
+ }
136
156
  });
137
157
  },
158
+ getContentState,
138
159
  getContentProps() {
160
+ const contentState = getContentState();
139
161
  return normalize.element({
140
- ...import_popover.parts.content.attrs,
162
+ ...import_popover.parts.content.attrs(scope.id),
141
163
  dir: prop("dir"),
142
164
  id: dom.getContentId(scope),
143
165
  tabIndex: -1,
144
166
  role: "dialog",
145
- "aria-modal": (0, import_dom_query.ariaAttr)(prop("modal")),
146
- hidden: !open,
147
- "data-state": open ? "open" : "closed",
148
- "data-expanded": (0, import_dom_query.dataAttr)(open),
167
+ "aria-modal": (0, import_dom_query.ariaAttr)(contentState.modal),
168
+ hidden: !contentState.open,
169
+ "data-state": contentState.open ? "open" : "closed",
170
+ "data-expanded": (0, import_dom_query.dataAttr)(contentState.open),
149
171
  "aria-labelledby": rendered.title ? dom.getTitleId(scope) : void 0,
150
172
  "aria-describedby": rendered.description ? dom.getDescriptionId(scope) : void 0,
151
- "data-placement": currentPlacement,
152
- "data-side": currentPlacementSide
173
+ "data-placement": contentState.placement,
174
+ "data-side": contentState.side,
175
+ ...(0, import_dismissable.getDismissableLayerAttrs)(layer),
176
+ style: (0, import_dismissable.getDismissableLayerStyle)(layer, { pointerEvents: true })
153
177
  });
154
178
  },
155
179
  getTitleProps() {
156
180
  return normalize.element({
157
- ...import_popover.parts.title.attrs,
181
+ ...import_popover.parts.title.attrs(scope.id),
158
182
  id: dom.getTitleId(scope),
159
183
  dir: prop("dir")
160
184
  });
161
185
  },
162
186
  getDescriptionProps() {
163
187
  return normalize.element({
164
- ...import_popover.parts.description.attrs,
188
+ ...import_popover.parts.description.attrs(scope.id),
165
189
  id: dom.getDescriptionId(scope),
166
190
  dir: prop("dir")
167
191
  });
168
192
  },
169
193
  getCloseTriggerProps() {
170
194
  return normalize.button({
171
- ...import_popover.parts.closeTrigger.attrs,
195
+ ...import_popover.parts.closeTrigger.attrs(scope.id),
172
196
  dir: prop("dir"),
173
- id: dom.getCloseTriggerId(scope),
174
197
  type: "button",
175
198
  "aria-label": translations.closeTriggerLabel,
176
199
  onClick(event) {
@@ -1,23 +1,41 @@
1
1
  // src/popover.connect.ts
2
+ import { getDismissableLayerAttrs, getDismissableLayerStyle } from "@zag-js/dismissable";
2
3
  import { ariaAttr, dataAttr, isLeftClick, isSafari } from "@zag-js/dom-query";
3
4
  import { getPlacementSide, getPlacementStyles } from "@zag-js/popper";
4
5
  import { parts } from "./popover.anatomy.mjs";
5
6
  import * as dom from "./popover.dom.mjs";
6
7
  function connect(service, normalize) {
7
- const { state, context, send, computed, prop, scope } = service;
8
+ const { state, context, send, prop, scope } = service;
9
+ const layer = context.get("layer");
8
10
  const translations = prop("translations");
9
11
  const open = state.matches("open");
10
12
  const currentPlacement = context.get("currentPlacement");
11
13
  const currentPlacementSide = currentPlacement ? getPlacementSide(currentPlacement) : void 0;
12
- const portalled = computed("currentPortalled");
13
14
  const rendered = context.get("renderedElements");
14
15
  const triggerValue = context.get("triggerValue");
15
16
  const popperStyles = getPlacementStyles({
16
17
  ...prop("positioning"),
17
18
  placement: currentPlacement
18
19
  });
20
+ function getTriggerState(props = {}) {
21
+ const { value } = props;
22
+ const current = value == null ? false : triggerValue === value;
23
+ return { value, current, open: value == null ? open : open && current };
24
+ }
25
+ function getPositionerState() {
26
+ return { nested: !!layer?.nested, hasNested: !!layer?.hasNested };
27
+ }
28
+ function getContentState() {
29
+ return {
30
+ open,
31
+ modal: !!prop("modal"),
32
+ nested: !!layer?.nested,
33
+ hasNested: !!layer?.hasNested,
34
+ placement: currentPlacement,
35
+ side: currentPlacementSide
36
+ };
37
+ }
19
38
  return {
20
- portalled,
21
39
  open,
22
40
  setOpen(nextOpen) {
23
41
  const open2 = state.matches("open");
@@ -33,41 +51,39 @@ function connect(service, normalize) {
33
51
  },
34
52
  getArrowProps() {
35
53
  return normalize.element({
36
- id: dom.getArrowId(scope),
37
- ...parts.arrow.attrs,
54
+ ...parts.arrow.attrs(scope.id),
38
55
  dir: prop("dir"),
39
56
  style: popperStyles.arrow
40
57
  });
41
58
  },
42
59
  getArrowTipProps() {
43
60
  return normalize.element({
44
- ...parts.arrowTip.attrs,
61
+ ...parts.arrowTip.attrs(scope.id),
45
62
  dir: prop("dir"),
46
63
  style: popperStyles.arrowTip
47
64
  });
48
65
  },
49
66
  getAnchorProps() {
50
67
  return normalize.element({
51
- ...parts.anchor.attrs,
52
- dir: prop("dir"),
53
- id: dom.getAnchorId(scope)
68
+ ...parts.anchor.attrs(scope.id),
69
+ dir: prop("dir")
54
70
  });
55
71
  },
72
+ getTriggerState,
56
73
  getTriggerProps(props = {}) {
57
74
  const { value } = props;
58
- const current = value == null ? false : triggerValue === value;
75
+ const triggerState = getTriggerState(props);
76
+ const { current } = triggerState;
59
77
  return normalize.button({
60
- ...parts.trigger.attrs,
78
+ ...parts.trigger.attrs(scope.id),
61
79
  dir: prop("dir"),
62
80
  type: "button",
63
81
  "data-placement": currentPlacement,
64
82
  "data-side": currentPlacementSide,
65
- id: dom.getTriggerId(scope, value),
66
- "data-ownedby": scope.id,
67
83
  "data-value": value,
68
84
  "data-current": dataAttr(current),
69
85
  "aria-haspopup": "dialog",
70
- "aria-expanded": value == null ? open : open && current,
86
+ "aria-expanded": triggerState.open,
71
87
  "data-state": open ? "open" : "closed",
72
88
  "aria-controls": dom.getContentId(scope),
73
89
  onPointerDown(event) {
@@ -88,55 +104,62 @@ function connect(service, normalize) {
88
104
  },
89
105
  getIndicatorProps() {
90
106
  return normalize.element({
91
- ...parts.indicator.attrs,
107
+ ...parts.indicator.attrs(scope.id),
92
108
  dir: prop("dir"),
93
109
  "data-state": open ? "open" : "closed"
94
110
  });
95
111
  },
112
+ getPositionerState,
96
113
  getPositionerProps() {
97
114
  return normalize.element({
98
- id: dom.getPositionerId(scope),
99
- ...parts.positioner.attrs,
115
+ ...parts.positioner.attrs(scope.id),
100
116
  dir: prop("dir"),
101
- style: popperStyles.floating
117
+ ...getDismissableLayerAttrs(layer),
118
+ style: {
119
+ ...popperStyles.floating,
120
+ ...getDismissableLayerStyle(layer, { zIndex: true })
121
+ }
102
122
  });
103
123
  },
124
+ getContentState,
104
125
  getContentProps() {
126
+ const contentState = getContentState();
105
127
  return normalize.element({
106
- ...parts.content.attrs,
128
+ ...parts.content.attrs(scope.id),
107
129
  dir: prop("dir"),
108
130
  id: dom.getContentId(scope),
109
131
  tabIndex: -1,
110
132
  role: "dialog",
111
- "aria-modal": ariaAttr(prop("modal")),
112
- hidden: !open,
113
- "data-state": open ? "open" : "closed",
114
- "data-expanded": dataAttr(open),
133
+ "aria-modal": ariaAttr(contentState.modal),
134
+ hidden: !contentState.open,
135
+ "data-state": contentState.open ? "open" : "closed",
136
+ "data-expanded": dataAttr(contentState.open),
115
137
  "aria-labelledby": rendered.title ? dom.getTitleId(scope) : void 0,
116
138
  "aria-describedby": rendered.description ? dom.getDescriptionId(scope) : void 0,
117
- "data-placement": currentPlacement,
118
- "data-side": currentPlacementSide
139
+ "data-placement": contentState.placement,
140
+ "data-side": contentState.side,
141
+ ...getDismissableLayerAttrs(layer),
142
+ style: getDismissableLayerStyle(layer, { pointerEvents: true })
119
143
  });
120
144
  },
121
145
  getTitleProps() {
122
146
  return normalize.element({
123
- ...parts.title.attrs,
147
+ ...parts.title.attrs(scope.id),
124
148
  id: dom.getTitleId(scope),
125
149
  dir: prop("dir")
126
150
  });
127
151
  },
128
152
  getDescriptionProps() {
129
153
  return normalize.element({
130
- ...parts.description.attrs,
154
+ ...parts.description.attrs(scope.id),
131
155
  id: dom.getDescriptionId(scope),
132
156
  dir: prop("dir")
133
157
  });
134
158
  },
135
159
  getCloseTriggerProps() {
136
160
  return normalize.button({
137
- ...parts.closeTrigger.attrs,
161
+ ...parts.closeTrigger.attrs(scope.id),
138
162
  dir: prop("dir"),
139
- id: dom.getCloseTriggerId(scope),
140
163
  type: "button",
141
164
  "aria-label": translations.closeTriggerLabel,
142
165
  onClick(event) {
@@ -9,7 +9,6 @@ declare const getTitleId: (scope: Scope) => any;
9
9
  declare const getDescriptionId: (scope: Scope) => any;
10
10
  declare const getCloseTriggerId: (scope: Scope) => any;
11
11
  declare const getAnchorEl: (scope: Scope) => HTMLElement | null;
12
- declare const getTriggerEl: (scope: Scope) => HTMLElement | null;
13
12
  declare const getTriggerEls: (scope: Scope) => HTMLElement[];
14
13
  declare const getActiveTriggerEl: (scope: Scope, value: string | null) => HTMLElement | null;
15
14
  declare const getContentEl: (scope: Scope) => HTMLElement | null;
@@ -19,4 +18,4 @@ declare const getDescriptionEl: (scope: Scope) => HTMLElement | null;
19
18
  declare const getFocusableEls: (scope: Scope) => HTMLElement[];
20
19
  declare const getFirstFocusableEl: (scope: Scope) => HTMLElement;
21
20
 
22
- export { getActiveTriggerEl, getAnchorEl, getAnchorId, getArrowId, getCloseTriggerId, getContentEl, getContentId, getDescriptionEl, getDescriptionId, getFirstFocusableEl, getFocusableEls, getPositionerEl, getPositionerId, getTitleEl, getTitleId, getTriggerEl, getTriggerEls, getTriggerId };
21
+ export { getActiveTriggerEl, getAnchorEl, getAnchorId, getArrowId, getCloseTriggerId, getContentEl, getContentId, getDescriptionEl, getDescriptionId, getFirstFocusableEl, getFocusableEls, getPositionerEl, getPositionerId, getTitleEl, getTitleId, getTriggerEls, getTriggerId };
@@ -9,7 +9,6 @@ declare const getTitleId: (scope: Scope) => any;
9
9
  declare const getDescriptionId: (scope: Scope) => any;
10
10
  declare const getCloseTriggerId: (scope: Scope) => any;
11
11
  declare const getAnchorEl: (scope: Scope) => HTMLElement | null;
12
- declare const getTriggerEl: (scope: Scope) => HTMLElement | null;
13
12
  declare const getTriggerEls: (scope: Scope) => HTMLElement[];
14
13
  declare const getActiveTriggerEl: (scope: Scope, value: string | null) => HTMLElement | null;
15
14
  declare const getContentEl: (scope: Scope) => HTMLElement | null;
@@ -19,4 +18,4 @@ declare const getDescriptionEl: (scope: Scope) => HTMLElement | null;
19
18
  declare const getFocusableEls: (scope: Scope) => HTMLElement[];
20
19
  declare const getFirstFocusableEl: (scope: Scope) => HTMLElement;
21
20
 
22
- export { getActiveTriggerEl, getAnchorEl, getAnchorId, getArrowId, getCloseTriggerId, getContentEl, getContentId, getDescriptionEl, getDescriptionId, getFirstFocusableEl, getFocusableEls, getPositionerEl, getPositionerId, getTitleEl, getTitleId, getTriggerEl, getTriggerEls, getTriggerId };
21
+ export { getActiveTriggerEl, getAnchorEl, getAnchorId, getArrowId, getCloseTriggerId, getContentEl, getContentId, getDescriptionEl, getDescriptionId, getFirstFocusableEl, getFocusableEls, getPositionerEl, getPositionerId, getTitleEl, getTitleId, getTriggerEls, getTriggerId };
@@ -35,38 +35,35 @@ __export(popover_dom_exports, {
35
35
  getPositionerId: () => getPositionerId,
36
36
  getTitleEl: () => getTitleEl,
37
37
  getTitleId: () => getTitleId,
38
- getTriggerEl: () => getTriggerEl,
39
38
  getTriggerEls: () => getTriggerEls,
40
39
  getTriggerId: () => getTriggerId
41
40
  });
42
41
  module.exports = __toCommonJS(popover_dom_exports);
43
42
  var import_dom_query = require("@zag-js/dom-query");
44
43
  var import_utils = require("@zag-js/utils");
45
- var getAnchorId = (scope) => scope.ids?.anchor ?? `popover:${scope.id}:anchor`;
44
+ var import_popover = require("./popover.anatomy.js");
45
+ var getAnchorId = (scope) => scope.ids?.anchor ?? `${scope.id}:anchor`;
46
46
  var getTriggerId = (scope, value) => {
47
47
  const customId = scope.ids?.trigger;
48
48
  if (customId != null) return (0, import_utils.isFunction)(customId) ? customId(value) : customId;
49
- return value ? `popover:${scope.id}:trigger:${value}` : `popover:${scope.id}:trigger`;
49
+ return value ? `${scope.id}:trigger:${value}` : `${scope.id}:trigger`;
50
50
  };
51
- var getContentId = (scope) => scope.ids?.content ?? `popover:${scope.id}:content`;
52
- var getPositionerId = (scope) => scope.ids?.positioner ?? `popover:${scope.id}:popper`;
53
- var getArrowId = (scope) => scope.ids?.arrow ?? `popover:${scope.id}:arrow`;
54
- var getTitleId = (scope) => scope.ids?.title ?? `popover:${scope.id}:title`;
55
- var getDescriptionId = (scope) => scope.ids?.description ?? `popover:${scope.id}:desc`;
56
- var getCloseTriggerId = (scope) => scope.ids?.closeTrigger ?? `popover:${scope.id}:close`;
57
- var getAnchorEl = (scope) => scope.getById(getAnchorId(scope));
58
- var getTriggerEl = (scope) => scope.getById(getTriggerId(scope));
59
- var getTriggerEls = (scope) => (0, import_dom_query.queryAll)(scope.getRootNode(), `[data-scope="popover"][data-part="trigger"]${(0, import_dom_query.getByOwnerId)(scope.id)}`);
51
+ var getContentId = (scope) => scope.ids?.content ?? `${scope.id}:content`;
52
+ var getPositionerId = (scope) => scope.ids?.positioner ?? `${scope.id}:positioner`;
53
+ var getArrowId = (scope) => scope.ids?.arrow ?? `${scope.id}:arrow`;
54
+ var getTitleId = (scope) => scope.ids?.title ?? `${scope.id}:title`;
55
+ var getDescriptionId = (scope) => scope.ids?.description ?? `${scope.id}:desc`;
56
+ var getCloseTriggerId = (scope) => scope.ids?.closeTrigger ?? `${scope.id}:close`;
57
+ var getAnchorEl = (scope) => scope.query(scope.selector(import_popover.parts.anchor));
58
+ var getTriggerEls = (scope) => scope.queryAll(scope.selector(import_popover.parts.trigger));
60
59
  var getActiveTriggerEl = (scope, value) => {
61
- if (value == null) {
62
- return getTriggerEl(scope) ?? getTriggerEls(scope)[0];
63
- }
64
- return scope.getById(getTriggerId(scope, value));
60
+ if (value == null) return getTriggerEls(scope)[0];
61
+ return scope.query(`${scope.selector(import_popover.parts.trigger)}[data-value="${value}"]`);
65
62
  };
66
- var getContentEl = (scope) => scope.getById(getContentId(scope));
67
- var getPositionerEl = (scope) => scope.getById(getPositionerId(scope));
68
- var getTitleEl = (scope) => scope.getById(getTitleId(scope));
69
- var getDescriptionEl = (scope) => scope.getById(getDescriptionId(scope));
63
+ var getContentEl = (scope) => scope.query(scope.selector(import_popover.parts.content));
64
+ var getPositionerEl = (scope) => scope.query(scope.selector(import_popover.parts.positioner));
65
+ var getTitleEl = (scope) => scope.query(scope.selector(import_popover.parts.title));
66
+ var getDescriptionEl = (scope) => scope.query(scope.selector(import_popover.parts.description));
70
67
  var getFocusableEls = (scope) => (0, import_dom_query.getFocusables)(getContentEl(scope));
71
68
  var getFirstFocusableEl = (scope) => getFocusableEls(scope)[0];
72
69
  // Annotate the CommonJS export names for ESM import in node:
@@ -86,7 +83,6 @@ var getFirstFocusableEl = (scope) => getFocusableEls(scope)[0];
86
83
  getPositionerId,
87
84
  getTitleEl,
88
85
  getTitleId,
89
- getTriggerEl,
90
86
  getTriggerEls,
91
87
  getTriggerId
92
88
  });
@@ -1,31 +1,29 @@
1
1
  // src/popover.dom.ts
2
- import { getByOwnerId, getFocusables, queryAll } from "@zag-js/dom-query";
2
+ import { getFocusables } from "@zag-js/dom-query";
3
3
  import { isFunction } from "@zag-js/utils";
4
- var getAnchorId = (scope) => scope.ids?.anchor ?? `popover:${scope.id}:anchor`;
4
+ import { parts } from "./popover.anatomy.mjs";
5
+ var getAnchorId = (scope) => scope.ids?.anchor ?? `${scope.id}:anchor`;
5
6
  var getTriggerId = (scope, value) => {
6
7
  const customId = scope.ids?.trigger;
7
8
  if (customId != null) return isFunction(customId) ? customId(value) : customId;
8
- return value ? `popover:${scope.id}:trigger:${value}` : `popover:${scope.id}:trigger`;
9
+ return value ? `${scope.id}:trigger:${value}` : `${scope.id}:trigger`;
9
10
  };
10
- var getContentId = (scope) => scope.ids?.content ?? `popover:${scope.id}:content`;
11
- var getPositionerId = (scope) => scope.ids?.positioner ?? `popover:${scope.id}:popper`;
12
- var getArrowId = (scope) => scope.ids?.arrow ?? `popover:${scope.id}:arrow`;
13
- var getTitleId = (scope) => scope.ids?.title ?? `popover:${scope.id}:title`;
14
- var getDescriptionId = (scope) => scope.ids?.description ?? `popover:${scope.id}:desc`;
15
- var getCloseTriggerId = (scope) => scope.ids?.closeTrigger ?? `popover:${scope.id}:close`;
16
- var getAnchorEl = (scope) => scope.getById(getAnchorId(scope));
17
- var getTriggerEl = (scope) => scope.getById(getTriggerId(scope));
18
- var getTriggerEls = (scope) => queryAll(scope.getRootNode(), `[data-scope="popover"][data-part="trigger"]${getByOwnerId(scope.id)}`);
11
+ var getContentId = (scope) => scope.ids?.content ?? `${scope.id}:content`;
12
+ var getPositionerId = (scope) => scope.ids?.positioner ?? `${scope.id}:positioner`;
13
+ var getArrowId = (scope) => scope.ids?.arrow ?? `${scope.id}:arrow`;
14
+ var getTitleId = (scope) => scope.ids?.title ?? `${scope.id}:title`;
15
+ var getDescriptionId = (scope) => scope.ids?.description ?? `${scope.id}:desc`;
16
+ var getCloseTriggerId = (scope) => scope.ids?.closeTrigger ?? `${scope.id}:close`;
17
+ var getAnchorEl = (scope) => scope.query(scope.selector(parts.anchor));
18
+ var getTriggerEls = (scope) => scope.queryAll(scope.selector(parts.trigger));
19
19
  var getActiveTriggerEl = (scope, value) => {
20
- if (value == null) {
21
- return getTriggerEl(scope) ?? getTriggerEls(scope)[0];
22
- }
23
- return scope.getById(getTriggerId(scope, value));
20
+ if (value == null) return getTriggerEls(scope)[0];
21
+ return scope.query(`${scope.selector(parts.trigger)}[data-value="${value}"]`);
24
22
  };
25
- var getContentEl = (scope) => scope.getById(getContentId(scope));
26
- var getPositionerEl = (scope) => scope.getById(getPositionerId(scope));
27
- var getTitleEl = (scope) => scope.getById(getTitleId(scope));
28
- var getDescriptionEl = (scope) => scope.getById(getDescriptionId(scope));
23
+ var getContentEl = (scope) => scope.query(scope.selector(parts.content));
24
+ var getPositionerEl = (scope) => scope.query(scope.selector(parts.positioner));
25
+ var getTitleEl = (scope) => scope.query(scope.selector(parts.title));
26
+ var getDescriptionEl = (scope) => scope.query(scope.selector(parts.description));
29
27
  var getFocusableEls = (scope) => getFocusables(getContentEl(scope));
30
28
  var getFirstFocusableEl = (scope) => getFocusableEls(scope)[0];
31
29
  export {
@@ -44,7 +42,6 @@ export {
44
42
  getPositionerId,
45
43
  getTitleEl,
46
44
  getTitleId,
47
- getTriggerEl,
48
45
  getTriggerEls,
49
46
  getTriggerId
50
47
  };
@@ -48,7 +48,6 @@ var machine = (0, import_core.createMachine)({
48
48
  closeOnEscape: true,
49
49
  autoFocus: true,
50
50
  modal: false,
51
- portalled: true,
52
51
  restoreFocus: true,
53
52
  ...props,
54
53
  translations: {
@@ -67,6 +66,9 @@ var machine = (0, import_core.createMachine)({
67
66
  },
68
67
  context({ bindable, prop, scope }) {
69
68
  return {
69
+ layer: bindable(() => ({
70
+ defaultValue: null
71
+ })),
70
72
  currentPlacement: bindable(() => ({
71
73
  defaultValue: void 0
72
74
  })),
@@ -85,9 +87,6 @@ var machine = (0, import_core.createMachine)({
85
87
  }))
86
88
  };
87
89
  },
88
- computed: {
89
- currentPortalled: ({ prop }) => !!prop("modal") || !!prop("portalled")
90
- },
91
90
  watch({ track, prop, action }) {
92
91
  track([() => prop("open")], () => {
93
92
  action(["toggleVisibility"]);
@@ -177,8 +176,8 @@ var machine = (0, import_core.createMachine)({
177
176
  context.set("currentPlacement", prop("positioning").placement);
178
177
  const anchorEl = dom.getAnchorEl(scope);
179
178
  const getPositionerEl2 = () => dom.getPositionerEl(scope);
180
- const getTriggerEl2 = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
181
- return (0, import_popper.getPlacement)(getTriggerEl2, getPositionerEl2, {
179
+ const getTriggerEl = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
180
+ return (0, import_popper.getPlacement)(getTriggerEl, getPositionerEl2, {
182
181
  ...prop("positioning"),
183
182
  defer: true,
184
183
  onComplete(data) {
@@ -186,13 +185,16 @@ var machine = (0, import_core.createMachine)({
186
185
  }
187
186
  });
188
187
  },
189
- trackDismissableElement({ send, prop, scope }) {
188
+ trackDismissableElement({ send, prop, scope, context }) {
190
189
  const getContentEl2 = () => dom.getContentEl(scope);
191
190
  let restoreFocus = true;
192
191
  return (0, import_dismissable.trackDismissableElement)(getContentEl2, {
193
192
  type: "popover",
194
193
  pointerBlocking: prop("modal"),
195
- exclude: [dom.getTriggerEl(scope), ...dom.getTriggerEls(scope)].filter(Boolean),
194
+ onLayerChange(layer) {
195
+ context.set("layer", layer);
196
+ },
197
+ exclude: dom.getTriggerEls(scope),
196
198
  defer: true,
197
199
  onEscapeKeyDown(event) {
198
200
  prop("onEscapeKeyDown")?.(event);
@@ -217,16 +219,25 @@ var machine = (0, import_core.createMachine)({
217
219
  });
218
220
  },
219
221
  proxyTabFocus({ prop, scope, context }) {
220
- if (prop("modal") || !prop("portalled")) return;
222
+ if (prop("modal")) return;
221
223
  const getContentEl2 = () => dom.getContentEl(scope);
222
- return (0, import_dom_query.proxyTabFocus)(getContentEl2, {
223
- triggerElement: dom.getActiveTriggerEl(scope, context.get("triggerValue")),
224
- defer: true,
225
- getShadowRoot: true,
226
- onFocus(el) {
227
- el.focus({ preventScroll: true });
228
- }
224
+ let cleanup;
225
+ const rafCleanup = (0, import_dom_query.raf)(() => {
226
+ const triggerEl = dom.getActiveTriggerEl(scope, context.get("triggerValue"));
227
+ const contentEl = getContentEl2();
228
+ if (!triggerEl || !contentEl || (0, import_dom_query.contains)(triggerEl.parentElement, contentEl)) return;
229
+ cleanup = (0, import_dom_query.proxyTabFocus)(getContentEl2, {
230
+ triggerElement: triggerEl,
231
+ getShadowRoot: true,
232
+ onFocus(el) {
233
+ el.focus({ preventScroll: true });
234
+ }
235
+ });
229
236
  });
237
+ return () => {
238
+ rafCleanup();
239
+ cleanup?.();
240
+ };
230
241
  },
231
242
  hideContentBelow({ prop, scope, context }) {
232
243
  if (!prop("modal")) return;
@@ -268,8 +279,8 @@ var machine = (0, import_core.createMachine)({
268
279
  reposition({ event, prop, scope, context }) {
269
280
  const anchorEl = dom.getAnchorEl(scope);
270
281
  const getPositionerEl2 = () => dom.getPositionerEl(scope);
271
- const getTriggerEl2 = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
272
- (0, import_popper.getPlacement)(getTriggerEl2, getPositionerEl2, {
282
+ const getTriggerEl = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
283
+ (0, import_popper.getPlacement)(getTriggerEl, getPositionerEl2, {
273
284
  ...prop("positioning"),
274
285
  ...event.options,
275
286
  defer: true,
@@ -2,7 +2,7 @@
2
2
  import { ariaHidden } from "@zag-js/aria-hidden";
3
3
  import { createMachine } from "@zag-js/core";
4
4
  import { trackDismissableElement } from "@zag-js/dismissable";
5
- import { getInitialFocus, proxyTabFocus, raf } from "@zag-js/dom-query";
5
+ import { contains, getInitialFocus, proxyTabFocus, raf } from "@zag-js/dom-query";
6
6
  import { trapFocus } from "@zag-js/focus-trap";
7
7
  import { getPlacement } from "@zag-js/popper";
8
8
  import { preventBodyScroll } from "@zag-js/remove-scroll";
@@ -14,7 +14,6 @@ var machine = createMachine({
14
14
  closeOnEscape: true,
15
15
  autoFocus: true,
16
16
  modal: false,
17
- portalled: true,
18
17
  restoreFocus: true,
19
18
  ...props,
20
19
  translations: {
@@ -33,6 +32,9 @@ var machine = createMachine({
33
32
  },
34
33
  context({ bindable, prop, scope }) {
35
34
  return {
35
+ layer: bindable(() => ({
36
+ defaultValue: null
37
+ })),
36
38
  currentPlacement: bindable(() => ({
37
39
  defaultValue: void 0
38
40
  })),
@@ -51,9 +53,6 @@ var machine = createMachine({
51
53
  }))
52
54
  };
53
55
  },
54
- computed: {
55
- currentPortalled: ({ prop }) => !!prop("modal") || !!prop("portalled")
56
- },
57
56
  watch({ track, prop, action }) {
58
57
  track([() => prop("open")], () => {
59
58
  action(["toggleVisibility"]);
@@ -143,8 +142,8 @@ var machine = createMachine({
143
142
  context.set("currentPlacement", prop("positioning").placement);
144
143
  const anchorEl = dom.getAnchorEl(scope);
145
144
  const getPositionerEl2 = () => dom.getPositionerEl(scope);
146
- const getTriggerEl2 = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
147
- return getPlacement(getTriggerEl2, getPositionerEl2, {
145
+ const getTriggerEl = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
146
+ return getPlacement(getTriggerEl, getPositionerEl2, {
148
147
  ...prop("positioning"),
149
148
  defer: true,
150
149
  onComplete(data) {
@@ -152,13 +151,16 @@ var machine = createMachine({
152
151
  }
153
152
  });
154
153
  },
155
- trackDismissableElement({ send, prop, scope }) {
154
+ trackDismissableElement({ send, prop, scope, context }) {
156
155
  const getContentEl2 = () => dom.getContentEl(scope);
157
156
  let restoreFocus = true;
158
157
  return trackDismissableElement(getContentEl2, {
159
158
  type: "popover",
160
159
  pointerBlocking: prop("modal"),
161
- exclude: [dom.getTriggerEl(scope), ...dom.getTriggerEls(scope)].filter(Boolean),
160
+ onLayerChange(layer) {
161
+ context.set("layer", layer);
162
+ },
163
+ exclude: dom.getTriggerEls(scope),
162
164
  defer: true,
163
165
  onEscapeKeyDown(event) {
164
166
  prop("onEscapeKeyDown")?.(event);
@@ -183,16 +185,25 @@ var machine = createMachine({
183
185
  });
184
186
  },
185
187
  proxyTabFocus({ prop, scope, context }) {
186
- if (prop("modal") || !prop("portalled")) return;
188
+ if (prop("modal")) return;
187
189
  const getContentEl2 = () => dom.getContentEl(scope);
188
- return proxyTabFocus(getContentEl2, {
189
- triggerElement: dom.getActiveTriggerEl(scope, context.get("triggerValue")),
190
- defer: true,
191
- getShadowRoot: true,
192
- onFocus(el) {
193
- el.focus({ preventScroll: true });
194
- }
190
+ let cleanup;
191
+ const rafCleanup = raf(() => {
192
+ const triggerEl = dom.getActiveTriggerEl(scope, context.get("triggerValue"));
193
+ const contentEl = getContentEl2();
194
+ if (!triggerEl || !contentEl || contains(triggerEl.parentElement, contentEl)) return;
195
+ cleanup = proxyTabFocus(getContentEl2, {
196
+ triggerElement: triggerEl,
197
+ getShadowRoot: true,
198
+ onFocus(el) {
199
+ el.focus({ preventScroll: true });
200
+ }
201
+ });
195
202
  });
203
+ return () => {
204
+ rafCleanup();
205
+ cleanup?.();
206
+ };
196
207
  },
197
208
  hideContentBelow({ prop, scope, context }) {
198
209
  if (!prop("modal")) return;
@@ -234,8 +245,8 @@ var machine = createMachine({
234
245
  reposition({ event, prop, scope, context }) {
235
246
  const anchorEl = dom.getAnchorEl(scope);
236
247
  const getPositionerEl2 = () => dom.getPositionerEl(scope);
237
- const getTriggerEl2 = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
238
- getPlacement(getTriggerEl2, getPositionerEl2, {
248
+ const getTriggerEl = () => anchorEl ?? dom.getActiveTriggerEl(scope, context.get("triggerValue"));
249
+ getPlacement(getTriggerEl, getPositionerEl2, {
239
250
  ...prop("positioning"),
240
251
  ...event.options,
241
252
  defer: true,
@@ -48,7 +48,6 @@ var props = (0, import_types.createProps)()([
48
48
  "onRequestDismiss",
49
49
  "open",
50
50
  "persistentElements",
51
- "portalled",
52
51
  "restoreFocus",
53
52
  "positioning",
54
53
  "translations",
@@ -23,7 +23,6 @@ var props = createProps()([
23
23
  "onRequestDismiss",
24
24
  "open",
25
25
  "persistentElements",
26
- "portalled",
27
26
  "restoreFocus",
28
27
  "positioning",
29
28
  "translations",
@@ -1,6 +1,6 @@
1
1
  import { Machine, EventObject, Service } from '@zag-js/core';
2
- import { DismissableElementHandlers, PersistentElementOptions } from '@zag-js/dismissable';
3
- import { PositioningOptions, Placement } from '@zag-js/popper';
2
+ import { DismissableElementHandlers, PersistentElementOptions, LayerSnapshot } from '@zag-js/dismissable';
3
+ import { PositioningOptions, Placement, PlacementSide } from '@zag-js/popper';
4
4
  export { Placement, PositioningOptions } from '@zag-js/popper';
5
5
  import { PropTypes, RequiredBy, CommonProperties, DirectionProperty, MaybeElement } from '@zag-js/types';
6
6
 
@@ -49,13 +49,6 @@ interface PopoverProps extends CommonProperties, DirectionProperty, DismissableE
49
49
  * @default false
50
50
  */
51
51
  modal?: boolean | undefined;
52
- /**
53
- * Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
54
- * of the popover content.
55
- *
56
- * @default true
57
- */
58
- portalled?: boolean | undefined;
59
52
  /**
60
53
  * Whether to automatically set focus on the first focusable
61
54
  * content within the popover when opened.
@@ -118,14 +111,12 @@ interface PopoverProps extends CommonProperties, DirectionProperty, DismissableE
118
111
  */
119
112
  onTriggerValueChange?: ((details: TriggerValueChangeDetails) => void) | undefined;
120
113
  }
121
- type PropsWithDefault = "closeOnInteractOutside" | "closeOnEscape" | "modal" | "portalled" | "autoFocus" | "restoreFocus" | "positioning" | "translations";
122
- type ComputedContext = Readonly<{
114
+ type PropsWithDefault = "closeOnInteractOutside" | "closeOnEscape" | "modal" | "autoFocus" | "restoreFocus" | "positioning" | "translations";
115
+ interface PrivateContext {
123
116
  /**
124
- * The computed value of `portalled`
117
+ * The computed layer stack state used for declarative styles and attributes.
125
118
  */
126
- currentPortalled: boolean;
127
- }>;
128
- interface PrivateContext {
119
+ layer: LayerSnapshot | null;
129
120
  /**
130
121
  * The elements that are rendered on mount
131
122
  */
@@ -146,7 +137,7 @@ interface PopoverSchema {
146
137
  props: RequiredBy<PopoverProps, PropsWithDefault>;
147
138
  state: "open" | "closed";
148
139
  context: PrivateContext;
149
- computed: ComputedContext;
140
+ computed: {};
150
141
  event: EventObject;
151
142
  action: string;
152
143
  effect: string;
@@ -160,11 +151,57 @@ interface TriggerProps {
160
151
  */
161
152
  value?: string;
162
153
  }
163
- interface PopoverApi<T extends PropTypes = PropTypes> {
154
+ interface TriggerState {
155
+ /**
156
+ * The value that identifies this specific trigger
157
+ */
158
+ value: string | undefined;
164
159
  /**
165
- * Whether the popover is portalled.
160
+ * Whether this trigger is the one that opened the popover
166
161
  */
167
- portalled: boolean;
162
+ current: boolean;
163
+ /**
164
+ * Whether the popover is open
165
+ */
166
+ open: boolean;
167
+ }
168
+ interface PositionerState {
169
+ /**
170
+ * Whether the popover is nested within another layered element
171
+ */
172
+ nested: boolean;
173
+ /**
174
+ * Whether the popover has nested layered elements within it
175
+ */
176
+ hasNested: boolean;
177
+ }
178
+ interface ContentState {
179
+ /**
180
+ * Whether the popover is open
181
+ */
182
+ open: boolean;
183
+ /**
184
+ * Whether the popover is modal
185
+ */
186
+ modal: boolean;
187
+ /**
188
+ * Whether the popover is nested within another layered element
189
+ */
190
+ nested: boolean;
191
+ /**
192
+ * Whether the popover has nested layered elements within it
193
+ */
194
+ hasNested: boolean;
195
+ /**
196
+ * The current placement of the content relative to the trigger
197
+ */
198
+ placement: Placement | undefined;
199
+ /**
200
+ * The side of the trigger the content is placed on
201
+ */
202
+ side: PlacementSide | undefined;
203
+ }
204
+ interface PopoverApi<T extends PropTypes = PropTypes> {
168
205
  /**
169
206
  * Whether the popover is open
170
207
  */
@@ -188,13 +225,25 @@ interface PopoverApi<T extends PropTypes = PropTypes> {
188
225
  getArrowProps: () => T["element"];
189
226
  getArrowTipProps: () => T["element"];
190
227
  getAnchorProps: () => T["element"];
228
+ /**
229
+ * Returns the state of a specific trigger, including whether it's the currently active one
230
+ */
231
+ getTriggerState: (props?: TriggerProps) => TriggerState;
191
232
  getTriggerProps: (props?: TriggerProps) => T["button"];
192
233
  getIndicatorProps: () => T["element"];
234
+ /**
235
+ * Returns the state of the positioner
236
+ */
237
+ getPositionerState: () => PositionerState;
193
238
  getPositionerProps: () => T["element"];
239
+ /**
240
+ * Returns the state of the content
241
+ */
242
+ getContentState: () => ContentState;
194
243
  getContentProps: () => T["element"];
195
244
  getTitleProps: () => T["element"];
196
245
  getDescriptionProps: () => T["element"];
197
246
  getCloseTriggerProps: () => T["button"];
198
247
  }
199
248
 
200
- export type { ElementIds, IntlTranslations, OpenChangeDetails, PopoverApi, PopoverMachine, PopoverProps, PopoverSchema, PopoverService, TriggerProps, TriggerValueChangeDetails };
249
+ export type { ContentState, ElementIds, IntlTranslations, OpenChangeDetails, PopoverApi, PopoverMachine, PopoverProps, PopoverSchema, PopoverService, PositionerState, TriggerProps, TriggerState, TriggerValueChangeDetails };
@@ -1,6 +1,6 @@
1
1
  import { Machine, EventObject, Service } from '@zag-js/core';
2
- import { DismissableElementHandlers, PersistentElementOptions } from '@zag-js/dismissable';
3
- import { PositioningOptions, Placement } from '@zag-js/popper';
2
+ import { DismissableElementHandlers, PersistentElementOptions, LayerSnapshot } from '@zag-js/dismissable';
3
+ import { PositioningOptions, Placement, PlacementSide } from '@zag-js/popper';
4
4
  export { Placement, PositioningOptions } from '@zag-js/popper';
5
5
  import { PropTypes, RequiredBy, CommonProperties, DirectionProperty, MaybeElement } from '@zag-js/types';
6
6
 
@@ -49,13 +49,6 @@ interface PopoverProps extends CommonProperties, DirectionProperty, DismissableE
49
49
  * @default false
50
50
  */
51
51
  modal?: boolean | undefined;
52
- /**
53
- * Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
54
- * of the popover content.
55
- *
56
- * @default true
57
- */
58
- portalled?: boolean | undefined;
59
52
  /**
60
53
  * Whether to automatically set focus on the first focusable
61
54
  * content within the popover when opened.
@@ -118,14 +111,12 @@ interface PopoverProps extends CommonProperties, DirectionProperty, DismissableE
118
111
  */
119
112
  onTriggerValueChange?: ((details: TriggerValueChangeDetails) => void) | undefined;
120
113
  }
121
- type PropsWithDefault = "closeOnInteractOutside" | "closeOnEscape" | "modal" | "portalled" | "autoFocus" | "restoreFocus" | "positioning" | "translations";
122
- type ComputedContext = Readonly<{
114
+ type PropsWithDefault = "closeOnInteractOutside" | "closeOnEscape" | "modal" | "autoFocus" | "restoreFocus" | "positioning" | "translations";
115
+ interface PrivateContext {
123
116
  /**
124
- * The computed value of `portalled`
117
+ * The computed layer stack state used for declarative styles and attributes.
125
118
  */
126
- currentPortalled: boolean;
127
- }>;
128
- interface PrivateContext {
119
+ layer: LayerSnapshot | null;
129
120
  /**
130
121
  * The elements that are rendered on mount
131
122
  */
@@ -146,7 +137,7 @@ interface PopoverSchema {
146
137
  props: RequiredBy<PopoverProps, PropsWithDefault>;
147
138
  state: "open" | "closed";
148
139
  context: PrivateContext;
149
- computed: ComputedContext;
140
+ computed: {};
150
141
  event: EventObject;
151
142
  action: string;
152
143
  effect: string;
@@ -160,11 +151,57 @@ interface TriggerProps {
160
151
  */
161
152
  value?: string;
162
153
  }
163
- interface PopoverApi<T extends PropTypes = PropTypes> {
154
+ interface TriggerState {
155
+ /**
156
+ * The value that identifies this specific trigger
157
+ */
158
+ value: string | undefined;
164
159
  /**
165
- * Whether the popover is portalled.
160
+ * Whether this trigger is the one that opened the popover
166
161
  */
167
- portalled: boolean;
162
+ current: boolean;
163
+ /**
164
+ * Whether the popover is open
165
+ */
166
+ open: boolean;
167
+ }
168
+ interface PositionerState {
169
+ /**
170
+ * Whether the popover is nested within another layered element
171
+ */
172
+ nested: boolean;
173
+ /**
174
+ * Whether the popover has nested layered elements within it
175
+ */
176
+ hasNested: boolean;
177
+ }
178
+ interface ContentState {
179
+ /**
180
+ * Whether the popover is open
181
+ */
182
+ open: boolean;
183
+ /**
184
+ * Whether the popover is modal
185
+ */
186
+ modal: boolean;
187
+ /**
188
+ * Whether the popover is nested within another layered element
189
+ */
190
+ nested: boolean;
191
+ /**
192
+ * Whether the popover has nested layered elements within it
193
+ */
194
+ hasNested: boolean;
195
+ /**
196
+ * The current placement of the content relative to the trigger
197
+ */
198
+ placement: Placement | undefined;
199
+ /**
200
+ * The side of the trigger the content is placed on
201
+ */
202
+ side: PlacementSide | undefined;
203
+ }
204
+ interface PopoverApi<T extends PropTypes = PropTypes> {
168
205
  /**
169
206
  * Whether the popover is open
170
207
  */
@@ -188,13 +225,25 @@ interface PopoverApi<T extends PropTypes = PropTypes> {
188
225
  getArrowProps: () => T["element"];
189
226
  getArrowTipProps: () => T["element"];
190
227
  getAnchorProps: () => T["element"];
228
+ /**
229
+ * Returns the state of a specific trigger, including whether it's the currently active one
230
+ */
231
+ getTriggerState: (props?: TriggerProps) => TriggerState;
191
232
  getTriggerProps: (props?: TriggerProps) => T["button"];
192
233
  getIndicatorProps: () => T["element"];
234
+ /**
235
+ * Returns the state of the positioner
236
+ */
237
+ getPositionerState: () => PositionerState;
193
238
  getPositionerProps: () => T["element"];
239
+ /**
240
+ * Returns the state of the content
241
+ */
242
+ getContentState: () => ContentState;
194
243
  getContentProps: () => T["element"];
195
244
  getTitleProps: () => T["element"];
196
245
  getDescriptionProps: () => T["element"];
197
246
  getCloseTriggerProps: () => T["button"];
198
247
  }
199
248
 
200
- export type { ElementIds, IntlTranslations, OpenChangeDetails, PopoverApi, PopoverMachine, PopoverProps, PopoverSchema, PopoverService, TriggerProps, TriggerValueChangeDetails };
249
+ export type { ContentState, ElementIds, IntlTranslations, OpenChangeDetails, PopoverApi, PopoverMachine, PopoverProps, PopoverSchema, PopoverService, PositionerState, TriggerProps, TriggerState, TriggerValueChangeDetails };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/popover",
3
- "version": "1.43.0",
3
+ "version": "2.0.0-next.1",
4
4
  "description": "Core logic for the popover widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -29,16 +29,16 @@
29
29
  "url": "https://github.com/chakra-ui/zag/issues"
30
30
  },
31
31
  "dependencies": {
32
- "@zag-js/anatomy": "1.43.0",
33
- "@zag-js/aria-hidden": "1.43.0",
34
- "@zag-js/core": "1.43.0",
35
- "@zag-js/dom-query": "1.43.0",
36
- "@zag-js/utils": "1.43.0",
37
- "@zag-js/dismissable": "1.43.0",
38
- "@zag-js/popper": "1.43.0",
39
- "@zag-js/remove-scroll": "1.43.0",
40
- "@zag-js/types": "1.43.0",
41
- "@zag-js/focus-trap": "1.43.0"
32
+ "@zag-js/anatomy": "2.0.0-next.1",
33
+ "@zag-js/aria-hidden": "2.0.0-next.1",
34
+ "@zag-js/core": "2.0.0-next.1",
35
+ "@zag-js/dom-query": "2.0.0-next.1",
36
+ "@zag-js/utils": "2.0.0-next.1",
37
+ "@zag-js/dismissable": "2.0.0-next.1",
38
+ "@zag-js/popper": "2.0.0-next.1",
39
+ "@zag-js/remove-scroll": "2.0.0-next.1",
40
+ "@zag-js/types": "2.0.0-next.1",
41
+ "@zag-js/focus-trap": "2.0.0-next.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "clean-package": "2.2.0"