@box-kite/react 1.0.0 → 2.0.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 (179) hide show
  1. package/.claude/rules/box-kite-rules.md +23 -1
  2. package/.claude/skills/box-kite/SKILL.md +134 -427
  3. package/.claude/skills/box-kite/references/components.md +235 -0
  4. package/.claude/skills/box-kite/references/extending.md +42 -0
  5. package/.claude/skills/box-kite/references/patterns.md +27 -0
  6. package/.claude/skills/box-kite/references/styling.md +222 -0
  7. package/.cursor/rules/box-kite.mdc +73 -0
  8. package/AGENTS.md +102 -0
  9. package/BOX_AI_CONTEXT.md +1124 -153
  10. package/BOX_KITE_AI_CONTEXT.md +1124 -153
  11. package/README.md +36 -2
  12. package/a11y.cjs +1 -1
  13. package/a11y.d.ts +1 -1
  14. package/a11y.mjs +3 -2
  15. package/anchor.cjs +1 -0
  16. package/anchor.d.ts +14 -0
  17. package/anchor.mjs +3 -0
  18. package/behavior.cjs +1 -1
  19. package/behavior.mjs +118 -136
  20. package/box.cjs +1 -1
  21. package/box.mjs +1 -1
  22. package/client.cjs +1 -1
  23. package/client.mjs +15 -14
  24. package/components/accordion.cjs +1 -0
  25. package/components/accordion.d.ts +114 -0
  26. package/components/accordion.mjs +251 -0
  27. package/components/button.cjs +1 -1
  28. package/components/button.d.ts +3 -0
  29. package/components/button.mjs +1 -1
  30. package/components/chart.cjs +1 -1
  31. package/components/chart.d.ts +2 -1
  32. package/components/chart.mjs +159 -184
  33. package/components/checkbox.cjs +1 -1
  34. package/components/checkbox.d.ts +8 -0
  35. package/components/checkbox.mjs +1 -1
  36. package/components/combobox/comboboxChips.d.ts +21 -0
  37. package/components/combobox/comboboxListbox.d.ts +47 -0
  38. package/components/combobox.cjs +1 -0
  39. package/components/combobox.d.ts +121 -0
  40. package/components/combobox.mjs +563 -0
  41. package/components/dataGrid/components/dataGridAggregateValue.d.ts +10 -0
  42. package/components/dataGrid/components/dataGridCell.d.ts +2 -1
  43. package/components/dataGrid/components/dataGridCellEditor.d.ts +15 -0
  44. package/components/dataGrid/components/dataGridCellPlaceholder.d.ts +14 -0
  45. package/components/dataGrid/components/dataGridCellTree.d.ts +16 -0
  46. package/components/dataGrid/components/dataGridDataSourceError.d.ts +12 -0
  47. package/components/dataGrid/components/dataGridExport.d.ts +10 -0
  48. package/components/dataGrid/components/dataGridFooter.d.ts +11 -0
  49. package/components/dataGrid/contracts/dataGridContract.d.ts +474 -16
  50. package/components/dataGrid/export/gridExport.d.ts +10 -0
  51. package/components/dataGrid/gridNavigationContext.d.ts +9 -1
  52. package/components/dataGrid/models/aggregateCellModel.d.ts +34 -0
  53. package/components/dataGrid/models/aggregationModel.d.ts +32 -0
  54. package/components/dataGrid/models/cellKeys.d.ts +11 -0
  55. package/components/dataGrid/models/cellModel.d.ts +27 -1
  56. package/components/dataGrid/models/columnModel.d.ts +12 -2
  57. package/components/dataGrid/models/dataSourceModel.d.ts +177 -0
  58. package/components/dataGrid/models/editModel.d.ts +77 -0
  59. package/components/dataGrid/models/exportModel.d.ts +51 -0
  60. package/components/dataGrid/models/gridModel.d.ts +108 -21
  61. package/components/dataGrid/models/groupRowCellModel.d.ts +11 -3
  62. package/components/dataGrid/models/groupRowModel.d.ts +22 -2
  63. package/components/dataGrid/models/rowModel.d.ts +13 -1
  64. package/components/dataGrid/models/sourceGroupRowModel.d.ts +45 -0
  65. package/components/dataGrid/models/sourceLevel.d.ts +71 -0
  66. package/components/dataGrid/models/sourceRowModel.d.ts +29 -0
  67. package/components/dataGrid/models/sourceTreeRowModel.d.ts +23 -0
  68. package/components/dataGrid/models/treeModel.d.ts +94 -0
  69. package/components/dataGrid/models/treeRow.d.ts +22 -0
  70. package/components/dataGrid/models/treeRowModel.d.ts +50 -0
  71. package/components/dataGrid.cjs +1 -1
  72. package/components/dataGrid.d.ts +4 -2
  73. package/components/dataGrid.mjs +4484 -2755
  74. package/components/dialog.cjs +1 -0
  75. package/components/dialog.d.ts +151 -0
  76. package/components/dialog.mjs +223 -0
  77. package/components/dropdown.cjs +1 -1
  78. package/components/dropdown.d.ts +30 -0
  79. package/components/dropdown.mjs +256 -244
  80. package/components/icon.cjs +1 -1
  81. package/components/icon.d.ts +2 -1
  82. package/components/icon.mjs +3 -3
  83. package/components/menu.cjs +1 -0
  84. package/components/menu.d.ts +234 -0
  85. package/components/menu.mjs +422 -0
  86. package/components/overlay.cjs +1 -1
  87. package/components/overlay.d.ts +30 -26
  88. package/components/overlay.mjs +45 -75
  89. package/components/popover.cjs +1 -0
  90. package/components/popover.d.ts +100 -0
  91. package/components/popover.mjs +69 -0
  92. package/components/presence.d.ts +6 -0
  93. package/components/progress.cjs +1 -0
  94. package/components/progress.d.ts +47 -0
  95. package/components/progress.mjs +28 -0
  96. package/components/radioButton.cjs +1 -1
  97. package/components/radioButton.d.ts +8 -0
  98. package/components/radioButton.mjs +1 -1
  99. package/components/radioGroup.cjs +1 -1
  100. package/components/radioGroup.d.ts +15 -2
  101. package/components/radioGroup.mjs +34 -30
  102. package/components/select.d.ts +9 -0
  103. package/components/semantics.cjs +1 -1
  104. package/components/semantics.d.ts +33 -28
  105. package/components/semantics.mjs +3 -3
  106. package/components/slider.cjs +1 -0
  107. package/components/slider.d.ts +98 -0
  108. package/components/slider.mjs +250 -0
  109. package/components/svg.cjs +1 -1
  110. package/components/svg.d.ts +25 -23
  111. package/components/svg.mjs +3 -3
  112. package/components/switch.cjs +1 -1
  113. package/components/switch.d.ts +9 -0
  114. package/components/switch.mjs +1 -1
  115. package/components/tabs.cjs +1 -0
  116. package/components/tabs.d.ts +87 -0
  117. package/components/tabs.mjs +324 -0
  118. package/components/textarea.cjs +1 -1
  119. package/components/textarea.d.ts +14 -0
  120. package/components/textarea.mjs +1 -1
  121. package/components/textbox.cjs +1 -1
  122. package/components/textbox.d.ts +12 -0
  123. package/components/textbox.mjs +1 -1
  124. package/components/toaster.cjs +1 -0
  125. package/components/toaster.d.ts +106 -0
  126. package/components/toaster.mjs +295 -0
  127. package/components/tooltip.cjs +1 -1
  128. package/components/tooltip.d.ts +39 -4
  129. package/components/tooltip.mjs +56 -54
  130. package/docs/a11y.md +199 -0
  131. package/docs/anchor.md +139 -0
  132. package/docs/components.md +48 -0
  133. package/docs/index.md +11 -0
  134. package/docs/props.md +1777 -0
  135. package/effects.cjs +1 -1
  136. package/effects.mjs +1 -1
  137. package/gridExport.cjs +2 -0
  138. package/gridExport.mjs +244 -0
  139. package/identity.cjs +1 -0
  140. package/identity.mjs +12 -0
  141. package/keyboard.cjs +1 -0
  142. package/keyboard.mjs +30 -0
  143. package/layer.cjs +1 -0
  144. package/layer.mjs +127 -0
  145. package/motion.cjs +1 -1
  146. package/motion.mjs +1 -1
  147. package/package.json +134 -10
  148. package/placement.cjs +1 -0
  149. package/placement.mjs +180 -0
  150. package/platform.cjs +1 -1
  151. package/platform.mjs +18 -5
  152. package/react/anchor/useAnchorPosition.d.ts +79 -0
  153. package/react/dialog/useScrollLock.d.ts +12 -0
  154. package/react/hooks/usePortalContainer.d.ts +6 -1
  155. package/react/hooks/useVirtualization.d.ts +24 -35
  156. package/react/popover/usePopoverLayer.d.ts +87 -0
  157. package/react-shared.cjs +1 -1
  158. package/react-shared.mjs +19 -2
  159. package/rsc.cjs +1 -1
  160. package/rsc.mjs +1 -1
  161. package/utils/accordion/accordionUtils.d.ts +48 -0
  162. package/utils/anchor/anchorUtils.d.ts +79 -0
  163. package/utils/array/lazyList.d.ts +10 -0
  164. package/utils/chart/chartPalette.d.ts +15 -0
  165. package/utils/chart/chartUtils.d.ts +2 -8
  166. package/utils/combobox/comboboxUtils.d.ts +89 -0
  167. package/utils/dom/domUtils.d.ts +6 -0
  168. package/utils/environment/environmentUtils.d.ts +10 -0
  169. package/utils/export/csvUtils.d.ts +23 -0
  170. package/utils/export/downloadUtils.d.ts +12 -0
  171. package/utils/export/xlsxUtils.d.ts +56 -0
  172. package/utils/export/zipUtils.d.ts +26 -0
  173. package/utils/keyboard/typeaheadUtils.d.ts +31 -0
  174. package/utils/menu/menuUtils.d.ts +25 -0
  175. package/utils/slider/sliderUtils.d.ts +67 -0
  176. package/utils/tabs/tabsUtils.d.ts +75 -0
  177. package/utils/toast/toastStore.d.ts +73 -0
  178. package/utils/virtual/virtualUtils.d.ts +47 -0
  179. /package/react/{a11y → identity}/useIdentifier.d.ts +0 -0
