@braintwopoint0/playback-commons 0.1.9 → 0.1.11
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/ui/index.d.ts +47 -1
- package/dist/ui/index.js +727 -89
- package/dist/ui/index.js.map +1 -1
- package/package.json +5 -2
package/dist/ui/index.js
CHANGED
|
@@ -15,7 +15,7 @@ function cn(...inputs) {
|
|
|
15
15
|
// src/ui/button.tsx
|
|
16
16
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
17
17
|
var buttonVariants = cva(
|
|
18
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
18
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium cursor-pointer ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
19
19
|
{
|
|
20
20
|
variants: {
|
|
21
21
|
variant: {
|
|
@@ -200,7 +200,7 @@ var Input = React4.forwardRef(
|
|
|
200
200
|
type,
|
|
201
201
|
className: cn(
|
|
202
202
|
`flex h-10 w-full border-none bg-zinc-800 text-white shadow-input rounded-lg px-3 py-2 text-sm file:border-0 file:bg-transparent
|
|
203
|
-
file:text-sm file:font-
|
|
203
|
+
file:text-sm file:font-medium placeholder:text-neutral-500
|
|
204
204
|
focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-neutral-600
|
|
205
205
|
disabled:cursor-not-allowed disabled:opacity-50
|
|
206
206
|
shadow-[0px_0px_1px_1px_var(--neutral-700)]
|
|
@@ -314,61 +314,147 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
|
314
314
|
// src/ui/select.tsx
|
|
315
315
|
import * as React6 from "react";
|
|
316
316
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
317
|
+
import { useMotionTemplate as useMotionTemplate2, useMotionValue as useMotionValue2, motion as motion2 } from "motion/react";
|
|
317
318
|
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
318
319
|
var Select = SelectPrimitive.Root;
|
|
319
320
|
var SelectGroup = SelectPrimitive.Group;
|
|
320
321
|
var SelectValue = SelectPrimitive.Value;
|
|
321
|
-
var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) =>
|
|
322
|
-
|
|
322
|
+
var SelectTrigger = React6.forwardRef(({ className, children, ...props }, ref) => {
|
|
323
|
+
const radius = 100;
|
|
324
|
+
const [visible, setVisible] = React6.useState(false);
|
|
325
|
+
let mouseX = useMotionValue2(0);
|
|
326
|
+
let mouseY = useMotionValue2(0);
|
|
327
|
+
function handleMouseMove({ currentTarget, clientX, clientY }) {
|
|
328
|
+
let { left, top } = currentTarget.getBoundingClientRect();
|
|
329
|
+
mouseX.set(clientX - left);
|
|
330
|
+
mouseY.set(clientY - top);
|
|
331
|
+
}
|
|
332
|
+
return /* @__PURE__ */ jsx7(
|
|
333
|
+
motion2.div,
|
|
334
|
+
{
|
|
335
|
+
style: {
|
|
336
|
+
background: useMotionTemplate2`
|
|
337
|
+
radial-gradient(
|
|
338
|
+
${visible ? radius + "px" : "0px"} circle at ${mouseX}px ${mouseY}px,
|
|
339
|
+
var(--timberwolf),
|
|
340
|
+
transparent 80%
|
|
341
|
+
)
|
|
342
|
+
`
|
|
343
|
+
},
|
|
344
|
+
onMouseMove: handleMouseMove,
|
|
345
|
+
onMouseEnter: () => setVisible(true),
|
|
346
|
+
onMouseLeave: () => setVisible(false),
|
|
347
|
+
className: "p-[2px] rounded-lg transition duration-300 group/input",
|
|
348
|
+
children: /* @__PURE__ */ jsxs3(
|
|
349
|
+
SelectPrimitive.Trigger,
|
|
350
|
+
{
|
|
351
|
+
ref,
|
|
352
|
+
className: cn(
|
|
353
|
+
"flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md bg-zinc-800 text-white px-3 py-2 text-sm border-none shadow-[0px_0px_1px_1px_var(--neutral-700)] group-hover/input:shadow-none transition duration-400 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
354
|
+
className
|
|
355
|
+
),
|
|
356
|
+
...props,
|
|
357
|
+
children: [
|
|
358
|
+
children,
|
|
359
|
+
/* @__PURE__ */ jsx7(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
360
|
+
"svg",
|
|
361
|
+
{
|
|
362
|
+
className: "h-4 w-4 opacity-50",
|
|
363
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
364
|
+
viewBox: "0 0 24 24",
|
|
365
|
+
fill: "none",
|
|
366
|
+
stroke: "currentColor",
|
|
367
|
+
strokeWidth: "2",
|
|
368
|
+
strokeLinecap: "round",
|
|
369
|
+
strokeLinejoin: "round",
|
|
370
|
+
children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" })
|
|
371
|
+
}
|
|
372
|
+
) })
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
);
|
|
378
|
+
});
|
|
379
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
380
|
+
var SelectScrollUpButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
|
|
381
|
+
SelectPrimitive.ScrollUpButton,
|
|
323
382
|
{
|
|
324
383
|
ref,
|
|
325
384
|
className: cn(
|
|
326
|
-
"flex
|
|
385
|
+
"flex cursor-default items-center justify-center py-1",
|
|
327
386
|
className
|
|
328
387
|
),
|
|
329
388
|
...props,
|
|
330
|
-
children:
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
"
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
) })
|
|
346
|
-
]
|
|
389
|
+
children: /* @__PURE__ */ jsx7(
|
|
390
|
+
"svg",
|
|
391
|
+
{
|
|
392
|
+
className: "h-4 w-4",
|
|
393
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
394
|
+
viewBox: "0 0 24 24",
|
|
395
|
+
fill: "none",
|
|
396
|
+
stroke: "currentColor",
|
|
397
|
+
strokeWidth: "2",
|
|
398
|
+
strokeLinecap: "round",
|
|
399
|
+
strokeLinejoin: "round",
|
|
400
|
+
children: /* @__PURE__ */ jsx7("path", { d: "m18 15-6-6-6 6" })
|
|
401
|
+
}
|
|
402
|
+
)
|
|
347
403
|
}
|
|
348
404
|
));
|
|
349
|
-
|
|
350
|
-
var
|
|
351
|
-
SelectPrimitive.
|
|
405
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
406
|
+
var SelectScrollDownButton = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
|
|
407
|
+
SelectPrimitive.ScrollDownButton,
|
|
352
408
|
{
|
|
353
409
|
ref,
|
|
354
410
|
className: cn(
|
|
355
|
-
"
|
|
356
|
-
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
411
|
+
"flex cursor-default items-center justify-center py-1",
|
|
357
412
|
className
|
|
358
413
|
),
|
|
359
|
-
position,
|
|
360
414
|
...props,
|
|
361
415
|
children: /* @__PURE__ */ jsx7(
|
|
362
|
-
|
|
416
|
+
"svg",
|
|
363
417
|
{
|
|
364
|
-
className:
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
418
|
+
className: "h-4 w-4",
|
|
419
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
420
|
+
viewBox: "0 0 24 24",
|
|
421
|
+
fill: "none",
|
|
422
|
+
stroke: "currentColor",
|
|
423
|
+
strokeWidth: "2",
|
|
424
|
+
strokeLinecap: "round",
|
|
425
|
+
strokeLinejoin: "round",
|
|
426
|
+
children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" })
|
|
369
427
|
}
|
|
370
428
|
)
|
|
371
429
|
}
|
|
430
|
+
));
|
|
431
|
+
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
432
|
+
var SelectContent = React6.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx7(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs3(
|
|
433
|
+
SelectPrimitive.Content,
|
|
434
|
+
{
|
|
435
|
+
ref,
|
|
436
|
+
className: cn(
|
|
437
|
+
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-neutral-700 bg-zinc-800 text-white shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
438
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
439
|
+
className
|
|
440
|
+
),
|
|
441
|
+
position,
|
|
442
|
+
...props,
|
|
443
|
+
children: [
|
|
444
|
+
/* @__PURE__ */ jsx7(SelectScrollUpButton, {}),
|
|
445
|
+
/* @__PURE__ */ jsx7(
|
|
446
|
+
SelectPrimitive.Viewport,
|
|
447
|
+
{
|
|
448
|
+
className: cn(
|
|
449
|
+
"p-1",
|
|
450
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
451
|
+
),
|
|
452
|
+
children
|
|
453
|
+
}
|
|
454
|
+
),
|
|
455
|
+
/* @__PURE__ */ jsx7(SelectScrollDownButton, {})
|
|
456
|
+
]
|
|
457
|
+
}
|
|
372
458
|
) }));
|
|
373
459
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
374
460
|
var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
|
|
@@ -376,12 +462,12 @@ var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /
|
|
|
376
462
|
{
|
|
377
463
|
ref,
|
|
378
464
|
className: cn(
|
|
379
|
-
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-
|
|
465
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-white/10 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
380
466
|
className
|
|
381
467
|
),
|
|
382
468
|
...props,
|
|
383
469
|
children: [
|
|
384
|
-
/* @__PURE__ */ jsx7("span", { className: "absolute
|
|
470
|
+
/* @__PURE__ */ jsx7("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx7(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx7(
|
|
385
471
|
"svg",
|
|
386
472
|
{
|
|
387
473
|
className: "h-4 w-4",
|
|
@@ -413,27 +499,27 @@ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
413
499
|
SelectPrimitive.Label,
|
|
414
500
|
{
|
|
415
501
|
ref,
|
|
416
|
-
className: cn("py-1.5
|
|
502
|
+
className: cn("px-2 py-1.5 text-sm font-semibold", className),
|
|
417
503
|
...props
|
|
418
504
|
}
|
|
419
505
|
));
|
|
420
506
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
421
507
|
|
|
422
508
|
// src/ui/animated-tooltip.tsx
|
|
423
|
-
import { useState as
|
|
509
|
+
import { useState as useState3 } from "react";
|
|
424
510
|
import {
|
|
425
|
-
motion as
|
|
511
|
+
motion as motion3,
|
|
426
512
|
useTransform,
|
|
427
|
-
useMotionValue as
|
|
513
|
+
useMotionValue as useMotionValue3,
|
|
428
514
|
useSpring
|
|
429
515
|
} from "motion/react";
|
|
430
516
|
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
431
517
|
var AnimatedTooltip = ({
|
|
432
518
|
items
|
|
433
519
|
}) => {
|
|
434
|
-
const [hoveredIndex, setHoveredIndex] =
|
|
520
|
+
const [hoveredIndex, setHoveredIndex] = useState3(null);
|
|
435
521
|
const springConfig = { stiffness: 100, damping: 5 };
|
|
436
|
-
const x =
|
|
522
|
+
const x = useMotionValue3(0);
|
|
437
523
|
const rotate = useSpring(
|
|
438
524
|
useTransform(x, [-100, 100], [-45, 45]),
|
|
439
525
|
springConfig
|
|
@@ -454,7 +540,7 @@ var AnimatedTooltip = ({
|
|
|
454
540
|
onMouseLeave: () => setHoveredIndex(null),
|
|
455
541
|
children: [
|
|
456
542
|
hoveredIndex === item.id && /* @__PURE__ */ jsxs4(
|
|
457
|
-
|
|
543
|
+
motion3.div,
|
|
458
544
|
{
|
|
459
545
|
initial: { opacity: 0, y: 20, scale: 0.6 },
|
|
460
546
|
animate: {
|
|
@@ -500,15 +586,15 @@ var AnimatedTooltip = ({
|
|
|
500
586
|
};
|
|
501
587
|
|
|
502
588
|
// src/ui/card-hover-effect.tsx
|
|
503
|
-
import { AnimatePresence as AnimatePresence2, motion as
|
|
589
|
+
import { AnimatePresence as AnimatePresence2, motion as motion4 } from "motion/react";
|
|
504
590
|
import Link from "next/link";
|
|
505
|
-
import { useState as
|
|
591
|
+
import { useState as useState4 } from "react";
|
|
506
592
|
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
507
593
|
var HoverEffect = ({
|
|
508
594
|
items,
|
|
509
595
|
className
|
|
510
596
|
}) => {
|
|
511
|
-
let [hoveredIndex, setHoveredIndex] =
|
|
597
|
+
let [hoveredIndex, setHoveredIndex] = useState4(null);
|
|
512
598
|
return /* @__PURE__ */ jsx9(
|
|
513
599
|
"div",
|
|
514
600
|
{
|
|
@@ -525,7 +611,7 @@ var HoverEffect = ({
|
|
|
525
611
|
onMouseLeave: () => setHoveredIndex(null),
|
|
526
612
|
children: [
|
|
527
613
|
/* @__PURE__ */ jsx9(AnimatePresence2, { children: hoveredIndex === idx && /* @__PURE__ */ jsx9(
|
|
528
|
-
|
|
614
|
+
motion4.span,
|
|
529
615
|
{
|
|
530
616
|
className: "absolute inset-0 h-full w-full bg-neutral-400/[0.5] block rounded-3xl",
|
|
531
617
|
layoutId: "hoverBackground",
|
|
@@ -605,16 +691,16 @@ var HoverCardDescription = ({
|
|
|
605
691
|
};
|
|
606
692
|
|
|
607
693
|
// src/ui/flip-words.tsx
|
|
608
|
-
import { useCallback, useEffect, useState as
|
|
609
|
-
import { AnimatePresence as AnimatePresence3, motion as
|
|
694
|
+
import { useCallback, useEffect, useState as useState5 } from "react";
|
|
695
|
+
import { AnimatePresence as AnimatePresence3, motion as motion5 } from "motion/react";
|
|
610
696
|
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
611
697
|
var FlipWords = ({
|
|
612
698
|
words,
|
|
613
699
|
duration = 3e3,
|
|
614
700
|
className
|
|
615
701
|
}) => {
|
|
616
|
-
const [currentWord, setCurrentWord] =
|
|
617
|
-
const [isAnimating, setIsAnimating] =
|
|
702
|
+
const [currentWord, setCurrentWord] = useState5(words[0]);
|
|
703
|
+
const [isAnimating, setIsAnimating] = useState5(false);
|
|
618
704
|
const startAnimation = useCallback(() => {
|
|
619
705
|
const word = words[words.indexOf(currentWord) + 1] || words[0];
|
|
620
706
|
setCurrentWord(word);
|
|
@@ -633,7 +719,7 @@ var FlipWords = ({
|
|
|
633
719
|
setIsAnimating(false);
|
|
634
720
|
},
|
|
635
721
|
children: /* @__PURE__ */ jsx10(
|
|
636
|
-
|
|
722
|
+
motion5.div,
|
|
637
723
|
{
|
|
638
724
|
initial: {
|
|
639
725
|
opacity: 0,
|
|
@@ -661,7 +747,7 @@ var FlipWords = ({
|
|
|
661
747
|
className
|
|
662
748
|
),
|
|
663
749
|
children: currentWord.split(" ").map((word, wordIndex) => /* @__PURE__ */ jsxs6(
|
|
664
|
-
|
|
750
|
+
motion5.span,
|
|
665
751
|
{
|
|
666
752
|
initial: { opacity: 0, y: 10, filter: "blur(8px)" },
|
|
667
753
|
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
|
@@ -672,7 +758,7 @@ var FlipWords = ({
|
|
|
672
758
|
className: "inline-block whitespace-nowrap",
|
|
673
759
|
children: [
|
|
674
760
|
word.split("").map((letter, letterIndex) => /* @__PURE__ */ jsx10(
|
|
675
|
-
|
|
761
|
+
motion5.span,
|
|
676
762
|
{
|
|
677
763
|
initial: { opacity: 0, y: 10, filter: "blur(8px)" },
|
|
678
764
|
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
|
@@ -699,21 +785,21 @@ var FlipWords = ({
|
|
|
699
785
|
|
|
700
786
|
// src/ui/hero-highlight.tsx
|
|
701
787
|
import {
|
|
702
|
-
useMotionValue as
|
|
703
|
-
motion as
|
|
704
|
-
useMotionTemplate as
|
|
788
|
+
useMotionValue as useMotionValue4,
|
|
789
|
+
motion as motion6,
|
|
790
|
+
useMotionTemplate as useMotionTemplate3,
|
|
705
791
|
animate
|
|
706
792
|
} from "motion/react";
|
|
707
|
-
import { useEffect as useEffect2, useState as
|
|
793
|
+
import { useEffect as useEffect2, useState as useState6 } from "react";
|
|
708
794
|
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
709
795
|
var HeroHighlight = ({
|
|
710
796
|
children,
|
|
711
797
|
className,
|
|
712
798
|
containerClassName
|
|
713
799
|
}) => {
|
|
714
|
-
let mouseX =
|
|
715
|
-
let mouseY =
|
|
716
|
-
const [isHoverable, setIsHoverable] =
|
|
800
|
+
let mouseX = useMotionValue4(0);
|
|
801
|
+
let mouseY = useMotionValue4(0);
|
|
802
|
+
const [isHoverable, setIsHoverable] = useState6(false);
|
|
717
803
|
useEffect2(() => {
|
|
718
804
|
const mediaQuery = window.matchMedia("(pointer: fine)");
|
|
719
805
|
setIsHoverable(mediaQuery.matches);
|
|
@@ -755,18 +841,18 @@ var HeroHighlight = ({
|
|
|
755
841
|
children: [
|
|
756
842
|
/* @__PURE__ */ jsx11("div", { className: "absolute inset-0 bg-dot-thick-neutral-800 pointer-events-none" }),
|
|
757
843
|
/* @__PURE__ */ jsx11(
|
|
758
|
-
|
|
844
|
+
motion6.div,
|
|
759
845
|
{
|
|
760
846
|
className: "pointer-events-none bg-dot-thick-gray-100 absolute inset-0 opacity-0 transition duration-300 group-hover:opacity-100",
|
|
761
847
|
style: {
|
|
762
|
-
WebkitMaskImage:
|
|
848
|
+
WebkitMaskImage: useMotionTemplate3`
|
|
763
849
|
radial-gradient(
|
|
764
850
|
200px circle at ${mouseX}px ${mouseY}px,
|
|
765
851
|
black 0%,
|
|
766
852
|
transparent 100%
|
|
767
853
|
)
|
|
768
854
|
`,
|
|
769
|
-
maskImage:
|
|
855
|
+
maskImage: useMotionTemplate3`
|
|
770
856
|
radial-gradient(
|
|
771
857
|
200px circle at ${mouseX}px ${mouseY}px,
|
|
772
858
|
black 0%,
|
|
@@ -786,7 +872,7 @@ var Highlight = ({
|
|
|
786
872
|
className
|
|
787
873
|
}) => {
|
|
788
874
|
return /* @__PURE__ */ jsx11(
|
|
789
|
-
|
|
875
|
+
motion6.span,
|
|
790
876
|
{
|
|
791
877
|
initial: {
|
|
792
878
|
backgroundSize: "0% 100%"
|
|
@@ -813,14 +899,555 @@ var Highlight = ({
|
|
|
813
899
|
);
|
|
814
900
|
};
|
|
815
901
|
|
|
816
|
-
// src/ui/
|
|
902
|
+
// src/ui/popover.tsx
|
|
817
903
|
import * as React10 from "react";
|
|
904
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
905
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
906
|
+
var Popover = PopoverPrimitive.Root;
|
|
907
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
908
|
+
var PopoverAnchor = PopoverPrimitive.Anchor;
|
|
909
|
+
var PopoverContent = React10.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx12(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx12(
|
|
910
|
+
PopoverPrimitive.Content,
|
|
911
|
+
{
|
|
912
|
+
ref,
|
|
913
|
+
align,
|
|
914
|
+
sideOffset,
|
|
915
|
+
className: cn(
|
|
916
|
+
"z-50 w-72 rounded-md border border-zinc-800 bg-zinc-950 p-4 text-zinc-50 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
|
917
|
+
className
|
|
918
|
+
),
|
|
919
|
+
...props
|
|
920
|
+
}
|
|
921
|
+
) }));
|
|
922
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
923
|
+
|
|
924
|
+
// src/ui/calendar.tsx
|
|
925
|
+
import * as React11 from "react";
|
|
926
|
+
import {
|
|
927
|
+
ChevronDownIcon,
|
|
928
|
+
ChevronLeftIcon,
|
|
929
|
+
ChevronRightIcon
|
|
930
|
+
} from "lucide-react";
|
|
931
|
+
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
932
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
933
|
+
function Calendar({
|
|
934
|
+
className,
|
|
935
|
+
classNames,
|
|
936
|
+
showOutsideDays = true,
|
|
937
|
+
captionLayout = "label",
|
|
938
|
+
buttonVariant = "ghost",
|
|
939
|
+
formatters,
|
|
940
|
+
components,
|
|
941
|
+
...props
|
|
942
|
+
}) {
|
|
943
|
+
const defaultClassNames = getDefaultClassNames();
|
|
944
|
+
return /* @__PURE__ */ jsx13(
|
|
945
|
+
DayPicker,
|
|
946
|
+
{
|
|
947
|
+
showOutsideDays,
|
|
948
|
+
className: cn(
|
|
949
|
+
"bg-zinc-950 group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
950
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
951
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
952
|
+
className
|
|
953
|
+
),
|
|
954
|
+
captionLayout,
|
|
955
|
+
formatters: {
|
|
956
|
+
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
957
|
+
...formatters
|
|
958
|
+
},
|
|
959
|
+
classNames: {
|
|
960
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
961
|
+
months: cn(
|
|
962
|
+
"relative flex flex-col gap-4 md:flex-row",
|
|
963
|
+
defaultClassNames.months
|
|
964
|
+
),
|
|
965
|
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
966
|
+
nav: cn(
|
|
967
|
+
"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
|
|
968
|
+
defaultClassNames.nav
|
|
969
|
+
),
|
|
970
|
+
button_previous: cn(
|
|
971
|
+
buttonVariants({ variant: buttonVariant }),
|
|
972
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
973
|
+
defaultClassNames.button_previous
|
|
974
|
+
),
|
|
975
|
+
button_next: cn(
|
|
976
|
+
buttonVariants({ variant: buttonVariant }),
|
|
977
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
978
|
+
defaultClassNames.button_next
|
|
979
|
+
),
|
|
980
|
+
month_caption: cn(
|
|
981
|
+
"flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]",
|
|
982
|
+
defaultClassNames.month_caption
|
|
983
|
+
),
|
|
984
|
+
dropdowns: cn(
|
|
985
|
+
"flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium",
|
|
986
|
+
defaultClassNames.dropdowns
|
|
987
|
+
),
|
|
988
|
+
dropdown_root: cn(
|
|
989
|
+
"has-focus:border-zinc-300 border-zinc-800 shadow-xs has-focus:ring-zinc-300/50 has-focus:ring-[3px] relative rounded-md border",
|
|
990
|
+
defaultClassNames.dropdown_root
|
|
991
|
+
),
|
|
992
|
+
dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
993
|
+
caption_label: cn(
|
|
994
|
+
"select-none font-medium",
|
|
995
|
+
captionLayout === "label" ? "text-sm" : "[&>svg]:text-zinc-400 flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
|
|
996
|
+
defaultClassNames.caption_label
|
|
997
|
+
),
|
|
998
|
+
table: "w-full border-collapse",
|
|
999
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
1000
|
+
weekday: cn(
|
|
1001
|
+
"text-zinc-400 flex-1 select-none rounded-md text-[0.8rem] font-normal",
|
|
1002
|
+
defaultClassNames.weekday
|
|
1003
|
+
),
|
|
1004
|
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
1005
|
+
week_number_header: cn(
|
|
1006
|
+
"w-[--cell-size] select-none",
|
|
1007
|
+
defaultClassNames.week_number_header
|
|
1008
|
+
),
|
|
1009
|
+
week_number: cn(
|
|
1010
|
+
"text-zinc-400 select-none text-[0.8rem]",
|
|
1011
|
+
defaultClassNames.week_number
|
|
1012
|
+
),
|
|
1013
|
+
day: cn(
|
|
1014
|
+
"group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
1015
|
+
defaultClassNames.day
|
|
1016
|
+
),
|
|
1017
|
+
range_start: cn(
|
|
1018
|
+
"bg-zinc-800 rounded-l-md",
|
|
1019
|
+
defaultClassNames.range_start
|
|
1020
|
+
),
|
|
1021
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
1022
|
+
range_end: cn("bg-zinc-800 rounded-r-md", defaultClassNames.range_end),
|
|
1023
|
+
today: cn(
|
|
1024
|
+
"bg-zinc-800 text-zinc-50 rounded-md data-[selected=true]:rounded-none",
|
|
1025
|
+
defaultClassNames.today
|
|
1026
|
+
),
|
|
1027
|
+
outside: cn(
|
|
1028
|
+
"text-zinc-400 aria-selected:text-zinc-400",
|
|
1029
|
+
defaultClassNames.outside
|
|
1030
|
+
),
|
|
1031
|
+
disabled: cn("text-zinc-400 opacity-50", defaultClassNames.disabled),
|
|
1032
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
1033
|
+
...classNames
|
|
1034
|
+
},
|
|
1035
|
+
components: {
|
|
1036
|
+
Root: ({ className: className2, rootRef, ...props2 }) => {
|
|
1037
|
+
return /* @__PURE__ */ jsx13(
|
|
1038
|
+
"div",
|
|
1039
|
+
{
|
|
1040
|
+
"data-slot": "calendar",
|
|
1041
|
+
ref: rootRef,
|
|
1042
|
+
className: cn(className2),
|
|
1043
|
+
...props2
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
},
|
|
1047
|
+
Chevron: ({ className: className2, orientation, ...props2 }) => {
|
|
1048
|
+
if (orientation === "left") {
|
|
1049
|
+
return /* @__PURE__ */ jsx13(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
|
|
1050
|
+
}
|
|
1051
|
+
if (orientation === "right") {
|
|
1052
|
+
return /* @__PURE__ */ jsx13(
|
|
1053
|
+
ChevronRightIcon,
|
|
1054
|
+
{
|
|
1055
|
+
className: cn("size-4", className2),
|
|
1056
|
+
...props2
|
|
1057
|
+
}
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
return /* @__PURE__ */ jsx13(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
|
|
1061
|
+
},
|
|
1062
|
+
DayButton: CalendarDayButton,
|
|
1063
|
+
WeekNumber: ({ children, ...props2 }) => {
|
|
1064
|
+
return /* @__PURE__ */ jsx13("td", { ...props2, children: /* @__PURE__ */ jsx13("div", { className: "flex size-[--cell-size] items-center justify-center text-center", children }) });
|
|
1065
|
+
},
|
|
1066
|
+
...components
|
|
1067
|
+
},
|
|
1068
|
+
...props
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function CalendarDayButton({
|
|
1073
|
+
className,
|
|
1074
|
+
day,
|
|
1075
|
+
modifiers,
|
|
1076
|
+
...props
|
|
1077
|
+
}) {
|
|
1078
|
+
const defaultClassNames = getDefaultClassNames();
|
|
1079
|
+
const ref = React11.useRef(null);
|
|
1080
|
+
React11.useEffect(() => {
|
|
1081
|
+
if (modifiers.focused) ref.current?.focus();
|
|
1082
|
+
}, [modifiers.focused]);
|
|
1083
|
+
return /* @__PURE__ */ jsx13(
|
|
1084
|
+
Button,
|
|
1085
|
+
{
|
|
1086
|
+
ref,
|
|
1087
|
+
variant: "ghost",
|
|
1088
|
+
size: "icon",
|
|
1089
|
+
"data-day": day.date.toLocaleDateString(),
|
|
1090
|
+
"data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
|
|
1091
|
+
"data-range-start": modifiers.range_start,
|
|
1092
|
+
"data-range-end": modifiers.range_end,
|
|
1093
|
+
"data-range-middle": modifiers.range_middle,
|
|
1094
|
+
className: cn(
|
|
1095
|
+
"data-[selected-single=true]:bg-zinc-50 data-[selected-single=true]:text-zinc-900 data-[range-middle=true]:bg-zinc-800 data-[range-middle=true]:text-zinc-50 data-[range-start=true]:bg-zinc-50 data-[range-start=true]:text-zinc-900 data-[range-end=true]:bg-zinc-50 data-[range-end=true]:text-zinc-900 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70",
|
|
1096
|
+
defaultClassNames.day,
|
|
1097
|
+
className
|
|
1098
|
+
),
|
|
1099
|
+
...props
|
|
1100
|
+
}
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// src/ui/date-picker.tsx
|
|
1105
|
+
import * as React12 from "react";
|
|
1106
|
+
import { CalendarIcon } from "lucide-react";
|
|
1107
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1108
|
+
function DatePicker({
|
|
1109
|
+
value,
|
|
1110
|
+
onChange,
|
|
1111
|
+
min,
|
|
1112
|
+
max,
|
|
1113
|
+
className,
|
|
1114
|
+
id,
|
|
1115
|
+
placeholder = "Pick a date"
|
|
1116
|
+
}) {
|
|
1117
|
+
const [open, setOpen] = React12.useState(false);
|
|
1118
|
+
const selectedDate = value ? /* @__PURE__ */ new Date(value + "T00:00:00") : void 0;
|
|
1119
|
+
const minDate = min ? /* @__PURE__ */ new Date(min + "T00:00:00") : void 0;
|
|
1120
|
+
const maxDate = max ? /* @__PURE__ */ new Date(max + "T00:00:00") : void 0;
|
|
1121
|
+
const formatDate2 = (date) => {
|
|
1122
|
+
return date.toLocaleDateString("en-GB", {
|
|
1123
|
+
day: "2-digit",
|
|
1124
|
+
month: "short",
|
|
1125
|
+
year: "numeric"
|
|
1126
|
+
});
|
|
1127
|
+
};
|
|
1128
|
+
const handleDateSelect = (date) => {
|
|
1129
|
+
if (date) {
|
|
1130
|
+
const year = date.getFullYear();
|
|
1131
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1132
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1133
|
+
onChange(`${year}-${month}-${day}`);
|
|
1134
|
+
setOpen(false);
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ jsxs8(Popover, { open, onOpenChange: setOpen, children: [
|
|
1138
|
+
/* @__PURE__ */ jsx14(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
|
|
1139
|
+
Button,
|
|
1140
|
+
{
|
|
1141
|
+
id,
|
|
1142
|
+
variant: "outline",
|
|
1143
|
+
className: cn(
|
|
1144
|
+
"w-full justify-start text-left font-normal h-10 bg-zinc-800 border-none text-white shadow-input rounded-md px-3 py-2 text-sm",
|
|
1145
|
+
"focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-neutral-600",
|
|
1146
|
+
"shadow-[0px_0px_1px_1px_var(--neutral-700)]",
|
|
1147
|
+
"hover:shadow-none transition duration-400",
|
|
1148
|
+
!selectedDate && "text-neutral-400",
|
|
1149
|
+
className
|
|
1150
|
+
),
|
|
1151
|
+
children: [
|
|
1152
|
+
/* @__PURE__ */ jsx14(CalendarIcon, { className: "mr-2 h-4 w-4" }),
|
|
1153
|
+
selectedDate ? formatDate2(selectedDate) : /* @__PURE__ */ jsx14("span", { children: placeholder })
|
|
1154
|
+
]
|
|
1155
|
+
}
|
|
1156
|
+
) }),
|
|
1157
|
+
/* @__PURE__ */ jsx14(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx14(
|
|
1158
|
+
Calendar,
|
|
1159
|
+
{
|
|
1160
|
+
mode: "single",
|
|
1161
|
+
selected: selectedDate,
|
|
1162
|
+
onSelect: handleDateSelect,
|
|
1163
|
+
disabled: (date) => {
|
|
1164
|
+
const dateAtMidnight = new Date(
|
|
1165
|
+
date.getFullYear(),
|
|
1166
|
+
date.getMonth(),
|
|
1167
|
+
date.getDate()
|
|
1168
|
+
);
|
|
1169
|
+
if (minDate) {
|
|
1170
|
+
const minDateAtMidnight = new Date(
|
|
1171
|
+
minDate.getFullYear(),
|
|
1172
|
+
minDate.getMonth(),
|
|
1173
|
+
minDate.getDate()
|
|
1174
|
+
);
|
|
1175
|
+
if (dateAtMidnight < minDateAtMidnight) return true;
|
|
1176
|
+
}
|
|
1177
|
+
if (maxDate) {
|
|
1178
|
+
const maxDateAtMidnight = new Date(
|
|
1179
|
+
maxDate.getFullYear(),
|
|
1180
|
+
maxDate.getMonth(),
|
|
1181
|
+
maxDate.getDate()
|
|
1182
|
+
);
|
|
1183
|
+
if (dateAtMidnight > maxDateAtMidnight) return true;
|
|
1184
|
+
}
|
|
1185
|
+
return false;
|
|
1186
|
+
},
|
|
1187
|
+
initialFocus: true
|
|
1188
|
+
}
|
|
1189
|
+
) })
|
|
1190
|
+
] });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/ui/time-picker.tsx
|
|
1194
|
+
import * as React13 from "react";
|
|
1195
|
+
import { ClockIcon } from "lucide-react";
|
|
1196
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1197
|
+
function TimePicker({
|
|
1198
|
+
value,
|
|
1199
|
+
onChange,
|
|
1200
|
+
placeholder = "Select time",
|
|
1201
|
+
className,
|
|
1202
|
+
disabled = false,
|
|
1203
|
+
min,
|
|
1204
|
+
max
|
|
1205
|
+
}) {
|
|
1206
|
+
const [open, setOpen] = React13.useState(false);
|
|
1207
|
+
const [hours, setHours] = React13.useState(
|
|
1208
|
+
value ? parseInt(value.split(":")[0]) : 9
|
|
1209
|
+
);
|
|
1210
|
+
const [minutes, setMinutes] = React13.useState(
|
|
1211
|
+
value ? parseInt(value.split(":")[1]) : 0
|
|
1212
|
+
);
|
|
1213
|
+
const formatTime = (h, m) => {
|
|
1214
|
+
return `${h.toString().padStart(2, "0")}:${m.toString().padStart(2, "0")}`;
|
|
1215
|
+
};
|
|
1216
|
+
const handleTimeSelect = (h, m) => {
|
|
1217
|
+
const timeString = formatTime(h, m);
|
|
1218
|
+
setHours(h);
|
|
1219
|
+
setMinutes(m);
|
|
1220
|
+
onChange?.(timeString);
|
|
1221
|
+
setOpen(false);
|
|
1222
|
+
};
|
|
1223
|
+
const generateTimeOptions = () => {
|
|
1224
|
+
const options = [];
|
|
1225
|
+
for (let h = 6; h <= 23; h++) {
|
|
1226
|
+
for (let m = 0; m < 60; m += 15) {
|
|
1227
|
+
const timeString = formatTime(h, m);
|
|
1228
|
+
if (min && timeString < min) continue;
|
|
1229
|
+
if (max && timeString > max) continue;
|
|
1230
|
+
options.push({ hours: h, minutes: m, display: timeString });
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return options;
|
|
1234
|
+
};
|
|
1235
|
+
const timeOptions = generateTimeOptions();
|
|
1236
|
+
const displayValue = value || "";
|
|
1237
|
+
return /* @__PURE__ */ jsxs9(Popover, { open, onOpenChange: setOpen, children: [
|
|
1238
|
+
/* @__PURE__ */ jsx15(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
1239
|
+
Button,
|
|
1240
|
+
{
|
|
1241
|
+
variant: "outline",
|
|
1242
|
+
className: cn(
|
|
1243
|
+
"w-full justify-start text-left font-normal h-10 bg-zinc-800 border-none text-white shadow-input rounded-md px-3 py-2 text-sm",
|
|
1244
|
+
"focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-neutral-600",
|
|
1245
|
+
"shadow-[0px_0px_1px_1px_var(--neutral-700)]",
|
|
1246
|
+
"hover:shadow-none transition duration-400",
|
|
1247
|
+
!value && "text-neutral-400",
|
|
1248
|
+
className
|
|
1249
|
+
),
|
|
1250
|
+
disabled,
|
|
1251
|
+
children: [
|
|
1252
|
+
/* @__PURE__ */ jsx15(ClockIcon, { className: "mr-2 h-4 w-4" }),
|
|
1253
|
+
displayValue || placeholder
|
|
1254
|
+
]
|
|
1255
|
+
}
|
|
1256
|
+
) }),
|
|
1257
|
+
/* @__PURE__ */ jsx15(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx15("div", { className: "max-h-60 overflow-y-auto", children: /* @__PURE__ */ jsx15("div", { className: "grid grid-cols-1 gap-1 p-2", children: timeOptions.map(({ hours: h, minutes: m, display }) => /* @__PURE__ */ jsx15(
|
|
1258
|
+
Button,
|
|
1259
|
+
{
|
|
1260
|
+
variant: value === display ? "default" : "ghost",
|
|
1261
|
+
className: "justify-start text-left h-8 text-sm",
|
|
1262
|
+
onClick: () => handleTimeSelect(h, m),
|
|
1263
|
+
children: display
|
|
1264
|
+
},
|
|
1265
|
+
display
|
|
1266
|
+
)) }) }) })
|
|
1267
|
+
] });
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
// src/ui/datetime-picker.tsx
|
|
1271
|
+
import * as React14 from "react";
|
|
1272
|
+
import { CalendarIcon as CalendarIcon2 } from "lucide-react";
|
|
1273
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1274
|
+
function DateTimePicker({
|
|
1275
|
+
value,
|
|
1276
|
+
onChange,
|
|
1277
|
+
placeholder = "Pick date & time",
|
|
1278
|
+
className,
|
|
1279
|
+
disabled = false,
|
|
1280
|
+
required = false
|
|
1281
|
+
}) {
|
|
1282
|
+
const [open, setOpen] = React14.useState(false);
|
|
1283
|
+
const hourRef = React14.useRef(null);
|
|
1284
|
+
const minuteRef = React14.useRef(null);
|
|
1285
|
+
const datePart = value ? value.split("T")[0] : "";
|
|
1286
|
+
const timePart = value ? value.split("T")[1] || "" : "";
|
|
1287
|
+
const selectedHour = timePart ? parseInt(timePart.split(":")[0]) : -1;
|
|
1288
|
+
const selectedMinute = timePart ? parseInt(timePart.split(":")[1]) : -1;
|
|
1289
|
+
const selectedDate = datePart ? /* @__PURE__ */ new Date(datePart + "T00:00:00") : void 0;
|
|
1290
|
+
const formatDisplay = (val) => {
|
|
1291
|
+
if (!val) return "";
|
|
1292
|
+
const [d, t] = val.split("T");
|
|
1293
|
+
if (!d) return "";
|
|
1294
|
+
const date = /* @__PURE__ */ new Date(d + "T00:00:00");
|
|
1295
|
+
const dateStr = date.toLocaleDateString("en-GB", {
|
|
1296
|
+
day: "2-digit",
|
|
1297
|
+
month: "short",
|
|
1298
|
+
year: "numeric"
|
|
1299
|
+
});
|
|
1300
|
+
if (!t) return dateStr;
|
|
1301
|
+
return `${dateStr}, ${t}`;
|
|
1302
|
+
};
|
|
1303
|
+
const buildValue = (date, hour, minute) => {
|
|
1304
|
+
const h = hour.toString().padStart(2, "0");
|
|
1305
|
+
const m = minute.toString().padStart(2, "0");
|
|
1306
|
+
return `${date}T${h}:${m}`;
|
|
1307
|
+
};
|
|
1308
|
+
const handleDateSelect = (date) => {
|
|
1309
|
+
if (!date) return;
|
|
1310
|
+
const year = date.getFullYear();
|
|
1311
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1312
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1313
|
+
const newDate = `${year}-${month}-${day}`;
|
|
1314
|
+
const h = selectedHour >= 0 ? selectedHour : 12;
|
|
1315
|
+
const m = selectedMinute >= 0 ? selectedMinute : 0;
|
|
1316
|
+
onChange(buildValue(newDate, h, m));
|
|
1317
|
+
};
|
|
1318
|
+
const handleHourSelect = (h) => {
|
|
1319
|
+
if (!datePart) {
|
|
1320
|
+
const now = /* @__PURE__ */ new Date();
|
|
1321
|
+
const year = now.getFullYear();
|
|
1322
|
+
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
1323
|
+
const day = String(now.getDate()).padStart(2, "0");
|
|
1324
|
+
const m = selectedMinute >= 0 ? selectedMinute : 0;
|
|
1325
|
+
onChange(buildValue(`${year}-${month}-${day}`, h, m));
|
|
1326
|
+
} else {
|
|
1327
|
+
const m = selectedMinute >= 0 ? selectedMinute : 0;
|
|
1328
|
+
onChange(buildValue(datePart, h, m));
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
const handleMinuteSelect = (m) => {
|
|
1332
|
+
if (!datePart) {
|
|
1333
|
+
const now = /* @__PURE__ */ new Date();
|
|
1334
|
+
const year = now.getFullYear();
|
|
1335
|
+
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
1336
|
+
const day = String(now.getDate()).padStart(2, "0");
|
|
1337
|
+
const h = selectedHour >= 0 ? selectedHour : 12;
|
|
1338
|
+
onChange(buildValue(`${year}-${month}-${day}`, h, m));
|
|
1339
|
+
} else {
|
|
1340
|
+
const h = selectedHour >= 0 ? selectedHour : 12;
|
|
1341
|
+
onChange(buildValue(datePart, h, m));
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
React14.useEffect(() => {
|
|
1345
|
+
if (open) {
|
|
1346
|
+
setTimeout(() => {
|
|
1347
|
+
if (hourRef.current && selectedHour >= 0) {
|
|
1348
|
+
const el = hourRef.current.querySelector(`[data-hour="${selectedHour}"]`);
|
|
1349
|
+
el?.scrollIntoView({ block: "center" });
|
|
1350
|
+
}
|
|
1351
|
+
if (minuteRef.current && selectedMinute >= 0) {
|
|
1352
|
+
const el = minuteRef.current.querySelector(`[data-minute="${selectedMinute}"]`);
|
|
1353
|
+
el?.scrollIntoView({ block: "center" });
|
|
1354
|
+
}
|
|
1355
|
+
}, 50);
|
|
1356
|
+
}
|
|
1357
|
+
}, [open, selectedHour, selectedMinute]);
|
|
1358
|
+
return /* @__PURE__ */ jsxs10(Popover, { open, onOpenChange: setOpen, children: [
|
|
1359
|
+
/* @__PURE__ */ jsx16(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
|
|
1360
|
+
Button,
|
|
1361
|
+
{
|
|
1362
|
+
type: "button",
|
|
1363
|
+
variant: "outline",
|
|
1364
|
+
disabled,
|
|
1365
|
+
className: cn(
|
|
1366
|
+
"w-full justify-start text-left font-normal h-10 bg-zinc-800 border-none text-white shadow-input rounded-md px-3 py-2 text-sm",
|
|
1367
|
+
"focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-neutral-600",
|
|
1368
|
+
"shadow-[0px_0px_1px_1px_var(--neutral-700)]",
|
|
1369
|
+
"hover:shadow-none transition duration-400",
|
|
1370
|
+
!value && "text-neutral-400",
|
|
1371
|
+
className
|
|
1372
|
+
),
|
|
1373
|
+
children: [
|
|
1374
|
+
/* @__PURE__ */ jsx16(CalendarIcon2, { className: "mr-2 h-4 w-4 shrink-0" }),
|
|
1375
|
+
value ? formatDisplay(value) : /* @__PURE__ */ jsx16("span", { children: placeholder })
|
|
1376
|
+
]
|
|
1377
|
+
}
|
|
1378
|
+
) }),
|
|
1379
|
+
/* @__PURE__ */ jsx16(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsxs10("div", { className: "flex", children: [
|
|
1380
|
+
/* @__PURE__ */ jsx16(
|
|
1381
|
+
Calendar,
|
|
1382
|
+
{
|
|
1383
|
+
mode: "single",
|
|
1384
|
+
selected: selectedDate,
|
|
1385
|
+
onSelect: handleDateSelect,
|
|
1386
|
+
initialFocus: true
|
|
1387
|
+
}
|
|
1388
|
+
),
|
|
1389
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex border-l border-zinc-800", children: [
|
|
1390
|
+
/* @__PURE__ */ jsxs10(
|
|
1391
|
+
"div",
|
|
1392
|
+
{
|
|
1393
|
+
ref: hourRef,
|
|
1394
|
+
className: "h-[280px] w-16 overflow-y-auto p-1",
|
|
1395
|
+
children: [
|
|
1396
|
+
/* @__PURE__ */ jsx16("div", { className: "px-1 py-1.5 text-center text-xs text-zinc-400 font-medium", children: "Hr" }),
|
|
1397
|
+
Array.from({ length: 24 }, (_, i) => /* @__PURE__ */ jsx16(
|
|
1398
|
+
"button",
|
|
1399
|
+
{
|
|
1400
|
+
"data-hour": i,
|
|
1401
|
+
type: "button",
|
|
1402
|
+
onClick: () => handleHourSelect(i),
|
|
1403
|
+
className: cn(
|
|
1404
|
+
"w-full rounded-md px-2 py-1.5 text-sm text-center cursor-pointer transition-colors",
|
|
1405
|
+
selectedHour === i ? "bg-zinc-50 text-zinc-900 font-medium" : "text-zinc-300 hover:bg-zinc-800"
|
|
1406
|
+
),
|
|
1407
|
+
children: i.toString().padStart(2, "0")
|
|
1408
|
+
},
|
|
1409
|
+
i
|
|
1410
|
+
))
|
|
1411
|
+
]
|
|
1412
|
+
}
|
|
1413
|
+
),
|
|
1414
|
+
/* @__PURE__ */ jsxs10(
|
|
1415
|
+
"div",
|
|
1416
|
+
{
|
|
1417
|
+
ref: minuteRef,
|
|
1418
|
+
className: "h-[280px] w-16 overflow-y-auto border-l border-zinc-800 p-1",
|
|
1419
|
+
children: [
|
|
1420
|
+
/* @__PURE__ */ jsx16("div", { className: "px-1 py-1.5 text-center text-xs text-zinc-400 font-medium", children: "Min" }),
|
|
1421
|
+
Array.from({ length: 12 }, (_, i) => i * 5).map((m) => /* @__PURE__ */ jsx16(
|
|
1422
|
+
"button",
|
|
1423
|
+
{
|
|
1424
|
+
"data-minute": m,
|
|
1425
|
+
type: "button",
|
|
1426
|
+
onClick: () => handleMinuteSelect(m),
|
|
1427
|
+
className: cn(
|
|
1428
|
+
"w-full rounded-md px-2 py-1.5 text-sm text-center cursor-pointer transition-colors",
|
|
1429
|
+
selectedMinute === m ? "bg-zinc-50 text-zinc-900 font-medium" : "text-zinc-300 hover:bg-zinc-800"
|
|
1430
|
+
),
|
|
1431
|
+
children: m.toString().padStart(2, "0")
|
|
1432
|
+
},
|
|
1433
|
+
m
|
|
1434
|
+
))
|
|
1435
|
+
]
|
|
1436
|
+
}
|
|
1437
|
+
)
|
|
1438
|
+
] })
|
|
1439
|
+
] }) })
|
|
1440
|
+
] });
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// src/ui/chart.tsx
|
|
1444
|
+
import * as React15 from "react";
|
|
818
1445
|
import * as RechartsPrimitive from "recharts";
|
|
819
|
-
import { Fragment as Fragment3, jsx as
|
|
1446
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
820
1447
|
var THEMES = { light: "", dark: ".dark" };
|
|
821
|
-
var ChartContext =
|
|
1448
|
+
var ChartContext = React15.createContext(null);
|
|
822
1449
|
function useChart() {
|
|
823
|
-
const context =
|
|
1450
|
+
const context = React15.useContext(ChartContext);
|
|
824
1451
|
if (!context) {
|
|
825
1452
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
826
1453
|
}
|
|
@@ -833,9 +1460,9 @@ function ChartContainer({
|
|
|
833
1460
|
config,
|
|
834
1461
|
...props
|
|
835
1462
|
}) {
|
|
836
|
-
const uniqueId =
|
|
1463
|
+
const uniqueId = React15.useId();
|
|
837
1464
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
838
|
-
return /* @__PURE__ */
|
|
1465
|
+
return /* @__PURE__ */ jsx17(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs11(
|
|
839
1466
|
"div",
|
|
840
1467
|
{
|
|
841
1468
|
"data-slot": "chart",
|
|
@@ -846,8 +1473,8 @@ function ChartContainer({
|
|
|
846
1473
|
),
|
|
847
1474
|
...props,
|
|
848
1475
|
children: [
|
|
849
|
-
/* @__PURE__ */
|
|
850
|
-
/* @__PURE__ */
|
|
1476
|
+
/* @__PURE__ */ jsx17(ChartStyle, { id: chartId, config }),
|
|
1477
|
+
/* @__PURE__ */ jsx17(RechartsPrimitive.ResponsiveContainer, { children })
|
|
851
1478
|
]
|
|
852
1479
|
}
|
|
853
1480
|
) });
|
|
@@ -859,7 +1486,7 @@ var ChartStyle = ({ id, config }) => {
|
|
|
859
1486
|
if (!colorConfig.length) {
|
|
860
1487
|
return null;
|
|
861
1488
|
}
|
|
862
|
-
return /* @__PURE__ */
|
|
1489
|
+
return /* @__PURE__ */ jsx17(
|
|
863
1490
|
"style",
|
|
864
1491
|
{
|
|
865
1492
|
dangerouslySetInnerHTML: {
|
|
@@ -894,7 +1521,7 @@ function ChartTooltipContent({
|
|
|
894
1521
|
labelKey
|
|
895
1522
|
}) {
|
|
896
1523
|
const { config } = useChart();
|
|
897
|
-
const tooltipLabel =
|
|
1524
|
+
const tooltipLabel = React15.useMemo(() => {
|
|
898
1525
|
if (hideLabel || !payload?.length) {
|
|
899
1526
|
return null;
|
|
900
1527
|
}
|
|
@@ -903,12 +1530,12 @@ function ChartTooltipContent({
|
|
|
903
1530
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
904
1531
|
const value = !labelKey && typeof label === "string" ? config[label]?.label || label : itemConfig?.label;
|
|
905
1532
|
if (labelFormatter) {
|
|
906
|
-
return /* @__PURE__ */
|
|
1533
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("font-medium", labelClassName), children: labelFormatter(value, payload) });
|
|
907
1534
|
}
|
|
908
1535
|
if (!value) {
|
|
909
1536
|
return null;
|
|
910
1537
|
}
|
|
911
|
-
return /* @__PURE__ */
|
|
1538
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("font-medium", labelClassName), children: value });
|
|
912
1539
|
}, [
|
|
913
1540
|
label,
|
|
914
1541
|
labelFormatter,
|
|
@@ -922,7 +1549,7 @@ function ChartTooltipContent({
|
|
|
922
1549
|
return null;
|
|
923
1550
|
}
|
|
924
1551
|
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
925
|
-
return /* @__PURE__ */
|
|
1552
|
+
return /* @__PURE__ */ jsxs11(
|
|
926
1553
|
"div",
|
|
927
1554
|
{
|
|
928
1555
|
className: cn(
|
|
@@ -931,19 +1558,19 @@ function ChartTooltipContent({
|
|
|
931
1558
|
),
|
|
932
1559
|
children: [
|
|
933
1560
|
!nestLabel ? tooltipLabel : null,
|
|
934
|
-
/* @__PURE__ */
|
|
1561
|
+
/* @__PURE__ */ jsx17("div", { className: "grid gap-1.5", children: payload.filter((item) => item.type !== "none").map((item, index) => {
|
|
935
1562
|
const key = `${nameKey || item.name || item.dataKey || "value"}`;
|
|
936
1563
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
937
1564
|
const indicatorColor = color || item.payload.fill || item.color;
|
|
938
|
-
return /* @__PURE__ */
|
|
1565
|
+
return /* @__PURE__ */ jsx17(
|
|
939
1566
|
"div",
|
|
940
1567
|
{
|
|
941
1568
|
className: cn(
|
|
942
1569
|
"flex w-full flex-wrap items-stretch gap-2",
|
|
943
1570
|
indicator === "dot" && "items-center"
|
|
944
1571
|
),
|
|
945
|
-
children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */
|
|
946
|
-
itemConfig?.icon ? /* @__PURE__ */
|
|
1572
|
+
children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
1573
|
+
itemConfig?.icon ? /* @__PURE__ */ jsx17(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsx17(
|
|
947
1574
|
"div",
|
|
948
1575
|
{
|
|
949
1576
|
className: cn(
|
|
@@ -961,7 +1588,7 @@ function ChartTooltipContent({
|
|
|
961
1588
|
}
|
|
962
1589
|
}
|
|
963
1590
|
),
|
|
964
|
-
/* @__PURE__ */
|
|
1591
|
+
/* @__PURE__ */ jsxs11(
|
|
965
1592
|
"div",
|
|
966
1593
|
{
|
|
967
1594
|
className: cn(
|
|
@@ -969,11 +1596,11 @@ function ChartTooltipContent({
|
|
|
969
1596
|
nestLabel ? "items-end" : "items-center"
|
|
970
1597
|
),
|
|
971
1598
|
children: [
|
|
972
|
-
/* @__PURE__ */
|
|
1599
|
+
/* @__PURE__ */ jsxs11("div", { className: "grid gap-1.5", children: [
|
|
973
1600
|
nestLabel ? tooltipLabel : null,
|
|
974
|
-
/* @__PURE__ */
|
|
1601
|
+
/* @__PURE__ */ jsx17("span", { className: "text-[var(--ash-grey)]", children: itemConfig?.label || item.name })
|
|
975
1602
|
] }),
|
|
976
|
-
item.value && /* @__PURE__ */
|
|
1603
|
+
item.value && /* @__PURE__ */ jsx17("span", { className: "text-[var(--timberwolf)] font-mono font-medium tabular-nums", children: item.value.toLocaleString() })
|
|
977
1604
|
]
|
|
978
1605
|
}
|
|
979
1606
|
)
|
|
@@ -998,7 +1625,7 @@ function ChartLegendContent({
|
|
|
998
1625
|
if (!payload?.length) {
|
|
999
1626
|
return null;
|
|
1000
1627
|
}
|
|
1001
|
-
return /* @__PURE__ */
|
|
1628
|
+
return /* @__PURE__ */ jsx17(
|
|
1002
1629
|
"div",
|
|
1003
1630
|
{
|
|
1004
1631
|
className: cn(
|
|
@@ -1009,14 +1636,14 @@ function ChartLegendContent({
|
|
|
1009
1636
|
children: payload.filter((item) => item.type !== "none").map((item) => {
|
|
1010
1637
|
const key = `${nameKey || item.dataKey || "value"}`;
|
|
1011
1638
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
1012
|
-
return /* @__PURE__ */
|
|
1639
|
+
return /* @__PURE__ */ jsxs11(
|
|
1013
1640
|
"div",
|
|
1014
1641
|
{
|
|
1015
1642
|
className: cn(
|
|
1016
1643
|
"flex items-center gap-1.5 text-[var(--ash-grey)]"
|
|
1017
1644
|
),
|
|
1018
1645
|
children: [
|
|
1019
|
-
itemConfig?.icon && !hideIcon ? /* @__PURE__ */
|
|
1646
|
+
itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsx17(itemConfig.icon, {}) : /* @__PURE__ */ jsx17(
|
|
1020
1647
|
"div",
|
|
1021
1648
|
{
|
|
1022
1649
|
className: "h-2 w-2 shrink-0 rounded-[2px]",
|
|
@@ -1051,6 +1678,8 @@ export {
|
|
|
1051
1678
|
AnimatedTooltip,
|
|
1052
1679
|
Badge,
|
|
1053
1680
|
Button,
|
|
1681
|
+
Calendar,
|
|
1682
|
+
CalendarDayButton,
|
|
1054
1683
|
Card,
|
|
1055
1684
|
CardContent,
|
|
1056
1685
|
CardDescription,
|
|
@@ -1063,6 +1692,8 @@ export {
|
|
|
1063
1692
|
ChartStyle,
|
|
1064
1693
|
ChartTooltip,
|
|
1065
1694
|
ChartTooltipContent,
|
|
1695
|
+
DatePicker,
|
|
1696
|
+
DateTimePicker,
|
|
1066
1697
|
Dialog,
|
|
1067
1698
|
DialogClose,
|
|
1068
1699
|
DialogContent,
|
|
@@ -1082,14 +1713,21 @@ export {
|
|
|
1082
1713
|
HoverEffect,
|
|
1083
1714
|
Input,
|
|
1084
1715
|
Label,
|
|
1716
|
+
Popover,
|
|
1717
|
+
PopoverAnchor,
|
|
1718
|
+
PopoverContent,
|
|
1719
|
+
PopoverTrigger,
|
|
1085
1720
|
Select,
|
|
1086
1721
|
SelectContent,
|
|
1087
1722
|
SelectGroup,
|
|
1088
1723
|
SelectItem,
|
|
1089
1724
|
SelectLabel,
|
|
1725
|
+
SelectScrollDownButton,
|
|
1726
|
+
SelectScrollUpButton,
|
|
1090
1727
|
SelectSeparator,
|
|
1091
1728
|
SelectTrigger,
|
|
1092
1729
|
SelectValue,
|
|
1730
|
+
TimePicker,
|
|
1093
1731
|
badgeVariants,
|
|
1094
1732
|
buttonVariants
|
|
1095
1733
|
};
|