@azmr/ui 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @azmr/ui
2
2
 
3
- React components wired to reactive Signals. The `Grid` component re-renders automatically when its Signal changes — no state management needed.
3
+ Accessible React design system built on Base UI and Tailwind v4 tokens: buttons, menus, modals, tables, toasts and more. Components that take a Signal, such as `Grid`, re-render when it changes, with no state management needed.
4
4
 
5
5
  ## Install
6
6
 
@@ -172,7 +172,8 @@ An unknown name renders nothing and logs one development warning; it never crash
172
172
  | `@azmr/ui/theme` | server-safe theme helpers: `createTheme`, cookies, `htmlAttributes`, `createLocale` | none, importable from Server Components and middleware |
173
173
  | `@azmr/ui/react` | `ThemeProvider`, `useTheme`, `LocaleProvider`, `useLocale` | `"use client"` |
174
174
  | `@azmr/ui/button` | `Button`, `buttonVariants` | `"use client"` |
175
- | `@azmr/ui/input` | `Input` | `"use client"` |
175
+ | `@azmr/ui/input` | `Input`, `Textarea` | `"use client"` |
176
+ | `@azmr/ui/field` | `Field`, `FieldRoot`, `FieldLabel`, `FieldDescription`, `FieldError` | `"use client"` |
176
177
  | `@azmr/ui/spinner` | `Spinner` | none, importable from Server Components |
177
178
  | `@azmr/ui/icons` | `Icon`, `createIconSet`, `registerIcons` | none, importable from Server Components |
178
179
  | `@azmr/ui/icons/lucide` | `Icon` bound to the curated Lucide set, `lucideIcons` | none, importable from Server Components |
@@ -237,7 +238,7 @@ All cell values are rendered through React's JSX escaping — `dangerouslySetInn
237
238
 
238
239
  ## Documentation
239
240
 
