@fabio.caffarello/react-design-system 4.1.0 → 4.3.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.
@@ -3,6 +3,7 @@ export * from "./tokens/spacing";
3
3
  export * from "./tokens/typography";
4
4
  export * from "./tokens/colors/index";
5
5
  export * from "./tokens/breakpoints";
6
+ export * from "./tokens/chart";
6
7
  export { cn } from "./utils";
7
8
  export { getSpacingClass, getSpacing } from "./tokens/spacing";
8
9
  export { getTypographyClasses, getTypography } from "./tokens/typography";
@@ -11,6 +12,7 @@ export { getBreakpoint, getMediaQuery } from "./tokens/breakpoints";
11
12
  export { getAnimationClass, getAnimation, getTransitionClass, } from "./tokens/animations";
12
13
  export { getZIndexClass, getZIndex } from "./tokens/z-index";
13
14
  export { getOpacityClass, getOpacity } from "./tokens/opacity";
15
+ export { getChartColor, getChartColorClass } from "./tokens/chart";
14
16
  export { ThemeProvider, ConfigProvider, ToastProvider, DialogProvider, useTheme, useConfig, useToastContext, useToastContextOptional, useDialogContext, useDialogContextOptional, ToastContext, DialogContext, type ThemeProviderProps, type ThemeContextValue, type ConfigProviderProps, type DesignSystemConfig, type ConfigContextValue, type ToastProviderProps, type DialogProviderProps, type Toast, type ToastContextValue, type ToastVariant, type DialogContextValue, } from "./providers/providers-bundle";
15
17
  export { AppProvider, useApp, type AppProviderProps, type AppProviderConfig, } from "./providers/AppProvider";
16
18
  export * from "./primitives";
@@ -0,0 +1,56 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ /**
3
+ * Semantic tone for a {@link DataBadge}. Mirrors the `Badge` vocabulary
4
+ * (role, not tone) so the soft-wash color treatment is shared and already
5
+ * AA-verified. Map a consumer's tone names onto these roles:
6
+ * `default → neutral`, `destructive → error`, `brand → primary`,
7
+ * `accent → info` (or `secondary`).
8
+ */
9
+ export type DataBadgeTone = "neutral" | "success" | "warning" | "error" | "info" | "primary" | "secondary";
10
+ export type DataBadgeSize = "sm" | "md";
11
+ export interface DataBadgeProps extends HTMLAttributes<HTMLSpanElement> {
12
+ /** Primary datum — the value the badge is about (e.g. "L2", "Aprovada"). */
13
+ label: ReactNode;
14
+ /**
15
+ * Provenance of the datum, rendered as a lesser-emphasis sub-label after
16
+ * the label (e.g. "Câmara", "Portal Transparência"). Omitted when absent.
17
+ */
18
+ source?: ReactNode;
19
+ /** Semantic tone (role-based color). Defaults to `neutral`. */
20
+ tone?: DataBadgeTone;
21
+ /** Optional decorative leading icon (rendered `aria-hidden`). */
22
+ icon?: ReactNode;
23
+ /** Size scale. Defaults to `md`. */
24
+ size?: DataBadgeSize;
25
+ }
26
+ /**
27
+ * DataBadge
28
+ *
29
+ * An inline metadata chip: a primary `label`, an optional lesser-emphasis
30
+ * `source` sub-label (the datum's provenance), a semantic `tone`, and an
31
+ * optional decorative `icon`. Built for transparency/data UIs where a value
32
+ * must travel with where it came from ("L2 · Portal Transparência").
33
+ *
34
+ * Why a separate primitive and not `Badge`: `Badge` is a single-string
35
+ * status label; `DataBadge` carries a value + its source as a structured
36
+ * pair. The `source` is the differentiator — it has no slot in `Badge` /
37
+ * `Chip` / `Info`.
38
+ *
39
+ * Accessibility: the visible text (label, then source) IS the accessible
40
+ * name — the separator and any `icon` are `aria-hidden`. Hierarchy between
41
+ * label and source is conveyed by size + weight, never by dropping the
42
+ * source below its tone's AA-safe text color. The root is a plain inline
43
+ * `<span>` with no live-region role (metadata is static, not announced);
44
+ * pass `role` / `aria-label` via props if a grouping role is wanted.
45
+ *
46
+ * Server-safe: no hooks, no client APIs, no DOM handlers of its own — ships
47
+ * from the `./server` entry.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * <DataBadge label="L2" source="Portal Transparência" tone="warning" />
52
+ * <DataBadge label="Aprovada" tone="success" />
53
+ * ```
54
+ */
55
+ declare const DataBadge: import("react").NamedExoticComponent<DataBadgeProps & import("react").RefAttributes<HTMLSpanElement>>;
56
+ export default DataBadge;
@@ -0,0 +1,2 @@
1
+ export { default } from "./DataBadge";
2
+ export type { DataBadgeProps } from "./DataBadge";
@@ -1,24 +1,22 @@
1
- import type { InputHTMLAttributes, ReactNode } from "react";
2
- export type InputSize = "sm" | "md" | "lg";
3
- export type InputVariant = "default" | "outlined" | "filled";
4
- export type InputState = "default" | "error" | "success";
5
- export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
6
- label?: ReactNode;
7
- error?: boolean;
8
- success?: boolean;
9
- helperText?: string;
10
- size?: InputSize;
11
- variant?: InputVariant;
12
- leftIcon?: ReactNode;
13
- rightIcon?: ReactNode;
1
+ import type { InputBaseProps } from "./InputBase";
2
+ export type { InputSize, InputVariant, InputState } from "./InputBase";
3
+ export interface InputProps extends Omit<InputBaseProps, "rightSlot"> {
14
4
  showClearButton?: boolean;
15
5
  onClear?: () => void;
16
6
  }
