@jbpark/ui-kit 6.0.0 → 6.0.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/Button.d.mts +24 -3
- package/dist/Button.d.mts.map +1 -1
- package/dist/Button.mjs +2 -4
- package/dist/Button.mjs.map +1 -1
- package/dist/components/atoms/date-picker.mjs +0 -1
- package/dist/components/atoms/date-picker.mjs.map +1 -1
- package/dist/components/molecules/upload.mjs +1 -1
- package/dist/components/molecules/upload.mjs.map +1 -1
- package/dist/components/organisms/drawer.mjs +1 -1
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/components/organisms/toast.mjs +1 -1
- package/dist/components/organisms/toast.mjs.map +1 -1
- package/dist/components/templates/page-header.mjs +1 -1
- package/dist/components/templates/page-header.mjs.map +1 -1
- package/package.json +1 -1
package/dist/Button.d.mts
CHANGED
|
@@ -11,11 +11,32 @@ interface Props extends Omit<NativeButtonProps, 'size' | 'variant' | 'type'> {
|
|
|
11
11
|
disabled?: boolean;
|
|
12
12
|
size?: 'small' | 'middle' | 'large';
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* @deprecated Use `variant` instead. `type` is an alias kept for backwards
|
|
15
|
+
* compatibility and will be removed in the next major.
|
|
16
|
+
*
|
|
17
|
+
* The two props address the same axis, and 3 of the 5 values (`dashed`,
|
|
18
|
+
* `text`, `link`) are already spelled identically — `<Button type="text">`
|
|
19
|
+
* and `<Button variant="text">` render the same thing. The only values
|
|
20
|
+
* `type` contributes are the aliases `primary` → `solid` and
|
|
21
|
+
* `default` → `outlined`. `variant` additionally offers `filled`, which
|
|
22
|
+
* `type` cannot express.
|
|
23
|
+
*
|
|
24
|
+
* Migration:
|
|
25
|
+
* | `type` | `variant` |
|
|
26
|
+
* | --------- | ----------- |
|
|
27
|
+
* | `primary` | `solid` |
|
|
28
|
+
* | `default` | `outlined` |
|
|
29
|
+
* | `dashed` | `dashed` |
|
|
30
|
+
* | `text` | `text` |
|
|
31
|
+
* | `link` | `link` |
|
|
32
|
+
*
|
|
33
|
+
* Passing both still lets `variant` win.
|
|
17
34
|
*/
|
|
18
35
|
type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';
|
|
36
|
+
/**
|
|
37
|
+
* Visual fill style. This is the canonical prop — prefer it over `type`.
|
|
38
|
+
* Defaults to `'outlined'` (matching the legacy `type="default"`).
|
|
39
|
+
*/
|
|
19
40
|
variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';
|
|
20
41
|
/**
|
|
21
42
|
* Native `<button>` `type` (`button`/`submit`/`reset`), kept separate
|
package/dist/Button.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":";;KAYK,oBAAoB,QAAM;EAC7B;;KAGG;UAeY,cAAc,KAC7B;EAGA,OAAO,QAAM;EACb;EACA;EACA;EACA;;;;;;EAMA;EACA
|
|
1
|
+
{"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":";;KAYK,oBAAoB,QAAM;EAC7B;;KAGG;UAeY,cAAc,KAC7B;EAGA,OAAO,QAAM;EACb;EACA;EACA;EACA;;;;;;;;;;;;;;;;;;;;;;;EAuBA;;;;;EAKA;;;;;;EAMA;EACA;EACA,QAAQ;EACR;IAAsB,MAAM,QAAM;;;cA2E9B,WAAU,MAAA,WAAA,MAAA,SAAA,UAAA,MAAA,OAAA,OAAA,OAAA,UAAA,SAAA,QAAA,SAAA,UAAA,gBAAA,SAiBb,UAAK,QAAA,IAAA"}
|
package/dist/Button.mjs
CHANGED
|
@@ -39,7 +39,7 @@ const shapesClasses = {
|
|
|
39
39
|
circle: "rounded-full",
|
|
40
40
|
round: "rounded-2xl"
|
|
41
41
|
};
|
|
42
|
-
const Button = ({ icon, className, type
|
|
42
|
+
const Button = ({ icon, className, type, variant, htmlType = "button", size, color = "default", shape, block = false, disabled, loading, danger, asChild = false, children, onMouseDown, ...props }) => {
|
|
43
43
|
const { componentSize, defaultProps } = useConfig();
|
|
44
44
|
const buttonDefaults = defaultProps?.button;
|
|
45
45
|
const resolvedSize = size ?? componentSize ?? "middle";
|
|
@@ -47,14 +47,12 @@ const Button = ({ icon, className, type = "default", variant, htmlType = "button
|
|
|
47
47
|
const iconOnly = icon && !children;
|
|
48
48
|
const computedColor = danger ? "danger" : color;
|
|
49
49
|
const colored = computedColor && computedColor !== "default";
|
|
50
|
-
const resolvedVariant = variant ?? typeToVariant[type] ?? "
|
|
50
|
+
const resolvedVariant = variant ?? (type ? typeToVariant[type] : void 0) ?? "outlined";
|
|
51
51
|
const isLoading = !!loading;
|
|
52
52
|
const Comp = asChild ? Slot : "button";
|
|
53
53
|
const displayIcon = loading ? typeof loading === "object" ? loading.icon : /* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin" }) : icon;
|
|
54
54
|
return /* @__PURE__ */ jsxs(Comp, {
|
|
55
55
|
"data-slot": "button",
|
|
56
|
-
"data-variant": "default",
|
|
57
|
-
"data-size": "default",
|
|
58
56
|
className: cn(BUTTON_BASE, "inline-flex items-center justify-center gap-x-2", "rounded-lg", "cursor-pointer", "h-auto py-0", "transition-all", variantClasses[resolvedVariant], sizesClasses[resolvedSize], iconOnly && ["p-0", iconClasses[resolvedSize]], shapesClasses[resolvedShape], block && "w-full", colored && (resolvedVariant === "solid" ? [
|
|
59
57
|
"bg-(--btn-bg)",
|
|
60
58
|
"hover:bg-(--btn-bg-hover)",
|
package/dist/Button.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.mjs","names":[],"sources":["../src/components/atoms/button.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport { Slot } from '@radix-ui/react-slot';\nimport { LoaderCircle } from 'lucide-react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { INTERACTIVE_CHASSIS } from '../../lib/chassis';\n\ntype NativeButtonProps = React.ComponentProps<'button'> & {\n asChild?: boolean;\n};\n\ntype PresetColors =\n | 'blue'\n | 'purple'\n | 'cyan'\n | 'green'\n | 'magenta'\n | 'pink'\n | 'red'\n | 'orange'\n | 'yellow'\n | 'volcano'\n | 'geekblue'\n | 'lime'\n | 'gold';\n\nexport interface Props extends Omit<\n NativeButtonProps,\n 'size' | 'variant' | 'type'\n> {\n icon?: React.ReactNode;\n block?: boolean;\n danger?: boolean;\n disabled?: boolean;\n size?: 'small' | 'middle' | 'large';\n /**\n *
|
|
1
|
+
{"version":3,"file":"Button.mjs","names":[],"sources":["../src/components/atoms/button.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport { Slot } from '@radix-ui/react-slot';\nimport { LoaderCircle } from 'lucide-react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { INTERACTIVE_CHASSIS } from '../../lib/chassis';\n\ntype NativeButtonProps = React.ComponentProps<'button'> & {\n asChild?: boolean;\n};\n\ntype PresetColors =\n | 'blue'\n | 'purple'\n | 'cyan'\n | 'green'\n | 'magenta'\n | 'pink'\n | 'red'\n | 'orange'\n | 'yellow'\n | 'volcano'\n | 'geekblue'\n | 'lime'\n | 'gold';\n\nexport interface Props extends Omit<\n NativeButtonProps,\n 'size' | 'variant' | 'type'\n> {\n icon?: React.ReactNode;\n block?: boolean;\n danger?: boolean;\n disabled?: boolean;\n size?: 'small' | 'middle' | 'large';\n /**\n * @deprecated Use `variant` instead. `type` is an alias kept for backwards\n * compatibility and will be removed in the next major.\n *\n * The two props address the same axis, and 3 of the 5 values (`dashed`,\n * `text`, `link`) are already spelled identically — `<Button type=\"text\">`\n * and `<Button variant=\"text\">` render the same thing. The only values\n * `type` contributes are the aliases `primary` → `solid` and\n * `default` → `outlined`. `variant` additionally offers `filled`, which\n * `type` cannot express.\n *\n * Migration:\n * | `type` | `variant` |\n * | --------- | ----------- |\n * | `primary` | `solid` |\n * | `default` | `outlined` |\n * | `dashed` | `dashed` |\n * | `text` | `text` |\n * | `link` | `link` |\n *\n * Passing both still lets `variant` win.\n */\n type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';\n /**\n * Visual fill style. This is the canonical prop — prefer it over `type`.\n * Defaults to `'outlined'` (matching the legacy `type=\"default\"`).\n */\n variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';\n /**\n * Native `<button>` `type` (`button`/`submit`/`reset`), kept separate\n * from the antd-style `type` above. Defaults to `'button'` so a Button\n * placed inside a `<form>` doesn't submit it unless explicitly opted in.\n */\n htmlType?: 'button' | 'submit' | 'reset';\n shape?: 'default' | 'circle' | 'round';\n color?: PresetColors | 'default' | 'primary' | 'danger';\n loading?: boolean | { icon: React.ReactNode };\n}\n\n// Chassis absorbed from core/button's cva base (#278 ③ / #294 Phase 4). The\n// shared focus/aria set lives in INTERACTIVE_CHASSIS; a Button additionally\n// disables and sizes its icons. Kept as constants so the absorb relocates this\n// treatment rather than dropping it (the #177 class of silent regression the\n// #300/#301 net guards).\nconst BUTTON_CHASSIS = cn(\n INTERACTIVE_CHASSIS,\n 'outline-none',\n 'disabled:pointer-events-none disabled:opacity-50',\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n);\n\n// Presentation the atom builds on. The size/variant/shape classes below still\n// override the incidental leftovers exactly as they did when this wrapped\n// core/button, so the rendered output is unchanged (verified against a\n// pre-refactor render matrix).\nconst BUTTON_BASE = cn(\n BUTTON_CHASSIS,\n 'gap-2 whitespace-nowrap font-medium transition-all',\n 'has-[>svg]:px-3',\n);\n\nconst variantClasses: Record<string, string> = {\n // solid used to inherit its fill from core/button's default variant; carry it\n // explicitly now that the primitive is absorbed. A colored solid overrides\n // this with the --btn-* custom properties further down.\n solid: cn('bg-primary text-primary-foreground', 'hover:bg-primary/90'),\n outlined: cn(\n 'border border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n dashed: cn(\n 'border border-dashed border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n filled: cn('bg-muted text-foreground', 'hover:bg-muted/80'),\n text: cn('bg-transparent text-foreground', 'hover:bg-accent'),\n link: cn(\n 'bg-transparent text-primary',\n 'underline-offset-4 hover:underline',\n 'hover:bg-primary/10',\n ),\n};\n\nconst typeToVariant: Record<string, string> = {\n primary: 'solid',\n default: 'outlined',\n dashed: 'dashed',\n text: 'text',\n link: 'link',\n};\n\nconst sizesClasses: Record<string, string> = {\n small: 'h-6 px-3 text-sm',\n middle: 'h-8 px-4 text-base',\n large: 'h-10 px-5 text-lg',\n};\n\nconst iconClasses: Record<string, string> = {\n small: `size-6 [&_svg:not([class*='size-'])]:size-3`,\n middle: `size-8 [&_svg:not([class*='size-'])]:size-4`,\n large: `size-10 [&_svg:not([class*='size-'])]:size-5`,\n};\n\nconst shapesClasses = {\n default: 'rounded-sm',\n circle: 'rounded-full',\n round: 'rounded-2xl',\n};\n\nconst Button = ({\n icon,\n className,\n type,\n variant,\n htmlType = 'button',\n size,\n color = 'default',\n shape,\n block = false,\n disabled,\n loading,\n danger,\n asChild = false,\n children,\n onMouseDown,\n ...props\n}: Props) => {\n const { componentSize, defaultProps } = useConfig();\n const buttonDefaults = defaultProps?.button as\n Partial<Pick<Props, 'shape'>> | undefined;\n const resolvedSize = size ?? componentSize ?? 'middle';\n const resolvedShape = shape ?? buttonDefaults?.shape ?? 'default';\n const iconOnly = icon && !children;\n const computedColor = danger ? 'danger' : color;\n const colored = computedColor && computedColor !== 'default';\n // `variant` is canonical; `type` is a deprecated alias resolved through\n // typeToVariant. The default lives here (not on the `type` parameter) so the\n // deprecated prop stays off the default path — a Button with neither prop\n // resolves straight to 'outlined'.\n const resolvedVariant =\n variant ?? (type ? typeToVariant[type] : undefined) ?? 'outlined';\n const isLoading = !!loading;\n\n const Comp = asChild ? Slot : 'button';\n\n const displayIcon = loading ? (\n typeof loading === 'object' ? (\n loading.icon\n ) : (\n <LoaderCircle className=\"animate-spin\" />\n )\n ) : (\n icon\n );\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(\n BUTTON_BASE,\n 'inline-flex items-center justify-center gap-x-2',\n 'rounded-lg',\n 'cursor-pointer',\n 'h-auto py-0',\n 'transition-all',\n variantClasses[resolvedVariant],\n sizesClasses[resolvedSize],\n iconOnly && ['p-0', iconClasses[resolvedSize]],\n shapesClasses[resolvedShape],\n block && 'w-full',\n colored &&\n (resolvedVariant === 'solid'\n ? [\n 'bg-(--btn-bg)',\n 'hover:bg-(--btn-bg-hover)',\n 'active:bg-(--btn-bg-active)',\n 'text-(--btn-fg)',\n 'border-(--btn-border)',\n ]\n : [\n 'text-(--btn-bg)',\n 'border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n //\n ]),\n className,\n //\n )}\n type={htmlType}\n disabled={disabled || isLoading}\n aria-busy={isLoading}\n data-color={computedColor}\n onMouseDown={e => {\n onMouseDown?.(e);\n }}\n {...props}\n >\n {displayIcon}\n {children}\n </Comp>\n );\n};\n\nexport default Button;\n"],"mappings":";;;;;;;;;AAoFA,MAAM,iBAAiB,GACrB,qBACA,gBACA,oDACA,mFACF;AAMA,MAAM,cAAc,GAClB,gBACA,sDACA,iBACF;AAEA,MAAM,iBAAyC;CAI7C,OAAO,GAAG,sCAAsC,qBAAqB;CACrE,UAAU,GACR,yEACA,iCACA,iBACF;CACA,QAAQ,GACN,uFACA,iCACA,iBACF;CACA,QAAQ,GAAG,4BAA4B,mBAAmB;CAC1D,MAAM,GAAG,kCAAkC,iBAAiB;CAC5D,MAAM,GACJ,+BACA,sCACA,qBACF;AACF;AAEA,MAAM,gBAAwC;CAC5C,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,MAAM;AACR;AAEA,MAAM,eAAuC;CAC3C,OAAO;CACP,QAAQ;CACR,OAAO;AACT;AAEA,MAAM,cAAsC;CAC1C,OAAO;CACP,QAAQ;CACR,OAAO;AACT;AAEA,MAAM,gBAAgB;CACpB,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAEA,MAAM,UAAU,EACd,MACA,WACA,MACA,SACA,WAAW,UACX,MACA,QAAQ,WACR,OACA,QAAQ,OACR,UACA,SACA,QACA,UAAU,OACV,UACA,aACA,GAAG,YACQ;CACX,MAAM,EAAE,eAAe,iBAAiB,UAAU;CAClD,MAAM,iBAAiB,cAAc;CAErC,MAAM,eAAe,QAAQ,iBAAiB;CAC9C,MAAM,gBAAgB,SAAS,gBAAgB,SAAS;CACxD,MAAM,WAAW,QAAQ,CAAC;CAC1B,MAAM,gBAAgB,SAAS,WAAW;CAC1C,MAAM,UAAU,iBAAiB,kBAAkB;CAKnD,MAAM,kBACJ,YAAY,OAAO,cAAc,QAAQ,KAAA,MAAc;CACzD,MAAM,YAAY,CAAC,CAAC;CAEpB,MAAM,OAAO,UAAU,OAAO;CAE9B,MAAM,cAAc,UAClB,OAAO,YAAY,WACjB,QAAQ,OAER,oBAAC,cAAD,EAAc,WAAU,eAAgB,CAAA,IAG1C;CAGF,OACE,qBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,aACA,mDACA,cACA,kBACA,eACA,kBACA,eAAe,kBACf,aAAa,eACb,YAAY,CAAC,OAAO,YAAY,aAAa,GAC7C,cAAc,gBACd,SAAS,UACT,YACG,oBAAoB,UACjB;GACE;GACA;GACA;GACA;GACA;EACF,IACA,CACE,mBACA,gEAEF,IACN,SAEF;EACA,MAAM;EACN,UAAU,YAAY;EACtB,aAAW;EACX,cAAY;EACZ,cAAa,MAAK;GAChB,cAAc,CAAC;EACjB;EACA,GAAI;EAtCN,UAAA,CAwCG,aACA,QACG;;AAEV"}
|
|
@@ -1 +1 @@
|
|
|
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 { useControllableState } from '@jbpark/use-hooks';\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { calendar } from '../../core';\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 disabled?: boolean;\n onChange?: (date: Date | undefined) => void;\n}\n\nconst DatePicker = ({\n defaultValue,\n value: _value,\n placeholder = 'Pick a date',\n className,\n disabled,\n onChange: _onChange = () => {},\n}: Props) => {\n const [value, onChange] = useControllableState<Date | undefined>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n const [open, setOpen] = useState(false);\n\n return (\n <Popover\n placement=\"bottomLeft\"\n open={open}\n onOpenChange={setOpen}\n content={\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={date => {\n onChange(date);\n setOpen(false);\n }}\n />\n }\n >\n <Button\n
|
|
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 { useControllableState } from '@jbpark/use-hooks';\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { calendar } from '../../core';\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 disabled?: boolean;\n onChange?: (date: Date | undefined) => void;\n}\n\nconst DatePicker = ({\n defaultValue,\n value: _value,\n placeholder = 'Pick a date',\n className,\n disabled,\n onChange: _onChange = () => {},\n}: Props) => {\n const [value, onChange] = useControllableState<Date | undefined>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n const [open, setOpen] = useState(false);\n\n return (\n <Popover\n placement=\"bottomLeft\"\n open={open}\n onOpenChange={setOpen}\n content={\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={date => {\n onChange(date);\n setOpen(false);\n }}\n />\n }\n >\n <Button\n icon={<CalendarIcon />}\n data-empty={!value}\n disabled={disabled}\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":";;;;;;;;;;;AAcA,MAAM,EAAE,aAAaA;AAWrB,MAAM,cAAc,EAClB,cACA,OAAO,QACP,cAAc,eACd,WACA,UACA,UAAU,kBAAkB,CAAC,QAClB;CACX,MAAM,CAAC,OAAO,YAAY,qBAAuC;EAC/D,OAAO;EACP;EACA,UAAU;CACZ,CAAC;CACD,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,OACE,oBAAC,SAAD;EACE,WAAU;EACJ;EACN,cAAc;EACd,SACE,oBAAC,UAAD;GACE,MAAK;GACL,UAAU;GACV,WAAU,SAAQ;IAChB,SAAS,IAAI;IACb,QAAQ,KAAK;GACf;EACD,CAAA;EAGH,UAAA,oBAAC,QAAD;GACE,MAAM,oBAAC,cAAD,CAAe,CAAA;GACrB,cAAY,CAAC;GACH;GACV,WAAW,GACT,8CACA,2CACA,SAEF;GAEC,UAAA,QAAQ,OAAO,OAAO,KAAK,IAAI;EAC1B,CAAA;CACD,CAAA;AAEb"}
|
|
@@ -93,7 +93,7 @@ const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept =
|
|
|
93
93
|
children: file.name
|
|
94
94
|
}),
|
|
95
95
|
/* @__PURE__ */ jsx(Button, {
|
|
96
|
-
|
|
96
|
+
variant: "text",
|
|
97
97
|
shape: "circle",
|
|
98
98
|
size: "small",
|
|
99
99
|
icon: /* @__PURE__ */ jsx(X, { className: "size-4" }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.mjs","names":["Upload","UploadIcon"],"sources":["../../../src/components/molecules/upload.tsx"],"sourcesContent":["'use client';\n\nimport { useId } from 'react';\n\nimport {\n useControllableState,\n useFileDrop,\n useFileToDataUrl,\n} 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\n// Monotonic per-session counter used as a uniqueness tiebreaker for file\n// uids. Guarantees a unique suffix even for the same file (identical\n// name/lastModified/size) added twice, which name+lastModified+size alone\n// can't. These uids are internal React keys, not cryptographic, so a plain\n// counter is enough — and it avoids a runtime `uuid` dependency.\nlet uidCounter = 0;\nconst nextUid = () => (uidCounter += 1);\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 * Called once per file that didn't make it in — either bumped by\n * `maxCount` or failed to read.\n */\n onReject?: (info: { file: File; reason: 'max-count' | 'read-error' }) => 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 onReject,\n}: Props) => {\n const inputId = useId();\n const readAsDataUrl = useFileToDataUrl();\n const [files, setFiles] = useControllableState<UploadFile[]>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n\n const addFiles = async (incoming: File[]) => {\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 const rejected = incoming.slice(remaining);\n\n rejected.forEach(file => onReject?.({ file, reason: 'max-count' }));\n\n if (accepted.length === 0) {\n return;\n }\n\n const uploaded = (\n await Promise.all(\n accepted.map(async file => {\n try {\n return {\n // `nextUid()` guarantees uniqueness even for the same file\n // added twice (identical name/lastModified/size), which\n // name+lastModified+size alone can't — a collision there\n // corrupted React's item keys and made removeFile's\n // uid-based filter delete both copies at once.\n uid: `${file.name}-${file.lastModified}-${file.size}-${nextUid()}`,\n name: file.name,\n url: await readAsDataUrl(file),\n };\n } catch {\n onReject?.({ file, reason: 'read-error' });\n return null;\n }\n }),\n )\n ).filter((file): file is UploadFile => file !== null);\n\n if (uploaded.length === 0) {\n return;\n }\n\n setFiles([...files, ...uploaded]);\n };\n\n const removeFile = (uid: string) => {\n setFiles(files.filter(file => file.uid !== uid));\n };\n\n const { dropRef, isDragging } = useFileDrop<HTMLLabelElement>({\n accept,\n multiple,\n disabled,\n onDrop: addFiles,\n });\n\n return (\n <div\n className={cn(\n 'flex flex-col gap-3',\n className,\n //\n )}\n >\n <label\n ref={dropRef}\n htmlFor={inputId}\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 isDragging && '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(Array.from(e.target.files));\n }\n e.target.value = '';\n }}\n />\n </label>\n\n {files.length > 0 && (\n <ul\n className={cn(\n 'm-0 flex list-none flex-col gap-2 p-0',\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
|
|
1
|
+
{"version":3,"file":"upload.mjs","names":["Upload","UploadIcon"],"sources":["../../../src/components/molecules/upload.tsx"],"sourcesContent":["'use client';\n\nimport { useId } from 'react';\n\nimport {\n useControllableState,\n useFileDrop,\n useFileToDataUrl,\n} 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\n// Monotonic per-session counter used as a uniqueness tiebreaker for file\n// uids. Guarantees a unique suffix even for the same file (identical\n// name/lastModified/size) added twice, which name+lastModified+size alone\n// can't. These uids are internal React keys, not cryptographic, so a plain\n// counter is enough — and it avoids a runtime `uuid` dependency.\nlet uidCounter = 0;\nconst nextUid = () => (uidCounter += 1);\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 * Called once per file that didn't make it in — either bumped by\n * `maxCount` or failed to read.\n */\n onReject?: (info: { file: File; reason: 'max-count' | 'read-error' }) => 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 onReject,\n}: Props) => {\n const inputId = useId();\n const readAsDataUrl = useFileToDataUrl();\n const [files, setFiles] = useControllableState<UploadFile[]>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n\n const addFiles = async (incoming: File[]) => {\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 const rejected = incoming.slice(remaining);\n\n rejected.forEach(file => onReject?.({ file, reason: 'max-count' }));\n\n if (accepted.length === 0) {\n return;\n }\n\n const uploaded = (\n await Promise.all(\n accepted.map(async file => {\n try {\n return {\n // `nextUid()` guarantees uniqueness even for the same file\n // added twice (identical name/lastModified/size), which\n // name+lastModified+size alone can't — a collision there\n // corrupted React's item keys and made removeFile's\n // uid-based filter delete both copies at once.\n uid: `${file.name}-${file.lastModified}-${file.size}-${nextUid()}`,\n name: file.name,\n url: await readAsDataUrl(file),\n };\n } catch {\n onReject?.({ file, reason: 'read-error' });\n return null;\n }\n }),\n )\n ).filter((file): file is UploadFile => file !== null);\n\n if (uploaded.length === 0) {\n return;\n }\n\n setFiles([...files, ...uploaded]);\n };\n\n const removeFile = (uid: string) => {\n setFiles(files.filter(file => file.uid !== uid));\n };\n\n const { dropRef, isDragging } = useFileDrop<HTMLLabelElement>({\n accept,\n multiple,\n disabled,\n onDrop: addFiles,\n });\n\n return (\n <div\n className={cn(\n 'flex flex-col gap-3',\n className,\n //\n )}\n >\n <label\n ref={dropRef}\n htmlFor={inputId}\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 isDragging && '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(Array.from(e.target.files));\n }\n e.target.value = '';\n }}\n />\n </label>\n\n {files.length > 0 && (\n <ul\n className={cn(\n 'm-0 flex list-none flex-col gap-2 p-0',\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 variant=\"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":"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"}
|
|
@@ -92,7 +92,7 @@ const Drawer = ({ open, title, extra, footer, closable = true, closeIcon, direct
|
|
|
92
92
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
93
93
|
className: "flex items-start gap-2",
|
|
94
94
|
children: [closable && /* @__PURE__ */ jsx(Button, {
|
|
95
|
-
|
|
95
|
+
variant: "text",
|
|
96
96
|
shape: "circle",
|
|
97
97
|
size: "small",
|
|
98
98
|
"aria-label": locale.close ?? DEFAULT_LOCALE.close,
|
|
@@ -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 { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport { drawer } from '../../core';\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `body.style.pointerEvents` is global state (per document), so several\n// mask-less overlays opening at once would otherwise race: each instance\n// would capture whatever the previous one had already written and the\n// last cleanup would restore a stale value. Reference counting makes only\n// the first instance capture the original value and only the last one\n// restore it. Keyed by document (not a single module-level counter) so\n// drawers portaled into different documents — e.g. live-editor's iframe\n// Renderer — don't share state with the host document.\ntype MaskLessState = { count: number; originalPointerEvents: string | null };\nconst maskLessStates = new WeakMap<Document, MaskLessState>();\n\nconst getMaskLessState = (doc: Document): MaskLessState => {\n let state = maskLessStates.get(doc);\n\n if (!state) {\n state = { count: 0, originalPointerEvents: null };\n maskLessStates.set(doc, state);\n }\n\n return state;\n};\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\n// Rounds the edge facing into the viewport — the opposite edge from\n// whichever side the drawer is anchored to.\nconst ROUNDED_CLASSES: Record<'top' | 'bottom' | 'left' | 'right', string> = {\n top: 'rounded-b-[30px]!',\n bottom: 'rounded-t-[30px]!',\n left: 'rounded-r-[30px]!',\n right: 'rounded-l-[30px]!',\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 const { locale } = useConfig();\n\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n const targetDocument = container?.ownerDocument ?? document;\n const targetWindow = targetDocument.defaultView ?? window;\n const body = targetDocument.body;\n const state = getMaskLessState(targetDocument);\n\n if (state.count === 0) {\n state.originalPointerEvents = body.style.pointerEvents;\n }\n state.count += 1;\n\n const raf = targetWindow.requestAnimationFrame(() => {\n body.style.pointerEvents = 'auto';\n });\n\n return () => {\n targetWindow.cancelAnimationFrame(raf);\n state.count -= 1;\n\n if (state.count === 0) {\n body.style.pointerEvents = state.originalPointerEvents ?? '';\n state.originalPointerEvents = null;\n }\n };\n }, [open, mask, container]);\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_CLASSES[direction] : '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
|
|
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 { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport { drawer } from '../../core';\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `body.style.pointerEvents` is global state (per document), so several\n// mask-less overlays opening at once would otherwise race: each instance\n// would capture whatever the previous one had already written and the\n// last cleanup would restore a stale value. Reference counting makes only\n// the first instance capture the original value and only the last one\n// restore it. Keyed by document (not a single module-level counter) so\n// drawers portaled into different documents — e.g. live-editor's iframe\n// Renderer — don't share state with the host document.\ntype MaskLessState = { count: number; originalPointerEvents: string | null };\nconst maskLessStates = new WeakMap<Document, MaskLessState>();\n\nconst getMaskLessState = (doc: Document): MaskLessState => {\n let state = maskLessStates.get(doc);\n\n if (!state) {\n state = { count: 0, originalPointerEvents: null };\n maskLessStates.set(doc, state);\n }\n\n return state;\n};\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\n// Rounds the edge facing into the viewport — the opposite edge from\n// whichever side the drawer is anchored to.\nconst ROUNDED_CLASSES: Record<'top' | 'bottom' | 'left' | 'right', string> = {\n top: 'rounded-b-[30px]!',\n bottom: 'rounded-t-[30px]!',\n left: 'rounded-r-[30px]!',\n right: 'rounded-l-[30px]!',\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 const { locale } = useConfig();\n\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n const targetDocument = container?.ownerDocument ?? document;\n const targetWindow = targetDocument.defaultView ?? window;\n const body = targetDocument.body;\n const state = getMaskLessState(targetDocument);\n\n if (state.count === 0) {\n state.originalPointerEvents = body.style.pointerEvents;\n }\n state.count += 1;\n\n const raf = targetWindow.requestAnimationFrame(() => {\n body.style.pointerEvents = 'auto';\n });\n\n return () => {\n targetWindow.cancelAnimationFrame(raf);\n state.count -= 1;\n\n if (state.count === 0) {\n body.style.pointerEvents = state.originalPointerEvents ?? '';\n state.originalPointerEvents = null;\n }\n };\n }, [open, mask, container]);\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_CLASSES[direction] : '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 variant=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label={locale.close ?? DEFAULT_LOCALE.close}\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":"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"}
|
|
@@ -43,7 +43,7 @@ const Toast = ({ type, title, description, icon, closable = true, action, classN
|
|
|
43
43
|
]
|
|
44
44
|
}),
|
|
45
45
|
closable && /* @__PURE__ */ jsx(Button, {
|
|
46
|
-
|
|
46
|
+
variant: "text",
|
|
47
47
|
shape: "circle",
|
|
48
48
|
size: "small",
|
|
49
49
|
"aria-label": locale.close ?? DEFAULT_LOCALE.close,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.mjs","names":[],"sources":["../../../src/components/organisms/toast.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTimeout } from '@jbpark/use-hooks';\nimport { Check, Info, OctagonAlert, OctagonX, X } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\nimport {\n type ImperativeStack,\n createImperativeStack,\n isBrowser,\n} from './imperative-stack';\n\ntype ToastType = 'info' | 'success' | 'error' | 'warning';\n\nexport interface Props {\n type?: ToastType;\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n closable?: boolean;\n action?: React.ReactNode;\n className?: string;\n onClose?: () => void;\n}\n\ninterface StaticProps extends Props {\n id?: string;\n duration?: number;\n container?: HTMLElement;\n}\n\nconst TYPE_ICONS: Record<ToastType, React.ReactNode> = {\n info: <Info className=\"text-blue-400\" />,\n success: <Check className=\"text-green-400\" />,\n error: <OctagonX className=\"text-red-400\" />,\n warning: <OctagonAlert className=\"text-yellow-400\" />,\n};\n\nconst Toast = ({\n type,\n title,\n description,\n icon,\n closable = true,\n action,\n className,\n onClose,\n}: Props) => {\n const { locale } = useConfig();\n\n return (\n <div\n role={type === 'error' ? 'alert' : 'status'}\n className={cn(\n 'pointer-events-auto flex w-80 items-start gap-3 rounded-lg',\n 'bg-background text-foreground border p-4 shadow-lg',\n className,\n //\n )}\n >\n {(icon || type) && (\n <div className=\"mt-0.5 shrink-0 [&_svg]:size-5\">\n {icon || (type && TYPE_ICONS[type])}\n </div>\n )}\n <div className=\"flex-1 space-y-1\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"text-muted-foreground text-sm\">{description}</p>\n )}\n {action && <div className=\"pt-1\">{action}</div>}\n </div>\n {closable && (\n <Button\n
|
|
1
|
+
{"version":3,"file":"toast.mjs","names":[],"sources":["../../../src/components/organisms/toast.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTimeout } from '@jbpark/use-hooks';\nimport { Check, Info, OctagonAlert, OctagonX, X } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\nimport {\n type ImperativeStack,\n createImperativeStack,\n isBrowser,\n} from './imperative-stack';\n\ntype ToastType = 'info' | 'success' | 'error' | 'warning';\n\nexport interface Props {\n type?: ToastType;\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n closable?: boolean;\n action?: React.ReactNode;\n className?: string;\n onClose?: () => void;\n}\n\ninterface StaticProps extends Props {\n id?: string;\n duration?: number;\n container?: HTMLElement;\n}\n\nconst TYPE_ICONS: Record<ToastType, React.ReactNode> = {\n info: <Info className=\"text-blue-400\" />,\n success: <Check className=\"text-green-400\" />,\n error: <OctagonX className=\"text-red-400\" />,\n warning: <OctagonAlert className=\"text-yellow-400\" />,\n};\n\nconst Toast = ({\n type,\n title,\n description,\n icon,\n closable = true,\n action,\n className,\n onClose,\n}: Props) => {\n const { locale } = useConfig();\n\n return (\n <div\n role={type === 'error' ? 'alert' : 'status'}\n className={cn(\n 'pointer-events-auto flex w-80 items-start gap-3 rounded-lg',\n 'bg-background text-foreground border p-4 shadow-lg',\n className,\n //\n )}\n >\n {(icon || type) && (\n <div className=\"mt-0.5 shrink-0 [&_svg]:size-5\">\n {icon || (type && TYPE_ICONS[type])}\n </div>\n )}\n <div className=\"flex-1 space-y-1\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"text-muted-foreground text-sm\">{description}</p>\n )}\n {action && <div className=\"pt-1\">{action}</div>}\n </div>\n {closable && (\n <Button\n variant=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label={locale.close ?? DEFAULT_LOCALE.close}\n icon={<X />}\n onClick={onClose}\n />\n )}\n </div>\n );\n};\n\nconst DEFAULT_DURATION = 4000;\n\nconst StaticToast = ({\n id,\n duration = DEFAULT_DURATION,\n container,\n onClose,\n ...props\n}: StaticProps & { id: string }): React.ReactPortal | null => {\n const [visible, setVisible] = useState(true);\n\n const close = () => {\n onClose?.();\n setVisible(false);\n setTimeout(() => {\n toastStack.destroy(id);\n }, 200);\n };\n\n const { reset, clear } = useTimeout(close, duration || null);\n\n if (!isBrowser) {\n return null;\n }\n\n return createPortal(\n <div\n className={cn(\n 'transition-all duration-200',\n visible ? 'opacity-100' : 'translate-x-2 opacity-0',\n )}\n // Without this, a toast with a closable/action button (or one the\n // user is mid-read on) could auto-dismiss itself out from under\n // them — hovering or focusing anything inside pauses the timer,\n // moving away restarts it from the full duration.\n onMouseEnter={clear}\n onMouseLeave={reset}\n onFocus={clear}\n onBlur={reset}\n >\n <Toast {...props} onClose={close} />\n </div>,\n toastStack.getRootElement(container)!,\n );\n};\n\nconst toastStack: ImperativeStack<StaticProps> =\n createImperativeStack<StaticProps>({\n createRootElement: () => {\n const el = document.createElement('div');\n el.setAttribute('role', 'region');\n // Plain DOM, created outside any React tree — no Config to read a\n // locale override from until #226 gives the imperative stack a way\n // to inherit one.\n el.setAttribute('aria-label', 'Notifications');\n el.style.zIndex = '10000';\n el.style.position = 'fixed';\n el.style.right = '0';\n el.style.bottom = '0';\n el.style.display = 'flex';\n el.style.flexDirection = 'column-reverse';\n el.style.gap = '8px';\n el.style.padding = '16px';\n el.style.pointerEvents = 'none';\n return el;\n },\n StackItem: StaticToast,\n });\n\nToast.destroy = toastStack.destroy;\n\nToast.destroyAll = () => {\n toastStack.destroy();\n};\n\ntype TriggerOptions = Omit<StaticProps, 'type' | 'title'>;\n\nToast.info = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ type: 'info', title, ...props });\nToast.success = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ type: 'success', title, ...props });\nToast.error = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ type: 'error', title, ...props });\nToast.warning = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ type: 'warning', title, ...props });\n\nexport default Toast;\nexport type { StaticProps as ToastOptions };\n"],"mappings":";;;;;;;;;;;AAqCA,MAAM,aAAiD;CACrD,MAAM,oBAAC,MAAD,EAAM,WAAU,gBAAiB,CAAA;CACvC,SAAS,oBAAC,OAAD,EAAO,WAAU,iBAAkB,CAAA;CAC5C,OAAO,oBAAC,UAAD,EAAU,WAAU,eAAgB,CAAA;CAC3C,SAAS,oBAAC,cAAD,EAAc,WAAU,kBAAmB,CAAA;AACtD;AAEA,MAAM,SAAS,EACb,MACA,OACA,aACA,MACA,WAAW,MACX,QACA,WACA,cACW;CACX,MAAM,EAAE,WAAW,UAAU;CAE7B,OACE,qBAAC,OAAD;EACE,MAAM,SAAS,UAAU,UAAU;EACnC,WAAW,GACT,8DACA,sDACA,SAEF;EAPF,UAAA;IASI,QAAQ,SACR,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,QAAS,QAAQ,WAAW;GAC1B,CAAA;GAEP,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,KAAD;MAAG,WAAU;MAAuB,UAAA;KAAS,CAAA;KAC5C,eACC,oBAAC,KAAD;MAAG,WAAU;MAAiC,UAAA;KAAe,CAAA;KAE9D,UAAU,oBAAC,OAAD;MAAK,WAAU;MAAQ,UAAA;KAAY,CAAA;IAC3C;;GACJ,YACC,oBAAC,QAAD;IACE,SAAQ;IACR,OAAM;IACN,MAAK;IACL,cAAY,OAAO,SAAS,eAAe;IAC3C,MAAM,oBAAC,GAAD,CAAI,CAAA;IACV,SAAS;GACV,CAAA;EAEA;;AAET;AAEA,MAAM,mBAAmB;AAEzB,MAAM,eAAe,EACnB,IACA,WAAW,kBACX,WACA,SACA,GAAG,YACyD;CAC5D,MAAM,CAAC,SAAS,cAAc,SAAS,IAAI;CAE3C,MAAM,cAAc;EAClB,UAAU;EACV,WAAW,KAAK;EAChB,iBAAiB;GACf,WAAW,QAAQ,EAAE;EACvB,GAAG,GAAG;CACR;CAEA,MAAM,EAAE,OAAO,UAAU,WAAW,OAAO,YAAY,IAAI;CAE3D,IAAI,CAAC,WACH,OAAO;CAGT,OAAO,aACL,oBAAC,OAAD;EACE,WAAW,GACT,+BACA,UAAU,gBAAgB,yBAC5B;EAKA,cAAc;EACd,cAAc;EACd,SAAS;EACT,QAAQ;EAER,UAAA,oBAAC,OAAD;GAAO,GAAI;GAAO,SAAS;EAAQ,CAAA;CAChC,CAAA,GACL,WAAW,eAAe,SAAS,CACrC;AACF;AAEA,MAAM,aACJ,sBAAmC;CACjC,yBAAyB;EACvB,MAAM,KAAK,SAAS,cAAc,KAAK;EACvC,GAAG,aAAa,QAAQ,QAAQ;EAIhC,GAAG,aAAa,cAAc,eAAe;EAC7C,GAAG,MAAM,SAAS;EAClB,GAAG,MAAM,WAAW;EACpB,GAAG,MAAM,QAAQ;EACjB,GAAG,MAAM,SAAS;EAClB,GAAG,MAAM,UAAU;EACnB,GAAG,MAAM,gBAAgB;EACzB,GAAG,MAAM,MAAM;EACf,GAAG,MAAM,UAAU;EACnB,GAAG,MAAM,gBAAgB;EACzB,OAAO;CACT;CACA,WAAW;AACb,CAAC;AAEH,MAAM,UAAU,WAAW;AAE3B,MAAM,mBAAmB;CACvB,WAAW,QAAQ;AACrB;AAIA,MAAM,QAAQ,OAAwB,UACpC,WAAW,OAAO;CAAE,MAAM;CAAQ;CAAO,GAAG;AAAM,CAAC;AACrD,MAAM,WAAW,OAAwB,UACvC,WAAW,OAAO;CAAE,MAAM;CAAW;CAAO,GAAG;AAAM,CAAC;AACxD,MAAM,SAAS,OAAwB,UACrC,WAAW,OAAO;CAAE,MAAM;CAAS;CAAO,GAAG;AAAM,CAAC;AACtD,MAAM,WAAW,OAAwB,UACvC,WAAW,OAAO;CAAE,MAAM;CAAW;CAAO,GAAG;AAAM,CAAC"}
|
|
@@ -13,7 +13,7 @@ const PageHeader = ({ title, subTitle, extra, backIcon, onBack, className, class
|
|
|
13
13
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
14
14
|
className: "flex items-start gap-2",
|
|
15
15
|
children: [onBack && /* @__PURE__ */ jsx(Button, {
|
|
16
|
-
|
|
16
|
+
variant: "text",
|
|
17
17
|
shape: "circle",
|
|
18
18
|
size: "small",
|
|
19
19
|
"aria-label": locale.back ?? DEFAULT_LOCALE.back,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-header.mjs","names":[],"sources":["../../../src/components/templates/page-header.tsx"],"sourcesContent":["'use client';\n\nimport { ArrowLeft } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nexport interface Props extends Omit<React.ComponentProps<'div'>, 'title'> {\n title?: React.ReactNode;\n subTitle?: React.ReactNode;\n extra?: React.ReactNode;\n backIcon?: React.ReactNode;\n onBack?: () => void;\n classNames?: {\n back?: string;\n title?: string;\n subTitle?: string;\n extra?: string;\n };\n}\n\n// Title + back button + extra action area — same shape as Drawer's header\n// (title/extra/closable), which this borrows the layout from wholesale;\n// PageHeader just swaps Drawer's close button for a back button.\nconst PageHeader = ({\n title,\n subTitle,\n extra,\n backIcon,\n onBack,\n className,\n classNames,\n children,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n <div className=\"flex items-start gap-2\">\n {onBack && (\n <Button\n
|
|
1
|
+
{"version":3,"file":"page-header.mjs","names":[],"sources":["../../../src/components/templates/page-header.tsx"],"sourcesContent":["'use client';\n\nimport { ArrowLeft } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nexport interface Props extends Omit<React.ComponentProps<'div'>, 'title'> {\n title?: React.ReactNode;\n subTitle?: React.ReactNode;\n extra?: React.ReactNode;\n backIcon?: React.ReactNode;\n onBack?: () => void;\n classNames?: {\n back?: string;\n title?: string;\n subTitle?: string;\n extra?: string;\n };\n}\n\n// Title + back button + extra action area — same shape as Drawer's header\n// (title/extra/closable), which this borrows the layout from wholesale;\n// PageHeader just swaps Drawer's close button for a back button.\nconst PageHeader = ({\n title,\n subTitle,\n extra,\n backIcon,\n onBack,\n className,\n classNames,\n children,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n <div className=\"flex items-start gap-2\">\n {onBack && (\n <Button\n variant=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label={locale.back ?? DEFAULT_LOCALE.back}\n icon={backIcon || <ArrowLeft />}\n onClick={onBack}\n className={cn(classNames?.back)}\n />\n )}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n {title && (\n <p className={cn('text-lg font-medium', classNames?.title)}>\n {title}\n </p>\n )}\n {subTitle && (\n <p\n className={cn(\n 'text-muted-foreground text-sm',\n classNames?.subTitle,\n )}\n >\n {subTitle}\n </p>\n )}\n </div>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n {children}\n </div>\n );\n};\n\nexport default PageHeader;\n"],"mappings":";;;;;;;AA0BA,MAAM,cAAc,EAClB,OACA,UACA,OACA,UACA,QACA,WACA,YACA,UACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,UAAU;CAE7B,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,uBAAuB,SAAS;EAAG,GAAI;EAA1D,UAAA,CACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,UACC,oBAAC,QAAD;IACE,SAAQ;IACR,OAAM;IACN,MAAK;IACL,cAAY,OAAO,QAAQ,eAAe;IAC1C,MAAM,YAAY,oBAAC,WAAD,CAAY,CAAA;IAC9B,SAAS;IACT,WAAW,GAAG,YAAY,IAAI;GAC/B,CAAA,GAEH,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACG,SACC,oBAAC,KAAD;MAAG,WAAW,GAAG,uBAAuB,YAAY,KAAK;MACtD,UAAA;KACA,CAAA,GAEJ,YACC,oBAAC,KAAD;MACE,WAAW,GACT,iCACA,YAAY,QACd;MAEC,UAAA;KACA,CAAA,CAEF;IACJ,CAAA,GAAA,kBAAkB,QAAO,MACxB,oBAAC,OAAD;KAAK,WAAW,GAAG,YAAY,YAAY,KAAK;KAAI,UAAA;IAAO,CAAA,CAC5D,CACE;GACF,CAAA,CAAA;EACJ,CAAA,GAAA,QACE;;AAET"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbpark/ui-kit",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.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",
|