@danxbot/ui 3.5.2 → 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.
@@ -0,0 +1,64 @@
1
+ import type { ReactNode } from "react";
2
+ import { type CardHeaderProps } from "./Card";
3
+ export type ConnectionHealth = "healthy" | "degraded" | "broken" | "unknown";
4
+ export interface ConnectionCardProps {
5
+ /**
6
+ * The service's brand mark. A consumer normally passes a real logo — an
7
+ * `<img>`, an inline SVG. Omit it and the card falls back to this library's
8
+ * own `Icon`, so a catalogue is never missing a media slot entirely just
9
+ * because one integration has no artwork yet.
10
+ */
11
+ logo?: ReactNode;
12
+ /** The service's name. Plain text — it is composed into the action button's
13
+ * accessible name (see `actionLabel`), which a JSX tree cannot be. */
14
+ name: string;
15
+ /** What this connection is FOR, one line — "Email via Mailchimp
16
+ * Transactional", not "Mailchimp integration". */
17
+ description?: ReactNode;
18
+ /** The four-state health model. See the file header for why not a boolean. */
19
+ status: ConnectionHealth;
20
+ /** A failure reason, a partial-failure explanation, or a last-checked
21
+ * timestamp — whatever the status badge does not already say. Rendered
22
+ * only when supplied; omitting it drops the line rather than reserving
23
+ * empty space for it. */
24
+ detail?: ReactNode;
25
+ /**
26
+ * The primary action's visible label — typically "Connect" for `unknown`,
27
+ * "Manage" (or "Reconnect", "Fix") otherwise. Omitting it renders no action
28
+ * at all, for a read-only tile.
29
+ *
30
+ * The button's PROMINENCE follows `status`, not this label's wording: an
31
+ * `unknown` card gets the solid, high-contrast treatment because getting it
32
+ * connected is the one thing worth doing; every other state gets the
33
+ * quieter outline treatment, because the card's border and badge are
34
+ * already carrying the "look here" signal and a second loud button would
35
+ * just compete with them.
36
+ */
37
+ actionLabel?: string;
38
+ onAction?: () => void;
39
+ /**
40
+ * Present (and non-`undefined`) disables the action and explains why.
41
+ *
42
+ * This is `IconButton`'s `disabledReason` contract, carried over verbatim:
43
+ * `aria-disabled` rather than native `disabled`, so the control stays
44
+ * hoverable and focusable — a `disabled` button drops out of hit-testing
45
+ * entirely, and a control nobody can point at can never be asked why it
46
+ * won't fire. The reason is announced two ways at once, neither of them
47
+ * "only on hover": an always-present `sr-only` node wired through
48
+ * `aria-describedby` for a screen reader, and a visible `Tooltip` that opens
49
+ * on focus as well as on pointer hover, for a keyboard user who generates
50
+ * no hover event at all.
51
+ */
52
+ actionDisabledReason?: string;
53
+ /**
54
+ * The heading level the name renders as. See `CardHeader.titleAs` — the
55
+ * reasoning is identical: a card's correct heading level is a property of
56
+ * where it sits in the page outline, not of the card, so only the caller
57
+ * of a whole catalogue grid knows it.
58
+ *
59
+ * @default "h3"
60
+ */
61
+ titleAs?: CardHeaderProps["titleAs"];
62
+ className?: string;
63
+ }
64
+ export declare function ConnectionCard({ logo, name, description, status, detail, actionLabel, onAction, actionDisabledReason, titleAs, className, }: ConnectionCardProps): import("react").JSX.Element;
@@ -57,7 +57,7 @@ export interface InputProps extends Omit<BaseInput.Props, "className" | "render"
57
57
  loading?: boolean;
58
58
  ref?: Ref<HTMLInputElement>;
59
59
  }
