@wisdomgarden/torque 0.2.1 → 0.2.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.
Files changed (63) hide show
  1. package/dist/common/is-dev.d.ts +1 -0
  2. package/dist/common/is-dev.js +5 -0
  3. package/dist/components/_inner/drawer/base-bottom-drawer.d.ts +1 -1
  4. package/dist/components/_inner/drawer/base-bottom-drawer.js +52 -44
  5. package/dist/components/_inner/menu/_web/menu.web.js +83 -72
  6. package/dist/components/_inner/portal/index.d.ts +1 -0
  7. package/dist/components/_inner/portal/index.js +5 -0
  8. package/dist/components/_inner/portal/portal.d.ts +14 -0
  9. package/dist/components/_inner/portal/portal.js +19 -0
  10. package/dist/components/button/styles/button-variables.module.css.js +1 -1
  11. package/dist/components/drawer/drawer.d.ts +1 -1
  12. package/dist/components/drawer/drawer.js +42 -34
  13. package/dist/components/modal/index.d.ts +1 -1
  14. package/dist/components/modal/modal.d.ts +7 -4
  15. package/dist/components/modal/modal.js +191 -44
  16. package/dist/components/modal/modal.module.css.js +20 -6
  17. package/dist/components/modal/modal.types.d.ts +96 -0
  18. package/dist/components/modal-deprecated/index.d.ts +2 -0
  19. package/dist/components/modal-deprecated/index.js +5 -0
  20. package/dist/components/modal-deprecated/modal-deprecated.d.ts +11 -0
  21. package/dist/components/modal-deprecated/modal-deprecated.js +70 -0
  22. package/dist/components/modal-deprecated/modal-deprecated.module.css.js +10 -0
  23. package/dist/components/notifications/index.d.ts +2 -0
  24. package/dist/components/notifications/index.js +4 -2
  25. package/dist/components/notifications/notifications-container.d.ts +9 -0
  26. package/dist/components/notifications/notifications-container.js +22 -0
  27. package/dist/components/overlay-layer/constants.d.ts +14 -0
  28. package/dist/components/overlay-layer/constants.js +8 -0
  29. package/dist/components/overlay-layer/index.d.ts +5 -0
  30. package/dist/components/overlay-layer/index.js +10 -0
  31. package/dist/components/overlay-layer/overlay-parent-context.d.ts +6 -0
  32. package/dist/components/overlay-layer/overlay-parent-context.js +18 -0
  33. package/dist/components/overlay-layer/overlay-stack-debug.d.ts +24 -0
  34. package/dist/components/overlay-layer/overlay-stack-debug.js +151 -0
  35. package/dist/components/overlay-layer/overlay-stack.d.ts +38 -0
  36. package/dist/components/overlay-layer/overlay-stack.js +137 -0
  37. package/dist/components/overlay-layer/overlay-tier-scope.d.ts +12 -0
  38. package/dist/components/overlay-layer/overlay-tier-scope.js +16 -0
  39. package/dist/components/overlay-layer/types.d.ts +63 -0
  40. package/dist/components/overlay-layer/use-mantine-overlay-layer.d.ts +21 -0
  41. package/dist/components/overlay-layer/use-mantine-overlay-layer.js +24 -0
  42. package/dist/components/overlay-layer/use-overlay-layer.d.ts +26 -0
  43. package/dist/components/overlay-layer/use-overlay-layer.js +77 -0
  44. package/dist/components/popover/hooks.d.ts +0 -1
  45. package/dist/components/popover/hooks.js +69 -83
  46. package/dist/components/popover/popover-context.d.ts +0 -1
  47. package/dist/components/popover/popover-context.js +3 -4
  48. package/dist/components/popover/popover-dropdown.js +110 -91
  49. package/dist/components/popover/popover.js +120 -129
  50. package/dist/components/popover/popover.types.d.ts +18 -5
  51. package/dist/components/tooltip/index.d.ts +10 -2
  52. package/dist/components/tooltip/index.js +100 -92
  53. package/dist/index.css +1 -1
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.js +193 -182
  56. package/dist/provider/hooks.js +12 -11
  57. package/dist/provider/ui-context.d.ts +10 -0
  58. package/dist/provider/ui-context.js +8 -7
  59. package/dist/provider/ui-provider.d.ts +23 -1
  60. package/dist/provider/ui-provider.js +17 -10
  61. package/package.json +3 -3
  62. package/dist/components/popover/popover-stack.d.ts +0 -10
  63. package/dist/components/popover/popover-stack.js +0 -24
