@pos-360/horizon 0.22.1 → 0.23.0

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.
@@ -16,6 +16,7 @@ var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
16
16
  var TabsPrimitive = require('@radix-ui/react-tabs');
17
17
  var ToggleGroupPrimitive = require('@radix-ui/react-toggle-group');
18
18
  var SwitchPrimitive = require('@radix-ui/react-switch');
19
+ var dateFns = require('date-fns');
19
20
 
20
21
  function _interopNamespace(e) {
21
22
  if (e && e.__esModule) return e;
@@ -2096,6 +2097,296 @@ var Switch = React10__namespace.forwardRef(({ className, size, label, labelPosit
2096
2097
  );
2097
2098
  });
2098
2099
  Switch.displayName = "Switch";
2100
+ var WEEKDAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
2101
+ function getCalendarDays(month) {
2102
+ const start = dateFns.startOfWeek(dateFns.startOfMonth(month), { weekStartsOn: 0 });
2103
+ const end = dateFns.endOfWeek(dateFns.endOfMonth(month), { weekStartsOn: 0 });
2104
+ return dateFns.eachDayOfInterval({ start, end });
2105
+ }
2106
+ function CalendarMonth({
2107
+ month,
2108
+ range,
2109
+ hoverDate,
2110
+ onDayClick,
2111
+ onDayHover,
2112
+ onPrevMonth,
2113
+ onNextMonth,
2114
+ showPrevNav = true,
2115
+ showNextNav = true
2116
+ }) {
2117
+ const days = getCalendarDays(month);
2118
+ const today = /* @__PURE__ */ new Date();
2119
+ const getEffectiveTo = () => range.to ?? hoverDate;
2120
+ const isInRange = (date) => {
2121
+ const { from } = range;
2122
+ const effectiveTo = getEffectiveTo();
2123
+ if (!from || !effectiveTo) return false;
2124
+ const [start, end] = dateFns.isBefore(from, effectiveTo) ? [from, effectiveTo] : [effectiveTo, from];
2125
+ return dateFns.isWithinInterval(date, { start, end });
2126
+ };
2127
+ const isRangeStart = (date) => {
2128
+ const { from } = range;
2129
+ const effectiveTo = getEffectiveTo();
2130
+ if (!from) return false;
2131
+ if (!effectiveTo) return dateFns.isSameDay(date, from);
2132
+ return dateFns.isBefore(from, effectiveTo) ? dateFns.isSameDay(date, from) : dateFns.isSameDay(date, effectiveTo);
2133
+ };
2134
+ const isRangeEnd = (date) => {
2135
+ const { from } = range;
2136
+ const effectiveTo = getEffectiveTo();
2137
+ if (!from || !effectiveTo) return false;
2138
+ return dateFns.isBefore(from, effectiveTo) ? dateFns.isSameDay(date, effectiveTo) : dateFns.isSameDay(date, from);
2139
+ };
2140
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[252px]", children: [
2141
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
2142
+ /* @__PURE__ */ jsxRuntime.jsx(
2143
+ "button",
2144
+ {
2145
+ onClick: onPrevMonth,
2146
+ className: chunk5XF7Y25B_js.cn(
2147
+ "p-1 rounded-md transition-colors",
2148
+ showPrevNav ? "hover:bg-gray-100 dark:hover:bg-neutral-700 text-gray-500 dark:text-gray-400" : "invisible pointer-events-none"
2149
+ ),
2150
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "w-4 h-4" })
2151
+ }
2152
+ ),
2153
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: dateFns.format(month, "MMMM yyyy") }),
2154
+ /* @__PURE__ */ jsxRuntime.jsx(
2155
+ "button",
2156
+ {
2157
+ onClick: onNextMonth,
2158
+ className: chunk5XF7Y25B_js.cn(
2159
+ "p-1 rounded-md transition-colors",
2160
+ showNextNav ? "hover:bg-gray-100 dark:hover:bg-neutral-700 text-gray-500 dark:text-gray-400" : "invisible pointer-events-none"
2161
+ ),
2162
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-4 h-4" })
2163
+ }
2164
+ )
2165
+ ] }),
2166
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 mb-1", children: WEEKDAYS.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
2167
+ "div",
2168
+ {
2169
+ className: "text-center text-xs font-medium text-gray-400 dark:text-gray-500 py-1",
2170
+ children: day
2171
+ },
2172
+ day
2173
+ )) }),
2174
+ /* @__PURE__ */ jsxRuntime.jsx(
2175
+ "div",
2176
+ {
2177
+ className: "grid grid-cols-7",
2178
+ onMouseLeave: () => onDayHover(void 0),
2179
+ children: days.map((day, idx) => {
2180
+ const outside = !dateFns.isSameMonth(day, month);
2181
+ const inRange = !outside && isInRange(day);
2182
+ const rangeStart = !outside && isRangeStart(day);
2183
+ const rangeEnd = !outside && isRangeEnd(day);
2184
+ const isToday = dateFns.isSameDay(day, today);
2185
+ return /* @__PURE__ */ jsxRuntime.jsx(
2186
+ "div",
2187
+ {
2188
+ className: chunk5XF7Y25B_js.cn(
2189
+ "h-9 flex items-center justify-center",
2190
+ (inRange || rangeStart || rangeEnd) && "bg-blue-50 dark:bg-blue-950/40",
2191
+ rangeStart && !rangeEnd && "rounded-l-full",
2192
+ rangeEnd && !rangeStart && "rounded-r-full",
2193
+ rangeStart && rangeEnd && "rounded-full"
2194
+ ),
2195
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2196
+ "button",
2197
+ {
2198
+ onClick: () => !outside && onDayClick(day),
2199
+ onMouseEnter: () => !outside && onDayHover(day),
2200
+ tabIndex: outside ? -1 : 0,
2201
+ className: chunk5XF7Y25B_js.cn(
2202
+ "w-8 h-8 rounded-full text-sm flex items-center justify-center transition-colors",
2203
+ outside && "text-gray-300 dark:text-gray-600 pointer-events-none",
2204
+ !outside && !rangeStart && !rangeEnd && "text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-neutral-700",
2205
+ !outside && inRange && !rangeStart && !rangeEnd && "text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/50",
2206
+ (rangeStart || rangeEnd) && "bg-blue-600 text-white hover:bg-blue-700 dark:hover:bg-blue-500",
2207
+ isToday && !rangeStart && !rangeEnd && !outside && "font-bold"
2208
+ ),
2209
+ children: dateFns.format(day, "d")
2210
+ }
2211
+ )
2212
+ },
2213
+ idx
2214
+ );
2215
+ })
2216
+ }
2217
+ )
2218
+ ] });
2219
+ }
2220
+ var DEFAULT_PRESETS = [
2221
+ {
2222
+ label: "Today",
2223
+ getRange: () => ({
2224
+ from: dateFns.startOfDay(/* @__PURE__ */ new Date()),
2225
+ to: dateFns.endOfDay(/* @__PURE__ */ new Date())
2226
+ })
2227
+ },
2228
+ {
2229
+ label: "Yesterday",
2230
+ getRange: () => {
2231
+ const d = dateFns.subDays(/* @__PURE__ */ new Date(), 1);
2232
+ return { from: dateFns.startOfDay(d), to: dateFns.endOfDay(d) };
2233
+ }
2234
+ },
2235
+ {
2236
+ label: "This Week",
2237
+ getRange: () => ({
2238
+ from: dateFns.startOfWeek(/* @__PURE__ */ new Date(), { weekStartsOn: 0 }),
2239
+ to: dateFns.endOfWeek(/* @__PURE__ */ new Date(), { weekStartsOn: 0 })
2240
+ })
2241
+ },
2242
+ {
2243
+ label: "Last Week",
2244
+ getRange: () => {
2245
+ const d = dateFns.subDays(/* @__PURE__ */ new Date(), 7);
2246
+ return {
2247
+ from: dateFns.startOfWeek(d, { weekStartsOn: 0 }),
2248
+ to: dateFns.endOfWeek(d, { weekStartsOn: 0 })
2249
+ };
2250
+ }
2251
+ },
2252
+ {
2253
+ label: "This Month",
2254
+ getRange: () => ({
2255
+ from: dateFns.startOfMonth(/* @__PURE__ */ new Date()),
2256
+ to: dateFns.endOfMonth(/* @__PURE__ */ new Date())
2257
+ })
2258
+ },
2259
+ {
2260
+ label: "Last Month",
2261
+ getRange: () => {
2262
+ const d = dateFns.subMonths(/* @__PURE__ */ new Date(), 1);
2263
+ return { from: dateFns.startOfMonth(d), to: dateFns.endOfMonth(d) };
2264
+ }
2265
+ }
2266
+ ];
2267
+ function formatDateRange(range, placeholder) {
2268
+ if (!range?.from) return placeholder;
2269
+ if (!range.to || dateFns.isSameDay(range.from, range.to)) {
2270
+ return dateFns.format(range.from, "MMM d, yyyy");
2271
+ }
2272
+ const sameYear = range.from.getFullYear() === range.to.getFullYear();
2273
+ if (sameYear) {
2274
+ return `${dateFns.format(range.from, "MMM d")} \u2013 ${dateFns.format(range.to, "MMM d, yyyy")}`;
2275
+ }
2276
+ return `${dateFns.format(range.from, "MMM d, yyyy")} \u2013 ${dateFns.format(range.to, "MMM d, yyyy")}`;
2277
+ }
2278
+ function DateRangePicker({
2279
+ value,
2280
+ onChange,
2281
+ presets = DEFAULT_PRESETS,
2282
+ placeholder = "Select date range",
2283
+ disabled = false,
2284
+ align = "start",
2285
+ className
2286
+ }) {
2287
+ const [open, setOpen] = React10__namespace.useState(false);
2288
+ const [internalRange, setInternalRange] = React10__namespace.useState({
2289
+ from: void 0,
2290
+ to: void 0
2291
+ });
2292
+ const [hoverDate, setHoverDate] = React10__namespace.useState();
2293
+ const [leftMonth, setLeftMonth] = React10__namespace.useState(
2294
+ () => dateFns.startOfMonth(value?.from ?? /* @__PURE__ */ new Date())
2295
+ );
2296
+ const [activePreset, setActivePreset] = React10__namespace.useState();
2297
+ const range = value ?? internalRange;
2298
+ const handleDayClick = (date) => {
2299
+ const { from, to } = range;
2300
+ if (!from || from && to) {
2301
+ const newRange2 = { from: date, to: void 0 };
2302
+ setActivePreset(void 0);
2303
+ if (onChange) onChange(newRange2);
2304
+ else setInternalRange(newRange2);
2305
+ return;
2306
+ }
2307
+ const [start, end] = dateFns.isBefore(from, date) ? [from, date] : [date, from];
2308
+ const newRange = { from: start, to: end };
2309
+ if (onChange) onChange(newRange);
2310
+ else setInternalRange(newRange);
2311
+ setHoverDate(void 0);
2312
+ setOpen(false);
2313
+ };
2314
+ const handlePreset = (preset) => {
2315
+ const newRange = preset.getRange();
2316
+ if (onChange) onChange(newRange);
2317
+ else setInternalRange(newRange);
2318
+ setActivePreset(preset.label);
2319
+ if (newRange.from) setLeftMonth(dateFns.startOfMonth(newRange.from));
2320
+ setOpen(false);
2321
+ };
2322
+ const rightMonth = dateFns.addMonths(leftMonth, 1);
2323
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
2324
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
2325
+ "button",
2326
+ {
2327
+ disabled,
2328
+ className: chunk5XF7Y25B_js.cn(
2329
+ "inline-flex items-center gap-2 rounded-md border border-gray-300 bg-white px-3 py-2 text-sm shadow-sm transition-colors",
2330
+ "hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2",
2331
+ "dark:border-neutral-600 dark:bg-neutral-800 dark:hover:bg-neutral-700",
2332
+ "disabled:pointer-events-none disabled:opacity-50",
2333
+ range.from ? "text-gray-900 dark:text-gray-100" : "text-gray-400 dark:text-gray-500",
2334
+ className
2335
+ ),
2336
+ children: [
2337
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CalendarIcon, { className: "w-4 h-4 shrink-0 text-gray-400 dark:text-gray-500" }),
2338
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatDateRange(range, placeholder) })
2339
+ ]
2340
+ }
2341
+ ) }),
2342
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align, className: "w-auto p-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex divide-x divide-gray-100 dark:divide-neutral-700", children: [
2343
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col p-3 gap-0.5 min-w-[130px]", children: [
2344
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-gray-400 dark:text-gray-500 uppercase tracking-wider mb-2 px-2", children: "Presets" }),
2345
+ presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
2346
+ "button",
2347
+ {
2348
+ onClick: () => handlePreset(preset),
2349
+ className: chunk5XF7Y25B_js.cn(
2350
+ "w-full text-left px-2 py-1.5 rounded-md text-sm transition-colors",
2351
+ activePreset === preset.label ? "bg-blue-50 text-blue-600 font-medium dark:bg-blue-950/50 dark:text-blue-400" : "text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-neutral-700"
2352
+ ),
2353
+ children: preset.label
2354
+ },
2355
+ preset.label
2356
+ ))
2357
+ ] }),
2358
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 p-4", children: [
2359
+ /* @__PURE__ */ jsxRuntime.jsx(
2360
+ CalendarMonth,
2361
+ {
2362
+ month: leftMonth,
2363
+ range,
2364
+ hoverDate,
2365
+ onDayClick: handleDayClick,
2366
+ onDayHover: setHoverDate,
2367
+ onPrevMonth: () => setLeftMonth(dateFns.subMonths(leftMonth, 1)),
2368
+ showPrevNav: true,
2369
+ showNextNav: false
2370
+ }
2371
+ ),
2372
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px bg-gray-100 dark:bg-neutral-700 self-stretch" }),
2373
+ /* @__PURE__ */ jsxRuntime.jsx(
2374
+ CalendarMonth,
2375
+ {
2376
+ month: rightMonth,
2377
+ range,
2378
+ hoverDate,
2379
+ onDayClick: handleDayClick,
2380
+ onDayHover: setHoverDate,
2381
+ onNextMonth: () => setLeftMonth(dateFns.addMonths(leftMonth, 1)),
2382
+ showPrevNav: false,
2383
+ showNextNav: true
2384
+ }
2385
+ )
2386
+ ] })
2387
+ ] }) })
2388
+ ] });
2389
+ }
2099
2390
 
