@ciridae/ui 0.3.2 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/dist/assets/ciridae/brand-background-dark.webp +0 -0
  2. package/dist/assets/ciridae/brand-background-light.webp +0 -0
  3. package/dist/assets/ciridae/ciridae-black.svg +17 -0
  4. package/dist/assets/ciridae/ciridae-brand-assets.d.ts +25 -0
  5. package/dist/assets/ciridae/ciridae-brand-assets.js +25 -0
  6. package/dist/assets/ciridae/ciridae-icon-black.png +0 -0
  7. package/dist/assets/ciridae/ciridae-icon-white.png +0 -0
  8. package/dist/assets/ciridae/ciridae-ui-wordmark-black.png +0 -0
  9. package/dist/assets/ciridae/ciridae-ui-wordmark-white.png +0 -0
  10. package/dist/assets/ciridae/ciridae-white.svg +17 -0
  11. package/dist/assets/ciridae/ciridae-wordmark-black.png +0 -0
  12. package/dist/assets/ciridae/ciridae-wordmark-white.png +0 -0
  13. package/dist/assets/ciridae/favicon.ico +0 -0
  14. package/dist/assets/ciridae/logo-white.png +0 -0
  15. package/dist/assets/ciridae/sign-in-screenshot.png +0 -0
  16. package/dist/components/blocks/admin-users-table.d.ts +22 -0
  17. package/dist/components/blocks/admin-users-table.js +115 -0
  18. package/dist/components/blocks/comment-composer.d.ts +16 -0
  19. package/dist/components/blocks/comment-composer.js +113 -0
  20. package/dist/components/blocks/comment-item.d.ts +8 -0
  21. package/dist/components/blocks/comment-item.js +45 -0
  22. package/dist/components/blocks/comment-thread.d.ts +18 -0
  23. package/dist/components/blocks/comment-thread.js +30 -0
  24. package/dist/components/blocks/comment-types.d.ts +18 -0
  25. package/dist/components/blocks/comment-types.js +11 -0
  26. package/dist/components/blocks/feedback-center-comments.d.ts +12 -0
  27. package/dist/components/blocks/feedback-center-comments.js +11 -0
  28. package/dist/components/blocks/feedback-center-sheet-parts.d.ts +34 -0
  29. package/dist/components/blocks/feedback-center-sheet-parts.js +44 -0
  30. package/dist/components/blocks/feedback-center-sheet.d.ts +19 -0
  31. package/dist/components/blocks/feedback-center-sheet.js +46 -0
  32. package/dist/components/blocks/feedback-composer-parts.d.ts +16 -0
  33. package/dist/components/blocks/feedback-composer-parts.js +43 -0
  34. package/dist/components/blocks/feedback-composer-types.d.ts +11 -0
  35. package/dist/components/blocks/feedback-composer-types.js +1 -0
  36. package/dist/components/blocks/feedback-composer.d.ts +17 -0
  37. package/dist/components/blocks/feedback-composer.js +112 -0
  38. package/dist/components/blocks/feedback-date-format.d.ts +5 -0
  39. package/dist/components/blocks/feedback-date-format.js +11 -0
  40. package/dist/components/blocks/feedback-detail-sheet.d.ts +9 -0
  41. package/dist/components/blocks/feedback-detail-sheet.js +41 -0
  42. package/dist/components/blocks/feedback-metrics.d.ts +6 -0
  43. package/dist/components/blocks/feedback-metrics.js +15 -0
  44. package/dist/components/blocks/feedback-sheet.d.ts +8 -0
  45. package/dist/components/blocks/feedback-sheet.js +16 -0
  46. package/dist/components/blocks/feedback-status-badge.d.ts +6 -0
  47. package/dist/components/blocks/feedback-status-badge.js +14 -0
  48. package/dist/components/blocks/feedback-table-row.d.ts +6 -0
  49. package/dist/components/blocks/feedback-table-row.js +37 -0
  50. package/dist/components/blocks/feedback-table-sort.d.ts +11 -0
  51. package/dist/components/blocks/feedback-table-sort.js +81 -0
  52. package/dist/components/blocks/feedback-table.d.ts +16 -0
  53. package/dist/components/blocks/feedback-table.js +45 -0
  54. package/dist/components/blocks/feedback-tracking-types.d.ts +78 -0
  55. package/dist/components/blocks/feedback-tracking-types.js +36 -0
  56. package/dist/components/blocks/feedback-type-badge.d.ts +6 -0
  57. package/dist/components/blocks/feedback-type-badge.js +12 -0
  58. package/dist/components/blocks/feedback-user-detail.d.ts +10 -0
  59. package/dist/components/blocks/feedback-user-detail.js +57 -0
  60. package/dist/components/blocks/feedback-user-list.d.ts +9 -0
  61. package/dist/components/blocks/feedback-user-list.js +33 -0
  62. package/dist/components/blocks/invite-user-sheet.d.ts +20 -0
  63. package/dist/components/blocks/invite-user-sheet.js +72 -0
  64. package/dist/components/blocks/kanban-board-parts.d.ts +26 -0
  65. package/dist/components/blocks/kanban-board-parts.js +85 -0
  66. package/dist/components/blocks/kanban-board-utils.d.ts +42 -0
  67. package/dist/components/blocks/kanban-board-utils.js +115 -0
  68. package/dist/components/blocks/kanban-board.d.ts +16 -0
  69. package/dist/components/blocks/kanban-board.js +36 -0
  70. package/dist/components/blocks/kanban-card.d.ts +10 -0
  71. package/dist/components/blocks/kanban-card.js +34 -0
  72. package/dist/components/blocks/kanban-column.d.ts +17 -0
  73. package/dist/components/blocks/kanban-column.js +34 -0
  74. package/dist/components/blocks/kanban-detail-sheet.d.ts +17 -0
  75. package/dist/components/blocks/kanban-detail-sheet.js +34 -0
  76. package/dist/components/blocks/kanban-types.d.ts +24 -0
  77. package/dist/components/blocks/kanban-types.js +1 -0
  78. package/dist/components/blocks/timestamp-format.d.ts +8 -0
  79. package/dist/components/blocks/timestamp-format.js +66 -0
  80. package/dist/components/pages/admin-users-page.d.ts +11 -0
  81. package/dist/components/pages/admin-users-page.js +30 -0
  82. package/dist/components/pages/feedback-stakeholder-page-parts.d.ts +18 -0
  83. package/dist/components/pages/feedback-stakeholder-page-parts.js +36 -0
  84. package/dist/components/pages/feedback-stakeholder-page.d.ts +9 -0
  85. package/dist/components/pages/feedback-stakeholder-page.js +66 -0
  86. package/dist/components/pages/kanban-page.d.ts +13 -0
  87. package/dist/components/pages/kanban-page.js +68 -0
  88. package/dist/components/ui/calendar.d.ts +2 -1
  89. package/dist/components/ui/calendar.js +1 -1
  90. package/dist/components/ui/dialog.d.ts +2 -1
  91. package/dist/components/ui/dialog.js +2 -2
  92. package/dist/components/ui/page-header.d.ts +15 -1
  93. package/dist/components/ui/page-header.js +20 -2
  94. package/dist/components/ui/resizable.d.ts +9 -2
  95. package/dist/components/ui/resizable.js +3 -3
  96. package/dist/components/ui/sidebar-account-menu.d.ts +3 -1
  97. package/dist/components/ui/sidebar-account-menu.js +5 -5
  98. package/dist/components/ui/sonner.d.ts +2 -2
  99. package/dist/components/ui/sonner.js +2 -2
  100. package/dist/styled-system/css/css.d.ts +11 -16
  101. package/dist/styled-system/css/cva.d.ts +2 -4
  102. package/dist/styled-system/css/cx.d.ts +2 -3
  103. package/dist/styled-system/css/index.d.ts +1 -1
  104. package/dist/styled-system/css/sva.d.ts +1 -2
  105. package/dist/styled-system/patterns/aspect-ratio.d.ts +5 -9
  106. package/dist/styled-system/patterns/bleed.d.ts +6 -10
  107. package/dist/styled-system/patterns/box.d.ts +4 -9
  108. package/dist/styled-system/patterns/center.d.ts +5 -9
  109. package/dist/styled-system/patterns/circle.d.ts +5 -9
  110. package/dist/styled-system/patterns/container.d.ts +4 -9
  111. package/dist/styled-system/patterns/cq.d.ts +6 -10
  112. package/dist/styled-system/patterns/divider.d.ts +7 -11
  113. package/dist/styled-system/patterns/flex.d.ts +11 -15
  114. package/dist/styled-system/patterns/float.d.ts +8 -12
  115. package/dist/styled-system/patterns/grid-item.d.ts +10 -14
  116. package/dist/styled-system/patterns/grid.d.ts +9 -13
  117. package/dist/styled-system/patterns/hstack.d.ts +6 -10
  118. package/dist/styled-system/patterns/index.d.ts +1 -1
  119. package/dist/styled-system/patterns/link-overlay.d.ts +4 -9
  120. package/dist/styled-system/patterns/spacer.d.ts +5 -9
  121. package/dist/styled-system/patterns/square.d.ts +5 -9
  122. package/dist/styled-system/patterns/stack.d.ts +8 -12
  123. package/dist/styled-system/patterns/visually-hidden.d.ts +4 -9
  124. package/dist/styled-system/patterns/vstack.d.ts +6 -10
  125. package/dist/styled-system/patterns/wrap.d.ts +9 -13
  126. package/dist/styled-system/tokens/index.d.ts +4 -6
  127. package/dist/styled-system/tokens/tokens.d.ts +42 -61
  128. package/dist/styled-system/types/composition.d.ts +20 -211
  129. package/dist/styled-system/types/conditions.d.ts +297 -303
  130. package/dist/styled-system/types/csstype.d.ts +20289 -22518
  131. package/dist/styled-system/types/global.d.ts +11 -12
  132. package/dist/styled-system/types/index.d.ts +2 -2
  133. package/dist/styled-system/types/parts.d.ts +2 -3
  134. package/dist/styled-system/types/pattern.d.ts +75 -71
  135. package/dist/styled-system/types/prop-type.d.ts +236 -233
  136. package/dist/styled-system/types/recipe.d.ts +114 -155
  137. package/dist/styled-system/types/selectors.d.ts +8 -58
  138. package/dist/styled-system/types/static-css.d.ts +40 -47
  139. package/dist/styled-system/types/style-props.d.ts +8078 -8082
  140. package/dist/styled-system/types/system-types.d.ts +69 -111
  141. package/dist/styles.css +490 -1
  142. package/package.json +159 -7
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ import type { StakeholderFeedbackItem } from "@ciridae/ui/feedback-tracking-types";
3
+ import { type FeedbackTableSort, type FeedbackTableSortKey } from "./feedback-table-sort";
4
+ type FeedbackTableProps = {
5
+ defaultSort?: FeedbackTableSort;
6
+ emptyAction?: React.ReactNode;
7
+ emptyDescription?: string;
8
+ emptyTitle?: string;
9
+ isLoading?: boolean;
10
+ items: StakeholderFeedbackItem[];
11
+ onSelectFeedback?: (item: StakeholderFeedbackItem) => void;
12
+ onSortChange?: (sort: FeedbackTableSort) => void;
13
+ sort?: FeedbackTableSort;
14
+ };
15
+ declare function FeedbackTable({ defaultSort, emptyAction, emptyDescription, emptyTitle, isLoading, items, onSelectFeedback, onSortChange, sort, }: FeedbackTableProps): React.JSX.Element;
16
+ export { FeedbackTable, type FeedbackTableProps, type FeedbackTableSort, type FeedbackTableSortKey };
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { InboxIcon } from "lucide-react";
4
+ import { DataTable, DataTableContent, DataTableEmpty, DataTableSkeleton, SortableTableHead, } from "@ciridae/ui/data-table";
5
+ import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@ciridae/ui/empty";
6
+ import { Table, TableBody, TableHead, TableHeader, TableRow } from "@ciridae/ui/table";
7
+ import { defaultFeedbackTableSort, getNextFeedbackTableSort, sortFeedbackItems, } from "./feedback-table-sort";
8
+ import { FeedbackTableRow } from "./feedback-table-row";
9
+ function FeedbackTable({ defaultSort = defaultFeedbackTableSort, emptyAction, emptyDescription = "No feedback has been submitted yet.", emptyTitle = "No feedback", isLoading = false, items, onSelectFeedback, onSortChange, sort, }) {
10
+ const [internalSort, setInternalSort] = React.useState(defaultSort);
11
+ const activeSort = sort ?? internalSort;
12
+ const sortedItems = React.useMemo(() => sortFeedbackItems(items, activeSort), [activeSort, items]);
13
+ const handleSortChange = React.useCallback((key) => {
14
+ const nextSort = getNextFeedbackTableSort(activeSort, key);
15
+ if (!sort)
16
+ setInternalSort(nextSort);
17
+ onSortChange?.(nextSort);
18
+ }, [activeSort, onSortChange, sort]);
19
+ if (isLoading)
20
+ return _jsx(FeedbackTableLoading, {});
21
+ if (items.length === 0) {
22
+ return (_jsx(FeedbackTableEmpty, { action: emptyAction, description: emptyDescription, title: emptyTitle }));
23
+ }
24
+ return (_jsx(DataTable, { children: _jsx(DataTableContent, { children: _jsx(FeedbackTableContent, { items: sortedItems, onSelectFeedback: onSelectFeedback, onSortChange: handleSortChange, sort: activeSort }) }) }));
25
+ }
26
+ function FeedbackTableLoading() {
27
+ return (_jsx(DataTable, { children: _jsx(DataTableSkeleton, { columns: 7, rows: 6 }) }));
28
+ }
29
+ function FeedbackTableEmpty({ action, description, title, }) {
30
+ return (_jsx(DataTable, { children: _jsx(DataTableEmpty, { className: "min-h-80 border-b-0", children: _jsx(FeedbackTableEmptyContent, { action: action, description: description, title: title }) }) }));
31
+ }
32
+ function FeedbackTableEmptyContent({ action, description, title, }) {
33
+ return (_jsxs(Empty, { className: "border-0", children: [_jsxs(EmptyHeader, { children: [_jsx(EmptyMedia, { variant: "icon", children: _jsx(InboxIcon, {}) }), _jsx(EmptyTitle, { children: title }), _jsx(EmptyDescription, { children: description })] }), action] }));
34
+ }
35
+ function FeedbackTableContent({ items, onSelectFeedback, onSortChange, sort, }) {
36
+ return (_jsxs(Table, { children: [_jsx(FeedbackTableHeader, { onSortChange: onSortChange, sort: sort }), _jsx(TableBody, { children: items.map((item) => (_jsx(FeedbackTableRow, { item: item, onSelectFeedback: onSelectFeedback }, item.id))) })] }));
37
+ }
38
+ function FeedbackTableHeader({ onSortChange, sort, }) {
39
+ return (_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Feedback" }), _jsx(FeedbackSortableHead, { label: "Type", onSortChange: onSortChange, sort: sort, sortKey: "type" }), _jsx(FeedbackSortableHead, { label: "Submitted by", onSortChange: onSortChange, sort: sort, sortKey: "submittedBy" }), _jsx(FeedbackSortableHead, { label: "Status", onSortChange: onSortChange, sort: sort, sortKey: "status" }), _jsx(FeedbackSortableHead, { label: "Submitted", onSortChange: onSortChange, sort: sort, sortKey: "submittedAt" }), _jsx(FeedbackSortableHead, { label: "Updated", onSortChange: onSortChange, sort: sort, sortKey: "updatedAt" }), _jsx(TableHead, { className: "text-right", children: "Files" })] }) }));
40
+ }
41
+ function FeedbackSortableHead({ label, onSortChange, sort, sortKey, }) {
42
+ const active = sort.key === sortKey;
43
+ return (_jsx(SortableTableHead, { active: active, direction: active ? sort.direction : "asc", onSort: () => onSortChange(sortKey), children: label }));
44
+ }
45
+ export { FeedbackTable };
@@ -0,0 +1,78 @@
1
+ type FeedbackStatus = "received" | "in_review" | "planned" | "in_progress" | "resolved";
2
+ type StakeholderFeedbackType = "bug" | "feature" | "general";
3
+ type FeedbackSubmittedBy = {
4
+ email?: string;
5
+ imageUrl?: string;
6
+ name: string;
7
+ organization?: string;
8
+ };
9
+ type FeedbackAttachment = {
10
+ name: string;
11
+ url?: string;
12
+ };
13
+ type StakeholderFeedbackItem = {
14
+ attachments?: FeedbackAttachment[];
15
+ description: string;
16
+ id: string;
17
+ referenceId?: string;
18
+ status: FeedbackStatus;
19
+ subject: string;
20
+ submittedAt: string;
21
+ submittedBy: FeedbackSubmittedBy;
22
+ type: StakeholderFeedbackType;
23
+ updatedAt?: string;
24
+ };
25
+ type UserFeedbackItem = {
26
+ attachments?: FeedbackAttachment[];
27
+ description: string;
28
+ id: string;
29
+ referenceId?: string;
30
+ status: FeedbackStatus;
31
+ subject: string;
32
+ submittedAt: string;
33
+ type: StakeholderFeedbackType;
34
+ updatedAt?: string;
35
+ };
36
+ type FeedbackMetrics = {
37
+ awaitingReview: number;
38
+ inProgress: number;
39
+ receivedThisWeek: number;
40
+ resolvedThisWeek: number;
41
+ triagedThisWeek: number;
42
+ };
43
+ declare const feedbackStatusLabels: Record<FeedbackStatus, string>;
44
+ declare const feedbackTypeLabels: Record<StakeholderFeedbackType, string>;
45
+ declare const feedbackStatusOptions: readonly [{
46
+ readonly label: "All statuses";
47
+ readonly value: "all";
48
+ }, {
49
+ readonly label: string;
50
+ readonly value: "received";
51
+ }, {
52
+ readonly label: string;
53
+ readonly value: "in_review";
54
+ }, {
55
+ readonly label: string;
56
+ readonly value: "planned";
57
+ }, {
58
+ readonly label: string;
59
+ readonly value: "in_progress";
60
+ }, {
61
+ readonly label: string;
62
+ readonly value: "resolved";
63
+ }];
64
+ declare const feedbackTypeOptions: readonly [{
65
+ readonly label: "All types";
66
+ readonly value: "all";
67
+ }, {
68
+ readonly label: string;
69
+ readonly value: "bug";
70
+ }, {
71
+ readonly label: string;
72
+ readonly value: "feature";
73
+ }, {
74
+ readonly label: string;
75
+ readonly value: "general";
76
+ }];
77
+ declare function getFeedbackInitials(name: string, email: string | undefined): string;
78
+ export { feedbackStatusLabels, feedbackStatusOptions, feedbackTypeLabels, feedbackTypeOptions, getFeedbackInitials, type FeedbackAttachment, type FeedbackMetrics, type FeedbackStatus, type FeedbackSubmittedBy, type StakeholderFeedbackItem, type StakeholderFeedbackType, type UserFeedbackItem, };
@@ -0,0 +1,36 @@
1
+ const feedbackStatusLabels = {
2
+ in_progress: "In progress",
3
+ in_review: "In review",
4
+ planned: "Planned",
5
+ received: "Received",
6
+ resolved: "Resolved",
7
+ };
8
+ const feedbackTypeLabels = {
9
+ bug: "Bug",
10
+ feature: "Feature request",
11
+ general: "General",
12
+ };
13
+ const feedbackStatusOptions = [
14
+ { label: "All statuses", value: "all" },
15
+ { label: feedbackStatusLabels.received, value: "received" },
16
+ { label: feedbackStatusLabels.in_review, value: "in_review" },
17
+ { label: feedbackStatusLabels.planned, value: "planned" },
18
+ { label: feedbackStatusLabels.in_progress, value: "in_progress" },
19
+ { label: feedbackStatusLabels.resolved, value: "resolved" },
20
+ ];
21
+ const feedbackTypeOptions = [
22
+ { label: "All types", value: "all" },
23
+ { label: feedbackTypeLabels.bug, value: "bug" },
24
+ { label: feedbackTypeLabels.feature, value: "feature" },
25
+ { label: feedbackTypeLabels.general, value: "general" },
26
+ ];
27
+ function getFeedbackInitials(name, email) {
28
+ const source = name.trim() || email || "Stakeholder";
29
+ return source
30
+ .split(/\s|@/)
31
+ .filter(Boolean)
32
+ .slice(0, 2)
33
+ .map((part) => part.charAt(0).toUpperCase())
34
+ .join("");
35
+ }
36
+ export { feedbackStatusLabels, feedbackStatusOptions, feedbackTypeLabels, feedbackTypeOptions, getFeedbackInitials, };
@@ -0,0 +1,6 @@
1
+ import { type StakeholderFeedbackType } from "./feedback-tracking-types";
2
+ type FeedbackTypeBadgeProps = {
3
+ type: StakeholderFeedbackType;
4
+ };
5
+ declare function FeedbackTypeBadge({ type }: FeedbackTypeBadgeProps): import("react").JSX.Element;
6
+ export { FeedbackTypeBadge, type FeedbackTypeBadgeProps };
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Badge } from "@ciridae/ui/badge";
3
+ import { feedbackTypeLabels } from "./feedback-tracking-types";
4
+ function FeedbackTypeBadge({ type }) {
5
+ return _jsx(Badge, { variant: feedbackTypeVariants[type], children: feedbackTypeLabels[type] });
6
+ }
7
+ const feedbackTypeVariants = {
8
+ bug: "destructive",
9
+ feature: "info",
10
+ general: "outline",
11
+ };
12
+ export { FeedbackTypeBadge };
@@ -0,0 +1,10 @@
1
+ import type * as React from "react";
2
+ import type { UserFeedbackItem } from "@ciridae/ui/feedback-tracking-types";
3
+ type FeedbackUserDetailProps = {
4
+ activityLabel?: string;
5
+ activitySlot?: React.ReactNode;
6
+ feedback?: UserFeedbackItem;
7
+ onBack?: () => void;
8
+ };
9
+ declare function FeedbackUserDetail({ activityLabel, activitySlot, feedback, onBack, }: FeedbackUserDetailProps): React.JSX.Element;
10
+ export { FeedbackUserDetail, type FeedbackUserDetailProps };
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ArrowLeftIcon, MessageSquareTextIcon, PaperclipIcon } from "lucide-react";
3
+ import { formatFeedbackTimestampFull, getFeedbackTimestampDateTime, } from "@ciridae/ui/feedback-date-format";
4
+ import { FeedbackStatusBadge } from "@ciridae/ui/feedback-status-badge";
5
+ import { FeedbackTypeBadge } from "@ciridae/ui/feedback-type-badge";
6
+ import { Button } from "@ciridae/ui/button";
7
+ import { Card } from "@ciridae/ui/card";
8
+ import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@ciridae/ui/empty";
9
+ import { Item, ItemContent, ItemGroup, ItemMedia, ItemTitle } from "@ciridae/ui/item";
10
+ import { PropertyList, PropertyListItem, PropertyListLabel, PropertyListValue, } from "@ciridae/ui/property-list";
11
+ function FeedbackUserDetail({ activityLabel = "Activity", activitySlot, feedback, onBack, }) {
12
+ if (!feedback)
13
+ return _jsx(FeedbackUserDetailEmpty, {});
14
+ return (_jsxs("div", { className: "grid content-start gap-(--panel-gap)", children: [_jsx(FeedbackUserDetailHeader, { feedback: feedback, onBack: onBack }), _jsx(FeedbackUserDetailMeta, { feedback: feedback }), _jsx(FeedbackUserDetailBody, { feedback: feedback }), _jsx(FeedbackUserAttachments, { feedback: feedback }), activitySlot ? (_jsx(FeedbackUserActivity, { activityLabel: activityLabel, activitySlot: activitySlot })) : null] }));
15
+ }
16
+ function FeedbackUserDetailHeader({ feedback, onBack, }) {
17
+ return (_jsx("header", { className: "grid gap-3", children: _jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [onBack ? _jsx(FeedbackUserDetailBackButton, { onBack: onBack }) : null, _jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [_jsx("h3", { className: "truncate text-sm font-medium text-foreground", children: feedback.subject }), _jsx(FeedbackUserDetailBadges, { feedback: feedback })] }) })] }) }));
18
+ }
19
+ function FeedbackUserDetailBadges({ feedback }) {
20
+ return (_jsxs("div", { className: "flex shrink-0 flex-wrap justify-end gap-2", children: [_jsx(FeedbackTypeBadge, { type: feedback.type }), _jsx(FeedbackStatusBadge, { status: feedback.status })] }));
21
+ }
22
+ function FeedbackUserDetailBackButton({ onBack }) {
23
+ return (_jsx(Button, { "aria-label": "Back to my feedback", className: "-ml-2 shrink-0", onClick: onBack, size: "icon", type: "button", variant: "ghost", children: _jsx(ArrowLeftIcon, {}) }));
24
+ }
25
+ function FeedbackUserDetailMeta({ feedback }) {
26
+ return (_jsxs(PropertyList, { children: [_jsx(FeedbackProperty, { label: "Submitted", children: _jsx(FeedbackUserDateValue, { value: feedback.submittedAt }) }), _jsx(FeedbackProperty, { label: "Updated", children: _jsx(FeedbackUserDateValue, { value: feedback.updatedAt }) }), _jsx(FeedbackProperty, { label: "Reference", children: _jsx("span", { className: "font-mono text-xs tabular-nums", children: feedback.referenceId ?? feedback.id }) })] }));
27
+ }
28
+ function FeedbackUserDetailBody({ feedback }) {
29
+ return (_jsxs(Card, { className: "grid gap-2 p-(--panel-padding)", children: [_jsx("div", { className: "text-meta text-muted-foreground", children: "Feedback" }), _jsx("p", { className: "text-sm whitespace-pre-wrap text-foreground", children: feedback.description })] }));
30
+ }
31
+ function FeedbackProperty({ children, label }) {
32
+ return (_jsxs(PropertyListItem, { children: [_jsx(PropertyListLabel, { children: label }), _jsx(PropertyListValue, { children: children })] }));
33
+ }
34
+ function FeedbackUserDateValue({ value }) {
35
+ return (_jsx("time", { className: "font-mono text-xs tabular-nums", dateTime: getFeedbackTimestampDateTime(value), children: formatFeedbackTimestampFull(value) }));
36
+ }
37
+ function FeedbackUserAttachments({ feedback }) {
38
+ const attachments = feedback.attachments ?? [];
39
+ if (attachments.length === 0)
40
+ return null;
41
+ return (_jsxs("section", { className: "grid gap-2", children: [_jsx("div", { className: "text-meta text-muted-foreground", children: "Attachments" }), _jsx(ItemGroup, { children: attachments.map((attachment, index) => (_jsxs(Item, { size: "sm", variant: "outline", children: [_jsx(ItemMedia, { variant: "icon", children: _jsx(PaperclipIcon, {}) }), _jsx(ItemContent, { children: _jsx(ItemTitle, { children: getAttachmentTitle(attachment) }) })] }, getAttachmentKey(attachment, index)))) })] }));
42
+ }
43
+ function getAttachmentKey(attachment, index) {
44
+ return `${attachment.url ?? attachment.name}-${index}`;
45
+ }
46
+ function getAttachmentTitle(attachment) {
47
+ if (!attachment.url)
48
+ return attachment.name;
49
+ return (_jsx("a", { className: "underline-offset-4 hover:underline", href: attachment.url, children: attachment.name }));
50
+ }
51
+ function FeedbackUserActivity({ activityLabel, activitySlot, }) {
52
+ return (_jsxs(Card, { className: "grid gap-2 p-(--panel-padding)", children: [_jsx("div", { className: "text-meta text-muted-foreground", children: activityLabel }), activitySlot] }));
53
+ }
54
+ function FeedbackUserDetailEmpty() {
55
+ return (_jsx(Empty, { className: "min-h-72 border border-dashed", children: _jsxs(EmptyHeader, { children: [_jsx(EmptyMedia, { variant: "icon", children: _jsx(MessageSquareTextIcon, {}) }), _jsx(EmptyTitle, { children: "Select feedback" }), _jsx(EmptyDescription, { children: "Choose a submission to see its progress and details." })] }) }));
56
+ }
57
+ export { FeedbackUserDetail };
@@ -0,0 +1,9 @@
1
+ import type { UserFeedbackItem } from "@ciridae/ui/feedback-tracking-types";
2
+ type FeedbackUserListProps = {
3
+ isLoading?: boolean;
4
+ items: UserFeedbackItem[];
5
+ onSelectFeedback?: (item: UserFeedbackItem) => void;
6
+ selectedId?: string;
7
+ };
8
+ declare function FeedbackUserList({ isLoading, items, onSelectFeedback, selectedId, }: FeedbackUserListProps): import("react").JSX.Element;
9
+ export { FeedbackUserList, type FeedbackUserListProps };
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { InboxIcon } from "lucide-react";
3
+ import { formatFeedbackTimestamp } from "@ciridae/ui/feedback-date-format";
4
+ import { FeedbackStatusBadge } from "@ciridae/ui/feedback-status-badge";
5
+ import { FeedbackTypeBadge } from "@ciridae/ui/feedback-type-badge";
6
+ import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@ciridae/ui/empty";
7
+ import { Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemTitle, } from "@ciridae/ui/item";
8
+ import { Skeleton } from "@ciridae/ui/skeleton";
9
+ import { cn } from "@ciridae/ui/utils";
10
+ function FeedbackUserList({ isLoading = false, items, onSelectFeedback, selectedId, }) {
11
+ if (isLoading)
12
+ return _jsx(FeedbackUserListLoading, {});
13
+ if (items.length === 0)
14
+ return _jsx(FeedbackUserListEmpty, {});
15
+ return (_jsx(ItemGroup, { className: "gap-2", children: items.map((item) => (_jsx(FeedbackUserListItem, { item: item, onSelectFeedback: onSelectFeedback, selected: item.id === selectedId }, item.id))) }));
16
+ }
17
+ function FeedbackUserListItem({ item, onSelectFeedback, selected, }) {
18
+ return (_jsx(Item, { "aria-current": selected ? "true" : undefined, asChild: true, className: cn("w-full cursor-pointer text-left", selected && "border-foreground/30 bg-muted/50"), size: "sm", variant: "outline", children: _jsx("button", { onClick: () => onSelectFeedback?.(item), type: "button", children: _jsx(FeedbackUserListItemContent, { item: item }) }) }));
19
+ }
20
+ function FeedbackUserListItemContent({ item }) {
21
+ return (_jsxs(_Fragment, { children: [_jsxs(ItemContent, { className: "min-w-0", children: [_jsx(ItemTitle, { className: "max-w-full truncate", children: item.subject }), _jsx(ItemDescription, { className: "line-clamp-1", children: item.description })] }), _jsxs(ItemActions, { className: "shrink-0", children: [_jsx(FeedbackTypeBadge, { type: item.type }), _jsx(FeedbackStatusBadge, { status: item.status })] }), _jsxs(ItemFooter, { children: [_jsx(FeedbackListDate, { label: "Submitted", value: item.submittedAt }), item.updatedAt ? _jsx(FeedbackListDate, { label: "Updated", value: item.updatedAt }) : null] })] }));
22
+ }
23
+ function FeedbackListDate({ label, value }) {
24
+ return (_jsxs("span", { className: "font-mono text-xs text-muted-foreground tabular-nums", children: [label, " ", formatFeedbackTimestamp(value)] }));
25
+ }
26
+ function FeedbackUserListLoading() {
27
+ return (_jsx("div", { "aria-label": "Loading feedback", className: "grid gap-2", role: "status", children: loadingItems.map((item) => (_jsxs("div", { className: "rounded-md border p-(--panel-padding)", children: [_jsx(Skeleton, { className: "mb-2 h-4 w-2/3" }), _jsx(Skeleton, { className: "mb-4 h-3 w-full" }), _jsx(Skeleton, { className: "h-3 w-1/2" })] }, item))) }));
28
+ }
29
+ function FeedbackUserListEmpty() {
30
+ return (_jsx(Empty, { className: "min-h-72 border border-dashed", children: _jsxs(EmptyHeader, { children: [_jsx(EmptyMedia, { variant: "icon", children: _jsx(InboxIcon, {}) }), _jsx(EmptyTitle, { children: "No feedback yet" }), _jsx(EmptyDescription, { children: "Feedback you submit will appear here with its current progress." })] }) }));
31
+ }
32
+ const loadingItems = ["first", "second", "third"];
33
+ export { FeedbackUserList };
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ type InviteUserRole = {
3
+ description?: string;
4
+ label: string;
5
+ value: string;
6
+ };
7
+ type InviteUserValues = {
8
+ email: string;
9
+ role: string;
10
+ };
11
+ type InviteUserSheetProps = {
12
+ defaultRole?: string;
13
+ isSubmitting?: boolean;
14
+ onOpenChange: (open: boolean) => void;
15
+ onSubmit: (values: InviteUserValues) => void | Promise<void>;
16
+ open: boolean;
17
+ roles: InviteUserRole[];
18
+ };
19
+ declare function InviteUserSheet({ defaultRole, isSubmitting, onOpenChange, onSubmit, open, roles, }: InviteUserSheetProps): React.JSX.Element;
20
+ export { InviteUserSheet, type InviteUserRole, type InviteUserSheetProps, type InviteUserValues };
@@ -0,0 +1,72 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { SendIcon } from "lucide-react";
4
+ import { Button } from "@ciridae/ui/button";
5
+ import { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, } from "@ciridae/ui/field";
6
+ import { Input } from "@ciridae/ui/input";
7
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@ciridae/ui/select";
8
+ import { Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@ciridae/ui/sheet";
9
+ function InviteUserSheet({ defaultRole, isSubmitting = false, onOpenChange, onSubmit, open, roles, }) {
10
+ const initialRole = getInitialRole(roles, defaultRole);
11
+ const formId = React.useId();
12
+ const emailFieldId = `${formId}-email`;
13
+ const roleFieldId = `${formId}-role`;
14
+ const [email, setEmail] = React.useState("");
15
+ const [role, setRole] = React.useState(initialRole);
16
+ const [error, setError] = React.useState();
17
+ React.useEffect(() => {
18
+ setRole(initialRole);
19
+ }, [initialRole]);
20
+ React.useEffect(() => {
21
+ if (open)
22
+ return;
23
+ setEmail("");
24
+ setError(undefined);
25
+ setRole(initialRole);
26
+ }, [initialRole, open]);
27
+ const submitInvite = async (event) => {
28
+ event.preventDefault();
29
+ const values = { email: email.trim(), role };
30
+ const validationError = getInviteValidationError(values);
31
+ setError(validationError);
32
+ if (validationError)
33
+ return;
34
+ try {
35
+ await onSubmit(values);
36
+ }
37
+ catch {
38
+ setError("Unable to send invite. Please try again.");
39
+ }
40
+ };
41
+ return (_jsx(Sheet, { onOpenChange: onOpenChange, open: open, children: _jsxs(SheetContent, { children: [_jsx(InviteUserSheetHeader, {}), _jsx(SheetBody, { children: _jsx("form", { className: "grid gap-(--panel-gap)", id: formId, onSubmit: submitInvite, children: _jsx(InviteUserFields, { email: email, emailFieldId: emailFieldId, error: error, isSubmitting: isSubmitting, onEmailChange: setEmail, onRoleChange: setRole, role: role, roleFieldId: roleFieldId, roles: roles }) }) }), _jsx(InviteUserSheetFooter, { formId: formId, isSubmitting: isSubmitting, roles: roles })] }) }));
42
+ }
43
+ function InviteUserSheetHeader() {
44
+ return (_jsxs(SheetHeader, { children: [_jsx(SheetTitle, { children: "Invite user" }), _jsx(SheetDescription, { children: "Add a teammate and send an application invite." })] }));
45
+ }
46
+ function InviteUserFields({ email, emailFieldId, error, isSubmitting, onEmailChange, onRoleChange, role, roleFieldId, roles, }) {
47
+ return (_jsxs(FieldGroup, { children: [_jsxs(Field, { "data-invalid": error === "Email is required", children: [_jsx(FieldLabel, { htmlFor: emailFieldId, children: "Email" }), _jsx(Input, { "aria-invalid": error === "Email is required", autoComplete: "email", disabled: isSubmitting, id: emailFieldId, onChange: (event) => onEmailChange(event.target.value), placeholder: "name@company.com", type: "email", value: email }), error === "Email is required" ? _jsx(FieldError, { children: error }) : null] }), _jsx(InviteUserRoleField, { error: error, isSubmitting: isSubmitting, onRoleChange: onRoleChange, role: role, roleFieldId: roleFieldId, roles: roles }), _jsx(InviteUserSubmitError, { error: error })] }));
48
+ }
49
+ function InviteUserSubmitError({ error }) {
50
+ if (!error || error === "Email is required" || error === "Role is required")
51
+ return null;
52
+ return _jsx(FieldError, { children: error });
53
+ }
54
+ function InviteUserRoleField({ error, isSubmitting, onRoleChange, role, roleFieldId, roles, }) {
55
+ return (_jsxs(Field, { "data-invalid": error === "Role is required", children: [_jsxs(FieldContent, { children: [_jsx(FieldLabel, { htmlFor: roleFieldId, children: "Role" }), _jsx(FieldDescription, { children: "Choose the initial access level for this user." })] }), _jsxs(Select, { disabled: isSubmitting || roles.length === 0, onValueChange: onRoleChange, value: role, children: [_jsx(SelectTrigger, { "aria-invalid": error === "Role is required", className: "w-full", id: roleFieldId, children: _jsx(SelectValue, { placeholder: "Select role" }) }), _jsx(SelectContent, { children: roles.map((item) => (_jsx(SelectItem, { value: item.value, children: item.label }, item.value))) })] }), error === "Role is required" ? _jsx(FieldError, { children: error }) : null] }));
56
+ }
57
+ function InviteUserSheetFooter({ formId, isSubmitting, roles, }) {
58
+ return (_jsx(SheetFooter, { children: _jsxs(Button, { disabled: roles.length === 0, form: formId, loading: isSubmitting, type: "submit", children: [_jsx(SendIcon, {}), "Send invite"] }) }));
59
+ }
60
+ function getInitialRole(roles, defaultRole) {
61
+ if (defaultRole && roles.some((role) => role.value === defaultRole))
62
+ return defaultRole;
63
+ return roles[0]?.value ?? "";
64
+ }
65
+ function getInviteValidationError(values) {
66
+ if (!values.email)
67
+ return "Email is required";
68
+ if (!values.role)
69
+ return "Role is required";
70
+ return undefined;
71
+ }
72
+ export { InviteUserSheet };
@@ -0,0 +1,26 @@
1
+ import type * as React from "react";
2
+ import type { KanbanCardData, KanbanColumnData, KanbanMoveEvent } from "@ciridae/ui/kanban-types";
3
+ import { type KanbanBoardState, type KanbanOverlayRect } from "@ciridae/ui/kanban-board-utils";
4
+ type KanbanBoardColumnProps = {
5
+ activeCardId: string | undefined;
6
+ activeCardRect: KanbanOverlayRect | undefined;
7
+ activeMove: KanbanMoveEvent | undefined;
8
+ boardState: KanbanBoardState;
9
+ column: KanbanColumnData;
10
+ columnMaxHeight: React.CSSProperties["maxHeight"];
11
+ empty?: React.ReactNode;
12
+ isLoading: boolean;
13
+ isOver: boolean;
14
+ onCardMove?: (event: KanbanMoveEvent) => void;
15
+ onCardSelect?: (card: KanbanCardData) => void;
16
+ renderCard?: (card: KanbanCardData) => React.ReactNode;
17
+ renderCardActions?: (card: KanbanCardData) => React.ReactNode;
18
+ renderColumnActions?: (column: KanbanColumnData) => React.ReactNode;
19
+ suppressSelectRef: React.MutableRefObject<boolean>;
20
+ };
21
+ declare function KanbanBoardColumn({ activeCardId, activeCardRect, activeMove, boardState, column, columnMaxHeight, empty, isLoading, isOver, onCardMove, onCardSelect, renderCard, renderCardActions, renderColumnActions, suppressSelectRef, }: KanbanBoardColumnProps): React.JSX.Element;
22
+ declare function KanbanDragOverlay({ activeCard, activeCardRect, }: {
23
+ activeCard: KanbanCardData | undefined;
24
+ activeCardRect: KanbanOverlayRect | undefined;
25
+ }): React.JSX.Element;
26
+ export { KanbanBoardColumn, KanbanDragOverlay };
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DragOverlay, useDroppable } from "@dnd-kit/core";
3
+ import { SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
4
+ import { CSS } from "@dnd-kit/utilities";
5
+ import { createPortal } from "react-dom";
6
+ import { KanbanCard } from "@ciridae/ui/kanban-card";
7
+ import { KanbanColumn } from "@ciridae/ui/kanban-column";
8
+ import { getColumnDroppableId, } from "@ciridae/ui/kanban-board-utils";
9
+ function KanbanBoardColumn({ activeCardId, activeCardRect, activeMove, boardState, column, columnMaxHeight, empty, isLoading, isOver, onCardMove, onCardSelect, renderCard, renderCardActions, renderColumnActions, suppressSelectRef, }) {
10
+ const cards = boardState.cardsByColumnId.get(column.id) ?? [];
11
+ const dropPlaceholderIndex = getDropPlaceholderIndex(column.id, activeMove);
12
+ const droppable = useDroppable({
13
+ data: { columnId: column.id, type: "column" },
14
+ id: getColumnDroppableId(column.id),
15
+ });
16
+ return (_jsx("div", { className: "w-72 shrink-0", ref: droppable.setNodeRef, children: _jsx(SortableContext, { items: cards.map((card) => card.id), strategy: verticalListSortingStrategy, children: _jsx(KanbanColumn, { actionsSlot: renderColumnActions?.(column), cards: cards, column: column, columnMaxHeight: columnMaxHeight, dropPlaceholder: dropPlaceholderIndex === undefined ? undefined : (_jsx(KanbanDropPlaceholder, { height: activeCardRect?.height })), dropPlaceholderIndex: dropPlaceholderIndex, empty: empty, isLoading: isLoading, isOver: isOver || droppable.isOver, renderCard: (card) => (_jsx(SortableKanbanCard, { activeCardHeight: activeCardRect?.height, activeCardMode: getActiveCardMode(card, activeMove), card: card, dragDisabled: Boolean(!onCardMove || card.disabled), isActiveCard: activeCardId === card.id, onCardSelect: onCardSelect, renderCard: renderCard, renderCardActions: renderCardActions, suppressSelectRef: suppressSelectRef })) }) }) }));
17
+ }
18
+ function SortableKanbanCard({ activeCardHeight, activeCardMode, card, dragDisabled, isActiveCard, onCardSelect, renderCard, renderCardActions, suppressSelectRef, }) {
19
+ const sortable = useSortable({
20
+ data: { card, columnId: card.columnId, type: "card" },
21
+ disabled: dragDisabled,
22
+ id: card.id,
23
+ });
24
+ const style = {
25
+ transform: CSS.Transform.toString(sortable.transform),
26
+ transition: sortable.transition,
27
+ };
28
+ return (_jsx("div", { ...sortable.attributes, ...sortable.listeners, "aria-disabled": card.disabled || undefined, className: "rounded-md outline-none focus-visible:ring-[var(--focus-ring-width)] focus-visible:ring-ring/50 data-[disabled=true]:cursor-default data-[disabled=true]:opacity-60 data-[draggable=true]:cursor-grab data-[draggable=true]:active:cursor-grabbing", "data-disabled": Boolean(card.disabled), "data-draggable": !dragDisabled, onClick: getSortableCardClickHandler({ card, onCardSelect, suppressSelectRef }), ref: sortable.setNodeRef, style: style, children: _jsx(SortableKanbanCardContent, { activeCardHeight: activeCardHeight, activeCardMode: activeCardMode, card: card, isActiveCard: isActiveCard, isDragging: sortable.isDragging, renderCard: renderCard, renderCardActions: renderCardActions }) }));
29
+ }
30
+ function SortableKanbanCardContent({ activeCardHeight, activeCardMode, card, isActiveCard, isDragging, renderCard, renderCardActions, }) {
31
+ if (isActiveCard && activeCardMode === "spacer") {
32
+ return _jsx(KanbanActiveCardSpacer, { height: activeCardHeight });
33
+ }
34
+ if (isActiveCard)
35
+ return _jsx(KanbanDropPlaceholder, { height: activeCardHeight });
36
+ if (renderCard)
37
+ return renderCard(card);
38
+ return _jsx(KanbanCard, { actionsSlot: renderCardActions?.(card), card: card, isDragging: isDragging });
39
+ }
40
+ function KanbanActiveCardSpacer({ height }) {
41
+ return _jsx("div", { "aria-hidden": "true", style: { height: height ? Math.max(height, 72) : 96 } });
42
+ }
43
+ function KanbanDropPlaceholder({ height }) {
44
+ return (_jsx("div", { "aria-hidden": "true", className: "rounded-md border border-dashed border-ring bg-muted/60 shadow-inner", style: { height: height ? Math.max(height, 72) : 96 } }));
45
+ }
46
+ function KanbanDragOverlay({ activeCard, activeCardRect, }) {
47
+ const overlay = (_jsx(DragOverlay, { adjustScale: false, children: activeCard ? (_jsx("div", { style: { width: activeCardRect?.width }, children: _jsx(KanbanCard, { card: activeCard, isDragging: true }) })) : null }));
48
+ if (typeof document === "undefined")
49
+ return overlay;
50
+ return createPortal(overlay, document.body);
51
+ }
52
+ function getSortableCardClickHandler({ card, onCardSelect, suppressSelectRef, }) {
53
+ return (event) => {
54
+ if (suppressSelectRef.current) {
55
+ event.preventDefault();
56
+ event.stopPropagation();
57
+ return;
58
+ }
59
+ if (!onCardSelect || card.disabled)
60
+ return;
61
+ if (event.target instanceof HTMLElement && event.target.closest("[data-kanban-card-action]")) {
62
+ return;
63
+ }
64
+ onCardSelect(card);
65
+ };
66
+ }
67
+ function getDropPlaceholderIndex(columnId, activeMove) {
68
+ if (!activeMove)
69
+ return undefined;
70
+ if (activeMove.fromColumnId === activeMove.toColumnId)
71
+ return undefined;
72
+ if (activeMove.toColumnId !== columnId)
73
+ return undefined;
74
+ return activeMove.toIndex;
75
+ }
76
+ function getActiveCardMode(card, activeMove) {
77
+ if (!activeMove)
78
+ return "placeholder";
79
+ if (activeMove.cardId !== card.id)
80
+ return "placeholder";
81
+ if (activeMove.fromColumnId === activeMove.toColumnId)
82
+ return "placeholder";
83
+ return "spacer";
84
+ }
85
+ export { KanbanBoardColumn, KanbanDragOverlay };
@@ -0,0 +1,42 @@
1
+ import type * as React from "react";
2
+ import type { DragEndEvent, DragOverEvent, DragStartEvent } from "@dnd-kit/core";
3
+ import type { KanbanCardData, KanbanColumnData, KanbanMoveEvent } from "@ciridae/ui/kanban-types";
4
+ type KanbanBoardState = {
5
+ cardById: Map<string, KanbanCardData>;
6
+ cardsByColumnId: Map<string, KanbanCardData[]>;
7
+ };
8
+ type KanbanOverlayRect = {
9
+ height: number;
10
+ width: number;
11
+ };
12
+ type KanbanDragStateSetters = {
13
+ setActiveCard: React.Dispatch<React.SetStateAction<KanbanCardData | undefined>>;
14
+ setActiveCardRect: React.Dispatch<React.SetStateAction<KanbanOverlayRect | undefined>>;
15
+ setActiveMove: React.Dispatch<React.SetStateAction<KanbanMoveEvent | undefined>>;
16
+ setOverColumnId: React.Dispatch<React.SetStateAction<string | undefined>>;
17
+ };
18
+ declare function getKanbanBoardState(columns: KanbanColumnData[], cards: KanbanCardData[]): {
19
+ cardById: Map<string, KanbanCardData>;
20
+ cardsByColumnId: Map<string, KanbanCardData[]>;
21
+ };
22
+ declare function getDragStartHandler({ cardById, setters, suppressSelectRef, }: {
23
+ cardById: Map<string, KanbanCardData>;
24
+ setters: KanbanDragStateSetters;
25
+ suppressSelectRef: React.MutableRefObject<boolean>;
26
+ }): (event: DragStartEvent) => void;
27
+ declare function getDragOverHandler({ boardState, setActiveMove, setOverColumnId, }: {
28
+ boardState: KanbanBoardState;
29
+ setActiveMove: React.Dispatch<React.SetStateAction<KanbanMoveEvent | undefined>>;
30
+ setOverColumnId: React.Dispatch<React.SetStateAction<string | undefined>>;
31
+ }): (event: DragOverEvent) => void;
32
+ declare function getDragEndHandler({ activeMove, boardState, onCardMove, setters, suppressSelectRef, }: {
33
+ activeMove: KanbanMoveEvent | undefined;
34
+ boardState: KanbanBoardState;
35
+ onCardMove?: (event: KanbanMoveEvent) => void;
36
+ setters: KanbanDragStateSetters;
37
+ suppressSelectRef: React.MutableRefObject<boolean>;
38
+ }): (event: DragEndEvent) => void;
39
+ declare function clearDragState(setters: KanbanDragStateSetters): void;
40
+ declare function getColumnDroppableId(columnId: string): string;
41
+ export { clearDragState, getColumnDroppableId, getDragEndHandler, getDragOverHandler, getDragStartHandler, getKanbanBoardState, };
42
+ export type { KanbanBoardState, KanbanDragStateSetters, KanbanOverlayRect };