17
7
  /**
18
8
  * Input Component
19
9
  *
20
- * A styled text input component with label, error/success states, icons, and clear button.
21
- * Uses Composite Pattern when combined with Label and ErrorMessage.
10
+ * The interactive text input: everything `InputBase` renders, plus the
11
+ * client-only affordances that require React state the password
12
+ * visibility toggle (`type="password"`), the clear button
13
+ * (`showClearButton`), and the `useId` auto-id fallback. It **composes**
14
+ * `InputBase` (issue #224): the presentational shell lives once in
15
+ * `InputBase`, and `Input` layers the stateful affixes on top, passing
16
+ * the resolved `id`, the toggled `type`, and its buttons via `rightSlot`.
17
+ *
18
+ * Need a server-renderable / native-form input with no client state?
19
+ * Import `InputBase` from `@fabio.caffarello/react-design-system/server`.
22
20
  *
23
21
  * @example
24
22
  * ```tsx
@@ -0,0 +1,52 @@
1
+ import type { InputHTMLAttributes, ReactNode } from "react";
2
+ export type InputSize = "sm" | "md" | "lg";
3
+ export type InputVariant = "default" | "outlined" | "filled";
4
+ export type InputState = "default" | "error" | "success";
5
+ export interface InputBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
6
+ label?: ReactNode;
7
+ error?: boolean;
8
+ success?: boolean;
9
+ helperText?: string;
10
+ size?: InputSize;
11
+ variant?: InputVariant;
12
+ leftIcon?: ReactNode;
13
+ rightIcon?: ReactNode;
14
+ /**
15
+ * Raw trailing-affix slot rendered inside the input's right edge with
16
+ * full interactivity (no `pointer-events-none`). The interactive
17
+ * `Input` injects its password-toggle / clear buttons here; consumers
18
+ * can use it for a static suffix (a unit, a badge). When omitted,
19
+ * `rightIcon` renders instead with the muted decorative treatment.
20
+ */
21
+ rightSlot?: ReactNode;
22
+ }
23
+ /**
24
+ * InputBase
25
+ *
26
+ * The **presentational core** of the text input — label, the `<input>`
27
+ * itself, decorative left/right icons, the trailing-affix slot, and the
28
+ * helper/error line. It holds **no React client state** (no `useState`,
29
+ * `useId`, `useCallback`), so it is server-safe and ships from the
30
+ * `./server` entry (issue #224).
31
+ *
32
+ * The interactive `Input` (default export of this folder) composes
33
+ * `InputBase`, owning the password-toggle state, the clear button, and
34
+ * the `useId` auto-id fallback — it passes the resolved `id`, the
35
+ * toggled `type`, and its affix buttons (`rightSlot`) down. Use
36
+ * `InputBase` directly for server-rendered / native-form inputs where
37
+ * none of that interactivity is needed (`<form method="GET">` filters,
38
+ * RSC pages).
39
+ *
40
+ * Accessible name: pass `id` when you pass `label` so the `<label
41
+ * htmlFor>` binds — `InputBase` does NOT auto-generate an id (that needs
42
+ * `useId`, which would make it client). A dev-only warning fires when a
43
+ * `label` is given without an `id`.
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * // Server component / native form — zero client state.
48
+ * <InputBase id="q" name="q" placeholder="Buscar…" />
49
+ * ```
50
+ */
51
+ declare const InputBase: import("react").ForwardRefExoticComponent<InputBaseProps & import("react").RefAttributes<HTMLInputElement>>;
52
+ export default InputBase;
@@ -1,2 +1,4 @@
1
1
  export { default } from "./Input";
