haze-ui 1.22.0 → 1.24.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.
Files changed (78) hide show
  1. package/README.md +7 -0
  2. package/dist/components/BottomSheet/BottomSheet.js +33 -16
  3. package/dist/components/Collapsible/Collapsible.js +34 -27
  4. package/dist/components/Combobox/Combobox.js +2 -1
  5. package/dist/components/ConfirmDialog/ConfirmDialog.js +60 -42
  6. package/dist/components/ContextMenu/ContextMenu.js +2 -1
  7. package/dist/components/ContextMenu/ContextMenuContent.js +33 -23
  8. package/dist/components/Datepicker/DatepickerCore.js +2 -1
  9. package/dist/components/Dialog/Dialog.js +40 -21
  10. package/dist/components/Drawer/Drawer.js +37 -18
  11. package/dist/components/DropdownMenu/DropdownMenu.js +27 -25
  12. package/dist/components/DropdownMenu/DropdownMenuContent.js +2 -2
  13. package/dist/components/Menu/Menu.js +43 -35
  14. package/dist/components/Popover/Popover.js +27 -25
  15. package/dist/components/Toast/Toast.js +25 -20
  16. package/dist/components/Toast/ToastContainer.js +31 -24
  17. package/dist/components/Tooltip/Tooltip.js +37 -34
  18. package/dist/css/alert.css +1 -1
  19. package/dist/css/approval-card.css +1 -1
  20. package/dist/css/async-section.css +1 -1
  21. package/dist/css/badge.css +1 -1
  22. package/dist/css/banner.css +1 -1
  23. package/dist/css/bottom-sheet.css +1 -1
  24. package/dist/css/chat-message.css +1 -1
  25. package/dist/css/code-block.css +1 -1
  26. package/dist/css/collapsible.css +1 -1
  27. package/dist/css/combobox.css +1 -1
  28. package/dist/css/confirm-dialog.css +1 -1
  29. package/dist/css/context-menu.css +2 -2
  30. package/dist/css/conversation-list.css +1 -1
  31. package/dist/css/datepicker.css +1 -1
  32. package/dist/css/dialog.css +1 -1
  33. package/dist/css/diff-viewer.css +1 -1
  34. package/dist/css/drawer.css +1 -1
  35. package/dist/css/dropdown-menu.css +2 -2
  36. package/dist/css/inline-edit.css +1 -1
  37. package/dist/css/log-viewer.css +1 -1
  38. package/dist/css/markdown-renderer.css +1 -1
  39. package/dist/css/menu.css +1 -1
  40. package/dist/css/navigation-bar.css +1 -1
  41. package/dist/css/popover.css +1 -1
  42. package/dist/css/step-timeline.css +1 -1
  43. package/dist/css/tag-group.css +1 -1
  44. package/dist/css/tag-input.css +1 -1
  45. package/dist/css/tag.css +1 -1
  46. package/dist/css/toast.css +1 -1
  47. package/dist/css/token-counter.css +1 -1
  48. package/dist/css/tokens.css +2 -1
  49. package/dist/css/tool-call-card.css +1 -1
  50. package/dist/css/tooltip.css +1 -1
  51. package/dist/haze-ui.css +36 -35
  52. package/dist/tokens/index.js +4 -1
  53. package/dist/tokens/motion.js +6 -0
  54. package/dist/tokens/oklch.js +117 -0
  55. package/dist/tokens/palette.js +327 -0
  56. package/dist/tokens/registry.js +154 -145
  57. package/dist/types/components/BottomSheet/BottomSheet.d.ts +3 -3
  58. package/dist/types/components/Collapsible/Collapsible.d.ts +1 -1
  59. package/dist/types/components/ConfirmDialog/ConfirmDialog.d.ts +3 -3
  60. package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +7 -1
  61. package/dist/types/components/Popover/Popover.d.ts +7 -1
  62. package/dist/types/components/Toast/Toast.d.ts +3 -3
  63. package/dist/types/components/Tooltip/Tooltip.d.ts +4 -1
  64. package/dist/types/tokens/index.d.ts +5 -0
  65. package/dist/types/tokens/motion.d.ts +1 -0
  66. package/dist/types/tokens/oklch.d.ts +35 -0
  67. package/dist/types/tokens/palette.d.ts +28 -0
  68. package/dist/types/utils/collision.d.ts +62 -0
  69. package/dist/types/utils/floating.d.ts +95 -19
  70. package/dist/types/utils/focus-scope.d.ts +25 -0
  71. package/dist/types/utils/focus.d.ts +23 -0
  72. package/dist/types/utils/presence.d.ts +22 -0
  73. package/dist/utils/collision.js +73 -0
  74. package/dist/utils/floating.js +195 -150
  75. package/dist/utils/focus-scope.js +63 -0
  76. package/dist/utils/focus.js +34 -0
  77. package/dist/utils/presence.js +72 -0
  78. package/package.json +4 -2
