@peasant-labs/fairtrade 0.0.1 → 0.0.2

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.
Files changed (64) hide show
  1. package/dist/lib/base.css +48 -0
  2. package/dist/lib/components.css +2 -0
  3. package/dist/lib/fonts.css +28 -0
  4. package/dist/lib/icons.js +1 -0
  5. package/dist/lib/tokens.css +184 -0
  6. package/dist/lib/tokens.json +768 -0
  7. package/dist/lib/types/Accordion.d.ts +47 -0
  8. package/dist/lib/types/Avatar.d.ts +94 -0
  9. package/dist/lib/types/BrandMark.d.ts +25 -0
  10. package/dist/lib/types/Breadcrumb.d.ts +66 -0
  11. package/dist/lib/types/Button.d.ts +86 -0
  12. package/dist/lib/types/Card.d.ts +145 -0
  13. package/dist/lib/types/ChartBar.d.ts +51 -0
  14. package/dist/lib/types/ChartLine.d.ts +54 -0
  15. package/dist/lib/types/Checkbox.d.ts +132 -0
  16. package/dist/lib/types/Chip.d.ts +85 -0
  17. package/dist/lib/types/CliOnboard.d.ts +68 -0
  18. package/dist/lib/types/CommandPalette.d.ts +6 -0
  19. package/dist/lib/types/CommitGraph.d.ts +71 -0
  20. package/dist/lib/types/ConnectionState.d.ts +82 -0
  21. package/dist/lib/types/ConsentDialog.d.ts +97 -0
  22. package/dist/lib/types/DataTable.d.ts +116 -0
  23. package/dist/lib/types/DateRange.d.ts +242 -0
  24. package/dist/lib/types/Dialog.d.ts +9 -0
  25. package/dist/lib/types/DiffView.d.ts +39 -0
  26. package/dist/lib/types/EmptyState.d.ts +28 -0
  27. package/dist/lib/types/EvidenceCaption.d.ts +39 -0
  28. package/dist/lib/types/Explainer.d.ts +82 -0
  29. package/dist/lib/types/FacetRail.d.ts +13 -0
  30. package/dist/lib/types/Feedback.d.ts +222 -0
  31. package/dist/lib/types/GroupedMultiSelect.d.ts +67 -0
  32. package/dist/lib/types/Input.d.ts +158 -0
  33. package/dist/lib/types/Intensity.d.ts +55 -0
  34. package/dist/lib/types/MapCanvas.d.ts +89 -0
  35. package/dist/lib/types/Menu.d.ts +62 -0
  36. package/dist/lib/types/ModerationQueue.d.ts +135 -0
  37. package/dist/lib/types/Pager.d.ts +47 -0
  38. package/dist/lib/types/Pagination.d.ts +50 -0
  39. package/dist/lib/types/PolicySelect.d.ts +80 -0
  40. package/dist/lib/types/ProviderIcon.d.ts +84 -0
  41. package/dist/lib/types/RailShell.d.ts +199 -0
  42. package/dist/lib/types/Redaction.d.ts +53 -0
  43. package/dist/lib/types/RoleRoster.d.ts +97 -0
  44. package/dist/lib/types/SignIn.d.ts +78 -0
  45. package/dist/lib/types/Sparkline.d.ts +19 -0
  46. package/dist/lib/types/StatTiles.d.ts +118 -0
  47. package/dist/lib/types/StepWizard.d.ts +92 -0
  48. package/dist/lib/types/StepsWaterfall.d.ts +67 -0
  49. package/dist/lib/types/Switch.d.ts +63 -0
  50. package/dist/lib/types/Tabs.d.ts +48 -0
  51. package/dist/lib/types/TimeStrip.d.ts +12 -0
  52. package/dist/lib/types/Timeline.d.ts +192 -0
  53. package/dist/lib/types/ToastHost.d.ts +70 -0
  54. package/dist/lib/types/ToolRenderers.d.ts +24 -0
  55. package/dist/lib/types/Tooltip.d.ts +80 -0
  56. package/dist/lib/types/Tour.d.ts +37 -0
  57. package/dist/lib/types/TranscriptMarkers.d.ts +50 -0
  58. package/dist/lib/types/Treemap.d.ts +77 -0
  59. package/dist/lib/types/VisibilityControl.d.ts +54 -0
  60. package/dist/lib/types/chart-shared.d.ts +63 -0
  61. package/dist/lib/types/icons.d.ts +1 -0
  62. package/dist/lib/types/index.d.ts +53 -0
  63. package/dist/lib/ui.js +8736 -0
  64. package/package.json +6 -5
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @typedef {Object} CheckboxProps
3
+ * @property {boolean} [checked] controlled checked state (pair with onChange)
4
+ * @property {boolean} [defaultChecked] initial state for uncontrolled use (default false)
5
+ * @property {(checked: boolean, event: import('react').ChangeEvent<HTMLInputElement>) => void} [onChange]
6
+ * @property {boolean} [disabled] native disabled attribute (default false)
7
+ * @property {import('react').ReactNode} [children] label text (rendered as passed, not lowercased)
8
+ */
9
+ /**
10
+ * A single checkbox: <label class="check"> wrapping the styled <input type="checkbox" class="check-box">.
11
+ * @param {CheckboxProps & import('react').InputHTMLAttributes<HTMLInputElement>} props
12
+ */
13
+ export default function Checkbox({ checked, defaultChecked, onChange, disabled, children, ...rest }: CheckboxProps & any): any;
14
+ /**
15
+ * @typedef {Object} RadioProps
16
+ * @property {string} name shared group name; radios must come in groups of >=2 so any one
17
+ * can be deselected by picking another. for a lone binary choice
18
+ * use Checkbox or Switch, never a single standalone Radio.
19
+ * @property {string} [value] the value submitted / matched when this radio is selected
20
+ * @property {boolean} [checked] controlled checked state (pair with onChange)
21
+ * @property {boolean} [defaultChecked] initial state for uncontrolled use (default false)
22
+ * @property {(event: import('react').ChangeEvent<HTMLInputElement>) => void} [onChange]
23
+ * @property {boolean} [disabled] native disabled attribute (default false)
24
+ * @property {import('react').ReactNode} [children] label text (rendered as passed, not lowercased)
25
+ */
26
+ /**
27
+ * A single radio: <label class="is-radio"> wrapping the styled <input type="radio" class="is-radio-dot">.
28
+ * Always render via RadioGroup (or at least two sibling radios sharing `name`) so a selection can be
29
+ * changed; a lone radio cannot be deselected, which is an accessibility anti-pattern. For a single
30
+ * binary choice use Checkbox or Switch instead.
31
+ * @param {RadioProps & import('react').InputHTMLAttributes<HTMLInputElement>} props
32
+ */
33
+ export function Radio({ name, value, checked, defaultChecked, onChange, disabled, children, ...rest }: RadioProps & any): any;
34
+ /**
35
+ * @typedef {Object} RadioOption
36
+ * @property {string} value
37
+ * @property {import('react').ReactNode} label
38
+ * @property {boolean} [disabled]
39
+ */
40
+ /**
41
+ * @typedef {Object} RadioGroupProps
42
+ * @property {string} name shared name for every radio in the group (required for single-select)
43
+ * @property {string} [value] controlled selected value (pair with onChange)
44
+ * @property {string} [defaultValue] initial selected value for uncontrolled use
45
+ * @property {(value: string, event: import('react').ChangeEvent<HTMLInputElement>) => void} [onChange]
46
+ * @property {RadioOption[]} options the choices to render
47
+ * @property {string} ariaLabel accessible name for the role=radiogroup container; required for
48
+ * an accessible group (a radiogroup with no name is an a11y failure)
49
+ */
50
+ /**
51
+ * A group of radios: <div class="is-radios" role="radiogroup"> of <label class="is-radio"> rows.
52
+ * Only one option is selectable because every input shares `name`.
53
+ * @param {RadioGroupProps & import('react').HTMLAttributes<HTMLDivElement>} props
54
+ */
55
+ export function RadioGroup({ name, value, defaultValue, onChange, options, ariaLabel, ...rest }: RadioGroupProps & any): any;
56
+ export type CheckboxProps = {
57
+ /**
58
+ * controlled checked state (pair with onChange)
59
+ */
60
+ checked?: boolean;
61
+ /**
62
+ * initial state for uncontrolled use (default false)
63
+ */
64
+ defaultChecked?: boolean;
65
+ onChange?: (checked: boolean, event: any) => void;
66
+ /**
67
+ * native disabled attribute (default false)
68
+ */
69
+ disabled?: boolean;
70
+ /**
71
+ * label text (rendered as passed, not lowercased)
72
+ */
73
+ children?: any;
74
+ };
75
+ export type RadioProps = {
76
+ /**
77
+ * shared group name; radios must come in groups of >=2 so any one
78
+ * can be deselected by picking another. for a lone binary choice
79
+ * use Checkbox or Switch, never a single standalone Radio.
80
+ */
81
+ name: string;
82
+ /**
83
+ * the value submitted / matched when this radio is selected
84
+ */
85
+ value?: string;
86
+ /**
87
+ * controlled checked state (pair with onChange)
88
+ */
89
+ checked?: boolean;
90
+ /**
91
+ * initial state for uncontrolled use (default false)
92
+ */
93
+ defaultChecked?: boolean;
94
+ onChange?: (event: any) => void;
95
+ /**
96
+ * native disabled attribute (default false)
97
+ */
98
+ disabled?: boolean;
99
+ /**
100
+ * label text (rendered as passed, not lowercased)
101
+ */
102
+ children?: any;
103
+ };
104
+ export type RadioOption = {
105
+ value: string;
106
+ label: any;
107
+ disabled?: boolean;
108
+ };
109
+ export type RadioGroupProps = {
110
+ /**
111
+ * shared name for every radio in the group (required for single-select)
112
+ */
113
+ name: string;
114
+ /**
115
+ * controlled selected value (pair with onChange)
116
+ */
117
+ value?: string;
118
+ /**
119
+ * initial selected value for uncontrolled use
120
+ */
121
+ defaultValue?: string;
122
+ onChange?: (value: string, event: any) => void;
123
+ /**
124
+ * the choices to render
125
+ */
126
+ options: RadioOption[];
127
+ /**
128
+ * accessible name for the role=radiogroup container; required for
129
+ * an accessible group (a radiogroup with no name is an a11y failure)
130
+ */
131
+ ariaLabel: string;
132
+ };
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @typedef {'ok'|'warn'|'err'} ChipTone
3
+ * @typedef {'sm'} ChipSize
4
+ */
5
+ /**
6
+ * a static chip: an icon names the thing, a short label confirms it, color reinforces. wraps
7
+ * `<span class="chip">` with the parametric tone / size modifiers and an optional real x-button.
8
+ * @param {object} props
9
+ * @param {ChipTone} [props.tone] - semantic tone -> .chip-ok / .chip-warn / .chip-err (default: none)
10
+ * @param {ChipSize} [props.size] - 'sm' -> .chip-sm dense box (default: none)
11
+ * @param {string} [props.brand] - a provider/company name (claude, gemini, openai, cursor, opencode, or an alias).
12
+ * When the chip names a company, pass this instead of `icon`: it leads with the real brand mark, never a generic glyph. (ignored when not resolvable)
13
+ * @param {React.ElementType} [props.icon] - leading lucide icon component ref (e.g. icon={Hash}) (ignored when `brand` is set)
14
+ * @param {boolean} [props.chrome=false] - mark this as a ui-chrome chip -> lowercases the label. Leave off for user content (ids, names, data values).
15
+ * @param {boolean} [props.removable=false] - render a real .chipx-x button with an X icon
16
+ * @param {() => void} [props.onRemove] - called when the x-button is clicked
17
+ * @param {string} [props.removeLabel] - aria-label for the x-button (default: `remove ${children}`; effectively required when children is not a plain string)
18
+ * @param {string} [props.className] - extra classes appended after the chip classes
19
+ * @param {React.ReactNode} props.children - the chip label / content (not force-lowercased unless chrome)
20
+ */
21
+ export default function Chip({ tone, size, brand, icon: Icon, chrome, removable, onRemove, removeLabel, className, children, ...rest }: {
22
+ tone?: ChipTone;
23
+ size?: ChipSize;
24
+ brand?: string;
25
+ icon?: React.ElementType;
26
+ chrome?: boolean;
27
+ removable?: boolean;
28
+ onRemove?: () => void;
29
+ removeLabel?: string;
30
+ className?: string;
31
+ children: React.ReactNode;
32
+ }): any;
33
+ /**
34
+ * a filter / toggle chip: a real `<button class="chip chip-toggle" aria-pressed>`. selected shows a
35
+ * leading check (.chipx-tick, revealed by css) and an amber fill; the css carries the rest. supports
36
+ * controlled (pressed + onChange) and uncontrolled (defaultPressed) use.
37
+ * @param {object} props
38
+ * @param {boolean} [props.pressed] - controlled pressed state
39
+ * @param {boolean} [props.defaultPressed=false] - initial pressed state when uncontrolled
40
+ * @param {(next: boolean) => void} [props.onChange] - called with the next pressed state on click
41
+ * @param {string} [props.brand] - a provider/company name; leads with the real brand mark when NOT pressed (ignored when `icon` is wanted instead)
42
+ * @param {React.ElementType} [props.icon] - leading icon shown when NOT pressed (e.g. icon={Filter}) (ignored when `brand` is set)
43
+ * @param {string} [props.className] - extra classes appended after the chip classes
44
+ * @param {React.ReactNode} props.children - the toggle label (not force-lowercased)
45
+ */
46
+ export function FilterChip({ pressed, defaultPressed, onChange, brand, icon: Icon, className, children, ...rest }: {
47
+ pressed?: boolean;
48
+ defaultPressed?: boolean;
49
+ onChange?: (next: boolean) => void;
50
+ brand?: string;
51
+ icon?: React.ElementType;
52
+ className?: string;
53
+ children: React.ReactNode;
54
+ }): any;
55
+ /**
56
+ * a status dot ALWAYS paired with a label, so status never rides on color alone. renders the small
57
+ * filled .chipx-dot square (tinted via the --c color var) followed by the required label text.
58
+ * by default it ships inside a `.chip` chassis to match the specimen; pass bare to drop the wrapper.
59
+ * @param {object} props
60
+ * @param {string} props.label - the status word (required; names the state) — not force-lowercased
61
+ * @param {string} [props.color] - css color for the dot, written to style="--c:..." (default: token fallback)
62
+ * @param {boolean} [props.bare=false] - omit the surrounding .chip wrapper, render dot + label only
63
+ * @param {string} [props.className] - extra classes appended after the chip class (ignored when bare)
64
+ */
65
+ export function StatusDot({ label, color, bare, className, ...rest }: {
66
+ label: string;
67
+ color?: string;
68
+ bare?: boolean;
69
+ className?: string;
70
+ }): any;
71
+ /**
72
+ * a numeric notification count: a trailing pill of tabular digits (.chipx-count). neutral by default;
73
+ * .unread flips it to the scarce amber. tnum keeps digits tabular.
74
+ * @param {object} props
75
+ * @param {number|string} props.count - the value to display
76
+ * @param {boolean} [props.unread=false] - amber unread treatment -> .unread
77
+ * @param {string} [props.className] - extra classes appended after the count classes
78
+ */
79
+ export function CountBadge({ count, unread, className, ...rest }: {
80
+ count: number | string;
81
+ unread?: boolean;
82
+ className?: string;
83
+ }): any;
84
+ export type ChipTone = "ok" | "warn" | "err";
85
+ export type ChipSize = "sm";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * CommandBlock — a square `$ command` block: a mono command line with a leading dim `$`, and a copy
3
+ * button that flips to an olive check + the word "copied" for ~1.5s.
4
+ *
5
+ * @param {object} props
6
+ * @param {string} props.command - the literal shell command (case preserved — never lowercased).
7
+ * @param {string} [props.label] - an accessible name for the copy button; defaults to the command.
8
+ * @param {string} [props.className] - extra classes appended to the root.
9
+ */
10
+ export function CommandBlock({ command, label, className, ...rest }: {
11
+ command: string;
12
+ label?: string;
13
+ className?: string;
14
+ }): any;
15
+ /**
16
+ * @typedef {object} CliStep
17
+ * @property {string} title - the step heading (e.g. "install"). Chrome — rendered lowercase by CSS.
18
+ * @property {string} [body] - optional prose explaining the step (body font, case preserved).
19
+ * @property {string} [command] - optional shell command for the step, rendered as a CommandBlock.
20
+ */
21
+ /**
22
+ * CliSteps — a numbered step list: each step is a square amber-tinted number marker + a title + an
23
+ * optional body + an optional CommandBlock, with a connector line running between the markers.
24
+ *
25
+ * @param {object} props
26
+ * @param {CliStep[]} props.steps - the steps, in order; numbered from 1.
27
+ * @param {string} [props.label='getting started'] - accessible name for the list (lowercase chrome).
28
+ * @param {string} [props.className] - extra classes appended to the root.
29
+ */
30
+ export function CliSteps({ steps, label, className, ...rest }: {
31
+ steps: CliStep[];
32
+ label?: string;
33
+ className?: string;
34
+ }): any;
35
+ /**
36
+ * GettingStarted — a dismissible card wrapping <CliSteps>: a header (title + close button) over the
37
+ * step list. Dismissing persists "dismissed" to localStorage under `storageKey`, so the card stays
38
+ * gone across reloads; when no key is given it dismisses for the session only.
39
+ *
40
+ * @param {object} props
41
+ * @param {string} [props.title='getting started'] - the card heading (lowercase chrome).
42
+ * @param {CliStep[]} props.steps - the onboarding steps, passed through to CliSteps.
43
+ * @param {string} [props.storageKey] - localStorage key the dismissed flag persists under.
44
+ * @param {() => void} [props.onDismiss] - called after the card is dismissed.
45
+ * @param {string} [props.className] - extra classes appended to the root.
46
+ */
47
+ export function GettingStarted({ title, steps, storageKey, onDismiss, className, ...rest }: {
48
+ title?: string;
49
+ steps: CliStep[];
50
+ storageKey?: string;
51
+ onDismiss?: () => void;
52
+ className?: string;
53
+ }): any;
54
+ export default CliSteps;
55
+ export type CliStep = {
56
+ /**
57
+ * - the step heading (e.g. "install"). Chrome — rendered lowercase by CSS.
58
+ */
59
+ title: string;
60
+ /**
61
+ * - optional prose explaining the step (body font, case preserved).
62
+ */
63
+ body?: string;
64
+ /**
65
+ * - optional shell command for the step, rendered as a CommandBlock.
66
+ */
67
+ command?: string;
68
+ };
@@ -0,0 +1,6 @@
1
+ export default function CommandPalette({ open, onClose, onTheme, sections }: {
2
+ open: any;
3
+ onClose: any;
4
+ onTheme: any;
5
+ sections: any;
6
+ }): any;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @typedef {object} Commit
3
+ * @property {string} id - stable key (e.g. short hash)
4
+ * @property {number} lane - 0 = main line; >0 = a branch lane
5
+ * @property {string[]} [parents] - parent commit ids (>1 = a merge commit)
6
+ * @property {string} message - the commit subject (USER CONTENT — case preserved)
7
+ * @property {string} [branch] - branch name for the chip (USER CONTENT — case preserved)
8
+ * @property {boolean} [session] - a recorded AI session sits behind this commit (-> filled + sparkle)
9
+ * @property {boolean} [merged] - this commit merged a branch back in (-> merged chip)
10
+ * @property {boolean} [tip] - this commit is a branch tip (-> small tip affordance)
11
+ * @property {string} [time] - relative time label (e.g. "8m ago") — already humanised by the caller
12
+ */
13
+ /**
14
+ * CommitGraph — render `commits` (newest first) as a lane gutter + a column of selectable rows.
15
+ *
16
+ * @param {object} props
17
+ * @param {Commit[]} props.commits - the history, newest first; lane 0 is the main line.
18
+ * @param {string} [props.selectedId] - id of the active/selected row (the scarce amber treatment).
19
+ * @param {(commit: Commit) => void} [props.onSelect] - called with the commit when a row is chosen.
20
+ * @param {boolean} [props.hasMore=false] - more history exists below the window -> show the "show older" ghost.
21
+ * @param {() => void} [props.onShowOlder] - called when "show older" is pressed.
22
+ * @param {string} [props.label='commit history'] - accessible name for the list (lowercase chrome).
23
+ * @param {string} [props.className] - extra classes appended to the root.
24
+ */
25
+ export default function CommitGraph({ commits, selectedId, onSelect, hasMore, onShowOlder, label, className, ...rest }: {
26
+ commits: Commit[];
27
+ selectedId?: string;
28
+ onSelect?: (commit: Commit) => void;
29
+ hasMore?: boolean;
30
+ onShowOlder?: () => void;
31
+ label?: string;
32
+ className?: string;
33
+ }): any;
34
+ export type Commit = {
35
+ /**
36
+ * - stable key (e.g. short hash)
37
+ */
38
+ id: string;
39
+ /**
40
+ * - 0 = main line; >0 = a branch lane
41
+ */
42
+ lane: number;
43
+ /**
44
+ * - parent commit ids (>1 = a merge commit)
45
+ */
46
+ parents?: string[];
47
+ /**
48
+ * - the commit subject (USER CONTENT — case preserved)
49
+ */
50
+ message: string;
51
+ /**
52
+ * - branch name for the chip (USER CONTENT — case preserved)
53
+ */
54
+ branch?: string;
55
+ /**
56
+ * - a recorded AI session sits behind this commit (-> filled + sparkle)
57
+ */
58
+ session?: boolean;
59
+ /**
60
+ * - this commit merged a branch back in (-> merged chip)
61
+ */
62
+ merged?: boolean;
63
+ /**
64
+ * - this commit is a branch tip (-> small tip affordance)
65
+ */
66
+ tip?: boolean;
67
+ /**
68
+ * - relative time label (e.g. "8m ago") — already humanised by the caller
69
+ */
70
+ time?: string;
71
+ };
@@ -0,0 +1,82 @@
1
+ /**
2
+ * ConnectionPill — the small, glanceable connection indicator. a square hairline pill carrying an
3
+ * icon and the word; the note ("on this computer · no internet") sits beside it as quiet mono
4
+ * chrome. the state never rides on color alone: the icon and the word both encode it (no status
5
+ * dot — a color-only dot would break that rule), and the whole pill is announced via role=status.
6
+ * the per-tone icon color is a tint on top, only where color is welcome.
7
+ *
8
+ * @param {object} props
9
+ * @param {'live'|'connecting'|'disconnected'} [props.status='live'] - the connection state.
10
+ * @param {boolean} [props.showNote=true] - render the trailing "on this computer · no internet"
11
+ * style note. set false for the tightest, word-only pill.
12
+ * @param {string} [props.className]
13
+ */
14
+ export function ConnectionPill({ status, showNote, className, ...rest }: {
15
+ status?: "live" | "connecting" | "disconnected";
16
+ showNote?: boolean;
17
+ className?: string;
18
+ }): any;
19
+ /**
20
+ * DataState — the discriminator between the states a data view can be in, so a dropped connection
21
+ * never reads as "empty". precedence is deliberate:
22
+ *
23
+ * loading → a skeleton (don't show "empty" before the answer is in).
24
+ * disconnected || error → the calm lost-connection panel + retry (the key rule:
25
+ * disconnected != empty — a lost socket is not zero results).
26
+ * empty → the teaching `empty` slot (connected, but genuinely nothing here).
27
+ * else → children (the real content).
28
+ *
29
+ * @param {object} props
30
+ * @param {'live'|'connecting'|'disconnected'} [props.status] - the live connection status. when
31
+ * 'disconnected', the lost-connection panel wins over `empty` even if `empty` is provided.
32
+ * @param {boolean} [props.loading] - data is in flight; show the skeleton.
33
+ * @param {boolean|string} [props.error] - an error occurred; truthy shows the lost-connection
34
+ * panel. a string overrides the panel body.
35
+ * @param {boolean} [props.empty] - connected, request resolved, but there is nothing to show.
36
+ * @param {import('react').ReactNode} [props.children] - the real content, shown when none of the
37
+ * above apply.
38
+ * @param {import('react').ReactNode} [props.emptyState] - the teaching empty slot (e.g. a
39
+ * <TeachingEmptyState/>), rendered when `empty` is true.
40
+ * @param {() => void} [props.onRetry] - retry handler for the lost-connection panel.
41
+ * @param {number} [props.skeletonRows=3] - how many skeleton bars to show while loading.
42
+ * @param {string} [props.className]
43
+ */
44
+ export function DataState({ status, loading, error, empty, children, emptyState, onRetry, skeletonRows, className, ...rest }: {
45
+ status?: "live" | "connecting" | "disconnected";
46
+ loading?: boolean;
47
+ error?: boolean | string;
48
+ empty?: boolean;
49
+ children?: any;
50
+ emptyState?: any;
51
+ onRetry?: () => void;
52
+ skeletonRows?: number;
53
+ className?: string;
54
+ }): any;
55
+ /**
56
+ * TeachingEmptyState — an empty state that TEACHES the mechanism instead of just declaring the
57
+ * absence. a leading icon, a title, a line of guidance, and a copy-able `$ command` chip (the
58
+ * actual command to run, e.g. `peasant ingest`) with an inline copy button — then a short privacy
59
+ * line, because the whole point is that this runs locally and nothing leaves the machine.
60
+ *
61
+ * @param {object} props
62
+ * @param {import('react').ComponentType} [props.icon=HardDrive] - lucide icon for the heading.
63
+ * @param {import('react').ReactNode} props.title - the short headline.
64
+ * @param {import('react').ReactNode} [props.body] - a line of guidance prose (what the command
65
+ * does, in plain words).
66
+ * @param {string} [props.command] - the command to teach, shown in a `$`-prefixed mono chip with a
67
+ * copy button. the `$` is decoration; only the command itself is copied.
68
+ * @param {import('react').ReactNode} [props.privacy] - the privacy line. defaults to "nothing
69
+ * leaves your machine". pass null to omit.
70
+ * @param {keyof JSX.IntrinsicElements} [props.as='h3'] - heading level for the title.
71
+ * @param {string} [props.className]
72
+ */
73
+ export function TeachingEmptyState({ icon: Icon, title, body, command, privacy, as: Heading, className, ...rest }: {
74
+ icon?: any;
75
+ title: any;
76
+ body?: any;
77
+ command?: string;
78
+ privacy?: any;
79
+ as?: keyof JSX.IntrinsicElements;
80
+ className?: string;
81
+ }): any;
82
+ export default ConnectionPill;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @typedef {Object} ConsentAxis
3
+ * @property {React.ElementType} [icon] lucide component for the row (rendered in a square chip)
4
+ * @property {string} key the mono, lowercase axis label (e.g. "identity", "data access")
5
+ * @property {React.ReactNode} value the chosen value — may contain user content (NOT lowercased)
6
+ * @property {React.ReactNode} [scope] optional "who can see / what changes" note shown under the value
7
+ * @property {'reveal'|'open'|'restricted'} [tone] colors the icon chip: reveal=amber, open=teal, restricted=clay
8
+ */
9
+ /**
10
+ * ConsentSummary — the reusable axes block. an aligned grid of rows, each an icon
11
+ * chip + a mono key + the value (+ an optional scope note). this is the seed that
12
+ * already lived in the join dialog; here it is generalized so every governance
13
+ * dialog renders the same legible "here is what is at stake" panel.
14
+ *
15
+ * @param {Object} props
16
+ * @param {ConsentAxis[]} props.axes the rows to render
17
+ * @param {string} [props.caption] optional mono eyebrow above the rows
18
+ * @param {string} [props.className] extra classes appended after .cns-summary
19
+ */
20
+ export function ConsentSummary({ axes, caption, className, ...rest }: {
21
+ axes: ConsentAxis[];
22
+ caption?: string;
23
+ className?: string;
24
+ }): any;
25
+ /**
26
+ * ConsentDialog — a scrim + bordered modal that frames a governance decision.
27
+ * structure: head (mono lowercase title + close) / body (intro prose, a
28
+ * <ConsentSummary>, an optional "i understand and consent" checkbox, optional
29
+ * extra children rendered after the summary) / foot (cancel secondary + the
30
+ * primary confirm in amber). when `requireConsent`, the primary stays disabled
31
+ * until the checkbox is ticked, so the irreversible action never rides on a
32
+ * single reflexive click.
33
+ *
34
+ * controlled by `open` + `onCancel`. focus is trapped while open; Escape and a
35
+ * scrim click cancel; focus returns to whatever was focused when it opened (or
36
+ * `returnFocusRef` if given); background scroll is locked.
37
+ *
38
+ * @param {Object} props
39
+ * @param {boolean} props.open whether the dialog is mounted/visible
40
+ * @param {React.ReactNode} props.title the mono lowercase head title (may embed a .cns-name)
41
+ * @param {React.ReactNode} [props.intro] reading-prose lede above the summary
42
+ * @param {ConsentAxis[]} [props.axes] axes for the embedded <ConsentSummary>
43
+ * @param {string} [props.summaryCaption] eyebrow above the summary rows
44
+ * @param {React.ReactNode} [props.children] extra content rendered after the summary (e.g. a retention choice)
45
+ * @param {string} [props.confirmLabel='confirm'] primary button label (mono lowercase)
46
+ * @param {React.ElementType} [props.confirmIcon] lucide icon for the primary button
47
+ * @param {string} [props.cancelLabel='cancel'] secondary button label
48
+ * @param {() => void} props.onCancel called on cancel / esc / scrim / close
49
+ * @param {() => void} props.onConfirm called when the (enabled) primary is pressed
50
+ * @param {boolean} [props.requireConsent=true] gate the primary behind the consent checkbox
51
+ * @param {React.ReactNode} [props.consentLabel] the checkbox label (default "i understand and consent")
52
+ * @param {'primary'|'danger'} [props.tone='primary'] primary button treatment (danger for leave/retract)
53
+ * @param {boolean} [props.busy=false] disables controls + shows the primary as busy
54
+ * @param {string} [props.labelId='cns-title'] id wiring aria-labelledby (unique it if two can co-exist)
55
+ * @param {React.RefObject<HTMLElement>} [props.returnFocusRef] where to send focus on close
56
+ */
57
+ export default function ConsentDialog({ open, title, intro, axes, summaryCaption, children, confirmLabel, confirmIcon: ConfirmIcon, cancelLabel, onCancel, onConfirm, requireConsent, consentLabel, tone, busy, labelId, returnFocusRef, }: {
58
+ open: boolean;
59
+ title: React.ReactNode;
60
+ intro?: React.ReactNode;
61
+ axes?: ConsentAxis[];
62
+ summaryCaption?: string;
63
+ children?: React.ReactNode;
64
+ confirmLabel?: string;
65
+ confirmIcon?: React.ElementType;
66
+ cancelLabel?: string;
67
+ onCancel: () => void;
68
+ onConfirm: () => void;
69
+ requireConsent?: boolean;
70
+ consentLabel?: React.ReactNode;
71
+ tone?: "primary" | "danger";
72
+ busy?: boolean;
73
+ labelId?: string;
74
+ returnFocusRef?: React.RefObject<HTMLElement>;
75
+ }): any;
76
+ export type ConsentAxis = {
77
+ /**
78
+ * lucide component for the row (rendered in a square chip)
79
+ */
80
+ icon?: React.ElementType;
81
+ /**
82
+ * the mono, lowercase axis label (e.g. "identity", "data access")
83
+ */
84
+ key: string;
85
+ /**
86
+ * the chosen value — may contain user content (NOT lowercased)
87
+ */
88
+ value: React.ReactNode;
89
+ /**
90
+ * optional "who can see / what changes" note shown under the value
91
+ */
92
+ scope?: React.ReactNode;
93
+ /**
94
+ * colors the icon chip: reveal=amber, open=teal, restricted=clay
95
+ */
96
+ tone?: "reveal" | "open" | "restricted";
97
+ };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * a sortable + selectable data table. square, hairline, mono headers; both themes
3
+ * via tokens. sort + selection state/logic are powered by TanStack Table
4
+ * (@tanstack/react-table, headless) while this component still renders its own markup
5
+ * + token classes, so the look is unchanged and growth (filtering, pagination, column
6
+ * sizing/visibility) is a config away. sorting cycles none -> asc -> desc -> none on a
7
+ * sortable header (a real <button>, so it is keyboard-operable), exposes aria-sort on the
8
+ * <th>, and shows a lucide chevron indicator. selection reuses the existing .check-box control:
9
+ * a header checkbox selects/clears all (with an indeterminate middle state) and
10
+ * each row carries its own. selected rows get a subtle highlight.
11
+ *
12
+ * sort + selection are each independently controlled OR uncontrolled:
13
+ * - sort: pass `sort` + `onSortChange` to control; otherwise `defaultSort` seeds it.
14
+ * - selection: pass `selectedKeys` + `onSelectionChange` to control; otherwise
15
+ * `defaultSelectedKeys` seeds it.
16
+ *
17
+ * @typedef {Object} DataTableColumn
18
+ * @property {string} key object key this column reads from each row.
19
+ * @property {React.ReactNode} label header text (kept as passed; not forced-lowercase).
20
+ * @property {boolean} [sortable] when true the header sorts; default false.
21
+ * @property {'left'|'right'|'center'} [align] cell alignment; 'right' also gets tabular nums. default 'left'.
22
+ * @property {string} [width] optional fixed column width (any css length, e.g. '12rem'); emits a <colgroup> entry so columns stay put as cell content changes.
23
+ * @property {(value: any, row: Object) => React.ReactNode} [render] custom cell renderer; falls back to row[key].
24
+ *
25
+ * @typedef {{ key: string, dir: 'asc'|'desc' } | null} DataTableSort
26
+ *
27
+ * @param {Object} props
28
+ * @param {DataTableColumn[]} props.columns column definitions.
29
+ * @param {Object[]} props.rows row objects.
30
+ * @param {boolean} [props.selectable=false] render the selection column.
31
+ * @param {(row: Object, index: number) => (string|number)} [props.rowKey] stable key per row; defaults to row.id ?? index.
32
+ * @param {DataTableSort} [props.defaultSort=null] initial sort (uncontrolled).
33
+ * @param {DataTableSort} [props.sort] controlled sort.
34
+ * @param {(next: DataTableSort) => void} [props.onSortChange] called with the next sort state.
35
+ * @param {Array<string|number>} [props.defaultSelectedKeys=[]] initial selection (uncontrolled).
36
+ * @param {Array<string|number>} [props.selectedKeys] controlled selection.
37
+ * @param {(keys: Array<string|number>) => void} [props.onSelectionChange] called with the next selection.
38
+ * @param {string} [props.caption] accessible <caption> for the table (visually present, mono/quiet).
39
+ * @param {string} [props.className] extra class on the scroll wrapper.
40
+ */
41
+ export default function DataTable({ columns, rows, selectable, rowKey, defaultSort, sort: sortProp, onSortChange, defaultSelectedKeys, selectedKeys: selectedProp, onSelectionChange, caption, className, }: {
42
+ columns: DataTableColumn[];
43
+ rows: any[];
44
+ selectable?: boolean;
45
+ rowKey?: (row: any, index: number) => (string | number);
46
+ defaultSort?: DataTableSort;
47
+ sort?: DataTableSort;
48
+ onSortChange?: (next: DataTableSort) => void;
49
+ defaultSelectedKeys?: Array<string | number>;
50
+ selectedKeys?: Array<string | number>;
51
+ onSelectionChange?: (keys: Array<string | number>) => void;
52
+ caption?: string;
53
+ className?: string;
54
+ }): any;
55
+ /**
56
+ * a sortable + selectable data table. square, hairline, mono headers; both themes
57
+ * via tokens. sort + selection state/logic are powered by TanStack Table
58
+ * (@tanstack/react-table, headless) while this component still renders its own markup
59
+ * + token classes, so the look is unchanged and growth (filtering, pagination, column
60
+ * sizing/visibility) is a config away. sorting cycles none -> asc -> desc -> none on a
61
+ * sortable header (a real <button>, so it is keyboard-operable), exposes aria-sort on the
62
+ * <th>, and shows a lucide chevron indicator. selection reuses the existing .check-box control:
63
+ * a header checkbox selects/clears all (with an indeterminate middle state) and
64
+ * each row carries its own. selected rows get a subtle highlight.
65
+ *
66
+ * sort + selection are each independently controlled OR uncontrolled:
67
+ * - sort: pass `sort` + `onSortChange` to control; otherwise `defaultSort` seeds it.
68
+ * - selection: pass `selectedKeys` + `onSelectionChange` to control; otherwise
69
+ * `defaultSelectedKeys` seeds it.
70
+ */
71
+ export type DataTableColumn = {
72
+ /**
73
+ * object key this column reads from each row.
74
+ */
75
+ key: string;
76
+ /**
77
+ * header text (kept as passed; not forced-lowercase).
78
+ */
79
+ label: React.ReactNode;
80
+ /**
81
+ * when true the header sorts; default false.
82
+ */
83
+ sortable?: boolean;
84
+ /**
85
+ * cell alignment; 'right' also gets tabular nums. default 'left'.
86
+ */
87
+ align?: "left" | "right" | "center";
88
+ /**
89
+ * optional fixed column width (any css length, e.g. '12rem'); emits a <colgroup> entry so columns stay put as cell content changes.
90
+ */
91
+ width?: string;
92
+ /**
93
+ * custom cell renderer; falls back to row[key].
94
+ */
95
+ render?: (value: any, row: any) => React.ReactNode;
96
+ };
97
+ /**
98
+ * a sortable + selectable data table. square, hairline, mono headers; both themes
99
+ * via tokens. sort + selection state/logic are powered by TanStack Table
100
+ * (@tanstack/react-table, headless) while this component still renders its own markup
101
+ * + token classes, so the look is unchanged and growth (filtering, pagination, column
102
+ * sizing/visibility) is a config away. sorting cycles none -> asc -> desc -> none on a
103
+ * sortable header (a real <button>, so it is keyboard-operable), exposes aria-sort on the
104
+ * <th>, and shows a lucide chevron indicator. selection reuses the existing .check-box control:
105
+ * a header checkbox selects/clears all (with an indeterminate middle state) and
106
+ * each row carries its own. selected rows get a subtle highlight.
107
+ *
108
+ * sort + selection are each independently controlled OR uncontrolled:
109
+ * - sort: pass `sort` + `onSortChange` to control; otherwise `defaultSort` seeds it.
110
+ * - selection: pass `selectedKeys` + `onSelectionChange` to control; otherwise
111
+ * `defaultSelectedKeys` seeds it.
112
+ */
113
+ export type DataTableSort = {
114
+ key: string;
115
+ dir: "asc" | "desc";
116
+ } | null;