@diwauhris/ui 1.7.16 → 1.7.18

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 CHANGED
@@ -4410,8 +4410,8 @@ body {
4410
4410
 
4411
4411
  /* ── Date Picker (react-calendar DIWA theme) ─────────────────────────────── */
4412
4412
  .pis-datepicker-popover {
4413
- position: absolute;
4414
4413
  z-index: 1050;
4414
+ pointer-events: auto;
4415
4415
  margin-top: 6px;
4416
4416
  background: #fff;
4417
4417
  border: 1px solid #dde3ec;
package/lib/index.cjs CHANGED
@@ -1237,7 +1237,9 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1237
1237
  top: rect.bottom + 4,
1238
1238
  left: rect.left,
1239
1239
  zIndex: 9999,
1240
- width: rect.width
1240
+ width: rect.width,
1241
+ pointerEvents: "auto",
1242
+ overscrollBehavior: "contain"
1241
1243
  });
1242
1244
  }, [isOpen]);
1243
1245
  (0, react.useEffect)(() => {
@@ -1338,6 +1340,12 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1338
1340
  role: "listbox",
1339
1341
  style: panelStyle,
1340
1342
  className: "bg-white border border-slate-200 rounded-xl shadow-lg max-h-60 overflow-y-auto",
1343
+ onWheel: (e) => {
1344
+ if (listRef.current) {
1345
+ listRef.current.scrollTop += e.deltaY;
1346
+ e.stopPropagation();
1347
+ }
1348
+ },
1341
1349
  children: error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1342
1350
  className: "px-3 py-2 text-sm text-rose-500 font-semibold",
1343
1351
  children: error
@@ -1384,6 +1392,25 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1384
1392
  */
1385
1393
  var POPOVER_WIDTH = 352;
1386
1394
  var CALENDAR_HEIGHT = 360;
1395
+ function getScrollParent(el) {
1396
+ if (!el || el === document.body) return null;
1397
+ const { overflowY, overflow } = getComputedStyle(el);
1398
+ if (["auto", "scroll"].includes(overflowY) || ["auto", "scroll"].includes(overflow)) return el;
1399
+ return getScrollParent(el.parentElement);
1400
+ }
1401
+ function computePopupStyle(rect) {
1402
+ const spaceBelow = window.innerHeight - rect.bottom;
1403
+ const spaceAbove = rect.top;
1404
+ const isNarrow = window.innerWidth < 368;
1405
+ const style = {
1406
+ position: "fixed",
1407
+ left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
1408
+ width: isNarrow ? `calc(100vw - 16px)` : void 0
1409
+ };
1410
+ if (spaceAbove > spaceBelow && spaceBelow < CALENDAR_HEIGHT / 3) style.top = Math.max(8, rect.top - CALENDAR_HEIGHT - 6);
1411
+ else style.top = rect.bottom + 6;
1412
+ return style;
1413
+ }
1387
1414
  function DatePicker({ value, onChange, placeholder, className, disabled, error, minDate, maxDate, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, required }) {
1388
1415
  const [isOpen, setIsOpen] = (0, react.useState)(false);
1389
1416
  const [popupStyle, setPopupStyle] = (0, react.useState)({});
@@ -1405,46 +1432,21 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
1405
1432
  const displayValue = selectedDate ? (0, date_fns.format)(selectedDate, "MMM d, yyyy") : "";
1406
1433
  const skipNextOpen = (0, react.useRef)(false);
1407
1434
  const openPopup = (0, react.useCallback)(() => {
1408
- if (disabled || !wrapperRef.current) return;
1435
+ if (disabled) return;
1409
1436
  if (skipNextOpen.current) {
1410
1437
  skipNextOpen.current = false;
1411
1438
  return;
1412
1439
  }
1413
- setPopupStyle({
1414
- position: "fixed",
1415
- top: -9999,
1416
- left: -9999,
1417
- visibility: "hidden"
1418
- });
1419
- setIsOpen(true);
1420
- }, [disabled]);
1421
- (0, react.useEffect)(() => {
1422
- if (!isOpen || !wrapperRef.current) return;
1423
- let frameId1;
1424
- let frameId2;
1425
- frameId1 = requestAnimationFrame(() => {
1426
- frameId2 = requestAnimationFrame(() => {
1440
+ setTimeout(() => {
1441
+ if (!wrapperRef.current) return;
1442
+ requestAnimationFrame(() => {
1427
1443
  if (!wrapperRef.current) return;
1428
- const rect = wrapperRef.current.getBoundingClientRect();
1429
- const spaceBelow = window.innerHeight - rect.bottom;
1430
- const spaceAbove = rect.top;
1431
- const isNarrow = window.innerWidth < 368;
1432
- const style = {
1433
- position: "fixed",
1434
- visibility: "visible",
1435
- left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
1436
- width: isNarrow ? `calc(100vw - 16px)` : void 0
1437
- };
1438
- if (spaceBelow >= CALENDAR_HEIGHT || spaceBelow >= spaceAbove) style.top = rect.bottom + 6;
1439
- else style.top = Math.max(8, rect.top - CALENDAR_HEIGHT - 6);
1444
+ const style = computePopupStyle(wrapperRef.current.getBoundingClientRect());
1440
1445
  setPopupStyle(style);
1446
+ setIsOpen(true);
1441
1447
  });
1442
- });
1443
- return () => {
1444
- cancelAnimationFrame(frameId1);
1445
- cancelAnimationFrame(frameId2);
1446
- };
1447
- }, [isOpen]);
1448
+ }, 50);
1449
+ }, [disabled]);
1448
1450
  (0, react.useEffect)(() => {
1449
1451
  function handleClickOutside(e) {
1450
1452
  const target = e.target;
@@ -1455,32 +1457,18 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
1455
1457
  }, []);
1456
1458
  (0, react.useEffect)(() => {
1457
1459
  if (!isOpen) return;
1458
- function getScrollParent(el) {
1459
- if (!el || el === document.body) return null;
1460
- const style = getComputedStyle(el);
1461
- if (["auto", "scroll"].includes(style.overflowY) || ["auto", "scroll"].includes(style.overflow)) return el;
1462
- return getScrollParent(el.parentElement);
1463
- }
1460
+ const close = () => setIsOpen(false);
1464
1461
  const scrollParent = getScrollParent(wrapperRef.current?.parentElement ?? null);
1465
- let scrollHandler = null;
1466
- let resizeHandler = null;
1467
- const frameId = requestAnimationFrame(() => {
1468
- scrollHandler = () => setIsOpen(false);
1469
- resizeHandler = () => setIsOpen(false);
1470
- if (scrollParent) scrollParent.addEventListener("scroll", scrollHandler, { passive: true });
1471
- window.addEventListener("scroll", scrollHandler, {
1472
- capture: true,
1473
- passive: true
1474
- });
1475
- window.addEventListener("resize", resizeHandler);
1462
+ if (scrollParent) scrollParent.addEventListener("scroll", close, { passive: true });
1463
+ window.addEventListener("scroll", close, {
1464
+ capture: true,
1465
+ passive: true
1476
1466
  });
1467
+ window.addEventListener("resize", close);
1477
1468
  return () => {
1478
- cancelAnimationFrame(frameId);
1479
- if (scrollHandler) {
1480
- if (scrollParent) scrollParent.removeEventListener("scroll", scrollHandler);
1481
- window.removeEventListener("scroll", scrollHandler, { capture: true });
1482
- }
1483
- if (resizeHandler) window.removeEventListener("resize", resizeHandler);
1469
+ if (scrollParent) scrollParent.removeEventListener("scroll", close);
1470
+ window.removeEventListener("scroll", close, { capture: true });
1471
+ window.removeEventListener("resize", close);
1484
1472
  };
1485
1473
  }, [isOpen]);
1486
1474
  (0, react.useEffect)(() => {
@@ -2351,7 +2339,17 @@ function Modal({ isOpen, onClose, title, children, icon, subtitle, headerMeta, f
2351
2339
  onOpenAutoFocus,
2352
2340
  onCloseAutoFocus,
2353
2341
  onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
2354
- onInteractOutside: preventClose ? (e) => e.preventDefault() : onInteractOutside,
2342
+ onInteractOutside: (e) => {
2343
+ if (e.target?.closest(".pis-datepicker-popover")) {
2344
+ e.preventDefault();
2345
+ return;
2346
+ }
2347
+ if (preventClose) {
2348
+ e.preventDefault();
2349
+ return;
2350
+ }
2351
+ onInteractOutside?.(e);
2352
+ },
2355
2353
  children: [
2356
2354
  !preventClose && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Close, {
2357
2355
  asChild: true,
@@ -2465,7 +2463,17 @@ function Dialog({ open, onClose, title, description, preventClose = false, size
2465
2463
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dialog.Portal, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dialog.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 duration-200" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dialog.Content, {
2466
2464
  className: cn("fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2", "flex w-full flex-col overflow-hidden", "rounded-lg bg-white shadow-xl", "max-h-[90vh] outline-none", SIZE_CLASS[size], "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", "duration-200"),
2467
2465
  onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
2468
- onInteractOutside: preventClose ? (e) => e.preventDefault() : onInteractOutside,
2466
+ onInteractOutside: (e) => {
2467
+ if (e.target?.closest(".pis-datepicker-popover")) {
2468
+ e.preventDefault();
2469
+ return;
2470
+ }
2471
+ if (preventClose) {
2472
+ e.preventDefault();
2473
+ return;
2474
+ }
2475
+ onInteractOutside?.(e);
2476
+ },
2469
2477
  onOpenAutoFocus,
2470
2478
  onCloseAutoFocus,
2471
2479
  style: { padding: 0 },
package/lib/index.mjs CHANGED
@@ -1213,7 +1213,9 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1213
1213
  top: rect.bottom + 4,
1214
1214
  left: rect.left,
1215
1215
  zIndex: 9999,
1216
- width: rect.width
1216
+ width: rect.width,
1217
+ pointerEvents: "auto",
1218
+ overscrollBehavior: "contain"
1217
1219
  });
1218
1220
  }, [isOpen]);
1219
1221
  useEffect(() => {
@@ -1314,6 +1316,12 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1314
1316
  role: "listbox",
1315
1317
  style: panelStyle,
1316
1318
  className: "bg-white border border-slate-200 rounded-xl shadow-lg max-h-60 overflow-y-auto",
1319
+ onWheel: (e) => {
1320
+ if (listRef.current) {
1321
+ listRef.current.scrollTop += e.deltaY;
1322
+ e.stopPropagation();
1323
+ }
1324
+ },
1317
1325
  children: error ? /* @__PURE__ */ jsx("div", {
1318
1326
  className: "px-3 py-2 text-sm text-rose-500 font-semibold",
1319
1327
  children: error
@@ -1360,6 +1368,25 @@ function Combobox({ value: controlledValue, defaultValue = "", onChange, options
1360
1368
  */
1361
1369
  var POPOVER_WIDTH = 352;
1362
1370
  var CALENDAR_HEIGHT = 360;
1371
+ function getScrollParent(el) {
1372
+ if (!el || el === document.body) return null;
1373
+ const { overflowY, overflow } = getComputedStyle(el);
1374
+ if (["auto", "scroll"].includes(overflowY) || ["auto", "scroll"].includes(overflow)) return el;
1375
+ return getScrollParent(el.parentElement);
1376
+ }
1377
+ function computePopupStyle(rect) {
1378
+ const spaceBelow = window.innerHeight - rect.bottom;
1379
+ const spaceAbove = rect.top;
1380
+ const isNarrow = window.innerWidth < 368;
1381
+ const style = {
1382
+ position: "fixed",
1383
+ left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
1384
+ width: isNarrow ? `calc(100vw - 16px)` : void 0
1385
+ };
1386
+ if (spaceAbove > spaceBelow && spaceBelow < CALENDAR_HEIGHT / 3) style.top = Math.max(8, rect.top - CALENDAR_HEIGHT - 6);
1387
+ else style.top = rect.bottom + 6;
1388
+ return style;
1389
+ }
1363
1390
  function DatePicker({ value, onChange, placeholder, className, disabled, error, minDate, maxDate, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, required }) {
1364
1391
  const [isOpen, setIsOpen] = useState(false);
1365
1392
  const [popupStyle, setPopupStyle] = useState({});
@@ -1381,46 +1408,21 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
1381
1408
  const displayValue = selectedDate ? format(selectedDate, "MMM d, yyyy") : "";
1382
1409
  const skipNextOpen = useRef(false);
1383
1410
  const openPopup = useCallback(() => {
1384
- if (disabled || !wrapperRef.current) return;
1411
+ if (disabled) return;
1385
1412
  if (skipNextOpen.current) {
1386
1413
  skipNextOpen.current = false;
1387
1414
  return;
1388
1415
  }
1389
- setPopupStyle({
1390
- position: "fixed",
1391
- top: -9999,
1392
- left: -9999,
1393
- visibility: "hidden"
1394
- });
1395
- setIsOpen(true);
1396
- }, [disabled]);
1397
- useEffect(() => {
1398
- if (!isOpen || !wrapperRef.current) return;
1399
- let frameId1;
1400
- let frameId2;
1401
- frameId1 = requestAnimationFrame(() => {
1402
- frameId2 = requestAnimationFrame(() => {
1416
+ setTimeout(() => {
1417
+ if (!wrapperRef.current) return;
1418
+ requestAnimationFrame(() => {
1403
1419
  if (!wrapperRef.current) return;
1404
- const rect = wrapperRef.current.getBoundingClientRect();
1405
- const spaceBelow = window.innerHeight - rect.bottom;
1406
- const spaceAbove = rect.top;
1407
- const isNarrow = window.innerWidth < 368;
1408
- const style = {
1409
- position: "fixed",
1410
- visibility: "visible",
1411
- left: isNarrow ? 8 : Math.max(8, Math.min(rect.left, window.innerWidth - POPOVER_WIDTH - 8)),
1412
- width: isNarrow ? `calc(100vw - 16px)` : void 0
1413
- };
1414
- if (spaceBelow >= CALENDAR_HEIGHT || spaceBelow >= spaceAbove) style.top = rect.bottom + 6;
1415
- else style.top = Math.max(8, rect.top - CALENDAR_HEIGHT - 6);
1420
+ const style = computePopupStyle(wrapperRef.current.getBoundingClientRect());
1416
1421
  setPopupStyle(style);
1422
+ setIsOpen(true);
1417
1423
  });
1418
- });
1419
- return () => {
1420
- cancelAnimationFrame(frameId1);
1421
- cancelAnimationFrame(frameId2);
1422
- };
1423
- }, [isOpen]);
1424
+ }, 50);
1425
+ }, [disabled]);
1424
1426
  useEffect(() => {
1425
1427
  function handleClickOutside(e) {
1426
1428
  const target = e.target;
@@ -1431,32 +1433,18 @@ function DatePicker({ value, onChange, placeholder, className, disabled, error,
1431
1433
  }, []);
1432
1434
  useEffect(() => {
1433
1435
  if (!isOpen) return;
1434
- function getScrollParent(el) {
1435
- if (!el || el === document.body) return null;
1436
- const style = getComputedStyle(el);
1437
- if (["auto", "scroll"].includes(style.overflowY) || ["auto", "scroll"].includes(style.overflow)) return el;
1438
- return getScrollParent(el.parentElement);
1439
- }
1436
+ const close = () => setIsOpen(false);
1440
1437
  const scrollParent = getScrollParent(wrapperRef.current?.parentElement ?? null);
1441
- let scrollHandler = null;
1442
- let resizeHandler = null;
1443
- const frameId = requestAnimationFrame(() => {
1444
- scrollHandler = () => setIsOpen(false);
1445
- resizeHandler = () => setIsOpen(false);
1446
- if (scrollParent) scrollParent.addEventListener("scroll", scrollHandler, { passive: true });
1447
- window.addEventListener("scroll", scrollHandler, {
1448
- capture: true,
1449
- passive: true
1450
- });
1451
- window.addEventListener("resize", resizeHandler);
1438
+ if (scrollParent) scrollParent.addEventListener("scroll", close, { passive: true });
1439
+ window.addEventListener("scroll", close, {
1440
+ capture: true,
1441
+ passive: true
1452
1442
  });
1443
+ window.addEventListener("resize", close);
1453
1444
  return () => {
1454
- cancelAnimationFrame(frameId);
1455
- if (scrollHandler) {
1456
- if (scrollParent) scrollParent.removeEventListener("scroll", scrollHandler);
1457
- window.removeEventListener("scroll", scrollHandler, { capture: true });
1458
- }
1459
- if (resizeHandler) window.removeEventListener("resize", resizeHandler);
1445
+ if (scrollParent) scrollParent.removeEventListener("scroll", close);
1446
+ window.removeEventListener("scroll", close, { capture: true });
1447
+ window.removeEventListener("resize", close);
1460
1448
  };
1461
1449
  }, [isOpen]);
1462
1450
  useEffect(() => {
@@ -2327,7 +2315,17 @@ function Modal({ isOpen, onClose, title, children, icon, subtitle, headerMeta, f
2327
2315
  onOpenAutoFocus,
2328
2316
  onCloseAutoFocus,
2329
2317
  onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
2330
- onInteractOutside: preventClose ? (e) => e.preventDefault() : onInteractOutside,
2318
+ onInteractOutside: (e) => {
2319
+ if (e.target?.closest(".pis-datepicker-popover")) {
2320
+ e.preventDefault();
2321
+ return;
2322
+ }
2323
+ if (preventClose) {
2324
+ e.preventDefault();
2325
+ return;
2326
+ }
2327
+ onInteractOutside?.(e);
2328
+ },
2331
2329
  children: [
2332
2330
  !preventClose && /* @__PURE__ */ jsx(DialogPrimitive.Close, {
2333
2331
  asChild: true,
@@ -2441,7 +2439,17 @@ function Dialog({ open, onClose, title, description, preventClose = false, size
2441
2439
  children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-brand-navy/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 duration-200" }), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
2442
2440
  className: cn("fixed left-1/2 top-1/2 z-50 -translate-x-1/2 -translate-y-1/2", "flex w-full flex-col overflow-hidden", "rounded-lg bg-white shadow-xl", "max-h-[90vh] outline-none", SIZE_CLASS[size], "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0", "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95", "duration-200"),
2443
2441
  onEscapeKeyDown: preventClose ? (e) => e.preventDefault() : onEscapeKeyDown,
2444
- onInteractOutside: preventClose ? (e) => e.preventDefault() : onInteractOutside,
2442
+ onInteractOutside: (e) => {
2443
+ if (e.target?.closest(".pis-datepicker-popover")) {
2444
+ e.preventDefault();
2445
+ return;
2446
+ }
2447
+ if (preventClose) {
2448
+ e.preventDefault();
2449
+ return;
2450
+ }
2451
+ onInteractOutside?.(e);
2452
+ },
2445
2453
  onOpenAutoFocus,
2446
2454
  onCloseAutoFocus,
2447
2455
  style: { padding: 0 },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@diwauhris/ui",
3
3
  "private": false,
4
- "version": "1.7.16",
4
+ "version": "1.7.18",
5
5
  "type": "module",
6
6
  "description": "DIWA UHRIS UI component library — React + Tailwind CSS",
7
7
  "keywords": [