@@ -0,0 +1,151 @@
1
+ "use client";
2
+ const I = "data-torque-overlay-debug", $ = "torqueOverlayStack", k = "torque:overlay-stack-debug", _ = "2147483647", C = "2147483646";
3
+ function A() {
4
+ try {
5
+ return JSON.parse(sessionStorage.getItem(k) ?? "");
6
+ } catch {
7
+ return { opened: !1 };
8
+ }
9
+ }
10
+ function m(d) {
11
+ try {
12
+ sessionStorage.setItem(k, JSON.stringify(d));
13
+ } catch {
14
+ }
15
+ }
16
+ function i(d, l, n) {
17
+ const r = document.createElement(d);
18
+ return r.style.cssText = l, n !== void 0 && (r.textContent = n), r;
19
+ }
20
+ function H(d) {
21
+ if (!d.closable) return "透明";
22
+ const l = [];
23
+ return d.closeOnEscape || l.push("吞 Esc"), d.closeOnClickOutside || l.push("点外不关"), l.join(" · ");
24
+ }
25
+ function M({
26
+ subscribe: d,
27
+ getSnapshot: l
28
+ }) {
29
+ let n = null, r = null, v = null, p = { x: 0, y: 0 }, b = /* @__PURE__ */ new Map(), u = null, o = null, f = null, x = 0;
30
+ const g = () => {
31
+ x && cancelAnimationFrame(x), x = 0, u = null, o?.remove(), o = null, f = null;
32
+ }, E = () => {
33
+ const t = u ? b.get(u) : void 0, e = t?.getElement();
34
+ if (!t || !e?.isConnected || !o || !f)
35
+ o && (o.style.display = "none");
36
+ else {
37
+ const a = e.getBoundingClientRect();
38
+ o.style.display = "block", o.style.left = `${a.left}px`, o.style.top = `${a.top}px`, o.style.width = `${a.width}px`, o.style.height = `${a.height}px`, f.textContent = `${t.name ?? t.id} · ${t.zIndex}`;
39
+ }
40
+ x = requestAnimationFrame(E);
41
+ }, O = (t) => {
42
+ u !== t && (u = t, o || (o = i(
43
+ "div",
44
+ `position:fixed;z-index:${C};pointer-events:none;box-sizing:border-box;border:2px solid var(--t-brand-1,#00a1b0);background:rgba(0,161,176,.12);border-radius:4px;`
45
+ ), o.setAttribute(I, ""), o.setAttribute("aria-hidden", "true"), f = i(
46
+ "span",
47
+ "position:absolute;left:-2px;bottom:100%;padding:1px 6px;white-space:nowrap;border-radius:4px 4px 0 0;background:var(--t-brand-1,#00a1b0);color:#fff;font:12px/18px system-ui,sans-serif;"
48
+ ), o.append(f), document.body.append(o)), x || E());
49
+ }, y = (t, e) => {
50
+ if (!n) return;
51
+ const a = Math.max(8, window.innerWidth - n.offsetWidth - 8), s = Math.max(8, window.innerHeight - n.offsetHeight - 8);
52
+ p = {
53
+ x: Math.min(Math.max(8, t), a),
54
+ y: Math.min(Math.max(8, e), s)
55
+ }, n.style.left = `${p.x}px`, n.style.top = `${p.y}px`;
56
+ }, w = () => {
57
+ if (!r) return;
58
+ const t = [...l()].reverse();
59
+ if (b = new Map(t.map((e) => [e.id, e])), u && !b.has(u) && g(), r.replaceChildren(), t.length === 0) {
60
+ r.append(
61
+ i(
62
+ "div",
63
+ "color:var(--t-text-3,#999);padding:4px 0;",
64
+ "没有打开的浮层"
65
+ )
66
+ );
67
+ return;
68
+ }
69
+ t.forEach((e, a) => {
70
+ const s = i(
71
+ "div",
72
+ "display:grid;grid-template-columns:20px 1fr auto;gap:8px;align-items:baseline;padding:3px 0;border-top:1px solid var(--t-line-5,#eee);"
73
+ );
74
+ s.dataset.overlayId = e.id, e.getElement() && (s.style.cursor = "crosshair"), s.append(
75
+ i("span", "color:var(--t-text-3,#999);", String(t.length - a)),
76
+ i(
77
+ "span",
78
+ "min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--t-text-1,#141414);",
79
+ e.name ?? e.id
80
+ ),
81
+ i(
82
+ "span",
83
+ "font-variant-numeric:tabular-nums;color:var(--t-text-1,#141414);font-weight:500;",
84
+ String(e.zIndex)
85
+ )
86
+ );
87
+ const c = H(e);
88
+ c && s.append(
89
+ i("span", ""),
90
+ i(
91
+ "span",
92
+ "grid-column:span 2;color:var(--t-text-3,#999);font-size:11px;",
93
+ c
94
+ )
95
+ ), r?.append(s);
96
+ });
97
+ }, G = (t) => {
98
+ if (!n || t.button !== 0) return;
99
+ const e = t.currentTarget, a = t.clientX - p.x, s = t.clientY - p.y;
100
+ e.setPointerCapture?.(t.pointerId);
101
+ const c = (D) => y(D.clientX - a, D.clientY - s), h = () => {
102
+ e.removeEventListener("pointermove", c), e.removeEventListener("pointerup", h), e.removeEventListener("pointercancel", h), m({ opened: !0, ...p });
103
+ };
104
+ e.addEventListener("pointermove", c), e.addEventListener("pointerup", h), e.addEventListener("pointercancel", h), t.preventDefault();
105
+ }, S = () => {
106
+ if (n || typeof document > "u" || !document.body) return;
107
+ n = i(
108
+ "div",
109
+ `position:fixed;z-index:${_};width:280px;max-height:60vh;display:flex;flex-direction:column;background:var(--t-fill-8,#fff);color:var(--t-text-1,#141414);border:1px solid var(--t-line-4,#ddd);border-radius:8px;box-shadow:var(--t-shadow-2,0 4px 16px rgba(0,0,0,.15));font:12px/18px system-ui,sans-serif;`
110
+ ), n.setAttribute(I, ""), n.setAttribute("role", "complementary"), n.setAttribute("aria-label", "Overlay stack debugger");
111
+ const t = i(
112
+ "div",
113
+ "display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:move;user-select:none;touch-action:none;border-bottom:1px solid var(--t-line-5,#eee);font-weight:500;"
114
+ );
115
+ t.append(i("span", "flex:1;", "层级栈(栈顶 → 栈底)"));
116
+ const e = i(
117
+ "button",
118
+ "border:0;background:none;cursor:pointer;color:var(--t-text-2,#666);font-size:16px;line-height:1;padding:0 2px;",
119
+ "×"
120
+ );
121
+ e.type = "button", e.setAttribute("aria-label", "Close overlay stack debugger"), e.addEventListener("pointerdown", (s) => s.stopPropagation()), e.addEventListener("click", () => L()), t.append(e), t.addEventListener("pointerdown", G), r = i("div", "overflow:auto;padding:4px 10px 8px;"), r.addEventListener("mouseover", (s) => {
122
+ const c = s.target.closest(
123
+ "[data-overlay-id]"
124
+ );
125
+ c?.dataset.overlayId ? O(c.dataset.overlayId) : g();
126
+ }), r.addEventListener("mouseleave", g), n.append(t, r), document.body.append(n);
127
+ const a = A();
128
+ y(
129
+ a.x ?? window.innerWidth - n.offsetWidth - 16,
130
+ a.y ?? 16
131
+ ), m({ opened: !0, ...p }), v = d(w), w();
132
+ }, L = () => {
133
+ g(), v?.(), v = null, n?.remove(), n = null, r = null, m({ opened: !1, ...p });
134
+ };
135
+ return { open: S, close: L };
136
+ }
137
+ function T(d) {
138
+ if (typeof window > "u") return;
139
+ const l = M(d);
140
+ Object.defineProperty(window, $, {
141
+ value: l,
142
+ configurable: !0,
143
+ writable: !0
144
+ }), A().opened && window.setTimeout(l.open, 0);
145
+ }
146
+ export {
147
+ I as OVERLAY_DEBUG_ATTRIBUTE,
148
+ $ as OVERLAY_DEBUG_GLOBAL,
149
+ M as createOverlayStackDebug,
150
+ T as installOverlayStackDebug
151
+ };
@@ -0,0 +1,38 @@
1
+ import type { OverlayCloseReason } from './types';
2
+ /** 每次渲染都会刷新的部分,栈里按引用读最新值,不因为它们变化而重新登记。 */
3
+ export interface OverlayHandlers {
4
+ close?: (reason: OverlayCloseReason) => void;
5
+ closeOnEscape: boolean;
6
+ closeOnClickOutside: boolean;
7
+ getElement: () => HTMLElement | null;
8
+ getInsideElements: () => Array<HTMLElement | null>;
9
+ name?: string;
10
+ }
11
+ export interface OverlayRegistration {
12
+ id: string;
13
+ /** 外面包着的浮层 id,从外到内 */
14
+ ancestors: readonly string[];
15
+ explicitZIndex: number | undefined;
16
+ tier: number;
17
+ handlersRef: {
18
+ readonly current: OverlayHandlers;
19
+ };
20
+ }
21
+ /**
22
+ * 按最终数值归档:小于 10000 是普通层,10000 以上按千位分档。
23
+ * 所以直接传 `zIndex={15002}` 的引导气泡归 15000 档,不会把普通层顶高。
24
+ */
25
+ export declare function toTierBucket(zIndex: number): number;
26
+ export declare function warnIfInvalidTier(tier: number): void;
27
+ /**
28
+ * 登记一个打开的浮层,返回只清理本次登记的注销函数。
29
+ *
30
+ * 新条目按"它下面的层"算层级;排在它后面的条目(同一次提交里先登记的子层)
31
+ * 重新计算,这样父子一起打开时子层仍在父层之上。
32
+ */
33
+ export declare function registerOverlay(registration: OverlayRegistration): () => void;
34
+ export declare function subscribeOverlayStack(listener: () => void): () => void;
35
+ export declare function getOverlayZIndex(id: string): number | undefined;
36
+ export declare function forgetOverlay(id: string): void;
37
+ /** 仅供测试:当前栈里的条目数 */
38
+ export declare function getOverlayStackSize(): number;
@@ -0,0 +1,137 @@
1
+ "use client";
2
+ import { isDev as g } from "../../common/is-dev.js";
3
+ import { OVERLAY_TIER_NOTIFICATION as E, OVERLAY_TOP_MIN as c, OVERLAY_TOP_MAX as f, OVERLAY_BASE as m } from "./constants.js";
4
+ import { OVERLAY_DEBUG_ATTRIBUTE as x, installOverlayStackDebug as w } from "./overlay-stack-debug.js";
5
+ const i = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Set();
6
+ let k = 0;
7
+ function u(e) {
8
+ return e < c ? m : Math.floor(e / 1e3) * 1e3;
9
+ }
10
+ function z(e) {
11
+ if (e === E) {
12
+ console.warn(
13
+ `[@wisdomgarden/torque] overlay tier ${e} is reserved for notifications. Pick another multiple of 1000 in [${c}, ${f}).`
14
+ );
15
+ return;
16
+ }
17
+ e === m || e >= c && e < f && e % 1e3 === 0 || console.warn(
18
+ `[@wisdomgarden/torque] overlay tier ${e} is invalid. Use OVERLAY_BASE (${m}) or a multiple of 1000 in [${c}, ${f}) other than ${E}.`
19
+ );
20
+ }
21
+ function d() {
22
+ const e = Array.from(i.values()), t = /* @__PURE__ */ new Map();
23
+ for (const n of e) {
24
+ let r = n.seq;
25
+ for (const o of e)
26
+ o.ancestors.includes(n.id) && (r = Math.min(r, o.seq));
27
+ t.set(n.id, r);
28
+ }
29
+ return e.sort(
30
+ (n, r) => t.get(n.id) - t.get(r.id) || n.ancestors.length - r.ancestors.length || n.seq - r.seq
31
+ );
32
+ }
33
+ function A(e, t) {
34
+ if (e.explicitZIndex !== void 0) return e.explicitZIndex;
35
+ const n = u(e.tier);
36
+ let r = -1 / 0;
37
+ for (const s of t)
38
+ s.bucket === n && (r = Math.max(r, s.zIndex));
39
+ const o = Math.max(e.tier, r + 1);
40
+ return g() && u(o) !== n && console.warn(
41
+ `[@wisdomgarden/torque] overlay "${e.handlersRef.current.name ?? e.id}" resolved z-index ${o}, which overflows its tier ${e.tier}. Too many overlays are open at once in this tier.`
42
+ ), o;
43
+ }
44
+ function O() {
45
+ h.forEach((e) => e());
46
+ }
47
+ function L() {
48
+ return d().map((e) => {
49
+ const t = e.handlersRef.current;
50
+ return {
51
+ id: e.id,
52
+ name: t.name,
53
+ zIndex: e.zIndex,
54
+ tierBucket: e.bucket,
55
+ closable: !!t.close,
56
+ closeOnEscape: t.closeOnEscape,
57
+ closeOnClickOutside: t.closeOnClickOutside,
58
+ getElement: t.getElement
59
+ };
60
+ });
61
+ }
62
+ function v(e) {
63
+ return e.composedPath().some(
64
+ (t) => t instanceof Element && t.hasAttribute(x)
65
+ );
66
+ }
67
+ function I(e) {
68
+ if (e.key !== "Escape" || e.isComposing || v(e)) return;
69
+ const t = e.target;
70
+ if (t instanceof Element && t.getAttribute("data-mantine-stop-propagation") === "true")
71
+ return;
72
+ const n = d().reverse().find((o) => o.handlersRef.current.close);
73
+ if (!n) return;
74
+ e.preventDefault(), e.stopImmediatePropagation();
75
+ const r = n.handlersRef.current;
76
+ r.closeOnEscape && r.close?.("escape");
77
+ }
78
+ function R(e, t) {
79
+ const n = t.getElement();
80
+ return n && e.includes(n) ? !0 : t.getInsideElements().some((r) => !!r && e.includes(r));
81
+ }
82
+ function a(e) {
83
+ if (v(e)) return;
84
+ const t = e.composedPath(), n = d().reverse().filter((r) => r.handlersRef.current.close);
85
+ for (const r of n) {
86
+ const o = r.handlersRef.current;
87
+ if (R(t, o) || !o.closeOnClickOutside) return;
88
+ o.close?.("outside");
89
+ }
90
+ }
91
+ function b() {
92
+ document.addEventListener("keydown", I), document.addEventListener("mousedown", a, !0), document.addEventListener("touchstart", a, !0);
93
+ }
94
+ function T() {
95
+ document.removeEventListener("keydown", I), document.removeEventListener("mousedown", a, !0), document.removeEventListener("touchstart", a, !0);
96
+ }
97
+ function M(e) {
98
+ i.size === 0 && b();
99
+ const t = {
100
+ ...e,
101
+ seq: k++,
102
+ zIndex: e.explicitZIndex ?? e.tier,
103
+ bucket: u(e.explicitZIndex ?? e.tier)
104
+ };
105
+ i.set(t.id, t);
106
+ const n = d(), r = n.indexOf(t);
107
+ for (let o = r; o < n.length; o++) {
108
+ const s = n[o], l = A(s, n.slice(0, o));
109
+ s.zIndex = l, s.bucket = u(l), p.set(s.id, l);
110
+ }
111
+ return O(), () => {
112
+ i.get(t.id) === t && (i.delete(t.id), i.size === 0 && T(), O());
113
+ };
114
+ }
115
+ function $(e) {
116
+ return h.add(e), () => {
117
+ h.delete(e);
118
+ };
119
+ }
120
+ function S(e) {
121
+ return p.get(e);
122
+ }
123
+ function D(e) {
124
+ p.delete(e);
125
+ }
126
+ g() && w({
127
+ subscribe: $,
128
+ getSnapshot: L
129
+ });
130
+ export {
131
+ D as forgetOverlay,
132
+ S as getOverlayZIndex,
133
+ M as registerOverlay,
134
+ $ as subscribeOverlayStack,
135
+ u as toTierBucket,
136
+ z as warnIfInvalidTier
137
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export interface OverlayTierScopeProps {
3
+ /** 里面不传档位的浮层默认进这一档。 */
4
+ readonly tier: number;
5
+ readonly children?: React.ReactNode;
6
+ }
7
+ /**
8
+ * 只告诉里面的 `useOverlayLayer` "默认用哪一档"。
9
+ * 不算数值、不进栈、不渲染任何 DOM;内层 scope 覆盖外层,显式传 `tier` 的浮层不受影响。
10
+ */
11
+ export declare function OverlayTierScope({ tier, children }: OverlayTierScopeProps): React.JSX.Element;
12
+ export declare function useOverlayScopeTier(): number | null;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ import { useContext as i, createContext as n } from "react";
4
+ import { isDev as u } from "../../common/is-dev.js";
5
+ import { warnIfInvalidTier as f } from "./overlay-stack.js";
6
+ const r = n(null);
7
+ function p({ tier: e, children: o }) {
8
+ return u() && f(e), /* @__PURE__ */ t(r.Provider, { value: e, children: o });
9
+ }
10
+ function v() {
11
+ return i(r);
12
+ }
13
+ export {
14
+ p as OverlayTierScope,
15
+ v as useOverlayScopeTier
16
+ };
@@ -0,0 +1,63 @@
1
+ import type { RefObject } from 'react';
2
+ /** 浮层被关闭的原因:按了 Escape,或点在了浮层外面。 */
3
+ export type OverlayCloseReason = 'escape' | 'outside';
4
+ export interface OverlayLayerOptions {
5
+ /** 是否打开。`true` 入栈、`false` 立刻出栈(不等关闭动画)。常驻元素传 `true`。 */
6
+ opened: boolean;
7
+ /**
8
+ * 显式层级。传了就直接用、不参与计算,但仍登记进栈,并按数值归档
9
+ * (小于 10000 归普通层,10000 以上按千位归档)。
10
+ */
11
+ zIndex?: number;
12
+ /**
13
+ * 档位基准。不传取外层 `OverlayTierScope`,再没有就是普通层 `OVERLAY_BASE`。
14
+ * 业务顶层档位只能是 `[10000, 16000)` 之间 1000 的整数倍,14000 保留给通知。
15
+ */
16
+ tier?: number;
17
+ /**
18
+ * 关闭函数。传了才参与 Escape 关和点外面关;不传 = 透明,只占层级,
19
+ * Escape 和点外面都当它不存在(Tooltip、悬浮按钮、AI 侧边栏)。
20
+ */
21
+ close?: (reason: OverlayCloseReason) => void;
22
+ /**
23
+ * 本层是参与关闭的最上层时,按 Escape 是否关闭它。
24
+ * `false` 时既不关它、也不关下面的层(吞掉这次按键)。
25
+ * @default true
26
+ */
27
+ closeOnEscape?: boolean;
28
+ /**
29
+ * 点在本层外面时是否关闭它。`false` 时它和它下面的层都不关。
30
+ * @default true
31
+ */
32
+ closeOnClickOutside?: boolean;
33
+ /** 额外算作"本层里面"的节点,例如 Popover 的触发按钮。 */
34
+ insideRefs?: ReadonlyArray<RefObject<HTMLElement | null>>;
35
+ /** 调试用名字。 */
36
+ name?: string;
37
+ }
38
+ export interface OverlayLayerResult {
39
+ /** 算好的层级,贴到浮层真正浮起来的那个节点上。 */
40
+ zIndex: number;
41
+ /**
42
+ * 贴到浮层面板上,用于判断点击是否在浮层里面。
43
+ * 传了 `close` 就必须贴;弹窗要贴在面板上,不能贴在含遮罩的根节点上。
44
+ */
45
+ ref: (element: HTMLElement | null) => void;
46
+ }
47
+ /** 调试快照里的一条:栈中一个打开着的浮层。只在开发环境有内容。 */
48
+ export interface OverlayStackDebugEntry {
49
+ /** hook 内部 id */
50
+ id: string;
51
+ /** 登记时传的 `name`,没传为 `undefined` */
52
+ name: string | undefined;
53
+ /** 当前层级 */
54
+ zIndex: number;
55
+ /** 归档的档位基准(普通层 200,顶层按千位) */
56
+ tierBucket: number;
57
+ /** 是否传了 `close`:`false` 即透明层,不参与 Escape 与点外面 */
58
+ closable: boolean;
59
+ closeOnEscape: boolean;
60
+ closeOnClickOutside: boolean;
61
+ /** 取浮层面板节点(没贴 ref 的返回 null),调试面板用来高亮 */
62
+ getElement: () => HTMLElement | null;
63
+ }
@@ -0,0 +1,21 @@
1
+ interface MantineOverlayProps {
2
+ opened: boolean;
3
+ onClose: () => void;
4
+ zIndex?: string | number;
5
+ closeOnClickOutside?: boolean;
6
+ closeOnEscape?: boolean;
7
+ }
8
+ /**
9
+ * 组件库内部用:让 Mantine 薄封装(ModalDeprecated / Drawer / BaseBottomDrawer)接入层级模块。
10
+ *
11
+ * 调用方要把 `rootRef` 贴到 Mantine 组件上、把 `zIndex` 传进去,并给 Mantine 传
12
+ * `closeOnEscape={false}` `closeOnClickOutside={false}`:Escape 与点遮罩统一由层级模块处理,
13
+ * 否则一次操作会被处理两遍。Mantine 不暴露面板节点,只能从根节点里找;遮罩也在根节点里,
14
+ * 所以不能直接拿根节点判断"点在里面"。
15
+ */
16
+ export declare function useMantineOverlayLayer(component: 'Modal' | 'Drawer', props: MantineOverlayProps, name: string): {
17
+ rootRef: import("react").RefObject<HTMLDivElement | null>;
18
+ zIndex: number;
19
+ id: string;
20
+ };
21
+ export {};
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { useProps as s } from "@mantine/core";
3
+ import { useRef as u } from "react";
4
+ import { useOverlayLayerInternal as i } from "./use-overlay-layer.js";
5
+ const d = { closeOnClickOutside: !0, closeOnEscape: !0 };
6
+ function f(t, e, l) {
7
+ const { closeOnClickOutside: r, closeOnEscape: c } = s(
8
+ t,
9
+ d,
10
+ e
11
+ ), n = u(null), o = i({
12
+ opened: e.opened,
13
+ zIndex: e.zIndex === void 0 ? void 0 : Number(e.zIndex),
14
+ close: () => e.onClose(),
15
+ closeOnEscape: c,
16
+ closeOnClickOutside: r,
17
+ getElement: () => n.current?.querySelector('[role="dialog"]') ?? null,
18
+ name: l
19
+ });
20
+ return { rootRef: n, zIndex: o.zIndex, id: o.id };
21
+ }
22
+ export {
23
+ f as useMantineOverlayLayer
24
+ };
@@ -0,0 +1,26 @@
1
+ import type { OverlayLayerOptions, OverlayLayerResult } from './types';
2
+ interface InternalOverlayLayerOptions extends OverlayLayerOptions {
3
+ /**
4
+ * 拿不到面板节点、没法贴 `ref` 时(Mantine 薄封装)按需查找面板。
5
+ * 不对外:业务浮层一律贴 `ref`。
6
+ */
7
+ getElement?: () => HTMLElement | null;
8
+ }
9
+ /** 组件库内部版本:额外返回 id,供 `OverlayParentProvider` 记录祖先链。 */
10
+ export declare function useOverlayLayerInternal(options: InternalOverlayLayerOptions): OverlayLayerResult & {
11
+ id: string;
12
+ };
13
+ /**
14
+ * 浮层层级 hook:算 z-index 并登记进全局栈,让之后打开的浮层排在上面;
15
+ * 传了 `close` 就参与 Escape 关(只关栈顶)和点外面关(从栈顶往下逐层)。
16
+ *
17
+ * 不需要被任何 Provider 包住,业务自定义浮层和组件库浮层遵守同一套规则。
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const { zIndex, ref } = useOverlayLayer({ opened, close: () => setOpened(false) });
22
+ * return <div ref={ref} style={{ zIndex }} className="fixed inset-x-0 bottom-0">…</div>;
23
+ * ```
24
+ */
25
+ export declare function useOverlayLayer(options: OverlayLayerOptions): OverlayLayerResult;
26
+ export {};
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { useIsomorphicEffect as v } from "@mantine/hooks";
3
+ import { useId as w, useRef as y, useEffect as m, useSyncExternalStore as A, useCallback as R } from "react";
4
+ import { isDev as I } from "../../common/is-dev.js";
5
+ import { OVERLAY_BASE as T } from "./constants.js";
6
+ import { useOverlayAncestors as b } from "./overlay-parent-context.js";
7
+ import { warnIfInvalidTier as k, subscribeOverlayStack as L, getOverlayZIndex as _, registerOverlay as z, forgetOverlay as C } from "./overlay-stack.js";
8
+ import { useOverlayScopeTier as N } from "./overlay-tier-scope.js";
9
+ const Z = 1e3, D = () => {
10
+ };
11
+ function M(s) {
12
+ const {
13
+ opened: t,
14
+ zIndex: r,
15
+ tier: o,
16
+ close: d,
17
+ closeOnEscape: f = !0,
18
+ closeOnClickOutside: p = !0,
19
+ insideRefs: O,
20
+ name: c,
21
+ getElement: g
22
+ } = s, x = N(), i = o ?? x ?? T, a = b().join("|"), e = w(), l = y(null), u = y({
23
+ closeOnEscape: f,
24
+ closeOnClickOutside: p,
25
+ getElement: () => l.current,
26
+ getInsideElements: () => []
27
+ });
28
+ v(() => {
29
+ u.current = {
30
+ close: d,
31
+ closeOnEscape: f,
32
+ closeOnClickOutside: p,
33
+ getElement: g ?? (() => l.current),
34
+ getInsideElements: () => (O ?? []).map((n) => n.current),
35
+ name: c
36
+ };
37
+ }), m(() => {
38
+ I() && o !== void 0 && k(o);
39
+ }, [o]);
40
+ const S = A(
41
+ L,
42
+ () => _(e),
43
+ D
44
+ );
45
+ v(() => {
46
+ if (t)
47
+ return z({
48
+ id: e,
49
+ ancestors: a ? a.split("|") : [],
50
+ explicitZIndex: r,
51
+ tier: i,
52
+ handlersRef: u
53
+ });
54
+ }, [t, r, i, e, a]), m(() => () => C(e), [e]);
55
+ const E = !!d;
56
+ m(() => {
57
+ if (!I() || !t || !E) return;
58
+ const n = window.setTimeout(() => {
59
+ u.current.getElement() || console.warn(
60
+ `[@wisdomgarden/torque] overlay "${c ?? e}" is open and closable but its \`ref\` is not attached to any element, so every click inside it counts as a click outside. Attach the returned \`ref\` to the panel.`
61
+ );
62
+ }, Z);
63
+ return () => window.clearTimeout(n);
64
+ }, [t, E, c, e]);
65
+ const h = R((n) => {
66
+ l.current = n;
67
+ }, []);
68
+ return { zIndex: r ?? S ?? i, ref: h, id: e };
69
+ }
70
+ function W(s) {
71
+ const { zIndex: t, ref: r } = M(s);
72
+ return { zIndex: t, ref: r };
73
+ }
74
+ export {
75
+ W as useOverlayLayer,
76
+ M as useOverlayLayerInternal
77
+ };
@@ -7,7 +7,6 @@ export declare function useAnimatedMount(opened: boolean, keepMounted?: boolean)
7
7
  };
8
8
  export declare function usePopoverFocus(trigger: PopoverTrigger, opened: boolean, animState: 'open' | 'closing', mounted: boolean, floatingRef: React.RefObject<HTMLDivElement | null>, getFloatingScopeElements: () => HTMLElement[], initialFocusRef?: React.RefObject<HTMLElement | null>, preventAutoFocus?: boolean): void;
9
9
  export declare function getFocusableElements(containers: Array<HTMLElement | null>): HTMLElement[];
10
- export declare function useEscapeClose(closeOnEscape: boolean, opened: boolean, close: () => void, referenceRef: React.RefObject<HTMLElement | null>, id: string, depth: number, restoreFocus?: () => void): void;
11
10
  export declare function useArrowStyle(withArrow: boolean, arrowData: {
12
11
  x?: number;
13
12
  y?: number;