@flamingo-stack/openframe-frontend-core 0.0.284 → 0.0.285

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 (65) hide show
  1. package/dist/{chunk-P4ARMFW3.js → chunk-23UOJUDF.js} +2 -2
  2. package/dist/{chunk-BRLGG3EZ.cjs → chunk-44ZFLMYC.cjs} +25 -25
  3. package/dist/{chunk-BRLGG3EZ.cjs.map → chunk-44ZFLMYC.cjs.map} +1 -1
  4. package/dist/{chunk-OUI2MBU7.js → chunk-53CFL7PH.js} +2 -2
  5. package/dist/{chunk-24L4FLRC.cjs → chunk-DPKUSBQH.cjs} +193 -116
  6. package/dist/chunk-DPKUSBQH.cjs.map +1 -0
  7. package/dist/{chunk-VKDJXB7L.js → chunk-KNCDUWY2.js} +2 -2
  8. package/dist/{chunk-33RLTUN2.js → chunk-O5N57CRV.js} +2 -2
  9. package/dist/{chunk-3SM6DA24.cjs → chunk-P45Q4QCU.cjs} +10 -10
  10. package/dist/{chunk-3SM6DA24.cjs.map → chunk-P45Q4QCU.cjs.map} +1 -1
  11. package/dist/{chunk-HX7ZGKQ4.cjs → chunk-RJUGNL2A.cjs} +6 -6
  12. package/dist/{chunk-HX7ZGKQ4.cjs.map → chunk-RJUGNL2A.cjs.map} +1 -1
  13. package/dist/{chunk-RGXDDOQR.js → chunk-VQW7CEGS.js} +1725 -1648
  14. package/dist/chunk-VQW7CEGS.js.map +1 -0
  15. package/dist/{chunk-XAS7JVHX.cjs → chunk-XDI5JSWB.cjs} +34 -34
  16. package/dist/{chunk-XAS7JVHX.cjs.map → chunk-XDI5JSWB.cjs.map} +1 -1
  17. package/dist/components/chat/index.cjs +2 -2
  18. package/dist/components/chat/index.js +1 -1
  19. package/dist/components/contact/index.cjs +3 -3
  20. package/dist/components/contact/index.js +2 -2
  21. package/dist/components/faq/index.cjs +3 -3
  22. package/dist/components/faq/index.js +2 -2
  23. package/dist/components/features/board/board-column.d.ts +3 -1
  24. package/dist/components/features/board/board-column.d.ts.map +1 -1
  25. package/dist/components/features/board/board-ticket-approval.d.ts +16 -0
  26. package/dist/components/features/board/board-ticket-approval.d.ts.map +1 -0
  27. package/dist/components/features/board/board.d.ts +3 -1
  28. package/dist/components/features/board/board.d.ts.map +1 -1
  29. package/dist/components/features/board/index.d.ts +3 -1
  30. package/dist/components/features/board/index.d.ts.map +1 -1
  31. package/dist/components/features/board/ticket-card.d.ts +3 -1
  32. package/dist/components/features/board/ticket-card.d.ts.map +1 -1
  33. package/dist/components/features/board/types.d.ts +11 -0
  34. package/dist/components/features/board/types.d.ts.map +1 -1
  35. package/dist/components/features/index.cjs +4 -2
  36. package/dist/components/features/index.cjs.map +1 -1
  37. package/dist/components/features/index.js +3 -1
  38. package/dist/components/index.cjs +55 -53
  39. package/dist/components/index.cjs.map +1 -1
  40. package/dist/components/index.js +6 -4
  41. package/dist/components/index.js.map +1 -1
  42. package/dist/components/navigation/index.cjs +2 -2
  43. package/dist/components/navigation/index.js +1 -1
  44. package/dist/components/related-content/index.cjs +3 -3
  45. package/dist/components/related-content/index.js +2 -2
  46. package/dist/components/tickets/index.cjs +52 -52
  47. package/dist/components/tickets/index.js +3 -3
  48. package/dist/components/ui/index.cjs +2 -2
  49. package/dist/components/ui/index.js +1 -1
  50. package/dist/index.cjs +4 -2
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.js +3 -1
  53. package/package.json +1 -1
  54. package/src/components/features/board/board-column.tsx +11 -1
  55. package/src/components/features/board/board-ticket-approval.tsx +76 -0
  56. package/src/components/features/board/board.tsx +6 -0
  57. package/src/components/features/board/index.ts +3 -0
  58. package/src/components/features/board/ticket-card.tsx +12 -0
  59. package/src/components/features/board/types.ts +12 -0
  60. package/dist/chunk-24L4FLRC.cjs.map +0 -1
  61. package/dist/chunk-RGXDDOQR.js.map +0 -1
  62. /package/dist/{chunk-P4ARMFW3.js.map → chunk-23UOJUDF.js.map} +0 -0
  63. /package/dist/{chunk-OUI2MBU7.js.map → chunk-53CFL7PH.js.map} +0 -0
  64. /package/dist/{chunk-VKDJXB7L.js.map → chunk-KNCDUWY2.js.map} +0 -0
  65. /package/dist/{chunk-33RLTUN2.js.map → chunk-O5N57CRV.js.map} +0 -0
