@payglocal_ui/flux-ui 0.3.0 → 0.3.1
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.cjs +429 -212
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +456 -239
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/copyable-cell-tooltip.test.tsx +81 -0
- package/src/__tests__/date-picker-show-time.test.tsx +189 -0
- package/src/__tests__/picker-in-dialog.test.tsx +140 -0
- package/src/copyable-cell.tsx +65 -26
- package/src/date-picker.tsx +459 -126
- package/src/index.ts +1 -1
- package/src/time-picker.tsx +95 -66
package/dist/index.cjs
CHANGED
|
@@ -2859,7 +2859,7 @@ function useSpotlight(steps, initialStep = 0) {
|
|
|
2859
2859
|
else setCurrentStep((s) => s + 1);
|
|
2860
2860
|
},
|
|
2861
2861
|
goBack: () => setCurrentStep((s) => Math.max(0, s - 1)),
|
|
2862
|
-
goTo: (
|
|
2862
|
+
goTo: (step2) => setCurrentStep(Math.max(0, Math.min(step2, steps.length - 1)))
|
|
2863
2863
|
};
|
|
2864
2864
|
}
|
|
2865
2865
|
|
|
@@ -3904,20 +3904,20 @@ var Progress = React36.forwardRef(({ className, value, variant = "default", size
|
|
|
3904
3904
|
] }));
|
|
3905
3905
|
Progress.displayName = "Progress";
|
|
3906
3906
|
var ProgressTracker = React36.forwardRef(
|
|
3907
|
-
({ className, steps, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { ref, className: cn("flex items-start", className), ...props, children: steps.map((
|
|
3907
|
+
({ className, steps, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { ref, className: cn("flex items-start", className), ...props, children: steps.map((step2, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(React36.Fragment, { children: [
|
|
3908
3908
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-col items-center gap-1.5 min-w-0", children: [
|
|
3909
3909
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: cn(
|
|
3910
3910
|
"flex h-8 w-8 shrink-0 items-center justify-center rounded-full border-2 text-sm font-semibold transition-colors",
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
), children:
|
|
3911
|
+
step2.status === "complete" && "bg-primary border-primary text-primary-foreground",
|
|
3912
|
+
step2.status === "current" && "bg-primary/10 border-primary text-primary",
|
|
3913
|
+
step2.status === "upcoming" && "bg-card border-border text-muted-foreground"
|
|
3914
|
+
), children: step2.status === "complete" ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.Check, { className: "size-4", strokeWidth: 2.5 }) : i + 1 }),
|
|
3915
3915
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "text-center px-1", children: [
|
|
3916
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: cn("text-xs font-medium",
|
|
3917
|
-
|
|
3916
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: cn("text-xs font-medium", step2.status === "upcoming" ? "text-muted-foreground" : "text-foreground"), children: step2.label }),
|
|
3917
|
+
step2.description && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[11px] text-muted-foreground mt-0.5", children: step2.description })
|
|
3918
3918
|
] })
|
|
3919
3919
|
] }),
|
|
3920
|
-
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex-1 mt-4 mx-1", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: cn("h-0.5 w-full rounded-full transition-colors",
|
|
3920
|
+
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex-1 mt-4 mx-1", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: cn("h-0.5 w-full rounded-full transition-colors", step2.status === "complete" ? "bg-primary" : "bg-border") }) })
|
|
3921
3921
|
] }, i)) })
|
|
3922
3922
|
);
|
|
3923
3923
|
ProgressTracker.displayName = "ProgressTracker";
|
|
@@ -4531,7 +4531,7 @@ var PAGE_BUTTON = "w-7 h-7 rounded-md flex items-center justify-center text-[12p
|
|
|
4531
4531
|
var PAGE_BUTTON_IDLE = "text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-30 disabled:cursor-not-allowed";
|
|
4532
4532
|
var PAGE_BUTTON_ACTIVE = "bg-primary text-primary-foreground shadow-sm";
|
|
4533
4533
|
function DataTableFooter({
|
|
4534
|
-
pad:
|
|
4534
|
+
pad: pad3,
|
|
4535
4535
|
summary,
|
|
4536
4536
|
countLabels,
|
|
4537
4537
|
leading,
|
|
@@ -4572,7 +4572,7 @@ function DataTableFooter({
|
|
|
4572
4572
|
{
|
|
4573
4573
|
className: cn(
|
|
4574
4574
|
"flex items-center gap-4 flex-wrap border-t border-border",
|
|
4575
|
-
|
|
4575
|
+
pad3,
|
|
4576
4576
|
summary === "none" && !showRowsPerPage && !leading ? "justify-end" : "justify-between"
|
|
4577
4577
|
),
|
|
4578
4578
|
children: [
|
|
@@ -4920,7 +4920,7 @@ function CopyableCell({
|
|
|
4920
4920
|
valueClassName
|
|
4921
4921
|
);
|
|
4922
4922
|
const elided = display !== void 0 && display !== value;
|
|
4923
|
-
const copyHint = copied ? "Copied" :
|
|
4923
|
+
const copyHint = copied ? "Copied" : `Copy ${label}`;
|
|
4924
4924
|
if (variant === "cell") {
|
|
4925
4925
|
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Tooltip, { children: [
|
|
4926
4926
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
@@ -4958,31 +4958,45 @@ function CopyableCell({
|
|
|
4958
4958
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipContent, { side: "top", className: "text-xs", children: copied ? "Copied" : "Copy" })
|
|
4959
4959
|
] }) });
|
|
4960
4960
|
}
|
|
4961
|
+
const valueNode = onClick ? (
|
|
4962
|
+
// A bare <button>, deliberately, where the rest of flux would reach for
|
|
4963
|
+
// `Button variant="link"`. That variant hard-codes `text-[15px]`, and
|
|
4964
|
+
// the obvious override — `text-[inherit]` — does not beat it: Tailwind
|
|
4965
|
+
// and tailwind-merge read `text-[<non-length>]` as a COLOUR, so the
|
|
4966
|
+
// size class survives and the cell renders 2px larger than every other
|
|
4967
|
+
// cell in the row. Preflight already gives a bare button `font: inherit`,
|
|
4968
|
+
// so this simply inherits the cell's size at whatever density the table
|
|
4969
|
+
// is using, which is what a cell should do.
|
|
4970
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4971
|
+
"button",
|
|
4972
|
+
{
|
|
4973
|
+
type: "button",
|
|
4974
|
+
onClick,
|
|
4975
|
+
title: elided ? void 0 : value,
|
|
4976
|
+
"aria-label": elided ? value : void 0,
|
|
4977
|
+
className: cn(
|
|
4978
|
+
"cursor-pointer bg-transparent p-0 text-left underline-offset-4",
|
|
4979
|
+
"hover:underline focus-visible:underline focus-visible:outline-none",
|
|
4980
|
+
text
|
|
4981
|
+
),
|
|
4982
|
+
children: display ?? value
|
|
4983
|
+
}
|
|
4984
|
+
)
|
|
4985
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4986
|
+
"span",
|
|
4987
|
+
{
|
|
4988
|
+
className: text,
|
|
4989
|
+
title: elided ? void 0 : value,
|
|
4990
|
+
"aria-hidden": elided || void 0,
|
|
4991
|
+
children: display ?? value
|
|
4992
|
+
}
|
|
4993
|
+
);
|
|
4961
4994
|
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cn("group/copy flex min-w-0 items-center gap-1", className), children: [
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
// size class survives and the cell renders 2px larger than every other
|
|
4968
|
-
// cell in the row. Preflight already gives a bare button `font: inherit`,
|
|
4969
|
-
// so this simply inherits the cell's size at whatever density the table
|
|
4970
|
-
// is using, which is what a cell should do.
|
|
4971
|
-
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4972
|
-
"button",
|
|
4973
|
-
{
|
|
4974
|
-
type: "button",
|
|
4975
|
-
onClick,
|
|
4976
|
-
title: value,
|
|
4977
|
-
className: cn(
|
|
4978
|
-
"cursor-pointer bg-transparent p-0 text-left underline-offset-4",
|
|
4979
|
-
"hover:underline focus-visible:underline focus-visible:outline-none",
|
|
4980
|
-
text
|
|
4981
|
-
),
|
|
4982
|
-
children: display ?? value
|
|
4983
|
-
}
|
|
4984
|
-
)
|
|
4985
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: text, title: value, children: display ?? value }),
|
|
4995
|
+
elided ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Tooltip, { children: [
|
|
4996
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipTrigger, { asChild: true, children: valueNode }),
|
|
4997
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipContent, { side: "top", className: "text-xs", children: value })
|
|
4998
|
+
] }) }) : valueNode,
|
|
4999
|
+
elided && !onClick && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "sr-only", children: value }),
|
|
4986
5000
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Tooltip, { children: [
|
|
4987
5001
|
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4988
5002
|
Button,
|
|
@@ -5922,6 +5936,7 @@ function CalendarDayButton({
|
|
|
5922
5936
|
// src/date-picker.tsx
|
|
5923
5937
|
var import_react14 = require("react");
|
|
5924
5938
|
var import_react_dom = require("react-dom");
|
|
5939
|
+
var import_react_remove_scroll = require("react-remove-scroll");
|
|
5925
5940
|
var import_lucide_react33 = require("lucide-react");
|
|
5926
5941
|
var import_framer_motion = require("framer-motion");
|
|
5927
5942
|
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
@@ -5941,30 +5956,117 @@ var MONTHS = [
|
|
|
5941
5956
|
];
|
|
5942
5957
|
var DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
5943
5958
|
var PRIMARY = "#0061E3";
|
|
5944
|
-
var
|
|
5959
|
+
var CALENDAR_W = 296;
|
|
5960
|
+
var TIME_COL_W = 58;
|
|
5961
|
+
var TIME_ITEM_H = 28;
|
|
5962
|
+
var TIME_COL_H = 232;
|
|
5945
5963
|
function daysInMonth(y, m) {
|
|
5946
5964
|
return new Date(y, m + 1, 0).getDate();
|
|
5947
5965
|
}
|
|
5948
5966
|
function firstDayOf(y, m) {
|
|
5949
5967
|
return new Date(y, m, 1).getDay();
|
|
5950
5968
|
}
|
|
5951
|
-
function
|
|
5969
|
+
function pad(n) {
|
|
5970
|
+
return String(n).padStart(2, "0");
|
|
5971
|
+
}
|
|
5972
|
+
function parseValue(s) {
|
|
5952
5973
|
if (!s) return null;
|
|
5953
|
-
const [
|
|
5974
|
+
const [datePart, timePart = ""] = s.trim().split(/[ T]/);
|
|
5975
|
+
const [y, m, d] = datePart.split("-").map(Number);
|
|
5954
5976
|
if (!y || !m || !d) return null;
|
|
5955
|
-
|
|
5977
|
+
const [hh = 0, mm = 0, ss = 0] = timePart ? timePart.split(":").map(Number) : [];
|
|
5978
|
+
return {
|
|
5979
|
+
y,
|
|
5980
|
+
m: m - 1,
|
|
5981
|
+
d,
|
|
5982
|
+
hh: Number.isFinite(hh) ? hh : 0,
|
|
5983
|
+
mm: Number.isFinite(mm) ? mm : 0,
|
|
5984
|
+
ss: Number.isFinite(ss) ? ss : 0
|
|
5985
|
+
};
|
|
5986
|
+
}
|
|
5987
|
+
function parseYMD(s) {
|
|
5988
|
+
const p = parseValue(s);
|
|
5989
|
+
return p ? { y: p.y, m: p.m, d: p.d } : null;
|
|
5956
5990
|
}
|
|
5957
5991
|
function toYMD(y, m, d) {
|
|
5958
|
-
return `${y}-${
|
|
5992
|
+
return `${y}-${pad(m + 1)}-${pad(d)}`;
|
|
5993
|
+
}
|
|
5994
|
+
function formatValue(p, showTime, showSecond) {
|
|
5995
|
+
const date = toYMD(p.y, p.m, p.d);
|
|
5996
|
+
if (!showTime) return date;
|
|
5997
|
+
return showSecond ? `${date} ${pad(p.hh)}:${pad(p.mm)}:${pad(p.ss)}` : `${date} ${pad(p.hh)}:${pad(p.mm)}`;
|
|
5959
5998
|
}
|
|
5960
|
-
function
|
|
5961
|
-
const
|
|
5999
|
+
function displayTime(p, showSecond) {
|
|
6000
|
+
const period = p.hh < 12 ? "AM" : "PM";
|
|
6001
|
+
const h12 = p.hh % 12 === 0 ? 12 : p.hh % 12;
|
|
6002
|
+
const base = showSecond ? `${pad(h12)}:${pad(p.mm)}:${pad(p.ss)}` : `${pad(h12)}:${pad(p.mm)}`;
|
|
6003
|
+
return `${base} ${period}`;
|
|
6004
|
+
}
|
|
6005
|
+
function displayValue(value, showTime, showSecond) {
|
|
6006
|
+
const p = parseValue(value);
|
|
5962
6007
|
if (!p) return "";
|
|
5963
|
-
|
|
6008
|
+
const date = `${pad(p.d)} ${MONTHS[p.m].slice(0, 3)} ${p.y}`;
|
|
6009
|
+
return showTime ? `${date}, ${displayTime(p, showSecond)}` : date;
|
|
6010
|
+
}
|
|
6011
|
+
function step(n) {
|
|
6012
|
+
return Math.max(1, Math.floor(n ?? 1));
|
|
5964
6013
|
}
|
|
5965
|
-
function
|
|
6014
|
+
function TimeColumn({
|
|
6015
|
+
label,
|
|
6016
|
+
items,
|
|
6017
|
+
selected,
|
|
6018
|
+
onSelect,
|
|
6019
|
+
render
|
|
6020
|
+
}) {
|
|
6021
|
+
const ref = (0, import_react14.useRef)(null);
|
|
6022
|
+
const index = items.indexOf(selected);
|
|
6023
|
+
(0, import_react14.useEffect)(() => {
|
|
6024
|
+
const el = ref.current;
|
|
6025
|
+
if (!el || index < 0) return;
|
|
6026
|
+
el.scrollTo({ top: index * TIME_ITEM_H, behavior: "smooth" });
|
|
6027
|
+
}, [index]);
|
|
6028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex flex-col border-l border-border", style: { width: TIME_COL_W }, children: [
|
|
6029
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "py-1 text-center text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70", children: label }),
|
|
6030
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6031
|
+
"div",
|
|
6032
|
+
{
|
|
6033
|
+
ref,
|
|
6034
|
+
className: "overflow-y-auto",
|
|
6035
|
+
style: { height: TIME_COL_H, scrollbarWidth: "none", msOverflowStyle: "none" },
|
|
6036
|
+
children: [
|
|
6037
|
+
items.map((item) => {
|
|
6038
|
+
const active = item === selected;
|
|
6039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6040
|
+
"button",
|
|
6041
|
+
{
|
|
6042
|
+
type: "button",
|
|
6043
|
+
onClick: () => onSelect(item),
|
|
6044
|
+
className: cn(
|
|
6045
|
+
"flex w-full items-center justify-center rounded-md text-[13px] font-medium transition-colors",
|
|
6046
|
+
active ? "font-semibold text-white" : "text-foreground hover:bg-muted"
|
|
6047
|
+
),
|
|
6048
|
+
style: { height: TIME_ITEM_H, background: active ? PRIMARY : void 0 },
|
|
6049
|
+
children: render ? render(item) : String(item)
|
|
6050
|
+
},
|
|
6051
|
+
String(item)
|
|
6052
|
+
);
|
|
6053
|
+
}),
|
|
6054
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { style: { height: TIME_COL_H - TIME_ITEM_H } })
|
|
6055
|
+
]
|
|
6056
|
+
}
|
|
6057
|
+
)
|
|
6058
|
+
] });
|
|
6059
|
+
}
|
|
6060
|
+
function DatePicker({ value, onChange, placeholder = "Select date", className, min, max, label, showTime = false, showNow = true }) {
|
|
5966
6061
|
const today = /* @__PURE__ */ new Date();
|
|
5967
|
-
const parsed =
|
|
6062
|
+
const parsed = parseValue(value);
|
|
6063
|
+
const timeOptions = (0, import_react14.useMemo)(
|
|
6064
|
+
() => typeof showTime === "object" ? showTime : {},
|
|
6065
|
+
[showTime]
|
|
6066
|
+
);
|
|
6067
|
+
const withTime = showTime !== false && showTime !== void 0;
|
|
6068
|
+
const use12Hours = timeOptions.use12Hours ?? true;
|
|
6069
|
+
const showSecond = timeOptions.showSecond ?? false;
|
|
5968
6070
|
const [open, setOpen] = (0, import_react14.useState)(false);
|
|
5969
6071
|
const [panelPos, setPanelPos] = (0, import_react14.useState)({ top: 0, left: 0 });
|
|
5970
6072
|
const [viewYear, setViewYear] = (0, import_react14.useState)(parsed?.y ?? today.getFullYear());
|
|
@@ -5983,34 +6085,39 @@ function DatePicker({ value, onChange, placeholder = "Select date", className, m
|
|
|
5983
6085
|
setViewMonth(parsed.m);
|
|
5984
6086
|
}
|
|
5985
6087
|
}, [value]);
|
|
6088
|
+
const columnCount = withTime ? (showSecond ? 3 : 2) + (use12Hours ? 1 : 0) : 0;
|
|
6089
|
+
const PANEL_W2 = CALENDAR_W + columnCount * TIME_COL_W;
|
|
6090
|
+
const PANEL_H2 = withTime ? 392 : 340;
|
|
5986
6091
|
function openPanel() {
|
|
5987
6092
|
if (!triggerRef.current) return;
|
|
5988
6093
|
const trigger = triggerRef.current;
|
|
5989
6094
|
const vw = window.innerWidth;
|
|
5990
6095
|
const vh = window.innerHeight;
|
|
5991
|
-
const PANEL_H2 = 340;
|
|
5992
6096
|
trigger.scrollIntoView({ block: "center", behavior: "auto" });
|
|
5993
6097
|
requestAnimationFrame(() => {
|
|
5994
6098
|
if (!triggerRef.current) return;
|
|
5995
6099
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
5996
6100
|
let left = rect.left;
|
|
5997
|
-
if (left +
|
|
6101
|
+
if (left + PANEL_W2 > vw - 8) left = vw - PANEL_W2 - 8;
|
|
6102
|
+
if (left < 8) left = 8;
|
|
5998
6103
|
let top = rect.bottom + 6;
|
|
5999
6104
|
if (top + PANEL_H2 > vh - 8) top = rect.top - PANEL_H2 - 6;
|
|
6105
|
+
if (top < 8) top = 8;
|
|
6000
6106
|
setPanelPos({ top, left });
|
|
6001
6107
|
setOpen(true);
|
|
6002
6108
|
});
|
|
6003
6109
|
}
|
|
6110
|
+
function closePanel() {
|
|
6111
|
+
setOpen(false);
|
|
6112
|
+
setYearMenu(false);
|
|
6113
|
+
setMonthMenu(false);
|
|
6114
|
+
}
|
|
6004
6115
|
(0, import_react14.useEffect)(() => {
|
|
6005
6116
|
if (!open) return;
|
|
6006
6117
|
function handler(e) {
|
|
6007
6118
|
const inTrigger = triggerRef.current?.contains(e.target);
|
|
6008
6119
|
const inPanel = panelRef.current?.contains(e.target);
|
|
6009
|
-
if (!inTrigger && !inPanel)
|
|
6010
|
-
setOpen(false);
|
|
6011
|
-
setYearMenu(false);
|
|
6012
|
-
setMonthMenu(false);
|
|
6013
|
-
}
|
|
6120
|
+
if (!inTrigger && !inPanel) closePanel();
|
|
6014
6121
|
}
|
|
6015
6122
|
document.addEventListener("mousedown", handler);
|
|
6016
6123
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -6053,18 +6160,251 @@ function DatePicker({ value, onChange, placeholder = "Select date", className, m
|
|
|
6053
6160
|
cells.push({ d, m, y, current: false });
|
|
6054
6161
|
}
|
|
6055
6162
|
const years = Array.from({ length: 15 }, (_, i) => today.getFullYear() - 2 + i);
|
|
6163
|
+
const fallback = parseValue(`2000-01-01 ${timeOptions.defaultValue ?? "00:00"}`);
|
|
6164
|
+
const current = parsed ?? {
|
|
6165
|
+
y: today.getFullYear(),
|
|
6166
|
+
m: today.getMonth(),
|
|
6167
|
+
d: today.getDate(),
|
|
6168
|
+
hh: fallback.hh,
|
|
6169
|
+
mm: fallback.mm,
|
|
6170
|
+
ss: fallback.ss
|
|
6171
|
+
};
|
|
6172
|
+
const emit = (0, import_react14.useCallback)(
|
|
6173
|
+
(next) => onChange(formatValue(next, withTime, showSecond)),
|
|
6174
|
+
[onChange, withTime, showSecond]
|
|
6175
|
+
);
|
|
6176
|
+
function patchTime(patch) {
|
|
6177
|
+
emit({ ...current, ...patch });
|
|
6178
|
+
}
|
|
6179
|
+
const hourStep = step(timeOptions.hourStep);
|
|
6180
|
+
const minuteStep = step(timeOptions.minuteStep);
|
|
6181
|
+
const secondStep = step(timeOptions.secondStep);
|
|
6182
|
+
const hourItems = use12Hours ? Array.from({ length: Math.ceil(12 / hourStep) }, (_, i) => i * hourStep % 12) : Array.from({ length: Math.ceil(24 / hourStep) }, (_, i) => i * hourStep);
|
|
6183
|
+
const minuteItems = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => i * minuteStep);
|
|
6184
|
+
const secondItems = Array.from({ length: Math.ceil(60 / secondStep) }, (_, i) => i * secondStep);
|
|
6185
|
+
const selectedHour = use12Hours ? current.hh % 12 : current.hh;
|
|
6186
|
+
const selectedMeridiem = current.hh < 12 ? "AM" : "PM";
|
|
6187
|
+
function selectHour(h) {
|
|
6188
|
+
if (!use12Hours) return patchTime({ hh: h });
|
|
6189
|
+
patchTime({ hh: selectedMeridiem === "AM" ? h : h + 12 });
|
|
6190
|
+
}
|
|
6191
|
+
function selectMeridiem(p) {
|
|
6192
|
+
const base = current.hh % 12;
|
|
6193
|
+
patchTime({ hh: p === "AM" ? base : base + 12 });
|
|
6194
|
+
}
|
|
6056
6195
|
function selectDay(cell) {
|
|
6057
6196
|
if (!cell.current) {
|
|
6058
6197
|
setViewYear(cell.y);
|
|
6059
6198
|
setViewMonth(cell.m);
|
|
6060
6199
|
}
|
|
6061
6200
|
if (cell.current && isDisabled(cell.y, cell.m, cell.d)) return;
|
|
6062
|
-
|
|
6063
|
-
setOpen(false);
|
|
6201
|
+
emit({ y: cell.y, m: cell.m, d: cell.d, hh: current.hh, mm: current.mm, ss: current.ss });
|
|
6202
|
+
if (!withTime) setOpen(false);
|
|
6203
|
+
}
|
|
6204
|
+
function selectNow() {
|
|
6205
|
+
const n = /* @__PURE__ */ new Date();
|
|
6206
|
+
if (isDisabled(n.getFullYear(), n.getMonth(), n.getDate())) return;
|
|
6207
|
+
emit({
|
|
6208
|
+
y: n.getFullYear(),
|
|
6209
|
+
m: n.getMonth(),
|
|
6210
|
+
d: n.getDate(),
|
|
6211
|
+
hh: n.getHours(),
|
|
6212
|
+
mm: n.getMinutes(),
|
|
6213
|
+
ss: n.getSeconds()
|
|
6214
|
+
});
|
|
6215
|
+
closePanel();
|
|
6064
6216
|
}
|
|
6065
6217
|
const isToday = (c) => c.d === today.getDate() && c.m === today.getMonth() && c.y === today.getFullYear();
|
|
6066
6218
|
const isSelected = (c) => !!parsed && c.d === parsed.d && c.m === parsed.m && c.y === parsed.y;
|
|
6067
|
-
const
|
|
6219
|
+
const calendar = /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { style: { width: CALENDAR_W }, className: "flex flex-col", children: [
|
|
6220
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex items-center justify-between px-4 pt-4 pb-3", children: [
|
|
6221
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6222
|
+
"button",
|
|
6223
|
+
{
|
|
6224
|
+
type: "button",
|
|
6225
|
+
onClick: prevMonth,
|
|
6226
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center text-muted-foreground hover:bg-muted transition-colors",
|
|
6227
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronLeft, { className: "w-4 h-4" })
|
|
6228
|
+
}
|
|
6229
|
+
),
|
|
6230
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
6231
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
|
|
6232
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6233
|
+
"button",
|
|
6234
|
+
{
|
|
6235
|
+
type: "button",
|
|
6236
|
+
onClick: () => {
|
|
6237
|
+
setMonthMenu((o) => !o);
|
|
6238
|
+
setYearMenu(false);
|
|
6239
|
+
},
|
|
6240
|
+
className: "flex items-center gap-1 px-2 py-1 rounded-lg text-[14px] font-semibold text-foreground hover:bg-muted transition-colors",
|
|
6241
|
+
children: [
|
|
6242
|
+
MONTHS[viewMonth].slice(0, 3),
|
|
6243
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronDown, { className: "w-3 h-3 text-muted-foreground" })
|
|
6244
|
+
]
|
|
6245
|
+
}
|
|
6246
|
+
),
|
|
6247
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_framer_motion.AnimatePresence, { children: monthMenu && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6248
|
+
import_framer_motion.motion.div,
|
|
6249
|
+
{
|
|
6250
|
+
initial: { opacity: 0, y: -4 },
|
|
6251
|
+
animate: { opacity: 1, y: 0 },
|
|
6252
|
+
exit: { opacity: 0, y: -4 },
|
|
6253
|
+
transition: { duration: 0.12 },
|
|
6254
|
+
className: "absolute top-full left-0 z-[10000] mt-1 max-h-[220px] min-w-[130px] overflow-y-auto rounded-xl border border-border bg-popover py-1 shadow-lg",
|
|
6255
|
+
children: MONTHS.map((mn, mi) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6256
|
+
"button",
|
|
6257
|
+
{
|
|
6258
|
+
type: "button",
|
|
6259
|
+
onClick: () => {
|
|
6260
|
+
setViewMonth(mi);
|
|
6261
|
+
setMonthMenu(false);
|
|
6262
|
+
},
|
|
6263
|
+
className: "w-full px-3 py-2 text-left text-[13px] text-foreground transition-colors hover:bg-muted",
|
|
6264
|
+
style: { fontWeight: mi === viewMonth ? 600 : 400, color: mi === viewMonth ? PRIMARY : void 0 },
|
|
6265
|
+
children: mn
|
|
6266
|
+
},
|
|
6267
|
+
mn
|
|
6268
|
+
))
|
|
6269
|
+
}
|
|
6270
|
+
) })
|
|
6271
|
+
] }),
|
|
6272
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
|
|
6273
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6274
|
+
"button",
|
|
6275
|
+
{
|
|
6276
|
+
type: "button",
|
|
6277
|
+
onClick: () => {
|
|
6278
|
+
setYearMenu((o) => !o);
|
|
6279
|
+
setMonthMenu(false);
|
|
6280
|
+
},
|
|
6281
|
+
className: "flex items-center gap-1 px-2 py-1 rounded-lg text-[14px] font-semibold text-foreground hover:bg-muted transition-colors",
|
|
6282
|
+
children: [
|
|
6283
|
+
viewYear,
|
|
6284
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronDown, { className: "w-3 h-3 text-muted-foreground" })
|
|
6285
|
+
]
|
|
6286
|
+
}
|
|
6287
|
+
),
|
|
6288
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_framer_motion.AnimatePresence, { children: yearMenu && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6289
|
+
import_framer_motion.motion.div,
|
|
6290
|
+
{
|
|
6291
|
+
initial: { opacity: 0, y: -4 },
|
|
6292
|
+
animate: { opacity: 1, y: 0 },
|
|
6293
|
+
exit: { opacity: 0, y: -4 },
|
|
6294
|
+
transition: { duration: 0.12 },
|
|
6295
|
+
className: "absolute top-full left-0 z-[10000] mt-1 max-h-[200px] min-w-[90px] overflow-y-auto rounded-xl border border-border bg-popover py-1 shadow-lg",
|
|
6296
|
+
children: years.map((yr) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6297
|
+
"button",
|
|
6298
|
+
{
|
|
6299
|
+
type: "button",
|
|
6300
|
+
onClick: () => {
|
|
6301
|
+
setViewYear(yr);
|
|
6302
|
+
setYearMenu(false);
|
|
6303
|
+
},
|
|
6304
|
+
className: "w-full px-3 py-2 text-left text-[13px] text-foreground transition-colors hover:bg-muted",
|
|
6305
|
+
style: { fontWeight: yr === viewYear ? 600 : 400, color: yr === viewYear ? PRIMARY : void 0 },
|
|
6306
|
+
children: yr
|
|
6307
|
+
},
|
|
6308
|
+
yr
|
|
6309
|
+
))
|
|
6310
|
+
}
|
|
6311
|
+
) })
|
|
6312
|
+
] })
|
|
6313
|
+
] }),
|
|
6314
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6315
|
+
"button",
|
|
6316
|
+
{
|
|
6317
|
+
type: "button",
|
|
6318
|
+
onClick: nextMonth,
|
|
6319
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center text-muted-foreground hover:bg-muted transition-colors",
|
|
6320
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronRight, { className: "w-4 h-4" })
|
|
6321
|
+
}
|
|
6322
|
+
)
|
|
6323
|
+
] }),
|
|
6324
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6325
|
+
"div",
|
|
6326
|
+
{
|
|
6327
|
+
className: "px-3 pb-1",
|
|
6328
|
+
style: { display: "grid", gridTemplateColumns: "repeat(7, minmax(0, 1fr))" },
|
|
6329
|
+
children: DAYS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "py-1 text-center text-[11.5px] font-semibold text-muted-foreground", children: d }, d))
|
|
6330
|
+
}
|
|
6331
|
+
),
|
|
6332
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6333
|
+
"div",
|
|
6334
|
+
{
|
|
6335
|
+
className: "gap-y-0.5 px-3 pb-4",
|
|
6336
|
+
style: { display: "grid", gridTemplateColumns: "repeat(7, minmax(0, 1fr))" },
|
|
6337
|
+
children: cells.map((cell, i) => {
|
|
6338
|
+
const selected = isSelected(cell);
|
|
6339
|
+
const tod = isToday(cell);
|
|
6340
|
+
const disabled = cell.current && isDisabled(cell.y, cell.m, cell.d);
|
|
6341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6342
|
+
"button",
|
|
6343
|
+
{
|
|
6344
|
+
type: "button",
|
|
6345
|
+
onClick: () => selectDay(cell),
|
|
6346
|
+
disabled,
|
|
6347
|
+
className: cn(
|
|
6348
|
+
"h-9 w-9 mx-auto rounded-full text-[13px] font-medium flex items-center justify-center transition-all",
|
|
6349
|
+
selected && "text-white font-semibold",
|
|
6350
|
+
!selected && tod && "font-semibold",
|
|
6351
|
+
!selected && !tod && cell.current && !disabled && "text-gray-800 hover:bg-gray-100",
|
|
6352
|
+
!selected && !cell.current && "text-gray-300 hover:bg-gray-50",
|
|
6353
|
+
disabled && "opacity-30 cursor-not-allowed"
|
|
6354
|
+
),
|
|
6355
|
+
style: selected ? { background: PRIMARY } : tod ? { background: `${PRIMARY}18`, color: PRIMARY } : {},
|
|
6356
|
+
children: cell.d
|
|
6357
|
+
},
|
|
6358
|
+
i
|
|
6359
|
+
);
|
|
6360
|
+
})
|
|
6361
|
+
}
|
|
6362
|
+
)
|
|
6363
|
+
] });
|
|
6364
|
+
const timeColumns = withTime && /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex pt-3", children: [
|
|
6365
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6366
|
+
TimeColumn,
|
|
6367
|
+
{
|
|
6368
|
+
label: "Hr",
|
|
6369
|
+
items: hourItems,
|
|
6370
|
+
selected: selectedHour,
|
|
6371
|
+
onSelect: selectHour,
|
|
6372
|
+
render: (h) => pad(use12Hours && h === 0 ? 12 : h)
|
|
6373
|
+
}
|
|
6374
|
+
),
|
|
6375
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(TimeColumn, { label: "Min", items: minuteItems, selected: current.mm, onSelect: (m) => patchTime({ mm: m }), render: pad }),
|
|
6376
|
+
showSecond && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(TimeColumn, { label: "Sec", items: secondItems, selected: current.ss, onSelect: (s) => patchTime({ ss: s }), render: pad }),
|
|
6377
|
+
use12Hours && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(TimeColumn, { label: "AM/PM", items: ["AM", "PM"], selected: selectedMeridiem, onSelect: selectMeridiem })
|
|
6378
|
+
] });
|
|
6379
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
|
|
6380
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex", children: [
|
|
6381
|
+
calendar,
|
|
6382
|
+
timeColumns
|
|
6383
|
+
] }),
|
|
6384
|
+
withTime && /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex items-center justify-between border-t border-border px-4 py-2.5", children: [
|
|
6385
|
+
showNow ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6386
|
+
"button",
|
|
6387
|
+
{
|
|
6388
|
+
type: "button",
|
|
6389
|
+
onClick: selectNow,
|
|
6390
|
+
className: "rounded-md px-1 text-[13px] font-medium transition-colors hover:underline",
|
|
6391
|
+
style: { color: PRIMARY },
|
|
6392
|
+
children: "Now"
|
|
6393
|
+
}
|
|
6394
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", {}),
|
|
6395
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6396
|
+
"button",
|
|
6397
|
+
{
|
|
6398
|
+
type: "button",
|
|
6399
|
+
onClick: closePanel,
|
|
6400
|
+
className: "rounded-lg px-3 py-1.5 text-[13px] font-semibold text-white transition-opacity hover:opacity-90",
|
|
6401
|
+
style: { background: PRIMARY },
|
|
6402
|
+
children: "OK"
|
|
6403
|
+
}
|
|
6404
|
+
)
|
|
6405
|
+
] })
|
|
6406
|
+
] });
|
|
6407
|
+
const panel = /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_framer_motion.AnimatePresence, { children: open && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6068
6408
|
import_framer_motion.motion.div,
|
|
6069
6409
|
{
|
|
6070
6410
|
ref: panelRef,
|
|
@@ -6077,149 +6417,21 @@ function DatePicker({ value, onChange, placeholder = "Select date", className, m
|
|
|
6077
6417
|
position: "fixed",
|
|
6078
6418
|
top: panelPos.top,
|
|
6079
6419
|
left: panelPos.left,
|
|
6080
|
-
width:
|
|
6420
|
+
width: PANEL_W2,
|
|
6081
6421
|
zIndex: 2e4,
|
|
6422
|
+
// A modal Radix Dialog sets `pointer-events: none` on <body> while
|
|
6423
|
+
// it is open, and this panel is portaled to <body> — so without
|
|
6424
|
+
// this every click on a day landed on nothing and the calendar
|
|
6425
|
+
// looked frozen inside a Dialog or Drawer. Hit-testing is
|
|
6426
|
+
// per-element, so re-enabling it here is enough; the page behind
|
|
6427
|
+
// the dialog stays inert. The click still reaches the dialog's
|
|
6428
|
+
// DismissableLayer through React's portal event propagation, so it
|
|
6429
|
+
// is treated as inside and does not dismiss the dialog.
|
|
6430
|
+
pointerEvents: "auto",
|
|
6082
6431
|
backgroundColor: "var(--popover)",
|
|
6083
6432
|
boxShadow: "0 16px 40px rgba(0,0,0,0.12), 0 4px 12px rgba(0,0,0,0.07)"
|
|
6084
6433
|
},
|
|
6085
|
-
children:
|
|
6086
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex items-center justify-between px-4 pt-4 pb-3", children: [
|
|
6087
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6088
|
-
"button",
|
|
6089
|
-
{
|
|
6090
|
-
onClick: prevMonth,
|
|
6091
|
-
className: "w-8 h-8 rounded-full flex items-center justify-center text-gray-500 hover:bg-gray-100 transition-colors",
|
|
6092
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronLeft, { className: "w-4 h-4" })
|
|
6093
|
-
}
|
|
6094
|
-
),
|
|
6095
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
6096
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
|
|
6097
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6098
|
-
"button",
|
|
6099
|
-
{
|
|
6100
|
-
onClick: () => {
|
|
6101
|
-
setMonthMenu((o) => !o);
|
|
6102
|
-
setYearMenu(false);
|
|
6103
|
-
},
|
|
6104
|
-
className: "flex items-center gap-1 px-2 py-1 rounded-lg text-[14px] font-semibold text-gray-900 hover:bg-gray-100 transition-colors",
|
|
6105
|
-
children: [
|
|
6106
|
-
MONTHS[viewMonth].slice(0, 3),
|
|
6107
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronDown, { className: "w-3 h-3 text-gray-400" })
|
|
6108
|
-
]
|
|
6109
|
-
}
|
|
6110
|
-
),
|
|
6111
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_framer_motion.AnimatePresence, { children: monthMenu && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6112
|
-
import_framer_motion.motion.div,
|
|
6113
|
-
{
|
|
6114
|
-
initial: { opacity: 0, y: -4 },
|
|
6115
|
-
animate: { opacity: 1, y: 0 },
|
|
6116
|
-
exit: { opacity: 0, y: -4 },
|
|
6117
|
-
transition: { duration: 0.12 },
|
|
6118
|
-
className: "absolute top-full left-0 z-[10000] mt-1 max-h-[220px] min-w-[130px] overflow-y-auto rounded-xl border border-border bg-popover py-1 shadow-lg",
|
|
6119
|
-
children: MONTHS.map((mn, mi) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6120
|
-
"button",
|
|
6121
|
-
{
|
|
6122
|
-
onClick: () => {
|
|
6123
|
-
setViewMonth(mi);
|
|
6124
|
-
setMonthMenu(false);
|
|
6125
|
-
},
|
|
6126
|
-
className: "w-full px-3 py-2 text-left text-[13px] text-foreground transition-colors hover:bg-muted",
|
|
6127
|
-
style: { fontWeight: mi === viewMonth ? 600 : 400, color: mi === viewMonth ? PRIMARY : void 0 },
|
|
6128
|
-
children: mn
|
|
6129
|
-
},
|
|
6130
|
-
mn
|
|
6131
|
-
))
|
|
6132
|
-
}
|
|
6133
|
-
) })
|
|
6134
|
-
] }),
|
|
6135
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "relative", children: [
|
|
6136
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
6137
|
-
"button",
|
|
6138
|
-
{
|
|
6139
|
-
onClick: () => {
|
|
6140
|
-
setYearMenu((o) => !o);
|
|
6141
|
-
setMonthMenu(false);
|
|
6142
|
-
},
|
|
6143
|
-
className: "flex items-center gap-1 px-2 py-1 rounded-lg text-[14px] font-semibold text-gray-900 hover:bg-gray-100 transition-colors",
|
|
6144
|
-
children: [
|
|
6145
|
-
viewYear,
|
|
6146
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronDown, { className: "w-3 h-3 text-gray-400" })
|
|
6147
|
-
]
|
|
6148
|
-
}
|
|
6149
|
-
),
|
|
6150
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_framer_motion.AnimatePresence, { children: yearMenu && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6151
|
-
import_framer_motion.motion.div,
|
|
6152
|
-
{
|
|
6153
|
-
initial: { opacity: 0, y: -4 },
|
|
6154
|
-
animate: { opacity: 1, y: 0 },
|
|
6155
|
-
exit: { opacity: 0, y: -4 },
|
|
6156
|
-
transition: { duration: 0.12 },
|
|
6157
|
-
className: "absolute top-full left-0 z-[10000] mt-1 max-h-[200px] min-w-[90px] overflow-y-auto rounded-xl border border-border bg-popover py-1 shadow-lg",
|
|
6158
|
-
children: years.map((yr) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6159
|
-
"button",
|
|
6160
|
-
{
|
|
6161
|
-
onClick: () => {
|
|
6162
|
-
setViewYear(yr);
|
|
6163
|
-
setYearMenu(false);
|
|
6164
|
-
},
|
|
6165
|
-
className: "w-full px-3 py-2 text-left text-[13px] text-foreground transition-colors hover:bg-muted",
|
|
6166
|
-
style: { fontWeight: yr === viewYear ? 600 : 400, color: yr === viewYear ? PRIMARY : void 0 },
|
|
6167
|
-
children: yr
|
|
6168
|
-
},
|
|
6169
|
-
yr
|
|
6170
|
-
))
|
|
6171
|
-
}
|
|
6172
|
-
) })
|
|
6173
|
-
] })
|
|
6174
|
-
] }),
|
|
6175
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6176
|
-
"button",
|
|
6177
|
-
{
|
|
6178
|
-
onClick: nextMonth,
|
|
6179
|
-
className: "w-8 h-8 rounded-full flex items-center justify-center text-gray-500 hover:bg-gray-100 transition-colors",
|
|
6180
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronRight, { className: "w-4 h-4" })
|
|
6181
|
-
}
|
|
6182
|
-
)
|
|
6183
|
-
] }),
|
|
6184
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6185
|
-
"div",
|
|
6186
|
-
{
|
|
6187
|
-
className: "px-3 pb-1",
|
|
6188
|
-
style: { display: "grid", gridTemplateColumns: "repeat(7, minmax(0, 1fr))" },
|
|
6189
|
-
children: DAYS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "py-1 text-center text-[11.5px] font-semibold text-muted-foreground", children: d }, d))
|
|
6190
|
-
}
|
|
6191
|
-
),
|
|
6192
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6193
|
-
"div",
|
|
6194
|
-
{
|
|
6195
|
-
className: "gap-y-0.5 px-3 pb-4",
|
|
6196
|
-
style: { display: "grid", gridTemplateColumns: "repeat(7, minmax(0, 1fr))" },
|
|
6197
|
-
children: cells.map((cell, i) => {
|
|
6198
|
-
const selected = isSelected(cell);
|
|
6199
|
-
const tod = isToday(cell);
|
|
6200
|
-
const disabled = cell.current && isDisabled(cell.y, cell.m, cell.d);
|
|
6201
|
-
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
6202
|
-
"button",
|
|
6203
|
-
{
|
|
6204
|
-
onClick: () => selectDay(cell),
|
|
6205
|
-
disabled,
|
|
6206
|
-
className: cn(
|
|
6207
|
-
"h-9 w-9 mx-auto rounded-full text-[13px] font-medium flex items-center justify-center transition-all",
|
|
6208
|
-
selected && "text-white font-semibold",
|
|
6209
|
-
!selected && tod && "font-semibold",
|
|
6210
|
-
!selected && !tod && cell.current && !disabled && "text-gray-800 hover:bg-gray-100",
|
|
6211
|
-
!selected && !cell.current && "text-gray-300 hover:bg-gray-50",
|
|
6212
|
-
disabled && "opacity-30 cursor-not-allowed"
|
|
6213
|
-
),
|
|
6214
|
-
style: selected ? { background: PRIMARY } : tod ? { background: `${PRIMARY}18`, color: PRIMARY } : {},
|
|
6215
|
-
children: cell.d
|
|
6216
|
-
},
|
|
6217
|
-
i
|
|
6218
|
-
);
|
|
6219
|
-
})
|
|
6220
|
-
}
|
|
6221
|
-
)
|
|
6222
|
-
]
|
|
6434
|
+
children: withTime ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_react_remove_scroll.RemoveScroll, { allowPinchZoom: true, children: body }) : body
|
|
6223
6435
|
}
|
|
6224
6436
|
) });
|
|
6225
6437
|
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cn("relative", className), children: [
|
|
@@ -6229,14 +6441,14 @@ function DatePicker({ value, onChange, placeholder = "Select date", className, m
|
|
|
6229
6441
|
{
|
|
6230
6442
|
ref: triggerRef,
|
|
6231
6443
|
type: "button",
|
|
6232
|
-
onClick: () => open ?
|
|
6444
|
+
onClick: () => open ? closePanel() : openPanel(),
|
|
6233
6445
|
className: cn(
|
|
6234
6446
|
"flex h-12 min-h-12 w-full items-center gap-3 rounded-xl border border-border bg-card px-5 text-left text-[15px] shadow-sm transition-colors",
|
|
6235
6447
|
open ? "border-ring ring-2 ring-ring/20" : "hover:border-muted-foreground/45"
|
|
6236
6448
|
),
|
|
6237
6449
|
children: [
|
|
6238
6450
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.CalendarDays, { className: "size-[1.125rem] shrink-0 text-muted-foreground" }),
|
|
6239
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: cn("flex-1", value ? "text-foreground" : "text-muted-foreground"), children: value ?
|
|
6451
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: cn("flex-1", value ? "text-foreground" : "text-muted-foreground"), children: value ? displayValue(value, withTime, showSecond) : placeholder }),
|
|
6240
6452
|
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(import_lucide_react33.ChevronDown, { className: cn("size-[1.125rem] shrink-0 text-muted-foreground transition-transform", open && "rotate-180") })
|
|
6241
6453
|
]
|
|
6242
6454
|
}
|
|
@@ -7789,9 +8001,10 @@ IconButton.displayName = "IconButton";
|
|
|
7789
8001
|
// src/time-picker.tsx
|
|
7790
8002
|
var React48 = __toESM(require("react"), 1);
|
|
7791
8003
|
var import_react_dom2 = require("react-dom");
|
|
8004
|
+
var import_react_remove_scroll2 = require("react-remove-scroll");
|
|
7792
8005
|
var import_lucide_react40 = require("lucide-react");
|
|
7793
8006
|
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
7794
|
-
function
|
|
8007
|
+
function pad2(n) {
|
|
7795
8008
|
return String(n).padStart(2, "0");
|
|
7796
8009
|
}
|
|
7797
8010
|
function parseHHMM(v) {
|
|
@@ -7804,15 +8017,15 @@ function parseHHMM(v) {
|
|
|
7804
8017
|
return { h, m };
|
|
7805
8018
|
}
|
|
7806
8019
|
function toHHMM(h, m) {
|
|
7807
|
-
return `${
|
|
8020
|
+
return `${pad2(h)}:${pad2(m)}`;
|
|
7808
8021
|
}
|
|
7809
|
-
function
|
|
8022
|
+
function displayTime2(value, use24Hour) {
|
|
7810
8023
|
const p = parseHHMM(value);
|
|
7811
8024
|
if (!p) return "";
|
|
7812
|
-
if (use24Hour) return `${
|
|
8025
|
+
if (use24Hour) return `${pad2(p.h)}:${pad2(p.m)}`;
|
|
7813
8026
|
const period = p.h < 12 ? "AM" : "PM";
|
|
7814
8027
|
const displayH = p.h % 12 === 0 ? 12 : p.h % 12;
|
|
7815
|
-
return `${
|
|
8028
|
+
return `${pad2(displayH)}:${pad2(p.m)} ${period}`;
|
|
7816
8029
|
}
|
|
7817
8030
|
var ITEM_H = 36;
|
|
7818
8031
|
var VISIBLE = 5;
|
|
@@ -7916,7 +8129,7 @@ function ScrollColumn({
|
|
|
7916
8129
|
)
|
|
7917
8130
|
] });
|
|
7918
8131
|
}
|
|
7919
|
-
var
|
|
8132
|
+
var PANEL_W = 224;
|
|
7920
8133
|
var PANEL_H = 220;
|
|
7921
8134
|
var TimePicker = React48.forwardRef(
|
|
7922
8135
|
({
|
|
@@ -7970,7 +8183,7 @@ var TimePicker = React48.forwardRef(
|
|
|
7970
8183
|
const vw = window.innerWidth;
|
|
7971
8184
|
const vh = window.innerHeight;
|
|
7972
8185
|
let left = rect.left;
|
|
7973
|
-
if (left +
|
|
8186
|
+
if (left + PANEL_W > vw - 8) left = vw - PANEL_W - 8;
|
|
7974
8187
|
let top = rect.bottom + 6;
|
|
7975
8188
|
if (top + PANEL_H > vh - 8) top = rect.top - PANEL_H - 6;
|
|
7976
8189
|
setPanelPos({ top, left });
|
|
@@ -8013,7 +8226,7 @@ var TimePicker = React48.forwardRef(
|
|
|
8013
8226
|
e.stopPropagation();
|
|
8014
8227
|
onValueChange("");
|
|
8015
8228
|
}
|
|
8016
|
-
const panel = open ? /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
8229
|
+
const panel = open ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_react_remove_scroll2.RemoveScroll, { allowPinchZoom: true, children: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
8017
8230
|
"div",
|
|
8018
8231
|
{
|
|
8019
8232
|
ref: panelRef,
|
|
@@ -8025,13 +8238,17 @@ var TimePicker = React48.forwardRef(
|
|
|
8025
8238
|
position: "fixed",
|
|
8026
8239
|
top: panelPos.top,
|
|
8027
8240
|
left: panelPos.left,
|
|
8028
|
-
width:
|
|
8029
|
-
zIndex: 2e4
|
|
8241
|
+
width: PANEL_W,
|
|
8242
|
+
zIndex: 2e4,
|
|
8243
|
+
// See DatePicker: a modal Radix Dialog puts `pointer-events: none`
|
|
8244
|
+
// on <body>, which this portaled panel would otherwise inherit —
|
|
8245
|
+
// the columns rendered but no row could be clicked.
|
|
8246
|
+
pointerEvents: "auto"
|
|
8030
8247
|
},
|
|
8031
8248
|
children: [
|
|
8032
8249
|
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex items-center gap-1.5 border-b border-border px-4 py-2.5", children: [
|
|
8033
8250
|
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react40.Clock, { className: "size-3.5 text-muted-foreground" }),
|
|
8034
|
-
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "text-[13px] font-medium text-muted-foreground", children: value ?
|
|
8251
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "text-[13px] font-medium text-muted-foreground", children: value ? displayTime2(value, use24Hour) : "\u2014" })
|
|
8035
8252
|
] }),
|
|
8036
8253
|
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
|
|
8037
8254
|
"div",
|
|
@@ -8052,7 +8269,7 @@ var TimePicker = React48.forwardRef(
|
|
|
8052
8269
|
items: hours,
|
|
8053
8270
|
selected: hour,
|
|
8054
8271
|
onSelect: handleHourChange,
|
|
8055
|
-
renderItem: (h) =>
|
|
8272
|
+
renderItem: (h) => pad2(h),
|
|
8056
8273
|
getKey: (h) => h
|
|
8057
8274
|
}
|
|
8058
8275
|
),
|
|
@@ -8063,7 +8280,7 @@ var TimePicker = React48.forwardRef(
|
|
|
8063
8280
|
items: minutes,
|
|
8064
8281
|
selected: minute,
|
|
8065
8282
|
onSelect: handleMinuteChange,
|
|
8066
|
-
renderItem: (m) =>
|
|
8283
|
+
renderItem: (m) => pad2(m),
|
|
8067
8284
|
getKey: (m) => m
|
|
8068
8285
|
}
|
|
8069
8286
|
),
|
|
@@ -8083,7 +8300,7 @@ var TimePicker = React48.forwardRef(
|
|
|
8083
8300
|
] })
|
|
8084
8301
|
]
|
|
8085
8302
|
}
|
|
8086
|
-
) : null;
|
|
8303
|
+
) }) : null;
|
|
8087
8304
|
function mergeRef(el) {
|
|
8088
8305
|
triggerRef.current = el;
|
|
8089
8306
|
if (typeof ref === "function") ref(el);
|
|
@@ -8115,7 +8332,7 @@ var TimePicker = React48.forwardRef(
|
|
|
8115
8332
|
"flex-1 truncate",
|
|
8116
8333
|
value ? "text-foreground" : "text-muted-foreground"
|
|
8117
8334
|
),
|
|
8118
|
-
children: value ?
|
|
8335
|
+
children: value ? displayTime2(value, use24Hour) : placeholder
|
|
8119
8336
|
}
|
|
8120
8337
|
),
|
|
8121
8338
|
value && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|