@cruxkit/button 0.0.2 → 0.0.4

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 CHANGED
@@ -8,12 +8,12 @@
8
8
  </div>
9
9
 
10
10
  <div align="center">
11
- <img src="https://img.shields.io/badge/v-0.0.2-black"/>
11
+ <img src="https://img.shields.io/badge/v-0.0.4-black"/>
12
12
  <a href="https://github.com/cruxkit-org"><img src="https://img.shields.io/badge/🔥-@cruxkit-black"/></a>
13
13
  <br>
14
- <img src="https://img.shields.io/badge/coverage-99%25-brightgreen" alt="Test Coverage" />
15
- <img src="https://img.shields.io/github/issues/cruxkit-orgz/button?style=flat" alt="Github Repo Issues" />
16
- <img src="https://img.shields.io/github/stars/cruxkit-orgz/button?style=social" alt="GitHub Repo stars" />
14
+ <img src="https://img.shields.io/badge/coverage-100%25-brightgreen" alt="Test Coverage" />
15
+ <img src="https://img.shields.io/github/issues/cruxkit-org/button?style=flat" alt="Github Repo Issues" />
16
+ <img src="https://img.shields.io/github/stars/cruxkit-org/button?style=social" alt="GitHub Repo stars" />
17
17
  </div>
18
18
  <br>
19
19
 
@@ -60,9 +60,7 @@
60
60
  - ### Basic usage
61
61
 
62
62
  ```tsx
63
- <Button>
64
- Click me
65
- </Button>
63
+ <Button text="Click me" />
66
64
  ```
67
65
 
68
66
  - ### With options
@@ -88,6 +86,9 @@
88
86
  href="https://example.com"
89
87
  variant="link"
90
88
  color="brand"
89
+ onMount={(el) => {
90
+ console.log('Button mounted', el);
91
+ }}
91
92
  >
92
93
  Learn more
93
94
  </Button>
@@ -104,76 +105,49 @@
104
105
  - #### Functions
105
106
 
106
107
  ```tsx
107
- /**
108
- * A polymorphic button component that supports multiple variants, colors, sizes, and states.
109
- *
110
- * @param props - The properties for the Button component.
111
- * @param props.variant - Visual style variant: `'solid' | 'outline' | 'ghost' | 'link'`.
112
- * @param props.color - Color theme: `'brand' | 'success' | 'warning' | 'error' | 'neutral'`.
113
- * @param props.size - Size scale: `'sm' | 'md' | 'lg'`.
114
- * @param props.fullWidth - Whether the button spans the full width of its container.
115
- * @param props.disabled - Whether the button is disabled.
116
- * @param props.loading - Whether the button is in a loading state (disables interaction).
117
- * @param props.leftIcon - Optional icon placed to the left of the label (string name or IconProps).
118
- * @param props.rightIcon - Optional icon placed to the right of the label (string name or IconProps).
119
- * @param props.as - Element type to render: `'button' | 'a' | any polymorphic component`.
120
- * @param props.children - Button label content.
121
- * @param props.className - Additional CSS classes appended to the built-in styles.
122
- * @param props.type - HTML button type attribute (only applied when `as="button"`).
123
- * @param props.restProps - Any other props are forwarded to the underlying element.
124
- *
125
- * @returns A JSX element representing the styled button.
126
- */
108
+ // A polymorphic button component that supports multiple variants, colors, sizes, and states.
127
109
  export function Button(props: ButtonProps): JSXElement
128
110
  ```
129
111
 
130
112
  - #### Types
131
113
 
