rich-react-component 0.1.0 → 0.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.
@@ -0,0 +1,65 @@
1
+ import { SidebarPresentation, SidebarTone, ThemeMode } from './Appearance';
2
+ import { ColorScheme } from './appearanceSchemes';
3
+ /**
4
+ * Every visible string is supplied by the caller — this component ships no
5
+ * built-in copy in any language, so it can be dropped into an application that
6
+ * owns its own localization.
7
+ */
8
+ export interface AppearanceMenuLabels {
9
+ presentation: {
10
+ title: string;
11
+ compact: string;
12
+ grouped: string;
13
+ };
14
+ mode: {
15
+ title: string;
16
+ light: string;
17
+ dark: string;
18
+ system: string;
19
+ };
20
+ tone: {
21
+ title: string;
22
+ light: string;
23
+ dark: string;
24
+ auto: string;
25
+ };
26
+ /** `options` maps a registered scheme id to its display name. */
27
+ colorScheme: {
28
+ title: string;
29
+ options: Record<string, string>;
30
+ };
31
+ }
32
+ /** Each section is hideable on its own. Omitted entries default to visible. */
33
+ export interface AppearanceMenuSections {
34
+ presentation?: boolean;
35
+ mode?: boolean;
36
+ tone?: boolean;
37
+ colorScheme?: boolean;
38
+ }
39
+ export interface AppearanceMenuProps {
40
+ labels: AppearanceMenuLabels;
41
+ sections?: AppearanceMenuSections;
42
+ className?: string;
43
+ /** Controlled values. When given, the provider is not written to for that setting. */
44
+ mode?: ThemeMode;
45
+ onModeChange?: (mode: ThemeMode) => void;
46
+ sidebarPresentation?: SidebarPresentation;
47
+ onSidebarPresentationChange?: (presentation: SidebarPresentation) => void;
48
+ sidebarTone?: SidebarTone;
49
+ onSidebarToneChange?: (tone: SidebarTone) => void;
50
+ colorSchemeId?: string;
51
+ onColorSchemeIdChange?: (id: string) => void;
52
+ /** Restrict/order the offered schemes. Defaults to every registered scheme. */
53
+ colorSchemes?: ColorScheme[];
54
+ }
55
+ /**
56
+ * Composable appearance selector. Drop it into a `Navbar` slot, a `Popover`,
57
+ * a `Menu` trigger's content, a settings drawer, or any application-owned
58
+ * container.
59
+ *
60
+ * Deliberately NOT a Metronic Layout Builder: it exposes exactly four
61
+ * independent settings and nothing else. It forces no persistence, mutates no
62
+ * global DOM, and makes no decision about who is allowed to change branding —
63
+ * those belong to the application.
64
+ */
65
+ export declare function AppearanceMenu({ labels, sections, className, mode, onModeChange, sidebarPresentation, onSidebarPresentationChange, sidebarTone, onSidebarToneChange, colorSchemeId, onColorSchemeIdChange, colorSchemes, }: AppearanceMenuProps): import("react").JSX.Element;
@@ -1,9 +1,16 @@
1
1
  import { ReactNode } from 'react';
2
2
  export type BadgeVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
3
+ /**
4
+ * How the variant colour is applied. Additive: `solid` is the existing
5
+ * behaviour and stays the default, so no current rendering changes.
6
+ */
7
+ export type BadgeAppearance = "solid" | "light" | "outline";
3
8
  export interface BadgeProps {
4
9
  variant?: BadgeVariant;
10
+ /** `light` and `outline` are the restrained forms for ordinary metadata. */
11
+ appearance?: BadgeAppearance;
5
12
  pill?: boolean;
6
13
  className?: string;
7
14
  children: ReactNode;
8
15
  }
9
- export declare function Badge({ variant, pill, className, children }: BadgeProps): import("react").JSX.Element;
16
+ export declare function Badge({ variant, appearance, pill, className, children }: BadgeProps): import("react").JSX.Element;
@@ -1,5 +1,13 @@
1
1
  import { ButtonHTMLAttributes, ReactNode } from 'react';
