@stll/ui 0.6.0 → 0.7.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/README.md +20 -0
- package/dist/components/application-shell.d.ts +27 -0
- package/dist/components/application-shell.js +25 -0
- package/dist/components/button-variants.d.ts +2 -2
- package/dist/components/input-group.d.ts +1 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +10 -1
- package/dist/lib/initials.d.ts +16 -0
- package/dist/lib/initials.js +27 -0
- package/dist/review/review-author-avatar.d.ts +23 -0
- package/dist/review/review-author-avatar.js +30 -0
- package/dist/review/review-comment-card.d.ts +33 -0
- package/dist/review/review-comment-card.js +76 -0
- package/dist/review/review-decision-actions.d.ts +32 -0
- package/dist/review/review-decision-actions.js +74 -0
- package/dist/review/review-diff-text.d.ts +33 -0
- package/dist/review/review-diff-text.js +67 -0
- package/dist/review/review-out-of-date-notice.d.ts +28 -0
- package/dist/review/review-out-of-date-notice.js +32 -0
- package/dist/review/review-severity-dot.d.ts +27 -0
- package/dist/review/review-severity-dot.js +35 -0
- package/dist/review/review-status-badge.d.ts +30 -0
- package/dist/review/review-status-badge.js +45 -0
- package/package.json +41 -1
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ so a bundler keeps only what is imported:
|
|
|
20
20
|
|
|
21
21
|
```tsx
|
|
22
22
|
import { Button } from "@stll/ui/button";
|
|
23
|
+
import { ApplicationShell } from "@stll/ui/application-shell";
|
|
23
24
|
import { Dialog, DialogPopup } from "@stll/ui/dialog";
|
|
24
25
|
import { Inspector, InspectorDock } from "@stll/ui/inspector";
|
|
25
26
|
import { cn } from "@stll/ui/utils";
|
|
@@ -29,6 +30,25 @@ One flat subpath per module: `@stll/ui/<name>` for components, hooks, and
|
|
|
29
30
|
helpers alike. `@stll/ui` re-exports all of them under one specifier for
|
|
30
31
|
convenience; the subpaths are the real surface, and in-repo code uses those.
|
|
31
32
|
|
|
33
|
+
## Application shell
|
|
34
|
+
|
|
35
|
+
`ApplicationShell` keeps the navigation, page chrome and content, and an
|
|
36
|
+
optional inline-end inspector as sibling columns. Pass the host application's
|
|
37
|
+
surfaces as slots; route state, navigation behavior, and inspector behavior
|
|
38
|
+
remain in the host.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { ApplicationShell } from "@stll/ui/application-shell";
|
|
42
|
+
|
|
43
|
+
<ApplicationShell
|
|
44
|
+
header={<PageHeader />}
|
|
45
|
+
inspector={<InspectorDock />}
|
|
46
|
+
sidebar={<Navigation />}
|
|
47
|
+
>
|
|
48
|
+
<Page />
|
|
49
|
+
</ApplicationShell>;
|
|
50
|
+
```
|
|
51
|
+
|
|
32
52
|
### Deprecated grouped subpaths
|
|
33
53
|
|
|
34
54
|
`@stll/ui/components/<name>`, `@stll/ui/hooks/<name>`, and
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/components/application-shell.d.ts
|
|
3
|
+
type ApplicationShellProps = {
|
|
4
|
+
/**
|
|
5
|
+
* The application navigation surface. It stays a direct sibling of the
|
|
6
|
+
* content column so sidebar implementations can reserve their own width.
|
|
7
|
+
*/
|
|
8
|
+
sidebar: ReactNode;
|
|
9
|
+
/** The route chrome rendered above the application content. */
|
|
10
|
+
header?: ReactNode | undefined;
|
|
11
|
+
/** An optional dock or rail at the inline-end edge. */
|
|
12
|
+
inspector?: ReactNode | undefined;
|
|
13
|
+
/** The active route or page content. */
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
className?: string | undefined;
|
|
16
|
+
mainClassName?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The three-column application frame: navigation, page chrome and content,
|
|
20
|
+
* then an optional inline-end inspector. Product navigation, route state, and
|
|
21
|
+
* inspector behaviour stay in the host; this primitive only owns the layout
|
|
22
|
+
* relationship that lets those surfaces share a viewport without nesting one
|
|
23
|
+
* inside another.
|
|
24
|
+
*/
|
|
25
|
+
declare const ApplicationShell: ({ children, className, header, inspector, mainClassName, sidebar }: ApplicationShellProps) => import("react").JSX.Element;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { ApplicationShell, type ApplicationShellProps };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/application-shell.tsx
|
|
4
|
+
/**
|
|
5
|
+
* The three-column application frame: navigation, page chrome and content,
|
|
6
|
+
* then an optional inline-end inspector. Product navigation, route state, and
|
|
7
|
+
* inspector behaviour stay in the host; this primitive only owns the layout
|
|
8
|
+
* relationship that lets those surfaces share a viewport without nesting one
|
|
9
|
+
* inside another.
|
|
10
|
+
*/
|
|
11
|
+
const ApplicationShell = ({ children, className, header, inspector, mainClassName, sidebar }) => /* @__PURE__ */ jsxs("div", {
|
|
12
|
+
className: cn("flex min-h-svh w-full", className),
|
|
13
|
+
"data-slot": "application-shell",
|
|
14
|
+
children: [
|
|
15
|
+
sidebar,
|
|
16
|
+
/* @__PURE__ */ jsxs("main", {
|
|
17
|
+
className: cn("bg-background relative flex w-full flex-1 flex-col overflow-hidden", "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2", mainClassName),
|
|
18
|
+
"data-slot": "application-shell-main",
|
|
19
|
+
children: [header, children]
|
|
20
|
+
}),
|
|
21
|
+
inspector
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ApplicationShell };
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
|
|
12
12
|
declare const buttonVariants: (props?: ({
|
|
13
|
-
size?: "sm" | "
|
|
14
|
-
variant?: "
|
|
13
|
+
size?: "xs" | "sm" | "icon" | "default" | "lg" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "xl" | null | undefined;
|
|
14
|
+
variant?: "destructive" | "outline" | "link" | "default" | "destructive-outline" | "ghost" | "secondary" | null | undefined;
|
|
15
15
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
16
16
|
//#endregion
|
|
17
17
|
export { buttonAccessibleDisabledClass, buttonVariants };
|
|
@@ -5,7 +5,7 @@ import * as React$1 from "react";
|
|
|
5
5
|
//#region src/components/input-group.d.ts
|
|
6
6
|
declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
|
7
7
|
declare const inputGroupAddonVariants: (props?: ({
|
|
8
|
-
align?: "inline-end" | "inline-start" | "block-
|
|
8
|
+
align?: "inline-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
|
|
9
9
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
10
|
declare const InputGroupAddon: ({ className, align, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) => React$1.JSX.Element;
|
|
11
11
|
declare const InputGroupText: ({ className, ...props }: React$1.ComponentProps<"span">) => React$1.JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import "./calendar/index.js";
|
|
|
5
5
|
import { Accordion, AccordionContent as AccordionPanel, AccordionItem, AccordionTrigger } from "./components/accordion.js";
|
|
6
6
|
import { OVERLAY_LAYER_CLASS_NAMES, OverlayLayer } from "./lib/overlay-layer.js";
|
|
7
7
|
import { AlertDialog, AlertDialogBackdrop, AlertDialogClose, AlertDialogContent as AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport } from "./components/alert-dialog.js";
|
|
8
|
+
import { ApplicationShell, ApplicationShellProps } from "./components/application-shell.js";
|
|
8
9
|
import { Avatar, AvatarFallback, AvatarImage } from "./components/avatar.js";
|
|
9
10
|
import { BidiDirection, BidiText, BidiTextProps, UserText } from "./components/bidi-text.js";
|
|
10
11
|
import { DiscordLogoIcon, GitHubLogoIcon } from "./components/brand-icons.js";
|
|
@@ -72,6 +73,14 @@ import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, RegisterKanbanBoardAutoScrollOptions,
|
|
|
72
73
|
import { ColorVariants, OptionColor, emptyColor, optionColors, resolveOptionColor } from "./lib/option-color.js";
|
|
73
74
|
import { KanbanBuiltInGroup, KanbanGroup, KanbanGroupOption, KanbanGrouping, KanbanSchema, ResolveKanbanGroupingParams, getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./kanban/grouping.js";
|
|
74
75
|
import "./kanban/index.js";
|
|
76
|
+
import { getInitials } from "./lib/initials.js";
|
|
75
77
|
import { cn, composeRefs } from "./lib/utils.js";
|
|
76
78
|
import { getFirstWeekday, getLocaleWeekInfo, getWeekendDays } from "./lib/week.js";
|
|
77
|
-
|
|
79
|
+
import { ReviewAuthorAvatar, UNKNOWN_AUTHOR_LABEL } from "./review/review-author-avatar.js";
|
|
80
|
+
import { ReviewCommentAuthor, ReviewCommentCard } from "./review/review-comment-card.js";
|
|
81
|
+
import { ReviewDecisionActions, ReviewDecisionSize, ReviewDecisionState } from "./review/review-decision-actions.js";
|
|
82
|
+
import { ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffSegment, ReviewDiffSegmentType, ReviewDiffText, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, reviewDiffSegmentKeys } from "./review/review-diff-text.js";
|
|
83
|
+
import { ReviewOutOfDateNotice, ReviewOutOfDateReason, ReviewOutOfDateTone } from "./review/review-out-of-date-notice.js";
|
|
84
|
+
import { ReviewStatusBadge, ReviewStatusSize, ReviewStatusTone, ReviewStatusVariant } from "./review/review-status-badge.js";
|
|
85
|
+
import { ReviewSeverityDot, ReviewSeverityLevel, ReviewStatusDot, reviewSeverityTone } from "./review/review-severity-dot.js";
|
|
86
|
+
export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, ApplicationShell, type ApplicationShellProps, Avatar, AvatarFallback, AvatarImage, type BidiDirection, BidiText, type BidiTextProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, type CalendarDateRange, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, type ColorPickerContentProps, type ColorPickerProps, type ColorPreset, ColorVariants, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, type DataTableAriaSort, type DataTableColumn, type DataTableProps, type DataTableRowAction, DatePickerPopover, type DatePickerPopoverProps, DestructiveActionConfirmation, DestructiveConfirmDialog, type DestructiveConfirmDialogProps, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, type HexColorPickerProps, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, type KanbanBuiltInGroup, type KanbanCardFieldSelection, KanbanCardShell, type KanbanCardShellProps, KanbanColumnHeader, type KanbanColumnHeaderProps, type KanbanDirection, KanbanDragHandle, type KanbanDragHandleProps, type KanbanGroup, type KanbanGroupOption, type KanbanGrouping, type KanbanHorizontalEdge, type KanbanSchema, type KanbanSortableBindings, KanbanSortableBoard, type KanbanSortableBoardProps, KanbanSortableColumns, type KanbanSortableColumnsProps, KanbanSortableList, type KanbanSortableListProps, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OptionColor, OutlineItem, OutlineRail, OutlineRailProps, OverlayLayer, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, type RegisterKanbanBoardAutoScrollOptions, type RegisterKanbanCardDragOptions, type ResolveKanbanGroupingParams, ResourceCalendar, type ResourceCalendarColumn, type ResourceCalendarEntry, type ResourceCalendarEntryTone, type ResourceCalendarLaneLayout, type ResourceCalendarLanePlacement, type ResourceCalendarPlacement, type ResourceCalendarResource, ReviewAuthorAvatar, ReviewCommentAuthor, ReviewCommentCard, ReviewDecisionActions, ReviewDecisionSize, ReviewDecisionState, ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffSegment, ReviewDiffSegmentType, ReviewDiffText, ReviewOutOfDateNotice, ReviewOutOfDateReason, ReviewOutOfDateTone, ReviewSeverityDot, ReviewSeverityLevel, ReviewStatusBadge, ReviewStatusDot, ReviewStatusSize, ReviewStatusTone, ReviewStatusVariant, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, ScrollToTopProps, SecretInput, type SecretInputProps, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, type SheetSide, SheetTitle, SheetTrigger, Skeleton, type SortDirection, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, Table, TableBody, TableCaption, TableCell, type TableColumnCapabilities, type TableColumnDescriptor, TableFooter, TableHead, TableHeader, TableRow, type TableSchema, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, type TextareaProps, type ToastPosition, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, UNKNOWN_AUTHOR_LABEL, type UseKanbanSortableOptions, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getInitials, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, reviewDiffSegmentKeys, reviewSeverityTone, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useKanbanSortable, useKanbanSortableSensors, useLatest, useViewportWidth, visibleColumnIds };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { Accordion, AccordionContent as AccordionPanel, AccordionItem, Accordion
|
|
|
3
3
|
import { OVERLAY_LAYER_CLASS_NAMES } from "./lib/overlay-layer.js";
|
|
4
4
|
import { Tooltip, TooltipContent as TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger } from "./components/tooltip.js";
|
|
5
5
|
import { AlertDialog, AlertDialogBackdrop, AlertDialogClose, AlertDialogContent as AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport } from "./components/alert-dialog.js";
|
|
6
|
+
import { ApplicationShell } from "./components/application-shell.js";
|
|
6
7
|
import { Avatar, AvatarFallback, AvatarImage } from "./components/avatar.js";
|
|
7
8
|
import { BidiText, UserText } from "./components/bidi-text.js";
|
|
8
9
|
import { DiscordLogoIcon, GitHubLogoIcon } from "./components/brand-icons.js";
|
|
@@ -69,5 +70,13 @@ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, K
|
|
|
69
70
|
import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, getKanbanHorizontalEdge } from "./kanban/sortable-edge.js";
|
|
70
71
|
import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./kanban/drag-interactions.js";
|
|
71
72
|
import { getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./kanban/grouping.js";
|
|
73
|
+
import { getInitials } from "./lib/initials.js";
|
|
72
74
|
import { emptyColor, optionColors, resolveOptionColor } from "./lib/option-color.js";
|
|
73
|
-
|
|
75
|
+
import { ReviewAuthorAvatar, UNKNOWN_AUTHOR_LABEL } from "./review/review-author-avatar.js";
|
|
76
|
+
import { ReviewCommentCard } from "./review/review-comment-card.js";
|
|
77
|
+
import { ReviewDecisionActions } from "./review/review-decision-actions.js";
|
|
78
|
+
import { ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffText, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, reviewDiffSegmentKeys } from "./review/review-diff-text.js";
|
|
79
|
+
import { ReviewOutOfDateNotice } from "./review/review-out-of-date-notice.js";
|
|
80
|
+
import { ReviewSeverityDot, ReviewStatusDot, reviewSeverityTone } from "./review/review-severity-dot.js";
|
|
81
|
+
import { ReviewStatusBadge } from "./review/review-status-badge.js";
|
|
82
|
+
export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, ApplicationShell, Avatar, AvatarFallback, AvatarImage, BidiText, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, DatePickerPopover, DestructiveActionConfirmation, DestructiveConfirmDialog, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanCardShell, KanbanColumnHeader, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OutlineRail, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, ResourceCalendar, ReviewAuthorAvatar, ReviewCommentCard, ReviewDecisionActions, ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffText, ReviewOutOfDateNotice, ReviewSeverityDot, ReviewStatusBadge, ReviewStatusDot, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, SecretInput, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, SheetTitle, SheetTrigger, Skeleton, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, UNKNOWN_AUTHOR_LABEL, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getInitials, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, reviewDiffSegmentKeys, reviewSeverityTone, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useKanbanSortable, useKanbanSortableSensors, useLatest, useViewportWidth, visibleColumnIds };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/lib/initials.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract up to two uppercase initials from a display name.
|
|
4
|
+
*
|
|
5
|
+
* Behaviour:
|
|
6
|
+
* - Multi-word: first letter of each of the first two words.
|
|
7
|
+
* "Eva Schmidt" → "ES", "Jan van Houten" → "JV"
|
|
8
|
+
* - Single-word (Latin): first two characters.
|
|
9
|
+
* "John" → "JO"
|
|
10
|
+
* - CJK / no-space scripts: first two characters.
|
|
11
|
+
* "王小明" → "王小"
|
|
12
|
+
* - Null / empty: "?"
|
|
13
|
+
*/
|
|
14
|
+
declare const getInitials: (name: string | null) => string;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { getInitials };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/lib/initials.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract up to two uppercase initials from a display name.
|
|
4
|
+
*
|
|
5
|
+
* Behaviour:
|
|
6
|
+
* - Multi-word: first letter of each of the first two words.
|
|
7
|
+
* "Eva Schmidt" → "ES", "Jan van Houten" → "JV"
|
|
8
|
+
* - Single-word (Latin): first two characters.
|
|
9
|
+
* "John" → "JO"
|
|
10
|
+
* - CJK / no-space scripts: first two characters.
|
|
11
|
+
* "王小明" → "王小"
|
|
12
|
+
* - Null / empty: "?"
|
|
13
|
+
*/
|
|
14
|
+
const getInitials = (name) => {
|
|
15
|
+
if (!name) return "?";
|
|
16
|
+
const trimmed = name.trim();
|
|
17
|
+
if (trimmed.length === 0) return "?";
|
|
18
|
+
const parts = trimmed.split(/\s+/u);
|
|
19
|
+
if (parts.length >= 2) {
|
|
20
|
+
const a = parts.at(0) ?? "";
|
|
21
|
+
const b = parts.at(1) ?? "";
|
|
22
|
+
return `${a.at(0) ?? ""}${b.at(0) ?? ""}`.toUpperCase();
|
|
23
|
+
}
|
|
24
|
+
return trimmed.slice(0, 2).toUpperCase();
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { getInitials };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Avatar } from "../components/avatar.js";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
//#region src/review/review-author-avatar.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shown when an author has neither a name nor anything to fall back on. This
|
|
6
|
+
* package carries no catalogs, so a localized host passes `fallbackLabel`;
|
|
7
|
+
* the constant is exported so every surface that needs the same placeholder
|
|
8
|
+
* outside an avatar reads it from here rather than minting its own.
|
|
9
|
+
*/
|
|
10
|
+
declare const UNKNOWN_AUTHOR_LABEL = "Unknown user";
|
|
11
|
+
type ReviewAuthorAvatarProps = Omit<ComponentProps<typeof Avatar>, "children" | "className"> & {
|
|
12
|
+
image?: string | null | undefined;
|
|
13
|
+
name?: string | null;
|
|
14
|
+
deleted?: boolean | undefined;
|
|
15
|
+
fallbackLabel?: string;
|
|
16
|
+
className?: string | undefined;
|
|
17
|
+
fallbackClassName?: string | undefined;
|
|
18
|
+
};
|
|
19
|
+
/** The author's face on any review surface: image when there is one, initials
|
|
20
|
+
* otherwise, dimmed once the account is gone. */
|
|
21
|
+
declare const ReviewAuthorAvatar: ({ deleted, image, name, fallbackLabel, className, fallbackClassName, ...avatarProps }: ReviewAuthorAvatarProps) => import("react").JSX.Element;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ReviewAuthorAvatar, UNKNOWN_AUTHOR_LABEL };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Avatar, AvatarFallback, AvatarImage } from "../components/avatar.js";
|
|
3
|
+
import { getInitials } from "../lib/initials.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/review/review-author-avatar.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Shown when an author has neither a name nor anything to fall back on. This
|
|
8
|
+
* package carries no catalogs, so a localized host passes `fallbackLabel`;
|
|
9
|
+
* the constant is exported so every surface that needs the same placeholder
|
|
10
|
+
* outside an avatar reads it from here rather than minting its own.
|
|
11
|
+
*/
|
|
12
|
+
const UNKNOWN_AUTHOR_LABEL = "Unknown user";
|
|
13
|
+
/** The author's face on any review surface: image when there is one, initials
|
|
14
|
+
* otherwise, dimmed once the account is gone. */
|
|
15
|
+
const ReviewAuthorAvatar = ({ deleted = false, image, name, fallbackLabel = UNKNOWN_AUTHOR_LABEL, className, fallbackClassName, ...avatarProps }) => {
|
|
16
|
+
const displayName = name?.trim() || fallbackLabel;
|
|
17
|
+
return /* @__PURE__ */ jsxs(Avatar, {
|
|
18
|
+
...avatarProps,
|
|
19
|
+
className: cn(className, deleted && "opacity-60 grayscale"),
|
|
20
|
+
children: [image ? /* @__PURE__ */ jsx(AvatarImage, {
|
|
21
|
+
alt: displayName,
|
|
22
|
+
src: image
|
|
23
|
+
}) : null, /* @__PURE__ */ jsx(AvatarFallback, {
|
|
24
|
+
className: cn(fallbackClassName, deleted && "bg-muted text-muted-foreground"),
|
|
25
|
+
children: getInitials(name ?? null)
|
|
26
|
+
})]
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { ReviewAuthorAvatar, UNKNOWN_AUTHOR_LABEL };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/review/review-comment-card.d.ts
|
|
3
|
+
type ReviewCommentAuthor = {
|
|
4
|
+
name: string | null;
|
|
5
|
+
image?: string | null | undefined;
|
|
6
|
+
deleted?: boolean | undefined;
|
|
7
|
+
};
|
|
8
|
+
type ReviewCommentCardProps = {
|
|
9
|
+
author: ReviewCommentAuthor;
|
|
10
|
+
/** Machine-readable instant for `<time>`; ISO string or Date. */
|
|
11
|
+
timestamp: string | Date;
|
|
12
|
+
/** The same instant, already formatted by the host's locale formatter. */
|
|
13
|
+
formattedTime: string;
|
|
14
|
+
body: ReactNode;
|
|
15
|
+
/** The text the comment was written against, when it is worth echoing. */
|
|
16
|
+
anchorText?: string | undefined;
|
|
17
|
+
/** The comment is anchored to text the document has since moved past. */
|
|
18
|
+
isStale?: boolean | undefined;
|
|
19
|
+
staleLabel?: string | undefined;
|
|
20
|
+
resolved?: boolean | undefined;
|
|
21
|
+
onToggleResolved?: (() => void) | undefined;
|
|
22
|
+
resolveLabel?: string | undefined;
|
|
23
|
+
reopenLabel?: string | undefined;
|
|
24
|
+
canDelete?: boolean | undefined;
|
|
25
|
+
onDelete?: (() => void) | undefined;
|
|
26
|
+
deleteLabel?: string | undefined;
|
|
27
|
+
className?: string;
|
|
28
|
+
};
|
|
29
|
+
/** One comment on a reviewed surface: who wrote it, when, what it says, what
|
|
30
|
+
* it points at, and the two things a reader can do to it. */
|
|
31
|
+
declare const ReviewCommentCard: ({ author, timestamp, formattedTime, body, anchorText, isStale, staleLabel, resolved, onToggleResolved, resolveLabel, reopenLabel, canDelete, onDelete, deleteLabel, className }: ReviewCommentCardProps) => import("react").JSX.Element;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ReviewCommentAuthor, ReviewCommentCard };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { BidiText } from "../components/bidi-text.js";
|
|
3
|
+
import { Button } from "../components/button.js";
|
|
4
|
+
import { ReviewAuthorAvatar } from "./review-author-avatar.js";
|
|
5
|
+
import { CheckIcon, RotateCcwIcon, Trash2Icon } from "lucide-react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/review/review-comment-card.tsx
|
|
8
|
+
/** One comment on a reviewed surface: who wrote it, when, what it says, what
|
|
9
|
+
* it points at, and the two things a reader can do to it. */
|
|
10
|
+
const ReviewCommentCard = ({ author, timestamp, formattedTime, body, anchorText, isStale = false, staleLabel, resolved = false, onToggleResolved, resolveLabel, reopenLabel, canDelete = false, onDelete, deleteLabel, className }) => /* @__PURE__ */ jsxs("article", {
|
|
11
|
+
className: cn("flex items-start gap-2 px-3 py-2", resolved && "opacity-60", className),
|
|
12
|
+
"data-slot": "review-comment-card",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsx(ReviewAuthorAvatar, {
|
|
15
|
+
className: "mt-0.5 size-5 shrink-0 text-[9px]",
|
|
16
|
+
deleted: author.deleted,
|
|
17
|
+
image: author.image,
|
|
18
|
+
name: author.name
|
|
19
|
+
}),
|
|
20
|
+
/* @__PURE__ */ jsxs("div", {
|
|
21
|
+
className: "min-w-0 flex-1",
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsxs("p", {
|
|
24
|
+
className: "text-muted-foreground flex min-w-0 items-baseline gap-1.5 text-[11px]",
|
|
25
|
+
children: [/* @__PURE__ */ jsx(BidiText, {
|
|
26
|
+
as: "span",
|
|
27
|
+
className: "text-foreground-strong-muted truncate font-medium",
|
|
28
|
+
children: author.name
|
|
29
|
+
}), /* @__PURE__ */ jsx("time", {
|
|
30
|
+
className: "shrink-0 tabular-nums",
|
|
31
|
+
dateTime: toIsoInstant(timestamp),
|
|
32
|
+
children: formattedTime
|
|
33
|
+
})]
|
|
34
|
+
}),
|
|
35
|
+
/* @__PURE__ */ jsx(BidiText, {
|
|
36
|
+
as: "div",
|
|
37
|
+
className: "text-foreground text-xs wrap-anywhere",
|
|
38
|
+
children: body
|
|
39
|
+
}),
|
|
40
|
+
anchorText === void 0 || anchorText === "" ? null : /* @__PURE__ */ jsx(BidiText, {
|
|
41
|
+
as: "p",
|
|
42
|
+
className: "text-muted-foreground mt-0.5 truncate text-[11px] italic",
|
|
43
|
+
children: anchorText
|
|
44
|
+
}),
|
|
45
|
+
isStale && staleLabel !== void 0 ? /* @__PURE__ */ jsx("p", {
|
|
46
|
+
className: "text-muted-foreground mt-0.5 text-[11px]",
|
|
47
|
+
children: staleLabel
|
|
48
|
+
}) : null
|
|
49
|
+
]
|
|
50
|
+
}),
|
|
51
|
+
/* @__PURE__ */ jsxs("div", {
|
|
52
|
+
className: "flex shrink-0 items-center gap-0.5",
|
|
53
|
+
children: [onToggleResolved === void 0 ? null : /* @__PURE__ */ jsx(Button, {
|
|
54
|
+
"aria-label": resolved ? reopenLabel : resolveLabel,
|
|
55
|
+
onClick: onToggleResolved,
|
|
56
|
+
size: "icon-xs",
|
|
57
|
+
variant: "ghost",
|
|
58
|
+
children: resolved ? /* @__PURE__ */ jsx(RotateCcwIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {})
|
|
59
|
+
}), canDelete && onDelete !== void 0 ? /* @__PURE__ */ jsx(Button, {
|
|
60
|
+
"aria-label": deleteLabel,
|
|
61
|
+
onClick: onDelete,
|
|
62
|
+
size: "icon-xs",
|
|
63
|
+
variant: "ghost",
|
|
64
|
+
children: /* @__PURE__ */ jsx(Trash2Icon, {})
|
|
65
|
+
}) : null]
|
|
66
|
+
})
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
/** `<time dateTime>` wants a machine-readable instant. An unparseable date
|
|
70
|
+
* yields no attribute rather than throwing on `toISOString`. */
|
|
71
|
+
const toIsoInstant = (timestamp) => {
|
|
72
|
+
if (typeof timestamp === "string") return timestamp;
|
|
73
|
+
return Number.isNaN(timestamp.getTime()) ? void 0 : timestamp.toISOString();
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { ReviewCommentCard };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/review/review-decision-actions.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Where a reviewable item stands. Undecided items offer accept/reject;
|
|
5
|
+
* decided ones offer the way back (revert the applied change, or reopen the
|
|
6
|
+
* decision). `applying` is undecided but in flight: the same pair, inert,
|
|
7
|
+
* so the row does not resize while the write lands.
|
|
8
|
+
*/
|
|
9
|
+
type ReviewDecisionState = "pending" | "accepted" | "rejected" | "dismissed" | "applying";
|
|
10
|
+
type ReviewDecisionSize = "xs" | "sm";
|
|
11
|
+
type ReviewDecisionActionsProps = {
|
|
12
|
+
state: ReviewDecisionState;
|
|
13
|
+
onAccept?: (() => void) | undefined;
|
|
14
|
+
onReject?: (() => void) | undefined;
|
|
15
|
+
onRevert?: (() => void) | undefined;
|
|
16
|
+
onReopen?: (() => void) | undefined;
|
|
17
|
+
size?: ReviewDecisionSize;
|
|
18
|
+
/** Labels are supplied by the host: this package carries no catalogs. */
|
|
19
|
+
acceptLabel?: ReactNode;
|
|
20
|
+
rejectLabel?: ReactNode;
|
|
21
|
+
revertLabel?: ReactNode;
|
|
22
|
+
/** Accessible name for the icon-only reopen control. */
|
|
23
|
+
reopenLabel?: string | undefined;
|
|
24
|
+
acceptTooltip?: ReactNode;
|
|
25
|
+
rejectTooltip?: ReactNode;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
className?: string;
|
|
28
|
+
};
|
|
29
|
+
/** Accept / reject / revert / reopen, in one shape, for every review surface. */
|
|
30
|
+
declare const ReviewDecisionActions: ({ state, onAccept, onReject, onRevert, onReopen, size, acceptLabel, rejectLabel, revertLabel, reopenLabel, acceptTooltip, rejectTooltip, disabled, className }: ReviewDecisionActionsProps) => import("react").JSX.Element | null;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ReviewDecisionActions, ReviewDecisionSize, ReviewDecisionState };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Button } from "../components/button.js";
|
|
3
|
+
import { CheckIcon, RotateCcwIcon, XIcon } from "lucide-react";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/review/review-decision-actions.tsx
|
|
6
|
+
/** Accept / reject / revert / reopen, in one shape, for every review surface. */
|
|
7
|
+
const ReviewDecisionActions = ({ state, onAccept, onReject, onRevert, onReopen, size = "sm", acceptLabel, rejectLabel, revertLabel, reopenLabel, acceptTooltip, rejectTooltip, disabled = false, className }) => {
|
|
8
|
+
const controls = renderControls({
|
|
9
|
+
acceptLabel,
|
|
10
|
+
acceptTooltip,
|
|
11
|
+
disabled,
|
|
12
|
+
onAccept,
|
|
13
|
+
onReject,
|
|
14
|
+
onReopen,
|
|
15
|
+
onRevert,
|
|
16
|
+
rejectLabel,
|
|
17
|
+
rejectTooltip,
|
|
18
|
+
reopenLabel,
|
|
19
|
+
revertLabel,
|
|
20
|
+
size,
|
|
21
|
+
state
|
|
22
|
+
});
|
|
23
|
+
if (controls === null) return null;
|
|
24
|
+
return /* @__PURE__ */ jsx("div", {
|
|
25
|
+
className: cn("flex items-center gap-1.5", className),
|
|
26
|
+
"data-slot": "review-decision-actions",
|
|
27
|
+
children: controls
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const renderControls = ({ acceptLabel, acceptTooltip, disabled, onAccept, onReject, onReopen, onRevert, rejectLabel, rejectTooltip, reopenLabel, revertLabel, size, state }) => {
|
|
31
|
+
switch (state) {
|
|
32
|
+
case "pending":
|
|
33
|
+
case "applying": {
|
|
34
|
+
const inert = disabled || state === "applying";
|
|
35
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [onAccept === void 0 ? null : /* @__PURE__ */ jsxs(Button, {
|
|
36
|
+
disabled: inert,
|
|
37
|
+
onClick: onAccept,
|
|
38
|
+
size,
|
|
39
|
+
tooltip: acceptTooltip,
|
|
40
|
+
variant: "default",
|
|
41
|
+
children: [/* @__PURE__ */ jsx(CheckIcon, {}), acceptLabel]
|
|
42
|
+
}), onReject === void 0 ? null : /* @__PURE__ */ jsxs(Button, {
|
|
43
|
+
disabled: inert,
|
|
44
|
+
onClick: onReject,
|
|
45
|
+
size,
|
|
46
|
+
tooltip: rejectTooltip,
|
|
47
|
+
variant: "outline",
|
|
48
|
+
children: [/* @__PURE__ */ jsx(XIcon, {}), rejectLabel]
|
|
49
|
+
})] });
|
|
50
|
+
}
|
|
51
|
+
case "accepted":
|
|
52
|
+
case "rejected":
|
|
53
|
+
case "dismissed":
|
|
54
|
+
if (onRevert === void 0 && onReopen === void 0) return null;
|
|
55
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [onRevert === void 0 ? null : /* @__PURE__ */ jsx(Button, {
|
|
56
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
57
|
+
disabled,
|
|
58
|
+
onClick: onRevert,
|
|
59
|
+
size,
|
|
60
|
+
variant: "ghost",
|
|
61
|
+
children: revertLabel
|
|
62
|
+
}), onReopen === void 0 ? null : /* @__PURE__ */ jsx(Button, {
|
|
63
|
+
"aria-label": reopenLabel,
|
|
64
|
+
disabled,
|
|
65
|
+
onClick: onReopen,
|
|
66
|
+
size: size === "xs" ? "icon-xs" : "icon-sm",
|
|
67
|
+
variant: "ghost",
|
|
68
|
+
children: /* @__PURE__ */ jsx(RotateCcwIcon, {})
|
|
69
|
+
})] });
|
|
70
|
+
default: return null;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { ReviewDecisionActions };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode } from "react";
|
|
2
|
+
//#region src/review/review-diff-text.d.ts
|
|
3
|
+
declare const TRACKED_DELETION_STYLE: CSSProperties;
|
|
4
|
+
declare const TRACKED_INSERTION_STYLE: CSSProperties;
|
|
5
|
+
type ReviewDiffSegmentType = "equal" | "insert" | "delete";
|
|
6
|
+
type ReviewDiffSegment = {
|
|
7
|
+
type: ReviewDiffSegmentType;
|
|
8
|
+
text: string;
|
|
9
|
+
};
|
|
10
|
+
type ReviewDiffProps = {
|
|
11
|
+
className?: string;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
/** Inserted text, wherever it is shown. */
|
|
15
|
+
declare const ReviewDiffInsertion: ({ className, children }: ReviewDiffProps) => import("react").JSX.Element;
|
|
16
|
+
/** Deleted text, wherever it is shown. */
|
|
17
|
+
declare const ReviewDiffDeletion: ({ className, children }: ReviewDiffProps) => import("react").JSX.Element;
|
|
18
|
+
type ReviewDiffTextProps = {
|
|
19
|
+
segments: readonly ReviewDiffSegment[];
|
|
20
|
+
className?: string;
|
|
21
|
+
};
|
|
22
|
+
/** A word-level diff rendered inline, in the product's one track-changes
|
|
23
|
+
* language. */
|
|
24
|
+
declare const ReviewDiffText: ({ segments, className }: ReviewDiffTextProps) => import("react").JSX.Element;
|
|
25
|
+
/**
|
|
26
|
+
* A stable render key per segment. Type and text alone repeat inside a single
|
|
27
|
+
* diff (the same word deleted twice), so each repetition carries its
|
|
28
|
+
* occurrence count; the result is stable across renders of the same diff and
|
|
29
|
+
* never falls back to the array index.
|
|
30
|
+
*/
|
|
31
|
+
declare const reviewDiffSegmentKeys: (segments: readonly ReviewDiffSegment[]) => string[];
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffSegment, ReviewDiffSegmentType, ReviewDiffText, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, reviewDiffSegmentKeys };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/review/review-diff-text.tsx
|
|
4
|
+
const TRACKED_DELETION_STYLE = {
|
|
5
|
+
color: "color-mix(in oklch, var(--destructive) 35%, var(--muted-foreground))",
|
|
6
|
+
textDecorationLine: "line-through",
|
|
7
|
+
textDecorationThickness: "1px",
|
|
8
|
+
textDecorationColor: "color-mix(in oklch, var(--destructive) 30%, var(--muted-foreground))"
|
|
9
|
+
};
|
|
10
|
+
const TRACKED_INSERTION_STYLE = {
|
|
11
|
+
borderRadius: "3px",
|
|
12
|
+
padding: "0 2px",
|
|
13
|
+
backgroundColor: "color-mix(in oklch, var(--success) 14%, transparent)",
|
|
14
|
+
boxShadow: "inset 0 0 0 1px color-mix(in oklch, var(--success) 28%, transparent)",
|
|
15
|
+
textDecorationLine: "none",
|
|
16
|
+
boxDecorationBreak: "clone",
|
|
17
|
+
WebkitBoxDecorationBreak: "clone"
|
|
18
|
+
};
|
|
19
|
+
/** Inserted text, wherever it is shown. */
|
|
20
|
+
const ReviewDiffInsertion = ({ className, children }) => /* @__PURE__ */ jsx("ins", {
|
|
21
|
+
className,
|
|
22
|
+
style: TRACKED_INSERTION_STYLE,
|
|
23
|
+
children
|
|
24
|
+
});
|
|
25
|
+
/** Deleted text, wherever it is shown. */
|
|
26
|
+
const ReviewDiffDeletion = ({ className, children }) => /* @__PURE__ */ jsx("del", {
|
|
27
|
+
className,
|
|
28
|
+
style: TRACKED_DELETION_STYLE,
|
|
29
|
+
children
|
|
30
|
+
});
|
|
31
|
+
/** A word-level diff rendered inline, in the product's one track-changes
|
|
32
|
+
* language. */
|
|
33
|
+
const ReviewDiffText = ({ segments, className }) => {
|
|
34
|
+
const keys = reviewDiffSegmentKeys(segments);
|
|
35
|
+
return /* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: cn(className),
|
|
37
|
+
"data-slot": "review-diff-text",
|
|
38
|
+
children: segments.map((segment, index) => /* @__PURE__ */ jsx(ReviewDiffSegmentSpan, { segment }, keys[index]))
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* A stable render key per segment. Type and text alone repeat inside a single
|
|
43
|
+
* diff (the same word deleted twice), so each repetition carries its
|
|
44
|
+
* occurrence count; the result is stable across renders of the same diff and
|
|
45
|
+
* never falls back to the array index.
|
|
46
|
+
*/
|
|
47
|
+
const reviewDiffSegmentKeys = (segments) => {
|
|
48
|
+
const seen = /* @__PURE__ */ new Map();
|
|
49
|
+
return segments.map((segment) => {
|
|
50
|
+
const base = `${segment.type}-${segment.text}`;
|
|
51
|
+
const occurrence = seen.get(base) ?? 0;
|
|
52
|
+
seen.set(base, occurrence + 1);
|
|
53
|
+
return `${base}-${occurrence}`;
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const ReviewDiffSegmentSpan = ({ segment }) => {
|
|
57
|
+
switch (segment.type) {
|
|
58
|
+
case "insert": return /* @__PURE__ */ jsx(ReviewDiffInsertion, { children: segment.text });
|
|
59
|
+
case "delete": return /* @__PURE__ */ jsx(ReviewDiffDeletion, { children: segment.text });
|
|
60
|
+
case "equal": return /* @__PURE__ */ jsx("span", { children: segment.text });
|
|
61
|
+
default:
|
|
62
|
+
segment.type;
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
export { ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffText, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, reviewDiffSegmentKeys };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/review/review-out-of-date-notice.d.ts
|
|
3
|
+
type ReviewOutOfDateTone = "warning" | "muted";
|
|
4
|
+
/**
|
|
5
|
+
* One reason a review has fallen behind. Carries its own key so the list is
|
|
6
|
+
* never rendered by array index: reasons come and go independently (the
|
|
7
|
+
* document changed, the playbook moved on, the source was deleted) and each
|
|
8
|
+
* one has a stable identity at its call site.
|
|
9
|
+
*/
|
|
10
|
+
type ReviewOutOfDateReason = {
|
|
11
|
+
id: string;
|
|
12
|
+
label: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
type ReviewOutOfDateNoticeProps = {
|
|
15
|
+
reasons: readonly ReviewOutOfDateReason[];
|
|
16
|
+
actionLabel?: ReactNode;
|
|
17
|
+
onAction?: (() => void) | undefined;
|
|
18
|
+
tone?: ReviewOutOfDateTone;
|
|
19
|
+
className?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* What a review no longer reflects. Every applicable reason is listed
|
|
23
|
+
* together: they are different reasons to run again, and a reviewer working
|
|
24
|
+
* through findings should see each one rather than the first.
|
|
25
|
+
*/
|
|
26
|
+
declare const ReviewOutOfDateNotice: ({ reasons, actionLabel, onAction, tone, className }: ReviewOutOfDateNoticeProps) => import("react").JSX.Element | null;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { ReviewOutOfDateNotice, ReviewOutOfDateReason, ReviewOutOfDateTone };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Button } from "../components/button.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/review/review-out-of-date-notice.tsx
|
|
5
|
+
/**
|
|
6
|
+
* What a review no longer reflects. Every applicable reason is listed
|
|
7
|
+
* together: they are different reasons to run again, and a reviewer working
|
|
8
|
+
* through findings should see each one rather than the first.
|
|
9
|
+
*/
|
|
10
|
+
const ReviewOutOfDateNotice = ({ reasons, actionLabel, onAction, tone = "warning", className }) => {
|
|
11
|
+
if (reasons.length === 0) return null;
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
className: cn("mb-2 rounded-lg border px-3 py-2", TONE_CLASS[tone], className),
|
|
14
|
+
"data-slot": "review-out-of-date-notice",
|
|
15
|
+
children: [/* @__PURE__ */ jsx("ul", {
|
|
16
|
+
className: "space-y-1 text-xs",
|
|
17
|
+
children: reasons.map((reason) => /* @__PURE__ */ jsx("li", { children: reason.label }, reason.id))
|
|
18
|
+
}), onAction === void 0 ? null : /* @__PURE__ */ jsx(Button, {
|
|
19
|
+
className: "mt-2",
|
|
20
|
+
onClick: onAction,
|
|
21
|
+
size: "xs",
|
|
22
|
+
variant: "outline",
|
|
23
|
+
children: actionLabel
|
|
24
|
+
})]
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const TONE_CLASS = {
|
|
28
|
+
warning: "border-warning/30 bg-warning/10 text-warning-foreground",
|
|
29
|
+
muted: "border-border bg-muted/50 text-muted-foreground"
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ReviewOutOfDateNotice };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ReviewStatusTone } from "./review-status-badge.js";
|
|
2
|
+
//#region src/review/review-severity-dot.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* How bad a finding is, on the one scale every review surface reports against.
|
|
5
|
+
* Vocabularies that stop short of five levels (a playbook's blocker/high/
|
|
6
|
+
* medium/low, a suggestion's high/medium/low/unspecified) map onto this at
|
|
7
|
+
* their call site rather than growing a palette of their own.
|
|
8
|
+
*/
|
|
9
|
+
type ReviewSeverityLevel = "critical" | "high" | "medium" | "low" | "none";
|
|
10
|
+
type ReviewSeverityDotProps = {
|
|
11
|
+
level: ReviewSeverityLevel;
|
|
12
|
+
className?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
/** The dot that precedes a severity label, and the one place a severity level
|
|
15
|
+
* turns into a colour. */
|
|
16
|
+
declare const ReviewSeverityDot: ({ level, className }: ReviewSeverityDotProps) => import("react").JSX.Element;
|
|
17
|
+
type ReviewStatusDotProps = {
|
|
18
|
+
tone: ReviewStatusTone;
|
|
19
|
+
className?: string | undefined;
|
|
20
|
+
};
|
|
21
|
+
/** The same dot keyed by tone, for vocabularies that are not severities
|
|
22
|
+
* (verdicts, directed impact, comparison assessments). */
|
|
23
|
+
declare const ReviewStatusDot: ({ tone, className }: ReviewStatusDotProps) => import("react").JSX.Element;
|
|
24
|
+
/** The tone a severity level carries, so a badge and its dot cannot disagree. */
|
|
25
|
+
declare const reviewSeverityTone: (level: ReviewSeverityLevel) => ReviewStatusTone;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { ReviewSeverityDot, ReviewSeverityLevel, ReviewStatusDot, reviewSeverityTone };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/review/review-severity-dot.tsx
|
|
4
|
+
/** The dot that precedes a severity label, and the one place a severity level
|
|
5
|
+
* turns into a colour. */
|
|
6
|
+
const ReviewSeverityDot = ({ level, className }) => /* @__PURE__ */ jsx(ReviewStatusDot, {
|
|
7
|
+
className,
|
|
8
|
+
tone: SEVERITY_TONE[level]
|
|
9
|
+
});
|
|
10
|
+
/** The same dot keyed by tone, for vocabularies that are not severities
|
|
11
|
+
* (verdicts, directed impact, comparison assessments). */
|
|
12
|
+
const ReviewStatusDot = ({ tone, className }) => /* @__PURE__ */ jsx("span", {
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
className: cn(REVIEW_STATUS_DOT_BASE_CLASS, TONE_DOT_CLASS[tone], className),
|
|
15
|
+
"data-slot": "review-status-dot"
|
|
16
|
+
});
|
|
17
|
+
/** The tone a severity level carries, so a badge and its dot cannot disagree. */
|
|
18
|
+
const reviewSeverityTone = (level) => SEVERITY_TONE[level];
|
|
19
|
+
const REVIEW_STATUS_DOT_BASE_CLASS = "size-1.5 shrink-0 rounded-full";
|
|
20
|
+
const SEVERITY_TONE = {
|
|
21
|
+
critical: "destructive",
|
|
22
|
+
high: "destructive",
|
|
23
|
+
medium: "warning",
|
|
24
|
+
low: "neutral",
|
|
25
|
+
none: "success"
|
|
26
|
+
};
|
|
27
|
+
const TONE_DOT_CLASS = {
|
|
28
|
+
neutral: "bg-muted-foreground",
|
|
29
|
+
success: "bg-success",
|
|
30
|
+
warning: "bg-warning",
|
|
31
|
+
destructive: "bg-destructive",
|
|
32
|
+
highlight: "bg-highlight-foreground"
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ReviewSeverityDot, ReviewStatusDot, reviewSeverityTone };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/review/review-status-badge.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The semantic weight of a review status, independent of the words a surface
|
|
5
|
+
* uses for it. Playbook verdicts, overall risk, proposal states, suggestion
|
|
6
|
+
* decisions and approval states each map their own vocabulary onto one tone,
|
|
7
|
+
* so "this is fine" reads as the same green everywhere and a reviewer never
|
|
8
|
+
* has to relearn a palette when moving between panels.
|
|
9
|
+
*/
|
|
10
|
+
type ReviewStatusTone = "neutral" | "success" | "warning" | "destructive" | "highlight";
|
|
11
|
+
type ReviewStatusVariant = "solid" | "outline" | "strong";
|
|
12
|
+
type ReviewStatusSize = "xs" | "sm";
|
|
13
|
+
type ReviewStatusBadgeProps = {
|
|
14
|
+
tone: ReviewStatusTone;
|
|
15
|
+
/** Outlined by default. `solid` adds a tonal wash for a status that has to
|
|
16
|
+
* carry more weight than its neighbours (an overall risk, an approval);
|
|
17
|
+
* `strong` fills it outright, reserved for the one state on a surface that
|
|
18
|
+
* must escalate past every other badge beside it. */
|
|
19
|
+
variant?: ReviewStatusVariant;
|
|
20
|
+
size?: ReviewStatusSize;
|
|
21
|
+
/** Leading glyph, typically a `<ReviewSeverityDot />`. */
|
|
22
|
+
icon?: ReactNode;
|
|
23
|
+
className?: string;
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
};
|
|
26
|
+
/** One status pill for every review surface: one radius, one padding scale,
|
|
27
|
+
* one tone vocabulary. */
|
|
28
|
+
declare const ReviewStatusBadge: ({ tone, variant, size, icon, className, children }: ReviewStatusBadgeProps) => import("react").JSX.Element;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { ReviewStatusBadge, ReviewStatusSize, ReviewStatusTone, ReviewStatusVariant };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/review/review-status-badge.tsx
|
|
4
|
+
/** One status pill for every review surface: one radius, one padding scale,
|
|
5
|
+
* one tone vocabulary. */
|
|
6
|
+
const ReviewStatusBadge = ({ tone, variant = "outline", size = "xs", icon, className, children }) => /* @__PURE__ */ jsxs("span", {
|
|
7
|
+
className: cn(REVIEW_STATUS_BADGE_BASE_CLASS, SIZE_CLASS[size], VARIANT_CLASS[variant], TONE_CLASS[variant][tone], className),
|
|
8
|
+
"data-slot": "review-status-badge",
|
|
9
|
+
children: [icon, children]
|
|
10
|
+
});
|
|
11
|
+
const REVIEW_STATUS_BADGE_BASE_CLASS = "inline-flex shrink-0 items-center rounded-full border font-medium whitespace-nowrap";
|
|
12
|
+
const SIZE_CLASS = {
|
|
13
|
+
xs: "gap-1 px-1.5 py-0.5 text-[11px]",
|
|
14
|
+
sm: "gap-1.5 px-2 py-0.5 text-xs"
|
|
15
|
+
};
|
|
16
|
+
const TONE_CLASS = {
|
|
17
|
+
outline: {
|
|
18
|
+
neutral: "border-border text-muted-foreground",
|
|
19
|
+
success: "border-success/30 text-success",
|
|
20
|
+
warning: "border-warning/30 text-warning-foreground",
|
|
21
|
+
destructive: "border-destructive/30 text-destructive",
|
|
22
|
+
highlight: "border-highlight text-highlight-foreground"
|
|
23
|
+
},
|
|
24
|
+
solid: {
|
|
25
|
+
neutral: "border-transparent bg-muted text-muted-foreground",
|
|
26
|
+
success: "border-transparent bg-success/12 text-success",
|
|
27
|
+
warning: "border-transparent bg-warning/12 text-warning-foreground",
|
|
28
|
+
destructive: "border-transparent bg-destructive/12 text-destructive",
|
|
29
|
+
highlight: "border-transparent bg-highlight/50 text-highlight-foreground"
|
|
30
|
+
},
|
|
31
|
+
strong: {
|
|
32
|
+
neutral: "border-transparent bg-muted-foreground text-background",
|
|
33
|
+
success: "border-transparent bg-success text-success-foreground",
|
|
34
|
+
warning: "border-transparent bg-warning text-warning-foreground",
|
|
35
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground",
|
|
36
|
+
highlight: "border-transparent bg-highlight text-highlight-foreground"
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const VARIANT_CLASS = {
|
|
40
|
+
outline: "",
|
|
41
|
+
solid: "",
|
|
42
|
+
strong: "[&_[data-slot=review-status-dot]]:bg-current"
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ReviewStatusBadge };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Stella's design system: bidi-aware React primitives built on Base UI, the dockable inspector pane, and the Tailwind v4 theme they are styled with.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"base-ui",
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"types": "./dist/components/alert-dialog.d.ts",
|
|
42
42
|
"import": "./dist/components/alert-dialog.js"
|
|
43
43
|
},
|
|
44
|
+
"./application-shell": {
|
|
45
|
+
"types": "./dist/components/application-shell.d.ts",
|
|
46
|
+
"import": "./dist/components/application-shell.js"
|
|
47
|
+
},
|
|
44
48
|
"./avatar": {
|
|
45
49
|
"types": "./dist/components/avatar.d.ts",
|
|
46
50
|
"import": "./dist/components/avatar.js"
|
|
@@ -133,6 +137,10 @@
|
|
|
133
137
|
"types": "./dist/components/input-group.d.ts",
|
|
134
138
|
"import": "./dist/components/input-group.js"
|
|
135
139
|
},
|
|
140
|
+
"./initials": {
|
|
141
|
+
"types": "./dist/lib/initials.d.ts",
|
|
142
|
+
"import": "./dist/lib/initials.js"
|
|
143
|
+
},
|
|
136
144
|
"./input-otp": {
|
|
137
145
|
"types": "./dist/components/input-otp.d.ts",
|
|
138
146
|
"import": "./dist/components/input-otp.js"
|
|
@@ -173,6 +181,34 @@
|
|
|
173
181
|
"types": "./dist/components/preview-pane.d.ts",
|
|
174
182
|
"import": "./dist/components/preview-pane.js"
|
|
175
183
|
},
|
|
184
|
+
"./review-author-avatar": {
|
|
185
|
+
"types": "./dist/review/review-author-avatar.d.ts",
|
|
186
|
+
"import": "./dist/review/review-author-avatar.js"
|
|
187
|
+
},
|
|
188
|
+
"./review-comment-card": {
|
|
189
|
+
"types": "./dist/review/review-comment-card.d.ts",
|
|
190
|
+
"import": "./dist/review/review-comment-card.js"
|
|
191
|
+
},
|
|
192
|
+
"./review-decision-actions": {
|
|
193
|
+
"types": "./dist/review/review-decision-actions.d.ts",
|
|
194
|
+
"import": "./dist/review/review-decision-actions.js"
|
|
195
|
+
},
|
|
196
|
+
"./review-diff-text": {
|
|
197
|
+
"types": "./dist/review/review-diff-text.d.ts",
|
|
198
|
+
"import": "./dist/review/review-diff-text.js"
|
|
199
|
+
},
|
|
200
|
+
"./review-out-of-date-notice": {
|
|
201
|
+
"types": "./dist/review/review-out-of-date-notice.d.ts",
|
|
202
|
+
"import": "./dist/review/review-out-of-date-notice.js"
|
|
203
|
+
},
|
|
204
|
+
"./review-severity-dot": {
|
|
205
|
+
"types": "./dist/review/review-severity-dot.d.ts",
|
|
206
|
+
"import": "./dist/review/review-severity-dot.js"
|
|
207
|
+
},
|
|
208
|
+
"./review-status-badge": {
|
|
209
|
+
"types": "./dist/review/review-status-badge.d.ts",
|
|
210
|
+
"import": "./dist/review/review-status-badge.js"
|
|
211
|
+
},
|
|
176
212
|
"./scroll-area": {
|
|
177
213
|
"types": "./dist/components/scroll-area.d.ts",
|
|
178
214
|
"import": "./dist/components/scroll-area.js"
|
|
@@ -282,6 +318,10 @@
|
|
|
282
318
|
"types": "./dist/components/alert-dialog.d.ts",
|
|
283
319
|
"import": "./dist/components/alert-dialog.js"
|
|
284
320
|
},
|
|
321
|
+
"./components/application-shell": {
|
|
322
|
+
"types": "./dist/components/application-shell.d.ts",
|
|
323
|
+
"import": "./dist/components/application-shell.js"
|
|
324
|
+
},
|
|
285
325
|
"./components/avatar": {
|
|
286
326
|
"types": "./dist/components/avatar.d.ts",
|
|
287
327
|
"import": "./dist/components/avatar.js"
|