astralis-ui 0.1.0 → 0.1.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.
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- const a = "astralis:fixed astralis:z-higher astralis:min-w-44 astralis:max-w-72 astralis:rounded-xl astralis:border-normal astralis:border-stroke-subtle astralis:bg-surface-panel astralis:shadow-lg astralis:p-1 astralis:outline-none astralis:transition-all astralis:duration-fast", t = (s) => s === "open" ? "astralis:opacity-100 astralis:scale-100" : "astralis:opacity-0 astralis:scale-95", l = "astralis:flex astralis:w-full astralis:cursor-pointer astralis:select-none astralis:items-center astralis:gap-2 astralis:rounded-lg astralis:px-2.5 astralis:py-1.5 astralis:text-sm astralis:text-label-base astralis:outline-none astralis:transition-colors astralis:focus:bg-surface-subtle astralis:aria-disabled:opacity-moderate astralis:aria-disabled:pointer-events-none", r = "astralis:text-label-error astralis:focus:bg-surface-error", e = "astralis:px-2.5 astralis:py-1.5 astralis:text-xs astralis:font-medium astralis:text-label-subtle", i = "astralis:my-1 astralis:h-px astralis:bg-stroke-subtle", n = "astralis:h-4 astralis:w-4 astralis:shrink-0 astralis:text-label-muted", o = "astralis:ml-auto astralis:pl-4 astralis:text-xs astralis:text-label-subtle";
2
+ const a = "astralis:fixed astralis:z-higher astralis:min-w-44 astralis:max-w-72 astralis:rounded-xl astralis:border-normal astralis:border-stroke-subtle astralis:bg-surface-panel astralis:shadow-lg astralis:p-1 astralis:outline-none astralis:transition astralis:duration-fast", t = (s) => s === "open" ? "astralis:opacity-100 astralis:scale-100" : "astralis:opacity-0 astralis:scale-95", l = "astralis:flex astralis:w-full astralis:cursor-pointer astralis:select-none astralis:items-center astralis:gap-2 astralis:rounded-lg astralis:px-2.5 astralis:py-1.5 astralis:text-sm astralis:text-label-base astralis:outline-none astralis:transition-colors astralis:focus:bg-surface-subtle astralis:aria-disabled:opacity-moderate astralis:aria-disabled:pointer-events-none", r = "astralis:text-label-error astralis:focus:bg-surface-error", e = "astralis:px-2.5 astralis:py-1.5 astralis:text-xs astralis:font-medium astralis:text-label-subtle", i = "astralis:my-1 astralis:h-px astralis:bg-stroke-subtle", n = "astralis:h-4 astralis:w-4 astralis:shrink-0 astralis:text-label-muted", o = "astralis:ml-auto astralis:pl-4 astralis:text-xs astralis:text-label-subtle";
3
3
  export {
4
4
  a as menuContentClasses,
5
5
  n as menuIconSlotClasses,
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx as a, jsxs as M } from "react/jsx-runtime";
2
+ import { jsx as n, jsxs as M } from "react/jsx-runtime";
3
3
  import { useMemo as S, useEffect as U } from "react";
4
4
  import { usePopover as $ } from "../popover.context.js";
5
5
  import { popoverArrowClasses as k, popoverContentClasses as q } from "../popover.styles.js";
@@ -8,8 +8,8 @@ import { usePresence as B } from "../../../../hooks/use-presence.js";
8
8
  import { useDismiss as F } from "../../../../hooks/use-dismiss.js";
9
9
  import { useAnchorPosition as G } from "../../../../hooks/use-anchor-position.js";
10
10
  import { astralisMerge as H } from "../../../../utils/astralis-merge.js";
