@jfrader/ui 0.3.0 → 0.4.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.
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+ import { a as e, n as t, t as n } from "./sx-Dx9JUKp5.js";
3
+ import { n as r, r as i } from "./theme-scope-t7nAKc2c.js";
4
+ import { useContext as a, useMemo as o } from "react";
5
+ import { vars as s } from "@jfrader/tokens/vars";
6
+ import { jsx as c } from "@emotion/react/jsx-runtime";
7
+ //#region src/styling/theme.ts
8
+ var l = s;
9
+ //#endregion
10
+ //#region src/components/theme-provider/theme-provider.tsx
11
+ function u({ theme: e = l, children: n }) {
12
+ return /* @__PURE__ */ c(t, {
13
+ theme: e,
14
+ children: n
15
+ });
16
+ }
17
+ u.displayName = "ThemeProvider";
18
+ function d() {
19
+ return e();
20
+ }
21
+ //#endregion
22
+ //#region src/components/theme-root/theme-root.tsx
23
+ function f({ ref: e, theme: t = "dark", portalContainer: s, className: l, sx: d, ...f }) {
24
+ let p = a(r), m = s === void 0 ? p?.portalContainer : s, h = o(() => ({
25
+ theme: t,
26
+ portalContainer: m
27
+ }), [t, m]);
28
+ return /* @__PURE__ */ c(r.Provider, {
29
+ value: h,
30
+ children: /* @__PURE__ */ c(u, { children: /* @__PURE__ */ c(n, {
31
+ className: l,
32
+ styles: i,
33
+ sx: d,
34
+ children: (n) => /* @__PURE__ */ c("div", {
35
+ "data-ui": "theme-root",
36
+ "data-theme": t,
37
+ ...f,
38
+ ref: e,
39
+ className: n
40
+ })
41
+ }) })
42
+ });
43
+ }
44
+ f.displayName = "ThemeRoot";
45
+ //#endregion
46
+ export { l as i, u as n, d as r, f as t };
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- export { t as ThemeRoot } from "./theme-root-BiXXvQvr.js";
2
+ export { t as ThemeRoot } from "./theme-root-BbTBuLMQ.js";
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { r as e } from "./sx-Dx9JUKp5.js";
3
+ import { createContext as t, useContext as n } from "react";
4
+ import { vars as r } from "@jfrader/tokens/vars";
5
+ import { jsx as i } from "@emotion/react/jsx-runtime";
6
+ //#region src/styling/theme-scope.tsx
7
+ var a = t(null);
8
+ function o() {
9
+ return n(a);
10
+ }
11
+ var s = e({
12
+ color: r.color.text,
13
+ colorScheme: "dark",
14
+ "&[data-theme=\"light\"]": { colorScheme: "light" }
15
+ }), c = e({ display: "contents" });
16
+ function l({ children: e }) {
17
+ let t = o();
18
+ return t ? /* @__PURE__ */ i("div", {
19
+ "data-ui": "theme-boundary",
20
+ "data-theme": t.theme,
21
+ css: [s, c],
22
+ children: e
23
+ }) : e;
24
+ }
25
+ l.displayName = "ThemeBoundary";
26
+ //#endregion
27
+ export { o as i, a as n, s as r, l as t };
@@ -0,0 +1,283 @@
1
+ 'use client';
2
+ import { r as e, t } from "./sx-Dx9JUKp5.js";
3
+ import { n } from "./media-D_eA_I-e.js";
4
+ import { t as r } from "./renderable-DzcIj1Lo.js";
5
+ import { t as i } from "./button-P2e7_44z.js";
6
+ import { i as a, t as o } from "./theme-scope-t7nAKc2c.js";
7
+ import { createContext as s, useCallback as c, useContext as l, useEffect as u, useId as d, useMemo as f, useRef as p, useState as m } from "react";
8
+ import { vars as h } from "@jfrader/tokens/vars";
9
+ import { Fragment as g, jsx as _, jsxs as v } from "@emotion/react/jsx-runtime";
10
+ import { createPortal as y } from "react-dom";
11
+ //#region src/components/toast/toast.tsx
12
+ var b = 4, x = 5e3, S = "Dismiss", C = 100, w = "min(380px, calc(100vw - 32px))", T = "3px", E = s(null), D = s(null), O = e({
13
+ position: "fixed",
14
+ insetBlockEnd: 0,
15
+ insetInlineEnd: 0,
16
+ display: "flex",
17
+ flexDirection: "column",
18
+ gap: h.space[2],
19
+ inlineSize: w,
20
+ margin: 0,
21
+ paddingInlineEnd: h.space[4],
22
+ paddingBlockEnd: h.space[4],
23
+ pointerEvents: "none",
24
+ fontFamily: h.font.sans
25
+ }), k = e({
26
+ boxSizing: "border-box",
27
+ display: "grid",
28
+ gridTemplateColumns: "minmax(0, 1fr) auto",
29
+ alignItems: "start",
30
+ gap: h.space[2],
31
+ backgroundColor: h.color.surfaceRaised,
32
+ border: `1px solid ${h.color.border}`,
33
+ borderRadius: h.radius.lg,
34
+ boxShadow: h.shadow.floating,
35
+ padding: h.space[3],
36
+ color: h.color.text,
37
+ lineHeight: h.lineHeight.base,
38
+ pointerEvents: "auto",
39
+ transitionProperty: "opacity, transform",
40
+ transitionDuration: h.motion.duration.base,
41
+ transitionTimingFunction: h.motion.easeStandard,
42
+ "&[data-populated=\"false\"]": { opacity: 0 },
43
+ "&[data-state=\"closing\"]": {
44
+ opacity: 0,
45
+ transform: `translateY(${h.space[2]})`,
46
+ pointerEvents: "none"
47
+ },
48
+ [n]: { transitionDuration: "0s" }
49
+ }), A = {
50
+ neutral: e({ borderInlineStart: `${T} solid ${h.color.borderStrong}` }),
51
+ success: e({ borderInlineStart: `${T} solid ${h.color.success}` }),
52
+ danger: e({ borderInlineStart: `${T} solid ${h.color.danger}` })
53
+ }, j = e({
54
+ display: "grid",
55
+ gap: h.space[1],
56
+ alignSelf: "center",
57
+ minInlineSize: 0
58
+ }), M = e({
59
+ margin: 0,
60
+ fontSize: h.textSize.sm,
61
+ fontWeight: h.fontWeight.semibold
62
+ }), N = e({
63
+ margin: 0,
64
+ fontSize: h.textSize.sm,
65
+ color: h.color.textMuted
66
+ }), P = e({
67
+ gridColumn: 2,
68
+ gridRow: 1,
69
+ inlineSize: "32px",
70
+ paddingInline: 0
71
+ }), F = e({ display: "contents" }), I = e({
72
+ gridColumn: "1 / -1",
73
+ display: "flex",
74
+ gap: h.space[2]
75
+ });
76
+ function L(e) {
77
+ let t = l(D);
78
+ if (!t) throw Error(`Toast.${e} must be rendered inside <Toast.Provider>.`);
79
+ return t;
80
+ }
81
+ function R() {
82
+ let e = l(E);
83
+ if (!e) throw Error("useToast() must be called inside <Toast.Provider>.");
84
+ return e;
85
+ }
86
+ function z({ children: e, max: t = b, duration: n = x, dismissLabel: r = S }) {
87
+ let i = d(), a = p(0), [o, s] = m([]), l = p([]), u = p(/* @__PURE__ */ new Map()), h = Math.max(1, Math.floor(Number.isFinite(t) ? t : b)), g = c((e, t) => {
88
+ t ? u.current.set(e, t) : u.current.delete(e);
89
+ }, []), v = c((e, t) => {
90
+ let n = new Set(t.filter((e) => e.state === "open").map((e) => u.current.get(e.id)));
91
+ for (let t of e) {
92
+ let e = u.current.get(t.id);
93
+ if (e?.contains(e.ownerDocument.activeElement)) {
94
+ Array.from(e.parentElement?.querySelectorAll("[data-ui=\"toast\"]") ?? []).find((e) => n.has(e))?.querySelector("[data-toast-dismiss]")?.focus();
95
+ break;
96
+ }
97
+ }
98
+ }, []), y = c((e) => {
99
+ a.current += 1;
100
+ let t = `${i}toast-${a.current}`, r = {
101
+ id: t,
102
+ options: {
103
+ ...e,
104
+ duration: e.duration === void 0 ? n : e.duration
105
+ },
106
+ state: "open"
107
+ }, o = l.current, c = [...o, r].slice(-h);
108
+ return v(o.filter((e) => !c.includes(e)), c), l.current = c, s(c), t;
109
+ }, [
110
+ i,
111
+ h,
112
+ n,
113
+ v
114
+ ]), C = c((e) => {
115
+ let t = l.current;
116
+ v(t.filter((t) => t.id === e), t.filter((t) => t.id !== e));
117
+ let n = t.map((t) => t.id === e && t.state === "open" ? {
118
+ ...t,
119
+ state: "closing"
120
+ } : t);
121
+ l.current = n, s(n);
122
+ }, [v]), w = c((e) => {
123
+ let t = l.current, n = t.filter((t) => t.id !== e);
124
+ v(t.filter((t) => t.id === e), n), l.current = n, s(n);
125
+ }, [v]), T = f(() => ({
126
+ toast: y,
127
+ dismiss: C
128
+ }), [y, C]), O = f(() => ({
129
+ toasts: o,
130
+ dismiss: C,
131
+ remove: w,
132
+ registerRoot: g,
133
+ dismissLabel: r
134
+ }), [
135
+ o,
136
+ C,
137
+ w,
138
+ g,
139
+ r
140
+ ]);
141
+ return /* @__PURE__ */ _(E.Provider, {
142
+ value: T,
143
+ children: /* @__PURE__ */ _(D.Provider, {
144
+ value: O,
145
+ children: e
146
+ })
147
+ });
148
+ }
149
+ z.displayName = "Toast.Provider";
150
+ function B({ ref: e, className: n, sx: r, ...i }) {
151
+ let { toasts: s } = L("Viewport"), c = p(null), [l, d] = m(null), f = a()?.portalContainer, h = f === void 0 ? l : f;
152
+ return u(() => {
153
+ d(c.current?.ownerDocument.body ?? null);
154
+ }, []), /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("span", {
155
+ hidden: !0,
156
+ ref: c
157
+ }), h && y(/* @__PURE__ */ _(o, { children: /* @__PURE__ */ _(t, {
158
+ className: n,
159
+ styles: O,
160
+ sx: r,
161
+ children: (t) => /* @__PURE__ */ _("div", {
162
+ ...i,
163
+ ref: e,
164
+ "data-ui": "toast-viewport",
165
+ className: t,
166
+ children: s.map((e) => /* @__PURE__ */ _(V, { record: e }, e.id))
167
+ })
168
+ }) }), h)] });
169
+ }
170
+ B.displayName = "Toast.Viewport";
171
+ function V({ record: e }) {
172
+ let { dismiss: t, remove: n, registerRoot: a, dismissLabel: o } = L("Viewport"), { id: s, options: l, state: d } = e, { title: f, description: h, tone: y = "neutral", action: b } = l, x = l.duration, S = p(null), w = c((e) => {
173
+ S.current = e, a(s, e);
174
+ }, [s, a]), [T, E] = m(!1), [D, O] = m(!1), [R, z] = m(!1), B = p(x ?? 0);
175
+ u(() => {
176
+ let e = setTimeout(() => E(!0), C);
177
+ return () => clearTimeout(e);
178
+ }, []);
179
+ let V = T && d === "open" && x !== null && !D && !R;
180
+ return u(() => {
181
+ if (!V) return;
182
+ let e = performance.now(), n = setTimeout(() => t(s), B.current);
183
+ return () => {
184
+ clearTimeout(n), B.current -= performance.now() - e;
185
+ };
186
+ }, [
187
+ V,
188
+ t,
189
+ s
190
+ ]), u(() => {
191
+ if (d !== "closing") return;
192
+ let e = S.current, t = e && typeof e.getAnimations == "function" ? e.getAnimations() : [], r = !1;
193
+ return Promise.allSettled(t.map((e) => e.finished)).then(() => {
194
+ r || n(s);
195
+ }), () => {
196
+ r = !0;
197
+ };
198
+ }, [
199
+ d,
200
+ n,
201
+ s
202
+ ]), /* @__PURE__ */ v("div", {
203
+ ref: w,
204
+ inert: d === "closing",
205
+ "data-ui": "toast",
206
+ "data-tone": y,
207
+ "data-state": d,
208
+ "data-populated": T,
209
+ onPointerEnter: () => O(!0),
210
+ onPointerLeave: () => O(!1),
211
+ onFocus: () => z(!0),
212
+ onBlur: (e) => {
213
+ e.currentTarget.contains(e.relatedTarget) || z(!1);
214
+ },
215
+ css: [k, A[y]],
216
+ children: [/* @__PURE__ */ _("div", {
217
+ role: y === "danger" ? "alert" : "status",
218
+ "aria-atomic": "true",
219
+ css: j,
220
+ children: T && /* @__PURE__ */ v(g, { children: [r(f) && /* @__PURE__ */ _("div", {
221
+ css: M,
222
+ children: f
223
+ }), r(h) && /* @__PURE__ */ _("div", {
224
+ css: N,
225
+ children: h
226
+ })] })
227
+ }), T && /* @__PURE__ */ v("div", {
228
+ css: F,
229
+ children: [/* @__PURE__ */ _(i, {
230
+ variant: "ghost",
231
+ size: "sm",
232
+ "aria-label": o,
233
+ "data-toast-dismiss": "",
234
+ onClick: () => t(s),
235
+ css: P,
236
+ children: /* @__PURE__ */ _(H, {})
237
+ }), b && /* @__PURE__ */ _("div", {
238
+ css: I,
239
+ children: /* @__PURE__ */ _(i, {
240
+ variant: "outline",
241
+ size: "sm",
242
+ onClick: (e) => {
243
+ b?.onClick(e), e.defaultPrevented || t(s);
244
+ },
245
+ children: b.label
246
+ })
247
+ })]
248
+ })]
249
+ });
250
+ }
251
+ function H() {
252
+ return /* @__PURE__ */ v("svg", {
253
+ "aria-hidden": "true",
254
+ viewBox: "0 0 16 16",
255
+ width: "16",
256
+ height: "16",
257
+ fill: "none",
258
+ stroke: "currentColor",
259
+ strokeWidth: "2",
260
+ strokeLinecap: "round",
261
+ children: [/* @__PURE__ */ _("line", {
262
+ x1: "4",
263
+ y1: "4",
264
+ x2: "12",
265
+ y2: "12"
266
+ }), /* @__PURE__ */ _("line", {
267
+ x1: "12",
268
+ y1: "4",
269
+ x2: "4",
270
+ y2: "12"
271
+ })]
272
+ });
273
+ }
274
+ function U(e) {
275
+ return /* @__PURE__ */ _(z, { ...e });
276
+ }
277
+ U.displayName = "Toast";
278
+ var W = Object.assign(U, {
279
+ Provider: z,
280
+ Viewport: B
281
+ });
282
+ //#endregion
283
+ export { R as n, W as t };
package/dist/toast.js CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- export { t as Toast, n as useToast } from "./toast-iqelR-r0.js";
2
+ export { t as Toast, n as useToast } from "./toast-CjmELMZZ.js";
@@ -2,40 +2,40 @@
2
2
  import { r as e, t } from "./sx-Dx9JUKp5.js";
