@stll/ui 0.6.0 → 0.8.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-rail.d.ts +20 -0
- package/dist/components/application-rail.js +52 -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/combobox.d.ts +3 -2
- package/dist/components/combobox.js +35 -7
- package/dist/components/command.d.ts +2 -1
- package/dist/components/command.js +8 -2
- package/dist/components/input-group.d.ts +1 -1
- package/dist/components/input.d.ts +2 -1
- package/dist/components/input.js +9 -2
- package/dist/components/select.d.ts +2 -1
- package/dist/components/select.js +8 -2
- package/dist/components/textarea.d.ts +2 -1
- package/dist/components/textarea.js +9 -2
- package/dist/index.d.ts +13 -1
- package/dist/index.js +14 -2
- package/dist/inspector/index.d.ts +2 -1
- package/dist/inspector/index.js +2 -1
- package/dist/inspector/tabs.d.ts +16 -0
- package/dist/inspector/tabs.js +49 -0
- package/dist/lib/control-size.d.ts +10 -0
- package/dist/lib/control-size.js +9 -0
- 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 +53 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { cn, composeRefs } from "./lib/utils.js";
|
|
2
2
|
import { Accordion, AccordionContent as AccordionPanel, AccordionItem, AccordionTrigger } from "./components/accordion.js";
|
|
3
|
+
import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX } from "./inspector/layout-tokens.js";
|
|
4
|
+
import { APPLICATION_RAIL_BUTTON_SIZE, APPLICATION_RAIL_ICON_SIZE, APPLICATION_RAIL_WIDTH, ApplicationRail, ApplicationRailButton, ApplicationRailContent, ApplicationRailFooter, ApplicationRailHeader, ApplicationRailMenu, ApplicationRailSeparator } from "./components/application-rail.js";
|
|
3
5
|
import { OVERLAY_LAYER_CLASS_NAMES } from "./lib/overlay-layer.js";
|
|
4
6
|
import { Tooltip, TooltipContent as TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger } from "./components/tooltip.js";
|
|
5
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 } from "./components/application-shell.js";
|
|
6
9
|
import { Avatar, AvatarFallback, AvatarImage } from "./components/avatar.js";
|
|
7
10
|
import { BidiText, UserText } from "./components/bidi-text.js";
|
|
8
11
|
import { DiscordLogoIcon, GitHubLogoIcon } from "./components/brand-icons.js";
|
|
@@ -13,6 +16,7 @@ import { Button } from "./components/button.js";
|
|
|
13
16
|
import { Checkbox } from "./components/checkbox.js";
|
|
14
17
|
import { ColorPicker, ColorPickerContent, DEFAULT_PRESETS } from "./components/color-picker.js";
|
|
15
18
|
import { containedEventHandler, containedHandler } from "./hooks/use-contained-handler.js";
|
|
19
|
+
import { CONTROL_SIZE, CONTROL_SIZES } from "./lib/control-size.js";
|
|
16
20
|
import { contentDir, isStructuredInputType, useContentDir } from "./hooks/use-content-dir.js";
|
|
17
21
|
import { Input } from "./components/input.js";
|
|
18
22
|
import { ScrollArea, ScrollBar } from "./components/scroll-area.js";
|
|
@@ -57,9 +61,9 @@ import { duplicateColumnIds, findTableColumn, hideableColumnIds, sortableColumnI
|
|
|
57
61
|
import { DataTable } from "./data-table/table.js";
|
|
58
62
|
import { useIsMobile } from "./hooks/use-mobile.js";
|
|
59
63
|
import { useViewportWidth } from "./hooks/use-viewport-width.js";
|
|
60
|
-
import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX } from "./inspector/layout-tokens.js";
|
|
61
64
|
import { Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle } from "./inspector/chrome.js";
|
|
62
65
|
import { InspectorDock } from "./inspector/dock.js";
|
|
66
|
+
import { InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs } from "./inspector/tabs.js";
|
|
63
67
|
import { INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, shouldForceSidebarCollapsed } from "./inspector/pane-width.js";
|
|
64
68
|
import { INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, parsePersistedPaneWidth, resolveDragWidth, resolveKeyboardWidth, useInspectorPaneWidth } from "./inspector/use-pane-width.js";
|
|
65
69
|
import { selectKanbanCardFieldIds } from "./kanban/card-properties.js";
|
|
@@ -69,5 +73,13 @@ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, K
|
|
|
69
73
|
import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, getKanbanHorizontalEdge } from "./kanban/sortable-edge.js";
|
|
70
74
|
import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./kanban/drag-interactions.js";
|
|
71
75
|
import { getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./kanban/grouping.js";
|
|
76
|
+
import { getInitials } from "./lib/initials.js";
|
|
72
77
|
import { emptyColor, optionColors, resolveOptionColor } from "./lib/option-color.js";
|
|
73
|
-
|
|
78
|
+
import { ReviewAuthorAvatar, UNKNOWN_AUTHOR_LABEL } from "./review/review-author-avatar.js";
|
|
79
|
+
import { ReviewCommentCard } from "./review/review-comment-card.js";
|
|
80
|
+
import { ReviewDecisionActions } from "./review/review-decision-actions.js";
|
|
81
|
+
import { ReviewDiffDeletion, ReviewDiffInsertion, ReviewDiffText, TRACKED_DELETION_STYLE, TRACKED_INSERTION_STYLE, reviewDiffSegmentKeys } from "./review/review-diff-text.js";
|
|
82
|
+
import { ReviewOutOfDateNotice } from "./review/review-out-of-date-notice.js";
|
|
83
|
+
import { ReviewSeverityDot, ReviewStatusDot, reviewSeverityTone } from "./review/review-severity-dot.js";
|
|
84
|
+
import { ReviewStatusBadge } from "./review/review-status-badge.js";
|
|
85
|
+
export { APPLICATION_RAIL_BUTTON_SIZE, APPLICATION_RAIL_ICON_SIZE, APPLICATION_RAIL_WIDTH, 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, ApplicationRail, ApplicationRailButton, ApplicationRailContent, ApplicationRailFooter, ApplicationRailHeader, ApplicationRailMenu, ApplicationRailSeparator, ApplicationShell, Avatar, AvatarFallback, AvatarImage, BidiText, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CONTROL_SIZE, CONTROL_SIZES, 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, InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs, 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 };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle } from "./chrome.js";
|
|
2
2
|
import { InspectorDock } from "./dock.js";
|
|
3
|
+
import { InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs } from "./tabs.js";
|
|
3
4
|
import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX } from "./layout-tokens.js";
|
|
4
5
|
import { INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, shouldForceSidebarCollapsed } from "./pane-width.js";
|
|
5
6
|
import { INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, parsePersistedPaneWidth, resolveDragWidth, resolveKeyboardWidth, useInspectorPaneWidth } from "./use-pane-width.js";
|
|
6
|
-
export { 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, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, parsePersistedPaneWidth, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKeyboardWidth, shouldForceSidebarCollapsed, useInspectorPaneWidth };
|
|
7
|
+
export { 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, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs, InspectorTitle, PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, parsePersistedPaneWidth, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKeyboardWidth, shouldForceSidebarCollapsed, useInspectorPaneWidth };
|
package/dist/inspector/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX } from "./layout-tokens.js";
|
|
2
2
|
import { Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle } from "./chrome.js";
|
|
3
3
|
import { InspectorDock } from "./dock.js";
|
|
4
|
+
import { InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs } from "./tabs.js";
|
|
4
5
|
import { INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, shouldForceSidebarCollapsed } from "./pane-width.js";
|
|
5
6
|
import { INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, parsePersistedPaneWidth, resolveDragWidth, resolveKeyboardWidth, useInspectorPaneWidth } from "./use-pane-width.js";
|
|
6
|
-
export { 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, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, parsePersistedPaneWidth, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKeyboardWidth, shouldForceSidebarCollapsed, useInspectorPaneWidth };
|
|
7
|
+
export { 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, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs, InspectorTitle, PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, parsePersistedPaneWidth, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKeyboardWidth, shouldForceSidebarCollapsed, useInspectorPaneWidth };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
import { Tabs } from "@base-ui/react/tabs";
|
|
3
|
+
//#region src/inspector/tabs.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A tabbed inspector keeps its content beside the same fixed-width rail as a
|
|
6
|
+
* docked inspector. The mobile layout moves the rail below the header rather
|
|
7
|
+
* than leaving a narrow column beside a full-screen sheet.
|
|
8
|
+
*/
|
|
9
|
+
declare const InspectorTabs: ({ className, ...props }: Omit<Tabs.Root.Props, "orientation">) => React$1.JSX.Element;
|
|
10
|
+
declare const INSPECTOR_RAIL_MEDIA_QUERY: "(min-width: 48rem)";
|
|
11
|
+
declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "horizontal" | "vertical";
|
|
12
|
+
declare const InspectorTabList: ({ className, ...props }: Tabs.List.Props) => React$1.JSX.Element;
|
|
13
|
+
declare const InspectorTab: ({ className, ...props }: Tabs.Tab.Props) => React$1.JSX.Element;
|
|
14
|
+
declare const InspectorTabPanel: ({ className, ...props }: Tabs.Panel.Props) => React$1.JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { INSPECTOR_RAIL_MEDIA_QUERY, InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs, resolveInspectorTabOrientation };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { TOOLBAR_ROW_HEIGHT } from "./layout-tokens.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import * as React$1 from "react";
|
|
6
|
+
import { Tabs } from "@base-ui/react/tabs";
|
|
7
|
+
//#region src/inspector/tabs.tsx
|
|
8
|
+
/**
|
|
9
|
+
* A tabbed inspector keeps its content beside the same fixed-width rail as a
|
|
10
|
+
* docked inspector. The mobile layout moves the rail below the header rather
|
|
11
|
+
* than leaving a narrow column beside a full-screen sheet.
|
|
12
|
+
*/
|
|
13
|
+
const InspectorTabs = ({ className, ...props }) => {
|
|
14
|
+
const isRailLayout = useInspectorRailLayout();
|
|
15
|
+
return /* @__PURE__ */ jsx(Tabs.Root, {
|
|
16
|
+
className: (state) => cn("grid h-full min-h-0 w-full grid-cols-1 grid-rows-[3rem_3rem_minmax(0,1fr)] overflow-hidden md:grid-cols-[3rem_minmax(0,1fr)] md:grid-rows-[3rem_minmax(0,1fr)]", resolveClassName(className, state)),
|
|
17
|
+
"data-slot": "inspector-tabs",
|
|
18
|
+
...props,
|
|
19
|
+
orientation: resolveInspectorTabOrientation(isRailLayout)
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const INSPECTOR_RAIL_MEDIA_QUERY = "(min-width: 48rem)";
|
|
23
|
+
const resolveInspectorTabOrientation = (isRailLayout) => isRailLayout ? "vertical" : "horizontal";
|
|
24
|
+
const subscribeToInspectorRailLayout = (onChange) => {
|
|
25
|
+
const mediaQueryList = window.matchMedia(INSPECTOR_RAIL_MEDIA_QUERY);
|
|
26
|
+
mediaQueryList.addEventListener("change", onChange);
|
|
27
|
+
return () => mediaQueryList.removeEventListener("change", onChange);
|
|
28
|
+
};
|
|
29
|
+
const getInspectorRailLayoutSnapshot = () => window.matchMedia(INSPECTOR_RAIL_MEDIA_QUERY).matches;
|
|
30
|
+
const getServerInspectorRailLayoutSnapshot = () => false;
|
|
31
|
+
const useInspectorRailLayout = () => React$1.useSyncExternalStore(subscribeToInspectorRailLayout, getInspectorRailLayoutSnapshot, getServerInspectorRailLayoutSnapshot);
|
|
32
|
+
const resolveClassName = (value, state) => typeof value === "function" ? value(state) : value;
|
|
33
|
+
const InspectorTabList = ({ className, ...props }) => /* @__PURE__ */ jsx(Tabs.List, {
|
|
34
|
+
className: (state) => cn("bg-sidebar col-start-1 row-start-2 flex min-w-0 shrink-0 scrollbar-none overflow-x-auto overflow-y-hidden overscroll-x-contain border-b md:row-span-2 md:row-start-1 md:h-full md:flex-col md:overflow-x-hidden md:overflow-y-auto md:overscroll-y-contain md:border-s md:border-e md:border-b-0 [&::-webkit-scrollbar]:hidden", TOOLBAR_ROW_HEIGHT, "md:w-12", resolveClassName(className, state)),
|
|
35
|
+
"data-slot": "inspector-tab-list",
|
|
36
|
+
...props
|
|
37
|
+
});
|
|
38
|
+
const InspectorTab = ({ className, ...props }) => /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
39
|
+
className: (state) => cn("group/tab text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring data-active:bg-background data-active:text-foreground data-active:before:bg-primary relative flex size-12 shrink-0 cursor-pointer items-center justify-center border-e transition-colors outline-none before:absolute before:inset-x-0 before:bottom-0 before:hidden before:h-0.5 focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-inset data-active:before:block data-disabled:pointer-events-none data-disabled:opacity-60 md:w-full md:flex-none md:border-e-0 md:border-b md:before:inset-y-0 md:before:start-0 md:before:h-auto md:before:w-0.5", resolveClassName(className, state)),
|
|
40
|
+
"data-slot": "inspector-tab",
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
const InspectorTabPanel = ({ className, ...props }) => /* @__PURE__ */ jsx(Tabs.Panel, {
|
|
44
|
+
className: (state) => cn("col-start-1 row-start-3 min-h-0 overflow-x-hidden overflow-y-auto overscroll-contain outline-none md:col-start-2 md:row-start-2", resolveClassName(className, state)),
|
|
45
|
+
"data-slot": "inspector-tab-panel",
|
|
46
|
+
...props
|
|
47
|
+
});
|
|
48
|
+
//#endregion
|
|
49
|
+
export { INSPECTOR_RAIL_MEDIA_QUERY, InspectorTab, InspectorTabList, InspectorTabPanel, InspectorTabs, resolveInspectorTabOrientation };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/lib/control-size.d.ts
|
|
2
|
+
declare const CONTROL_SIZE: Readonly<{
|
|
3
|
+
readonly sm: "sm";
|
|
4
|
+
readonly default: "default";
|
|
5
|
+
readonly lg: "lg";
|
|
6
|
+
}>;
|
|
7
|
+
type ControlSize = (typeof CONTROL_SIZE)[keyof typeof CONTROL_SIZE];
|
|
8
|
+
declare const CONTROL_SIZES: readonly ("sm" | "default" | "lg")[];
|
|
9
|
+
//#endregion
|
|
10
|
+
export { CONTROL_SIZE, CONTROL_SIZES, type ControlSize };
|
|
@@ -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 };
|