@alexandregme/zljs 1.19.1 → 2.0.1

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,39 @@ A change that needs action in an app has a **Migration** note. When updating, re
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [2.0.1] - 2026-11-03
12
+
13
+ ### Changed
14
+
15
+ - The colored toasts of `Toaster` follow the `--color-zl-*` theme values: the text is the `-strong` value, the background is the color at 15% over white and the border is the color at 30%. `error` uses `danger`
16
+
17
+ ### Fixed
18
+
19
+ - `Toaster` holds 4.5:1 on the text of each toast type. The rich colors of Sonner stayed under it on their light backgrounds
20
+ - A toast from `useToastStore` no longer replaces a toast from `toast()` that is showing. Both numbered their toasts from 1
21
+ - A toast and its close button draw a real focus outline in the text color. Their `box-shadow` ring was about 1.6:1 and disappeared in forced colors mode
22
+
23
+ ## [2.0.0] - 2026-11-03
24
+
25
+ ### Added
26
+
27
+ - Auxiliary colors `orange`, `pink` and `purple`, with the `AuxiliaryColor` type and the `--color-zl-<color>` and `--color-zl-<color>-strong` theme values. They have no meaning of their own and only `Tag` takes them
28
+ - `TagColor` type, and `Tag` takes `primary`, `success`, `danger`, `warning`, `info` and `muted`
29
+ - `removeLabel` on `Tag`, to name the remove button when several tags show at once. It defaults to `Remover`
30
+
31
+ ### Changed
32
+
33
+ - `Tag` follows the `--color-zl-*` theme values: its background is the color at 15% and its text is the `-strong` value. Its default color is `primary`, no longer `blue`
34
+ - The remove button of `Tag` takes the text color of the `Tag`, for its icon and its focus outline
35
+
36
+ ### Removed
37
+
38
+ - The `blue`, `green`, `red`, `yellow` and `gray` colors of `Tag`. `orange` stays. `StatsCard` and `DataColor` keep them
39
+
40
+ #### Migration
41
+
42
+ Search the app for `<Tag` and read its props, which can sit on the next lines (`grep -rn -A3 "<Tag"`). Replace `color`: `blue` → `primary`, `green` → `success`, `red` → `danger`, `yellow` → `warning`, `gray` → `muted`. A variable typed `DataColor` that reaches a `Tag` becomes `TagColor`. A test that asserts `bg-*-100` or `text-*-700` on a `Tag` moves to `bg-zl-<color>/15` and `text-zl-<color>-strong`. Don't change `StatsCard`.
43
+
11
44
  ## [1.19.1] - 2026-11-03
12
45
 
13
46
  ### Changed