132
114
  ```tsx
133
- export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | number;
134
-
135
- export type IconData = Record<string, unknown>;
136
- export { iconCatalog };
137
- export type IconName = CatalogIconName;
138
-
139
- interface IconConfigBase {
140
- size? : IconSize
141
- color? : string
142
- spin? : boolean
143
- pulse? : boolean
144
- rotate? : 0 | 90 | 180 | 270
145
- flip? : 'horizontal' | 'vertical' | 'both'
146
- [key: string] : unknown
147
- }
148
-
149
- export interface NamedIconConfig extends IconConfigBase {
150
- name : IconName
151
- svg? : never
152
- viewBox? : never
115
+ export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'link';
116
+ export type ButtonColor = 'brand' | 'success' | 'warning' | 'error' | 'neutral';
117
+ export type ButtonSize = 'sm' | 'md' | 'lg';
118
+
119
+ export interface ButtonProps {
120
+ variant? : ButtonVariant;
121
+ color? : ButtonColor;
122
+ size? : ButtonSize;
123
+ fullWidth? : boolean;
124
+ disabled? : boolean;
125
+ loading? : boolean;
126
+
127
+ leftIcon? : IconProps | IconName;
128
+ rightIcon? : IconProps | IconName;
129
+
130
+ as? : ContainerAs;
131
+
132
+ text? : string | number;
133
+ children? : JSXElement | string | number;
134
+
135
+ className? : string;
136
+ id? : string;
137
+ type? : 'button' | 'submit' | 'reset';
138
+ href? : string;
139
+ target? : string;
140
+ rel? : string;
141
+
142
+ 'aria-label'? : string;
143
+ role? : string;
144
+
145
+ onMount? : (e: HTMLElement) => void;
146
+ onLoad? : (e: HTMLElement) => void;
147
+ onClick? : (e: MouseEvent) => void;
148
+ onMouseEnter? : (e: MouseEvent) => void;
149
+ onMouseLeave? : (e: MouseEvent) => void;
153
150
  }
154
-
155
- export interface CustomIconConfig extends IconConfigBase {
156
- name? : string
157
- svg : string
158
- viewBox? : string
159
- }
160
-
161
- export type IconConfig = NamedIconConfig | CustomIconConfig;
162
-
163
- export type IconProps = IconConfig | IconName;
164
- ```
165
-
166
- - #### Constants
167
-
168
- ```tsx
169
- export const sizeMap: Record<string, string> = {
170
- xs : '0.75rem',
171
- sm : '1rem',
172
- md : '1.25rem',
173
- lg : '1.5rem',
174
- xl : '2rem',
175
- xxl : '2.5rem'
176
- };
177
151
  ```
178
152
 
