@diwauhris/ui 1.7.26 → 1.7.28
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/lib/assets/ui.css +6 -0
- package/lib/index.cjs +46 -24
- package/lib/index.mjs +47 -25
- package/lib/types/ui-library/gallery/date-picker/DatePicker.d.ts +4 -1
- package/package.json +1 -1
package/lib/assets/ui.css
CHANGED
|
@@ -4442,6 +4442,12 @@ body {
|
|
|
4442
4442
|
animation: datepickerIn 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
4443
4443
|
overflow: hidden;
|
|
4444
4444
|
}
|
|
4445
|
+
/* Hidden during initial measurement — no animation until final position is set */
|
|
4446
|
+
.pis-datepicker-popover--measuring {
|
|
4447
|
+
opacity: 0;
|
|
4448
|
+
pointer-events: none;
|
|
4449
|
+
animation: none;
|
|
4450
|
+
}
|
|
4445
4451
|
@keyframes datepickerIn {
|
|
4446
4452
|
from { opacity: 0; transform: translateY(6px) scale(0.97); }
|
|
4447
4453
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
package/lib/index.cjs
CHANGED
|
@@ -1408,16 +1408,20 @@ function computePopupStyle(rect, placement = "auto", measuredHeight) {
|
|
|
1408
1408
|
left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
|
|
1409
1409
|
width: isNarrow ? `calc(100vw - 16px)` : void 0
|
|
1410
1410
|
};
|
|
1411
|
-
|
|
1411
|
+
const placeBelow = placement === "below" ? true : placement === "above" ? false : spaceBelow >= height || spaceBelow >= spaceAbove;
|
|
1412
|
+
if (placeBelow) style.top = Math.min(rect.bottom + 6, window.innerHeight - height - 8);
|
|
1412
1413
|
else style.top = Math.max(rect.top - height - 6, 8);
|
|
1413
|
-
return
|
|
1414
|
+
return {
|
|
1415
|
+
style,
|
|
1416
|
+
placedAbove: !placeBelow
|
|
1417
|
+
};
|
|
1414
1418
|
}
|
|
1415
1419
|
function DatePicker({ value, onChange, placeholder, className, disabled, error, minDate, maxDate, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, required, dateFormat = "MMM d, yyyy", clearable = false, onOpenChange, placement = "auto", locale, name, isDateDisabled, readOnly = false, open, defaultOpen = false }) {
|
|
1416
1420
|
const isControlled = open !== void 0;
|
|
1417
1421
|
const [uncontrolledOpen, setUncontrolledOpen] = (0, react.useState)(defaultOpen);
|
|
1418
1422
|
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1419
1423
|
const [popupStyle, setPopupStyle] = (0, react.useState)({});
|
|
1420
|
-
const
|
|
1424
|
+
const placedAbove = (0, react.useRef)(false);
|
|
1421
1425
|
const wrapperRef = (0, react.useRef)(null);
|
|
1422
1426
|
const popoverRef = (0, react.useRef)(null);
|
|
1423
1427
|
const inputRef = (0, react.useRef)(null);
|
|
@@ -1455,9 +1459,8 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1455
1459
|
if (!wrapperRef.current) return;
|
|
1456
1460
|
requestAnimationFrame(() => {
|
|
1457
1461
|
if (!wrapperRef.current) return;
|
|
1458
|
-
const
|
|
1459
|
-
|
|
1460
|
-
setPositioned(false);
|
|
1462
|
+
const result = computePopupStyle(wrapperRef.current.getBoundingClientRect(), placement);
|
|
1463
|
+
placedAbove.current = result.placedAbove;
|
|
1461
1464
|
setIsOpen(true);
|
|
1462
1465
|
});
|
|
1463
1466
|
}, 50);
|
|
@@ -1467,52 +1470,71 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1467
1470
|
placement,
|
|
1468
1471
|
setIsOpen
|
|
1469
1472
|
]);
|
|
1470
|
-
(0, react.
|
|
1473
|
+
const [popoverReady, setPopoverReady] = (0, react.useState)(false);
|
|
1474
|
+
(0, react.useEffect)(() => {
|
|
1471
1475
|
if (!isOpen) {
|
|
1472
|
-
|
|
1476
|
+
setPopoverReady(false);
|
|
1477
|
+
setPopupStyle({});
|
|
1473
1478
|
return;
|
|
1474
1479
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1480
|
+
const frameId = requestAnimationFrame(() => {
|
|
1481
|
+
if (!popoverRef.current || !wrapperRef.current) return;
|
|
1482
|
+
const measuredHeight = popoverRef.current.offsetHeight;
|
|
1483
|
+
const result = computePopupStyle(wrapperRef.current.getBoundingClientRect(), placedAbove.current ? "above" : "below", measuredHeight);
|
|
1484
|
+
setPopupStyle(result.style);
|
|
1485
|
+
setPopoverReady(true);
|
|
1486
|
+
});
|
|
1487
|
+
return () => cancelAnimationFrame(frameId);
|
|
1488
|
+
}, [isOpen]);
|
|
1481
1489
|
(0, react.useEffect)(() => {
|
|
1490
|
+
if (!isOpen) return;
|
|
1482
1491
|
function handleClickOutside(e) {
|
|
1483
1492
|
const target = e.target;
|
|
1484
|
-
if (
|
|
1493
|
+
if (!popoverRef.current) return;
|
|
1494
|
+
const inWrapper = wrapperRef.current?.contains(target);
|
|
1495
|
+
const inPopover = popoverRef.current.contains(target);
|
|
1496
|
+
if (!inWrapper && !inPopover) setIsOpen(false);
|
|
1485
1497
|
}
|
|
1486
1498
|
document.addEventListener("mousedown", handleClickOutside);
|
|
1487
1499
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1488
|
-
}, []);
|
|
1500
|
+
}, [isOpen, setIsOpen]);
|
|
1489
1501
|
(0, react.useEffect)(() => {
|
|
1490
1502
|
if (!isOpen) return;
|
|
1503
|
+
let armed = false;
|
|
1504
|
+
const armTimer = window.setTimeout(() => {
|
|
1505
|
+
armed = true;
|
|
1506
|
+
}, 100);
|
|
1491
1507
|
const close = () => setIsOpen(false);
|
|
1508
|
+
const onScroll = () => {
|
|
1509
|
+
if (armed) close();
|
|
1510
|
+
};
|
|
1492
1511
|
const scrollParent = getScrollParent(wrapperRef.current?.parentElement ?? null);
|
|
1493
|
-
if (scrollParent) scrollParent.addEventListener("scroll",
|
|
1494
|
-
window.addEventListener("scroll",
|
|
1512
|
+
if (scrollParent) scrollParent.addEventListener("scroll", onScroll, { passive: true });
|
|
1513
|
+
window.addEventListener("scroll", onScroll, {
|
|
1495
1514
|
capture: true,
|
|
1496
1515
|
passive: true
|
|
1497
1516
|
});
|
|
1498
1517
|
window.addEventListener("resize", close);
|
|
1499
1518
|
return () => {
|
|
1500
|
-
|
|
1501
|
-
|
|
1519
|
+
window.clearTimeout(armTimer);
|
|
1520
|
+
if (scrollParent) scrollParent.removeEventListener("scroll", onScroll);
|
|
1521
|
+
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
1502
1522
|
window.removeEventListener("resize", close);
|
|
1503
1523
|
};
|
|
1504
|
-
}, [isOpen]);
|
|
1524
|
+
}, [isOpen, setIsOpen]);
|
|
1505
1525
|
(0, react.useEffect)(() => {
|
|
1506
1526
|
if (!isOpen) return;
|
|
1507
1527
|
function handleFocusOut(e) {
|
|
1508
1528
|
if (!e.relatedTarget) return;
|
|
1509
1529
|
const target = e.relatedTarget;
|
|
1510
|
-
|
|
1530
|
+
const inWrapper = wrapperRef.current?.contains(target);
|
|
1531
|
+
const inPopover = popoverRef.current?.contains(target);
|
|
1532
|
+
if (!inWrapper && !inPopover) setIsOpen(false);
|
|
1511
1533
|
}
|
|
1512
1534
|
const wrapper = wrapperRef.current;
|
|
1513
1535
|
wrapper?.addEventListener("focusout", handleFocusOut);
|
|
1514
1536
|
return () => wrapper?.removeEventListener("focusout", handleFocusOut);
|
|
1515
|
-
}, [isOpen]);
|
|
1537
|
+
}, [isOpen, setIsOpen]);
|
|
1516
1538
|
function handleKeyDown(e) {
|
|
1517
1539
|
if (e.key === "Escape") {
|
|
1518
1540
|
e.preventDefault();
|
|
@@ -1578,7 +1600,7 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1578
1600
|
className: "pis-datepicker-popover",
|
|
1579
1601
|
style: {
|
|
1580
1602
|
...popupStyle,
|
|
1581
|
-
visibility:
|
|
1603
|
+
visibility: popoverReady ? "visible" : "hidden"
|
|
1582
1604
|
},
|
|
1583
1605
|
role: "dialog",
|
|
1584
1606
|
"aria-label": ariaLabel ? `${ariaLabel} calendar` : "Date picker",
|
package/lib/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clsx } from "clsx";
|
|
2
2
|
import { twMerge } from "tailwind-merge";
|
|
3
3
|
import * as React$1 from "react";
|
|
4
|
-
import React, { cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId,
|
|
4
|
+
import React, { cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { createPortal } from "react-dom";
|
|
7
7
|
import { AlertCircle, AlertTriangle, Archive, ArchiveRestore, ArrowDown, Ban, CalendarDays, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Clock, Command, File, Home, Info, Minus, RotateCcw, Search as Search$1, ShieldCheck, TrendingDown, TrendingUp, UploadCloud, X, ZoomIn, ZoomOut } from "lucide-react";
|
|
@@ -1384,16 +1384,20 @@ function computePopupStyle(rect, placement = "auto", measuredHeight) {
|
|
|
1384
1384
|
left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
|
|
1385
1385
|
width: isNarrow ? `calc(100vw - 16px)` : void 0
|
|
1386
1386
|
};
|
|
1387
|
-
|
|
1387
|
+
const placeBelow = placement === "below" ? true : placement === "above" ? false : spaceBelow >= height || spaceBelow >= spaceAbove;
|
|
1388
|
+
if (placeBelow) style.top = Math.min(rect.bottom + 6, window.innerHeight - height - 8);
|
|
1388
1389
|
else style.top = Math.max(rect.top - height - 6, 8);
|
|
1389
|
-
return
|
|
1390
|
+
return {
|
|
1391
|
+
style,
|
|
1392
|
+
placedAbove: !placeBelow
|
|
1393
|
+
};
|
|
1390
1394
|
}
|
|
1391
1395
|
function DatePicker({ value, onChange, placeholder, className, disabled, error, minDate, maxDate, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, required, dateFormat = "MMM d, yyyy", clearable = false, onOpenChange, placement = "auto", locale, name, isDateDisabled, readOnly = false, open, defaultOpen = false }) {
|
|
1392
1396
|
const isControlled = open !== void 0;
|
|
1393
1397
|
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
1394
1398
|
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
1395
1399
|
const [popupStyle, setPopupStyle] = useState({});
|
|
1396
|
-
const
|
|
1400
|
+
const placedAbove = useRef(false);
|
|
1397
1401
|
const wrapperRef = useRef(null);
|
|
1398
1402
|
const popoverRef = useRef(null);
|
|
1399
1403
|
const inputRef = useRef(null);
|
|
@@ -1431,9 +1435,8 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1431
1435
|
if (!wrapperRef.current) return;
|
|
1432
1436
|
requestAnimationFrame(() => {
|
|
1433
1437
|
if (!wrapperRef.current) return;
|
|
1434
|
-
const
|
|
1435
|
-
|
|
1436
|
-
setPositioned(false);
|
|
1438
|
+
const result = computePopupStyle(wrapperRef.current.getBoundingClientRect(), placement);
|
|
1439
|
+
placedAbove.current = result.placedAbove;
|
|
1437
1440
|
setIsOpen(true);
|
|
1438
1441
|
});
|
|
1439
1442
|
}, 50);
|
|
@@ -1443,52 +1446,71 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1443
1446
|
placement,
|
|
1444
1447
|
setIsOpen
|
|
1445
1448
|
]);
|
|
1446
|
-
|
|
1449
|
+
const [popoverReady, setPopoverReady] = useState(false);
|
|
1450
|
+
useEffect(() => {
|
|
1447
1451
|
if (!isOpen) {
|
|
1448
|
-
|
|
1452
|
+
setPopoverReady(false);
|
|
1453
|
+
setPopupStyle({});
|
|
1449
1454
|
return;
|
|
1450
1455
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1456
|
+
const frameId = requestAnimationFrame(() => {
|
|
1457
|
+
if (!popoverRef.current || !wrapperRef.current) return;
|
|
1458
|
+
const measuredHeight = popoverRef.current.offsetHeight;
|
|
1459
|
+
const result = computePopupStyle(wrapperRef.current.getBoundingClientRect(), placedAbove.current ? "above" : "below", measuredHeight);
|
|
1460
|
+
setPopupStyle(result.style);
|
|
1461
|
+
setPopoverReady(true);
|
|
1462
|
+
});
|
|
1463
|
+
return () => cancelAnimationFrame(frameId);
|
|
1464
|
+
}, [isOpen]);
|
|
1457
1465
|
useEffect(() => {
|
|
1466
|
+
if (!isOpen) return;
|
|
1458
1467
|
function handleClickOutside(e) {
|
|
1459
1468
|
const target = e.target;
|
|
1460
|
-
if (
|
|
1469
|
+
if (!popoverRef.current) return;
|
|
1470
|
+
const inWrapper = wrapperRef.current?.contains(target);
|
|
1471
|
+
const inPopover = popoverRef.current.contains(target);
|
|
1472
|
+
if (!inWrapper && !inPopover) setIsOpen(false);
|
|
1461
1473
|
}
|
|
1462
1474
|
document.addEventListener("mousedown", handleClickOutside);
|
|
1463
1475
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1464
|
-
}, []);
|
|
1476
|
+
}, [isOpen, setIsOpen]);
|
|
1465
1477
|
useEffect(() => {
|
|
1466
1478
|
if (!isOpen) return;
|
|
1479
|
+
let armed = false;
|
|
1480
|
+
const armTimer = window.setTimeout(() => {
|
|
1481
|
+
armed = true;
|
|
1482
|
+
}, 100);
|
|
1467
1483
|
const close = () => setIsOpen(false);
|
|
1484
|
+
const onScroll = () => {
|
|
1485
|
+
if (armed) close();
|
|
1486
|
+
};
|
|
1468
1487
|
const scrollParent = getScrollParent(wrapperRef.current?.parentElement ?? null);
|
|
1469
|
-
if (scrollParent) scrollParent.addEventListener("scroll",
|
|
1470
|
-
window.addEventListener("scroll",
|
|
1488
|
+
if (scrollParent) scrollParent.addEventListener("scroll", onScroll, { passive: true });
|
|
1489
|
+
window.addEventListener("scroll", onScroll, {
|
|
1471
1490
|
capture: true,
|
|
1472
1491
|
passive: true
|
|
1473
1492
|
});
|
|
1474
1493
|
window.addEventListener("resize", close);
|
|
1475
1494
|
return () => {
|
|
1476
|
-
|
|
1477
|
-
|
|
1495
|
+
window.clearTimeout(armTimer);
|
|
1496
|
+
if (scrollParent) scrollParent.removeEventListener("scroll", onScroll);
|
|
1497
|
+
window.removeEventListener("scroll", onScroll, { capture: true });
|
|
1478
1498
|
window.removeEventListener("resize", close);
|
|
1479
1499
|
};
|
|
1480
|
-
}, [isOpen]);
|
|
1500
|
+
}, [isOpen, setIsOpen]);
|
|
1481
1501
|
useEffect(() => {
|
|
1482
1502
|
if (!isOpen) return;
|
|
1483
1503
|
function handleFocusOut(e) {
|
|
1484
1504
|
if (!e.relatedTarget) return;
|
|
1485
1505
|
const target = e.relatedTarget;
|
|
1486
|
-
|
|
1506
|
+
const inWrapper = wrapperRef.current?.contains(target);
|
|
1507
|
+
const inPopover = popoverRef.current?.contains(target);
|
|
1508
|
+
if (!inWrapper && !inPopover) setIsOpen(false);
|
|
1487
1509
|
}
|
|
1488
1510
|
const wrapper = wrapperRef.current;
|
|
1489
1511
|
wrapper?.addEventListener("focusout", handleFocusOut);
|
|
1490
1512
|
return () => wrapper?.removeEventListener("focusout", handleFocusOut);
|
|
1491
|
-
}, [isOpen]);
|
|
1513
|
+
}, [isOpen, setIsOpen]);
|
|
1492
1514
|
function handleKeyDown(e) {
|
|
1493
1515
|
if (e.key === "Escape") {
|
|
1494
1516
|
e.preventDefault();
|
|
@@ -1554,7 +1576,7 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
|
|
|
1554
1576
|
className: "pis-datepicker-popover",
|
|
1555
1577
|
style: {
|
|
1556
1578
|
...popupStyle,
|
|
1557
|
-
visibility:
|
|
1579
|
+
visibility: popoverReady ? "visible" : "hidden"
|
|
1558
1580
|
},
|
|
1559
1581
|
role: "dialog",
|
|
1560
1582
|
"aria-label": ariaLabel ? `${ariaLabel} calendar` : "Date picker",
|
|
@@ -53,6 +53,9 @@ interface DatePickerProps {
|
|
|
53
53
|
/** Initial open state when uncontrolled. Ignored when `open` is provided. */
|
|
54
54
|
defaultOpen?: boolean;
|
|
55
55
|
}
|
|
56
|
-
export declare function computePopupStyle(rect: DOMRect, placement?: 'auto' | 'below' | 'above', measuredHeight?: number):
|
|
56
|
+
export declare function computePopupStyle(rect: DOMRect, placement?: 'auto' | 'below' | 'above', measuredHeight?: number): {
|
|
57
|
+
style: React.CSSProperties;
|
|
58
|
+
placedAbove: boolean;
|
|
59
|
+
};
|
|
57
60
|
export declare function DatePicker({ value, onChange, placeholder, className, disabled, error, minDate, maxDate, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, required, dateFormat, clearable, onOpenChange, placement, locale, name, isDateDisabled, readOnly, open, defaultOpen, }: DatePickerProps): import("react").JSX.Element;
|
|
58
61
|
export {};
|