@eintrek/erp-theme 1.4.9 → 1.4.10

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.js CHANGED
@@ -258,133 +258,192 @@ function BreadcrumbSeparator({ children, className, ...props }) {
258
258
  return (require$$1.jsx("li", { "data-slot": "breadcrumb-separator", role: "presentation", "aria-hidden": "true", className: cn$1("[&>svg]:size-3.5", className), ...props, children: children ?? require$$1.jsx(lucideReact.ChevronRight, {}) }));
259
259
  }
260
260
 
261
- function Calendar({ className, selected, onSelect, mode = "single", disabled, }) {
262
- const [currentMonth, setCurrentMonth] = React__namespace.useState(new Date());
263
- const today = new Date();
264
- const year = currentMonth.getFullYear();
265
- const month = currentMonth.getMonth();
266
- const firstDayOfMonth = new Date(year, month, 1);
267
- const lastDayOfMonth = new Date(year, month + 1, 0);
268
- const firstDayOfWeek = firstDayOfMonth.getDay();
269
- const daysInMonth = lastDayOfMonth.getDate();
270
- const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
271
- const getDaysInMonth = () => {
272
- const days = [];
273
- // Add empty cells for days before the first day of the month
274
- for (let i = 0; i < firstDayOfWeek; i++) {
275
- days.push(null);
276
- }
277
- // Add days of the month
278
- for (let day = 1; day <= daysInMonth; day++) {
279
- days.push(new Date(year, month, day));
280
- }
281
- return days;
282
- };
283
- const isSelected = (date) => {
284
- if (!selected)
285
- return false;
286
- if (mode === "single" && selected instanceof Date) {
287
- return date.toDateString() === selected.toDateString();
288
- }
289
- if (mode === "range" && selected && typeof selected === "object" && "from" in selected) {
290
- const range = selected;
291
- if (range.from && range.to) {
292
- return date >= range.from && date <= range.to;
293
- }
294
- if (range.from) {
295
- return date.toDateString() === range.from.toDateString();
296
- }
297
- }
298
- if (mode === "multiple" && Array.isArray(selected)) {
299
- return selected.some(d => d.toDateString() === date.toDateString());
300
- }
301
- return false;
302
- };
303
- const isToday = (date) => {
304
- return date.toDateString() === today.toDateString();
305
- };
306
- const isDisabled = (date) => {
307
- if (disabled)
308
- return disabled(date);
309
- return false;
310
- };
311
- const handleDateClick = (date) => {
312
- if (isDisabled(date))
313
- return;
314
- if (mode === "single") {
315
- onSelect?.(date);
316
- }
317
- else if (mode === "range") {
318
- // Simple range selection - click to set start, click again to set end
319
- if (!selected || typeof selected !== "object" || !("from" in selected)) {
320
- onSelect?.({ from: date, to: undefined });
321
- }
322
- else {
323
- const range = selected;
324
- if (!range.from) {
325
- onSelect?.({ from: date, to: undefined });
326
- }
327
- else if (!range.to) {
328
- if (date >= range.from) {
329
- onSelect?.({ from: range.from, to: date });
330
- }
331
- else {
332
- onSelect?.({ from: date, to: range.from });
333
- }
334
- }
335
- else {
336
- onSelect?.({ from: date, to: undefined });
337
- }
338
- }
339
- }
340
- else if (mode === "multiple") {
341
- const currentSelection = Array.isArray(selected) ? selected : [];
342
- const isAlreadySelected = currentSelection.some(d => d.toDateString() === date.toDateString());
343
- if (isAlreadySelected) {
344
- onSelect?.(currentSelection.filter(d => d.toDateString() !== date.toDateString()));
345
- }
346
- else {
347
- onSelect?.([...currentSelection, date]);
348
- }
349
- }
350
- };
351
- const navigateMonth = (direction) => {
352
- setCurrentMonth(prev => {
353
- const newMonth = new Date(prev);
354
- if (direction === "prev") {
355
- newMonth.setMonth(prev.getMonth() - 1);
356
- }
357
- else {
358
- newMonth.setMonth(prev.getMonth() + 1);
359
- }
360
- return newMonth;
361
- });
362
- };
363
- const days = getDaysInMonth();
364
- return (require$$1.jsxs("div", { "data-slot": "calendar", className: cn$1("bg-background group/calendar p-3 w-fit", className), children: [require$$1.jsxs("div", { className: "flex items-center justify-between mb-4", children: [require$$1.jsx(Button, { variant: "ghost", size: "icon", onClick: () => navigateMonth("prev"), className: "h-8 w-8 p-0", children: require$$1.jsx(lucideReact.ChevronLeftIcon, { className: "h-4 w-4" }) }), require$$1.jsx("div", { className: "text-sm font-medium", children: currentMonth.toLocaleDateString("default", { month: "long", year: "numeric" }) }), require$$1.jsx(Button, { variant: "ghost", size: "icon", onClick: () => navigateMonth("next"), className: "h-8 w-8 p-0", children: require$$1.jsx(lucideReact.ChevronRightIcon, { className: "h-4 w-4" }) })] }), require$$1.jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: weekDays.map((day) => (require$$1.jsx("div", { className: "text-muted-foreground text-xs font-normal text-center h-8 flex items-center justify-center", children: day }, day))) }), require$$1.jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((date, index) => {
365
- if (!date) {
366
- return require$$1.jsx("div", { className: "h-8" }, index);
367
- }
368
- const isDateSelected = isSelected(date);
369
- const isDateToday = isToday(date);
370
- const isDateDisabled = isDisabled(date);
371
- return (require$$1.jsx(Button, { variant: "ghost", size: "icon", className: cn$1("h-8 w-8 p-0 text-sm font-normal", isDateSelected && "bg-primary text-primary-foreground", isDateToday && !isDateSelected && "bg-accent text-accent-foreground", isDateDisabled && "opacity-50 cursor-not-allowed", "hover:bg-accent hover:text-accent-foreground"), onClick: () => handleDateClick(date), disabled: isDateDisabled, children: date.getDate() }, date.toISOString()));
372
- }) })] }));
261
+ /**
262
+ * @module constants
263
+ * @summary Useful constants
264
+ * @description
265
+ * Collection of useful date constants.
266
+ *
267
+ * The constants could be imported from `date-fns/constants`:
268
+ *
269
+ * ```ts
270
+ * import { maxTime, minTime } from "./constants/date-fns/constants";
271
+ *
272
+ * function isAllowedTime(time) {
273
+ * return time <= maxTime && time >= minTime;
274
+ * }
275
+ * ```
276
+ */
277
+
278
+
279
+ /**
280
+ * @constant
281
+ * @name constructFromSymbol
282
+ * @summary Symbol enabling Date extensions to inherit properties from the reference date.
283
+ *
284
+ * The symbol is used to enable the `constructFrom` function to construct a date
285
+ * using a reference date and a value. It allows to transfer extra properties
286
+ * from the reference date to the new date. It's useful for extensions like
287
+ * [`TZDate`](https://github.com/date-fns/tz) that accept a time zone as
288
+ * a constructor argument.
289
+ */
290
+ const constructFromSymbol = Symbol.for("constructDateFrom");
291
+
292
+ /**
293
+ * @name constructFrom
294
+ * @category Generic Helpers
295
+ * @summary Constructs a date using the reference date and the value
296
+ *
297
+ * @description
298
+ * The function constructs a new date using the constructor from the reference
299
+ * date and the given value. It helps to build generic functions that accept
300
+ * date extensions.
301
+ *
302
+ * It defaults to `Date` if the passed reference date is a number or a string.
303
+ *
304
+ * Starting from v3.7.0, it allows to construct a date using `[Symbol.for("constructDateFrom")]`
305
+ * enabling to transfer extra properties from the reference date to the new date.
306
+ * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
307
+ * that accept a time zone as a constructor argument.
308
+ *
309
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
310
+ *
311
+ * @param date - The reference date to take constructor from
312
+ * @param value - The value to create the date
313
+ *
314
+ * @returns Date initialized using the given date and value
315
+ *
316
+ * @example
317
+ * import { constructFrom } from "./constructFrom/date-fns";
318
+ *
319
+ * // A function that clones a date preserving the original type
320
+ * function cloneDate<DateType extends Date>(date: DateType): DateType {
321
+ * return constructFrom(
322
+ * date, // Use constructor from the given date
323
+ * date.getTime() // Use the date value to create a new date
324
+ * );
325
+ * }
326
+ */
327
+ function constructFrom(date, value) {
328
+ if (typeof date === "function") return date(value);
329
+
330
+ if (date && typeof date === "object" && constructFromSymbol in date)
331
+ return date[constructFromSymbol](value);
332
+
333
+ if (date instanceof Date) return new date.constructor(value);
334
+
335
+ return new Date(value);
373
336
  }
