@danxbot/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/dist/fonts/bricolage-grotesque-0.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-1.woff2 +0 -0
- package/dist/fonts/bricolage-grotesque-2.woff2 +0 -0
- package/dist/fonts/figtree-0.woff2 +0 -0
- package/dist/fonts/figtree-1.woff2 +0 -0
- package/dist/fonts/figtree-2.woff2 +0 -0
- package/dist/fonts/figtree-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-0.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-1.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-10.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-11.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-2.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-3.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-4.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-5.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-6.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-7.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-8.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-9.woff2 +0 -0
- package/dist/fonts.css +187 -0
- package/dist/index.js +42425 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +190 -0
- package/dist/types/components/Accordion.d.ts +15 -0
- package/dist/types/components/AppShell.d.ts +58 -0
- package/dist/types/components/Avatar.d.ts +154 -0
- package/dist/types/components/Badge.d.ts +73 -0
- package/dist/types/components/Button.d.ts +103 -0
- package/dist/types/components/Card.d.ts +193 -0
- package/dist/types/components/Choice.d.ts +112 -0
- package/dist/types/components/CodeEditor.d.ts +86 -0
- package/dist/types/components/Combobox.d.ts +37 -0
- package/dist/types/components/CommandPalette.d.ts +33 -0
- package/dist/types/components/DatePicker.d.ts +20 -0
- package/dist/types/components/Dialog.d.ts +117 -0
- package/dist/types/components/DragDrop.d.ts +60 -0
- package/dist/types/components/ErrorBoundary.d.ts +16 -0
- package/dist/types/components/Field.d.ts +37 -0
- package/dist/types/components/FileUpload.d.ts +22 -0
- package/dist/types/components/Icon.d.ts +40 -0
- package/dist/types/components/Input.d.ts +120 -0
- package/dist/types/components/Loading.d.ts +83 -0
- package/dist/types/components/MarkdownEditor.d.ts +24 -0
- package/dist/types/components/Menu.d.ts +57 -0
- package/dist/types/components/Navigation.d.ts +46 -0
- package/dist/types/components/NumberInput.d.ts +88 -0
- package/dist/types/components/OTPInput.d.ts +11 -0
- package/dist/types/components/Panel.d.ts +94 -0
- package/dist/types/components/Popover.d.ts +64 -0
- package/dist/types/components/Progress.d.ts +178 -0
- package/dist/types/components/Select.d.ts +53 -0
- package/dist/types/components/Slider.d.ts +203 -0
- package/dist/types/components/Spinner.d.ts +29 -0
- package/dist/types/components/Stat.d.ts +98 -0
- package/dist/types/components/StatusSelect.d.ts +23 -0
- package/dist/types/components/Surface.d.ts +110 -0
- package/dist/types/components/Table.d.ts +46 -0
- package/dist/types/components/Tabs.d.ts +84 -0
- package/dist/types/components/ThemeMenu.d.ts +4 -0
- package/dist/types/components/Toast.d.ts +46 -0
- package/dist/types/components/Toggle.d.ts +65 -0
- package/dist/types/components/Tree.d.ts +20 -0
- package/dist/types/components/calendar/CalendarMonth.d.ts +33 -0
- package/dist/types/components/calendar/CalendarTimeGrid.d.ts +75 -0
- package/dist/types/components/calendar/EventActions.d.ts +17 -0
- package/dist/types/components/calendar/format.d.ts +43 -0
- package/dist/types/components/calendar/index.d.ts +9 -0
- package/dist/types/components/calendar/palette.d.ts +17 -0
- package/dist/types/components/calendar/use-calendar-drag.d.ts +54 -0
- package/dist/types/components/calendar/use-event-keyboard.d.ts +24 -0
- package/dist/types/components/calendar/use-grid-navigation.d.ts +47 -0
- package/dist/types/components/calendar/use-now.d.ts +20 -0
- package/dist/types/components/chat/Attachment.d.ts +49 -0
- package/dist/types/components/chat/Chat.d.ts +60 -0
- package/dist/types/components/chat/Composer.d.ts +29 -0
- package/dist/types/components/chat/ContextMeter.d.ts +55 -0
- package/dist/types/components/chat/EffortControl.d.ts +23 -0
- package/dist/types/components/chat/Markdown.d.ts +22 -0
- package/dist/types/components/chat/Message.d.ts +59 -0
- package/dist/types/components/chat/MessageScroller.d.ts +13 -0
- package/dist/types/components/chat/ModelSelector.d.ts +44 -0
- package/dist/types/components/chat/types.d.ts +155 -0
- package/dist/types/components/code-editor/context.d.ts +32 -0
- package/dist/types/components/code-editor/editing.d.ts +39 -0
- package/dist/types/components/code-editor/highlight.d.ts +20 -0
- package/dist/types/components/code-editor/recipe.d.ts +109 -0
- package/dist/types/components/code-editor/state.d.ts +14 -0
- package/dist/types/components/drag-drop/context.d.ts +45 -0
- package/dist/types/components/drag-drop/recipe.d.ts +121 -0
- package/dist/types/components/drag-drop/shift.d.ts +66 -0
- package/dist/types/components/markdown/Affordances.d.ts +76 -0
- package/dist/types/components/rbac/AccountMenu.d.ts +8 -0
- package/dist/types/components/rbac/DevToolsPopover.d.ts +5 -0
- package/dist/types/components/rbac/ProfilePage.d.ts +1 -0
- package/dist/types/components/rbac/RBACProvider.d.ts +64 -0
- package/dist/types/components/rbac/RolePermissionMatrix.d.ts +6 -0
- package/dist/types/components/rbac/RolesPermissionsPage.d.ts +1 -0
- package/dist/types/components/rbac/index.d.ts +7 -0
- package/dist/types/components/rbac/types.d.ts +26 -0
- package/dist/types/components/roadmap/PhaseManager.d.ts +19 -0
- package/dist/types/components/roadmap/RoadmapItemCard.d.ts +45 -0
- package/dist/types/components/roadmap/RoadmapPage.d.ts +9 -0
- package/dist/types/components/roadmap/RoadmapSwimlaneBoard.d.ts +9 -0
- package/dist/types/components/roadmap/UseCaseCard.d.ts +14 -0
- package/dist/types/components/roadmap/UseCaseLedgerPage.d.ts +21 -0
- package/dist/types/components/roadmap/chip-tones.d.ts +2 -0
- package/dist/types/components/roadmap/derive.d.ts +12 -0
- package/dist/types/components/roadmap/index.d.ts +9 -0
- package/dist/types/components/roadmap/types.d.ts +54 -0
- package/dist/types/icons/data.d.ts +1318 -0
- package/dist/types/index.d.ts +97 -0
- package/dist/types/lib/calendar/band-packer.d.ts +53 -0
- package/dist/types/lib/calendar/drag.d.ts +125 -0
- package/dist/types/lib/calendar/index.d.ts +4 -0
- package/dist/types/lib/calendar/lane-packer.d.ts +88 -0
- package/dist/types/lib/calendar/segments.d.ts +91 -0
- package/dist/types/lib/calendar/types.d.ts +166 -0
- package/dist/types/lib/cn.d.ts +7 -0
- package/dist/types/lib/dnd/announce.d.ts +132 -0
- package/dist/types/lib/dnd/autoscroll.d.ts +88 -0
- package/dist/types/lib/dnd/geometry.d.ts +78 -0
- package/dist/types/lib/dnd/index.d.ts +16 -0
- package/dist/types/lib/dnd/sensors/gesture.d.ts +37 -0
- package/dist/types/lib/dnd/sensors/keyboard.d.ts +50 -0
- package/dist/types/lib/dnd/sensors/pointer.d.ts +59 -0
- package/dist/types/lib/dnd/session.d.ts +99 -0
- package/dist/types/lib/dnd/types.d.ts +162 -0
- package/dist/types/lib/dnd/use-drag.d.ts +56 -0
- package/dist/types/lib/icons.d.ts +40 -0
- package/dist/types/lib/markdown/caret-map.d.ts +48 -0
- package/dist/types/lib/markdown/caret.d.ts +6 -0
- package/dist/types/lib/markdown/commands.d.ts +170 -0
- package/dist/types/lib/markdown/convert.d.ts +82 -0
- package/dist/types/lib/markdown/dom.d.ts +67 -0
- package/dist/types/lib/markdown/edit.d.ts +16 -0
- package/dist/types/lib/markdown/history.d.ts +47 -0
- package/dist/types/lib/markdown/hotkeys.d.ts +39 -0
- package/dist/types/lib/markdown/input.d.ts +15 -0
- package/dist/types/lib/markdown/keys.d.ts +34 -0
- package/dist/types/lib/markdown/paste.d.ts +9 -0
- package/dist/types/lib/markdown/position.d.ts +43 -0
- package/dist/types/lib/markdown/project.d.ts +88 -0
- package/dist/types/lib/markdown/reconcile.d.ts +63 -0
- package/dist/types/lib/markdown/surface.d.ts +177 -0
- package/dist/types/lib/persist.d.ts +40 -0
- package/dist/types/lib/preferences.d.ts +80 -0
- package/dist/types/lib/sim/createSimStore.d.ts +18 -0
- package/dist/types/lib/sim/index.d.ts +5 -0
- package/dist/types/lib/sim/latency.d.ts +10 -0
- package/dist/types/lib/sim/registry.d.ts +14 -0
- package/dist/types/lib/sim/settings.d.ts +11 -0
- package/dist/types/lib/sim/types.d.ts +3 -0
- package/dist/types/lib/syntax/index.d.ts +16 -0
- package/dist/types/lib/syntax/languages/bash.d.ts +1 -0
- package/dist/types/lib/syntax/languages/css.d.ts +1 -0
- package/dist/types/lib/syntax/languages/html.d.ts +17 -0
- package/dist/types/lib/syntax/languages/index.d.ts +33 -0
- package/dist/types/lib/syntax/languages/javascript.d.ts +22 -0
- package/dist/types/lib/syntax/languages/json.d.ts +1 -0
- package/dist/types/lib/syntax/languages/mongodb.d.ts +1 -0
- package/dist/types/lib/syntax/languages/plain.d.ts +9 -0
- package/dist/types/lib/syntax/languages/sql.d.ts +4 -0
- package/dist/types/lib/syntax/languages/vue.d.ts +1 -0
- package/dist/types/lib/syntax/languages/yaml.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/frames.d.ts +145 -0
- package/dist/types/lib/syntax/markdown/grammar.d.ts +1 -0
- package/dist/types/lib/syntax/markdown/index.d.ts +4 -0
- package/dist/types/lib/syntax/markdown/inline.d.ts +21 -0
- package/dist/types/lib/syntax/markdown/parse.d.ts +11 -0
- package/dist/types/lib/syntax/markdown/render.d.ts +19 -0
- package/dist/types/lib/syntax/markdown/spans.d.ts +84 -0
- package/dist/types/lib/syntax/markdown/types.d.ts +108 -0
- package/dist/types/lib/syntax/registry.d.ts +37 -0
- package/dist/types/lib/syntax/tokenize.d.ts +17 -0
- package/dist/types/lib/syntax/types.d.ts +119 -0
- package/dist/types/lib/time/index.d.ts +3 -0
- package/dist/types/lib/time/plain.d.ts +61 -0
- package/dist/types/lib/time/types.d.ts +87 -0
- package/dist/types/lib/time/zone.d.ts +97 -0
- package/dist/types/lib/use-media-query.d.ts +29 -0
- package/package.json +130 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ContainerId, DragAxis, DragState, LayoutSnapshot } from "../../lib/dnd";
|
|
2
|
+
export interface ContainerShift {
|
|
3
|
+
axis: DragAxis;
|
|
4
|
+
/** Items in this container with the carried one removed. */
|
|
5
|
+
restCount: number;
|
|
6
|
+
/**
|
|
7
|
+
* The carried item's extent along the axis — the size of the hole that opens.
|
|
8
|
+
* The step neighbours move by is this PLUS the spacing between two items,
|
|
9
|
+
* because the arriving item brings its own gap with it.
|
|
10
|
+
*/
|
|
11
|
+
gapSize: number;
|
|
12
|
+
/** `gapSize` plus the measured spacing: how far one neighbour moves. */
|
|
13
|
+
step: number;
|
|
14
|
+
/** Measured spacing between two adjacent items of this container. */
|
|
15
|
+
spacing: number;
|
|
16
|
+
/** Insertion index in this container, or null when it is not the target. */
|
|
17
|
+
markerAt: number | null;
|
|
18
|
+
/** Displacement along the axis, in px, for the rest item at `restIndex`. */
|
|
19
|
+
itemShift: (restIndex: number) => number;
|
|
20
|
+
/**
|
|
21
|
+
* Displacement for the insertion marker rendered before rest item
|
|
22
|
+
* `restIndex` — or at `restCount`, meaning after every item.
|
|
23
|
+
*
|
|
24
|
+
* The marker takes ONLY the home-slot half. It IS the gap, so applying the
|
|
25
|
+
* gap displacement to it would move it out of the space it marks.
|
|
26
|
+
*/
|
|
27
|
+
markerShift: (restIndex: number) => number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Everything one container needs to render the shift, or null when no drag is
|
|
31
|
+
* in flight and nothing should move.
|
|
32
|
+
*
|
|
33
|
+
* `lifted` says whether something else is carrying the card — a
|
|
34
|
+
* `<DragDropOverlay>` is mounted. It decides ONLY whether the home slot closes,
|
|
35
|
+
* and the reason is not cosmetic: with no overlay the card is still sitting in
|
|
36
|
+
* its own slot, so closing that slot slides a neighbour underneath it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function containerShift(layout: LayoutSnapshot | null, state: DragState, container: ContainerId, lifted: boolean): ContainerShift | null;
|
|
39
|
+
/** A rect in viewport coordinates. */
|
|
40
|
+
export interface GapRect {
|
|
41
|
+
top: number;
|
|
42
|
+
left: number;
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Where the opened gap sits on screen, for a carried card that has no pointer
|
|
48
|
+
* to follow.
|
|
49
|
+
*
|
|
50
|
+
* Viewport coordinates, taken from the same snapshot the shift is computed
|
|
51
|
+
* from, so the two cannot disagree about where the hole is. The snapshot is
|
|
52
|
+
* re-taken whenever the keyboard insertion point moves out of view
|
|
53
|
+
* (`autoscroll.ts#keepKeyboardTargetVisible`), which is the only thing that
|
|
54
|
+
* moves these boxes during a keyboard drag.
|
|
55
|
+
*/
|
|
56
|
+
export declare function gapRect(layout: LayoutSnapshot | null, state: DragState, lifted: boolean): GapRect | null;
|
|
57
|
+
/**
|
|
58
|
+
* The shift as an inline style.
|
|
59
|
+
*
|
|
60
|
+
* `translate` rather than `transform`, so a component can still rotate or scale
|
|
61
|
+
* the same element without the two having to be composed into one string — the
|
|
62
|
+
* floating clone does exactly that.
|
|
63
|
+
*/
|
|
64
|
+
export declare function shiftStyle(axis: DragAxis, distance: number): {
|
|
65
|
+
translate: string;
|
|
66
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type BlockInfo, type BlockKind, type ConstructInfo } from "../../lib/markdown/convert";
|
|
2
|
+
import { type Command } from "../../lib/markdown/commands";
|
|
3
|
+
import type { MarkdownSurface } from "../../lib/markdown/surface";
|
|
4
|
+
export interface EditorState {
|
|
5
|
+
source: string;
|
|
6
|
+
/** Collapsed caret offset, or null when there is no selection in the host. */
|
|
7
|
+
caret: number | null;
|
|
8
|
+
/** True when the selection covers something. */
|
|
9
|
+
ranged: boolean;
|
|
10
|
+
block: BlockInfo | null;
|
|
11
|
+
construct: ConstructInfo | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Tracks source and selection, and derives what is under the caret.
|
|
15
|
+
*
|
|
16
|
+
* `selectionchange` is a DOCUMENT event and the only signal for a caret the
|
|
17
|
+
* browser moved on its own — a click, a drag, an arrow key. It fires for the
|
|
18
|
+
* surface's own restore too, which is harmless here because this only reads.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useEditorState(surface: MarkdownSurface | null, version: number): EditorState;
|
|
21
|
+
interface TypeChoice {
|
|
22
|
+
kind: BlockKind;
|
|
23
|
+
level?: number;
|
|
24
|
+
label: string;
|
|
25
|
+
icon: string;
|
|
26
|
+
}
|
|
27
|
+
export interface LineHandleProps {
|
|
28
|
+
surface: MarkdownSurface | null;
|
|
29
|
+
state: EditorState;
|
|
30
|
+
run: (command: Command) => void;
|
|
31
|
+
/** The container the handle is positioned inside. */
|
|
32
|
+
container: HTMLElement | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A type control beside the line under the pointer, or under the caret.
|
|
36
|
+
*
|
|
37
|
+
* ON HOVER AND ON THE CARET'S LINE, never on every line at once: a permanent
|
|
38
|
+
* gutter of forty identical buttons is noise, and one that follows the pointer
|
|
39
|
+
* is discoverable the moment a pointer moves. The caret's line is included so
|
|
40
|
+
* the control exists for someone who is not using a pointer at all.
|
|
41
|
+
*/
|
|
42
|
+
export declare function LineHandle({ surface, state, run, container }: LineHandleProps): import("react").JSX.Element | null;
|
|
43
|
+
export interface ConstructBarProps {
|
|
44
|
+
surface: MarkdownSurface | null;
|
|
45
|
+
state: EditorState;
|
|
46
|
+
run: (command: Command) => void;
|
|
47
|
+
container: HTMLElement | null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The controls for whatever the caret is inside — a link, an image, a fence or
|
|
51
|
+
* a table.
|
|
52
|
+
*
|
|
53
|
+
* IT APPEARS BY ITSELF rather than waiting for a click, and that is a decision
|
|
54
|
+
* the always-hidden markup forces. A destination the caret cannot enter and a
|
|
55
|
+
* control that has to be found are the same thing as no control at all; a small
|
|
56
|
+
* bar anchored to the construct you are already standing in is the shortest
|
|
57
|
+
* path from "I want to change this URL" to changing it.
|
|
58
|
+
*/
|
|
59
|
+
export declare function ConstructBar({ surface, state, run, container }: ConstructBarProps): import("react").JSX.Element | null;
|
|
60
|
+
export interface ConversionMenuProps {
|
|
61
|
+
surface: MarkdownSurface | null;
|
|
62
|
+
state: EditorState;
|
|
63
|
+
run: (command: Command) => void;
|
|
64
|
+
container: HTMLElement | null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Right-click conversions for a selection.
|
|
68
|
+
*
|
|
69
|
+
* OURS ONLY WHEN THERE IS SOMETHING TO CONVERT. Swallowing every right-click
|
|
70
|
+
* costs the browser's own spellcheck suggestions, which is a worse trade than
|
|
71
|
+
* this menu is worth — so with no selection and nothing under the pointer, the
|
|
72
|
+
* native menu is left alone.
|
|
73
|
+
*/
|
|
74
|
+
export declare function ConversionMenu({ surface, state, run, container }: ConversionMenuProps): import("react").JSX.Element | null;
|
|
75
|
+
export declare const AFFORDANCE_TYPES: TypeChoice[];
|
|
76
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AccountMenuProps {
|
|
2
|
+
onNavigateProfile?: () => void;
|
|
3
|
+
onNavigateRoles?: () => void;
|
|
4
|
+
onSwitchTeam?: (teamId: string) => void;
|
|
5
|
+
onSignOut?: () => void;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function AccountMenu({ onNavigateProfile, onNavigateRoles, onSwitchTeam, onSignOut, className, }: AccountMenuProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface DevToolsPopoverProps {
|
|
2
|
+
/** Deep link to the dev-only Use Case Ledger. Omit and the row does not render. */
|
|
3
|
+
onOpenUseCaseLedger?: () => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function DevToolsPopover({ onOpenUseCaseLedger }?: DevToolsPopoverProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ProfilePage(): import("react").JSX.Element;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Permission, Role, Team, TeamMembership, User } from "./types";
|
|
3
|
+
export interface RBACProviderProps {
|
|
4
|
+
currentUser: User;
|
|
5
|
+
roles: Role[];
|
|
6
|
+
permissions: Permission[];
|
|
7
|
+
teams: Team[];
|
|
8
|
+
/** All memberships for `currentUser`, across every team — not just the current one. */
|
|
9
|
+
memberships: TeamMembership[];
|
|
10
|
+
currentTeamId: string;
|
|
11
|
+
/**
|
|
12
|
+
* Decides who may open the Dev Tools "view as" escape hatch.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately a predicate over the consumer's OWN data (`user`, `roles`,
|
|
15
|
+
* `memberships`) rather than a boolean prop or a hardcoded role check. The
|
|
16
|
+
* library has no idea what "admin enough to use dev tools" means for any
|
|
17
|
+
* given consumer — one app might key it off a role id, another off a team
|
|
18
|
+
* membership count, another off a flag on `User` this contract doesn't even
|
|
19
|
+
* define. Only the consumer's own data model can answer that, so the
|
|
20
|
+
* decision is handed back to them wholesale.
|
|
21
|
+
*/
|
|
22
|
+
canAccessDevTools: (user: User, roles: Role[], memberships: TeamMembership[]) => boolean;
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
export interface RBACHookResult {
|
|
26
|
+
actualUser: User;
|
|
27
|
+
currentTeam: Team | undefined;
|
|
28
|
+
/** The role backing `actualUser`'s own membership in `currentTeamId` — never affected by impersonation. */
|
|
29
|
+
actualRole: Role | undefined;
|
|
30
|
+
/** `null` when not impersonating. */
|
|
31
|
+
viewingAsRoleId: string | null;
|
|
32
|
+
setViewingAsRoleId: (id: string | null) => void;
|
|
33
|
+
/** `actualRole`, unless impersonating — then the impersonated role. */
|
|
34
|
+
effectiveRole: Role | undefined;
|
|
35
|
+
effectivePermissionKeys: Set<string>;
|
|
36
|
+
hasPermission: (key: string) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether the REAL logged-in user may open Dev Tools.
|
|
39
|
+
*
|
|
40
|
+
* See the block comment above `evaluateCanAccessDevTools` below for why this
|
|
41
|
+
* is computed from `actualUser`/`roles`/`memberships` and can NEVER be
|
|
42
|
+
* re-derived from `effectiveRole` / `viewingAsRoleId` — that is the entire
|
|
43
|
+
* point of this field existing on the hook at all.
|
|
44
|
+
*/
|
|
45
|
+
canAccessDevTools: boolean;
|
|
46
|
+
isImpersonating: boolean;
|
|
47
|
+
roles: Role[];
|
|
48
|
+
permissions: Permission[];
|
|
49
|
+
teams: Team[];
|
|
50
|
+
}
|
|
51
|
+
export declare function RBACProvider({ currentUser, roles, permissions, teams, memberships, currentTeamId, canAccessDevTools, children, }: RBACProviderProps): import("react").JSX.Element;
|
|
52
|
+
/**
|
|
53
|
+
* Reads the RBAC context.
|
|
54
|
+
*
|
|
55
|
+
* Throws rather than returning `undefined` — the same shape as
|
|
56
|
+
* `useDragDrop` / `useDragDropContainer` (`drag-drop/context.ts`) and every
|
|
57
|
+
* other multi-part context in this library. A component that silently
|
|
58
|
+
* received `undefined` here would fail wherever it FIRST tries to read a
|
|
59
|
+
* field off the result, several lines and possibly several components away
|
|
60
|
+
* from the actual mistake (forgetting the `<RBACProvider>` wrapper) — a
|
|
61
|
+
* blank permissions list is a much harder bug to trace back than a thrown
|
|
62
|
+
* error naming the missing provider.
|
|
63
|
+
*/
|
|
64
|
+
export declare function useRBAC(): RBACHookResult;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Permission, Role } from "./types";
|
|
2
|
+
export interface RolePermissionMatrixProps {
|
|
3
|
+
roles: Role[];
|
|
4
|
+
permissions: Permission[];
|
|
5
|
+
}
|
|
6
|
+
export declare function RolePermissionMatrix({ roles, permissions }: RolePermissionMatrixProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function RolesPermissionsPage(): import("react").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface Permission {
|
|
2
|
+
/** Arbitrary, consumer-defined. The library only ever compares keys for equality. */
|
|
3
|
+
key: string;
|
|
4
|
+
label: string;
|
|
5
|
+
category?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Role {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
permissionKeys: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface User {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
email: string;
|
|
16
|
+
avatarUrl?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface Team {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
export interface TeamMembership {
|
|
23
|
+
userId: string;
|
|
24
|
+
teamId: string;
|
|
25
|
+
roleId: string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Phase, RoadmapItem } from "./types";
|
|
2
|
+
export interface PhaseManagerProps {
|
|
3
|
+
phases: Phase[];
|
|
4
|
+
/** Read-only — used only to compute the delete guard below. */
|
|
5
|
+
roadmapItems: RoadmapItem[];
|
|
6
|
+
/** `order` is pre-computed by this component (next after the current max)
|
|
7
|
+
so the caller only has to assign an id and persist. */
|
|
8
|
+
onCreate: (phase: {
|
|
9
|
+
name: string;
|
|
10
|
+
order: number;
|
|
11
|
+
}) => void;
|
|
12
|
+
onRename: (id: string, name: string) => void;
|
|
13
|
+
/** The full phase list, reordered and renumbered (`order` === new index) —
|
|
14
|
+
the caller persists each row's new `order`, e.g. one `update` per id. */
|
|
15
|
+
onReorder: (phases: Phase[]) => void;
|
|
16
|
+
onDelete: (id: string) => void;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function PhaseManager({ phases, roadmapItems, onCreate, onRename, onReorder, onDelete, className, }: PhaseManagerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type BadgeProps } from "../Badge";
|
|
2
|
+
import type { Domain, Phase, RoadmapItem, RoadmapItemStatus, UseCase, UseCaseStatus } from "./types";
|
|
3
|
+
export declare const ROADMAP_ITEM_STATUS_BADGE: Record<RoadmapItemStatus, {
|
|
4
|
+
tone: BadgeProps["tone"];
|
|
5
|
+
label: string;
|
|
6
|
+
live?: boolean;
|
|
7
|
+
}>;
|
|
8
|
+
export interface RoadmapItemCardProps {
|
|
9
|
+
item: RoadmapItem;
|
|
10
|
+
domain: Domain;
|
|
11
|
+
/** `domain`'s position in the FULL `domains[]` list the caller was handed —
|
|
12
|
+
computed once by the caller (`domains.findIndex(...)`, or a `.map()`
|
|
13
|
+
index), never re-derived here. Drives the domain Badge's cycling tone
|
|
14
|
+
via `toneForIndex`, the same "the card computes nothing it wasn't
|
|
15
|
+
explicitly handed" pattern already used for `useCases` below. */
|
|
16
|
+
domainIndex: number;
|
|
17
|
+
phase: Phase;
|
|
18
|
+
/** Same pattern as `domainIndex`, for `phase`. */
|
|
19
|
+
phaseIndex: number;
|
|
20
|
+
/** This item's OWN use cases (already filtered by `goalRef === item.ref`) —
|
|
21
|
+
the card computes its status from exactly this list and renders nothing
|
|
22
|
+
more, so a caller handing it the wrong slice silently mis-derives status
|
|
23
|
+
rather than the card silently re-filtering a different assumption. */
|
|
24
|
+
useCases: UseCase[];
|
|
25
|
+
/** Forwarded to each `UseCaseCard`'s `onStatusChange` as
|
|
26
|
+
`onUseCaseStatusChange(useCase.ref, status)`. Omitted (the default,
|
|
27
|
+
`RoadmapSwimlaneBoard`'s customer-facing use) keeps every `UseCaseCard`
|
|
28
|
+
read-only — see `UseCaseCard`'s own `onStatusChange` doc. */
|
|
29
|
+
onUseCaseStatusChange?: (ref: string, status: UseCaseStatus) => void;
|
|
30
|
+
defaultExpanded?: boolean;
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A single roadmap item, expandable to reveal the use cases behind it.
|
|
35
|
+
*
|
|
36
|
+
* COLLAPSED BY DEFAULT, REVEALED BY A CLICK — this is the literal "click a
|
|
37
|
+
* roadmap item to see the use cases inside it" interaction from the product
|
|
38
|
+
* spec, not a static list that happens to render inside a card. A disclosure
|
|
39
|
+
* button (`aria-expanded` + `aria-controls`) rather than making the whole card
|
|
40
|
+
* clickable: a card-sized hit target with no visible affordance is the classic
|
|
41
|
+
* "is this a link or a label" ambiguity, and a card is also where a consumer
|
|
42
|
+
* may reasonably want to add its OWN click behaviour (e.g. deep-linking) later
|
|
43
|
+
* without fighting this one for the same element.
|
|
44
|
+
*/
|
|
45
|
+
export declare function RoadmapItemCard({ item, domain, domainIndex, phase, phaseIndex, useCases, onUseCaseStatusChange, defaultExpanded, className, }: RoadmapItemCardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Domain, Phase, RoadmapItem, UseCase } from "./types";
|
|
2
|
+
export interface RoadmapPageProps {
|
|
3
|
+
domains: Domain[];
|
|
4
|
+
phases: Phase[];
|
|
5
|
+
items: RoadmapItem[];
|
|
6
|
+
useCases: UseCase[];
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function RoadmapPage({ domains, phases, items, useCases, className }: RoadmapPageProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Domain, Phase, RoadmapItem, UseCase } from "./types";
|
|
2
|
+
export interface RoadmapSwimlaneBoardProps {
|
|
3
|
+
domains: Domain[];
|
|
4
|
+
phases: Phase[];
|
|
5
|
+
items: RoadmapItem[];
|
|
6
|
+
useCases: UseCase[];
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function RoadmapSwimlaneBoard({ domains, phases, items, useCases, className, }: RoadmapSwimlaneBoardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { UseCase, UseCaseStatus } from "./types";
|
|
2
|
+
export interface UseCaseCardProps {
|
|
3
|
+
useCase: UseCase;
|
|
4
|
+
/**
|
|
5
|
+
* Makes `status` user-settable: supplying this swaps the read-only status
|
|
6
|
+
* Badge for a `Select`. Omitted (the default) keeps the Badge — so
|
|
7
|
+
* `RoadmapPage`'s customer-facing rendering of this card, if it ever
|
|
8
|
+
* renders one directly, is never forced into an editable control just
|
|
9
|
+
* because this component knows how to be one.
|
|
10
|
+
*/
|
|
11
|
+
onStatusChange?: (status: UseCaseStatus) => void;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function UseCaseCard({ useCase, onStatusChange, className }: UseCaseCardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Domain, Phase, RoadmapItem, UseCase, UseCaseStatus } from "./types";
|
|
2
|
+
export interface UseCaseLedgerPageProps {
|
|
3
|
+
domains: Domain[];
|
|
4
|
+
phases: Phase[];
|
|
5
|
+
items: RoadmapItem[];
|
|
6
|
+
useCases: UseCase[];
|
|
7
|
+
/** Forwarded to every `RoadmapItemCard` -> `UseCaseCard` on this page,
|
|
8
|
+
making every use case's status genuinely user-settable here. Omitted
|
|
9
|
+
keeps every status read-only, the same default `UseCaseCard` itself
|
|
10
|
+
carries. */
|
|
11
|
+
onUseCaseStatusChange?: (ref: string, status: UseCaseStatus) => void;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Dev-facing ledger — the operator's view of EVERYTHING, unlike `RoadmapPage`
|
|
16
|
+
* which filters to `customerVisible` items only. No visibility filtering
|
|
17
|
+
* happens here on purpose: this is the surface where an internal-only item, or
|
|
18
|
+
* one still "unresolved" because a use case needs a human decision, is
|
|
19
|
+
* supposed to be visible.
|
|
20
|
+
*/
|
|
21
|
+
export declare function UseCaseLedgerPage({ domains, phases, items, useCases, onUseCaseStatusChange, className, }: UseCaseLedgerPageProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RoadmapItemStatus, UseCase } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* A RoadmapItem's status is derived from its own UseCases, never hand-set —
|
|
4
|
+
* the same reasoning as any parent whose state depends on its children:
|
|
5
|
+
* hand-set it and it silently drifts the moment a child changes underneath it.
|
|
6
|
+
*
|
|
7
|
+
* Rejected cases fall out of the rollup entirely — dead weight, not a blocker.
|
|
8
|
+
* A goal left with no live cases (everything rejected) is "unresolved" rather
|
|
9
|
+
* than defaulting to "planned", which would misreport a goal that needs a
|
|
10
|
+
* human decision as one that simply hasn't started.
|
|
11
|
+
*/
|
|
12
|
+
export declare function deriveRoadmapItemStatus(useCases: UseCase[]): RoadmapItemStatus;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export * from "./derive";
|
|
3
|
+
export * from "./chip-tones";
|
|
4
|
+
export * from "./UseCaseCard";
|
|
5
|
+
export * from "./RoadmapItemCard";
|
|
6
|
+
export * from "./RoadmapSwimlaneBoard";
|
|
7
|
+
export * from "./UseCaseLedgerPage";
|
|
8
|
+
export * from "./RoadmapPage";
|
|
9
|
+
export * from "./PhaseManager";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type UseCaseStatus = "pending" | "in-progress" | "verified" | "rejected";
|
|
2
|
+
/** Derived, never stored — see `deriveRoadmapItemStatus` in `derive.ts`. */
|
|
3
|
+
export type RoadmapItemStatus = "planned" | "in-progress" | "shipped" | "unresolved";
|
|
4
|
+
export interface Domain {
|
|
5
|
+
slug: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A user-managed ordering bucket for `RoadmapItem`s — "MVP", "Phase 1",
|
|
11
|
+
* "Backlog" — in the consumer's own words. No fixed vocabulary: this library
|
|
12
|
+
* ships zero opinion about what phases exist, the same as `Domain`. CRUD for
|
|
13
|
+
* this list lives in `PhaseManager`.
|
|
14
|
+
*/
|
|
15
|
+
export interface Phase {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
/** Display/sort order — lower sorts first. */
|
|
19
|
+
order: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RoadmapItem {
|
|
22
|
+
/** e.g. "RM-001". Monotonic, never reused — the consumer's concern to assign. */
|
|
23
|
+
ref: string;
|
|
24
|
+
title: string;
|
|
25
|
+
/** One-line, customer-safe summary — what renders on the public Roadmap card. */
|
|
26
|
+
summary?: string;
|
|
27
|
+
domainSlug: string;
|
|
28
|
+
/** The owning `Phase.id`. Required — every roadmap item belongs to exactly
|
|
29
|
+
one phase; there is no "no phase" state, the same as `domainSlug`. */
|
|
30
|
+
phaseId: string;
|
|
31
|
+
/** Gates whether this item (and its rollup status) appears on the public Roadmap. */
|
|
32
|
+
customerVisible: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface UseCaseDecision {
|
|
35
|
+
timestamp: string;
|
|
36
|
+
note: string;
|
|
37
|
+
}
|
|
38
|
+
export interface UseCase {
|
|
39
|
+
/** e.g. "UC-001". */
|
|
40
|
+
ref: string;
|
|
41
|
+
/** The parent RoadmapItem's `ref`. */
|
|
42
|
+
goalRef: string;
|
|
43
|
+
title: string;
|
|
44
|
+
description: string;
|
|
45
|
+
/** Long-form rationale — rendered collapsed by default. */
|
|
46
|
+
background?: string;
|
|
47
|
+
/** User-managed. Verified and Rejected are the only end states. */
|
|
48
|
+
status: UseCaseStatus;
|
|
49
|
+
/** Claude-managed. */
|
|
50
|
+
implemented: boolean;
|
|
51
|
+
implementedNote?: string;
|
|
52
|
+
/** Append-only decision log — caveats, reversals, "why it landed here". */
|
|
53
|
+
decisions?: UseCaseDecision[];
|
|
54
|
+
}
|