2
- export type ButtonVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark" | "link" | "outline-primary" | "outline-secondary";
2
+ export type ButtonVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark" | "link" | "outline-primary" | "outline-secondary"
3
+ /**
4
+ * Contextual light variants — a soft tinted surface with the contextual
5
+ * foreground, the Metronic Bootstrap signature for a secondary action.
6
+ * Added additively; Bootstrap has no `btn-light-*` rule of its own, so these
7
+ * render as a plain button until `rich-react-component/style.css` is
8
+ * imported, and no existing variant changed.
9
+ */
10
+ | "light-primary" | "light-secondary" | "light-success" | "light-danger" | "light-warning" | "light-info";
3
11
  export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "className" | "type" | "disabled"> {
4
12
  variant?: ButtonVariant;
5
13
  size?: "sm" | "lg";
@@ -1,9 +1,23 @@
1
1
  import { ReactNode } from 'react';
2
2
  export interface CardProps {
3
+ /** Standard header — renders an icon/avatar + title + subtitle row with a right-aligned actions slot, no manual header markup required. */
4
+ title?: ReactNode;
5
+ subtitle?: ReactNode;
6
+ /** Mutually exclusive with `avatar` — `avatar` wins if both are given. */
7
+ icon?: ReactNode;
8
+ avatar?: ReactNode;
9
+ /** Right-aligned header slot, typically Buttons/IconButtons/Menu. */
10
+ actions?: ReactNode;
11
+ /**
12
+ * Escape hatch for header content the title/subtitle/icon/avatar/actions
13
+ * shape can't express. Wins over all of the above when provided.
14
+ */
3
15
  header?: ReactNode;
4
16
  footer?: ReactNode;
17
+ /** Replaces `children` with a generic loading skeleton (reuses `Skeleton`, doc: no bespoke shimmer). */
18
+ loading?: boolean;
5
19
  className?: string;
6
20
  children?: ReactNode;
7
21
  }
8
22
  /** Generic content container — the most basic layout primitive, used to group everything else. */
9
- export declare function Card({ header, footer, className, children }: CardProps): import("react").JSX.Element;
23
+ export declare function Card({ title, subtitle, icon, avatar, actions, header, footer, loading, className, children }: CardProps): import("react").JSX.Element;
@@ -1,10 +1,34 @@
1
1
  import { ReactNode } from 'react';
2
+ export type DataGridAlign = "start" | "center" | "end";
3
+ /**
4
+ * Closed, finite formatter set — the same contract the Smart layer's
5
+ * `format` metadata already targeted, now owned here instead of being
6
+ * duplicated in a second Smart-side formatter map (doc: "Base DataGrid owns
7
+ * reusable presentation capability, Smart chooses a supported formatter").
8
+ * Never accepts an arbitrary/serialized function — that stays Smart's
9
+ * closed-enum contract too.
10
+ */
11
+ export type DataGridFormat = "text" | "date" | "currency" | "boolean";
12
+ export declare const dataGridFormatters: Record<DataGridFormat, (value: unknown) => ReactNode>;
2
13
  export interface DataGridColumn<TRow> {
3
- key: string;
14
+ /** Row-identity/sort key. Defaults to `field` when omitted — required only if `field` is also omitted (a fully custom `render`-only column). */
15
+ key?: string;
16
+ /** Row property this column reads its value from — strongly typed against `TRow`. Enables the declarative `align`/`format`/`formatter` path below instead of a `render` callback. */
17
+ field?: keyof TRow & string;
4
18
  header: string;
5
- render?: (row: TRow) => ReactNode;
6
- sortable?: boolean;
19
+ align?: DataGridAlign;
20
+ /** Defaults to `align` when omitted. */
21
+ headerAlign?: DataGridAlign;
7
22
  width?: string;
23
+ minWidth?: string;
24
+ maxWidth?: string;
25
+ sortable?: boolean;
26
+ /** Built-in formatter selection — the normal way to display a field (see `dataGridFormatters`). */
27
+ format?: DataGridFormat;
28
+ /** Escape hatch for a computed display value that still gets the standard aligned cell wrapper. */
29
+ formatter?: (value: unknown, row: TRow) => ReactNode;
30
+ /** Escape hatch for a fully custom cell — the exception, not the default way to display a field. */
31
+ render?: (row: TRow) => ReactNode;
8
32
  }
9
33
  export type DataGridSort = {
10
34
  key: string;
@@ -0,0 +1,20 @@
1
+ import { StackProps } from './Stack';
2
+ export type FlexGap = NonNullable<StackProps["gap"]> | "xs" | "sm" | "md" | "lg" | "xl";
3
+ export interface FlexProps extends Omit<StackProps, "gap"> {
4
+ gap?: FlexGap;
5
+ /** `flex-grow-1` on the container itself (for a Flex nested inside another flex layout). */
6
+ grow?: boolean;
7
+ /** `flex-shrink-0` on the container itself. */
8
+ shrink?: boolean;
9
+ /** `w-100`. */
10
+ fullWidth?: boolean;
11
+ }
12
+ /**
13
+ * Arbitrary flex layout on top of the same `d-flex` machinery Stack already
14
+ * owns (doc: "do not duplicate Stack") — only the defaults and the extra
15
+ * grow/shrink/fullWidth concerns differ. Stack defaults to a column
16
+ * (vertical list of children); Flex defaults to a row, matching the
17
+ * `<div className="d-flex align-items-center justify-content-between">`
18
+ * call sites it's meant to replace.
19
+ */
20
+ export declare function Flex({ direction, gap, grow, shrink, fullWidth, className, ...rest }: FlexProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { ButtonProps } from './Button';
3
+ import { IconProps } from './Icon';
4
+ export interface IconButtonProps extends Omit<ButtonProps, "children"> {
5
+ /** Icon class name(s), passed straight through to `Icon` (icon-set agnostic — doc section 15). */
6
+ icon: string;
7
+ /** Required — an icon-only control has no visible text, so it must carry its own accessible name. */
8
+ "aria-label": string;
9
+ iconSize?: IconProps["size"];
10
+ /** Optional tooltip, composed from the existing `Tooltip` primitive rather than a second hover-label implementation. */
11
+ tooltip?: ReactNode;
12
+ }
13
+ /** Composes Button + Icon (doc: reuse, don't build a second button system) for the common icon-only action button. */
14
+ export declare function IconButton({ icon, "aria-label": ariaLabel, iconSize, tooltip, variant, loading, className, ...rest }: IconButtonProps): import("react").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ListItemProps {
3
+ /** Typically an `Avatar` or `Icon`. */
4
+ leading?: ReactNode;
5
+ title: ReactNode;
6
+ description?: ReactNode;
7
+ /** Typically an `IconButton`, `Badge`, or `Sparkline`. */
8
+ trailing?: ReactNode;
9
+ /** Presence makes the row an interactive `<button>` (established row-action pattern). */
10
+ onClick?: () => void;
11
+ disabled?: boolean;
12
+ /** Tighter vertical rhythm for dense lists (e.g. inside a DataGrid cell). */
13
+ dense?: boolean;
14
+ className?: string;
15
+ }
16
+ /**
17
+ * Generic leading/title-description/trailing row — the same shape as MUI's
18
+ * `ListItem` + `ListItemAvatar` + `ListItemText` or Ant Design's
19
+ * `List.Item.Meta`. Replaces repeated `<div className="d-flex
20
+ * align-items-center"><Avatar/><div><span/><span/></div></div>` markup.
21
+ * Intentionally has no domain-specific counterpart (no `AuthorItem`/
22
+ * `UserItem`) — callers pass whatever leading/title/description/trailing
23
+ * content their row needs.
24
+ */
25
+ export declare function ListItem({ leading, title, description, trailing, onClick, disabled, dense, className }: ListItemProps): import("react").JSX.Element;
@@ -1,31 +1,121 @@
1
- import { ReactNode } from 'react';
2
- export interface SidebarLeafItem {
3
- key: string;
4
- label: ReactNode;
5
- icon?: ReactNode;
6
- href?: string;
7
- onClick?: () => void;
8
- active?: boolean;
9
- disabled?: boolean;
1
+ import { CSSProperties, MouseEvent, ReactNode } from 'react';
2
+ import { SidebarPresentation, SidebarTone } from './Appearance';
3
+ import { SidebarExpandMode, SidebarItem, SidebarLinkItem, SidebarSection, SidebarSelectHandler } from './sidebarModel';
4
+ export type { SidebarActionItem, SidebarCollapsibleItem, SidebarDividerItem, SidebarExpandMode, SidebarGroup, SidebarGroupItem, SidebarItem, SidebarLeafItem, SidebarLinkItem, SidebarParentItem, SidebarSection, SidebarSelectHandler, } from './sidebarModel';
5
+ export { isSidebarExpandable, isSidebarParent, legacyActiveKey, legacyDefaultExpandedKeys, toSidebarItems } from './sidebarModel';
6
+ /**
7
+ * How the current route may change which branches are open.
8
+ *
9
+ * - `never` — the active route never touches expansion.
10
+ * - `on-active-change` — the active branch opens on mount and again whenever
11
+ * `activeKey` changes, and the user may close it afterwards. This is what
12
+ * `expandActivePath` means.
13
+ * - `always` — active ancestors are forced open on every render, so the active
14
+ * branch cannot be closed. Kept because it was the behaviour `expandActivePath`
15
+ * used to have; it is not the default and not recommended.
16
+ */
17
+ export type SidebarActivePathExpansion = "never" | "on-active-change" | "always";
18
+ /**
19
+ * `grouped` is the presentation this component has always rendered and stays
20
+ * the default. Alias of the appearance layer's `SidebarPresentation` so the
21
+ * two can never drift apart.
22
+ */
23
+ export type SidebarVariant = SidebarPresentation;
24
+ export interface SidebarLinkRenderProps {
25
+ item: SidebarLinkItem;
26
+ href: string;
27
+ className: string;
28
+ style: CSSProperties;
29
+ children: ReactNode;
30
+ onClick: (event: MouseEvent<HTMLAnchorElement>) => void;
31
+ "aria-current": "page" | undefined;
32
+ "aria-disabled": true | undefined;
33
+ "aria-label": string | undefined;
34
+ "data-active-ancestor": "true" | undefined;
35
+ target: string | undefined;
36
+ rel: string | undefined;
10
37
  }
11
- export interface SidebarGroup {
12
- key: string;
38
+ /**
39
+ * Lets the application swap the anchor for its own router link. Base stays
40
+ * routing-agnostic: no router package is imported and no route matching
41
+ * happens here (doc section 22).
42
+ */
43
+ export type SidebarLinkRenderer = (props: SidebarLinkRenderProps) => ReactNode;
44
+ export interface SidebarCollapseControlProps {
45
+ collapsed: boolean;
46
+ toggle: () => void;
13
47
  label: string;
14
- items: SidebarLeafItem[];
15
- defaultOpen?: boolean;
16
48
  }
17
- export type SidebarSection = SidebarLeafItem | SidebarGroup;
18
49
  export interface SidebarProps {
19
- sections: SidebarSection[];
50
+ /** Recursive navigation model. Takes precedence over `sections` when both are given. */
51
+ items?: SidebarItem[];
52
+ /** @deprecated Legacy flat/one-level model. Still fully supported; normalized onto `items`. */
53
+ sections?: SidebarSection[];
54
+ /** `grouped` (default, the historical presentation) or the compact Metronic-style aside. */
55
+ variant?: SidebarVariant;
56
+ /** Surface tone. `auto` inherits the page theme; `light`/`dark` scope Bootstrap 5.3's own `data-bs-theme`. */
57
+ tone?: SidebarTone;
58
+ /** The one authoritative active identity. Ancestors are derived, not passed in. */
59
+ activeKey?: string;
60
+ /**
61
+ * Open the branch leading to `activeKey`. Off by default, so legacy rendering
62
+ * is unchanged. Shorthand for `activePathExpansion="on-active-change"`: the
63
+ * path opens on mount and whenever `activeKey` changes, and stays closable by
64
+ * hand in between.
65
+ */
66
+ expandActivePath?: boolean;
67
+ /** Explicit strategy. Wins over `expandActivePath` when both are given. */
68
+ activePathExpansion?: SidebarActivePathExpansion;
69
+ expandedKeys?: string[];
70
+ defaultExpandedKeys?: string[];
71
+ onExpandedKeysChange?: (keys: string[]) => void;
72
+ /** `multiple` (default) reproduces the legacy independent-groups behavior. */
73
+ expandMode?: SidebarExpandMode;
74
+ collapsed?: boolean;
75
+ defaultCollapsed?: boolean;
76
+ onCollapsedChange?: (collapsed: boolean) => void;
77
+ /** Render the collapse/expand control. */
78
+ collapsible?: boolean;
79
+ renderCollapseControl?: (props: SidebarCollapseControlProps) => ReactNode;
80
+ /** Accessible name of the control while expanded (i.e. the action it performs). */
81
+ collapseLabel?: string;
82
+ /** Accessible name of the control while collapsed. */
83
+ expandLabel?: string;
84
+ mobileOpen?: boolean;
85
+ defaultMobileOpen?: boolean;
86
+ onMobileOpenChange?: (open: boolean) => void;
87
+ /** Accessible name for the mobile drawer dialog. Falls back to `navLabel`. */
88
+ mobileLabel?: string;
89
+ /** Close the mobile drawer when a link or action is selected. */
90
+ closeMobileOnSelect?: boolean;
20
91
  header?: ReactNode;
21
92
  footer?: ReactNode;
93
+ /**
94
+ * Footer presentation while collapsed. A footer sized for the expanded aside
95
+ * cannot survive a ~58px rail — a select or an input would simply be clipped —
96
+ * and CSS alone cannot turn one control into another. Supply a compact
97
+ * icon-sized control here. Additive: when it is omitted the footer region is
98
+ * not rendered while collapsed, so nothing is clipped and no focusable
99
+ * control is left in a region the user cannot read.
100
+ */
101
+ collapsedFooter?: ReactNode;
22
102
  className?: string;
103
+ /** Accessible name of the navigation landmark. */
104
+ navLabel?: string;
105
+ onSelect?: SidebarSelectHandler;
106
+ renderLink?: SidebarLinkRenderer;
23
107
  }
24
108
  /**
25
- * Persistent vertical navigation. Leaf entries render as plain nav links;
26
- * grouped/collapsible sections reuse Accordion (doc section 20 — no second
27
- * independent collapse implementation) instead of reimplementing open/close
28
- * state. Active-state comes from the `active` flag the caller passes in —
29
- * routing/URL matching is the consuming app's job (doc section 22).
109
+ * Persistent vertical navigation.
110
+ *
111
+ * One recursive tree, one authoritative expansion state and one authoritative
112
+ * `activeKey` — no per-group Accordion instance and no per-item `active`
113
+ * boolean to keep in sync. The legacy `sections` shape is normalized onto the
114
+ * same model (`toSidebarItems`) so there is a single rendering path
115
+ * (doc section 20).
116
+ *
117
+ * Routing stays out of Base: real destinations render as anchors (or the
118
+ * consumer's `renderLink`), commands render as buttons, and URL matching
119
+ * remains the application's job (doc section 22).
30
120
  */
31
- export declare function Sidebar({ sections, header, footer, className }: SidebarProps): import("react").JSX.Element;
121
+ export declare function Sidebar({ items, sections, variant, tone, activeKey, expandActivePath, activePathExpansion, expandedKeys, defaultExpandedKeys, onExpandedKeysChange, expandMode, collapsed, defaultCollapsed, onCollapsedChange, collapsible, renderCollapseControl, collapseLabel, expandLabel, mobileOpen, defaultMobileOpen, onMobileOpenChange, mobileLabel, closeMobileOnSelect, header, footer, collapsedFooter, className, navLabel, onSelect, renderLink, }: SidebarProps): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ export type SparklineType = "line" | "area" | "bar";
2
+ export type SparklineTone = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "dark";
3
+ export interface SparklineProps {
4
+ type?: SparklineType;
5
+ data: number[];
6
+ tone?: SparklineTone;
7
+ width?: number;
8
+ height?: number;
9
+ strokeWidth?: number;
10
+ className?: string;
11
+ /** Accessible label — omit for a purely decorative chart (default: aria-hidden), same convention as `Icon`. */
12
+ label?: string;
13
+ }
14
+ /**
15
+ * Compact inline chart — the established dashboard "sparkline" concept
16
+ * (MUI X `SparkLineChart`, DevExtreme/Kendo Sparkline). Implemented with
17
+ * plain inline SVG rather than a charting dependency: this repo doesn't
18
+ * already depend on one, and a public API shaped around `data`/`type`/
19
+ * `tone` stays implementation-agnostic either way (doc: avoid unnecessary
20
+ * dependencies; don't leak chart-library config as the public API).
21
+ */
22
+ export declare function Sparkline({ type, data, tone, width, height, strokeWidth, className, label }: SparklineProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from 'react';
2
+ export type StatisticTrend = "up" | "down" | "neutral";
3
+ export interface StatisticProps {
4
+ label: ReactNode;
5
+ value: number | string;
6
+ prefix?: ReactNode;
7
+ suffix?: ReactNode;
8
+ /** Decimal places applied when `value` is a number. */
9
+ precision?: number;
10
+ trend?: StatisticTrend;
11
+ delta?: ReactNode;
12
+ loading?: boolean;
13
+ className?: string;
14
+ }
15
+ /** Label/value/prefix/suffix/trend — the established dashboard "Statistic"/"Stat" pattern (MUI, Ant Design, Mantine). No dashboard business logic. */
16
+ export declare function Statistic({ label, value, prefix, suffix, precision, trend, delta, loading, className }: StatisticProps): import("react").JSX.Element;
@@ -1,16 +1,33 @@
1
1
  import { ReactNode } from 'react';
2
+ export type TabsVariant = "default" | "underline" | "pill" | "card" | "button";
3
+ export type TabsOrientation = "horizontal" | "vertical";
4
+ export type TabsSize = "sm" | "lg";
2
5
  export interface TabItem {
3
6
  key: string;
4
- label: string;
7
+ label: ReactNode;
8
+ /** Icon class name(s), passed straight through to `Icon` (icon-set agnostic — doc section 15). */
9
+ icon?: string;
10
+ badge?: ReactNode;
5
11
  disabled?: boolean;
6
- content: ReactNode;
12
+ /**
13
+ * Optional — a tab can be nav-only (content driven externally, e.g. by
14
+ * the same `activeKey` state feeding a sibling `DataGrid`) instead of
15
+ * owning its panel.
16
+ */
17
+ content?: ReactNode;
7
18
  }
8
19
  export interface TabsProps {
9
20
  items: TabItem[];
10
21
  activeKey?: string;
11
22
  defaultActiveKey?: string;
12
23
  onChange?: (key: string) => void;
24
+ /** Generic nav look, not a Metronic widget name — express a Metronic visual as `variant="pill"` + `icon`, not a new named variant. */
25
+ variant?: TabsVariant;
26
+ orientation?: TabsOrientation;
27
+ size?: TabsSize;
28
+ /** Tab list fills its container width (`nav-fill`). */
29
+ stretch?: boolean;
13
30
  className?: string;
14
31
  }
15
32
  /** Tab definitions (`items`) are kept separate from rendering, per doc section 16. */
16
- export declare function Tabs({ items, activeKey, defaultActiveKey, onChange, className }: TabsProps): import("react").JSX.Element;
33
+ export declare function Tabs({ items, activeKey, defaultActiveKey, onChange, variant, orientation, size, stretch, className }: TabsProps): import("react").JSX.Element;
@@ -1,7 +1,9 @@
1
1
  import { ReactNode } from 'react';
2
- import { BadgeVariant } from './Badge';
2
+ import { BadgeAppearance, BadgeVariant } from './Badge';
3
3
  export interface TagProps {
4
4
  variant?: BadgeVariant;
5
+ /** Same additive contract as Badge; `solid` stays the default. */
6
+ appearance?: BadgeAppearance;
5
7
  onRemove?: () => void;
6
8
  className?: string;
7
9
  children: ReactNode;
@@ -11,4 +13,4 @@ export interface TagProps {
11
13
  * from Badge is purely behavioral: Tag is removable/interactive, Badge is
12
14
  * static.
13
15
  */
14
- export declare function Tag({ variant, onRemove, className, children }: TagProps): import("react").JSX.Element;
16
+ export declare function Tag({ variant, appearance, onRemove, className, children }: TagProps): import("react").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { ElementType, ReactNode } from 'react';
2
+ export type TextSize = "xs" | "sm" | "md" | "lg" | "xl";
3
+ export type TextWeight = "normal" | "medium" | "semibold" | "bold";
4
+ export type TextTone = "default" | "muted" | "primary" | "success" | "danger" | "warning" | "info";
5
+ export type TextAlign = "start" | "center" | "end";
6
+ export interface TextProps {
7
+ /** Rendered element — defaults to `span`. Pass e.g. `"h3"`/`"p"`/`"label"` for a semantic element without losing the typography contract. */
8
+ as?: ElementType;
9
+ size?: TextSize;
10
+ weight?: TextWeight;
11
+ tone?: TextTone;
12
+ align?: TextAlign;
13
+ /** Single-line ellipsis truncation. */
14
+ truncate?: boolean;
15
+ /** `false` disables wrapping (`text-nowrap`) without truncating. */
16
+ wrap?: boolean;
17
+ className?: string;
18
+ children?: ReactNode;
19
+ }
20
+ /** Generic typography primitive — replaces ad hoc `<span className="text-gray-500 fw-semibold fs-7">` markup at call sites. */
21
+ export declare function Text({ as, size, weight, tone, align, truncate, wrap, className, children }: TextProps): import("react").JSX.Element;
@@ -4,6 +4,13 @@ export interface TooltipProps {
4
4
  children: ReactNode;
5
5
  placement?: "top" | "bottom";
6
6
  className?: string;
7
+ /**
8
+ * Class for the trigger wrapper. The wrapper is inline-block by default,
9
+ * which is right for an inline trigger but wrong for a full-width row (e.g.
10
+ * a collapsed Sidebar item), so callers can override the display here
11
+ * instead of reimplementing a second tooltip.
12
+ */
13
+ wrapperClassName?: string;
7
14
  }
8
15
  /**
9
16
  * Reuses the existing Popup primitive (open/close, escape-to-close, outside
@@ -18,4 +25,4 @@ export interface TooltipProps {
18
25
  * conservative choice here, not less (doc section 18: "do NOT introduce
19
26
  * another positioning library unless actually necessary").
20
27
  */
21
- export declare function Tooltip({ content, children, placement, className }: TooltipProps): import("react").JSX.Element;
28
+ export declare function Tooltip({ content, children, placement, className, wrapperClassName }: TooltipProps): import("react").JSX.Element;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Semantic color schemes.
3
+ *
4
+ * A scheme is deliberately NOT a single raw color. Changing only the primary
5
+ * hue leaves buttons, active components and menu states inconsistent, so a
6
+ * scheme is a complete coordinated token family that is validated before it
7
+ * can be registered or applied.
8
+ *
9
+ * Variable mapping (verified against the repository's real styling stack —
10
+ * `bootstrap@5.3.8`, which is this package's peer dependency):
11
+ *
12
+ * - `--bs-primary` and `--bs-primary-rgb` genuinely exist in Bootstrap 5.3 and
13
+ * are written directly, so Bootstrap's own components follow the scheme.
14
+ * - `--bs-primary-active`, `--bs-primary-light`, `--bs-primary-inverse`,
15
+ * `--bs-component-*` and `--bs-menu-link-color-*` do NOT exist in Bootstrap.
16
+ * They are Metronic's names. They are emitted anyway so that an application
17
+ * that really does ship Metronic gets a coordinated result instead of a
18
+ * half-recolored theme.
19
+ * - `--rrc-*` are this repository's own tokens, which are what this library's
20
+ * stylesheet actually consumes. Each one falls back to the Bootstrap or
21
+ * Metronic variable when present, so the mapping works with Metronic, with
22
+ * plain Bootstrap, and with neither.
23
+ */
24
+ /** The full token family a scheme must define. */
25
+ export interface ColorSchemeTokens {
26
+ primary: string;
27
+ primaryActive: string;
28
+ primaryLight: string;
29
+ /** Foreground placed on top of `primary` — the scheme's contrast value. */
30
+ primaryInverse: string;
31
+ /** Comma-separated channels of `primary`, e.g. "13, 110, 253". */
32
+ primaryRgb: string;
33
+ componentActiveColor: string;
34
+ componentActiveBg: string;
35
+ componentHoverColor: string;
36
+ componentHoverBg: string;
37
+ componentCheckedColor: string;
38
+ componentCheckedBg: string;
39
+ menuLinkColorHover: string;
40
+ menuLinkColorShow: string;
41
+ menuLinkColorHere: string;
42
+ menuLinkColorActive: string;
43
+ }
44
+ export interface ColorScheme {
45
+ id: string;
46
+ tokens: ColorSchemeTokens;
47
+ /**
48
+ * Optional swatch color for a selector UI. Defaults to `tokens.primary`.
49
+ * Never the scheme's identity — selection must be indicated by more than
50
+ * color alone, so the selector also renders a real label and a checked state.
51
+ */
52
+ swatch?: string;
53
+ }
54
+ export declare const COLOR_SCHEME_TOKEN_KEYS: readonly (keyof ColorSchemeTokens)[];
55
+ /** True only when every required token is present and non-empty. */
56
+ export declare function isValidColorScheme(value: unknown): value is ColorScheme;
57
+ export interface ColorSchemeSeed {
58
+ id: string;
59
+ primary: string;
60
+ primaryActive: string;
61
+ primaryLight: string;
62
+ primaryInverse: string;
63
+ primaryRgb: string;
64
+ swatch?: string;
65
+ }
66
+ /**
67
+ * Derives the coordinated component/menu tokens from the four primary shades,
68
+ * so a scheme author cannot accidentally register a half-defined family.
69
+ * Callers that need full control can build a `ColorScheme` literal instead.
70
+ */
71
+ export declare function createColorScheme(seed: ColorSchemeSeed): ColorScheme;
72
+ /** The scheme applied when nothing else is selected — Bootstrap's own primary. */
73
+ export declare const DEFAULT_COLOR_SCHEME_ID = "blue";
74
+ /**
75
+ * Registers an application-owned scheme. Rejects an incomplete family rather
76
+ * than applying a partially recolored theme.
77
+ */
78
+ export declare function registerColorScheme(scheme: ColorScheme): void;
79
+ export declare function getColorScheme(id: string): ColorScheme | undefined;
80
+ /** Registered schemes in registration order — built-ins first. */
81
+ export declare function listColorSchemes(): ColorScheme[];
82
+ /**
83
+ * Resolves an identifier to a scheme, falling back to the default rather than
84
+ * throwing, so an unknown persisted value degrades safely.
85
+ */
86
+ export declare function resolveColorScheme(id: string | undefined): ColorScheme;
87
+ /**
88
+ * The scheme as CSS custom properties, ready to spread into a `style` object
89
+ * or write onto a DOM node. Emits the real Bootstrap variables, the
90
+ * Metronic-compatible names, and this repository's own `--rrc-*` tokens.
91
+ */
92
+ export declare function colorSchemeCssVariables(scheme: ColorScheme): Record<string, string>;
@@ -47,6 +47,16 @@ export * from './Icon';
47
47
  export * from './Navbar';
48
48
  export * from './Sidebar';
49
49
  export * from './PageHeader';
50
+ export * from './Text';
51
+ export * from './Flex';
52
+ export * from './IconButton';
53
+ export * from './ListItem';
54
+ export * from './Sparkline';
55
+ export * from './Statistic';
56
+ export { AppearanceProvider, useAppearance, createAppearanceInitScript, THEME_MODES, SIDEBAR_PRESENTATIONS, SIDEBAR_TONES } from './Appearance';
57
+ export type { AppearanceContextValue, AppearanceInitScriptOptions, AppearanceProviderProps, AppearanceSettings, AppearanceStorage, ResolvedTheme, SidebarPresentation, SidebarTone, ThemeMode, } from './Appearance';
58
+ export * from './appearanceSchemes';
59
+ export * from './AppearanceMenu';
50
60
  export { Popup } from './shared/Popup';
51
61
  export type { PopupProps } from './shared/Popup';
52
62
  export { Label } from './shared/Label';