374
- function DateInput({ value, onChange, placeholder = "Select date", className, disabled = false }) {
375
- const handleChange = (event) => {
376
- const dateValue = event.target.value;
377
- if (dateValue) {
378
- onChange?.(new Date(dateValue));
379
- }
380
- else {
381
- onChange?.(undefined);
382
- }
383
- };
384
- const formatDateForInput = (date) => {
385
- return date.toISOString().split('T')[0];
386
- };
387
- return (require$$1.jsx("input", { type: "date", value: value ? formatDateForInput(value) : "", onChange: handleChange, placeholder: placeholder, disabled: disabled, className: cn$1("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className) }));
337
+
338
+ /**
339
+ * @name toDate
340
+ * @category Common Helpers
341
+ * @summary Convert the given argument to an instance of Date.
342
+ *
343
+ * @description
344
+ * Convert the given argument to an instance of Date.
345
+ *
346
+ * If the argument is an instance of Date, the function returns its clone.
347
+ *
348
+ * If the argument is a number, it is treated as a timestamp.
349
+ *
350
+ * If the argument is none of the above, the function returns Invalid Date.
351
+ *
352
+ * Starting from v3.7.0, it clones a date using `[Symbol.for("constructDateFrom")]`
353
+ * enabling to transfer extra properties from the reference date to the new date.
354
+ * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
355
+ * that accept a time zone as a constructor argument.
356
+ *
357
+ * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
358
+ *
359
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
360
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
361
+ *
362
+ * @param argument - The value to convert
363
+ *
364
+ * @returns The parsed date in the local time zone
365
+ *
366
+ * @example
367
+ * // Clone the date:
368
+ * const result = toDate(new Date(2014, 1, 11, 11, 30, 30))
369
+ * //=> Tue Feb 11 2014 11:30:30
370
+ *
371
+ * @example
372
+ * // Convert the timestamp to date:
373
+ * const result = toDate(1392098430000)
374
+ * //=> Tue Feb 11 2014 11:30:30
375
+ */
376
+ function toDate(argument, context) {
377
+ // [TODO] Get rid of `toDate` or `constructFrom`?
378
+ return constructFrom(argument, argument);
379
+ }
380
+
381
+ /**
382
+ * The {@link endOfMonth} function options.
383
+ */
384
+
385
+ /**
386
+ * @name endOfMonth
387
+ * @category Month Helpers
388
+ * @summary Return the end of a month for the given date.
389
+ *
390
+ * @description
391
+ * Return the end of a month for the given date.
392
+ * The result will be in the local timezone.
393
+ *
394
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
395
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
396
+ *
397
+ * @param date - The original date
398
+ * @param options - An object with options
399
+ *
400
+ * @returns The end of a month
401
+ *
402
+ * @example
403
+ * // The end of a month for 2 September 2014 11:55:00:
404
+ * const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))
405
+ * //=> Tue Sep 30 2014 23:59:59.999
406
+ */
407
+ function endOfMonth(date, options) {
408
+ const _date = toDate(date);
409
+ const month = _date.getMonth();
410
+ _date.setFullYear(_date.getFullYear(), month + 1, 0);
411
+ _date.setHours(23, 59, 59, 999);
412
+ return _date;
413
+ }
414
+
415
+ /**
416
+ * The {@link startOfMonth} function options.
417
+ */
418
+
419
+ /**
420
+ * @name startOfMonth
421
+ * @category Month Helpers
422
+ * @summary Return the start of a month for the given date.
423
+ *
424
+ * @description
425
+ * Return the start of a month for the given date. The result will be in the local timezone.
426
+ *
427
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.
428
+ * Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
429
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed,
430
+ * or inferred from the arguments.
431
+ *
432
+ * @param date - The original date
433
+ * @param options - An object with options
434
+ *
435
+ * @returns The start of a month
436
+ *
437
+ * @example
438
+ * // The start of a month for 2 September 2014 11:55:00:
439
+ * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))
440
+ * //=> Mon Sep 01 2014 00:00:00
441
+ */
442
+ function startOfMonth(date, options) {
443
+ const _date = toDate(date);
444
+ _date.setDate(1);
445
+ _date.setHours(0, 0, 0, 0);
446
+ return _date;
388
447
  }
389
448
 
390
449
  function buildFormatLongFn(args) {
@@ -539,123 +598,241 @@ function buildMatchPatternFn(args) {
539
598
  }
540
599
 
541
600
  /**
542
- * @module constants
543
- * @summary Useful constants
544
- * @description
545
- * Collection of useful date constants.
546
- *
547
- * The constants could be imported from `date-fns/constants`:
548
- *
549
- * ```ts
550
- * import { maxTime, minTime } from "./constants/date-fns/constants";
551
- *
552
- * function isAllowedTime(time) {
553
- * return time <= maxTime && time >= minTime;
554
- * }
555
- * ```
601
+ * Thai month names in Buddhist calendar
556
602
  */
557
-
558
-
603
+ const THAI_MONTH_NAMES = [
604
+ "มกราคม",
605
+ "กุมภาพันธ์",
606
+ "มีนาคม",
607
+ "เมษายน",
608
+ "พฤษภาคม",
609
+ "มิถุนายน",
610
+ "กรกฎาคม",
611
+ "สิงหาคม",
612
+ "กันยายน",
613
+ "ตุลาคม",
614
+ "พฤศจิกายน",
615
+ "ธันวาคม",
616
+ ];
559
617
  /**
560
- * @constant
561
- * @name constructFromSymbol
562
- * @summary Symbol enabling Date extensions to inherit properties from the reference date.
618
+ * Convert Gregorian year to Buddhist year
619
+ * Buddhist calendar is 543 years ahead of Gregorian calendar
563
620
  *
564
- * The symbol is used to enable the `constructFrom` function to construct a date
565
- * using a reference date and a value. It allows to transfer extra properties
566
- * from the reference date to the new date. It's useful for extensions like
567
- * [`TZDate`](https://github.com/date-fns/tz) that accept a time zone as
568
- * a constructor argument.
621
+ * @param gregorianYear - The Gregorian year (e.g., 2024)
622
+ * @returns The Buddhist year (e.g., 2567)
623
+ *
624
+ * @example
625
+ * toBuddhistYear(2024); // returns 2567
569
626
  */
570
- const constructFromSymbol = Symbol.for("constructDateFrom");
571
-
627
+ function toBuddhistYear(gregorianYear) {
628
+ return gregorianYear + 543;
629
+ }
572
630
  /**
573
- * @name constructFrom
574
- * @category Generic Helpers
575
- * @summary Constructs a date using the reference date and the value
576
- *
577
- * @description
578
- * The function constructs a new date using the constructor from the reference
579
- * date and the given value. It helps to build generic functions that accept
580
- * date extensions.
581
- *
582
- * It defaults to `Date` if the passed reference date is a number or a string.
583
- *
584
- * Starting from v3.7.0, it allows to construct a date using `[Symbol.for("constructDateFrom")]`
585
- * enabling to transfer extra properties from the reference date to the new date.
586
- * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
587
- * that accept a time zone as a constructor argument.
588
- *
589
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
590
- *
591
- * @param date - The reference date to take constructor from
592
- * @param value - The value to create the date
631
+ * Convert Buddhist year to Gregorian year
593
632
  *
594
- * @returns Date initialized using the given date and value
633
+ * @param buddhistYear - The Buddhist year (e.g., 2567)
634
+ * @returns The Gregorian year (e.g., 2024)
595
635
  *
596
636
  * @example
597
- * import { constructFrom } from "./constructFrom/date-fns";
598
- *
599
- * // A function that clones a date preserving the original type
600
- * function cloneDate<DateType extends Date>(date: DateType): DateType {
601
- * return constructFrom(
602
- * date, // Use constructor from the given date
603
- * date.getTime() // Use the date value to create a new date
604
- * );
605
- * }
637
+ * toGregorianYear(2567); // returns 2024
606
638
  */
607
- function constructFrom(date, value) {
608
- if (typeof date === "function") return date(value);
609
-
610
- if (date && typeof date === "object" && constructFromSymbol in date)
611
- return date[constructFromSymbol](value);
612
-
613
- if (date instanceof Date) return new date.constructor(value);
614
-
615
- return new Date(value);
639
+ function toGregorianYear(buddhistYear) {
640
+ return buddhistYear - 543;
616
641
  }
617
-
618
642
  /**
619
- * @name toDate
620
- * @category Common Helpers
621
- * @summary Convert the given argument to an instance of Date.
622
- *
623
- * @description
624
- * Convert the given argument to an instance of Date.
625
- *
626
- * If the argument is an instance of Date, the function returns its clone.
627
- *
628
- * If the argument is a number, it is treated as a timestamp.
629
- *
630
- * If the argument is none of the above, the function returns Invalid Date.
643
+ * Get the first and last day of a month
631
644
  *
632
- * Starting from v3.7.0, it clones a date using `[Symbol.for("constructDateFrom")]`
633
- * enabling to transfer extra properties from the reference date to the new date.
634
- * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
635
- * that accept a time zone as a constructor argument.
645
+ * @param date - The date within the month
646
+ * @returns Object with start and end dates of the month
636
647
  *
637
- * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
648
+ * @example
649
+ * getMonthDateRange(new Date('2024-06-15'));
650
+ * // returns { start: Date('2024-06-01'), end: Date('2024-06-30') }
651
+ */
652
+ function getMonthDateRange(date) {
653
+ const start = startOfMonth(date);
654
+ const end = endOfMonth(date);
655
+ return { start, end };
656
+ }
657
+ /**
658
+ * Format a date to Thai Buddhist calendar month display
638
659
  *
639
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
640
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
660
+ * @param date - The date to format
661
+ * @returns Formatted string in Thai Buddhist calendar (e.g., "มกราคม 2568")
641
662
  *
642
- * @param argument - The value to convert
663
+ * @example
664
+ * formatThaiMonth(new Date('2024-01-15')); // returns "มกราคม 2567"
665
+ * formatThaiMonth(new Date('2024-12-25')); // returns "ธันวาคม 2567"
666
+ */
667
+ function formatThaiMonth(date) {
668
+ const monthIndex = date.getMonth();
669
+ const gregorianYear = date.getFullYear();
670
+ const buddhistYear = toBuddhistYear(gregorianYear);
671
+ return `${THAI_MONTH_NAMES[monthIndex]} ${buddhistYear}`;
672
+ }
673
+ /**
674
+ * Format a date to short Thai Buddhist calendar format
643
675
  *
644
- * @returns The parsed date in the local time zone
676
+ * @param date - The date to format
677
+ * @returns Formatted string (e.g., "01/2568")
645
678
  *
646
679
  * @example
647
- * // Clone the date:
648
- * const result = toDate(new Date(2014, 1, 11, 11, 30, 30))
649
- * //=> Tue Feb 11 2014 11:30:30
680
+ * formatThaiMonthShort(new Date('2024-01-15')); // returns "01/2567"
681
+ */
682
+ function formatThaiMonthShort(date) {
683
+ const month = String(date.getMonth() + 1).padStart(2, "0");
684
+ const gregorianYear = date.getFullYear();
685
+ const buddhistYear = toBuddhistYear(gregorianYear);
686
+ return `${month}/${buddhistYear}`;
687
+ }
688
+ /**
689
+ * Get Thai month name by index (0-11)
690
+ *
691
+ * @param monthIndex - Month index (0 = January, 11 = December)
692
+ * @returns Thai month name
650
693
  *
651
694
  * @example
652
- * // Convert the timestamp to date:
653
- * const result = toDate(1392098430000)
654
- * //=> Tue Feb 11 2014 11:30:30
695
+ * getThaiMonthName(0); // returns "มกราคม"
696
+ * getThaiMonthName(11); // returns "ธันวาคม"
655
697
  */
656
- function toDate(argument, context) {
657
- // [TODO] Get rid of `toDate` or `constructFrom`?
658
- return constructFrom(argument, argument);
698
+ function getThaiMonthName(monthIndex) {
699
+ if (monthIndex < 0 || monthIndex > 11) {
700
+ throw new Error("Month index must be between 0 and 11");
701
+ }
702
+ return THAI_MONTH_NAMES[monthIndex];
703
+ }
704
+
705
+ /** Thai weekday abbreviations (Sunday-first, matching JS getDay()). */
706
+ const WEEK_DAYS_TH = ["อา.", "จ.", "อ.", "พ.", "พฤ.", "ศ.", "ส."];
707
+ function formatMonthCaption(date) {
708
+ return `${THAI_MONTH_NAMES[date.getMonth()]} ${toBuddhistYear(date.getFullYear())}`;
709
+ }
710
+ function Calendar({ className, selected, onSelect, mode = "single", disabled, }) {
711
+ const [currentMonth, setCurrentMonth] = React__namespace.useState(new Date());
712
+ const today = new Date();
713
+ const year = currentMonth.getFullYear();
714
+ const month = currentMonth.getMonth();
715
+ const firstDayOfMonth = new Date(year, month, 1);
716
+ const lastDayOfMonth = new Date(year, month + 1, 0);
717
+ const firstDayOfWeek = firstDayOfMonth.getDay();
718
+ const daysInMonth = lastDayOfMonth.getDate();
719
+ const getDaysInMonth = () => {
720
+ const days = [];
721
+ // Add empty cells for days before the first day of the month
722
+ for (let i = 0; i < firstDayOfWeek; i++) {
723
+ days.push(null);
724
+ }
725
+ // Add days of the month
726
+ for (let day = 1; day <= daysInMonth; day++) {
727
+ days.push(new Date(year, month, day));
728
+ }
729
+ return days;
730
+ };
731
+ const isSelected = (date) => {
732
+ if (!selected)
733
+ return false;
734
+ if (mode === "single" && selected instanceof Date) {
735
+ return date.toDateString() === selected.toDateString();
736
+ }
737
+ if (mode === "range" && selected && typeof selected === "object" && "from" in selected) {
738
+ const range = selected;
739
+ if (range.from && range.to) {
740
+ return date >= range.from && date <= range.to;
741
+ }
742
+ if (range.from) {
743
+ return date.toDateString() === range.from.toDateString();
744
+ }
745
+ }
746
+ if (mode === "multiple" && Array.isArray(selected)) {
747
+ return selected.some(d => d.toDateString() === date.toDateString());
748
+ }
749
+ return false;
750
+ };
751
+ const isToday = (date) => {
752
+ return date.toDateString() === today.toDateString();
753
+ };
754
+ const isDisabled = (date) => {
755
+ if (disabled)
756
+ return disabled(date);
757
+ return false;
758
+ };
759
+ const handleDateClick = (date) => {
760
+ if (isDisabled(date))
761
+ return;
762
+ if (mode === "single") {
763
+ onSelect?.(date);
764
+ }
765
+ else if (mode === "range") {
766
+ // Simple range selection - click to set start, click again to set end
767
+ if (!selected || typeof selected !== "object" || !("from" in selected)) {
768
+ onSelect?.({ from: date, to: undefined });
769
+ }
770
+ else {
771
+ const range = selected;
772
+ if (!range.from) {
773
+ onSelect?.({ from: date, to: undefined });
774
+ }
775
+ else if (!range.to) {
776
+ if (date >= range.from) {
777
+ onSelect?.({ from: range.from, to: date });
778
+ }
779
+ else {
780
+ onSelect?.({ from: date, to: range.from });
781
+ }
782
+ }
783
+ else {
784
+ onSelect?.({ from: date, to: undefined });
785
+ }
786
+ }
787
+ }
788
+ else if (mode === "multiple") {
789
+ const currentSelection = Array.isArray(selected) ? selected : [];
790
+ const isAlreadySelected = currentSelection.some(d => d.toDateString() === date.toDateString());
791
+ if (isAlreadySelected) {
792
+ onSelect?.(currentSelection.filter(d => d.toDateString() !== date.toDateString()));
793
+ }
794
+ else {
795
+ onSelect?.([...currentSelection, date]);
796
+ }
797
+ }
798
+ };
799
+ const navigateMonth = (direction) => {
800
+ setCurrentMonth(prev => {
801
+ const newMonth = new Date(prev);
802
+ if (direction === "prev") {
803
+ newMonth.setMonth(prev.getMonth() - 1);
804
+ }
805
+ else {
806
+ newMonth.setMonth(prev.getMonth() + 1);
807
+ }
808
+ return newMonth;
809
+ });
810
+ };
811
+ const days = getDaysInMonth();
812
+ return (require$$1.jsxs("div", { "data-slot": "calendar", className: cn$1("bg-background group/calendar p-3 w-fit", className), children: [require$$1.jsxs("div", { className: "flex items-center justify-between mb-4", children: [require$$1.jsx(Button, { variant: "ghost", size: "icon", onClick: () => navigateMonth("prev"), className: "h-8 w-8 p-0", children: require$$1.jsx(lucideReact.ChevronLeftIcon, { className: "h-4 w-4" }) }), require$$1.jsx("div", { className: "text-sm font-medium", children: formatMonthCaption(currentMonth) }), require$$1.jsx(Button, { variant: "ghost", size: "icon", onClick: () => navigateMonth("next"), className: "h-8 w-8 p-0", children: require$$1.jsx(lucideReact.ChevronRightIcon, { className: "h-4 w-4" }) })] }), require$$1.jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: WEEK_DAYS_TH.map((day) => (require$$1.jsx("div", { className: "text-muted-foreground text-xs font-normal text-center h-8 flex items-center justify-center", children: day }, day))) }), require$$1.jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((date, index) => {
813
+ if (!date) {
814
+ return require$$1.jsx("div", { className: "h-8" }, index);
815
+ }
816
+ const isDateSelected = isSelected(date);
817
+ const isDateToday = isToday(date);
818
+ const isDateDisabled = isDisabled(date);
819
+ return (require$$1.jsx(Button, { variant: "ghost", size: "icon", className: cn$1("h-8 w-8 p-0 text-sm font-normal", isDateSelected && "bg-primary text-primary-foreground", isDateToday && !isDateSelected && "bg-accent text-accent-foreground", isDateDisabled && "opacity-50 cursor-not-allowed", "hover:bg-accent hover:text-accent-foreground"), onClick: () => handleDateClick(date), disabled: isDateDisabled, children: date.getDate() }, date.toISOString()));
820
+ }) })] }));
821
+ }
822
+ function DateInput({ value, onChange, placeholder = "Select date", className, disabled = false }) {
823
+ const handleChange = (event) => {
824
+ const dateValue = event.target.value;
825
+ if (dateValue) {
826
+ onChange?.(new Date(dateValue));
827
+ }
828
+ else {
829
+ onChange?.(undefined);
830
+ }
831
+ };
832
+ const formatDateForInput = (date) => {
833
+ return date.toISOString().split('T')[0];
834
+ };
835
+ return (require$$1.jsx("input", { type: "date", value: value ? formatDateForInput(value) : "", onChange: handleChange, placeholder: placeholder, disabled: disabled, className: cn$1("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className) }));
659
836
  }
660
837
 
661
838
  const formatDistanceLocale = {
@@ -34432,179 +34609,6 @@ const RegistryItemRow = ({ item }) => {
34432
34609
  return (require$$1.jsxs(TableRow, { children: [require$$1.jsx(TableCell, { className: "w-50 font-medium", children: item.title }), require$$1.jsx(TableCell, { children: require$$1.jsx(Button, { variant: "link", asChild: true, children: require$$1.jsx("a", { target: "_blank", href: `${getBaseUrl()}/registry/${item.name}`, children: "Link" }) }) }), require$$1.jsx(TableCell, { children: require$$1.jsx(Button, { variant: "link", asChild: true, children: require$$1.jsx("a", { href: `${getBaseUrl()}/storybook/?path=/docs/${item.meta.story}--docs`, children: "Story" }) }) }), require$$1.jsx(TableCell, { children: require$$1.jsx(CommandBlock, { command: `npx shadcn@latest add ${getBaseUrl()}/registry/${item.name}` }) })] }, item.name));
34433
34610
  };
34434
34611
 
34435
- /**
34436
- * The {@link endOfMonth} function options.
34437
- */
34438
-
34439
- /**
34440
- * @name endOfMonth
34441
- * @category Month Helpers
34442
- * @summary Return the end of a month for the given date.
34443
- *
34444
- * @description
34445
- * Return the end of a month for the given date.
34446
- * The result will be in the local timezone.
34447
- *
34448
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
34449
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
34450
- *
34451
- * @param date - The original date
34452
- * @param options - An object with options
34453
- *
34454
- * @returns The end of a month
34455
- *
34456
- * @example
34457
- * // The end of a month for 2 September 2014 11:55:00:
34458
- * const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))
34459
- * //=> Tue Sep 30 2014 23:59:59.999
34460
- */
34461
- function endOfMonth(date, options) {
34462
- const _date = toDate(date);
34463
- const month = _date.getMonth();
34464
- _date.setFullYear(_date.getFullYear(), month + 1, 0);
34465
- _date.setHours(23, 59, 59, 999);
34466
- return _date;
34467
- }
34468
-
34469
- /**
34470
- * The {@link startOfMonth} function options.
34471
- */
34472
-
34473
- /**
34474
- * @name startOfMonth
34475
- * @category Month Helpers
34476
- * @summary Return the start of a month for the given date.
34477
- *
34478
- * @description
34479
- * Return the start of a month for the given date. The result will be in the local timezone.
34480
- *
34481
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.
34482
- * Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
34483
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed,
34484
- * or inferred from the arguments.
34485
- *
34486
- * @param date - The original date
34487
- * @param options - An object with options
34488
- *
34489
- * @returns The start of a month
34490
- *
34491
- * @example
34492
- * // The start of a month for 2 September 2014 11:55:00:
34493
- * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))
34494
- * //=> Mon Sep 01 2014 00:00:00
34495
- */
34496
- function startOfMonth(date, options) {
34497
- const _date = toDate(date);
34498
- _date.setDate(1);
34499
- _date.setHours(0, 0, 0, 0);
34500
- return _date;
34501
- }
34502
-
34503
- /**
34504
- * Thai month names in Buddhist calendar
34505
- */
34506
- const THAI_MONTH_NAMES = [
34507
- "มกราคม",
34508
- "กุมภาพันธ์",
34509
- "มีนาคม",
34510
- "เมษายน",
34511
- "พฤษภาคม",
34512
- "มิถุนายน",
34513
- "กรกฎาคม",
34514
- "สิงหาคม",
34515
- "กันยายน",
34516
- "ตุลาคม",
34517
- "พฤศจิกายน",
34518
- "ธันวาคม",
34519
- ];
34520
- /**
34521
- * Convert Gregorian year to Buddhist year
34522
- * Buddhist calendar is 543 years ahead of Gregorian calendar
34523
- *
34524
- * @param gregorianYear - The Gregorian year (e.g., 2024)
34525
- * @returns The Buddhist year (e.g., 2567)
34526
- *
34527
- * @example
34528
- * toBuddhistYear(2024); // returns 2567
34529
- */
34530
- function toBuddhistYear(gregorianYear) {
34531
- return gregorianYear + 543;
34532
- }
34533
- /**
34534
- * Convert Buddhist year to Gregorian year
34535
- *
34536
- * @param buddhistYear - The Buddhist year (e.g., 2567)
34537
- * @returns The Gregorian year (e.g., 2024)
34538
- *
34539
- * @example
34540
- * toGregorianYear(2567); // returns 2024
34541
- */
34542
- function toGregorianYear(buddhistYear) {
34543
- return buddhistYear - 543;
34544
- }
34545
- /**
34546
- * Get the first and last day of a month
34547
- *
34548
- * @param date - The date within the month
34549
- * @returns Object with start and end dates of the month
34550
- *
34551
- * @example
34552
- * getMonthDateRange(new Date('2024-06-15'));
34553
- * // returns { start: Date('2024-06-01'), end: Date('2024-06-30') }
34554
- */
34555
- function getMonthDateRange(date) {
34556
- const start = startOfMonth(date);
34557
- const end = endOfMonth(date);
34558
- return { start, end };
34559
- }
34560
- /**
34561
- * Format a date to Thai Buddhist calendar month display
34562
- *
34563
- * @param date - The date to format
34564
- * @returns Formatted string in Thai Buddhist calendar (e.g., "มกราคม 2568")
34565
- *
34566
- * @example
34567
- * formatThaiMonth(new Date('2024-01-15')); // returns "มกราคม 2567"
34568
- * formatThaiMonth(new Date('2024-12-25')); // returns "ธันวาคม 2567"
34569
- */
34570
- function formatThaiMonth(date) {
34571
- const monthIndex = date.getMonth();
34572
- const gregorianYear = date.getFullYear();
34573
- const buddhistYear = toBuddhistYear(gregorianYear);
34574
- return `${THAI_MONTH_NAMES[monthIndex]} ${buddhistYear}`;
34575
- }
34576
- /**
34577
- * Format a date to short Thai Buddhist calendar format
34578
- *
34579
- * @param date - The date to format
34580
- * @returns Formatted string (e.g., "01/2568")
34581
- *
34582
- * @example
34583
- * formatThaiMonthShort(new Date('2024-01-15')); // returns "01/2567"
34584
- */
34585
- function formatThaiMonthShort(date) {
34586
- const month = String(date.getMonth() + 1).padStart(2, "0");
34587
- const gregorianYear = date.getFullYear();
34588
- const buddhistYear = toBuddhistYear(gregorianYear);
34589
- return `${month}/${buddhistYear}`;
34590
- }
34591
- /**
34592
- * Get Thai month name by index (0-11)
34593
- *
34594
- * @param monthIndex - Month index (0 = January, 11 = December)
34595
- * @returns Thai month name
34596
- *
34597
- * @example
34598
- * getThaiMonthName(0); // returns "มกราคม"
34599
- * getThaiMonthName(11); // returns "ธันวาคม"
34600
- */
34601
- function getThaiMonthName(monthIndex) {
34602
- if (monthIndex < 0 || monthIndex > 11) {
34603
- throw new Error("Month index must be between 0 and 11");
34604
- }
34605
- return THAI_MONTH_NAMES[monthIndex];
34606
- }
34607
-
34608
34612
  /**
34609
34613
  * Convert a number to its Thai baht textual representation
34610
34614
  * (e.g. 1234.50 → "หนึ่งพันสองร้อยสามสิบสี่บาทห้าสิบสตางค์").