package/dist/index.js CHANGED
@@ -62,6 +62,7 @@ import {
62
62
  Board,
63
63
  BoardColumn,
64
64
  BoardColumnHeader,
65
+ BoardTicketApproval,
65
66
  BrandAssociationCard,
66
67
  BrandAssociationGrid,
67
68
  Breadcrumb,
@@ -692,7 +693,7 @@ import {
692
693
  validateEmailDomain,
693
694
  validateEmailDomainList,
694
695
  validatePhoneNumber
695
- } from "./chunk-RGXDDOQR.js";
696
+ } from "./chunk-VQW7CEGS.js";
696
697
  import {
697
698
  CommandApprovalToast,
698
699
  DEFAULT_MIN_FILL_MS,
@@ -1215,6 +1216,7 @@ export {
1215
1216
  Board,
1216
1217
  BoardColumn,
1217
1218
  BoardColumnHeader,
1219
+ BoardTicketApproval,
1218
1220
  BotIcon,
1219
1221
  BrandAssociationCard,
1220
1222
  BrandAssociationGrid,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamingo-stack/openframe-frontend-core",
3
- "version": "0.0.284",
3
+ "version": "0.0.285",
4
4
  "description": "Shared design system and components for all Flamingo platforms",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,6 +19,8 @@ export interface BoardColumnProps {
19
19
  onArchive?: (columnId: string) => void
20
20
  getTicketHref?: (ticketId: string) => string
21
21
  renderAssignSlot?: (ticket: BoardTicket) => React.ReactNode
22
+ onApprove?: (ticketId: string, requestId?: string) => void | Promise<void>
23
+ onReject?: (ticketId: string, requestId?: string) => void | Promise<void>
22
24
  onLoadMore?: (columnId: string) => void
23
25
  loadMoreRootMargin?: string
24
26
  joinLeft?: boolean
@@ -33,6 +35,8 @@ export function BoardColumn({
33
35
  onArchive,
34
36
  getTicketHref,
35
37
  renderAssignSlot,
38
+ onApprove,
39
+ onReject,
36
40
  onLoadMore,
37
41
  loadMoreRootMargin = '200px 0px',
38
42
  joinLeft = false,
@@ -64,6 +68,8 @@ export function BoardColumn({
64
68
  column={column}
65
69
  getTicketHref={getTicketHref}
66
70
  renderAssignSlot={renderAssignSlot}
71
+ onApprove={onApprove}
72
+ onReject={onReject}
67
73
  onLoadMore={onLoadMore}
68
74
  loadMoreRootMargin={loadMoreRootMargin}
69
75
  />
@@ -77,11 +83,13 @@ interface ColumnBodyProps {
77
83
  column: BoardColumnDef
78
84
  getTicketHref?: (ticketId: string) => string
79
85
  renderAssignSlot?: (ticket: BoardTicket) => React.ReactNode
86
+ onApprove?: (ticketId: string, requestId?: string) => void | Promise<void>
87
+ onReject?: (ticketId: string, requestId?: string) => void | Promise<void>
80
88
  onLoadMore?: (columnId: string) => void
81
89
  loadMoreRootMargin: string
82
90
  }
83
91
 
84
- function ColumnBody({ column, getTicketHref, renderAssignSlot, onLoadMore, loadMoreRootMargin }: ColumnBodyProps) {
92
+ function ColumnBody({ column, getTicketHref, renderAssignSlot, onApprove, onReject, onLoadMore, loadMoreRootMargin }: ColumnBodyProps) {
85
93
  const ticketIds = React.useMemo(() => column.tickets.map(t => t.id), [column.tickets])
86
94
 
87
95
  const droppableData = React.useMemo(
@@ -150,6 +158,8 @@ function ColumnBody({ column, getTicketHref, renderAssignSlot, onLoadMore, loadM
150
158
  columnColor={column.color}
151
159
  href={getTicketHref?.(t.id)}
152
160
  renderAssignSlot={renderAssignSlot}
161
+ onApprove={onApprove}
162
+ onReject={onReject}
153
163
  dragDisabled={column.dragDisabled}
154
164
  />
155
165
  ))
@@ -0,0 +1,76 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cn } from '../../../utils/cn'
5
+ import { ApprovalBatchMessage } from '../../chat/approval-batch-message'
6
+ import { useCollapsible } from '../../chat/hooks/use-collapsible'
7
+ import { Chevron02DownIcon, Chevron02UpIcon, DotsLoaderIcon, ShieldCheckIcon } from '../../icons-v2-generated'
8
+ import type { BoardTicketPendingApproval } from './types'
9
+
10
+ export interface BoardTicketApprovalProps {
11
+ pendingApproval: BoardTicketPendingApproval
12
+ onApprove?: (requestId?: string) => void | Promise<void>
13
+ onReject?: (requestId?: string) => void | Promise<void>
14
+ }
15
+
16
+ /**
17
+ * Inline, collapsed-by-default approval section for a board ticket card. Expands to
18
+ * the shared {@link ApprovalBatchMessage} so the request can be approved/rejected
19
+ * without leaving the board. The header switches between the client variant (grey,
20
+ * "Pending client approval") and the technician/admin variant (yellow shield,
21
+ * "Technician approval required") on `approvalType`.
22
+ */
23
+ export function BoardTicketApproval({ pendingApproval, onApprove, onReject }: BoardTicketApprovalProps) {
24
+ const [expanded, setExpanded] = React.useState(false)
25
+ const { innerRef, containerStyle } = useCollapsible({ expanded })
26
+ const isAdmin = pendingApproval.approvalType === 'ADMIN'
27
+
28
+ return (
29
+ <div className="pointer-events-auto flex flex-col">
30
+ <button
31
+ type="button"
32
+ onClick={() => setExpanded(v => !v)}
33
+ aria-expanded={expanded}
34
+ className="flex w-full cursor-pointer items-center gap-[var(--spacing-system-xxs)] text-h6"
35
+ >
36
+ <span
37
+ className={cn(
38
+ 'flex min-w-0 flex-1 items-center gap-[var(--spacing-system-xxs)]',
39
+ isAdmin ? 'text-ods-open-yellow' : 'text-ods-text-secondary',
40
+ )}
41
+ >
42
+ {isAdmin ? (
43
+ <ShieldCheckIcon className="size-4 shrink-0" />
44
+ ) : (
45
+ <DotsLoaderIcon size={16} className="shrink-0" />
46
+ )}
47
+ <span className="flex-1 truncate text-left">
48
+ {isAdmin ? 'Technician approval required' : 'Pending client approval'}
49
+ </span>
50
+ </span>
51
+ {expanded ? (
52
+ <Chevron02UpIcon className="size-4 shrink-0 text-ods-text-secondary" />
53
+ ) : (
54
+ <Chevron02DownIcon className="size-4 shrink-0 text-ods-text-secondary" />
55
+ )}
56
+ </button>
57
+
58
+ <div style={containerStyle}>
59
+ <div ref={innerRef} className="pt-[var(--spacing-system-xs)]">
60
+ <ApprovalBatchMessage
61
+ className="mb-0"
62
+ data={{
63
+ approvalRequestId: pendingApproval.id,
64
+ approvalType: pendingApproval.approvalType ?? 'CLIENT',
65
+ toolCalls: pendingApproval.toolCalls ?? [],
66
+ }}
67
+ status="pending"
68
+ showExecutionStatus={false}
69
+ onApprove={onApprove}
70
+ onReject={onReject}
71
+ />
72
+ </div>
73
+ </div>
74
+ </div>
75
+ )
76
+ }
@@ -32,6 +32,8 @@ export interface BoardProps {
32
32
  onArchiveColumn?: (columnId: string) => void
33
33
  getTicketHref?: (ticketId: string) => string
34
34
  renderAssignSlot?: (ticket: BoardTicket) => React.ReactNode
35
+ onApprove?: (ticketId: string, requestId?: string) => void | Promise<void>
36
+ onReject?: (ticketId: string, requestId?: string) => void | Promise<void>
35
37
  collapseStorageKey?: string
36
38
  loadMoreRootMargin?: string
37
39
  className?: string
@@ -45,6 +47,8 @@ export function Board({
45
47
  onArchiveColumn,
46
48
  getTicketHref,
47
49
  renderAssignSlot,
50
+ onApprove,
51
+ onReject,
48
52
  collapseStorageKey,
49
53
  loadMoreRootMargin,
50
54
  className,
@@ -271,6 +275,8 @@ export function Board({
271
275
  onArchive={onArchiveColumn}
272
276
  getTicketHref={getTicketHref}
273
277
  renderAssignSlot={renderAssignSlot}
278
+ onApprove={onApprove}
279
+ onReject={onReject}
274
280
  onLoadMore={onLoadMore}
275
281
  loadMoreRootMargin={loadMoreRootMargin}
276
282
  joinLeft={joinLeft}
@@ -8,6 +8,8 @@ export { BoardColumnHeader } from './board-column-header'
8
8
  export type { BoardColumnHeaderProps } from './board-column-header'
9
9
  export { TicketCard } from './ticket-card'
10
10
  export type { TicketCardProps } from './ticket-card'
11
+ export { BoardTicketApproval } from './board-ticket-approval'
12
+ export type { BoardTicketApprovalProps } from './board-ticket-approval'
11
13
  export { TicketCardSkeleton } from './ticket-card-skeleton'
12
14
  export type { TicketCardSkeletonProps } from './ticket-card-skeleton'
13
15
  export { useBoardCollapse } from './use-board-collapse'
@@ -23,4 +25,5 @@ export type {
23
25
  BoardPriority,
24
26
  BoardTicket,
25
27
  BoardTicketAssignee,
28
+ BoardTicketPendingApproval,
26
29
  } from './types'
@@ -11,6 +11,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../
11
11
  import { cn } from '../../../utils/cn'
12
12
  import { getReadableTextColor } from '../../../utils/ods-color-utils'
13
13
  import { formatTicketRelativeTime, formatTicketFullTimestamp } from '../../../utils/date-utils'
14
+ import { BoardTicketApproval } from './board-ticket-approval'
14
15
  import type { BoardPriority, BoardTicket } from './types'
15
16
 
16
17
  const PRIORITY_COLOR_CLASS: Record<BoardPriority, string> = {
@@ -31,6 +32,8 @@ export interface TicketCardProps {
31
32
  isOverlay?: boolean
32
33
  dragDisabled?: boolean
33
34
  renderAssignSlot?: (ticket: BoardTicket) => React.ReactNode
35
+ onApprove?: (ticketId: string, requestId?: string) => void | Promise<void>
36
+ onReject?: (ticketId: string, requestId?: string) => void | Promise<void>
34
37
  }
35
38
 
36
39
  export function TicketCard({
@@ -41,6 +44,8 @@ export function TicketCard({
41
44
  isOverlay = false,
42
45
  dragDisabled,
43
46
  renderAssignSlot,
47
+ onApprove,
48
+ onReject,
44
49
  }: TicketCardProps) {
45
50
  const sortableData = React.useMemo(
46
51
  () => ({ columnId, type: 'ticket' as const }),
@@ -143,6 +148,13 @@ export function TicketCard({
143
148
  style={{ backgroundColor: columnColor, color: newMessageTextColor }}
144
149
  />
145
150
  )}
151
+ {ticket.pendingApproval && (
152
+ <BoardTicketApproval
153
+ pendingApproval={ticket.pendingApproval}
154
+ onApprove={onApprove ? requestId => onApprove(ticket.id, requestId) : undefined}
155
+ onReject={onReject ? requestId => onReject(ticket.id, requestId) : undefined}
156
+ />
157
+ )}
146
158
  </>
147
159
  )
148
160
 
@@ -1,7 +1,18 @@
1
+ import type { PendingToolCallData } from '../../chat/types'
1
2
  import type { TicketStatus } from '../../ui/ticket-status-tag'
2
3
 
3
4
  export type BoardPriority = 'low' | 'medium' | 'high' | 'urgent'
4
5
 
6
+ /** Latest pending tool-approval request attached to a board ticket (from `Ticket.pendingApproval`). */
7
+ export interface BoardTicketPendingApproval {
8
+ id: string
9
+ approvalType?: string
10
+ command?: string
11
+ explanation?: string
12
+ createdAt?: string
13
+ toolCalls?: PendingToolCallData[]
14
+ }
15
+
5
16
  export interface BoardTicketAssignee {
6
17
  id: string
7
18
  initials?: string
@@ -22,6 +33,7 @@ export interface BoardTicket {
22
33
  tags?: string[]
23
34
  createdAt?: string
24
35
  hasNewMessage?: boolean
36
+ pendingApproval?: BoardTicketPendingApproval
25
37
  }
26
38
 
27
39
  export interface BoardColumnDef {