@broberg/app-shell 0.13.1 → 0.14.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.
- package/README.md +15 -1
- package/css/app-shell.css +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js.map +1 -1
- package/dist/preact.cjs +65 -17
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +4 -0
- package/dist/preact.d.ts +4 -0
- package/dist/preact.js +65 -17
- package/dist/preact.js.map +1 -1
- package/package.json +1 -1
package/dist/preact.cjs
CHANGED
|
@@ -517,27 +517,50 @@ function RowActions(props) {
|
|
|
517
517
|
const btn = hooks.useRef(null);
|
|
518
518
|
const menu = hooks.useRef(null);
|
|
519
519
|
const [stack, setStack] = hooks.useState([]);
|
|
520
|
-
const [hi,
|
|
520
|
+
const [hi, setHiState] = hooks.useState(0);
|
|
521
|
+
const hiRef = hooks.useRef(0);
|
|
522
|
+
const setHi = (n) => {
|
|
523
|
+
hiRef.current = n;
|
|
524
|
+
setHiState(n);
|
|
525
|
+
};
|
|
526
|
+
const [armed, setArmedState] = hooks.useState(null);
|
|
527
|
+
const armedRef = hooks.useRef(null);
|
|
528
|
+
const setArmed = (v) => {
|
|
529
|
+
armedRef.current = v;
|
|
530
|
+
setArmedState(v);
|
|
531
|
+
};
|
|
532
|
+
const items = hooks.useRef([]);
|
|
533
|
+
const onKeyDownRef = hooks.useRef(() => {
|
|
534
|
+
});
|
|
521
535
|
const [value, setValue] = hooks.useState("");
|
|
522
536
|
const [pos, setPos] = hooks.useState(void 0);
|
|
523
537
|
const view = stack[stack.length - 1];
|
|
524
538
|
const open = !!view;
|
|
539
|
+
const stackRef = hooks.useRef([]);
|
|
540
|
+
const setStackNow = (next) => {
|
|
541
|
+
stackRef.current = next;
|
|
542
|
+
setStack(next);
|
|
543
|
+
};
|
|
525
544
|
const close = (refocus = true) => {
|
|
526
|
-
|
|
545
|
+
setStackNow([]);
|
|
546
|
+
setArmed(null);
|
|
527
547
|
if (refocus) btn.current?.focus();
|
|
528
548
|
};
|
|
529
549
|
const show = (v) => {
|
|
530
|
-
|
|
550
|
+
setStackNow([...stackRef.current, v]);
|
|
531
551
|
setHi(0);
|
|
552
|
+
setArmed(null);
|
|
532
553
|
if (v.kind === "input") setValue(v.action.input.value);
|
|
533
554
|
};
|
|
534
555
|
const back = () => {
|
|
535
|
-
|
|
556
|
+
setStackNow(stackRef.current.slice(0, -1));
|
|
536
557
|
setHi(0);
|
|
558
|
+
setArmed(null);
|
|
537
559
|
};
|
|
538
560
|
const pick = (a) => {
|
|
539
561
|
if (a.submenu?.length) return show({ kind: "list", actions: a.submenu, title: a.label });
|
|
540
562
|
if (a.input) return show({ kind: "input", action: a });
|
|
563
|
+
if (a.confirm && armedRef.current !== a.id) return setArmed(a.id);
|
|
541
564
|
close();
|
|
542
565
|
props.onAction(a.id);
|
|
543
566
|
};
|
|
@@ -554,50 +577,69 @@ function RowActions(props) {
|
|
|
554
577
|
const left = Math.max(m, Math.min(r.right - w, vw - w - m));
|
|
555
578
|
const top = r.bottom + 4 + h <= vh - m || r.top - 4 - h < m ? Math.min(r.bottom + 4, vh - m - h) : r.top - 4 - h;
|
|
556
579
|
setPos({ position: "fixed", left: `${left}px`, top: `${Math.max(m, top)}px`, width: `${w}px` });
|
|
557
|
-
if (view?.kind === "input") menu.current?.querySelector("input")?.focus();
|
|
558
|
-
else menu.current?.focus();
|
|
559
580
|
}, [open, stack.length]);
|
|
560
|
-
hooks.
|
|
581
|
+
hooks.useLayoutEffect(() => {
|
|
582
|
+
if (!open || !pos) return;
|
|
583
|
+
if (view?.kind === "input") menu.current?.querySelector("input")?.focus();
|
|
584
|
+
else items.current[hiRef.current]?.focus();
|
|
585
|
+
}, [open, pos, hi, stack.length]);
|
|
586
|
+
hooks.useLayoutEffect(() => {
|
|
561
587
|
if (!open) return;
|
|
562
588
|
const outside = (e) => {
|
|
563
589
|
const n = e.target instanceof Node ? e.target : null;
|
|
564
590
|
if (n && (menu.current?.contains(n) || btn.current?.contains(n))) return;
|
|
565
591
|
close(false);
|
|
566
592
|
};
|
|
593
|
+
const early = (e) => {
|
|
594
|
+
const n = e.target instanceof Node ? e.target : null;
|
|
595
|
+
if (n && menu.current?.contains(n)) return;
|
|
596
|
+
if (e.key === "Enter" || e.key === " " || e.key === "Spacebar" || e.key === "Tab") return;
|
|
597
|
+
onKeyDownRef.current(e);
|
|
598
|
+
};
|
|
599
|
+
document.addEventListener("keydown", early, true);
|
|
567
600
|
document.addEventListener("mousedown", outside);
|
|
568
601
|
window.addEventListener("scroll", outside, true);
|
|
569
602
|
window.addEventListener("resize", outside);
|
|
570
603
|
return () => {
|
|
604
|
+
document.removeEventListener("keydown", early, true);
|
|
571
605
|
document.removeEventListener("mousedown", outside);
|
|
572
606
|
window.removeEventListener("scroll", outside, true);
|
|
573
607
|
window.removeEventListener("resize", outside);
|
|
574
608
|
};
|
|
575
609
|
}, [open]);
|
|
576
610
|
const onKeyDown = (e) => {
|
|
577
|
-
|
|
611
|
+
const stack2 = stackRef.current;
|
|
612
|
+
const view2 = stack2[stack2.length - 1];
|
|
613
|
+
if (!view2) return;
|
|
578
614
|
e.stopPropagation();
|
|
579
615
|
if (e.key === "Escape") {
|
|
580
616
|
e.preventDefault();
|
|
581
617
|
return close();
|
|
582
618
|
}
|
|
583
|
-
if (
|
|
619
|
+
if (view2.kind === "input") {
|
|
584
620
|
if (e.key === "Enter") {
|
|
585
621
|
e.preventDefault();
|
|
586
|
-
save(
|
|
622
|
+
save(view2.action);
|
|
587
623
|
}
|
|
588
624
|
return;
|
|
589
625
|
}
|
|
590
|
-
if ((e.key === "ArrowLeft" || e.key === "Backspace") &&
|
|
626
|
+
if ((e.key === "ArrowLeft" || e.key === "Backspace") && stack2.length > 1) {
|
|
591
627
|
e.preventDefault();
|
|
592
628
|
return back();
|
|
593
629
|
}
|
|
594
|
-
const list =
|
|
595
|
-
|
|
630
|
+
const list = view2.actions;
|
|
631
|
+
if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
|
|
632
|
+
e.preventDefault();
|
|
633
|
+
const at = items.current.findIndex((b) => b === document.activeElement);
|
|
634
|
+
const idx = at >= 0 ? at : hiRef.current;
|
|
635
|
+
return list[idx] ? pick(list[idx]) : void 0;
|
|
636
|
+
}
|
|
637
|
+
const { state, intent } = uiControlsCore.selectKeyReducer({ open: true, highlighted: hiRef.current }, e.key, list.length);
|
|
596
638
|
if (intent.type === "select") {
|
|
597
639
|
e.preventDefault();
|
|
598
640
|
return pick(list[intent.index]);
|
|
599
641
|
}
|
|
600
|
-
if (state.highlighted !==
|
|
642
|
+
if (state.highlighted !== hiRef.current) {
|
|
601
643
|
e.preventDefault();
|
|
602
644
|
return setHi(state.highlighted);
|
|
603
645
|
}
|
|
@@ -607,6 +649,7 @@ function RowActions(props) {
|
|
|
607
649
|
pick(byKbd);
|
|
608
650
|
}
|
|
609
651
|
};
|
|
652
|
+
onKeyDownRef.current = onKeyDown;
|
|
610
653
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
611
654
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
612
655
|
"button",
|
|
@@ -618,7 +661,7 @@ function RowActions(props) {
|
|
|
618
661
|
"aria-label": `${t.moreFor} ${props.item.label}`,
|
|
619
662
|
"aria-haspopup": "menu",
|
|
620
663
|
"aria-expanded": open,
|
|
621
|
-
onClick: () =>
|
|
664
|
+
onClick: () => stackRef.current.length ? close() : show({ kind: "list", actions: props.item.actions }),
|
|
622
665
|
children: /* @__PURE__ */ jsxRuntime.jsx(IconMore, {})
|
|
623
666
|
}
|
|
624
667
|
),
|
|
@@ -643,13 +686,18 @@ function RowActions(props) {
|
|
|
643
686
|
{
|
|
644
687
|
type: "button",
|
|
645
688
|
role: "menuitem",
|
|
646
|
-
|
|
689
|
+
ref: (el) => {
|
|
690
|
+
items.current[i] = el;
|
|
691
|
+
},
|
|
692
|
+
tabIndex: i === hi ? 0 : -1,
|
|
693
|
+
class: "bas-rowmenu__item" + (i === hi ? " is-active" : "") + (a.danger ? " is-danger" : "") + (armed === a.id ? " is-armed" : ""),
|
|
647
694
|
"data-testid": `sidebar-item-${id}-action-${a.id}`,
|
|
648
695
|
onMouseEnter: () => setHi(i),
|
|
696
|
+
onFocus: () => setHi(i),
|
|
649
697
|
onClick: () => pick(a),
|
|
650
698
|
children: [
|
|
651
699
|
a.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-rowmenu__icon", children: a.icon }) : null,
|
|
652
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-rowmenu__label", children: a.label }),
|
|
700
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { class: "bas-rowmenu__label", children: armed === a.id && a.confirm ? a.confirm.label : a.label }),
|
|
653
701
|
a.submenu?.length ? /* @__PURE__ */ jsxRuntime.jsx(IconChevronRight, {}) : a.kbd ? /* @__PURE__ */ jsxRuntime.jsx("kbd", { class: "bas-rowmenu__kbd", children: a.kbd.toUpperCase() }) : null
|
|
654
702
|
]
|
|
655
703
|
},
|