@@ -0,0 +1,295 @@
1
+ "use client";
2
+ import { a as e, t } from "../platform.mjs";
3
+ import { t as n } from "../client.mjs";
4
+ import { n as r } from "../effects.mjs";
5
+ import i from "../box.mjs";
6
+ import { t as a } from "../motion.mjs";
7
+ import { useCallback as o, useRef as s, useState as c } from "react";
8
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
9
+ import { createPortal as d } from "react-dom";
10
+ import { useSyncExternalStore as f } from "use-sync-external-store/shim";
11
+ //#region src/utils/toast/toastStore.ts
12
+ var p = {
13
+ toasts: [],
14
+ overflow: 0
15
+ }, m = 0;
16
+ function h() {
17
+ return m += 1, `toast-${m}`;
18
+ }
19
+ function g(e) {
20
+ let t = [], n = p, r = e?.limit ?? 3, i = e?.duration ?? 5e3, a = !1, o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map(), c = (e) => {
21
+ let t = s.get(e);
22
+ t?.handle && clearTimeout(t.handle), s.delete(e);
23
+ }, l = () => {
24
+ let e = 0;
25
+ t = t.map((t) => {
26
+ let n = !t.open || e++ < r;
27
+ return t.visible === n ? t : {
28
+ ...t,
29
+ visible: n
30
+ };
31
+ }), n = {
32
+ toasts: t,
33
+ overflow: Math.max(0, e - r)
34
+ }, u(), o.forEach((e) => e());
35
+ };
36
+ function u() {
37
+ let e = /* @__PURE__ */ new Set();
38
+ for (let n of t) {
39
+ if (!n.open || !n.visible || !Number.isFinite(n.duration)) continue;
40
+ e.add(n.id);
41
+ let t = s.get(n.id) ?? {
42
+ handle: null,
43
+ remaining: n.duration,
44
+ startedAt: 0
45
+ };
46
+ s.set(n.id, t), !(a || t.handle) && (t.startedAt = Date.now(), t.handle = setTimeout(() => {
47
+ s.delete(n.id), f(n.id, "timeout");
48
+ }, t.remaining));
49
+ }
50
+ for (let t of [...s.keys()]) e.has(t) || c(t);
51
+ }
52
+ let d = (e, t) => t ?? (e === "loading" ? Infinity : i);
53
+ function f(e, n = "imperative") {
54
+ let r = [];
55
+ t = t.map((t) => !t.open || e !== void 0 && t.id !== e ? t : (r.push(t), c(t.id), {
56
+ ...t,
57
+ open: !1
58
+ })), r.length && (l(), r.forEach((e) => e.onDismiss?.(n)));
59
+ }
60
+ function m(e, n, r) {
61
+ let i = !1;
62
+ t = t.map((t) => {
63
+ if (t.id !== e) return t;
64
+ i = !0, c(e);
65
+ let a = r?.kind ?? t.kind;
66
+ return {
67
+ ...t,
68
+ ...r,
69
+ id: e,
70
+ message: n,
71
+ kind: a,
72
+ duration: r?.duration ?? (r?.kind ? d(a) : t.duration),
73
+ open: !0
74
+ };
75
+ }), i && l();
76
+ }
77
+ function g(e, n) {
78
+ let r = n?.id ?? h();
79
+ if (n?.id && t.some((e) => e.id === r)) return m(r, e, n), r;
80
+ let i = n?.kind ?? "default";
81
+ return t = [...t, {
82
+ id: r,
83
+ kind: i,
84
+ message: e,
85
+ description: n?.description,
86
+ duration: d(i, n?.duration),
87
+ action: n?.action,
88
+ dismissible: n?.dismissible ?? !0,
89
+ onDismiss: n?.onDismiss,
90
+ open: !0,
91
+ visible: !1
92
+ }], l(), r;
93
+ }
94
+ return {
95
+ subscribe(e) {
96
+ return o.add(e), () => o.delete(e);
97
+ },
98
+ getSnapshot: () => n,
99
+ getServerSnapshot: () => p,
100
+ add: g,
101
+ update: m,
102
+ dismiss: f,
103
+ remove(e) {
104
+ let n = t.filter((t) => t.id !== e);
105
+ n.length !== t.length && (c(e), t = n, l());
106
+ },
107
+ setLimit(e) {
108
+ e !== r && (r = e, l());
109
+ },
110
+ setDefaultDuration(e) {
111
+ i = e;
112
+ },
113
+ pause() {
114
+ if (!a) {
115
+ a = !0;
116
+ for (let e of s.values()) e.handle && (clearTimeout(e.handle), e.handle = null, e.remaining = Math.max(0, e.remaining - (Date.now() - e.startedAt)));
117
+ }
118
+ },
119
+ resume() {
120
+ a && (a = !1, u());
121
+ },
122
+ reset() {
123
+ for (let e of [...s.keys()]) c(e);
124
+ t = [], n = p, o.forEach((e) => e());
125
+ }
126
+ };
127
+ }
128
+ //#endregion
129
+ //#region src/components/toaster.tsx
130
+ var _ = g(), v = (e) => (t, n) => _.add(t, {
131
+ ...n,
132
+ kind: e
133
+ }), y = Object.assign((e, t) => _.add(e, t), {
134
+ success: v("success"),
135
+ error: v("error"),
136
+ warning: v("warning"),
137
+ info: v("info"),
138
+ loading: v("loading"),
139
+ update: (e, t, n) => _.update(e, t, n),
140
+ dismiss: (e) => _.dismiss(e, "imperative"),
141
+ promise(e, t, n) {
142
+ let r = _.add(t.loading, {
143
+ ...n,
144
+ id: n?.id,
145
+ kind: "loading"
146
+ }), i = (e, t) => typeof e == "function" ? e(t) : e;
147
+ return e.then((e) => _.update(r, i(t.success, e), { kind: "success" }), (e) => _.update(r, i(t.error, e), { kind: "error" })), e;
148
+ }
149
+ }), b = {
150
+ "top-start": "topStart",
151
+ "top-center": "topCenter",
152
+ "top-end": "topEnd",
153
+ "bottom-start": "bottomStart",
154
+ "bottom-center": "bottomCenter",
155
+ "bottom-end": "bottomEnd"
156
+ };
157
+ function x(e, t) {
158
+ let n = t.toLowerCase().split("+"), r = n[n.length - 1], i = new Set(n.slice(0, -1));
159
+ return e.key.toLowerCase() === r && e.altKey === i.has("alt") && e.ctrlKey === i.has("ctrl") && e.shiftKey === i.has("shift") && e.metaKey === i.has("meta");
160
+ }
161
+ function S(e) {
162
+ let { toast: t, store: n, fromTop: o, closeLabel: s } = e, { mounted: c, ref: d, props: f } = a({ present: t.open });
163
+ if (r(() => {
164
+ c || n.remove(t.id);
165
+ }, [
166
+ c,
167
+ n,
168
+ t.id
169
+ ]), !c) return null;
170
+ let p = t.action, m = () => {
171
+ p?.onClick(), p?.closeOnClick !== !1 && n.dismiss(t.id, "action");
172
+ };
173
+ return /* @__PURE__ */ u(i, {
174
+ ref: d,
175
+ component: "toaster.toast",
176
+ variant: {
177
+ [t.kind]: t.kind !== "default",
178
+ fromTop: o
179
+ },
180
+ props: {
181
+ ...t.kind === "error" ? { role: "alert" } : {},
182
+ "data-toast-id": t.id,
183
+ ...f
184
+ },
185
+ children: [
186
+ /* @__PURE__ */ l(i, {
187
+ component: "toaster.message",
188
+ children: t.message
189
+ }),
190
+ t.description !== void 0 && /* @__PURE__ */ l(i, {
191
+ component: "toaster.description",
192
+ children: t.description
193
+ }),
194
+ p && /* @__PURE__ */ l(i, {
195
+ tag: "button",
196
+ component: "toaster.action",
197
+ props: {
198
+ type: "button",
199
+ onClick: m
200
+ },
201
+ children: p.label
202
+ }),
203
+ t.dismissible && /* @__PURE__ */ l(i, {
204
+ tag: "button",
205
+ component: "toaster.close",
206
+ props: {
207
+ type: "button",
208
+ "aria-label": s,
209
+ onClick: () => n.dismiss(t.id, "close")
210
+ }
211
+ })
212
+ ]
213
+ });
214
+ }
215
+ function C(a) {
216
+ let { position: p = "bottom-end", limit: m = 3, duration: h = 5e3, label: g = "Notifications", closeLabel: v = "Close", overflowLabel: y = (e) => `+${e} more`, hotkey: C = "F6", store: w = _, props: T, ...E } = a, D = f(w.subscribe, w.getSnapshot, w.getServerSnapshot), [O, k] = c(!0), A = n(!O), j = s(null), M = s(null), N = s({
217
+ hovered: !1,
218
+ focused: !1,
219
+ hidden: !1
220
+ }), P = o(() => {
221
+ let { hovered: e, focused: t, hidden: n } = N.current;
222
+ e || t || n ? w.pause() : w.resume();
223
+ }, [w]);
224
+ r(() => {
225
+ e() || k(!1);
226
+ }, []), r(() => w.setLimit(m), [w, m]), r(() => w.setDefaultDuration(h), [w, h]), r(() => {
227
+ let t = j.current;
228
+ !O || !e() || !t || !t.isConnected || t.matches(":popover-open") || t.showPopover();
229
+ }), r(() => {
230
+ let e = t();
231
+ if (!e) return;
232
+ let n = new AbortController();
233
+ return e.addEventListener("visibilitychange", () => {
234
+ N.current.hidden = e.hidden, P();
235
+ }, { signal: n.signal }), () => n.abort();
236
+ }, [P]), r(() => {
237
+ let e = t();
238
+ if (!C || !e) return;
239
+ let n = new AbortController();
240
+ return e.addEventListener("keydown", (t) => {
241
+ !x(t, C) || !j.current || (t.preventDefault(), M.current = e.activeElement, j.current.focus());
242
+ }, { signal: n.signal }), () => n.abort();
243
+ }, [C]);
244
+ let F = (e) => !!e && !!j.current?.contains(e), I = () => {
245
+ N.current.hovered = !0, P();
246
+ }, L = (e) => {
247
+ F(e.relatedTarget) || (N.current.hovered = !1, P());
248
+ }, R = (e) => {
249
+ N.current.focused = !0, P(), F(e.relatedTarget) || (M.current = e.relatedTarget);
250
+ }, z = (e) => {
251
+ F(e.relatedTarget) || (N.current.focused = !1, P());
252
+ }, B = (e) => {
253
+ if (e.key !== "Escape") return;
254
+ let t = (e.target.closest?.("[data-toast-id]"))?.getAttribute("data-toast-id");
255
+ t && w.dismiss(t, "close"), w.getSnapshot().toasts.some((e) => e.open) ? j.current?.focus() : M.current?.focus();
256
+ }, V = p.startsWith("top"), H = D.toasts.filter((e) => e.visible), U = V ? [...H].reverse() : H, W = D.overflow > 0 && /* @__PURE__ */ l(i, {
257
+ component: "toaster.overflow",
258
+ children: y(D.overflow)
259
+ }), G = /* @__PURE__ */ u(i, {
260
+ tag: "section",
261
+ ref: j,
262
+ component: "toaster",
263
+ ...E,
264
+ variant: [E.variant, { [b[p]]: !0 }],
265
+ props: {
266
+ ...O ? { popover: "manual" } : {},
267
+ "aria-live": "polite",
268
+ "aria-atomic": "false",
269
+ "aria-relevant": "additions text",
270
+ "aria-label": g,
271
+ tabIndex: -1,
272
+ ...T,
273
+ onPointerOver: I,
274
+ onPointerOut: L,
275
+ onFocus: R,
276
+ onBlur: z,
277
+ onKeyDown: B
278
+ },
279
+ children: [
280
+ !V && W,
281
+ U.map((e) => /* @__PURE__ */ l(S, {
282
+ toast: e,
283
+ store: w,
284
+ fromTop: V,
285
+ closeLabel: v
286
+ }, e.id)),
287
+ V && W
288
+ ]
289
+ });
290
+ return O ? G : A ? d(G, A) : null;
291
+ }
292
+ var w = C;
293
+ w.displayName = "Toaster";
294
+ //#endregion
295
+ export { g as createToastStore, w as default, _ as defaultToastStore, y as toast };
@@ -1 +1 @@
1
- "use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../behavior.cjs"),t=require("./overlay.cjs"),n=require("./presence.cjs");let r=require("react"),i=require("react/jsx-runtime");function a(a){let{content:o,children:s,open:c,defaultOpen:l=!1,onOpenChange:u,openDelay:d=300,closeDelay:f=150,adjustTranslateX:p,adjustTranslateY:m,props:h,...g}=a,_=e.n(`tooltip`),v=g.id??_,[y,b]=e.a({value:c,defaultValue:l,onChange:u}),[x,S]=(0,r.useState)(null),C=(0,r.useRef)(null),w=(0,r.useRef)(void 0),T=(0,r.useRef)(!1),E=(0,r.useRef)(!1),D=(0,r.useRef)(!1),O=(0,r.useRef)(!1),k=(0,r.useCallback)(()=>{clearTimeout(w.current),w.current=void 0},[]),A=(0,r.useCallback)((e,t)=>{if(k(),e<=0){t();return}w.current=setTimeout(()=>{w.current=void 0,t()},e)},[k]),j=(0,r.useCallback)((e,t)=>{A(f,()=>{T.current||E.current||D.current||b(!1,{reason:e,event:t})})},[f,A,b]);e.i({enabled:y,outsidePointer:!1,inside:[C],onDismiss:(e,t)=>{k(),O.current=!0,b(!1,{reason:e,event:t})}}),(0,r.useEffect)(()=>k,[k]);let M=y&&o!=null,N=e.o(e=>{T.current=!0,!O.current&&A(d,()=>b(!0,{reason:`hover`,event:e}))}),P=e.o(e=>{T.current=!1,O.current=!1,j(`pointer-leave`,e)}),F=e.o(e=>{D.current=!0,k(),b(!0,{reason:`focus`,event:e})}),I=e.o(e=>{D.current=!1,O.current=!1,j(`blur`,e)}),L=e.o(()=>{E.current=!0,k()}),R=e.o(e=>{E.current=!1,j(`pointer-leave`,e)}),z=(0,r.useMemo)(()=>({ref:S,props:{"aria-describedby":M?v:void 0,onPointerEnter:N,onPointerLeave:P,onFocus:F,onBlur:I}}),[I,N,F,P,M,v]);return(0,i.jsxs)(i.Fragment,{children:[s(z),(0,i.jsx)(n.default,{present:M,children:e=>(0,i.jsx)(t.default,{ref:C,contentRef:e.ref,anchor:x,anchorSide:`bottom`,matchWidth:!1,adjustTranslateX:p,adjustTranslateY:m??`4px`,component:`tooltip`,...g,variant:[g.variant,{closed:!e.present}],id:v,props:{role:`tooltip`,...e.props,...h,onPointerEnter:L,onPointerLeave:R},children:o})})]})}a.displayName=`Tooltip`,exports.default=a;
1
+ "use client";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../behavior.cjs"),t=require("../identity.cjs"),n=require("./overlay.cjs"),r=require("./presence.cjs");let i=require("react"),a=require("react/jsx-runtime");function o(o){let{content:s,children:c,open:l,defaultOpen:u=!1,onOpenChange:d,openDelay:f=300,closeDelay:p=150,side:m=`bottom`,align:h=`center`,offset:g=1,flip:_=!0,props:v,...y}=o,b=t.t(`tooltip`),x=y.id??b,[S,C]=e.i({value:l,defaultValue:u,onChange:d}),[w,T]=(0,i.useState)(null),E=(0,i.useRef)(null),D=(0,i.useRef)(void 0),O=(0,i.useRef)(!1),k=(0,i.useRef)(!1),A=(0,i.useRef)(!1),j=(0,i.useRef)(!1),M=(0,i.useCallback)(()=>{clearTimeout(D.current),D.current=void 0},[]),N=(0,i.useCallback)((e,t)=>{if(M(),e<=0){t();return}D.current=setTimeout(()=>{D.current=void 0,t()},e)},[M]),P=(0,i.useCallback)((e,t)=>{N(p,()=>{O.current||k.current||A.current||C(!1,{reason:e,event:t})})},[p,N,C]);e.r({enabled:S,outsidePointer:!1,inside:[E],onDismiss:(e,t)=>{M(),j.current=!0,C(!1,{reason:e,event:t})}}),(0,i.useEffect)(()=>M,[M]);let F=S&&s!=null,I=e.a(e=>{O.current=!0,!j.current&&N(f,()=>C(!0,{reason:`hover`,event:e}))}),L=e.a(e=>{O.current=!1,j.current=!1,P(`pointer-leave`,e)}),R=e.a(e=>{A.current=!0,M(),C(!0,{reason:`focus`,event:e})}),z=e.a(e=>{A.current=!1,j.current=!1,P(`blur`,e)}),B=e.a(()=>{k.current=!0,M()}),V=e.a(e=>{k.current=!1,P(`pointer-leave`,e)}),H=(0,i.useMemo)(()=>({ref:T,props:{"aria-describedby":F?x:void 0,onPointerEnter:I,onPointerLeave:L,onFocus:R,onBlur:z}}),[z,I,R,L,F,x]);return(0,a.jsxs)(a.Fragment,{children:[c(H),(0,a.jsx)(r.default,{present:F,children:e=>(0,a.jsx)(n.default,{ref:E,contentRef:e.ref,anchor:w,side:m,align:h,offset:g,flip:_,matchWidth:!1,component:`tooltip`,...y,variant:[y.variant,{closed:!e.present}],id:x,props:{role:`tooltip`,...e.props,...v,onPointerEnter:B,onPointerLeave:V},children:s})})]})}o.displayName=`Tooltip`,exports.default=o;
@@ -1,6 +1,7 @@
1
1
  import { BoxProps } from '../box';
