@walidsj/react-ui 0.1.1 → 0.1.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
@@ -29,13 +29,14 @@ Import the compiled stylesheet once, then use components from the package
29
29
  root:
30
30
 
31
31
  ``` tsx
32
- import { Button, Input } from "@walidsj/react-ui";
32
+ import { Button, Input, Textarea } from "@walidsj/react-ui";
33
33
  import "@walidsj/react-ui/style.css";
34
34
 
35
35
  export function Example() {
36
36
  return (
37
37
  <div style={{ display: "grid", gap: "1rem", maxWidth: "24rem" }}>
38
38
  <Input aria-label="Full name" placeholder="Full name" />
39
+ <Textarea aria-label="Notes" placeholder="Notes" size="lg" />
39
40
  <Button variant="primary" size="md">
40
41
  Save changes
41
42
  </Button>
@@ -69,6 +70,7 @@ Renders a native `<input>` and forwards native input props and refs.
69
70
  | Prop | Type | Default |
70
71
  | ----------- | --------- | ------- |
71
72
  | `invalid` | `boolean` | `false` |
73
+ | `size` | `sm \| md \| lg` | `md` |
72
74
  | `className` | `string` | — |
73
75
 
74
76
  `invalid` sets `aria-invalid="true"` and applies error styling. A
@@ -76,8 +78,34 @@ consumer-provided `aria-invalid` value is preserved when `invalid` is
76
78
  not set. Labels, descriptions, and error messages are composed by the
77
79
  consumer.
78
80
 
79
- Both components merge `className` with their internal classes. Conflicting
80
- Tailwind utilities are resolved with `tailwind-merge`.
81
+ `size` controls the input height and horizontal padding:
82
+
83
+ - `sm`: compact control (`h-8`)
84
+ - `md`: default control (`h-10`)
85
+ - `lg`: larger control (`h-12`)
86
+
87
+ ### Textarea
88
+
89
+ Renders a native `<textarea>` and forwards native textarea props and refs.
90
+
91
+ | Prop | Type | Default |
92
+ | ----------- | ---------------- | ------- |
93
+ | `invalid` | `boolean` | `false` |
94
+ | `size` | `sm \| md \| lg` | `md` |
95
+ | `className` | `string` | — |
96
+
97
+ `invalid` sets `aria-invalid="true"` and applies error styling. A
98
+ consumer-provided `aria-invalid` value is preserved when `invalid` is not set.
99
+ Labels, descriptions, and error messages are composed by the consumer.
100
+
101
+ `size` controls the minimum height and horizontal padding:
102
+
103
+ - `sm`: compact textarea (`min-h-16`)
104
+ - `md`: default textarea (`min-h-20`)
105
+ - `lg`: larger textarea (`min-h-28`)
106
+
107
+ Both form controls merge `className` with their internal classes using the
108
+ `cn` package. Consumers do not need to install `clsx` or `tailwind-merge`.
81
109
 
82
110
  ## Styling
83
111
 
@@ -1,2 +1,2 @@
1
- export type { InputProps } from './input';
1
+ export type { InputProps, InputSize } from './input';
2
2
  export { Input } from './input';
@@ -1,5 +1,13 @@
1
+ import { VariantProps } from 'class-variance-authority';
1
2
  import { ComponentPropsWithoutRef } from 'react';
2
- export interface InputProps extends ComponentPropsWithoutRef<"input"> {
3
+ declare const inputVariants: (props?: ({
4
+ size?: "sm" | "md" | "lg" | null | undefined;
5
+ invalid?: boolean | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export type InputSize = NonNullable<VariantProps<typeof inputVariants>["size"]>;
8
+ export interface InputProps extends Omit<ComponentPropsWithoutRef<"input">, "size"> {
3
9
  invalid?: boolean;
10
+ size?: InputSize;
4
11
  }
5
12
  export declare const Input: import('react').ForwardRefExoticComponent<InputProps & import('react').RefAttributes<HTMLInputElement>>;
13
+ export {};
@@ -0,0 +1 @@
1
+ export { Textarea, type TextareaProps, type TextareaSize } from './textarea';
@@ -0,0 +1,13 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+ import { ComponentPropsWithoutRef } from 'react';
3
+ declare const textareaVariants: (props?: ({
4
+ size?: "sm" | "md" | "lg" | null | undefined;
5
+ invalid?: boolean | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export type TextareaSize = NonNullable<VariantProps<typeof textareaVariants>["size"]>;
8
+ export interface TextareaProps extends ComponentPropsWithoutRef<"textarea"> {
9
+ invalid?: boolean;
10
+ size?: TextareaSize;
11
+ }
12
+ export declare const Textarea: import('react').ForwardRefExoticComponent<TextareaProps & import('react').RefAttributes<HTMLTextAreaElement>>;
13
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export type { ButtonProps, ButtonSize, ButtonVariant, } from './components/button';
2
2
  export { Button } from './components/button';
3
- export type { InputProps } from './components/input';
3
+ export type { InputProps, InputSize } from './components/input';
4
4
  export { Input } from './components/input';
5
+ export type { TextareaProps, TextareaSize } from './components/textarea';
6
+ export { Textarea } from './components/textarea';
package/dist/index.js CHANGED
@@ -1,9 +1,22 @@
1
1
  import { Button as Button$1 } from "@base-ui/react/button";
2
- import { clsx } from "clsx";
3
2
  import { forwardRef } from "react";
4
- import { twMerge } from "tailwind-merge";
3
+ import { cn } from "cn";
5
4
  import { jsx } from "react/jsx-runtime";
6
5
  import { Input as Input$1 } from "@base-ui/react/input";
6
+ // node_modules/clsx/dist/clsx.mjs
7
+ function r(e) {
8
+ var t, f, n = "";
9
+ if ("string" == typeof e || "number" == typeof e) n += e;
10
+ else if ("object" == typeof e) if (Array.isArray(e)) {
11
+ var o = e.length;
12
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
13
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
14
+ return n;
15
+ }
16
+ function clsx() {
17
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
18
+ return n;
19
+ }
7
20
  // node_modules/class-variance-authority/dist/index.mjs
8
21
  /**
9
22
  * Copyright 2022 Joe Bell. All rights reserved.
@@ -56,18 +69,14 @@ var cva = (base, config) => (props) => {
56
69
  ] : acc;
57
70
  }, []), props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
58
71
  };
59
- // src/lib/cn.ts
60
- function cn(...inputs) {
61
- return twMerge(clsx(inputs));
62
- }
63
72
  // src/components/button/button.tsx
64
- var buttonVariants = cva("inline-flex select-none items-center justify-center whitespace-nowrap rounded-ui-md font-medium transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50", {
73
+ var buttonVariants = cva("rounded-ui-md focus-visible:ring-ring focus-visible:ring-offset-background inline-flex items-center justify-center font-medium whitespace-nowrap transition-colors outline-none select-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", {
65
74
  variants: {
66
75
  variant: {
67
76
  primary: "bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80",
68
77
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 active:bg-secondary/70",
69
- outline: "border border-border bg-transparent text-foreground hover:bg-muted active:bg-muted/70",
70
- ghost: "bg-transparent text-foreground hover:bg-muted active:bg-muted/70",
78
+ outline: "border-border text-foreground hover:bg-muted active:bg-muted/70 border bg-transparent",
79
+ ghost: "text-foreground hover:bg-muted active:bg-muted/70 bg-transparent",
71
80
  danger: "bg-danger text-danger-foreground hover:bg-danger/90 active:bg-danger/80"
72
81
  },
73
82
  size: {
@@ -93,14 +102,63 @@ var Button = forwardRef(function Button({ className, variant = "primary", size =
93
102
  });
94
103
  });
95
104
  // src/components/input/input.tsx
96
- var Input = forwardRef(function Input({ className, invalid = false, "aria-invalid": ariaInvalid, ...props }, ref) {
105
+ var inputVariants = cva("rounded-ui-md border-border bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/30 flex w-full border py-2 shadow-sm transition-colors outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50", {
106
+ variants: {
107
+ size: {
108
+ sm: "h-8 px-2.5 text-sm",
109
+ md: "h-10 px-3 text-sm",
110
+ lg: "h-12 px-4 text-base"
111
+ },
112
+ invalid: {
113
+ true: "border-danger focus-visible:ring-danger/30",
114
+ false: ""
115
+ }
116
+ },
117
+ defaultVariants: {
118
+ size: "md",
119
+ invalid: false
120
+ }
121
+ });
122
+ var Input = forwardRef(function Input({ className, invalid = false, size = "md", "aria-invalid": ariaInvalid, ...props }, ref) {
97
123
  return /* @__PURE__ */ jsx(Input$1, {
98
124
  ...props,
99
125
  ref,
100
126
  "aria-invalid": invalid || ariaInvalid,
101
- className: cn("flex h-10 w-full rounded-ui-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-danger aria-[invalid=true]:focus-visible:ring-danger/30", className)
127
+ className: cn(inputVariants({
128
+ size,
129
+ invalid
130
+ }), className)
131
+ });
132
+ });
133
+ // src/components/textarea/textarea.tsx
134
+ var textareaVariants = cva("rounded-ui-md border-border bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/30 flex w-full resize-y border py-2 shadow-sm transition-colors outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50", {
135
+ variants: {
136
+ size: {
137
+ sm: "min-h-16 px-2.5 text-sm",
138
+ md: "min-h-20 px-3 text-sm",
139
+ lg: "min-h-28 px-4 text-base"
140
+ },
141
+ invalid: {
142
+ true: "border-danger focus-visible:ring-danger/30",
143
+ false: ""
144
+ }
145
+ },
146
+ defaultVariants: {
147
+ size: "md",
148
+ invalid: false
149
+ }
150
+ });
151
+ var Textarea = forwardRef(function Textarea({ className, invalid = false, size = "md", "aria-invalid": ariaInvalid, ...props }, ref) {
152
+ return /* @__PURE__ */ jsx("textarea", {
153
+ ...props,
154
+ ref,
155
+ "aria-invalid": invalid || ariaInvalid,
156
+ className: cn(textareaVariants({
157
+ size,
158
+ invalid
159
+ }), className)
102
160
  });
103
161
  });
104
- export { Button, Input };
162
+ export { Button, Input, Textarea };
105
163
 
106
164
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["BaseButton","BaseInput"],"sources":["../node_modules/class-variance-authority/dist/index.mjs","../src/lib/cn.ts","../src/components/button/button.tsx","../src/components/input/input.tsx"],"sourcesContent":["/**\n * Copyright 2022 Joe Bell. All rights reserved.\n *\n * This file is licensed to you under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with the\n * License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */ import { clsx } from \"clsx\";\nconst falsyToString = (value)=>typeof value === \"boolean\" ? `${value}` : value === 0 ? \"0\" : value;\nexport const cx = clsx;\nexport const cva = (base, config)=>(props)=>{\n var _config_compoundVariants;\n if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n const { variants, defaultVariants } = config;\n const getVariantClassNames = Object.keys(variants).map((variant)=>{\n const variantProp = props === null || props === void 0 ? void 0 : props[variant];\n const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];\n if (variantProp === null) return null;\n const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);\n return variants[variant][variantKey];\n });\n const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param)=>{\n let [key, value] = param;\n if (value === undefined) {\n return acc;\n }\n acc[key] = value;\n return acc;\n }, {});\n const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param)=>{\n let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;\n return Object.entries(compoundVariantOptions).every((param)=>{\n let [key, value] = param;\n return Array.isArray(value) ? value.includes({\n ...defaultVariants,\n ...propsWithoutUndefined\n }[key]) : ({\n ...defaultVariants,\n ...propsWithoutUndefined\n })[key] === value;\n }) ? [\n ...acc,\n cvClass,\n cvClassName\n ] : acc;\n }, []);\n return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n };\n\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { type ComponentPropsWithoutRef, forwardRef, type Ref } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex select-none items-center justify-center whitespace-nowrap rounded-ui-md font-medium transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 active:bg-secondary/70\",\n outline:\n \"border border-border bg-transparent text-foreground hover:bg-muted active:bg-muted/70\",\n ghost:\n \"bg-transparent text-foreground hover:bg-muted active:bg-muted/70\",\n danger:\n \"bg-danger text-danger-foreground hover:bg-danger/90 active:bg-danger/80\",\n },\n size: {\n sm: \"h-8 gap-1.5 px-3 text-sm\",\n md: \"h-10 gap-2 px-4 text-sm\",\n lg: \"h-12 gap-2.5 px-6 text-base\",\n },\n },\n defaultVariants: {\n variant: \"primary\",\n size: \"md\",\n },\n },\n);\n\nexport type ButtonVariant = NonNullable<\n VariantProps<typeof buttonVariants>[\"variant\"]\n>;\nexport type ButtonSize = NonNullable<\n VariantProps<typeof buttonVariants>[\"size\"]\n>;\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", size = \"md\", type = \"button\", ...props },\n ref,\n ) {\n return (\n <BaseButton\n {...props}\n ref={ref as Ref<HTMLElement>}\n type={type}\n className={cn(buttonVariants({ variant, size }), className)}\n />\n );\n },\n);\n","import { Input as BaseInput } from \"@base-ui/react/input\";\nimport { type ComponentPropsWithoutRef, forwardRef, type Ref } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport interface InputProps extends ComponentPropsWithoutRef<\"input\"> {\n invalid?: boolean;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { className, invalid = false, \"aria-invalid\": ariaInvalid, ...props },\n ref,\n) {\n return (\n <BaseInput\n {...props}\n ref={ref as Ref<HTMLElement>}\n aria-invalid={invalid || ariaInvalid}\n className={cn(\n \"flex h-10 w-full rounded-ui-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-danger aria-[invalid=true]:focus-visible:ring-danger/30\",\n className,\n )}\n />\n );\n});\n"],"ignoreList":[0],"mappings":";;;;;;;;;;;;;;;;;;;;;GAeA,IAAM,iBAAiB,UAAQ,OAAO,UAAU,YAAY,GAAG,UAAU,UAAU,IAAI,MAAM;AAC7F,IAAa,KAAK;AAClB,IAAa,OAAO,MAAM,YAAU,UAAQ;CACpC,IAAI;CACJ,KAAK,WAAW,QAAQ,WAAW,KAAK,IAAI,KAAK,IAAI,OAAO,aAAa,MAAM,OAAO,GAAG,MAAM,UAAU,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,OAAO,UAAU,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,SAAS;CACvN,MAAM,EAAE,UAAU,oBAAoB;CACtC,MAAM,uBAAuB,OAAO,KAAK,QAAQ,CAAC,CAAC,KAAK,YAAU;EAC9D,MAAM,cAAc,UAAU,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM;EACxE,MAAM,qBAAqB,oBAAoB,QAAQ,oBAAoB,KAAK,IAAI,KAAK,IAAI,gBAAgB;EAC7G,IAAI,gBAAgB,MAAM,OAAO;EACjC,MAAM,aAAa,cAAc,WAAW,KAAK,cAAc,kBAAkB;EACjF,OAAO,SAAS,QAAQ,CAAC;CAC7B,CAAC;CACD,MAAM,wBAAwB,SAAS,OAAO,QAAQ,KAAK,CAAC,CAAC,QAAQ,KAAK,UAAQ;EAC9E,IAAI,CAAC,KAAK,SAAS;EACnB,IAAI,UAAU,KAAA,GACV,OAAO;EAEX,IAAI,OAAO;EACX,OAAO;CACX,GAAG,CAAC,CAAC;CAkBL,OAAO,GAAG,MAAM,sBAjBqB,WAAW,QAAQ,WAAW,KAAK,IAAI,KAAK,KAAK,2BAA2B,OAAO,sBAAsB,QAAQ,6BAA6B,KAAK,IAAI,KAAK,IAAI,yBAAyB,QAAQ,KAAK,UAAQ;EAC/O,IAAI,EAAE,OAAO,SAAS,WAAW,aAAa,GAAG,2BAA2B;EAC5E,OAAO,OAAO,QAAQ,sBAAsB,CAAC,CAAC,OAAO,UAAQ;GACzD,IAAI,CAAC,KAAK,SAAS;GACnB,OAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS;IACzC,GAAG;IACH,GAAG;GACP,EAAE,IAAI,IAAK;IACP,GAAG;IACH,GAAG;GACP,EAAG,SAAS;EAChB,CAAC,IAAI;GACD,GAAG;GACH;GACA;EACJ,IAAI;CACR,GAAG,CAAC,CAAC,GAC+D,UAAU,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,OAAO,UAAU,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,MAAM,SAAS;AAChM;;ACnDJ,SAAgB,GAAG,GAAG,QAAsB;CAC1C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;ACAA,IAAM,iBAAiB,IACrB,iSACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,WACE;GACF,SACE;GACF,OACE;GACF,QACE;EACJ;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;AACF,CACF;AAcA,IAAa,SAAS,WACpB,SAAS,OACP,EAAE,WAAW,UAAU,WAAW,OAAO,MAAM,OAAO,UAAU,GAAG,SACnE,KACA;CACA,OACE,oBAACA,UAAD;EACE,GAAI;EACC;EACC;EACN,WAAW,GAAG,eAAe;GAAE;GAAS;EAAK,CAAC,GAAG,SAAS;CAC3D,CAAA;AAEL,CACF;;ACpDA,IAAa,QAAQ,WAAyC,SAAS,MACrE,EAAE,WAAW,UAAU,OAAO,gBAAgB,aAAa,GAAG,SAC9D,KACA;CACA,OACE,oBAACC,SAAD;EACE,GAAI;EACC;EACL,gBAAc,WAAW;EACzB,WAAW,GACT,+XACA,SACF;CACD,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"index.js","names":["BaseButton","BaseInput"],"sources":["../node_modules/clsx/dist/clsx.mjs","../node_modules/class-variance-authority/dist/index.mjs","../src/components/button/button.tsx","../src/components/input/input.tsx","../src/components/textarea/textarea.tsx"],"sourcesContent":["function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","/**\n * Copyright 2022 Joe Bell. All rights reserved.\n *\n * This file is licensed to you under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with the\n * License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */ import { clsx } from \"clsx\";\nconst falsyToString = (value)=>typeof value === \"boolean\" ? `${value}` : value === 0 ? \"0\" : value;\nexport const cx = clsx;\nexport const cva = (base, config)=>(props)=>{\n var _config_compoundVariants;\n if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n const { variants, defaultVariants } = config;\n const getVariantClassNames = Object.keys(variants).map((variant)=>{\n const variantProp = props === null || props === void 0 ? void 0 : props[variant];\n const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];\n if (variantProp === null) return null;\n const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);\n return variants[variant][variantKey];\n });\n const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param)=>{\n let [key, value] = param;\n if (value === undefined) {\n return acc;\n }\n acc[key] = value;\n return acc;\n }, {});\n const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param)=>{\n let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;\n return Object.entries(compoundVariantOptions).every((param)=>{\n let [key, value] = param;\n return Array.isArray(value) ? value.includes({\n ...defaultVariants,\n ...propsWithoutUndefined\n }[key]) : ({\n ...defaultVariants,\n ...propsWithoutUndefined\n })[key] === value;\n }) ? [\n ...acc,\n cvClass,\n cvClassName\n ] : acc;\n }, []);\n return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);\n };\n\n","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { type ComponentPropsWithoutRef, forwardRef, type Ref } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nconst buttonVariants = cva(\n \"rounded-ui-md focus-visible:ring-ring focus-visible:ring-offset-background inline-flex items-center justify-center font-medium whitespace-nowrap transition-colors outline-none select-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 active:bg-secondary/70\",\n outline:\n \"border-border text-foreground hover:bg-muted active:bg-muted/70 border bg-transparent\",\n ghost:\n \"text-foreground hover:bg-muted active:bg-muted/70 bg-transparent\",\n danger:\n \"bg-danger text-danger-foreground hover:bg-danger/90 active:bg-danger/80\",\n },\n size: {\n sm: \"h-8 gap-1.5 px-3 text-sm\",\n md: \"h-10 gap-2 px-4 text-sm\",\n lg: \"h-12 gap-2.5 px-6 text-base\",\n },\n },\n defaultVariants: {\n variant: \"primary\",\n size: \"md\",\n },\n },\n);\n\nexport type ButtonVariant = NonNullable<\n VariantProps<typeof buttonVariants>[\"variant\"]\n>;\nexport type ButtonSize = NonNullable<\n VariantProps<typeof buttonVariants>[\"size\"]\n>;\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", size = \"md\", type = \"button\", ...props },\n ref,\n ) {\n return (\n <BaseButton\n {...props}\n ref={ref as Ref<HTMLElement>}\n type={type}\n className={cn(buttonVariants({ variant, size }), className)}\n />\n );\n },\n);\n","import { Input as BaseInput } from \"@base-ui/react/input\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { type ComponentPropsWithoutRef, forwardRef, type Ref } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nconst inputVariants = cva(\n \"rounded-ui-md border-border bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/30 flex w-full border py-2 shadow-sm transition-colors outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n size: {\n sm: \"h-8 px-2.5 text-sm\",\n md: \"h-10 px-3 text-sm\",\n lg: \"h-12 px-4 text-base\",\n },\n invalid: {\n true: \"border-danger focus-visible:ring-danger/30\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"md\",\n invalid: false,\n },\n },\n);\n\nexport type InputSize = NonNullable<VariantProps<typeof inputVariants>[\"size\"]>;\n\nexport interface InputProps\n extends Omit<ComponentPropsWithoutRef<\"input\">, \"size\"> {\n invalid?: boolean;\n size?: InputSize;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n className,\n invalid = false,\n size = \"md\",\n \"aria-invalid\": ariaInvalid,\n ...props\n },\n ref,\n) {\n return (\n <BaseInput\n {...props}\n ref={ref as Ref<HTMLElement>}\n aria-invalid={invalid || ariaInvalid}\n className={cn(inputVariants({ size, invalid }), className)}\n />\n );\n});\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport { type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nconst textareaVariants = cva(\n \"rounded-ui-md border-border bg-background text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/30 flex w-full resize-y border py-2 shadow-sm transition-colors outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50\",\n {\n variants: {\n size: {\n sm: \"min-h-16 px-2.5 text-sm\",\n md: \"min-h-20 px-3 text-sm\",\n lg: \"min-h-28 px-4 text-base\",\n },\n invalid: {\n true: \"border-danger focus-visible:ring-danger/30\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"md\",\n invalid: false,\n },\n },\n);\n\nexport type TextareaSize = NonNullable<\n VariantProps<typeof textareaVariants>[\"size\"]\n>;\n\nexport interface TextareaProps extends ComponentPropsWithoutRef<\"textarea\"> {\n invalid?: boolean;\n size?: TextareaSize;\n}\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n function Textarea(\n {\n className,\n invalid = false,\n size = \"md\",\n \"aria-invalid\": ariaInvalid,\n ...props\n },\n ref,\n ) {\n return (\n <textarea\n {...props}\n ref={ref}\n aria-invalid={invalid || ariaInvalid}\n className={cn(textareaVariants({ size, invalid }), className)}\n />\n );\n },\n);\n"],"ignoreList":[0,1],"mappings":"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"}
package/dist/lib/cn.d.ts CHANGED
@@ -1,2 +1 @@
1
- import { ClassValue } from 'clsx';
2
- export declare function cn(...inputs: ClassValue[]): string;
1
+ export { cn } from 'cn';
package/dist/style.css CHANGED
@@ -57,10 +57,26 @@
57
57
  height: calc(var(--spacing) * 12);
58
58
  }
59
59
 
60
+ .min-h-16 {
61
+ min-height: calc(var(--spacing) * 16);
62
+ }
63
+
64
+ .min-h-20 {
65
+ min-height: calc(var(--spacing) * 20);
66
+ }
67
+
68
+ .min-h-28 {
69
+ min-height: calc(var(--spacing) * 28);
70
+ }
71
+
60
72
  .w-full {
61
73
  width: 100%;
62
74
  }
63
75
 
76
+ .resize-y {
77
+ resize: vertical;
78
+ }
79
+
64
80
  .items-center {
65
81
  align-items: center;
66
82
  }
@@ -94,6 +110,10 @@
94
110
  border-color: var(--ui-border);
95
111
  }
96
112
 
113
+ .border-danger {
114
+ border-color: var(--ui-danger);
115
+ }
116
+
97
117
  .bg-background {
98
118
  background-color: var(--ui-background);
99
119
  }
@@ -114,6 +134,10 @@
114
134
  background-color: #0000;
115
135
  }
116
136
 
137
+ .px-2\.5 {
138
+ padding-inline: calc(var(--spacing) * 2.5);
139
+ }
140
+
117
141
  .px-3 {
118
142
  padding-inline: calc(var(--spacing) * 3);
119
143
  }
@@ -240,6 +264,16 @@
240
264
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
241
265
  }
242
266
 
267
+ .focus-visible\:ring-danger\/30:focus-visible {
268
+ --tw-ring-color: var(--ui-danger);
269
+ }
270
+
271
+ @supports (color: color-mix(in lab, red, red)) {
272
+ .focus-visible\:ring-danger\/30:focus-visible {
273
+ --tw-ring-color: color-mix(in oklab, var(--ui-danger) 30%, transparent);
274
+ }
275
+ }
276
+
243
277
  .focus-visible\:ring-ring:focus-visible, .focus-visible\:ring-ring\/30:focus-visible {
244
278
  --tw-ring-color: var(--ui-ring);
245
279
  }
@@ -310,20 +344,6 @@
310
344
  .disabled\:opacity-50:disabled {
311
345
  opacity: .5;
312
346
  }
313
-
314
- .aria-\[invalid\=true\]\:border-danger[aria-invalid="true"] {
315
- border-color: var(--ui-danger);
316
- }
317
-
318
- .aria-\[invalid\=true\]\:focus-visible\:ring-danger\/30[aria-invalid="true"]:focus-visible {
319
- --tw-ring-color: var(--ui-danger);
320
- }
321
-
322
- @supports (color: color-mix(in lab, red, red)) {
323
- .aria-\[invalid\=true\]\:focus-visible\:ring-danger\/30[aria-invalid="true"]:focus-visible {
324
- --tw-ring-color: color-mix(in oklab, var(--ui-danger) 30%, transparent);
325
- }
326
- }
327
347
  }
328
348
 
329
349
  :root {
package/package.json CHANGED
@@ -1,22 +1,29 @@
1
1
  {
2
2
  "name": "@walidsj/react-ui",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "Accessible React components styled with Tailwind CSS v4 and built on Base UI primitives.",
5
- "license": "MIT",
6
- "author": "walidsj (https://github.com/walidsj)",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/walidsj/walid-ui.git"
10
- },
5
+ "keywords": [
6
+ "react",
7
+ "design-system",
8
+ "component-library",
9
+ "tailwindcss",
10
+ "base-ui",
11
+ "typescript"
12
+ ],
11
13
  "homepage": "https://github.com/walidsj/walid-ui#readme",
12
14
  "bugs": {
13
15
  "url": "https://github.com/walidsj/walid-ui/issues"
14
16
  },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/walidsj/walid-ui.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": "walidsj (https://github.com/walidsj)",
23
+ "sideEffects": [
24
+ "**/*.css"
25
+ ],
15
26
  "type": "module",
16
- "packageManager": "bun@1.4.4",
17
- "main": "./dist/index.js",
18
- "module": "./dist/index.js",
19
- "types": "./dist/index.d.ts",
20
27
  "exports": {
21
28
  ".": {
22
29
  "types": "./dist/index.d.ts",
@@ -25,47 +32,28 @@
25
32
  "./style.css": "./dist/style.css",
26
33
  "./package.json": "./package.json"
27
34
  },
35
+ "main": "./dist/index.js",
36
+ "module": "./dist/index.js",
37
+ "types": "./dist/index.d.ts",
28
38
  "files": [
29
39
  "dist"
30
40
  ],
31
- "sideEffects": [
32
- "**/*.css"
33
- ],
34
- "publishConfig": {
35
- "access": "public"
36
- },
37
- "engines": {
38
- "node": ">=20.19.0"
39
- },
40
- "keywords": [
41
- "react",
42
- "design-system",
43
- "component-library",
44
- "tailwindcss",
45
- "base-ui",
46
- "typescript"
47
- ],
48
41
  "scripts": {
49
- "dev": "vite build --watch",
50
42
  "build": "vite build",
51
- "typecheck": "tsc --noEmit",
52
- "test": "vitest run",
53
- "test:watch": "vitest",
54
- "lint": "biome check .",
43
+ "clean": "rm -rf dist coverage",
44
+ "dev": "vite build --watch",
55
45
  "format": "biome format --write .",
56
46
  "format:check": "biome format .",
57
- "clean": "rm -rf dist coverage",
58
- "prepublishOnly": "bun run clean && bun run lint && bun run typecheck && bun run test && bun run build"
59
- },
60
- "peerDependencies": {
61
- "react": "^19.0.0",
62
- "react-dom": "^19.0.0"
47
+ "lint": "biome check .",
48
+ "prepublishOnly": "bun run clean && bun run lint && bun run typecheck && bun run test && bun run build",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest",
51
+ "typecheck": "tsc --noEmit"
63
52
  },
64
53
  "dependencies": {
65
54
  "@base-ui/react": "^1.9.0",
66
55
  "class-variance-authority": "^0.7.1",
67
- "clsx": "^2.1.1",
68
- "tailwind-merge": "^3.7.0"
56
+ "cn": "^0.5.0"
69
57
  },
70
58
  "devDependencies": {
71
59
  "@biomejs/biome": "2.6.3",
@@ -86,5 +74,16 @@
86
74
  "vite": "8.3.5",
87
75
  "vite-plugin-dts": "5.1.2",
88
76
  "vitest": "5.0.5"
77
+ },
78
+ "peerDependencies": {
79
+ "react": "^19.0.0",
80
+ "react-dom": "^19.0.0"
81
+ },
82
+ "packageManager": "bun@1.4.4",
83
+ "engines": {
84
+ "node": ">=20.19.0"
85
+ },
86
+ "publishConfig": {
87
+ "access": "public"
89
88
  }
90
89
  }