11
- const l = 160;
12
- function _({ children: n, className: f = "", withArrow: c = !1, ...p }) {
11
+ const a = 160;
12
+ function _({ children: l, className: f = "", withArrow: c = !1, ...p }) {
13
13
  const {
14
14
  open: o,
15
15
  close: m,
@@ -28,7 +28,7 @@ function _({ children: n, className: f = "", withArrow: c = !1, ...p }) {
28
28
  avoidCollisions: x,
29
29
  closeOnEsc: C,
30
30
  closeOnOutsidePointer: I
31
- } = $(), { mounted: w, state: D } = B(o, l), { x: T, y: A, side: r, arrow: i } = G({
31
+ } = $(), { mounted: w, state: D } = B(o, a), { x: T, y: A, side: r, arrow: i } = G({
32
32
  open: o,
33
33
  anchorRef: s,
34
34
  floatingRef: t,
@@ -46,7 +46,7 @@ function _({ children: n, className: f = "", withArrow: c = !1, ...p }) {
46
46
  };
47
47
  }, [o, t, s]), !w) return null;
48
48
  const N = D === "open", e = {};
49
- return r === "bottom" ? (e.top = -4, e.left = i.left) : r === "top" ? (e.bottom = -4, e.left = i.left) : r === "right" ? (e.left = -4, e.top = i.top) : (e.right = -4, e.top = i.top), /* @__PURE__ */ a(z, { children: /* @__PURE__ */ M(
49
+ return r === "bottom" ? (e.top = -4, e.left = i.left) : r === "top" ? (e.bottom = -4, e.left = i.left) : r === "right" ? (e.left = -4, e.top = i.top) : (e.right = -4, e.top = i.top), /* @__PURE__ */ n(z, { children: /* @__PURE__ */ M(
50
50
  "div",
51
51
  {
52
52
  ref: t,
@@ -56,17 +56,18 @@ function _({ children: n, className: f = "", withArrow: c = !1, ...p }) {
56
56
  "aria-describedby": y ? g : void 0,
57
57
  tabIndex: -1,
58
58
  "data-side": r,
59
- style: { left: T, top: A, transitionDuration: `${l}ms` },
59
+ style: { left: T, top: A, transitionDuration: `${a}ms` },
60
60
  className: H(
61
61
  q,
62
- "astralis:p-4 astralis:transition-all",
62
+ // `transition` (not -all): left/top must snap, never animate.
63
+ "astralis:p-4 astralis:transition",
63
64
  N ? "astralis:opacity-100 astralis:scale-100" : "astralis:opacity-0 astralis:scale-95",
64
65
  f
65
66
  ),
66
67
  ...p,
67
68
  children: [
68
- n,
69
- c && /* @__PURE__ */ a("div", { ref: d, className: k, style: e })
69
+ l,
70
+ c && /* @__PURE__ */ n("div", { ref: d, className: k, style: e })
70
71
  ]
71
72
  }
72
73
  ) });
@@ -1,10 +1,8 @@
1
1
  "use client";
2
- import { useState as u, useEffect as n } from "react";
3
- import { createPortal as f } from "react-dom";
4
- function m({ children: t, container: e }) {
5
- const [o, r] = u(!1);
6
- return n(() => r(!0), []), o ? f(t, e ?? document.body) : null;
2
+ import { createPortal as n } from "react-dom";
3
+ function r({ children: e, container: t }) {
4
+ return typeof document > "u" ? null : n(e, t ?? document.body);
7
5
  }
8
6
  export {
9
- m as Portal
7
+ r as Portal
10
8
  };
@@ -1,39 +1,41 @@
1
1
  "use client";
2
- import { useState as S, useCallback as k, useLayoutEffect as A } from "react";
2
+ import { useState as B, useCallback as S, useLayoutEffect as k } from "react";
3
3
  const L = { top: "bottom", bottom: "top", left: "right", right: "left" };
4
- function H({
5
- open: b,
6
- anchorRef: M,
7
- floatingRef: p,
4
+ function C({
5
+ open: p,
6
+ anchorRef: v,
7
+ floatingRef: l,
8
8
  side: o = "bottom",
9
9
  align: w = "center",
10
10
  sideOffset: m = 8,
11
- alignOffset: l = 0,
12
- avoidCollisions: u = !0,
11
+ alignOffset: s = 0,
12
+ avoidCollisions: a = !0,
13
13
  padding: r = 8
14
14
  }) {
15
- const [P, y] = S({ x: 0, y: 0, side: o, arrow: {} }), i = k(() => {
16
- const v = M.current, x = p.current;
17
- if (!v || !x) return;
18
- const t = v.getBoundingClientRect(), e = x.getBoundingClientRect(), f = window.innerWidth, g = window.innerHeight, z = o === "top" || o === "bottom";
15
+ const [y, P] = B({ x: 0, y: 0, side: o, arrow: {} }), h = S(() => {
16
+ const u = v.current, x = l.current;
17
+ if (!u || !x) return;
18
+ const t = u.getBoundingClientRect(), e = x.getBoundingClientRect(), f = window.innerWidth, E = window.innerHeight, T = o === "top" || o === "bottom";
19
19
  let c = o;
20
- if (u) {
21
- const a = { top: t.top, bottom: g - t.bottom, left: t.left, right: f - t.right }, B = (z ? e.height : e.width) + m + r;
22
- a[o] < B && a[L[o]] > a[o] && (c = L[o]);
20
+ if (a) {
21
+ const M = { top: t.top, bottom: E - t.bottom, left: t.left, right: f - t.right }, z = (T ? e.height : e.width) + m + r;
22
+ M[o] < z && M[L[o]] > M[o] && (c = L[o]);
23
23
  }
24
- const E = c === "top" || c === "bottom";
25
- let h = 0, n = 0;
26
- c === "bottom" ? n = t.bottom + m : c === "top" ? n = t.top - e.height - m : c === "right" ? h = t.right + m : h = t.left - e.width - m, E ? (h = w === "center" ? t.left + t.width / 2 - e.width / 2 : w === "start" ? t.left : t.right - e.width, h += l) : (n = w === "center" ? t.top + t.height / 2 - e.height / 2 : w === "start" ? t.top : t.bottom - e.height, n += l), u && (h = Math.min(Math.max(r, h), Math.max(r, f - e.width - r)), n = Math.min(Math.max(r, n), Math.max(r, g - e.height - r)));
27
- const s = {};
28
- E ? s.left = Math.min(Math.max(10, t.left + t.width / 2 - h), e.width - 10) : s.top = Math.min(Math.max(10, t.top + t.height / 2 - n), e.height - 10), y({ x: h, y: n, side: c, arrow: s });
29
- }, [M, p, o, w, m, l, u, r]);
30
- return A(() => {
31
- if (b)
32
- return i(), window.addEventListener("scroll", i, !0), window.addEventListener("resize", i), () => {
33
- window.removeEventListener("scroll", i, !0), window.removeEventListener("resize", i);
34
- };
35
- }, [b, i]), { ...P, update: i };
24
+ const g = c === "top" || c === "bottom";
25
+ let n = 0, i = 0;
26
+ c === "bottom" ? i = t.bottom + m : c === "top" ? i = t.top - e.height - m : c === "right" ? n = t.right + m : n = t.left - e.width - m, g ? (n = w === "center" ? t.left + t.width / 2 - e.width / 2 : w === "start" ? t.left : t.right - e.width, n += s) : (i = w === "center" ? t.top + t.height / 2 - e.height / 2 : w === "start" ? t.top : t.bottom - e.height, i += s), a && (n = Math.min(Math.max(r, n), Math.max(r, f - e.width - r)), i = Math.min(Math.max(r, i), Math.max(r, E - e.height - r)));
27
+ const b = {};
28
+ g ? b.left = Math.min(Math.max(10, t.left + t.width / 2 - n), e.width - 10) : b.top = Math.min(Math.max(10, t.top + t.height / 2 - i), e.height - 10), P({ x: n, y: i, side: c, arrow: b });
29
+ }, [v, l, o, w, m, s, a, r]);
30
+ return k(() => {
31
+ if (!p) return;
32
+ h();
33
+ let u = null;
34
+ return l.current || (u = setTimeout(h, 0)), window.addEventListener("scroll", h, !0), window.addEventListener("resize", h), () => {
35
+ u && clearTimeout(u), window.removeEventListener("scroll", h, !0), window.removeEventListener("resize", h);
36
+ };
37
+ }, [p, h, l]), { ...y, update: h };
36
38
  }
37
39
  export {
38
- H as useAnchorPosition
40
+ C as useAnchorPosition
39
41
  };
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { useRef as v, useEffect as b } from "react";
3
- import { lockBodyScroll as p, unlockBodyScroll as E, isTopOverlay as h, pushOverlay as k, popOverlay as A } from "../utils/overlay-stack.js";
3
+ import { lockBodyScroll as p, isTopOverlay as E, pushOverlay as h, popOverlay as k, unlockBodyScroll as A } from "../utils/overlay-stack.js";
4
4
  const a = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
5
5
  function T(r, c, d = {}) {
6
6
  const { closeOnEsc: s = !0 } = d, o = v(null);
7
7
  return b(() => {
8
8
  if (!r) return;
9
- const u = k();
9
+ const u = h();
10
10
  p();
11
11
  const m = document.activeElement, y = setTimeout(() => {
12
12
  const e = o.current;
@@ -15,7 +15,7 @@ function T(r, c, d = {}) {
15
15
  e.querySelectorAll(a)
16
16
  )[0] ?? e).focus();
17
17
  }, 0), l = (e) => {
18
- if (h(u)) {
18
+ if (E(u)) {
19
19
  if (e.key === "Escape") {
20
20
  s && c(!1);
21
21
  return;
@@ -33,7 +33,7 @@ function T(r, c, d = {}) {
33
33
  }
34
34
  };
35
35
  return document.addEventListener("keydown", l), () => {
36
- document.removeEventListener("keydown", l), A(u), E(), clearTimeout(y), m?.focus();
36
+ document.removeEventListener("keydown", l), k(u), A(), clearTimeout(y), m?.focus();
37
37
  };
38
38
  }, [r, c, s]), { containerRef: o };
39
39
  }
package/dist/index.d.ts CHANGED
@@ -2272,7 +2272,13 @@ export declare function PopoverTitle({ children, className }: PopoverSectionProp
2272
2272
 
2273
2273
  export declare function PopoverTrigger({ children }: PopoverSlotProps): ReactElement<any, string | JSXElementConstructor<any>>;
2274
2274
 
2275
- /** Renders children into `document.body` (after mount, so it's SSR-safe). */
2275
+ /**
2276
+ * Renders children into `document.body`. Guarded for SSR (no document on the
2277
+ * server) but NOT deferred behind an effect: overlay panels must exist in the
2278
+ * same commit that opens them, so anchor positioning can measure them in its
2279
+ * layout effect. (Portal children are never server-rendered or hydrated, so
2280
+ * rendering the portal during the client render is safe.)
2281
+ */
2276
2282
  export declare function Portal({ children, container }: {
2277
2283
  children: ReactNode;
2278
2284
  container?: HTMLElement;