@hyddenlabs/hydn-ui 0.3.14 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/forms/button/button-with-icon.d.ts +3 -0
- package/dist/components/forms/button/button-with-icon.d.ts.map +1 -1
- package/dist/components/forms/button/button-with-icon.js +23 -2
- package/dist/components/forms/button/button-with-icon.js.map +1 -1
- package/dist/components/forms/button/button.d.ts +4 -0
- package/dist/components/forms/button/button.d.ts.map +1 -1
- package/dist/components/forms/button/button.js +20 -6
- package/dist/components/forms/button/button.js.map +1 -1
- package/dist/components/forms/button/icon-button.d.ts +2 -0
- package/dist/components/forms/button/icon-button.d.ts.map +1 -1
- package/dist/components/forms/button/icon-button.js +3 -0
- package/dist/components/forms/button/icon-button.js.map +1 -1
- package/dist/components/forms/button/inline-button.d.ts +2 -0
- package/dist/components/forms/button/inline-button.d.ts.map +1 -1
- package/dist/components/forms/button/inline-button.js +8 -3
- package/dist/components/forms/button/inline-button.js.map +1 -1
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +35 -35
- package/dist/theme/tokens.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,10 @@ export interface ButtonWithIconProps extends Omit<BaseButtonProps, 'icon' | 'sty
|
|
|
6
6
|
icon?: string;
|
|
7
7
|
iconSize?: IconSize;
|
|
8
8
|
iconColor?: ColorVariant | 'currentColor';
|
|
9
|
+
/** Visual style for the button - renamed from `style` to avoid HTML attribute conflict */
|
|
9
10
|
buttonStyle?: BaseButtonProps['style'];
|
|
11
|
+
/** Visual style to apply on hover - alias of `hoverStyle`, consistent with `buttonStyle` naming */
|
|
12
|
+
hoverButtonStyle?: BaseButtonProps['hoverStyle'];
|
|
10
13
|
children?: React.ReactNode;
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button-with-icon.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/button-with-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAQ,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAe,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;IAC1C,WAAW,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;GAGG;AACH,QAAA,MAAM,cAAc,+
|
|
1
|
+
{"version":3,"file":"button-with-icon.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/button-with-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAQ,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAe,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC;IAClF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;IAC1C,0FAA0F;IAC1F,WAAW,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;GAGG;AACH,QAAA,MAAM,cAAc,+FA6BnB,CAAC;AAIF,eAAe,cAAc,CAAC"}
|
|
@@ -3,9 +3,30 @@ import React from "react";
|
|
|
3
3
|
import { Icon } from "../../system/icon/icon.js";
|
|
4
4
|
import Button from "./button.js";
|
|
5
5
|
const ButtonWithIcon = React.forwardRef(
|
|
6
|
-
({
|
|
6
|
+
({
|
|
7
|
+
icon,
|
|
8
|
+
iconSize = "md",
|
|
9
|
+
iconColor = "currentColor",
|
|
10
|
+
iconPosition = "left",
|
|
11
|
+
buttonStyle,
|
|
12
|
+
hoverButtonStyle,
|
|
13
|
+
hoverStyle,
|
|
14
|
+
children,
|
|
15
|
+
...rest
|
|
16
|
+
}, ref) => {
|
|
7
17
|
const iconNode = icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: iconSize, color: iconColor }) : null;
|
|
8
|
-
return /* @__PURE__ */ jsx(
|
|
18
|
+
return /* @__PURE__ */ jsx(
|
|
19
|
+
Button,
|
|
20
|
+
{
|
|
21
|
+
ref,
|
|
22
|
+
icon: iconNode,
|
|
23
|
+
iconPosition,
|
|
24
|
+
style: buttonStyle,
|
|
25
|
+
hoverStyle: hoverButtonStyle ?? hoverStyle,
|
|
26
|
+
...rest,
|
|
27
|
+
children
|
|
28
|
+
}
|
|
29
|
+
);
|
|
9
30
|
}
|
|
10
31
|
);
|
|
11
32
|
ButtonWithIcon.displayName = "ButtonWithIcon";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button-with-icon.js","sources":["../../../../src/components/forms/button/button-with-icon.tsx"],"sourcesContent":["import React from 'react';\nimport { Icon, IconSize } from '../../system/icon';\nimport Button, { ButtonProps as BaseButtonProps } from './button';\nimport { ColorVariant } from '../../../theme/tokens';\n\nexport interface ButtonWithIconProps extends Omit<BaseButtonProps, 'icon' | 'style'> {\n icon?: string;\n iconSize?: IconSize;\n iconColor?: ColorVariant | 'currentColor';\n buttonStyle?: BaseButtonProps['style'];\n children?: React.ReactNode;\n}\n\n/**\n * ButtonWithIcon - Button using Icon wrapper for consistent icon sizing\n * Usage: <ButtonWithIcon icon=\"plus\" iconSize=\"md\">Add</ButtonWithIcon>\n */\nconst ButtonWithIcon = React.forwardRef<HTMLButtonElement, ButtonWithIconProps>(\n (\n {
|
|
1
|
+
{"version":3,"file":"button-with-icon.js","sources":["../../../../src/components/forms/button/button-with-icon.tsx"],"sourcesContent":["import React from 'react';\nimport { Icon, IconSize } from '../../system/icon';\nimport Button, { ButtonProps as BaseButtonProps } from './button';\nimport { ColorVariant } from '../../../theme/tokens';\n\nexport interface ButtonWithIconProps extends Omit<BaseButtonProps, 'icon' | 'style'> {\n icon?: string;\n iconSize?: IconSize;\n iconColor?: ColorVariant | 'currentColor';\n /** Visual style for the button - renamed from `style` to avoid HTML attribute conflict */\n buttonStyle?: BaseButtonProps['style'];\n /** Visual style to apply on hover - alias of `hoverStyle`, consistent with `buttonStyle` naming */\n hoverButtonStyle?: BaseButtonProps['hoverStyle'];\n children?: React.ReactNode;\n}\n\n/**\n * ButtonWithIcon - Button using Icon wrapper for consistent icon sizing\n * Usage: <ButtonWithIcon icon=\"plus\" iconSize=\"md\">Add</ButtonWithIcon>\n */\nconst ButtonWithIcon = React.forwardRef<HTMLButtonElement, ButtonWithIconProps>(\n (\n {\n icon,\n iconSize = 'md',\n iconColor = 'currentColor',\n iconPosition = 'left',\n buttonStyle,\n hoverButtonStyle,\n hoverStyle,\n children,\n ...rest\n },\n ref\n ) => {\n const iconNode = icon ? <Icon name={icon} size={iconSize} color={iconColor} /> : null;\n return (\n <Button\n ref={ref}\n icon={iconNode}\n iconPosition={iconPosition}\n style={buttonStyle}\n hoverStyle={hoverButtonStyle ?? hoverStyle}\n {...rest}\n >\n {children}\n </Button>\n );\n }\n);\n\nButtonWithIcon.displayName = 'ButtonWithIcon';\n\nexport default ButtonWithIcon;\n"],"names":[],"mappings":";;;;AAoBA,MAAM,iBAAiB,MAAM;AAAA,EAC3B,CACE;AAAA,IACE;AAAA,IACA,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,WAAW,OAAO,oBAAC,MAAA,EAAK,MAAM,MAAM,MAAM,UAAU,OAAO,UAAA,CAAW,IAAK;AACjF,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,OAAO;AAAA,QACP,YAAY,oBAAoB;AAAA,QAC/B,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,eAAe,cAAc;"}
|
|
@@ -46,6 +46,10 @@ export type ButtonProps = {
|
|
|
46
46
|
align?: Alignment;
|
|
47
47
|
/** Applies active/pressed state styling */
|
|
48
48
|
active?: boolean;
|
|
49
|
+
/** Color variant to use when the button is hovered - overrides `variant` on hover */
|
|
50
|
+
hoverVariant?: ColorVariant;
|
|
51
|
+
/** Visual style to use when the button is hovered - overrides `style` on hover */
|
|
52
|
+
hoverStyle?: 'solid' | 'outline' | 'ghost' | 'link' | 'soft' | 'none';
|
|
49
53
|
/** ARIA expanded state - indicates if controlled element is expanded */
|
|
50
54
|
'aria-expanded'?: boolean;
|
|
51
55
|
/** ARIA haspopup - indicates element has popup menu/dialog */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/button.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/button.tsx"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ const Button = React.forwardRef(
|
|
|
27
27
|
wide = false,
|
|
28
28
|
align,
|
|
29
29
|
active = false,
|
|
30
|
+
hoverVariant,
|
|
31
|
+
hoverStyle: hoverStyleProp,
|
|
30
32
|
"aria-expanded": ariaExpanded,
|
|
31
33
|
"aria-haspopup": ariaHaspopup,
|
|
32
34
|
"aria-controls": ariaControls,
|
|
@@ -36,12 +38,24 @@ const Button = React.forwardRef(
|
|
|
36
38
|
rel
|
|
37
39
|
}, ref) => {
|
|
38
40
|
const isIconOnly = icon && !children;
|
|
41
|
+
const hasHoverOverride = Boolean(hoverVariant || hoverStyleProp);
|
|
42
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
43
|
+
const effectiveVariant = hasHoverOverride && isHovered ? hoverVariant ?? variant : variant;
|
|
44
|
+
const effectiveStyle = hasHoverOverride && isHovered ? hoverStyleProp ?? style : style;
|
|
45
|
+
const handleMouseEnter = hasHoverOverride ? (e) => {
|
|
46
|
+
setIsHovered(true);
|
|
47
|
+
onMouseEnter?.(e);
|
|
48
|
+
} : onMouseEnter;
|
|
49
|
+
const handleMouseLeave = hasHoverOverride ? (e) => {
|
|
50
|
+
setIsHovered(false);
|
|
51
|
+
onMouseLeave?.(e);
|
|
52
|
+
} : onMouseLeave;
|
|
39
53
|
if (isIconOnly && !ariaLabel) {
|
|
40
54
|
console.warn("Button: Icon-only buttons require an ariaLabel for accessibility");
|
|
41
55
|
}
|
|
42
56
|
const getStyleClasses = () => {
|
|
43
|
-
const variantKey =
|
|
44
|
-
switch (
|
|
57
|
+
const variantKey = effectiveVariant;
|
|
58
|
+
switch (effectiveStyle) {
|
|
45
59
|
case "outline":
|
|
46
60
|
return `${colorVariants.outline[variantKey]}`;
|
|
47
61
|
case "ghost":
|
|
@@ -113,9 +127,9 @@ const Button = React.forwardRef(
|
|
|
113
127
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
128
|
onClick,
|
|
115
129
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
|
-
onMouseEnter,
|
|
130
|
+
onMouseEnter: handleMouseEnter,
|
|
117
131
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
-
onMouseLeave,
|
|
132
|
+
onMouseLeave: handleMouseLeave,
|
|
119
133
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
120
134
|
onMouseDown,
|
|
121
135
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -133,8 +147,8 @@ const Button = React.forwardRef(
|
|
|
133
147
|
ref,
|
|
134
148
|
type,
|
|
135
149
|
onClick,
|
|
136
|
-
onMouseEnter,
|
|
137
|
-
onMouseLeave,
|
|
150
|
+
onMouseEnter: handleMouseEnter,
|
|
151
|
+
onMouseLeave: handleMouseLeave,
|
|
138
152
|
onMouseDown,
|
|
139
153
|
onBlur,
|
|
140
154
|
"aria-label": ariaLabel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","sources":["../../../../src/components/forms/button/button.tsx"],"sourcesContent":["import React from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { interactiveSizes, InteractiveSize, InputWidth, inputWidthSizes } from '../../../theme/size-tokens';\nimport { Alignment, colorVariants, inputAlignClasses, ColorVariant } from '../../../theme/tokens';\n\nexport type ButtonProps = {\n /** Button label content - text, icons, or other elements */\n children?: React.ReactNode;\n /** Click event handler */\n onClick?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse enter event handler */\n onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse leave event handler */\n onMouseLeave?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse down event handler */\n onMouseDown?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Blur event handler */\n onBlur?: (e: React.FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Accessible label for icon-only buttons (required when no children) */\n ariaLabel?: string;\n /** Disables button interaction and applies disabled styling */\n disabled?: boolean;\n /** HTML button type attribute (ignored when `to` or `href` is set) */\n type?: 'button' | 'submit' | 'reset';\n /** Additional CSS classes applied to the button */\n className?: string;\n /** Icon element to display alongside button text */\n icon?: React.ReactNode;\n /** Position of the icon relative to button text */\n iconPosition?: 'left' | 'right';\n /** Color variant affecting button appearance */\n variant?: ColorVariant;\n /** Visual style modifier - solid (filled), outline (bordered), ghost (transparent), link (text-only), soft (subtle background), or none (no background at all) */\n style?: 'solid' | 'outline' | 'ghost' | 'link' | 'soft' | 'none';\n /** Size variant - uses unified size system (xs, sm, md, lg, xl) */\n size?: InteractiveSize;\n /** Border radius style - default (rounded), pill (fully rounded), square (sharp corners), circle (for icon-only buttons) */\n rounded?: 'default' | 'pill' | 'square' | 'circle';\n /** Shows loading spinner and disables interaction */\n loading?: boolean;\n /** Width of the button */\n width?: InputWidth;\n /** When true, button spans full width of container (same as width=\"full\") */\n fullWidth?: boolean;\n /** When true, button uses wider min-width (good for prominent actions) */\n wide?: boolean;\n /** Aligns the button within its container: left, center, or right */\n align?: Alignment;\n /** Applies active/pressed state styling */\n active?: boolean;\n /** ARIA expanded state - indicates if controlled element is expanded */\n 'aria-expanded'?: boolean;\n /** ARIA haspopup - indicates element has popup menu/dialog */\n 'aria-haspopup'?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n /** ARIA controls - ID of element controlled by this button */\n 'aria-controls'?: string;\n /**\n * React Router path. When provided the component renders as a `<Link>` (anchor tag)\n * instead of a `<button>`, giving you router-aware navigation with full button styling.\n */\n to?: string;\n /**\n * Plain URL. When provided (and `to` is not set) the component renders as an `<a>` tag.\n * Use `to` instead when navigating within the app so React Router manages the history.\n */\n href?: string;\n /** Link target attribute (`_blank`, `_self`, etc.) – only used when `to` or `href` is set */\n target?: React.HTMLAttributeAnchorTarget;\n /** Rel attribute for the anchor – defaults to `\"noreferrer noopener\"` when `target=\"_blank\"` */\n rel?: string;\n};\n\n/**\n * Accessible Button component\n * - Color variants: neutral, primary, accent, info, success, warning, error\n * - Style modifiers: solid (default), outline, ghost, link, soft\n * - Sizes: xs, sm, md (default), lg, xl\n * - Supports icons with flexible positioning (left/right)\n * - Icon-only buttons require `ariaLabel` for accessibility\n * - Pass `to` to render as a React Router `<Link>`, or `href` for a plain `<a>`, keeping full button styling\n */\nconst Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n (\n {\n children,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onMouseDown,\n onBlur,\n ariaLabel,\n disabled = false,\n type = 'button',\n className = '',\n icon,\n iconPosition = 'left',\n variant = 'neutral',\n style = 'solid',\n size = 'md',\n rounded = 'default',\n loading = false,\n width = 'auto',\n fullWidth = false,\n wide = false,\n align,\n active = false,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHaspopup,\n 'aria-controls': ariaControls,\n to,\n href,\n target,\n rel\n },\n ref\n ) => {\n const isIconOnly = icon && !children;\n\n // Icon-only buttons MUST have an aria-label for accessibility\n if (isIconOnly && !ariaLabel) {\n // eslint-disable-next-line no-console\n console.warn('Button: Icon-only buttons require an ariaLabel for accessibility');\n }\n\n // Style modifiers\n const getStyleClasses = () => {\n const variantKey = variant as keyof typeof colorVariants.solid;\n\n switch (style) {\n case 'outline':\n return `${colorVariants.outline[variantKey]}`;\n case 'ghost':\n return colorVariants.ghost[variantKey];\n case 'link':\n return colorVariants.link[variantKey];\n case 'soft':\n return colorVariants.soft[variantKey];\n case 'none':\n return colorVariants.none[variantKey];\n case 'solid':\n default:\n return `${colorVariants.solid[variantKey]} shadow-sm hover:shadow-md`;\n }\n };\n\n // Sizes - from unified size system\n const sizeConfig = interactiveSizes[size];\n const sizeClasses = `${sizeConfig.height} ${sizeConfig.padding} ${sizeConfig.text}`;\n\n const roundedClasses = {\n default: 'rounded-md',\n pill: 'rounded-full',\n square: 'rounded-none aspect-square',\n circle: 'rounded-full aspect-square'\n };\n\n // Show loading spinner or icon\n const displayIcon = loading ? (\n <svg className=\"animate-spin h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n ) : (\n icon\n );\n\n const styleClasses = getStyleClasses();\n const effectiveWidth = fullWidth ? 'full' : wide ? 'xl' : width;\n const widthClasses = inputWidthSizes[effectiveWidth];\n const alignmentClass = align ? inputAlignClasses[align] : '';\n const activeClasses = active ? 'active:scale-95' : '';\n\n const shouldRenderIconSlots = !isIconOnly && Boolean(displayIcon);\n const cloneIcon = () => {\n if (!displayIcon) return null;\n if (React.isValidElement(displayIcon)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.cloneElement(displayIcon as React.ReactElement<any>, { 'aria-hidden': false });\n }\n return displayIcon;\n };\n\n const showLeftIcon = shouldRenderIconSlots && iconPosition === 'left';\n const showRightIcon = shouldRenderIconSlots && iconPosition === 'right';\n\n // Check if className contains display utilities to avoid conflicts\n const hasDisplayOverride =\n className.includes('hidden') ||\n className.includes('inline') ||\n className.includes('block') ||\n className.includes('flex');\n const baseDisplayClass = hasDisplayOverride ? '' : 'inline-flex';\n\n const isDisabled = disabled || loading;\n\n const combinedClassName = `${baseDisplayClass} items-center justify-center ${alignmentClass} ${roundedClasses[rounded]} font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${styleClasses} ${sizeClasses} ${\n isIconOnly ? 'p-0' : ''\n } ${widthClasses} ${activeClasses} ${isDisabled && (to || href) ? 'pointer-events-none opacity-50' : ''} ${className}`;\n\n const innerContent = (\n <>\n {showLeftIcon && <span className=\"flex shrink-0 items-center mr-2\">{cloneIcon()}</span>}\n {isIconOnly ? (\n <span className=\"inline-flex items-center justify-center\">{displayIcon}</span>\n ) : (\n <span className=\"inline-flex flex-1 justify-center text-center\">{children}</span>\n )}\n {showRightIcon && <span className=\"flex shrink-0 items-center ml-2\">{cloneIcon()}</span>}\n </>\n );\n\n const sharedLinkProps = {\n 'aria-label': ariaLabel,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHaspopup,\n 'aria-controls': ariaControls,\n 'aria-disabled': isDisabled || undefined,\n tabIndex: isDisabled ? -1 : undefined,\n target,\n rel: rel ?? (target === '_blank' ? 'noopener noreferrer' : undefined),\n className: combinedClassName,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onClick: onClick as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseEnter: onMouseEnter as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseLeave: onMouseLeave as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseDown: onMouseDown as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onBlur: onBlur as any\n };\n\n if (to) {\n return (\n <Link to={to} ref={ref as React.Ref<HTMLAnchorElement>} {...sharedLinkProps}>\n {innerContent}\n </Link>\n );\n }\n\n if (href) {\n return (\n <a href={href} ref={ref as React.Ref<HTMLAnchorElement>} {...sharedLinkProps}>\n {innerContent}\n </a>\n );\n }\n\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n type={type}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onMouseDown={onMouseDown}\n onBlur={onBlur}\n aria-label={ariaLabel}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHaspopup}\n aria-controls={ariaControls}\n disabled={isDisabled}\n className={combinedClassName}\n >\n {innerContent}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport default Button;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"button.js","sources":["../../../../src/components/forms/button/button.tsx"],"sourcesContent":["import React from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { interactiveSizes, InteractiveSize, InputWidth, inputWidthSizes } from '../../../theme/size-tokens';\nimport { Alignment, colorVariants, inputAlignClasses, ColorVariant } from '../../../theme/tokens';\n\nexport type ButtonProps = {\n /** Button label content - text, icons, or other elements */\n children?: React.ReactNode;\n /** Click event handler */\n onClick?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse enter event handler */\n onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse leave event handler */\n onMouseLeave?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Mouse down event handler */\n onMouseDown?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Blur event handler */\n onBlur?: (e: React.FocusEvent<HTMLButtonElement | HTMLAnchorElement>) => void;\n /** Accessible label for icon-only buttons (required when no children) */\n ariaLabel?: string;\n /** Disables button interaction and applies disabled styling */\n disabled?: boolean;\n /** HTML button type attribute (ignored when `to` or `href` is set) */\n type?: 'button' | 'submit' | 'reset';\n /** Additional CSS classes applied to the button */\n className?: string;\n /** Icon element to display alongside button text */\n icon?: React.ReactNode;\n /** Position of the icon relative to button text */\n iconPosition?: 'left' | 'right';\n /** Color variant affecting button appearance */\n variant?: ColorVariant;\n /** Visual style modifier - solid (filled), outline (bordered), ghost (transparent), link (text-only), soft (subtle background), or none (no background at all) */\n style?: 'solid' | 'outline' | 'ghost' | 'link' | 'soft' | 'none';\n /** Size variant - uses unified size system (xs, sm, md, lg, xl) */\n size?: InteractiveSize;\n /** Border radius style - default (rounded), pill (fully rounded), square (sharp corners), circle (for icon-only buttons) */\n rounded?: 'default' | 'pill' | 'square' | 'circle';\n /** Shows loading spinner and disables interaction */\n loading?: boolean;\n /** Width of the button */\n width?: InputWidth;\n /** When true, button spans full width of container (same as width=\"full\") */\n fullWidth?: boolean;\n /** When true, button uses wider min-width (good for prominent actions) */\n wide?: boolean;\n /** Aligns the button within its container: left, center, or right */\n align?: Alignment;\n /** Applies active/pressed state styling */\n active?: boolean;\n /** Color variant to use when the button is hovered - overrides `variant` on hover */\n hoverVariant?: ColorVariant;\n /** Visual style to use when the button is hovered - overrides `style` on hover */\n hoverStyle?: 'solid' | 'outline' | 'ghost' | 'link' | 'soft' | 'none';\n /** ARIA expanded state - indicates if controlled element is expanded */\n 'aria-expanded'?: boolean;\n /** ARIA haspopup - indicates element has popup menu/dialog */\n 'aria-haspopup'?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n /** ARIA controls - ID of element controlled by this button */\n 'aria-controls'?: string;\n /**\n * React Router path. When provided the component renders as a `<Link>` (anchor tag)\n * instead of a `<button>`, giving you router-aware navigation with full button styling.\n */\n to?: string;\n /**\n * Plain URL. When provided (and `to` is not set) the component renders as an `<a>` tag.\n * Use `to` instead when navigating within the app so React Router manages the history.\n */\n href?: string;\n /** Link target attribute (`_blank`, `_self`, etc.) – only used when `to` or `href` is set */\n target?: React.HTMLAttributeAnchorTarget;\n /** Rel attribute for the anchor – defaults to `\"noreferrer noopener\"` when `target=\"_blank\"` */\n rel?: string;\n};\n\n/**\n * Accessible Button component\n * - Color variants: neutral, primary, accent, info, success, warning, error\n * - Style modifiers: solid (default), outline, ghost, link, soft\n * - Sizes: xs, sm, md (default), lg, xl\n * - Supports icons with flexible positioning (left/right)\n * - Icon-only buttons require `ariaLabel` for accessibility\n * - Pass `to` to render as a React Router `<Link>`, or `href` for a plain `<a>`, keeping full button styling\n */\nconst Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n (\n {\n children,\n onClick,\n onMouseEnter,\n onMouseLeave,\n onMouseDown,\n onBlur,\n ariaLabel,\n disabled = false,\n type = 'button',\n className = '',\n icon,\n iconPosition = 'left',\n variant = 'neutral',\n style = 'solid',\n size = 'md',\n rounded = 'default',\n loading = false,\n width = 'auto',\n fullWidth = false,\n wide = false,\n align,\n active = false,\n hoverVariant,\n hoverStyle: hoverStyleProp,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHaspopup,\n 'aria-controls': ariaControls,\n to,\n href,\n target,\n rel\n },\n ref\n ) => {\n const isIconOnly = icon && !children;\n\n // Hover override tracking\n const hasHoverOverride = Boolean(hoverVariant || hoverStyleProp);\n const [isHovered, setIsHovered] = React.useState(false);\n const effectiveVariant = hasHoverOverride && isHovered ? (hoverVariant ?? variant) : variant;\n const effectiveStyle = hasHoverOverride && isHovered ? (hoverStyleProp ?? style) : style;\n\n const handleMouseEnter = hasHoverOverride\n ? (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsHovered(true);\n onMouseEnter?.(e);\n }\n : onMouseEnter;\n\n const handleMouseLeave = hasHoverOverride\n ? (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsHovered(false);\n onMouseLeave?.(e);\n }\n : onMouseLeave;\n\n // Icon-only buttons MUST have an aria-label for accessibility\n if (isIconOnly && !ariaLabel) {\n // eslint-disable-next-line no-console\n console.warn('Button: Icon-only buttons require an ariaLabel for accessibility');\n }\n\n // Style modifiers\n const getStyleClasses = () => {\n const variantKey = effectiveVariant as keyof typeof colorVariants.solid;\n\n switch (effectiveStyle) {\n case 'outline':\n return `${colorVariants.outline[variantKey]}`;\n case 'ghost':\n return colorVariants.ghost[variantKey];\n case 'link':\n return colorVariants.link[variantKey];\n case 'soft':\n return colorVariants.soft[variantKey];\n case 'none':\n return colorVariants.none[variantKey];\n case 'solid':\n default:\n return `${colorVariants.solid[variantKey]} shadow-sm hover:shadow-md`;\n }\n };\n\n // Sizes - from unified size system\n const sizeConfig = interactiveSizes[size];\n const sizeClasses = `${sizeConfig.height} ${sizeConfig.padding} ${sizeConfig.text}`;\n\n const roundedClasses = {\n default: 'rounded-md',\n pill: 'rounded-full',\n square: 'rounded-none aspect-square',\n circle: 'rounded-full aspect-square'\n };\n\n // Show loading spinner or icon\n const displayIcon = loading ? (\n <svg className=\"animate-spin h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n ) : (\n icon\n );\n\n const styleClasses = getStyleClasses();\n const effectiveWidth = fullWidth ? 'full' : wide ? 'xl' : width;\n const widthClasses = inputWidthSizes[effectiveWidth];\n const alignmentClass = align ? inputAlignClasses[align] : '';\n const activeClasses = active ? 'active:scale-95' : '';\n\n const shouldRenderIconSlots = !isIconOnly && Boolean(displayIcon);\n const cloneIcon = () => {\n if (!displayIcon) return null;\n if (React.isValidElement(displayIcon)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.cloneElement(displayIcon as React.ReactElement<any>, { 'aria-hidden': false });\n }\n return displayIcon;\n };\n\n const showLeftIcon = shouldRenderIconSlots && iconPosition === 'left';\n const showRightIcon = shouldRenderIconSlots && iconPosition === 'right';\n\n // Check if className contains display utilities to avoid conflicts\n const hasDisplayOverride =\n className.includes('hidden') ||\n className.includes('inline') ||\n className.includes('block') ||\n className.includes('flex');\n const baseDisplayClass = hasDisplayOverride ? '' : 'inline-flex';\n\n const isDisabled = disabled || loading;\n\n const combinedClassName = `${baseDisplayClass} items-center justify-center ${alignmentClass} ${roundedClasses[rounded]} font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${styleClasses} ${sizeClasses} ${\n isIconOnly ? 'p-0' : ''\n } ${widthClasses} ${activeClasses} ${isDisabled && (to || href) ? 'pointer-events-none opacity-50' : ''} ${className}`;\n\n const innerContent = (\n <>\n {showLeftIcon && <span className=\"flex shrink-0 items-center mr-2\">{cloneIcon()}</span>}\n {isIconOnly ? (\n <span className=\"inline-flex items-center justify-center\">{displayIcon}</span>\n ) : (\n <span className=\"inline-flex flex-1 justify-center text-center\">{children}</span>\n )}\n {showRightIcon && <span className=\"flex shrink-0 items-center ml-2\">{cloneIcon()}</span>}\n </>\n );\n\n const sharedLinkProps = {\n 'aria-label': ariaLabel,\n 'aria-expanded': ariaExpanded,\n 'aria-haspopup': ariaHaspopup,\n 'aria-controls': ariaControls,\n 'aria-disabled': isDisabled || undefined,\n tabIndex: isDisabled ? -1 : undefined,\n target,\n rel: rel ?? (target === '_blank' ? 'noopener noreferrer' : undefined),\n className: combinedClassName,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onClick: onClick as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseEnter: handleMouseEnter as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseLeave: handleMouseLeave as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMouseDown: onMouseDown as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onBlur: onBlur as any\n };\n\n if (to) {\n return (\n <Link to={to} ref={ref as React.Ref<HTMLAnchorElement>} {...sharedLinkProps}>\n {innerContent}\n </Link>\n );\n }\n\n if (href) {\n return (\n <a href={href} ref={ref as React.Ref<HTMLAnchorElement>} {...sharedLinkProps}>\n {innerContent}\n </a>\n );\n }\n\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n type={type}\n onClick={onClick}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseDown={onMouseDown}\n onBlur={onBlur}\n aria-label={ariaLabel}\n aria-expanded={ariaExpanded}\n aria-haspopup={ariaHaspopup}\n aria-controls={ariaControls}\n disabled={isDisabled}\n className={combinedClassName}\n >\n {innerContent}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n\nexport default Button;\n"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export interface IconButtonProps extends Omit<BaseButtonProps, 'icon' | 'style'
|
|
|
8
8
|
iconSize?: IconSize;
|
|
9
9
|
iconColor?: ColorVariant | 'currentColor';
|
|
10
10
|
buttonStyle?: BaseButtonProps['style'];
|
|
11
|
+
/** Visual style to apply on hover - alias of `hoverStyle`, consistent with `buttonStyle` naming */
|
|
12
|
+
hoverButtonStyle?: BaseButtonProps['hoverStyle'];
|
|
11
13
|
/** Remove the default button sizing so the icon renders without extra padding */
|
|
12
14
|
noPadding?: boolean;
|
|
13
15
|
/** Icon to display on hover (if not provided, hover will keep the same icon) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/icon-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAQ,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAe,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;IAC1C,WAAW,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;GAGG;AACH,QAAA,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/icon-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAQ,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAe,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC3F,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;IAC1C,WAAW,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IACjD,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED;;;GAGG;AACH,QAAA,MAAM,UAAU,2FAmGf,CAAC;AAIF,eAAe,UAAU,CAAC"}
|
|
@@ -8,6 +8,8 @@ const IconButton = React.forwardRef(
|
|
|
8
8
|
iconSize = "md",
|
|
9
9
|
iconColor = "currentColor",
|
|
10
10
|
buttonStyle,
|
|
11
|
+
hoverButtonStyle,
|
|
12
|
+
hoverStyle,
|
|
11
13
|
noPadding = false,
|
|
12
14
|
ariaLabel,
|
|
13
15
|
hoverIcon,
|
|
@@ -68,6 +70,7 @@ const IconButton = React.forwardRef(
|
|
|
68
70
|
ref: mergedRef,
|
|
69
71
|
icon: iconNode,
|
|
70
72
|
style: buttonStyle,
|
|
73
|
+
hoverStyle: hoverButtonStyle ?? hoverStyle,
|
|
71
74
|
ariaLabel,
|
|
72
75
|
onMouseEnter: handleMouseEnter,
|
|
73
76
|
onMouseLeave: handleMouseLeave,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button.js","sources":["../../../../src/components/forms/button/icon-button.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { Icon, IconSize } from '../../system/icon';\nimport Button, { ButtonProps as BaseButtonProps } from './button';\nimport { ColorVariant } from '../../../theme/tokens';\n\nexport interface IconButtonProps extends Omit<BaseButtonProps, 'icon' | 'style' | 'children'> {\n icon: string;\n ariaLabel: string;\n iconSize?: IconSize;\n iconColor?: ColorVariant | 'currentColor';\n buttonStyle?: BaseButtonProps['style'];\n /** Remove the default button sizing so the icon renders without extra padding */\n noPadding?: boolean;\n /** Icon to display on hover (if not provided, hover will keep the same icon) */\n hoverIcon?: string;\n children?: never;\n}\n\n/**\n * IconButton - Icon-only button using Icon wrapper for consistent icon sizing\n * Usage: <IconButton icon=\"plus\" iconSize=\"md\" ariaLabel=\"Add item\" />\n */\nconst IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n {\n icon,\n iconSize = 'md',\n iconColor = 'currentColor',\n buttonStyle,\n noPadding = false,\n ariaLabel,\n hoverIcon,\n onMouseEnter,\n onMouseLeave,\n onClick,\n className = '',\n ...rest\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = useState(false);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n\n // Merged callback ref that handles both internal and forwarded refs\n const mergedRef = useCallback(\n (node: HTMLButtonElement | null) => {\n // Update internal ref\n buttonRef.current = node;\n\n // Forward to external ref\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {\n setIsHovered(true);\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {\n setIsHovered(false);\n onMouseLeave?.(e);\n };\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Reset hover state on click - handles click-drag scenarios\n // where mouseLeave might not fire\n setIsHovered(false);\n onClick?.(e);\n };\n\n // Global mousemove listener to detect when mouse leaves button during drag\n useEffect(() => {\n if (!hoverIcon || !isHovered) return;\n\n const handleGlobalMouseMove = (e: MouseEvent) => {\n if (!buttonRef.current) return;\n\n const rect = buttonRef.current.getBoundingClientRect();\n const isOutside =\n e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;\n\n if (isOutside) {\n setIsHovered(false);\n }\n };\n\n document.addEventListener('mousemove', handleGlobalMouseMove);\n return () => {\n document.removeEventListener('mousemove', handleGlobalMouseMove);\n };\n }, [hoverIcon, isHovered]);\n\n const displayIcon = isHovered && hoverIcon ? hoverIcon : icon;\n const iconNode = displayIcon ? <Icon name={displayIcon} size={iconSize} color={iconColor} /> : null;\n const paddingClasses = noPadding ? '!px-0 !py-0 !h-auto !min-h-0 !w-auto !min-w-0' : '';\n const hoverClasses = noPadding ? 'hover:!bg-transparent active:!bg-transparent' : '';\n const mergedClassName = [paddingClasses, hoverClasses, className].filter(Boolean).join(' ');\n\n return (\n <Button\n ref={mergedRef}\n icon={iconNode}\n style={buttonStyle}\n ariaLabel={ariaLabel}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleClick}\n className={mergedClassName}\n {...rest}\n />\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\n"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"icon-button.js","sources":["../../../../src/components/forms/button/icon-button.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { Icon, IconSize } from '../../system/icon';\nimport Button, { ButtonProps as BaseButtonProps } from './button';\nimport { ColorVariant } from '../../../theme/tokens';\n\nexport interface IconButtonProps extends Omit<BaseButtonProps, 'icon' | 'style' | 'children'> {\n icon: string;\n ariaLabel: string;\n iconSize?: IconSize;\n iconColor?: ColorVariant | 'currentColor';\n buttonStyle?: BaseButtonProps['style'];\n /** Visual style to apply on hover - alias of `hoverStyle`, consistent with `buttonStyle` naming */\n hoverButtonStyle?: BaseButtonProps['hoverStyle'];\n /** Remove the default button sizing so the icon renders without extra padding */\n noPadding?: boolean;\n /** Icon to display on hover (if not provided, hover will keep the same icon) */\n hoverIcon?: string;\n children?: never;\n}\n\n/**\n * IconButton - Icon-only button using Icon wrapper for consistent icon sizing\n * Usage: <IconButton icon=\"plus\" iconSize=\"md\" ariaLabel=\"Add item\" />\n */\nconst IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n {\n icon,\n iconSize = 'md',\n iconColor = 'currentColor',\n buttonStyle,\n hoverButtonStyle,\n hoverStyle,\n noPadding = false,\n ariaLabel,\n hoverIcon,\n onMouseEnter,\n onMouseLeave,\n onClick,\n className = '',\n ...rest\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = useState(false);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n\n // Merged callback ref that handles both internal and forwarded refs\n const mergedRef = useCallback(\n (node: HTMLButtonElement | null) => {\n // Update internal ref\n buttonRef.current = node;\n\n // Forward to external ref\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {\n setIsHovered(true);\n onMouseEnter?.(e);\n };\n\n const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {\n setIsHovered(false);\n onMouseLeave?.(e);\n };\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // Reset hover state on click - handles click-drag scenarios\n // where mouseLeave might not fire\n setIsHovered(false);\n onClick?.(e);\n };\n\n // Global mousemove listener to detect when mouse leaves button during drag\n useEffect(() => {\n if (!hoverIcon || !isHovered) return;\n\n const handleGlobalMouseMove = (e: MouseEvent) => {\n if (!buttonRef.current) return;\n\n const rect = buttonRef.current.getBoundingClientRect();\n const isOutside =\n e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;\n\n if (isOutside) {\n setIsHovered(false);\n }\n };\n\n document.addEventListener('mousemove', handleGlobalMouseMove);\n return () => {\n document.removeEventListener('mousemove', handleGlobalMouseMove);\n };\n }, [hoverIcon, isHovered]);\n\n const displayIcon = isHovered && hoverIcon ? hoverIcon : icon;\n const iconNode = displayIcon ? <Icon name={displayIcon} size={iconSize} color={iconColor} /> : null;\n const paddingClasses = noPadding ? '!px-0 !py-0 !h-auto !min-h-0 !w-auto !min-w-0' : '';\n const hoverClasses = noPadding ? 'hover:!bg-transparent active:!bg-transparent' : '';\n const mergedClassName = [paddingClasses, hoverClasses, className].filter(Boolean).join(' ');\n\n return (\n <Button\n ref={mergedRef}\n icon={iconNode}\n style={buttonStyle}\n hoverStyle={hoverButtonStyle ?? hoverStyle}\n ariaLabel={ariaLabel}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleClick}\n className={mergedClassName}\n {...rest}\n />\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\n"],"names":[],"mappings":";;;;AAwBA,MAAM,aAAa,MAAM;AAAA,EACvB,CACE;AAAA,IACE;AAAA,IACA,WAAW;AAAA,IACX,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,UAAM,YAAY,OAAiC,IAAI;AAGvD,UAAM,YAAY;AAAA,MAChB,CAAC,SAAmC;AAElC,kBAAU,UAAU;AAGpB,YAAI,OAAO,QAAQ,YAAY;AAC7B,cAAI,IAAI;AAAA,QACV,WAAW,KAAK;AACd,cAAI,UAAU;AAAA,QAChB;AAAA,MACF;AAAA,MACA,CAAC,GAAG;AAAA,IAAA;AAGN,UAAM,mBAAmB,CAAC,MAA2C;AACnE,mBAAa,IAAI;AACjB,qBAAe,CAAC;AAAA,IAClB;AAEA,UAAM,mBAAmB,CAAC,MAA2C;AACnE,mBAAa,KAAK;AAClB,qBAAe,CAAC;AAAA,IAClB;AAEA,UAAM,cAAc,CAAC,MAA2C;AAG9D,mBAAa,KAAK;AAClB,gBAAU,CAAC;AAAA,IACb;AAGA,cAAU,MAAM;AACd,UAAI,CAAC,aAAa,CAAC,UAAW;AAE9B,YAAM,wBAAwB,CAAC,MAAkB;AAC/C,YAAI,CAAC,UAAU,QAAS;AAExB,cAAM,OAAO,UAAU,QAAQ,sBAAA;AAC/B,cAAM,YACJ,EAAE,UAAU,KAAK,QAAQ,EAAE,UAAU,KAAK,SAAS,EAAE,UAAU,KAAK,OAAO,EAAE,UAAU,KAAK;AAE9F,YAAI,WAAW;AACb,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAEA,eAAS,iBAAiB,aAAa,qBAAqB;AAC5D,aAAO,MAAM;AACX,iBAAS,oBAAoB,aAAa,qBAAqB;AAAA,MACjE;AAAA,IACF,GAAG,CAAC,WAAW,SAAS,CAAC;AAEzB,UAAM,cAAc,aAAa,YAAY,YAAY;AACzD,UAAM,WAAW,cAAc,oBAAC,MAAA,EAAK,MAAM,aAAa,MAAM,UAAU,OAAO,UAAA,CAAW,IAAK;AAC/F,UAAM,iBAAiB,YAAY,kDAAkD;AACrF,UAAM,eAAe,YAAY,iDAAiD;AAClF,UAAM,kBAAkB,CAAC,gBAAgB,cAAc,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE1F,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,YAAY,oBAAoB;AAAA,QAChC;AAAA,QACA,cAAc;AAAA,QACd,cAAc;AAAA,QACd,SAAS;AAAA,QACT,WAAW;AAAA,QACV,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEA,WAAW,cAAc;"}
|
|
@@ -23,6 +23,8 @@ export type InlineButtonProps = {
|
|
|
23
23
|
underline?: boolean;
|
|
24
24
|
/** Icon size token - defaults to 'xs' to match text size */
|
|
25
25
|
iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
26
|
+
/** Color variant to use when the button is hovered - overrides `variant` on hover */
|
|
27
|
+
hoverVariant?: ColorVariant;
|
|
26
28
|
};
|
|
27
29
|
/**
|
|
28
30
|
* Inline Button - a minimal button designed to be embedded within text
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/inline-button.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"inline-button.d.ts","sourceRoot":"","sources":["../../../../src/components/forms/button/inline-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4CAA4C;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0BAA0B;IAC1B,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC3D,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC5C,qFAAqF;IACrF,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,YAAY,6FAiEjB,CAAC;AAIF,eAAe,YAAY,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
3
|
import { Icon } from "../../system/icon/icon.js";
|
|
4
4
|
const InlineButton = React.forwardRef(
|
|
5
5
|
({
|
|
@@ -13,8 +13,11 @@ const InlineButton = React.forwardRef(
|
|
|
13
13
|
variant = "primary",
|
|
14
14
|
loading = false,
|
|
15
15
|
underline = true,
|
|
16
|
-
iconSize = "xs"
|
|
16
|
+
iconSize = "xs",
|
|
17
|
+
hoverVariant
|
|
17
18
|
}, ref) => {
|
|
19
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
20
|
+
const effectiveVariant = hoverVariant && isHovered ? hoverVariant : variant;
|
|
18
21
|
const variantClasses = {
|
|
19
22
|
neutral: "text-neutral hover:text-neutral-hover active:text-neutral-active",
|
|
20
23
|
primary: "text-primary hover:text-primary-hover active:text-primary-active",
|
|
@@ -31,7 +34,7 @@ const InlineButton = React.forwardRef(
|
|
|
31
34
|
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
|
|
32
35
|
disabled || loading ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
33
36
|
underline ? "hover:underline" : "",
|
|
34
|
-
variantClasses[
|
|
37
|
+
variantClasses[effectiveVariant],
|
|
35
38
|
className
|
|
36
39
|
].filter(Boolean).join(" ");
|
|
37
40
|
const iconElement = icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: iconSize }) : null;
|
|
@@ -41,6 +44,8 @@ const InlineButton = React.forwardRef(
|
|
|
41
44
|
ref,
|
|
42
45
|
type,
|
|
43
46
|
onClick,
|
|
47
|
+
onMouseEnter: hoverVariant ? () => setIsHovered(true) : void 0,
|
|
48
|
+
onMouseLeave: hoverVariant ? () => setIsHovered(false) : void 0,
|
|
44
49
|
disabled: disabled || loading,
|
|
45
50
|
"aria-label": ariaLabel,
|
|
46
51
|
className: baseClasses,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-button.js","sources":["../../../../src/components/forms/button/inline-button.tsx"],"sourcesContent":["import React from 'react';\nimport { ColorVariant } from '../../../theme/tokens';\nimport { Icon } from '../../system/icon/icon';\n\nexport type InlineButtonProps = {\n /** Button label content - typically text */\n children: React.ReactNode;\n /** Click event handler */\n onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n /** Accessible label (optional, children used by default) */\n ariaLabel?: string;\n /** Disables button interaction and applies disabled styling */\n disabled?: boolean;\n /** HTML button type attribute */\n type?: 'button' | 'submit' | 'reset';\n /** Additional CSS classes applied to the button */\n className?: string;\n /** Icon name string passed to the Icon component to display alongside button text */\n icon?: string;\n /** Color variant - defaults to primary for link-like appearance */\n variant?: ColorVariant;\n /** Shows loading spinner and disables interaction */\n loading?: boolean;\n /** Whether to show underline on hover (default: true) */\n underline?: boolean;\n /** Icon size token - defaults to 'xs' to match text size */\n iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n};\n\n/**\n * Inline Button - a minimal button designed to be embedded within text\n *\n * Perfect for use cases like:\n * - \"By signing in, you agree to our [Terms of Service]\"\n * - \"Learn more about [pricing]\"\n * - Inline actions within paragraphs\n *\n * Features:\n * - No background or padding by default\n * - Inherits surrounding text sizing\n * - Optional icon support\n * - Color variants for different contexts\n * - Hover underline (can be disabled)\n * - Fully accessible\n */\nconst InlineButton = React.forwardRef<HTMLButtonElement, InlineButtonProps>(\n (\n {\n children,\n onClick,\n ariaLabel,\n disabled = false,\n type = 'button',\n className = '',\n icon,\n variant = 'primary',\n loading = false,\n underline = true,\n iconSize = 'xs'\n },\n ref\n ) => {\n // Color variant styles\n const variantClasses: Record<ColorVariant, string> = {\n neutral: 'text-neutral hover:text-neutral-hover active:text-neutral-active',\n primary: 'text-primary hover:text-primary-hover active:text-primary-active',\n accent: 'text-accent hover:text-accent-hover active:text-accent-active',\n info: 'text-info hover:text-info-hover active:text-info-active',\n success: 'text-success hover:text-success-hover active:text-success-active',\n warning: 'text-warning hover:text-warning-hover active:text-warning-active',\n error: 'text-error hover:text-error-hover active:text-error-active'\n };\n\n // Base classes - minimal styling, inline with text\n const baseClasses = [\n 'inline-flex items-center gap-0.5',\n 'font-medium',\n 'transition-colors duration-200',\n 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',\n disabled || loading ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',\n underline ? 'hover:underline' : '',\n variantClasses[
|
|
1
|
+
{"version":3,"file":"inline-button.js","sources":["../../../../src/components/forms/button/inline-button.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { ColorVariant } from '../../../theme/tokens';\nimport { Icon } from '../../system/icon/icon';\n\nexport type InlineButtonProps = {\n /** Button label content - typically text */\n children: React.ReactNode;\n /** Click event handler */\n onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;\n /** Accessible label (optional, children used by default) */\n ariaLabel?: string;\n /** Disables button interaction and applies disabled styling */\n disabled?: boolean;\n /** HTML button type attribute */\n type?: 'button' | 'submit' | 'reset';\n /** Additional CSS classes applied to the button */\n className?: string;\n /** Icon name string passed to the Icon component to display alongside button text */\n icon?: string;\n /** Color variant - defaults to primary for link-like appearance */\n variant?: ColorVariant;\n /** Shows loading spinner and disables interaction */\n loading?: boolean;\n /** Whether to show underline on hover (default: true) */\n underline?: boolean;\n /** Icon size token - defaults to 'xs' to match text size */\n iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Color variant to use when the button is hovered - overrides `variant` on hover */\n hoverVariant?: ColorVariant;\n};\n\n/**\n * Inline Button - a minimal button designed to be embedded within text\n *\n * Perfect for use cases like:\n * - \"By signing in, you agree to our [Terms of Service]\"\n * - \"Learn more about [pricing]\"\n * - Inline actions within paragraphs\n *\n * Features:\n * - No background or padding by default\n * - Inherits surrounding text sizing\n * - Optional icon support\n * - Color variants for different contexts\n * - Hover underline (can be disabled)\n * - Fully accessible\n */\nconst InlineButton = React.forwardRef<HTMLButtonElement, InlineButtonProps>(\n (\n {\n children,\n onClick,\n ariaLabel,\n disabled = false,\n type = 'button',\n className = '',\n icon,\n variant = 'primary',\n loading = false,\n underline = true,\n iconSize = 'xs',\n hoverVariant\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = useState(false);\n const effectiveVariant = hoverVariant && isHovered ? hoverVariant : variant;\n\n // Color variant styles\n const variantClasses: Record<ColorVariant, string> = {\n neutral: 'text-neutral hover:text-neutral-hover active:text-neutral-active',\n primary: 'text-primary hover:text-primary-hover active:text-primary-active',\n accent: 'text-accent hover:text-accent-hover active:text-accent-active',\n info: 'text-info hover:text-info-hover active:text-info-active',\n success: 'text-success hover:text-success-hover active:text-success-active',\n warning: 'text-warning hover:text-warning-hover active:text-warning-active',\n error: 'text-error hover:text-error-hover active:text-error-active'\n };\n\n // Base classes - minimal styling, inline with text\n const baseClasses = [\n 'inline-flex items-center gap-0.5',\n 'font-medium',\n 'transition-colors duration-200',\n 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',\n disabled || loading ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',\n underline ? 'hover:underline' : '',\n variantClasses[effectiveVariant],\n className\n ]\n .filter(Boolean)\n .join(' ');\n\n // Clone icon and apply size to make it proportional to text\n const iconElement = icon ? <Icon name={icon} size={iconSize} /> : null;\n\n return (\n <button\n ref={ref}\n type={type}\n onClick={onClick}\n onMouseEnter={hoverVariant ? () => setIsHovered(true) : undefined}\n onMouseLeave={hoverVariant ? () => setIsHovered(false) : undefined}\n disabled={disabled || loading}\n aria-label={ariaLabel}\n className={baseClasses}\n >\n {children}\n {iconElement}\n </button>\n );\n }\n);\n\nInlineButton.displayName = 'InlineButton';\n\nexport default InlineButton;\n"],"names":[],"mappings":";;;AA+CA,MAAM,eAAe,MAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,OAAO;AAAA,IACP,YAAY;AAAA,IACZ;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,WAAW;AAAA,IACX;AAAA,EAAA,GAEF,QACG;AACH,UAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,UAAM,mBAAmB,gBAAgB,YAAY,eAAe;AAGpE,UAAM,iBAA+C;AAAA,MACnD,SAAS;AAAA,MACT,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;AAIT,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,UAAU,kCAAkC;AAAA,MACxD,YAAY,oBAAoB;AAAA,MAChC,eAAe,gBAAgB;AAAA,MAC/B;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAGX,UAAM,cAAc,OAAO,oBAAC,MAAA,EAAK,MAAM,MAAM,MAAM,UAAU,IAAK;AAElE,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc,eAAe,MAAM,aAAa,IAAI,IAAI;AAAA,QACxD,cAAc,eAAe,MAAM,aAAa,KAAK,IAAI;AAAA,QACzD,UAAU,YAAY;AAAA,QACtB,cAAY;AAAA,QACZ,WAAW;AAAA,QAEV,UAAA;AAAA,UAAA;AAAA,UACA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,aAAa,cAAc;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/theme/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDlB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,MAAM,CAAC;AAC7C,eAAO,MAAM,eAAe,EAA0B,UAAU,EAAE,CAAC;AAEnE,eAAO,MAAM,kBAAkB,sFAAuF,CAAC;AACvH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AACnE,MAAM,MAAM,eAAe,GAAG,GAAG,gBAAgB,IAAI,UAAU,EAAE,CAAC;AAElE,eAAO,MAAM,iBAAiB,mnRAE7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,eAAe,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvG;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;AAKhH;;GAEG;AACH,KAAK,kBAAkB,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE;IAC1B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,kBAAkB,GAAG;QAAE,QAAQ,EAAE,kBAAkB,CAAA;KAAE,CAAC;IAC7D,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/theme/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDlB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,MAAM,CAAC;AAC7C,eAAO,MAAM,eAAe,EAA0B,UAAU,EAAE,CAAC;AAEnE,eAAO,MAAM,kBAAkB,sFAAuF,CAAC;AACvH,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AACnE,MAAM,MAAM,eAAe,GAAG,GAAG,gBAAgB,IAAI,UAAU,EAAE,CAAC;AAElE,eAAO,MAAM,iBAAiB,mnRAE7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,eAAe,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvG;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AAE/F;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC;AAKhH;;GAEG;AACH,KAAK,kBAAkB,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE;IAC1B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,kBAAkB,GAAG;QAAE,QAAQ,EAAE,kBAAkB,CAAA;KAAE,CAAC;IAC7D,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,CAAC;CAmItE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,aAAa,CAAC;AAC3D,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,iBAAiB,IAAI,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3F,eAAO,MAAM,KAAK;;;;;CAKjB,CAAC;AAEF,eAAO,MAAM,KAAK;;;CAGjB,CAAC;AAEF,eAAO,MAAM,UAAU,sCAAuC,CAAC;AAC/D,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAIvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,g0BAyDtB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/theme/tokens.js
CHANGED
|
@@ -57,13 +57,13 @@ const outlineBaseClasses = "border-2 bg-transparent transition-colors transition
|
|
|
57
57
|
const colorVariants = {
|
|
58
58
|
// Solid buttons/elements - filled background
|
|
59
59
|
solid: {
|
|
60
|
-
neutral: "bg-neutral text-neutral-foreground hover:bg-neutral-hover active:bg-neutral-active",
|
|
61
|
-
primary: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
|
|
62
|
-
accent: "bg-accent text-accent-foreground hover:bg-accent-hover active:bg-accent-active",
|
|
63
|
-
info: "bg-info text-info-foreground hover:bg-info-hover active:bg-info-active",
|
|
64
|
-
success: "bg-success text-success-foreground hover:bg-success-hover active:bg-success-active",
|
|
65
|
-
warning: "bg-warning text-warning-foreground hover:bg-warning-hover active:bg-warning-active",
|
|
66
|
-
error: "bg-error text-error-foreground hover:bg-error-hover active:bg-error-active"
|
|
60
|
+
neutral: "border-2 border-transparent bg-neutral text-neutral-foreground hover:bg-neutral-hover active:bg-neutral-active",
|
|
61
|
+
primary: "border-2 border-transparent bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
|
|
62
|
+
accent: "border-2 border-transparent bg-accent text-accent-foreground hover:bg-accent-hover active:bg-accent-active",
|
|
63
|
+
info: "border-2 border-transparent bg-info text-info-foreground hover:bg-info-hover active:bg-info-active",
|
|
64
|
+
success: "border-2 border-transparent bg-success text-success-foreground hover:bg-success-hover active:bg-success-active",
|
|
65
|
+
warning: "border-2 border-transparent bg-warning text-warning-foreground hover:bg-warning-hover active:bg-warning-active",
|
|
66
|
+
error: "border-2 border-transparent bg-error text-error-foreground hover:bg-error-hover active:bg-error-active"
|
|
67
67
|
},
|
|
68
68
|
// Outline style - transparent with border
|
|
69
69
|
outline: {
|
|
@@ -77,43 +77,43 @@ const colorVariants = {
|
|
|
77
77
|
},
|
|
78
78
|
// Ghost style - transparent with subtle hover
|
|
79
79
|
ghost: {
|
|
80
|
-
neutral: "bg-transparent text-foreground hover:bg-neutral/10 active:bg-neutral/20",
|
|
81
|
-
primary: "bg-transparent text-primary hover:bg-primary/10 active:bg-primary/20",
|
|
82
|
-
accent: "bg-transparent text-accent hover:bg-accent/10 active:bg-accent/20",
|
|
83
|
-
info: "bg-transparent text-info hover:bg-info/10 active:bg-info/20",
|
|
84
|
-
success: "bg-transparent text-success hover:bg-success/10 active:bg-success/20",
|
|
85
|
-
warning: "bg-transparent text-warning hover:bg-warning/10 active:bg-warning/20",
|
|
86
|
-
error: "bg-transparent text-error hover:bg-error/10 active:bg-error/20"
|
|
80
|
+
neutral: "border-2 border-transparent bg-transparent text-foreground hover:bg-neutral/10 active:bg-neutral/20",
|
|
81
|
+
primary: "border-2 border-transparent bg-transparent text-primary hover:bg-primary/10 active:bg-primary/20",
|
|
82
|
+
accent: "border-2 border-transparent bg-transparent text-accent hover:bg-accent/10 active:bg-accent/20",
|
|
83
|
+
info: "border-2 border-transparent bg-transparent text-info hover:bg-info/10 active:bg-info/20",
|
|
84
|
+
success: "border-2 border-transparent bg-transparent text-success hover:bg-success/10 active:bg-success/20",
|
|
85
|
+
warning: "border-2 border-transparent bg-transparent text-warning hover:bg-warning/10 active:bg-warning/20",
|
|
86
|
+
error: "border-2 border-transparent bg-transparent text-error hover:bg-error/10 active:bg-error/20"
|
|
87
87
|
},
|
|
88
88
|
// Soft style - subtle background
|
|
89
89
|
soft: {
|
|
90
|
-
neutral: "bg-neutral/20 text-neutral hover:bg-neutral/30 active:bg-neutral/40",
|
|
91
|
-
primary: "bg-primary/20 text-primary hover:bg-primary/30 active:bg-primary/40",
|
|
92
|
-
accent: "bg-accent/20 text-accent hover:bg-accent/30 active:bg-accent/40",
|
|
93
|
-
info: "bg-info/20 text-info hover:bg-info/30 active:bg-info/40",
|
|
94
|
-
success: "bg-success/20 text-success hover:bg-success/30 active:bg-success/40",
|
|
95
|
-
warning: "bg-warning/20 text-warning hover:bg-warning/30 active:bg-warning/40",
|
|
96
|
-
error: "bg-error/20 text-error hover:bg-error/30 active:bg-error/40"
|
|
90
|
+
neutral: "border-2 border-transparent bg-neutral/20 text-neutral hover:bg-neutral/30 active:bg-neutral/40",
|
|
91
|
+
primary: "border-2 border-transparent bg-primary/20 text-primary hover:bg-primary/30 active:bg-primary/40",
|
|
92
|
+
accent: "border-2 border-transparent bg-accent/20 text-accent hover:bg-accent/30 active:bg-accent/40",
|
|
93
|
+
info: "border-2 border-transparent bg-info/20 text-info hover:bg-info/30 active:bg-info/40",
|
|
94
|
+
success: "border-2 border-transparent bg-success/20 text-success hover:bg-success/30 active:bg-success/40",
|
|
95
|
+
warning: "border-2 border-transparent bg-warning/20 text-warning hover:bg-warning/30 active:bg-warning/40",
|
|
96
|
+
error: "border-2 border-transparent bg-error/20 text-error hover:bg-error/30 active:bg-error/40"
|
|
97
97
|
},
|
|
98
98
|
// None style - fully transparent, no background on any state
|
|
99
99
|
none: {
|
|
100
|
-
neutral: "bg-transparent text-foreground hover:bg-transparent active:bg-transparent",
|
|
101
|
-
primary: "bg-transparent text-primary hover:bg-transparent active:bg-transparent",
|
|
102
|
-
accent: "bg-transparent text-accent hover:bg-transparent active:bg-transparent",
|
|
103
|
-
info: "bg-transparent text-info hover:bg-transparent active:bg-transparent",
|
|
104
|
-
success: "bg-transparent text-success hover:bg-transparent active:bg-transparent",
|
|
105
|
-
warning: "bg-transparent text-warning hover:bg-transparent active:bg-transparent",
|
|
106
|
-
error: "bg-transparent text-error hover:bg-transparent active:bg-transparent"
|
|
100
|
+
neutral: "border-2 border-transparent bg-transparent text-foreground hover:bg-transparent active:bg-transparent",
|
|
101
|
+
primary: "border-2 border-transparent bg-transparent text-primary hover:bg-transparent active:bg-transparent",
|
|
102
|
+
accent: "border-2 border-transparent bg-transparent text-accent hover:bg-transparent active:bg-transparent",
|
|
103
|
+
info: "border-2 border-transparent bg-transparent text-info hover:bg-transparent active:bg-transparent",
|
|
104
|
+
success: "border-2 border-transparent bg-transparent text-success hover:bg-transparent active:bg-transparent",
|
|
105
|
+
warning: "border-2 border-transparent bg-transparent text-warning hover:bg-transparent active:bg-transparent",
|
|
106
|
+
error: "border-2 border-transparent bg-transparent text-error hover:bg-transparent active:bg-transparent"
|
|
107
107
|
},
|
|
108
108
|
// Link style - text only with underline on hover
|
|
109
109
|
link: {
|
|
110
|
-
neutral: "bg-transparent text-foreground underline-offset-4 hover:underline",
|
|
111
|
-
primary: "bg-transparent text-primary underline-offset-4 hover:underline",
|
|
112
|
-
accent: "bg-transparent text-accent underline-offset-4 hover:underline",
|
|
113
|
-
info: "bg-transparent text-info underline-offset-4 hover:underline",
|
|
114
|
-
success: "bg-transparent text-success underline-offset-4 hover:underline",
|
|
115
|
-
warning: "bg-transparent text-warning underline-offset-4 hover:underline",
|
|
116
|
-
error: "bg-transparent text-error underline-offset-4 hover:underline"
|
|
110
|
+
neutral: "border-2 border-transparent bg-transparent text-foreground underline-offset-4 hover:underline",
|
|
111
|
+
primary: "border-2 border-transparent bg-transparent text-primary underline-offset-4 hover:underline",
|
|
112
|
+
accent: "border-2 border-transparent bg-transparent text-accent underline-offset-4 hover:underline",
|
|
113
|
+
info: "border-2 border-transparent bg-transparent text-info underline-offset-4 hover:underline",
|
|
114
|
+
success: "border-2 border-transparent bg-transparent text-success underline-offset-4 hover:underline",
|
|
115
|
+
warning: "border-2 border-transparent bg-transparent text-warning underline-offset-4 hover:underline",
|
|
116
|
+
error: "border-2 border-transparent bg-transparent text-error underline-offset-4 hover:underline"
|
|
117
117
|
},
|
|
118
118
|
// Badge/Chip style - subtle filled background with border
|
|
119
119
|
badge: {
|
package/dist/theme/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sources":["../../src/theme/tokens.ts"],"sourcesContent":["/**\n * Theme color tokens and helpers for the design system.\n * Maps CSS custom properties from globals.css (light/dark) to JS for inline styles and class generation.\n */\n\nexport const colors = {\n background: 'var(--background)',\n 'background-hover': 'var(--background-hover)',\n 'background-active': 'var(--background-active)',\n foreground: 'var(--foreground)',\n 'foreground-hover': 'var(--foreground-hover)',\n card: 'var(--card)',\n 'card-hover': 'var(--card-hover)',\n 'card-active': 'var(--card-active)',\n 'card-foreground': 'var(--card-foreground)',\n popover: 'var(--popover)',\n 'popover-foreground': 'var(--popover-foreground)',\n primary: 'var(--primary)',\n 'primary-hover': 'var(--primary-hover)',\n 'primary-active': 'var(--primary-active)',\n 'primary-foreground': 'var(--primary-foreground)',\n accent: 'var(--accent)',\n 'accent-hover': 'var(--accent-hover)',\n 'accent-active': 'var(--accent-active)',\n 'accent-foreground': 'var(--accent-foreground)',\n neutral: 'var(--neutral)',\n 'neutral-hover': 'var(--neutral-hover)',\n 'neutral-active': 'var(--neutral-active)',\n 'neutral-foreground': 'var(--neutral-foreground)',\n muted: 'var(--muted)',\n 'muted-hover': 'var(--muted-hover)',\n 'muted-active': 'var(--muted-active)',\n 'muted-foreground': 'var(--muted-foreground)',\n error: 'var(--error)',\n 'error-hover': 'var(--error-hover)',\n 'error-active': 'var(--error-active)',\n 'error-foreground': 'var(--error-foreground)',\n success: 'var(--success)',\n 'success-hover': 'var(--success-hover)',\n 'success-active': 'var(--success-active)',\n 'success-foreground': 'var(--success-foreground)',\n warning: 'var(--warning)',\n 'warning-hover': 'var(--warning-hover)',\n 'warning-active': 'var(--warning-active)',\n 'warning-foreground': 'var(--warning-foreground)',\n info: 'var(--info)',\n 'info-hover': 'var(--info-hover)',\n 'info-active': 'var(--info-active)',\n 'info-foreground': 'var(--info-foreground)',\n border: 'var(--border)',\n 'border-hover': 'var(--border-hover)',\n input: 'var(--input)',\n 'input-hover': 'var(--input-hover)',\n ring: 'var(--ring)'\n};\n\nexport type ThemeColor = keyof typeof colors;\nexport const themeColorNames = Object.keys(colors) as ThemeColor[];\n\nexport const colorClassPrefixes = ['text', 'bg', 'border', 'ring', 'outline', 'decoration', 'fill', 'stroke'] as const;\nexport type ColorClassPrefix = (typeof colorClassPrefixes)[number];\nexport type ThemeColorClass = `${ColorClassPrefix}-${ThemeColor}`;\n\nexport const themeColorClasses = colorClassPrefixes.flatMap((prefix) =>\n themeColorNames.map((color) => `${prefix}-${color}` as ThemeColorClass)\n);\n\nexport type ThemeColorProp = ThemeColor | ThemeColorClass;\n\n/**\n * Core color variants used across all components\n * Use this type for component `variant` props to ensure consistency\n * Includes: neutral, primary, accent, info, success, warning, error\n */\nexport type ColorVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'info' | 'accent';\n\n/**\n * Notification/alert-specific color variants (excludes neutral/primary/accent)\n * For feedback components like Alert, Toast, etc.\n */\nexport type NotificationColorVariant = Exclude<ColorVariant, 'neutral' | 'primary' | 'accent'>;\n\n/**\n * Common color variants for most components (the essential 5)\n * Includes: neutral, primary, success, warning, error\n */\nexport type CommonColorVariant = Extract<ColorVariant, 'neutral' | 'primary' | 'success' | 'warning' | 'error'>;\n\nconst outlineBaseClasses =\n 'border-2 bg-transparent transition-colors transition-shadow duration-200 ease-out focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-transparent' as const;\n\n/**\n * Type-safe record ensuring all color variants are defined for each style\n */\ntype ColorVariantRecord = Record<ColorVariant, string>;\n\n/**\n * Standardized color variant classes for consistent component styling\n * All variants support: neutral, primary, accent, info, success, warning, error\n */\nexport const colorVariants: {\n solid: ColorVariantRecord;\n outline: ColorVariantRecord;\n ghost: ColorVariantRecord;\n soft: ColorVariantRecord;\n link: ColorVariantRecord;\n none: ColorVariantRecord;\n badge: ColorVariantRecord & { inverted: ColorVariantRecord };\n alert: ColorVariantRecord;\n breadcrumb: { link: ColorVariantRecord; active: ColorVariantRecord };\n} = {\n // Solid buttons/elements - filled background\n solid: {\n neutral: 'bg-neutral text-neutral-foreground hover:bg-neutral-hover active:bg-neutral-active',\n primary: 'bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active',\n accent: 'bg-accent text-accent-foreground hover:bg-accent-hover active:bg-accent-active',\n info: 'bg-info text-info-foreground hover:bg-info-hover active:bg-info-active',\n success: 'bg-success text-success-foreground hover:bg-success-hover active:bg-success-active',\n warning: 'bg-warning text-warning-foreground hover:bg-warning-hover active:bg-warning-active',\n error: 'bg-error text-error-foreground hover:bg-error-hover active:bg-error-active'\n },\n\n // Outline style - transparent with border\n outline: {\n neutral: `${outlineBaseClasses} border-neutral text-neutral hover:border-neutral-hover hover:text-neutral-hover hover:shadow-[inset_0_0_0_1px_var(--neutral))] focus-visible:shadow-[inset_0_0_0_1px_var(--neutral))] focus-visible:outline-neutral/3`,\n primary: `${outlineBaseClasses} border-primary text-primary hover:border-primary-hover hover:text-primary-hover hover:shadow-[inset_0_0_0_1px_var(--primary))] focus-visible:shadow-[inset_0_0_0_1px_var(--primary))] focus-visible:outline-primary/3`,\n accent: `${outlineBaseClasses} border-accent text-accent hover:border-accent-hover hover:text-accent-hover hover:shadow-[inset_0_0_0_1px_var(--accent))] focus-visible:shadow-[inset_0_0_0_1px_var(--accent))] focus-visible:outline-accent/3`,\n info: `${outlineBaseClasses} border-info text-info hover:border-info-hover hover:text-info-hover hover:shadow-[inset_0_0_0_1px_var(--info))] focus-visible:shadow-[inset_0_0_0_1px_var(--info))] focus-visible:outline-info/3`,\n success: `${outlineBaseClasses} border-success text-success hover:border-success-hover hover:text-success-hover hover:shadow-[inset_0_0_0_1px_var(--success))] focus-visible:shadow-[inset_0_0_0_1px_var(--success))] focus-visible:outline-success/3`,\n warning: `${outlineBaseClasses} border-warning text-warning hover:border-warning-hover hover:text-warning-hover hover:shadow-[inset_0_0_0_1px_var(--warning))] focus-visible:shadow-[inset_0_0_0_1px_var(--warning))] focus-visible:outline-warning/3`,\n error: `${outlineBaseClasses} border-error text-error hover:border-error-hover hover:text-error-hover hover:shadow-[inset_0_0_0_1px_var(--error))] focus-visible:shadow-[inset_0_0_0_1px_var(--error))] focus-visible:outline-error/5`\n },\n\n // Ghost style - transparent with subtle hover\n ghost: {\n neutral: 'bg-transparent text-foreground hover:bg-neutral/10 active:bg-neutral/20',\n primary: 'bg-transparent text-primary hover:bg-primary/10 active:bg-primary/20',\n accent: 'bg-transparent text-accent hover:bg-accent/10 active:bg-accent/20',\n info: 'bg-transparent text-info hover:bg-info/10 active:bg-info/20',\n success: 'bg-transparent text-success hover:bg-success/10 active:bg-success/20',\n warning: 'bg-transparent text-warning hover:bg-warning/10 active:bg-warning/20',\n error: 'bg-transparent text-error hover:bg-error/10 active:bg-error/20'\n },\n\n // Soft style - subtle background\n soft: {\n neutral: 'bg-neutral/20 text-neutral hover:bg-neutral/30 active:bg-neutral/40',\n primary: 'bg-primary/20 text-primary hover:bg-primary/30 active:bg-primary/40',\n accent: 'bg-accent/20 text-accent hover:bg-accent/30 active:bg-accent/40',\n info: 'bg-info/20 text-info hover:bg-info/30 active:bg-info/40',\n success: 'bg-success/20 text-success hover:bg-success/30 active:bg-success/40',\n warning: 'bg-warning/20 text-warning hover:bg-warning/30 active:bg-warning/40',\n error: 'bg-error/20 text-error hover:bg-error/30 active:bg-error/40'\n },\n\n // None style - fully transparent, no background on any state\n none: {\n neutral: 'bg-transparent text-foreground hover:bg-transparent active:bg-transparent',\n primary: 'bg-transparent text-primary hover:bg-transparent active:bg-transparent',\n accent: 'bg-transparent text-accent hover:bg-transparent active:bg-transparent',\n info: 'bg-transparent text-info hover:bg-transparent active:bg-transparent',\n success: 'bg-transparent text-success hover:bg-transparent active:bg-transparent',\n warning: 'bg-transparent text-warning hover:bg-transparent active:bg-transparent',\n error: 'bg-transparent text-error hover:bg-transparent active:bg-transparent'\n },\n\n // Link style - text only with underline on hover\n link: {\n neutral: 'bg-transparent text-foreground underline-offset-4 hover:underline',\n primary: 'bg-transparent text-primary underline-offset-4 hover:underline',\n accent: 'bg-transparent text-accent underline-offset-4 hover:underline',\n info: 'bg-transparent text-info underline-offset-4 hover:underline',\n success: 'bg-transparent text-success underline-offset-4 hover:underline',\n warning: 'bg-transparent text-warning underline-offset-4 hover:underline',\n error: 'bg-transparent text-error underline-offset-4 hover:underline'\n },\n\n // Badge/Chip style - subtle filled background with border\n badge: {\n neutral: 'bg-neutral/5 text-neutral border border-neutral',\n primary: 'bg-primary/5 text-primary border border-primary',\n accent: 'bg-accent/5 text-accent border border-accent',\n info: 'bg-info/5 text-info border border-info',\n success: 'bg-success/5 text-success border border-success',\n warning: 'bg-warning/5 text-warning border border-warning',\n error: 'bg-error/5 text-error border border-error',\n inverted: {\n neutral: 'bg-neutral/40 text-neutral-foreground border border-neutral',\n primary: 'bg-primary/90 text-primary-foreground border border-primary-foreground',\n accent: 'bg-accent/90 text-accent-foreground border border-accent',\n info: 'bg-info/90 text-info-foreground border border-info',\n success: 'bg-success/90 text-success-foreground border border-success',\n warning: 'bg-warning/90 text-warning-foreground border border-warning',\n error: 'bg-error/90 text-error-foreground border border-error'\n }\n },\n\n // Alert style - translucent background with border\n alert: {\n neutral: 'bg-neutral/30 text-foreground border-neutral/50 backdrop-blur-3xl',\n primary: 'bg-primary/30 text-foreground border-primary/50 backdrop-blur-3xl',\n accent: 'bg-accent/30 text-foreground border-accent/50 backdrop-blur-3xl',\n info: 'bg-info/30 text-foreground border-info/50 backdrop-blur-3xl',\n success: 'bg-success/30 text-foreground border-success/50 backdrop-blur-3xl',\n warning: 'bg-warning/30 text-foreground border-warning/50 backdrop-blur-3xl',\n error: 'bg-error/30 text-foreground border-error/50 backdrop-blur-3xl'\n },\n\n // Breadcrumb style - link and active states\n breadcrumb: {\n link: {\n neutral:\n 'text-neutral hover:text-neutral-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-neutral-ring rounded px-1 -mx-1',\n primary:\n 'text-primary hover:text-primary-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary-ring rounded px-1 -mx-1',\n accent:\n 'text-accent hover:text-accent-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-accent-ring rounded px-1 -mx-1',\n info: 'text-info hover:text-info-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-info-ring rounded px-1 -mx-1',\n success:\n 'text-success hover:text-success-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-success-ring rounded px-1 -mx-1',\n warning:\n 'text-warning hover:text-warning-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-warning-ring rounded px-1 -mx-1',\n error:\n 'text-error hover:text-error-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-error-ring rounded px-1 -mx-1'\n },\n active: {\n neutral: 'text-neutral-active font-medium',\n primary: 'text-primary-active font-medium',\n accent: 'text-accent-active font-medium',\n info: 'text-info-active font-medium',\n success: 'text-success-active font-medium',\n warning: 'text-warning-active font-medium',\n error: 'text-error-active font-medium'\n }\n }\n};\n\nexport type ColorVariantStyle = keyof typeof colorVariants;\nexport type ColorVariantKey<T extends ColorVariantStyle> = keyof (typeof colorVariants)[T];\n\nexport const radii = {\n sm: '0.25rem',\n md: '0.5rem',\n lg: '0.75rem',\n xl: '1rem'\n};\n\nexport const fonts = {\n sans: \"'Inter', system-ui, sans-serif\",\n mono: \"'JetBrains Mono', monospace\"\n};\n\nexport const alignments = ['left', 'center', 'right'] as const;\nexport type Alignment = (typeof alignments)[number];\n\nexport const inputAlignClasses: Record<Alignment, string> = {\n left: 'mr-auto',\n center: 'mx-auto',\n right: 'ml-auto'\n};\n\n/**\n * HTML autocomplete attribute values for form inputs\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete\n */\nexport const autocompleteOptions = [\n 'on',\n 'off',\n 'address-line1',\n 'address-line2',\n 'address-line3',\n 'address-level1',\n 'address-level2',\n 'address-level3',\n 'address-level4',\n 'street-address',\n 'country',\n 'country-name',\n 'postal-code',\n 'name',\n 'additional-name',\n 'family-name',\n 'given-name',\n 'honoric-prefix',\n 'honoric-suffix',\n 'nickname',\n 'organization-title',\n 'username',\n 'new-password',\n 'current-password',\n 'bday',\n 'bday-day',\n 'bday-month',\n 'bday-year',\n 'sex',\n 'one-time-code',\n 'organization',\n 'cc-name',\n 'cc-given-name',\n 'cc-additional-name',\n 'cc-family-name',\n 'cc-number',\n 'cc-exp',\n 'cc-exp-month',\n 'cc-exp-year',\n 'cc-csc',\n 'cc-type',\n 'transaction-currency',\n 'transaction-amount',\n 'language',\n 'url',\n 'email',\n 'photo',\n 'tel',\n 'tel-country-code',\n 'tel-national',\n 'tel-area-code',\n 'tel-local',\n 'tel-local-prefix',\n 'tel-local-suffix',\n 'tel-extension',\n 'impp'\n] as const;\n\nexport type AutocompleteOption = (typeof autocompleteOptions)[number];\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tokens.js","sources":["../../src/theme/tokens.ts"],"sourcesContent":["/**\n * Theme color tokens and helpers for the design system.\n * Maps CSS custom properties from globals.css (light/dark) to JS for inline styles and class generation.\n */\n\nexport const colors = {\n background: 'var(--background)',\n 'background-hover': 'var(--background-hover)',\n 'background-active': 'var(--background-active)',\n foreground: 'var(--foreground)',\n 'foreground-hover': 'var(--foreground-hover)',\n card: 'var(--card)',\n 'card-hover': 'var(--card-hover)',\n 'card-active': 'var(--card-active)',\n 'card-foreground': 'var(--card-foreground)',\n popover: 'var(--popover)',\n 'popover-foreground': 'var(--popover-foreground)',\n primary: 'var(--primary)',\n 'primary-hover': 'var(--primary-hover)',\n 'primary-active': 'var(--primary-active)',\n 'primary-foreground': 'var(--primary-foreground)',\n accent: 'var(--accent)',\n 'accent-hover': 'var(--accent-hover)',\n 'accent-active': 'var(--accent-active)',\n 'accent-foreground': 'var(--accent-foreground)',\n neutral: 'var(--neutral)',\n 'neutral-hover': 'var(--neutral-hover)',\n 'neutral-active': 'var(--neutral-active)',\n 'neutral-foreground': 'var(--neutral-foreground)',\n muted: 'var(--muted)',\n 'muted-hover': 'var(--muted-hover)',\n 'muted-active': 'var(--muted-active)',\n 'muted-foreground': 'var(--muted-foreground)',\n error: 'var(--error)',\n 'error-hover': 'var(--error-hover)',\n 'error-active': 'var(--error-active)',\n 'error-foreground': 'var(--error-foreground)',\n success: 'var(--success)',\n 'success-hover': 'var(--success-hover)',\n 'success-active': 'var(--success-active)',\n 'success-foreground': 'var(--success-foreground)',\n warning: 'var(--warning)',\n 'warning-hover': 'var(--warning-hover)',\n 'warning-active': 'var(--warning-active)',\n 'warning-foreground': 'var(--warning-foreground)',\n info: 'var(--info)',\n 'info-hover': 'var(--info-hover)',\n 'info-active': 'var(--info-active)',\n 'info-foreground': 'var(--info-foreground)',\n border: 'var(--border)',\n 'border-hover': 'var(--border-hover)',\n input: 'var(--input)',\n 'input-hover': 'var(--input-hover)',\n ring: 'var(--ring)'\n};\n\nexport type ThemeColor = keyof typeof colors;\nexport const themeColorNames = Object.keys(colors) as ThemeColor[];\n\nexport const colorClassPrefixes = ['text', 'bg', 'border', 'ring', 'outline', 'decoration', 'fill', 'stroke'] as const;\nexport type ColorClassPrefix = (typeof colorClassPrefixes)[number];\nexport type ThemeColorClass = `${ColorClassPrefix}-${ThemeColor}`;\n\nexport const themeColorClasses = colorClassPrefixes.flatMap((prefix) =>\n themeColorNames.map((color) => `${prefix}-${color}` as ThemeColorClass)\n);\n\nexport type ThemeColorProp = ThemeColor | ThemeColorClass;\n\n/**\n * Core color variants used across all components\n * Use this type for component `variant` props to ensure consistency\n * Includes: neutral, primary, accent, info, success, warning, error\n */\nexport type ColorVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'error' | 'info' | 'accent';\n\n/**\n * Notification/alert-specific color variants (excludes neutral/primary/accent)\n * For feedback components like Alert, Toast, etc.\n */\nexport type NotificationColorVariant = Exclude<ColorVariant, 'neutral' | 'primary' | 'accent'>;\n\n/**\n * Common color variants for most components (the essential 5)\n * Includes: neutral, primary, success, warning, error\n */\nexport type CommonColorVariant = Extract<ColorVariant, 'neutral' | 'primary' | 'success' | 'warning' | 'error'>;\n\nconst outlineBaseClasses =\n 'border-2 bg-transparent transition-colors transition-shadow duration-200 ease-out focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-transparent' as const;\n\n/**\n * Type-safe record ensuring all color variants are defined for each style\n */\ntype ColorVariantRecord = Record<ColorVariant, string>;\n\n/**\n * Standardized color variant classes for consistent component styling\n * All variants support: neutral, primary, accent, info, success, warning, error\n */\nexport const colorVariants: {\n solid: ColorVariantRecord;\n outline: ColorVariantRecord;\n ghost: ColorVariantRecord;\n soft: ColorVariantRecord;\n link: ColorVariantRecord;\n none: ColorVariantRecord;\n badge: ColorVariantRecord & { inverted: ColorVariantRecord };\n alert: ColorVariantRecord;\n breadcrumb: { link: ColorVariantRecord; active: ColorVariantRecord };\n} = {\n // Solid buttons/elements - filled background\n solid: {\n neutral:\n 'border-2 border-transparent bg-neutral text-neutral-foreground hover:bg-neutral-hover active:bg-neutral-active',\n primary:\n 'border-2 border-transparent bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active',\n accent:\n 'border-2 border-transparent bg-accent text-accent-foreground hover:bg-accent-hover active:bg-accent-active',\n info: 'border-2 border-transparent bg-info text-info-foreground hover:bg-info-hover active:bg-info-active',\n success:\n 'border-2 border-transparent bg-success text-success-foreground hover:bg-success-hover active:bg-success-active',\n warning:\n 'border-2 border-transparent bg-warning text-warning-foreground hover:bg-warning-hover active:bg-warning-active',\n error: 'border-2 border-transparent bg-error text-error-foreground hover:bg-error-hover active:bg-error-active'\n },\n\n // Outline style - transparent with border\n outline: {\n neutral: `${outlineBaseClasses} border-neutral text-neutral hover:border-neutral-hover hover:text-neutral-hover hover:shadow-[inset_0_0_0_1px_var(--neutral))] focus-visible:shadow-[inset_0_0_0_1px_var(--neutral))] focus-visible:outline-neutral/3`,\n primary: `${outlineBaseClasses} border-primary text-primary hover:border-primary-hover hover:text-primary-hover hover:shadow-[inset_0_0_0_1px_var(--primary))] focus-visible:shadow-[inset_0_0_0_1px_var(--primary))] focus-visible:outline-primary/3`,\n accent: `${outlineBaseClasses} border-accent text-accent hover:border-accent-hover hover:text-accent-hover hover:shadow-[inset_0_0_0_1px_var(--accent))] focus-visible:shadow-[inset_0_0_0_1px_var(--accent))] focus-visible:outline-accent/3`,\n info: `${outlineBaseClasses} border-info text-info hover:border-info-hover hover:text-info-hover hover:shadow-[inset_0_0_0_1px_var(--info))] focus-visible:shadow-[inset_0_0_0_1px_var(--info))] focus-visible:outline-info/3`,\n success: `${outlineBaseClasses} border-success text-success hover:border-success-hover hover:text-success-hover hover:shadow-[inset_0_0_0_1px_var(--success))] focus-visible:shadow-[inset_0_0_0_1px_var(--success))] focus-visible:outline-success/3`,\n warning: `${outlineBaseClasses} border-warning text-warning hover:border-warning-hover hover:text-warning-hover hover:shadow-[inset_0_0_0_1px_var(--warning))] focus-visible:shadow-[inset_0_0_0_1px_var(--warning))] focus-visible:outline-warning/3`,\n error: `${outlineBaseClasses} border-error text-error hover:border-error-hover hover:text-error-hover hover:shadow-[inset_0_0_0_1px_var(--error))] focus-visible:shadow-[inset_0_0_0_1px_var(--error))] focus-visible:outline-error/5`\n },\n\n // Ghost style - transparent with subtle hover\n ghost: {\n neutral: 'border-2 border-transparent bg-transparent text-foreground hover:bg-neutral/10 active:bg-neutral/20',\n primary: 'border-2 border-transparent bg-transparent text-primary hover:bg-primary/10 active:bg-primary/20',\n accent: 'border-2 border-transparent bg-transparent text-accent hover:bg-accent/10 active:bg-accent/20',\n info: 'border-2 border-transparent bg-transparent text-info hover:bg-info/10 active:bg-info/20',\n success: 'border-2 border-transparent bg-transparent text-success hover:bg-success/10 active:bg-success/20',\n warning: 'border-2 border-transparent bg-transparent text-warning hover:bg-warning/10 active:bg-warning/20',\n error: 'border-2 border-transparent bg-transparent text-error hover:bg-error/10 active:bg-error/20'\n },\n\n // Soft style - subtle background\n soft: {\n neutral: 'border-2 border-transparent bg-neutral/20 text-neutral hover:bg-neutral/30 active:bg-neutral/40',\n primary: 'border-2 border-transparent bg-primary/20 text-primary hover:bg-primary/30 active:bg-primary/40',\n accent: 'border-2 border-transparent bg-accent/20 text-accent hover:bg-accent/30 active:bg-accent/40',\n info: 'border-2 border-transparent bg-info/20 text-info hover:bg-info/30 active:bg-info/40',\n success: 'border-2 border-transparent bg-success/20 text-success hover:bg-success/30 active:bg-success/40',\n warning: 'border-2 border-transparent bg-warning/20 text-warning hover:bg-warning/30 active:bg-warning/40',\n error: 'border-2 border-transparent bg-error/20 text-error hover:bg-error/30 active:bg-error/40'\n },\n\n // None style - fully transparent, no background on any state\n none: {\n neutral: 'border-2 border-transparent bg-transparent text-foreground hover:bg-transparent active:bg-transparent',\n primary: 'border-2 border-transparent bg-transparent text-primary hover:bg-transparent active:bg-transparent',\n accent: 'border-2 border-transparent bg-transparent text-accent hover:bg-transparent active:bg-transparent',\n info: 'border-2 border-transparent bg-transparent text-info hover:bg-transparent active:bg-transparent',\n success: 'border-2 border-transparent bg-transparent text-success hover:bg-transparent active:bg-transparent',\n warning: 'border-2 border-transparent bg-transparent text-warning hover:bg-transparent active:bg-transparent',\n error: 'border-2 border-transparent bg-transparent text-error hover:bg-transparent active:bg-transparent'\n },\n\n // Link style - text only with underline on hover\n link: {\n neutral: 'border-2 border-transparent bg-transparent text-foreground underline-offset-4 hover:underline',\n primary: 'border-2 border-transparent bg-transparent text-primary underline-offset-4 hover:underline',\n accent: 'border-2 border-transparent bg-transparent text-accent underline-offset-4 hover:underline',\n info: 'border-2 border-transparent bg-transparent text-info underline-offset-4 hover:underline',\n success: 'border-2 border-transparent bg-transparent text-success underline-offset-4 hover:underline',\n warning: 'border-2 border-transparent bg-transparent text-warning underline-offset-4 hover:underline',\n error: 'border-2 border-transparent bg-transparent text-error underline-offset-4 hover:underline'\n },\n\n // Badge/Chip style - subtle filled background with border\n badge: {\n neutral: 'bg-neutral/5 text-neutral border border-neutral',\n primary: 'bg-primary/5 text-primary border border-primary',\n accent: 'bg-accent/5 text-accent border border-accent',\n info: 'bg-info/5 text-info border border-info',\n success: 'bg-success/5 text-success border border-success',\n warning: 'bg-warning/5 text-warning border border-warning',\n error: 'bg-error/5 text-error border border-error',\n inverted: {\n neutral: 'bg-neutral/40 text-neutral-foreground border border-neutral',\n primary: 'bg-primary/90 text-primary-foreground border border-primary-foreground',\n accent: 'bg-accent/90 text-accent-foreground border border-accent',\n info: 'bg-info/90 text-info-foreground border border-info',\n success: 'bg-success/90 text-success-foreground border border-success',\n warning: 'bg-warning/90 text-warning-foreground border border-warning',\n error: 'bg-error/90 text-error-foreground border border-error'\n }\n },\n\n // Alert style - translucent background with border\n alert: {\n neutral: 'bg-neutral/30 text-foreground border-neutral/50 backdrop-blur-3xl',\n primary: 'bg-primary/30 text-foreground border-primary/50 backdrop-blur-3xl',\n accent: 'bg-accent/30 text-foreground border-accent/50 backdrop-blur-3xl',\n info: 'bg-info/30 text-foreground border-info/50 backdrop-blur-3xl',\n success: 'bg-success/30 text-foreground border-success/50 backdrop-blur-3xl',\n warning: 'bg-warning/30 text-foreground border-warning/50 backdrop-blur-3xl',\n error: 'bg-error/30 text-foreground border-error/50 backdrop-blur-3xl'\n },\n\n // Breadcrumb style - link and active states\n breadcrumb: {\n link: {\n neutral:\n 'text-neutral hover:text-neutral-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-neutral-ring rounded px-1 -mx-1',\n primary:\n 'text-primary hover:text-primary-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary-ring rounded px-1 -mx-1',\n accent:\n 'text-accent hover:text-accent-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-accent-ring rounded px-1 -mx-1',\n info: 'text-info hover:text-info-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-info-ring rounded px-1 -mx-1',\n success:\n 'text-success hover:text-success-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-success-ring rounded px-1 -mx-1',\n warning:\n 'text-warning hover:text-warning-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-warning-ring rounded px-1 -mx-1',\n error:\n 'text-error hover:text-error-hover hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-error-ring rounded px-1 -mx-1'\n },\n active: {\n neutral: 'text-neutral-active font-medium',\n primary: 'text-primary-active font-medium',\n accent: 'text-accent-active font-medium',\n info: 'text-info-active font-medium',\n success: 'text-success-active font-medium',\n warning: 'text-warning-active font-medium',\n error: 'text-error-active font-medium'\n }\n }\n};\n\nexport type ColorVariantStyle = keyof typeof colorVariants;\nexport type ColorVariantKey<T extends ColorVariantStyle> = keyof (typeof colorVariants)[T];\n\nexport const radii = {\n sm: '0.25rem',\n md: '0.5rem',\n lg: '0.75rem',\n xl: '1rem'\n};\n\nexport const fonts = {\n sans: \"'Inter', system-ui, sans-serif\",\n mono: \"'JetBrains Mono', monospace\"\n};\n\nexport const alignments = ['left', 'center', 'right'] as const;\nexport type Alignment = (typeof alignments)[number];\n\nexport const inputAlignClasses: Record<Alignment, string> = {\n left: 'mr-auto',\n center: 'mx-auto',\n right: 'ml-auto'\n};\n\n/**\n * HTML autocomplete attribute values for form inputs\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete\n */\nexport const autocompleteOptions = [\n 'on',\n 'off',\n 'address-line1',\n 'address-line2',\n 'address-line3',\n 'address-level1',\n 'address-level2',\n 'address-level3',\n 'address-level4',\n 'street-address',\n 'country',\n 'country-name',\n 'postal-code',\n 'name',\n 'additional-name',\n 'family-name',\n 'given-name',\n 'honoric-prefix',\n 'honoric-suffix',\n 'nickname',\n 'organization-title',\n 'username',\n 'new-password',\n 'current-password',\n 'bday',\n 'bday-day',\n 'bday-month',\n 'bday-year',\n 'sex',\n 'one-time-code',\n 'organization',\n 'cc-name',\n 'cc-given-name',\n 'cc-additional-name',\n 'cc-family-name',\n 'cc-number',\n 'cc-exp',\n 'cc-exp-month',\n 'cc-exp-year',\n 'cc-csc',\n 'cc-type',\n 'transaction-currency',\n 'transaction-amount',\n 'language',\n 'url',\n 'email',\n 'photo',\n 'tel',\n 'tel-country-code',\n 'tel-national',\n 'tel-area-code',\n 'tel-local',\n 'tel-local-prefix',\n 'tel-local-suffix',\n 'tel-extension',\n 'impp'\n] as const;\n\nexport type AutocompleteOption = (typeof autocompleteOptions)[number];\n"],"names":[],"mappings":"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"}
|