2
2
  export type { InputProps, InputSize, InputVariant, InputState } from "./Input";
3
+ export { default as InputBase } from "./InputBase";
4
+ export type { InputBaseProps } from "./InputBase";
@@ -40,3 +40,5 @@ export type { ChipProps, ChipVariant, ChipSize } from "./Chip";
40
40
  export * from "./Avatar";
41
41
  export { Dot } from "./Dot";
42
42
  export type { DotProps, DotVariant, DotSize } from "./Dot";
43
+ export { default as DataBadge } from "./DataBadge";
44
+ export type { DataBadgeProps } from "./DataBadge";
@@ -4,10 +4,14 @@ export { default as Button } from "./primitives/Button/Button";
4
4
  export type { ButtonProps, ButtonSize, ButtonVariant, } from "./primitives/Button/Button";
5
5
  export { default as Chip } from "./primitives/Chip/Chip";
6
6
  export type { ChipProps, ChipSize, ChipVariant } from "./primitives/Chip/Chip";
7
+ export { default as DataBadge } from "./primitives/DataBadge/DataBadge";
8
+ export type { DataBadgeProps, DataBadgeSize, DataBadgeTone, } from "./primitives/DataBadge/DataBadge";
7
9
  export { default as ErrorMessage } from "./primitives/ErrorMessage/ErrorMessage";
8
10
  export type { ErrorMessageProps } from "./primitives/ErrorMessage/ErrorMessage";
9
11
  export { default as Info } from "./primitives/Info/Info";
10
12
  export type { InfoProps } from "./primitives/Info/Info";
13
+ export { default as InputBase } from "./primitives/Input/InputBase";
14
+ export type { InputBaseProps, InputSize, InputVariant, InputState, } from "./primitives/Input/InputBase";
11
15
  export { default as Label } from "./primitives/Label/Label";
12
16
  export { default as Progress } from "./primitives/Progress/Progress";
13
17
  export type { ProgressProps, ProgressSize, ProgressVariant, } from "./primitives/Progress/Progress";
@@ -7,6 +7,23 @@
7
7
  * Color Palette Visualization
8
8
  */
9
9
  export declare function ColorPalette(): import("react").JSX.Element;
