@jbpark/ui-kit 3.0.0 → 3.1.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.
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/components/atoms/date-picker.d.ts
4
+ interface Props {
5
+ defaultValue?: Date;
6
+ value?: Date;
7
+ placeholder?: string;
8
+ className?: string;
9
+ onChange?: (date: Date | undefined) => void;
10
+ }
11
+ declare const DatePicker: ({
12
+ defaultValue,
13
+ value: _value,
14
+ placeholder,
15
+ className,
16
+ onChange: _onChange
17
+ }: Props) => react_jsx_runtime0.JSX.Element;
18
+ //#endregion
19
+ export { DatePicker };
20
+ //# sourceMappingURL=date-picker.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-picker.d.mts","names":[],"sources":["../../../src/components/atoms/date-picker.tsx"],"mappings":";;;UAeU,KAAA;EACR,YAAA,GAAe,IAAA;EACf,KAAA,GAAQ,IAAA;EACR,WAAA;EACA,SAAA;EACA,QAAA,IAAY,IAAA,EAAM,IAAA;AAAA;AAAA,cAGd,UAAA;EAAc,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,WAAA;EAAA,SAAA;EAAA,QAAA,EAAA;AAAA,GAMjB,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../utils.mjs";
4
+ import { button_exports } from "../../core/button.mjs";
5
+ import { calendar_exports } from "../../core/calendar.mjs";
6
+ import Popover from "./popover.mjs";
7
+ import { CalendarIcon } from "lucide-react";
8
+ import { useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { format } from "date-fns";
11
+
12
+ //#region src/components/atoms/date-picker.tsx
13
+ const { Calendar } = calendar_exports;
14
+ const { buttonVariants } = button_exports;
15
+ const DatePicker = ({ defaultValue, value: _value, placeholder = "Pick a date", className, onChange: _onChange = () => {} }) => {
16
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
17
+ const controlled = _value !== void 0;
18
+ const value = controlled ? _value : uncontrolledValue;
19
+ const onChange = (date) => {
20
+ if (!controlled) setUncontrolledValue(date);
21
+ _onChange(date);
22
+ };
23
+ return /* @__PURE__ */ jsx(Popover, {
24
+ placement: "bottomLeft",
25
+ content: /* @__PURE__ */ jsx(Calendar, {
26
+ mode: "single",
27
+ selected: value,
28
+ onSelect: onChange
29
+ }),
30
+ children: /* @__PURE__ */ jsxs("button", {
31
+ type: "button",
32
+ "data-empty": !value,
33
+ className: cn(buttonVariants({ variant: "outline" }), "w-full justify-start text-left font-normal", "data-[empty=true]:text-muted-foreground", className),
34
+ children: [/* @__PURE__ */ jsx(CalendarIcon, {}), value ? format(value, "PPP") : placeholder]
35
+ })
36
+ });
37
+ };
38
+
39
+ //#endregion
40
+ export { DatePicker as default };
41
+ //# sourceMappingURL=date-picker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-picker.mjs","names":["calendar","button"],"sources":["../../../src/components/atoms/date-picker.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\n\nimport { button, calendar } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport Popover from './popover';\n\nconst { Calendar } = calendar;\nconst { buttonVariants } = button;\n\ninterface Props {\n defaultValue?: Date;\n value?: Date;\n placeholder?: string;\n className?: string;\n onChange?: (date: Date | undefined) => void;\n}\n\nconst DatePicker = ({\n defaultValue,\n value: _value,\n placeholder = 'Pick a date',\n className,\n onChange: _onChange = () => {},\n}: Props) => {\n const [uncontrolledValue, setUncontrolledValue] = useState<Date | undefined>(\n defaultValue,\n );\n\n const controlled = _value !== undefined;\n const value = controlled ? _value : uncontrolledValue;\n\n const onChange = (date: Date | undefined) => {\n if (!controlled) {\n setUncontrolledValue(date);\n }\n _onChange(date);\n };\n\n return (\n <Popover\n placement=\"bottomLeft\"\n content={<Calendar mode=\"single\" selected={value} onSelect={onChange} />}\n >\n <button\n type=\"button\"\n data-empty={!value}\n className={cn(\n buttonVariants({ variant: 'outline' }),\n 'w-full justify-start text-left font-normal',\n 'data-[empty=true]:text-muted-foreground',\n className,\n //\n )}\n >\n <CalendarIcon />\n {value ? format(value, 'PPP') : placeholder}\n </button>\n </Popover>\n );\n};\n\nexport default DatePicker;\nexport type { Props };\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,EAAE,aAAaA;AACrB,MAAM,EAAE,mBAAmBC;AAU3B,MAAM,cAAc,EAClB,cACA,OAAO,QACP,cAAc,eACd,WACA,UAAU,kBAAkB,SACjB;CACX,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,aACD;CAED,MAAM,aAAa,WAAW;CAC9B,MAAM,QAAQ,aAAa,SAAS;CAEpC,MAAM,YAAY,SAA2B;AAC3C,MAAI,CAAC,WACH,sBAAqB,KAAK;AAE5B,YAAU,KAAK;;AAGjB,QACE,oBAAC;EACC,WAAU;EACV,SAAS,oBAAC;GAAS,MAAK;GAAS,UAAU;GAAO,UAAU;IAAY;YAExE,qBAAC;GACC,MAAK;GACL,cAAY,CAAC;GACb,WAAW,GACT,eAAe,EAAE,SAAS,WAAW,CAAC,EACtC,8CACA,2CACA,UAED;cAED,oBAAC,iBAAe,EACf,QAAQ,OAAO,OAAO,MAAM,GAAG;IACzB;GACD"}
@@ -4,17 +4,17 @@ import { cn } from "../../../utils.mjs";
4
4
  import FloatButton from "./float-button.mjs";
5
5
  import { ArrowUp } from "lucide-react";
6
6
  import { jsx } from "react/jsx-runtime";
7
- import { useWindowScroll } from "@uidotdev/usehooks";
7
+ import { useWindowScroll } from "@jbpark/use-hooks";
8
8
 
9
9
  //#region src/components/atoms/float-button/back-top.tsx
10
10
  const BackTop = ({ visibilityHeight = 450, className, onClick, ...props }) => {
11
- const [{ y }, scrollTo] = useWindowScroll();
11
+ const { y } = useWindowScroll();
12
12
  return /* @__PURE__ */ jsx(FloatButton, {
13
13
  "aria-label": "맨 위로",
14
14
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
15
15
  className: cn(className, (!y || visibilityHeight > y) && "hidden"),
16
16
  onClick: (e) => {
17
- scrollTo({
17
+ window.scrollTo({
18
18
  left: 0,
19
19
  top: 0,
20
20
  behavior: "smooth"
@@ -1 +1 @@
1
- {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { MouseEvent } from 'react';\n\nimport { useWindowScroll } from '@uidotdev/usehooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const [{ y }, scrollTo] = useWindowScroll();\n\n return (\n <FloatButton\n aria-label=\"맨 위로\"\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;AAiBA,MAAM,WAAW,EACf,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,CAAC,EAAE,KAAK,YAAY,iBAAiB;AAE3C,QACE,oBAAC;EACC,cAAW;EACX,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AACZ,YAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACjD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
1
+ {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { MouseEvent } from 'react';\n\nimport { useWindowScroll } from '@jbpark/use-hooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const { y } = useWindowScroll();\n\n return (\n <FloatButton\n aria-label=\"맨 위로\"\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;AAiBA,MAAM,WAAW,EACf,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,EAAE,MAAM,iBAAiB;AAE/B,QACE,oBAAC;EACC,cAAW;EACX,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AACZ,UAAO,SAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACxD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
@@ -3,6 +3,7 @@ import Tag from "../../Tag.mjs";
3
3
  import Typography from "../../Typography.mjs";
4
4
  import { Checkbox } from "./checkbox/index.mjs";
5
5
  import { ColorPicker } from "./color-picker.mjs";
6
+ import { DatePicker } from "./date-picker.mjs";
6
7
  import { FloatButton } from "./float-button/index.mjs";
7
8
  import { Input } from "./input/index.mjs";
8
9
  import { Popover } from "./popover.mjs";
@@ -6,4 +6,5 @@ import Space from "../../Space.mjs";
6
6
  import { Collapse } from "./collapse.mjs";
7
7
  import { Dropdown } from "./dropdown.mjs";
8
8
  import { Marquees } from "./marquees/index.mjs";
9
- import { Splitter } from "./splitter/index.mjs";
9
+ import { Splitter } from "./splitter/index.mjs";
10
+ import { Upload, UploadFile } from "./upload.mjs";
@@ -0,0 +1,37 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/components/molecules/upload.d.ts
4
+ interface UploadFile {
5
+ uid: string;
6
+ name: string;
7
+ url: string;
8
+ }
9
+ interface Props {
10
+ defaultValue?: UploadFile[];
11
+ value?: UploadFile[];
12
+ multiple?: boolean;
13
+ accept?: string;
14
+ maxCount?: number;
15
+ disabled?: boolean;
16
+ className?: string;
17
+ classNames?: {
18
+ dropzone?: string;
19
+ list?: string;
20
+ item?: string;
21
+ };
22
+ onChange?: (files: UploadFile[]) => void;
23
+ }
24
+ declare const Upload: ({
25
+ defaultValue,
26
+ value: _value,
27
+ multiple,
28
+ accept,
29
+ maxCount,
30
+ disabled,
31
+ className,
32
+ classNames,
33
+ onChange: _onChange
34
+ }: Props) => react_jsx_runtime0.JSX.Element;
35
+ //#endregion
36
+ export { Upload, UploadFile };
37
+ //# sourceMappingURL=upload.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.mts","names":[],"sources":["../../../src/components/molecules/upload.tsx"],"mappings":";;;UASiB,UAAA;EACf,GAAA;EACA,IAAA;EACA,GAAA;AAAA;AAAA,UAGe,KAAA;EACf,YAAA,GAAe,UAAA;EACf,KAAA,GAAQ,UAAA;EACR,QAAA;EACA,MAAA;EACA,QAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;IACE,QAAA;IACA,IAAA;IACA,IAAA;EAAA;EAEF,QAAA,IAAY,KAAA,EAAO,UAAA;AAAA;AAAA,cAOf,MAAA;EAAU,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,MAAA;EAAA,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,UAAA;EAAA,QAAA,EAAA;AAAA,GAUb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -0,0 +1,101 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../utils.mjs";
4
+ import { Upload, X } from "lucide-react";
5
+ import { useId, useState } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useFileToDataUrl } from "@jbpark/use-hooks";
8
+
9
+ //#region src/components/molecules/upload.tsx
10
+ const isImage = (file) => /^data:image\//.test(file.url) || /\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);
11
+ const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept = "image/*", maxCount, disabled, className, classNames, onChange: _onChange = () => {} }) => {
12
+ const inputId = useId();
13
+ const readAsDataUrl = useFileToDataUrl();
14
+ const [isDragOver, setIsDragOver] = useState(false);
15
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
16
+ const controlled = _value !== void 0;
17
+ const files = controlled ? _value : uncontrolledValue;
18
+ const onChange = (next) => {
19
+ if (!controlled) setUncontrolledValue(next);
20
+ _onChange(next);
21
+ };
22
+ const addFiles = async (fileList) => {
23
+ const incoming = Array.from(fileList);
24
+ const remaining = typeof maxCount === "number" ? Math.max(0, maxCount - files.length) : incoming.length;
25
+ const accepted = incoming.slice(0, remaining);
26
+ const uploaded = await Promise.all(accepted.map(async (file) => ({
27
+ uid: `${file.name}-${file.lastModified}-${file.size}`,
28
+ name: file.name,
29
+ url: await readAsDataUrl(file)
30
+ })));
31
+ onChange([...files, ...uploaded]);
32
+ };
33
+ const removeFile = (uid) => {
34
+ onChange(files.filter((file) => file.uid !== uid));
35
+ };
36
+ return /* @__PURE__ */ jsxs("div", {
37
+ className: cn("flex flex-col gap-3", className),
38
+ children: [/* @__PURE__ */ jsxs("label", {
39
+ htmlFor: inputId,
40
+ onDragOver: (e) => {
41
+ e.preventDefault();
42
+ if (!disabled) setIsDragOver(true);
43
+ },
44
+ onDragLeave: () => setIsDragOver(false),
45
+ onDrop: (e) => {
46
+ e.preventDefault();
47
+ setIsDragOver(false);
48
+ if (disabled) return;
49
+ if (e.dataTransfer.files.length) addFiles(e.dataTransfer.files);
50
+ },
51
+ className: cn("flex cursor-pointer flex-col items-center justify-center gap-2", "rounded-md border border-dashed p-6 text-center", "text-muted-foreground text-sm", "transition-colors", isDragOver && "border-primary bg-accent", disabled && "pointer-events-none cursor-not-allowed opacity-50", classNames?.dropzone),
52
+ children: [
53
+ /* @__PURE__ */ jsx(Upload, { className: "size-6" }),
54
+ /* @__PURE__ */ jsxs("span", { children: [
55
+ "Click or drag file",
56
+ multiple ? "s" : "",
57
+ " to upload"
58
+ ] }),
59
+ /* @__PURE__ */ jsx("input", {
60
+ id: inputId,
61
+ type: "file",
62
+ accept,
63
+ multiple,
64
+ disabled,
65
+ className: "hidden",
66
+ onChange: (e) => {
67
+ if (e.target.files?.length) addFiles(e.target.files);
68
+ e.target.value = "";
69
+ }
70
+ })
71
+ ]
72
+ }), files.length > 0 && /* @__PURE__ */ jsx("ul", {
73
+ className: cn("flex flex-col gap-2", classNames?.list),
74
+ children: files.map((file) => /* @__PURE__ */ jsxs("li", {
75
+ className: cn("flex items-center gap-2 rounded-md border p-2", classNames?.item),
76
+ children: [
77
+ isImage(file) && /* @__PURE__ */ jsx("img", {
78
+ src: file.url,
79
+ alt: "",
80
+ className: "size-10 shrink-0 rounded object-cover"
81
+ }),
82
+ /* @__PURE__ */ jsx("span", {
83
+ className: "flex-1 truncate text-sm",
84
+ children: file.name
85
+ }),
86
+ /* @__PURE__ */ jsx("button", {
87
+ type: "button",
88
+ onClick: () => removeFile(file.uid),
89
+ className: "text-muted-foreground hover:text-foreground shrink-0",
90
+ "aria-label": `Remove ${file.name}`,
91
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
92
+ })
93
+ ]
94
+ }, file.uid))
95
+ })]
96
+ });
97
+ };
98
+
99
+ //#endregion
100
+ export { Upload$1 as default };
101
+ //# sourceMappingURL=upload.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.mjs","names":["Upload","UploadIcon"],"sources":["../../../src/components/molecules/upload.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState } from 'react';\n\nimport { useFileToDataUrl } from '@jbpark/use-hooks';\nimport { Upload as UploadIcon, X } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nexport interface UploadFile {\n uid: string;\n name: string;\n url: string;\n}\n\nexport interface Props {\n defaultValue?: UploadFile[];\n value?: UploadFile[];\n multiple?: boolean;\n accept?: string;\n maxCount?: number;\n disabled?: boolean;\n className?: string;\n classNames?: {\n dropzone?: string;\n list?: string;\n item?: string;\n };\n onChange?: (files: UploadFile[]) => void;\n}\n\nconst isImage = (file: UploadFile) =>\n /^data:image\\//.test(file.url) ||\n /\\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);\n\nconst Upload = ({\n defaultValue = [],\n value: _value,\n multiple = true,\n accept = 'image/*',\n maxCount,\n disabled,\n className,\n classNames,\n onChange: _onChange = () => {},\n}: Props) => {\n const inputId = useId();\n const readAsDataUrl = useFileToDataUrl();\n const [isDragOver, setIsDragOver] = useState(false);\n const [uncontrolledValue, setUncontrolledValue] =\n useState<UploadFile[]>(defaultValue);\n\n const controlled = _value !== undefined;\n const files = controlled ? _value : uncontrolledValue;\n\n const onChange = (next: UploadFile[]) => {\n if (!controlled) {\n setUncontrolledValue(next);\n }\n _onChange(next);\n };\n\n const addFiles = async (fileList: FileList) => {\n const incoming = Array.from(fileList);\n const remaining =\n typeof maxCount === 'number'\n ? Math.max(0, maxCount - files.length)\n : incoming.length;\n\n const accepted = incoming.slice(0, remaining);\n\n const uploaded = await Promise.all(\n accepted.map(async file => ({\n uid: `${file.name}-${file.lastModified}-${file.size}`,\n name: file.name,\n url: await readAsDataUrl(file),\n })),\n );\n\n onChange([...files, ...uploaded]);\n };\n\n const removeFile = (uid: string) => {\n onChange(files.filter(file => file.uid !== uid));\n };\n\n return (\n <div\n className={cn(\n 'flex flex-col gap-3',\n className,\n //\n )}\n >\n <label\n htmlFor={inputId}\n onDragOver={e => {\n e.preventDefault();\n if (!disabled) {\n setIsDragOver(true);\n }\n }}\n onDragLeave={() => setIsDragOver(false)}\n onDrop={e => {\n e.preventDefault();\n setIsDragOver(false);\n\n if (disabled) {\n return;\n }\n\n if (e.dataTransfer.files.length) {\n addFiles(e.dataTransfer.files);\n }\n }}\n className={cn(\n 'flex cursor-pointer flex-col items-center justify-center gap-2',\n 'rounded-md border border-dashed p-6 text-center',\n 'text-muted-foreground text-sm',\n 'transition-colors',\n isDragOver && 'border-primary bg-accent',\n disabled && 'pointer-events-none cursor-not-allowed opacity-50',\n classNames?.dropzone,\n //\n )}\n >\n <UploadIcon className=\"size-6\" />\n <span>Click or drag file{multiple ? 's' : ''} to upload</span>\n <input\n id={inputId}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n className=\"hidden\"\n onChange={e => {\n if (e.target.files?.length) {\n addFiles(e.target.files);\n }\n e.target.value = '';\n }}\n />\n </label>\n\n {files.length > 0 && (\n <ul\n className={cn(\n 'flex flex-col gap-2',\n classNames?.list,\n //\n )}\n >\n {files.map(file => (\n <li\n key={file.uid}\n className={cn(\n 'flex items-center gap-2 rounded-md border p-2',\n classNames?.item,\n //\n )}\n >\n {isImage(file) && (\n <img\n src={file.url}\n alt=\"\"\n className=\"size-10 shrink-0 rounded object-cover\"\n />\n )}\n <span className=\"flex-1 truncate text-sm\">{file.name}</span>\n <button\n type=\"button\"\n onClick={() => removeFile(file.uid)}\n className=\"text-muted-foreground hover:text-foreground shrink-0\"\n aria-label={`Remove ${file.name}`}\n >\n <X className=\"size-4\" />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nexport default Upload;\n"],"mappings":";;;;;;;;;AA+BA,MAAM,WAAW,SACf,gBAAgB,KAAK,KAAK,IAAI,IAC9B,+BAA+B,KAAK,KAAK,KAAK;AAEhD,MAAMA,YAAU,EACd,eAAe,EAAE,EACjB,OAAO,QACP,WAAW,MACX,SAAS,WACT,UACA,UACA,WACA,YACA,UAAU,kBAAkB,SACjB;CACX,MAAM,UAAU,OAAO;CACvB,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,CAAC,mBAAmB,wBACxB,SAAuB,aAAa;CAEtC,MAAM,aAAa,WAAW;CAC9B,MAAM,QAAQ,aAAa,SAAS;CAEpC,MAAM,YAAY,SAAuB;AACvC,MAAI,CAAC,WACH,sBAAqB,KAAK;AAE5B,YAAU,KAAK;;CAGjB,MAAM,WAAW,OAAO,aAAuB;EAC7C,MAAM,WAAW,MAAM,KAAK,SAAS;EACrC,MAAM,YACJ,OAAO,aAAa,WAChB,KAAK,IAAI,GAAG,WAAW,MAAM,OAAO,GACpC,SAAS;EAEf,MAAM,WAAW,SAAS,MAAM,GAAG,UAAU;EAE7C,MAAM,WAAW,MAAM,QAAQ,IAC7B,SAAS,IAAI,OAAM,UAAS;GAC1B,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,aAAa,GAAG,KAAK;GAC/C,MAAM,KAAK;GACX,KAAK,MAAM,cAAc,KAAK;GAC/B,EAAE,CACJ;AAED,WAAS,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;;CAGnC,MAAM,cAAc,QAAgB;AAClC,WAAS,MAAM,QAAO,SAAQ,KAAK,QAAQ,IAAI,CAAC;;AAGlD,QACE,qBAAC;EACC,WAAW,GACT,uBACA,UAED;aAED,qBAAC;GACC,SAAS;GACT,aAAY,MAAK;AACf,MAAE,gBAAgB;AAClB,QAAI,CAAC,SACH,eAAc,KAAK;;GAGvB,mBAAmB,cAAc,MAAM;GACvC,SAAQ,MAAK;AACX,MAAE,gBAAgB;AAClB,kBAAc,MAAM;AAEpB,QAAI,SACF;AAGF,QAAI,EAAE,aAAa,MAAM,OACvB,UAAS,EAAE,aAAa,MAAM;;GAGlC,WAAW,GACT,kEACA,mDACA,iCACA,qBACA,cAAc,4BACd,YAAY,qDACZ,YAAY,SAEb;;IAED,oBAACC,UAAW,WAAU,WAAW;IACjC,qBAAC;KAAK;KAAmB,WAAW,MAAM;KAAG;QAAiB;IAC9D,oBAAC;KACC,IAAI;KACJ,MAAK;KACG;KACE;KACA;KACV,WAAU;KACV,WAAU,MAAK;AACb,UAAI,EAAE,OAAO,OAAO,OAClB,UAAS,EAAE,OAAO,MAAM;AAE1B,QAAE,OAAO,QAAQ;;MAEnB;;IACI,EAEP,MAAM,SAAS,KACd,oBAAC;GACC,WAAW,GACT,uBACA,YAAY,KAEb;aAEA,MAAM,KAAI,SACT,qBAAC;IAEC,WAAW,GACT,iDACA,YAAY,KAEb;;KAEA,QAAQ,KAAK,IACZ,oBAAC;MACC,KAAK,KAAK;MACV,KAAI;MACJ,WAAU;OACV;KAEJ,oBAAC;MAAK,WAAU;gBAA2B,KAAK;OAAY;KAC5D,oBAAC;MACC,MAAK;MACL,eAAe,WAAW,KAAK,IAAI;MACnC,WAAU;MACV,cAAY,UAAU,KAAK;gBAE3B,oBAAC,KAAE,WAAU,WAAW;OACjB;;MAtBJ,KAAK,IAuBP,CACL;IACC;GAEH"}
@@ -5,7 +5,7 @@ import Title from "../../atoms/typography/title.mjs";
5
5
  import Skeleton from "../../atoms/skeleton/index.mjs";
6
6
  import React, { useEffect, useRef } from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
- import { useIntersectionObserver } from "@uidotdev/usehooks";
8
+ import { useIntersectionObserver } from "@jbpark/use-hooks";
9
9
 
10
10
  //#region src/components/organisms/list/list.tsx
11
11
  const List = ({ loading, loaderProps, loader, header, title, titleLevel = 2, empty, scroll, data, className, classNames, renderItem = () => null, itemKey, ...props }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"list.mjs","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useRef } from 'react';\n\nimport { useIntersectionObserver } from '@uidotdev/usehooks';\n\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Skeleton from '../../atoms/skeleton';\nimport { Title } from '../../atoms/typography';\n\ninterface Props<T> extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title'\n> {\n loading?: boolean;\n loaderProps?: React.ComponentProps<typeof Skeleton>;\n loader?: React.ReactNode;\n title?: React.ReactNode;\n titleLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n header?: React.ReactNode;\n empty?: React.ReactNode;\n classNames?: {\n title?: string;\n header?: string;\n body?: string;\n };\n scroll?: {\n hasMore: boolean;\n loading: boolean;\n loader?: React.ReactNode;\n options?: IntersectionObserverInit;\n /**\n * Called when more items should be fetched. `List` tracks in-flight\n * requests via `loading` — the caller MUST flip `loading` back to\n * `false` when the fetch settles, including on failure/rejection.\n * If `loading` never becomes `false` again after a failed fetch,\n * `List` will stop calling `next()` for subsequent intersections.\n */\n next: () => void;\n };\n data?: T[];\n renderItem?: (item: T, index: number) => React.ReactNode;\n itemKey?: (item: T, index: number) => React.Key;\n}\n\nconst List = <T,>({\n loading,\n loaderProps,\n loader,\n header,\n title,\n titleLevel = 2,\n empty,\n scroll,\n data,\n className,\n classNames,\n renderItem = () => null,\n itemKey,\n ...props\n}: Props<T>) => {\n const [loaderRef, entry] = useIntersectionObserver({\n threshold: 0,\n root: null,\n rootMargin: '0px',\n ...scroll?.options,\n });\n\n // `scroll` is typically a new object identity every render, so this\n // effect re-runs often. Guard with a ref (updated synchronously, unlike\n // the `loading` prop which only reflects the caller's next state update)\n // to avoid firing `next()` again for the same in-flight request before\n // the caller's `loading` has had a chance to become true.\n const fetchingRef = useRef(false);\n\n useEffect(() => {\n if (!scroll) {\n return;\n }\n\n if (scroll.loading) {\n fetchingRef.current = false;\n return;\n }\n\n if (entry?.isIntersecting && scroll.hasMore && !fetchingRef.current) {\n fetchingRef.current = true;\n scroll.next();\n }\n }, [entry, scroll]);\n\n if (loading) {\n return (\n loader || (\n <div className={cn(className)} {...props}>\n <div className={cn(classNames?.title)}>{title && <Skeleton />}</div>\n <div className={cn(classNames?.header)}>\n {header && <Skeleton size=\"small\" />}\n </div>\n <div className={cn('space-y-2', classNames?.body)}>\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n </div>\n </div>\n )\n );\n }\n\n if (!data?.length && empty) {\n return (\n <div className={cn(className)} {...props}>\n {empty}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n className,\n //\n )}\n {...props}\n >\n {renderConditional(title, v => (\n <Title\n level={titleLevel}\n className={cn(\n 'px-1.5 py-4',\n 'text-black-90 text-lg leading-5.75 font-bold',\n //\n )}\n >\n {v}\n </Title>\n ))}\n <div className={cn(classNames?.header)}>{header}</div>\n <div role=\"list\" className={cn('space-y-2', classNames?.body)}>\n {data?.map((item, i) =>\n itemKey ? (\n <React.Fragment key={itemKey(item, i)}>\n {renderItem(item, i)}\n </React.Fragment>\n ) : (\n renderItem(item, i)\n ),\n )}\n {scroll?.loading &&\n (scroll?.loader ?? (\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n ))}\n {scroll && <div ref={loaderRef} />}\n </div>\n </div>\n );\n};\n\nexport default List;\n"],"mappings":";;;;;;;;;;AA8CA,MAAM,QAAY,EAChB,SACA,aACA,QACA,QACA,OACA,aAAa,GACb,OACA,QACA,MACA,WACA,YACA,mBAAmB,MACnB,SACA,GAAG,YACW;CACd,MAAM,CAAC,WAAW,SAAS,wBAAwB;EACjD,WAAW;EACX,MAAM;EACN,YAAY;EACZ,GAAG,QAAQ;EACZ,CAAC;CAOF,MAAM,cAAc,OAAO,MAAM;AAEjC,iBAAgB;AACd,MAAI,CAAC,OACH;AAGF,MAAI,OAAO,SAAS;AAClB,eAAY,UAAU;AACtB;;AAGF,MAAI,OAAO,kBAAkB,OAAO,WAAW,CAAC,YAAY,SAAS;AACnE,eAAY,UAAU;AACtB,UAAO,MAAM;;IAEd,CAAC,OAAO,OAAO,CAAC;AAEnB,KAAI,QACF,QACE,UACE,qBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;;GACjC,oBAAC;IAAI,WAAW,GAAG,YAAY,MAAM;cAAG,SAAS,oBAAC,aAAW;KAAO;GACpE,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cACnC,UAAU,oBAAC,YAAS,MAAK,UAAU;KAChC;GACN,oBAAC;IAAI,WAAW,GAAG,aAAa,YAAY,KAAK;cAC/C,oBAAC,SAAS;KAAK,OAAO;KAAI,KAAK;KAAI,GAAI;MAAe;KAClD;;GACF;AAKZ,KAAI,CAAC,MAAM,UAAU,MACnB,QACE,oBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;YAChC;GACG;AAIV,QACE,qBAAC;EACC,WAAW,GACT,UAED;EACD,GAAI;;GAEH,kBAAkB,QAAO,MACxB,oBAAC;IACC,OAAO;IACP,WAAW,GACT,eACA,+CAED;cAEA;KACK,CACR;GACF,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cAAG;KAAa;GACtD,qBAAC;IAAI,MAAK;IAAO,WAAW,GAAG,aAAa,YAAY,KAAK;;KAC1D,MAAM,KAAK,MAAM,MAChB,UACE,oBAAC,MAAM,sBACJ,WAAW,MAAM,EAAE,IADD,QAAQ,MAAM,EAAE,CAEpB,GAEjB,WAAW,MAAM,EAAE,CAEtB;KACA,QAAQ,YACN,QAAQ,UACP,oBAAC,SAAS;MAAK,OAAO;MAAI,KAAK;MAAI,GAAI;OAAe;KAEzD,UAAU,oBAAC,SAAI,KAAK,YAAa;;KAC9B;;GACF"}
1
+ {"version":3,"file":"list.mjs","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useRef } from 'react';\n\nimport { useIntersectionObserver } from '@jbpark/use-hooks';\n\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Skeleton from '../../atoms/skeleton';\nimport { Title } from '../../atoms/typography';\n\ninterface Props<T> extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title'\n> {\n loading?: boolean;\n loaderProps?: React.ComponentProps<typeof Skeleton>;\n loader?: React.ReactNode;\n title?: React.ReactNode;\n titleLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n header?: React.ReactNode;\n empty?: React.ReactNode;\n classNames?: {\n title?: string;\n header?: string;\n body?: string;\n };\n scroll?: {\n hasMore: boolean;\n loading: boolean;\n loader?: React.ReactNode;\n options?: IntersectionObserverInit;\n /**\n * Called when more items should be fetched. `List` tracks in-flight\n * requests via `loading` — the caller MUST flip `loading` back to\n * `false` when the fetch settles, including on failure/rejection.\n * If `loading` never becomes `false` again after a failed fetch,\n * `List` will stop calling `next()` for subsequent intersections.\n */\n next: () => void;\n };\n data?: T[];\n renderItem?: (item: T, index: number) => React.ReactNode;\n itemKey?: (item: T, index: number) => React.Key;\n}\n\nconst List = <T,>({\n loading,\n loaderProps,\n loader,\n header,\n title,\n titleLevel = 2,\n empty,\n scroll,\n data,\n className,\n classNames,\n renderItem = () => null,\n itemKey,\n ...props\n}: Props<T>) => {\n const [loaderRef, entry] = useIntersectionObserver({\n threshold: 0,\n root: null,\n rootMargin: '0px',\n ...scroll?.options,\n });\n\n // `scroll` is typically a new object identity every render, so this\n // effect re-runs often. Guard with a ref (updated synchronously, unlike\n // the `loading` prop which only reflects the caller's next state update)\n // to avoid firing `next()` again for the same in-flight request before\n // the caller's `loading` has had a chance to become true.\n const fetchingRef = useRef(false);\n\n useEffect(() => {\n if (!scroll) {\n return;\n }\n\n if (scroll.loading) {\n fetchingRef.current = false;\n return;\n }\n\n if (entry?.isIntersecting && scroll.hasMore && !fetchingRef.current) {\n fetchingRef.current = true;\n scroll.next();\n }\n }, [entry, scroll]);\n\n if (loading) {\n return (\n loader || (\n <div className={cn(className)} {...props}>\n <div className={cn(classNames?.title)}>{title && <Skeleton />}</div>\n <div className={cn(classNames?.header)}>\n {header && <Skeleton size=\"small\" />}\n </div>\n <div className={cn('space-y-2', classNames?.body)}>\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n </div>\n </div>\n )\n );\n }\n\n if (!data?.length && empty) {\n return (\n <div className={cn(className)} {...props}>\n {empty}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n className,\n //\n )}\n {...props}\n >\n {renderConditional(title, v => (\n <Title\n level={titleLevel}\n className={cn(\n 'px-1.5 py-4',\n 'text-black-90 text-lg leading-5.75 font-bold',\n //\n )}\n >\n {v}\n </Title>\n ))}\n <div className={cn(classNames?.header)}>{header}</div>\n <div role=\"list\" className={cn('space-y-2', classNames?.body)}>\n {data?.map((item, i) =>\n itemKey ? (\n <React.Fragment key={itemKey(item, i)}>\n {renderItem(item, i)}\n </React.Fragment>\n ) : (\n renderItem(item, i)\n ),\n )}\n {scroll?.loading &&\n (scroll?.loader ?? (\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n ))}\n {scroll && <div ref={loaderRef} />}\n </div>\n </div>\n );\n};\n\nexport default List;\n"],"mappings":";;;;;;;;;;AA8CA,MAAM,QAAY,EAChB,SACA,aACA,QACA,QACA,OACA,aAAa,GACb,OACA,QACA,MACA,WACA,YACA,mBAAmB,MACnB,SACA,GAAG,YACW;CACd,MAAM,CAAC,WAAW,SAAS,wBAAwB;EACjD,WAAW;EACX,MAAM;EACN,YAAY;EACZ,GAAG,QAAQ;EACZ,CAAC;CAOF,MAAM,cAAc,OAAO,MAAM;AAEjC,iBAAgB;AACd,MAAI,CAAC,OACH;AAGF,MAAI,OAAO,SAAS;AAClB,eAAY,UAAU;AACtB;;AAGF,MAAI,OAAO,kBAAkB,OAAO,WAAW,CAAC,YAAY,SAAS;AACnE,eAAY,UAAU;AACtB,UAAO,MAAM;;IAEd,CAAC,OAAO,OAAO,CAAC;AAEnB,KAAI,QACF,QACE,UACE,qBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;;GACjC,oBAAC;IAAI,WAAW,GAAG,YAAY,MAAM;cAAG,SAAS,oBAAC,aAAW;KAAO;GACpE,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cACnC,UAAU,oBAAC,YAAS,MAAK,UAAU;KAChC;GACN,oBAAC;IAAI,WAAW,GAAG,aAAa,YAAY,KAAK;cAC/C,oBAAC,SAAS;KAAK,OAAO;KAAI,KAAK;KAAI,GAAI;MAAe;KAClD;;GACF;AAKZ,KAAI,CAAC,MAAM,UAAU,MACnB,QACE,oBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;YAChC;GACG;AAIV,QACE,qBAAC;EACC,WAAW,GACT,UAED;EACD,GAAI;;GAEH,kBAAkB,QAAO,MACxB,oBAAC;IACC,OAAO;IACP,WAAW,GACT,eACA,+CAED;cAEA;KACK,CACR;GACF,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cAAG;KAAa;GACtD,qBAAC;IAAI,MAAK;IAAO,WAAW,GAAG,aAAa,YAAY,KAAK;;KAC1D,MAAM,KAAK,MAAM,MAChB,UACE,oBAAC,MAAM,sBACJ,WAAW,MAAM,EAAE,IADD,QAAQ,MAAM,EAAE,CAEpB,GAEjB,WAAW,MAAM,EAAE,CAEtB;KACA,QAAQ,YACN,QAAQ,UACP,oBAAC,SAAS;MAAK,OAAO;MAAI,KAAK;MAAI,GAAI;OAAe;KAEzD,UAAU,oBAAC,SAAI,KAAK,YAAa;;KAC9B;;GACF"}
@@ -22,5 +22,5 @@ declare function Button({
22
22
  ...props
23
23
  }: Props): react_jsx_runtime0.JSX.Element;
24
24
  //#endregion
25
- export { type Props, button_d_exports };
25
+ export { Button, type Props, button_d_exports };
26
26
  //# sourceMappingURL=button.d.mts.map
@@ -51,5 +51,5 @@ function Button({ className, variant = "default", size = "default", asChild = fa
51
51
  }
52
52
 
53
53
  //#endregion
54
- export { Button, button_exports };
54
+ export { Button, buttonVariants, button_exports };
55
55
  //# sourceMappingURL=button.mjs.map
@@ -0,0 +1,30 @@
1
+ import { Button } from "./button.mjs";
2
+ import * as React$1 from "react";
3
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+ import { DayButton, DayPicker } from "react-day-picker";
5
+
6
+ //#region src/core/calendar.d.ts
7
+ declare namespace calendar_d_exports {
8
+ export { Calendar, CalendarDayButton };
9
+ }
10
+ declare function Calendar({
11
+ className,
12
+ classNames,
13
+ showOutsideDays,
14
+ captionLayout,
15
+ buttonVariant,
16
+ formatters,
17
+ components,
18
+ ...props
19
+ }: React$1.ComponentProps<typeof DayPicker> & {
20
+ buttonVariant?: React$1.ComponentProps<typeof Button>['variant'];
21
+ }): react_jsx_runtime0.JSX.Element;
22
+ declare function CalendarDayButton({
23
+ className,
24
+ day,
25
+ modifiers,
26
+ ...props
27
+ }: React$1.ComponentProps<typeof DayButton>): react_jsx_runtime0.JSX.Element;
28
+ //#endregion
29
+ export { calendar_d_exports };
30
+ //# sourceMappingURL=calendar.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.mts","names":[],"sources":["../../src/core/calendar.tsx"],"mappings":";;;;;;;;;iBAeS,QAAA,CAAA;EACP,SAAA;EACA,UAAA;EACA,eAAA;EACA,aAAA;EACA,aAAA;EACA,UAAA;EACA,UAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,SAAA;EAC7B,aAAA,GAAgB,OAAA,CAAM,cAAA,QAAsB,MAAA;AAAA,IAC7C,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAkKQ,iBAAA,CAAA;EACP,SAAA;EACA,GAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,OAAA,CAAM,cAAA,QAAsB,SAAA,IAAU,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -0,0 +1,136 @@
1
+ 'use client';
2
+
3
+ import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
4
+ import { cn } from "../utils.mjs";
5
+ import { Button, buttonVariants } from "./button.mjs";
6
+ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
7
+ import * as React$1 from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ import { DayPicker, getDefaultClassNames } from "react-day-picker";
10
+
11
+ //#region src/core/calendar.tsx
12
+ var calendar_exports = /* @__PURE__ */ __exportAll({
13
+ Calendar: () => Calendar,
14
+ CalendarDayButton: () => CalendarDayButton
15
+ });
16
+ function Calendar({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", formatters, components, ...props }) {
17
+ const defaultClassNames = getDefaultClassNames();
18
+ return /* @__PURE__ */ jsx(DayPicker, {
19
+ showOutsideDays,
20
+ className: cn(`bg-background group/calendar p-3 [--cell-size:2rem]
21
+ [[data-slot=card-content]_&]:bg-transparent
22
+ [[data-slot=popover-content]_&]:bg-transparent`, String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`, String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, className),
23
+ captionLayout,
24
+ formatters: {
25
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
26
+ ...formatters
27
+ },
28
+ classNames: {
29
+ root: cn("w-fit", defaultClassNames.root),
30
+ months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
31
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
32
+ nav: cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", defaultClassNames.nav),
33
+ button_previous: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_previous),
34
+ button_next: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_next),
35
+ month_caption: cn("flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", defaultClassNames.month_caption),
36
+ dropdowns: cn("flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
37
+ dropdown_root: cn(`has-focus:border-ring border-input shadow-xs
38
+ has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md
39
+ border`, defaultClassNames.dropdown_root),
40
+ dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
41
+ caption_label: cn("select-none font-medium", captionLayout === "label" ? "text-sm" : `[&>svg]:text-muted-foreground flex h-8 items-center gap-1
42
+ rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5`, defaultClassNames.caption_label),
43
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
44
+ weekdays: cn("flex", defaultClassNames.weekdays),
45
+ weekday: cn("text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", defaultClassNames.weekday),
46
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
47
+ week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
48
+ week_number: cn("text-muted-foreground select-none text-[0.8rem]", defaultClassNames.week_number),
49
+ day: cn(`group/day relative aspect-square h-full w-full select-none p-0
50
+ text-center [&:first-child[data-selected=true]_button]:rounded-l-md
51
+ [&:last-child[data-selected=true]_button]:rounded-r-md`, defaultClassNames.day),
52
+ range_start: cn("bg-accent rounded-l-md", defaultClassNames.range_start),
53
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
54
+ range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
55
+ today: cn("bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", defaultClassNames.today),
56
+ outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
57
+ disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
58
+ hidden: cn("invisible", defaultClassNames.hidden),
59
+ ...classNames
60
+ },
61
+ components: {
62
+ Root: ({ className, rootRef, ...props }) => {
63
+ return /* @__PURE__ */ jsx("div", {
64
+ "data-slot": "calendar",
65
+ ref: rootRef,
66
+ className: cn(className),
67
+ ...props
68
+ });
69
+ },
70
+ Chevron: ({ className, orientation, ...props }) => {
71
+ if (orientation === "left") return /* @__PURE__ */ jsx(ChevronLeftIcon, {
72
+ className: cn("size-4", className),
73
+ ...props
74
+ });
75
+ if (orientation === "right") return /* @__PURE__ */ jsx(ChevronRightIcon, {
76
+ className: cn("size-4", className),
77
+ ...props
78
+ });
79
+ return /* @__PURE__ */ jsx(ChevronDownIcon, {
80
+ className: cn("size-4", className),
81
+ ...props
82
+ });
83
+ },
84
+ DayButton: CalendarDayButton,
85
+ WeekNumber: ({ children, ...props }) => {
86
+ return /* @__PURE__ */ jsx("td", {
87
+ ...props,
88
+ children: /* @__PURE__ */ jsx("div", {
89
+ className: "flex size-[--cell-size] items-center justify-center\n text-center",
90
+ children
91
+ })
92
+ });
93
+ },
94
+ ...components
95
+ },
96
+ ...props
97
+ });
98
+ }
99
+ function CalendarDayButton({ className, day, modifiers, ...props }) {
100
+ const defaultClassNames = getDefaultClassNames();
101
+ const ref = React$1.useRef(null);
102
+ React$1.useEffect(() => {
103
+ if (modifiers.focused) ref.current?.focus();
104
+ }, [modifiers.focused]);
105
+ return /* @__PURE__ */ jsx(Button, {
106
+ ref,
107
+ variant: "ghost",
108
+ size: "icon",
109
+ "data-day": day.date.toLocaleDateString(),
110
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
111
+ "data-range-start": modifiers.range_start,
112
+ "data-range-end": modifiers.range_end,
113
+ "data-range-middle": modifiers.range_middle,
114
+ className: cn(`data-[selected-single=true]:bg-primary
115
+ data-[selected-single=true]:text-primary-foreground
116
+ data-[range-middle=true]:bg-accent
117
+ data-[range-middle=true]:text-accent-foreground
118
+ data-[range-start=true]:bg-primary
119
+ data-[range-start=true]:text-primary-foreground
120
+ data-[range-end=true]:bg-primary
121
+ data-[range-end=true]:text-primary-foreground
122
+ group-data-[focused=true]/day:border-ring
123
+ group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto
124
+ w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal
125
+ group-data-[focused=true]/day:relative
126
+ group-data-[focused=true]/day:z-10
127
+ group-data-[focused=true]/day:ring-[3px]
128
+ data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none
129
+ data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70`, defaultClassNames.day, className),
130
+ ...props
131
+ });
132
+ }
133
+
134
+ //#endregion
135
+ export { calendar_exports };
136
+ //# sourceMappingURL=calendar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.mjs","names":["React"],"sources":["../../src/core/calendar.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker';\n\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { Button, buttonVariants } from './button';\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = 'label',\n buttonVariant = 'ghost',\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>['variant'];\n}) {\n const defaultClassNames = getDefaultClassNames();\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n `bg-background group/calendar p-3 [--cell-size:2rem]\n [[data-slot=card-content]_&]:bg-transparent\n [[data-slot=popover-content]_&]:bg-transparent`,\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className,\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: date =>\n date.toLocaleString('default', { month: 'short' }),\n ...formatters,\n }}\n classNames={{\n root: cn('w-fit', defaultClassNames.root),\n months: cn(\n 'relative flex flex-col gap-4 md:flex-row',\n defaultClassNames.months,\n ),\n month: cn('flex w-full flex-col gap-4', defaultClassNames.month),\n nav: cn(\n 'absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1',\n defaultClassNames.nav,\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',\n defaultClassNames.button_previous,\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',\n defaultClassNames.button_next,\n ),\n month_caption: cn(\n 'flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]',\n defaultClassNames.month_caption,\n ),\n dropdowns: cn(\n 'flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium',\n defaultClassNames.dropdowns,\n ),\n dropdown_root: cn(\n `has-focus:border-ring border-input shadow-xs\n has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md\n border`,\n defaultClassNames.dropdown_root,\n ),\n dropdown: cn(\n 'bg-popover absolute inset-0 opacity-0',\n defaultClassNames.dropdown,\n ),\n caption_label: cn(\n 'select-none font-medium',\n captionLayout === 'label'\n ? 'text-sm'\n : `[&>svg]:text-muted-foreground flex h-8 items-center gap-1\n rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5`,\n defaultClassNames.caption_label,\n ),\n month_grid: cn('w-full border-collapse', defaultClassNames.month_grid),\n weekdays: cn('flex', defaultClassNames.weekdays),\n weekday: cn(\n 'text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal',\n defaultClassNames.weekday,\n ),\n week: cn('mt-2 flex w-full', defaultClassNames.week),\n week_number_header: cn(\n 'w-[--cell-size] select-none',\n defaultClassNames.week_number_header,\n ),\n week_number: cn(\n 'text-muted-foreground select-none text-[0.8rem]',\n defaultClassNames.week_number,\n ),\n day: cn(\n `group/day relative aspect-square h-full w-full select-none p-0\n text-center [&:first-child[data-selected=true]_button]:rounded-l-md\n [&:last-child[data-selected=true]_button]:rounded-r-md`,\n defaultClassNames.day,\n ),\n range_start: cn(\n 'bg-accent rounded-l-md',\n defaultClassNames.range_start,\n ),\n range_middle: cn('rounded-none', defaultClassNames.range_middle),\n range_end: cn('bg-accent rounded-r-md', defaultClassNames.range_end),\n today: cn(\n 'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',\n defaultClassNames.today,\n ),\n outside: cn(\n 'text-muted-foreground aria-selected:text-muted-foreground',\n defaultClassNames.outside,\n ),\n disabled: cn(\n 'text-muted-foreground opacity-50',\n defaultClassNames.disabled,\n ),\n hidden: cn('invisible', defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n // eslint-disable-next-line react/prop-types -- typed via DayPicker's `components` prop, not local PropTypes\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n );\n },\n // eslint-disable-next-line react/prop-types -- typed via DayPicker's `components` prop, not local PropTypes\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === 'left') {\n return (\n <ChevronLeftIcon className={cn('size-4', className)} {...props} />\n );\n }\n\n if (orientation === 'right') {\n return (\n <ChevronRightIcon\n className={cn('size-4', className)}\n {...props}\n />\n );\n }\n\n return (\n <ChevronDownIcon className={cn('size-4', className)} {...props} />\n );\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div\n className=\"flex size-[--cell-size] items-center justify-center\n text-center\"\n >\n {children}\n </div>\n </td>\n );\n },\n ...components,\n }}\n {...props}\n />\n );\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames();\n\n const ref = React.useRef<HTMLButtonElement>(null);\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus();\n }, [modifiers.focused]);\n\n return (\n <Button\n ref={ref}\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n `data-[selected-single=true]:bg-primary\n data-[selected-single=true]:text-primary-foreground\n data-[range-middle=true]:bg-accent\n data-[range-middle=true]:text-accent-foreground\n data-[range-start=true]:bg-primary\n data-[range-start=true]:text-primary-foreground\n data-[range-end=true]:bg-primary\n data-[range-end=true]:text-primary-foreground\n group-data-[focused=true]/day:border-ring\n group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto\n w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal\n group-data-[focused=true]/day:relative\n group-data-[focused=true]/day:z-10\n group-data-[focused=true]/day:ring-[3px]\n data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none\n data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70`,\n defaultClassNames.day,\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Calendar, CalendarDayButton };\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAS,SAAS,EAChB,WACA,YACA,kBAAkB,MAClB,gBAAgB,SAChB,gBAAgB,SAChB,YACA,YACA,GAAG,SAGF;CACD,MAAM,oBAAoB,sBAAsB;AAEhD,QACE,oBAAC;EACkB;EACjB,WAAW,GACT;;yDAGA,OAAO,GAAG,6CACV,OAAO,GAAG,iDACV,UACD;EACc;EACf,YAAY;GACV,sBAAqB,SACnB,KAAK,eAAe,WAAW,EAAE,OAAO,SAAS,CAAC;GACpD,GAAG;GACJ;EACD,YAAY;GACV,MAAM,GAAG,SAAS,kBAAkB,KAAK;GACzC,QAAQ,GACN,4CACA,kBAAkB,OACnB;GACD,OAAO,GAAG,8BAA8B,kBAAkB,MAAM;GAChE,KAAK,GACH,2EACA,kBAAkB,IACnB;GACD,iBAAiB,GACf,eAAe,EAAE,SAAS,eAAe,CAAC,EAC1C,4EACA,kBAAkB,gBACnB;GACD,aAAa,GACX,eAAe,EAAE,SAAS,eAAe,CAAC,EAC1C,4EACA,kBAAkB,YACnB;GACD,eAAe,GACb,4EACA,kBAAkB,cACnB;GACD,WAAW,GACT,uFACA,kBAAkB,UACnB;GACD,eAAe,GACb;;mBAGA,kBAAkB,cACnB;GACD,UAAU,GACR,yCACA,kBAAkB,SACnB;GACD,eAAe,GACb,2BACA,kBAAkB,UACd,YACA;8DAEJ,kBAAkB,cACnB;GACD,YAAY,GAAG,0BAA0B,kBAAkB,WAAW;GACtE,UAAU,GAAG,QAAQ,kBAAkB,SAAS;GAChD,SAAS,GACP,iFACA,kBAAkB,QACnB;GACD,MAAM,GAAG,oBAAoB,kBAAkB,KAAK;GACpD,oBAAoB,GAClB,+BACA,kBAAkB,mBACnB;GACD,aAAa,GACX,mDACA,kBAAkB,YACnB;GACD,KAAK,GACH;;mEAGA,kBAAkB,IACnB;GACD,aAAa,GACX,0BACA,kBAAkB,YACnB;GACD,cAAc,GAAG,gBAAgB,kBAAkB,aAAa;GAChE,WAAW,GAAG,0BAA0B,kBAAkB,UAAU;GACpE,OAAO,GACL,iFACA,kBAAkB,MACnB;GACD,SAAS,GACP,6DACA,kBAAkB,QACnB;GACD,UAAU,GACR,oCACA,kBAAkB,SACnB;GACD,QAAQ,GAAG,aAAa,kBAAkB,OAAO;GACjD,GAAG;GACJ;EACD,YAAY;GAEV,OAAO,EAAE,WAAW,SAAS,GAAG,YAAY;AAC1C,WACE,oBAAC;KACC,aAAU;KACV,KAAK;KACL,WAAW,GAAG,UAAU;KACxB,GAAI;MACJ;;GAIN,UAAU,EAAE,WAAW,aAAa,GAAG,YAAY;AACjD,QAAI,gBAAgB,OAClB,QACE,oBAAC;KAAgB,WAAW,GAAG,UAAU,UAAU;KAAE,GAAI;MAAS;AAItE,QAAI,gBAAgB,QAClB,QACE,oBAAC;KACC,WAAW,GAAG,UAAU,UAAU;KAClC,GAAI;MACJ;AAIN,WACE,oBAAC;KAAgB,WAAW,GAAG,UAAU,UAAU;KAAE,GAAI;MAAS;;GAGtE,WAAW;GACX,aAAa,EAAE,UAAU,GAAG,YAAY;AACtC,WACE,oBAAC;KAAG,GAAI;eACN,oBAAC;MACC,WAAU;MAGT;OACG;MACH;;GAGT,GAAG;GACJ;EACD,GAAI;GACJ;;AAIN,SAAS,kBAAkB,EACzB,WACA,KACA,WACA,GAAG,SACsC;CACzC,MAAM,oBAAoB,sBAAsB;CAEhD,MAAM,MAAMA,QAAM,OAA0B,KAAK;AACjD,SAAM,gBAAgB;AACpB,MAAI,UAAU,QAAS,KAAI,SAAS,OAAO;IAC1C,CAAC,UAAU,QAAQ,CAAC;AAEvB,QACE,oBAAC;EACM;EACL,SAAQ;EACR,MAAK;EACL,YAAU,IAAI,KAAK,oBAAoB;EACvC,wBACE,UAAU,YACV,CAAC,UAAU,eACX,CAAC,UAAU,aACX,CAAC,UAAU;EAEb,oBAAkB,UAAU;EAC5B,kBAAgB,UAAU;EAC1B,qBAAmB,UAAU;EAC7B,WAAW,GACT;;;;;;;;;;;;;;;kFAgBA,kBAAkB,KAClB,UACD;EACD,GAAI;GACJ"}
package/dist/core.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { accordion_d_exports } from "./core/accordion.mjs";
2
2
  import { badge_d_exports } from "./core/badge.mjs";
3
3
  import { button_d_exports } from "./core/button.mjs";
4
+ import { calendar_d_exports } from "./core/calendar.mjs";
4
5
  import { checkbox_d_exports } from "./core/checkbox.mjs";
5
6
  import { dialog_d_exports } from "./core/dialog.mjs";
6
7
  import { drawer_d_exports } from "./core/drawer.mjs";
@@ -16,4 +17,4 @@ import { separator_d_exports } from "./core/separator.mjs";
16
17
  import { skeleton_d_exports } from "./core/skeleton.mjs";
17
18
  import { switch_d_exports } from "./core/switch.mjs";
18
19
  import { textarea_d_exports } from "./core/textarea.mjs";
19
- export { accordion_d_exports as accordion, badge_d_exports as badge, button_d_exports as button, checkbox_d_exports as checkbox, dialog_d_exports as dialog, drawer_d_exports as drawer, field_d_exports as field, input_d_exports as input, label_d_exports as label, popover_d_exports as popover, progress_d_exports as progress, radio_group_d_exports as radio, resizable_d_exports as resizable, select_d_exports as select, separator_d_exports as separator, skeleton_d_exports as skeleton, switch_d_exports as switchComponent, textarea_d_exports as textarea };
20
+ export { accordion_d_exports as accordion, badge_d_exports as badge, button_d_exports as button, calendar_d_exports as calendar, checkbox_d_exports as checkbox, dialog_d_exports as dialog, drawer_d_exports as drawer, field_d_exports as field, input_d_exports as input, label_d_exports as label, popover_d_exports as popover, progress_d_exports as progress, radio_group_d_exports as radio, resizable_d_exports as resizable, select_d_exports as select, separator_d_exports as separator, skeleton_d_exports as skeleton, switch_d_exports as switchComponent, textarea_d_exports as textarea };
package/dist/core.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { accordion_exports } from "./core/accordion.mjs";
2
2
  import { badge_exports } from "./core/badge.mjs";
3
3
  import { button_exports } from "./core/button.mjs";
4
+ import { calendar_exports } from "./core/calendar.mjs";
4
5
  import { checkbox_exports } from "./core/checkbox.mjs";
5
6
  import { dialog_exports } from "./core/dialog.mjs";
6
7
  import { drawer_exports } from "./core/drawer.mjs";
@@ -17,4 +18,4 @@ import { skeleton_exports } from "./core/skeleton.mjs";
17
18
  import { switch_exports } from "./core/switch.mjs";
18
19
  import { textarea_exports } from "./core/textarea.mjs";
19
20
 
20
- export { accordion_exports as accordion, badge_exports as badge, button_exports as button, checkbox_exports as checkbox, dialog_exports as dialog, drawer_exports as drawer, field_exports as field, input_exports as input, label_exports as label, popover_exports as popover, progress_exports as progress, radio_group_exports as radio, resizable_exports as resizable, select_exports as select, separator_exports as separator, skeleton_exports as skeleton, switch_exports as switchComponent, textarea_exports as textarea };
21
+ export { accordion_exports as accordion, badge_exports as badge, button_exports as button, calendar_exports as calendar, checkbox_exports as checkbox, dialog_exports as dialog, drawer_exports as drawer, field_exports as field, input_exports as input, label_exports as label, popover_exports as popover, progress_exports as progress, radio_group_exports as radio, resizable_exports as resizable, select_exports as select, separator_exports as separator, skeleton_exports as skeleton, switch_exports as switchComponent, textarea_exports as textarea };
package/dist/index.d.mts CHANGED
@@ -8,6 +8,7 @@ import Space from "./Space.mjs";
8
8
  import Layout from "./Layout.mjs";
9
9
  import { Checkbox } from "./components/atoms/checkbox/index.mjs";
10
10
  import { ColorPicker } from "./components/atoms/color-picker.mjs";
11
+ import { DatePicker } from "./components/atoms/date-picker.mjs";
11
12
  import { FloatButton } from "./components/atoms/float-button/index.mjs";
12
13
  import { Input } from "./components/atoms/input/index.mjs";
13
14
  import { Popover } from "./components/atoms/popover.mjs";
@@ -22,6 +23,7 @@ import { Collapse } from "./components/molecules/collapse.mjs";
22
23
  import { Dropdown } from "./components/molecules/dropdown.mjs";
23
24
  import { Marquees } from "./components/molecules/marquees/index.mjs";
24
25
  import { Splitter } from "./components/molecules/splitter/index.mjs";
26
+ import { Upload, UploadFile } from "./components/molecules/upload.mjs";
25
27
  import "./components/molecules/index.mjs";
26
28
  import { Drawer, Props as Props$1 } from "./components/organisms/drawer.mjs";
27
29
  import { List } from "./components/organisms/list/index.mjs";
@@ -33,4 +35,4 @@ import { ThemeConfig, ThemeToken } from "./providers/Config/types.mjs";
33
35
  import { useConfig } from "./providers/Config/context.mjs";
34
36
  import { Config, Props } from "./providers/Config/index.mjs";
35
37
  import "./providers/index.mjs";
36
- export { Button, Card, Checkbox, Collapse, ColorPicker, Config, Props as ConfigProps, Drawer, Props$1 as DrawerProps, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, ThemeConfig, ThemeToken, Typography, useConfig };
38
+ export { Button, Card, Checkbox, Collapse, ColorPicker, Config, Props as ConfigProps, DatePicker, Drawer, Props$1 as DrawerProps, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, ThemeConfig, ThemeToken, Typography, Upload, UploadFile, useConfig };
package/dist/index.mjs CHANGED
@@ -4,6 +4,7 @@ import Checkbox from "./components/atoms/checkbox/index.mjs";
4
4
  import Typography from "./Typography.mjs";
5
5
  import Popover from "./components/atoms/popover.mjs";
6
6
  import ColorPicker from "./components/atoms/color-picker.mjs";
7
+ import DatePicker from "./components/atoms/date-picker.mjs";
7
8
  import FloatButton from "./components/atoms/float-button/index.mjs";
8
9
  import Input from "./components/atoms/input/index.mjs";
9
10
  import Progress from "./components/atoms/progress.mjs";
@@ -21,6 +22,7 @@ import Marquees from "./components/molecules/marquees/index.mjs";
21
22
  import Reveals from "./Reveals.mjs";
22
23
  import Splitter from "./components/molecules/splitter/index.mjs";
23
24
  import Space from "./Space.mjs";
25
+ import Upload from "./components/molecules/upload.mjs";
24
26
  import Drawer from "./components/organisms/drawer.mjs";
25
27
  import List from "./components/organisms/list/index.mjs";
26
28
  import Modal from "./components/organisms/modal.mjs";
@@ -29,4 +31,4 @@ import Layout from "./Layout.mjs";
29
31
  import { useConfig } from "./providers/Config/context.mjs";
30
32
  import Config from "./providers/Config/index.mjs";
31
33
 
32
- export { Button, Card, Checkbox, Collapse, ColorPicker, Config, Drawer, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, Typography, useConfig };
34
+ export { Button, Card, Checkbox, Collapse, ColorPicker, Config, DatePicker, Drawer, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, Typography, Upload, useConfig };
package/dist/style.css CHANGED
@@ -207,6 +207,9 @@
207
207
  .pointer-events-none {
208
208
  pointer-events: none;
209
209
  }
210
+ .invisible {
211
+ visibility: hidden;
212
+ }
210
213
  .sr-only {
211
214
  position: absolute;
212
215
  width: 1px;
@@ -239,6 +242,9 @@
239
242
  .inset-0 {
240
243
  inset: calc(var(--spacing) * 0);
241
244
  }
245
+ .inset-x-0 {
246
+ inset-inline: calc(var(--spacing) * 0);
247
+ }
242
248
  .top-0 {
243
249
  top: calc(var(--spacing) * 0);
244
250
  }
@@ -347,6 +353,9 @@
347
353
  .my-1 {
348
354
  margin-block: calc(var(--spacing) * 1);
349
355
  }
356
+ .mt-2 {
357
+ margin-top: calc(var(--spacing) * 2);
358
+ }
350
359
  .mt-3 {
351
360
  margin-top: calc(var(--spacing) * 3);
352
361
  }
@@ -462,6 +471,10 @@
462
471
  width: calc(var(--spacing) * 10);
463
472
  height: calc(var(--spacing) * 10);
464
473
  }
474
+ .size-\[--cell-size\] {
475
+ width: --cell-size;
476
+ height: --cell-size;
477
+ }
465
478
  .h-2 {
466
479
  height: calc(var(--spacing) * 2);
467
480
  }
@@ -501,6 +514,9 @@
501
514
  .h-50 {
502
515
  height: calc(var(--spacing) * 50);
503
516
  }
517
+ .h-\[--cell-size\] {
518
+ height: --cell-size;
519
+ }
504
520
  .h-\[var\(--radix-select-trigger-height\)\] {
505
521
  height: var(--radix-select-trigger-height);
506
522
  }
@@ -558,6 +574,9 @@
558
574
  .w-100 {
559
575
  width: calc(var(--spacing) * 100);
560
576
  }
577
+ .w-\[--cell-size\] {
578
+ width: --cell-size;
579
+ }
561
580
  .w-\[100px\] {
562
581
  width: 100px;
563
582
  }
@@ -588,6 +607,9 @@
588
607
  .min-w-80 {
589
608
  min-width: calc(var(--spacing) * 80);
590
609
  }
610
+ .min-w-\[--cell-size\] {
611
+ min-width: --cell-size;
612
+ }
591
613
  .min-w-\[8rem\] {
592
614
  min-width: 8rem;
593
615
  }
@@ -618,6 +640,9 @@
618
640
  .basis-auto {
619
641
  flex-basis: auto;
620
642
  }
643
+ .border-collapse {
644
+ border-collapse: collapse;
645
+ }
621
646
  .origin-\(--radix-popover-content-transform-origin\) {
622
647
  transform-origin: var(--radix-popover-content-transform-origin);
623
648
  }
@@ -739,6 +764,9 @@
739
764
  .justify-end {
740
765
  justify-content: flex-end;
741
766
  }
767
+ .justify-start {
768
+ justify-content: flex-start;
769
+ }
742
770
  .gap-0 {
743
771
  gap: calc(var(--spacing) * 0);
744
772
  }
@@ -785,6 +813,11 @@
785
813
  .gap-y-5 {
786
814
  row-gap: calc(var(--spacing) * 5);
787
815
  }
816
+ .truncate {
817
+ overflow: hidden;
818
+ text-overflow: ellipsis;
819
+ white-space: nowrap;
820
+ }
788
821
  .overflow-auto {
789
822
  overflow: auto;
790
823
  }
@@ -838,6 +871,10 @@
838
871
  border-top-left-radius: var(--radius);
839
872
  border-bottom-left-radius: var(--radius);
840
873
  }
874
+ .rounded-l-md {
875
+ border-top-left-radius: calc(var(--radius) - 2px);
876
+ border-bottom-left-radius: calc(var(--radius) - 2px);
877
+ }
841
878
  .rounded-l-none {
842
879
  border-top-left-radius: 0;
843
880
  border-bottom-left-radius: 0;
@@ -846,6 +883,10 @@
846
883
  border-top-right-radius: var(--radius);
847
884
  border-bottom-right-radius: var(--radius);
848
885
  }
886
+ .rounded-r-md {
887
+ border-top-right-radius: calc(var(--radius) - 2px);
888
+ border-bottom-right-radius: calc(var(--radius) - 2px);
889
+ }
849
890
  .rounded-r-none {
850
891
  border-top-right-radius: 0;
851
892
  border-bottom-right-radius: 0;
@@ -1000,6 +1041,9 @@
1000
1041
  .fill-primary {
1001
1042
  fill: var(--primary);
1002
1043
  }
1044
+ .object-cover {
1045
+ object-fit: cover;
1046
+ }
1003
1047
  .p-0 {
1004
1048
  padding: calc(var(--spacing) * 0);
1005
1049
  }
@@ -1009,6 +1053,12 @@
1009
1053
  .p-1 {
1010
1054
  padding: calc(var(--spacing) * 1);
1011
1055
  }
1056
+ .p-2 {
1057
+ padding: calc(var(--spacing) * 2);
1058
+ }
1059
+ .p-3 {
1060
+ padding: calc(var(--spacing) * 3);
1061
+ }
1012
1062
  .p-4 {
1013
1063
  padding: calc(var(--spacing) * 4);
1014
1064
  }
@@ -1042,6 +1092,9 @@
1042
1092
  .px-6 {
1043
1093
  padding-inline: calc(var(--spacing) * 6);
1044
1094
  }
1095
+ .px-\[--cell-size\] {
1096
+ padding-inline: --cell-size;
1097
+ }
1045
1098
  .py-0 {
1046
1099
  padding-block: calc(var(--spacing) * 0);
1047
1100
  }
@@ -1066,6 +1119,9 @@
1066
1119
  .pt-2 {
1067
1120
  padding-top: calc(var(--spacing) * 2);
1068
1121
  }
1122
+ .pr-1 {
1123
+ padding-right: calc(var(--spacing) * 1);
1124
+ }
1069
1125
  .pr-8 {
1070
1126
  padding-right: calc(var(--spacing) * 8);
1071
1127
  }
@@ -1128,6 +1184,9 @@
1128
1184
  font-size: var(--text-xs);
1129
1185
  line-height: var(--tw-leading, var(--text-xs--line-height));
1130
1186
  }
1187
+ .text-\[0\.8rem\] {
1188
+ font-size: 0.8rem;
1189
+ }
1131
1190
  .text-\[10px\] {
1132
1191
  font-size: 10px;
1133
1192
  }
@@ -1178,6 +1237,9 @@
1178
1237
  .text-\(--btn-fg\) {
1179
1238
  color: var(--btn-fg);
1180
1239
  }
1240
+ .text-accent-foreground {
1241
+ color: var(--accent-foreground);
1242
+ }
1181
1243
  .text-blue-400 {
1182
1244
  color: var(--color-blue-400);
1183
1245
  }
@@ -1364,6 +1426,9 @@
1364
1426
  -webkit-user-select: none;
1365
1427
  user-select: none;
1366
1428
  }
1429
+ .\[--cell-size\:2rem\] {
1430
+ --cell-size: 2rem;
1431
+ }
1367
1432
  .group-hover\:border-current {
1368
1433
  &:is(:where(.group):hover *) {
1369
1434
  @media (hover: hover) {
@@ -1391,6 +1456,35 @@
1391
1456
  opacity: 50%;
1392
1457
  }
1393
1458
  }
1459
+ .group-data-\[focused\=true\]\/day\:relative {
1460
+ &:is(:where(.group\/day)[data-focused="true"] *) {
1461
+ position: relative;
1462
+ }
1463
+ }
1464
+ .group-data-\[focused\=true\]\/day\:z-10 {
1465
+ &:is(:where(.group\/day)[data-focused="true"] *) {
1466
+ z-index: 10;
1467
+ }
1468
+ }
1469
+ .group-data-\[focused\=true\]\/day\:border-ring {
1470
+ &:is(:where(.group\/day)[data-focused="true"] *) {
1471
+ border-color: var(--ring);
1472
+ }
1473
+ }
1474
+ .group-data-\[focused\=true\]\/day\:ring-\[3px\] {
1475
+ &:is(:where(.group\/day)[data-focused="true"] *) {
1476
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1477
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1478
+ }
1479
+ }
1480
+ .group-data-\[focused\=true\]\/day\:ring-ring\/50 {
1481
+ &:is(:where(.group\/day)[data-focused="true"] *) {
1482
+ --tw-ring-color: var(--ring);
1483
+ @supports (color: color-mix(in lab, red, red)) {
1484
+ --tw-ring-color: color-mix(in oklab, var(--ring) 50%, transparent);
1485
+ }
1486
+ }
1487
+ }
1394
1488
  .group-data-\[size\=default\]\/switch\:size-4 {
1395
1489
  &:is(:where(.group\/switch)[data-size="default"] *) {
1396
1490
  width: calc(var(--spacing) * 4);
@@ -1937,6 +2031,13 @@
1937
2031
  }
1938
2032
  }
1939
2033
  }
2034
+ .hover\:text-foreground {
2035
+ &:hover {
2036
+ @media (hover: hover) {
2037
+ color: var(--foreground);
2038
+ }
2039
+ }
2040
+ }
1940
2041
  .hover\:no-underline {
1941
2042
  &:hover {
1942
2043
  @media (hover: hover) {
@@ -2076,6 +2177,25 @@
2076
2177
  opacity: 50%;
2077
2178
  }
2078
2179
  }
2180
+ .has-focus\:border-ring {
2181
+ &:has(*:focus) {
2182
+ border-color: var(--ring);
2183
+ }
2184
+ }
2185
+ .has-focus\:ring-\[3px\] {
2186
+ &:has(*:focus) {
2187
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2188
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2189
+ }
2190
+ }
2191
+ .has-focus\:ring-ring\/50 {
2192
+ &:has(*:focus) {
2193
+ --tw-ring-color: var(--ring);
2194
+ @supports (color: color-mix(in lab, red, red)) {
2195
+ --tw-ring-color: color-mix(in oklab, var(--ring) 50%, transparent);
2196
+ }
2197
+ }
2198
+ }
2079
2199
  .has-data-\[state\=checked\]\:border-primary {
2080
2200
  &:has(*[data-state="checked"]) {
2081
2201
  border-color: var(--primary);
@@ -2145,6 +2265,11 @@
2145
2265
  padding-inline: calc(var(--spacing) * 4);
2146
2266
  }
2147
2267
  }
2268
+ .aria-disabled\:opacity-50 {
2269
+ &[aria-disabled="true"] {
2270
+ opacity: 50%;
2271
+ }
2272
+ }
2148
2273
  .aria-invalid\:border-destructive {
2149
2274
  &[aria-invalid="true"] {
2150
2275
  border-color: var(--destructive);
@@ -2158,6 +2283,11 @@
2158
2283
  }
2159
2284
  }
2160
2285
  }
2286
+ .aria-selected\:text-muted-foreground {
2287
+ &[aria-selected="true"] {
2288
+ color: var(--muted-foreground);
2289
+ }
2290
+ }
2161
2291
  .aria-\[orientation\=horizontal\]\:h-px {
2162
2292
  &[aria-orientation="horizontal"] {
2163
2293
  height: 1px;
@@ -2230,6 +2360,11 @@
2230
2360
  opacity: 50%;
2231
2361
  }
2232
2362
  }
2363
+ .data-\[empty\=true\]\:text-muted-foreground {
2364
+ &[data-empty="true"] {
2365
+ color: var(--muted-foreground);
2366
+ }
2367
+ }
2233
2368
  .data-\[invalid\=true\]\:text-destructive {
2234
2369
  &[data-invalid="true"] {
2235
2370
  color: var(--destructive);
@@ -2260,6 +2395,66 @@
2260
2395
  color: var(--muted-foreground);
2261
2396
  }
2262
2397
  }
2398
+ .data-\[range-end\=true\]\:rounded-md {
2399
+ &[data-range-end="true"] {
2400
+ border-radius: calc(var(--radius) - 2px);
2401
+ }
2402
+ }
2403
+ .data-\[range-end\=true\]\:bg-primary {
2404
+ &[data-range-end="true"] {
2405
+ background-color: var(--primary);
2406
+ }
2407
+ }
2408
+ .data-\[range-end\=true\]\:text-primary-foreground {
2409
+ &[data-range-end="true"] {
2410
+ color: var(--primary-foreground);
2411
+ }
2412
+ }
2413
+ .data-\[range-middle\=true\]\:rounded-none {
2414
+ &[data-range-middle="true"] {
2415
+ border-radius: 0;
2416
+ }
2417
+ }
2418
+ .data-\[range-middle\=true\]\:bg-accent {
2419
+ &[data-range-middle="true"] {
2420
+ background-color: var(--accent);
2421
+ }
2422
+ }
2423
+ .data-\[range-middle\=true\]\:text-accent-foreground {
2424
+ &[data-range-middle="true"] {
2425
+ color: var(--accent-foreground);
2426
+ }
2427
+ }
2428
+ .data-\[range-start\=true\]\:rounded-md {
2429
+ &[data-range-start="true"] {
2430
+ border-radius: calc(var(--radius) - 2px);
2431
+ }
2432
+ }
2433
+ .data-\[range-start\=true\]\:bg-primary {
2434
+ &[data-range-start="true"] {
2435
+ background-color: var(--primary);
2436
+ }
2437
+ }
2438
+ .data-\[range-start\=true\]\:text-primary-foreground {
2439
+ &[data-range-start="true"] {
2440
+ color: var(--primary-foreground);
2441
+ }
2442
+ }
2443
+ .data-\[selected-single\=true\]\:bg-primary {
2444
+ &[data-selected-single="true"] {
2445
+ background-color: var(--primary);
2446
+ }
2447
+ }
2448
+ .data-\[selected-single\=true\]\:text-primary-foreground {
2449
+ &[data-selected-single="true"] {
2450
+ color: var(--primary-foreground);
2451
+ }
2452
+ }
2453
+ .data-\[selected\=true\]\:rounded-none {
2454
+ &[data-selected="true"] {
2455
+ border-radius: 0;
2456
+ }
2457
+ }
2263
2458
  .data-\[side\=bottom\]\:translate-y-1 {
2264
2459
  &[data-side="bottom"] {
2265
2460
  --tw-translate-y: calc(var(--spacing) * 1);
@@ -2605,6 +2800,11 @@
2605
2800
  }
2606
2801
  }
2607
2802
  }
2803
+ .md\:flex-row {
2804
+ @media (width >= 48rem) {
2805
+ flex-direction: row;
2806
+ }
2807
+ }
2608
2808
  .md\:gap-1\.5 {
2609
2809
  @media (width >= 48rem) {
2610
2810
  gap: calc(var(--spacing) * 1.5);
@@ -2833,6 +3033,30 @@
2833
3033
  display: none;
2834
3034
  }
2835
3035
  }
3036
+ .\[\&\:first-child\[data-selected\=true\]_button\]\:rounded-l-md {
3037
+ &:first-child[data-selected=true] button {
3038
+ border-top-left-radius: calc(var(--radius) - 2px);
3039
+ border-bottom-left-radius: calc(var(--radius) - 2px);
3040
+ }
3041
+ }
3042
+ .rtl\:\*\*\:\[\.rdp-button\\_next\>svg\]\:rotate-180 {
3043
+ &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
3044
+ :is(& *) {
3045
+ &:is(.rdp-button_next>svg) {
3046
+ rotate: 180deg;
3047
+ }
3048
+ }
3049
+ }
3050
+ }
3051
+ .rtl\:\*\*\:\[\.rdp-button\\_previous\>svg\]\:rotate-180 {
3052
+ &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
3053
+ :is(& *) {
3054
+ &:is(.rdp-button_previous>svg) {
3055
+ rotate: 180deg;
3056
+ }
3057
+ }
3058
+ }
3059
+ }
2836
3060
  .\*\:\[span\]\:last\:flex {
2837
3061
  :is(& > *) {
2838
3062
  &:is(span) {
@@ -2860,6 +3084,12 @@
2860
3084
  }
2861
3085
  }
2862
3086
  }
3087
+ .\[\&\:last-child\[data-selected\=true\]_button\]\:rounded-r-md {
3088
+ &:last-child[data-selected=true] button {
3089
+ border-top-right-radius: calc(var(--radius) - 2px);
3090
+ border-bottom-right-radius: calc(var(--radius) - 2px);
3091
+ }
3092
+ }
2863
3093
  .\[\&\>\*\]\:w-full {
2864
3094
  &>* {
2865
3095
  width: 100%;
@@ -2932,6 +3162,17 @@
2932
3162
  color: var(--primary);
2933
3163
  }
2934
3164
  }
3165
+ .\[\&\>span\]\:text-xs {
3166
+ &>span {
3167
+ font-size: var(--text-xs);
3168
+ line-height: var(--tw-leading, var(--text-xs--line-height));
3169
+ }
3170
+ }
3171
+ .\[\&\>span\]\:opacity-70 {
3172
+ &>span {
3173
+ opacity: 70%;
3174
+ }
3175
+ }
2935
3176
  .\[\&\>svg\]\:pointer-events-none {
2936
3177
  &>svg {
2937
3178
  pointer-events: none;
@@ -2943,6 +3184,17 @@
2943
3184
  height: calc(var(--spacing) * 3);
2944
3185
  }
2945
3186
  }
3187
+ .\[\&\>svg\]\:size-3\.5 {
3188
+ &>svg {
3189
+ width: calc(var(--spacing) * 3.5);
3190
+ height: calc(var(--spacing) * 3.5);
3191
+ }
3192
+ }
3193
+ .\[\&\>svg\]\:text-muted-foreground {
3194
+ &>svg {
3195
+ color: var(--muted-foreground);
3196
+ }
3197
+ }
2946
3198
  .\[\&\[aria-orientation\=horizontal\]\>div\]\:rotate-90 {
2947
3199
  &[aria-orientation=horizontal]>div {
2948
3200
  rotate: 90deg;
@@ -2953,6 +3205,16 @@
2953
3205
  rotate: 180deg;
2954
3206
  }
2955
3207
  }
3208
+ .\[\[data-slot\=card-content\]_\&\]\:bg-transparent {
3209
+ [data-slot=card-content] & {
3210
+ background-color: transparent;
3211
+ }
3212
+ }
3213
+ .\[\[data-slot\=popover-content\]_\&\]\:bg-transparent {
3214
+ [data-slot=popover-content] & {
3215
+ background-color: transparent;
3216
+ }
3217
+ }
2956
3218
  .\[\[data-variant\=legend\]\+\&\]\:-mt-1\.5 {
2957
3219
  [data-variant=legend]+& {
2958
3220
  margin-top: calc(var(--spacing) * -1.5);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbpark/ui-kit",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Modern React UI component library built with TypeScript, Tailwind CSS, and Radix UI. Featuring atoms, molecules, organisms and layout templates for building beautiful interfaces.",
5
5
  "keywords": [
6
6
  "react",
@@ -126,7 +126,7 @@
126
126
  },
127
127
  "dependencies": {
128
128
  "@gsap/react": "^2.1.2",
129
- "@jbpark/use-hooks": "^2.1.0",
129
+ "@jbpark/use-hooks": "^2.6.0",
130
130
  "@radix-ui/react-accordion": "^1.2.12",
131
131
  "@radix-ui/react-checkbox": "^1.3.3",
132
132
  "@radix-ui/react-dialog": "^1.1.15",
@@ -135,15 +135,16 @@
135
135
  "@radix-ui/react-progress": "^1.1.7",
136
136
  "@radix-ui/react-slot": "^1.2.3",
137
137
  "@radix-ui/react-switch": "^1.2.6",
138
- "@uidotdev/usehooks": "^2.4.1",
139
138
  "class-variance-authority": "^0.7.1",
140
139
  "clsx": "^2.1.1",
140
+ "date-fns": "^4.4.0",
141
141
  "gsap": "^3.15.0",
142
142
  "lucide-react": "^0.542.0",
143
143
  "motion": "^12.23.12",
144
144
  "postcss": "^8.4.31",
145
145
  "radix-ui": "^1.4.3",
146
146
  "react-colorful": "^5.6.1",
147
+ "react-day-picker": "^10.0.1",
147
148
  "react-resizable-panels": "^4.10.0",
148
149
  "react-use": "^17.6.0",
149
150
  "swiper": "^11.2.10",