179
153
  <div align="center"> <img src="./assets/img/line.png" alt="line" style="display: block; margin-top:20px;margin-bottom:20px;width:500px;"/> </div>
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var container=require('@cruxkit/container'),text=require('@cruxkit/text'),icon=require('@cruxkit/icon'),jsxRuntime=require('@minejs/jsx/jsx-runtime');var T={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},E={sm:1,md:2,lg:2},J={sm:"sm",md:"md",lg:"lg"},M={sm:"sm",md:"md",lg:"lg"},X={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"]}};function u(e,o){if(!e)return null;let n=M[o];if(typeof e=="string")return jsxRuntime.jsx("span",{className:"inline-flex shrink-0",children:jsxRuntime.jsx(icon.Icon,{name:e,size:n})});let r=e.size??n;return jsxRuntime.jsx("span",{className:"inline-flex shrink-0",children:jsxRuntime.jsx(icon.Icon,{...e,size:r})})}function W(e){let{variant:o="solid",color:n="brand",size:r="md",fullWidth:g=false,disabled:v=false,loading:m=false,leftIcon:f,rightIcon:h,as:c="button",children:s,className:x,type:w="button",...y}=e,z=["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"],i=[];(m||v)&&i.push("opacity-50","cursor-not-allowed","pointer-events-none"),g&&i.push("w-full");let S=X[o][n],B=[...z,...i,...S,x].filter(Boolean).join(" "),b=T[r],I=E[r],C=J[r],a=[],d=u(f,r),l=u(h,r);d&&a.push(d),s!=null&&s!==""&&a.push(jsxRuntime.jsx(text.Text,{as:"span",size:C,children:s})),l&&a.push(l);let P=c==="button"?{type:w}:{};return jsxRuntime.jsx(container.Container,{as:c,display:"inline-flex",align:"center",justify:"center",gap:I,px:b.px,py:b.py,radius:"md",className:B,...P,...y,children:a})}exports.Button=W;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var container=require('@cruxkit/container'),text=require('@cruxkit/text'),icon=require('@cruxkit/icon'),client=require('@cruxjs/client'),jsxRuntime=require('@minejs/jsx/jsx-runtime');var G={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},K={sm:1,md:2,lg:2},Q={sm:"sm",md:"md",lg:"lg"},U={sm:"sm",md:"md",lg:"lg"},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"]}},E=new WeakSet,M=new WeakSet,I=new WeakSet,$=5,ee=100;function N(r,l){if(!r)return null;let o=U[l];if(typeof r=="string")return jsxRuntime.jsx("span",{className:"inline-flex shrink-0",children:jsxRuntime.jsx(icon.Icon,{name:r,size:o})});let t=r.size??o;return jsxRuntime.jsx("span",{className:"inline-flex shrink-0",children:jsxRuntime.jsx(icon.Icon,{...r,size:t})})}function oe(r){let{variant:l="solid",color:o="brand",size:t="md",fullWidth:C=false,disabled:R=false,loading:k=false,leftIcon:L,rightIcon:P,as:m="button",text:n,children:A,className:q,type:H="button",onMount:b,onLoad:u,...X}=r,_=["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"],p=[];(k||R)&&p.push("opacity-50","cursor-not-allowed","pointer-events-none"),C&&p.push("w-full");let J=Z[l][o],W=[..._,...p,...J,q].filter(Boolean).join(" "),v=G[t],j=K[t],F=Q[t],i=[],f=N(L,t),h=N(P,t);f&&i.push(f);let x=typeof n=="string"&&n.includes("."),c=A??(x?"--":n);c!=null&&c!==""&&i.push(jsxRuntime.jsx(text.Text,{as:"span",size:F,"data-role":"btn-label",className:"flex items-center",children:c})),h&&i.push(h);let O=m==="button"?{type:H}:{},y=x,w=b||u||y?e=>{if(e){if(b&&!E.has(e)&&(E.add(e),b(e)),u&&!M.has(e)){M.add(e);let d=()=>{u(e);};typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>{requestAnimationFrame(d);}):setTimeout(d,0);}if(y&&!I.has(e)){let d=a=>{typeof queueMicrotask=="function"?queueMicrotask(a):setTimeout(a,0);},S=a=>{let z=e.querySelector('[data-role="btn-label"]');if(!z||typeof n!="string")return;let g=client.t(n,void 0,"--");if(g!==n&&g!=="--"||a>=$){z.textContent=String(g),I.add(e);return}setTimeout(()=>{S(a+1);},ee);};d(()=>{S(0);});}}}:void 0,T={as:m,display:"inline-flex",align:"center",justify:"center",gap:j,px:v.px,py:v.py,radius:"md",className:W,...O,...X};return w&&(T.ref=w),jsxRuntime.jsx(container.Container,{...T,children:i})}exports.Button=oe;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/kit/button.tsx"],"names":["sizePaddingMap","sizeGapMap","labelSizeMap","iconSizeMap","variantClasses","renderIcon","icon","size","iconSize","jsx","Icon","resolvedSize","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","children","className","type","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","Text","elementTypeProps","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\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 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 children,\r\n className,\r\n type = 'button',\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 if (children !== undefined && children !== null && children !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize}>\r\n {children}\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 return (\r\n <Container\r\n as={as}\r\n display = \"inline-flex\"\r\n align = \"center\"\r\n justify = \"center\"\r\n gap = {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 {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","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"]}
package/dist/index.d.cts CHANGED
@@ -15,6 +15,7 @@ interface ButtonProps {
15
15
  leftIcon?: IconProps | IconName;
16
16
  rightIcon?: IconProps | IconName;
17
17
  as?: ContainerAs;
18
+ text?: string | number;
18
19
  children?: JSXElement | string | number;
19
20
  className?: string;
20
21
  id?: string;
@@ -24,6 +25,8 @@ interface ButtonProps {
24
25
  rel?: string;
25
26
  'aria-label'?: string;
26
27
  role?: string;
28
+ onMount?: (e: HTMLElement) => void;
29
+ onLoad?: (e: HTMLElement) => void;
27
30
  onClick?: (e: MouseEvent) => void;
28
31
  onMouseEnter?: (e: MouseEvent) => void;
29
32
  onMouseLeave?: (e: MouseEvent) => void;
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ interface ButtonProps {
15
15
  leftIcon?: IconProps | IconName;
16
16
  rightIcon?: IconProps | IconName;
17
17
  as?: ContainerAs;
18
+ text?: string | number;
18
19
  children?: JSXElement | string | number;
19
20
  className?: string;
20
21
  id?: string;
@@ -24,6 +25,8 @@ interface ButtonProps {
24
25
  rel?: string;
25
26
  'aria-label'?: string;
26
27
  role?: string;
28
+ onMount?: (e: HTMLElement) => void;
29
+ onLoad?: (e: HTMLElement) => void;
27
30
  onClick?: (e: MouseEvent) => void;
28
31
  onMouseEnter?: (e: MouseEvent) => void;
29
32
  onMouseLeave?: (e: MouseEvent) => void;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import {Container}from'@cruxkit/container';import {Text}from'@cruxkit/text';import {Icon}from'@cruxkit/icon';import {jsx}from'@minejs/jsx/jsx-runtime';var T={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},E={sm:1,md:2,lg:2},J={sm:"sm",md:"md",lg:"lg"},M={sm:"sm",md:"md",lg:"lg"},X={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"]}};function u(e,o){if(!e)return null;let n=M[o];if(typeof e=="string")return jsx("span",{className:"inline-flex shrink-0",children:jsx(Icon,{name:e,size:n})});let r=e.size??n;return jsx("span",{className:"inline-flex shrink-0",children:jsx(Icon,{...e,size:r})})}function W(e){let{variant:o="solid",color:n="brand",size:r="md",fullWidth:g=false,disabled:v=false,loading:m=false,leftIcon:f,rightIcon:h,as:c="button",children:s,className:x,type:w="button",...y}=e,z=["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"],i=[];(m||v)&&i.push("opacity-50","cursor-not-allowed","pointer-events-none"),g&&i.push("w-full");let S=X[o][n],B=[...z,...i,...S,x].filter(Boolean).join(" "),b=T[r],I=E[r],C=J[r],a=[],d=u(f,r),l=u(h,r);d&&a.push(d),s!=null&&s!==""&&a.push(jsx(Text,{as:"span",size:C,children:s})),l&&a.push(l);let P=c==="button"?{type:w}:{};return jsx(Container,{as:c,display:"inline-flex",align:"center",justify:"center",gap:I,px:b.px,py:b.py,radius:"md",className:B,...P,...y,children:a})}export{W as Button};//# sourceMappingURL=index.js.map
1
+ import {Container}from'@cruxkit/container';import {Text}from'@cruxkit/text';import {Icon}from'@cruxkit/icon';import {t}from'@cruxjs/client';import {jsx}from'@minejs/jsx/jsx-runtime';var G={sm:{px:3,py:1},md:{px:4,py:2},lg:{px:6,py:3}},K={sm:1,md:2,lg:2},Q={sm:"sm",md:"md",lg:"lg"},U={sm:"sm",md:"md",lg:"lg"},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"]}},E=new WeakSet,M=new WeakSet,I=new WeakSet,$=5,ee=100;function N(r,l){if(!r)return null;let o=U[l];if(typeof r=="string")return jsx("span",{className:"inline-flex shrink-0",children:jsx(Icon,{name:r,size:o})});let t=r.size??o;return jsx("span",{className:"inline-flex shrink-0",children:jsx(Icon,{...r,size:t})})}function oe(r){let{variant:l="solid",color:o="brand",size:t$1="md",fullWidth:C=false,disabled:R=false,loading:k=false,leftIcon:L,rightIcon:P,as:m="button",text:n,children:A,className:q,type:H="button",onMount:b,onLoad:u,...X}=r,_=["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"],p=[];(k||R)&&p.push("opacity-50","cursor-not-allowed","pointer-events-none"),C&&p.push("w-full");let J=Z[l][o],W=[..._,...p,...J,q].filter(Boolean).join(" "),v=G[t$1],j=K[t$1],F=Q[t$1],i=[],f=N(L,t$1),h=N(P,t$1);f&&i.push(f);let x=typeof n=="string"&&n.includes("."),c=A??(x?"--":n);c!=null&&c!==""&&i.push(jsx(Text,{as:"span",size:F,"data-role":"btn-label",className:"flex items-center",children:c})),h&&i.push(h);let O=m==="button"?{type:H}:{},y=x,w=b||u||y?e=>{if(e){if(b&&!E.has(e)&&(E.add(e),b(e)),u&&!M.has(e)){M.add(e);let d=()=>{u(e);};typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>{requestAnimationFrame(d);}):setTimeout(d,0);}if(y&&!I.has(e)){let d=a=>{typeof queueMicrotask=="function"?queueMicrotask(a):setTimeout(a,0);},S=a=>{let z=e.querySelector('[data-role="btn-label"]');if(!z||typeof n!="string")return;let g=t(n,void 0,"--");if(g!==n&&g!=="--"||a>=$){z.textContent=String(g),I.add(e);return}setTimeout(()=>{S(a+1);},ee);};d(()=>{S(0);});}}}:void 0,T={as:m,display:"inline-flex",align:"center",justify:"center",gap:j,px:v.px,py:v.py,radius:"md",className:W,...O,...X};return w&&(T.ref=w),jsx(Container,{...T,children:i})}export{oe 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","renderIcon","icon","size","iconSize","jsx","Icon","resolvedSize","Button","props","variant","color","fullWidth","disabled","loading","leftIcon","rightIcon","as","children","className","type","restProps","baseClasses","stateClasses","paletteClasses","classes","padding","gap","labelSize","content","left","right","Text","elementTypeProps","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\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 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 children,\r\n className,\r\n type = 'button',\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 if (children !== undefined && children !== null && children !== '') {\r\n content.push(\r\n <Text as=\"span\" size={labelSize}>\r\n {children}\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 return (\r\n <Container\r\n as={as}\r\n display = \"inline-flex\"\r\n align = \"center\"\r\n justify = \"center\"\r\n gap = {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 {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","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cruxkit/button",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
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,6 +40,7 @@
40
40
  "bun": "^1.3.3"
41
41
  },
42
42
  "dependencies": {
43
+ "@cruxjs/client": "^0.2.1",
43
44
  "@cruxkit/container": "^0.0.2",
44
45
  "@cruxkit/icon": "^0.0.3",
45
46
  "@cruxkit/text": "^0.0.2",