@alexandregme/zljs 1.9.0 → 1.10.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/CHANGELOG.md CHANGED
@@ -8,6 +8,35 @@ A change that needs action in an app has a **Migration** note. When updating, re
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.10.0] - 2026-11-02
12
+
13
+ ### Added
14
+
15
+ - `Input` takes `autoComplete` and `required`
16
+
17
+ ### Changed
18
+
19
+ - `Input` requires `label` or `aria-label` in its type, so a field can't be left without a name
20
+ - `Input` draws a real `focus-visible` outline in the theme's `primary` color instead of a `focus:ring`, so focus stays visible in forced colors mode, and an app's own color reaches it
21
+ - `Input` border is now `gray-500` instead of `gray-300`, for 3:1 contrast, and its placeholder is `gray-500`, for 4.5:1
22
+
23
+ ### Fixed
24
+
25
+ - `Input` with `error` sets `aria-invalid` and points `aria-describedby` to the message, so a screen reader announces both
26
+
27
+ #### Migration
28
+
29
+ Only an `Input` with neither `label` nor `aria-label`, code that extends `InputProps`, and tests that assert its old classes need a change. To find them, run the commands below from the app's root. The first also finds other components named `Input`, and those stay as they are:
30
+
31
+ ```sh
32
+ grep -rnE "<Input([[:space:]/>]|$)|\bInputProps\b" . --include='*.ts' --include='*.tsx' --exclude-dir=node_modules --exclude-dir=.next
33
+ grep -rnE "border-gray-300|focus:ring-blue-500|focus:border-transparent" . --include='*.test.*' --exclude-dir=node_modules --exclude-dir=.next
34
+ ```
35
+
36
+ Give each field a `label`, or an `aria-label` when the context already says what it is. Replace `interface X extends InputProps` with `type X = InputProps & { ... }`, because `InputProps` is now a union. In tests, replace those classes with `focus-visible:outline-zl-primary` and `border-gray-500`.
37
+
38
+ `FormInput` already requires `label`, so it doesn't change.
39
+
11
40
  ## [1.9.0] - 2026-11-02
12
41
 
13
42
  ### Added
@@ -48,6 +77,7 @@ Replace the shade with the class of the `color` being tested, for example `/(^|\
48
77
 
49
78
  The message of `Error` is `text-zl-danger`. `none` and `ghost` didn't change.
50
79
 
51
- [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.9.0...HEAD
80
+ [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.10.0...HEAD
81
+ [1.10.0]: https://github.com/alexandregme/zljs/compare/v1.9.0...v1.10.0
52
82
  [1.9.0]: https://github.com/alexandregme/zljs/compare/v1.8.0...v1.9.0
53
83
  [1.8.0]: https://github.com/alexandregme/zljs/compare/v1.7.0...v1.8.0
@@ -49,7 +49,7 @@ var label = tv2({
49
49
  base: "text-sm font-medium text-gray-700"
50
50
  });
51
51
  var input = tv2({
52
- base: "px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
52
+ base: "px-3 py-2 border border-gray-500 rounded-md text-sm placeholder:text-gray-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zl-primary disabled:bg-gray-100 disabled:cursor-not-allowed"
53
53
  });
54
54
 
55
55
  // core/forms/input/input.tsx
@@ -61,14 +61,17 @@ var Input = forwardRef(
61
61
  name,
62
62
  type = "text",
63
63
  placeholder,
64
+ autoComplete,
64
65
  value,
65
66
  error: error2,
66
67
  disabled,
68
+ required,
67
69
  onChange,
68
70
  onBlur,
69
71
  onKeyDown
70
72
  }, ref) => {
71
73
  const id = useId();
74
+ const errorId = `${id}-error`;
72
75
  return /* @__PURE__ */ jsxs("div", { className: wrapper(), children: [
73
76
  labelText && /* @__PURE__ */ jsx3("label", { htmlFor: id, className: label(), children: labelText }),
74
77
  /* @__PURE__ */ jsx3(
@@ -79,16 +82,20 @@ var Input = forwardRef(
79
82
  name,
80
83
  type,
81
84
  placeholder,
85
+ autoComplete,
82
86
  value,
83
87
  disabled,
88
+ required,
84
89
  onChange,
85
90
  onBlur,
86
91
  onKeyDown,
87
92
  "aria-label": ariaLabel,
93
+ "aria-invalid": error2 ? true : void 0,
94
+ "aria-describedby": error2 ? errorId : void 0,
88
95
  className: input()
89
96
  }
90
97
  ),
91
- error2 && /* @__PURE__ */ jsx3(Error, { message: error2 })
98
+ error2 && /* @__PURE__ */ jsx3(Error, { id: errorId, message: error2 })
92
99
  ] });
93
100
  }
94
101
  );
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ChangeEvent, FormEvent, FocusEvent, KeyboardEvent } from 'react';
2
+ import { ReactNode, ChangeEvent, FormEvent, HTMLInputAutoCompleteAttribute, FocusEvent, KeyboardEvent } from 'react';
3
3
  export { FormInput, FormInputProps, FormProvider, FormProviderProps } from './rhf/index.js';
4
4
  export { toast } from 'sonner';
5
5
  import * as zustand from 'zustand';
@@ -98,19 +98,26 @@ interface FormProps {
98
98
 
99
99
  declare const Form: ({ children, onSubmit, disabled }: FormProps) => react.JSX.Element;
100
100
 
101
- interface InputProps {
102
- label?: string;
101
+ type InputName = {
102
+ label: string;
103
103
  "aria-label"?: string;
104
+ } | {
105
+ label?: undefined;
106
+ "aria-label": string;
107
+ };
108
+ type InputProps = InputName & {
104
109
  name?: string;
105
110
  type?: "text" | "password" | "email";
106
111
  placeholder?: string;
112
+ autoComplete?: HTMLInputAutoCompleteAttribute;
107
113
  value?: string;
108
114
  error?: string;
109
115
  disabled?: boolean;
116
+ required?: boolean;
110
117
  onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
111
118
  onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
112
119
  onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
113
- }
120
+ };
114
121
 
115
122
  declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
116
123
 
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  FormInput,
5
5
  FormProvider,
6
6
  Input
7
- } from "./chunk-WZNUKE6S.js";
7
+ } from "./chunk-2RTPRD3E.js";
8
8
 
9
9
  // core/icon/icon.tsx
10
10
  import * as LucideIcons from "lucide-react";
package/dist/rhf/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  FormInput,
4
4
  FormProvider
5
- } from "../chunk-WZNUKE6S.js";
5
+ } from "../chunk-2RTPRD3E.js";
6
6
  export {
7
7
  FormInput,
8
8
  FormProvider
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexandregme/zljs",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Opinionated, accessible React component library for enterprise apps (Next.js, Tailwind CSS v4).",
5
5
  "keywords": [
6
6
  "react",