@flamingo-stack/openframe-frontend-core 0.0.340 → 0.0.341-snapshot.20260630022404

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 (108) hide show
  1. package/dist/{chunk-4K2M2WC4.cjs → chunk-2L6PCJGJ.cjs} +26 -26
  2. package/dist/{chunk-4K2M2WC4.cjs.map → chunk-2L6PCJGJ.cjs.map} +1 -1
  3. package/dist/{chunk-TVCBMR3N.cjs → chunk-3GNUN3UF.cjs} +7 -7
  4. package/dist/{chunk-TVCBMR3N.cjs.map → chunk-3GNUN3UF.cjs.map} +1 -1
  5. package/dist/{chunk-7TENQYAJ.js → chunk-6DKQW5OB.js} +2 -2
  6. package/dist/{chunk-53MGSWCC.js → chunk-D6OFQCBQ.js} +4 -4
  7. package/dist/{chunk-DRO773DG.cjs → chunk-EEAUFJOJ.cjs} +56 -56
  8. package/dist/{chunk-DRO773DG.cjs.map → chunk-EEAUFJOJ.cjs.map} +1 -1
  9. package/dist/{chunk-MNLQMAY3.js → chunk-G5BJ5EJ3.js} +2 -2
  10. package/dist/{chunk-KE2PMD6A.js → chunk-GGHWEV6K.js} +2 -2
  11. package/dist/{chunk-SIK5LBUN.cjs → chunk-HHEN6U6D.cjs} +25 -25
  12. package/dist/{chunk-SIK5LBUN.cjs.map → chunk-HHEN6U6D.cjs.map} +1 -1
  13. package/dist/{chunk-YEB5Z76W.cjs → chunk-K4NVJM6V.cjs} +62 -62
  14. package/dist/{chunk-YEB5Z76W.cjs.map → chunk-K4NVJM6V.cjs.map} +1 -1
  15. package/dist/{chunk-OVN265XQ.js → chunk-KDFQXI6L.js} +2 -2
  16. package/dist/{chunk-NDHQG4I4.js → chunk-M4JER3ZJ.js} +227 -173
  17. package/dist/chunk-M4JER3ZJ.js.map +1 -0
  18. package/dist/{chunk-EXFHHZ2C.cjs → chunk-MGYDI2R4.cjs} +9 -9
  19. package/dist/{chunk-EXFHHZ2C.cjs.map → chunk-MGYDI2R4.cjs.map} +1 -1
  20. package/dist/{chunk-W7J46YKF.js → chunk-MQXK5YZJ.js} +2 -2
  21. package/dist/{chunk-HVYR323G.cjs → chunk-NBZR5OEQ.cjs} +15 -15
  22. package/dist/{chunk-HVYR323G.cjs.map → chunk-NBZR5OEQ.cjs.map} +1 -1
  23. package/dist/{chunk-BMSJTLGO.cjs → chunk-NLJUVRVX.cjs} +12 -12
  24. package/dist/{chunk-BMSJTLGO.cjs.map → chunk-NLJUVRVX.cjs.map} +1 -1
  25. package/dist/{chunk-ERMMMQET.cjs → chunk-NRRBPW33.cjs} +388 -334
  26. package/dist/chunk-NRRBPW33.cjs.map +1 -0
  27. package/dist/{chunk-DFFOCQFO.cjs → chunk-NXDUUG3E.cjs} +5 -5
  28. package/dist/{chunk-DFFOCQFO.cjs.map → chunk-NXDUUG3E.cjs.map} +1 -1
  29. package/dist/{chunk-L6YX6D26.cjs → chunk-PRVRFN5Y.cjs} +31 -31
  30. package/dist/{chunk-L6YX6D26.cjs.map → chunk-PRVRFN5Y.cjs.map} +1 -1
  31. package/dist/{chunk-NC3DJLP5.js → chunk-SSWHDTUV.js} +4 -4
  32. package/dist/{chunk-573LTCRV.js → chunk-TV3BIALE.js} +2 -2
  33. package/dist/{chunk-TOMTBXM7.js → chunk-VVKLQXWF.js} +2 -2
  34. package/dist/{chunk-GGFJ5OQ3.js → chunk-VZM3OH26.js} +4 -4
  35. package/dist/{chunk-VA3GDVOV.cjs → chunk-YHHGM3EL.cjs} +37 -37
  36. package/dist/{chunk-VA3GDVOV.cjs.map → chunk-YHHGM3EL.cjs.map} +1 -1
  37. package/dist/{chunk-T4SW6GOR.js → chunk-YHXX7WEL.js} +4 -4
  38. package/dist/components/case-studies/index.cjs +8 -8
  39. package/dist/components/case-studies/index.js +2 -2
  40. package/dist/components/chat/chat-composer.d.ts +4 -1
  41. package/dist/components/chat/chat-composer.d.ts.map +1 -1
  42. package/dist/components/chat/chat-input.d.ts.map +1 -1
  43. package/dist/components/chat/chat-quick-action-row.d.ts +6 -1
  44. package/dist/components/chat/chat-quick-action-row.d.ts.map +1 -1
  45. package/dist/components/chat/guide-welcome.d.ts +5 -5
  46. package/dist/components/chat/guide-welcome.d.ts.map +1 -1
  47. package/dist/components/chat/index.cjs +2 -2
  48. package/dist/components/chat/index.js +1 -1
  49. package/dist/components/chat/types/component.types.d.ts +6 -0
  50. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  51. package/dist/components/contact/index.cjs +3 -3
  52. package/dist/components/contact/index.js +2 -2
  53. package/dist/components/docs/index.cjs +5 -5
  54. package/dist/components/docs/index.js +4 -4
  55. package/dist/components/embeds/index.cjs +3 -3
  56. package/dist/components/embeds/index.js +2 -2
  57. package/dist/components/faq/index.cjs +3 -3
  58. package/dist/components/faq/index.js +2 -2
  59. package/dist/components/features/index.cjs +2 -2
  60. package/dist/components/features/index.js +1 -1
  61. package/dist/components/help-center-pages/index.cjs +20 -20
  62. package/dist/components/help-center-pages/index.js +11 -11
  63. package/dist/components/index.cjs +121 -121
  64. package/dist/components/index.js +9 -9
  65. package/dist/components/navigation/index.cjs +2 -2
  66. package/dist/components/navigation/index.js +1 -1
  67. package/dist/components/onboarding-guides/index.cjs +5 -5
  68. package/dist/components/onboarding-guides/index.js +4 -4
  69. package/dist/components/related-content/index.cjs +3 -3
  70. package/dist/components/related-content/index.js +2 -2
  71. package/dist/components/tickets/index.cjs +5 -5
  72. package/dist/components/tickets/index.js +4 -4
  73. package/dist/components/ui/index.cjs +2 -2
  74. package/dist/components/ui/index.js +1 -1
  75. package/dist/components/ui/table/table-row.d.ts +1 -1
  76. package/dist/components/ui/table/table-row.d.ts.map +1 -1
  77. package/dist/components/ui/table/table.d.ts +1 -1
  78. package/dist/components/ui/table/table.d.ts.map +1 -1
  79. package/dist/components/ui/table/types.d.ts +16 -0
  80. package/dist/components/ui/table/types.d.ts.map +1 -1
  81. package/dist/components/ui/table/use-table-motion.d.ts +20 -0
  82. package/dist/components/ui/table/use-table-motion.d.ts.map +1 -0
  83. package/dist/index.cjs +2 -2
  84. package/dist/index.js +1 -1
  85. package/package.json +1 -1
  86. package/src/components/chat/chat-composer.tsx +5 -0
  87. package/src/components/chat/chat-input.tsx +39 -1
  88. package/src/components/chat/chat-quick-action-row.tsx +20 -0
  89. package/src/components/chat/embeddable-chat.tsx +21 -23
  90. package/src/components/chat/guide-welcome.tsx +21 -11
  91. package/src/components/chat/types/component.types.ts +6 -0
  92. package/src/components/ui/table/table-row.tsx +16 -3
  93. package/src/components/ui/table/table.tsx +34 -15
  94. package/src/components/ui/table/types.ts +17 -0
  95. package/src/components/ui/table/use-table-motion.ts +48 -0
  96. package/dist/chunk-ERMMMQET.cjs.map +0 -1
  97. package/dist/chunk-NDHQG4I4.js.map +0 -1
  98. /package/dist/{chunk-7TENQYAJ.js.map → chunk-6DKQW5OB.js.map} +0 -0
  99. /package/dist/{chunk-53MGSWCC.js.map → chunk-D6OFQCBQ.js.map} +0 -0
  100. /package/dist/{chunk-MNLQMAY3.js.map → chunk-G5BJ5EJ3.js.map} +0 -0
  101. /package/dist/{chunk-KE2PMD6A.js.map → chunk-GGHWEV6K.js.map} +0 -0
  102. /package/dist/{chunk-OVN265XQ.js.map → chunk-KDFQXI6L.js.map} +0 -0
  103. /package/dist/{chunk-W7J46YKF.js.map → chunk-MQXK5YZJ.js.map} +0 -0
  104. /package/dist/{chunk-NC3DJLP5.js.map → chunk-SSWHDTUV.js.map} +0 -0
  105. /package/dist/{chunk-573LTCRV.js.map → chunk-TV3BIALE.js.map} +0 -0
  106. /package/dist/{chunk-TOMTBXM7.js.map → chunk-VVKLQXWF.js.map} +0 -0
  107. /package/dist/{chunk-GGFJ5OQ3.js.map → chunk-VZM3OH26.js.map} +0 -0
  108. /package/dist/{chunk-T4SW6GOR.js.map → chunk-YHXX7WEL.js.map} +0 -0