2
2
  import { ChangeHandler } from '../react/a11y/useControllableState';
3
3
  import { ComponentsAndVariants } from '@box-kite/core/types';
4
+ import { AnchorAlign, AnchorSide } from '../utils/anchor/anchorUtils';
4
5
  /** Why the tooltip opened or closed — `onOpenChange` gets this alongside the event that did it. */
5
6
  export type TooltipReason = 'hover' | 'focus' | 'pointer-leave' | 'blur' | 'escape';
6
7
  /** The DOM attributes and handlers the trigger has to carry. */
@@ -25,7 +26,7 @@ export interface TooltipTrigger {
25
26
  ref: React.RefCallback<HTMLElement>;
26
27
  props: TooltipTriggerAttributes;
27
28
  }
28
- type TooltipBoxProps<TKey extends keyof ComponentsAndVariants> = Omit<BoxProps<'div', TKey>, 'children' | 'content' | 'open'>;
29
+ type TooltipBoxProps<TKey extends keyof ComponentsAndVariants> = Omit<BoxProps<'div', TKey>, 'children' | 'content' | 'open' | 'flip'>;
29
30
  interface Props<TKey extends keyof ComponentsAndVariants> extends TooltipBoxProps<TKey> {
30
31
  /** The description itself. Nothing renders while this is empty. */
31
32
  content?: React.ReactNode;
@@ -33,7 +34,10 @@ interface Props<TKey extends keyof ComponentsAndVariants> extends TooltipBoxProp
33
34
  children: (trigger: TooltipTrigger) => React.ReactNode;
34
35
  /** Controlled open state. Leave it out and the tooltip owns it. */
35
36
  open?: boolean;
37
+ /** Whether it starts open, when the tooltip owns its own state. */
36
38
  defaultOpen?: boolean;
39
+ /** Fires with the new state and why it changed — `'hover'`, `'focus'`, `'pointer-leave'`, `'blur'`
40
+ * or `'escape'`. */
37
41
  onOpenChange?: ChangeHandler<boolean, TooltipReason>;
38
42
  /**
39
43
  * How long the pointer has to rest on the trigger, in ms. Default 300 — sweeping across a toolbar should
@@ -42,12 +46,24 @@ interface Props<TKey extends keyof ComponentsAndVariants> extends TooltipBoxProp
42
46
  openDelay?: number;
43
47
  /** The grace period after the pointer leaves, in ms. Default 150, so the pointer can reach the tooltip (WCAG 1.4.13). */
44
48
  closeDelay?: number;
45
- adjustTranslateX?: string;
46
- adjustTranslateY?: string;
49
+ /**
50
+ * Which side of the trigger the bubble sits on — `top`/`bottom` are the block axis, `start`/`end` the
51
+ * inline one. Default `'bottom'`, and a side with no room flips to its opposite either way.
52
+ */
53
+ side?: AnchorSide;
54
+ /** Which of the trigger's edges to line the bubble up with along the other axis. Default `'center'`. */
55
+ align?: AnchorAlign;
56
+ /**
57
+ * The gap between trigger and bubble, on the ÷4 spacing scale. Default 1 — 4px, which is near enough
58
+ * for the pointer to cross without leaving the trigger (WCAG 1.4.13) and far enough to read as a layer.
59
+ */
60
+ offset?: number;
61
+ /** Whether a side with no room may be swapped for its opposite. Default `true`. */
62
+ flip?: boolean;
47
63
  }