2100
2391
  exports.Button = Button;
2101
2392
  exports.Card = Card;
@@ -2106,6 +2397,8 @@ exports.CardHeader = CardHeader;
2106
2397
  exports.CardTitle = CardTitle;
2107
2398
  exports.Checkbox = Checkbox;
2108
2399
  exports.ColumnSelection = ColumnSelection;
2400
+ exports.DEFAULT_PRESETS = DEFAULT_PRESETS;
2401
+ exports.DateRangePicker = DateRangePicker;
2109
2402
  exports.Dialog = Dialog;
2110
2403
  exports.DialogClose = DialogClose;
2111
2404
  exports.DialogContent = DialogContent;
@@ -2195,5 +2488,5 @@ exports.useColumnVisibility = useColumnVisibility;
2195
2488
  exports.useFormContext = useFormContext;
2196
2489
  exports.useFormFieldContext = useFormFieldContext;
2197
2490
  exports.useTableSelection = useTableSelection;
2198
- //# sourceMappingURL=chunk-CY7BVG4S.js.map
2199
- //# sourceMappingURL=chunk-CY7BVG4S.js.map
2491
+ //# sourceMappingURL=chunk-J2AWNOYH.js.map
2492
+ //# sourceMappingURL=chunk-J2AWNOYH.js.map