@tempots/beatui 1.1.2 → 1.1.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.
@@ -0,0 +1 @@
1
+ "use strict";const e=require("@tempots/dom"),q=require("@tempots/ui"),K=require("@tempots/std"),W=require("./use-animated-toggle-cKcuItmz.cjs"),M=require("./session-id-B5lJMzbB.cjs");function H(u){const o={fade:!0,scale:!0};return u.startsWith("top")?(o.slide="down",o.transformOrigin="bottom"):u.startsWith("bottom")?(o.slide="up",o.transformOrigin="top"):u.startsWith("left")?(o.slide="right",o.transformOrigin="right"):u.startsWith("right")&&(o.slide="left",o.transformOrigin="left"),o}function $(u){const{content:o,placement:E="top",showDelay:A=250,hideDelay:D=500,mainAxisOffset:k=8,crossAxisOffset:F=0,showOn:d="hover-focus",closable:b=!0,arrow:P,role:p,hasPopup:I="dialog",open:y}=u;return q.PopOver((g,c)=>{const s=y??e.prop(!1),l=W.useAnimatedElementToggle({initialStatus:"closed"}),L=M.sessionId("flyout");let m=null,f=null,O=!1,v;function T(){t!=null&&(clearTimeout(t),t=null),a!=null&&(clearTimeout(a),a=null),f&&(f(),f=null),m&&(document.removeEventListener("keydown",m),m=null),O=!1}function S(){e.Value.get(b)&&(m=r=>{r.key==="Escape"&&s.set(!1)},document.addEventListener("keydown",m)),O=!0,g({placement:E??"top",mainAxisOffset:k,crossAxisOffset:F,arrow:P,content:e.WithElement(r=>{l.setElement(r);const h=typeof d=="function"?null:e.Value.get(d);(h==="hover"||h==="hover-focus")&&(r.addEventListener("mouseenter",()=>s.set(!0)),r.addEventListener("mouseleave",()=>s.set(!1))),f=K.delayedAnimationFrame(()=>{l.open(),f=null});const C=x=>{e.Value.get(b)&&x.key==="Escape"&&(x.preventDefault(),x.stopPropagation(),s.set(!1))};document.addEventListener("keydown",C,!0);let V=null;return e.Value.get(b)&&(V=x=>{const _=x.target;!r.contains(_)&&!v?.contains(_)&&s.set(!1)},document.addEventListener("click",V)),e.Fragment(e.OnDispose(()=>{V&&(document.removeEventListener("click",V),V=null),T(),document.removeEventListener("keydown",C,!0)}),e.attr.class("bc-flyout-container"),W.AnimatedToggleClass({animation:e.Value.map(E,H),status:l.status}),e.attr.id(L),e.attr.tabindex(-1),e.html.div(e.attr.class("bc-flyout"),p?e.attr.role(p):e.attr.role("dialog"),o()))})})}let t=null;function n(){if(t!=null&&(clearTimeout(t),t=null),a!=null&&(clearTimeout(a),a=null),l.isOpened.value||l.isOpening.value||l.isStartOpening.value)return;if(l.isClosing.value||l.isStartClosing.value){l.open();return}const r=e.Value.get(A);t=setTimeout(()=>{t=null,S()},r)}let a=null;function i(){if(!O&&t==null)return;if(t!=null&&(clearTimeout(t),t=null),a!=null&&(clearTimeout(a),a=null),f&&(f(),f=null,O)){c(),T();return}const r=e.Value.get(D);a=setTimeout(()=>{a=null,l.close(),l.listenOnClosed(()=>{c(),T()})},r)}const w=s.onChange(r=>{r?n():i()});return s.value&&n(),e.WithElement(r=>{v=r;const h=e.Fragment(e.aria.expanded(s),e.aria.controls(L),e.aria.haspopup(I));if(typeof d=="function")return e.Fragment(e.OnDispose(w),h,d(s));const C=d;return e.Fragment(e.OnDispose(w),h,e.OneOfValue(C,{"hover-focus":()=>e.Fragment(e.on.mouseenter(()=>s.set(!0)),e.on.mouseleave(()=>s.set(!1)),e.on.focus(()=>s.set(!0)),e.on.blur(()=>s.set(!1))),hover:()=>e.Fragment(e.on.mouseenter(()=>s.set(!0)),e.on.mouseleave(()=>s.set(!1))),focus:()=>e.Fragment(e.on.focus(()=>s.set(!0)),e.on.blur(()=>s.set(!1))),click:()=>e.on.click(()=>s.set(!s.value)),never:()=>null}))})})}function z(u){const{items:o,placement:E="bottom-start",showDelay:A=0,hideDelay:D=100,mainAxisOffset:k=4,crossAxisOffset:F=0,showOn:d="click",closable:b=!0,onClose:P,onAction:p,ariaLabel:I,ariaLabelledBy:y}=u,g=M.sessionId("menu"),c=e.prop(-1),s=e.prop([]),l=e.prop(!1);let L=null;return l.onChange(m=>{m||P?.()}),$({open:l,content:()=>e.WithElement(m=>{L=document.activeElement;const f=(t,n,a)=>{if(n.length===0)return-1;let i=t+a,w=0;for(;w<n.length;){i>=n.length&&(i=0),i<0&&(i=n.length-1);const r=n[i];if(r&&r.getAttribute("aria-disabled")!=="true")return i;i+=a,w++}return t},O=t=>{const n=s.value,a=c.value;switch(t.key){case"ArrowDown":t.preventDefault(),t.stopPropagation();const i=f(a,n,1);v(i,n);break;case"ArrowUp":t.preventDefault(),t.stopPropagation();const w=f(a,n,-1);v(w,n);break;case"Enter":case" ":if(t.preventDefault(),t.stopPropagation(),a>=0&&n[a]){const r=n[a];if(r.getAttribute("aria-disabled")==="true")return;const h=r.getAttribute("data-key");h&&p&&p(h),r.click(),l.set(!1)}break;case"Escape":l.set(!1);break;case"Home":t.preventDefault(),t.stopPropagation(),n.length>0&&v(0,n);break;case"End":t.preventDefault(),t.stopPropagation(),n.length>0&&v(n.length-1,n);break;case"ArrowRight":if(t.preventDefault(),t.stopPropagation(),a>=0&&n[a]){const r=n[a];r.classList.contains("bc-menu-item--has-submenu")&&r.dispatchEvent(new Event("mouseenter"))}break;case"ArrowLeft":t.preventDefault(),t.stopPropagation(),l.set(!1);break}},v=(t,n)=>{c.value>=0&&n[c.value]&&(n[c.value].classList.remove("bc-menu-item--focused"),n[c.value].removeAttribute("aria-selected")),t>=0&&n[t]&&(n[t].classList.add("bc-menu-item--focused"),n[t].setAttribute("aria-selected","true"),c.set(t),typeof n[t].scrollIntoView=="function"&&n[t].scrollIntoView({block:"nearest"}))},T=()=>{const t=Array.from(m.querySelectorAll('[role="menuitem"]'));if(s.set(t),t.length>0){const n=t.findIndex(a=>a.getAttribute("aria-disabled")!=="true");n>=0&&v(n,t)}},S=new MutationObserver(T);return S.observe(m,{childList:!0,subtree:!0}),setTimeout(()=>{T(),m.focus()},0),document.addEventListener("keydown",O,!0),e.Fragment(e.OnDispose(()=>{S.disconnect(),document.removeEventListener("keydown",O,!0),L&&L.focus()}),e.attr.class("bc-menu"),e.attr.id(g),e.attr.role("menu"),e.attr.tabindex(-1),e.aria.orientation("vertical"),I?e.aria.label(I):e.Empty,y?e.aria.labelledby(y):e.Empty,e.aria.activedescendant(c.map(t=>{const n=s.value;return t>=0&&n[t]?n[t].id||`${g}-item-${t}`:""})),e.on.click(t=>{const a=t.target.closest('[role="menuitem"]');if(a&&a.getAttribute("aria-disabled")!=="true"){const i=a.getAttribute("data-key");i&&p&&p(i),l.set(!1)}}),e.html.div(e.attr.class("sr-only"),e.aria.live("polite"),e.aria.atomic(!0),c.map(t=>{const n=s.value;if(t>=0&&n[t]){const a=n[t].textContent||"";return n[t].getAttribute("aria-disabled")==="true"?`${a}, disabled`:`${a}, ${t+1} of ${n.length}`}return""})),...o())}),placement:E,showDelay:A,hideDelay:D,mainAxisOffset:k,crossAxisOffset:F,showOn:d,closable:b,role:"menu"})}function B(u){const{key:o,content:E,before:A,after:D,disabled:k=!1,onClick:F,ariaLabel:d,submenu:b,submenuPlacement:P="right-start"}=u,p=o??M.sessionId("menu-item"),I=`menu-item-${p}`,y=b!=null;return e.html.div(e.attr.class(e.computedOf(k)(g=>`bc-menu-item ${g?"bc-menu-item--disabled":""} ${y?"bc-menu-item--has-submenu":""}`)),e.attr.id(I),e.attr.role("menuitem"),e.attr.tabindex(-1),e.dataAttr("key",p),e.aria.disabled(k),e.aria.selected(!1),y?e.aria.expanded(!1):e.Empty,d?e.aria.label(d):e.Empty,e.on.click(g=>{if(e.Value.get(k)){g.preventDefault(),g.stopPropagation();return}F?.()}),A&&e.html.span(e.attr.class("bc-menu-item__start"),A),e.html.span(e.attr.class("bc-menu-item__content"),E),D&&e.html.span(e.attr.class("bc-menu-item__end"),D),y&&b?$({content:()=>e.Fragment(e.attr.class("bc-menu bc-submenu"),e.attr.role("menu"),...b()),placement:P,showOn:"hover",hasPopup:"menu",showDelay:100,hideDelay:300,mainAxisOffset:0,crossAxisOffset:0,role:"menu"}):e.Empty)}function N(u={}){const{label:o}=u;return e.html.div(e.attr.class("bc-menu-separator"),e.attr.role("separator"),e.aria.orientation("horizontal"),o&&e.html.span(e.attr.class("bc-menu-separator__label"),o))}exports.Flyout=$;exports.Menu=z;exports.MenuItem=B;exports.MenuSeparator=N;
@@ -0,0 +1,366 @@
1
+ import { prop as q, WithElement as B, Fragment as k, aria as u, OnDispose as z, OneOfValue as j, on as p, Value as A, attr as a, html as E, Empty as W, computedOf as G, dataAttr as J } from "@tempots/dom";
2
+ import { PopOver as Q } from "@tempots/ui";
3
+ import { delayedAnimationFrame as X } from "@tempots/std";
4
+ import { u as Y, A as Z } from "./use-animated-toggle-C3asw_Sg.js";
5
+ import { s as N } from "./session-id-3KiilioY.js";
6
+ function ee(c) {
7
+ const l = { fade: !0, scale: !0 };
8
+ return c.startsWith("top") ? (l.slide = "down", l.transformOrigin = "bottom") : c.startsWith("bottom") ? (l.slide = "up", l.transformOrigin = "top") : c.startsWith("left") ? (l.slide = "right", l.transformOrigin = "right") : c.startsWith("right") && (l.slide = "left", l.transformOrigin = "left"), l;
9
+ }
10
+ function U(c) {
11
+ const {
12
+ content: l,
13
+ placement: T = "top",
14
+ showDelay: P = 250,
15
+ hideDelay: x = 500,
16
+ mainAxisOffset: D = 8,
17
+ crossAxisOffset: _ = 0,
18
+ showOn: b = "hover-focus",
19
+ closable: h = !0,
20
+ arrow: F,
21
+ role: g,
22
+ hasPopup: C = "dialog",
23
+ open: w
24
+ } = c;
25
+ return Q((v, f) => {
26
+ const s = w ?? q(!1), r = Y({
27
+ initialStatus: "closed"
28
+ }), S = N("flyout");
29
+ let m = null, d = null, I = !1, O;
30
+ function $() {
31
+ e != null && (clearTimeout(e), e = null), n != null && (clearTimeout(n), n = null), d && (d(), d = null), m && (document.removeEventListener("keydown", m), m = null), I = !1;
32
+ }
33
+ function K() {
34
+ A.get(h) && (m = (o) => {
35
+ o.key === "Escape" && s.set(!1);
36
+ }, document.addEventListener("keydown", m)), I = !0, v({
37
+ placement: T ?? "top",
38
+ mainAxisOffset: D,
39
+ crossAxisOffset: _,
40
+ arrow: F,
41
+ content: B((o) => {
42
+ r.setElement(o);
43
+ const y = typeof b == "function" ? null : A.get(b);
44
+ (y === "hover" || y === "hover-focus") && (o.addEventListener("mouseenter", () => s.set(!0)), o.addEventListener("mouseleave", () => s.set(!1))), d = X(() => {
45
+ r.open(), d = null;
46
+ });
47
+ const H = (V) => {
48
+ A.get(h) && V.key === "Escape" && (V.preventDefault(), V.stopPropagation(), s.set(!1));
49
+ };
50
+ document.addEventListener("keydown", H, !0);
51
+ let M = null;
52
+ return A.get(h) && (M = (V) => {
53
+ const R = V.target;
54
+ !o.contains(R) && !O?.contains(R) && s.set(!1);
55
+ }, document.addEventListener("click", M)), k(
56
+ z(() => {
57
+ M && (document.removeEventListener("click", M), M = null), $(), document.removeEventListener("keydown", H, !0);
58
+ }),
59
+ a.class("bc-flyout-container"),
60
+ Z({
61
+ animation: A.map(T, ee),
62
+ status: r.status
63
+ }),
64
+ a.id(S),
65
+ a.tabindex(-1),
66
+ // Make focusable for screen readers
67
+ E.div(
68
+ a.class("bc-flyout"),
69
+ g ? a.role(g) : a.role("dialog"),
70
+ // Default to dialog role
71
+ l()
72
+ )
73
+ );
74
+ })
75
+ });
76
+ }
77
+ let e = null;
78
+ function t() {
79
+ if (e != null && (clearTimeout(e), e = null), n != null && (clearTimeout(n), n = null), r.isOpened.value || r.isOpening.value || r.isStartOpening.value)
80
+ return;
81
+ if (r.isClosing.value || r.isStartClosing.value) {
82
+ r.open();
83
+ return;
84
+ }
85
+ const o = A.get(P);
86
+ e = setTimeout(() => {
87
+ e = null, K();
88
+ }, o);
89
+ }
90
+ let n = null;
91
+ function i() {
92
+ if (!I && e == null)
93
+ return;
94
+ if (e != null && (clearTimeout(e), e = null), n != null && (clearTimeout(n), n = null), d && (d(), d = null, I)) {
95
+ f(), $();
96
+ return;
97
+ }
98
+ const o = A.get(x);
99
+ n = setTimeout(() => {
100
+ n = null, r.close(), r.listenOnClosed(() => {
101
+ f(), $();
102
+ });
103
+ }, o);
104
+ }
105
+ const L = s.onChange((o) => {
106
+ o ? t() : i();
107
+ });
108
+ return s.value && t(), B((o) => {
109
+ O = o;
110
+ const y = k(
111
+ u.expanded(s),
112
+ u.controls(S),
113
+ u.haspopup(
114
+ C
115
+ )
116
+ );
117
+ if (typeof b == "function")
118
+ return k(
119
+ z(L),
120
+ y,
121
+ b(s)
122
+ );
123
+ const H = b;
124
+ return k(
125
+ z(L),
126
+ y,
127
+ j(H, {
128
+ "hover-focus": () => k(
129
+ p.mouseenter(() => s.set(!0)),
130
+ p.mouseleave(() => s.set(!1)),
131
+ p.focus(() => s.set(!0)),
132
+ p.blur(() => s.set(!1))
133
+ ),
134
+ hover: () => k(
135
+ p.mouseenter(() => s.set(!0)),
136
+ p.mouseleave(() => s.set(!1))
137
+ ),
138
+ focus: () => k(
139
+ p.focus(() => s.set(!0)),
140
+ p.blur(() => s.set(!1))
141
+ ),
142
+ click: () => p.click(() => s.set(!s.value)),
143
+ never: () => null
144
+ })
145
+ );
146
+ });
147
+ });
148
+ }
149
+ function le(c) {
150
+ const {
151
+ items: l,
152
+ placement: T = "bottom-start",
153
+ showDelay: P = 0,
154
+ hideDelay: x = 100,
155
+ mainAxisOffset: D = 4,
156
+ crossAxisOffset: _ = 0,
157
+ showOn: b = "click",
158
+ closable: h = !0,
159
+ onClose: F,
160
+ onAction: g,
161
+ ariaLabel: C,
162
+ ariaLabelledBy: w
163
+ } = c, v = N("menu"), f = q(-1), s = q([]), r = q(!1);
164
+ let S = null;
165
+ return r.onChange((m) => {
166
+ m || F?.();
167
+ }), U({
168
+ open: r,
169
+ content: () => B((m) => {
170
+ S = document.activeElement;
171
+ const d = (e, t, n) => {
172
+ if (t.length === 0) return -1;
173
+ let i = e + n, L = 0;
174
+ for (; L < t.length; ) {
175
+ i >= t.length && (i = 0), i < 0 && (i = t.length - 1);
176
+ const o = t[i];
177
+ if (o && o.getAttribute("aria-disabled") !== "true")
178
+ return i;
179
+ i += n, L++;
180
+ }
181
+ return e;
182
+ }, I = (e) => {
183
+ const t = s.value, n = f.value;
184
+ switch (e.key) {
185
+ case "ArrowDown":
186
+ e.preventDefault(), e.stopPropagation();
187
+ const i = d(n, t, 1);
188
+ O(i, t);
189
+ break;
190
+ case "ArrowUp":
191
+ e.preventDefault(), e.stopPropagation();
192
+ const L = d(n, t, -1);
193
+ O(L, t);
194
+ break;
195
+ case "Enter":
196
+ case " ":
197
+ if (e.preventDefault(), e.stopPropagation(), n >= 0 && t[n]) {
198
+ const o = t[n];
199
+ if (o.getAttribute("aria-disabled") === "true")
200
+ return;
201
+ const y = o.getAttribute("data-key");
202
+ y && g && g(y), o.click(), r.set(!1);
203
+ }
204
+ break;
205
+ case "Escape":
206
+ r.set(!1);
207
+ break;
208
+ case "Home":
209
+ e.preventDefault(), e.stopPropagation(), t.length > 0 && O(0, t);
210
+ break;
211
+ case "End":
212
+ e.preventDefault(), e.stopPropagation(), t.length > 0 && O(t.length - 1, t);
213
+ break;
214
+ case "ArrowRight":
215
+ if (e.preventDefault(), e.stopPropagation(), n >= 0 && t[n]) {
216
+ const o = t[n];
217
+ o.classList.contains(
218
+ "bc-menu-item--has-submenu"
219
+ ) && o.dispatchEvent(new Event("mouseenter"));
220
+ }
221
+ break;
222
+ case "ArrowLeft":
223
+ e.preventDefault(), e.stopPropagation(), r.set(!1);
224
+ break;
225
+ }
226
+ }, O = (e, t) => {
227
+ f.value >= 0 && t[f.value] && (t[f.value].classList.remove(
228
+ "bc-menu-item--focused"
229
+ ), t[f.value].removeAttribute("aria-selected")), e >= 0 && t[e] && (t[e].classList.add("bc-menu-item--focused"), t[e].setAttribute("aria-selected", "true"), f.set(e), typeof t[e].scrollIntoView == "function" && t[e].scrollIntoView({ block: "nearest" }));
230
+ }, $ = () => {
231
+ const e = Array.from(
232
+ m.querySelectorAll('[role="menuitem"]')
233
+ );
234
+ if (s.set(e), e.length > 0) {
235
+ const t = e.findIndex(
236
+ (n) => n.getAttribute("aria-disabled") !== "true"
237
+ );
238
+ t >= 0 && O(t, e);
239
+ }
240
+ }, K = new MutationObserver($);
241
+ return K.observe(m, { childList: !0, subtree: !0 }), setTimeout(() => {
242
+ $(), m.focus();
243
+ }, 0), document.addEventListener("keydown", I, !0), k(
244
+ z(() => {
245
+ K.disconnect(), document.removeEventListener("keydown", I, !0), S && S.focus();
246
+ }),
247
+ a.class("bc-menu"),
248
+ a.id(v),
249
+ a.role("menu"),
250
+ a.tabindex(-1),
251
+ u.orientation("vertical"),
252
+ C ? u.label(C) : W,
253
+ w ? u.labelledby(w) : W,
254
+ u.activedescendant(
255
+ f.map((e) => {
256
+ const t = s.value;
257
+ return e >= 0 && t[e] ? t[e].id || `${v}-item-${e}` : "";
258
+ })
259
+ ),
260
+ p.click((e) => {
261
+ const n = e.target.closest('[role="menuitem"]');
262
+ if (n && n.getAttribute("aria-disabled") !== "true") {
263
+ const i = n.getAttribute("data-key");
264
+ i && g && g(i), r.set(!1);
265
+ }
266
+ }),
267
+ // Live region for screen reader announcements
268
+ E.div(
269
+ a.class("sr-only"),
270
+ u.live("polite"),
271
+ u.atomic(!0),
272
+ f.map((e) => {
273
+ const t = s.value;
274
+ if (e >= 0 && t[e]) {
275
+ const n = t[e].textContent || "";
276
+ return t[e].getAttribute("aria-disabled") === "true" ? `${n}, disabled` : `${n}, ${e + 1} of ${t.length}`;
277
+ }
278
+ return "";
279
+ })
280
+ ),
281
+ ...l()
282
+ );
283
+ }),
284
+ placement: T,
285
+ showDelay: P,
286
+ hideDelay: x,
287
+ mainAxisOffset: D,
288
+ crossAxisOffset: _,
289
+ showOn: b,
290
+ closable: h,
291
+ role: "menu"
292
+ });
293
+ }
294
+ function re(c) {
295
+ const {
296
+ key: l,
297
+ content: T,
298
+ before: P,
299
+ after: x,
300
+ disabled: D = !1,
301
+ onClick: _,
302
+ ariaLabel: b,
303
+ submenu: h,
304
+ submenuPlacement: F = "right-start"
305
+ } = c, g = l ?? N("menu-item"), C = `menu-item-${g}`, w = h != null;
306
+ return E.div(
307
+ a.class(
308
+ G(D)(
309
+ (v) => `bc-menu-item ${v ? "bc-menu-item--disabled" : ""} ${w ? "bc-menu-item--has-submenu" : ""}`
310
+ )
311
+ ),
312
+ a.id(C),
313
+ a.role("menuitem"),
314
+ a.tabindex(-1),
315
+ J("key", g),
316
+ u.disabled(D),
317
+ u.selected(!1),
318
+ // Will be updated by focus management
319
+ w ? u.expanded(!1) : W,
320
+ b ? u.label(b) : W,
321
+ p.click((v) => {
322
+ if (A.get(D)) {
323
+ v.preventDefault(), v.stopPropagation();
324
+ return;
325
+ }
326
+ _?.();
327
+ }),
328
+ // Before content
329
+ P && E.span(a.class("bc-menu-item__start"), P),
330
+ // Main content
331
+ E.span(a.class("bc-menu-item__content"), T),
332
+ // After content
333
+ x && E.span(a.class("bc-menu-item__end"), x),
334
+ // Submenu (if present)
335
+ w && h ? U({
336
+ content: () => k(
337
+ a.class("bc-menu bc-submenu"),
338
+ a.role("menu"),
339
+ ...h()
340
+ ),
341
+ placement: F,
342
+ showOn: "hover",
343
+ hasPopup: "menu",
344
+ showDelay: 100,
345
+ hideDelay: 300,
346
+ mainAxisOffset: 0,
347
+ crossAxisOffset: 0,
348
+ role: "menu"
349
+ }) : W
350
+ );
351
+ }
352
+ function ie(c = {}) {
353
+ const { label: l } = c;
354
+ return E.div(
355
+ a.class("bc-menu-separator"),
356
+ a.role("separator"),
357
+ u.orientation("horizontal"),
358
+ l && E.span(a.class("bc-menu-separator__label"), l)
359
+ );
360
+ }
361
+ export {
362
+ U as F,
363
+ le as M,
364
+ re as a,
365
+ ie as b
366
+ };
@@ -1,4 +1,4 @@
1
- import { Renderable, TNode, Value } from '@tempots/dom';
1
+ import { Renderable, TNode, Value, Prop } from '@tempots/dom';
2
2
  import { Placement } from '@tempots/ui';