48
64
  /**
49
65
  * The APG tooltip: a description that appears on hover *and* on focus and stays until the user is done
50
- * with it. Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
66
+ * with it.
51
67
  *
52
68
  * ```tsx
53
69
  * <Tooltip content="Deletes the row for good">{(trigger) => <Button {...trigger}>Delete</Button>}</Tooltip>
@@ -58,6 +74,25 @@ interface Props<TKey extends keyof ComponentsAndVariants> extends TooltipBoxProp
58
74
  * on `aria-describedby` costs the thing the pattern is for. The component owns `role="tooltip"`, the
59
75
  * `aria-describedby`, and WCAG 1.4.13's three obligations — dismissible with Escape without moving focus,
60
76
  * hoverable, and never closed on a timer. Focus never enters it: a focusable tooltip is a mislabelled dialog.
77
+ *
78
+ * @pattern https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
79
+ * @a11y `role="tooltip"` on the bubble and `aria-describedby` on the trigger, so the description is read
80
+ * as part of the control rather than as text that happens to be nearby.
81
+ * @a11y WCAG 1.4.13, all three parts: Escape dismisses it without moving focus, the pointer can travel
82
+ * onto the bubble and read it, and nothing hides it on a timer.
83
+ * @a11y The bubble is never in the tab order — a focusable tooltip is a dialog with the wrong role — and
84
+ * it renders nothing at all while `content` is empty.
85
+ * @keyboard Tab — Shows it as soon as the trigger has focus, ignoring `openDelay`: a keyboard user asked
86
+ * for it by arriving.
87
+ * @keyboard Escape — Hides it, leaving focus on the trigger. It stays hidden until the pointer or focus
88
+ * leaves and comes back.
89
+ * @keyboard Tab, again — Reaches the next control, and the tooltip closes behind it.
90
+ * @keyboard (Pointer) Resting on the trigger — Shows it after `openDelay`, 300 ms by default: sweeping
91
+ * across a toolbar should not light every control up.
92
+ * @keyboard (Pointer) Leaving the trigger — Hides it after `closeDelay`, 150 ms — unless the pointer
93
+ * lands on the tooltip itself.
94
+ * @keyboard (Pointer) Moving onto the tooltip — Keeps it open for as long as the pointer is there, so a
95
+ * long description can be read or selected.
61
96
  */
