@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.
- package/dist/lib/base.css +48 -0
- package/dist/lib/components.css +2 -0
- package/dist/lib/fonts.css +28 -0
- package/dist/lib/icons.js +1 -0
- package/dist/lib/tokens.css +184 -0
- package/dist/lib/tokens.json +768 -0
- package/dist/lib/types/Accordion.d.ts +47 -0
- package/dist/lib/types/Avatar.d.ts +94 -0
- package/dist/lib/types/BrandMark.d.ts +25 -0
- package/dist/lib/types/Breadcrumb.d.ts +66 -0
- package/dist/lib/types/Button.d.ts +86 -0
- package/dist/lib/types/Card.d.ts +145 -0
- package/dist/lib/types/ChartBar.d.ts +51 -0
- package/dist/lib/types/ChartLine.d.ts +54 -0
- package/dist/lib/types/Checkbox.d.ts +132 -0
- package/dist/lib/types/Chip.d.ts +85 -0
- package/dist/lib/types/CliOnboard.d.ts +68 -0
- package/dist/lib/types/CommandPalette.d.ts +6 -0
- package/dist/lib/types/CommitGraph.d.ts +71 -0
- package/dist/lib/types/ConnectionState.d.ts +82 -0
- package/dist/lib/types/ConsentDialog.d.ts +97 -0
- package/dist/lib/types/DataTable.d.ts +116 -0
- package/dist/lib/types/DateRange.d.ts +242 -0
- package/dist/lib/types/Dialog.d.ts +9 -0
- package/dist/lib/types/DiffView.d.ts +39 -0
- package/dist/lib/types/EmptyState.d.ts +28 -0
- package/dist/lib/types/EvidenceCaption.d.ts +39 -0
- package/dist/lib/types/Explainer.d.ts +82 -0
- package/dist/lib/types/FacetRail.d.ts +13 -0
- package/dist/lib/types/Feedback.d.ts +222 -0
- package/dist/lib/types/GroupedMultiSelect.d.ts +67 -0
- package/dist/lib/types/Input.d.ts +158 -0
- package/dist/lib/types/Intensity.d.ts +55 -0
- package/dist/lib/types/MapCanvas.d.ts +89 -0
- package/dist/lib/types/Menu.d.ts +62 -0
- package/dist/lib/types/ModerationQueue.d.ts +135 -0
- package/dist/lib/types/Pager.d.ts +47 -0
- package/dist/lib/types/Pagination.d.ts +50 -0
- package/dist/lib/types/PolicySelect.d.ts +80 -0
- package/dist/lib/types/ProviderIcon.d.ts +84 -0
- package/dist/lib/types/RailShell.d.ts +199 -0
- package/dist/lib/types/Redaction.d.ts +53 -0
- package/dist/lib/types/RoleRoster.d.ts +97 -0
- package/dist/lib/types/SignIn.d.ts +78 -0
- package/dist/lib/types/Sparkline.d.ts +19 -0
- package/dist/lib/types/StatTiles.d.ts +118 -0
- package/dist/lib/types/StepWizard.d.ts +92 -0
- package/dist/lib/types/StepsWaterfall.d.ts +67 -0
- package/dist/lib/types/Switch.d.ts +63 -0
- package/dist/lib/types/Tabs.d.ts +48 -0
- package/dist/lib/types/TimeStrip.d.ts +12 -0
- package/dist/lib/types/Timeline.d.ts +192 -0
- package/dist/lib/types/ToastHost.d.ts +70 -0
- package/dist/lib/types/ToolRenderers.d.ts +24 -0
- package/dist/lib/types/Tooltip.d.ts +80 -0
- package/dist/lib/types/Tour.d.ts +37 -0
- package/dist/lib/types/TranscriptMarkers.d.ts +50 -0
- package/dist/lib/types/Treemap.d.ts +77 -0
- package/dist/lib/types/VisibilityControl.d.ts +54 -0
- package/dist/lib/types/chart-shared.d.ts +63 -0
- package/dist/lib/types/icons.d.ts +1 -0
- package/dist/lib/types/index.d.ts +53 -0
- package/dist/lib/ui.js +8736 -0
- 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,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;
|