3
3
  import { t as n } from "./use-controlled-state-CVXDa-qM.js";
4
4
  import { t as r } from "./trigger-style-B1KVC8O1.js";
5
- import { t as i } from "./use-overlay-floating-efeqppiw.js";
6
- import { createContext as a, useContext as o, useMemo as s } from "react";
7
- import { vars as c } from "@jfrader/tokens/vars";
8
- import { jsx as l } from "@emotion/react/jsx-runtime";
9
- import { FloatingPortal as u, useDismiss as d, useFocus as f, useHover as p, useInteractions as m, useMergeRefs as h, useRole as g } from "@floating-ui/react";
5
+ import { n as i, t as a } from "./use-overlay-floating-Bit-f0FU.js";
6
+ import { createContext as o, useContext as s, useMemo as c } from "react";
7
+ import { vars as l } from "@jfrader/tokens/vars";
8
+ import { jsx as u } from "@emotion/react/jsx-runtime";
9
+ import { useDismiss as d, useFocus as f, useHover as p, useInteractions as m, useMergeRefs as h, useRole as g } from "@floating-ui/react";
10
10
  //#region src/components/tooltip/tooltip.tsx
11
- var _ = 300, v = 100, y = a(null);
11
+ var _ = 300, v = 100, y = o(null);
12
12
  function b(e) {
13
- let t = o(y);
13
+ let t = s(y);
14
14
  if (!t) throw Error(`Tooltip.${e} must be rendered inside <Tooltip>.`);
15
15
  return t;
16
16
  }
