@jbpark/ui-kit 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Button.d.mts +48 -12
- package/dist/Button.d.mts.map +1 -1
- package/dist/Button.mjs +62 -11
- package/dist/Button.mjs.map +1 -1
- package/dist/Tag.d.mts +8 -11
- package/dist/Tag.d.mts.map +1 -1
- package/dist/Tag.mjs +8 -7
- package/dist/Tag.mjs.map +1 -1
- package/dist/components/atoms/date-picker.mjs +1 -1
- package/dist/components/atoms/float-button/float-button.d.mts.map +1 -1
- package/dist/components/atoms/float-button/float-button.mjs +2 -1
- package/dist/components/atoms/float-button/float-button.mjs.map +1 -1
- package/dist/components/atoms/input/search.mjs +1 -1
- package/dist/components/atoms/radio/group.mjs +1 -1
- package/dist/components/atoms/radio/radio.d.mts +1 -1
- package/dist/components/molecules/dropdown.d.mts.map +1 -1
- package/dist/components/molecules/dropdown.mjs +2 -1
- package/dist/components/molecules/dropdown.mjs.map +1 -1
- package/dist/components/molecules/marquees/item.d.mts +2 -1
- package/dist/components/molecules/marquees/item.d.mts.map +1 -1
- package/dist/components/molecules/marquees/item.mjs +20 -5
- package/dist/components/molecules/marquees/item.mjs.map +1 -1
- package/dist/components/molecules/marquees/marquees.d.mts +2 -1
- package/dist/components/molecules/marquees/marquees.d.mts.map +1 -1
- package/dist/components/molecules/marquees/marquees.mjs +3 -2
- package/dist/components/molecules/marquees/marquees.mjs.map +1 -1
- package/dist/components/organisms/drawer.mjs +8 -8
- package/dist/components/organisms/drawer.mjs.map +1 -1
- package/dist/components/organisms/modal.d.mts +4 -5
- package/dist/components/organisms/modal.d.mts.map +1 -1
- package/dist/components/organisms/modal.mjs +5 -6
- package/dist/components/organisms/modal.mjs.map +1 -1
- package/dist/components/organisms/toast.d.mts +2 -8
- package/dist/components/organisms/toast.d.mts.map +1 -1
- package/dist/components/organisms/toast.mjs +4 -5
- package/dist/components/organisms/toast.mjs.map +1 -1
- package/dist/components/templates/layout/header.d.mts.map +1 -1
- package/dist/components/templates/layout/header.mjs +2 -1
- package/dist/components/templates/layout/header.mjs.map +1 -1
- package/dist/components/templates/layout/sider.mjs.map +1 -1
- package/dist/components/templates/page-header.mjs +4 -4
- package/dist/components/templates/page-header.mjs.map +1 -1
- package/dist/core/badge.d.mts +25 -2
- package/dist/core/badge.d.mts.map +1 -0
- package/dist/core/badge.mjs +47 -0
- package/dist/core/badge.mjs.map +1 -0
- package/dist/core/button.d.mts +14 -2
- package/dist/core/button.d.mts.map +1 -0
- package/dist/core/dialog.mjs +5 -5
- package/dist/core/dialog.mjs.map +1 -1
- package/dist/core/drawer.mjs +3 -2
- package/dist/core/drawer.mjs.map +1 -1
- package/dist/core/field.d.mts +1 -1
- package/dist/core/popover.mjs +3 -2
- package/dist/core/popover.mjs.map +1 -1
- package/dist/core/select.d.mts.map +1 -1
- package/dist/core/select.mjs +3 -2
- package/dist/core/select.mjs.map +1 -1
- package/dist/lib/colors.d.mts +6 -31
- package/dist/lib/colors.d.mts.map +1 -1
- package/dist/lib/z-layers.mjs +33 -0
- package/dist/lib/z-layers.mjs.map +1 -0
- package/dist/style.css +32 -34
- package/dist/utils.d.mts +12 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +12 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/lib/chassis.mjs +0 -23
- package/dist/lib/chassis.mjs.map +0 -1
package/dist/Button.d.mts
CHANGED
|
@@ -1,15 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Button as Button$1 } from "./core/button.mjs";
|
|
2
|
+
import "./core/index.mjs";
|
|
3
|
+
import { PresetColor } from "./lib/colors.mjs";
|
|
2
4
|
import * as React$1 from "react";
|
|
3
5
|
//#region src/components/atoms/button.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
declare const Core: typeof Button$1;
|
|
7
|
+
/**
|
|
8
|
+
* shadcn's own `variant` words, accepted on top of this component's own
|
|
9
|
+
* vocabulary rather than replacing it. They are sugar in exactly the sense
|
|
10
|
+
* `type` is: each expands to a `(color, variant)` pair, so a snippet copied
|
|
11
|
+
* from the shadcn docs renders as the nearest thing on this library's scale
|
|
12
|
+
* instead of erroring.
|
|
13
|
+
*
|
|
14
|
+
* `link` is deliberately absent: it already exists as one of this component's
|
|
15
|
+
* own variants and already renders what shadcn's `link` renders, so mapping it
|
|
16
|
+
* would change `variant="link"`'s resolved colour from `default` to `primary`
|
|
17
|
+
* for existing callers.
|
|
18
|
+
*/
|
|
19
|
+
type ShadcnVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';
|
|
20
|
+
/**
|
|
21
|
+
* shadcn's `size` words. The `icon*` entries additionally force the icon-only
|
|
22
|
+
* (square, unpadded) treatment, which this component otherwise infers from
|
|
23
|
+
* `icon` being set with no children — without that, the shadcn idiom of
|
|
24
|
+
* passing the icon as *children* (`<Button size="icon"><Trash /></Button>`)
|
|
25
|
+
* would render a normal padded button.
|
|
26
|
+
*/
|
|
27
|
+
type ShadcnSize = 'default' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg';
|
|
28
|
+
interface Props extends Omit<React$1.ComponentProps<typeof Core>, 'size' | 'variant' | 'type'> {
|
|
8
29
|
icon?: React$1.ReactNode;
|
|
9
30
|
block?: boolean;
|
|
10
31
|
danger?: boolean;
|
|
11
32
|
disabled?: boolean;
|
|
12
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Size on this library's antd-style scale. shadcn's words are accepted too
|
|
35
|
+
* and map onto that scale: `sm`/`xs` → `small`, `default` → `middle`,
|
|
36
|
+
* `lg` → `large`. There is no separate `xs` step here, so `xs` renders as
|
|
37
|
+
* `small`. The `icon*` entries pick the same sizes and additionally force
|
|
38
|
+
* the icon-only treatment.
|
|
39
|
+
*/
|
|
40
|
+
size?: 'small' | 'middle' | 'large' | ShadcnSize;
|
|
13
41
|
/**
|
|
14
42
|
* Syntactic sugar for a `(color, variant)` pair. **Will follow `variant` and
|
|
15
43
|
* `color` if provided** — `type` only fills in the axes you leave unset.
|
|
@@ -31,8 +59,19 @@ interface Props extends Omit<NativeButtonProps, 'size' | 'variant' | 'type'> {
|
|
|
31
59
|
/**
|
|
32
60
|
* Visual fill style, independent of `color`. Defaults to `'outlined'`.
|
|
33
61
|
* Takes precedence over whatever `type` would have supplied.
|
|
62
|
+
*
|
|
63
|
+
* shadcn's words are accepted here as well and expand to a `(color, variant)`
|
|
64
|
+
* pair the same way `type` does — `destructive` ≡ `color="danger"
|
|
65
|
+
* variant="solid"`, `outline` ≡ `outlined`, `secondary` ≡ `filled`,
|
|
66
|
+
* `ghost` ≡ `text`, `default` ≡ `color="primary" variant="solid"`. An
|
|
67
|
+
* explicit `color` still wins over the one the word implies.
|
|
68
|
+
*
|
|
69
|
+
* ⚠️ `variant="default"` (shadcn: a filled primary button) and
|
|
70
|
+
* `type="default"` (antd: a plain outlined button) mean opposite things.
|
|
71
|
+
* They are different props, so nothing collides at runtime, but don't read
|
|
72
|
+
* one as the other.
|
|
34
73
|
*/
|
|
35
|
-
variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';
|
|
74
|
+
variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link' | ShadcnVariant;
|
|
36
75
|
/**
|
|
37
76
|
* Native `<button>` `type` (`button`/`submit`/`reset`), kept separate
|
|
38
77
|
* from the antd-style `type` above. Defaults to `'button'` so a Button
|
|
@@ -44,12 +83,9 @@ interface Props extends Omit<NativeButtonProps, 'size' | 'variant' | 'type'> {
|
|
|
44
83
|
* Color, independent of `variant`. Defaults to `'default'`, or to whatever
|
|
45
84
|
* `type` maps to when `type` is set. `danger` overrides this.
|
|
46
85
|
*
|
|
47
|
-
* Preset hues use Tailwind's colour names (#342).
|
|
48
|
-
* `magenta`/`geekblue`/`gold`/`volcano` still work and render unchanged, but
|
|
49
|
-
* are deprecated — use `fuchsia`/`indigo`/`amber` instead (`volcano` has no
|
|
50
|
-
* successor; it is `orange` one lightness step darker).
|
|
86
|
+
* Preset hues use Tailwind's colour names (#342).
|
|
51
87
|
*/
|
|
52
|
-
color?: PresetColor |
|
|
88
|
+
color?: PresetColor | 'default' | 'primary' | 'danger';
|
|
53
89
|
loading?: boolean | {
|
|
54
90
|
icon: React$1.ReactNode;
|
|
55
91
|
};
|
package/dist/Button.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":";;;;;cAaM,aAAI;;;;;;;;;;;;;KAcL;;;;;;;;KAUA;UAGY,cAAc,KAC7B,QAAM,sBAAsB;EAG5B,OAAO,QAAM;EACb;EACA;EACA;;;;;;;;EAQA,sCAAsC;;;;;;;;;;;;;;;;;;EAkBtC;;;;;;;;;;;;;;;;EAgBA,yEAOI;;;;;;EAMJ;EACA;;;;;;;EAOA,QAAQ;EACR;IAAsB,MAAM,QAAM;;;cAmH9B,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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "./utils.mjs";
|
|
3
3
|
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { Button as Button$1 } from "./core/button.mjs";
|
|
5
5
|
import "react";
|
|
6
|
-
import {
|
|
6
|
+
import { Slottable } from "@radix-ui/react-slot";
|
|
7
7
|
import { LoaderCircle } from "lucide-react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/atoms/button.tsx
|
|
10
|
-
const
|
|
11
|
-
const BUTTON_BASE = cn(
|
|
10
|
+
const Core = Button$1;
|
|
11
|
+
const BUTTON_BASE = cn("gap-2 whitespace-nowrap font-medium transition-all", "has-[>svg]:px-3");
|
|
12
12
|
const variantClasses = {
|
|
13
13
|
solid: cn("bg-primary text-primary-foreground", "hover:bg-primary/90"),
|
|
14
14
|
outlined: cn("border border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]", "bg-background text-foreground", "hover:bg-accent"),
|
|
@@ -46,6 +46,51 @@ const typeToColorVariant = {
|
|
|
46
46
|
variant: "link"
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* shadcn's variant words → the `(color, variant)` pair each stands for here.
|
|
51
|
+
* Same contract as `typeToColorVariant` above: the word only fills axes the
|
|
52
|
+
* caller left unset, so an explicit `color` still wins over the implied one.
|
|
53
|
+
*/
|
|
54
|
+
const shadcnVariantToColorVariant = {
|
|
55
|
+
default: {
|
|
56
|
+
color: "primary",
|
|
57
|
+
variant: "solid"
|
|
58
|
+
},
|
|
59
|
+
destructive: {
|
|
60
|
+
color: "danger",
|
|
61
|
+
variant: "solid"
|
|
62
|
+
},
|
|
63
|
+
outline: {
|
|
64
|
+
color: "default",
|
|
65
|
+
variant: "outlined"
|
|
66
|
+
},
|
|
67
|
+
secondary: {
|
|
68
|
+
color: "default",
|
|
69
|
+
variant: "filled"
|
|
70
|
+
},
|
|
71
|
+
ghost: {
|
|
72
|
+
color: "default",
|
|
73
|
+
variant: "text"
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/** shadcn's size words → this library's scale. */
|
|
77
|
+
const shadcnSizeToSize = {
|
|
78
|
+
default: "middle",
|
|
79
|
+
xs: "small",
|
|
80
|
+
sm: "small",
|
|
81
|
+
lg: "large",
|
|
82
|
+
icon: "middle",
|
|
83
|
+
"icon-xs": "small",
|
|
84
|
+
"icon-sm": "small",
|
|
85
|
+
"icon-lg": "large"
|
|
86
|
+
};
|
|
87
|
+
/** The `size` words that also mean "render this icon-only". */
|
|
88
|
+
const ICON_SIZES = /* @__PURE__ */ new Set([
|
|
89
|
+
"icon",
|
|
90
|
+
"icon-xs",
|
|
91
|
+
"icon-sm",
|
|
92
|
+
"icon-lg"
|
|
93
|
+
]);
|
|
49
94
|
const sizesClasses = {
|
|
50
95
|
small: "h-6 px-3 text-sm",
|
|
51
96
|
middle: "h-8 px-4 text-base",
|
|
@@ -64,18 +109,24 @@ const shapesClasses = {
|
|
|
64
109
|
const Button = ({ icon, className, type, variant, htmlType = "button", size, color, shape, block = false, disabled, loading, danger, asChild = false, children, onMouseDown, ...props }) => {
|
|
65
110
|
const { componentSize, defaultProps } = useConfig();
|
|
66
111
|
const buttonDefaults = defaultProps?.button;
|
|
67
|
-
const resolvedSize = size ?? componentSize ?? "middle";
|
|
68
112
|
const resolvedShape = shape ?? buttonDefaults?.shape ?? "default";
|
|
69
|
-
const
|
|
113
|
+
const variantAlias = variant && variant in shadcnVariantToColorVariant ? shadcnVariantToColorVariant[variant] : void 0;
|
|
114
|
+
const ownVariant = variantAlias?.variant ?? variant;
|
|
115
|
+
const resolvedSize = (size && size in shadcnSizeToSize ? shadcnSizeToSize[size] : size) ?? componentSize ?? "middle";
|
|
116
|
+
const iconOnly = size != null && ICON_SIZES.has(size) || !!(icon && !children);
|
|
70
117
|
const typeDefaults = type ? typeToColorVariant[type] : void 0;
|
|
71
|
-
const resolvedVariant =
|
|
72
|
-
const computedColor = danger ? "danger" : color ?? typeDefaults?.color ?? buttonDefaults?.color ?? "default";
|
|
118
|
+
const resolvedVariant = ownVariant ?? typeDefaults?.variant ?? buttonDefaults?.variant ?? "outlined";
|
|
119
|
+
const computedColor = danger ? "danger" : color ?? variantAlias?.color ?? typeDefaults?.color ?? buttonDefaults?.color ?? "default";
|
|
73
120
|
const colored = computedColor !== "default";
|
|
74
121
|
const isLoading = !!loading;
|
|
75
|
-
const Comp = asChild ? Slot : "button";
|
|
76
122
|
const displayIcon = loading ? typeof loading === "object" ? loading.icon : /* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin" }) : icon;
|
|
77
|
-
return /* @__PURE__ */ jsxs(
|
|
123
|
+
return /* @__PURE__ */ jsxs(Core, {
|
|
124
|
+
variant: null,
|
|
125
|
+
size: null,
|
|
126
|
+
asChild,
|
|
78
127
|
"data-slot": "button",
|
|
128
|
+
"data-variant": resolvedVariant,
|
|
129
|
+
"data-size": resolvedSize,
|
|
79
130
|
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" ? [
|
|
80
131
|
"bg-(--btn-bg)",
|
|
81
132
|
"hover:bg-(--btn-bg-hover)",
|
|
@@ -91,7 +142,7 @@ const Button = ({ icon, className, type, variant, htmlType = "button", size, col
|
|
|
91
142
|
onMouseDown?.(e);
|
|
92
143
|
},
|
|
93
144
|
...props,
|
|
94
|
-
children: [displayIcon, children]
|
|
145
|
+
children: [displayIcon, /* @__PURE__ */ jsx(Slottable, { children })]
|
|
95
146
|
});
|
|
96
147
|
};
|
|
97
148
|
//#endregion
|
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';\nimport { type DeprecatedPresetColor, type PresetColor } from '../../lib/colors';\n\ntype NativeButtonProps = React.ComponentProps<'button'> & {\n asChild?: boolean;\n};\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 * Syntactic sugar for a `(color, variant)` pair. **Will follow `variant` and\n * `color` if provided** — `type` only fills in the axes you leave unset.\n *\n * | `type` | equivalent to |\n * | --------- | -------------------------------------- |\n * | `primary` | `color=\"primary\" variant=\"solid\"` |\n * | `default` | `color=\"default\" variant=\"outlined\"` |\n * | `dashed` | `color=\"default\" variant=\"dashed\"` |\n * | `text` | `color=\"default\" variant=\"text\"` |\n * | `link` | `color=\"primary\" variant=\"link\"` |\n *\n * So `<Button type=\"primary\">` is the same as\n * `<Button color=\"primary\" variant=\"solid\">`, and\n * `<Button type=\"primary\" variant=\"filled\">` keeps the primary color but\n * renders filled. `danger` still overrides the resolved color.\n */\n type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';\n /**\n * Visual fill style, independent of `color`. Defaults to `'outlined'`.\n * Takes precedence over whatever `type` would have supplied.\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 /**\n * Color, independent of `variant`. Defaults to `'default'`, or to whatever\n * `type` maps to when `type` is set. `danger` overrides this.\n *\n * Preset hues use Tailwind's colour names (#342). The pre-8.0 spellings\n * `magenta`/`geekblue`/`gold`/`volcano` still work and render unchanged, but\n * are deprecated — use `fuchsia`/`indigo`/`amber` instead (`volcano` has no\n * successor; it is `orange` one lightness step darker).\n */\n color?:\n PresetColor | DeprecatedPresetColor | '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\n/**\n * antd-style syntactic sugar: each `type` expands to a `(color, variant)` pair.\n * Explicit `color`/`variant` props win over whatever the `type` maps to, so\n * `type` only fills in the axes the caller left unset.\n *\n * Mirrors antd: `<Button type=\"primary\">` ≡ `<Button color=\"primary\" variant=\"solid\">`.\n */\nconst typeToColorVariant: Record<\n NonNullable<Props['type']>,\n { color: NonNullable<Props['color']>; variant: NonNullable<Props['variant']> }\n> = {\n primary: { color: 'primary', variant: 'solid' },\n default: { color: 'default', variant: 'outlined' },\n dashed: { color: 'default', variant: 'dashed' },\n text: { color: 'default', variant: 'text' },\n link: { color: 'primary', variant: '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,\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' | 'variant' | 'color'>> | undefined;\n const resolvedSize = size ?? componentSize ?? 'middle';\n const resolvedShape = shape ?? buttonDefaults?.shape ?? 'default';\n const iconOnly = icon && !children;\n // `type` is syntactic sugar that expands to a (color, variant) pair; explicit\n // `color`/`variant` win over it, so `type` only fills the axes left unset.\n // A `Config` default sits below the call-site `type` (which is more specific)\n // but above the library built-in. `danger` still trumps everything, matching\n // antd. Defaults live here rather than on the parameters so `type` gets a\n // chance to supply them first.\n const typeDefaults = type ? typeToColorVariant[type] : undefined;\n const resolvedVariant =\n variant ?? typeDefaults?.variant ?? buttonDefaults?.variant ?? 'outlined';\n const computedColor = danger\n ? 'danger'\n : (color ?? typeDefaults?.color ?? buttonDefaults?.color ?? 'default');\n const colored = computedColor !== 'default';\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":";;;;;;;;;AA2EA,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;;;;;;;;AASA,MAAM,qBAGF;CACF,SAAS;EAAE,OAAO;EAAW,SAAS;CAAQ;CAC9C,SAAS;EAAE,OAAO;EAAW,SAAS;CAAW;CACjD,QAAQ;EAAE,OAAO;EAAW,SAAS;CAAS;CAC9C,MAAM;EAAE,OAAO;EAAW,SAAS;CAAO;CAC1C,MAAM;EAAE,OAAO;EAAW,SAAS;CAAO;AAC5C;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,OACA,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;CAO1B,MAAM,eAAe,OAAO,mBAAmB,QAAQ,KAAA;CACvD,MAAM,kBACJ,WAAW,cAAc,WAAW,gBAAgB,WAAW;CACjE,MAAM,gBAAgB,SAClB,WACC,SAAS,cAAc,SAAS,gBAAgB,SAAS;CAC9D,MAAM,UAAU,kBAAkB;CAClC,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
|
+
{"version":3,"file":"Button.mjs","names":["button.Button"],"sources":["../src/components/atoms/button.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport { Slottable } 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 { button } from '../../core';\nimport { type PresetColor } from '../../lib/colors';\n\nconst Core = button.Button;\n\n/**\n * shadcn's own `variant` words, accepted on top of this component's own\n * vocabulary rather than replacing it. They are sugar in exactly the sense\n * `type` is: each expands to a `(color, variant)` pair, so a snippet copied\n * from the shadcn docs renders as the nearest thing on this library's scale\n * instead of erroring.\n *\n * `link` is deliberately absent: it already exists as one of this component's\n * own variants and already renders what shadcn's `link` renders, so mapping it\n * would change `variant=\"link\"`'s resolved colour from `default` to `primary`\n * for existing callers.\n */\ntype ShadcnVariant =\n 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';\n\n/**\n * shadcn's `size` words. The `icon*` entries additionally force the icon-only\n * (square, unpadded) treatment, which this component otherwise infers from\n * `icon` being set with no children — without that, the shadcn idiom of\n * passing the icon as *children* (`<Button size=\"icon\"><Trash /></Button>`)\n * would render a normal padded button.\n */\ntype ShadcnSize =\n 'default' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg';\n\nexport interface Props extends Omit<\n React.ComponentProps<typeof Core>,\n 'size' | 'variant' | 'type'\n> {\n icon?: React.ReactNode;\n block?: boolean;\n danger?: boolean;\n disabled?: boolean;\n /**\n * Size on this library's antd-style scale. shadcn's words are accepted too\n * and map onto that scale: `sm`/`xs` → `small`, `default` → `middle`,\n * `lg` → `large`. There is no separate `xs` step here, so `xs` renders as\n * `small`. The `icon*` entries pick the same sizes and additionally force\n * the icon-only treatment.\n */\n size?: 'small' | 'middle' | 'large' | ShadcnSize;\n /**\n * Syntactic sugar for a `(color, variant)` pair. **Will follow `variant` and\n * `color` if provided** — `type` only fills in the axes you leave unset.\n *\n * | `type` | equivalent to |\n * | --------- | -------------------------------------- |\n * | `primary` | `color=\"primary\" variant=\"solid\"` |\n * | `default` | `color=\"default\" variant=\"outlined\"` |\n * | `dashed` | `color=\"default\" variant=\"dashed\"` |\n * | `text` | `color=\"default\" variant=\"text\"` |\n * | `link` | `color=\"primary\" variant=\"link\"` |\n *\n * So `<Button type=\"primary\">` is the same as\n * `<Button color=\"primary\" variant=\"solid\">`, and\n * `<Button type=\"primary\" variant=\"filled\">` keeps the primary color but\n * renders filled. `danger` still overrides the resolved color.\n */\n type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';\n /**\n * Visual fill style, independent of `color`. Defaults to `'outlined'`.\n * Takes precedence over whatever `type` would have supplied.\n *\n * shadcn's words are accepted here as well and expand to a `(color, variant)`\n * pair the same way `type` does — `destructive` ≡ `color=\"danger\"\n * variant=\"solid\"`, `outline` ≡ `outlined`, `secondary` ≡ `filled`,\n * `ghost` ≡ `text`, `default` ≡ `color=\"primary\" variant=\"solid\"`. An\n * explicit `color` still wins over the one the word implies.\n *\n * ⚠️ `variant=\"default\"` (shadcn: a filled primary button) and\n * `type=\"default\"` (antd: a plain outlined button) mean opposite things.\n * They are different props, so nothing collides at runtime, but don't read\n * one as the other.\n */\n variant?:\n | 'solid'\n | 'outlined'\n | 'dashed'\n | 'filled'\n | 'text'\n | 'link'\n | ShadcnVariant;\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 /**\n * Color, independent of `variant`. Defaults to `'default'`, or to whatever\n * `type` maps to when `type` is set. `danger` overrides this.\n *\n * Preset hues use Tailwind's colour names (#342).\n */\n color?: PresetColor | 'default' | 'primary' | 'danger';\n loading?: boolean | { icon: React.ReactNode };\n}\n\n// Geometry, the focus/aria/disabled chassis and the svg sizing come from\n// `core/button` again (#278 ③ is reversed here — see the core membership rule\n// in CLAUDE.md). Unlike Tag, Button pins no core variant at all: it passes\n// `variant={null} size={null}`, which cva treats as \"skip this axis entirely\",\n// so the primitive contributes only its base string and the atom keeps full\n// ownership of every colour and size class below. That leaves nothing for the\n// `variant=\"…\"` smell check to flag.\n//\n// The base still carries `rounded-md` and `text-sm`; the `rounded-*` from\n// `shapesClasses` and the `text-*` from `sizesClasses` come later in the class\n// list and override them, exactly as they did when this was absorbed.\nconst BUTTON_BASE = cn(\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\n/**\n * antd-style syntactic sugar: each `type` expands to a `(color, variant)` pair.\n * Explicit `color`/`variant` props win over whatever the `type` maps to, so\n * `type` only fills in the axes the caller left unset.\n *\n * Mirrors antd: `<Button type=\"primary\">` ≡ `<Button color=\"primary\" variant=\"solid\">`.\n */\nconst typeToColorVariant: Record<\n NonNullable<Props['type']>,\n { color: NonNullable<Props['color']>; variant: NonNullable<Props['variant']> }\n> = {\n primary: { color: 'primary', variant: 'solid' },\n default: { color: 'default', variant: 'outlined' },\n dashed: { color: 'default', variant: 'dashed' },\n text: { color: 'default', variant: 'text' },\n link: { color: 'primary', variant: 'link' },\n};\n\n/** The half of `variant` that is this component's own vocabulary. */\ntype OwnVariant = Exclude<NonNullable<Props['variant']>, ShadcnVariant>;\n\ntype OwnSize = 'small' | 'middle' | 'large';\n\n/**\n * shadcn's variant words → the `(color, variant)` pair each stands for here.\n * Same contract as `typeToColorVariant` above: the word only fills axes the\n * caller left unset, so an explicit `color` still wins over the implied one.\n */\nconst shadcnVariantToColorVariant: Record<\n ShadcnVariant,\n { color: NonNullable<Props['color']>; variant: OwnVariant }\n> = {\n default: { color: 'primary', variant: 'solid' },\n destructive: { color: 'danger', variant: 'solid' },\n outline: { color: 'default', variant: 'outlined' },\n secondary: { color: 'default', variant: 'filled' },\n ghost: { color: 'default', variant: 'text' },\n};\n\n/** shadcn's size words → this library's scale. */\nconst shadcnSizeToSize: Record<ShadcnSize, OwnSize> = {\n default: 'middle',\n xs: 'small',\n sm: 'small',\n lg: 'large',\n icon: 'middle',\n 'icon-xs': 'small',\n 'icon-sm': 'small',\n 'icon-lg': 'large',\n};\n\n/** The `size` words that also mean \"render this icon-only\". */\nconst ICON_SIZES = new Set<string>(['icon', 'icon-xs', 'icon-sm', 'icon-lg']);\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,\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' | 'variant' | 'color'>> | undefined;\n const resolvedShape = shape ?? buttonDefaults?.shape ?? 'default';\n // Both `variant` and `size` accept this library's own words *and* shadcn's.\n // Translate the shadcn ones first so everything below reasons in one\n // vocabulary; a word this library already owns (`link`, `text`, `small`, …)\n // is passed through untouched.\n const variantAlias =\n variant && variant in shadcnVariantToColorVariant\n ? shadcnVariantToColorVariant[variant as ShadcnVariant]\n : undefined;\n const ownVariant =\n variantAlias?.variant ?? (variant as OwnVariant | undefined);\n const ownSize =\n size && size in shadcnSizeToSize\n ? shadcnSizeToSize[size as ShadcnSize]\n : (size as OwnSize | undefined);\n const resolvedSize = ownSize ?? componentSize ?? 'middle';\n // A shadcn `size=\"icon*\"` says \"icon-only\" explicitly; otherwise it is\n // inferred from an `icon` with no children, which is how this component has\n // always detected it.\n const iconOnly =\n (size != null && ICON_SIZES.has(size)) || !!(icon && !children);\n // `type` is syntactic sugar that expands to a (color, variant) pair; explicit\n // `color`/`variant` win over it, so `type` only fills the axes left unset.\n // A shadcn `variant` word carries an implied colour and sits between the two:\n // more specific than `type`, less than an explicit `color`.\n // A `Config` default sits below the call-site `type` (which is more specific)\n // but above the library built-in. `danger` still trumps everything, matching\n // antd. Defaults live here rather than on the parameters so `type` gets a\n // chance to supply them first.\n const typeDefaults = type ? typeToColorVariant[type] : undefined;\n const resolvedVariant =\n ownVariant ??\n typeDefaults?.variant ??\n buttonDefaults?.variant ??\n 'outlined';\n const computedColor = danger\n ? 'danger'\n : (color ??\n variantAlias?.color ??\n typeDefaults?.color ??\n buttonDefaults?.color ??\n 'default');\n const colored = computedColor !== 'default';\n const isLoading = !!loading;\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 <Core\n // cva skips an axis entirely when it is passed `null`, so the primitive\n // contributes only its base string and this atom keeps ownership of\n // every colour/size class.\n variant={null}\n size={null}\n asChild={asChild}\n data-slot=\"button\"\n data-variant={resolvedVariant}\n data-size={resolvedSize}\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 {/*\n A Button renders two children (the icon slot and the caller's content),\n but Radix's Slot accepts multiple children only when exactly one is\n marked `Slottable` — without this marker `asChild` threw\n \"Slot failed to slot onto its children\" for *every* call, icon or not.\n `Slottable` is a plain fragment when `asChild` is false, so the\n non-asChild markup is unchanged.\n */}\n <Slottable>{children}</Slottable>\n </Core>\n );\n};\n\nexport default Button;\n"],"mappings":";;;;;;;;;AAaA,MAAM,OAAOA;AAgHb,MAAM,cAAc,GAClB,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;;;;;;;;AASA,MAAM,qBAGF;CACF,SAAS;EAAE,OAAO;EAAW,SAAS;CAAQ;CAC9C,SAAS;EAAE,OAAO;EAAW,SAAS;CAAW;CACjD,QAAQ;EAAE,OAAO;EAAW,SAAS;CAAS;CAC9C,MAAM;EAAE,OAAO;EAAW,SAAS;CAAO;CAC1C,MAAM;EAAE,OAAO;EAAW,SAAS;CAAO;AAC5C;;;;;;AAYA,MAAM,8BAGF;CACF,SAAS;EAAE,OAAO;EAAW,SAAS;CAAQ;CAC9C,aAAa;EAAE,OAAO;EAAU,SAAS;CAAQ;CACjD,SAAS;EAAE,OAAO;EAAW,SAAS;CAAW;CACjD,WAAW;EAAE,OAAO;EAAW,SAAS;CAAS;CACjD,OAAO;EAAE,OAAO;EAAW,SAAS;CAAO;AAC7C;;AAGA,MAAM,mBAAgD;CACpD,SAAS;CACT,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,WAAW;CACX,WAAW;CACX,WAAW;AACb;;AAGA,MAAM,6BAAa,IAAI,IAAY;CAAC;CAAQ;CAAW;CAAW;AAAS,CAAC;AAE5E,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,OACA,OACA,QAAQ,OACR,UACA,SACA,QACA,UAAU,OACV,UACA,aACA,GAAG,YACQ;CACX,MAAM,EAAE,eAAe,iBAAiB,UAAU;CAClD,MAAM,iBAAiB,cAAc;CAErC,MAAM,gBAAgB,SAAS,gBAAgB,SAAS;CAKxD,MAAM,eACJ,WAAW,WAAW,8BAClB,4BAA4B,WAC5B,KAAA;CACN,MAAM,aACJ,cAAc,WAAY;CAK5B,MAAM,gBAHJ,QAAQ,QAAQ,mBACZ,iBAAiB,QAChB,SACyB,iBAAiB;CAIjD,MAAM,WACH,QAAQ,QAAQ,WAAW,IAAI,IAAI,KAAM,CAAC,EAAE,QAAQ,CAAC;CASxD,MAAM,eAAe,OAAO,mBAAmB,QAAQ,KAAA;CACvD,MAAM,kBACJ,cACA,cAAc,WACd,gBAAgB,WAChB;CACF,MAAM,gBAAgB,SAClB,WACC,SACD,cAAc,SACd,cAAc,SACd,gBAAgB,SAChB;CACJ,MAAM,UAAU,kBAAkB;CAClC,MAAM,YAAY,CAAC,CAAC;CAEpB,MAAM,cAAc,UAClB,OAAO,YAAY,WACjB,QAAQ,OAER,oBAAC,cAAD,EAAc,WAAU,eAAgB,CAAA,IAG1C;CAGF,OACE,qBAAC,MAAD;EAIE,SAAS;EACT,MAAM;EACG;EACT,aAAU;EACV,gBAAc;EACd,aAAW;EACX,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;EA9CN,UAAA,CAgDG,aASD,oBAAC,WAAD,EAAY,SAAoB,CAAA,CAC5B;;AAEV"}
|
package/dist/Tag.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Badge } from "./core/badge.mjs";
|
|
2
|
+
import "./core/index.mjs";
|
|
3
|
+
import { PresetColor } from "./lib/colors.mjs";
|
|
2
4
|
import * as React$1 from "react";
|
|
3
5
|
//#region src/components/atoms/tag.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
7
|
-
interface Props extends Omit<NativeSpanProps, 'variant' | 'color'> {
|
|
6
|
+
declare const Core: typeof Badge;
|
|
7
|
+
interface Props extends Omit<React$1.ComponentProps<typeof Core>, 'variant' | 'color'> {
|
|
8
8
|
/**
|
|
9
9
|
* Fill style, aligned with `Button`'s vocabulary (#320). The pre-7.0
|
|
10
10
|
* `'default'` spelling was removed — use `'filled'`, which renders
|
|
@@ -20,14 +20,11 @@ interface Props extends Omit<NativeSpanProps, 'variant' | 'color'> {
|
|
|
20
20
|
* `success`/`warning` have no `Button` counterpart on purpose: a Tag marks
|
|
21
21
|
* state, which is why antd's Tag also carries them while its Button does not.
|
|
22
22
|
*
|
|
23
|
-
* Preset hues use Tailwind's colour names (#342).
|
|
24
|
-
* `magenta`/`geekblue`/`gold`/`volcano` still work and render unchanged, but
|
|
25
|
-
* are deprecated — use `fuchsia`/`indigo`/`amber` instead (`volcano` has no
|
|
26
|
-
* successor; it is `orange` one lightness step darker).
|
|
23
|
+
* Preset hues use Tailwind's colour names (#342).
|
|
27
24
|
*/
|
|
28
|
-
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | PresetColor
|
|
25
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | PresetColor;
|
|
29
26
|
}
|
|
30
|
-
declare const Tag: ({ className, variant, color,
|
|
27
|
+
declare const Tag: ({ className, variant, color, children, ...props }: Props) => React$1.JSX.Element;
|
|
31
28
|
//#endregion
|
|
32
29
|
export { Props, Tag as default };
|
|
33
30
|
//# sourceMappingURL=Tag.d.mts.map
|
package/dist/Tag.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tag.d.mts","names":[],"sources":["../src/components/atoms/tag.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Tag.d.mts","names":[],"sources":["../src/components/atoms/tag.tsx"],"mappings":";;;;;cAUM,aAAI;UAEO,cAAc,KAC7B,QAAM,sBAAsB;;;;;;EAQ5B;;;;;;;;;;;;EAYA,mEAC6D;;cA0BzD,QAAO,WAAA,SAAA,OAAA,aAAA,SAAmD,UAAK,QAAA,IAAA"}
|
package/dist/Tag.mjs
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "./utils.mjs";
|
|
3
3
|
import { useConfig } from "./providers/config/context.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { Badge } from "./core/badge.mjs";
|
|
5
5
|
import "react";
|
|
6
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
7
6
|
import { jsx } from "react/jsx-runtime";
|
|
8
7
|
//#region src/components/atoms/tag.tsx
|
|
9
|
-
const
|
|
8
|
+
const Core = Badge;
|
|
9
|
+
const CORE_VARIANT = "outline";
|
|
10
10
|
const fillClasses = cn("border-transparent bg-(--tag-tint) text-(--tag-fg)");
|
|
11
11
|
const outlinedClasses = cn("border-(--tag-bg) text-(--tag-fg)");
|
|
12
|
-
const Tag = ({ className, variant, color,
|
|
12
|
+
const Tag = ({ className, variant, color, children, ...props }) => {
|
|
13
13
|
const { defaultProps } = useConfig();
|
|
14
14
|
const tagDefaults = defaultProps?.tag;
|
|
15
15
|
const resolvedVariant = variant ?? tagDefaults?.variant ?? "filled";
|
|
16
16
|
const resolvedColor = color ?? tagDefaults?.color ?? "default";
|
|
17
|
-
return /* @__PURE__ */ jsx(
|
|
18
|
-
|
|
17
|
+
return /* @__PURE__ */ jsx(Core, {
|
|
18
|
+
variant: CORE_VARIANT,
|
|
19
|
+
"data-slot": "tag",
|
|
19
20
|
"data-color": resolvedColor,
|
|
20
21
|
"data-variant": resolvedVariant,
|
|
21
|
-
className: cn(
|
|
22
|
+
className: cn("rounded-full px-2.5 py-1", resolvedVariant === "outlined" ? outlinedClasses : fillClasses, className),
|
|
22
23
|
...props,
|
|
23
24
|
children
|
|
24
25
|
});
|
package/dist/Tag.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tag.mjs","names":[],"sources":["../src/components/atoms/tag.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport {
|
|
1
|
+
{"version":3,"file":"Tag.mjs","names":["badge.Badge"],"sources":["../src/components/atoms/tag.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { badge } from '../../core';\nimport { type PresetColor } from '../../lib/colors';\n\nconst Core = badge.Badge;\n\nexport interface Props extends Omit<\n React.ComponentProps<typeof Core>,\n 'variant' | 'color'\n> {\n /**\n * Fill style, aligned with `Button`'s vocabulary (#320). The pre-7.0\n * `'default'` spelling was removed — use `'filled'`, which renders\n * identically.\n */\n variant?: 'filled' | 'outlined';\n /**\n * Colour. Every value — the semantic states (`primary`/`success`/`warning`/\n * `danger`) as well as the palette shared with `Button` (`blue`, `red`,\n * `amber`, …) — resolves through the same `data-color` + `--tag-*` system\n * (#320), so any of them can be re-themed the same way.\n *\n * `success`/`warning` have no `Button` counterpart on purpose: a Tag marks\n * state, which is why antd's Tag also carries them while its Button does not.\n *\n * Preset hues use Tailwind's colour names (#342).\n */\n color?:\n 'default' | 'primary' | 'success' | 'warning' | 'danger' | PresetColor;\n}\n\n// Geometry, the focus/aria chassis and the svg sizing all come from\n// `core/badge` now (#278 ③ is reversed here — see the core membership rule in\n// CLAUDE.md). Tag pins the core `outline` variant because it supplies exactly\n// the neutral base Tag wants — a border plus `text-foreground` and the `[a&]`\n// hover treatment — and then repaints border/text/fill from the `--tag-*`\n// custom properties below. Pinning one core variant is deliberate and is why\n// the membership rule had to change; the alternative (absorbing the primitive)\n// is what left `core/badge` orphaned and three upstream releases stale.\nconst CORE_VARIANT = 'outline';\n\n// Every colour — semantic states and shared presets alike — resolves from the\n// `--tag-*` custom properties that `globals.css` sets per `data-color` (#320).\n// Before 7.0 only the presets took this path while the states carried bespoke\n// Tailwind classes, which meant `[data-color]` hooks and `--tag-*` overrides\n// worked on some colours but silently not on others.\n//\n// --tag-bg the hue; the border in `outlined`\n// --tag-fg text colour (defaults to --tag-bg)\n// --tag-tint the fill behind `filled` (defaults to a 10% --tag-bg wash)\nconst fillClasses = cn('border-transparent bg-(--tag-tint) text-(--tag-fg)');\n\nconst outlinedClasses = cn('border-(--tag-bg) text-(--tag-fg)');\n\nconst Tag = ({ className, variant, color, children, ...props }: Props) => {\n const { defaultProps } = useConfig();\n const tagDefaults = defaultProps?.tag as\n Partial<Pick<Props, 'variant' | 'color'>> | undefined;\n // An explicit prop wins over a `Config` default, which wins over the built-in\n // — the same resolution order `Button` uses.\n const resolvedVariant = variant ?? tagDefaults?.variant ?? 'filled';\n const resolvedColor = color ?? tagDefaults?.color ?? 'default';\n const isOutlined = resolvedVariant === 'outlined';\n\n return (\n <Core\n variant={CORE_VARIANT}\n // Overrides the core primitive's own `data-slot=\"badge\"`. The slot now\n // matches the public component name, which frees `badge` for the\n // antd-style Badge (a count/dot decorator, a different component from\n // this chip — shadcn's Badge is what antd calls a Tag).\n data-slot=\"tag\"\n // Emitted for every colour, not just the presets, so consumers can hook\n // `[data-color]` / `[data-variant]` uniformly. `data-variant` is what\n // lets `globals.css` give `default` a different text colour when\n // outlined without reintroducing a second class path here; it also\n // replaces the core primitive's own `data-variant`, which would\n // otherwise report the pinned core variant rather than Tag's.\n data-color={resolvedColor}\n data-variant={resolvedVariant}\n className={cn(\n 'rounded-full px-2.5 py-1',\n isOutlined ? outlinedClasses : fillClasses,\n className,\n //\n )}\n {...props}\n >\n {children}\n </Core>\n );\n};\n\nexport default Tag;\n"],"mappings":";;;;;;;AAUA,MAAM,OAAOA;AAmCb,MAAM,eAAe;AAWrB,MAAM,cAAc,GAAG,oDAAoD;AAE3E,MAAM,kBAAkB,GAAG,mCAAmC;AAE9D,MAAM,OAAO,EAAE,WAAW,SAAS,OAAO,UAAU,GAAG,YAAmB;CACxE,MAAM,EAAE,iBAAiB,UAAU;CACnC,MAAM,cAAc,cAAc;CAIlC,MAAM,kBAAkB,WAAW,aAAa,WAAW;CAC3D,MAAM,gBAAgB,SAAS,aAAa,SAAS;CAGrD,OACE,oBAAC,MAAD;EACE,SAAS;EAKT,aAAU;EAOV,cAAY;EACZ,gBAAc;EACd,WAAW,GACT,4BAnBa,oBAAoB,aAoBpB,kBAAkB,aAC/B,SAEF;EACA,GAAI;EAEH;CACG,CAAA;AAEV"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../utils.mjs";
|
|
3
|
-
import Button from "../../Button.mjs";
|
|
4
3
|
import { calendar_exports } from "../../core/calendar.mjs";
|
|
4
|
+
import Button from "../../Button.mjs";
|
|
5
5
|
import Popover from "./popover.mjs";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { CalendarIcon } from "lucide-react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"float-button.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/float-button.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"float-button.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/float-button.tsx"],"mappings":";;UAKiB,cAAc;cAEzB,gBAAe,WAAA,aAAA,SAAmC,0BAAK,IAAA"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { cn } from "../../../utils.mjs";
|
|
2
|
+
import { OVERLAY_LAYER } from "../../../lib/z-layers.mjs";
|
|
2
3
|
import Button from "../../../Button.mjs";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/atoms/float-button/float-button.tsx
|
|
5
6
|
const FloatButton = ({ className, children, ...props }) => {
|
|
6
7
|
return /* @__PURE__ */ jsx(Button, {
|
|
7
|
-
className: cn("fixed right-5 bottom-5 rounded-full", "
|
|
8
|
+
className: cn("fixed right-5 bottom-5 rounded-full", OVERLAY_LAYER, "h-12 w-12", "shadow-md", className),
|
|
8
9
|
variant: "outlined",
|
|
9
10
|
...props,
|
|
10
11
|
children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"float-button.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/float-button.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport Button, { Props as ButtonProps } from '../button';\n\nexport interface Props extends ButtonProps {}\n\nconst FloatButton = ({ className, children, ...props }: Props) => {\n return (\n <Button\n className={cn(\n 'fixed right-5 bottom-5 rounded-full',\n '
|
|
1
|
+
{"version":3,"file":"float-button.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/float-button.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport { OVERLAY_LAYER } from '../../../lib/z-layers';\nimport Button, { Props as ButtonProps } from '../button';\n\nexport interface Props extends ButtonProps {}\n\nconst FloatButton = ({ className, children, ...props }: Props) => {\n return (\n <Button\n className={cn(\n 'fixed right-5 bottom-5 rounded-full',\n OVERLAY_LAYER,\n 'h-12 w-12',\n 'shadow-md',\n className,\n )}\n variant=\"outlined\"\n {...props}\n >\n {children}\n </Button>\n );\n};\n\nexport default FloatButton;\n"],"mappings":";;;;;AAOA,MAAM,eAAe,EAAE,WAAW,UAAU,GAAG,YAAmB;CAChE,OACE,oBAAC,QAAD;EACE,WAAW,GACT,uCACA,eACA,aACA,aACA,SACF;EACA,SAAQ;EACR,GAAI;EAEH;CACK,CAAA;AAEZ"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../utils.mjs";
|
|
3
3
|
import { DEFAULT_LOCALE, useConfig } from "../../../providers/config/context.mjs";
|
|
4
|
-
import Button from "../../../Button.mjs";
|
|
5
4
|
import { input_exports } from "../../../core/input.mjs";
|
|
5
|
+
import Button from "../../../Button.mjs";
|
|
6
6
|
import { useRef, useState } from "react";
|
|
7
7
|
import { CircleX, Search } from "lucide-react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../utils.mjs";
|
|
3
|
-
import Button from "../../../Button.mjs";
|
|
4
3
|
import { radio_group_exports } from "../../../core/radio-group.mjs";
|
|
4
|
+
import Button from "../../../Button.mjs";
|
|
5
5
|
import { normalizeOptions, warnOnDuplicateOptionValues } from "../option-group.mjs";
|
|
6
6
|
import { RadioGroupContext } from "./context.mjs";
|
|
7
7
|
import Radio from "./radio.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { OptionValue } from "../option-group.mjs";
|
|
2
1
|
import { RadioGroup } from "../../../core/radio-group.mjs";
|
|
3
2
|
import "../../../core/index.mjs";
|
|
3
|
+
import { OptionValue } from "../option-group.mjs";
|
|
4
4
|
//#region src/components/atoms/radio/radio.d.ts
|
|
5
5
|
declare const Core: typeof RadioGroup;
|
|
6
6
|
interface Props extends Omit<React.ComponentPropsWithoutRef<typeof Core>, 'onChange' | 'value'> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.d.mts","names":[],"sources":["../../../src/components/molecules/dropdown.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"dropdown.d.mts","names":[],"sources":["../../../src/components/molecules/dropdown.tsx"],"mappings":";;KAYK,sBAAsB;UAEV,cAAc,MAAM;EACnC;EACA;EACA,OAAO;EACP,eAAe;;cAGX,aAAY,UAAA,MAAA,SAAA,MAAA,OAAA,cAAA,eAAA,WAAA,cAAA,iBAAA,SAUf,0BAAK,IAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../utils.mjs";
|
|
3
|
+
import "../../lib/z-layers.mjs";
|
|
3
4
|
import Menu from "./menu/menu.mjs";
|
|
4
5
|
import { useId, useRef } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -60,7 +61,7 @@ const Dropdown = ({ children, menu, trigger = "hover", open: _open, onOpenChange
|
|
|
60
61
|
},
|
|
61
62
|
children
|
|
62
63
|
}), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(motion.div, {
|
|
63
|
-
className: cn("absolute top-full
|
|
64
|
+
className: cn("absolute top-full pt-2", "z-1000"),
|
|
64
65
|
initial: {
|
|
65
66
|
opacity: 0,
|
|
66
67
|
y: -10
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.mjs","names":[],"sources":["../../../src/components/molecules/dropdown.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useRef } from 'react';\n\nimport { useControllableState, useKeyPress } from '@jbpark/use-hooks';\nimport { AnimatePresence, motion } from 'motion/react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Menu, { MenuProps } from './menu';\n\ntype ChangeEventHandler = (open: boolean) => void;\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n open?: boolean;\n trigger?: 'hover' | 'click';\n menu?: MenuProps;\n onOpenChange?: ChangeEventHandler;\n}\n\nconst Dropdown = ({\n children,\n menu,\n trigger = 'hover',\n open: _open,\n onOpenChange: _onOpenChange = () => {},\n className,\n onMouseEnter,\n onMouseLeave,\n ...props\n}: Props) => {\n const [open, onOpenChange] = useControllableState<boolean>({\n value: _open,\n defaultValue: false,\n onChange: _onOpenChange,\n });\n\n const isClickTrigger = trigger === 'click';\n const menuId = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n useKeyPress(\n 'esc',\n () => {\n onOpenChange(false);\n },\n { target: triggerRef },\n );\n\n useKeyPress(\n ['Enter', 'space'],\n event => {\n event.preventDefault();\n onOpenChange(!open);\n },\n { target: triggerRef, enabled: isClickTrigger },\n );\n\n return (\n <div\n {...props}\n ref={containerRef}\n className={cn(\n 'relative',\n 'inline-block cursor-pointer',\n className,\n //\n )}\n onMouseEnter={event => {\n onMouseEnter?.(event);\n if (isClickTrigger) {\n return;\n }\n onOpenChange(true);\n }}\n onMouseLeave={event => {\n onMouseLeave?.(event);\n if (isClickTrigger) {\n return;\n }\n onOpenChange(false);\n }}\n >\n <div\n ref={triggerRef}\n role={isClickTrigger ? 'button' : undefined}\n tabIndex={isClickTrigger ? 0 : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? menuId : undefined}\n onClick={() => {\n if (!isClickTrigger) {\n return;\n }\n onOpenChange(!open);\n }}\n onFocus={() => {\n if (isClickTrigger) {\n return;\n }\n onOpenChange(true);\n }}\n onBlur={e => {\n // Without this check, moving focus from the trigger into the\n // menu itself (e.g. via Tab) closed the dropdown before the\n // user could ever reach it — the mouse path avoided the same\n // bug only by way of onMouseDown's preventDefault below, which\n // does nothing for keyboard focus. Mirrors the containment\n // check menu/item/item.tsx already uses for the same reason.\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n onOpenChange(false);\n }\n }}\n >\n {children}\n </div>\n <AnimatePresence>\n {open && (\n <motion.div\n className={cn(\n 'absolute top-full
|
|
1
|
+
{"version":3,"file":"dropdown.mjs","names":[],"sources":["../../../src/components/molecules/dropdown.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useRef } from 'react';\n\nimport { useControllableState, useKeyPress } from '@jbpark/use-hooks';\nimport { AnimatePresence, motion } from 'motion/react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { OVERLAY_LAYER } from '../../lib/z-layers';\nimport Menu, { MenuProps } from './menu';\n\ntype ChangeEventHandler = (open: boolean) => void;\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n open?: boolean;\n trigger?: 'hover' | 'click';\n menu?: MenuProps;\n onOpenChange?: ChangeEventHandler;\n}\n\nconst Dropdown = ({\n children,\n menu,\n trigger = 'hover',\n open: _open,\n onOpenChange: _onOpenChange = () => {},\n className,\n onMouseEnter,\n onMouseLeave,\n ...props\n}: Props) => {\n const [open, onOpenChange] = useControllableState<boolean>({\n value: _open,\n defaultValue: false,\n onChange: _onOpenChange,\n });\n\n const isClickTrigger = trigger === 'click';\n const menuId = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n useKeyPress(\n 'esc',\n () => {\n onOpenChange(false);\n },\n { target: triggerRef },\n );\n\n useKeyPress(\n ['Enter', 'space'],\n event => {\n event.preventDefault();\n onOpenChange(!open);\n },\n { target: triggerRef, enabled: isClickTrigger },\n );\n\n return (\n <div\n {...props}\n ref={containerRef}\n className={cn(\n 'relative',\n 'inline-block cursor-pointer',\n className,\n //\n )}\n onMouseEnter={event => {\n onMouseEnter?.(event);\n if (isClickTrigger) {\n return;\n }\n onOpenChange(true);\n }}\n onMouseLeave={event => {\n onMouseLeave?.(event);\n if (isClickTrigger) {\n return;\n }\n onOpenChange(false);\n }}\n >\n <div\n ref={triggerRef}\n role={isClickTrigger ? 'button' : undefined}\n tabIndex={isClickTrigger ? 0 : undefined}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? menuId : undefined}\n onClick={() => {\n if (!isClickTrigger) {\n return;\n }\n onOpenChange(!open);\n }}\n onFocus={() => {\n if (isClickTrigger) {\n return;\n }\n onOpenChange(true);\n }}\n onBlur={e => {\n // Without this check, moving focus from the trigger into the\n // menu itself (e.g. via Tab) closed the dropdown before the\n // user could ever reach it — the mouse path avoided the same\n // bug only by way of onMouseDown's preventDefault below, which\n // does nothing for keyboard focus. Mirrors the containment\n // check menu/item/item.tsx already uses for the same reason.\n if (!containerRef.current?.contains(e.relatedTarget as Node)) {\n onOpenChange(false);\n }\n }}\n >\n {children}\n </div>\n <AnimatePresence>\n {open && (\n <motion.div\n className={cn(\n 'absolute top-full pt-2',\n OVERLAY_LAYER,\n //\n )}\n initial={{ opacity: 0, y: -10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.1 }}\n >\n <Menu\n {...menu}\n id={menuId}\n onMouseDown={e => {\n e.preventDefault();\n }}\n />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n};\n\nexport default Dropdown;\n"],"mappings":";;;;;;;;;AAqBA,MAAM,YAAY,EAChB,UACA,MACA,UAAU,SACV,MAAM,OACN,cAAc,sBAAsB,CAAC,GACrC,WACA,cACA,cACA,GAAG,YACQ;CACX,MAAM,CAAC,MAAM,gBAAgB,qBAA8B;EACzD,OAAO;EACP,cAAc;EACd,UAAU;CACZ,CAAC;CAED,MAAM,iBAAiB,YAAY;CACnC,MAAM,SAAS,MAAM;CACrB,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,aAAa,OAAuB,IAAI;CAE9C,YACE,aACM;EACJ,aAAa,KAAK;CACpB,GACA,EAAE,QAAQ,WAAW,CACvB;CAEA,YACE,CAAC,SAAS,OAAO,IACjB,UAAS;EACP,MAAM,eAAe;EACrB,aAAa,CAAC,IAAI;CACpB,GACA;EAAE,QAAQ;EAAY,SAAS;CAAe,CAChD;CAEA,OACE,qBAAC,OAAD;EACE,GAAI;EACJ,KAAK;EACL,WAAW,GACT,YACA,+BACA,SAEF;EACA,eAAc,UAAS;GACrB,eAAe,KAAK;GACpB,IAAI,gBACF;GAEF,aAAa,IAAI;EACnB;EACA,eAAc,UAAS;GACrB,eAAe,KAAK;GACpB,IAAI,gBACF;GAEF,aAAa,KAAK;EACpB;EAtBF,UAAA,CAwBE,oBAAC,OAAD;GACE,KAAK;GACL,MAAM,iBAAiB,WAAW,KAAA;GAClC,UAAU,iBAAiB,IAAI,KAAA;GAC/B,iBAAc;GACd,iBAAe;GACf,iBAAe,OAAO,SAAS,KAAA;GAC/B,eAAe;IACb,IAAI,CAAC,gBACH;IAEF,aAAa,CAAC,IAAI;GACpB;GACA,eAAe;IACb,IAAI,gBACF;IAEF,aAAa,IAAI;GACnB;GACA,SAAQ,MAAK;IAOX,IAAI,CAAC,aAAa,SAAS,SAAS,EAAE,aAAqB,GACzD,aAAa,KAAK;GAEtB;GAEC;EACE,CAAA,GACL,oBAAC,iBAAD,EAAA,UACG,QACC,oBAAC,OAAO,KAAR;GACE,WAAW,GACT,0BAAA,QAGF;GACA,SAAS;IAAE,SAAS;IAAG,GAAG;GAAI;GAC9B,SAAS;IAAE,SAAS;IAAG,GAAG;GAAE;GAC5B,MAAM;IAAE,SAAS;IAAG,GAAG;GAAI;GAC3B,YAAY,EAAE,UAAU,GAAI;GAE5B,UAAA,oBAAC,MAAD;IACE,GAAI;IACJ,IAAI;IACJ,cAAa,MAAK;KAChB,EAAE,eAAe;IACnB;GACD,CAAA;EACS,CAAA,EAEC,CAAA,CACd;;AAET"}
|
|
@@ -5,12 +5,13 @@ interface ItemProps {
|
|
|
5
5
|
autoFill?: boolean | number;
|
|
6
6
|
pause?: boolean;
|
|
7
7
|
pauseOnHover?: boolean;
|
|
8
|
+
gap?: number;
|
|
8
9
|
children?: React.ReactNode;
|
|
9
10
|
}
|
|
10
11
|
interface Props extends Omit<React.ComponentPropsWithoutRef<'div'>, 'key'>, ItemProps {
|
|
11
12
|
width: string | number;
|
|
12
13
|
}
|
|
13
|
-
declare const Item: ({ width: _width, speed, autoFill, pause: _pause, pauseOnHover, children }: Props) => import("react").JSX.Element;
|
|
14
|
+
declare const Item: ({ width: _width, speed, autoFill, pause: _pause, pauseOnHover, gap, children }: Props) => import("react").JSX.Element;
|
|
14
15
|
//#endregion
|
|
15
16
|
export { ItemProps, Props, Item as default };
|
|
16
17
|
//# sourceMappingURL=item.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";UASiB;EACf,MAAM,MAAM;EACZ;EACA;EACA;EACA;EACA,WAAW,MAAM;;UAGF,cACP,KAAK,MAAM,yCAAyC;EAC5D;;
|
|
1
|
+
{"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";UASiB;EACf,MAAM,MAAM;EACZ;EACA;EACA;EACA;EACA;EACA,WAAW,MAAM;;UAGF,cACP,KAAK,MAAM,yCAAyC;EAC5D;;cAoBI,SAAQ,OAAA,QAAA,OAAA,UAAA,OAAA,QAAA,cAAA,KAAA,YAQX,0BAAK,IAAA"}
|
|
@@ -6,22 +6,32 @@ import { useGSAP } from "@gsap/react";
|
|
|
6
6
|
import { gsap } from "gsap";
|
|
7
7
|
//#region src/components/molecules/marquees/item.tsx
|
|
8
8
|
const INITIAL_AUTO_FILL_GUESS = 10;
|
|
9
|
-
const
|
|
9
|
+
const resolveInitialRepeatCount = (autoFill) => {
|
|
10
|
+
if (!autoFill) return 0;
|
|
11
|
+
return typeof autoFill === "boolean" ? INITIAL_AUTO_FILL_GUESS : autoFill;
|
|
12
|
+
};
|
|
13
|
+
const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = false, pauseOnHover = false, gap = 0, children }) => {
|
|
10
14
|
const itemRefs = useRef([]);
|
|
11
15
|
const containerRef = useRef(null);
|
|
12
16
|
const tweenRef = useRef(null);
|
|
13
17
|
const [width, setWidth] = useState(_width);
|
|
14
18
|
const { pause, hoverEvents } = usePauseOnHover(pauseOnHover);
|
|
15
|
-
const [repeatCount, setRepeatCount] = useState(autoFill
|
|
19
|
+
const [repeatCount, setRepeatCount] = useState(resolveInitialRepeatCount(autoFill));
|
|
16
20
|
const [prevWidthProp, setPrevWidthProp] = useState(_width);
|
|
17
21
|
const [prevAutoFill, setPrevAutoFill] = useState(autoFill);
|
|
22
|
+
const [prevGap, setPrevGap] = useState(gap);
|
|
18
23
|
if (_width !== prevWidthProp) {
|
|
19
24
|
setPrevWidthProp(_width);
|
|
20
25
|
setWidth(_width);
|
|
21
26
|
}
|
|
22
27
|
if (autoFill !== prevAutoFill) {
|
|
23
28
|
setPrevAutoFill(autoFill);
|
|
24
|
-
setRepeatCount(autoFill
|
|
29
|
+
setRepeatCount(resolveInitialRepeatCount(autoFill));
|
|
30
|
+
}
|
|
31
|
+
if (gap !== prevGap) {
|
|
32
|
+
setPrevGap(gap);
|
|
33
|
+
setWidth(_width);
|
|
34
|
+
setRepeatCount(resolveInitialRepeatCount(autoFill));
|
|
25
35
|
}
|
|
26
36
|
const isPaused = _pause || pause;
|
|
27
37
|
useEffect(() => {
|
|
@@ -43,7 +53,8 @@ const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = fa
|
|
|
43
53
|
}, [
|
|
44
54
|
autoFill,
|
|
45
55
|
width,
|
|
46
|
-
children
|
|
56
|
+
children,
|
|
57
|
+
gap
|
|
47
58
|
]);
|
|
48
59
|
useGSAP(() => {
|
|
49
60
|
if (!containerRef.current || typeof width === "string") return;
|
|
@@ -79,8 +90,12 @@ const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = fa
|
|
|
79
90
|
ref: (el) => {
|
|
80
91
|
if (el) itemRefs.current[index] = el;
|
|
81
92
|
},
|
|
93
|
+
style: { paddingRight: gap },
|
|
94
|
+
children
|
|
95
|
+
}), [...Array(typeof autoFill === "number" ? autoFill : repeatCount)].map((_, i) => /* @__PURE__ */ jsx("div", {
|
|
96
|
+
style: { paddingRight: gap },
|
|
82
97
|
children
|
|
83
|
-
}
|
|
98
|
+
}, i))]
|
|
84
99
|
}, index))
|
|
85
100
|
})
|
|
86
101
|
});
|