@neoptocom/neopto-ui 1.5.3 → 1.6.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.
- package/dist/index.cjs +398 -85
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +363 -52
- package/package.json +1 -1
- package/src/components/Autocomplete.tsx +1 -1
- package/src/components/Calendar.tsx +217 -0
- package/src/components/DateInput.tsx +225 -0
- package/src/components/Input.tsx +28 -2
- package/src/index.ts +5 -1
- package/src/stories/DateInput.stories.tsx +136 -0
- package/src/stories/Input.stories.tsx +11 -0
package/dist/index.d.cts
CHANGED
|
@@ -70,6 +70,8 @@ type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
|
70
70
|
legendProps?: React.HTMLAttributes<HTMLLegendElement>;
|
|
71
71
|
/** Flag to visually mark the input as errored */
|
|
72
72
|
error?: boolean;
|
|
73
|
+
/** Optional icon name to display on the inner right of the input */
|
|
74
|
+
icon?: string;
|
|
73
75
|
};
|
|
74
76
|
declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
75
77
|
/** Input visual variant */
|
|
@@ -82,6 +84,8 @@ declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttribu
|
|
|
82
84
|
legendProps?: React.HTMLAttributes<HTMLLegendElement>;
|
|
83
85
|
/** Flag to visually mark the input as errored */
|
|
84
86
|
error?: boolean;
|
|
87
|
+
/** Optional icon name to display on the inner right of the input */
|
|
88
|
+
icon?: string;
|
|
85
89
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
86
90
|
|
|
87
91
|
type TextareaProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'> & {
|
|
@@ -388,4 +392,51 @@ interface BreadcrumbProps {
|
|
|
388
392
|
*/
|
|
389
393
|
declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
|
|
390
394
|
|
|
391
|
-
|
|
395
|
+
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type"> & {
|
|
396
|
+
/** Label text displayed above the input */
|
|
397
|
+
label?: string;
|
|
398
|
+
/** Current date value */
|
|
399
|
+
value?: Date | null;
|
|
400
|
+
/** Callback when date changes */
|
|
401
|
+
onChange: (date: Date) => void;
|
|
402
|
+
/** Flag to visually mark the input as errored */
|
|
403
|
+
error?: boolean;
|
|
404
|
+
/** Minimum selectable date */
|
|
405
|
+
minDate?: Date;
|
|
406
|
+
/** Maximum selectable date */
|
|
407
|
+
maxDate?: Date;
|
|
408
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
409
|
+
placeholder?: string;
|
|
410
|
+
};
|
|
411
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type" | "value"> & {
|
|
412
|
+
/** Label text displayed above the input */
|
|
413
|
+
label?: string;
|
|
414
|
+
/** Current date value */
|
|
415
|
+
value?: Date | null;
|
|
416
|
+
/** Callback when date changes */
|
|
417
|
+
onChange: (date: Date) => void;
|
|
418
|
+
/** Flag to visually mark the input as errored */
|
|
419
|
+
error?: boolean;
|
|
420
|
+
/** Minimum selectable date */
|
|
421
|
+
minDate?: Date;
|
|
422
|
+
/** Maximum selectable date */
|
|
423
|
+
maxDate?: Date;
|
|
424
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
425
|
+
placeholder?: string;
|
|
426
|
+
} & React.RefAttributes<HTMLInputElement>>;
|
|
427
|
+
|
|
428
|
+
type CalendarProps = {
|
|
429
|
+
/** Currently selected date */
|
|
430
|
+
selectedDate?: Date;
|
|
431
|
+
/** Callback when a date is selected */
|
|
432
|
+
onDateSelect: (date: Date) => void;
|
|
433
|
+
/** Today's date (for highlighting) */
|
|
434
|
+
today?: Date;
|
|
435
|
+
/** Minimum selectable date */
|
|
436
|
+
minDate?: Date;
|
|
437
|
+
/** Maximum selectable date */
|
|
438
|
+
maxDate?: Date;
|
|
439
|
+
};
|
|
440
|
+
declare function Calendar({ selectedDate, onDateSelect, today, minDate, maxDate, }: CalendarProps): react_jsx_runtime.JSX.Element;
|
|
441
|
+
|
|
442
|
+
export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, DateInput, type DateInputProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
|
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
|
70
70
|
legendProps?: React.HTMLAttributes<HTMLLegendElement>;
|
|
71
71
|
/** Flag to visually mark the input as errored */
|
|
72
72
|
error?: boolean;
|
|
73
|
+
/** Optional icon name to display on the inner right of the input */
|
|
74
|
+
icon?: string;
|
|
73
75
|
};
|
|
74
76
|
declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & {
|
|
75
77
|
/** Input visual variant */
|
|
@@ -82,6 +84,8 @@ declare const Input: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttribu
|
|
|
82
84
|
legendProps?: React.HTMLAttributes<HTMLLegendElement>;
|
|
83
85
|
/** Flag to visually mark the input as errored */
|
|
84
86
|
error?: boolean;
|
|
87
|
+
/** Optional icon name to display on the inner right of the input */
|
|
88
|
+
icon?: string;
|
|
85
89
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
86
90
|
|
|
87
91
|
type TextareaProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'> & {
|
|
@@ -388,4 +392,51 @@ interface BreadcrumbProps {
|
|
|
388
392
|
*/
|
|
389
393
|
declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
|
|
390
394
|
|
|
391
|
-
|
|
395
|
+
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type"> & {
|
|
396
|
+
/** Label text displayed above the input */
|
|
397
|
+
label?: string;
|
|
398
|
+
/** Current date value */
|
|
399
|
+
value?: Date | null;
|
|
400
|
+
/** Callback when date changes */
|
|
401
|
+
onChange: (date: Date) => void;
|
|
402
|
+
/** Flag to visually mark the input as errored */
|
|
403
|
+
error?: boolean;
|
|
404
|
+
/** Minimum selectable date */
|
|
405
|
+
minDate?: Date;
|
|
406
|
+
/** Maximum selectable date */
|
|
407
|
+
maxDate?: Date;
|
|
408
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
409
|
+
placeholder?: string;
|
|
410
|
+
};
|
|
411
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type" | "value"> & {
|
|
412
|
+
/** Label text displayed above the input */
|
|
413
|
+
label?: string;
|
|
414
|
+
/** Current date value */
|
|
415
|
+
value?: Date | null;
|
|
416
|
+
/** Callback when date changes */
|
|
417
|
+
onChange: (date: Date) => void;
|
|
418
|
+
/** Flag to visually mark the input as errored */
|
|
419
|
+
error?: boolean;
|
|
420
|
+
/** Minimum selectable date */
|
|
421
|
+
minDate?: Date;
|
|
422
|
+
/** Maximum selectable date */
|
|
423
|
+
maxDate?: Date;
|
|
424
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
425
|
+
placeholder?: string;
|
|
426
|
+
} & React.RefAttributes<HTMLInputElement>>;
|
|
427
|
+
|
|
428
|
+
type CalendarProps = {
|
|
429
|
+
/** Currently selected date */
|
|
430
|
+
selectedDate?: Date;
|
|
431
|
+
/** Callback when a date is selected */
|
|
432
|
+
onDateSelect: (date: Date) => void;
|
|
433
|
+
/** Today's date (for highlighting) */
|
|
434
|
+
today?: Date;
|
|
435
|
+
/** Minimum selectable date */
|
|
436
|
+
minDate?: Date;
|
|
437
|
+
/** Maximum selectable date */
|
|
438
|
+
maxDate?: Date;
|
|
439
|
+
};
|
|
440
|
+
declare function Calendar({ selectedDate, onDateSelect, today, minDate, maxDate, }: CalendarProps): react_jsx_runtime.JSX.Element;
|
|
441
|
+
|
|
442
|
+
export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, DateInput, type DateInputProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import * as
|
|
2
|
+
import * as React11 from 'react';
|
|
3
3
|
import { useState, useEffect, useMemo, useId, useRef, useCallback } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
|
|
@@ -243,7 +243,40 @@ function Card({
|
|
|
243
243
|
}
|
|
244
244
|
);
|
|
245
245
|
}
|
|
246
|
-
var
|
|
246
|
+
var sizeMap = {
|
|
247
|
+
sm: 16,
|
|
248
|
+
md: 24,
|
|
249
|
+
lg: 36
|
|
250
|
+
};
|
|
251
|
+
function Icon({
|
|
252
|
+
name,
|
|
253
|
+
className = "",
|
|
254
|
+
title,
|
|
255
|
+
size = "md",
|
|
256
|
+
fill = 0
|
|
257
|
+
}) {
|
|
258
|
+
const fontSize = sizeMap[size] ?? sizeMap.md;
|
|
259
|
+
const hasColorClass = /\b(?:text-|fill-|stroke-)\S+/.test(className);
|
|
260
|
+
const style = {
|
|
261
|
+
fontVariationSettings: `'FILL' ${fill}, 'wght' 300, 'GRAD' 0, 'opsz' ${fontSize}`,
|
|
262
|
+
fontSize,
|
|
263
|
+
lineHeight: 1,
|
|
264
|
+
display: "inline-block",
|
|
265
|
+
verticalAlign: "middle",
|
|
266
|
+
...hasColorClass ? {} : { color: "inherit" }
|
|
267
|
+
};
|
|
268
|
+
return /* @__PURE__ */ jsx(
|
|
269
|
+
"span",
|
|
270
|
+
{
|
|
271
|
+
className: `material-symbols-rounded rounded ${className}`,
|
|
272
|
+
style,
|
|
273
|
+
"aria-hidden": title ? void 0 : true,
|
|
274
|
+
title,
|
|
275
|
+
children: name
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
var Input = React11.forwardRef(
|
|
247
280
|
({
|
|
248
281
|
className,
|
|
249
282
|
disabled,
|
|
@@ -252,14 +285,17 @@ var Input = React3.forwardRef(
|
|
|
252
285
|
fieldsetProps,
|
|
253
286
|
legendProps,
|
|
254
287
|
error = false,
|
|
288
|
+
icon,
|
|
255
289
|
...props
|
|
256
290
|
}, ref) => {
|
|
257
291
|
const isInlineVariant = variant === "inline";
|
|
258
292
|
const shouldUseInlineStyles = isInlineVariant || Boolean(label);
|
|
259
293
|
const isError = error && !disabled;
|
|
294
|
+
const hasIcon = Boolean(icon);
|
|
260
295
|
const inputClasses = [
|
|
261
296
|
"w-full bg-transparent outline-none transition-colors",
|
|
262
|
-
shouldUseInlineStyles ? "h-9" : "h-12
|
|
297
|
+
shouldUseInlineStyles ? "h-9" : "h-12 rounded-full",
|
|
298
|
+
shouldUseInlineStyles ? hasIcon ? "pr-8" : "" : hasIcon ? "px-4 pr-10" : "px-4",
|
|
263
299
|
"font-['Poppins'] text-sm placeholder:text-[var(--muted-fg)]"
|
|
264
300
|
];
|
|
265
301
|
if (!shouldUseInlineStyles) {
|
|
@@ -286,6 +322,12 @@ var Input = React3.forwardRef(
|
|
|
286
322
|
const inputClassName = inputClasses.join(" ");
|
|
287
323
|
const inputElement = /* @__PURE__ */ jsx("input", { ref, disabled, className: inputClassName, ...props });
|
|
288
324
|
if (!label) {
|
|
325
|
+
if (hasIcon) {
|
|
326
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
327
|
+
inputElement,
|
|
328
|
+
/* @__PURE__ */ jsx("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(Icon, { name: icon, className: "text-[var(--muted-fg)] opacity-50" }) })
|
|
329
|
+
] });
|
|
330
|
+
}
|
|
289
331
|
return inputElement;
|
|
290
332
|
}
|
|
291
333
|
const { className: fieldsetClassNameProp = "", ...restFieldsetProps } = fieldsetProps ?? {};
|
|
@@ -317,14 +359,17 @@ var Input = React3.forwardRef(
|
|
|
317
359
|
children: label
|
|
318
360
|
}
|
|
319
361
|
),
|
|
320
|
-
/* @__PURE__ */ jsx("div", { className: "relative flex pl-5 pr-3 pb-1 h-full", children: /* @__PURE__ */
|
|
362
|
+
/* @__PURE__ */ jsx("div", { className: "relative flex pl-5 pr-3 pb-1 h-full", children: /* @__PURE__ */ jsxs("div", { className: "flex w-full relative", children: [
|
|
363
|
+
inputElement,
|
|
364
|
+
hasIcon && /* @__PURE__ */ jsx("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(Icon, { name: icon, className: "text-[var(--muted-fg)] opacity-50" }) })
|
|
365
|
+
] }) })
|
|
321
366
|
]
|
|
322
367
|
}
|
|
323
368
|
);
|
|
324
369
|
}
|
|
325
370
|
);
|
|
326
371
|
Input.displayName = "Input";
|
|
327
|
-
var Textarea =
|
|
372
|
+
var Textarea = React11.forwardRef(
|
|
328
373
|
({ className, disabled, variant = "default", ...props }, ref) => {
|
|
329
374
|
const isInline = variant === "inline";
|
|
330
375
|
return /* @__PURE__ */ jsx(
|
|
@@ -353,7 +398,7 @@ var Textarea = React3.forwardRef(
|
|
|
353
398
|
);
|
|
354
399
|
Textarea.displayName = "Textarea";
|
|
355
400
|
function useIsomorphicLayoutEffect(effect, deps) {
|
|
356
|
-
const useEffectHook = typeof window !== "undefined" ?
|
|
401
|
+
const useEffectHook = typeof window !== "undefined" ? React11.useLayoutEffect : React11.useEffect;
|
|
357
402
|
useEffectHook(effect, deps);
|
|
358
403
|
}
|
|
359
404
|
function Modal({
|
|
@@ -365,9 +410,9 @@ function Modal({
|
|
|
365
410
|
zIndex = 50,
|
|
366
411
|
showDecorations = true
|
|
367
412
|
}) {
|
|
368
|
-
const [mounted, setMounted] =
|
|
369
|
-
const [isDark, setIsDark] =
|
|
370
|
-
|
|
413
|
+
const [mounted, setMounted] = React11.useState(false);
|
|
414
|
+
const [isDark, setIsDark] = React11.useState(false);
|
|
415
|
+
React11.useEffect(() => {
|
|
371
416
|
const checkDarkMode = () => {
|
|
372
417
|
const hasDarkClass = document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.querySelector(".dark") !== null;
|
|
373
418
|
setIsDark(hasDarkClass);
|
|
@@ -390,7 +435,7 @@ function Modal({
|
|
|
390
435
|
document.body.style.overflow = original;
|
|
391
436
|
};
|
|
392
437
|
}, [open]);
|
|
393
|
-
|
|
438
|
+
React11.useEffect(() => {
|
|
394
439
|
if (!open) return;
|
|
395
440
|
const onKey = (e) => {
|
|
396
441
|
if (e.key === "Escape") onClose?.();
|
|
@@ -550,7 +595,7 @@ function AvatarGroup({
|
|
|
550
595
|
overlapPx = 8,
|
|
551
596
|
withRings = true
|
|
552
597
|
}) {
|
|
553
|
-
const avatars =
|
|
598
|
+
const avatars = React11.Children.toArray(children);
|
|
554
599
|
const displayAvatars = typeof max === "number" ? avatars.slice(0, max) : avatars;
|
|
555
600
|
const extraCount = typeof max === "number" && avatars.length > max ? avatars.length - max : 0;
|
|
556
601
|
return /* @__PURE__ */ jsxs("div", { className: ["flex items-center", className].filter(Boolean).join(" "), children: [
|
|
@@ -604,39 +649,6 @@ function Skeleton({ className = "", rounded = "md", ...props }) {
|
|
|
604
649
|
}
|
|
605
650
|
);
|
|
606
651
|
}
|
|
607
|
-
var sizeMap = {
|
|
608
|
-
sm: 16,
|
|
609
|
-
md: 24,
|
|
610
|
-
lg: 36
|
|
611
|
-
};
|
|
612
|
-
function Icon({
|
|
613
|
-
name,
|
|
614
|
-
className = "",
|
|
615
|
-
title,
|
|
616
|
-
size = "md",
|
|
617
|
-
fill = 0
|
|
618
|
-
}) {
|
|
619
|
-
const fontSize = sizeMap[size] ?? sizeMap.md;
|
|
620
|
-
const hasColorClass = /\b(?:text-|fill-|stroke-)\S+/.test(className);
|
|
621
|
-
const style = {
|
|
622
|
-
fontVariationSettings: `'FILL' ${fill}, 'wght' 300, 'GRAD' 0, 'opsz' ${fontSize}`,
|
|
623
|
-
fontSize,
|
|
624
|
-
lineHeight: 1,
|
|
625
|
-
display: "inline-block",
|
|
626
|
-
verticalAlign: "middle",
|
|
627
|
-
...hasColorClass ? {} : { color: "inherit" }
|
|
628
|
-
};
|
|
629
|
-
return /* @__PURE__ */ jsx(
|
|
630
|
-
"span",
|
|
631
|
-
{
|
|
632
|
-
className: `material-symbols-rounded rounded ${className}`,
|
|
633
|
-
style,
|
|
634
|
-
"aria-hidden": title ? void 0 : true,
|
|
635
|
-
title,
|
|
636
|
-
children: name
|
|
637
|
-
}
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
652
|
function getIconButtonClasses(variant = "ghost", size = "md", className) {
|
|
641
653
|
const base = "cursor-pointer flex items-center justify-center rounded-full flex-shrink-0 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50";
|
|
642
654
|
const variants = {
|
|
@@ -651,7 +663,7 @@ function getIconButtonClasses(variant = "ghost", size = "md", className) {
|
|
|
651
663
|
};
|
|
652
664
|
return [base, variants[variant], sizes[size], className].filter(Boolean).join(" ");
|
|
653
665
|
}
|
|
654
|
-
var IconButton =
|
|
666
|
+
var IconButton = React11.forwardRef(
|
|
655
667
|
({
|
|
656
668
|
variant,
|
|
657
669
|
size,
|
|
@@ -810,7 +822,7 @@ function Autocomplete({
|
|
|
810
822
|
"fieldset",
|
|
811
823
|
{
|
|
812
824
|
className: [
|
|
813
|
-
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors h-
|
|
825
|
+
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors h-14",
|
|
814
826
|
"border-[var(--border)] focus-within:border-[var(--color-brand)]",
|
|
815
827
|
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
816
828
|
].join(" "),
|
|
@@ -1025,7 +1037,7 @@ function Search({
|
|
|
1025
1037
|
const el = list.children[idx];
|
|
1026
1038
|
el?.scrollIntoView({ block: "nearest" });
|
|
1027
1039
|
}
|
|
1028
|
-
|
|
1040
|
+
React11.useEffect(() => {
|
|
1029
1041
|
return () => {
|
|
1030
1042
|
if (searchTimeoutRef.current) {
|
|
1031
1043
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1132,7 +1144,7 @@ function getButtonClasses(variant = "primary", size = "md", fullWidth, className
|
|
|
1132
1144
|
className
|
|
1133
1145
|
].filter(Boolean).join(" ");
|
|
1134
1146
|
}
|
|
1135
|
-
var Button =
|
|
1147
|
+
var Button = React11.forwardRef(
|
|
1136
1148
|
({ variant, size, fullWidth, className, children, icon, ...props }, ref) => {
|
|
1137
1149
|
return /* @__PURE__ */ jsx(
|
|
1138
1150
|
"button",
|
|
@@ -1204,8 +1216,8 @@ function Counter({
|
|
|
1204
1216
|
className = "",
|
|
1205
1217
|
...props
|
|
1206
1218
|
}) {
|
|
1207
|
-
const [count, setCount] =
|
|
1208
|
-
|
|
1219
|
+
const [count, setCount] = React11.useState(value);
|
|
1220
|
+
React11.useEffect(() => {
|
|
1209
1221
|
setCount(value);
|
|
1210
1222
|
}, [value]);
|
|
1211
1223
|
const handleIncrement = () => {
|
|
@@ -1438,7 +1450,7 @@ var AgentButton = ({
|
|
|
1438
1450
|
);
|
|
1439
1451
|
};
|
|
1440
1452
|
var AgentButton_default = AgentButton;
|
|
1441
|
-
var MessageBubble =
|
|
1453
|
+
var MessageBubble = React11.forwardRef(
|
|
1442
1454
|
({ direction, color, children, className, ...props }, ref) => {
|
|
1443
1455
|
const borderRadiusClass = direction === "left" ? "[border-radius:16px_16px_16px_2px]" : direction === "right" ? "[border-radius:16px_16px_2px_16px]" : "rounded-2xl";
|
|
1444
1456
|
const backgroundColor = color || "var(--muted)";
|
|
@@ -1516,5 +1528,304 @@ var Breadcrumb = ({
|
|
|
1516
1528
|
] }, index);
|
|
1517
1529
|
}) }) });
|
|
1518
1530
|
};
|
|
1531
|
+
var DAYS_OF_WEEK = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1532
|
+
var MONTHS = [
|
|
1533
|
+
"January",
|
|
1534
|
+
"February",
|
|
1535
|
+
"March",
|
|
1536
|
+
"April",
|
|
1537
|
+
"May",
|
|
1538
|
+
"June",
|
|
1539
|
+
"July",
|
|
1540
|
+
"August",
|
|
1541
|
+
"September",
|
|
1542
|
+
"October",
|
|
1543
|
+
"November",
|
|
1544
|
+
"December"
|
|
1545
|
+
];
|
|
1546
|
+
function isSameDay(date1, date2) {
|
|
1547
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1548
|
+
}
|
|
1549
|
+
function isSameMonth(date1, date2) {
|
|
1550
|
+
return date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1551
|
+
}
|
|
1552
|
+
function startOfDay(date) {
|
|
1553
|
+
const d = new Date(date);
|
|
1554
|
+
d.setHours(0, 0, 0, 0);
|
|
1555
|
+
return d;
|
|
1556
|
+
}
|
|
1557
|
+
function Calendar({
|
|
1558
|
+
selectedDate,
|
|
1559
|
+
onDateSelect,
|
|
1560
|
+
today = /* @__PURE__ */ new Date(),
|
|
1561
|
+
minDate,
|
|
1562
|
+
maxDate
|
|
1563
|
+
}) {
|
|
1564
|
+
const [currentMonth, setCurrentMonth] = React11.useState(
|
|
1565
|
+
selectedDate || /* @__PURE__ */ new Date()
|
|
1566
|
+
);
|
|
1567
|
+
const todayStart = startOfDay(today);
|
|
1568
|
+
const selectedDateStart = selectedDate ? startOfDay(selectedDate) : null;
|
|
1569
|
+
const firstDayOfMonth = new Date(
|
|
1570
|
+
currentMonth.getFullYear(),
|
|
1571
|
+
currentMonth.getMonth(),
|
|
1572
|
+
1
|
|
1573
|
+
);
|
|
1574
|
+
const lastDayOfMonth = new Date(
|
|
1575
|
+
currentMonth.getFullYear(),
|
|
1576
|
+
currentMonth.getMonth() + 1,
|
|
1577
|
+
0
|
|
1578
|
+
);
|
|
1579
|
+
const daysInMonth = lastDayOfMonth.getDate();
|
|
1580
|
+
const startingDayOfWeek = firstDayOfMonth.getDay();
|
|
1581
|
+
const prevMonth = () => {
|
|
1582
|
+
setCurrentMonth(
|
|
1583
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
|
|
1584
|
+
);
|
|
1585
|
+
};
|
|
1586
|
+
const nextMonth = () => {
|
|
1587
|
+
setCurrentMonth(
|
|
1588
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
|
|
1589
|
+
);
|
|
1590
|
+
};
|
|
1591
|
+
const handleDateClick = (day) => {
|
|
1592
|
+
const date = new Date(
|
|
1593
|
+
currentMonth.getFullYear(),
|
|
1594
|
+
currentMonth.getMonth(),
|
|
1595
|
+
day
|
|
1596
|
+
);
|
|
1597
|
+
const dateStart = startOfDay(date);
|
|
1598
|
+
if (minDate && dateStart < startOfDay(minDate)) return;
|
|
1599
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return;
|
|
1600
|
+
onDateSelect(date);
|
|
1601
|
+
};
|
|
1602
|
+
const isDateDisabled = (day) => {
|
|
1603
|
+
const date = new Date(
|
|
1604
|
+
currentMonth.getFullYear(),
|
|
1605
|
+
currentMonth.getMonth(),
|
|
1606
|
+
day
|
|
1607
|
+
);
|
|
1608
|
+
const dateStart = startOfDay(date);
|
|
1609
|
+
if (minDate && dateStart < startOfDay(minDate)) return true;
|
|
1610
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return true;
|
|
1611
|
+
return false;
|
|
1612
|
+
};
|
|
1613
|
+
const days = [];
|
|
1614
|
+
for (let i = 0; i < startingDayOfWeek; i++) {
|
|
1615
|
+
days.push(null);
|
|
1616
|
+
}
|
|
1617
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
1618
|
+
days.push(day);
|
|
1619
|
+
}
|
|
1620
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
1621
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1622
|
+
/* @__PURE__ */ jsx(
|
|
1623
|
+
"button",
|
|
1624
|
+
{
|
|
1625
|
+
type: "button",
|
|
1626
|
+
onClick: prevMonth,
|
|
1627
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1628
|
+
"aria-label": "Previous month",
|
|
1629
|
+
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_left" })
|
|
1630
|
+
}
|
|
1631
|
+
),
|
|
1632
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-sm font-medium text-[var(--fg)]", children: [
|
|
1633
|
+
MONTHS[currentMonth.getMonth()],
|
|
1634
|
+
" ",
|
|
1635
|
+
currentMonth.getFullYear()
|
|
1636
|
+
] }),
|
|
1637
|
+
/* @__PURE__ */ jsx(
|
|
1638
|
+
"button",
|
|
1639
|
+
{
|
|
1640
|
+
type: "button",
|
|
1641
|
+
onClick: nextMonth,
|
|
1642
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1643
|
+
"aria-label": "Next month",
|
|
1644
|
+
children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_right" })
|
|
1645
|
+
}
|
|
1646
|
+
)
|
|
1647
|
+
] }),
|
|
1648
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS_OF_WEEK.map((day) => /* @__PURE__ */ jsx(
|
|
1649
|
+
"div",
|
|
1650
|
+
{
|
|
1651
|
+
className: "text-xs text-center text-[var(--muted-fg)] font-medium py-1",
|
|
1652
|
+
children: day
|
|
1653
|
+
},
|
|
1654
|
+
day
|
|
1655
|
+
)) }),
|
|
1656
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((day, idx) => {
|
|
1657
|
+
if (day === null) {
|
|
1658
|
+
return /* @__PURE__ */ jsx("div", { className: "aspect-square" }, `empty-${idx}`);
|
|
1659
|
+
}
|
|
1660
|
+
const date = new Date(
|
|
1661
|
+
currentMonth.getFullYear(),
|
|
1662
|
+
currentMonth.getMonth(),
|
|
1663
|
+
day
|
|
1664
|
+
);
|
|
1665
|
+
const dateStart = startOfDay(date);
|
|
1666
|
+
const isSelected = selectedDateStart && isSameDay(dateStart, selectedDateStart);
|
|
1667
|
+
const isToday = isSameDay(dateStart, todayStart);
|
|
1668
|
+
const isDisabled = isDateDisabled(day);
|
|
1669
|
+
const isCurrentMonth = isSameMonth(dateStart, currentMonth);
|
|
1670
|
+
return /* @__PURE__ */ jsx(
|
|
1671
|
+
"button",
|
|
1672
|
+
{
|
|
1673
|
+
type: "button",
|
|
1674
|
+
onClick: () => handleDateClick(day),
|
|
1675
|
+
disabled: isDisabled,
|
|
1676
|
+
className: [
|
|
1677
|
+
"aspect-square rounded-lg text-sm transition-colors",
|
|
1678
|
+
isSelected ? "bg-[var(--color-brand)] text-white font-medium" : isToday ? "bg-[var(--muted)] text-[var(--fg)] font-medium border border-[var(--color-brand)]" : "text-[var(--fg)] hover:bg-[var(--muted)]",
|
|
1679
|
+
isDisabled ? "opacity-30 cursor-not-allowed" : "cursor-pointer",
|
|
1680
|
+
!isCurrentMonth ? "opacity-50" : ""
|
|
1681
|
+
].filter(Boolean).join(" "),
|
|
1682
|
+
children: day
|
|
1683
|
+
},
|
|
1684
|
+
day
|
|
1685
|
+
);
|
|
1686
|
+
}) })
|
|
1687
|
+
] });
|
|
1688
|
+
}
|
|
1689
|
+
function formatDate(date) {
|
|
1690
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1691
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1692
|
+
const year = date.getFullYear();
|
|
1693
|
+
return `${day}/${month}/${year}`;
|
|
1694
|
+
}
|
|
1695
|
+
function parseDate(dateString) {
|
|
1696
|
+
const parts = dateString.split("/");
|
|
1697
|
+
if (parts.length !== 3) return null;
|
|
1698
|
+
const day = parseInt(parts[0], 10);
|
|
1699
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
1700
|
+
const year = parseInt(parts[2], 10);
|
|
1701
|
+
if (isNaN(day) || isNaN(month) || isNaN(year)) return null;
|
|
1702
|
+
const date = new Date(year, month, day);
|
|
1703
|
+
if (date.getDate() !== day || date.getMonth() !== month || date.getFullYear() !== year) {
|
|
1704
|
+
return null;
|
|
1705
|
+
}
|
|
1706
|
+
return date;
|
|
1707
|
+
}
|
|
1708
|
+
function isValidDate(date) {
|
|
1709
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
1710
|
+
}
|
|
1711
|
+
function startOfDay2(date) {
|
|
1712
|
+
const d = new Date(date);
|
|
1713
|
+
d.setHours(0, 0, 0, 0);
|
|
1714
|
+
return d;
|
|
1715
|
+
}
|
|
1716
|
+
var DateInput = React11.forwardRef(
|
|
1717
|
+
({
|
|
1718
|
+
label,
|
|
1719
|
+
value,
|
|
1720
|
+
onChange,
|
|
1721
|
+
error = false,
|
|
1722
|
+
disabled = false,
|
|
1723
|
+
minDate,
|
|
1724
|
+
maxDate,
|
|
1725
|
+
placeholder = "00/00/0000",
|
|
1726
|
+
className = "",
|
|
1727
|
+
...props
|
|
1728
|
+
}, ref) => {
|
|
1729
|
+
const [inputValue, setInputValue] = React11.useState(
|
|
1730
|
+
value && isValidDate(value) ? formatDate(value) : placeholder
|
|
1731
|
+
);
|
|
1732
|
+
const [isFocused, setIsFocused] = React11.useState(false);
|
|
1733
|
+
const [showCalendar, setShowCalendar] = React11.useState(false);
|
|
1734
|
+
const [initialDateSet, setInitialDateSet] = React11.useState(true);
|
|
1735
|
+
const containerRef = React11.useRef(null);
|
|
1736
|
+
React11.useEffect(() => {
|
|
1737
|
+
if (value && isValidDate(value)) {
|
|
1738
|
+
setInputValue(formatDate(value));
|
|
1739
|
+
} else {
|
|
1740
|
+
setInputValue(placeholder);
|
|
1741
|
+
}
|
|
1742
|
+
}, [value, placeholder]);
|
|
1743
|
+
React11.useEffect(() => {
|
|
1744
|
+
if (showCalendar && initialDateSet) {
|
|
1745
|
+
const today = /* @__PURE__ */ new Date();
|
|
1746
|
+
onChange(today);
|
|
1747
|
+
setInputValue(formatDate(today));
|
|
1748
|
+
setInitialDateSet(false);
|
|
1749
|
+
}
|
|
1750
|
+
}, [showCalendar, initialDateSet, onChange]);
|
|
1751
|
+
React11.useEffect(() => {
|
|
1752
|
+
const handleClickOutside = (event) => {
|
|
1753
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1754
|
+
setShowCalendar(false);
|
|
1755
|
+
setInitialDateSet(false);
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1759
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1760
|
+
}, []);
|
|
1761
|
+
const handleInputChange = (e) => {
|
|
1762
|
+
let rawValue = e.target.value;
|
|
1763
|
+
rawValue = rawValue.replace(/\D/g, "").replace(/^(\d{2})/, "$1/").replace(/^(\d{2}\/\d{2})/, "$1/").slice(0, 10);
|
|
1764
|
+
setInputValue(rawValue);
|
|
1765
|
+
if (rawValue.length === 10) {
|
|
1766
|
+
const parsedDate = parseDate(rawValue);
|
|
1767
|
+
if (parsedDate && isValidDate(parsedDate)) {
|
|
1768
|
+
onChange(parsedDate);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
};
|
|
1772
|
+
const handleCalendarSelect = (date) => {
|
|
1773
|
+
const selectedDate = parseDate(inputValue);
|
|
1774
|
+
const sameDay = selectedDate && isValidDate(selectedDate) && selectedDate.getDate() === date.getDate() && selectedDate.getMonth() === date.getMonth() && selectedDate.getFullYear() === date.getFullYear();
|
|
1775
|
+
if (!sameDay) {
|
|
1776
|
+
onChange(date);
|
|
1777
|
+
setInputValue(formatDate(date));
|
|
1778
|
+
}
|
|
1779
|
+
setInitialDateSet(false);
|
|
1780
|
+
setShowCalendar(false);
|
|
1781
|
+
};
|
|
1782
|
+
const handleInputFocus = () => {
|
|
1783
|
+
setIsFocused(true);
|
|
1784
|
+
setShowCalendar(true);
|
|
1785
|
+
};
|
|
1786
|
+
const handleInputBlur = () => {
|
|
1787
|
+
setIsFocused(false);
|
|
1788
|
+
const parsed = parseDate(inputValue);
|
|
1789
|
+
if (!parsed || !isValidDate(parsed)) {
|
|
1790
|
+
const today = /* @__PURE__ */ new Date();
|
|
1791
|
+
onChange(today);
|
|
1792
|
+
setInputValue(formatDate(today));
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
const isEmpty = inputValue === placeholder;
|
|
1796
|
+
const textColorClass = isEmpty ? "text-[var(--muted-fg)]" : "";
|
|
1797
|
+
return /* @__PURE__ */ jsxs("div", { className: ["relative w-full", className].join(" "), ref: containerRef, children: [
|
|
1798
|
+
/* @__PURE__ */ jsx(
|
|
1799
|
+
Input,
|
|
1800
|
+
{
|
|
1801
|
+
ref,
|
|
1802
|
+
label,
|
|
1803
|
+
type: "text",
|
|
1804
|
+
value: inputValue,
|
|
1805
|
+
onChange: handleInputChange,
|
|
1806
|
+
onFocus: handleInputFocus,
|
|
1807
|
+
onBlur: handleInputBlur,
|
|
1808
|
+
onClick: () => !disabled && setShowCalendar(true),
|
|
1809
|
+
disabled,
|
|
1810
|
+
error,
|
|
1811
|
+
icon: "calendar_today",
|
|
1812
|
+
className: textColorClass,
|
|
1813
|
+
...props
|
|
1814
|
+
}
|
|
1815
|
+
),
|
|
1816
|
+
showCalendar && !disabled && /* @__PURE__ */ jsx("div", { className: "absolute z-20 mt-2 w-full max-w-sm", children: /* @__PURE__ */ jsx(Card, { className: "p-4", showDecorations: false, children: /* @__PURE__ */ jsx(
|
|
1817
|
+
Calendar,
|
|
1818
|
+
{
|
|
1819
|
+
selectedDate: inputValue !== placeholder && parseDate(inputValue) && isValidDate(parseDate(inputValue)) ? parseDate(inputValue) : /* @__PURE__ */ new Date(),
|
|
1820
|
+
onDateSelect: handleCalendarSelect,
|
|
1821
|
+
today: startOfDay2(/* @__PURE__ */ new Date()),
|
|
1822
|
+
minDate,
|
|
1823
|
+
maxDate
|
|
1824
|
+
}
|
|
1825
|
+
) }) })
|
|
1826
|
+
] });
|
|
1827
|
+
}
|
|
1828
|
+
);
|
|
1829
|
+
DateInput.displayName = "DateInput";
|
|
1519
1830
|
|
|
1520
|
-
export { AgentButton_default as AgentButton, AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, BackgroundBlur, Breadcrumb, Button, Card, Chip, Counter, Icon, IconButton, Input, MessageBubble, Modal, Search, Separator, Skeleton, Textarea, Typo, assets_exports as assets };
|
|
1831
|
+
export { AgentButton_default as AgentButton, AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, BackgroundBlur, Breadcrumb, Button, Calendar, Card, Chip, Counter, DateInput, Icon, IconButton, Input, MessageBubble, Modal, Search, Separator, Skeleton, Textarea, Typo, assets_exports as assets };
|