@rackbops/ui-react 0.1.11 → 0.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/Dialog.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type DialogHTMLAttributes, type ReactNode, type RefAttributes } from "react";
2
2
  export interface DialogProps extends Omit<DialogHTMLAttributes<HTMLDialogElement>, "open" | "title" | "onClose">, RefAttributes<HTMLDialogElement> {
3
3
  open: boolean;
4
- onClose?: () => void;
4
+ onClose: () => void;
5
5
  title?: ReactNode;
6
6
  actions?: ReactNode;
7
7
  }
package/dist/Dialog.js CHANGED
@@ -1,26 +1,23 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { forwardRef, useEffect, useId, useRef, } from "react";
2
+ import { forwardRef, useEffect, useId, useImperativeHandle, useRef, } from "react";
3
3
  import { cx } from "./cx.js";
4
- /** Combines an internal ref this component needs with a consumer-supplied one,
5
- * so both end up pointing at the same DOM node. */
6
- function mergeRefs(...refs) {
7
- return (node) => {
8
- for (const ref of refs) {
9
- if (typeof ref === "function")
10
- ref(node);
11
- else if (ref)
12
- ref.current = node;
13
- }
14
- };
15
- }
16
4
  /** A native <dialog> driven by the `open` prop (showModal/close). */
17
5
  export const Dialog = forwardRef(function Dialog({ open, onClose, title, actions, children, className, ...rest }, forwardedRef) {
18
6
  const internalRef = useRef(null);
19
7
  const titleId = useId();
20
- // No dependency array: a native close (Escape, or a method="dialog" form)
21
- // flips el.open out from under the `open` prop with nothing to reconcile
22
- // them, so a stranded open=true re-render must re-sync too, not just a
23
- // render where `open` itself changed (issue #31).
8
+ // Expose the same <dialog> node this component drives to a forwarded ref,
9
+ // instead of a fresh callback-ref identity per render. A per-render merge
10
+ // callback re-attaches every render and never runs a React 19 cleanup-style
11
+ // consumer ref's cleanup; `useImperativeHandle` with [] deps attaches once
12
+ // and detaches (running that cleanup) on unmount (issue #83).
13
+ useImperativeHandle(forwardedRef, () => internalRef.current, []);
14
+ // `onClose` is required, so the parent is always told when the platform
15
+ // closes the dialog (Escape, a method="dialog" form) and keeps `open` in
16
+ // sync -- `open` is the single source of truth. That makes `[open]` the
17
+ // correct, complete dependency: reconcile only when the desired state
18
+ // changes, which reopens on a real false->true transition without the
19
+ // spontaneous reopens a dependency-less effect caused on unrelated renders
20
+ // (issue #83, completing #31).
24
21
  useEffect(() => {
25
22
  const el = internalRef.current;
26
23
  if (!el)
@@ -29,7 +26,7 @@ export const Dialog = forwardRef(function Dialog({ open, onClose, title, actions
29
26
  el.showModal();
30
27
  else if (!open && el.open)
31
28
  el.close();
32
- });
33
- return (_jsxs("dialog", { ref: mergeRefs(internalRef, forwardedRef), className: cx("rb-dialog", className), onClose: onClose, "aria-labelledby": title !== undefined ? titleId : undefined, ...rest, children: [_jsxs("div", { className: "rb-dialog__body", children: [title !== undefined && (_jsx("h2", { id: titleId, className: "rb-dialog__title", children: title })), children] }), actions !== undefined && _jsx("div", { className: "rb-dialog__actions", children: actions })] }));
29
+ }, [open]);
30
+ return (_jsxs("dialog", { ref: internalRef, className: cx("rb-dialog", className), onClose: onClose, "aria-labelledby": title !== undefined ? titleId : undefined, ...rest, children: [_jsxs("div", { className: "rb-dialog__body", children: [title !== undefined && (_jsx("h2", { id: titleId, className: "rb-dialog__title", children: title })), children] }), actions !== undefined && _jsx("div", { className: "rb-dialog__actions", children: actions })] }));
34
31
  });
35
32
  Dialog.displayName = "Dialog";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rackbops/ui-react",
3
- "version": "0.1.11",
3
+ "version": "0.2.0",
4
4
  "description": "React components styled by @rackbops/styles rackbops themes.",
5
5
  "license": "MIT",
6
6
  "repository": {