@mirror-physics/fractal-ui 0.2.0-next.84 → 0.2.0-next.86
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/dist/column-editor.css.map +1 -1
- package/dist/index.cjs +27 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +43 -12
- package/dist/index.css.map +1 -1
- package/dist/index.js +27 -9
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +3 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1427,6 +1427,9 @@ import * as React11 from "react";
|
|
|
1427
1427
|
import { Close as Close2, Check as Check2, MagnifyingGlass as MagnifyingGlass2, ChevronDown, ChevronLeft, ChevronRight as ChevronRight2, ChevronUp } from "@mirror-physics/fractal-icons";
|
|
1428
1428
|
|
|
1429
1429
|
// src/components/Dropdown/position.ts
|
|
1430
|
+
function isDropdownTriggerVisible(trigger, bounds) {
|
|
1431
|
+
return trigger.right > bounds.left && trigger.left < bounds.right && trigger.bottom > bounds.top && trigger.top < bounds.bottom;
|
|
1432
|
+
}
|
|
1430
1433
|
function positionDropdown(trigger, panel, bounds, direction, align) {
|
|
1431
1434
|
const gap = 4;
|
|
1432
1435
|
const width = Math.min(panel.width, Math.max(0, bounds.right - bounds.left));
|
|
@@ -1497,6 +1500,9 @@ function Dropdown({
|
|
|
1497
1500
|
}) {
|
|
1498
1501
|
const [query, setQuery] = React11.useState("");
|
|
1499
1502
|
const searchRef = React11.useRef(null);
|
|
1503
|
+
const searchContainerRef = React11.useRef(null);
|
|
1504
|
+
const optionsRef = React11.useRef(null);
|
|
1505
|
+
const [optionsScrolled, setOptionsScrolled] = React11.useState(false);
|
|
1500
1506
|
const accessibleLabel = triggerLabel ?? fieldLabel ?? "Options";
|
|
1501
1507
|
const size = controlSize ?? sizeAlias;
|
|
1502
1508
|
const canClear = clearable && !disabled && (multiple ? selectedValues.length > 0 && Boolean(onSelectionChange) : Boolean(selectedValue) && Boolean(onSelect));
|
|
@@ -1534,6 +1540,11 @@ function Dropdown({
|
|
|
1534
1540
|
setOpen(false);
|
|
1535
1541
|
triggerRef.current?.focus();
|
|
1536
1542
|
}, open);
|
|
1543
|
+
React11.useLayoutEffect(() => {
|
|
1544
|
+
if (!open) return;
|
|
1545
|
+
if (optionsRef.current) optionsRef.current.scrollTop = 0;
|
|
1546
|
+
setOptionsScrolled(false);
|
|
1547
|
+
}, [open, query]);
|
|
1537
1548
|
React11.useLayoutEffect(() => {
|
|
1538
1549
|
const root = rootRef.current;
|
|
1539
1550
|
const trigger = triggerRef.current;
|
|
@@ -1559,19 +1570,24 @@ function Dropdown({
|
|
|
1559
1570
|
bounds.bottom = Math.min(bounds.bottom, rect.top + ancestor.clientTop + ancestor.clientHeight);
|
|
1560
1571
|
}
|
|
1561
1572
|
}
|
|
1573
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1574
|
+
if (!isDropdownTriggerVisible(triggerRect, bounds)) {
|
|
1575
|
+
focusOnOpen.current = false;
|
|
1576
|
+
setOpen(false);
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1562
1579
|
const padding = Math.max(0, collisionPadding);
|
|
1563
1580
|
bounds.left += padding;
|
|
1564
1581
|
bounds.right = Math.max(bounds.left, bounds.right - padding);
|
|
1565
1582
|
bounds.top += padding;
|
|
1566
1583
|
bounds.bottom = Math.max(bounds.top, bounds.bottom - padding);
|
|
1567
|
-
const triggerRect = trigger.getBoundingClientRect();
|
|
1568
1584
|
const rootRect = root.getBoundingClientRect();
|
|
1569
1585
|
const availableWidth = bounds.right - bounds.left;
|
|
1570
1586
|
const heightLimit = Math.max(0, maxHeight);
|
|
1571
1587
|
panel.style.maxWidth = `${availableWidth}px`;
|
|
1572
1588
|
panel.style.minWidth = `${Math.min(triggerRect.width, availableWidth)}px`;
|
|
1573
1589
|
const panelRect = panel.getBoundingClientRect();
|
|
1574
|
-
const desiredHeight = Math.min(heightLimit,
|
|
1590
|
+
const desiredHeight = Math.min(heightLimit, (optionsRef.current?.scrollHeight ?? 0) + (searchContainerRef.current?.offsetHeight ?? 0) + parseFloat(getComputedStyle(panel).paddingTop) + parseFloat(getComputedStyle(panel).paddingBottom) + panel.offsetHeight - panel.clientHeight);
|
|
1575
1591
|
const position = positionDropdown(triggerRect, { width: panelRect.width, height: desiredHeight }, bounds, direction, align);
|
|
1576
1592
|
const nextStyle = {
|
|
1577
1593
|
left: position.left - rootRect.left - root.clientLeft + root.scrollLeft,
|
|
@@ -1584,8 +1600,9 @@ function Dropdown({
|
|
|
1584
1600
|
panel.style[key] = `${nextStyle[key]}px`;
|
|
1585
1601
|
}
|
|
1586
1602
|
setPanelStyle((previous) => Object.entries(nextStyle).every(([key, value]) => previous[key] === value) ? previous : nextStyle);
|
|
1603
|
+
return true;
|
|
1587
1604
|
};
|
|
1588
|
-
updatePosition();
|
|
1605
|
+
if (!updatePosition()) return;
|
|
1589
1606
|
if (searchable && !panel.contains(document.activeElement)) searchRef.current?.focus({ preventScroll: true });
|
|
1590
1607
|
if (focusOnOpen.current) {
|
|
1591
1608
|
focusOnOpen.current = false;
|
|
@@ -1596,6 +1613,7 @@ function Dropdown({
|
|
|
1596
1613
|
const resize = new ResizeObserver(updatePosition);
|
|
1597
1614
|
resize.observe(root);
|
|
1598
1615
|
resize.observe(panel);
|
|
1616
|
+
if (optionsRef.current) resize.observe(optionsRef.current);
|
|
1599
1617
|
for (let ancestor = root.parentElement; ancestor; ancestor = ancestor.parentElement) {
|
|
1600
1618
|
resize.observe(ancestor);
|
|
1601
1619
|
}
|
|
@@ -1695,11 +1713,11 @@ function Dropdown({
|
|
|
1695
1713
|
className: cn("fractal-dropdown-panel", `fractal-dropdown-panel--${size}`, panelClassName),
|
|
1696
1714
|
style: panelStyle,
|
|
1697
1715
|
children: [
|
|
1698
|
-
searchable && /* @__PURE__ */ jsxs17("div", { className: "fractal-dropdown-search", children: [
|
|
1716
|
+
searchable && /* @__PURE__ */ jsx19("div", { ref: searchContainerRef, className: "fractal-dropdown-search-container", "data-scrolled": optionsScrolled, children: /* @__PURE__ */ jsxs17("div", { className: "fractal-dropdown-search", children: [
|
|
1699
1717
|
/* @__PURE__ */ jsx19(MagnifyingGlass2, { "aria-hidden": "true" }),
|
|
1700
1718
|
/* @__PURE__ */ jsx19("input", { ref: searchRef, type: "search", "aria-label": searchPlaceholder, placeholder: searchPlaceholder, value: query, onChange: (event) => setQuery(event.target.value) })
|
|
1701
|
-
] }),
|
|
1702
|
-
/* @__PURE__ */ jsxs17("div", { role: "listbox", id: `${menuId}-options`, "aria-label": accessibleLabel, "aria-multiselectable": multiple || void 0, children: [
|
|
1719
|
+
] }) }),
|
|
1720
|
+
/* @__PURE__ */ jsxs17("div", { ref: optionsRef, className: "fractal-dropdown-options", onScroll: (event) => setOptionsScrolled(event.currentTarget.scrollTop > 0), role: "listbox", id: `${menuId}-options`, "aria-label": accessibleLabel, "aria-multiselectable": multiple || void 0, children: [
|
|
1703
1721
|
label != null && /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-label", children: label }),
|
|
1704
1722
|
visibleItems.map((item, index) => {
|
|
1705
1723
|
const topDivider = item.border === "top" ? /* @__PURE__ */ jsx19("div", { className: "fractal-dropdown-separator" }) : null;
|
|
@@ -1739,9 +1757,9 @@ function Dropdown({
|
|
|
1739
1757
|
),
|
|
1740
1758
|
bottomDivider
|
|
1741
1759
|
] }, item.value);
|
|
1742
|
-
})
|
|
1743
|
-
|
|
1744
|
-
|
|
1760
|
+
}),
|
|
1761
|
+
!selectableItems.length && /* @__PURE__ */ jsx19("p", { role: "status", className: "fractal-dropdown-label", children: emptyMessage })
|
|
1762
|
+
] })
|
|
1745
1763
|
]
|
|
1746
1764
|
}
|
|
1747
1765
|
)
|