@flamingo-stack/openframe-frontend-core 0.0.523-1663.4375.1 → 0.0.523-1680.4386.1
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/dist/chat-protocol/events.d.ts +46 -1
- package/dist/chat-protocol/events.d.ts.map +1 -1
- package/dist/chat-protocol/index.cjs +57 -0
- package/dist/chat-protocol/index.cjs.map +1 -1
- package/dist/chat-protocol/index.js +56 -1
- package/dist/chat-protocol/index.js.map +1 -1
- package/dist/chat-protocol/nats-decoder.d.ts.map +1 -1
- package/dist/{chunk-NMZ33YWL.js → chunk-2ALPHSGU.js} +4 -4
- package/dist/{chunk-KBE7SNFZ.cjs → chunk-2MPS2QY5.cjs} +5 -5
- package/dist/{chunk-KBE7SNFZ.cjs.map → chunk-2MPS2QY5.cjs.map} +1 -1
- package/dist/{chunk-LJCBSJFU.cjs → chunk-3OFRFRBW.cjs} +26 -26
- package/dist/{chunk-LJCBSJFU.cjs.map → chunk-3OFRFRBW.cjs.map} +1 -1
- package/dist/{chunk-7EYNWY2N.js → chunk-43MPUCDL.js} +2 -2
- package/dist/{chunk-NBANPQ3N.js → chunk-4DJL34HL.js} +2 -2
- package/dist/{chunk-PZVYYDFL.cjs → chunk-6MW6ELZQ.cjs} +37 -37
- package/dist/{chunk-PZVYYDFL.cjs.map → chunk-6MW6ELZQ.cjs.map} +1 -1
- package/dist/{chunk-H5TAFA4H.cjs → chunk-ARCH6RK6.cjs} +4 -4
- package/dist/{chunk-H5TAFA4H.cjs.map → chunk-ARCH6RK6.cjs.map} +1 -1
- package/dist/{chunk-L4DKYRHG.js → chunk-C7T363HO.js} +2 -2
- package/dist/{chunk-OPU5BLBT.js → chunk-CBD3IHPF.js} +2 -2
- package/dist/{chunk-HPGBHELQ.cjs → chunk-CE4CBCKX.cjs} +7 -7
- package/dist/{chunk-HPGBHELQ.cjs.map → chunk-CE4CBCKX.cjs.map} +1 -1
- package/dist/{chunk-7LSK5YFW.js → chunk-E2W2XMX2.js} +2 -2
- package/dist/{chunk-VYRP7JOD.cjs → chunk-HM53VV7K.cjs} +1245 -923
- package/dist/chunk-HM53VV7K.cjs.map +1 -0
- package/dist/{chunk-QBLLF7VS.js → chunk-HYVYAWUO.js} +2 -2
- package/dist/{chunk-YJLQQGLH.js → chunk-INTFGXHO.js} +5625 -5303
- package/dist/chunk-INTFGXHO.js.map +1 -0
- package/dist/{chunk-43QX3P4G.cjs → chunk-JBCNOJMX.cjs} +3 -3
- package/dist/{chunk-43QX3P4G.cjs.map → chunk-JBCNOJMX.cjs.map} +1 -1
- package/dist/{chunk-ZIIIYUZ5.cjs → chunk-KSZPPVXT.cjs} +11 -11
- package/dist/{chunk-ZIIIYUZ5.cjs.map → chunk-KSZPPVXT.cjs.map} +1 -1
- package/dist/{chunk-ICWQQQTR.js → chunk-LEMU4JMX.js} +2 -2
- package/dist/{chunk-OGXZCZSA.cjs → chunk-M7FGOI4V.cjs} +31 -31
- package/dist/{chunk-OGXZCZSA.cjs.map → chunk-M7FGOI4V.cjs.map} +1 -1
- package/dist/{chunk-FP6HEAQC.js → chunk-MVYTOP3B.js} +5 -5
- package/dist/{chunk-ANKQQTAI.js → chunk-MYQAF43S.js} +4 -4
- package/dist/{chunk-J2OPY22M.cjs → chunk-OPPGJ4PY.cjs} +87 -87
- package/dist/{chunk-J2OPY22M.cjs.map → chunk-OPPGJ4PY.cjs.map} +1 -1
- package/dist/{chunk-7ZIGB34Y.js → chunk-QCWVGCT3.js} +6 -6
- package/dist/{chunk-JGYVXVN6.cjs → chunk-QRYJYZTW.cjs} +61 -61
- package/dist/{chunk-JGYVXVN6.cjs.map → chunk-QRYJYZTW.cjs.map} +1 -1
- package/dist/{chunk-JKUYXCG2.cjs → chunk-S4BAM7EC.cjs} +9 -9
- package/dist/{chunk-JKUYXCG2.cjs.map → chunk-S4BAM7EC.cjs.map} +1 -1
- package/dist/{chunk-7RIYOJLG.cjs → chunk-TH4BQCOD.cjs} +26 -26
- package/dist/{chunk-7RIYOJLG.cjs.map → chunk-TH4BQCOD.cjs.map} +1 -1
- package/dist/{chunk-M45XIHZY.js → chunk-TPIF252F.js} +2 -2
- package/dist/{chunk-D3PPR2WR.cjs → chunk-YTLLRLMU.cjs} +14 -14
- package/dist/{chunk-D3PPR2WR.cjs.map → chunk-YTLLRLMU.cjs.map} +1 -1
- package/dist/{chunk-BPBMHS4U.js → chunk-ZYBBV6CK.js} +2 -2
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/escalation-offer-message.d.ts +26 -0
- package/dist/components/chat/escalation-offer-message.d.ts.map +1 -0
- package/dist/components/chat/index.cjs +6 -2
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +2 -0
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +5 -1
- package/dist/components/chat/stream/chat-stream-reducer.d.ts +1 -1
- package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -1
- package/dist/components/chat/stream/message-mutations.d.ts +6 -2
- package/dist/components/chat/stream/message-mutations.d.ts.map +1 -1
- package/dist/components/chat/ticket-escalated-message.d.ts +25 -0
- package/dist/components/chat/ticket-escalated-message.d.ts.map +1 -0
- package/dist/components/chat/types/message.types.d.ts +74 -2
- package/dist/components/chat/types/message.types.d.ts.map +1 -1
- package/dist/components/chat/types/processing.types.d.ts +13 -0
- package/dist/components/chat/types/processing.types.d.ts.map +1 -1
- package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
- package/dist/components/chat/utils/history-merge.d.ts.map +1 -1
- package/dist/components/chat/utils/message-segment-accumulator.d.ts +21 -2
- package/dist/components/chat/utils/message-segment-accumulator.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/board/ticket-card.d.ts.map +1 -1
- package/dist/components/features/board/types.d.ts +7 -0
- package/dist/components/features/board/types.d.ts.map +1 -1
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +22 -22
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +136 -132
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +15 -11
- package/dist/components/index.js.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +34 -34
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +6 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +5 -1
- package/dist/index.cjs +6 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +29 -0
- package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +32 -0
- package/src/chat-protocol/events.ts +66 -0
- package/src/chat-protocol/nats-decoder.ts +47 -0
- package/src/components/chat/__tests__/escalation-offer.test.ts +276 -0
- package/src/components/chat/chat-message-enhanced.tsx +15 -0
- package/src/components/chat/chat-message-list.tsx +3 -1
- package/src/components/chat/escalation-offer-message.tsx +49 -0
- package/src/components/chat/index.ts +2 -0
- package/src/components/chat/stream/chat-stream-reducer.ts +50 -0
- package/src/components/chat/stream/message-mutations.ts +47 -20
- package/src/components/chat/ticket-escalated-message.tsx +68 -0
- package/src/components/chat/types/message.types.ts +86 -1
- package/src/components/chat/types/processing.types.ts +13 -0
- package/src/components/chat/utils/extract-incomplete-message-state.ts +10 -0
- package/src/components/chat/utils/history-merge.ts +7 -0
- package/src/components/chat/utils/message-segment-accumulator.ts +81 -2
- package/src/components/chat/utils/process-historical-messages.ts +123 -4
- package/src/components/features/board/ticket-card.tsx +7 -1
- package/src/components/features/board/types.ts +7 -0
- package/src/stories/EscalationOfferMessage.stories.tsx +86 -0
- package/src/stories/TicketCard.stories.tsx +12 -0
- package/src/stories/TicketEscalatedMessage.stories.tsx +98 -0
- package/dist/chunk-VYRP7JOD.cjs.map +0 -1
- package/dist/chunk-YJLQQGLH.js.map +0 -1
- /package/dist/{chunk-NMZ33YWL.js.map → chunk-2ALPHSGU.js.map} +0 -0
- /package/dist/{chunk-7EYNWY2N.js.map → chunk-43MPUCDL.js.map} +0 -0
- /package/dist/{chunk-NBANPQ3N.js.map → chunk-4DJL34HL.js.map} +0 -0
- /package/dist/{chunk-L4DKYRHG.js.map → chunk-C7T363HO.js.map} +0 -0
- /package/dist/{chunk-OPU5BLBT.js.map → chunk-CBD3IHPF.js.map} +0 -0
- /package/dist/{chunk-7LSK5YFW.js.map → chunk-E2W2XMX2.js.map} +0 -0
- /package/dist/{chunk-QBLLF7VS.js.map → chunk-HYVYAWUO.js.map} +0 -0
- /package/dist/{chunk-ICWQQQTR.js.map → chunk-LEMU4JMX.js.map} +0 -0
- /package/dist/{chunk-FP6HEAQC.js.map → chunk-MVYTOP3B.js.map} +0 -0
- /package/dist/{chunk-ANKQQTAI.js.map → chunk-MYQAF43S.js.map} +0 -0
- /package/dist/{chunk-7ZIGB34Y.js.map → chunk-QCWVGCT3.js.map} +0 -0
- /package/dist/{chunk-M45XIHZY.js.map → chunk-TPIF252F.js.map} +0 -0
- /package/dist/{chunk-BPBMHS4U.js.map → chunk-ZYBBV6CK.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import { useSortable } from '@dnd-kit/sortable'
|
|
|
4
4
|
import { CSS } from '@dnd-kit/utilities'
|
|
5
5
|
import Link from '../../../embed-shims/next-link'
|
|
6
6
|
import * as React from 'react'
|
|
7
|
-
import { LaptopIcon, Flag02Icon, MessagesIcon } from '../../icons-v2-generated'
|
|
7
|
+
import { LaptopIcon, Flag02Icon, MessagesIcon, UserCheckIcon } from '../../icons-v2-generated'
|
|
8
8
|
import { DeletedUserAvatar } from '../../ui/deleted-user-avatar'
|
|
9
9
|
import { SquareAvatar } from '../../ui/square-avatar'
|
|
10
10
|
import { Tag } from '../../ui/tag'
|
|
@@ -119,6 +119,12 @@ export function TicketCardBody({ ticket, columnColor, renderAssignSlot, onApprov
|
|
|
119
119
|
</Tooltip>
|
|
120
120
|
</TooltipProvider>
|
|
121
121
|
)}
|
|
122
|
+
{ticket.escalatedByUser && (
|
|
123
|
+
<div className="flex items-center gap-[var(--spacing-system-xxs)] text-h6 text-ods-open-yellow">
|
|
124
|
+
<UserCheckIcon className="size-4 shrink-0" />
|
|
125
|
+
<span className="truncate">Escalated by User</span>
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
122
128
|
{showNewMessage && (
|
|
123
129
|
<Tag
|
|
124
130
|
label="New Message"
|
|
@@ -36,6 +36,13 @@ export interface BoardTicket {
|
|
|
36
36
|
createdAt?: string
|
|
37
37
|
hasNewMessage?: boolean
|
|
38
38
|
pendingApproval?: BoardTicketPendingApproval
|
|
39
|
+
/**
|
|
40
|
+
* The client asked for a human and confirmed the handoff, so this ticket
|
|
41
|
+
* reached its lane by escalation rather than an inactivity auto-escalation or
|
|
42
|
+
* an admin takeover. Called out on the card because it changes how urgently a
|
|
43
|
+
* technician should pick it up.
|
|
44
|
+
*/
|
|
45
|
+
escalatedByUser?: boolean
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
export interface BoardColumnDef {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
|
|
4
|
+
import { EscalationOfferMessage } from "../components/chat/escalation-offer-message";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `escalation_offer` message segment — Fae asking the client to confirm a
|
|
8
|
+
* handoff to a human technician (Figma: fae chat › "escalation to admin").
|
|
9
|
+
*
|
|
10
|
+
* Renders THROUGH the client approval card rather than reimplementing it, so
|
|
11
|
+
* it is pixel-identical to `Chat/Client/ApprovalRequestMessage` down to the
|
|
12
|
+
* Approve/Reject labels and the resolved pill. What differs is the wiring:
|
|
13
|
+
* approve/reject call the ticket-escalation GraphQL mutations, never the
|
|
14
|
+
* tool-approval endpoint — which is why it is a distinct segment type.
|
|
15
|
+
*
|
|
16
|
+
* The body copy is backend-fixed; the client never composes it. `origin`
|
|
17
|
+
* (TOOL / MANUAL / a trigger reason) is decoded for telemetry only — every
|
|
18
|
+
* origin renders the same card.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const OFFER_TEXT =
|
|
22
|
+
"Having issues with the AI assistant? This ticket can be handed off to a technician. Fae will no longer respond in this conversation. A technician will review the ticket and reply when available.";
|
|
23
|
+
|
|
24
|
+
const baseData = { offerId: "offer-1", text: OFFER_TEXT, origin: "MANUAL" };
|
|
25
|
+
|
|
26
|
+
const plainDecorator = (Story: React.ComponentType) => (
|
|
27
|
+
<div style={{ maxWidth: 600, background: "var(--color-bg)" }} className="p-4">
|
|
28
|
+
<Story />
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const meta = {
|
|
33
|
+
title: "Chat/Client/EscalationOfferMessage",
|
|
34
|
+
component: EscalationOfferMessage,
|
|
35
|
+
tags: ["autodocs"],
|
|
36
|
+
parameters: {
|
|
37
|
+
docs: {
|
|
38
|
+
description: {
|
|
39
|
+
component:
|
|
40
|
+
"Renders an `escalation_offer` segment: the backend-fixed handoff prompt with Approve/Reject, or a resolved status pill. Approve performs the handoff (ticket → Tech Required, Fae goes silent); Reject just records the choice.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
decorators: [plainDecorator],
|
|
45
|
+
} satisfies Meta<typeof EscalationOfferMessage>;
|
|
46
|
+
|
|
47
|
+
export default meta;
|
|
48
|
+
type Story = StoryObj<typeof meta>;
|
|
49
|
+
|
|
50
|
+
/** Pending — the client has not decided yet. */
|
|
51
|
+
export const Pending: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
data: baseData,
|
|
54
|
+
status: "pending",
|
|
55
|
+
onApprove: () => {},
|
|
56
|
+
onReject: () => {},
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Approved — the handoff ran. Paired in the thread with `TicketEscalatedMessage`. */
|
|
61
|
+
export const ApprovedByUser: Story = {
|
|
62
|
+
args: { data: baseData, status: "approved", resolvedByName: "John Smith" },
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/** Declined — the client chose to keep working with Fae. */
|
|
66
|
+
export const DeclinedByUser: Story = {
|
|
67
|
+
args: { data: baseData, status: "rejected", resolvedByName: "John Smith" },
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Superseded — the client typed a new message over the pending offer, which
|
|
72
|
+
* the backend treats as declining it. Maps onto the shared `cancelled` status.
|
|
73
|
+
*/
|
|
74
|
+
export const Superseded: Story = {
|
|
75
|
+
args: { data: baseData, status: "cancelled", resolvedByName: "John Smith" },
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** Raised by Fae's own `escalateToHuman` tool call rather than the header action. */
|
|
79
|
+
export const FromToolCall: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
data: { ...baseData, origin: "TOOL" },
|
|
82
|
+
status: "pending",
|
|
83
|
+
onApprove: () => {},
|
|
84
|
+
onReject: () => {},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -150,6 +150,18 @@ export const WithNewMessage: Story = {
|
|
|
150
150
|
},
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/**
|
|
154
|
+
* The client asked for a human and confirmed the handoff — an amber footer row
|
|
155
|
+
* distinguishing it from an inactivity auto-escalation or an admin takeover,
|
|
156
|
+
* which reach the same lane silently. Driven by the ticket's `escalatedByUser`
|
|
157
|
+
* field, not by a label.
|
|
158
|
+
*/
|
|
159
|
+
export const EscalatedByUser: Story = {
|
|
160
|
+
args: {
|
|
161
|
+
ticket: { ...BASE_TICKET, id: 'ticket-escalated', escalatedByUser: true },
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
|
|
153
165
|
/**
|
|
154
166
|
* Pending CLIENT approval — collapsed grey "Pending client approval" row with a
|
|
155
167
|
* loader glyph. Expand it to reach the shared approve/reject affordance.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
|
|
4
|
+
import { TicketEscalatedMessage } from "../components/chat/ticket-escalated-message";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `ticket_escalated` message segment — the handoff receipt (Figma:
|
|
8
|
+
* `ai-assistant-info`, type=escalation).
|
|
9
|
+
*
|
|
10
|
+
* A first-class block on the wire, NOT something the client infers from an
|
|
11
|
+
* escalation offer's state, so it also covers the inactivity auto-escalation —
|
|
12
|
+
* a path that raises no offer at all.
|
|
13
|
+
*
|
|
14
|
+
* The body is whatever the backend authored, so the reason it gives stays
|
|
15
|
+
* server-side: the card never branches on `data.reason`, which is why a reason
|
|
16
|
+
* added server-side needs no client change. The body WRAPS rather than
|
|
17
|
+
* truncating as the mock does — see the component for why — so the block is
|
|
18
|
+
* 72px only while the text fits two lines.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const baseData = {
|
|
22
|
+
ticketId: "68a1f0c2b3d4e5f6a7b8c9d0",
|
|
23
|
+
ticketNumber: 1002,
|
|
24
|
+
reason: "INACTIVITY",
|
|
25
|
+
text: "Automatically escalated to a human technician because the conversation had no new messages for an extended period.",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Fixed so the timestamp doesn't churn between snapshots. */
|
|
29
|
+
const TIMESTAMP = new Date("2026-08-07T14:47:00");
|
|
30
|
+
|
|
31
|
+
const plainDecorator = (Story: React.ComponentType) => (
|
|
32
|
+
<div style={{ maxWidth: 600, background: "var(--color-bg)" }} className="p-4">
|
|
33
|
+
<Story />
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const meta = {
|
|
38
|
+
title: "Chat/Client/TicketEscalatedMessage",
|
|
39
|
+
component: TicketEscalatedMessage,
|
|
40
|
+
tags: ["autodocs"],
|
|
41
|
+
parameters: {
|
|
42
|
+
docs: {
|
|
43
|
+
description: {
|
|
44
|
+
component:
|
|
45
|
+
"Renders a `TICKET_ESCALATED` block: a bordered info tile, the fixed 'Handed Off to a Technician' title, the message timestamp, and the backend's explanation.",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
decorators: [plainDecorator],
|
|
50
|
+
} satisfies Meta<typeof TicketEscalatedMessage>;
|
|
51
|
+
|
|
52
|
+
export default meta;
|
|
53
|
+
type Story = StoryObj<typeof meta>;
|
|
54
|
+
|
|
55
|
+
/** The inactivity auto-escalation — the only reason the wire defines today. */
|
|
56
|
+
export const Inactivity: Story = {
|
|
57
|
+
args: { data: baseData, timestamp: TIMESTAMP },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* `text` is nullable on the wire; the card falls back to the design's generic
|
|
62
|
+
* line rather than rendering an empty body.
|
|
63
|
+
*/
|
|
64
|
+
export const NoBodyFallback: Story = {
|
|
65
|
+
args: { data: { ...baseData, text: undefined }, timestamp: TIMESTAMP },
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** No timestamp — the row collapses to title-only, body unchanged. */
|
|
69
|
+
export const WithoutTimestamp: Story = {
|
|
70
|
+
args: { data: baseData },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** Long explanation — wraps and the block grows; nothing is clipped. */
|
|
74
|
+
export const LongBody: Story = {
|
|
75
|
+
args: {
|
|
76
|
+
data: {
|
|
77
|
+
...baseData,
|
|
78
|
+
text: "Automatically escalated to a human technician because the conversation had no new messages for an extended period while the ticket was still assigned to the AI assistant, and no diagnostic step produced a resolution.",
|
|
79
|
+
},
|
|
80
|
+
timestamp: TIMESTAMP,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A reason the client has never seen. The open `TicketEscalationReason` union
|
|
86
|
+
* plus rendering from `text` mean a reason added server-side needs no client
|
|
87
|
+
* change — this story is the regression guard for that.
|
|
88
|
+
*/
|
|
89
|
+
export const UnknownReason: Story = {
|
|
90
|
+
args: {
|
|
91
|
+
data: {
|
|
92
|
+
...baseData,
|
|
93
|
+
reason: "USER_REQUESTED",
|
|
94
|
+
text: "Escalated at the user's request.",
|
|
95
|
+
},
|
|
96
|
+
timestamp: TIMESTAMP,
|
|
97
|
+
},
|
|
98
|
+
};
|