3
3
  /**
4
4
  * Built-in trigger modes that control how the {@link Flyout} is shown.
@@ -12,14 +12,13 @@ import { Placement } from '@tempots/ui';
12
12
  export type FlyoutTrigger = 'hover' | 'focus' | 'hover-focus' | 'click' | 'never';
13
13
  /**
14
14
  * Custom trigger function for the {@link Flyout} component.
15
- * Receives `show` and `hide` callbacks and returns trigger content that controls
15
+ * Receives the open state signal and returns trigger content that controls
16
16
  * when the flyout appears and disappears.
17
17
  *
18
- * @param show - Call to show the flyout
19
- * @param hide - Call to hide the flyout
18
+ * @param open - Writable signal representing the flyout's open state. Set to `true` to show, `false` to hide.
20
19
  * @returns A renderable node containing the trigger logic
21
20
  */
22
- export type FlyoutTriggerFunction = (show: () => void, hide: () => void) => TNode;
21
+ export type FlyoutTriggerFunction = (open: Prop<boolean>) => TNode;
23
22
  /**
24
23
  * Positioning data for a popover arrow element, provided by the PopOver positioning engine.
25
24
  */
@@ -101,6 +100,17 @@ export interface FlyoutOptions {
101
100
  * @default 'dialog'
102
101
  */
103
102
  hasPopup?: Value<boolean | 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'>;
103
+ /**
104
+ * External signal controlling the flyout's open/closed state.
105
+ * When provided, this signal becomes the single source of truth:
106
+ * - Setting it to `true` opens the flyout (respecting `showDelay`)
107
+ * - Setting it to `false` closes the flyout (respecting `hideDelay`)
108
+ * - Internal close paths (click-outside, Escape) set this signal to `false`
109
+ * - Built-in and custom triggers toggle this signal
110
+ *
111
+ * When omitted, the flyout manages its own internal open state.
112
+ */
113
+ open?: Prop<boolean>;
104
114
  }
105
115
  /**
106
116
  * Flexible popover component with configurable trigger modes, animated transitions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tempots/beatui",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.es.js",