60
- export declare function Input({ className, size, leading, trailing, loading, ref, ...props }: InputProps): import("react").JSX.Element;
60
+ export declare function Input(allProps: InputProps): import("react").JSX.Element;
61
61
  declare const textarea: import("tailwind-variants").TVReturnType<{
62
62
  size: {
63
63
  sm: "rounded-md px-3 py-2 text-xs";
@@ -0,0 +1,48 @@
1
+ import type { Ref } from "react";
2
+ import { type FieldProps } from "./Field";
3
+ import { type InputProps } from "./Input";
4
+ export type SecretValue = {
5
+ kind: "unchanged";
6
+ } | {
7
+ kind: "set";
8
+ value: string;
9
+ } | {
10
+ kind: "cleared";
11
+ };
12
+ export interface SecretFieldProps extends Pick<FieldProps, "label" | "description" | "error" | "required" | "disabled" | "name" | "className">, Pick<InputProps, "size" | "placeholder"> {
13
+ /** The pending edit. See the module doc comment for why this is not a `string`. */
14
+ value: SecretValue;
15
+ onChange: (value: SecretValue) => void;
16
+ /**
17
+ * Whether a secret is CURRENTLY stored server-side, independent of `value`
18
+ * — this is the fact the empty, masked field is standing in for. Drives the
19
+ * "a secret is stored" announcement, the hint row, and whether the clear
20
+ * action is offered at all (there is nothing to clear when nothing is set).
21
+ */
22
+ configured: boolean;
23
+ /**
24
+ * A partial, already-safe rendering of the stored value — e.g. `{ prefix:
25
+ * "sk-ab", suffix: "9f4c" }` for a key the consuming app's own API already
26
+ * truncates before it ever reaches the client. This is NOT the secret; it
27
+ * is a confirmation aid ("is this the key I think it is?") and is shown
28
+ * only while a stored value exists and has not been typed over or cleared.
29
+ */
30
+ hint?: {
31
+ prefix: string;
32
+ suffix: string;
33
+ };
34
+ /** When the stored value was last written, for the same confirmation purpose as `hint`. */
35
+ updatedAt?: string | Date;
36
+ /** Who wrote it, if the caller's system tracks that. */
37
+ updatedBy?: string;
38
+ /**
39
+ * Offers a show/hide toggle for text the operator just TYPED. Default true.
40
+ * Never offered for the stored value — see the module doc comment — and
41
+ * never rendered while there is no typed text to reveal.
42
+ */
43
+ revealable?: boolean;
44
+ /** Label on the destructive confirm button. Default "Clear". */
45
+ clearConfirmLabel?: string;
46
+ ref?: Ref<HTMLInputElement>;
47
+ }
48
+ export declare function SecretField({ value, onChange, configured, hint, updatedAt, updatedBy, revealable, clearConfirmLabel, label, description, error, required, disabled, name, placeholder, size, className, ref, }: SecretFieldProps): import("react").JSX.Element;
@@ -0,0 +1,130 @@
1
+ import { type ReactNode } from "react";
2
+ import { type CardHeaderProps } from "./Card";
3
+ /**
4
+ * What `SettingRow` hands to a `control` supplied as a render function —
5
+ * two ARIA id references to place on the control's own focusable element(s).
6
+ *
7
+ * WHY A RENDER PROP, NOT AN AUTOMATIC ASSOCIATION LIKE `Field`.
8
+ *
9
+ * `Field` (this library's other labelled wrapper) gets the label/description
10
+ * link for free, but only because every control it has ever wrapped is one of
11
+ * THIS library's own Base UI–backed primitives — `Checkbox`, `Switch`,
12
+ * `Input`, `Select`… — and those read Base UI's internal field context
13
+ * themselves to pick up `aria-describedby`. That mechanism is a private
14
+ * implementation detail of Base UI (there is no public hook a third-party
15
+ * control could subscribe to), so it silently does NOTHING for anything that
16
+ * is not one of those primitives.
17
+ *
18
+ * `SettingRow.control` is typed to accept literally anything a settings page
19
+ * might need in that slot — a bare `<input>`, a third-party widget, a
20
+ * composite the CONSUMER wrote that has never heard of this library, let
21
+ * alone Base UI's field internals. Wrapping arbitrary children in the same
22
+ * context-based `Field` would look correct and associate nothing, which is
23
+ * the worse failure: it fails silently, exactly the thing this component
24
+ * exists to prevent for settings prose.
25
+ *
26
+ * So the association is made an explicit VALUE instead of an implicit
27
+ * context read: `SettingRow` generates the ids, and a `control` passed as a
28
+ * function receives them and is responsible for spreading them onto the
29
+ * element that actually receives focus (the switch's button, the input
30
+ * itself, a slider's thumb — for a multi-thumb control, every thumb).
31
+ *
32
+ * `control` may also be passed as a plain `ReactNode` — the escape hatch for
33
+ * a control that already carries its own accessible name and description
34
+ * through some other channel (for example a `SwitchField`/`Field`-wrapped
35
+ * control, or a composite region where per-control labelling does not apply)
36
+ * — in which case NEITHER id is wired anywhere, and getting the control
37
+ * properly named and described is entirely the caller's responsibility.
38
+ */
39
+ export interface SettingRowControlRenderProps {
40
+ /** Always present — `label` is required, so the row always has a name to give. */
41
+ "aria-labelledby": string;
42
+ /** `undefined` when this row has no `description` — nothing to describe with. */
43
+ "aria-describedby": string | undefined;
44
+ }
45
+ export interface SettingRowBaseProps {
46
+ /** The setting's name. Always rendered as visible text and always given an id. */
47
+ label: ReactNode;
48
+ /**
49
+ * What the setting actually DOES, in one line. Always visible — see the
50
+ * module doc comment for why this is not a tooltip. Rendered with a
51
+ * generated id and, when `control` is a render function, offered to it via
52
+ * `SettingRowControlRenderProps["aria-describedby"]`.
53
+ */
54
+ description?: ReactNode;
55
+ /**
56
+ * The long-form "why this matters" — collapsed by default, revealed by a
57
+ * disclosure built on this library's `Collapsible`. Omit entirely when
58
+ * `description` alone says everything worth saying; not every setting earns
59
+ * a second paragraph.
60
+ */
61
+ details?: ReactNode;
62
+ /** Accessible name + visible label of the `details` disclosure trigger. */
63
+ detailsLabel?: ReactNode;
64
+ /** Renders the `details` disclosure already open — for a setting a caller deep-links to. */
65
+ detailsDefaultOpen?: boolean;
66
+ /**
67
+ * The CONSEQUENCE of changing this setting, stated plainly — "takes effect
68
+ * on next dispatch", "requires a worker restart" — never the mechanism. See
69
+ * the module doc comment: this is what stops a setting from silently not
70
+ * applying yet.
71
+ */
72
+ effect?: ReactNode;
73
+ /**
74
+ * Right-aligned indicator — a `Badge` showing the setting's current derived
75
+ * state, most often. Rendered beside the control, not inside it, so it
76
+ * survives a `readOnly` row where there is no control at all.
77
+ */
78
+ status?: ReactNode;
79
+ className?: string;
80
+ }
81
+ export interface SettingRowEditableProps extends SettingRowBaseProps {
82
+ readOnly?: undefined;
83
+ /**
84
+ * The setting's control. Either a plain node, or a function receiving the
85
+ * ids to associate — see `SettingRowControlRenderProps`.
86
+ */
87
+ control: ReactNode | ((renderProps: SettingRowControlRenderProps) => ReactNode);
88
+ }
89
+ export interface SettingRowReadOnlyProps extends SettingRowBaseProps {
90
+ /**
91
+ * Presents this row as READ-ONLY instead of rendering `control` at all —
92
+ * see the module doc comment for why this is a first-class state rather
93
+ * than a disabled control. `reason` is required; `value`, when given, is
94
+ * the setting's current value, shown as plain text beside it.
95
+ */
96
+ readOnly: {
97
+ reason: ReactNode;
98
+ value?: ReactNode;
99
+ };
100
+ control?: undefined;
101
+ }
102
+ export type SettingRowProps = SettingRowEditableProps | SettingRowReadOnlyProps;
103
+ export declare function SettingRow(props: SettingRowProps): import("react").JSX.Element;
104
+ export interface SettingGroupProps {
105
+ /** The group's name — e.g. "Notifications", "Dispatch limits". */
106
+ title: ReactNode;
107
+ /** One line of context for the whole group. */
108
+ description?: ReactNode;
109
+ /** @default "h3" — see `CardHeader`'s own doc comment on why this is the caller's call. */
110
+ titleAs?: CardHeaderProps["titleAs"];
111
+ /** Where a Save button or a "last changed" line lives. Rendered as a `CardFooter`. */
112
+ footer?: ReactNode;
113
+ className?: string;
114
+ /** `SettingRow` elements, in display order. */
115
+ children: ReactNode;
116
+ }
117
+ /**
118
+ * A titled card holding several `SettingRow`s.
119
+ *
120
+ * `SettingGroup` simply IS a `Card` — a fixed shape (`CardHeader` for the
121
+ * title/description, a divided list of rows, an optional `CardFooter`) built
122
+ * from parts this library already ships, rather than a new container
123
+ * component that happens to look like one. Nesting, theming, radius
124
+ * arithmetic and padding all come from `Card` for free, and any future fix to
125
+ * that component (the nested-radius correction, for one) reaches every
126
+ * settings page without this file changing at all. The rows themselves supply
127
+ * only the divider and the per-row padding — everything else about "a card
128
+ * with a header" was already solved.
129
+ */
130
+ export declare function SettingGroup({ title, description, titleAs, footer, className, children, }: SettingGroupProps): import("react").JSX.Element;
@@ -24,6 +24,21 @@ export interface DataTableProps<TData> {
24
24
  refreshing?: boolean;
25
25
  /** Skeleton row count while `loading`. */
26
26
  loadingRows?: number;
27
+ /**
28
+ * Rows per page. **Omit for no pagination** — that is the default and it is
29
+ * what every existing consumer already gets, unchanged.
30
+ *
31
+ * WHY OPT-IN RATHER THAN A DEFAULT PAGE SIZE: paginating a table nobody
32
+ * asked to paginate hides rows. A short table that suddenly grows a footer
33
+ * and a "1 of 3" is a worse regression than a long table, because the rows
34
+ * that vanished were on screen yesterday. So the caller says when the list
35
+ * is long enough to warrant it.
36
+ *
37
+ * The `Pagination` control this renders has existed in this library since
38
+ * long before `DataTable` did, as a fully independent component that was
39
+ * never connected to anything. This is that connection.
40
+ */
41
+ pageSize?: number;
27
42
  emptyState?: ReactNode;
28
43
  onRowClick?: (row: TData) => void;
29
44
  /** Rendered above the table; receives the table instance for counts/filters. */
@@ -31,7 +46,7 @@ export interface DataTableProps<TData> {
31
46
  className?: string;
32
47
  getRowId?: (row: TData, index: number) => string;
33
48
  }
34
- export declare function DataTable<TData>({ data, columns, density, selectable, maxHeight, zebra, loading, refreshing, loadingRows, emptyState, onRowClick, toolbar, className, getRowId, }: DataTableProps<TData>): import("react").JSX.Element;
49
+ export declare function DataTable<TData>({ data, columns, density, selectable, maxHeight, zebra, loading, refreshing, loadingRows, pageSize, emptyState, onRowClick, toolbar, className, getRowId, }: DataTableProps<TData>): import("react").JSX.Element;
35
50
  export declare function TableEmptyState({ icon, title, description, action, }: {
36
51
  icon?: ReactNode;
37
52
  title?: string;
@@ -21,6 +21,9 @@ export { Skeleton, SkeletonText, LoadingOverlay, type SkeletonProps, type Skelet
21
21
  export { ErrorBoundary } from "./components/ErrorBoundary";
22
22
  export { Field, FieldSet, type FieldProps, type FieldSetProps } from "./components/Field";
23
23
  export { Input, Textarea, type InputProps, type TextareaProps } from "./components/Input";
24
+ export { SecretField, type SecretFieldProps, type SecretValue } from "./components/SecretField";
25
+ export { SettingRow, SettingGroup, type SettingRowProps, type SettingGroupProps, type SettingRowControlRenderProps, } from "./components/SettingRow";
26
+ export { ConnectionCard, type ConnectionCardProps, type ConnectionHealth, } from "./components/ConnectionCard";
24
27
  export { Checkbox, Switch, Radio, RadioGroup, CheckboxField, SwitchField, RadioField, RadioCard, type CheckboxProps, type SwitchProps, type RadioProps, type RadioGroupProps, type CheckboxFieldProps, type SwitchFieldProps, type RadioFieldProps, type RadioCardProps, } from "./components/Choice";
25
28
  export { Dialog, DialogClose, AlertDialog, type DialogProps, type AlertDialogProps, } from "./components/Dialog";
26
29
  export { Popover, PopoverClose, Tooltip, TooltipProvider, type PopoverProps, type TooltipProps, } from "./components/Popover";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "3.5.2",
3
+ "version": "3.6.0",
4
4
  "type": "module",
5
5
  "description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
6
6
  "license": "MIT",