@jbpark/ui-kit 3.1.0 → 3.2.1
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/components/atoms/date-picker.mjs +7 -7
- package/dist/components/atoms/date-picker.mjs.map +1 -1
- package/dist/components/molecules/upload.d.mts.map +1 -1
- package/dist/components/molecules/upload.mjs +7 -4
- package/dist/components/molecules/upload.mjs.map +1 -1
- package/dist/components/organisms/drawer.mjs +3 -3
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/core/calendar.mjs +7 -7
- package/dist/core/calendar.mjs.map +1 -1
- package/dist/style.css +15 -12
- package/package.json +1 -1
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils.mjs";
|
|
4
|
-
import { button_exports } from "../../core/button.mjs";
|
|
5
4
|
import { calendar_exports } from "../../core/calendar.mjs";
|
|
5
|
+
import Button from "../../Button.mjs";
|
|
6
6
|
import Popover from "./popover.mjs";
|
|
7
7
|
import { CalendarIcon } from "lucide-react";
|
|
8
8
|
import { useState } from "react";
|
|
9
|
-
import { jsx
|
|
9
|
+
import { jsx } from "react/jsx-runtime";
|
|
10
10
|
import { format } from "date-fns";
|
|
11
11
|
|
|
12
12
|
//#region src/components/atoms/date-picker.tsx
|
|
13
13
|
const { Calendar } = calendar_exports;
|
|
14
|
-
const { buttonVariants } = button_exports;
|
|
15
14
|
const DatePicker = ({ defaultValue, value: _value, placeholder = "Pick a date", className, onChange: _onChange = () => {} }) => {
|
|
16
15
|
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
17
16
|
const controlled = _value !== void 0;
|
|
@@ -27,11 +26,12 @@ const DatePicker = ({ defaultValue, value: _value, placeholder = "Pick a date",
|
|
|
27
26
|
selected: value,
|
|
28
27
|
onSelect: onChange
|
|
29
28
|
}),
|
|
30
|
-
children: /* @__PURE__ */
|
|
31
|
-
type: "
|
|
29
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
30
|
+
type: "default",
|
|
31
|
+
icon: /* @__PURE__ */ jsx(CalendarIcon, {}),
|
|
32
32
|
"data-empty": !value,
|
|
33
|
-
className: cn(
|
|
34
|
-
children:
|
|
33
|
+
className: cn("w-full justify-start text-left font-normal", "data-[empty=true]:text-muted-foreground", className),
|
|
34
|
+
children: value ? format(value, "PPP") : placeholder
|
|
35
35
|
})
|
|
36
36
|
});
|
|
37
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.mjs","names":["calendar"
|
|
1
|
+
{"version":3,"file":"date-picker.mjs","names":["calendar"],"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 { calendar } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from './button';\nimport Popover from './popover';\n\nconst { Calendar } = calendar;\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=\"default\"\n icon={<CalendarIcon />}\n data-empty={!value}\n className={cn(\n 'w-full justify-start text-left font-normal',\n 'data-[empty=true]:text-muted-foreground',\n className,\n //\n )}\n >\n {value ? format(value, 'PPP') : placeholder}\n </Button>\n </Popover>\n );\n};\n\nexport default DatePicker;\nexport type { Props };\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,EAAE,aAAaA;AAUrB,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,oBAAC;GACC,MAAK;GACL,MAAM,oBAAC,iBAAe;GACtB,cAAY,CAAC;GACb,WAAW,GACT,8CACA,2CACA,UAED;aAEA,QAAQ,OAAO,OAAO,MAAM,GAAG;IACzB;GACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.mts","names":[],"sources":["../../../src/components/molecules/upload.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"upload.d.mts","names":[],"sources":["../../../src/components/molecules/upload.tsx"],"mappings":";;;UAWiB,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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../utils.mjs";
|
|
4
|
+
import Button from "../../Button.mjs";
|
|
4
5
|
import { Upload, X } from "lucide-react";
|
|
5
6
|
import { useId, useState } from "react";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -83,12 +84,14 @@ const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept =
|
|
|
83
84
|
className: "flex-1 truncate text-sm",
|
|
84
85
|
children: file.name
|
|
85
86
|
}),
|
|
86
|
-
/* @__PURE__ */ jsx(
|
|
87
|
-
type: "
|
|
87
|
+
/* @__PURE__ */ jsx(Button, {
|
|
88
|
+
type: "text",
|
|
89
|
+
shape: "circle",
|
|
90
|
+
size: "small",
|
|
91
|
+
icon: /* @__PURE__ */ jsx(X, { className: "size-4" }),
|
|
88
92
|
onClick: () => removeFile(file.uid),
|
|
89
93
|
className: "text-muted-foreground hover:text-foreground shrink-0",
|
|
90
|
-
"aria-label": `Remove ${file.name}
|
|
91
|
-
children: /* @__PURE__ */ jsx(X, { className: "size-4" })
|
|
94
|
+
"aria-label": `Remove ${file.name}`
|
|
92
95
|
})
|
|
93
96
|
]
|
|
94
97
|
}, file.uid))
|
|
@@ -1 +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 <
|
|
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\nimport Button from '../atoms/button';\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=\"text\"\n shape=\"circle\"\n size=\"small\"\n icon={<X className=\"size-4\" />}\n onClick={() => removeFile(file.uid)}\n className=\"text-muted-foreground hover:text-foreground shrink-0\"\n aria-label={`Remove ${file.name}`}\n />\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nexport default Upload;\n"],"mappings":";;;;;;;;;;AAiCA,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,OAAM;MACN,MAAK;MACL,MAAM,oBAAC,KAAE,WAAU,WAAW;MAC9B,eAAe,WAAW,KAAK,IAAI;MACnC,WAAU;MACV,cAAY,UAAU,KAAK;OAC3B;;MAvBG,KAAK,IAwBP,CACL;IACC;GAEH"}
|
|
@@ -67,15 +67,15 @@ const Drawer = ({ open, title, extra, footer, closable = true, closeIcon, direct
|
|
|
67
67
|
className: cn(classNames?.header, !title && "p-0"),
|
|
68
68
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
69
69
|
className: "flex items-start gap-2",
|
|
70
|
-
children: [
|
|
70
|
+
children: [closable && /* @__PURE__ */ jsx(Button, {
|
|
71
71
|
type: "text",
|
|
72
72
|
shape: "circle",
|
|
73
73
|
size: "small",
|
|
74
74
|
"aria-label": "닫기",
|
|
75
|
-
icon:
|
|
75
|
+
icon: closeIcon || /* @__PURE__ */ jsx(X, {}),
|
|
76
76
|
onClick: onClose,
|
|
77
77
|
className: cn(classNames?.close)
|
|
78
|
-
})
|
|
78
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
79
79
|
className: "flex flex-1 items-start justify-between gap-2",
|
|
80
80
|
children: [/* @__PURE__ */ jsx(DrawerTitle, {
|
|
81
81
|
className: cn(classNames?.title),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `document.body.style.pointerEvents` is global state, so several mask-less\n// overlays opening at once would otherwise race: each instance would capture\n// whatever the previous one had already written and the last cleanup would\n// restore a stale value. Reference counting makes only the first instance\n// capture the original value and only the last one restore it.\nlet maskLessOverlayCount = 0;\nlet originalBodyPointerEvents: string | null = null;\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n if (maskLessOverlayCount === 0) {\n originalBodyPointerEvents = document.body.style.pointerEvents;\n }\n maskLessOverlayCount += 1;\n\n const raf = window.requestAnimationFrame(() => {\n document.body.style.pointerEvents = 'auto';\n });\n\n return () => {\n window.cancelAnimationFrame(raf);\n maskLessOverlayCount -= 1;\n\n if (maskLessOverlayCount === 0) {\n document.body.style.pointerEvents = originalBodyPointerEvents ?? '';\n originalBodyPointerEvents = null;\n }\n };\n }, [open, mask]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? 'rounded-t-[30px]!' : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {
|
|
1
|
+
{"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `document.body.style.pointerEvents` is global state, so several mask-less\n// overlays opening at once would otherwise race: each instance would capture\n// whatever the previous one had already written and the last cleanup would\n// restore a stale value. Reference counting makes only the first instance\n// capture the original value and only the last one restore it.\nlet maskLessOverlayCount = 0;\nlet originalBodyPointerEvents: string | null = null;\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n if (maskLessOverlayCount === 0) {\n originalBodyPointerEvents = document.body.style.pointerEvents;\n }\n maskLessOverlayCount += 1;\n\n const raf = window.requestAnimationFrame(() => {\n document.body.style.pointerEvents = 'auto';\n });\n\n return () => {\n window.cancelAnimationFrame(raf);\n maskLessOverlayCount -= 1;\n\n if (maskLessOverlayCount === 0) {\n document.body.style.pointerEvents = originalBodyPointerEvents ?? '';\n originalBodyPointerEvents = null;\n }\n };\n }, [open, mask]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? 'rounded-t-[30px]!' : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {closable && (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label=\"닫기\"\n icon={closeIcon || <X />}\n onClick={onClose}\n className={cn(classNames?.close)}\n />\n )}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <DrawerTitle className={cn(classNames?.title)}>\n {title}\n </DrawerTitle>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n <DrawerDescription className=\"hidden\" />\n </DrawerHeader>\n <div\n className={cn(\n 'overflow-auto p-5',\n classNames?.body,\n //\n )}\n >\n {children}\n </div>\n {renderConditional(footer, v => (\n <DrawerFooter className={cn(classNames?.footer)}>{v}</DrawerFooter>\n ))}\n </DrawerContent>\n </DrawerCore>\n );\n};\n\nexport default Drawer;\n"],"mappings":";;;;;;;;;;AAWA,MAAM,EACJ,eACA,QAAQ,YACR,mBACA,cACA,cACA,gBACEA;AAOJ,IAAI,uBAAuB;AAC3B,IAAI,4BAA2C;AAkC/C,MAAM,QAAgC;CACpC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACP;AAED,MAAM,iBACJ,WACA,SACwB;CACxB,MAAM,QAAQ,MAAM,SAAS;AAE7B,QAAO,cAAc,SAAS,cAAc,WACxC,EAAE,QAAQ,OAAO,GACjB,EAAE,OAAO,OAAO;;AAGtB,MAAM,UAAU,EACd,MACA,OACA,OACA,QACA,WAAW,MACX,WACA,YAAY,UACZ,OAAO,UACP,eAAe,MACf,YAAY,MACZ,YAAY,OACZ,UAAU,OACV,OAAO,MACP,WACA,YACA,OACA,UACA,WACA,SACA,GAAG,YACQ;AACX,iBAAgB;AACd,MAAI,CAAC,QAAQ,KACX;AAGF,MAAI,yBAAyB,EAC3B,6BAA4B,SAAS,KAAK,MAAM;AAElD,0BAAwB;EAExB,MAAM,MAAM,OAAO,4BAA4B;AAC7C,YAAS,KAAK,MAAM,gBAAgB;IACpC;AAEF,eAAa;AACX,UAAO,qBAAqB,IAAI;AAChC,2BAAwB;AAExB,OAAI,yBAAyB,GAAG;AAC9B,aAAS,KAAK,MAAM,gBAAgB,6BAA6B;AACjE,gCAA4B;;;IAG/B,CAAC,MAAM,KAAK,CAAC;AAEhB,QACE,oBAAC;EACO;EACK;EACX,YAAY,CAAC;EACF;EACX,eAAc,SAAQ;AACpB,OAAI,CAAC,KACH,UAAS;;EAGb,GAAI;YAEJ,qBAAC;GACC,WAAW,GACT,4BACA,UAAU,sBAAsB,iBAChC,YAAY,SACZ,UAED;GACU;GACL;GACN,uBAAsB,UAAS;AAC7B,QAAI,CAAC,aACH,OAAM,gBAAgB;;GAG1B,YAAY;IACV,MAAM,YAAY,QAAQ;IAC1B,WAAW,YAAY,aAAa;IACrC;GACD,OAAO;IACL,GAAG,cAAc,WAAW,KAAK;IACjC,GAAG;IACJ;;IAED,qBAAC;KACC,WAAW,GACT,YAAY,QACZ,CAAC,SAAS,MAEX;gBAED,qBAAC;MAAI,WAAU;iBACZ,YACC,oBAAC;OACC,MAAK;OACL,OAAM;OACN,MAAK;OACL,cAAW;OACX,MAAM,aAAa,oBAAC,MAAI;OACxB,SAAS;OACT,WAAW,GAAG,YAAY,MAAM;QAChC,EAEJ,qBAAC;OAAI,WAAU;kBACb,oBAAC;QAAY,WAAW,GAAG,YAAY,MAAM;kBAC1C;SACW,EACb,kBAAkB,QAAO,MACxB,oBAAC;QAAI,WAAW,GAAG,YAAY,YAAY,MAAM;kBAAG;SAAQ,CAC5D;QACE;OACF,EACN,oBAAC,qBAAkB,WAAU,WAAW;MAC3B;IACf,oBAAC;KACC,WAAW,GACT,qBACA,YAAY,KAEb;KAEA;MACG;IACL,kBAAkB,SAAQ,MACzB,oBAAC;KAAa,WAAW,GAAG,YAAY,OAAO;eAAG;MAAiB,CACnE;;IACY;GACL"}
|
package/dist/core/calendar.mjs
CHANGED
|
@@ -30,10 +30,10 @@ function Calendar({ className, classNames, showOutsideDays = true, captionLayout
|
|
|
30
30
|
months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
|
|
31
31
|
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
32
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-
|
|
34
|
-
button_next: cn(buttonVariants({ variant: buttonVariant }), "h-
|
|
35
|
-
month_caption: cn("flex h-
|
|
36
|
-
dropdowns: cn("flex h-
|
|
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
37
|
dropdown_root: cn(`has-focus:border-ring border-input shadow-xs
|
|
38
38
|
has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md
|
|
39
39
|
border`, defaultClassNames.dropdown_root),
|
|
@@ -44,7 +44,7 @@ function Calendar({ className, classNames, showOutsideDays = true, captionLayout
|
|
|
44
44
|
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
45
45
|
weekday: cn("text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", defaultClassNames.weekday),
|
|
46
46
|
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
47
|
-
week_number_header: cn("w-
|
|
47
|
+
week_number_header: cn("w-(--cell-size) select-none", defaultClassNames.week_number_header),
|
|
48
48
|
week_number: cn("text-muted-foreground select-none text-[0.8rem]", defaultClassNames.week_number),
|
|
49
49
|
day: cn(`group/day relative aspect-square h-full w-full select-none p-0
|
|
50
50
|
text-center [&:first-child[data-selected=true]_button]:rounded-l-md
|
|
@@ -86,7 +86,7 @@ function Calendar({ className, classNames, showOutsideDays = true, captionLayout
|
|
|
86
86
|
return /* @__PURE__ */ jsx("td", {
|
|
87
87
|
...props,
|
|
88
88
|
children: /* @__PURE__ */ jsx("div", {
|
|
89
|
-
className: "flex size-
|
|
89
|
+
className: "flex size-(--cell-size) items-center justify-center\n text-center",
|
|
90
90
|
children
|
|
91
91
|
})
|
|
92
92
|
});
|
|
@@ -121,7 +121,7 @@ function CalendarDayButton({ className, day, modifiers, ...props }) {
|
|
|
121
121
|
data-[range-end=true]:text-primary-foreground
|
|
122
122
|
group-data-[focused=true]/day:border-ring
|
|
123
123
|
group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto
|
|
124
|
-
w-full min-w-
|
|
124
|
+
w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal
|
|
125
125
|
group-data-[focused=true]/day:relative
|
|
126
126
|
group-data-[focused=true]/day:z-10
|
|
127
127
|
group-data-[focused=true]/day:ring-[3px]
|
|
@@ -1 +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":"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"}
|
|
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":"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"}
|
package/dist/style.css
CHANGED
|
@@ -431,6 +431,10 @@
|
|
|
431
431
|
.aspect-square {
|
|
432
432
|
aspect-ratio: 1 / 1;
|
|
433
433
|
}
|
|
434
|
+
.size-\(--cell-size\) {
|
|
435
|
+
width: var(--cell-size);
|
|
436
|
+
height: var(--cell-size);
|
|
437
|
+
}
|
|
434
438
|
.size-2 {
|
|
435
439
|
width: calc(var(--spacing) * 2);
|
|
436
440
|
height: calc(var(--spacing) * 2);
|
|
@@ -471,9 +475,8 @@
|
|
|
471
475
|
width: calc(var(--spacing) * 10);
|
|
472
476
|
height: calc(var(--spacing) * 10);
|
|
473
477
|
}
|
|
474
|
-
.
|
|
475
|
-
|
|
476
|
-
height: --cell-size;
|
|
478
|
+
.h-\(--cell-size\) {
|
|
479
|
+
height: var(--cell-size);
|
|
477
480
|
}
|
|
478
481
|
.h-2 {
|
|
479
482
|
height: calc(var(--spacing) * 2);
|
|
@@ -541,6 +544,9 @@
|
|
|
541
544
|
.min-h-screen {
|
|
542
545
|
min-height: 100vh;
|
|
543
546
|
}
|
|
547
|
+
.w-\(--cell-size\) {
|
|
548
|
+
width: var(--cell-size);
|
|
549
|
+
}
|
|
544
550
|
.w-3 {
|
|
545
551
|
width: calc(var(--spacing) * 3);
|
|
546
552
|
}
|
|
@@ -574,9 +580,6 @@
|
|
|
574
580
|
.w-100 {
|
|
575
581
|
width: calc(var(--spacing) * 100);
|
|
576
582
|
}
|
|
577
|
-
.w-\[--cell-size\] {
|
|
578
|
-
width: --cell-size;
|
|
579
|
-
}
|
|
580
583
|
.w-\[100px\] {
|
|
581
584
|
width: 100px;
|
|
582
585
|
}
|
|
@@ -601,15 +604,15 @@
|
|
|
601
604
|
.max-w-\[calc\(100\%-2rem\)\] {
|
|
602
605
|
max-width: calc(100% - 2rem);
|
|
603
606
|
}
|
|
607
|
+
.min-w-\(--cell-size\) {
|
|
608
|
+
min-width: var(--cell-size);
|
|
609
|
+
}
|
|
604
610
|
.min-w-0 {
|
|
605
611
|
min-width: calc(var(--spacing) * 0);
|
|
606
612
|
}
|
|
607
613
|
.min-w-80 {
|
|
608
614
|
min-width: calc(var(--spacing) * 80);
|
|
609
615
|
}
|
|
610
|
-
.min-w-\[--cell-size\] {
|
|
611
|
-
min-width: --cell-size;
|
|
612
|
-
}
|
|
613
616
|
.min-w-\[8rem\] {
|
|
614
617
|
min-width: 8rem;
|
|
615
618
|
}
|
|
@@ -1068,6 +1071,9 @@
|
|
|
1068
1071
|
.p-6 {
|
|
1069
1072
|
padding: calc(var(--spacing) * 6);
|
|
1070
1073
|
}
|
|
1074
|
+
.px-\(--cell-size\) {
|
|
1075
|
+
padding-inline: var(--cell-size);
|
|
1076
|
+
}
|
|
1071
1077
|
.px-1 {
|
|
1072
1078
|
padding-inline: calc(var(--spacing) * 1);
|
|
1073
1079
|
}
|
|
@@ -1092,9 +1098,6 @@
|
|
|
1092
1098
|
.px-6 {
|
|
1093
1099
|
padding-inline: calc(var(--spacing) * 6);
|
|
1094
1100
|
}
|
|
1095
|
-
.px-\[--cell-size\] {
|
|
1096
|
-
padding-inline: --cell-size;
|
|
1097
|
-
}
|
|
1098
1101
|
.py-0 {
|
|
1099
1102
|
padding-block: calc(var(--spacing) * 0);
|
|
1100
1103
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbpark/ui-kit",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
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",
|