@@ -32,12 +32,12 @@ export interface GuideWelcomeProps {
32
32
  * `subtitle` is present. */
33
33
  subtitleLoading?: boolean
34
34
  /** Quick-action chips — caller-provided; there are no built-in defaults, so
35
- * the chip row is omitted entirely unless the host supplies actions. The row
36
- * is a single line: as many chips as fit render inline and the rest collapse
37
- * under a trailing "⋯" overflow menu (width-measured by `ChatQuickActionRow`,
38
- * so the inline count adapts to the available width — no fixed cap). */
35
+ * the chip row is omitted entirely unless the host supplies actions. ALL
36
+ * chips render in a wrapping row (no "⋯" overflow collapse) so every action
37
+ * is directly hoverable hover/focus previews the action's full `prompt` in
38
+ * the composer; click sends it. */
39
39
  quickActions?: ReadonlyArray<GuideQuickAction>
40
- /** Fired when a quick-action chip (inline or menu) is activated. */
40
+ /** Fired when a quick-action chip is activated (click). */
41
41
  onQuickAction?: (action: GuideQuickAction) => void
42
42
  /** Pointer/keyboard focus enters a quick-action chip — e.g. preview the
43
43
  * action's full `prompt` in the composer input. */
@@ -105,8 +105,9 @@ export function GuideWelcome({
105
105
  return () => ro.disconnect()
106
106
  }, [updateScrollFade])
107
107
 
108
- // Map to the shared width-measured chip row's shape. As many chips as fit on
109
- // ONE line render inline; the rest collapse under the trailing "⋯" menu.
108
+ // Map to the shared `ChatQuickActionRow` chip shape. In `wrap` mode every chip
109
+ // renders (no overflow), and `onHoverStart`/`onHoverEnd` drive the composer
110
+ // prompt preview.
110
111
  const chipItems = React.useMemo(
111
112
  () =>
112
113
  quickActions.map((action) => ({
@@ -197,10 +198,19 @@ export function GuideWelcome({
197
198
  />
198
199
  </div>
199
200
 
200
- {/* Pinned quick-action chips always visible above the composer.
201
- Single line: as many chips as fit render inline, the rest collapse
202
- into the trailing "⋯" menu (width-measured by `ChatQuickActionRow`). */}
203
- {quickActions.length > 0 && <ChatQuickActionRow chips={chipItems} />}
201
+ {/* Pinned quick-action chips above the composer the shared
202
+ `ChatQuickActionRow` in `wrap` mode: ALL chips render (no "⋯" overflow
203
+ collapse) so every action is directly hoverable; hover/focus previews
204
+ the action's full prompt in the composer, click sends it. Capped height
205
+ + internal scroll so a long (host/admin-driven) list can't grow the
206
+ pinned area without bound and squeeze the composer on short screens. */}
207
+ {quickActions.length > 0 && (
208
+ <ChatQuickActionRow
209
+ wrap
210
+ chips={chipItems}
211
+ className="max-h-28 overflow-y-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-ods-border/30"
212
+ />
213
+ )}
204
214
  </div>
205
215
  )
206
216
  }
@@ -399,6 +399,12 @@ export interface ChatInputProps extends Omit<TextareaHTMLAttributes<HTMLTextArea
399
399
  /** Suppress the textarea's own border/bg/radius — an outer card draws it
400
400
  * instead (composer context-chip layout). Forwarded to `Textarea.hideBorder`. */
401
401
  hideBorder?: boolean
402
+ /** Ephemeral, non-destructive preview text shown over the editor — e.g.
403
+ * previewing a hovered quick-action's full prompt before the user commits it.
404
+ * Purely declarative: it NEVER touches the editor's real value. While set, it
405
+ * visually replaces the editor (even an in-progress draft); clearing it
406
+ * (undefined) restores whatever the user had — empty or typed — verbatim. */
407
+ previewText?: string
402
408
  }
403
409
 
404
410
  export interface ChatInputRef {
@@ -20,9 +20,21 @@ export function TableRow<T = any>({
20
20
  compact,
21
21
  selectable,
22
22
  selected,
23
- onSelect
23
+ onSelect,
24
+ animateRowReorder,
25
+ motionDiv
24
26
  }: TableRowProps<T>) {
25
27
  const isLinkMode = Boolean(href) && !onClick
28
+ // Opt-in FLIP: the outer row becomes a `motion.div` (passed down lazily from
29
+ // Table, so framer-motion stays out of the default bundle) that animates only
30
+ // its position (`layout="position"`) so reordering doesn't distort inner cell
31
+ // content (CircularProgress / ProgressBar). Plain `<div>` when off, or until
32
+ // framer-motion has loaded — zero cost on the default path.
33
+ const animate = Boolean(animateRowReorder && motionDiv)
34
+ const Row: any = animate ? motionDiv : 'div'
35
+ const motionProps = animate
36
+ ? { layout: 'position' as const, transition: { layout: { duration: 0.35, ease: [0.22, 1, 0.36, 1] as const } } }
37
+ : {}
26
38
 
27
39
  const handleRowClick = (e: React.MouseEvent) => {
28
40
  const target = e.target as HTMLElement
@@ -67,7 +79,8 @@ export function TableRow<T = any>({
67
79
  }
68
80
 
69
81
  return (
70
- <div
82
+ <Row
83
+ {...motionProps}
71
84
  className={cn(
72
85
  'relative rounded-[6px] bg-ods-card border border-ods-border overflow-hidden',
73
86
  (onClick || isLinkMode) && 'cursor-pointer hover:bg-ods-bg-active transition-colors',
@@ -112,6 +125,6 @@ export function TableRow<T = any>({
112
125
  </TableCell>
113
126
  ))}
114
127
  </div>
115
- </div>
128
+ </Row>
116
129
  )
117
130
  }
@@ -10,6 +10,7 @@ import { TableEmptyState } from './table-empty-state'
10
10
  import { TableHeader } from './table-header'
11
11
  import { TableRow } from './table-row'
12
12
  import { ROW_HEIGHT_DESKTOP, ROW_HEIGHT_MOBILE, TableCardSkeleton } from './table-skeleton'
13
+ import { useTableMotion } from './use-table-motion'
13
14
  import type { RowAction, TableColumn, TableProps } from './types'
14
15
 
15
16
  /**
@@ -118,7 +119,11 @@ export function Table<T = any>({
118
119
  infiniteScroll,
119
120
  stickyHeader,
120
121
  stickyHeaderOffset,
122
+ animateRowReorder,
121
123
  }: TableProps<T>) {
124
+ // Opt-in row-reorder animation: framer-motion is loaded lazily (its own chunk)
125
+ // ONLY when `animateRowReorder` is set, so the default table stays motion-free.
126
+ const tableMotion = useTableMotion(Boolean(animateRowReorder))
122
127
  const columnsWithActions = injectSyntheticColumns(columns, rowActions, renderRowActions, rowHref)
123
128
  const getRowHref = (item: T): string | undefined => {
124
129
  if (onRowClick || !rowHref) return undefined
@@ -252,21 +257,35 @@ export function Table<T = any>({
252
257
  <TableEmptyState message={emptyMessage} />
253
258
  ) : (
254
259
  <>
255
- {data.map((item, index) => (
256
- <TableRow
257
- key={getRowKey(item, index)}
258
- item={item}
259
- columns={columnsWithActions}
260
- onClick={onRowClick}
261
- href={getRowHref(item)}
262
- className={getRowClassName(item, index)}
263
- index={index}
264
- compact={compact}
265
- selectable={selectable}
266
- selected={isRowSelected(item)}
267
- onSelect={handleSelectRow}
268
- />
269
- ))}
260
+ {/* Real data rows. When `animateRowReorder` is on, wrap ONLY these
261
+ in a `LayoutGroup` so a reorder (same key, new order) animates via
262
+ FLIP — the invisible placeholder rows below are intentionally left
263
+ outside it. `AnimatePresence` is not needed here: the row set is
264
+ stable across a reorder (no enter/exit); add it if a future task
265
+ animates rows being added/removed. */}
266
+ {(() => {
267
+ const rows = data.map((item, index) => (
268
+ <TableRow
269
+ key={getRowKey(item, index)}
270
+ item={item}
271
+ columns={columnsWithActions}
272
+ onClick={onRowClick}
273
+ href={getRowHref(item)}
274
+ className={getRowClassName(item, index)}
275
+ index={index}
276
+ compact={compact}
277
+ selectable={selectable}
278
+ selected={isRowSelected(item)}
279
+ onSelect={handleSelectRow}
280
+ animateRowReorder={animateRowReorder}
281
+ motionDiv={tableMotion?.motionDiv}
282
+ />
283
+ ))
284
+ // LayoutGroup only once framer-motion has lazily resolved; until
285
+ // then (and when off) rows render as plain `<div>`s.
286
+ const LayoutGroup = tableMotion?.LayoutGroup
287
+ return animateRowReorder && LayoutGroup ? <LayoutGroup>{rows}</LayoutGroup> : rows
288
+ })()}
270
289
  {/* Infinite scroll: skeleton rows */}
271
290
  {infiniteScroll?.isFetchingNextPage && (
272
291
  <TableCardSkeleton
@@ -151,6 +151,15 @@ export interface TableProps<T = any> {
151
151
  stickyHeader?: boolean
152
152
  /** Tailwind top class for sticky header offset, e.g. "top-[72px]" */
153
153
  stickyHeaderOffset?: string
154
+
155
+ /**
156
+ * Opt-in: render body rows as `motion.div` with `layout="position"` so a data
157
+ * reorder (same `rowKey`, new order) animates via FLIP. Off by default — all
158
+ * existing usages are unaffected. Honor `prefers-reduced-motion` at the call
159
+ * site (pass `false` when reduced motion is requested) so the lib prop stays
160
+ * purely mechanical and adds zero motion runtime when off.
161
+ */
162
+ animateRowReorder?: boolean
154
163
  }
155
164
 
156
165
  /** @deprecated Use types from `data-table` instead. */
@@ -209,6 +218,14 @@ export interface TableRowProps<T = any> {
209
218
  selectable?: boolean
210
219
  selected?: boolean
211
220
  onSelect?: (item: T) => void
221
+ /** Opt-in FLIP reorder — see `TableProps.animateRowReorder`. Forwarded by `Table`. */
222
+ animateRowReorder?: boolean
223
+ /**
224
+ * Internal: the lazily-resolved framer-motion `motion.div`, injected by `Table`
225
+ * so framer-motion stays out of the default bundle. `any` so this module never
226
+ * statically references framer-motion. Plain `<div>` is used until it's set.
227
+ */
228
+ motionDiv?: any
212
229
  }
213
230
 
214
231
  /** @deprecated Use types from `data-table` instead. */
@@ -0,0 +1,48 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+
5
+ /**
6
+ * Framer Motion runtime resolved lazily for the opt-in row-reorder animation.
7
+ * `motionDiv` is `motion.div`; `LayoutGroup` coordinates the FLIP.
8
+ */
9
+ export interface TableMotionRuntime {
10
+ // framer-motion component types are intentionally `any` here so the base table
11
+ // never has to statically reference framer-motion (keeping it out of the
12
+ // default bundle).
13
+ motionDiv: any
14
+ LayoutGroup: any
15
+ }
16
+
17
+ /**
18
+ * Lazily loads `framer-motion` — via a dynamic `import()` so it lands in its own
19
+ * chunk — ONLY when row-reorder animation is enabled. Consumers that never set
20
+ * `animateRowReorder` never pull framer-motion into their bundle (the default
21
+ * `Table`/`TableRow` path stays motion-free).
22
+ *
23
+ * Returns `null` until the module resolves (and always when `enabled` is false);
24
+ * callers render plain DOM in the meantime, so the first paint is non-animated
25
+ * and the FLIP kicks in once the chunk has loaded.
26
+ */
27
+ export function useTableMotion(enabled: boolean): TableMotionRuntime | null {
28
+ const [runtime, setRuntime] = useState<TableMotionRuntime | null>(null)
29
+
30
+ useEffect(() => {
31
+ if (!enabled || runtime) return
32
+ let active = true
33
+ import('framer-motion')
34
+ .then((m) => {
35
+ if (active) setRuntime({ motionDiv: m.motion.div, LayoutGroup: m.LayoutGroup })
36
+ })
37
+ .catch(() => {
38
+ // Chunk-load failure → keep `runtime` null so the table degrades to
39
+ // plain (non-animated) rows, instead of surfacing an unhandled
40
+ // promise rejection / global chunk-load error.
41
+ })
42
+ return () => {
43
+ active = false
44
+ }
45
+ }, [enabled, runtime])
46
+
47
+ return enabled ? runtime : null
48
+ }