@@ -302,7 +335,9 @@ Replace the shade with the class of the `color` being tested, for example `/(^|\
302
335
 
303
336
  The message of `Error` is `text-zl-danger`. `none` and `ghost` didn't change.
304
337
 
305
- [Unreleased]: https://github.com/alexandregme/zljs/compare/v1.19.1...HEAD
338
+ [Unreleased]: https://github.com/alexandregme/zljs/compare/v2.0.1...HEAD
339
+ [2.0.1]: https://github.com/alexandregme/zljs/compare/v2.0.0...v2.0.1
340
+ [2.0.0]: https://github.com/alexandregme/zljs/compare/v1.19.1...v2.0.0
306
341
  [1.19.1]: https://github.com/alexandregme/zljs/compare/v1.19.0...v1.19.1
307
342
  [1.19.0]: https://github.com/alexandregme/zljs/compare/v1.18.1...v1.19.0
308
343
  [1.18.1]: https://github.com/alexandregme/zljs/compare/v1.18.0...v1.18.1
package/README.md CHANGED
@@ -58,12 +58,14 @@ The components work with no setup, using the default colors. To use your own, re
58
58
 
59
59
  `primary`, `success`, `danger`, `warning`, `info` and `muted` each take one value (`--color-zl-<color>`), used for text and the focus outline. The others follow it, and you can redefine them too:
60
60
 
61
- | Value | Used for | Default |
62
- | --------------------------- | ---------------------- | ------------------------------------------ |
63
- | `--color-zl-<color>-strong` | Link hover | 30% darker |
64
- | `--color-zl-<color>-bg` | Button background | The color itself (`warning`: `yellow-500`) |
65
- | `--color-zl-<color>-hover` | Button hover | The background, 15% darker |
66
- | `--color-zl-<color>-on` | Text on the background | White (`warning`: `gray-900`) |
61
+ | Value | Used for | Default |
62
+ | --------------------------- | ----------------------- | ------------------------------------------ |
63
+ | `--color-zl-<color>-strong` | Link hover and Tag text | 30% darker |
64
+ | `--color-zl-<color>-bg` | Button background | The color itself (`warning`: `yellow-500`) |
65
+ | `--color-zl-<color>-hover` | Button hover | The background, 15% darker |
66
+ | `--color-zl-<color>-on` | Text on the background | White (`warning`: `gray-900`) |
67
+
68
+ A `Tag` also takes the auxiliary colors `orange`, `pink` and `purple`, which have no meaning of their own: use them to tell categories apart. Each has only `--color-zl-<color>` and `--color-zl-<color>-strong`. The first, at 15%, is the `Tag` background, and the second is its text.
67
69
 
68
70
  Only the defaults are checked for contrast. Check your own choice: 4.5:1 for text, on `--color-zl-<color>` against the page and on `-on` against `-bg`, and 3:1 for the focus outline. A value set on a nested element doesn't reach the values derived from it, so set them in `@theme` or `:root`.
69
71
 
@@ -166,16 +166,40 @@ var useToastStore = create()(
166
166
  // core/toaster/toaster.tsx
167
167
  import { useEffect } from "react";
168
168
  import { Toaster as SonnerToaster, toast } from "sonner";
169
+
170
+ // core/toaster/toaster.styles.ts
171
+ import { tv as tv4 } from "tailwind-variants";
172
+ var focusOutline = "focus-visible:outline-2! focus-visible:outline-offset-2! focus-visible:outline-current!";
173
+ var toaster = tv4({
174
+ slots: {
175
+ toast: focusOutline,
176
+ closeButton: focusOutline
177
+ }
178
+ });
179
+ var toasterColors = {
180
+ "--success-text": "var(--color-zl-success-strong)",
181
+ "--success-bg": "color-mix(in oklab, var(--color-zl-success) 15%, white)",
182
+ "--success-border": "color-mix(in oklab, var(--color-zl-success) 30%, white)",
183
+ "--info-text": "var(--color-zl-info-strong)",
184
+ "--info-bg": "color-mix(in oklab, var(--color-zl-info) 15%, white)",
185
+ "--info-border": "color-mix(in oklab, var(--color-zl-info) 30%, white)",
186
+ "--warning-text": "var(--color-zl-warning-strong)",
187
+ "--warning-bg": "color-mix(in oklab, var(--color-zl-warning) 15%, white)",
188
+ "--warning-border": "color-mix(in oklab, var(--color-zl-warning) 30%, white)",
189
+ "--error-text": "var(--color-zl-danger-strong)",
190
+ "--error-bg": "color-mix(in oklab, var(--color-zl-danger) 15%, white)",
191
+ "--error-border": "color-mix(in oklab, var(--color-zl-danger) 30%, white)"
192
+ };
193
+
194
+ // core/toaster/toaster.tsx
169
195
  import { jsx as jsx4 } from "react/jsx-runtime";
170
196
  var Toaster = () => {
171
197
  const toasts = useToastStore((s) => s.toasts);
172
198
  const removeToast = useToastStore((s) => s.removeToast);
199
+ const { toast: toastStyles, closeButton } = toaster();
173
200
  useEffect(() => {
174
201
  toasts.forEach((t) => {
175
- toast[t.type](t.message, {
176
- id: t.id,
177
- onDismiss: () => removeToast(t.id)
178
- });
202
+ toast[t.type](t.message, { id: `store-${t.id}` });
179
203
  removeToast(t.id);
180
204
  });
181
205
  }, [toasts, removeToast]);
@@ -187,7 +211,11 @@ var Toaster = () => {
187
211
  closeButton: true,
188
212
  duration: 4e3,
189
213
  expand: true,
190
- visibleToasts: 5
214
+ visibleToasts: 5,
215
+ style: toasterColors,
216
+ toastOptions: {
217
+ classNames: { toast: toastStyles(), closeButton: closeButton() }
218
+ }
191
219
  }
192
220
  );
193
221
  };
@@ -350,8 +378,8 @@ var spinnerIcons = {
350
378
  };
351
379
 
352
380
  // core/spinner/spinner.styles.ts
353
- import { tv as tv4 } from "tailwind-variants";
354
- var spinner = tv4({
381
+ import { tv as tv5 } from "tailwind-variants";
382
+ var spinner = tv5({
355
383
  base: "inline-flex animate-spin"
356
384
  });
357
385
 
@@ -373,8 +401,8 @@ var Spinner = ({
373
401
  );
374
402
 
375
403
  // core/loader/loader.styles.ts
376
- import { tv as tv5 } from "tailwind-variants";
377
- var loader = tv5({
404
+ import { tv as tv6 } from "tailwind-variants";
405
+ var loader = tv6({
378
406
  base: "flex fixed inset-0 justify-center items-center bg-black/20 text-zl-primary z-50"
379
407
  });
380
408
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ChangeEvent, FormEvent, HTMLInputAutoCompleteAttribute, FocusEvent, KeyboardEvent, Ref } from 'react';
3
- import { S as SemanticColor, D as DataColor, R as ReduxProviderProps } from './redux-provider.interface-BmROR8Ev.js';
3
+ import { S as SemanticColor, D as DataColor, A as AuxiliaryColor, R as ReduxProviderProps } from './redux-provider.interface-DXOZKAMA.js';
4
4
  export { FormInput, FormInputProps, FormProvider, FormProviderProps } from './rhf/index.js';
5
5
  export { toast } from 'sonner';
6
6
  import * as zustand from 'zustand';
@@ -262,13 +262,15 @@ interface SidebarProps {
262
262
 
263
263
  declare const Sidebar: ({ sections, user, activeHref, defaultCollapsed, collapseLabel, homeHref, homeLabel, onLogout, }: SidebarProps) => react.JSX.Element;
264
264
 
265
+ type TagColor = Exclude<SemanticColor, "none"> | AuxiliaryColor;
265
266
  interface TagProps {
266
267
  children: ReactNode;
267
- color?: DataColor;
268
+ color?: TagColor;
268
269
  onRemove?: () => void;
270
+ removeLabel?: string;
269
271
  }
270
272
 
271
- declare const Tag: ({ children, color, onRemove }: TagProps) => react.JSX.Element;
273
+ declare const Tag: ({ children, color, onRemove, removeLabel, }: TagProps) => react.JSX.Element;
272
274
 
273
275
  declare const Toaster: () => react.JSX.Element;
274
276
 
@@ -465,5 +467,5 @@ declare class HTTPClient {
465
467
  patch<T = unknown>(url: string, config?: HttpRequestConfig): Promise<T | undefined>;
466
468
  }
467
469
 
468
- export { Button, Checkbox, ConnectedModal, DataColor, DataGrid, Error, Form, HTTPClient, Heading, Icon, Input, Loader, Modal, Radio, ReduxProvider, ReduxProviderProps, Select, SemanticColor, Sidebar, Spinner, StatsCard, Tag, Text, TextArea, Toaster, WhatsAppButton, splitURLasPath, useAppStore, useModalStore, usePageStore, useRouterStore, useToastStore };
469
- export type { AppState, ButtonColor, ButtonProps, ButtonVariant, CheckboxProps, CheckboxVariant, ConnectedModalProps, DataGridColumn, DataGridProps, ErrorProps, FormProps, HeadingProps, HttpClientConfig, HttpRequestConfig, IconName, IconProps, InputProps, LoaderProps, ModalEntry, ModalProps, ModalState, PageState, RadioProps, ReduxStore, RouterState, SelectOption, SelectProps, SidebarItem, SidebarProps, SidebarSection, SidebarUser, Size, SpinnerProps, SpinnerVariant, StatsCardProps, TagProps, TextAreaProps, TextProps, TextVariant, Toast, ToastState, ToastType, WhatsAppButtonProps };
470
+ export { AuxiliaryColor, Button, Checkbox, ConnectedModal, DataColor, DataGrid, Error, Form, HTTPClient, Heading, Icon, Input, Loader, Modal, Radio, ReduxProvider, ReduxProviderProps, Select, SemanticColor, Sidebar, Spinner, StatsCard, Tag, Text, TextArea, Toaster, WhatsAppButton, splitURLasPath, useAppStore, useModalStore, usePageStore, useRouterStore, useToastStore };
471
+ export type { AppState, ButtonColor, ButtonProps, ButtonVariant, CheckboxProps, CheckboxVariant, ConnectedModalProps, DataGridColumn, DataGridProps, ErrorProps, FormProps, HeadingProps, HttpClientConfig, HttpRequestConfig, IconName, IconProps, InputProps, LoaderProps, ModalEntry, ModalProps, ModalState, PageState, RadioProps, ReduxStore, RouterState, SelectOption, SelectProps, SidebarItem, SidebarProps, SidebarSection, SidebarUser, Size, SpinnerProps, SpinnerVariant, StatsCardProps, TagColor, TagProps, TextAreaProps, TextProps, TextVariant, Toast, ToastState, ToastType, WhatsAppButtonProps };
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  usePageStore,
13
13
  useRouterStore,
14
14
  useToastStore
15
- } from "./chunk-O6UAZGBC.js";
15
+ } from "./chunk-5VIR5UAF.js";
16
16
  import {
17
17
  Error,
18
18
  FormInput,
@@ -502,25 +502,42 @@ var tag = tv7({
502
502
  base: "inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium",
503
503
  variants: {
504
504
  color: {
505
- blue: "bg-blue-100 text-blue-700",
506
- green: "bg-green-100 text-green-700",
507
- red: "bg-red-100 text-red-700",
508
- yellow: "bg-yellow-100 text-yellow-700",
509
- gray: "bg-slate-100 text-slate-700",
510
- orange: "bg-orange-100 text-orange-700"
505
+ primary: "bg-zl-primary/15 text-zl-primary-strong",
506
+ success: "bg-zl-success/15 text-zl-success-strong",
507
+ danger: "bg-zl-danger/15 text-zl-danger-strong",
508
+ warning: "bg-zl-warning/15 text-zl-warning-strong",
509
+ info: "bg-zl-info/15 text-zl-info-strong",
510
+ muted: "bg-zl-muted/15 text-zl-muted-strong",
511
+ orange: "bg-zl-orange/15 text-zl-orange-strong",
512
+ pink: "bg-zl-pink/15 text-zl-pink-strong",
513
+ purple: "bg-zl-purple/15 text-zl-purple-strong"
511
514
  }
512
515
  },
513
516
  defaultVariants: {
514
- color: "blue"
517
+ color: "primary"
515
518
  }
516
519
  });
517
520
 
518
521
  // core/tag/tag.tsx
519
522
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
520
- var Tag = ({ children, color = "blue", onRemove }) => {
523
+ var Tag = ({
524
+ children,
525
+ color = "primary",
526
+ onRemove,
527
+ removeLabel = "Remover"
528
+ }) => {
521
529
  return /* @__PURE__ */ jsxs7("span", { "data-testid": "tag", className: tag({ color }), children: [
522
530
  children,
523
- onRemove && /* @__PURE__ */ jsx8(Button, { size: "sm", icon: "X", "aria-label": "Remover", onClick: onRemove })
531
+ onRemove && /* @__PURE__ */ jsx8(
532
+ Button,
533
+ {
534
+ color: "ghost",
535
+ size: "sm",
536
+ icon: "X",
537
+ "aria-label": removeLabel,
538
+ onClick: onRemove
539
+ }
540
+ )
524
541
  ] });
525
542
  };
526
543
 
@@ -564,7 +581,6 @@ var DataGridStatusBar = ({
564
581
  activeFilters.map((filter) => /* @__PURE__ */ jsxs8(
565
582
  Tag,
566
583
  {
567
- color: "blue",
568
584
  onRemove: () => handleClearFilter(filter.column),
569
585
  children: [
570
586
  /* @__PURE__ */ jsxs8("span", { className: "font-medium", children: [
@@ -7,7 +7,7 @@ import {
7
7
  Toaster,
8
8
  usePageStore,
9
9
  useRouterStore
10
- } from "../chunk-O6UAZGBC.js";
10
+ } from "../chunk-5VIR5UAF.js";
11
11
 
12
12
  // core/next/root-layout/root-layout.styles.ts
13
13
  import { tv } from "tailwind-variants";
@@ -9,6 +9,10 @@ type SemanticColor = "primary" | "success" | "danger" | "warning" | "info" | "mu
9
9
  * Literal colors for data visualization components (StatsCard, etc.)
10
10
  */
11
11
  type DataColor = "blue" | "red" | "yellow" | "green" | "gray" | "orange";
12
+ /**
13
+ * Extra colors with no meaning of their own, to tell categories apart (Tag)
14
+ */
15
+ type AuxiliaryColor = "orange" | "pink" | "purple";
12
16
 
13
17
  interface ReduxProviderProps {
14
18
  children: ReactNode;
@@ -18,4 +22,4 @@ interface ReduxProviderProps {
18
22
  coreReducers?: Record<string, Reducer>;
19
23
  }
20
24
 
21
- export type { DataColor as D, ReduxProviderProps as R, SemanticColor as S };
25
+ export type { AuxiliaryColor as A, DataColor as D, ReduxProviderProps as R, SemanticColor as S };
@@ -3,12 +3,17 @@
3
3
  the styles. Only the defaults are checked for contrast.
4
4
 
5
5
  Each color has five values, and the others follow the first unless redefined:
6
- --color-zl-<color> text and focus outline
7
- --color-zl-<color>-strong link hover
6
+ --color-zl-<color> text, focus outline and tag background, at 15%
7
+ --color-zl-<color>-strong link hover and tag text
8
8
  --color-zl-<color>-bg button background
9
9
  --color-zl-<color>-hover button hover
10
10
  --color-zl-<color>-on text on the background
11
11
 
12
+ The auxiliary colors (orange, pink, purple) have no meaning of their own. Tag
13
+ is their only user, so they have two values:
14
+ --color-zl-<color> tag background, at 15%
15
+ --color-zl-<color>-strong tag text
16
+
12
17
  Prettier is off for this block to keep one value per line. */
13
18
 
14
19
  /* prettier-ignore */
@@ -54,4 +59,16 @@
54
59
  --color-zl-muted-bg: var(--color-zl-muted);
55
60
  --color-zl-muted-hover: color-mix(in oklab, var(--color-zl-muted-bg), black 15%);
56
61
  --color-zl-muted-on: var(--color-white);
62
+
63
+ /* Orange */
64
+ --color-zl-orange: var(--color-orange-700);
65
+ --color-zl-orange-strong: color-mix(in oklab, var(--color-zl-orange), black 30%);
66
+
67
+ /* Pink */
68
+ --color-zl-pink: var(--color-pink-700);
69
+ --color-zl-pink-strong: color-mix(in oklab, var(--color-zl-pink), black 30%);
70
+
71
+ /* Purple */
72
+ --color-zl-purple: var(--color-purple-700);
73
+ --color-zl-purple-strong: color-mix(in oklab, var(--color-zl-purple), black 30%);
57
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexandregme/zljs",
3
- "version": "1.19.1",
3
+ "version": "2.0.1",
4
4
  "description": "Opinionated, accessible React component library for enterprise apps (Next.js, Tailwind CSS v4).",
5
5
  "keywords": [
6
6
  "react",