@flamingo-stack/openframe-frontend-core 0.0.665 → 0.0.666
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/{chunk-MNUR6PAJ.cjs → chunk-23XIOIGS.cjs} +392 -370
- package/dist/chunk-23XIOIGS.cjs.map +1 -0
- package/dist/{chunk-LCYYTWRF.cjs → chunk-2S44CUCH.cjs} +4 -4
- package/dist/{chunk-LCYYTWRF.cjs.map → chunk-2S44CUCH.cjs.map} +1 -1
- package/dist/{chunk-LXL3PZE2.cjs → chunk-7H7LYI4M.cjs} +10 -10
- package/dist/{chunk-LXL3PZE2.cjs.map → chunk-7H7LYI4M.cjs.map} +1 -1
- package/dist/{chunk-L4ZNA3NX.cjs → chunk-AAIL6J56.cjs} +3 -3
- package/dist/{chunk-L4ZNA3NX.cjs.map → chunk-AAIL6J56.cjs.map} +1 -1
- package/dist/{chunk-QR3NUFA5.js → chunk-CRDKQMTP.js} +2 -2
- package/dist/{chunk-77WMNQTE.js → chunk-CYPLD5F3.js} +3 -3
- package/dist/{chunk-BPKEDLGR.js → chunk-DDW7G6U7.js} +5 -5
- package/dist/{chunk-OLCI3UA5.js → chunk-EYCF3GGM.js} +6 -6
- package/dist/{chunk-Z2MJPTIB.js → chunk-HQHZZ3SL.js} +3 -3
- package/dist/{chunk-DNFC6RYF.js → chunk-ILAEMVAI.js} +2 -2
- package/dist/{chunk-3SS37SNM.cjs → chunk-IUNCGKFP.cjs} +10 -10
- package/dist/{chunk-3SS37SNM.cjs.map → chunk-IUNCGKFP.cjs.map} +1 -1
- package/dist/{chunk-OMTLCMQB.js → chunk-IWCYTHNG.js} +31 -9
- package/dist/chunk-IWCYTHNG.js.map +1 -0
- package/dist/{chunk-RT5JNTCN.js → chunk-JBRNIUYC.js} +3 -3
- package/dist/{chunk-FGQSSFP4.cjs → chunk-KDFSFVNX.cjs} +10 -10
- package/dist/{chunk-FGQSSFP4.cjs.map → chunk-KDFSFVNX.cjs.map} +1 -1
- package/dist/{chunk-XCACXPCM.cjs → chunk-L7QXTWI7.cjs} +22 -22
- package/dist/{chunk-XCACXPCM.cjs.map → chunk-L7QXTWI7.cjs.map} +1 -1
- package/dist/{chunk-CQJXOBWK.js → chunk-NIVLGQKS.js} +3 -3
- package/dist/{chunk-GDTFJ5QN.js → chunk-O5GV3WQO.js} +2 -2
- package/dist/{chunk-ZGPST26T.cjs → chunk-OPY4JNY2.cjs} +45 -45
- package/dist/{chunk-ZGPST26T.cjs.map → chunk-OPY4JNY2.cjs.map} +1 -1
- package/dist/{chunk-ZMZUF6FX.cjs → chunk-QSYYYL55.cjs} +3 -3
- package/dist/{chunk-ZMZUF6FX.cjs.map → chunk-QSYYYL55.cjs.map} +1 -1
- package/dist/{chunk-RM4S53GB.js → chunk-R6NU4QFR.js} +2 -2
- package/dist/{chunk-BKCPXDOE.js → chunk-SCRVQY42.js} +2 -2
- package/dist/{chunk-MBLACUCE.js → chunk-V3B37LQY.js} +5 -5
- package/dist/{chunk-JHAS6Y7P.js → chunk-VI35TSB2.js} +4 -4
- package/dist/{chunk-KBUYG5N6.cjs → chunk-VN2U4EBP.cjs} +33 -33
- package/dist/{chunk-KBUYG5N6.cjs.map → chunk-VN2U4EBP.cjs.map} +1 -1
- package/dist/{chunk-6W5N23LC.cjs → chunk-VUYRTI3Z.cjs} +26 -26
- package/dist/{chunk-6W5N23LC.cjs.map → chunk-VUYRTI3Z.cjs.map} +1 -1
- package/dist/{chunk-6FD7ZEBY.cjs → chunk-W2WEIVHT.cjs} +163 -163
- package/dist/{chunk-6FD7ZEBY.cjs.map → chunk-W2WEIVHT.cjs.map} +1 -1
- package/dist/{chunk-EMJAT6IK.cjs → chunk-WI5LLFA6.cjs} +15 -15
- package/dist/{chunk-EMJAT6IK.cjs.map → chunk-WI5LLFA6.cjs.map} +1 -1
- package/dist/{chunk-JHH7NETU.cjs → chunk-XMY2XTHG.cjs} +5 -5
- package/dist/{chunk-JHH7NETU.cjs.map → chunk-XMY2XTHG.cjs.map} +1 -1
- package/dist/{chunk-LTW2GWJ2.cjs → chunk-XSRIPH6U.cjs} +22 -22
- package/dist/{chunk-LTW2GWJ2.cjs.map → chunk-XSRIPH6U.cjs.map} +1 -1
- package/dist/{chunk-X32X52VN.cjs → chunk-YAF2JKAK.cjs} +71 -71
- package/dist/{chunk-X32X52VN.cjs.map → chunk-YAF2JKAK.cjs.map} +1 -1
- package/dist/{chunk-YRMKUDOE.js → chunk-YVMSA7LR.js} +5 -5
- package/dist/{chunk-O3GB7JFL.js → chunk-ZDGEJFDG.js} +3 -3
- package/dist/components/case-studies/index.cjs +14 -14
- package/dist/components/case-studies/index.js +3 -3
- package/dist/components/chat/chat-composer.d.ts +10 -1
- package/dist/components/chat/chat-composer.d.ts.map +1 -1
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +10 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/types/component.types.d.ts +7 -0
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/docs/index.cjs +7 -7
- package/dist/components/docs/index.js +6 -6
- package/dist/components/embeds/index.cjs +4 -4
- package/dist/components/embeds/index.js +3 -3
- package/dist/components/faq/index.cjs +4 -4
- package/dist/components/faq/index.js +3 -3
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/help-center-pages/index.cjs +23 -23
- package/dist/components/help-center-pages/index.js +14 -14
- package/dist/components/index.cjs +39 -39
- package/dist/components/index.js +13 -13
- package/dist/components/meeting-scheduler/index.cjs +24 -24
- package/dist/components/meeting-scheduler/index.js +2 -2
- package/dist/components/navigation/index.cjs +6 -6
- package/dist/components/navigation/index.js +5 -5
- package/dist/components/onboarding-guides/index.cjs +6 -6
- package/dist/components/onboarding-guides/index.js +5 -5
- package/dist/components/tickets/index.cjs +7 -7
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +3 -3
- package/dist/components/ui/index.js +2 -2
- package/dist/index.cjs +7 -7
- package/dist/index.js +6 -6
- package/package.json +1 -1
- package/src/components/chat/chat-composer.tsx +21 -5
- package/src/components/chat/chat-input.tsx +15 -3
- package/src/components/chat/embeddable-chat.tsx +16 -2
- package/src/components/chat/types/component.types.ts +7 -0
- package/src/stories/EmbeddableChat.stories.tsx +21 -0
- package/dist/chunk-MNUR6PAJ.cjs.map +0 -1
- package/dist/chunk-OMTLCMQB.js.map +0 -1
- /package/dist/{chunk-QR3NUFA5.js.map → chunk-CRDKQMTP.js.map} +0 -0
- /package/dist/{chunk-77WMNQTE.js.map → chunk-CYPLD5F3.js.map} +0 -0
- /package/dist/{chunk-BPKEDLGR.js.map → chunk-DDW7G6U7.js.map} +0 -0
- /package/dist/{chunk-OLCI3UA5.js.map → chunk-EYCF3GGM.js.map} +0 -0
- /package/dist/{chunk-Z2MJPTIB.js.map → chunk-HQHZZ3SL.js.map} +0 -0
- /package/dist/{chunk-DNFC6RYF.js.map → chunk-ILAEMVAI.js.map} +0 -0
- /package/dist/{chunk-RT5JNTCN.js.map → chunk-JBRNIUYC.js.map} +0 -0
- /package/dist/{chunk-CQJXOBWK.js.map → chunk-NIVLGQKS.js.map} +0 -0
- /package/dist/{chunk-GDTFJ5QN.js.map → chunk-O5GV3WQO.js.map} +0 -0
- /package/dist/{chunk-RM4S53GB.js.map → chunk-R6NU4QFR.js.map} +0 -0
- /package/dist/{chunk-BKCPXDOE.js.map → chunk-SCRVQY42.js.map} +0 -0
- /package/dist/{chunk-MBLACUCE.js.map → chunk-V3B37LQY.js.map} +0 -0
- /package/dist/{chunk-JHAS6Y7P.js.map → chunk-VI35TSB2.js.map} +0 -0
- /package/dist/{chunk-YRMKUDOE.js.map → chunk-YVMSA7LR.js.map} +0 -0
- /package/dist/{chunk-O3GB7JFL.js.map → chunk-ZDGEJFDG.js.map} +0 -0
|
@@ -12,10 +12,20 @@ import { ModelDisplay } from './model-display';
|
|
|
12
12
|
import type { ChatInputRef, ModelDisplayProps } from './types/component.types';
|
|
13
13
|
import type { ChatContextItem, ChatContextPickerConfig } from './types/context-item.types';
|
|
14
14
|
|
|
15
|
+
/** Why the composer takes no input, in the user's words — shown where the prompt would be. */
|
|
16
|
+
export interface ChatComposerLock {
|
|
17
|
+
placeholder: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export interface ChatComposerProps {
|
|
16
21
|
/** Read-only archived chat → render the unarchive placeholder instead of the
|
|
17
22
|
* input (Figma node 7361:426949). */
|
|
18
23
|
archived?: boolean;
|
|
24
|
+
/** The host cannot take a message right now — e.g. the AI balance is spent
|
|
25
|
+
* and the agents are paused (Figma 954:28455). The composer keeps its place
|
|
26
|
+
* but takes no input: the editor is disabled with the lock's copy in the
|
|
27
|
+
* prompt's place, and the `+` menu, the chips and Send are inert. */
|
|
28
|
+
lock?: ChatComposerLock | null;
|
|
19
29
|
inputRef: Ref<ChatInputRef>;
|
|
20
30
|
onSend: (text: string) => void;
|
|
21
31
|
onStop: () => void;
|
|
@@ -80,6 +90,7 @@ export interface ChatComposerProps {
|
|
|
80
90
|
*/
|
|
81
91
|
export function ChatComposer({
|
|
82
92
|
archived = false,
|
|
93
|
+
lock = null,
|
|
83
94
|
inputRef,
|
|
84
95
|
onSend,
|
|
85
96
|
onStop,
|
|
@@ -107,6 +118,7 @@ export function ChatComposer({
|
|
|
107
118
|
previewText,
|
|
108
119
|
}: ChatComposerProps) {
|
|
109
120
|
const contextEnabled = !!contextPicker && !archived;
|
|
121
|
+
const locked = lock != null;
|
|
110
122
|
const selected = selectedContextItems ?? [];
|
|
111
123
|
const memory = contextMemoryItems ?? [];
|
|
112
124
|
|
|
@@ -131,11 +143,15 @@ export function ChatComposer({
|
|
|
131
143
|
onStop={onStop}
|
|
132
144
|
sending={sending}
|
|
133
145
|
placeholder={placeholder}
|
|
146
|
+
// Locked: the editor is disabled and the lock's copy stands where the
|
|
147
|
+
// prompt would; there is nothing to focus, so autofocus stands down too.
|
|
148
|
+
disabled={locked}
|
|
149
|
+
disabledPlaceholder={lock?.placeholder}
|
|
134
150
|
previewText={previewText}
|
|
135
151
|
fullWidth
|
|
136
152
|
className="px-0"
|
|
137
153
|
reserveAvatarOffset={false}
|
|
138
|
-
autoFocus={autoFocus}
|
|
154
|
+
autoFocus={locked ? false : autoFocus}
|
|
139
155
|
slashCommands={slashCommands}
|
|
140
156
|
onMentionQueryChange={contextEnabled ? onMentionQueryChange : undefined}
|
|
141
157
|
onValueChange={contextEnabled ? onValueChange : undefined}
|
|
@@ -148,7 +164,7 @@ export function ChatComposer({
|
|
|
148
164
|
<ChatComposerPlusMenu
|
|
149
165
|
onToggle={() => (contextPickerOpen ? onCloseContextPicker?.() : onOpenContextPicker?.())}
|
|
150
166
|
open={contextPickerOpen}
|
|
151
|
-
disabled={attachmentsDisabled}
|
|
167
|
+
disabled={attachmentsDisabled || locked}
|
|
152
168
|
dropdown={
|
|
153
169
|
contextPicker ? (
|
|
154
170
|
<ChatContextPicker
|
|
@@ -202,7 +218,7 @@ export function ChatComposer({
|
|
|
202
218
|
items={memory}
|
|
203
219
|
onRemove={onRemoveContextMemoryItem}
|
|
204
220
|
resolveIcon={resolveContextIcon}
|
|
205
|
-
disabled={sending}
|
|
221
|
+
disabled={sending || locked}
|
|
206
222
|
className="rounded-t-md"
|
|
207
223
|
/>
|
|
208
224
|
{selected.length > 0 && (
|
|
@@ -210,7 +226,7 @@ export function ChatComposer({
|
|
|
210
226
|
items={selected}
|
|
211
227
|
onRemove={onRemoveContextItem}
|
|
212
228
|
resolveIcon={resolveContextIcon}
|
|
213
|
-
disabled={sending}
|
|
229
|
+
disabled={sending || locked}
|
|
214
230
|
className={cn(
|
|
215
231
|
'border-b border-ods-border bg-ods-bg p-2',
|
|
216
232
|
// Only the TOP strip rounds into the card corner.
|
|
@@ -236,7 +252,7 @@ export function ChatComposer({
|
|
|
236
252
|
attachmentsEnabled
|
|
237
253
|
attachmentsCount={attachmentsCount}
|
|
238
254
|
onAddFiles={onAddFiles}
|
|
239
|
-
disabled={attachmentsDisabled}
|
|
255
|
+
disabled={attachmentsDisabled || locked}
|
|
240
256
|
/>
|
|
241
257
|
)}
|
|
242
258
|
<div className="min-w-0 flex-1">
|
|
@@ -167,6 +167,7 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
167
167
|
placeholder = 'Enter your Request...',
|
|
168
168
|
reserveAvatarOffset: _reserveAvatarOffset,
|
|
169
169
|
disabled = false,
|
|
170
|
+
disabledPlaceholder = 'Connection lost. Waiting to reconnect...',
|
|
170
171
|
autoFocus = false,
|
|
171
172
|
fullWidth = false,
|
|
172
173
|
allowEmptySend = false,
|
|
@@ -607,8 +608,18 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
607
608
|
the draft is EMPTY, so the editor is always on its plain line
|
|
608
609
|
box here. */}
|
|
609
610
|
{isEmpty && !showPreview && (
|
|
610
|
-
<span
|
|
611
|
-
{
|
|
611
|
+
<span
|
|
612
|
+
className={cn(
|
|
613
|
+
// One line, clipped with an ellipsis (Figma 954:28455): the
|
|
614
|
+
// disabled copy is a sentence, and the panel's narrowest
|
|
615
|
+
// width does not fit it — wrapped, it ran under the row.
|
|
616
|
+
'pointer-events-none absolute left-0 top-0 w-full select-none truncate text-h4',
|
|
617
|
+
// Disabled reads as disabled (Figma 954:28455): the copy says
|
|
618
|
+
// why, and the colour says it is not an invitation to type.
|
|
619
|
+
disabled ? 'text-ods-text-disabled' : 'text-ods-text-secondary',
|
|
620
|
+
)}
|
|
621
|
+
>
|
|
622
|
+
{disabled ? disabledPlaceholder : placeholder}
|
|
612
623
|
</span>
|
|
613
624
|
)}
|
|
614
625
|
{/* Ghost preview of a hovered quick-action's prompt. Overlaid like
|
|
@@ -642,7 +653,8 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
642
653
|
data-editor
|
|
643
654
|
role="textbox"
|
|
644
655
|
aria-multiline="true"
|
|
645
|
-
|
|
656
|
+
// Named by what it shows: locked, the lock's copy is the name.
|
|
657
|
+
aria-label={disabled ? disabledPlaceholder : typeof placeholder === 'string' ? placeholder : 'Message'}
|
|
646
658
|
// `sending` blocks SENDING, never typing. Taking
|
|
647
659
|
// `contentEditable` away under a focused editor blurs it, and
|
|
648
660
|
// iOS dismisses the keyboard on blur; restoring it re-establishes
|
|
@@ -62,7 +62,7 @@ import { CollisionBoundaryContext, PortalContainerContext } from '../ui/portal-c
|
|
|
62
62
|
import { SquareAvatar } from '../ui/square-avatar';
|
|
63
63
|
import { ChatArchivePage } from './chat-archive-page';
|
|
64
64
|
import { ChatAttachmentChipStrip } from './chat-attachment-bar';
|
|
65
|
-
import { ChatComposer } from './chat-composer';
|
|
65
|
+
import { ChatComposer, type ChatComposerLock } from './chat-composer';
|
|
66
66
|
import { chatDialogMenuItems } from './chat-dialog-menu-items';
|
|
67
67
|
import { ChatHeaderIconButton } from './chat-header-icon-button';
|
|
68
68
|
import { ChatHeaderSearchField } from './chat-header-search-field';
|
|
@@ -185,6 +185,15 @@ export interface EmbeddableChatProps {
|
|
|
185
185
|
* cursor. Scrolling is intentionally disabled too. Defaults to `false`.
|
|
186
186
|
*/
|
|
187
187
|
previewMode?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* The host cannot serve a message right now — e.g. the tenant's AI balance
|
|
190
|
+
* is spent and the agents are paused (Figma 954:28455). The composer stays
|
|
191
|
+
* in place but takes no input: the editor is disabled with `placeholder`
|
|
192
|
+
* where the prompt would be, and the `+` menu and Send are inert. Sends that
|
|
193
|
+
* bypass the composer (quick-action chips, imperative prompts) are the
|
|
194
|
+
* host's to hold back — it owns their callbacks. `null`/unset = live.
|
|
195
|
+
*/
|
|
196
|
+
composerLock?: ChatComposerLock | null;
|
|
188
197
|
/** Optional builders for chat-card types whose props live in hub-land
|
|
189
198
|
* (programs + product_release). Forwarded straight to
|
|
190
199
|
* `renderChatInlineEntityCard`. */
|
|
@@ -943,6 +952,7 @@ function EmbeddableChatInner({
|
|
|
943
952
|
defaultOpen,
|
|
944
953
|
showInternalTrigger = true,
|
|
945
954
|
previewMode = false,
|
|
955
|
+
composerLock = null,
|
|
946
956
|
extras,
|
|
947
957
|
tableIdForDocumentType,
|
|
948
958
|
modes,
|
|
@@ -1571,6 +1581,9 @@ function EmbeddableChatInner({
|
|
|
1571
1581
|
|
|
1572
1582
|
const handleSend = useCallback(
|
|
1573
1583
|
(text: string) => {
|
|
1584
|
+
// Locked: the disabled editor cannot submit, but a queued Enter or a
|
|
1585
|
+
// stale ref call still lands here — refused at the seam, not by luck.
|
|
1586
|
+
if (composerLock) return;
|
|
1574
1587
|
// Append chat-attachment markdown lines to the user's bubble.
|
|
1575
1588
|
let augmentedText = text;
|
|
1576
1589
|
if (readyAttachments.length > 0) {
|
|
@@ -1598,7 +1611,7 @@ function EmbeddableChatInner({
|
|
|
1598
1611
|
setContextItems([]);
|
|
1599
1612
|
}
|
|
1600
1613
|
},
|
|
1601
|
-
[sendMessage, readyAttachments, viewUrlPrefix, clearAttachments, contextItems],
|
|
1614
|
+
[composerLock, sendMessage, readyAttachments, viewUrlPrefix, clearAttachments, contextItems],
|
|
1602
1615
|
);
|
|
1603
1616
|
|
|
1604
1617
|
/**
|
|
@@ -2649,6 +2662,7 @@ function EmbeddableChatInner({
|
|
|
2649
2662
|
|
|
2650
2663
|
<ChatComposer
|
|
2651
2664
|
archived={isViewingArchived}
|
|
2665
|
+
lock={composerLock}
|
|
2652
2666
|
inputRef={chatInputRef}
|
|
2653
2667
|
onSend={handleSend}
|
|
2654
2668
|
onStop={stopMessage}
|
|
@@ -453,6 +453,13 @@ export interface ChatInputProps extends Omit<TextareaHTMLAttributes<HTMLTextArea
|
|
|
453
453
|
*/
|
|
454
454
|
reserveAvatarOffset?: boolean;
|
|
455
455
|
disabled?: boolean;
|
|
456
|
+
/**
|
|
457
|
+
* Placeholder shown while `disabled`, in the prompt's place — what the user
|
|
458
|
+
* cannot do right now. Defaults to the connection-lost copy, which is what
|
|
459
|
+
* `disabled` has meant so far (the ticket reply composer); a host that
|
|
460
|
+
* disables the input for another reason says so here.
|
|
461
|
+
*/
|
|
462
|
+
disabledPlaceholder?: string;
|
|
456
463
|
maxRows?: number;
|
|
457
464
|
showSendButton?: boolean;
|
|
458
465
|
sendButtonLabel?: string;
|
|
@@ -535,6 +535,27 @@ export const MingoOnly: Story = {
|
|
|
535
535
|
args: {},
|
|
536
536
|
};
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* The host cannot serve a message — the tenant's AI balance is spent and the
|
|
540
|
+
* agents are paused (Figma 954:28455). The panel reads as usual; the composer
|
|
541
|
+
* keeps its place, says why it takes nothing, and its `+` and Send are inert.
|
|
542
|
+
*/
|
|
543
|
+
export const ComposerLocked: Story = {
|
|
544
|
+
render: args => (
|
|
545
|
+
<EmbeddableChat
|
|
546
|
+
{...args}
|
|
547
|
+
modes={{
|
|
548
|
+
mingo: createMockMingoConfig(),
|
|
549
|
+
}}
|
|
550
|
+
defaultActiveMode="mingo"
|
|
551
|
+
defaultOpen
|
|
552
|
+
showInternalTrigger={false}
|
|
553
|
+
composerLock={{ placeholder: 'Mingo chat unavailable. Top up your balance.' }}
|
|
554
|
+
/>
|
|
555
|
+
),
|
|
556
|
+
args: {},
|
|
557
|
+
};
|
|
558
|
+
|
|
538
559
|
// =============================================================================
|
|
539
560
|
// 3. Both modes (toggle visible — openframe-frontend target)
|
|
540
561
|
// =============================================================================
|