@optifye/dashboard-core 6.11.30 → 6.11.32

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/index.css CHANGED
@@ -447,10 +447,6 @@ body {
447
447
  left: -0.125rem;
448
448
  right: -0.125rem;
449
449
  }
450
- .inset-x-0 {
451
- left: 0px;
452
- right: 0px;
453
- }
454
450
  .inset-y-0 {
455
451
  top: 0px;
456
452
  bottom: 0px;
@@ -665,9 +661,6 @@ body {
665
661
  .z-\[100\] {
666
662
  z-index: 100;
667
663
  }
668
- .z-\[1\] {
669
- z-index: 1;
670
- }
671
664
  .z-\[60\] {
672
665
  z-index: 60;
673
666
  }
@@ -1148,6 +1141,9 @@ body {
1148
1141
  .max-h-48 {
1149
1142
  max-height: 12rem;
1150
1143
  }
1144
+ .max-h-52 {
1145
+ max-height: 13rem;
1146
+ }
1151
1147
  .max-h-56 {
1152
1148
  max-height: 14rem;
1153
1149
  }
@@ -1157,6 +1153,9 @@ body {
1157
1153
  .max-h-64 {
1158
1154
  max-height: 16rem;
1159
1155
  }
1156
+ .max-h-72 {
1157
+ max-height: 18rem;
1158
+ }
1160
1159
  .max-h-\[--radix-select-content-available-height\] {
1161
1160
  max-height: var(--radix-select-content-available-height);
1162
1161
  }
@@ -1813,9 +1812,6 @@ body {
1813
1812
  .cursor-default {
1814
1813
  cursor: default;
1815
1814
  }
1816
- .cursor-grab {
1817
- cursor: grab;
1818
- }
1819
1815
  .cursor-help {
1820
1816
  cursor: help;
1821
1817
  }
@@ -4273,9 +4269,6 @@ body {
4273
4269
  .font-extrabold {
4274
4270
  font-weight: 800;
4275
4271
  }
4276
- .font-light {
4277
- font-weight: 300;
4278
- }
4279
4272
  .font-medium {
4280
4273
  font-weight: 500;
4281
4274
  }
@@ -4871,14 +4864,6 @@ body {
4871
4864
  var(--tw-ring-shadow, 0 0 #0000),
4872
4865
  var(--tw-shadow);
4873
4866
  }
4874
- .shadow-\[0_8px_30px_rgba\(0\,0\,0\,0\.08\)\,0_2px_8px_rgba\(0\,0\,0\,0\.04\)\] {
4875
- --tw-shadow: 0 8px 30px rgba(0,0,0,0.08),0 2px 8px rgba(0,0,0,0.04);
4876
- --tw-shadow-colored: 0 8px 30px var(--tw-shadow-color), 0 2px 8px var(--tw-shadow-color);
4877
- box-shadow:
4878
- var(--tw-ring-offset-shadow, 0 0 #0000),
4879
- var(--tw-ring-shadow, 0 0 #0000),
4880
- var(--tw-shadow);
4881
- }
4882
4867
  .shadow-inner {
4883
4868
  --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
4884
4869
  --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);
@@ -6101,9 +6086,6 @@ input[type=range]:active::-moz-range-thumb {
6101
6086
  --tw-scale-y: 0.99;
6102
6087
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
6103
6088
  }
6104
- .active\:cursor-grabbing:active {
6105
- cursor: grabbing;
6106
- }
6107
6089
  .active\:bg-blue-800:active {
6108
6090
  --tw-bg-opacity: 1;
6109
6091
  background-color: rgb(30 64 175 / var(--tw-bg-opacity, 1));
@@ -6311,9 +6293,6 @@ input[type=range]:active::-moz-range-thumb {
6311
6293
  .sm\:right-4 {
6312
6294
  right: 1rem;
6313
6295
  }
6314
- .sm\:right-auto {
6315
- right: auto;
6316
- }
6317
6296
  .sm\:top-0 {
6318
6297
  top: 0px;
6319
6298
  }
@@ -6507,9 +6486,6 @@ input[type=range]:active::-moz-range-thumb {
6507
6486
  .sm\:w-\[180px\] {
6508
6487
  width: 180px;
6509
6488
  }
6510
- .sm\:w-\[264px\] {
6511
- width: 264px;
6512
- }
6513
6489
  .sm\:w-\[320px\] {
6514
6490
  width: 320px;
6515
6491
  }
package/dist/index.js CHANGED
@@ -39432,240 +39432,99 @@ var SegmentedTimeInput = ({
39432
39432
  }
39433
39433
  );
39434
39434
  };
39435
- var SCROLLBAR_HIDE_ID = "tp-scrollbar-hide";
39436
- var injectScrollbarHideCSS = () => {
39437
- if (typeof document === "undefined") return;
39438
- if (document.getElementById(SCROLLBAR_HIDE_ID)) return;
39439
- const style = document.createElement("style");
39440
- style.id = SCROLLBAR_HIDE_ID;
39441
- style.textContent = ".tp-scroll-hide::-webkit-scrollbar{display:none}";
39442
- document.head.appendChild(style);
39443
- };
39444
- var ITEM_H = 40;
39445
- var VISIBLE = 5;
39446
- var WHEEL_H = ITEM_H * VISIBLE;
39447
- var PAD = Math.floor(VISIBLE / 2);
39448
- var ScrollColumn = ({ items, selected, onSelect, width = 56 }) => {
39449
- const elRef = React142.useRef(null);
39450
- const suppressRef = React142.useRef(false);
39451
- const snapTimerRef = React142.useRef(null);
39452
- const mountedRef = React142.useRef(false);
39453
- const dragging = React142.useRef(false);
39454
- const dragStartY = React142.useRef(0);
39455
- const dragStartScroll = React142.useRef(0);
39456
- React142.useEffect(() => {
39457
- injectScrollbarHideCSS();
39458
- }, []);
39459
- React142.useEffect(() => {
39460
- const idx = items.findIndex((i) => i.value === selected);
39461
- if (idx < 0 || !elRef.current || suppressRef.current) return;
39462
- const target = idx * ITEM_H;
39463
- if (!mountedRef.current) {
39464
- suppressRef.current = true;
39465
- elRef.current.scrollTop = target;
39466
- setTimeout(() => {
39467
- if (elRef.current) elRef.current.scrollTop = target;
39468
- setTimeout(() => {
39469
- suppressRef.current = false;
39470
- mountedRef.current = true;
39471
- }, 200);
39472
- }, 30);
39473
- } else {
39474
- elRef.current.scrollTo({ top: target, behavior: "smooth" });
39475
- }
39476
- }, [selected, items]);
39477
- const scheduleSnap = React142.useCallback(() => {
39478
- if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
39479
- snapTimerRef.current = setTimeout(() => {
39480
- if (!elRef.current || suppressRef.current) return;
39481
- const idx = Math.round(elRef.current.scrollTop / ITEM_H);
39482
- const clamped = Math.max(0, Math.min(items.length - 1, idx));
39483
- suppressRef.current = true;
39484
- elRef.current.scrollTo({ top: clamped * ITEM_H, behavior: "smooth" });
39485
- const item = items[clamped];
39486
- if (item && item.value !== selected) onSelect(item.value);
39487
- setTimeout(() => {
39488
- suppressRef.current = false;
39489
- }, 150);
39490
- }, 100);
39491
- }, [items, selected, onSelect]);
39492
- const onScroll = React142.useCallback(() => {
39493
- if (suppressRef.current) return;
39494
- scheduleSnap();
39495
- }, [scheduleSnap]);
39496
- const onMouseDown = React142.useCallback((e) => {
39497
- dragging.current = true;
39498
- dragStartY.current = e.clientY;
39499
- dragStartScroll.current = elRef.current?.scrollTop ?? 0;
39500
- e.preventDefault();
39501
- const onMove = (ev) => {
39502
- if (!dragging.current || !elRef.current) return;
39503
- const dy = dragStartY.current - ev.clientY;
39504
- elRef.current.scrollTop = dragStartScroll.current + dy;
39505
- };
39506
- const onUp = () => {
39507
- dragging.current = false;
39508
- scheduleSnap();
39509
- document.removeEventListener("mousemove", onMove);
39510
- document.removeEventListener("mouseup", onUp);
39511
- };
39512
- document.addEventListener("mousemove", onMove);
39513
- document.addEventListener("mouseup", onUp);
39514
- }, [scheduleSnap]);
39515
- const onTouchStart = React142.useCallback((e) => {
39516
- dragging.current = true;
39517
- dragStartY.current = e.touches[0].clientY;
39518
- dragStartScroll.current = elRef.current?.scrollTop ?? 0;
39519
- }, []);
39520
- const onTouchMove = React142.useCallback((e) => {
39521
- if (!dragging.current || !elRef.current) return;
39522
- const dy = dragStartY.current - e.touches[0].clientY;
39523
- elRef.current.scrollTop = dragStartScroll.current + dy;
39524
- e.preventDefault();
39525
- }, []);
39526
- const onTouchEnd = React142.useCallback(() => {
39527
- dragging.current = false;
39528
- scheduleSnap();
39529
- }, [scheduleSnap]);
39530
- const handleClick = React142.useCallback((value, idx) => {
39531
- onSelect(value);
39532
- if (elRef.current) {
39533
- suppressRef.current = true;
39534
- elRef.current.scrollTo({ top: idx * ITEM_H, behavior: "smooth" });
39535
- setTimeout(() => {
39536
- suppressRef.current = false;
39537
- }, 250);
39435
+ var generateTimeSlots = () => {
39436
+ const slots = [];
39437
+ for (let hour = 0; hour < 24; hour++) {
39438
+ for (let minute = 0; minute < 60; minute += 5) {
39439
+ const time24 = `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
39440
+ const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
39441
+ const ampm = hour < 12 ? "AM" : "PM";
39442
+ const time12 = `${hour12}:${minute.toString().padStart(2, "0")} ${ampm}`;
39443
+ slots.push({ value: time24, label: time12 });
39538
39444
  }
39539
- }, [onSelect]);
39540
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative select-none", style: { width, height: WHEEL_H }, children: [
39541
- /* @__PURE__ */ jsxRuntime.jsx(
39542
- "div",
39543
- {
39544
- className: "absolute left-1 right-1 rounded-lg bg-blue-50/80 border border-blue-200/60 pointer-events-none z-0",
39545
- style: { top: PAD * ITEM_H, height: ITEM_H }
39546
- }
39547
- ),
39548
- /* @__PURE__ */ jsxRuntime.jsx(
39549
- "div",
39550
- {
39551
- className: "absolute inset-x-0 top-0 pointer-events-none z-10",
39552
- style: { height: ITEM_H * 1.8, background: "linear-gradient(to bottom, white 0%, rgba(255,255,255,0.85) 50%, transparent 100%)" }
39553
- }
39554
- ),
39555
- /* @__PURE__ */ jsxRuntime.jsx(
39556
- "div",
39557
- {
39558
- className: "absolute inset-x-0 bottom-0 pointer-events-none z-10",
39559
- style: { height: ITEM_H * 1.8, background: "linear-gradient(to top, white 0%, rgba(255,255,255,0.85) 50%, transparent 100%)" }
39560
- }
39561
- ),
39562
- /* @__PURE__ */ jsxRuntime.jsxs(
39563
- "div",
39564
- {
39565
- ref: elRef,
39566
- onScroll,
39567
- onMouseDown,
39568
- onTouchStart,
39569
- onTouchMove,
39570
- onTouchEnd,
39571
- className: "h-full overflow-y-auto tp-scroll-hide relative z-[1] cursor-grab active:cursor-grabbing",
39572
- style: { scrollbarWidth: "none", msOverflowStyle: "none" },
39573
- role: "listbox",
39574
- children: [
39575
- Array.from({ length: PAD }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: ITEM_H }, "aria-hidden": true }, `pt-${i}`)),
39576
- items.map((item, idx) => {
39577
- const isSel = item.value === selected;
39578
- return /* @__PURE__ */ jsxRuntime.jsx(
39579
- "div",
39580
- {
39581
- onClick: () => handleClick(item.value, idx),
39582
- className: `flex items-center justify-center transition-all duration-100 ${isSel ? "text-gray-900 font-semibold text-[15px]" : "text-gray-300 text-sm"}`,
39583
- style: { height: ITEM_H },
39584
- role: "option",
39585
- "aria-selected": isSel,
39586
- children: item.label
39587
- },
39588
- item.value
39589
- );
39590
- }),
39591
- Array.from({ length: PAD }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: ITEM_H }, "aria-hidden": true }, `pb-${i}`))
39592
- ]
39593
- }
39594
- )
39595
- ] });
39445
+ }
39446
+ return slots;
39596
39447
  };
39597
- var HOURS = Array.from({ length: 12 }, (_, i) => ({ value: i + 1, label: (i + 1).toString() }));
39598
- var MINUTES = Array.from({ length: 60 }, (_, i) => ({ value: i, label: pad22(i) }));
39448
+ var TIME_SLOTS = generateTimeSlots();
39599
39449
  var TimePopover = ({
39600
39450
  hour,
39601
39451
  minute,
39602
39452
  period,
39603
- onHourChange,
39604
- onMinuteChange,
39605
- onPeriodChange,
39606
- onClose,
39607
- onNow
39453
+ onTimeChange,
39454
+ onClose
39608
39455
  }) => {
39609
- const bandCenter = PAD * ITEM_H + ITEM_H / 2;
39456
+ const [searchTerm, setSearchTerm] = React142.useState("");
39457
+ const inputRef = React142.useRef(null);
39458
+ const listRef = React142.useRef(null);
39459
+ const selectedValue = to24h(hour, minute, period);
39460
+ React142.useEffect(() => {
39461
+ setTimeout(() => inputRef.current?.focus(), 100);
39462
+ }, []);
39463
+ React142.useEffect(() => {
39464
+ if (!listRef.current) return;
39465
+ const selectedEl = listRef.current.querySelector('[data-selected="true"]');
39466
+ if (selectedEl) {
39467
+ selectedEl.scrollIntoView({ block: "center" });
39468
+ }
39469
+ }, []);
39470
+ const filteredSlots = React142.useMemo(() => {
39471
+ if (!searchTerm) return TIME_SLOTS;
39472
+ const term = searchTerm.toLowerCase().trim();
39473
+ return TIME_SLOTS.filter((slot) => {
39474
+ const label = slot.label.toLowerCase();
39475
+ return label.startsWith(term) || // Handle "05" matching "5:00" — strip leading zero from search
39476
+ label.startsWith(term.replace(/^0+/, "")) || // Handle 24h input like "17" matching "17:00" via the value
39477
+ slot.value.startsWith(term);
39478
+ });
39479
+ }, [searchTerm]);
39480
+ const handleSelect = (timeValue) => {
39481
+ onTimeChange(timeValue);
39482
+ onClose();
39483
+ };
39484
+ const handleKeyDown = (e) => {
39485
+ if (e.key === "Escape") {
39486
+ onClose();
39487
+ } else if (e.key === "Enter") {
39488
+ e.preventDefault();
39489
+ if (filteredSlots.length > 0) {
39490
+ handleSelect(filteredSlots[0].value);
39491
+ }
39492
+ }
39493
+ };
39610
39494
  return /* @__PURE__ */ jsxRuntime.jsxs(
39611
39495
  "div",
39612
39496
  {
39613
- className: "absolute z-50 left-0 right-0 sm:left-auto sm:right-auto sm:w-[264px] mt-1.5 bg-white border border-gray-200 rounded-2xl shadow-[0_8px_30px_rgba(0,0,0,0.08),0_2px_8px_rgba(0,0,0,0.04)] overflow-hidden",
39497
+ className: "absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-72 overflow-hidden",
39614
39498
  role: "dialog",
39615
39499
  "aria-label": "Choose time",
39616
39500
  onClick: (e) => e.stopPropagation(),
39617
39501
  children: [
39618
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-center px-4 pt-4 pb-2", children: [
39619
- /* @__PURE__ */ jsxRuntime.jsx(ScrollColumn, { items: HOURS, selected: hour, onSelect: (v) => onHourChange(v), width: 52 }),
39620
- /* @__PURE__ */ jsxRuntime.jsx(
39621
- "div",
39622
- {
39623
- className: "text-gray-300 text-lg font-light flex-shrink-0 w-4 text-center select-none",
39624
- style: { marginTop: bandCenter - 12 },
39625
- children: ":"
39626
- }
39627
- ),
39628
- /* @__PURE__ */ jsxRuntime.jsx(ScrollColumn, { items: MINUTES, selected: minute, onSelect: (v) => onMinuteChange(v), width: 52 }),
39629
- /* @__PURE__ */ jsxRuntime.jsx(
39630
- "div",
39631
- {
39632
- className: "flex flex-col gap-1.5 ml-3 flex-shrink-0",
39633
- style: { marginTop: bandCenter - 38 },
39634
- children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsxRuntime.jsx(
39635
- "button",
39636
- {
39637
- type: "button",
39638
- onClick: () => onPeriodChange(p),
39639
- className: `w-12 h-8 rounded-lg text-[11px] font-bold tracking-widest transition-all duration-150 ${period === p ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 text-gray-400 hover:bg-gray-200 hover:text-gray-600"}`,
39640
- "aria-pressed": period === p,
39641
- children: p
39642
- },
39643
- p
39644
- ))
39645
- }
39646
- )
39647
- ] }),
39648
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-4 border-t border-gray-100" }),
39649
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2.5", children: [
39650
- /* @__PURE__ */ jsxRuntime.jsx(
39651
- "button",
39652
- {
39653
- type: "button",
39654
- onClick: onNow,
39655
- className: "text-[13px] font-medium text-blue-600 hover:text-blue-700 transition-colors px-2.5 py-1 rounded-md hover:bg-blue-50",
39656
- children: "Now"
39657
- }
39658
- ),
39659
- /* @__PURE__ */ jsxRuntime.jsx(
39502
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntime.jsx(
39503
+ "input",
39504
+ {
39505
+ ref: inputRef,
39506
+ type: "text",
39507
+ placeholder: "Search time...",
39508
+ value: searchTerm,
39509
+ onChange: (e) => setSearchTerm(e.target.value),
39510
+ onKeyDown: handleKeyDown,
39511
+ className: "w-full px-3 py-2 text-sm border border-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
39512
+ }
39513
+ ) }),
39514
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: listRef, className: "overflow-y-auto max-h-52", children: filteredSlots.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: "No matching times" }) : filteredSlots.map((slot) => {
39515
+ const isSelected = slot.value === selectedValue;
39516
+ return /* @__PURE__ */ jsxRuntime.jsx(
39660
39517
  "button",
39661
39518
  {
39662
39519
  type: "button",
39663
- onClick: onClose,
39664
- className: "text-[13px] font-medium text-white bg-blue-600 hover:bg-blue-700 px-4 py-1.5 rounded-lg transition-colors shadow-sm",
39665
- children: "Done"
39666
- }
39667
- )
39668
- ] })
39520
+ "data-selected": isSelected,
39521
+ onClick: () => handleSelect(slot.value),
39522
+ className: `w-full px-3 py-2 text-left text-sm transition-colors duration-100 ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
39523
+ children: slot.label
39524
+ },
39525
+ slot.value
39526
+ );
39527
+ }) })
39669
39528
  ]
39670
39529
  }
39671
39530
  );
@@ -39705,15 +39564,6 @@ var TimePickerDropdown = ({
39705
39564
  const handlePeriodChange = React142.useCallback((p) => {
39706
39565
  emitChange(hour, minute, p);
39707
39566
  }, [emitChange, hour, minute]);
39708
- const handleNow = React142.useCallback(() => {
39709
- const now4 = /* @__PURE__ */ new Date();
39710
- const h24 = now4.getHours();
39711
- const m = now4.getMinutes();
39712
- const p = h24 >= 12 ? "PM" : "AM";
39713
- let h12 = h24 % 12;
39714
- if (h12 === 0) h12 = 12;
39715
- emitChange(h12, m, p);
39716
- }, [emitChange]);
39717
39567
  const handleSegmentFocus = React142.useCallback((seg) => {
39718
39568
  setActiveSegment(seg);
39719
39569
  if (!hasValue) {
@@ -39732,13 +39582,8 @@ var TimePickerDropdown = ({
39732
39582
  }, [disabled, hasValue, onChange]);
39733
39583
  const handleContainerClick = React142.useCallback(() => {
39734
39584
  if (disabled) return;
39735
- if (!activeSegment) {
39736
- setActiveSegment("hour");
39737
- if (!hasValue) {
39738
- onChange(to24h(12, 0, "AM"));
39739
- }
39740
- }
39741
- }, [disabled, activeSegment, hasValue, onChange]);
39585
+ togglePopover();
39586
+ }, [disabled, togglePopover]);
39742
39587
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative ${className}`, ref: containerRef, children: [
39743
39588
  /* @__PURE__ */ jsxRuntime.jsxs(
39744
39589
  "div",
@@ -39819,11 +39664,8 @@ var TimePickerDropdown = ({
39819
39664
  hour,
39820
39665
  minute,
39821
39666
  period,
39822
- onHourChange: handleHourChange,
39823
- onMinuteChange: handleMinuteChange,
39824
- onPeriodChange: handlePeriodChange,
39825
- onClose: () => setIsPopoverOpen(false),
39826
- onNow: handleNow
39667
+ onTimeChange: onChange,
39668
+ onClose: () => setIsPopoverOpen(false)
39827
39669
  }
39828
39670
  )
39829
39671
  ] });
@@ -41256,7 +41098,7 @@ var FileManagerFilters = ({
41256
41098
  document.body.style.overflow = "unset";
41257
41099
  };
41258
41100
  }, [showTimeFilterModal, showIdleLabelFilterModal]);
41259
- const generateTimeSlots = React142.useCallback(() => {
41101
+ const generateTimeSlots2 = React142.useCallback(() => {
41260
41102
  const slots = [];
41261
41103
  for (let hour = 0; hour < 24; hour++) {
41262
41104
  for (let minute = 0; minute < 60; minute += 15) {
@@ -41269,7 +41111,7 @@ var FileManagerFilters = ({
41269
41111
  }
41270
41112
  return slots;
41271
41113
  }, []);
41272
- const timeSlots = React142.useMemo(() => generateTimeSlots(), [generateTimeSlots]);
41114
+ const timeSlots = React142.useMemo(() => generateTimeSlots2(), [generateTimeSlots2]);
41273
41115
  const filteredStartSlots = React142.useMemo(
41274
41116
  () => timeSlots.filter(
41275
41117
  (slot) => slot.label.toLowerCase().includes(startSearchTerm.toLowerCase())
package/dist/index.mjs CHANGED
@@ -39403,240 +39403,99 @@ var SegmentedTimeInput = ({
39403
39403
  }
39404
39404
  );
39405
39405
  };
39406
- var SCROLLBAR_HIDE_ID = "tp-scrollbar-hide";
39407
- var injectScrollbarHideCSS = () => {
39408
- if (typeof document === "undefined") return;
39409
- if (document.getElementById(SCROLLBAR_HIDE_ID)) return;
39410
- const style = document.createElement("style");
39411
- style.id = SCROLLBAR_HIDE_ID;
39412
- style.textContent = ".tp-scroll-hide::-webkit-scrollbar{display:none}";
39413
- document.head.appendChild(style);
39414
- };
39415
- var ITEM_H = 40;
39416
- var VISIBLE = 5;
39417
- var WHEEL_H = ITEM_H * VISIBLE;
39418
- var PAD = Math.floor(VISIBLE / 2);
39419
- var ScrollColumn = ({ items, selected, onSelect, width = 56 }) => {
39420
- const elRef = useRef(null);
39421
- const suppressRef = useRef(false);
39422
- const snapTimerRef = useRef(null);
39423
- const mountedRef = useRef(false);
39424
- const dragging = useRef(false);
39425
- const dragStartY = useRef(0);
39426
- const dragStartScroll = useRef(0);
39427
- useEffect(() => {
39428
- injectScrollbarHideCSS();
39429
- }, []);
39430
- useEffect(() => {
39431
- const idx = items.findIndex((i) => i.value === selected);
39432
- if (idx < 0 || !elRef.current || suppressRef.current) return;
39433
- const target = idx * ITEM_H;
39434
- if (!mountedRef.current) {
39435
- suppressRef.current = true;
39436
- elRef.current.scrollTop = target;
39437
- setTimeout(() => {
39438
- if (elRef.current) elRef.current.scrollTop = target;
39439
- setTimeout(() => {
39440
- suppressRef.current = false;
39441
- mountedRef.current = true;
39442
- }, 200);
39443
- }, 30);
39444
- } else {
39445
- elRef.current.scrollTo({ top: target, behavior: "smooth" });
39446
- }
39447
- }, [selected, items]);
39448
- const scheduleSnap = useCallback(() => {
39449
- if (snapTimerRef.current) clearTimeout(snapTimerRef.current);
39450
- snapTimerRef.current = setTimeout(() => {
39451
- if (!elRef.current || suppressRef.current) return;
39452
- const idx = Math.round(elRef.current.scrollTop / ITEM_H);
39453
- const clamped = Math.max(0, Math.min(items.length - 1, idx));
39454
- suppressRef.current = true;
39455
- elRef.current.scrollTo({ top: clamped * ITEM_H, behavior: "smooth" });
39456
- const item = items[clamped];
39457
- if (item && item.value !== selected) onSelect(item.value);
39458
- setTimeout(() => {
39459
- suppressRef.current = false;
39460
- }, 150);
39461
- }, 100);
39462
- }, [items, selected, onSelect]);
39463
- const onScroll = useCallback(() => {
39464
- if (suppressRef.current) return;
39465
- scheduleSnap();
39466
- }, [scheduleSnap]);
39467
- const onMouseDown = useCallback((e) => {
39468
- dragging.current = true;
39469
- dragStartY.current = e.clientY;
39470
- dragStartScroll.current = elRef.current?.scrollTop ?? 0;
39471
- e.preventDefault();
39472
- const onMove = (ev) => {
39473
- if (!dragging.current || !elRef.current) return;
39474
- const dy = dragStartY.current - ev.clientY;
39475
- elRef.current.scrollTop = dragStartScroll.current + dy;
39476
- };
39477
- const onUp = () => {
39478
- dragging.current = false;
39479
- scheduleSnap();
39480
- document.removeEventListener("mousemove", onMove);
39481
- document.removeEventListener("mouseup", onUp);
39482
- };
39483
- document.addEventListener("mousemove", onMove);
39484
- document.addEventListener("mouseup", onUp);
39485
- }, [scheduleSnap]);
39486
- const onTouchStart = useCallback((e) => {
39487
- dragging.current = true;
39488
- dragStartY.current = e.touches[0].clientY;
39489
- dragStartScroll.current = elRef.current?.scrollTop ?? 0;
39490
- }, []);
39491
- const onTouchMove = useCallback((e) => {
39492
- if (!dragging.current || !elRef.current) return;
39493
- const dy = dragStartY.current - e.touches[0].clientY;
39494
- elRef.current.scrollTop = dragStartScroll.current + dy;
39495
- e.preventDefault();
39496
- }, []);
39497
- const onTouchEnd = useCallback(() => {
39498
- dragging.current = false;
39499
- scheduleSnap();
39500
- }, [scheduleSnap]);
39501
- const handleClick = useCallback((value, idx) => {
39502
- onSelect(value);
39503
- if (elRef.current) {
39504
- suppressRef.current = true;
39505
- elRef.current.scrollTo({ top: idx * ITEM_H, behavior: "smooth" });
39506
- setTimeout(() => {
39507
- suppressRef.current = false;
39508
- }, 250);
39406
+ var generateTimeSlots = () => {
39407
+ const slots = [];
39408
+ for (let hour = 0; hour < 24; hour++) {
39409
+ for (let minute = 0; minute < 60; minute += 5) {
39410
+ const time24 = `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`;
39411
+ const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
39412
+ const ampm = hour < 12 ? "AM" : "PM";
39413
+ const time12 = `${hour12}:${minute.toString().padStart(2, "0")} ${ampm}`;
39414
+ slots.push({ value: time24, label: time12 });
39509
39415
  }
39510
- }, [onSelect]);
39511
- return /* @__PURE__ */ jsxs("div", { className: "relative select-none", style: { width, height: WHEEL_H }, children: [
39512
- /* @__PURE__ */ jsx(
39513
- "div",
39514
- {
39515
- className: "absolute left-1 right-1 rounded-lg bg-blue-50/80 border border-blue-200/60 pointer-events-none z-0",
39516
- style: { top: PAD * ITEM_H, height: ITEM_H }
39517
- }
39518
- ),
39519
- /* @__PURE__ */ jsx(
39520
- "div",
39521
- {
39522
- className: "absolute inset-x-0 top-0 pointer-events-none z-10",
39523
- style: { height: ITEM_H * 1.8, background: "linear-gradient(to bottom, white 0%, rgba(255,255,255,0.85) 50%, transparent 100%)" }
39524
- }
39525
- ),
39526
- /* @__PURE__ */ jsx(
39527
- "div",
39528
- {
39529
- className: "absolute inset-x-0 bottom-0 pointer-events-none z-10",
39530
- style: { height: ITEM_H * 1.8, background: "linear-gradient(to top, white 0%, rgba(255,255,255,0.85) 50%, transparent 100%)" }
39531
- }
39532
- ),
39533
- /* @__PURE__ */ jsxs(
39534
- "div",
39535
- {
39536
- ref: elRef,
39537
- onScroll,
39538
- onMouseDown,
39539
- onTouchStart,
39540
- onTouchMove,
39541
- onTouchEnd,
39542
- className: "h-full overflow-y-auto tp-scroll-hide relative z-[1] cursor-grab active:cursor-grabbing",
39543
- style: { scrollbarWidth: "none", msOverflowStyle: "none" },
39544
- role: "listbox",
39545
- children: [
39546
- Array.from({ length: PAD }).map((_, i) => /* @__PURE__ */ jsx("div", { style: { height: ITEM_H }, "aria-hidden": true }, `pt-${i}`)),
39547
- items.map((item, idx) => {
39548
- const isSel = item.value === selected;
39549
- return /* @__PURE__ */ jsx(
39550
- "div",
39551
- {
39552
- onClick: () => handleClick(item.value, idx),
39553
- className: `flex items-center justify-center transition-all duration-100 ${isSel ? "text-gray-900 font-semibold text-[15px]" : "text-gray-300 text-sm"}`,
39554
- style: { height: ITEM_H },
39555
- role: "option",
39556
- "aria-selected": isSel,
39557
- children: item.label
39558
- },
39559
- item.value
39560
- );
39561
- }),
39562
- Array.from({ length: PAD }).map((_, i) => /* @__PURE__ */ jsx("div", { style: { height: ITEM_H }, "aria-hidden": true }, `pb-${i}`))
39563
- ]
39564
- }
39565
- )
39566
- ] });
39416
+ }
39417
+ return slots;
39567
39418
  };
39568
- var HOURS = Array.from({ length: 12 }, (_, i) => ({ value: i + 1, label: (i + 1).toString() }));
39569
- var MINUTES = Array.from({ length: 60 }, (_, i) => ({ value: i, label: pad22(i) }));
39419
+ var TIME_SLOTS = generateTimeSlots();
39570
39420
  var TimePopover = ({
39571
39421
  hour,
39572
39422
  minute,
39573
39423
  period,
39574
- onHourChange,
39575
- onMinuteChange,
39576
- onPeriodChange,
39577
- onClose,
39578
- onNow
39424
+ onTimeChange,
39425
+ onClose
39579
39426
  }) => {
39580
- const bandCenter = PAD * ITEM_H + ITEM_H / 2;
39427
+ const [searchTerm, setSearchTerm] = useState("");
39428
+ const inputRef = useRef(null);
39429
+ const listRef = useRef(null);
39430
+ const selectedValue = to24h(hour, minute, period);
39431
+ useEffect(() => {
39432
+ setTimeout(() => inputRef.current?.focus(), 100);
39433
+ }, []);
39434
+ useEffect(() => {
39435
+ if (!listRef.current) return;
39436
+ const selectedEl = listRef.current.querySelector('[data-selected="true"]');
39437
+ if (selectedEl) {
39438
+ selectedEl.scrollIntoView({ block: "center" });
39439
+ }
39440
+ }, []);
39441
+ const filteredSlots = useMemo(() => {
39442
+ if (!searchTerm) return TIME_SLOTS;
39443
+ const term = searchTerm.toLowerCase().trim();
39444
+ return TIME_SLOTS.filter((slot) => {
39445
+ const label = slot.label.toLowerCase();
39446
+ return label.startsWith(term) || // Handle "05" matching "5:00" — strip leading zero from search
39447
+ label.startsWith(term.replace(/^0+/, "")) || // Handle 24h input like "17" matching "17:00" via the value
39448
+ slot.value.startsWith(term);
39449
+ });
39450
+ }, [searchTerm]);
39451
+ const handleSelect = (timeValue) => {
39452
+ onTimeChange(timeValue);
39453
+ onClose();
39454
+ };
39455
+ const handleKeyDown = (e) => {
39456
+ if (e.key === "Escape") {
39457
+ onClose();
39458
+ } else if (e.key === "Enter") {
39459
+ e.preventDefault();
39460
+ if (filteredSlots.length > 0) {
39461
+ handleSelect(filteredSlots[0].value);
39462
+ }
39463
+ }
39464
+ };
39581
39465
  return /* @__PURE__ */ jsxs(
39582
39466
  "div",
39583
39467
  {
39584
- className: "absolute z-50 left-0 right-0 sm:left-auto sm:right-auto sm:w-[264px] mt-1.5 bg-white border border-gray-200 rounded-2xl shadow-[0_8px_30px_rgba(0,0,0,0.08),0_2px_8px_rgba(0,0,0,0.04)] overflow-hidden",
39468
+ className: "absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-72 overflow-hidden",
39585
39469
  role: "dialog",
39586
39470
  "aria-label": "Choose time",
39587
39471
  onClick: (e) => e.stopPropagation(),
39588
39472
  children: [
39589
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-center px-4 pt-4 pb-2", children: [
39590
- /* @__PURE__ */ jsx(ScrollColumn, { items: HOURS, selected: hour, onSelect: (v) => onHourChange(v), width: 52 }),
39591
- /* @__PURE__ */ jsx(
39592
- "div",
39593
- {
39594
- className: "text-gray-300 text-lg font-light flex-shrink-0 w-4 text-center select-none",
39595
- style: { marginTop: bandCenter - 12 },
39596
- children: ":"
39597
- }
39598
- ),
39599
- /* @__PURE__ */ jsx(ScrollColumn, { items: MINUTES, selected: minute, onSelect: (v) => onMinuteChange(v), width: 52 }),
39600
- /* @__PURE__ */ jsx(
39601
- "div",
39602
- {
39603
- className: "flex flex-col gap-1.5 ml-3 flex-shrink-0",
39604
- style: { marginTop: bandCenter - 38 },
39605
- children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsx(
39606
- "button",
39607
- {
39608
- type: "button",
39609
- onClick: () => onPeriodChange(p),
39610
- className: `w-12 h-8 rounded-lg text-[11px] font-bold tracking-widest transition-all duration-150 ${period === p ? "bg-blue-600 text-white shadow-sm" : "bg-gray-100 text-gray-400 hover:bg-gray-200 hover:text-gray-600"}`,
39611
- "aria-pressed": period === p,
39612
- children: p
39613
- },
39614
- p
39615
- ))
39616
- }
39617
- )
39618
- ] }),
39619
- /* @__PURE__ */ jsx("div", { className: "mx-4 border-t border-gray-100" }),
39620
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2.5", children: [
39621
- /* @__PURE__ */ jsx(
39622
- "button",
39623
- {
39624
- type: "button",
39625
- onClick: onNow,
39626
- className: "text-[13px] font-medium text-blue-600 hover:text-blue-700 transition-colors px-2.5 py-1 rounded-md hover:bg-blue-50",
39627
- children: "Now"
39628
- }
39629
- ),
39630
- /* @__PURE__ */ jsx(
39473
+ /* @__PURE__ */ jsx("div", { className: "p-2 border-b border-gray-100", children: /* @__PURE__ */ jsx(
39474
+ "input",
39475
+ {
39476
+ ref: inputRef,
39477
+ type: "text",
39478
+ placeholder: "Search time...",
39479
+ value: searchTerm,
39480
+ onChange: (e) => setSearchTerm(e.target.value),
39481
+ onKeyDown: handleKeyDown,
39482
+ className: "w-full px-3 py-2 text-sm border border-gray-200 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
39483
+ }
39484
+ ) }),
39485
+ /* @__PURE__ */ jsx("div", { ref: listRef, className: "overflow-y-auto max-h-52", children: filteredSlots.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-sm text-gray-400 text-center", children: "No matching times" }) : filteredSlots.map((slot) => {
39486
+ const isSelected = slot.value === selectedValue;
39487
+ return /* @__PURE__ */ jsx(
39631
39488
  "button",
39632
39489
  {
39633
39490
  type: "button",
39634
- onClick: onClose,
39635
- className: "text-[13px] font-medium text-white bg-blue-600 hover:bg-blue-700 px-4 py-1.5 rounded-lg transition-colors shadow-sm",
39636
- children: "Done"
39637
- }
39638
- )
39639
- ] })
39491
+ "data-selected": isSelected,
39492
+ onClick: () => handleSelect(slot.value),
39493
+ className: `w-full px-3 py-2 text-left text-sm transition-colors duration-100 ${isSelected ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
39494
+ children: slot.label
39495
+ },
39496
+ slot.value
39497
+ );
39498
+ }) })
39640
39499
  ]
39641
39500
  }
39642
39501
  );
@@ -39676,15 +39535,6 @@ var TimePickerDropdown = ({
39676
39535
  const handlePeriodChange = useCallback((p) => {
39677
39536
  emitChange(hour, minute, p);
39678
39537
  }, [emitChange, hour, minute]);
39679
- const handleNow = useCallback(() => {
39680
- const now4 = /* @__PURE__ */ new Date();
39681
- const h24 = now4.getHours();
39682
- const m = now4.getMinutes();
39683
- const p = h24 >= 12 ? "PM" : "AM";
39684
- let h12 = h24 % 12;
39685
- if (h12 === 0) h12 = 12;
39686
- emitChange(h12, m, p);
39687
- }, [emitChange]);
39688
39538
  const handleSegmentFocus = useCallback((seg) => {
39689
39539
  setActiveSegment(seg);
39690
39540
  if (!hasValue) {
@@ -39703,13 +39553,8 @@ var TimePickerDropdown = ({
39703
39553
  }, [disabled, hasValue, onChange]);
39704
39554
  const handleContainerClick = useCallback(() => {
39705
39555
  if (disabled) return;
39706
- if (!activeSegment) {
39707
- setActiveSegment("hour");
39708
- if (!hasValue) {
39709
- onChange(to24h(12, 0, "AM"));
39710
- }
39711
- }
39712
- }, [disabled, activeSegment, hasValue, onChange]);
39556
+ togglePopover();
39557
+ }, [disabled, togglePopover]);
39713
39558
  return /* @__PURE__ */ jsxs("div", { className: `relative ${className}`, ref: containerRef, children: [
39714
39559
  /* @__PURE__ */ jsxs(
39715
39560
  "div",
@@ -39790,11 +39635,8 @@ var TimePickerDropdown = ({
39790
39635
  hour,
39791
39636
  minute,
39792
39637
  period,
39793
- onHourChange: handleHourChange,
39794
- onMinuteChange: handleMinuteChange,
39795
- onPeriodChange: handlePeriodChange,
39796
- onClose: () => setIsPopoverOpen(false),
39797
- onNow: handleNow
39638
+ onTimeChange: onChange,
39639
+ onClose: () => setIsPopoverOpen(false)
39798
39640
  }
39799
39641
  )
39800
39642
  ] });
@@ -41227,7 +41069,7 @@ var FileManagerFilters = ({
41227
41069
  document.body.style.overflow = "unset";
41228
41070
  };
41229
41071
  }, [showTimeFilterModal, showIdleLabelFilterModal]);
41230
- const generateTimeSlots = useCallback(() => {
41072
+ const generateTimeSlots2 = useCallback(() => {
41231
41073
  const slots = [];
41232
41074
  for (let hour = 0; hour < 24; hour++) {
41233
41075
  for (let minute = 0; minute < 60; minute += 15) {
@@ -41240,7 +41082,7 @@ var FileManagerFilters = ({
41240
41082
  }
41241
41083
  return slots;
41242
41084
  }, []);
41243
- const timeSlots = useMemo(() => generateTimeSlots(), [generateTimeSlots]);
41085
+ const timeSlots = useMemo(() => generateTimeSlots2(), [generateTimeSlots2]);
41244
41086
  const filteredStartSlots = useMemo(
41245
41087
  () => timeSlots.filter(
41246
41088
  (slot) => slot.label.toLowerCase().includes(startSearchTerm.toLowerCase())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optifye/dashboard-core",
3
- "version": "6.11.30",
3
+ "version": "6.11.32",
4
4
  "description": "Reusable UI & logic for Optifye dashboard",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",