10
+ /**
11
+ * Solid status fills + on-color text.
12
+ *
13
+ * Each swatch is a real `bg-{status}-solid` carrying `text-fg-on-{status}`
14
+ * (white). These are the TEXT-CARRYING status solids — distinct from the
15
+ * decorative `bg-{status}` used by Dot/Progress. White clears WCAG AA for
16
+ * normal text against every fill (ratios annotated).
17
+ */
18
+ export declare function StatusSolidColors(): import("react").JSX.Element;
19
+ /**
20
+ * Data-visualization categorical palette (Okabe-Ito).
21
+ *
22
+ * Eight colorblind-safe categorical colors for chart series. Distinct from
23
+ * the semantic feedback colors — these encode category, not state. Consume
24
+ * via `getChartColor(i)` (0-based, wraps modulo 8, theme-aware).
25
+ */
26
+ export declare function ChartPalette(): import("react").JSX.Element;
10
27
  /**
11
28
  * Spacing Reference Visualization
12
29
  */
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Data-Visualization Categorical Palette (Okabe-Ito)
3
+ *
4
+ * Eight colorblind-safe categorical colors for chart series (parties, vote
5
+ * types, ranges, …). This is a SEPARATE axis from the semantic feedback
6
+ * colors: `success`/`warning`/`error`/`info` encode *state*, never
7
+ * *category* — using `error` for "series 3" is semantically wrong and
8
+ * destroys meaning. A categorical palette answers "which series is this",
9
+ * and it must stay distinguishable under color-vision deficiency.
10
+ *
11
+ * The values are the canonical Okabe & Ito (2008) palette — the reference
12
+ * categorical palette engineered to be distinguishable in deuteranopia,
13
+ * protanopia, and tritanopia — with `black` swapped for a neutral gray so
14
+ * the 8th series survives on a dark canvas. Light values are the canonical
15
+ * tones; the dark theme lifts each toward higher luminance (hue preserved)
16
+ * so every series clears the WCAG 1.4.11 graphical-object 3:1 contrast over
17
+ * `surface-canvas` (slate-950). The CSS source of truth is
18
+ * `src/styles/semantic/colors.css` (light) and `src/styles/themes/dark.css`
19
+ * (dark, both blocks).
20
+ *
21
+ * On-WHITE caveat: orange/sky-blue/yellow/gray are below 3:1 against a white
22
+ * canvas — an intrinsic property of Okabe-Ito's light hues. Fine for FILLS
23
+ * (bars, areas, large marks); for thin strokes (lines, 1px borders) add a
24
+ * stroke/outline or use a darker series first. Colorblind-safety (the point
25
+ * of the palette) is preserved regardless.
26
+ */
27
+ /** Number of distinct colors in the categorical palette. */
28
+ export declare const CHART_PALETTE_SIZE: 8;
29
+ /** 1-based position within the categorical palette. */
30
+ export type ChartColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
31
+ export interface ChartColorToken {
32
+ /** 1-based palette position (matches the `--color-chart-N` token). */
33
+ index: ChartColorIndex;
34
+ /** Okabe-Ito hue name — use for legends / documentation. */
35
+ name: string;
36
+ /** Theme-aware CSS reference, e.g. `"var(--color-chart-1)"`. */
37
+ var: string;
38
+ /** Tailwind background class, e.g. `"bg-chart-1"`. */
39
+ bg: string;
40
+ /** Tailwind text class, e.g. `"text-chart-1"`. */
41
+ text: string;
42
+ }
43
+ /**
44
+ * Palette metadata in canonical order. The actual color values live in CSS
45
+ * (theme-aware); these tokens carry the references and human-readable names.
46
+ */
47
+ export declare const CHART_PALETTE_TOKENS: readonly ChartColorToken[];
48
+ /**
49
+ * Resolve a chart series index to a theme-aware color reference.
50
+ *
51
+ * `seriesIndex` is **0-based** (built for `data.map((d, i) => …)`) and wraps
52
+ * modulo {@link CHART_PALETTE_SIZE}, so a 10-series chart cycles back to the
53
+ * first color rather than running out. Negative indices wrap correctly too.
54
+ * The returned `var(--color-chart-N)` resolves per active theme (light/dark),
55
+ * so charts re-tint automatically — pass it straight to a recharts
56
+ * `fill`/`stroke` or an inline `style`.
57
+ *
58
+ * @example
59
+ * ```tsx
60
+ * import { getChartColor } from "@fabio.caffarello/react-design-system";
61
+ *
62
+ * {series.map((s, i) => (
63
+ * <Bar key={s.id} dataKey={s.id} fill={getChartColor(i)} />
64
+ * ))}
65
+ * ```
66
+ *
67
+ * @param seriesIndex - 0-based series position.
68
+ * @returns A `var(--color-chart-N)` reference (theme-aware).
69
+ */
70
+ export declare function getChartColor(seriesIndex: number): string;
71
+ /**
72
+ * Tailwind class variant of {@link getChartColor} for DOM elements (legend
73
+ * dots, swatches) where a class is more convenient than an inline style.
74
+ *
75
+ * @param seriesIndex - 0-based series position (wraps modulo the palette).
76
+ * @param property - `"bg"` (default) or `"text"`.
77
+ * @returns A `bg-chart-N` / `text-chart-N` class string.
78
+ */
79
+ export declare function getChartColorClass(seriesIndex: number, property?: "bg" | "text"): string;
@@ -30,3 +30,6 @@ export { SIDEBAR_TOKENS, getNestedIndentClass } from "./sidebar";
30
30
  export * from "./switch";
31
31
  export { SWITCH_TOKENS, getSwitchClasses } from "./switch";
32
32
  export type { SwitchSizeToken } from "./switch";
33
+ export * from "./chart";
34
+ export { CHART_PALETTE_SIZE, CHART_PALETTE_TOKENS, getChartColor, getChartColorClass, } from "./chart";
35
+ export type { ChartColorIndex, ChartColorToken } from "./chart";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fabio.caffarello/react-design-system",
3
3
  "private": false,
4
- "version": "4.1.0",
4
+ "version": "4.3.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",