@duskmoon-dev/components 0.5.2 → 0.5.3

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,9 +1,11 @@
1
1
  "use client";
2
2
 
3
3
  // src/components/popconfirm/Popconfirm.tsx
4
- import {
4
+ import React2, {
5
5
  forwardRef,
6
6
  useId,
7
+ useLayoutEffect,
8
+ useRef,
7
9
  useState
8
10
  } from "react";
9
11
 
@@ -441,6 +443,27 @@ var Popconfirm = forwardRef(({
441
443
  const isControlled = open !== undefined;
442
444
  const visible = isControlled ? open : internalOpen;
443
445
  const popupId = id ? `${id}-popconfirm` : generatedPopupId;
446
+ const anchorName = `--dm-popconfirm-${generatedPopupId.replace(/[^a-zA-Z0-9_-]/g, "")}`;
447
+ const popupRef = useRef(null);
448
+ const desiredOpen = useRef(visible);
449
+ desiredOpen.current = visible;
450
+ const shouldRenderPopup = !destroyTooltipOnHide || visible;
451
+ useLayoutEffect(() => {
452
+ const popup = popupRef.current;
453
+ if (!popup || typeof popup.showPopover !== "function")
454
+ return;
455
+ if (visible && !popup.matches(":popover-open"))
456
+ popup.showPopover();
457
+ else if (!visible && popup.matches(":popover-open"))
458
+ popup.hidePopover();
459
+ }, [visible, shouldRenderPopup]);
460
+ useLayoutEffect(() => {
461
+ const popup = popupRef.current;
462
+ return () => {
463
+ if (popup?.matches(":popover-open"))
464
+ popup.hidePopover();
465
+ };
466
+ }, [shouldRenderPopup]);
444
467
  function setVisible(nextOpen) {
445
468
  if (disabled) {
446
469
  return;
@@ -467,6 +490,8 @@ var Popconfirm = forwardRef(({
467
490
  try {
468
491
  await result;
469
492
  close();
493
+ } catch {
494
+ return;
470
495
  } finally {
471
496
  if (loading) {
472
497
  setConfirmLoading(false);
@@ -486,6 +511,8 @@ var Popconfirm = forwardRef(({
486
511
  }
487
512
  }
488
513
  function handleClick(event) {
514
+ if (popupRef.current?.contains(event.target))
515
+ return;
489
516
  onClick?.(event);
490
517
  if (hasTrigger(trigger, "click")) {
491
518
  setVisible(!visible);
@@ -510,13 +537,12 @@ var Popconfirm = forwardRef(({
510
537
  setVisible(false);
511
538
  }
512
539
  }
513
- const shouldRenderPopup = !destroyTooltipOnHide || visible;
514
540
  return /* @__PURE__ */ jsxs2("span", {
515
541
  ...props,
516
542
  ref,
517
543
  className: popconfirmWrapperClass,
518
- "aria-describedby": visible ? popupId : undefined,
519
544
  "aria-expanded": visible || undefined,
545
+ style: { ...props.style, anchorName },
520
546
  onMouseEnter: handleMouseEnter,
521
547
  onMouseLeave: handleMouseLeave,
522
548
  onClick: handleClick,
@@ -524,10 +550,28 @@ var Popconfirm = forwardRef(({
524
550
  onFocus: handleFocus,
525
551
  onBlur: handleBlur,
526
552
  children: [
527
- children,
553
+ React2.isValidElement(children) && children.type !== React2.Fragment ? React2.cloneElement(children, { "aria-controls": popupId, "aria-expanded": Boolean(visible) }) : children,
528
554
  shouldRenderPopup ? /* @__PURE__ */ jsxs2("span", {
529
555
  id: popupId,
530
- role: "tooltip",
556
+ ref: popupRef,
557
+ popover: "auto",
558
+ style: { positionAnchor: anchorName },
559
+ onToggle: (event) => {
560
+ if (event.target !== event.currentTarget)
561
+ return;
562
+ const nextOpen = event.newState === "open";
563
+ if (nextOpen === visible)
564
+ return;
565
+ setVisible(nextOpen);
566
+ if (isControlled && visible && !nextOpen) {
567
+ const popup = event.currentTarget;
568
+ queueMicrotask(() => {
569
+ if (popup.isConnected && desiredOpen.current && !popup.matches(":popover-open")) {
570
+ popup.showPopover();
571
+ }
572
+ });
573
+ }
574
+ },
531
575
  className: getPopconfirmClasses({
532
576
  placement,
533
577
  open: visible,
@@ -159,10 +159,8 @@ var Popover = forwardRef(({
159
159
  event.preventDefault();
160
160
  }
161
161
  }
162
- const hasContent = Boolean(content || title);
163
162
  const shouldRenderContent = !destroyTooltipOnHide || visible;
164
163
  const triggerProps = {
165
- "aria-describedby": hasContent && visible ? tooltipId : undefined,
166
164
  onMouseEnter: triggerHandlers.onMouseEnter ? handleMouseEnter : undefined,
167
165
  onMouseLeave: triggerHandlers.onMouseLeave ? handleMouseLeave : undefined,
168
166
  onFocus: triggerHandlers.onFocus ? handleFocus : undefined,
@@ -171,7 +169,6 @@ var Popover = forwardRef(({
171
169
  onClick: triggerHandlers.onClick ? handleClick : undefined
172
170
  };
173
171
  const triggerNode = isValidElement(children) ? cloneElement(children, {
174
- "aria-describedby": triggerProps["aria-describedby"] ?? children.props["aria-describedby"],
175
172
  onMouseEnter: (event) => {
176
173
  callHandler(children.props.onMouseEnter, event);
177
174
  triggerProps.onMouseEnter?.(event);
@@ -208,7 +205,6 @@ var Popover = forwardRef(({
208
205
  ref: popoverRef,
209
206
  id: tooltipId,
210
207
  popover: "auto",
211
- role: "tooltip",
212
208
  style: { positionAnchor: anchorName },
213
209
  onToggle: (event) => {
214
210
  const nextOpen = event.newState === "open";
@@ -6,7 +6,7 @@ export interface TooltipProps extends Omit<ComponentProps<"span">, "title"> {
6
6
  placement?: TooltipPlacement;
7
7
  open?: boolean;
8
8
  defaultOpen?: boolean;
9
- /** Called when hover, focus, or dismissal requests a visibility change.
9
+ /** Called when native interest changes visibility, or a controlled interaction requests it.
10
10
  * Controlled tooltips use manual popovers and stay open until `open` changes. */
11
11
  onOpenChange?: (open: boolean) => void;
12
12
  /** @deprecated Native tooltips follow Core's arrowless automatic placement. */
@@ -62,7 +62,7 @@ var Tooltip = forwardRef(({
62
62
  open,
63
63
  defaultOpen,
64
64
  onOpenChange,
65
- arrow = true,
65
+ arrow = false,
66
66
  size = "md",
67
67
  className,
68
68
  children,
@@ -90,12 +90,21 @@ var Tooltip = forwardRef(({
90
90
  controlledRef.current = isControlled;
91
91
  onOpenChangeRef.current = onOpenChange;
92
92
  const hasTitle = Boolean(title);
93
+ const nativeInterest = !isControlled && React.isValidElement(children) && (typeof children.type !== "string" || children.type === "button" || children.type === "a") && children.type !== React.Fragment;
93
94
  useEffect(() => {
94
95
  const surface = surfaceRef.current;
95
96
  if (!surface)
96
97
  return;
97
98
  const tooltipSurface = surface;
98
99
  function handleToggle(event) {
100
+ if (nativeInterest) {
101
+ const next = event.newState === "open";
102
+ if (next !== tooltipSurface.matches(":popover-open") || next === visibleRef.current)
103
+ return;
104
+ onOpenChangeRef.current?.(next);
105
+ setInternalOpen(next);
106
+ return;
107
+ }
99
108
  if (event.newState !== "closed" || !visibleRef.current || isControlled || isControlled !== controlledRef.current || tooltipSurface.matches(":popover-open")) {
100
109
  return;
101
110
  }
@@ -107,7 +116,14 @@ var Tooltip = forwardRef(({
107
116
  }
108
117
  surface.addEventListener("toggle", handleToggle);
109
118
  return () => surface.removeEventListener("toggle", handleToggle);
110
- }, [hasTitle, isControlled]);
119
+ }, [hasTitle, isControlled, nativeInterest]);
120
+ useEffect(() => {
121
+ const surface = surfaceRef.current;
122
+ return () => {
123
+ if (surface?.matches(":popover-open"))
124
+ surface.hidePopover();
125
+ };
126
+ }, [hasTitle, isControlled, nativeInterest]);
111
127
  useEffect(() => {
112
128
  const surface = surfaceRef.current;
113
129
  if (!surface)
@@ -157,21 +173,29 @@ var Tooltip = forwardRef(({
157
173
  }
158
174
  function showTooltip(event) {
159
175
  onMouseEnter?.(event);
176
+ if (nativeInterest)
177
+ return;
160
178
  hoveredRef.current = true;
161
179
  updateInteraction();
162
180
  }
163
181
  function hideTooltip(event) {
164
182
  onMouseLeave?.(event);
183
+ if (nativeInterest)
184
+ return;
165
185
  hoveredRef.current = false;
166
186
  updateInteraction();
167
187
  }
168
188
  function focusTooltip(event) {
169
189
  onFocus?.(event);
190
+ if (nativeInterest)
191
+ return;
170
192
  focusedRef.current = true;
171
193
  updateInteraction();
172
194
  }
173
195
  function blurTooltip(event) {
174
196
  onBlur?.(event);
197
+ if (nativeInterest)
198
+ return;
175
199
  if (event.currentTarget.contains(event.relatedTarget))
176
200
  return;
177
201
  focusedRef.current = false;
@@ -180,6 +204,13 @@ var Tooltip = forwardRef(({
180
204
  let trigger = children;
181
205
  if (hasTitle && React.isValidElement(children) && children.type !== React.Fragment) {
182
206
  trigger = React.cloneElement(children, {
207
+ ...nativeInterest ? {
208
+ interestfor: tooltipId,
209
+ style: {
210
+ ...children.props.style,
211
+ anchorName: anchor
212
+ }
213
+ } : {},
183
214
  "aria-describedby": [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ")
184
215
  });
185
216
  }
@@ -187,7 +218,10 @@ var Tooltip = forwardRef(({
187
218
  ...props,
188
219
  ref,
189
220
  className: tooltipWrapperClass,
190
- style: { ...style, anchorName: anchor },
221
+ style: {
222
+ ...style,
223
+ ...nativeInterest ? {} : { anchorName: anchor }
224
+ },
191
225
  "aria-describedby": hasTitle && trigger === children ? [props["aria-describedby"], tooltipId].filter(Boolean).join(" ") : props["aria-describedby"],
192
226
  onMouseEnter: showTooltip,
193
227
  onMouseLeave: hideTooltip,
@@ -1 +1 @@
1
- export declare const version = "0.5.2";
1
+ export declare const version = "0.5.3";