@@ -1,203 +1,248 @@
1
1
 
2
2
  import { classnames as e } from "./classnames.js";
3
+ import { whenExitSettles as t } from "./presence.js";
4
+ import { computeFloatingPosition as n, resolvePadding as r } from "./collision.js";
3
5
  /* empty css */
4
- import { jsx as t } from "react/jsx-runtime";
5
- import { useCallback as n, useEffect as r, useId as i, useRef as a, useState as o } from "react";
6
+ import { jsx as i } from "react/jsx-runtime";
7
+ import { useCallback as a, useEffect as o, useId as s, useRef as c, useState as l } from "react";
6
8
  //#region src/lib/utils/floating.tsx
7
- var s = 500;
8
- function c() {
9
+ var u = 500;
10
+ function d() {
9
11
  return typeof HTMLElement < "u" && "popover" in HTMLElement.prototype;
10
12
  }
11
- function l() {
12
- return c() && typeof CSS < "u" && typeof CSS.supports == "function" && CSS.supports("anchor-name: --haze-floating-probe");
13
+ function f() {
14
+ return d() && typeof CSS < "u" && typeof CSS.supports == "function" && CSS.supports("anchor-name: --haze-floating-probe");
13
15
  }
14
- var u = "haze-floating__floatingNative", d = "haze-floating__floatingAnchored", f = "haze-floating__floatingFixed", p = "haze-floating__floatingHidden", m = "haze-floating__anchoredBottom", h = "haze-floating__anchoredBottomSpan", g = "haze-floating__anchoredBottomCenter", _ = "haze-floating__anchoredBottomEnd", v = "haze-floating__anchoredTop", y = "haze-floating__anchoredLeft", b = "haze-floating__anchoredRight", x = "haze-floating__fallbackBottom", S = x, C = "haze-floating__fallbackBottomCenter", w = "haze-floating__fallbackBottomEnd", T = "haze-floating__fallbackTop", E = "haze-floating__fallbackLeft", D = "haze-floating__fallbackRight", O = "haze-floating__gapBelow", k = "haze-floating__gapAbove", A = "haze-floating__gapBefore", j = "haze-floating__gapAfter", M = {
15
- bottom: m,
16
- "bottom-span": h,
17
- "bottom-center": g,
18
- "bottom-end": _,
19
- top: v,
20
- left: y,
21
- right: b
22
- }, N = {
23
- bottom: x,
24
- "bottom-span": S,
25
- "bottom-center": C,
26
- "bottom-end": w,
27
- top: T,
28
- left: E,
29
- right: D
30
- }, P = {
31
- bottom: O,
32
- "bottom-span": O,
33
- "bottom-center": O,
16
+ var p = "haze-floating__floatingNative", m = "haze-floating__floatingAnchored", h = "haze-floating__floatingFixed", g = "haze-floating__floatingHidden", _ = "haze-floating__floatingAnimated", v = "haze-floating__anchoredBottom", y = "haze-floating__anchoredBottomSpan", b = "haze-floating__anchoredBottomCenter", x = "haze-floating__anchoredBottomEnd", S = "haze-floating__anchoredTop", C = "haze-floating__anchoredLeft", w = "haze-floating__anchoredRight", T = "haze-floating__fallbackBottom", E = T, D = "haze-floating__fallbackBottomCenter", O = "haze-floating__fallbackBottomEnd", k = "haze-floating__fallbackTop", A = "haze-floating__fallbackLeft", j = "haze-floating__fallbackRight", M = "haze-floating__gapBelow", N = "haze-floating__gapAbove", P = "haze-floating__gapBefore", F = "haze-floating__gapAfter", I = {
17
+ bottom: v,
18
+ "bottom-span": y,
19
+ "bottom-center": b,
20
+ "bottom-end": x,
21
+ top: S,
22
+ left: C,
23
+ right: w
24
+ }, L = {
25
+ bottom: T,
26
+ "bottom-span": E,
27
+ "bottom-center": D,
34
28
  "bottom-end": O,
35
29
  top: k,
36
30
  left: A,
37
31
  right: j
32
+ }, R = {
33
+ bottom: M,
34
+ "bottom-span": M,
35
+ "bottom-center": M,
36
+ "bottom-end": M,
37
+ top: N,
38
+ left: P,
39
+ right: F
38
40
  };
39
- function F({ open: e, setOpen: t, triggerRef: m, panelRef: h }) {
40
- let g = `--haze-floating-${i().replace(/[^a-zA-Z0-9]/g, "")}`, _ = c(), v = l(), y = a(!1), [b, x] = o(!1), S = a(null), C = a(-Infinity), w = a(-Infinity);
41
- r(() => {
42
- let n = h.current;
43
- if (!n || !_) return;
44
- n !== S.current && (S.current = n, y.current = !1, x(!1));
45
- let r = (n) => {
46
- let r = n.newState;
47
- y.current = r === "open", x(y.current), r === "closed" && e ? (performance.now() - C.current < s && (w.current = performance.now()), C.current = -Infinity, t(!1)) : r === "open" && !e && t(!0);
41
+ function z({ open: e, setOpen: n, triggerRef: r, panelRef: i, animated: g, collision: _ }) {
42
+ let v = `--haze-floating-${s().replace(/[^a-zA-Z0-9]/g, "")}`, y = d(), b = f(), [x, S] = l(!e);
43
+ o(() => {
44
+ e && S(!1);
45
+ }, [e]);
46
+ let C = c(!1), [w, T] = l(!1), E = c(null), D = c(-Infinity), O = c(-Infinity), k = c(null);
47
+ o(() => {
48
+ let r = i.current;
49
+ if (!r || !y) return;
50
+ r !== E.current && (E.current = r, C.current = !1, T(!1));
51
+ let a = !0, o = () => {
52
+ k.current = { el: r }, r.hidePopover();
53
+ }, s = () => {
54
+ if (!(!C.current || r !== i.current)) {
55
+ if (g) {
56
+ let e = () => {
57
+ !a || !C.current || r !== i.current || o();
58
+ }, n = t(r);
59
+ n ? n.then(e) : e();
60
+ } else o();
61
+ }
62
+ }, c = (t) => {
63
+ let i = t.newState;
64
+ if (C.current = i === "open", T(C.current), i === "closed") {
65
+ g && S(!0);
66
+ let t = k.current?.el === r;
67
+ if (k.current = null, t) {
68
+ e && r.showPopover();
69
+ return;
70
+ }
71
+ e && (performance.now() - D.current < u && (O.current = performance.now()), D.current = -Infinity, n(!1));
72
+ } else e || s();
73
+ };
74
+ return r.addEventListener("toggle", c), e ? C.current || r.showPopover() : s(), () => {
75
+ a = !1, r.removeEventListener("toggle", c);
48
76
  };
49
- return n.addEventListener("toggle", r), e && !y.current ? n.showPopover() : !e && y.current && n.hidePopover(), () => n.removeEventListener("toggle", r);
50
77
  }, [
51
- _,
78
+ y,
52
79
  e,
53
- t,
54
- h
55
- ]), r(() => {
56
- if (_ || !e) return;
57
- let n = (e) => e instanceof Node && !!(m.current?.contains(e) || h.current?.contains(e)), r = (e) => {
58
- n(e.target) || t(!1);
59
- }, i = (e) => {
60
- e.key === "Escape" && t(!1);
80
+ n,
81
+ i,
82
+ g
83
+ ]), o(() => {
84
+ if (y || !e) return;
85
+ let t = (e) => e instanceof Node && !!(r.current?.contains(e) || i.current?.contains(e)), a = (e) => {
86
+ t(e.target) || n(!1);
87
+ }, o = (e) => {
88
+ e.key === "Escape" && n(!1);
61
89
  };
62
- return document.addEventListener("pointerdown", r), document.addEventListener("keydown", i), () => {
63
- document.removeEventListener("pointerdown", r), document.removeEventListener("keydown", i);
90
+ return document.addEventListener("pointerdown", a), document.addEventListener("keydown", o), () => {
91
+ document.removeEventListener("pointerdown", a), document.removeEventListener("keydown", o);
64
92
  };
65
93
  }, [
66
- _,
94
+ y,
67
95
  e,
68
- t,
69
- m,
70
- h
96
+ n,
97
+ r,
98
+ i
99
+ ]), o(() => {
100
+ if (y || !g || e || x) return;
101
+ let n = !0, r = i.current, a = r ? t(r) : null, o = () => {
102
+ n && S(!0);
103
+ };
104
+ return a ? a.then(o) : o(), () => {
105
+ n = !1;
106
+ };
107
+ }, [
108
+ y,
109
+ g,
110
+ e,
111
+ x,
112
+ i
71
113
  ]);
72
- let T = n(() => {
73
- e && (C.current = performance.now());
74
- }, [e]), E = n(() => {
75
- if (performance.now() - w.current < s) {
76
- w.current = -Infinity;
114
+ let A = a(() => {
115
+ e && (D.current = performance.now());
116
+ }, [e]), j = a(() => {
117
+ if (performance.now() - O.current < u) {
118
+ O.current = -Infinity;
77
119
  return;
78
120
  }
79
- t((e) => !e);
80
- }, [t]);
121
+ n((e) => !e);
122
+ }, [n]);
81
123
  return {
82
124
  open: e,
83
- native: _,
84
- anchored: v,
85
- shown: _ ? b : e,
86
- anchorName: g,
87
- triggerStyle: v ? { anchorName: g } : void 0,
88
- onTriggerPointerDown: T,
89
- onTriggerClick: E,
125
+ native: y,
126
+ anchored: b,
127
+ shown: y ? w : e,
128
+ dataState: g ? e ? "open" : "closed" : void 0,
129
+ exited: g ? x : !e,
130
+ collision: _,
131
+ anchorName: v,
132
+ triggerStyle: b ? { anchorName: v } : void 0,
133
+ onTriggerPointerDown: A,
134
+ onTriggerClick: j,
90
135
  panelAttrs: {
91
- popover: _ ? "auto" : void 0,
92
- style: v ? { "--haze-floating-anchor": g } : void 0
136
+ popover: y ? "auto" : void 0,
137
+ style: b ? { "--haze-floating-anchor": v } : void 0
93
138
  },
94
139
  panelClasses: [
95
- _ && u,
96
- _ && v && d,
97
- _ && !v && f,
98
- !_ && !e && p
140
+ y && p,
141
+ y && b && m,
142
+ y && !b && h,
143
+ !y && !e && (!g || x) && "haze-floating__floatingHidden",
144
+ !!g && "haze-floating__floatingAnimated"
99
145
  ],
100
- triggerRef: m,
101
- panelRef: h
146
+ triggerRef: r,
147
+ panelRef: i
102
148
  };
103
149
  }
104
- function I(e, t) {
150
+ function B(e, t) {
105
151
  return t === "point" ? [] : [
106
- e.native && e.anchored && M[t],
107
- e.native && !e.anchored && P[t],
108
- !e.native && N[t]
152
+ e.native && e.anchored && I[t],
153
+ e.native && !e.anchored && R[t],
154
+ !e.native && L[t]
109
155
  ];
110
156
  }
111
- function L(e, t) {
157
+ function V(e, t) {
112
158
  return parseFloat(getComputedStyle(e)[t]) || 0;
113
159
  }
114
- function R(e, t, n) {
115
- if (n === "point") return;
116
- let r = t.getBoundingClientRect(), i = e.getBoundingClientRect(), a = {
160
+ function H(e, t, n, r, i) {
161
+ let a = r, o = Math.max(a, n - i - t);
162
+ return Math.min(Math.max(e, a), o) - e;
163
+ }
164
+ function U(e, t, i, a) {
165
+ if (i === "point") return;
166
+ let o = t.getBoundingClientRect(), s = e.getBoundingClientRect(), c = {
117
167
  width: window.innerWidth,
118
168
  height: window.innerHeight
119
- }, o = r.left + r.width / 2 - i.width / 2, s = r.top + r.height / 2 - i.height / 2, c = {
120
- below: L(e, "marginTop"),
121
- above: L(e, "marginBottom"),
122
- after: L(e, "marginLeft"),
123
- before: L(e, "marginRight")
124
- }, l = (e, t) => ({
125
- top: e === "bottom" ? r.bottom + c.below : r.top - i.height - c.above,
126
- left: t === "start" ? r.left : t === "end" ? r.right - i.width : o
127
- }), u = (e) => ({
128
- top: s,
129
- left: e === "right" ? r.right + c.after : r.left - i.width - c.before
130
- }), d = {
131
- bottom: {
132
- side: "bottom",
133
- align: "start"
134
- },
135
- "bottom-span": {
136
- side: "bottom",
137
- align: "start"
138
- },
139
- "bottom-center": {
140
- side: "bottom",
141
- align: "center"
142
- },
143
- "bottom-end": {
144
- side: "bottom",
145
- align: "end"
146
- },
147
- top: {
148
- side: "top",
149
- align: "center"
169
+ }, l = {
170
+ below: V(e, "marginTop"),
171
+ above: V(e, "marginBottom"),
172
+ before: V(e, "marginRight"),
173
+ after: V(e, "marginLeft")
174
+ }, { top: u, left: d } = n({
175
+ trigger: o,
176
+ panel: s,
177
+ viewport: c,
178
+ placement: i,
179
+ gap: l,
180
+ strategy: {
181
+ flip: a?.flip ?? !0,
182
+ shift: a?.shift ?? !0,
183
+ padding: r(a?.collisionPadding)
150
184
  }
151
- }, { top: f, left: p } = n === "left" || n === "right" ? u(n) : l(d[n].side, d[n].align);
152
- if (n === "left" || n === "right") {
153
- let e = n === "right" ? p + i.width > a.width : p < 0, t = n === "right" ? r.left - i.width - c.before >= 0 : r.right + i.width + c.after <= a.width;
154
- e && t && ({top: f, left: p} = u(n === "right" ? "left" : "right"));
155
- } else {
156
- let { side: e, align: t } = d[n], o = e === "bottom" ? f + i.height > a.height : f < 0, s = e === "bottom" ? r.top - i.height - c.above >= 0 : r.bottom + i.height + c.below <= a.height;
157
- o && s && ({top: f, left: p} = l(e === "bottom" ? "top" : "bottom", t));
158
- }
159
- f = Math.min(Math.max(f, 0), Math.max(0, a.height - i.height)), p = Math.min(Math.max(p, 0), Math.max(0, a.width - i.width)), e.style.top = `${f}px`, e.style.left = `${p}px`;
185
+ });
186
+ e.style.top = `${u}px`, e.style.left = `${d}px`;
160
187
  }
161
- function z({ behavior: e, placement: t }) {
162
- let { native: n, anchored: i, open: a, triggerRef: o, panelRef: s } = e;
163
- r(() => {
164
- if (!n || i || t === "point" || !a) return;
165
- let e = s.current, r = o.current;
166
- if (!e || !r) return;
167
- let c = () => R(e, r, t);
168
- return c(), window.addEventListener("scroll", c, !0), window.addEventListener("resize", c), () => {
169
- window.removeEventListener("scroll", c, !0), window.removeEventListener("resize", c);
188
+ function W({ behavior: e, placement: t, collision: n }) {
189
+ let { native: i, anchored: a, shown: s, triggerRef: c, panelRef: l } = e;
190
+ o(() => {
191
+ if (!i || t === "point" || !s) return;
192
+ let e = l.current;
193
+ if (!e) return;
194
+ if (a) {
195
+ let i = n?.shift !== !1, a = r(n?.collisionPadding), o = t === "left" || t === "right", s = () => {
196
+ if (!i) {
197
+ e.style.translate = "";
198
+ return;
199
+ }
200
+ let t = e.getBoundingClientRect(), n = o ? 0 : H(t.left, t.width, window.innerWidth, a.left, a.right), r = o ? H(t.top, t.height, window.innerHeight, a.top, a.bottom) : 0;
201
+ e.style.translate = n === 0 && r === 0 ? "" : `${n}px ${r}px`;
202
+ };
203
+ return s(), window.addEventListener("scroll", s, !0), window.addEventListener("resize", s), () => {
204
+ window.removeEventListener("scroll", s, !0), window.removeEventListener("resize", s), e.style.translate = "";
205
+ };
206
+ }
207
+ let o = c.current;
208
+ if (!o) return;
209
+ let u = () => U(e, o, t, n);
210
+ return u(), window.addEventListener("scroll", u, !0), window.addEventListener("resize", u), () => {
211
+ window.removeEventListener("scroll", u, !0), window.removeEventListener("resize", u);
170
212
  };
171
213
  }, [
172
- n,
173
214
  i,
174
215
  a,
216
+ s,
175
217
  t,
176
- o,
177
- s
218
+ n,
219
+ c,
220
+ l
178
221
  ]);
179
222
  }
180
- function B({ behavior: n, placement: r, visualClass: i, className: a, style: o, children: s, ...c }) {
181
- z({
182
- behavior: n,
183
- placement: r ?? "point"
223
+ function G({ behavior: t, placement: n, collision: r, visualClass: a, className: o, style: s, children: c, ...l }) {
224
+ W({
225
+ behavior: t,
226
+ placement: n ?? "point",
227
+ collision: r ?? t.collision
184
228
  });
185
- let l = n.panelAttrs.style || o ? {
186
- ...n.panelAttrs.style,
187
- ...o
229
+ let u = t.panelAttrs.style || s ? {
230
+ ...t.panelAttrs.style,
231
+ ...s
188
232
  } : void 0;
189
- return /* @__PURE__ */ t("div", {
190
- ...c,
191
- ...n.panelAttrs,
192
- style: l,
233
+ return /* @__PURE__ */ i("div", {
234
+ ...t.dataState !== void 0 && { "data-state": t.dataState },
235
+ ...l,
236
+ ...t.panelAttrs,
237
+ style: u,
193
238
  className: e([
194
- i,
195
- ...n.panelClasses,
196
- ...r ? I(n, r) : [],
197
- a
239
+ a,
240
+ ...t.panelClasses,
241
+ ...n ? B(t, n) : [],
242
+ o
198
243
  ]),
199
- children: s
244
+ children: c
200
245
  });
201
246
  }
202
247
  //#endregion
203
- export { B as FloatingPanel, I as floatingPlacementClasses, R as placeFloatingPanel, l as supportsAnchorPositioning, c as supportsNativePopover, F as useFloating, z as useFloatingPosition };
248
+ export { G as FloatingPanel, _ as floatingAnimated, g as floatingHidden, B as floatingPlacementClasses, U as placeFloatingPanel, f as supportsAnchorPositioning, d as supportsNativePopover, z as useFloating, W as useFloatingPosition };
@@ -0,0 +1,63 @@
1
+ import { focusFirst as e, getTabbables as t } from "./focus.js";
2
+ import { useCallback as n, useEffect as r, useLayoutEffect as i, useRef as a } from "react";
3
+ //#region src/lib/utils/focus-scope.ts
4
+ var o = "hazefocusmount", s = "hazefocusunmount";
5
+ function c() {
6
+ document.body.focus(), document.activeElement !== document.body && document.activeElement instanceof HTMLElement && document.activeElement.blur();
7
+ }
8
+ function l(l) {
9
+ let u = a(l);
10
+ i(() => {
11
+ u.current = l;
12
+ });
13
+ let d = a(null), f = a(null), p = n((e) => {
14
+ d.current = e;
15
+ }, []);
16
+ return r(() => {
17
+ if (!l.enabled) return;
18
+ let n = u.current, r = !1, i = document.activeElement;
19
+ f.current = i instanceof HTMLElement ? i : null;
20
+ let a = new Event(o, {
21
+ bubbles: !1,
22
+ cancelable: !0
23
+ });
24
+ d.current?.dispatchEvent(a), n.onMountAutoFocus?.(a), !a.defaultPrevented && n.autoFocus !== !1 && d.current && e(d.current);
25
+ let p = (e) => {
26
+ if (e.key !== "Tab") return;
27
+ let n = d.current;
28
+ if (!n) return;
29
+ let r = t(n), i = r[0], a = r[r.length - 1];
30
+ if (!i || !a) {
31
+ e.preventDefault();
32
+ return;
33
+ }
34
+ let o = document.activeElement, s = o !== null && n.contains(o);
35
+ e.shiftKey ? (o === i || !s) && (e.preventDefault(), a.focus()) : (o === a || !s) && (e.preventDefault(), i.focus());
36
+ }, m = (t) => {
37
+ let n = d.current;
38
+ if (!n || !(t.target instanceof Node) || !n.contains(t.target)) return;
39
+ let i = t.relatedTarget;
40
+ (i instanceof Node ? !n.contains(i) : document.activeElement === document.body) && queueMicrotask(() => {
41
+ if (r) return;
42
+ let t = d.current;
43
+ if (!t) return;
44
+ let n = document.activeElement;
45
+ n !== null && t.contains(n) || e(t);
46
+ });
47
+ };
48
+ return n.trapped && (document.addEventListener("keydown", p), document.addEventListener("focusout", m)), () => {
49
+ r = !0, n.trapped && (document.removeEventListener("keydown", p), document.removeEventListener("focusout", m));
50
+ let e = u.current, t = new Event(s, {
51
+ bubbles: !1,
52
+ cancelable: !0
53
+ });
54
+ if (d.current?.dispatchEvent(t), e.onUnmountAutoFocus?.(t), t.defaultPrevented || e.returnFocus === !1) return;
55
+ let i = d.current, a = document.activeElement, o = i !== null && a !== null && i.contains(a);
56
+ if (a !== document.body && a !== null && !o) return;
57
+ let l = f.current;
58
+ l?.isConnected && l.focus(), document.activeElement !== l && c();
59
+ };
60
+ }, [l.enabled]), p;
61
+ }
62
+ //#endregion
63
+ export { l as useFocusScope };
@@ -0,0 +1,34 @@
1
+ //#region src/lib/utils/focus.ts
2
+ var e = [
3
+ "a[href]:not([disabled])",
4
+ "button:not([disabled])",
5
+ "input:not([disabled]):not([type=hidden])",
6
+ "select:not([disabled])",
7
+ "textarea:not([disabled])",
8
+ "[tabindex]:not([tabindex=\"-1\"])",
9
+ "[contenteditable=true]",
10
+ "audio[controls]",
11
+ "video[controls]",
12
+ "details > summary:first-of-type"
13
+ ].join(", ");
14
+ function t(e) {
15
+ return (e instanceof HTMLButtonElement || e instanceof HTMLInputElement || e instanceof HTMLSelectElement || e instanceof HTMLTextAreaElement || e instanceof HTMLOptionElement) && e.disabled;
16
+ }
17
+ function n(e) {
18
+ return typeof e.checkVisibility != "function" || e.checkVisibility({
19
+ checkOpacity: !0,
20
+ checkVisibilityCSS: !0
21
+ });
22
+ }
23
+ function r(r) {
24
+ return !r.matches(e) || r.getAttribute("tabindex") === "-1" || r.hasAttribute("hidden") || t(r) ? !1 : n(r);
25
+ }
26
+ function i(t) {
27
+ return t ? Array.from(t.querySelectorAll(e)).filter(r) : [];
28
+ }
29
+ function a(e) {
30
+ let t = i(e)[0] ?? e;
31
+ return t === e && e.getAttribute("tabindex") === null && (e.tabIndex = -1), t.focus(), document.activeElement === t;
32
+ }
33
+ //#endregion
34
+ export { e as TABBABLE_SELECTOR, a as focusFirst, i as getTabbables, r as isTabbable };
@@ -0,0 +1,72 @@
1
+ import { cloneElement as e, useEffect as t, useRef as n, useState as r } from "react";
2
+ //#region src/lib/utils/presence.tsx
3
+ var i = /* @__PURE__ */ new WeakMap();
4
+ function a(e) {
5
+ if (typeof requestAnimationFrame == "function") {
6
+ requestAnimationFrame(() => requestAnimationFrame(e));
7
+ return;
8
+ }
9
+ setTimeout(e, 32);
10
+ }
11
+ function o(e) {
12
+ let t = 0;
13
+ for (let n of e.split(",")) {
14
+ let e = n.trim(), r = Number.parseFloat(e);
15
+ if (Number.isNaN(r)) continue;
16
+ let i = e.endsWith("ms") ? r : r * 1e3;
17
+ i > t && (t = i);
18
+ }
19
+ return t;
20
+ }
21
+ function s(e) {
22
+ return new Promise((t) => {
23
+ a(() => {
24
+ let n = getComputedStyle(e), r = o(n.animationDuration) + o(n.animationDelay), i = o(n.transitionDuration) + o(n.transitionDelay);
25
+ if (!(n.animationName !== "none" && r > 0 || n.transitionProperty !== "none" && i > 0)) {
26
+ t();
27
+ return;
28
+ }
29
+ let a = () => {
30
+ e.removeEventListener("animationend", s), e.removeEventListener("transitionend", c), window.clearTimeout(l), t();
31
+ }, s = (t) => {
32
+ t.target === e && a();
33
+ }, c = (t) => {
34
+ t.target === e && a();
35
+ };
36
+ e.addEventListener("animationend", s), e.addEventListener("transitionend", c);
37
+ let l = window.setTimeout(a, Math.max(r, i));
38
+ });
39
+ });
40
+ }
41
+ function c(e) {
42
+ if (!e.isConnected) return null;
43
+ let t = i.get(e);
44
+ if (t) return t;
45
+ let n = s(e);
46
+ return i.set(e, n), n.then(() => i.delete(e)), n;
47
+ }
48
+ function l({ present: i, children: a, onExited: o }) {
49
+ let [s, l] = r(i), [u, d] = r(() => i ? "open" : "closed"), [f, p] = r(i), m = n(null);
50
+ if (i !== f && (p(i), i ? (l(!0), d("open")) : d("closed")), t(() => {
51
+ if (!s || u !== "closed") return;
52
+ let e = !0, t = m.current, n = t ? c(t) : null, r = () => {
53
+ e && (e = !1, l(!1), o?.());
54
+ };
55
+ return n ? n.then(r) : r(), () => {
56
+ e = !1;
57
+ };
58
+ }, [
59
+ s,
60
+ u,
61
+ o
62
+ ]), !s) return null;
63
+ let h = a, g = h.props.ref;
64
+ return e(h, {
65
+ ...h.props["data-state"] === void 0 ? { "data-state": u } : {},
66
+ ref: (e) => {
67
+ m.current = e, typeof g == "function" ? g(e) : g && (g.current = e);
68
+ }
69
+ });
70
+ }
71
+ //#endregion
72
+ export { l as Presence, c as whenExitSettles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haze-ui",
3
- "version": "1.22.0",
3
+ "version": "1.24.0",
4
4
  "type": "module",
5
5
  "description": "A React UI component library powered by react-use-control and Linaria",
6
6
  "main": "./dist/index.js",
@@ -46,7 +46,7 @@
46
46
  "lint": "eslint --fix src *.mjs",
47
47
  "deploy": "npm run build:demo && gh-pages -d dist",
48
48
  "test": "vitest run",
49
- "test:e2e": "playwright test --config e2e/playwright.config.ts",
49
+ "test:e2e": "PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=1 playwright test --config e2e/playwright.config.ts",
50
50
  "test:watch": "vitest",
51
51
  "typecheck": "tsc --noEmit",
52
52
  "prepublishOnly": "npm run build",
@@ -89,6 +89,7 @@
89
89
  "@testing-library/jest-dom": "^7.0.1",
90
90
  "@testing-library/react": "^16.3.3",
91
91
  "@testing-library/user-event": "^14.6.6",
92
+ "@types/culori": "^4.0.1",
92
93
  "@types/jest-axe": "^3.5.9",
93
94
  "@types/node": "^26.4.0",
94
95
  "@types/ramda": "^0.32.0",
@@ -102,6 +103,7 @@
102
103
  "babel-plugin-transform-jsx-condition": "^0.1.3",
103
104
  "commitizen": "^4.3.2",
104
105
  "core-js": "^3.50.0",
106
+ "culori": "^4.0.2",
105
107
  "date-fns": "^4.4.0",
106
108
  "eslint": "^10.9.1",
107
109
  "eslint-plugin-compat": "^7.0.2",