@cruxkit/button 0.0.4 → 0.0.6
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/README.md +8 -5
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div align="center">
|
|
11
|
-
<img src="https://img.shields.io/badge/v-0.0.
|
|
11
|
+
<img src="https://img.shields.io/badge/v-0.0.6-black"/>
|
|
12
12
|
<a href="https://github.com/cruxkit-org"><img src="https://img.shields.io/badge/🔥-@cruxkit-black"/></a>
|
|
13
13
|
<br>
|
|
14
14
|
<img src="https://img.shields.io/badge/coverage-100%25-brightgreen" alt="Test Coverage" />
|
|
@@ -70,13 +70,15 @@
|
|
|
70
70
|
Save
|
|
71
71
|
</Button>
|
|
72
72
|
|
|
73
|
+
<Button icon={Icon('plus')} variant="ghost" />
|
|
74
|
+
|
|
73
75
|
<Button
|
|
74
76
|
variant="outline"
|
|
75
77
|
color="success"
|
|
76
78
|
size="sm"
|
|
77
79
|
fullWidth
|
|
78
|
-
leftIcon=
|
|
79
|
-
rightIcon={
|
|
80
|
+
leftIcon={Icon('check')}
|
|
81
|
+
rightIcon={Icon('arrow-right')}
|
|
80
82
|
>
|
|
81
83
|
Continue
|
|
82
84
|
</Button>
|
|
@@ -124,8 +126,9 @@
|
|
|
124
126
|
disabled? : boolean;
|
|
125
127
|
loading? : boolean;
|
|
126
128
|
|
|
127
|
-
leftIcon? :
|
|
128
|
-
rightIcon? :
|
|
129
|
+
leftIcon? : JSXElement;
|
|
130
|
+
rightIcon? : JSXElement;
|
|
131
|
+
icon? : JSXElement;
|
|
129
132
|
|
|
130
133
|
as? : ContainerAs;
|
|
131
134
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var container=require('@cruxkit/container'),text=require('@cruxkit/text'),
|
|
1
|
+
'use strict';var container=require('@cruxkit/container'),text=require('@cruxkit/text'),client=require('@cruxjs/client'),jsxRuntime=require('@minejs/jsx/jsx-runtime');var K={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},Q={sm:1,md:2,lg:2},U={sm:"sm",md:"md",lg:"lg"};var Z={solid:{brand:["bg-brand","text-inverse","border","border-transparent","hover:bg-brand-hover","active:bg-brand-active","active:scale-95","shadow-sm","hover:shadow-md"],success:["bg-success","text-inverse","border","border-transparent","hover:bg-success-hover","active:bg-success-active","active:scale-95","shadow-sm","hover:shadow-md"],warning:["bg-warning","text-inverse","border","border-transparent","hover:bg-warning-hover","active:bg-warning-active","active:scale-95","shadow-sm","hover:shadow-md"],error:["bg-error","text-inverse","border","border-transparent","hover:bg-error-hover","active:bg-error-active","active:scale-95","shadow-sm","hover:shadow-md"],neutral:["bg-surface","text-1","border","border-1","hover:bg-raised","active:bg-tertiary","active:scale-95","shadow-sm","hover:shadow-md"]},outline:{brand:["bg-transparent","text-brand","border","border-brand","hover:bg-brand-subtle","active:bg-brand-subtle","active:scale-95"],success:["bg-transparent","text-success","border","border-success","hover:bg-success-subtle","active:bg-success-subtle","active:scale-95"],warning:["bg-transparent","text-warning","border","border-warning","hover:bg-warning-subtle","active:bg-warning-subtle","active:scale-95"],error:["bg-transparent","text-error","border","border-error","hover:bg-error-subtle","active:bg-error-subtle","active:scale-95"],neutral:["bg-transparent","text-1","border","border-1","hover:bg-raised","active:bg-tertiary","active:scale-95"]},ghost:{brand:["bg-transparent","text-brand","border","border-transparent","hover:bg-brand-subtle","active:bg-brand-subtle","active:scale-95"],success:["bg-transparent","text-success","border","border-transparent","hover:bg-success-subtle","active:bg-success-subtle","active:scale-95"],warning:["bg-transparent","text-warning","border","border-transparent","hover:bg-warning-subtle","active:bg-warning-subtle","active:scale-95"],error:["bg-transparent","text-error","border","border-transparent","hover:bg-error-subtle","active:bg-error-subtle","active:scale-95"],neutral:["bg-transparent","text-1","border","border-transparent","hover:bg-raised","active:bg-tertiary","active:scale-95"]},link:{brand:["bg-transparent","text-brand","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],success:["bg-transparent","text-success","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],warning:["bg-transparent","text-warning","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],error:["bg-transparent","text-error","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],neutral:["bg-transparent","text-1","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"]}},z=new WeakSet,R=new WeakSet,L=new WeakSet,$=5,ee=100;function p(a,v){return a?jsxRuntime.jsx("span",{className:"inline-flex shrink-0",children:a}):null}function ae(a){let{variant:v="solid",color:k="brand",size:r="md",fullWidth:C=false,disabled:A=false,loading:N=false,leftIcon:P,rightIcon:q,icon:m,as:f="button",text:t,children:H,className:I,type:X="button",onMount:c,onLoad:d,...J}=a,_=["inline-flex","items-center","justify-center","font-medium","transition-all","duration-150","select-none","focus:outline-none","focus-visible:ring","focus-visible:ring-offset-2"],l=[];(N||A)&&l.push("opacity-50","cursor-not-allowed","pointer-events-none"),C&&l.push("w-full");let W=Z[v][k],j=[..._,...l,...W,I].filter(Boolean).join(" "),b=K[r],F=Q[r],O=U[r],n=[],h=p(P),x=p(q),w=p(m);h&&n.push(h),w&&n.push(w);let y=typeof t=="string"&&t.includes("."),o=H??(y?"--":t);o!=null&&o!==""&&n.push(jsxRuntime.jsx(text.Text,{as:"span",size:O,"data-role":"btn-label",className:"flex items-center",children:o})),x&&n.push(x);let V=f==="button"?{type:X}:{},T=y,S=c||d||T?e=>{if(e){if(c&&!z.has(e)&&(z.add(e),c(e)),d&&!R.has(e)){R.add(e);let i=()=>{d(e);};typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>{requestAnimationFrame(i);}):setTimeout(i,0);}if(T&&!L.has(e)){let i=s=>{typeof queueMicrotask=="function"?queueMicrotask(s):setTimeout(s,0);},B=s=>{let M=e.querySelector('[data-role="btn-label"]');if(!M||typeof t!="string")return;let u=client.t(t,void 0,"--");if(u!==t&&u!=="--"||s>=$){M.textContent=String(u),L.add(e);return}setTimeout(()=>{B(s+1);},ee);};i(()=>{B(0);});}}}:void 0,E={as:f,display:"inline-flex",align:"center",justify:"center",gap:F,px:m?b.py:b.px,py:b.py,radius:"md",className:j,...V,...J};return S&&(E.ref=S),jsxRuntime.jsx(container.Container,{...E,children:n})}exports.Button=ae;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/kit/button.tsx"],"names":["sizePaddingMap","sizeGapMap","labelSizeMap","iconSizeMap","variantClasses","mountedElements","loadedElements","translatedElements","MAX_TRANSLATION_ATTEMPTS","TRANSLATION_RETRY_DELAY_MS","renderIcon","icon","size","iconSize","jsx","Icon","resolvedSize","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","text","children","className","type","onMount","onLoad","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","isKeyLikeText","label","Text","elementTypeProps","shouldTranslate","handleRef","element","runLoad","schedule","fn","attemptTranslate","attempt","labelNode","translated","t","containerProps","Container"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/kit/button.tsx\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import type { JSXElement } from '@minejs/jsx';\r\n import { Container } from '@cruxkit/container';\r\n import { Text } from '@cruxkit/text';\r\n import { Icon, type IconProps, type IconName, type IconConfig } from '@cruxkit/icon';\r\n import type { ButtonProps, ButtonSize, ButtonColor, ButtonVariant } from '../types';\r\n import { t } from '@cruxjs/client';\r\n \r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\r\n\r\n const sizePaddingMap: Record<ButtonSize, { px: 3 | 4 | 6; py: 1 | 2 | 3 }> = {\r\n sm: { px: 3, py: 1 },\r\n md: { px: 4, py: 2 },\r\n lg: { px: 6, py: 3 }\r\n };\r\n\r\n const sizeGapMap: Record<ButtonSize, 1 | 2> = {\r\n sm: 1,\r\n md: 2,\r\n lg: 2\r\n };\r\n\r\n const labelSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const iconSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const variantClasses: Record<ButtonVariant, Record<ButtonColor, string[]>> = {\r\n solid: {\r\n brand: [\r\n 'bg-brand',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-hover',\r\n 'active:bg-brand-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n success: [\r\n 'bg-success',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-hover',\r\n 'active:bg-success-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n warning: [\r\n 'bg-warning',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-hover',\r\n 'active:bg-warning-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n error: [\r\n 'bg-error',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-hover',\r\n 'active:bg-error-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n neutral: [\r\n 'bg-surface',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ]\r\n },\r\n outline: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-brand',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-success',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-warning',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-error',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n ghost: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n link: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ]\r\n }\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n const mountedElements = new WeakSet<HTMLElement>();\r\n const loadedElements = new WeakSet<HTMLElement>();\r\n const translatedElements = new WeakSet<HTMLElement>();\r\n const MAX_TRANSLATION_ATTEMPTS = 5;\r\n const TRANSLATION_RETRY_DELAY_MS = 100;\r\n\r\n type ButtonContainerProps = {\r\n as?: unknown;\r\n display?: string;\r\n align?: string;\r\n justify?: string;\r\n gap?: number;\r\n px?: number;\r\n py?: number;\r\n radius?: string;\r\n className?: string;\r\n ref?: (element: HTMLElement | null) => void;\r\n } & Record<string, unknown>;\r\n\r\n function renderIcon(icon: IconProps | IconName | undefined, size: ButtonSize): JSXElement | null {\r\n if (!icon) return null;\r\n\r\n const iconSize = iconSizeMap[size];\r\n\r\n if (typeof icon === 'string') {\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n <Icon name={icon as IconName} size={iconSize} />\r\n </span>\r\n );\r\n }\r\n\r\n const resolvedSize = ((icon as IconProps) as IconConfig).size ?? iconSize;\r\n\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n <Icon {...icon} size={resolvedSize} />\r\n </span>\r\n );\r\n }\r\n\r\n /**\r\n * A polymorphic button component that supports multiple variants, colors, sizes, and states.\r\n *\r\n * @param props - The properties for the Button component.\r\n * @param props.variant - Visual style variant: `'solid' | 'outline' | 'ghost' | 'link'`.\r\n * @param props.color - Color theme: `'brand' | 'success' | 'warning' | 'error' | 'neutral'`.\r\n * @param props.size - Size scale: `'sm' | 'md' | 'lg'`.\r\n * @param props.fullWidth - Whether the button spans the full width of its container.\r\n * @param props.disabled - Whether the button is disabled.\r\n * @param props.loading - Whether the button is in a loading state (disables interaction).\r\n * @param props.leftIcon - Optional icon placed to the left of the label (string name or IconProps).\r\n * @param props.rightIcon - Optional icon placed to the right of the label (string name or IconProps).\r\n * @param props.as - Element type to render: `'button' | 'a' | any polymorphic component`.\r\n * @param props.children - Button label content.\r\n * @param props.className - Additional CSS classes appended to the built-in styles.\r\n * @param props.type - HTML button type attribute (only applied when `as=\"button\"`).\r\n * @param props.restProps - Any other props are forwarded to the underlying element.\r\n *\r\n * @returns A JSX element representing the styled button.\r\n *\r\n * @example\r\n * ```tsx\r\n * <Button variant=\"solid\" color=\"brand\" size=\"md\" onClick={handleClick}>\r\n * Save\r\n * </Button>\r\n * ```\r\n */\r\n export function Button(props: ButtonProps): JSXElement {\r\n const {\r\n variant = 'solid',\r\n color = 'brand',\r\n size = 'md',\r\n fullWidth = false,\r\n disabled = false,\r\n loading = false,\r\n leftIcon,\r\n rightIcon,\r\n as = 'button',\r\n text,\r\n children,\r\n className,\r\n type = 'button',\r\n onMount,\r\n onLoad,\r\n ...restProps\r\n } = props;\r\n\r\n const baseClasses = [\r\n 'inline-flex',\r\n 'items-center',\r\n 'justify-center',\r\n 'font-medium',\r\n 'transition-all',\r\n 'duration-150',\r\n 'select-none',\r\n 'focus:outline-none',\r\n 'focus-visible:ring',\r\n 'focus-visible:ring-offset-2'\r\n ];\r\n\r\n const stateClasses = [];\r\n\r\n if (loading || disabled) {\r\n stateClasses.push('opacity-50', 'cursor-not-allowed', 'pointer-events-none');\r\n }\r\n\r\n if (fullWidth) {\r\n stateClasses.push('w-full');\r\n }\r\n\r\n const paletteClasses = variantClasses[variant][color];\r\n\r\n const classes = [\r\n ...baseClasses,\r\n ...stateClasses,\r\n ...paletteClasses,\r\n className\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n const padding = sizePaddingMap[size];\r\n const gap = sizeGapMap[size];\r\n const labelSize = labelSizeMap[size];\r\n\r\n const content: JSXElement[] = [];\r\n\r\n const left = renderIcon(leftIcon, size);\r\n const right = renderIcon(rightIcon, size);\r\n\r\n if (left) {\r\n content.push(left);\r\n }\r\n\r\n const isKeyLikeText = typeof text === 'string' && text.includes('.');\r\n const label = children ?? (isKeyLikeText ? '--' : text);\r\n\r\n if (label !== undefined && label !== null && label !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize} data-role=\"btn-label\" className='flex items-center'>\r\n {label}\r\n </Text>\r\n );\r\n }\r\n\r\n if (right) {\r\n content.push(right);\r\n }\r\n\r\n const elementType = as;\r\n\r\n const elementTypeProps =\r\n elementType === 'button'\r\n ? { type }\r\n : {};\r\n\r\n const shouldTranslate = isKeyLikeText;\r\n\r\n const handleRef =\r\n (onMount || onLoad || shouldTranslate)\r\n ? (element: HTMLElement | null) => {\r\n if (!element) return;\r\n\r\n if (onMount && !mountedElements.has(element)) {\r\n mountedElements.add(element);\r\n onMount(element);\r\n }\r\n\r\n if (onLoad && !loadedElements.has(element)) {\r\n loadedElements.add(element);\r\n\r\n const runLoad = () => {\r\n onLoad(element);\r\n };\r\n\r\n if (typeof requestAnimationFrame === 'function') {\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(runLoad);\r\n });\r\n } else {\r\n setTimeout(runLoad, 0);\r\n }\r\n }\r\n\r\n if (shouldTranslate && !translatedElements.has(element)) {\r\n const schedule = (fn: () => void) => {\r\n if (typeof queueMicrotask === 'function') {\r\n queueMicrotask(fn);\r\n } else {\r\n setTimeout(fn, 0);\r\n }\r\n };\r\n\r\n const attemptTranslate = (attempt: number) => {\r\n const labelNode = element.querySelector('[data-role=\\\"btn-label\\\"]');\r\n\r\n if (!labelNode || typeof text !== 'string') return;\r\n\r\n let translated = t(text as string, undefined, '--');\r\n\r\n if (translated !== text && translated !== '--' || attempt >= MAX_TRANSLATION_ATTEMPTS) {\r\n (labelNode as HTMLElement).textContent = String(translated);\r\n translatedElements.add(element);\r\n return;\r\n }\r\n\r\n setTimeout(\r\n () => {\r\n attemptTranslate(attempt + 1);\r\n },\r\n TRANSLATION_RETRY_DELAY_MS\r\n );\r\n };\r\n\r\n schedule(() => {\r\n attemptTranslate(0);\r\n });\r\n }\r\n }\r\n : undefined;\r\n\r\n const containerProps: ButtonContainerProps = {\r\n as,\r\n display : 'inline-flex',\r\n align : 'center',\r\n justify : 'center',\r\n gap,\r\n px : padding.px,\r\n py : padding.py,\r\n radius : 'md',\r\n className : classes,\r\n ...elementTypeProps,\r\n ...restProps\r\n };\r\n\r\n if (handleRef) {\r\n containerProps.ref = handleRef;\r\n }\r\n\r\n return (\r\n <Container {...(containerProps as Record<string, unknown>)}>\r\n {content}\r\n </Container>\r\n );\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/kit/button.tsx"],"names":["sizePaddingMap","sizeGapMap","labelSizeMap","variantClasses","mountedElements","loadedElements","translatedElements","MAX_TRANSLATION_ATTEMPTS","TRANSLATION_RETRY_DELAY_MS","renderIcon","icon","size","jsx","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","text","children","className","type","onMount","onLoad","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","centerIcon","isKeyLikeText","label","Text","elementTypeProps","shouldTranslate","handleRef","element","runLoad","schedule","fn","attemptTranslate","attempt","labelNode","translated","t","containerProps","Container"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/kit/button.tsx\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import type { JSXElement } from '@minejs/jsx';\r\n import { Container } from '@cruxkit/container';\r\n import { Text } from '@cruxkit/text';\r\n import type { ButtonProps, ButtonSize, ButtonColor, ButtonVariant } from '../types';\r\n import { t } from '@cruxjs/client';\r\n \r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\r\n\r\n const sizePaddingMap: Record<ButtonSize, { px: 3 | 4 | 6; py: 1 | 2 | 3 }> = {\r\n sm: { px: 3, py: 1 },\r\n md: { px: 4, py: 2 },\r\n lg: { px: 6, py: 3 }\r\n };\r\n\r\n const sizeGapMap: Record<ButtonSize, 1 | 2> = {\r\n sm: 1,\r\n md: 2,\r\n lg: 2\r\n };\r\n\r\n const labelSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const iconSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const variantClasses: Record<ButtonVariant, Record<ButtonColor, string[]>> = {\r\n solid: {\r\n brand: [\r\n 'bg-brand',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-hover',\r\n 'active:bg-brand-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n success: [\r\n 'bg-success',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-hover',\r\n 'active:bg-success-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n warning: [\r\n 'bg-warning',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-hover',\r\n 'active:bg-warning-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n error: [\r\n 'bg-error',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-hover',\r\n 'active:bg-error-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n neutral: [\r\n 'bg-surface',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ]\r\n },\r\n outline: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-brand',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-success',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-warning',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-error',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n ghost: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n link: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ]\r\n }\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n const mountedElements = new WeakSet<HTMLElement>();\r\n const loadedElements = new WeakSet<HTMLElement>();\r\n const translatedElements = new WeakSet<HTMLElement>();\r\n const MAX_TRANSLATION_ATTEMPTS = 5;\r\n const TRANSLATION_RETRY_DELAY_MS = 100;\r\n\r\n type ButtonContainerProps = {\r\n as?: unknown;\r\n display?: string;\r\n align?: string;\r\n justify?: string;\r\n gap?: number;\r\n px?: number;\r\n py?: number;\r\n radius?: string;\r\n className?: string;\r\n ref?: (element: HTMLElement | null) => void;\r\n } & Record<string, unknown>;\r\n\r\n function renderIcon(icon: JSXElement | undefined, size: ButtonSize): JSXElement | null {\r\n if (!icon) return null;\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n {icon}\r\n </span>\r\n );\r\n }\r\n\r\n /**\r\n * A polymorphic button component that supports multiple variants, colors, sizes, and states.\r\n *\r\n * @param props - The properties for the Button component.\r\n * @param props.variant - Visual style variant: `'solid' | 'outline' | 'ghost' | 'link'`.\r\n * @param props.color - Color theme: `'brand' | 'success' | 'warning' | 'error' | 'neutral'`.\r\n * @param props.size - Size scale: `'sm' | 'md' | 'lg'`.\r\n * @param props.fullWidth - Whether the button spans the full width of its container.\r\n * @param props.disabled - Whether the button is disabled.\r\n * @param props.loading - Whether the button is in a loading state (disables interaction).\r\n * @param props.leftIcon - Optional icon placed to the left of the label (string name or IconProps).\r\n * @param props.rightIcon - Optional icon placed to the right of the label (string name or IconProps).\r\n * @param props.as - Element type to render: `'button' | 'a' | any polymorphic component`.\r\n * @param props.children - Button label content.\r\n * @param props.className - Additional CSS classes appended to the built-in styles.\r\n * @param props.type - HTML button type attribute (only applied when `as=\"button\"`).\r\n * @param props.restProps - Any other props are forwarded to the underlying element.\r\n *\r\n * @returns A JSX element representing the styled button.\r\n *\r\n * @example\r\n * ```tsx\r\n * <Button variant=\"solid\" color=\"brand\" size=\"md\" onClick={handleClick}>\r\n * Save\r\n * </Button>\r\n * ```\r\n */\r\n export function Button(props: ButtonProps): JSXElement {\r\n const {\r\n variant = 'solid',\r\n color = 'brand',\r\n size = 'md',\r\n fullWidth = false,\r\n disabled = false,\r\n loading = false,\r\n leftIcon,\r\n rightIcon,\r\n icon,\r\n as = 'button',\r\n text,\r\n children,\r\n className,\r\n type = 'button',\r\n onMount,\r\n onLoad,\r\n ...restProps\r\n } = props;\r\n\r\n const baseClasses = [\r\n 'inline-flex',\r\n 'items-center',\r\n 'justify-center',\r\n 'font-medium',\r\n 'transition-all',\r\n 'duration-150',\r\n 'select-none',\r\n 'focus:outline-none',\r\n 'focus-visible:ring',\r\n 'focus-visible:ring-offset-2'\r\n ];\r\n\r\n const stateClasses = [];\r\n\r\n if (loading || disabled) {\r\n stateClasses.push('opacity-50', 'cursor-not-allowed', 'pointer-events-none');\r\n }\r\n\r\n if (fullWidth) {\r\n stateClasses.push('w-full');\r\n }\r\n\r\n const paletteClasses = variantClasses[variant][color];\r\n\r\n const classes = [\r\n ...baseClasses,\r\n ...stateClasses,\r\n ...paletteClasses,\r\n className\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n const padding = sizePaddingMap[size];\r\n const gap = sizeGapMap[size];\r\n const labelSize = labelSizeMap[size];\r\n\r\n const content: JSXElement[] = [];\r\n\r\n const left = renderIcon(leftIcon, size);\r\n const right = renderIcon(rightIcon, size);\r\n const centerIcon = renderIcon(icon, size);\r\n\r\n if (left) {\r\n content.push(left);\r\n }\r\n\r\n if (centerIcon) {\r\n content.push(centerIcon);\r\n }\r\n\r\n const isKeyLikeText = typeof text === 'string' && text.includes('.');\r\n const label = children ?? (isKeyLikeText ? '--' : text);\r\n\r\n if (label !== undefined && label !== null && label !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize} data-role=\"btn-label\" className='flex items-center'>\r\n {label}\r\n </Text>\r\n );\r\n }\r\n\r\n if (right) {\r\n content.push(right);\r\n }\r\n\r\n const elementType = as;\r\n\r\n const elementTypeProps =\r\n elementType === 'button'\r\n ? { type }\r\n : {};\r\n\r\n const shouldTranslate = isKeyLikeText;\r\n\r\n const handleRef =\r\n (onMount || onLoad || shouldTranslate)\r\n ? (element: HTMLElement | null) => {\r\n if (!element) return;\r\n\r\n if (onMount && !mountedElements.has(element)) {\r\n mountedElements.add(element);\r\n onMount(element);\r\n }\r\n\r\n if (onLoad && !loadedElements.has(element)) {\r\n loadedElements.add(element);\r\n\r\n const runLoad = () => {\r\n onLoad(element);\r\n };\r\n\r\n if (typeof requestAnimationFrame === 'function') {\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(runLoad);\r\n });\r\n } else {\r\n setTimeout(runLoad, 0);\r\n }\r\n }\r\n\r\n if (shouldTranslate && !translatedElements.has(element)) {\r\n const schedule = (fn: () => void) => {\r\n if (typeof queueMicrotask === 'function') {\r\n queueMicrotask(fn);\r\n } else {\r\n setTimeout(fn, 0);\r\n }\r\n };\r\n\r\n const attemptTranslate = (attempt: number) => {\r\n const labelNode = element.querySelector('[data-role=\\\"btn-label\\\"]');\r\n\r\n if (!labelNode || typeof text !== 'string') return;\r\n\r\n let translated = t(text as string, undefined, '--');\r\n\r\n if (translated !== text && translated !== '--' || attempt >= MAX_TRANSLATION_ATTEMPTS) {\r\n (labelNode as HTMLElement).textContent = String(translated);\r\n translatedElements.add(element);\r\n return;\r\n }\r\n\r\n setTimeout(\r\n () => {\r\n attemptTranslate(attempt + 1);\r\n },\r\n TRANSLATION_RETRY_DELAY_MS\r\n );\r\n };\r\n\r\n schedule(() => {\r\n attemptTranslate(0);\r\n });\r\n }\r\n }\r\n : undefined;\r\n\r\n const containerProps: ButtonContainerProps = {\r\n as,\r\n display : 'inline-flex',\r\n align : 'center',\r\n justify : 'center',\r\n gap,\r\n px : icon ? padding.py : padding.px,\r\n py : padding.py,\r\n radius : 'md',\r\n className : classes,\r\n ...elementTypeProps,\r\n ...restProps\r\n };\r\n\r\n if (handleRef) {\r\n containerProps.ref = handleRef;\r\n }\r\n\r\n return (\r\n <Container {...(containerProps as Record<string, unknown>)}>\r\n {content}\r\n </Container>\r\n );\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { JSXElement } from '@minejs/jsx';
|
|
2
2
|
import { ContainerAs } from '@cruxkit/container';
|
|
3
|
-
import { IconProps, IconName } from '@cruxkit/icon';
|
|
4
3
|
|
|
5
4
|
type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'link';
|
|
6
5
|
type ButtonColor = 'brand' | 'success' | 'warning' | 'error' | 'neutral';
|
|
@@ -12,8 +11,9 @@ interface ButtonProps {
|
|
|
12
11
|
fullWidth?: boolean;
|
|
13
12
|
disabled?: boolean;
|
|
14
13
|
loading?: boolean;
|
|
15
|
-
leftIcon?:
|
|
16
|
-
rightIcon?:
|
|
14
|
+
leftIcon?: JSXElement;
|
|
15
|
+
rightIcon?: JSXElement;
|
|
16
|
+
icon?: JSXElement;
|
|
17
17
|
as?: ContainerAs;
|
|
18
18
|
text?: string | number;
|
|
19
19
|
children?: JSXElement | string | number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { JSXElement } from '@minejs/jsx';
|
|
2
2
|
import { ContainerAs } from '@cruxkit/container';
|
|
3
|
-
import { IconProps, IconName } from '@cruxkit/icon';
|
|
4
3
|
|
|
5
4
|
type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'link';
|
|
6
5
|
type ButtonColor = 'brand' | 'success' | 'warning' | 'error' | 'neutral';
|
|
@@ -12,8 +11,9 @@ interface ButtonProps {
|
|
|
12
11
|
fullWidth?: boolean;
|
|
13
12
|
disabled?: boolean;
|
|
14
13
|
loading?: boolean;
|
|
15
|
-
leftIcon?:
|
|
16
|
-
rightIcon?:
|
|
14
|
+
leftIcon?: JSXElement;
|
|
15
|
+
rightIcon?: JSXElement;
|
|
16
|
+
icon?: JSXElement;
|
|
17
17
|
as?: ContainerAs;
|
|
18
18
|
text?: string | number;
|
|
19
19
|
children?: JSXElement | string | number;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {Container}from'@cruxkit/container';import {Text}from'@cruxkit/text';import {
|
|
1
|
+
import {Container}from'@cruxkit/container';import {Text}from'@cruxkit/text';import {t}from'@cruxjs/client';import {jsx}from'@minejs/jsx/jsx-runtime';var K={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},Q={sm:1,md:2,lg:2},U={sm:"sm",md:"md",lg:"lg"};var Z={solid:{brand:["bg-brand","text-inverse","border","border-transparent","hover:bg-brand-hover","active:bg-brand-active","active:scale-95","shadow-sm","hover:shadow-md"],success:["bg-success","text-inverse","border","border-transparent","hover:bg-success-hover","active:bg-success-active","active:scale-95","shadow-sm","hover:shadow-md"],warning:["bg-warning","text-inverse","border","border-transparent","hover:bg-warning-hover","active:bg-warning-active","active:scale-95","shadow-sm","hover:shadow-md"],error:["bg-error","text-inverse","border","border-transparent","hover:bg-error-hover","active:bg-error-active","active:scale-95","shadow-sm","hover:shadow-md"],neutral:["bg-surface","text-1","border","border-1","hover:bg-raised","active:bg-tertiary","active:scale-95","shadow-sm","hover:shadow-md"]},outline:{brand:["bg-transparent","text-brand","border","border-brand","hover:bg-brand-subtle","active:bg-brand-subtle","active:scale-95"],success:["bg-transparent","text-success","border","border-success","hover:bg-success-subtle","active:bg-success-subtle","active:scale-95"],warning:["bg-transparent","text-warning","border","border-warning","hover:bg-warning-subtle","active:bg-warning-subtle","active:scale-95"],error:["bg-transparent","text-error","border","border-error","hover:bg-error-subtle","active:bg-error-subtle","active:scale-95"],neutral:["bg-transparent","text-1","border","border-1","hover:bg-raised","active:bg-tertiary","active:scale-95"]},ghost:{brand:["bg-transparent","text-brand","border","border-transparent","hover:bg-brand-subtle","active:bg-brand-subtle","active:scale-95"],success:["bg-transparent","text-success","border","border-transparent","hover:bg-success-subtle","active:bg-success-subtle","active:scale-95"],warning:["bg-transparent","text-warning","border","border-transparent","hover:bg-warning-subtle","active:bg-warning-subtle","active:scale-95"],error:["bg-transparent","text-error","border","border-transparent","hover:bg-error-subtle","active:bg-error-subtle","active:scale-95"],neutral:["bg-transparent","text-1","border","border-transparent","hover:bg-raised","active:bg-tertiary","active:scale-95"]},link:{brand:["bg-transparent","text-brand","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],success:["bg-transparent","text-success","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],warning:["bg-transparent","text-warning","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],error:["bg-transparent","text-error","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"],neutral:["bg-transparent","text-1","border","border-transparent","hover:underline","underline-offset-4","decoration-2","px-1"]}},z=new WeakSet,R=new WeakSet,L=new WeakSet,$=5,ee=100;function p(a,v){return a?jsx("span",{className:"inline-flex shrink-0",children:a}):null}function ae(a){let{variant:v="solid",color:k="brand",size:r="md",fullWidth:C=false,disabled:A=false,loading:N=false,leftIcon:P,rightIcon:q,icon:m,as:f="button",text:t$1,children:H,className:I,type:X="button",onMount:c,onLoad:d,...J}=a,_=["inline-flex","items-center","justify-center","font-medium","transition-all","duration-150","select-none","focus:outline-none","focus-visible:ring","focus-visible:ring-offset-2"],l=[];(N||A)&&l.push("opacity-50","cursor-not-allowed","pointer-events-none"),C&&l.push("w-full");let W=Z[v][k],j=[..._,...l,...W,I].filter(Boolean).join(" "),b=K[r],F=Q[r],O=U[r],n=[],h=p(P),x=p(q),w=p(m);h&&n.push(h),w&&n.push(w);let y=typeof t$1=="string"&&t$1.includes("."),o=H??(y?"--":t$1);o!=null&&o!==""&&n.push(jsx(Text,{as:"span",size:O,"data-role":"btn-label",className:"flex items-center",children:o})),x&&n.push(x);let V=f==="button"?{type:X}:{},T=y,S=c||d||T?e=>{if(e){if(c&&!z.has(e)&&(z.add(e),c(e)),d&&!R.has(e)){R.add(e);let i=()=>{d(e);};typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>{requestAnimationFrame(i);}):setTimeout(i,0);}if(T&&!L.has(e)){let i=s=>{typeof queueMicrotask=="function"?queueMicrotask(s):setTimeout(s,0);},B=s=>{let M=e.querySelector('[data-role="btn-label"]');if(!M||typeof t$1!="string")return;let u=t(t$1,void 0,"--");if(u!==t$1&&u!=="--"||s>=$){M.textContent=String(u),L.add(e);return}setTimeout(()=>{B(s+1);},ee);};i(()=>{B(0);});}}}:void 0,E={as:f,display:"inline-flex",align:"center",justify:"center",gap:F,px:m?b.py:b.px,py:b.py,radius:"md",className:j,...V,...J};return S&&(E.ref=S),jsx(Container,{...E,children:n})}export{ae as Button};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/kit/button.tsx"],"names":["sizePaddingMap","sizeGapMap","labelSizeMap","iconSizeMap","variantClasses","mountedElements","loadedElements","translatedElements","MAX_TRANSLATION_ATTEMPTS","TRANSLATION_RETRY_DELAY_MS","renderIcon","icon","size","iconSize","jsx","Icon","resolvedSize","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","text","children","className","type","onMount","onLoad","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","isKeyLikeText","label","Text","elementTypeProps","shouldTranslate","handleRef","element","runLoad","schedule","fn","attemptTranslate","attempt","labelNode","translated","t","containerProps","Container"],"mappings":"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","file":"index.js","sourcesContent":["// src/kit/button.tsx\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import type { JSXElement } from '@minejs/jsx';\r\n import { Container } from '@cruxkit/container';\r\n import { Text } from '@cruxkit/text';\r\n import { Icon, type IconProps, type IconName, type IconConfig } from '@cruxkit/icon';\r\n import type { ButtonProps, ButtonSize, ButtonColor, ButtonVariant } from '../types';\r\n import { t } from '@cruxjs/client';\r\n \r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\r\n\r\n const sizePaddingMap: Record<ButtonSize, { px: 3 | 4 | 6; py: 1 | 2 | 3 }> = {\r\n sm: { px: 3, py: 1 },\r\n md: { px: 4, py: 2 },\r\n lg: { px: 6, py: 3 }\r\n };\r\n\r\n const sizeGapMap: Record<ButtonSize, 1 | 2> = {\r\n sm: 1,\r\n md: 2,\r\n lg: 2\r\n };\r\n\r\n const labelSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const iconSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const variantClasses: Record<ButtonVariant, Record<ButtonColor, string[]>> = {\r\n solid: {\r\n brand: [\r\n 'bg-brand',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-hover',\r\n 'active:bg-brand-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n success: [\r\n 'bg-success',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-hover',\r\n 'active:bg-success-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n warning: [\r\n 'bg-warning',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-hover',\r\n 'active:bg-warning-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n error: [\r\n 'bg-error',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-hover',\r\n 'active:bg-error-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n neutral: [\r\n 'bg-surface',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ]\r\n },\r\n outline: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-brand',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-success',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-warning',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-error',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n ghost: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n link: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ]\r\n }\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n const mountedElements = new WeakSet<HTMLElement>();\r\n const loadedElements = new WeakSet<HTMLElement>();\r\n const translatedElements = new WeakSet<HTMLElement>();\r\n const MAX_TRANSLATION_ATTEMPTS = 5;\r\n const TRANSLATION_RETRY_DELAY_MS = 100;\r\n\r\n type ButtonContainerProps = {\r\n as?: unknown;\r\n display?: string;\r\n align?: string;\r\n justify?: string;\r\n gap?: number;\r\n px?: number;\r\n py?: number;\r\n radius?: string;\r\n className?: string;\r\n ref?: (element: HTMLElement | null) => void;\r\n } & Record<string, unknown>;\r\n\r\n function renderIcon(icon: IconProps | IconName | undefined, size: ButtonSize): JSXElement | null {\r\n if (!icon) return null;\r\n\r\n const iconSize = iconSizeMap[size];\r\n\r\n if (typeof icon === 'string') {\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n <Icon name={icon as IconName} size={iconSize} />\r\n </span>\r\n );\r\n }\r\n\r\n const resolvedSize = ((icon as IconProps) as IconConfig).size ?? iconSize;\r\n\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n <Icon {...icon} size={resolvedSize} />\r\n </span>\r\n );\r\n }\r\n\r\n /**\r\n * A polymorphic button component that supports multiple variants, colors, sizes, and states.\r\n *\r\n * @param props - The properties for the Button component.\r\n * @param props.variant - Visual style variant: `'solid' | 'outline' | 'ghost' | 'link'`.\r\n * @param props.color - Color theme: `'brand' | 'success' | 'warning' | 'error' | 'neutral'`.\r\n * @param props.size - Size scale: `'sm' | 'md' | 'lg'`.\r\n * @param props.fullWidth - Whether the button spans the full width of its container.\r\n * @param props.disabled - Whether the button is disabled.\r\n * @param props.loading - Whether the button is in a loading state (disables interaction).\r\n * @param props.leftIcon - Optional icon placed to the left of the label (string name or IconProps).\r\n * @param props.rightIcon - Optional icon placed to the right of the label (string name or IconProps).\r\n * @param props.as - Element type to render: `'button' | 'a' | any polymorphic component`.\r\n * @param props.children - Button label content.\r\n * @param props.className - Additional CSS classes appended to the built-in styles.\r\n * @param props.type - HTML button type attribute (only applied when `as=\"button\"`).\r\n * @param props.restProps - Any other props are forwarded to the underlying element.\r\n *\r\n * @returns A JSX element representing the styled button.\r\n *\r\n * @example\r\n * ```tsx\r\n * <Button variant=\"solid\" color=\"brand\" size=\"md\" onClick={handleClick}>\r\n * Save\r\n * </Button>\r\n * ```\r\n */\r\n export function Button(props: ButtonProps): JSXElement {\r\n const {\r\n variant = 'solid',\r\n color = 'brand',\r\n size = 'md',\r\n fullWidth = false,\r\n disabled = false,\r\n loading = false,\r\n leftIcon,\r\n rightIcon,\r\n as = 'button',\r\n text,\r\n children,\r\n className,\r\n type = 'button',\r\n onMount,\r\n onLoad,\r\n ...restProps\r\n } = props;\r\n\r\n const baseClasses = [\r\n 'inline-flex',\r\n 'items-center',\r\n 'justify-center',\r\n 'font-medium',\r\n 'transition-all',\r\n 'duration-150',\r\n 'select-none',\r\n 'focus:outline-none',\r\n 'focus-visible:ring',\r\n 'focus-visible:ring-offset-2'\r\n ];\r\n\r\n const stateClasses = [];\r\n\r\n if (loading || disabled) {\r\n stateClasses.push('opacity-50', 'cursor-not-allowed', 'pointer-events-none');\r\n }\r\n\r\n if (fullWidth) {\r\n stateClasses.push('w-full');\r\n }\r\n\r\n const paletteClasses = variantClasses[variant][color];\r\n\r\n const classes = [\r\n ...baseClasses,\r\n ...stateClasses,\r\n ...paletteClasses,\r\n className\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n const padding = sizePaddingMap[size];\r\n const gap = sizeGapMap[size];\r\n const labelSize = labelSizeMap[size];\r\n\r\n const content: JSXElement[] = [];\r\n\r\n const left = renderIcon(leftIcon, size);\r\n const right = renderIcon(rightIcon, size);\r\n\r\n if (left) {\r\n content.push(left);\r\n }\r\n\r\n const isKeyLikeText = typeof text === 'string' && text.includes('.');\r\n const label = children ?? (isKeyLikeText ? '--' : text);\r\n\r\n if (label !== undefined && label !== null && label !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize} data-role=\"btn-label\" className='flex items-center'>\r\n {label}\r\n </Text>\r\n );\r\n }\r\n\r\n if (right) {\r\n content.push(right);\r\n }\r\n\r\n const elementType = as;\r\n\r\n const elementTypeProps =\r\n elementType === 'button'\r\n ? { type }\r\n : {};\r\n\r\n const shouldTranslate = isKeyLikeText;\r\n\r\n const handleRef =\r\n (onMount || onLoad || shouldTranslate)\r\n ? (element: HTMLElement | null) => {\r\n if (!element) return;\r\n\r\n if (onMount && !mountedElements.has(element)) {\r\n mountedElements.add(element);\r\n onMount(element);\r\n }\r\n\r\n if (onLoad && !loadedElements.has(element)) {\r\n loadedElements.add(element);\r\n\r\n const runLoad = () => {\r\n onLoad(element);\r\n };\r\n\r\n if (typeof requestAnimationFrame === 'function') {\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(runLoad);\r\n });\r\n } else {\r\n setTimeout(runLoad, 0);\r\n }\r\n }\r\n\r\n if (shouldTranslate && !translatedElements.has(element)) {\r\n const schedule = (fn: () => void) => {\r\n if (typeof queueMicrotask === 'function') {\r\n queueMicrotask(fn);\r\n } else {\r\n setTimeout(fn, 0);\r\n }\r\n };\r\n\r\n const attemptTranslate = (attempt: number) => {\r\n const labelNode = element.querySelector('[data-role=\\\"btn-label\\\"]');\r\n\r\n if (!labelNode || typeof text !== 'string') return;\r\n\r\n let translated = t(text as string, undefined, '--');\r\n\r\n if (translated !== text && translated !== '--' || attempt >= MAX_TRANSLATION_ATTEMPTS) {\r\n (labelNode as HTMLElement).textContent = String(translated);\r\n translatedElements.add(element);\r\n return;\r\n }\r\n\r\n setTimeout(\r\n () => {\r\n attemptTranslate(attempt + 1);\r\n },\r\n TRANSLATION_RETRY_DELAY_MS\r\n );\r\n };\r\n\r\n schedule(() => {\r\n attemptTranslate(0);\r\n });\r\n }\r\n }\r\n : undefined;\r\n\r\n const containerProps: ButtonContainerProps = {\r\n as,\r\n display : 'inline-flex',\r\n align : 'center',\r\n justify : 'center',\r\n gap,\r\n px : padding.px,\r\n py : padding.py,\r\n radius : 'md',\r\n className : classes,\r\n ...elementTypeProps,\r\n ...restProps\r\n };\r\n\r\n if (handleRef) {\r\n containerProps.ref = handleRef;\r\n }\r\n\r\n return (\r\n <Container {...(containerProps as Record<string, unknown>)}>\r\n {content}\r\n </Container>\r\n );\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/kit/button.tsx"],"names":["sizePaddingMap","sizeGapMap","labelSizeMap","variantClasses","mountedElements","loadedElements","translatedElements","MAX_TRANSLATION_ATTEMPTS","TRANSLATION_RETRY_DELAY_MS","renderIcon","icon","size","jsx","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","text","children","className","type","onMount","onLoad","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","centerIcon","isKeyLikeText","label","Text","elementTypeProps","shouldTranslate","handleRef","element","runLoad","schedule","fn","attemptTranslate","attempt","labelNode","translated","t","containerProps","Container"],"mappings":"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","file":"index.js","sourcesContent":["// src/kit/button.tsx\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import type { JSXElement } from '@minejs/jsx';\r\n import { Container } from '@cruxkit/container';\r\n import { Text } from '@cruxkit/text';\r\n import type { ButtonProps, ButtonSize, ButtonColor, ButtonVariant } from '../types';\r\n import { t } from '@cruxjs/client';\r\n \r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\r\n\r\n const sizePaddingMap: Record<ButtonSize, { px: 3 | 4 | 6; py: 1 | 2 | 3 }> = {\r\n sm: { px: 3, py: 1 },\r\n md: { px: 4, py: 2 },\r\n lg: { px: 6, py: 3 }\r\n };\r\n\r\n const sizeGapMap: Record<ButtonSize, 1 | 2> = {\r\n sm: 1,\r\n md: 2,\r\n lg: 2\r\n };\r\n\r\n const labelSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const iconSizeMap: Record<ButtonSize, 'sm' | 'md' | 'lg'> = {\r\n sm: 'sm',\r\n md: 'md',\r\n lg: 'lg'\r\n };\r\n\r\n const variantClasses: Record<ButtonVariant, Record<ButtonColor, string[]>> = {\r\n solid: {\r\n brand: [\r\n 'bg-brand',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-hover',\r\n 'active:bg-brand-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n success: [\r\n 'bg-success',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-hover',\r\n 'active:bg-success-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n warning: [\r\n 'bg-warning',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-hover',\r\n 'active:bg-warning-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n error: [\r\n 'bg-error',\r\n 'text-inverse',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-hover',\r\n 'active:bg-error-active',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ],\r\n neutral: [\r\n 'bg-surface',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95',\r\n 'shadow-sm',\r\n 'hover:shadow-md'\r\n ]\r\n },\r\n outline: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-brand',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-success',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-warning',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-error',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-1',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n ghost: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-brand-subtle',\r\n 'active:bg-brand-subtle',\r\n 'active:scale-95'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-success-subtle',\r\n 'active:bg-success-subtle',\r\n 'active:scale-95'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-warning-subtle',\r\n 'active:bg-warning-subtle',\r\n 'active:scale-95'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-error-subtle',\r\n 'active:bg-error-subtle',\r\n 'active:scale-95'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:bg-raised',\r\n 'active:bg-tertiary',\r\n 'active:scale-95'\r\n ]\r\n },\r\n link: {\r\n brand: [\r\n 'bg-transparent',\r\n 'text-brand',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n success: [\r\n 'bg-transparent',\r\n 'text-success',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n warning: [\r\n 'bg-transparent',\r\n 'text-warning',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n error: [\r\n 'bg-transparent',\r\n 'text-error',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ],\r\n neutral: [\r\n 'bg-transparent',\r\n 'text-1',\r\n 'border',\r\n 'border-transparent',\r\n 'hover:underline',\r\n 'underline-offset-4',\r\n 'decoration-2',\r\n 'px-1'\r\n ]\r\n }\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n const mountedElements = new WeakSet<HTMLElement>();\r\n const loadedElements = new WeakSet<HTMLElement>();\r\n const translatedElements = new WeakSet<HTMLElement>();\r\n const MAX_TRANSLATION_ATTEMPTS = 5;\r\n const TRANSLATION_RETRY_DELAY_MS = 100;\r\n\r\n type ButtonContainerProps = {\r\n as?: unknown;\r\n display?: string;\r\n align?: string;\r\n justify?: string;\r\n gap?: number;\r\n px?: number;\r\n py?: number;\r\n radius?: string;\r\n className?: string;\r\n ref?: (element: HTMLElement | null) => void;\r\n } & Record<string, unknown>;\r\n\r\n function renderIcon(icon: JSXElement | undefined, size: ButtonSize): JSXElement | null {\r\n if (!icon) return null;\r\n return (\r\n <span className=\"inline-flex shrink-0\">\r\n {icon}\r\n </span>\r\n );\r\n }\r\n\r\n /**\r\n * A polymorphic button component that supports multiple variants, colors, sizes, and states.\r\n *\r\n * @param props - The properties for the Button component.\r\n * @param props.variant - Visual style variant: `'solid' | 'outline' | 'ghost' | 'link'`.\r\n * @param props.color - Color theme: `'brand' | 'success' | 'warning' | 'error' | 'neutral'`.\r\n * @param props.size - Size scale: `'sm' | 'md' | 'lg'`.\r\n * @param props.fullWidth - Whether the button spans the full width of its container.\r\n * @param props.disabled - Whether the button is disabled.\r\n * @param props.loading - Whether the button is in a loading state (disables interaction).\r\n * @param props.leftIcon - Optional icon placed to the left of the label (string name or IconProps).\r\n * @param props.rightIcon - Optional icon placed to the right of the label (string name or IconProps).\r\n * @param props.as - Element type to render: `'button' | 'a' | any polymorphic component`.\r\n * @param props.children - Button label content.\r\n * @param props.className - Additional CSS classes appended to the built-in styles.\r\n * @param props.type - HTML button type attribute (only applied when `as=\"button\"`).\r\n * @param props.restProps - Any other props are forwarded to the underlying element.\r\n *\r\n * @returns A JSX element representing the styled button.\r\n *\r\n * @example\r\n * ```tsx\r\n * <Button variant=\"solid\" color=\"brand\" size=\"md\" onClick={handleClick}>\r\n * Save\r\n * </Button>\r\n * ```\r\n */\r\n export function Button(props: ButtonProps): JSXElement {\r\n const {\r\n variant = 'solid',\r\n color = 'brand',\r\n size = 'md',\r\n fullWidth = false,\r\n disabled = false,\r\n loading = false,\r\n leftIcon,\r\n rightIcon,\r\n icon,\r\n as = 'button',\r\n text,\r\n children,\r\n className,\r\n type = 'button',\r\n onMount,\r\n onLoad,\r\n ...restProps\r\n } = props;\r\n\r\n const baseClasses = [\r\n 'inline-flex',\r\n 'items-center',\r\n 'justify-center',\r\n 'font-medium',\r\n 'transition-all',\r\n 'duration-150',\r\n 'select-none',\r\n 'focus:outline-none',\r\n 'focus-visible:ring',\r\n 'focus-visible:ring-offset-2'\r\n ];\r\n\r\n const stateClasses = [];\r\n\r\n if (loading || disabled) {\r\n stateClasses.push('opacity-50', 'cursor-not-allowed', 'pointer-events-none');\r\n }\r\n\r\n if (fullWidth) {\r\n stateClasses.push('w-full');\r\n }\r\n\r\n const paletteClasses = variantClasses[variant][color];\r\n\r\n const classes = [\r\n ...baseClasses,\r\n ...stateClasses,\r\n ...paletteClasses,\r\n className\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n const padding = sizePaddingMap[size];\r\n const gap = sizeGapMap[size];\r\n const labelSize = labelSizeMap[size];\r\n\r\n const content: JSXElement[] = [];\r\n\r\n const left = renderIcon(leftIcon, size);\r\n const right = renderIcon(rightIcon, size);\r\n const centerIcon = renderIcon(icon, size);\r\n\r\n if (left) {\r\n content.push(left);\r\n }\r\n\r\n if (centerIcon) {\r\n content.push(centerIcon);\r\n }\r\n\r\n const isKeyLikeText = typeof text === 'string' && text.includes('.');\r\n const label = children ?? (isKeyLikeText ? '--' : text);\r\n\r\n if (label !== undefined && label !== null && label !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize} data-role=\"btn-label\" className='flex items-center'>\r\n {label}\r\n </Text>\r\n );\r\n }\r\n\r\n if (right) {\r\n content.push(right);\r\n }\r\n\r\n const elementType = as;\r\n\r\n const elementTypeProps =\r\n elementType === 'button'\r\n ? { type }\r\n : {};\r\n\r\n const shouldTranslate = isKeyLikeText;\r\n\r\n const handleRef =\r\n (onMount || onLoad || shouldTranslate)\r\n ? (element: HTMLElement | null) => {\r\n if (!element) return;\r\n\r\n if (onMount && !mountedElements.has(element)) {\r\n mountedElements.add(element);\r\n onMount(element);\r\n }\r\n\r\n if (onLoad && !loadedElements.has(element)) {\r\n loadedElements.add(element);\r\n\r\n const runLoad = () => {\r\n onLoad(element);\r\n };\r\n\r\n if (typeof requestAnimationFrame === 'function') {\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(runLoad);\r\n });\r\n } else {\r\n setTimeout(runLoad, 0);\r\n }\r\n }\r\n\r\n if (shouldTranslate && !translatedElements.has(element)) {\r\n const schedule = (fn: () => void) => {\r\n if (typeof queueMicrotask === 'function') {\r\n queueMicrotask(fn);\r\n } else {\r\n setTimeout(fn, 0);\r\n }\r\n };\r\n\r\n const attemptTranslate = (attempt: number) => {\r\n const labelNode = element.querySelector('[data-role=\\\"btn-label\\\"]');\r\n\r\n if (!labelNode || typeof text !== 'string') return;\r\n\r\n let translated = t(text as string, undefined, '--');\r\n\r\n if (translated !== text && translated !== '--' || attempt >= MAX_TRANSLATION_ATTEMPTS) {\r\n (labelNode as HTMLElement).textContent = String(translated);\r\n translatedElements.add(element);\r\n return;\r\n }\r\n\r\n setTimeout(\r\n () => {\r\n attemptTranslate(attempt + 1);\r\n },\r\n TRANSLATION_RETRY_DELAY_MS\r\n );\r\n };\r\n\r\n schedule(() => {\r\n attemptTranslate(0);\r\n });\r\n }\r\n }\r\n : undefined;\r\n\r\n const containerProps: ButtonContainerProps = {\r\n as,\r\n display : 'inline-flex',\r\n align : 'center',\r\n justify : 'center',\r\n gap,\r\n px : icon ? padding.py : padding.px,\r\n py : padding.py,\r\n radius : 'md',\r\n className : classes,\r\n ...elementTypeProps,\r\n ...restProps\r\n };\r\n\r\n if (handleRef) {\r\n containerProps.ref = handleRef;\r\n }\r\n\r\n return (\r\n <Container {...(containerProps as Record<string, unknown>)}>\r\n {content}\r\n </Container>\r\n );\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cruxkit/button",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Polymorphic, theme-aware button component for the Cruxkit ecosystem, built on @minejs/jsx.",
|
|
5
5
|
"keywords": ["crux", "kit", "button"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,25 +40,25 @@
|
|
|
40
40
|
"bun": "^1.3.3"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@cruxjs/client": "^0.2.
|
|
43
|
+
"@cruxjs/client": "^0.2.2",
|
|
44
44
|
"@cruxkit/container": "^0.0.2",
|
|
45
|
-
"@cruxkit/icon": "^0.0.3",
|
|
46
45
|
"@cruxkit/text": "^0.0.2",
|
|
47
|
-
"@minejs/jsx": "^0.1.
|
|
46
|
+
"@minejs/jsx": "^0.1.4"
|
|
48
47
|
},
|
|
49
48
|
"devDependencies": {
|
|
49
|
+
"@cruxkit/icon": "^0.0.5",
|
|
50
50
|
"@eslint/js": "^9.39.2",
|
|
51
|
-
"@stylistic/eslint-plugin": "^5.
|
|
52
|
-
"@types/bun": "^1.3.
|
|
51
|
+
"@stylistic/eslint-plugin": "^5.7.0",
|
|
52
|
+
"@types/bun": "^1.3.6",
|
|
53
53
|
"@types/jsdom": "^27.0.0",
|
|
54
|
-
"@types/node": "^20.19.
|
|
55
|
-
"@types/react": "^19.2.
|
|
54
|
+
"@types/node": "^20.19.30",
|
|
55
|
+
"@types/react": "^19.2.9",
|
|
56
56
|
"bun-plugin-dts": "^0.3.0",
|
|
57
|
-
"bun-types": "^1.3.
|
|
57
|
+
"bun-types": "^1.3.6",
|
|
58
58
|
"jsdom": "^27.4.0",
|
|
59
59
|
"ts-node": "^10.9.2",
|
|
60
60
|
"tsup": "^8.5.1",
|
|
61
61
|
"typescript": "^5.9.3",
|
|
62
|
-
"typescript-eslint": "^8.
|
|
62
|
+
"typescript-eslint": "^8.53.1"
|
|
63
63
|
}
|
|
64
64
|
}
|