@jbpark/ui-kit 6.1.0 → 6.2.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 +2 -2
- package/dist/Button.d.mts.map +1 -1
- package/dist/Button.mjs +2 -2
- package/dist/Button.mjs.map +1 -1
- package/dist/Space.d.mts.map +1 -1
- package/dist/Space.mjs +6 -2
- package/dist/Space.mjs.map +1 -1
- package/dist/Tag.d.mts +17 -3
- package/dist/Tag.d.mts.map +1 -1
- package/dist/Tag.mjs +14 -2
- package/dist/Tag.mjs.map +1 -1
- package/dist/components/atoms/index.d.mts +2 -1
- package/dist/components/atoms/slider/index.mjs +7 -0
- package/dist/components/atoms/slider/index.mjs.map +1 -0
- package/dist/components/atoms/slider/slider.d.mts +17 -0
- package/dist/components/atoms/slider/slider.d.mts.map +1 -0
- package/dist/components/atoms/slider/slider.mjs +36 -0
- package/dist/components/atoms/slider/slider.mjs.map +1 -0
- package/dist/components/organisms/modal.d.mts +9 -1
- package/dist/components/organisms/modal.d.mts.map +1 -1
- package/dist/components/organisms/modal.mjs +14 -10
- package/dist/components/organisms/modal.mjs.map +1 -1
- package/dist/components/organisms/toast.d.mts +10 -4
- package/dist/components/organisms/toast.d.mts.map +1 -1
- package/dist/components/organisms/toast.mjs +10 -9
- package/dist/components/organisms/toast.mjs.map +1 -1
- package/dist/core/index.d.mts +1 -0
- package/dist/core/slider.d.mts +2 -0
- package/dist/core/slider.mjs +54 -0
- package/dist/core/slider.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/dist/lib/colors.d.mts +12 -0
- package/dist/lib/colors.d.mts.map +1 -0
- package/dist/lib/colors.mjs +28 -0
- package/dist/lib/colors.mjs.map +1 -0
- package/dist/style.css +95 -0
- package/package.json +2 -1
package/dist/Button.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { PresetColor } from "./lib/colors.mjs";
|
|
1
2
|
import * as React$1 from "react";
|
|
2
3
|
//#region src/components/atoms/button.d.ts
|
|
3
4
|
type NativeButtonProps = React$1.ComponentProps<'button'> & {
|
|
4
5
|
asChild?: boolean;
|
|
5
6
|
};
|
|
6
|
-
type PresetColors = 'blue' | 'purple' | 'cyan' | 'green' | 'magenta' | 'pink' | 'red' | 'orange' | 'yellow' | 'volcano' | 'geekblue' | 'lime' | 'gold';
|
|
7
7
|
interface Props extends Omit<NativeButtonProps, 'size' | 'variant' | 'type'> {
|
|
8
8
|
icon?: React$1.ReactNode;
|
|
9
9
|
block?: boolean;
|
|
@@ -44,7 +44,7 @@ interface Props extends Omit<NativeButtonProps, 'size' | 'variant' | 'type'> {
|
|
|
44
44
|
* Color, independent of `variant`. Defaults to `'default'`, or to whatever
|
|
45
45
|
* `type` maps to when `type` is set. `danger` overrides this.
|
|
46
46
|
*/
|
|
47
|
-
color?:
|
|
47
|
+
color?: PresetColor | 'default' | 'primary' | 'danger';
|
|
48
48
|
loading?: boolean | {
|
|
49
49
|
icon: React$1.ReactNode;
|
|
50
50
|
};
|
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":";;;KAaK,oBAAoB,QAAM;EAC7B;;UAGe,cAAc,KAC7B;EAGA,OAAO,QAAM;EACb;EACA;EACA;EACA;;;;;;;;;;;;;;;;;;EAkBA;;;;;EAKA;;;;;;EAMA;EACA;;;;;EAKA,QAAQ;EACR;IAAsB,MAAM,QAAM;;;cAqF9B,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
|
@@ -68,8 +68,8 @@ const Button = ({ icon, className, type, variant, htmlType = "button", size, col
|
|
|
68
68
|
const resolvedShape = shape ?? buttonDefaults?.shape ?? "default";
|
|
69
69
|
const iconOnly = icon && !children;
|
|
70
70
|
const typeDefaults = type ? typeToColorVariant[type] : void 0;
|
|
71
|
-
const resolvedVariant = variant ?? typeDefaults?.variant ?? "outlined";
|
|
72
|
-
const computedColor = danger ? "danger" : color ?? typeDefaults?.color ?? "default";
|
|
71
|
+
const resolvedVariant = variant ?? typeDefaults?.variant ?? buttonDefaults?.variant ?? "outlined";
|
|
72
|
+
const computedColor = danger ? "danger" : color ?? typeDefaults?.color ?? buttonDefaults?.color ?? "default";
|
|
73
73
|
const colored = computedColor !== "default";
|
|
74
74
|
const isLoading = !!loading;
|
|
75
75
|
const Comp = asChild ? Slot : "button";
|
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 * 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 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\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'>> | 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 // `danger` still trumps everything, matching antd. Defaults live here rather\n // than on the parameters so `type` gets a chance to supply them first.\n const typeDefaults = type ? typeToColorVariant[type] : undefined;\n const resolvedVariant = variant ?? typeDefaults?.variant ?? 'outlined';\n const computedColor = danger\n ? 'danger'\n : (color ?? typeDefaults?.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":";;;;;;;;;AAmFA,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;CAK1B,MAAM,eAAe,OAAO,mBAAmB,QAAQ,KAAA;CACvD,MAAM,kBAAkB,WAAW,cAAc,WAAW;CAC5D,MAAM,gBAAgB,SAClB,WACC,SAAS,cAAc,SAAS;CACrC,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":[],"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 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 color?: PresetColor | '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":";;;;;;;;;AAqEA,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"}
|
package/dist/Space.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Space.d.mts","names":[],"sources":["../src/components/molecules/space.tsx"],"mappings":";
|
|
1
|
+
{"version":3,"file":"Space.d.mts","names":[],"sources":["../src/components/molecules/space.tsx"],"mappings":";UASiB,cAAc,MAAM;EACnC;EACA,SAAS,MAAM;EACf;EACA;EACA;EACA;EACA,QAAQ,MAAM;EACd;IACE;IACA;;;cAiBE,UAAS,SAAA,QAAA,UAAA,MAAA,aAAA,OAAA,MAAA,OAAA,WAAA,MAAA,QAAA,UAAA,SAcZ,0BAAK,IAAA"}
|
package/dist/Space.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
2
4
|
import Skeleton from "./components/atoms/skeleton/index.mjs";
|
|
3
5
|
import { Children } from "react";
|
|
4
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -14,8 +16,10 @@ const aligns = {
|
|
|
14
16
|
center: "items-center text-center",
|
|
15
17
|
baseline: "items-baseline text-baseline"
|
|
16
18
|
};
|
|
17
|
-
const Space = ({ loading, loader, children, size
|
|
18
|
-
const
|
|
19
|
+
const Space = ({ loading, loader, children, size, orientation = "horizontal", align = "center", wrap = false, split, className, grid, hidden, style, ...props }) => {
|
|
20
|
+
const { componentSize } = useConfig();
|
|
21
|
+
const resolvedSize = size ?? componentSize ?? "middle";
|
|
22
|
+
const [x, y] = typeof resolvedSize === "string" ? sizes[resolvedSize] || [0, 0] : Array.isArray(resolvedSize) ? resolvedSize : [resolvedSize, resolvedSize];
|
|
19
23
|
const count = Children.count(children);
|
|
20
24
|
if (loading) return /* @__PURE__ */ jsx("div", {
|
|
21
25
|
className: cn(hidden && "hidden", className),
|
package/dist/Space.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Space.mjs","names":[],"sources":["../src/components/molecules/space.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Space.mjs","names":[],"sources":["../src/components/molecules/space.tsx"],"sourcesContent":["'use client';\n\nimport { Children } from 'react';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Skeleton from '../atoms/skeleton';\n\nexport interface Props extends React.ComponentPropsWithRef<'div'> {\n loading?: boolean;\n loader?: React.ReactNode;\n orientation?: 'horizontal' | 'vertical';\n size?: 'small' | 'middle' | 'large' | number | number[];\n align?: 'start' | 'end' | 'center' | 'baseline';\n wrap?: boolean;\n split?: React.ReactNode;\n grid?: {\n rows?: number;\n cols?: number;\n };\n}\n\nconst sizes: Record<string, number[]> = {\n small: [4, 4],\n middle: [8, 8],\n large: [16, 16],\n};\n\nconst aligns: Record<string, string> = {\n start: 'items-start text-start',\n end: 'items-end text-end',\n center: 'items-center text-center',\n baseline: 'items-baseline text-baseline',\n};\n\nconst Space = ({\n loading,\n loader,\n children,\n size,\n orientation = 'horizontal',\n align = 'center',\n wrap = false,\n split,\n className,\n grid,\n hidden,\n style,\n ...props\n}: Props) => {\n const { componentSize } = useConfig();\n // `size` overrides the global `componentSize` from `Config`, which in turn\n // falls back to `middle` — the same resolution order `Button` uses so a single\n // `<Config componentSize>` sizes both. Numeric/array gaps bypass the token.\n const resolvedSize = size ?? componentSize ?? 'middle';\n const [x, y] =\n typeof resolvedSize === 'string'\n ? sizes[resolvedSize] || [0, 0]\n : Array.isArray(resolvedSize)\n ? resolvedSize\n : [resolvedSize, resolvedSize];\n const count = Children.count(children);\n\n if (loading) {\n return (\n <div\n className={cn(hidden && 'hidden', className)}\n style={style}\n hidden={hidden}\n {...props}\n >\n {loader || <Skeleton />}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'flex flex-nowrap',\n orientation === 'horizontal' ? 'flex-row' : 'flex-col',\n wrap && 'flex-wrap',\n aligns[align],\n grid && 'grid',\n hidden && 'hidden',\n className,\n )}\n style={{\n columnGap: x,\n rowGap: y,\n gridTemplateRows: grid?.rows\n ? `repeat(${grid.rows}, minmax(0, 1fr))`\n : undefined,\n gridTemplateColumns: grid?.cols\n ? `repeat(${grid.cols}, minmax(0, 1fr))`\n : undefined,\n ...style,\n }}\n hidden={hidden}\n {...props}\n >\n {Children.map(children, (child, i) => (\n <>\n {child}\n {split && i < count - 1 && split}\n </>\n ))}\n </div>\n );\n};\n\nexport default Space;\n"],"mappings":";;;;;;;AAuBA,MAAM,QAAkC;CACtC,OAAO,CAAC,GAAG,CAAC;CACZ,QAAQ,CAAC,GAAG,CAAC;CACb,OAAO,CAAC,IAAI,EAAE;AAChB;AAEA,MAAM,SAAiC;CACrC,OAAO;CACP,KAAK;CACL,QAAQ;CACR,UAAU;AACZ;AAEA,MAAM,SAAS,EACb,SACA,QACA,UACA,MACA,cAAc,cACd,QAAQ,UACR,OAAO,OACP,OACA,WACA,MACA,QACA,OACA,GAAG,YACQ;CACX,MAAM,EAAE,kBAAkB,UAAU;CAIpC,MAAM,eAAe,QAAQ,iBAAiB;CAC9C,MAAM,CAAC,GAAG,KACR,OAAO,iBAAiB,WACpB,MAAM,iBAAiB,CAAC,GAAG,CAAC,IAC5B,MAAM,QAAQ,YAAY,IACxB,eACA,CAAC,cAAc,YAAY;CACnC,MAAM,QAAQ,SAAS,MAAM,QAAQ;CAErC,IAAI,SACF,OACE,oBAAC,OAAD;EACE,WAAW,GAAG,UAAU,UAAU,SAAS;EACpC;EACC;EACR,GAAI;EAEH,UAAA,UAAU,oBAAC,UAAD,CAAW,CAAA;CACnB,CAAA;CAIT,OACE,oBAAC,OAAD;EACE,WAAW,GACT,oBACA,gBAAgB,eAAe,aAAa,YAC5C,QAAQ,aACR,OAAO,QACP,QAAQ,QACR,UAAU,UACV,SACF;EACA,OAAO;GACL,WAAW;GACX,QAAQ;GACR,kBAAkB,MAAM,OACpB,UAAU,KAAK,KAAK,qBACpB,KAAA;GACJ,qBAAqB,MAAM,OACvB,UAAU,KAAK,KAAK,qBACpB,KAAA;GACJ,GAAG;EACL;EACQ;EACR,GAAI;EAEH,UAAA,SAAS,IAAI,WAAW,OAAO,MAC9B,qBAAA,YAAA,EAAA,UAAA,CACG,OACA,SAAS,IAAI,QAAQ,KAAK,KAC3B,EAAA,CAAA,CACH;CACE,CAAA;AAET"}
|
package/dist/Tag.d.mts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
+
import { PresetColor } from "./lib/colors.mjs";
|
|
1
2
|
import * as React$1 from "react";
|
|
2
3
|
//#region src/components/atoms/tag.d.ts
|
|
3
4
|
type NativeSpanProps = React$1.ComponentProps<'span'> & {
|
|
4
5
|
asChild?: boolean;
|
|
5
6
|
};
|
|
6
|
-
interface Props extends Omit<NativeSpanProps, 'variant'> {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
interface Props extends Omit<NativeSpanProps, 'variant' | 'color'> {
|
|
8
|
+
/**
|
|
9
|
+
* Fill style, aligned with `Button`'s vocabulary. `'default'` is a
|
|
10
|
+
* **deprecated alias** for `'filled'` — it still renders identically, but
|
|
11
|
+
* prefer `'filled'` going forward (#320).
|
|
12
|
+
*
|
|
13
|
+
* @remarks `'default'` will be removed in a future major.
|
|
14
|
+
*/
|
|
15
|
+
variant?: 'filled' | 'outlined' | 'default';
|
|
16
|
+
/**
|
|
17
|
+
* Colour, sharing `Button`'s preset palette. The named states
|
|
18
|
+
* (`primary`/`success`/`warning`/`danger`) keep their semantic look; the
|
|
19
|
+
* shared presets (`blue`, `red`, `gold`, …) are backed by the same
|
|
20
|
+
* `data-color` system as `Button` (#320).
|
|
21
|
+
*/
|
|
22
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | PresetColor;
|
|
9
23
|
}
|
|
10
24
|
declare const Tag: ({ className, variant, color, asChild, children, ...props }: Props) => React$1.JSX.Element;
|
|
11
25
|
//#endregion
|
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":";;;KAYK,kBAAkB,QAAM;EAC3B;;UAGe,cAAc,KAAK;;;;;;;;EAQlC;;;;;;;EAOA,mEAC6D;;cAgDzD,QAAO,WAAA,SAAA,OAAA,SAAA,aAAA,SAOV,UAAK,QAAA,IAAA"}
|
package/dist/Tag.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { cn } from "./utils.mjs";
|
|
3
|
+
import { useConfig } from "./providers/config/context.mjs";
|
|
2
4
|
import { INTERACTIVE_CHASSIS } from "./lib/chassis.mjs";
|
|
5
|
+
import { isPresetColor } from "./lib/colors.mjs";
|
|
3
6
|
import "react";
|
|
4
7
|
import { Slot } from "@radix-ui/react-slot";
|
|
5
8
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -19,10 +22,19 @@ const outlinedColorClasses = {
|
|
|
19
22
|
warning: "border-yellow-500 text-yellow-600 dark:text-yellow-400",
|
|
20
23
|
danger: "border-destructive text-destructive"
|
|
21
24
|
};
|
|
22
|
-
const
|
|
25
|
+
const presetFillClasses = cn("border-transparent", "bg-[color-mix(in_oklch,var(--tag-bg),transparent_90%)]", "text-(--tag-bg)");
|
|
26
|
+
const presetOutlinedClasses = cn("border-(--tag-bg) text-(--tag-bg)");
|
|
27
|
+
const Tag = ({ className, variant, color, asChild = false, children, ...props }) => {
|
|
28
|
+
const { defaultProps } = useConfig();
|
|
29
|
+
const tagDefaults = defaultProps?.tag;
|
|
30
|
+
const resolvedVariant = variant ?? tagDefaults?.variant ?? "filled";
|
|
31
|
+
const resolvedColor = color ?? tagDefaults?.color ?? "default";
|
|
32
|
+
const isOutlined = resolvedVariant === "outlined";
|
|
33
|
+
const preset = isPresetColor(resolvedColor);
|
|
23
34
|
return /* @__PURE__ */ jsx(asChild ? Slot : "span", {
|
|
24
35
|
"data-slot": "badge",
|
|
25
|
-
|
|
36
|
+
"data-color": preset ? resolvedColor : void 0,
|
|
37
|
+
className: cn(TAG_BASE, "rounded-full px-2.5 py-1", "text-xs font-medium", preset ? isOutlined ? presetOutlinedClasses : presetFillClasses : isOutlined ? outlinedColorClasses[resolvedColor] : fillColorClasses[resolvedColor], className),
|
|
26
38
|
...props,
|
|
27
39
|
children
|
|
28
40
|
});
|
package/dist/Tag.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tag.mjs","names":[],"sources":["../src/components/atoms/tag.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Tag.mjs","names":[],"sources":["../src/components/atoms/tag.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport { Slot } from '@radix-ui/react-slot';\n\nimport { useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { INTERACTIVE_CHASSIS } from '../../lib/chassis';\nimport { type PresetColor, isPresetColor } from '../../lib/colors';\n\ntype NativeSpanProps = React.ComponentProps<'span'> & {\n asChild?: boolean;\n};\n\nexport interface Props extends Omit<NativeSpanProps, 'variant' | 'color'> {\n /**\n * Fill style, aligned with `Button`'s vocabulary. `'default'` is a\n * **deprecated alias** for `'filled'` — it still renders identically, but\n * prefer `'filled'` going forward (#320).\n *\n * @remarks `'default'` will be removed in a future major.\n */\n variant?: 'filled' | 'outlined' | 'default';\n /**\n * Colour, sharing `Button`'s preset palette. The named states\n * (`primary`/`success`/`warning`/`danger`) keep their semantic look; the\n * shared presets (`blue`, `red`, `gold`, …) are backed by the same\n * `data-color` system as `Button` (#320).\n */\n color?:\n 'default' | 'primary' | 'success' | 'warning' | 'danger' | PresetColor;\n}\n\n// Base absorbed from core/badge's cva base + its `outline` variant, which Tag\n// always rendered as (#278 ③ / #294 Phase 4). The shared focus/aria/centering\n// set lives in INTERACTIVE_CHASSIS; a Tag adds badge geometry and its svg\n// sizing but — unlike Button — no `disabled:*` (a Tag is not disableable). The\n// rounded/padding leftovers are overridden by the atom classes below exactly as\n// before, so the rendered output is unchanged (verified against a pre-refactor\n// render matrix).\nconst TAG_BASE = cn(\n INTERACTIVE_CHASSIS,\n 'border w-fit whitespace-nowrap overflow-hidden',\n 'text-xs font-medium gap-1 transition-[color,box-shadow]',\n '[&>svg]:size-3 [&>svg]:pointer-events-none',\n 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',\n);\n\nconst fillColorClasses: Record<string, string> = {\n default: 'border-transparent bg-muted text-muted-foreground',\n primary: 'border-transparent bg-primary/10 text-primary',\n success:\n 'border-transparent bg-green-500/10 text-green-600 dark:text-green-400',\n warning:\n 'border-transparent bg-yellow-500/10 text-yellow-600 dark:text-yellow-400',\n danger: 'border-transparent bg-destructive/10 text-destructive',\n};\n\nconst outlinedColorClasses: Record<string, string> = {\n default: 'border-border text-foreground',\n primary: 'border-primary text-primary',\n success: 'border-green-500 text-green-600 dark:text-green-400',\n warning: 'border-yellow-500 text-yellow-600 dark:text-yellow-400',\n danger: 'border-destructive text-destructive',\n};\n\n// Preset colours resolve their hue from the shared `--tag-bg` custom property\n// (globals.css, keyed on `data-color`) rather than a per-colour Tailwind class,\n// so `Tag` and `Button` stay in lock-step. Fill uses a 10% tint behind the\n// full-strength hue; outlined borders and texts it directly.\nconst presetFillClasses = cn(\n 'border-transparent',\n 'bg-[color-mix(in_oklch,var(--tag-bg),transparent_90%)]',\n 'text-(--tag-bg)',\n);\n\nconst presetOutlinedClasses = cn('border-(--tag-bg) text-(--tag-bg)');\n\nconst Tag = ({\n className,\n variant,\n color,\n asChild = false,\n children,\n ...props\n}: 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 // `'default'` is the pre-#320 spelling of `'filled'`; fold it in so the alias\n // renders identically.\n const isOutlined = resolvedVariant === 'outlined';\n const preset = isPresetColor(resolvedColor);\n const Comp = asChild ? Slot : 'span';\n\n return (\n <Comp\n data-slot=\"badge\"\n // Only preset colours drive the `--tag-*` system; the named states keep\n // their bespoke classes, so existing usage renders byte-identical.\n data-color={preset ? resolvedColor : undefined}\n className={cn(\n TAG_BASE,\n 'rounded-full px-2.5 py-1',\n 'text-xs font-medium',\n preset\n ? isOutlined\n ? presetOutlinedClasses\n : presetFillClasses\n : isOutlined\n ? outlinedColorClasses[resolvedColor]\n : fillColorClasses[resolvedColor],\n className,\n //\n )}\n {...props}\n >\n {children}\n </Comp>\n );\n};\n\nexport default Tag;\n"],"mappings":";;;;;;;;;AA0CA,MAAM,WAAW,GACf,qBACA,kDACA,2DACA,8CACA,wEACF;AAEA,MAAM,mBAA2C;CAC/C,SAAS;CACT,SAAS;CACT,SACE;CACF,SACE;CACF,QAAQ;AACV;AAEA,MAAM,uBAA+C;CACnD,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;AACV;AAMA,MAAM,oBAAoB,GACxB,sBACA,0DACA,iBACF;AAEA,MAAM,wBAAwB,GAAG,mCAAmC;AAEpE,MAAM,OAAO,EACX,WACA,SACA,OACA,UAAU,OACV,UACA,GAAG,YACQ;CACX,MAAM,EAAE,iBAAiB,UAAU;CACnC,MAAM,cAAc,cAAc;CAIlC,MAAM,kBAAkB,WAAW,aAAa,WAAW;CAC3D,MAAM,gBAAgB,SAAS,aAAa,SAAS;CAGrD,MAAM,aAAa,oBAAoB;CACvC,MAAM,SAAS,cAAc,aAAa;CAG1C,OACE,oBAHW,UAAU,OAAO,QAG5B;EACE,aAAU;EAGV,cAAY,SAAS,gBAAgB,KAAA;EACrC,WAAW,GACT,UACA,4BACA,uBACA,SACI,aACE,wBACA,oBACF,aACE,qBAAqB,iBACrB,iBAAiB,gBACvB,SAEF;EACA,GAAI;EAEH;CACG,CAAA;AAEV"}
|
|
@@ -11,6 +11,7 @@ import Progress from "./progress.mjs";
|
|
|
11
11
|
import Radio from "./radio/index.mjs";
|
|
12
12
|
import Select from "./select.mjs";
|
|
13
13
|
import Skeleton from "./skeleton/index.mjs";
|
|
14
|
+
import Slider from "./slider/slider.mjs";
|
|
14
15
|
import Spin from "./spin.mjs";
|
|
15
16
|
import Switch from "./switch.mjs";
|
|
16
|
-
export { Button, Checkbox, ColorPicker, DatePicker, FloatButton, Input, Popover, Progress, Radio, Select, Skeleton, Spin, Switch, Tag, Typography };
|
|
17
|
+
export { Button, Checkbox, ColorPicker, DatePicker, FloatButton, Input, Popover, Progress, Radio, Select, Skeleton, Slider, Spin, Switch, Tag, Typography };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/atoms/slider/index.ts"],"sourcesContent":["import Slider, { type Props, type SliderValue } from './slider';\n\nexport default Slider;\nexport type { Props, SliderValue };\n"],"mappings":";;AAEA,IAAA,iBAAe"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/components/atoms/slider/slider.d.ts
|
|
2
|
+
/** A single thumb (`number`) or a two-thumb range (`[min, max]`). */
|
|
3
|
+
type SliderValue = number | number[];
|
|
4
|
+
interface Props extends Omit<React.ComponentPropsWithoutRef<'span'>, 'onChange' | 'defaultValue' | 'dir'> {
|
|
5
|
+
value?: SliderValue;
|
|
6
|
+
defaultValue?: SliderValue;
|
|
7
|
+
min?: number;
|
|
8
|
+
max?: number;
|
|
9
|
+
step?: number;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
orientation?: 'horizontal' | 'vertical';
|
|
12
|
+
onChange?: (value: SliderValue) => void;
|
|
13
|
+
}
|
|
14
|
+
declare const Slider: ({ value: _value, defaultValue, min, max, step, disabled, orientation, onChange: _onChange, className, ...props }: Props) => import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Props, SliderValue, Slider as default };
|
|
17
|
+
//# sourceMappingURL=slider.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slider.d.mts","names":[],"sources":["../../../../src/components/atoms/slider/slider.tsx"],"mappings":";;KAWY;UAEK,cAAc,KAC7B,MAAM;EAGN,QAAQ;EACR,eAAe;EACf;EACA;EACA;EACA;EACA;EACA,YAAY,OAAO;;cAWf,WAAU,OAAA,QAAA,cAAA,KAAA,KAAA,MAAA,UAAA,aAAA,UAAA,WAAA,cAAA,SAWb,0BAAK,IAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../../utils.mjs";
|
|
3
|
+
import { slider_exports } from "../../../core/slider.mjs";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useControllableState } from "@jbpark/use-hooks";
|
|
6
|
+
//#region src/components/atoms/slider/slider.tsx
|
|
7
|
+
const { Slider: Core } = slider_exports;
|
|
8
|
+
const toArray = (value) => {
|
|
9
|
+
if (value === void 0) return;
|
|
10
|
+
return Array.isArray(value) ? value : [value];
|
|
11
|
+
};
|
|
12
|
+
const Slider = ({ value: _value, defaultValue, min = 0, max = 100, step = 1, disabled, orientation = "horizontal", onChange: _onChange = () => {}, className, ...props }) => {
|
|
13
|
+
const isRange = Array.isArray(_value ?? defaultValue);
|
|
14
|
+
const [value, onChange] = useControllableState({
|
|
15
|
+
value: toArray(_value),
|
|
16
|
+
defaultValue: toArray(defaultValue) ?? [min],
|
|
17
|
+
onChange: (next) => {
|
|
18
|
+
_onChange(isRange ? next : next[0] ?? min);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsx(Core, {
|
|
22
|
+
value,
|
|
23
|
+
min,
|
|
24
|
+
max,
|
|
25
|
+
step,
|
|
26
|
+
disabled,
|
|
27
|
+
orientation,
|
|
28
|
+
className: cn(className),
|
|
29
|
+
onValueChange: onChange,
|
|
30
|
+
...props
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { Slider as default };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=slider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slider.mjs","names":["slider"],"sources":["../../../../src/components/atoms/slider/slider.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { slider } from '../../../core';\n\nconst { Slider: Core } = slider;\n\n/** A single thumb (`number`) or a two-thumb range (`[min, max]`). */\nexport type SliderValue = number | number[];\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'span'>,\n 'onChange' | 'defaultValue' | 'dir'\n> {\n value?: SliderValue;\n defaultValue?: SliderValue;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n orientation?: 'horizontal' | 'vertical';\n onChange?: (value: SliderValue) => void;\n}\n\nconst toArray = (value: SliderValue | undefined): number[] | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n return Array.isArray(value) ? value : [value];\n};\n\nconst Slider = ({\n value: _value,\n defaultValue,\n min = 0,\n max = 100,\n step = 1,\n disabled,\n orientation = 'horizontal',\n onChange: _onChange = () => {},\n className,\n ...props\n}: Props) => {\n // A `number[]` value/defaultValue means the consumer wants a range; a bare\n // `number` means a single thumb. Radix works in `number[]` throughout, so we\n // normalise on the way in and hand the original shape back through `onChange`.\n const isRange = Array.isArray(_value ?? defaultValue);\n\n const [value, onChange] = useControllableState<number[]>({\n value: toArray(_value),\n defaultValue: toArray(defaultValue) ?? [min],\n onChange: next => {\n _onChange(isRange ? next : (next[0] ?? min));\n },\n });\n\n return (\n <Core\n value={value}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n orientation={orientation}\n className={cn(className)}\n onValueChange={onChange}\n {...props}\n />\n );\n};\n\nexport default Slider;\n"],"mappings":";;;;;;AAQA,MAAM,EAAE,QAAQ,SAASA;AAmBzB,MAAM,WAAW,UAAyD;CACxE,IAAI,UAAU,KAAA,GACZ;CAGF,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAC9C;AAEA,MAAM,UAAU,EACd,OAAO,QACP,cACA,MAAM,GACN,MAAM,KACN,OAAO,GACP,UACA,cAAc,cACd,UAAU,kBAAkB,CAAC,GAC7B,WACA,GAAG,YACQ;CAIX,MAAM,UAAU,MAAM,QAAQ,UAAU,YAAY;CAEpD,MAAM,CAAC,OAAO,YAAY,qBAA+B;EACvD,OAAO,QAAQ,MAAM;EACrB,cAAc,QAAQ,YAAY,KAAK,CAAC,GAAG;EAC3C,WAAU,SAAQ;GAChB,UAAU,UAAU,OAAQ,KAAK,MAAM,GAAI;EAC7C;CACF,CAAC;CAED,OACE,oBAAC,MAAD;EACS;EACF;EACA;EACC;EACI;EACG;EACb,WAAW,GAAG,SAAS;EACvB,eAAe;EACf,GAAI;CACL,CAAA;AAEL"}
|
|
@@ -26,8 +26,16 @@ interface Props {
|
|
|
26
26
|
onOk?: () => void;
|
|
27
27
|
onCancel?: () => void;
|
|
28
28
|
}
|
|
29
|
+
type ModalStatus = 'info' | 'success' | 'error' | 'warning';
|
|
29
30
|
interface StaticProps extends Props {
|
|
30
|
-
|
|
31
|
+
status?: ModalStatus;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use `status` for the semantic state. Kept as an alias so
|
|
34
|
+
* existing `type="info|success|error|warning"` calls keep working. `confirm`
|
|
35
|
+
* is an interaction mode, not a status — call `Modal.confirm()` instead
|
|
36
|
+
* (still accepted here as `type="confirm"` for back-compat).
|
|
37
|
+
*/
|
|
38
|
+
type?: ModalStatus | 'confirm';
|
|
31
39
|
id?: string;
|
|
32
40
|
icon?: React.ReactNode;
|
|
33
41
|
container?: HTMLElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.d.mts","names":[],"sources":["../../../src/components/organisms/modal.tsx"],"mappings":";;UAiCiB;EACf;EACA;EACA;IAGM,YAAY,MAAM;IAClB;;EAEN,YAAY,MAAM;EAClB,QAAQ,MAAM;EACd,UAAU,MAAM;EAChB,SAAS,MAAM;EACf;EACA;IACE;IACA;IACA;IACA;;EAEF,QAAQ,MAAM;EACd;EACA;EACA,YAAY;EACZ,WAAW,MAAM;EACjB;EACA;;
|
|
1
|
+
{"version":3,"file":"modal.d.mts","names":[],"sources":["../../../src/components/organisms/modal.tsx"],"mappings":";;UAiCiB;EACf;EACA;EACA;IAGM,YAAY,MAAM;IAClB;;EAEN,YAAY,MAAM;EAClB,QAAQ,MAAM;EACd,UAAU,MAAM;EAChB,SAAS,MAAM;EACf;EACA;IACE;IACA;IACA;IACA;;EAEF,QAAQ,MAAM;EACd;EACA;EACA,YAAY;EACZ,WAAW,MAAM;EACjB;EACA;;KAGG;UAEK,oBAAoB;EAC5B,SAAS;;;;;;;EAOT,OAAO;EACP;EACA,OAAO,MAAM;EACb,YAAY;;cAGR;KAkBH,MAAA,cAAA,UAAA,WAAA,WAAA,YAAA,OAAA,OAAA,SAAA,QAAA,WAAA,UAAA,QAAA,YAAA,MAAA,aAAA,SAAA,QAAK,MAAA,IAAA;;;EAwNa,KAAA,OAAA;EAEG,QAAA,OAAA;EAEF,MAAA,OAAA;EAEE,QAAA,OAAA;EAIA,QAAA,OAAA"}
|
|
@@ -10,8 +10,10 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
import { createPortal } from "react-dom";
|
|
11
11
|
//#region src/components/organisms/modal.tsx
|
|
12
12
|
const { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } = dialog_exports;
|
|
13
|
-
const Modal = ({ open = false, maskClosable
|
|
14
|
-
const { locale } = useConfig();
|
|
13
|
+
const Modal = ({ open = false, maskClosable, closable = false, closeIcon, className, classNames, style, title, content, footer, container, children, okText, cancelText, onOk, onCancel, ...props }) => {
|
|
14
|
+
const { locale, defaultProps } = useConfig();
|
|
15
|
+
const modalDefaults = defaultProps?.modal;
|
|
16
|
+
const resolvedMaskClosable = maskClosable ?? modalDefaults?.maskClosable ?? false;
|
|
15
17
|
if (typeof window === "undefined") return null;
|
|
16
18
|
return /* @__PURE__ */ jsx(Dialog, {
|
|
17
19
|
open,
|
|
@@ -30,7 +32,7 @@ const Modal = ({ open = false, maskClosable = false, closable = false, closeIcon
|
|
|
30
32
|
closeIcon,
|
|
31
33
|
container,
|
|
32
34
|
onPointerDownOutside: (event) => {
|
|
33
|
-
if (!
|
|
35
|
+
if (!resolvedMaskClosable) event.preventDefault();
|
|
34
36
|
},
|
|
35
37
|
children: [
|
|
36
38
|
/* @__PURE__ */ jsxs(DialogHeader, {
|
|
@@ -63,11 +65,13 @@ const STATIC_ICONS = {
|
|
|
63
65
|
warning: /* @__PURE__ */ jsx(OctagonAlert, { className: "text-yellow-400" }),
|
|
64
66
|
confirm: /* @__PURE__ */ jsx(CircleQuestionMark, {})
|
|
65
67
|
};
|
|
66
|
-
const StaticModal = ({ id, type, title, content, okText, cancelText, container, icon, onOk, onCancel, ...props }) => {
|
|
68
|
+
const StaticModal = ({ id, status, type, title, content, okText, cancelText, container, icon, onOk, onCancel, ...props }) => {
|
|
67
69
|
const { locale } = useConfig();
|
|
68
70
|
const [open, setOpen] = useState(true);
|
|
69
71
|
const resolvedOkText = okText ?? locale.ok ?? DEFAULT_LOCALE.ok;
|
|
70
72
|
const resolvedCancelText = cancelText ?? locale.cancel ?? DEFAULT_LOCALE.cancel;
|
|
73
|
+
const isConfirm = type === "confirm";
|
|
74
|
+
const resolvedStatus = status ?? (isConfirm ? void 0 : type);
|
|
71
75
|
const closeModal = (callback) => {
|
|
72
76
|
callback?.();
|
|
73
77
|
setOpen(false);
|
|
@@ -75,7 +79,7 @@ const StaticModal = ({ id, type, title, content, okText, cancelText, container,
|
|
|
75
79
|
modalStack.destroy(id);
|
|
76
80
|
}, 200);
|
|
77
81
|
};
|
|
78
|
-
const footer =
|
|
82
|
+
const footer = isConfirm ? /* @__PURE__ */ jsxs("div", {
|
|
79
83
|
className: "grid w-full grid-cols-5 gap-x-2",
|
|
80
84
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
81
85
|
variant: "outlined",
|
|
@@ -104,7 +108,7 @@ const StaticModal = ({ id, type, title, content, okText, cancelText, container,
|
|
|
104
108
|
},
|
|
105
109
|
title: /* @__PURE__ */ jsxs("p", {
|
|
106
110
|
className: cn("text-center text-lg leading-normal whitespace-pre-wrap", "flex items-center justify-center gap-x-2"),
|
|
107
|
-
children: [icon ||
|
|
111
|
+
children: [icon || (isConfirm ? STATIC_ICONS.confirm : resolvedStatus && STATIC_ICONS[resolvedStatus]), title]
|
|
108
112
|
}),
|
|
109
113
|
container,
|
|
110
114
|
onCancel: () => closeModal(onCancel),
|
|
@@ -126,19 +130,19 @@ Modal.destroyAll = () => {
|
|
|
126
130
|
modalStack.destroy();
|
|
127
131
|
};
|
|
128
132
|
Modal.info = (props) => modalStack.render({
|
|
129
|
-
|
|
133
|
+
status: "info",
|
|
130
134
|
...props
|
|
131
135
|
});
|
|
132
136
|
Modal.success = (props) => modalStack.render({
|
|
133
|
-
|
|
137
|
+
status: "success",
|
|
134
138
|
...props
|
|
135
139
|
});
|
|
136
140
|
Modal.error = (props) => modalStack.render({
|
|
137
|
-
|
|
141
|
+
status: "error",
|
|
138
142
|
...props
|
|
139
143
|
});
|
|
140
144
|
Modal.warning = (props) => modalStack.render({
|
|
141
|
-
|
|
145
|
+
status: "warning",
|
|
142
146
|
...props
|
|
143
147
|
});
|
|
144
148
|
Modal.confirm = (props) => modalStack.render({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.mjs","names":["dialog"],"sources":["../../../src/components/organisms/modal.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport {\n Check,\n CircleQuestionMark,\n Info,\n OctagonAlert,\n OctagonX,\n} from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { dialog } from '../../core';\nimport Button from '../atoms/button';\nimport {\n type ImperativeStack,\n createImperativeStack,\n isBrowser,\n} from './imperative-stack';\n\nconst {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} = dialog;\n\nexport interface Props {\n open?: boolean;\n maskClosable?: boolean;\n closable?:\n | boolean\n | {\n closeIcon?: React.ReactNode;\n disabled?: boolean;\n };\n closeIcon?: React.ReactNode;\n title?: React.ReactNode;\n content?: React.ReactNode;\n footer?: React.ReactNode;\n className?: string;\n classNames?: {\n mask?: string;\n header?: string;\n body?: string;\n footer?: string;\n };\n style?: React.CSSProperties;\n okText?: string;\n cancelText?: string;\n container?: HTMLElement;\n children?: React.ReactNode;\n onOk?: () => void;\n onCancel?: () => void;\n}\n\ninterface StaticProps extends Props {\n type?: 'info' | 'success' | 'error' | 'warning' | 'confirm';\n id?: string;\n icon?: React.ReactNode;\n container?: HTMLElement;\n}\n\nconst Modal = ({\n open = false,\n maskClosable = false,\n closable = false,\n closeIcon,\n className,\n classNames,\n style,\n title,\n content,\n footer,\n container,\n children,\n okText,\n cancelText,\n onOk,\n onCancel,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n if (typeof window === 'undefined') {\n return null;\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open: boolean) => {\n if (!open) {\n onCancel?.();\n }\n }}\n {...props}\n >\n <DialogContent\n className={cn(\n 'rounded-lg p-4 max-sm:max-w-[80%]',\n 'border-none outline-none',\n className,\n )}\n classNames={{\n ...classNames,\n mask: cn('bg-black/60', classNames?.mask),\n }}\n style={style}\n closable={closable}\n closeIcon={closeIcon}\n container={container}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n >\n {/**\n * @todo [Dialog & AlertDialog] fix: can't get id correctly in shadow dom\n * @see https://github.com/radix-ui/primitives/pull/3384\n **/}\n <DialogHeader\n className={cn(\n classNames?.header,\n !title && 'hidden',\n //\n )}\n >\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription className=\"hidden\" />\n </DialogHeader>\n <div className={cn('break-all', classNames?.body)}>\n {children ?? content}\n </div>\n {footer !== null && (\n <DialogFooter\n className={cn('flex-row justify-end gap-x-2', classNames?.footer)}\n >\n {footer || (\n <>\n <Button onClick={onOk}>\n {okText ?? locale.ok ?? DEFAULT_LOCALE.ok}\n </Button>\n <Button variant=\"outlined\" onClick={onCancel}>\n {cancelText ?? locale.cancel ?? DEFAULT_LOCALE.cancel}\n </Button>\n </>\n )}\n </DialogFooter>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nconst STATIC_ICONS = {\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 confirm: <CircleQuestionMark />,\n};\n\nconst StaticModal = ({\n id,\n type,\n title,\n content,\n okText,\n cancelText,\n container,\n icon,\n onOk,\n onCancel,\n ...props\n}: StaticProps & { id: string }): React.ReactPortal | null => {\n const { locale } = useConfig();\n const [open, setOpen] = useState(true);\n const resolvedOkText = okText ?? locale.ok ?? DEFAULT_LOCALE.ok;\n const resolvedCancelText =\n cancelText ?? locale.cancel ?? DEFAULT_LOCALE.cancel;\n\n const closeModal = (callback?: () => void) => {\n callback?.();\n setOpen(false);\n setTimeout(() => {\n modalStack.destroy(id);\n }, 200);\n };\n\n const footer =\n type === 'confirm' ? (\n <div className=\"grid w-full grid-cols-5 gap-x-2\">\n <Button\n variant=\"outlined\"\n className=\"col-span-2\"\n onClick={() => closeModal(onCancel)}\n >\n {resolvedCancelText}\n </Button>\n <Button className=\"col-span-3\" onClick={() => closeModal(onOk)}>\n {resolvedOkText}\n </Button>\n </div>\n ) : (\n <Button\n className={cn(\n 'grow',\n //\n )}\n onClick={() => closeModal(onOk)}\n >\n {resolvedOkText}\n </Button>\n );\n\n if (!isBrowser) {\n return null;\n }\n\n return createPortal(\n <Modal\n open={open}\n footer={footer}\n className={cn(\n 'z-10000',\n 'box-content w-100',\n 'rounded-3xl p-4',\n 'gap-y-0',\n )}\n classNames={{\n mask: 'z-10000 bg-black/[.6]',\n body: cn(\n 'text-black-70 whitespace-pre-wrap text-center',\n content && 'mt-3',\n ),\n footer: 'mt-9',\n }}\n title={\n <p\n className={cn(\n 'text-center text-lg leading-normal whitespace-pre-wrap',\n 'flex items-center justify-center gap-x-2',\n //\n )}\n >\n {icon || (type && STATIC_ICONS[type])}\n {title}\n </p>\n }\n container={container}\n onCancel={() => closeModal(onCancel)}\n {...props}\n >\n {content}\n </Modal>,\n modalStack.getRootElement(container)!,\n );\n};\n\n// No `role`/`aria-modal` here — this element is only a mount point for the\n// imperative stack, not the dialog itself. Radix already renders its own\n// `role=\"dialog\"`/`aria-modal=\"true\"` on the actual `DialogContent` via\n// portal once a modal is open. Setting it here as well would (a) leave\n// `aria-modal=\"true\"` on the page permanently, even with zero modals open,\n// hiding the rest of the document from screen readers, and (b) duplicate\n// Radix's own dialog role once one is open.\nconst modalStack: ImperativeStack<StaticProps> =\n createImperativeStack<StaticProps>({\n createRootElement: () => {\n const el = document.createElement('div');\n el.style.zIndex = '10000';\n el.style.position = 'absolute';\n return el;\n },\n StackItem: StaticModal,\n });\n\nModal.destroy = modalStack.destroy;\n\nModal.destroyAll = () => {\n modalStack.destroy();\n};\n\nModal.info = (props: StaticProps) =>\n modalStack.render({ type: 'info', ...props });\nModal.success = (props: StaticProps) =>\n modalStack.render({ type: 'success', ...props });\nModal.error = (props: StaticProps) =>\n modalStack.render({ type: 'error', ...props });\nModal.warning = (props: StaticProps) =>\n modalStack.render({ type: 'warning', ...props });\nModal.confirm = (props: StaticProps) =>\n modalStack.render({ type: 'confirm', ...props });\n\nexport default Modal;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal.mjs","names":["dialog"],"sources":["../../../src/components/organisms/modal.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport {\n Check,\n CircleQuestionMark,\n Info,\n OctagonAlert,\n OctagonX,\n} from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { dialog } from '../../core';\nimport Button from '../atoms/button';\nimport {\n type ImperativeStack,\n createImperativeStack,\n isBrowser,\n} from './imperative-stack';\n\nconst {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} = dialog;\n\nexport interface Props {\n open?: boolean;\n maskClosable?: boolean;\n closable?:\n | boolean\n | {\n closeIcon?: React.ReactNode;\n disabled?: boolean;\n };\n closeIcon?: React.ReactNode;\n title?: React.ReactNode;\n content?: React.ReactNode;\n footer?: React.ReactNode;\n className?: string;\n classNames?: {\n mask?: string;\n header?: string;\n body?: string;\n footer?: string;\n };\n style?: React.CSSProperties;\n okText?: string;\n cancelText?: string;\n container?: HTMLElement;\n children?: React.ReactNode;\n onOk?: () => void;\n onCancel?: () => void;\n}\n\ntype ModalStatus = 'info' | 'success' | 'error' | 'warning';\n\ninterface StaticProps extends Props {\n status?: ModalStatus;\n /**\n * @deprecated Use `status` for the semantic state. Kept as an alias so\n * existing `type=\"info|success|error|warning\"` calls keep working. `confirm`\n * is an interaction mode, not a status — call `Modal.confirm()` instead\n * (still accepted here as `type=\"confirm\"` for back-compat).\n */\n type?: ModalStatus | 'confirm';\n id?: string;\n icon?: React.ReactNode;\n container?: HTMLElement;\n}\n\nconst Modal = ({\n open = false,\n maskClosable,\n closable = false,\n closeIcon,\n className,\n classNames,\n style,\n title,\n content,\n footer,\n container,\n children,\n okText,\n cancelText,\n onOk,\n onCancel,\n ...props\n}: Props) => {\n const { locale, defaultProps } = useConfig();\n const modalDefaults = defaultProps?.modal as\n Partial<Pick<Props, 'maskClosable'>> | undefined;\n // Explicit prop > `Config` default > built-in, matching Button/Tag.\n const resolvedMaskClosable =\n maskClosable ?? modalDefaults?.maskClosable ?? false;\n\n if (typeof window === 'undefined') {\n return null;\n }\n\n return (\n <Dialog\n open={open}\n onOpenChange={(open: boolean) => {\n if (!open) {\n onCancel?.();\n }\n }}\n {...props}\n >\n <DialogContent\n className={cn(\n 'rounded-lg p-4 max-sm:max-w-[80%]',\n 'border-none outline-none',\n className,\n )}\n classNames={{\n ...classNames,\n mask: cn('bg-black/60', classNames?.mask),\n }}\n style={style}\n closable={closable}\n closeIcon={closeIcon}\n container={container}\n onPointerDownOutside={event => {\n if (!resolvedMaskClosable) {\n event.preventDefault();\n }\n }}\n >\n {/**\n * @todo [Dialog & AlertDialog] fix: can't get id correctly in shadow dom\n * @see https://github.com/radix-ui/primitives/pull/3384\n **/}\n <DialogHeader\n className={cn(\n classNames?.header,\n !title && 'hidden',\n //\n )}\n >\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription className=\"hidden\" />\n </DialogHeader>\n <div className={cn('break-all', classNames?.body)}>\n {children ?? content}\n </div>\n {footer !== null && (\n <DialogFooter\n className={cn('flex-row justify-end gap-x-2', classNames?.footer)}\n >\n {footer || (\n <>\n <Button onClick={onOk}>\n {okText ?? locale.ok ?? DEFAULT_LOCALE.ok}\n </Button>\n <Button variant=\"outlined\" onClick={onCancel}>\n {cancelText ?? locale.cancel ?? DEFAULT_LOCALE.cancel}\n </Button>\n </>\n )}\n </DialogFooter>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nconst STATIC_ICONS = {\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 confirm: <CircleQuestionMark />,\n};\n\nconst StaticModal = ({\n id,\n status,\n type,\n title,\n content,\n okText,\n cancelText,\n container,\n icon,\n onOk,\n onCancel,\n ...props\n}: StaticProps & { id: string }): React.ReactPortal | null => {\n const { locale } = useConfig();\n const [open, setOpen] = useState(true);\n const resolvedOkText = okText ?? locale.ok ?? DEFAULT_LOCALE.ok;\n const resolvedCancelText =\n cancelText ?? locale.cancel ?? DEFAULT_LOCALE.cancel;\n // `confirm` is an interaction mode (two-button footer), not a status. The\n // semantic state comes from `status`, with `type` as its deprecated alias.\n const isConfirm = type === 'confirm';\n const resolvedStatus = status ?? (isConfirm ? undefined : type);\n\n const closeModal = (callback?: () => void) => {\n callback?.();\n setOpen(false);\n setTimeout(() => {\n modalStack.destroy(id);\n }, 200);\n };\n\n const footer = isConfirm ? (\n <div className=\"grid w-full grid-cols-5 gap-x-2\">\n <Button\n variant=\"outlined\"\n className=\"col-span-2\"\n onClick={() => closeModal(onCancel)}\n >\n {resolvedCancelText}\n </Button>\n <Button className=\"col-span-3\" onClick={() => closeModal(onOk)}>\n {resolvedOkText}\n </Button>\n </div>\n ) : (\n <Button\n className={cn(\n 'grow',\n //\n )}\n onClick={() => closeModal(onOk)}\n >\n {resolvedOkText}\n </Button>\n );\n\n if (!isBrowser) {\n return null;\n }\n\n return createPortal(\n <Modal\n open={open}\n footer={footer}\n className={cn(\n 'z-10000',\n 'box-content w-100',\n 'rounded-3xl p-4',\n 'gap-y-0',\n )}\n classNames={{\n mask: 'z-10000 bg-black/[.6]',\n body: cn(\n 'text-black-70 whitespace-pre-wrap text-center',\n content && 'mt-3',\n ),\n footer: 'mt-9',\n }}\n title={\n <p\n className={cn(\n 'text-center text-lg leading-normal whitespace-pre-wrap',\n 'flex items-center justify-center gap-x-2',\n //\n )}\n >\n {icon ||\n (isConfirm\n ? STATIC_ICONS.confirm\n : resolvedStatus && STATIC_ICONS[resolvedStatus])}\n {title}\n </p>\n }\n container={container}\n onCancel={() => closeModal(onCancel)}\n {...props}\n >\n {content}\n </Modal>,\n modalStack.getRootElement(container)!,\n );\n};\n\n// No `role`/`aria-modal` here — this element is only a mount point for the\n// imperative stack, not the dialog itself. Radix already renders its own\n// `role=\"dialog\"`/`aria-modal=\"true\"` on the actual `DialogContent` via\n// portal once a modal is open. Setting it here as well would (a) leave\n// `aria-modal=\"true\"` on the page permanently, even with zero modals open,\n// hiding the rest of the document from screen readers, and (b) duplicate\n// Radix's own dialog role once one is open.\nconst modalStack: ImperativeStack<StaticProps> =\n createImperativeStack<StaticProps>({\n createRootElement: () => {\n const el = document.createElement('div');\n el.style.zIndex = '10000';\n el.style.position = 'absolute';\n return el;\n },\n StackItem: StaticModal,\n });\n\nModal.destroy = modalStack.destroy;\n\nModal.destroyAll = () => {\n modalStack.destroy();\n};\n\nModal.info = (props: StaticProps) =>\n modalStack.render({ status: 'info', ...props });\nModal.success = (props: StaticProps) =>\n modalStack.render({ status: 'success', ...props });\nModal.error = (props: StaticProps) =>\n modalStack.render({ status: 'error', ...props });\nModal.warning = (props: StaticProps) =>\n modalStack.render({ status: 'warning', ...props });\n// `confirm` is a mode, not a status, so it rides the `type` axis (the only\n// place it lives) rather than `status`.\nModal.confirm = (props: StaticProps) =>\n modalStack.render({ type: 'confirm', ...props });\n\nexport default Modal;\n"],"mappings":"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"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
//#region src/components/organisms/toast.d.ts
|
|
2
|
-
type
|
|
2
|
+
type ToastStatus = 'info' | 'success' | 'error' | 'warning';
|
|
3
3
|
interface Props {
|
|
4
|
-
|
|
4
|
+
status?: ToastStatus;
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated Use `status`. Kept as an alias so existing
|
|
7
|
+
* `type="info|success|error|warning"` usage keeps working; `status` matches
|
|
8
|
+
* the shared semantic-state vocabulary used by `Result`.
|
|
9
|
+
*/
|
|
10
|
+
type?: ToastStatus;
|
|
5
11
|
title: React.ReactNode;
|
|
6
12
|
description?: React.ReactNode;
|
|
7
13
|
icon?: React.ReactNode;
|
|
@@ -16,7 +22,7 @@ interface StaticProps extends Props {
|
|
|
16
22
|
container?: HTMLElement;
|
|
17
23
|
}
|
|
18
24
|
declare const Toast: {
|
|
19
|
-
({ type, title, description, icon, closable, action, className, onClose }: Props): import("react").JSX.Element;
|
|
25
|
+
({ status, type, title, description, icon, closable, action, className, onClose }: Props): import("react").JSX.Element;
|
|
20
26
|
destroy: (id?: string) => void;
|
|
21
27
|
destroyAll(): void;
|
|
22
28
|
info(title: React.ReactNode, props?: TriggerOptions): string | undefined;
|
|
@@ -24,7 +30,7 @@ declare const Toast: {
|
|
|
24
30
|
error(title: React.ReactNode, props?: TriggerOptions): string | undefined;
|
|
25
31
|
warning(title: React.ReactNode, props?: TriggerOptions): string | undefined;
|
|
26
32
|
};
|
|
27
|
-
type TriggerOptions = Omit<StaticProps, 'type' | 'title'>;
|
|
33
|
+
type TriggerOptions = Omit<StaticProps, 'status' | 'type' | 'title'>;
|
|
28
34
|
//#endregion
|
|
29
35
|
export { Props, type StaticProps as ToastOptions, Toast as default };
|
|
30
36
|
//# sourceMappingURL=toast.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.d.mts","names":[],"sources":["../../../src/components/organisms/toast.tsx"],"mappings":";KAkBK;UAEY;EACf,OAAO;EACP,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,OAAO,MAAM;EACb;EACA,SAAS,MAAM;EACf;EACA;;UAGQ,oBAAoB;EAC5B;EACA;EACA,YAAY;;cAUR;
|
|
1
|
+
{"version":3,"file":"toast.d.mts","names":[],"sources":["../../../src/components/organisms/toast.tsx"],"mappings":";KAkBK;UAEY;EACf,SAAS;;;;;;EAMT,OAAO;EACP,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,OAAO,MAAM;EACb;EACA,SAAS,MAAM;EACf;EACA;;UAGQ,oBAAoB;EAC5B;EACA;EACA,YAAY;;cAUR;KAUH,QAAA,MAAA,OAAA,aAAA,MAAA,UAAA,QAAA,WAAA,WAAA,wBAAK,IAAA;;;EAsHa,KAAA,OAAA,MAAM,WAAS,QAAU;EAEtB,QAAA,OAAA,MAAM,WAAS,QAAU;EAE3B,MAAA,OAAA,MAAM,WAAS,QAAU;EAEvB,QAAA,OAAA,MAAM,WAAS,QAAU;;KAR5C,iBAAiB,KAAK"}
|
|
@@ -9,21 +9,22 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
import { useTimeout } from "@jbpark/use-hooks";
|
|
10
10
|
import { createPortal } from "react-dom";
|
|
11
11
|
//#region src/components/organisms/toast.tsx
|
|
12
|
-
const
|
|
12
|
+
const STATUS_ICONS = {
|
|
13
13
|
info: /* @__PURE__ */ jsx(Info, { className: "text-blue-400" }),
|
|
14
14
|
success: /* @__PURE__ */ jsx(Check, { className: "text-green-400" }),
|
|
15
15
|
error: /* @__PURE__ */ jsx(OctagonX, { className: "text-red-400" }),
|
|
16
16
|
warning: /* @__PURE__ */ jsx(OctagonAlert, { className: "text-yellow-400" })
|
|
17
17
|
};
|
|
18
|
-
const Toast = ({ type, title, description, icon, closable = true, action, className, onClose }) => {
|
|
18
|
+
const Toast = ({ status, type, title, description, icon, closable = true, action, className, onClose }) => {
|
|
19
19
|
const { locale } = useConfig();
|
|
20
|
+
const resolvedStatus = status ?? type;
|
|
20
21
|
return /* @__PURE__ */ jsxs("div", {
|
|
21
|
-
role:
|
|
22
|
+
role: resolvedStatus === "error" ? "alert" : "status",
|
|
22
23
|
className: cn("pointer-events-auto flex w-80 items-start gap-3 rounded-lg", "bg-background text-foreground border p-4 shadow-lg", className),
|
|
23
24
|
children: [
|
|
24
|
-
(icon ||
|
|
25
|
+
(icon || resolvedStatus) && /* @__PURE__ */ jsx("div", {
|
|
25
26
|
className: "mt-0.5 shrink-0 [&_svg]:size-5",
|
|
26
|
-
children: icon ||
|
|
27
|
+
children: icon || resolvedStatus && STATUS_ICONS[resolvedStatus]
|
|
27
28
|
}),
|
|
28
29
|
/* @__PURE__ */ jsxs("div", {
|
|
29
30
|
className: "flex-1 space-y-1",
|
|
@@ -100,22 +101,22 @@ Toast.destroyAll = () => {
|
|
|
100
101
|
toastStack.destroy();
|
|
101
102
|
};
|
|
102
103
|
Toast.info = (title, props) => toastStack.render({
|
|
103
|
-
|
|
104
|
+
status: "info",
|
|
104
105
|
title,
|
|
105
106
|
...props
|
|
106
107
|
});
|
|
107
108
|
Toast.success = (title, props) => toastStack.render({
|
|
108
|
-
|
|
109
|
+
status: "success",
|
|
109
110
|
title,
|
|
110
111
|
...props
|
|
111
112
|
});
|
|
112
113
|
Toast.error = (title, props) => toastStack.render({
|
|
113
|
-
|
|
114
|
+
status: "error",
|
|
114
115
|
title,
|
|
115
116
|
...props
|
|
116
117
|
});
|
|
117
118
|
Toast.warning = (title, props) => toastStack.render({
|
|
118
|
-
|
|
119
|
+
status: "warning",
|
|
119
120
|
title,
|
|
120
121
|
...props
|
|
121
122
|
});
|
|
@@ -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
|
|
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 ToastStatus = 'info' | 'success' | 'error' | 'warning';\n\nexport interface Props {\n status?: ToastStatus;\n /**\n * @deprecated Use `status`. Kept as an alias so existing\n * `type=\"info|success|error|warning\"` usage keeps working; `status` matches\n * the shared semantic-state vocabulary used by `Result`.\n */\n type?: ToastStatus;\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 STATUS_ICONS: Record<ToastStatus, 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 status,\n type,\n title,\n description,\n icon,\n closable = true,\n action,\n className,\n onClose,\n}: Props) => {\n const { locale } = useConfig();\n // `type` is the deprecated alias for `status`; prefer `status` when both set.\n const resolvedStatus = status ?? type;\n\n return (\n <div\n role={resolvedStatus === '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 || resolvedStatus) && (\n <div className=\"mt-0.5 shrink-0 [&_svg]:size-5\">\n {icon || (resolvedStatus && STATUS_ICONS[resolvedStatus])}\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, 'status' | 'type' | 'title'>;\n\nToast.info = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ status: 'info', title, ...props });\nToast.success = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ status: 'success', title, ...props });\nToast.error = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ status: 'error', title, ...props });\nToast.warning = (title: React.ReactNode, props?: TriggerOptions) =>\n toastStack.render({ status: 'warning', title, ...props });\n\nexport default Toast;\nexport type { StaticProps as ToastOptions };\n"],"mappings":"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"}
|
package/dist/core/index.d.mts
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.mjs";
|
|
3
|
+
import { cn } from "../utils.mjs";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
7
|
+
//#region src/core/slider.tsx
|
|
8
|
+
var slider_exports = /* @__PURE__ */ __exportAll({ Slider: () => Slider });
|
|
9
|
+
function Slider({ className, defaultValue, value, min = 0, max = 100, ...props }) {
|
|
10
|
+
const thumbs = React$1.useMemo(() => {
|
|
11
|
+
if (Array.isArray(value)) return value;
|
|
12
|
+
if (Array.isArray(defaultValue)) return defaultValue;
|
|
13
|
+
return [min, max];
|
|
14
|
+
}, [
|
|
15
|
+
value,
|
|
16
|
+
defaultValue,
|
|
17
|
+
min,
|
|
18
|
+
max
|
|
19
|
+
]);
|
|
20
|
+
return /* @__PURE__ */ jsxs(SliderPrimitive.Root, {
|
|
21
|
+
"data-slot": "slider",
|
|
22
|
+
defaultValue,
|
|
23
|
+
value,
|
|
24
|
+
min,
|
|
25
|
+
max,
|
|
26
|
+
className: cn(`relative flex w-full touch-none items-center select-none
|
|
27
|
+
data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50
|
|
28
|
+
data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44
|
|
29
|
+
data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col`, className),
|
|
30
|
+
...props,
|
|
31
|
+
children: [/* @__PURE__ */ jsx(SliderPrimitive.Track, {
|
|
32
|
+
"data-slot": "slider-track",
|
|
33
|
+
className: cn(`bg-input relative grow overflow-hidden rounded-full
|
|
34
|
+
data-[orientation=horizontal]:h-1.5
|
|
35
|
+
data-[orientation=horizontal]:w-full
|
|
36
|
+
data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5`),
|
|
37
|
+
children: /* @__PURE__ */ jsx(SliderPrimitive.Range, {
|
|
38
|
+
"data-slot": "slider-range",
|
|
39
|
+
className: cn(`bg-primary absolute data-[orientation=horizontal]:h-full
|
|
40
|
+
data-[orientation=vertical]:w-full`)
|
|
41
|
+
})
|
|
42
|
+
}), Array.from({ length: thumbs.length }, (_, index) => /* @__PURE__ */ jsx(SliderPrimitive.Thumb, {
|
|
43
|
+
"data-slot": "slider-thumb",
|
|
44
|
+
className: cn(`border-primary bg-background ring-ring/50 block size-4 shrink-0
|
|
45
|
+
rounded-full border shadow-sm transition-[color,box-shadow]
|
|
46
|
+
hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden
|
|
47
|
+
disabled:pointer-events-none disabled:opacity-50`)
|
|
48
|
+
}, index))]
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Slider, slider_exports };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=slider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slider.mjs","names":["React"],"sources":["../../src/core/slider.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nimport * as SliderPrimitive from '@radix-ui/react-slider';\n\nimport { cn } from '@repo/ui/utils';\n\nfunction Slider({\n className,\n defaultValue,\n value,\n min = 0,\n max = 100,\n ...props\n}: React.ComponentProps<typeof SliderPrimitive.Root>) {\n const thumbs = React.useMemo(() => {\n if (Array.isArray(value)) {\n return value;\n }\n if (Array.isArray(defaultValue)) {\n return defaultValue;\n }\n return [min, max];\n }, [value, defaultValue, min, max]);\n\n return (\n <SliderPrimitive.Root\n data-slot=\"slider\"\n defaultValue={defaultValue}\n value={value}\n min={min}\n max={max}\n className={cn(\n `relative flex w-full touch-none items-center select-none\n data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\n data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44\n data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col`,\n className,\n )}\n {...props}\n >\n <SliderPrimitive.Track\n data-slot=\"slider-track\"\n className={cn(\n `bg-input relative grow overflow-hidden rounded-full\n data-[orientation=horizontal]:h-1.5\n data-[orientation=horizontal]:w-full\n data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5`,\n )}\n >\n <SliderPrimitive.Range\n data-slot=\"slider-range\"\n className={cn(\n `bg-primary absolute data-[orientation=horizontal]:h-full\n data-[orientation=vertical]:w-full`,\n )}\n />\n </SliderPrimitive.Track>\n {Array.from({ length: thumbs.length }, (_, index) => (\n <SliderPrimitive.Thumb\n data-slot=\"slider-thumb\"\n key={index}\n className={cn(\n `border-primary bg-background ring-ring/50 block size-4 shrink-0\n rounded-full border shadow-sm transition-[color,box-shadow]\n hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden\n disabled:pointer-events-none disabled:opacity-50`,\n )}\n />\n ))}\n </SliderPrimitive.Root>\n );\n}\n\nexport { Slider };\n"],"mappings":";;;;;;;;AAQA,SAAS,OAAO,EACd,WACA,cACA,OACA,MAAM,GACN,MAAM,KACN,GAAG,SACiD;CACpD,MAAM,SAASA,QAAM,cAAc;EACjC,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO;EAET,IAAI,MAAM,QAAQ,YAAY,GAC5B,OAAO;EAET,OAAO,CAAC,KAAK,GAAG;CAClB,GAAG;EAAC;EAAO;EAAc;EAAK;CAAG,CAAC;CAElC,OACE,qBAAC,gBAAgB,MAAjB;EACE,aAAU;EACI;EACP;EACF;EACA;EACL,WAAW,GACT;;;kFAIA,SACF;EACA,GAAI;EAbN,UAAA,CAeE,oBAAC,gBAAgB,OAAjB;GACE,aAAU;GACV,WAAW,GACT;;;+EAIF;GAEA,UAAA,oBAAC,gBAAgB,OAAjB;IACE,aAAU;IACV,WAAW,GACT;+CAEF;GACD,CAAA;EACoB,CAAA,GACtB,MAAM,KAAK,EAAE,QAAQ,OAAO,OAAO,IAAI,GAAG,UACzC,oBAAC,gBAAgB,OAAjB;GACE,aAAU;GAEV,WAAW,GACT;;;6DAIF;EACD,GAPM,KAON,CACF,CACmB;;AAE1B"}
|
package/dist/index.d.mts
CHANGED
|
@@ -22,6 +22,7 @@ import Progress from "./components/atoms/progress.mjs";
|
|
|
22
22
|
import Radio from "./components/atoms/radio/index.mjs";
|
|
23
23
|
import Select from "./components/atoms/select.mjs";
|
|
24
24
|
import Skeleton from "./components/atoms/skeleton/index.mjs";
|
|
25
|
+
import Slider from "./components/atoms/slider/slider.mjs";
|
|
25
26
|
import Spin from "./components/atoms/spin.mjs";
|
|
26
27
|
import Switch from "./components/atoms/switch.mjs";
|
|
27
28
|
import "./components/atoms/index.mjs";
|
|
@@ -51,4 +52,4 @@ import { ComponentSize, DefaultProps, Locale, ThemeConfig, ThemeToken } from "./
|
|
|
51
52
|
import { DEFAULT_LOCALE, useConfig } from "./providers/config/context.mjs";
|
|
52
53
|
import Config, { Props as Props$3 } from "./providers/config/config.mjs";
|
|
53
54
|
import { ConfigSnapshotProvider, getRootConfigValue } from "./providers/config/registry.mjs";
|
|
54
|
-
export { Button, Card, type Props as CardProps, Checkbox, Col, type Props$1 as ColProps, Collapse, type Props$2 as CollapseProps, ColorPicker, type ComponentSize, Config, type Props$3 as ConfigProps, ConfigSnapshotProvider, Container, type Props$4 as ContainerProps, type Props$5 as ContentProps, DEFAULT_LOCALE, DatePicker, type DefaultProps, Drawer, type Props$6 as DrawerProps, Dropdown, type Props$7 as DropdownProps, Empty, type Props$8 as EmptyProps, FloatButton, type Props$9 as FooterProps, type Props$10 as HeaderProps, Input, Layout, type Props$11 as LayoutProps, List, type Props$12 as ListProps, type Locale, Marquees, type Props$13 as MarqueesProps, Menu, type Props$14 as MenuProps, Modal, type Props$15 as ModalProps, PageHeader, type Props$16 as PageHeaderProps, Popover, Progress, Radio, Result, type Props$17 as ResultProps, Reveals, type Props$18 as RevealsProps, Row, type Props$19 as RowProps, Select, type Props$20 as SiderProps, Skeleton, Space, type Props$21 as SpaceProps, Spin, Splitter, type Props$22 as SplitterProps, Swiper, type Props$23 as SwiperProps, Switch, Tag, type ThemeConfig, type ThemeToken, Toast, type StaticProps as ToastOptions, Typography, Upload, type UploadFile, type Props$24 as UploadProps, getRootConfigValue, useConfig };
|
|
55
|
+
export { Button, Card, type Props as CardProps, Checkbox, Col, type Props$1 as ColProps, Collapse, type Props$2 as CollapseProps, ColorPicker, type ComponentSize, Config, type Props$3 as ConfigProps, ConfigSnapshotProvider, Container, type Props$4 as ContainerProps, type Props$5 as ContentProps, DEFAULT_LOCALE, DatePicker, type DefaultProps, Drawer, type Props$6 as DrawerProps, Dropdown, type Props$7 as DropdownProps, Empty, type Props$8 as EmptyProps, FloatButton, type Props$9 as FooterProps, type Props$10 as HeaderProps, Input, Layout, type Props$11 as LayoutProps, List, type Props$12 as ListProps, type Locale, Marquees, type Props$13 as MarqueesProps, Menu, type Props$14 as MenuProps, Modal, type Props$15 as ModalProps, PageHeader, type Props$16 as PageHeaderProps, Popover, Progress, Radio, Result, type Props$17 as ResultProps, Reveals, type Props$18 as RevealsProps, Row, type Props$19 as RowProps, Select, type Props$20 as SiderProps, Skeleton, Slider, Space, type Props$21 as SpaceProps, Spin, Splitter, type Props$22 as SplitterProps, Swiper, type Props$23 as SwiperProps, Switch, Tag, type ThemeConfig, type ThemeToken, Toast, type StaticProps as ToastOptions, Typography, Upload, type UploadFile, type Props$24 as UploadProps, getRootConfigValue, useConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import Progress from "./components/atoms/progress.mjs";
|
|
|
14
14
|
import Radio from "./components/atoms/radio/index.mjs";
|
|
15
15
|
import Select from "./components/atoms/select.mjs";
|
|
16
16
|
import Skeleton from "./components/atoms/skeleton/index.mjs";
|
|
17
|
+
import slider_default from "./components/atoms/slider/index.mjs";
|
|
17
18
|
import Spin from "./components/atoms/spin.mjs";
|
|
18
19
|
import Switch from "./components/atoms/switch.mjs";
|
|
19
20
|
import Tag from "./Tag.mjs";
|
|
@@ -38,4 +39,4 @@ import Result from "./components/templates/result.mjs";
|
|
|
38
39
|
import PageHeader from "./components/templates/page-header.mjs";
|
|
39
40
|
import Row from "./components/templates/grid/row.mjs";
|
|
40
41
|
import Col from "./components/templates/grid/col.mjs";
|
|
41
|
-
export { Button, Card, Checkbox, Col, Collapse, ColorPicker, Config, ConfigSnapshotProvider, Container, DEFAULT_LOCALE, DatePicker, Drawer, Dropdown, Empty, FloatButton, Input, Layout, List, Marquees, Menu, Modal, PageHeader, Popover, Progress, Radio, Result, Reveals, Row, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, Toast, Typography, Upload, getRootConfigValue, useConfig };
|
|
42
|
+
export { Button, Card, Checkbox, Col, Collapse, ColorPicker, Config, ConfigSnapshotProvider, Container, DEFAULT_LOCALE, DatePicker, Drawer, Dropdown, Empty, FloatButton, Input, Layout, List, Marquees, Menu, Modal, PageHeader, Popover, Progress, Radio, Result, Reveals, Row, Select, Skeleton, slider_default as Slider, Space, Spin, Splitter, Swiper, Switch, Tag, Toast, Typography, Upload, getRootConfigValue, useConfig };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/lib/colors.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The shared preset colour palette. `Button` and `Tag` both express these via
|
|
4
|
+
* the `--btn-*` / `--tag-*` custom-property systems in `globals.css` (keyed off
|
|
5
|
+
* `data-color`), so the same word means the same hue on either component
|
|
6
|
+
* (#320). Keep this list in sync with the `[data-color='…']` rules there.
|
|
7
|
+
*/
|
|
8
|
+
declare const PRESET_COLORS: readonly ["blue", "purple", "cyan", "green", "magenta", "pink", "red", "orange", "yellow", "volcano", "geekblue", "lime", "gold"];
|
|
9
|
+
type PresetColor = (typeof PRESET_COLORS)[number];
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PRESET_COLORS, PresetColor };
|
|
12
|
+
//# sourceMappingURL=colors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.d.mts","names":[],"sources":["../../src/lib/colors.ts"],"mappings":";;;;;;;cAMa;KAgBD,sBAAsB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/lib/colors.ts
|
|
2
|
+
/**
|
|
3
|
+
* The shared preset colour palette. `Button` and `Tag` both express these via
|
|
4
|
+
* the `--btn-*` / `--tag-*` custom-property systems in `globals.css` (keyed off
|
|
5
|
+
* `data-color`), so the same word means the same hue on either component
|
|
6
|
+
* (#320). Keep this list in sync with the `[data-color='…']` rules there.
|
|
7
|
+
*/
|
|
8
|
+
const PRESET_COLORS = [
|
|
9
|
+
"blue",
|
|
10
|
+
"purple",
|
|
11
|
+
"cyan",
|
|
12
|
+
"green",
|
|
13
|
+
"magenta",
|
|
14
|
+
"pink",
|
|
15
|
+
"red",
|
|
16
|
+
"orange",
|
|
17
|
+
"yellow",
|
|
18
|
+
"volcano",
|
|
19
|
+
"geekblue",
|
|
20
|
+
"lime",
|
|
21
|
+
"gold"
|
|
22
|
+
];
|
|
23
|
+
/** Runtime membership test — true when `color` is one of the shared presets. */
|
|
24
|
+
const isPresetColor = (color) => PRESET_COLORS.includes(color);
|
|
25
|
+
//#endregion
|
|
26
|
+
export { PRESET_COLORS, isPresetColor };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=colors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.mjs","names":[],"sources":["../../src/lib/colors.ts"],"sourcesContent":["/**\n * The shared preset colour palette. `Button` and `Tag` both express these via\n * the `--btn-*` / `--tag-*` custom-property systems in `globals.css` (keyed off\n * `data-color`), so the same word means the same hue on either component\n * (#320). Keep this list in sync with the `[data-color='…']` rules there.\n */\nexport const PRESET_COLORS = [\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] as const;\n\nexport type PresetColor = (typeof PRESET_COLORS)[number];\n\n/** Runtime membership test — true when `color` is one of the shared presets. */\nexport const isPresetColor = (color: string): color is PresetColor =>\n (PRESET_COLORS as readonly string[]).includes(color);\n"],"mappings":";;;;;;;AAMA,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAKA,MAAa,iBAAiB,UAC3B,cAAoC,SAAS,KAAK"}
|
package/dist/style.css
CHANGED
|
@@ -149,6 +149,45 @@
|
|
|
149
149
|
[data-slot="button"][data-color="gold"] {
|
|
150
150
|
--btn-bg: #f59e0b;
|
|
151
151
|
}
|
|
152
|
+
[data-slot="badge"][data-color="blue"] {
|
|
153
|
+
--tag-bg: #3b82f6;
|
|
154
|
+
}
|
|
155
|
+
[data-slot="badge"][data-color="purple"] {
|
|
156
|
+
--tag-bg: #a855f7;
|
|
157
|
+
}
|
|
158
|
+
[data-slot="badge"][data-color="cyan"] {
|
|
159
|
+
--tag-bg: #06b6d4;
|
|
160
|
+
}
|
|
161
|
+
[data-slot="badge"][data-color="green"] {
|
|
162
|
+
--tag-bg: #22c55e;
|
|
163
|
+
}
|
|
164
|
+
[data-slot="badge"][data-color="magenta"] {
|
|
165
|
+
--tag-bg: #d946ef;
|
|
166
|
+
}
|
|
167
|
+
[data-slot="badge"][data-color="pink"] {
|
|
168
|
+
--tag-bg: #ec4899;
|
|
169
|
+
}
|
|
170
|
+
[data-slot="badge"][data-color="red"] {
|
|
171
|
+
--tag-bg: #ef4444;
|
|
172
|
+
}
|
|
173
|
+
[data-slot="badge"][data-color="orange"] {
|
|
174
|
+
--tag-bg: #f97316;
|
|
175
|
+
}
|
|
176
|
+
[data-slot="badge"][data-color="yellow"] {
|
|
177
|
+
--tag-bg: #eab308;
|
|
178
|
+
}
|
|
179
|
+
[data-slot="badge"][data-color="volcano"] {
|
|
180
|
+
--tag-bg: #ea580c;
|
|
181
|
+
}
|
|
182
|
+
[data-slot="badge"][data-color="geekblue"] {
|
|
183
|
+
--tag-bg: #6366f1;
|
|
184
|
+
}
|
|
185
|
+
[data-slot="badge"][data-color="lime"] {
|
|
186
|
+
--tag-bg: #84cc16;
|
|
187
|
+
}
|
|
188
|
+
[data-slot="badge"][data-color="gold"] {
|
|
189
|
+
--tag-bg: #f59e0b;
|
|
190
|
+
}
|
|
152
191
|
[data-slot="col"] {
|
|
153
192
|
flex-basis: calc(var(--col-span-xs) / 24 * 100%);
|
|
154
193
|
max-width: calc(var(--col-span-xs) / 24 * 100%);
|
|
@@ -786,6 +825,9 @@
|
|
|
786
825
|
.cursor-pointer {
|
|
787
826
|
cursor: pointer;
|
|
788
827
|
}
|
|
828
|
+
.touch-none {
|
|
829
|
+
touch-action: none;
|
|
830
|
+
}
|
|
789
831
|
.resize {
|
|
790
832
|
resize: both;
|
|
791
833
|
}
|
|
@@ -1033,6 +1075,9 @@
|
|
|
1033
1075
|
.border-\(--btn-border\) {
|
|
1034
1076
|
border-color: var(--btn-border);
|
|
1035
1077
|
}
|
|
1078
|
+
.border-\(--tag-bg\) {
|
|
1079
|
+
border-color: var(--tag-bg);
|
|
1080
|
+
}
|
|
1036
1081
|
.border-\[color-mix\(in_oklch\,var\(--btn-border\)\,transparent_50\%\)\] {
|
|
1037
1082
|
border-color: var(--btn-border);
|
|
1038
1083
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -1072,6 +1117,12 @@
|
|
|
1072
1117
|
.bg-\(--btn-bg\) {
|
|
1073
1118
|
background-color: var(--btn-bg);
|
|
1074
1119
|
}
|
|
1120
|
+
.bg-\[color-mix\(in_oklch\,var\(--tag-bg\)\,transparent_90\%\)\] {
|
|
1121
|
+
background-color: var(--tag-bg);
|
|
1122
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1123
|
+
background-color: color-mix(in oklch,var(--tag-bg),transparent 90%);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1075
1126
|
.bg-accent {
|
|
1076
1127
|
background-color: var(--accent);
|
|
1077
1128
|
}
|
|
@@ -1120,6 +1171,9 @@
|
|
|
1120
1171
|
.bg-inherit {
|
|
1121
1172
|
background-color: inherit;
|
|
1122
1173
|
}
|
|
1174
|
+
.bg-input {
|
|
1175
|
+
background-color: var(--input);
|
|
1176
|
+
}
|
|
1123
1177
|
.bg-muted {
|
|
1124
1178
|
background-color: var(--muted);
|
|
1125
1179
|
}
|
|
@@ -1361,6 +1415,9 @@
|
|
|
1361
1415
|
.text-\(--btn-fg\) {
|
|
1362
1416
|
color: var(--btn-fg);
|
|
1363
1417
|
}
|
|
1418
|
+
.text-\(--tag-bg\) {
|
|
1419
|
+
color: var(--tag-bg);
|
|
1420
|
+
}
|
|
1364
1421
|
.text-accent-foreground {
|
|
1365
1422
|
color: var(--accent-foreground);
|
|
1366
1423
|
}
|
|
@@ -1467,6 +1524,12 @@
|
|
|
1467
1524
|
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
1468
1525
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
1469
1526
|
}
|
|
1527
|
+
.ring-ring\/50 {
|
|
1528
|
+
--tw-ring-color: var(--ring);
|
|
1529
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1530
|
+
--tw-ring-color: color-mix(in oklab, var(--ring) 50%, transparent);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1470
1533
|
.ring-offset-background {
|
|
1471
1534
|
--tw-ring-offset-color: var(--background);
|
|
1472
1535
|
}
|
|
@@ -1979,6 +2042,10 @@
|
|
|
1979
2042
|
.hover\:opacity-100:hover {
|
|
1980
2043
|
opacity: 100%;
|
|
1981
2044
|
}
|
|
2045
|
+
.hover\:ring-4:hover {
|
|
2046
|
+
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
2047
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2048
|
+
}
|
|
1982
2049
|
}
|
|
1983
2050
|
.focus\:bg-accent:focus {
|
|
1984
2051
|
background-color: var(--accent);
|
|
@@ -2012,6 +2079,10 @@
|
|
|
2012
2079
|
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
2013
2080
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2014
2081
|
}
|
|
2082
|
+
.focus-visible\:ring-4:focus-visible {
|
|
2083
|
+
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
2084
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
2085
|
+
}
|
|
2015
2086
|
.focus-visible\:ring-\[3px\]:focus-visible {
|
|
2016
2087
|
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
2017
2088
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
@@ -2163,6 +2234,9 @@
|
|
|
2163
2234
|
.data-\[disabled\]\:pointer-events-none[data-disabled] {
|
|
2164
2235
|
pointer-events: none;
|
|
2165
2236
|
}
|
|
2237
|
+
.data-\[disabled\]\:cursor-not-allowed[data-disabled] {
|
|
2238
|
+
cursor: not-allowed;
|
|
2239
|
+
}
|
|
2166
2240
|
.data-\[disabled\]\:opacity-50[data-disabled] {
|
|
2167
2241
|
opacity: 50%;
|
|
2168
2242
|
}
|
|
@@ -2172,6 +2246,12 @@
|
|
|
2172
2246
|
.data-\[invalid\=true\]\:text-destructive[data-invalid="true"] {
|
|
2173
2247
|
color: var(--destructive);
|
|
2174
2248
|
}
|
|
2249
|
+
.data-\[orientation\=horizontal\]\:h-1\.5[data-orientation="horizontal"] {
|
|
2250
|
+
height: calc(var(--spacing) * 1.5);
|
|
2251
|
+
}
|
|
2252
|
+
.data-\[orientation\=horizontal\]\:h-full[data-orientation="horizontal"] {
|
|
2253
|
+
height: 100%;
|
|
2254
|
+
}
|
|
2175
2255
|
.data-\[orientation\=horizontal\]\:h-px[data-orientation="horizontal"] {
|
|
2176
2256
|
height: 1px;
|
|
2177
2257
|
}
|
|
@@ -2181,9 +2261,24 @@
|
|
|
2181
2261
|
.data-\[orientation\=vertical\]\:h-full[data-orientation="vertical"] {
|
|
2182
2262
|
height: 100%;
|
|
2183
2263
|
}
|
|
2264
|
+
.data-\[orientation\=vertical\]\:min-h-44[data-orientation="vertical"] {
|
|
2265
|
+
min-height: calc(var(--spacing) * 44);
|
|
2266
|
+
}
|
|
2267
|
+
.data-\[orientation\=vertical\]\:w-1\.5[data-orientation="vertical"] {
|
|
2268
|
+
width: calc(var(--spacing) * 1.5);
|
|
2269
|
+
}
|
|
2270
|
+
.data-\[orientation\=vertical\]\:w-auto[data-orientation="vertical"] {
|
|
2271
|
+
width: auto;
|
|
2272
|
+
}
|
|
2273
|
+
.data-\[orientation\=vertical\]\:w-full[data-orientation="vertical"] {
|
|
2274
|
+
width: 100%;
|
|
2275
|
+
}
|
|
2184
2276
|
.data-\[orientation\=vertical\]\:w-px[data-orientation="vertical"] {
|
|
2185
2277
|
width: 1px;
|
|
2186
2278
|
}
|
|
2279
|
+
.data-\[orientation\=vertical\]\:flex-col[data-orientation="vertical"] {
|
|
2280
|
+
flex-direction: column;
|
|
2281
|
+
}
|
|
2187
2282
|
.data-\[placeholder\]\:text-muted-foreground[data-placeholder] {
|
|
2188
2283
|
color: var(--muted-foreground);
|
|
2189
2284
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbpark/ui-kit",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Modern React UI component library built with TypeScript, Tailwind CSS, and Radix UI. Featuring atoms, molecules, organisms and layout templates for building beautiful interfaces.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -140,6 +140,7 @@
|
|
|
140
140
|
"@radix-ui/react-radio-group": "^1.4.7",
|
|
141
141
|
"@radix-ui/react-select": "^2.3.7",
|
|
142
142
|
"@radix-ui/react-separator": "^1.1.15",
|
|
143
|
+
"@radix-ui/react-slider": "^1.4.7",
|
|
143
144
|
"@radix-ui/react-slot": "^1.3.3",
|
|
144
145
|
"@radix-ui/react-switch": "^1.3.7",
|
|
145
146
|
"class-variance-authority": "^0.7.1",
|