@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.
Files changed (109) hide show
  1. package/dist/{chunk-MNUR6PAJ.cjs → chunk-23XIOIGS.cjs} +392 -370
  2. package/dist/chunk-23XIOIGS.cjs.map +1 -0
  3. package/dist/{chunk-LCYYTWRF.cjs → chunk-2S44CUCH.cjs} +4 -4
  4. package/dist/{chunk-LCYYTWRF.cjs.map → chunk-2S44CUCH.cjs.map} +1 -1
  5. package/dist/{chunk-LXL3PZE2.cjs → chunk-7H7LYI4M.cjs} +10 -10
  6. package/dist/{chunk-LXL3PZE2.cjs.map → chunk-7H7LYI4M.cjs.map} +1 -1
  7. package/dist/{chunk-L4ZNA3NX.cjs → chunk-AAIL6J56.cjs} +3 -3
  8. package/dist/{chunk-L4ZNA3NX.cjs.map → chunk-AAIL6J56.cjs.map} +1 -1
  9. package/dist/{chunk-QR3NUFA5.js → chunk-CRDKQMTP.js} +2 -2
  10. package/dist/{chunk-77WMNQTE.js → chunk-CYPLD5F3.js} +3 -3
  11. package/dist/{chunk-BPKEDLGR.js → chunk-DDW7G6U7.js} +5 -5
  12. package/dist/{chunk-OLCI3UA5.js → chunk-EYCF3GGM.js} +6 -6
  13. package/dist/{chunk-Z2MJPTIB.js → chunk-HQHZZ3SL.js} +3 -3
  14. package/dist/{chunk-DNFC6RYF.js → chunk-ILAEMVAI.js} +2 -2
  15. package/dist/{chunk-3SS37SNM.cjs → chunk-IUNCGKFP.cjs} +10 -10
  16. package/dist/{chunk-3SS37SNM.cjs.map → chunk-IUNCGKFP.cjs.map} +1 -1
  17. package/dist/{chunk-OMTLCMQB.js → chunk-IWCYTHNG.js} +31 -9
  18. package/dist/chunk-IWCYTHNG.js.map +1 -0
  19. package/dist/{chunk-RT5JNTCN.js → chunk-JBRNIUYC.js} +3 -3
  20. package/dist/{chunk-FGQSSFP4.cjs → chunk-KDFSFVNX.cjs} +10 -10
  21. package/dist/{chunk-FGQSSFP4.cjs.map → chunk-KDFSFVNX.cjs.map} +1 -1
  22. package/dist/{chunk-XCACXPCM.cjs → chunk-L7QXTWI7.cjs} +22 -22
  23. package/dist/{chunk-XCACXPCM.cjs.map → chunk-L7QXTWI7.cjs.map} +1 -1
  24. package/dist/{chunk-CQJXOBWK.js → chunk-NIVLGQKS.js} +3 -3
  25. package/dist/{chunk-GDTFJ5QN.js → chunk-O5GV3WQO.js} +2 -2
  26. package/dist/{chunk-ZGPST26T.cjs → chunk-OPY4JNY2.cjs} +45 -45
  27. package/dist/{chunk-ZGPST26T.cjs.map → chunk-OPY4JNY2.cjs.map} +1 -1
  28. package/dist/{chunk-ZMZUF6FX.cjs → chunk-QSYYYL55.cjs} +3 -3
  29. package/dist/{chunk-ZMZUF6FX.cjs.map → chunk-QSYYYL55.cjs.map} +1 -1
  30. package/dist/{chunk-RM4S53GB.js → chunk-R6NU4QFR.js} +2 -2
  31. package/dist/{chunk-BKCPXDOE.js → chunk-SCRVQY42.js} +2 -2
  32. package/dist/{chunk-MBLACUCE.js → chunk-V3B37LQY.js} +5 -5
  33. package/dist/{chunk-JHAS6Y7P.js → chunk-VI35TSB2.js} +4 -4
  34. package/dist/{chunk-KBUYG5N6.cjs → chunk-VN2U4EBP.cjs} +33 -33
  35. package/dist/{chunk-KBUYG5N6.cjs.map → chunk-VN2U4EBP.cjs.map} +1 -1
  36. package/dist/{chunk-6W5N23LC.cjs → chunk-VUYRTI3Z.cjs} +26 -26
  37. package/dist/{chunk-6W5N23LC.cjs.map → chunk-VUYRTI3Z.cjs.map} +1 -1
  38. package/dist/{chunk-6FD7ZEBY.cjs → chunk-W2WEIVHT.cjs} +163 -163
  39. package/dist/{chunk-6FD7ZEBY.cjs.map → chunk-W2WEIVHT.cjs.map} +1 -1
  40. package/dist/{chunk-EMJAT6IK.cjs → chunk-WI5LLFA6.cjs} +15 -15
  41. package/dist/{chunk-EMJAT6IK.cjs.map → chunk-WI5LLFA6.cjs.map} +1 -1
  42. package/dist/{chunk-JHH7NETU.cjs → chunk-XMY2XTHG.cjs} +5 -5
  43. package/dist/{chunk-JHH7NETU.cjs.map → chunk-XMY2XTHG.cjs.map} +1 -1
  44. package/dist/{chunk-LTW2GWJ2.cjs → chunk-XSRIPH6U.cjs} +22 -22
  45. package/dist/{chunk-LTW2GWJ2.cjs.map → chunk-XSRIPH6U.cjs.map} +1 -1
  46. package/dist/{chunk-X32X52VN.cjs → chunk-YAF2JKAK.cjs} +71 -71
  47. package/dist/{chunk-X32X52VN.cjs.map → chunk-YAF2JKAK.cjs.map} +1 -1
  48. package/dist/{chunk-YRMKUDOE.js → chunk-YVMSA7LR.js} +5 -5
  49. package/dist/{chunk-O3GB7JFL.js → chunk-ZDGEJFDG.js} +3 -3
  50. package/dist/components/case-studies/index.cjs +14 -14
  51. package/dist/components/case-studies/index.js +3 -3
  52. package/dist/components/chat/chat-composer.d.ts +10 -1
  53. package/dist/components/chat/chat-composer.d.ts.map +1 -1
  54. package/dist/components/chat/chat-input.d.ts.map +1 -1
  55. package/dist/components/chat/embeddable-chat.d.ts +10 -0
  56. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  57. package/dist/components/chat/index.cjs +2 -2
  58. package/dist/components/chat/index.js +1 -1
  59. package/dist/components/chat/types/component.types.d.ts +7 -0
  60. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  61. package/dist/components/contact/index.cjs +4 -4
  62. package/dist/components/contact/index.js +3 -3
  63. package/dist/components/docs/index.cjs +7 -7
  64. package/dist/components/docs/index.js +6 -6
  65. package/dist/components/embeds/index.cjs +4 -4
  66. package/dist/components/embeds/index.js +3 -3
  67. package/dist/components/faq/index.cjs +4 -4
  68. package/dist/components/faq/index.js +3 -3
  69. package/dist/components/features/index.cjs +3 -3
  70. package/dist/components/features/index.js +2 -2
  71. package/dist/components/help-center-pages/index.cjs +23 -23
  72. package/dist/components/help-center-pages/index.js +14 -14
  73. package/dist/components/index.cjs +39 -39
  74. package/dist/components/index.js +13 -13
  75. package/dist/components/meeting-scheduler/index.cjs +24 -24
  76. package/dist/components/meeting-scheduler/index.js +2 -2
  77. package/dist/components/navigation/index.cjs +6 -6
  78. package/dist/components/navigation/index.js +5 -5
  79. package/dist/components/onboarding-guides/index.cjs +6 -6
  80. package/dist/components/onboarding-guides/index.js +5 -5
  81. package/dist/components/tickets/index.cjs +7 -7
  82. package/dist/components/tickets/index.js +6 -6
  83. package/dist/components/ui/index.cjs +3 -3
  84. package/dist/components/ui/index.js +2 -2
  85. package/dist/index.cjs +7 -7
  86. package/dist/index.js +6 -6
  87. package/package.json +1 -1
  88. package/src/components/chat/chat-composer.tsx +21 -5
  89. package/src/components/chat/chat-input.tsx +15 -3
  90. package/src/components/chat/embeddable-chat.tsx +16 -2
  91. package/src/components/chat/types/component.types.ts +7 -0
  92. package/src/stories/EmbeddableChat.stories.tsx +21 -0
  93. package/dist/chunk-MNUR6PAJ.cjs.map +0 -1
  94. package/dist/chunk-OMTLCMQB.js.map +0 -1
  95. /package/dist/{chunk-QR3NUFA5.js.map → chunk-CRDKQMTP.js.map} +0 -0
  96. /package/dist/{chunk-77WMNQTE.js.map → chunk-CYPLD5F3.js.map} +0 -0
  97. /package/dist/{chunk-BPKEDLGR.js.map → chunk-DDW7G6U7.js.map} +0 -0
  98. /package/dist/{chunk-OLCI3UA5.js.map → chunk-EYCF3GGM.js.map} +0 -0
  99. /package/dist/{chunk-Z2MJPTIB.js.map → chunk-HQHZZ3SL.js.map} +0 -0
  100. /package/dist/{chunk-DNFC6RYF.js.map → chunk-ILAEMVAI.js.map} +0 -0
  101. /package/dist/{chunk-RT5JNTCN.js.map → chunk-JBRNIUYC.js.map} +0 -0
  102. /package/dist/{chunk-CQJXOBWK.js.map → chunk-NIVLGQKS.js.map} +0 -0
  103. /package/dist/{chunk-GDTFJ5QN.js.map → chunk-O5GV3WQO.js.map} +0 -0
  104. /package/dist/{chunk-RM4S53GB.js.map → chunk-R6NU4QFR.js.map} +0 -0
  105. /package/dist/{chunk-BKCPXDOE.js.map → chunk-SCRVQY42.js.map} +0 -0
  106. /package/dist/{chunk-MBLACUCE.js.map → chunk-V3B37LQY.js.map} +0 -0
  107. /package/dist/{chunk-JHAS6Y7P.js.map → chunk-VI35TSB2.js.map} +0 -0
  108. /package/dist/{chunk-YRMKUDOE.js.map → chunk-YVMSA7LR.js.map} +0 -0
  109. /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 className="pointer-events-none absolute left-0 top-0 select-none text-ods-text-secondary text-h4">
611
- {disabled ? 'Connection lost. Waiting to reconnect...' : placeholder}
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
- aria-label={typeof placeholder === 'string' ? placeholder : 'Message'}
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
  // =============================================================================