@flamingo-stack/openframe-frontend-core 0.0.534 → 0.0.535-1762.4618.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/{chunk-67MWXMNT.cjs → chunk-2AMYXNQ2.cjs} +26 -26
- package/dist/{chunk-67MWXMNT.cjs.map → chunk-2AMYXNQ2.cjs.map} +1 -1
- package/dist/{chunk-BUVD2OAI.js → chunk-5OPVJBHQ.js} +4 -4
- package/dist/{chunk-BSE2UT6L.js → chunk-6OZWDOP5.js} +2 -2
- package/dist/{chunk-KZ6PWFHK.js → chunk-7TQDW3PE.js} +2 -2
- package/dist/{chunk-H4W4LENJ.js → chunk-A5EA3YO7.js} +5 -5
- package/dist/{chunk-JELZAWSM.cjs → chunk-CMIHA6TT.cjs} +3 -3
- package/dist/{chunk-JELZAWSM.cjs.map → chunk-CMIHA6TT.cjs.map} +1 -1
- package/dist/{chunk-ZKQXE2P4.cjs → chunk-DK6IYFLD.cjs} +9 -9
- package/dist/{chunk-ZKQXE2P4.cjs.map → chunk-DK6IYFLD.cjs.map} +1 -1
- package/dist/{chunk-ONIYUMTO.js → chunk-DRJC7TTW.js} +2 -2
- package/dist/{chunk-MLILEBJU.cjs → chunk-ENOER2QA.cjs} +61 -61
- package/dist/{chunk-MLILEBJU.cjs.map → chunk-ENOER2QA.cjs.map} +1 -1
- package/dist/{chunk-O6VJZX2N.js → chunk-GBWS62LR.js} +51 -34
- package/dist/chunk-GBWS62LR.js.map +1 -0
- package/dist/{chunk-NCUKKJRG.cjs → chunk-GF5A23J3.cjs} +87 -87
- package/dist/{chunk-NCUKKJRG.cjs.map → chunk-GF5A23J3.cjs.map} +1 -1
- package/dist/{chunk-2YJ2CVRC.cjs → chunk-GRGFMXNO.cjs} +31 -31
- package/dist/{chunk-2YJ2CVRC.cjs.map → chunk-GRGFMXNO.cjs.map} +1 -1
- package/dist/{chunk-MTCU5MQN.js → chunk-GS4R5UQ7.js} +2 -2
- package/dist/{chunk-POFCTXNH.js → chunk-HNZDQ4SH.js} +2 -2
- package/dist/{chunk-YW2ZU7LC.cjs → chunk-HSRHPF32.cjs} +7 -7
- package/dist/{chunk-YW2ZU7LC.cjs.map → chunk-HSRHPF32.cjs.map} +1 -1
- package/dist/{chunk-UWB33C6R.cjs → chunk-JW4BTXVH.cjs} +14 -14
- package/dist/{chunk-UWB33C6R.cjs.map → chunk-JW4BTXVH.cjs.map} +1 -1
- package/dist/{chunk-VYOGAQLM.js → chunk-JWJQHURJ.js} +2 -2
- package/dist/{chunk-W4MXOBEW.js → chunk-JWWZFEFI.js} +2 -2
- package/dist/{chunk-LBZEPB4Y.cjs → chunk-JZMQQBUC.cjs} +11 -11
- package/dist/{chunk-LBZEPB4Y.cjs.map → chunk-JZMQQBUC.cjs.map} +1 -1
- package/dist/{chunk-2ALT6CTY.js → chunk-QHOVACZK.js} +2 -2
- package/dist/{chunk-LYRGM25P.cjs → chunk-T4GNFVT3.cjs} +51 -34
- package/dist/chunk-T4GNFVT3.cjs.map +1 -0
- package/dist/{chunk-M5ODB6RQ.cjs → chunk-T743Z3KN.cjs} +37 -37
- package/dist/{chunk-M5ODB6RQ.cjs.map → chunk-T743Z3KN.cjs.map} +1 -1
- package/dist/{chunk-EBSZWSC5.cjs → chunk-TOWXHZF5.cjs} +4 -4
- package/dist/{chunk-EBSZWSC5.cjs.map → chunk-TOWXHZF5.cjs.map} +1 -1
- package/dist/{chunk-ZLLXYE2G.js → chunk-URBYMQ4Z.js} +4 -4
- package/dist/{chunk-UMDGRL6A.cjs → chunk-WL3PP4D6.cjs} +26 -26
- package/dist/{chunk-UMDGRL6A.cjs.map → chunk-WL3PP4D6.cjs.map} +1 -1
- package/dist/{chunk-WBYRBTAS.js → chunk-WXRQYGE5.js} +2 -2
- package/dist/{chunk-D62VYSTL.js → chunk-XPKCOZQE.js} +6 -6
- package/dist/{chunk-RHKH4YUY.cjs → chunk-ZUVBTDLG.cjs} +5 -5
- package/dist/{chunk-RHKH4YUY.cjs.map → chunk-ZUVBTDLG.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +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/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 +132 -132
- package/dist/components/index.js +11 -11
- 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/file-upload.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/chat/chat-input.tsx +84 -32
- package/src/components/ui/file-upload.tsx +5 -1
- package/dist/chunk-LYRGM25P.cjs.map +0 -1
- package/dist/chunk-O6VJZX2N.js.map +0 -1
- /package/dist/{chunk-BUVD2OAI.js.map → chunk-5OPVJBHQ.js.map} +0 -0
- /package/dist/{chunk-BSE2UT6L.js.map → chunk-6OZWDOP5.js.map} +0 -0
- /package/dist/{chunk-KZ6PWFHK.js.map → chunk-7TQDW3PE.js.map} +0 -0
- /package/dist/{chunk-H4W4LENJ.js.map → chunk-A5EA3YO7.js.map} +0 -0
- /package/dist/{chunk-ONIYUMTO.js.map → chunk-DRJC7TTW.js.map} +0 -0
- /package/dist/{chunk-MTCU5MQN.js.map → chunk-GS4R5UQ7.js.map} +0 -0
- /package/dist/{chunk-POFCTXNH.js.map → chunk-HNZDQ4SH.js.map} +0 -0
- /package/dist/{chunk-VYOGAQLM.js.map → chunk-JWJQHURJ.js.map} +0 -0
- /package/dist/{chunk-W4MXOBEW.js.map → chunk-JWWZFEFI.js.map} +0 -0
- /package/dist/{chunk-2ALT6CTY.js.map → chunk-QHOVACZK.js.map} +0 -0
- /package/dist/{chunk-ZLLXYE2G.js.map → chunk-URBYMQ4Z.js.map} +0 -0
- /package/dist/{chunk-WBYRBTAS.js.map → chunk-WXRQYGE5.js.map} +0 -0
- /package/dist/{chunk-D62VYSTL.js.map → chunk-XPKCOZQE.js.map} +0 -0
|
@@ -168,6 +168,13 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
168
168
|
} = rest as typeof rest & { rows?: number }
|
|
169
169
|
|
|
170
170
|
const [value, setValue] = useState('')
|
|
171
|
+
// Whether the editor currently holds at least one committed mention chip —
|
|
172
|
+
// it alone needs the tall line box (see the editor's className). Read from the
|
|
173
|
+
// DOM, NOT by testing the draft against `MENTION_GLOBAL`: that regex also
|
|
174
|
+
// matches ordinary typed text (`meet @3:00`, `@prod:us-east`), which would
|
|
175
|
+
// switch the editor to a 36px line box with no chip on screen. Chips are only
|
|
176
|
+
// ever created by `rebuildDom`, so the two writers below cover every path.
|
|
177
|
+
const [hasChips, setHasChips] = useState(false)
|
|
171
178
|
const [focused, setFocused] = useState(false)
|
|
172
179
|
const [isStopping, setIsStopping] = useState(false)
|
|
173
180
|
// The ghost preview is dismissed as soon as the user edits the draft (typing
|
|
@@ -224,7 +231,12 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
224
231
|
if (typeof caret === 'number') placeCaretAtOffset(el, caret)
|
|
225
232
|
else placeCaretAtEnd(el)
|
|
226
233
|
}
|
|
234
|
+
setHasChips(el.querySelector('[data-token]') !== null)
|
|
227
235
|
}
|
|
236
|
+
// Advance the mirror HERE, not only on the next render: `fire` clears the
|
|
237
|
+
// draft and then reads it back within the same tick to decide whether a
|
|
238
|
+
// refused send may restore it.
|
|
239
|
+
valueRef.current = next
|
|
228
240
|
setValue(next)
|
|
229
241
|
}, [])
|
|
230
242
|
|
|
@@ -233,19 +245,31 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
233
245
|
(message: string) => {
|
|
234
246
|
const can = (message.length > 0 || allowEmptySend) && !sending && !disabled
|
|
235
247
|
if (!can || !onSend) return
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
248
|
+
// Clear FIRST and put it back only if the host refuses, rather than
|
|
249
|
+
// clearing once the send settles. The editor stays typable while `sending`
|
|
250
|
+
// (see `contentEditable` below), and a host whose `onSend` is async —
|
|
251
|
+
// `TicketReplyComposer` awaits a round trip — leaves a window in which the
|
|
252
|
+
// user starts their next message; a deferred clear would silently delete
|
|
253
|
+
// it. Restoring is guarded on the box still being empty for the same
|
|
254
|
+
// reason. `applyValue` advances `valueRef` synchronously, so the guard
|
|
255
|
+
// reads the cleared draft even when `onSend` refuses in the same tick.
|
|
256
|
+
const sentMeta = metaRef.current
|
|
257
|
+
metaRef.current = new Map()
|
|
258
|
+
applyValue('')
|
|
259
|
+
shouldRefocusRef.current = true
|
|
260
|
+
focusEditor()
|
|
261
|
+
const restore = () => {
|
|
262
|
+
if (valueRef.current.length > 0) return
|
|
263
|
+
metaRef.current = sentMeta
|
|
264
|
+
applyValue(message)
|
|
242
265
|
}
|
|
266
|
+
const result = onSend(message)
|
|
243
267
|
if (result instanceof Promise) {
|
|
244
268
|
void result.then((ok) => {
|
|
245
|
-
if (ok
|
|
269
|
+
if (ok === false) restore()
|
|
246
270
|
})
|
|
247
|
-
} else if (result
|
|
248
|
-
|
|
271
|
+
} else if (result === false) {
|
|
272
|
+
restore()
|
|
249
273
|
}
|
|
250
274
|
},
|
|
251
275
|
[allowEmptySend, sending, disabled, onSend, focusEditor, applyValue],
|
|
@@ -351,6 +375,9 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
351
375
|
const syncFromDom = useCallback(() => {
|
|
352
376
|
const el = editorRef.current
|
|
353
377
|
if (!el) return
|
|
378
|
+
// Typing can DELETE a chip (they are atomic `contentEditable=false` nodes),
|
|
379
|
+
// so the flag has to be re-read here too, not just where chips are built.
|
|
380
|
+
setHasChips(el.querySelector('[data-token]') !== null)
|
|
354
381
|
setValue(serialize(el))
|
|
355
382
|
}, [])
|
|
356
383
|
|
|
@@ -452,14 +479,13 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
452
479
|
const hasContent = value.trim().length > 0 || allowEmptySend
|
|
453
480
|
const sendDisabled = sending || disabled || !hasContent
|
|
454
481
|
const isEmpty = value.length === 0
|
|
455
|
-
const isDisabled = sending || disabled
|
|
456
482
|
// Non-destructive ghost preview (e.g. a hovered quick-action's full prompt).
|
|
457
483
|
// Shown whenever a `previewText` is set (even over an existing draft): the
|
|
458
484
|
// editor's real value is NEVER touched — it's just visually hidden behind the
|
|
459
485
|
// ghost while previewing, and reappears verbatim once `previewText` clears.
|
|
460
486
|
// Declarative, no `setValue` / draft save-restore. Suppressed the moment the
|
|
461
487
|
// user edits the draft (`previewDismissed`) so typing is never hidden.
|
|
462
|
-
const showPreview = !
|
|
488
|
+
const showPreview = !sending && !disabled && !!previewText && !previewDismissed
|
|
463
489
|
|
|
464
490
|
return (
|
|
465
491
|
<div
|
|
@@ -493,24 +519,28 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
493
519
|
}}
|
|
494
520
|
className={cn(
|
|
495
521
|
// `items-center` keeps the empty single-line text AND a mention chip
|
|
496
|
-
// vertically centered the same way. `py-1.5`
|
|
497
|
-
// editor's `leading-9` (36px) →
|
|
498
|
-
//
|
|
499
|
-
// (incl. its ~3.5px vertical-align overhead), so there's almost
|
|
500
|
-
// slack for the chip to drift in → it reads as centered
|
|
501
|
-
//
|
|
522
|
+
// vertically centered the same way. With a chip in the box, `py-1.5`
|
|
523
|
+
// (6px) pairs with the editor's `leading-9` (36px) → that row is
|
|
524
|
+
// 36 + 2*6 = 48px. The 36px line box is just barely above the 32px
|
|
525
|
+
// chip (incl. its ~3.5px vertical-align overhead), so there's almost
|
|
526
|
+
// no slack for the chip to drift in → it reads as centered.
|
|
527
|
+
// A chipless row is shorter than its content box and the `min-h-*`
|
|
528
|
+
// here is what sets its height: 48px from `md` up, 44px below.
|
|
502
529
|
"flex w-full items-center gap-2 px-3 py-1.5 min-h-11 md:min-h-12 cursor-text group transition-colors duration-200",
|
|
503
530
|
!hideBorder && "rounded-[6px] border bg-ods-card border-ods-border",
|
|
504
|
-
!hideBorder && (focused ? "border-ods-accent" : !
|
|
505
|
-
!hideBorder &&
|
|
531
|
+
!hideBorder && (focused ? "border-ods-accent" : !disabled && "hover:bg-ods-bg-hover hover:border-ods-border-hover"),
|
|
532
|
+
!hideBorder && disabled && "!cursor-not-allowed bg-ods-bg",
|
|
506
533
|
hideBorder && "bg-transparent",
|
|
507
534
|
)}
|
|
508
535
|
>
|
|
509
536
|
{startIcon && <span className="flex h-6 shrink-0 items-center">{startIcon}</span>}
|
|
510
537
|
|
|
511
538
|
<div className="relative flex-1 min-w-0">
|
|
539
|
+
{/* No chip-line override on the placeholder: it only renders while
|
|
540
|
+
the draft is EMPTY, so the editor is always on its plain line
|
|
541
|
+
box here. */}
|
|
512
542
|
{isEmpty && !showPreview && (
|
|
513
|
-
<span className="pointer-events-none absolute left-0 top-0 select-none text-h4
|
|
543
|
+
<span className="pointer-events-none absolute left-0 top-0 select-none text-h4 text-ods-text-secondary">
|
|
514
544
|
{disabled ? "Connection lost. Waiting to reconnect..." : placeholder}
|
|
515
545
|
</span>
|
|
516
546
|
)}
|
|
@@ -525,7 +555,7 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
525
555
|
text; clearing `previewText` restores the (opacity-hidden)
|
|
526
556
|
editor. */}
|
|
527
557
|
{showPreview && (
|
|
528
|
-
<p className="pointer-events-none absolute inset-x-0 top-0 m-0 select-none truncate text-h4
|
|
558
|
+
<p className={cn("pointer-events-none absolute inset-x-0 top-0 m-0 select-none truncate text-h4 text-ods-text-secondary", hasChips && "!leading-9")}>
|
|
529
559
|
{previewText}
|
|
530
560
|
</p>
|
|
531
561
|
)}
|
|
@@ -540,7 +570,21 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
540
570
|
role="textbox"
|
|
541
571
|
aria-multiline="true"
|
|
542
572
|
aria-label={typeof placeholder === 'string' ? placeholder : 'Message'}
|
|
543
|
-
|
|
573
|
+
// `sending` blocks SENDING, never typing. Taking
|
|
574
|
+
// `contentEditable` away under a focused editor blurs it, and
|
|
575
|
+
// iOS dismisses the keyboard on blur; restoring it re-establishes
|
|
576
|
+
// the input session (and the refocus-after-send effect below
|
|
577
|
+
// re-presents the keyboard once more), so on a phone the keyboard
|
|
578
|
+
// flashed shut and open again around every send — repeatedly,
|
|
579
|
+
// because a host's `sending` toggles once per phase of a turn
|
|
580
|
+
// (`chatLoading` in `embeddable-chat` is `isTyping ||
|
|
581
|
+
// isCompacting`, and the legacy Mingo page adds dialog creation).
|
|
582
|
+
// Nothing is lost by staying editable: `fire()` and the send
|
|
583
|
+
// button are both gated on `sending` already, so a draft typed
|
|
584
|
+
// while a turn streams simply waits for its turn — Enter is a
|
|
585
|
+
// no-op until the send button lights back up. Only `disabled` —
|
|
586
|
+
// the transport is gone — takes the editor out of service.
|
|
587
|
+
contentEditable={!disabled}
|
|
544
588
|
suppressContentEditableWarning
|
|
545
589
|
spellCheck
|
|
546
590
|
onInput={handleInput}
|
|
@@ -558,17 +602,25 @@ const ChatInput = forwardRef<ChatInputRef, ChatInputProps>((allProps, ref) => {
|
|
|
558
602
|
// see the preview comment above) and is only made transparent;
|
|
559
603
|
// the absolutely-positioned single-line preview paints over it.
|
|
560
604
|
showPreview && "opacity-0",
|
|
561
|
-
// `leading-9` (36px) sits just above the 32px chip's
|
|
562
|
-
// (~35.5px incl. vertical-align overhead): the LINE
|
|
563
|
-
// height (deterministic 48px, no overflow) AND the
|
|
564
|
-
// keeps the chip centered
|
|
565
|
-
// `
|
|
566
|
-
//
|
|
567
|
-
//
|
|
568
|
-
//
|
|
569
|
-
|
|
605
|
+
// WITH chips, `leading-9` (36px) sits just above the 32px chip's
|
|
606
|
+
// line-box need (~35.5px incl. vertical-align overhead): the LINE
|
|
607
|
+
// drives row height (deterministic 48px, no overflow) AND the
|
|
608
|
+
// near-zero slack keeps the chip centered against the `align-top`
|
|
609
|
+
// `h-9` wrapper `buildChipEl` gives it. ~4px gap between wrapped
|
|
610
|
+
// chip rows.
|
|
611
|
+
// WITHOUT chips there is nothing tall to center, and forcing the
|
|
612
|
+
// same 36px box on 14px phone text (`text-h4`) put a blank line's
|
|
613
|
+
// worth of air between every wrapped row — so plain drafts keep
|
|
614
|
+
// `text-h4`'s own responsive line-height (20px / 24px at md).
|
|
615
|
+
// `min-h-*` pins the single-line box even when EMPTY: a
|
|
616
|
+
// non-editable (`contentEditable=false`, i.e. `disabled`) empty div
|
|
617
|
+
// would otherwise collapse to 0px, and `items-center` would
|
|
618
|
+
// re-center the shorter wrapper in the row — dropping the `top-0`
|
|
619
|
+
// placeholder down.
|
|
620
|
+
"text-h4 text-ods-text-primary",
|
|
621
|
+
hasChips ? "min-h-9 !leading-9" : "min-h-[var(--font-line-space-h4-body)]",
|
|
570
622
|
"scrollbar-thin scrollbar-track-transparent scrollbar-thumb-ods-border/30 hover:scrollbar-thumb-ods-text-secondary/30",
|
|
571
|
-
|
|
623
|
+
disabled && "cursor-not-allowed",
|
|
572
624
|
)}
|
|
573
625
|
/>
|
|
574
626
|
</div>
|
|
@@ -325,7 +325,11 @@ export function FileUpload<T extends FileUploadCandidate = File>({
|
|
|
325
325
|
// already on screen, an unreadable selection), and this runs from a click
|
|
326
326
|
// handler where a rejection would go unhandled.
|
|
327
327
|
try {
|
|
328
|
-
|
|
328
|
+
// Skip the empty (cancelled) case rather than routing it through
|
|
329
|
+
// handleFiles, whose first act is to clear a validation message the user
|
|
330
|
+
// may still be reading.
|
|
331
|
+
const picked = await pickFiles()
|
|
332
|
+
if (picked.length > 0) handleFiles(picked)
|
|
329
333
|
} catch (err) {
|
|
330
334
|
setValidationError(err instanceof Error ? err.message : "Could not open the file picker")
|
|
331
335
|
}
|