@fabio.caffarello/react-design-system 3.4.0 → 3.6.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/dist/index.cjs +44 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1901 -1790
- package/dist/index.js.map +1 -1
- package/dist/react-design-system.css +1 -1
- package/dist/server/index.cjs +10 -10
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +554 -456
- package/dist/server/index.js.map +1 -1
- package/dist/ui/components/Card/Card.d.ts +26 -19
- package/dist/ui/components/Card/CardActions.d.ts +21 -0
- package/dist/ui/components/Card/CardBody.d.ts +6 -0
- package/dist/ui/components/Card/CardHeader.d.ts +6 -0
- package/dist/ui/components/Card/CardSubtitle.d.ts +6 -0
- package/dist/ui/components/Card/CardTitle.d.ts +22 -0
- package/dist/ui/components/Card/index.d.ts +12 -0
- package/dist/ui/hooks/useScrollSpy.d.ts +116 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/server.d.ts +11 -0
- package/package.json +1 -1
|
@@ -1,26 +1,33 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type FC, type HTMLAttributes } from "react";
|
|
2
|
+
import { CardHeader } from "./CardHeader";
|
|
3
|
+
import { CardTitle } from "./CardTitle";
|
|
4
|
+
import { CardSubtitle } from "./CardSubtitle";
|
|
5
|
+
import { CardActions } from "./CardActions";
|
|
6
|
+
import { CardBody } from "./CardBody";
|
|
7
|
+
export interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
8
|
variant?: "default" | "hover" | "selected";
|
|
4
9
|
padding?: "none" | "small" | "medium" | "large";
|
|
5
10
|
onClick?: () => void;
|
|
6
11
|
"aria-label"?: string;
|
|
7
12
|
"aria-labelledby"?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Render the root as a semantic `<section>` instead of `<div>`.
|
|
15
|
+
* When `true`, the Card becomes a landmark — a screen-reader-visible
|
|
16
|
+
* region in the document outline — so it MUST carry an accessible
|
|
17
|
+
* name (either `aria-labelledby` pointing to a `Card.Title` `id` or
|
|
18
|
+
* `aria-label`). A dev-only warning is emitted when this contract
|
|
19
|
+
* isn't met; an anonymous landmark hurts navigation by announcing
|
|
20
|
+
* "region" without a name.
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
asSection?: boolean;
|
|
8
24
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* @example
|
|
18
|
-
* ```tsx
|
|
19
|
-
* <Card variant="hover" padding="large">
|
|
20
|
-
* <h3>Card Title</h3>
|
|
21
|
-
* <p>Card content</p>
|
|
22
|
-
* </Card>
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
declare const Card: import("react").MemoExoticComponent<({ variant, padding, className, onClick, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, children, ...props }: Props) => import("react").JSX.Element>;
|
|
25
|
+
type CardCompound = FC<CardProps> & {
|
|
26
|
+
Header: typeof CardHeader;
|
|
27
|
+
Title: typeof CardTitle;
|
|
28
|
+
Subtitle: typeof CardSubtitle;
|
|
29
|
+
Actions: typeof CardActions;
|
|
30
|
+
Body: typeof CardBody;
|
|
31
|
+
};
|
|
32
|
+
declare const Card: CardCompound;
|
|
26
33
|
export default Card;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export interface CardActionsProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* CardActions — wrapper that hosts consumer-supplied action buttons
|
|
7
|
+
* within a `Card.Header`.
|
|
8
|
+
*
|
|
9
|
+
* The `data-card-actions` attribute is the structural marker `CardHeader`
|
|
10
|
+
* uses (via Tailwind v4 `:has()` selectors) to switch its grid layout
|
|
11
|
+
* from a single column to `[1fr auto]` when actions are present, so
|
|
12
|
+
* Title/Subtitle stack in column 1 and the action row spans both rows
|
|
13
|
+
* in column 2. Consumers should not override this attribute.
|
|
14
|
+
*
|
|
15
|
+
* This component is presentational: it emits no handlers on the DOM
|
|
16
|
+
* itself. The action elements (typically `<Button>`) are consumer-supplied
|
|
17
|
+
* and React's RSC boundary keeps them as client references — the
|
|
18
|
+
* wrapper stays server-safe.
|
|
19
|
+
*/
|
|
20
|
+
export declare function CardActions({ children, className, ...props }: CardActionsProps): import("react").JSX.Element;
|
|
21
|
+
export default CardActions;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function CardBody({ children, className, ...props }: CardBodyProps): import("react").JSX.Element;
|
|
6
|
+
export default CardBody;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function CardHeader({ children, className, ...props }: CardHeaderProps): import("react").JSX.Element;
|
|
6
|
+
export default CardHeader;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export interface CardSubtitleProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function CardSubtitle({ children, className, ...props }: CardSubtitleProps): import("react").JSX.Element;
|
|
6
|
+
export default CardSubtitle;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
export type CardTitleAs = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
3
|
+
export interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
/**
|
|
6
|
+
* Optional icon rendered before the title text.
|
|
7
|
+
*/
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Optional badge rendered after the title text.
|
|
11
|
+
*/
|
|
12
|
+
badge?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Heading level. Default `h2` — the typical depth for a card title
|
|
15
|
+
* inside a page that already has an `h1`. Use `h3` (or deeper) when
|
|
16
|
+
* the card sits inside a nested section.
|
|
17
|
+
* @default 'h2'
|
|
18
|
+
*/
|
|
19
|
+
as?: CardTitleAs;
|
|
20
|
+
}
|
|
21
|
+
export declare function CardTitle({ children, icon, badge, as: As, className, ...props }: CardTitleProps): import("react").JSX.Element;
|
|
22
|
+
export default CardTitle;
|
|
@@ -1 +1,13 @@
|
|
|
1
1
|
export { default } from "./Card";
|
|
2
|
+
export { default as Card } from "./Card";
|
|
3
|
+
export type { CardProps } from "./Card";
|
|
4
|
+
export { CardHeader } from "./CardHeader";
|
|
5
|
+
export type { CardHeaderProps } from "./CardHeader";
|
|
6
|
+
export { CardTitle } from "./CardTitle";
|
|
7
|
+
export type { CardTitleProps, CardTitleAs } from "./CardTitle";
|
|
8
|
+
export { CardSubtitle } from "./CardSubtitle";
|
|
9
|
+
export type { CardSubtitleProps } from "./CardSubtitle";
|
|
10
|
+
export { CardActions } from "./CardActions";
|
|
11
|
+
export type { CardActionsProps } from "./CardActions";
|
|
12
|
+
export { CardBody } from "./CardBody";
|
|
13
|
+
export type { CardBodyProps } from "./CardBody";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for `useScrollSpy`.
|
|
3
|
+
*/
|
|
4
|
+
export interface UseScrollSpyOptions {
|
|
5
|
+
/**
|
|
6
|
+
* `IntersectionObserver` `rootMargin`. Shrinks the effective viewport
|
|
7
|
+
* the observer reports on. The default `"0px 0px -50% 0px"` shrinks
|
|
8
|
+
* the bottom edge by half — a section is considered "in view" only
|
|
9
|
+
* when part of it sits in the upper half of the viewport, which is
|
|
10
|
+
* the canonical "table-of-contents follows the scroll" behaviour. To
|
|
11
|
+
* compensate for a sticky header, prefix the top with a negative
|
|
12
|
+
* pixel value, e.g. `"-56px 0px -50% 0px"`.
|
|
13
|
+
*
|
|
14
|
+
* @default "0px 0px -50% 0px"
|
|
15
|
+
*/
|
|
16
|
+
rootMargin?: string;
|
|
17
|
+
/**
|
|
18
|
+
* `IntersectionObserver` `threshold`. With the default `0`, the
|
|
19
|
+
* observer fires when any part of the target enters the (margin-
|
|
20
|
+
* shrunken) viewport.
|
|
21
|
+
*
|
|
22
|
+
* @default 0
|
|
23
|
+
*/
|
|
24
|
+
threshold?: number | number[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Track which section of a long scroll surface is currently in view,
|
|
28
|
+
* suitable for a table-of-contents nav that highlights the active section
|
|
29
|
+
* (the classic "scroll spy" pattern).
|
|
30
|
+
*
|
|
31
|
+
* The hook resolves each `id` to a DOM element via
|
|
32
|
+
* `document.getElementById`, observes those elements with a single
|
|
33
|
+
* `IntersectionObserver`, and returns the **id of the topmost visible
|
|
34
|
+
* section**. Returns `null` when nothing has reported as visible yet —
|
|
35
|
+
* including on the server, during the first render before the effect
|
|
36
|
+
* runs, and any frame where no observed section intersects the
|
|
37
|
+
* (margin-shrunken) viewport.
|
|
38
|
+
*
|
|
39
|
+
* ### Behavioural contract
|
|
40
|
+
*
|
|
41
|
+
* - **Return value.** `string | null`. `null` until at least one section
|
|
42
|
+
* has been reported intersecting; never falls back to a "first id"
|
|
43
|
+
* heuristic. Consumers that want a default highlight should fall back
|
|
44
|
+
* themselves: `active ?? ids[0]`.
|
|
45
|
+
* - **Tie-breaking.** When multiple sections intersect simultaneously,
|
|
46
|
+
* the hook picks the one **closest to the top of the viewport**
|
|
47
|
+
* (smallest `boundingClientRect.top`). This matches the user's
|
|
48
|
+
* expectation that scrolling DOWN advances the highlight forward, not
|
|
49
|
+
* backward.
|
|
50
|
+
* - **Missing ids.** An id that resolves to no element is skipped
|
|
51
|
+
* silently. The observer is created only when at least one element
|
|
52
|
+
* resolves; an empty `ids` array (or one with all-missing ids) leaves
|
|
53
|
+
* `activeId` as `null` and creates no observer.
|
|
54
|
+
* - **Cleanup.** The observer is disconnected on unmount and when the
|
|
55
|
+
* `ids` set changes, before a new observer is created. No leaks.
|
|
56
|
+
* - **Re-observation on `ids` change.** The hook detects changes via a
|
|
57
|
+
* string sentinel `ids.join("|")`. Pass `ids` as a stable reference
|
|
58
|
+
* (constant module-scope array, or `useMemo`) to avoid recreating the
|
|
59
|
+
* observer on every render. The hook does not memoise `ids` for you
|
|
60
|
+
* because the consumer typically already knows whether the array is
|
|
61
|
+
* stable.
|
|
62
|
+
* - **SSR safety.** `IntersectionObserver` and `document` are accessed
|
|
63
|
+
* only inside `useEffect`, which never runs on the server. The hook
|
|
64
|
+
* returns `null` during server rendering and the first client render
|
|
65
|
+
* pre-commit. A `typeof window` guard inside the effect protects
|
|
66
|
+
* older runtimes that evaluate `useEffect` outside a browser.
|
|
67
|
+
* - **`useState` initial value.** Always `null`. Returning the first id
|
|
68
|
+
* would highlight a section that the user has not yet seen and
|
|
69
|
+
* contradict the SSR/hydration contract.
|
|
70
|
+
*
|
|
71
|
+
* ### Why this lives in the design system as a hook, not as a component
|
|
72
|
+
*
|
|
73
|
+
* The visual surface (a sticky nav with highlighted active item) is
|
|
74
|
+
* already covered by `Navigation` + `NavLink` with the `active` prop. A
|
|
75
|
+
* `<ScrollSpy>` component would fuse behaviour and visual, restrict
|
|
76
|
+
* layout choice, and couple to a sibling component (`SectionCard`) via
|
|
77
|
+
* an opaque id-string convention. As a hook the consumer keeps the
|
|
78
|
+
* `ids` constant in one place and composes the nav however they want:
|
|
79
|
+
* vertical, horizontal, sticky, in a drawer, etc.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* "use client";
|
|
84
|
+
* import { useScrollSpy, Navigation, NavLink } from "@fabio.caffarello/react-design-system";
|
|
85
|
+
*
|
|
86
|
+
* const SECTIONS = ["intro", "votos", "gastos"];
|
|
87
|
+
*
|
|
88
|
+
* function ProfileToc() {
|
|
89
|
+
* const active = useScrollSpy(SECTIONS, { rootMargin: "-56px 0px -50% 0px" });
|
|
90
|
+
* return (
|
|
91
|
+
* <nav className="sticky top-14">
|
|
92
|
+
* <Navigation orientation="vertical">
|
|
93
|
+
* {SECTIONS.map((id) => (
|
|
94
|
+
* <NavLink
|
|
95
|
+
* key={id}
|
|
96
|
+
* href={`#${id}`}
|
|
97
|
+
* active={id === active}
|
|
98
|
+
* aria-current={id === active ? "location" : undefined}
|
|
99
|
+
* >
|
|
100
|
+
* {id}
|
|
101
|
+
* </NavLink>
|
|
102
|
+
* ))}
|
|
103
|
+
* </Navigation>
|
|
104
|
+
* </nav>
|
|
105
|
+
* );
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @param ids - Element ids to observe, in document order. Stable
|
|
110
|
+
* reference recommended (constant or `useMemo`).
|
|
111
|
+
* @param options - Optional `IntersectionObserver` overrides — see
|
|
112
|
+
* {@link UseScrollSpyOptions}.
|
|
113
|
+
* @returns The id of the topmost visible section, or `null` when
|
|
114
|
+
* nothing is reported visible yet.
|
|
115
|
+
*/
|
|
116
|
+
export declare function useScrollSpy(ids: string[], options?: UseScrollSpyOptions): string | null;
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -15,3 +15,5 @@ export { ThemeProvider, ConfigProvider, ToastProvider, DialogProvider, useTheme,
|
|
|
15
15
|
export { AppProvider, useApp, type AppProviderProps, type AppProviderConfig, } from "./providers/AppProvider";
|
|
16
16
|
export * from "./primitives";
|
|
17
17
|
export * from "./components";
|
|
18
|
+
export { useScrollSpy } from "./hooks/useScrollSpy";
|
|
19
|
+
export type { UseScrollSpyOptions } from "./hooks/useScrollSpy";
|
package/dist/ui/server.d.ts
CHANGED
|
@@ -24,6 +24,17 @@ export type { StackProps } from "./layouts/Stack/Stack";
|
|
|
24
24
|
export { default as Breadcrumb } from "./components/Breadcrumb/Breadcrumb";
|
|
25
25
|
export type { BreadcrumbItem } from "./components/Breadcrumb/Breadcrumb";
|
|
26
26
|
export { default as Card } from "./components/Card/Card";
|
|
27
|
+
export type { CardProps } from "./components/Card/Card";
|
|
28
|
+
export { CardHeader } from "./components/Card/CardHeader";
|
|
29
|
+
export type { CardHeaderProps } from "./components/Card/CardHeader";
|
|
30
|
+
export { CardTitle } from "./components/Card/CardTitle";
|
|
31
|
+
export type { CardTitleProps, CardTitleAs } from "./components/Card/CardTitle";
|
|
32
|
+
export { CardSubtitle } from "./components/Card/CardSubtitle";
|
|
33
|
+
export type { CardSubtitleProps } from "./components/Card/CardSubtitle";
|
|
34
|
+
export { CardActions } from "./components/Card/CardActions";
|
|
35
|
+
export type { CardActionsProps } from "./components/Card/CardActions";
|
|
36
|
+
export { CardBody } from "./components/Card/CardBody";
|
|
37
|
+
export type { CardBodyProps } from "./components/Card/CardBody";
|
|
27
38
|
export { DialogHeader } from "./components/Dialog/DialogHeader";
|
|
28
39
|
export type { DialogHeaderProps } from "./components/Dialog/DialogHeader";
|
|
29
40
|
export { DialogFooter } from "./components/Dialog/DialogFooter";
|