@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,80 @@
1
+ /**
2
+ * @typedef {Object} PolicyOption
3
+ * @property {string} value the value submitted / matched when selected.
4
+ * @property {import('react').ReactNode} label the bold option label (mono).
5
+ * @property {import('react').ReactNode} [rationale] one-line plain-prose explanation (body font).
6
+ * @property {boolean} [disabled] native disabled state for this option.
7
+ */
8
+ /**
9
+ * @typedef {Object} PolicySelectProps
10
+ * @property {import('react').ReactNode} label the field label above the control (mono, lowercase chrome).
11
+ * @property {string} name form name; the shared radio group name in the radio variant.
12
+ * @property {string} [value] controlled selected value; pair with onChange.
13
+ * @property {string} [defaultValue] initial value for uncontrolled use.
14
+ * @property {(value: string) => void} [onChange] called with the next value on selection.
15
+ * @property {PolicyOption[]} options the choices to render (each {value,label,rationale}).
16
+ * @property {'radio'|'select'} [variant='radio'] layout: a rationale-per-row radio group, or a native select.
17
+ * @property {import('react').ReactNode} [hint] optional one-line helper beneath the label.
18
+ * @property {string} [id] id for the control / radiogroup; auto-generated when omitted.
19
+ */
20
+ /**
21
+ * A governance policy selector. See PolicySelectProps.
22
+ * @param {PolicySelectProps} props
23
+ */
24
+ export default function PolicySelect({ label, name, value, defaultValue, onChange, options, variant, hint, id, }: PolicySelectProps): any;
25
+ export type PolicyOption = {
26
+ /**
27
+ * the value submitted / matched when selected.
28
+ */
29
+ value: string;
30
+ /**
31
+ * the bold option label (mono).
32
+ */
33
+ label: any;
34
+ /**
35
+ * one-line plain-prose explanation (body font).
36
+ */
37
+ rationale?: any;
38
+ /**
39
+ * native disabled state for this option.
40
+ */
41
+ disabled?: boolean;
42
+ };
43
+ export type PolicySelectProps = {
44
+ /**
45
+ * the field label above the control (mono, lowercase chrome).
46
+ */
47
+ label: any;
48
+ /**
49
+ * form name; the shared radio group name in the radio variant.
50
+ */
51
+ name: string;
52
+ /**
53
+ * controlled selected value; pair with onChange.
54
+ */
55
+ value?: string;
56
+ /**
57
+ * initial value for uncontrolled use.
58
+ */
59
+ defaultValue?: string;
60
+ /**
61
+ * called with the next value on selection.
62
+ */
63
+ onChange?: (value: string) => void;
64
+ /**
65
+ * the choices to render (each {value,label,rationale}).
66
+ */
67
+ options: PolicyOption[];
68
+ /**
69
+ * layout: a rationale-per-row radio group, or a native select.
70
+ */
71
+ variant?: "radio" | "select";
72
+ /**
73
+ * optional one-line helper beneath the label.
74
+ */
75
+ hint?: any;
76
+ /**
77
+ * id for the control / radiogroup; auto-generated when omitted.
78
+ */
79
+ id?: string;
80
+ };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * ProviderIcon — the real brand mark for a harness, single-color via currentColor.
3
+ *
4
+ * decorative by default (it is paired with a name in every composite below). pass
5
+ * `label` to make a STANDALONE mark informative (role="img" + the provider name).
6
+ * pass `accent` to tint the mark with its provider accent instead of inheriting
7
+ * the surrounding text color — but remember the accent is never the sole signal.
8
+ *
9
+ * @param {object} props
10
+ * @param {'claude-code'|'gemini-cli'|'codex'|'opencode'|'cursor'} props.harness
11
+ * @param {number} [props.size] explicit px; omit to inherit the contextual icon size.
12
+ * @param {boolean} [props.accent] tint with PROVIDER_ACCENT[harness] (default: currentColor).
13
+ * @param {boolean|string} [props.label] true → the provider name as aria-label; a string overrides.
14
+ * @param {string} [props.className] extra classes appended after `pv-icon`.
15
+ * @returns {JSX.Element|null} null when `harness` is unknown.
16
+ */
17
+ export function ProviderIcon({ harness, size, accent, label, className, ...rest }: {
18
+ harness: "claude-code" | "gemini-cli" | "codex" | "opencode" | "cursor";
19
+ size?: number;
20
+ accent?: boolean;
21
+ label?: boolean | string;
22
+ className?: string;
23
+ }): JSX.Element | null;
24
+ /**
25
+ * ProviderTag — a square hairline chip: the real mark + the lowercase harness slug.
26
+ *
27
+ * the system's chip look (mono, hairline border, radius 0, lowercase chrome). the
28
+ * mark sits to the left of the slug so the chip is never color-only: even fully
29
+ * monochrome it names the provider in words. pass `accent` to tint the mark.
30
+ *
31
+ * @param {object} props
32
+ * @param {'claude-code'|'gemini-cli'|'codex'|'opencode'|'cursor'} props.harness
33
+ * @param {boolean} [props.accent] tint the mark with the provider accent (default: ink).
34
+ * @param {string} [props.className]
35
+ * @returns {JSX.Element|null}
36
+ */
37
+ export function ProviderTag({ harness, accent, className, ...rest }: {
38
+ harness: "claude-code" | "gemini-cli" | "codex" | "opencode" | "cursor";
39
+ accent?: boolean;
40
+ className?: string;
41
+ }): JSX.Element | null;
42
+ /**
43
+ * ProviderName — mark + the harness slug as a plain inline label (no chip border).
44
+ *
45
+ * the in-prose form: use it inline in a sentence or a table cell. pass `accent` to
46
+ * tint BOTH the mark and the slug with the provider accent (the slug gets a
47
+ * non-color cue regardless — it is real text, so it is readable mono-color too).
48
+ *
49
+ * @param {object} props
50
+ * @param {'claude-code'|'gemini-cli'|'codex'|'opencode'|'cursor'} props.harness
51
+ * @param {boolean} [props.accent] tint mark + label with the provider accent.
52
+ * @param {string} [props.className]
53
+ * @returns {JSX.Element|null}
54
+ */
55
+ export function ProviderName({ harness, accent, className, ...rest }: {
56
+ harness: "claude-code" | "gemini-cli" | "codex" | "opencode" | "cursor";
57
+ accent?: boolean;
58
+ className?: string;
59
+ }): JSX.Element | null;
60
+ /**
61
+ * AccentLegend — the per-provider accent map, documented as a UI.
62
+ *
63
+ * one row per harness across four aligned columns: the real mark, the provider
64
+ * name, the accent swatch, then its token name written out. the swatch sits after
65
+ * the mark + name on purpose — they already identify the provider, so the legend
66
+ * reads correctly with the color stripped (the neuroinclusive rule made visible),
67
+ * and the swatch keeps its own column so the colors line up down the list.
68
+ *
69
+ * @param {object} props
70
+ * @param {string} [props.className]
71
+ * @returns {JSX.Element}
72
+ */
73
+ export function AccentLegend({ className, ...rest }: {
74
+ className?: string;
75
+ }): JSX.Element;
76
+ export const HARNESSES: string[];
77
+ export const PROVIDER_ACCENT: {
78
+ 'claude-code': string;
79
+ 'gemini-cli': string;
80
+ codex: string;
81
+ opencode: string;
82
+ cursor: string;
83
+ };
84
+ export default ProviderIcon;
@@ -0,0 +1,199 @@
1
+ /**
2
+ * @typedef {Object} RailShellProps
3
+ * @property {React.ReactNode} [toolbar] optional sticky top toolbar (mono chrome row); omitted when absent.
4
+ * @property {React.ReactNode} children the main content / canvas column (scrolls; min-width:0).
5
+ * @property {React.ReactNode} rail the rail contents — compose with <RailSection> children.
6
+ * @property {'left'|'right'} [railSide='right'] which side the desktop rail sits on.
7
+ * @property {string} [sheetTitle='details'] the bottom-sheet toggle label (mono, lowercased) on mobile.
8
+ * @property {React.ReactNode} [sheetMeta] quiet right-side content in the sheet header (e.g. a count).
9
+ * @property {string} [className] extra class on the root.
10
+ */
11
+ /**
12
+ * The shell frame: a two-column canvas + sticky-rail layout on desktop that collapses the rail into
13
+ * a fixed bottom-sheet below 880px. The main column scrolls and is min-width:0 so a wide canvas
14
+ * stays contained; the rail is a 320px sticky hairline card. The same `rail` content renders in both
15
+ * the desktop card and the mobile sheet, so avoid `id` attributes inside it. The sheet's expand /
16
+ * collapse is a button reporting aria-expanded and is wired to the sheet body via aria-controls.
17
+ */
18
+ export default function RailShell({ toolbar, children, rail, railSide, sheetTitle, sheetMeta, className, }: {
19
+ toolbar: any;
20
+ children: any;
21
+ rail: any;
22
+ railSide?: string;
23
+ sheetTitle?: string;
24
+ sheetMeta: any;
25
+ className?: string;
26
+ }): any;
27
+ /**
28
+ * @typedef {Object} RailSectionProps
29
+ * @property {React.ReactNode} [title] mono section header (lowercased by css).
30
+ * @property {React.ComponentType} [icon] optional lucide icon component shown before the title.
31
+ * @property {React.ReactNode} [meta] quiet right-aligned header content (a count, a glyph).
32
+ * @property {React.ReactNode} children the section body.
33
+ * @property {boolean} [collapsible=false] when true, the header is a button that toggles the body.
34
+ * @property {boolean} [defaultOpen=true] initial open state when collapsible.
35
+ * @property {string} [className] extra class on the section.
36
+ */
37
+ /**
38
+ * One titled hairline section inside a rail: a mono header (optional icon + title + meta) over a
39
+ * body. When `collapsible`, the header becomes a button reporting aria-expanded and wired to the
40
+ * body via aria-controls; the chevron rotates open. Sections divide from one another with the
41
+ * rail card's hairlines.
42
+ */
43
+ export function RailSection({ title, icon: Icon, meta, children, collapsible, defaultOpen, className, }: {
44
+ title: any;
45
+ icon: any;
46
+ meta: any;
47
+ children: any;
48
+ collapsible?: boolean;
49
+ defaultOpen?: boolean;
50
+ className?: string;
51
+ }): any;
52
+ /**
53
+ * @typedef {Object} SplitRailProps
54
+ * @property {React.ReactNode} left content of the left column (e.g. an outline tree).
55
+ * @property {React.ReactNode} right content of the right column (e.g. filters).
56
+ * @property {string} [leftTitle='outline'] left column header (mono, lowercased).
57
+ * @property {string} [rightTitle='filters'] right column header (mono, lowercased).
58
+ * @property {React.ComponentType} [leftIcon] optional lucide icon for the left header.
59
+ * @property {React.ComponentType} [rightIcon] optional lucide icon for the right header.
60
+ * @property {React.ReactNode} [leftMeta] quiet right-aligned content in the left header.
61
+ * @property {React.ReactNode} [rightMeta] quiet right-aligned content in the right header.
62
+ * @property {string} [className] extra class on the root.
63
+ */
64
+ /**
65
+ * The dual-rail variant: two independently-collapsible columns (outline-left / filters-right), each
66
+ * a hairline panel that collapses on its own. Side by side on desktop; stacks to a single column on
67
+ * mobile. Use as the `rail` of a RailShell, or standalone as a two-pane control surface.
68
+ */
69
+ export function SplitRail({ left, right, leftTitle, rightTitle, leftIcon, rightIcon, leftMeta, rightMeta, className, }: {
70
+ left: any;
71
+ right: any;
72
+ leftTitle?: string;
73
+ rightTitle?: string;
74
+ leftIcon: any;
75
+ rightIcon: any;
76
+ leftMeta: any;
77
+ rightMeta: any;
78
+ className?: string;
79
+ }): any;
80
+ export type RailShellProps = {
81
+ /**
82
+ * optional sticky top toolbar (mono chrome row); omitted when absent.
83
+ */
84
+ toolbar?: React.ReactNode;
85
+ /**
86
+ * the main content / canvas column (scrolls; min-width:0).
87
+ */
88
+ children: React.ReactNode;
89
+ /**
90
+ * the rail contents — compose with <RailSection> children.
91
+ */
92
+ rail: React.ReactNode;
93
+ /**
94
+ * which side the desktop rail sits on.
95
+ */
96
+ railSide?: "left" | "right";
97
+ /**
98
+ * the bottom-sheet toggle label (mono, lowercased) on mobile.
99
+ */
100
+ sheetTitle?: string;
101
+ /**
102
+ * quiet right-side content in the sheet header (e.g. a count).
103
+ */
104
+ sheetMeta?: React.ReactNode;
105
+ /**
106
+ * extra class on the root.
107
+ */
108
+ className?: string;
109
+ };
110
+ export type RailSectionProps = {
111
+ /**
112
+ * mono section header (lowercased by css).
113
+ */
114
+ title?: React.ReactNode;
115
+ /**
116
+ * optional lucide icon component shown before the title.
117
+ */
118
+ icon?: React.ComponentType;
119
+ /**
120
+ * quiet right-aligned header content (a count, a glyph).
121
+ */
122
+ meta?: React.ReactNode;
123
+ /**
124
+ * the section body.
125
+ */
126
+ children: React.ReactNode;
127
+ /**
128
+ * when true, the header is a button that toggles the body.
129
+ */
130
+ collapsible?: boolean;
131
+ /**
132
+ * initial open state when collapsible.
133
+ */
134
+ defaultOpen?: boolean;
135
+ /**
136
+ * extra class on the section.
137
+ */
138
+ className?: string;
139
+ };
140
+ export type SplitRailPanelProps = {
141
+ /**
142
+ * mono header for the column.
143
+ */
144
+ title?: React.ReactNode;
145
+ /**
146
+ * optional lucide icon before the title.
147
+ */
148
+ icon?: React.ComponentType;
149
+ /**
150
+ * quiet right-aligned header content.
151
+ */
152
+ meta?: React.ReactNode;
153
+ /**
154
+ * the column body.
155
+ */
156
+ children: React.ReactNode;
157
+ /**
158
+ * initial open state (each column collapses independently).
159
+ */
160
+ defaultOpen?: boolean;
161
+ };
162
+ export type SplitRailProps = {
163
+ /**
164
+ * content of the left column (e.g. an outline tree).
165
+ */
166
+ left: React.ReactNode;
167
+ /**
168
+ * content of the right column (e.g. filters).
169
+ */
170
+ right: React.ReactNode;
171
+ /**
172
+ * left column header (mono, lowercased).
173
+ */
174
+ leftTitle?: string;
175
+ /**
176
+ * right column header (mono, lowercased).
177
+ */
178
+ rightTitle?: string;
179
+ /**
180
+ * optional lucide icon for the left header.
181
+ */
182
+ leftIcon?: React.ComponentType;
183
+ /**
184
+ * optional lucide icon for the right header.
185
+ */
186
+ rightIcon?: React.ComponentType;
187
+ /**
188
+ * quiet right-aligned content in the left header.
189
+ */
190
+ leftMeta?: React.ReactNode;
191
+ /**
192
+ * quiet right-aligned content in the right header.
193
+ */
194
+ rightMeta?: React.ReactNode;
195
+ /**
196
+ * extra class on the root.
197
+ */
198
+ className?: string;
199
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * RedactionReview — the safe-by-default review surface.
3
+ *
4
+ * @param {object} props
5
+ * @param {'minimal'|'standard'|'maximum'} [props.level='standard'] - the selected redaction level
6
+ * @param {(level: string) => void} [props.onLevel] - called with the next level on select
7
+ * @param {Array<{id, category, confidence:number, before?:string, secret?:string, after:string, kept?:boolean}>} [props.matches]
8
+ * - the flagged matches. `before`/`secret` is the original (one or the other), `after` the
9
+ * redacted form. `kept` (controlled mode) = the user opted OUT, secret leaves as-is.
10
+ * @param {(id: string, kept: boolean) => void} [props.onToggle] - called when a match is toggled;
11
+ * when given, the component is controlled (read `kept` off each match).
12
+ * @param {number} [props.scanned] - sessions/files scanned so far (defaults to `total`: done).
13
+ * @param {number} [props.total=0] - total to scan.
14
+ * @param {string|boolean} [props.failure] - honest-failure banner text; truthy shows the banner.
15
+ * @param {string} [props.className]
16
+ */
17
+ export function RedactionReview({ level, onLevel, matches, onToggle, scanned, total, failure, className, ...rest }: {
18
+ level?: "minimal" | "standard" | "maximum";
19
+ onLevel?: (level: string) => void;
20
+ matches?: Array<{
21
+ id: any;
22
+ category: any;
23
+ confidence: number;
24
+ before?: string;
25
+ secret?: string;
26
+ after: string;
27
+ kept?: boolean;
28
+ }>;
29
+ onToggle?: (id: string, kept: boolean) => void;
30
+ scanned?: number;
31
+ total?: number;
32
+ failure?: string | boolean;
33
+ className?: string;
34
+ }): any;
35
+ /**
36
+ * WhereDoesThisGo — the transparency panel shown before an outbound action. the destination url,
37
+ * then a two-column split: "what gets sent" (Send icon, add rail) vs "what stays private" (Lock
38
+ * icon, neutral rail). calm, square, hairline. each column header pairs an icon with its word so
39
+ * the two halves never read on color alone.
40
+ *
41
+ * @param {object} props
42
+ * @param {string} props.destination - the outbound url (code -> mono, not lowercased)
43
+ * @param {string[]} [props.sent] - the things that WILL be sent
44
+ * @param {string[]} [props.private] - the things that stay on the machine
45
+ * @param {string} [props.className]
46
+ */
47
+ export function WhereDoesThisGo({ destination, sent, private: stays, className, ...rest }: {
48
+ destination: string;
49
+ sent?: string[];
50
+ private?: string[];
51
+ className?: string;
52
+ }): any;
53
+ export default RedactionReview;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The inline destructive-confirm: a trigger button that, on click, swaps in place to
3
+ * "{label}? [yes] [cancel]" — never a modal, so the row never reflows out from under the cursor.
4
+ * yes fires onConfirm and (if it doesn't throw) reverts to the trigger; cancel reverts immediately.
5
+ *
6
+ * @param {Object} props
7
+ * @param {React.ReactNode} [props.label='remove'] the trigger's lowercase chrome label
8
+ * @param {string} [props.confirmLabel] the verb echoed in the prompt + on yes (defaults to label, lowercased)
9
+ * @param {React.ReactNode} [props.icon] optional leading glyph for the trigger (e.g. <Trash2 />)
10
+ * @param {() => (void | Promise<void>)} props.onConfirm fired when yes is activated
11
+ * @param {boolean} [props.busy=false] external pending flag — disables yes + shows "{verb}…"
12
+ * @param {boolean} [props.disabled=false] disables the trigger entirely
13
+ * @param {string} [props['aria-label']] accessible name for the trigger (defaults from label/confirmLabel)
14
+ * @param {string} [props.className] extra class on the wrapper
15
+ */
16
+ export function ConfirmInline({ label, confirmLabel, icon, onConfirm, busy, disabled, "aria-label": ariaLabel, className, }: {
17
+ label?: React.ReactNode;
18
+ confirmLabel?: string;
19
+ icon?: React.ReactNode;
20
+ onConfirm: () => (void | Promise<void>);
21
+ busy?: boolean;
22
+ disabled?: boolean;
23
+ }): any;
24
+ /**
25
+ * @typedef {Object} RosterMember
26
+ * @property {string} handle the member's handle (user content — never lowercased)
27
+ * @property {string} [name] display name (user content)
28
+ * @property {'owner'|'member'|'contributor'|'guest'} role the member's role
29
+ * @property {boolean} [owner] locks the row: role select disabled, "owner" shown as text + lock glyph, no remove
30
+ * @property {string} [org] an org affiliation chip (user content, e.g. a github org login)
31
+ * @property {string} [avatar] avatar image url; falls back to the handle's initial
32
+ * @property {string} [id] stable key (defaults to handle)
33
+ */
34
+ /**
35
+ * A member role roster: one row per member with avatar/handle + name, an org chip, a role select,
36
+ * and (for non-owner rows) an inline remove. Owner rows are locked — the role reads as plain
37
+ * "owner" text beside a lock glyph and there's no remove, mirroring village where the owner can't
38
+ * be reassigned or removed here.
39
+ *
40
+ * @param {Object} props
41
+ * @param {RosterMember[]} props.members the members to list
42
+ * @param {(member: RosterMember, role: string) => void} [props.onRole] fired when a row's role select changes
43
+ * @param {(member: RosterMember) => (void | Promise<void>)} [props.onRemove] fired when a row's remove is confirmed
44
+ * @param {string} [props.title='members'] section header label (lowercase chrome)
45
+ * @param {string[]} [props.roles] selectable roles (default member/contributor/guest; owner is never offered)
46
+ */
47
+ export default function RoleRoster({ members, onRole, onRemove, title, roles, }: {
48
+ members: RosterMember[];
49
+ onRole?: (member: RosterMember, role: string) => void;
50
+ onRemove?: (member: RosterMember) => (void | Promise<void>);
51
+ title?: string;
52
+ roles?: string[];
53
+ }): any;
54
+ /**
55
+ * A clay-bordered section wrapping destructive actions (e.g. "delete collective"). Fronted by a
56
+ * warning glyph + the literal word "warning" so the danger framing is never carried by the clay
57
+ * border alone. children is the body — typically a sentence of consequence + a
58
+ * <ConfirmInline confirmLabel="delete" />.
59
+ *
60
+ * @param {Object} props
61
+ * @param {React.ReactNode} [props.title='danger zone'] the section header label (lowercase chrome)
62
+ * @param {React.ReactNode} props.children the destructive actions / explanation
63
+ */
64
+ export function DangerZone({ title, children }: {
65
+ title?: React.ReactNode;
66
+ children: React.ReactNode;
67
+ }): any;
68
+ export type RosterMember = {
69
+ /**
70
+ * the member's handle (user content — never lowercased)
71
+ */
72
+ handle: string;
73
+ /**
74
+ * display name (user content)
75
+ */
76
+ name?: string;
77
+ /**
78
+ * the member's role
79
+ */
80
+ role: "owner" | "member" | "contributor" | "guest";
81
+ /**
82
+ * locks the row: role select disabled, "owner" shown as text + lock glyph, no remove
83
+ */
84
+ owner?: boolean;
85
+ /**
86
+ * an org affiliation chip (user content, e.g. a github org login)
87
+ */
88
+ org?: string;
89
+ /**
90
+ * avatar image url; falls back to the handle's initial
91
+ */
92
+ avatar?: string;
93
+ /**
94
+ * stable key (defaults to handle)
95
+ */
96
+ id?: string;
97
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * SignInProviders — a multi-provider OAuth split button.
3
+ *
4
+ * the first provider is the PRIMARY action ("continue with <label>"); the rest
5
+ * live behind a chevron that opens a keyboard-operable menu. clicking the
6
+ * primary or any menu row calls onSignIn(providerId).
7
+ *
8
+ * @param {object} props
9
+ * @param {Array<{id:string,label:string}>} [props.providers] ordered; [0] is primary. defaults to PROVIDERS.
10
+ * @param {(id:string)=>void} [props.onSignIn] called with the chosen provider id.
11
+ * @param {string} [props.className]
12
+ * @returns {JSX.Element|null}
13
+ */
14
+ export function SignInProviders({ providers, onSignIn, className, ...rest }: {
15
+ providers?: Array<{
16
+ id: string;
17
+ label: string;
18
+ }>;
19
+ onSignIn?: (id: string) => void;
20
+ className?: string;
21
+ }): JSX.Element | null;
22
+ /**
23
+ * HandleClaim — the post-OAuth handle-claim card.
24
+ *
25
+ * a mono @-prefixed input with live validation shown as an ICON + a WORD (never
26
+ * color alone), one or two suggestion chips, and a "claim handle" button that
27
+ * stays disabled until the handle validates as available. the typed handle keeps
28
+ * its case; validation normalizes a copy.
29
+ *
30
+ * @param {object} props
31
+ * @param {(handle:string)=>void} [props.onSubmit] called with the typed handle on claim.
32
+ * @param {(raw:string)=>{state:'idle'|'available'|'taken'|'invalid'|'checking',hint?:string}} [props.validate]
33
+ * override the validator; defaults to the built-in handle rule + taken set.
34
+ * @param {string} [props.initialValue] seed the field (kept verbatim, case preserved).
35
+ * @param {string} [props.suggestedFrom] a provider username to derive suggestion chips from.
36
+ * @param {string[]} [props.suggestions] explicit suggestion chips (overrides suggestedFrom).
37
+ * @param {string} [props.className]
38
+ * @returns {JSX.Element}
39
+ */
40
+ export function HandleClaim({ onSubmit, validate, initialValue, suggestedFrom, suggestions, className, ...rest }: {
41
+ onSubmit?: (handle: string) => void;
42
+ validate?: (raw: string) => {
43
+ state: "idle" | "available" | "taken" | "invalid" | "checking";
44
+ hint?: string;
45
+ };
46
+ initialValue?: string;
47
+ suggestedFrom?: string;
48
+ suggestions?: string[];
49
+ className?: string;
50
+ }): JSX.Element;
51
+ /**
52
+ * OnboardingCard — the two steps composed into one onboarding specimen: the
53
+ * provider split button up top, the handle-claim card below. a thin pass-through
54
+ * wrapper so a consumer (and the combined story) can show the whole front door.
55
+ *
56
+ * @param {object} props
57
+ * @param {Array<{id:string,label:string}>} [props.providers]
58
+ * @param {(id:string)=>void} [props.onSignIn]
59
+ * @param {(handle:string)=>void} [props.onSubmit]
60
+ * @param {string} [props.suggestedFrom]
61
+ * @param {string} [props.className]
62
+ * @returns {JSX.Element}
63
+ */
64
+ export function OnboardingCard({ providers, onSignIn, onSubmit, suggestedFrom, className, ...rest }: {
65
+ providers?: Array<{
66
+ id: string;
67
+ label: string;
68
+ }>;
69
+ onSignIn?: (id: string) => void;
70
+ onSubmit?: (handle: string) => void;
71
+ suggestedFrom?: string;
72
+ className?: string;
73
+ }): JSX.Element;
74
+ export const PROVIDERS: {
75
+ id: string;
76
+ label: string;
77
+ }[];
78
+ export default SignInProviders;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param {Object} props
3
+ * @param {Array<number|Object>} props.data numbers, or objects with a `value` key.
4
+ * @param {'line'|'bar'} [props.type='line'] line or mini-bar.
5
+ * @param {'teal'|'olive'|'clay'|'mauve'|'amber'|1|2|3|4} [props.color='teal'] token colour.
6
+ * @param {number} [props.width=88] px width.
7
+ * @param {number} [props.height=24] px height.
8
+ * @param {string} props.label accessible name (e.g. "sessions, last 8 weeks, trending up"). required.
9
+ * @param {string} [props.className] extra class.
10
+ */
11
+ export default function Sparkline({ data, type, color, width, height, label, className }: {
12
+ data: Array<number | any>;
13
+ type?: "line" | "bar";
14
+ color?: "teal" | "olive" | "clay" | "mauve" | "amber" | 1 | 2 | 3 | 4;
15
+ width?: number;
16
+ height?: number;
17
+ label: string;
18
+ className?: string;
19
+ }): any;