@alexandregme/zljs 1.11.0 → 1.12.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,34 @@ A change that needs action in an app has a **Migration** note. When updating, re
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [1.12.0] - 2026-11-02
12
+
13
+ ### Added
14
+
15
+ - `TextArea` takes `aria-label`, `name`, `autoComplete`, `required`, `onBlur`, `onKeyDown` and `ref`, as `Input` and `Select` do, so it works with `register` from `react-hook-form`
16
+
17
+ ### Changed
18
+
19
+ - `TextArea` requires `label` or `aria-label` in its type, instead of always `label`
20
+ - `TextArea` 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
+ - `TextArea` 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
+ - `TextArea` with `error` sets `aria-invalid` and points `aria-describedby` to the message, so a screen reader announces both
26
+ - `TextArea` uses `resize-y`. It had a class that doesn't exist in Tailwind, so it only resized vertically in apps with Tailwind's base styles
27
+
28
+ #### Migration
29
+
30
+ Only code that extends `TextAreaProps` and tests that assert its old classes need a change. To find them, run the commands below from the app's root:
31
+
32
+ ```sh
33
+ grep -rnE "\bTextAreaProps\b" . --include='*.ts' --include='*.tsx' --exclude-dir=node_modules --exclude-dir=.next
34
+ grep -rnE "border-gray-300|focus:ring-blue-500|focus:border-transparent|resize-vertical" . --include='*.test.*' --exclude-dir=node_modules --exclude-dir=.next
35
+ ```
36
+
37
+ Replace `interface X extends TextAreaProps` with `type X = TextAreaProps & { ... }`, because `TextAreaProps` is now a union. In tests, replace those classes with `focus-visible:outline-zl-primary`, `border-gray-500` and `resize-y`.
38
+
11
39
  ## [1.11.0] - 2026-11-02
12
40
 
13
41
  ### Added
@@ -106,7 +134,8 @@ Replace the shade with the class of the `color` being tested, for example `/(^|\
106
134
 
107
135
  The message of `Error` is `text-zl-danger`. `none` and `ghost` didn't change.
108
136
 
109
- [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.11.0...HEAD
137
+ [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.12.0...HEAD
138
+ [1.12.0]: https://github.com/alexandregme/zljs/compare/v1.11.0...v1.12.0
110
139
  [1.11.0]: https://github.com/alexandregme/zljs/compare/v1.10.0...v1.11.0
111
140
  [1.10.0]: https://github.com/alexandregme/zljs/compare/v1.9.0...v1.10.0
112
141
  [1.9.0]: https://github.com/alexandregme/zljs/compare/v1.8.0...v1.9.0
package/dist/index.d.ts CHANGED
@@ -160,17 +160,29 @@ type SelectProps = SelectName & {
160
160
 
161
161
  declare const Select: ({ label: labelText, "aria-label": ariaLabel, name, options, placeholder, autoComplete, value, error, disabled, required, onChange, onBlur, onKeyDown, ref, }: SelectProps) => react.JSX.Element;
162
162
 
163
- interface TextAreaProps {
163
+ type TextAreaName = {
164
164
  label: string;
165
+ "aria-label"?: string;
166
+ } | {
167
+ label?: undefined;
168
+ "aria-label": string;
169
+ };
170
+ type TextAreaProps = TextAreaName & {
171
+ name?: string;
165
172
  placeholder?: string;
173
+ autoComplete?: HTMLInputAutoCompleteAttribute;
166
174
  value?: string;
167
175
  rows?: number;
168
176
  error?: string;
169
177
  disabled?: boolean;
178
+ required?: boolean;
170
179
  onChange?: (event: ChangeEvent<HTMLTextAreaElement>) => void;
171
- }
180
+ onBlur?: (event: FocusEvent<HTMLTextAreaElement>) => void;
181
+ onKeyDown?: (event: KeyboardEvent<HTMLTextAreaElement>) => void;
182
+ ref?: Ref<HTMLTextAreaElement>;
183
+ };
172
184
 
173
- declare const TextArea: ({ label: labelText, placeholder, value, rows, error, disabled, onChange, }: TextAreaProps) => react.JSX.Element;
185
+ declare const TextArea: ({ label: labelText, "aria-label": ariaLabel, name, placeholder, autoComplete, value, rows, error, disabled, required, onChange, onBlur, onKeyDown, ref, }: TextAreaProps) => react.JSX.Element;
174
186
 
175
187
  declare const Icon: ({ name, size, "aria-label": ariaLabel, }: IconProps) => react.JSX.Element;
176
188
 
package/dist/index.js CHANGED
@@ -421,36 +421,53 @@ var label4 = tv6({
421
421
  base: "text-sm font-medium text-gray-700"
422
422
  });
423
423
  var textarea = tv6({
424
- base: "px-3 py-2 border border-gray-300 rounded-md text-sm resize-vertical focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed"
424
+ base: "px-3 py-2 border border-gray-500 rounded-md text-sm placeholder:text-gray-500 resize-y focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zl-primary disabled:bg-gray-100 disabled:cursor-not-allowed"
425
425
  });
426
426
 
427
427
  // core/forms/text-area/text-area.tsx
428
428
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
429
429
  var TextArea = ({
430
430
  label: labelText,
431
+ "aria-label": ariaLabel,
432
+ name,
431
433
  placeholder,
434
+ autoComplete,
432
435
  value,
433
436
  rows = 3,
434
437
  error,
435
438
  disabled,
436
- onChange
439
+ required,
440
+ onChange,
441
+ onBlur,
442
+ onKeyDown,
443
+ ref
437
444
  }) => {
438
445
  const id = useId4();
446
+ const errorId = `${id}-error`;
439
447
  return /* @__PURE__ */ jsxs5("div", { className: wrapper4(), children: [
440
- /* @__PURE__ */ jsx7("label", { htmlFor: id, className: label4(), children: labelText }),
448
+ labelText && /* @__PURE__ */ jsx7("label", { htmlFor: id, className: label4(), children: labelText }),
441
449
  /* @__PURE__ */ jsx7(
442
450
  "textarea",
443
451
  {
452
+ ref,
444
453
  id,
454
+ name,
445
455
  placeholder,
456
+ autoComplete,
446
457
  value,
447
458
  rows,
448
459
  disabled,
460
+ required,
449
461
  onChange,
462
+ onBlur,
463
+ onKeyDown,
464
+ "aria-label": ariaLabel,
465
+ "aria-invalid": error ? true : void 0,
466
+ "aria-describedby": error ? errorId : void 0,
450
467
  className: textarea()
451
468
  }
452
469
  ),
453
- error && /* @__PURE__ */ jsx7(Error, { message: error })
470
+ error && /* @__PURE__ */ jsx7(Error, { id: errorId, message: error })
454
471
  ] });
455
472
  };
456
473
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexandregme/zljs",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Opinionated, accessible React component library for enterprise apps (Next.js, Tailwind CSS v4).",
5
5
  "keywords": [
6
6
  "react",