62
97
  declare function Tooltip<TKey extends keyof ComponentsAndVariants = 'tooltip'>(props: Props<TKey>): import("react").JSX.Element;
63
98
  export default Tooltip;
@@ -1,103 +1,105 @@
1
1
  "use client";
2
- import { a as e, i as t, n, o as r } from "../behavior.mjs";
2
+ import { a as e, i as t, r as n } from "../behavior.mjs";
3
+ import { t as r } from "../identity.mjs";
3
4
  import i from "./overlay.mjs";
4
5
  import a from "./presence.mjs";
5
6
  import { useCallback as o, useEffect as s, useMemo as c, useRef as l, useState as u } from "react";
6
7
  import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
7
8
  //#region src/components/tooltip.tsx
8
9
  function m(m) {
9
- let { content: h, children: g, open: _, defaultOpen: v = !1, onOpenChange: y, openDelay: b = 300, closeDelay: x = 150, adjustTranslateX: S, adjustTranslateY: C, props: w, ...T } = m, E = n("tooltip"), D = T.id ?? E, [O, k] = e({
10
+ let { content: h, children: g, open: _, defaultOpen: v = !1, onOpenChange: y, openDelay: b = 300, closeDelay: x = 150, side: S = "bottom", align: C = "center", offset: w = 1, flip: T = !0, props: E, ...D } = m, O = r("tooltip"), k = D.id ?? O, [A, j] = t({
10
11
  value: _,
11
12
  defaultValue: v,
12
13
  onChange: y
13
- }), [A, j] = u(null), M = l(null), N = l(void 0), P = l(!1), F = l(!1), I = l(!1), L = l(!1), R = o(() => {
14
- clearTimeout(N.current), N.current = void 0;
15
- }, []), z = o((e, t) => {
16
- if (R(), e <= 0) {
14
+ }), [M, N] = u(null), P = l(null), F = l(void 0), I = l(!1), L = l(!1), R = l(!1), z = l(!1), B = o(() => {
15
+ clearTimeout(F.current), F.current = void 0;
16
+ }, []), V = o((e, t) => {
17
+ if (B(), e <= 0) {
17
18
  t();
18
19
  return;
19
20
  }
20
- N.current = setTimeout(() => {
21
- N.current = void 0, t();
21
+ F.current = setTimeout(() => {
22
+ F.current = void 0, t();
22
23
  }, e);
23
- }, [R]), B = o((e, t) => {
24
- z(x, () => {
25
- P.current || F.current || I.current || k(!1, {
24
+ }, [B]), H = o((e, t) => {
25
+ V(x, () => {
26
+ I.current || L.current || R.current || j(!1, {
26
27
  reason: e,
27
28
  event: t
28
29
  });
29
30
  });
30
31
  }, [
31
32
  x,
32
- z,
33
- k
33
+ V,
34
+ j
34
35
  ]);
35
- t({
36
- enabled: O,
36
+ n({
37
+ enabled: A,
37
38
  outsidePointer: !1,
38
- inside: [M],
39
+ inside: [P],
39
40
  onDismiss: (e, t) => {
40
- R(), L.current = !0, k(!1, {
41
+ B(), z.current = !0, j(!1, {
41
42
  reason: e,
42
43
  event: t
43
44
  });
44
45
  }
45
- }), s(() => R, [R]);
46
- let V = O && h != null, H = r((e) => {
47
- P.current = !0, !L.current && z(b, () => k(!0, {
46
+ }), s(() => B, [B]);
47
+ let U = A && h != null, W = e((e) => {
48
+ I.current = !0, !z.current && V(b, () => j(!0, {
48
49
  reason: "hover",
49
50
  event: e
50
51
  }));
51
- }), U = r((e) => {
52
- P.current = !1, L.current = !1, B("pointer-leave", e);
53
- }), W = r((e) => {
54
- I.current = !0, R(), k(!0, {
52
+ }), G = e((e) => {
53
+ I.current = !1, z.current = !1, H("pointer-leave", e);
54
+ }), K = e((e) => {
55
+ R.current = !0, B(), j(!0, {
55
56
  reason: "focus",
56
57
  event: e
57
58
  });
58
- }), G = r((e) => {
59
- I.current = !1, L.current = !1, B("blur", e);
60
- }), K = r(() => {
61
- F.current = !0, R();
62
- }), q = r((e) => {
63
- F.current = !1, B("pointer-leave", e);
64
- }), J = c(() => ({
65
- ref: j,
59
+ }), q = e((e) => {
60
+ R.current = !1, z.current = !1, H("blur", e);
61
+ }), J = e(() => {
62
+ L.current = !0, B();
63
+ }), Y = e((e) => {
64
+ L.current = !1, H("pointer-leave", e);
65
+ }), X = c(() => ({
66
+ ref: N,
66
67
  props: {
67
- "aria-describedby": V ? D : void 0,
68
- onPointerEnter: H,
69
- onPointerLeave: U,
70
- onFocus: W,
71
- onBlur: G
68
+ "aria-describedby": U ? k : void 0,
69
+ onPointerEnter: W,
70
+ onPointerLeave: G,
71
+ onFocus: K,
72
+ onBlur: q
72
73
  }
73
74
  }), [
74
- G,
75
- H,
75
+ q,
76
76
  W,
77
+ K,
78
+ G,
77
79
  U,
78
- V,
79
- D
80
+ k
80
81
  ]);
81
- return /* @__PURE__ */ p(d, { children: [g(J), /* @__PURE__ */ f(a, {
82
- present: V,
82
+ return /* @__PURE__ */ p(d, { children: [g(X), /* @__PURE__ */ f(a, {
83
+ present: U,
83
84
  children: (e) => /* @__PURE__ */ f(i, {
84
- ref: M,
85
+ ref: P,
85
86
  contentRef: e.ref,
86
- anchor: A,
87
- anchorSide: "bottom",
87
+ anchor: M,
88
+ side: S,
89
+ align: C,
90
+ offset: w,
91
+ flip: T,
88
92
  matchWidth: !1,
89
- adjustTranslateX: S,
90
- adjustTranslateY: C ?? "4px",
91
93
  component: "tooltip",
92
- ...T,
93
- variant: [T.variant, { closed: !e.present }],
94
- id: D,
94
+ ...D,
95
+ variant: [D.variant, { closed: !e.present }],
96
+ id: k,
95
97
  props: {
96
98
  role: "tooltip",
97
99
  ...e.props,
98
- ...w,
99
- onPointerEnter: K,
100
- onPointerLeave: q
100
+ ...E,
101
+ onPointerEnter: J,
102
+ onPointerLeave: Y
101
103
  },
102
104
  children: h
103
105
  })