240
- Full docs at [docs.azmara.io](https://docs.azmara.io)
241
+ Full docs at [platform.azmara.io](https://platform.azmara.io/docs/packages/ui)
241
242
 
242
243
  ## License
243
244
 
@@ -61,4 +61,4 @@ declare const Button: react.ForwardRefExoticComponent<(Omit<BaseButtonProps & {
61
61
  size?: TextButtonSize;
62
62
  }, "ref">) & react.RefAttributes<HTMLButtonElement>>;
63
63
 
64
- export { type ButtonOwnProps as B, Button as a, type ButtonProps as b, buttonVariants as c };
64
+ export { Button as B, type ButtonProps as a, buttonVariants as b, type ButtonOwnProps as c };
package/dist/button.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as ButtonOwnProps } from './button-CYt2Zw3D.js';
2
- export { a as Button, b as ButtonProps, c as buttonVariants } from './button-CYt2Zw3D.js';
1
+ import { c as ButtonOwnProps } from './button-D_1Tb_Km.js';
2
+ export { B as Button, a as ButtonProps, b as buttonVariants } from './button-D_1Tb_Km.js';
3
3
  import * as react from 'react';
4
4
  import { HTMLAttributes, ReactNode } from 'react';
5
5
  import { ButtonProps } from '@base-ui/react/button';
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ import {
3
+ Field
4
+ } from "./chunk-ZJV2SYVH.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-2TQSHVXA.js";
8
+
9
+ // src/components/input/input.tsx
10
+ import { forwardRef } from "react";
11
+
12
+ // src/primitives/input.ts
13
+ import { Input } from "@base-ui/react/input";
14
+
15
+ // src/components/input/input.tsx
16
+ import { jsx } from "react/jsx-runtime";
17
+ var Input2 = forwardRef(function Input3({ className, type = "text", ...props }, ref) {
18
+ return /* @__PURE__ */ jsx(
19
+ Input,
20
+ {
21
+ ref,
22
+ type,
23
+ className: cn(
24
+ "flex h-(--density-control-height) w-full min-w-0 rounded-md border border-input bg-background px-(--density-control-padding-x) py-1 text-sm text-foreground",
25
+ "transition-colors duration-(--motion-duration-fast) ease-standard",
26
+ "outline-none placeholder:text-muted-foreground",
27
+ "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring",
28
+ "aria-invalid:border-destructive data-[invalid]:border-destructive",
29
+ "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 read-only:bg-muted",
30
+ className
31
+ ),
32
+ ...props
33
+ }
34
+ );
35
+ });
36
+
37
+ // src/components/input/textarea.tsx
38
+ import { forwardRef as forwardRef2 } from "react";
39
+ import { jsx as jsx2 } from "react/jsx-runtime";
40
+ var Textarea = forwardRef2(function Textarea2({ className, autoResize, rows = 3, onValueChange, ...props }, ref) {
41
+ return /* @__PURE__ */ jsx2(
42
+ Field.Control,
43
+ {
44
+ ref,
45
+ render: /* @__PURE__ */ jsx2("textarea", { rows }),
46
+ onValueChange: onValueChange ? (value) => onValueChange(value) : void 0,
47
+ className: cn(
48
+ "flex min-h-16 w-full min-w-0 rounded-md border border-input bg-background px-(--density-control-padding-x) py-2 text-sm text-foreground",
49
+ "transition-colors duration-(--motion-duration-fast) ease-standard",
50
+ "outline-none placeholder:text-muted-foreground",
51
+ "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring",
52
+ "aria-invalid:border-destructive data-[invalid]:border-destructive",
53
+ "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 read-only:bg-muted",
54
+ autoResize ? "resize-none field-sizing-content" : "resize-y",
55
+ className
56
+ ),
57
+ ...props
58
+ }
59
+ );
60
+ });
61
+
62
+ export {
63
+ Input2 as Input,
64
+ Textarea
65
+ };
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ // src/primitives/field.ts
4
+ import { Field } from "@base-ui/react/field";
5
+
6
+ export {
7
+ Field
8
+ };
@@ -0,0 +1,57 @@
1
+ import * as react from 'react';
2
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
3
+ import * as _base_ui_react_field from '@base-ui/react/field';
4
+ import { Field as Field$1 } from '@base-ui/react/field';
5
+
6
+ type Classed<T> = Omit<T, "className"> & {
7
+ className?: string;
8
+ };
9
+ /** Groups a control with its label, description and error. Base UI wires the ids between them. */
10
+ declare const FieldRoot: react.ForwardRefExoticComponent<Omit<Omit<Omit<_base_ui_react_field.FieldRootProps, "ref"> & react.RefAttributes<HTMLDivElement>, "ref">, "className"> & {
11
+ className?: string;
12
+ } & react.RefAttributes<HTMLDivElement>>;
13
+ type FieldLabelProps = Classed<ComponentPropsWithoutRef<typeof Field$1.Label>> & {
14
+ /** Shows a required marker. It is hidden from screen readers, which hear `aria-required` on the control instead. */
15
+ required?: boolean;
16
+ };
17
+ /** The control's `<label>`, associated with it automatically. */
18
+ declare const FieldLabel: react.ForwardRefExoticComponent<Omit<Omit<Omit<_base_ui_react_field.FieldLabelProps, "ref"> & react.RefAttributes<HTMLElement>, "ref">, "className"> & {
19
+ className?: string;
20
+ } & {
21
+ /** Shows a required marker. It is hidden from screen readers, which hear `aria-required` on the control instead. */
22
+ required?: boolean;
23
+ } & react.RefAttributes<HTMLElement>>;
24
+ /** Help text for the control, read out after its label through `aria-describedby`. */
25
+ declare const FieldDescription: react.ForwardRefExoticComponent<Omit<Omit<Omit<_base_ui_react_field.FieldDescriptionProps, "ref"> & react.RefAttributes<HTMLParagraphElement>, "ref">, "className"> & {
26
+ className?: string;
27
+ } & react.RefAttributes<HTMLParagraphElement>>;
28
+ /**
29
+ * The error message. With no `match` it shows the field's own validation messages (the `validate`
30
+ * prop or native constraints); pass `match` to show it whenever an outside library, such as
31
+ * React Hook Form, says the field is invalid.
32
+ */
33
+ declare const FieldError: react.ForwardRefExoticComponent<Omit<Omit<Omit<_base_ui_react_field.FieldErrorProps, "ref"> & react.RefAttributes<HTMLDivElement>, "ref">, "className"> & {
34
+ className?: string;
35
+ } & react.RefAttributes<HTMLDivElement>>;
36
+ interface FieldProps extends Classed<Omit<ComponentPropsWithoutRef<typeof Field$1.Root>, "children">> {
37
+ label?: ReactNode;
38
+ description?: ReactNode;
39
+ /**
40
+ * The error to show, for example `errors.email?.message` from React Hook Form. Any value
41
+ * other than `undefined`, `null`, `false` or `""` marks the field invalid.
42
+ */
43
+ error?: ReactNode;
44
+ /** Shows the required marker and sets `aria-required` on the control. */
45
+ required?: boolean;
46
+ /** One control: `Input`, `Textarea` or any Base UI control. */
47
+ children: ReactNode;
48
+ }
49
+ /**
50
+ * A labelled form control. Wraps one control and wires `id`, `aria-labelledby`,
51
+ * `aria-describedby`, `aria-invalid` and `aria-errormessage` for it. Errors appear in a polite
52
+ * live region, so screen readers announce them when they arrive. Use the parts (`FieldRoot`,
53
+ * `FieldLabel`, `FieldDescription`, `FieldError`) for layouts this one doesn't cover.
54
+ */
55
+ declare const Field: react.ForwardRefExoticComponent<FieldProps & react.RefAttributes<HTMLDivElement>>;
56
+
57
+ export { Field, FieldDescription, FieldError, FieldLabel, type FieldLabelProps, type FieldProps, FieldRoot };
package/dist/field.js ADDED
@@ -0,0 +1,82 @@
1
+ "use client";
2
+ import {
3
+ Field
4
+ } from "./chunk-ZJV2SYVH.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-2TQSHVXA.js";
8
+
9
+ // src/components/field/field.tsx
10
+ import {
11
+ Children,
12
+ cloneElement,
13
+ forwardRef,
14
+ isValidElement,
15
+ useId
16
+ } from "react";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ var FieldRoot = forwardRef(function FieldRoot2({ className, ...props }, ref) {
19
+ return /* @__PURE__ */ jsx(Field.Root, { ref, className: cn("flex flex-col gap-1.5", className), ...props });
20
+ });
21
+ var FieldLabel = forwardRef(function FieldLabel2({ className, required, children, ...props }, ref) {
22
+ return /* @__PURE__ */ jsxs(
23
+ Field.Label,
24
+ {
25
+ ref,
26
+ className: cn(
27
+ "text-sm font-medium leading-none text-foreground data-[disabled]:opacity-50",
28
+ className
29
+ ),
30
+ ...props,
31
+ children: [
32
+ children,
33
+ required ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ms-0.5 text-destructive", children: "*" }) : null
34
+ ]
35
+ }
36
+ );
37
+ });
38
+ var FieldDescription = forwardRef(function FieldDescription2({ className, ...props }, ref) {
39
+ return /* @__PURE__ */ jsx(
40
+ Field.Description,
41
+ {
42
+ ref,
43
+ className: cn("text-sm text-muted-foreground", className),
44
+ ...props
45
+ }
46
+ );
47
+ });
48
+ var FieldError = forwardRef(function FieldError2({ className, ...props }, ref) {
49
+ return /* @__PURE__ */ jsx(
50
+ Field.Error,
51
+ {
52
+ ref,
53
+ className: cn("text-sm font-medium text-destructive", className),
54
+ ...props
55
+ }
56
+ );
57
+ });
58
+ function hasError(error) {
59
+ return error !== void 0 && error !== null && error !== false && error !== "";
60
+ }
61
+ var Field2 = forwardRef(function Field3({ label, description, error, required, invalid, children, ...props }, ref) {
62
+ const errorId = useId();
63
+ const showError = hasError(error);
64
+ const only = Children.count(children) === 1 && isValidElement(children) ? children : null;
65
+ const control = only ? cloneElement(only, {
66
+ ...required ? { "aria-required": true } : {},
67
+ ...showError ? { "aria-errormessage": errorId } : {}
68
+ }) : children;
69
+ return /* @__PURE__ */ jsxs(FieldRoot, { ref, invalid: showError || invalid, ...props, children: [
70
+ label !== void 0 ? /* @__PURE__ */ jsx(FieldLabel, { required, children: label }) : null,
71
+ description !== void 0 ? /* @__PURE__ */ jsx(FieldDescription, { children: description }) : null,
72
+ control,
73
+ /* @__PURE__ */ jsx("div", { "aria-live": "polite", className: "empty:-mt-1.5", children: /* @__PURE__ */ jsx(FieldError, { id: errorId, ...showError ? { match: true, children: error } : {} }) })
74
+ ] });
75
+ });
76
+ export {
77
+ Field2 as Field,
78
+ FieldDescription,
79
+ FieldError,
80
+ FieldLabel,
81
+ FieldRoot
82
+ };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { a as Button, b as ButtonProps, c as buttonVariants } from './button-CYt2Zw3D.js';
2
- export { Input, InputProps } from './input.js';
1
+ export { B as Button, a as ButtonProps, b as buttonVariants } from './button-D_1Tb_Km.js';
2
+ export { I as Input, a as InputProps } from './input-BS0DXbuH.js';
3
3
  import * as react from 'react';
4
4
  import { SVGProps, HTMLAttributes, ReactNode, ElementType, ComponentPropsWithoutRef, Ref, ReactElement, ComponentType } from 'react';
5
5
  import { Signal } from '@azmr/core';
package/dist/index.js CHANGED
@@ -18,7 +18,8 @@ import {
18
18
  import "./chunk-EE4V6XMB.js";
19
19
  import {
20
20
  Input
21
- } from "./chunk-GX2YEJ43.js";
21
+ } from "./chunk-V6RHWYYO.js";
22
+ import "./chunk-ZJV2SYVH.js";
22
23
  import {
23
24
  cn
24
25
  } from "./chunk-2TQSHVXA.js";
@@ -0,0 +1,14 @@
1
+ import * as react from 'react';
2
+ import { InputProps as InputProps$1 } from '@base-ui/react/input';
3
+
4
+ interface InputProps extends Omit<InputProps$1, "className"> {
5
+ className?: string;
6
+ }
7
+ /**
8
+ * A text input. `ref` is the real `<input>`, so `react-hook-form`'s `register()` works with
9
+ * no `Controller`. Height and horizontal padding follow the density tokens. Native `onChange`
10
+ * and the typed `onValueChange(value)` both fire.
11
+ */
12
+ declare const Input: react.ForwardRefExoticComponent<Omit<InputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
13
+
14
+ export { Input as I, type InputProps as a };
package/dist/input.d.ts CHANGED
@@ -1,14 +1,20 @@
1
+ export { I as Input, a as InputProps } from './input-BS0DXbuH.js';
1
2
  import * as react from 'react';
2
- import { InputProps as InputProps$1 } from '@base-ui/react/input';
3
+ import { ComponentPropsWithoutRef } from 'react';
4
+ import '@base-ui/react/input';
3
5
 
4
- interface InputProps extends Omit<InputProps$1, "className"> {
6
+ interface TextareaProps extends Omit<ComponentPropsWithoutRef<"textarea">, "className" | "defaultValue"> {
5
7
  className?: string;
8
+ defaultValue?: string;
9
+ /** Grows with its content (CSS `field-sizing: content`) instead of scrolling. */
10
+ autoResize?: boolean;
11
+ /** Typed alternative to `onChange`; both fire. */
12
+ onValueChange?: (value: string) => void;
6
13
  }
7
14
  /**
8
- * A text input. `ref` is the real `<input>`, so `react-hook-form`'s `register()` works with
9
- * no `Controller`. Height and horizontal padding follow the density tokens. Native `onChange`
10
- * and the typed `onValueChange(value)` both fire.
15
+ * A multi-line text input. `ref` is the real `<textarea>`, so `react-hook-form`'s `register()`
16
+ * works with no `Controller`. Inside a `Field` it is labelled and described automatically.
11
17
  */
12
- declare const Input: react.ForwardRefExoticComponent<Omit<InputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
18
+ declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
13
19
 
14
- export { Input, type InputProps };
20
+ export { Textarea, type TextareaProps };
package/dist/input.js CHANGED
@@ -1,8 +1,11 @@
1
1
  "use client";
2
2
  import {
3
- Input
4
- } from "./chunk-GX2YEJ43.js";
3
+ Input,
4
+ Textarea
5
+ } from "./chunk-V6RHWYYO.js";
6
+ import "./chunk-ZJV2SYVH.js";
5
7
  import "./chunk-2TQSHVXA.js";
6
8
  export {
7
- Input
9
+ Input,
10
+ Textarea
8
11
  };
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { ButtonProps } from '@base-ui/react/button';
4
- import { B as ButtonOwnProps } from './button-CYt2Zw3D.js';
4
+ import { c as ButtonOwnProps } from './button-D_1Tb_Km.js';
5
5
  import 'class-variance-authority';
6
6
  import 'class-variance-authority/types';
7
7
 
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@azmr/ui",
3
- "version": "0.4.0",
4
- "description": "React UI components wired to reactive Signals — Grid, useSignal",
3
+ "version": "0.5.0",
4
+ "description": "Accessible React design system on Base UI and Tailwind v4 tokens — buttons, menus, modals, tables, toasts and more, with Signal-aware hooks",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Alshafaraz Gazi <alshafaraz.gazi@gmail.com>",
8
- "homepage": "https://docs.azmara.io",
8
+ "homepage": "https://platform.azmara.io/docs/packages/ui",
9
+ "bugs": {
10
+ "url": "https://github.com/azmara-labs/platform/issues"
11
+ },
9
12
  "repository": {
10
13
  "type": "git",
11
14
  "url": "git+https://github.com/azmara-labs/platform.git",
@@ -18,7 +21,10 @@
18
21
  "reactive",
19
22
  "signals",
20
23
  "data-table",
21
- "azmara"
24
+ "azmara",
25
+ "design-system",
26
+ "base-ui",
27
+ "tailwindcss"
22
28
  ],
23
29
  "engines": {
24
30
  "node": ">=18.0.0"
@@ -57,6 +63,10 @@
57
63
  "types": "./dist/input.d.ts",
58
64
  "import": "./dist/input.js"
59
65
  },
66
+ "./field": {
67
+ "types": "./dist/field.d.ts",
68
+ "import": "./dist/field.js"
69
+ },
60
70
  "./spinner": {
61
71
  "types": "./dist/spinner.d.ts",
62
72
  "import": "./dist/spinner.js"
@@ -202,13 +212,13 @@
202
212
  "react": "^19.2.8",
203
213
  "react-dom": "^19.2.8",
204
214
  "react-hook-form": "^7.90.0",
205
- "shadcn": "4.21.4",
215
+ "shadcn": "4.22.1",
206
216
  "size-limit": "^14.2.0",
207
217
  "tailwindcss": "^4.3.3",
208
218
  "tsup": "^8.5.1",
209
219
  "typescript": "^5.7.3",
210
220
  "vitest": "^4.1.11",
211
- "@azmr/core": "0.1.0"
221
+ "@azmr/core": "0.1.1"
212
222
  },
213
223
  "publishConfig": {
214
224
  "access": "public"
@@ -1,36 +0,0 @@
1
- "use client";
2
- import {
3
- cn
4
- } from "./chunk-2TQSHVXA.js";
5
-
6
- // src/components/input/input.tsx
7
- import { forwardRef } from "react";
8
-
9
- // src/primitives/input.ts
10
- import { Input } from "@base-ui/react/input";
11
-
12
- // src/components/input/input.tsx
13
- import { jsx } from "react/jsx-runtime";
14
- var Input2 = forwardRef(function Input3({ className, type = "text", ...props }, ref) {
15
- return /* @__PURE__ */ jsx(
16
- Input,
17
- {
18
- ref,
19
- type,
20
- className: cn(
21
- "flex h-(--density-control-height) w-full min-w-0 rounded-md border border-input bg-background px-(--density-control-padding-x) py-1 text-sm text-foreground",
22
- "transition-colors duration-(--motion-duration-fast) ease-standard",
23
- "outline-none placeholder:text-muted-foreground",
24
- "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring",
25
- "aria-invalid:border-destructive data-[invalid]:border-destructive",
26
- "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 read-only:bg-muted",
27
- className
28
- ),
29
- ...props
30
- }
31
- );
32
- });
33
-
34
- export {
35
- Input2 as Input
36
- };