17
17
  var x = e({
18
18
  boxSizing: "border-box",
19
- backgroundColor: c.color.bgSoft,
20
- border: `1px solid ${c.color.border}`,
21
- borderRadius: c.radius.sm,
22
- boxShadow: c.shadow.raised,
23
- padding: `${c.space[1]} ${c.space[2]}`,
19
+ backgroundColor: l.color.bgSoft,
20
+ border: `1px solid ${l.color.border}`,
21
+ borderRadius: l.radius.sm,
22
+ boxShadow: l.shadow.raised,
23
+ padding: `${l.space[1]} ${l.space[2]}`,
24
24
  maxInlineSize: "260px",
25
- color: c.color.text,
26
- fontFamily: c.font.sans,
27
- fontSize: c.textSize.sm,
28
- lineHeight: c.lineHeight.base
25
+ color: l.color.text,
26
+ fontFamily: l.font.sans,
27
+ fontSize: l.textSize.sm,
28
+ lineHeight: l.lineHeight.base
29
29
  });
30
- function S({ open: e, defaultOpen: t = !1, onOpenChange: r, placement: a = "top", openDelay: o = _, closeDelay: c = v, children: u }) {
31
- let [h = !1, b] = n(e, t, r), { refs: x, floatingStyles: S, context: C } = i({
30
+ function S({ open: e, defaultOpen: t = !1, onOpenChange: r, placement: i = "top", openDelay: o = _, closeDelay: s = v, children: l }) {
31
+ let [h = !1, b] = n(e, t, r), { refs: x, floatingStyles: S, context: C } = a({
32
32
  open: h,
33
- placement: a,
33
+ placement: i,
34
34
  onOpenChange: b
35
35
  }), w = p(C, {
36
36
  delay: {
37
37
  open: o,
38
- close: c
38
+ close: s
39
39
  },
40
40
  move: !1
41
41
  }), T = f(C), E = d(C, { escapeKey: !0 }), D = g(C, { role: "tooltip" }), { getReferenceProps: O, getFloatingProps: k } = m([
@@ -43,7 +43,7 @@ function S({ open: e, defaultOpen: t = !1, onOpenChange: r, placement: a = "top"
43
43
  T,
44
44
  E,
45
45
  D
46
- ]), A = s(() => ({
46
+ ]), A = c(() => ({
47
47
  open: h,
48
48
  refs: x,
49
49
  floatingStyles: S,
@@ -56,22 +56,22 @@ function S({ open: e, defaultOpen: t = !1, onOpenChange: r, placement: a = "top"
56
56
  O,
57
57
  k
58
58
  ]);
59
- return /* @__PURE__ */ l(y.Provider, {
59
+ return /* @__PURE__ */ u(y.Provider, {
60
60
  value: A,
61
- children: u
61
+ children: l
62
62
  });
63
63
  }
64
64
  S.displayName = "Tooltip";
65
65
  function C({ ref: e, "aria-describedby": n, className: i, sx: a, ...o }) {
66
- let { refs: s, getReferenceProps: c } = b("Trigger"), u = h([s.setReference, e]), d = c(o), f = [n, d["aria-describedby"]].filter(Boolean).join(" ") || void 0;
67
- return /* @__PURE__ */ l(t, {
66
+ let { refs: s, getReferenceProps: c } = b("Trigger"), l = h([s.setReference, e]), d = c(o), f = [n, d["aria-describedby"]].filter(Boolean).join(" ") || void 0;
67
+ return /* @__PURE__ */ u(t, {
68
68
  className: i,
69
69
  styles: r,
70
70
  sx: a,
71
- children: (e) => /* @__PURE__ */ l("button", {
71
+ children: (e) => /* @__PURE__ */ u("button", {
72
72
  type: "button",
73
73
  ...d,
74
- ref: u,
74
+ ref: l,
75
75
  "aria-describedby": f,
76
76
  "data-ui": "tooltip-trigger",
77
77
  className: e
@@ -79,21 +79,21 @@ function C({ ref: e, "aria-describedby": n, className: i, sx: a, ...o }) {
79
79
  });
80
80
  }
81
81
  C.displayName = "Tooltip.Trigger";
82
- function w({ ref: e, style: n, className: r, sx: i, ...a }) {
83
- let { open: o, refs: s, floatingStyles: c, getFloatingProps: d } = b("Content"), f = h([s.setFloating, e]);
84
- if (!o) return null;
85
- let { tabIndex: p, ...m } = d(a);
86
- return /* @__PURE__ */ l(u, { children: /* @__PURE__ */ l(t, {
82
+ function w({ ref: e, style: n, className: r, sx: a, ...o }) {
83
+ let { open: s, refs: c, floatingStyles: l, getFloatingProps: d } = b("Content"), f = h([c.setFloating, e]);
84
+ if (!s) return null;
85
+ let { tabIndex: p, ...m } = d(o);
86
+ return /* @__PURE__ */ u(i, { children: /* @__PURE__ */ u(t, {
87
87
  className: r,
88
88
  styles: x,
89
- sx: i,
90
- children: (e) => /* @__PURE__ */ l("div", {
89
+ sx: a,
90
+ children: (e) => /* @__PURE__ */ u("div", {
91
91
  ...m,
92
92
  ref: f,
93
93
  "data-ui": "tooltip",
94
94
  style: {
95
95
  ...n,
96
- ...c
96
+ ...l
97
97
  },
98
98
  className: e
99
99
  })
package/dist/tooltip.js CHANGED
@@ -1,2 +1,2 @@
1
1
  'use client';
2
- export { t as Tooltip } from "./tooltip-CB-HC1js.js";
2
+ export { t as Tooltip } from "./tooltip-CaL3rKbV.js";
@@ -1,11 +1,17 @@
1
- import type { ComponentPropsWithRef, ReactNode } from 'react';
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
2
  import { type SxProps } from '../../styling/sx';
3
- export type ThemeName = 'dark' | 'light';
3
+ import { type ThemeName } from '../../styling/theme-scope';
4
+ export type { ThemeName };
4
5
  export interface ThemeRootProps extends ComponentPropsWithRef<'div'>, SxProps {
5
6
  theme?: ThemeName;
7
+ /**
8
+ * Where overlays inside this root portal to. Omitted: the enclosing ThemeRoot's container, else
9
+ * the default (`body`). `null`: overlays wait until the host element is set.
10
+ */
11
+ portalContainer?: HTMLElement | null;
6
12
  children?: ReactNode;
7
13
  }
8
- export declare function ThemeRoot({ ref, theme, className, sx, ...rest }: ThemeRootProps): import("@emotion/react/jsx-runtime").JSX.Element;
14
+ export declare function ThemeRoot({ ref, theme, portalContainer, className, sx, ...rest }: ThemeRootProps): import("@emotion/react/jsx-runtime").JSX.Element;
9
15
  export declare namespace ThemeRoot {
10
16
  var displayName: string;
11
17
  }
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from 'react';
2
+ export declare function OverlayPortal({ children }: {
3
+ children?: ReactNode;
4
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
5
+ export declare namespace OverlayPortal {
6
+ var displayName: string;
7
+ }
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from 'react';
2
+ export type ThemeName = 'dark' | 'light';
3
+ export interface ThemeScope {
4
+ theme: ThemeName;
5
+ /** `undefined` keeps default portal routing; `null` holds portals until the host exists. */
6
+ portalContainer: HTMLElement | null | undefined;
7
+ }
8
+ export declare const ThemeScopeContext: import("react").Context<ThemeScope | null>;
9
+ /** The nearest ThemeRoot's scope, or `null` outside any ThemeRoot (page theme applies). */
10
+ export declare function useThemeScope(): ThemeScope | null;
11
+ /** What a `data-theme` scope root sets besides the attribute: inherited text color and color-scheme. */
12
+ export declare const themeScopeStyle: import("@emotion/react").SerializedStyles;
13
+ /** Re-applies the nearest ThemeRoot's theme around portaled content; renders children bare outside one. */
14
+ export declare function ThemeBoundary({ children }: {
15
+ children?: ReactNode;
16
+ }): string | number | bigint | boolean | import("@emotion/react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
17
+ export declare namespace ThemeBoundary {
18
+ var displayName: string;
19
+ }
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+ import { i as e, t } from "./theme-scope-t7nAKc2c.js";
3
+ import { jsx as n } from "@emotion/react/jsx-runtime";
4
+ import { FloatingPortal as r, autoUpdate as i, flip as a, offset as o, shift as s, useFloating as c } from "@floating-ui/react";
5
+ //#region src/overlay/overlay-portal.tsx
6
+ function l({ children: i }) {
7
+ let a = e();
8
+ return /* @__PURE__ */ n(r, {
9
+ root: a?.portalContainer,
10
+ children: /* @__PURE__ */ n(t, { children: i })
11
+ });
12
+ }
13
+ l.displayName = "OverlayPortal";
14
+ //#endregion
15
+ //#region src/overlay/use-overlay-floating.ts
16
+ var u = 8, d = 8;
17
+ function f({ open: e, onOpenChange: t, placement: n }) {
18
+ return c({
19
+ open: e,
20
+ onOpenChange: t,
21
+ placement: n,
22
+ middleware: [
23
+ o(u),
24
+ a({ padding: d }),
25
+ s({ padding: d })
26
+ ],
27
+ whileElementsMounted: i
28
+ });
29
+ }
30
+ //#endregion
31
+ export { l as n, f as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jfrader/ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "React components styled with Emotion and themed through CSS custom properties.",
5
5
  "keywords": [
6
6
  "react",
@@ -178,7 +178,7 @@
178
178
  "@emotion/react": "^11.14.0",
179
179
  "@emotion/styled": "^11.14.0",
180
180
  "@floating-ui/react": "^0.27.20",
181
- "@jfrader/tokens": "0.3.0"
181
+ "@jfrader/tokens": "0.4.0"
182
182
  },
183
183
  "peerDependencies": {
184
184
  "react": "^19.0.0",