@rackbops/ui-react 0.2.13 → 0.2.15
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/Dialog.d.ts +5 -0
- package/dist/LinksIndex.d.ts +11 -0
- package/dist/LinksIndex.js +14 -8
- package/dist/NavRail.d.ts +6 -3
- package/dist/NavRail.js +5 -3
- package/dist/Tabs.d.ts +2 -3
- package/dist/Tabs.js +8 -2
- package/dist/feedback.d.ts +5 -0
- package/dist/feedback.js +1 -0
- package/dist/form.d.ts +5 -1
- package/dist/form.js +8 -8
- package/package.json +1 -1
package/dist/Dialog.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ import { type DialogHTMLAttributes, type ReactNode, type RefAttributes } from "r
|
|
|
2
2
|
export interface DialogProps extends Omit<DialogHTMLAttributes<HTMLDialogElement>, "open" | "title" | "onClose">, RefAttributes<HTMLDialogElement> {
|
|
3
3
|
open: boolean;
|
|
4
4
|
onClose: () => void;
|
|
5
|
+
/**
|
|
6
|
+
* Renders as a heading in `.rb-dialog__title` (linked via aria-labelledby), replacing the
|
|
7
|
+
* native HTML `title` tooltip attribute -- there's no way to set a real tooltip through
|
|
8
|
+
* this component.
|
|
9
|
+
*/
|
|
5
10
|
title?: ReactNode;
|
|
6
11
|
actions?: ReactNode;
|
|
7
12
|
}
|
package/dist/LinksIndex.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { type HTMLAttributes, type RefAttributes } from "react";
|
|
2
2
|
export interface LinkUrl {
|
|
3
3
|
label: string;
|
|
4
|
+
/**
|
|
5
|
+
* Rendered as-is in an <a href> -- consumer-authored/trusted data (the app/site URLs you
|
|
6
|
+
* configure), not sanitized against `javascript:`-style schemes. Don't feed this untrusted
|
|
7
|
+
* input without validating the scheme first.
|
|
8
|
+
*/
|
|
4
9
|
url: string;
|
|
5
10
|
}
|
|
6
11
|
export interface LinkCategory {
|
|
@@ -20,6 +25,12 @@ export interface LinkItem {
|
|
|
20
25
|
export interface LinksIndexProps extends HTMLAttributes<HTMLDivElement>, RefAttributes<HTMLDivElement> {
|
|
21
26
|
categories: LinkCategory[];
|
|
22
27
|
links: LinkItem[];
|
|
28
|
+
/**
|
|
29
|
+
* Heading level for each category label; each card's own heading renders one level deeper
|
|
30
|
+
* (clamped to h6). Set this to match whatever heading LinksIndex is embedded under, so
|
|
31
|
+
* heading order stays sequential instead of skipping or repeating a level. Defaults to 2.
|
|
32
|
+
*/
|
|
33
|
+
level?: 2 | 3 | 4 | 5 | 6;
|
|
23
34
|
}
|
|
24
35
|
/**
|
|
25
36
|
* A generic, data-driven grouped index of apps/sites. Iterates `categories` in order, each a group
|
package/dist/LinksIndex.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef } from "react";
|
|
2
|
+
import { forwardRef, } from "react";
|
|
3
3
|
import { Card } from "./Card.js";
|
|
4
4
|
import { Badge } from "./feedback.js";
|
|
5
5
|
// Structural inline layout only -- the card/badge surfaces + colour come from @rackbops/styles
|
|
@@ -17,23 +17,29 @@ const listStyle = { listStyle: "none", margin: 0, padding: 0 };
|
|
|
17
17
|
// External = an http(s) or protocol-relative (`//host`) url -> opens in a new tab; anything else
|
|
18
18
|
// (relative, mailto:, tel:, ...) stays a plain in-page link.
|
|
19
19
|
const isExternal = (url) => /^(https?:)?\/\//i.test(url);
|
|
20
|
-
function LinkCard({ link }) {
|
|
21
|
-
|
|
20
|
+
function LinkCard({ link, level }) {
|
|
21
|
+
const Heading = `h${level}`;
|
|
22
|
+
return (_jsxs(Card, { children: [_jsxs(Heading, { children: [link.name, link.monitored ? (_jsxs(_Fragment, { children: [" ", _jsx(Badge, { variant: "success", children: "monitored" })] })) : null] }), link.description ? _jsx("p", { children: link.description }) : null, _jsx("ul", { style: listStyle, children: link.urls.map((u) => (
|
|
23
|
+
// Two urls on one link can share a `url` with different `label`s ("prod" /
|
|
24
|
+
// "canonical") -- key on the pair, not the url alone, so they don't collide.
|
|
25
|
+
_jsx("li", { children: isExternal(u.url) ? (_jsx("a", { href: u.url, target: "_blank", rel: "noreferrer noopener", children: u.label })) : (_jsx("a", { href: u.url, children: u.label })) }, `${u.label}::${u.url}`))) }), link.host ? _jsx("p", { children: link.host }) : null] }));
|
|
22
26
|
}
|
|
23
|
-
function Group({ label, items }) {
|
|
24
|
-
|
|
27
|
+
function Group({ label, items, level, }) {
|
|
28
|
+
const Heading = `h${level}`;
|
|
29
|
+
const cardLevel = (level < 6 ? level + 1 : 6);
|
|
30
|
+
return (_jsxs("section", { children: [_jsx(Heading, { children: label }), _jsx("div", { style: gridStyle, children: items.map((link) => (_jsx(LinkCard, { link: link, level: cardLevel }, link.name))) })] }));
|
|
25
31
|
}
|
|
26
32
|
/**
|
|
27
33
|
* A generic, data-driven grouped index of apps/sites. Iterates `categories` in order, each a group
|
|
28
34
|
* of `rb-card`s; links whose `category` is not listed collect into a trailing "Other" group. No
|
|
29
35
|
* router assumed -- external URLs open in a new tab. Themed by the consumer's `data-rb-style`.
|
|
30
36
|
*/
|
|
31
|
-
export const LinksIndex = forwardRef(function LinksIndex({ categories, links, className, ...rest }, ref) {
|
|
37
|
+
export const LinksIndex = forwardRef(function LinksIndex({ categories, links, className, level = 2, ...rest }, ref) {
|
|
32
38
|
const known = new Set(categories.map((c) => c.id));
|
|
33
39
|
const other = links.filter((l) => !known.has(l.category));
|
|
34
40
|
return (_jsxs("div", { ref: ref, className: className, ...rest, children: [categories.map((cat) => {
|
|
35
41
|
const items = links.filter((l) => l.category === cat.id);
|
|
36
|
-
return items.length > 0 ? _jsx(Group, { label: cat.label, items: items }, cat.id) : null;
|
|
37
|
-
}), other.length > 0 ? _jsx(Group, { label: "Other", items: other }) : null] }));
|
|
42
|
+
return items.length > 0 ? (_jsx(Group, { label: cat.label, items: items, level: level }, cat.id)) : null;
|
|
43
|
+
}), other.length > 0 ? _jsx(Group, { label: "Other", items: other, level: level }) : null] }));
|
|
38
44
|
});
|
|
39
45
|
LinksIndex.displayName = "LinksIndex";
|
package/dist/NavRail.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type HTMLAttributes, type ReactNode, type RefAttributes } from "react";
|
|
2
|
-
export interface NavRailItem {
|
|
1
|
+
import { type AnchorHTMLAttributes, type HTMLAttributes, type ReactNode, type RefAttributes } from "react";
|
|
2
|
+
export interface NavRailItem extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "id" | "href"> {
|
|
3
3
|
/** Matched against `activeId`; also used as the React list key. */
|
|
4
4
|
id: string;
|
|
5
5
|
label: ReactNode;
|
|
6
6
|
href?: string;
|
|
7
|
+
[dataAttr: `data-${string}`]: unknown;
|
|
7
8
|
}
|
|
8
9
|
export interface NavRailProps extends HTMLAttributes<HTMLElement>, RefAttributes<HTMLElement> {
|
|
9
10
|
items: NavRailItem[];
|
|
@@ -14,6 +15,8 @@ export interface NavRailProps extends HTMLAttributes<HTMLElement>, RefAttributes
|
|
|
14
15
|
/**
|
|
15
16
|
* A vertical nav container (.rb-nav-rail) rendering one NavLink per item.
|
|
16
17
|
* Controlled by the caller via `activeId`, same as NavLink's own `active` prop --
|
|
17
|
-
* this component owns no state of its own.
|
|
18
|
+
* this component owns no state of its own. Any extra props on an item (onClick, target,
|
|
19
|
+
* rel, aria-*, data-*, className, ...) forward onto that item's own NavLink/<a> -- e.g. to
|
|
20
|
+
* intercept a click for a client router while still setting a real `href`.
|
|
18
21
|
*/
|
|
19
22
|
export declare const NavRail: import("react").ForwardRefExoticComponent<Omit<NavRailProps, "ref"> & RefAttributes<HTMLElement>>;
|
package/dist/NavRail.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef } from "react";
|
|
2
|
+
import { forwardRef, } from "react";
|
|
3
3
|
import { cx } from "./cx.js";
|
|
4
4
|
import { NavLink } from "./NavLink.js";
|
|
5
5
|
/**
|
|
6
6
|
* A vertical nav container (.rb-nav-rail) rendering one NavLink per item.
|
|
7
7
|
* Controlled by the caller via `activeId`, same as NavLink's own `active` prop --
|
|
8
|
-
* this component owns no state of its own.
|
|
8
|
+
* this component owns no state of its own. Any extra props on an item (onClick, target,
|
|
9
|
+
* rel, aria-*, data-*, className, ...) forward onto that item's own NavLink/<a> -- e.g. to
|
|
10
|
+
* intercept a click for a client router while still setting a real `href`.
|
|
9
11
|
*/
|
|
10
12
|
export const NavRail = forwardRef(function NavRail({ items, activeId, className, ...rest }, ref) {
|
|
11
|
-
return (_jsx("nav", { ref: ref, className: cx("rb-nav-rail", className), ...rest, children: items.map((
|
|
13
|
+
return (_jsx("nav", { ref: ref, className: cx("rb-nav-rail", className), ...rest, children: items.map(({ id, label, href, ...itemRest }) => (_jsx(NavLink, { href: href, active: id === activeId, ...itemRest, children: label }, id))) }));
|
|
12
14
|
});
|
|
13
15
|
NavRail.displayName = "NavRail";
|
package/dist/Tabs.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { type ReactNode, type RefAttributes } from "react";
|
|
1
|
+
import { type HTMLAttributes, type ReactNode, type RefAttributes } from "react";
|
|
2
2
|
export interface TabItem {
|
|
3
3
|
id: string;
|
|
4
4
|
label: ReactNode;
|
|
5
5
|
content: ReactNode;
|
|
6
6
|
}
|
|
7
|
-
export interface TabsProps extends RefAttributes<HTMLDivElement> {
|
|
7
|
+
export interface TabsProps extends HTMLAttributes<HTMLDivElement>, RefAttributes<HTMLDivElement> {
|
|
8
8
|
items: TabItem[];
|
|
9
9
|
/** Initially active tab id; defaults to the first item. */
|
|
10
10
|
defaultId?: string;
|
|
11
|
-
className?: string;
|
|
12
11
|
}
|
|
13
12
|
export declare const Tabs: import("react").ForwardRefExoticComponent<Omit<TabsProps, "ref"> & RefAttributes<HTMLDivElement>>;
|
package/dist/Tabs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useId, useRef, useState, } from "react";
|
|
3
3
|
import { cx } from "./cx.js";
|
|
4
|
-
export const Tabs = forwardRef(function Tabs({ items, defaultId, className }, ref) {
|
|
4
|
+
export const Tabs = forwardRef(function Tabs({ items, defaultId, className, ...rest }, ref) {
|
|
5
5
|
const base = useId();
|
|
6
6
|
const [active, setActive] = useState(defaultId ?? items[0]?.id);
|
|
7
7
|
// Fall back to the first tab if `active` names no item, so exactly one tab is
|
|
@@ -26,7 +26,13 @@ export const Tabs = forwardRef(function Tabs({ items, defaultId, className }, re
|
|
|
26
26
|
// Move focus with the selection — the whole point of the roving tabindex.
|
|
27
27
|
tabRefs.current[next]?.focus();
|
|
28
28
|
};
|
|
29
|
-
return (
|
|
29
|
+
return (
|
|
30
|
+
// The outer <div> is a plain structural wrapper -- an ARIA tablist should
|
|
31
|
+
// contain only `tab` children, so the tabpanels below live as its
|
|
32
|
+
// siblings instead. That's the element `ref` points to; className and
|
|
33
|
+
// arbitrary props (aria-label, data-testid, id, ...) belong on the actual
|
|
34
|
+
// role="tablist" element, which is what they're meant to reach.
|
|
35
|
+
_jsxs("div", { ref: ref, children: [_jsx("div", { className: cx("rb-tabs", className), role: "tablist", ...rest, children: items.map((t, idx) => {
|
|
30
36
|
const selected = t.id === activeId;
|
|
31
37
|
return (_jsx("button", { ref: (el) => {
|
|
32
38
|
tabRefs.current[idx] = el;
|
package/dist/feedback.d.ts
CHANGED
|
@@ -6,8 +6,13 @@ export interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, RefAttribut
|
|
|
6
6
|
export declare const Badge: import("react").ForwardRefExoticComponent<Omit<BadgeProps, "ref"> & RefAttributes<HTMLSpanElement>>;
|
|
7
7
|
export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, "title">, RefAttributes<HTMLDivElement> {
|
|
8
8
|
variant?: SemanticVariant;
|
|
9
|
+
/**
|
|
10
|
+
* Renders as a heading in `.rb-alert__title`, replacing the native HTML `title` tooltip
|
|
11
|
+
* attribute -- there's no way to set a real tooltip through this component.
|
|
12
|
+
*/
|
|
9
13
|
title?: ReactNode;
|
|
10
14
|
}
|
|
15
|
+
/** A status banner (.rb-alert); `role="alert"` announces it to screen readers on mount/update. */
|
|
11
16
|
export declare const Alert: import("react").ForwardRefExoticComponent<Omit<AlertProps, "ref"> & RefAttributes<HTMLDivElement>>;
|
|
12
17
|
export interface ProgressProps extends ProgressHTMLAttributes<HTMLProgressElement>, RefAttributes<HTMLProgressElement> {
|
|
13
18
|
}
|
package/dist/feedback.js
CHANGED
|
@@ -5,6 +5,7 @@ export const Badge = forwardRef(function Badge({ variant, className, ...rest },
|
|
|
5
5
|
return (_jsx("span", { ref: ref, className: cx("rb-badge", variant && `rb-badge--${variant}`, className), ...rest }));
|
|
6
6
|
});
|
|
7
7
|
Badge.displayName = "Badge";
|
|
8
|
+
/** A status banner (.rb-alert); `role="alert"` announces it to screen readers on mount/update. */
|
|
8
9
|
export const Alert = forwardRef(function Alert({ variant, title, className, children, ...rest }, ref) {
|
|
9
10
|
return (_jsxs("div", { ref: ref, role: "alert", className: cx("rb-alert", variant && `rb-alert--${variant}`, className), ...rest, children: [title !== undefined && _jsx("div", { className: "rb-alert__title", children: title }), children] }));
|
|
10
11
|
});
|
package/dist/form.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type HTMLAttributes, type InputHTMLAttributes, type LabelHTMLAttributes, type ReactNode, type RefAttributes, type SelectHTMLAttributes, type TextareaHTMLAttributes } from "react";
|
|
1
|
+
import { type CSSProperties, type HTMLAttributes, type InputHTMLAttributes, type LabelHTMLAttributes, type ReactNode, type RefAttributes, type SelectHTMLAttributes, type TextareaHTMLAttributes } from "react";
|
|
2
2
|
export interface InputProps extends InputHTMLAttributes<HTMLInputElement>, RefAttributes<HTMLInputElement> {
|
|
3
3
|
}
|
|
4
4
|
export declare const Input: import("react").ForwardRefExoticComponent<Omit<InputProps, "ref"> & RefAttributes<HTMLInputElement>>;
|
|
@@ -17,6 +17,10 @@ export declare const Field: import("react").ForwardRefExoticComponent<Omit<Field
|
|
|
17
17
|
export interface ChoiceProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type">, RefAttributes<HTMLInputElement> {
|
|
18
18
|
/** Optional label text; when set the control is wrapped in a .rb-choice row. */
|
|
19
19
|
label?: ReactNode;
|
|
20
|
+
/** Styles the .rb-choice row itself (e.g. margins, flex alignment) -- `className` still styles the control. Only used when `label` is set. */
|
|
21
|
+
wrapperClassName?: string;
|
|
22
|
+
/** Styles the .rb-choice row itself; `style` still styles the control. Only used when `label` is set. */
|
|
23
|
+
wrapperStyle?: CSSProperties;
|
|
20
24
|
}
|
|
21
25
|
export declare const Checkbox: import("react").ForwardRefExoticComponent<Omit<ChoiceProps, "ref"> & RefAttributes<HTMLInputElement>>;
|
|
22
26
|
export declare const Radio: import("react").ForwardRefExoticComponent<Omit<ChoiceProps, "ref"> & RefAttributes<HTMLInputElement>>;
|
package/dist/form.js
CHANGED
|
@@ -22,20 +22,20 @@ export const Field = forwardRef(function Field({ className, ...rest }, ref) {
|
|
|
22
22
|
});
|
|
23
23
|
Field.displayName = "Field";
|
|
24
24
|
/** A checkbox/radio/switch control, optionally wrapped with its label. */
|
|
25
|
-
function ChoiceControl({ label, control }) {
|
|
25
|
+
function ChoiceControl({ label, control, wrapperClassName, wrapperStyle, }) {
|
|
26
26
|
if (label === undefined)
|
|
27
27
|
return _jsx(_Fragment, { children: control });
|
|
28
|
-
return (_jsxs("label", { className: "rb-choice", children: [control, label] }));
|
|
28
|
+
return (_jsxs("label", { className: cx("rb-choice", wrapperClassName), style: wrapperStyle, children: [control, label] }));
|
|
29
29
|
}
|
|
30
|
-
export const Checkbox = forwardRef(function Checkbox({ label, className, ...rest }, ref) {
|
|
31
|
-
return (_jsx(ChoiceControl, { label: label, control: _jsx("input", { ref: ref, type: "checkbox", className: cx("rb-checkbox", className), ...rest }) }));
|
|
30
|
+
export const Checkbox = forwardRef(function Checkbox({ label, className, wrapperClassName, wrapperStyle, ...rest }, ref) {
|
|
31
|
+
return (_jsx(ChoiceControl, { label: label, wrapperClassName: wrapperClassName, wrapperStyle: wrapperStyle, control: _jsx("input", { ref: ref, type: "checkbox", className: cx("rb-checkbox", className), ...rest }) }));
|
|
32
32
|
});
|
|
33
33
|
Checkbox.displayName = "Checkbox";
|
|
34
|
-
export const Radio = forwardRef(function Radio({ label, className, ...rest }, ref) {
|
|
35
|
-
return (_jsx(ChoiceControl, { label: label, control: _jsx("input", { ref: ref, type: "radio", className: cx("rb-radio", className), ...rest }) }));
|
|
34
|
+
export const Radio = forwardRef(function Radio({ label, className, wrapperClassName, wrapperStyle, ...rest }, ref) {
|
|
35
|
+
return (_jsx(ChoiceControl, { label: label, wrapperClassName: wrapperClassName, wrapperStyle: wrapperStyle, control: _jsx("input", { ref: ref, type: "radio", className: cx("rb-radio", className), ...rest }) }));
|
|
36
36
|
});
|
|
37
37
|
Radio.displayName = "Radio";
|
|
38
|
-
export const Switch = forwardRef(function Switch({ label, className, ...rest }, ref) {
|
|
39
|
-
return (_jsx(ChoiceControl, { label: label, control: _jsx("input", { ref: ref, type: "checkbox", role: "switch", className: cx("rb-switch", className), ...rest }) }));
|
|
38
|
+
export const Switch = forwardRef(function Switch({ label, className, wrapperClassName, wrapperStyle, ...rest }, ref) {
|
|
39
|
+
return (_jsx(ChoiceControl, { label: label, wrapperClassName: wrapperClassName, wrapperStyle: wrapperStyle, control: _jsx("input", { ref: ref, type: "checkbox", role: "switch", className: cx("rb-switch", className), ...rest }) }));
|
|
40
40
|
});
|
|
41
41
|
Switch.displayName = "Switch";
|