@flamingo-stack/openframe-frontend-core 0.0.290 → 0.0.291-snapshot.20260618233000

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 (138) hide show
  1. package/dist/{chunk-EL5GCMPU.cjs → chunk-2BMVBPC7.cjs} +9 -9
  2. package/dist/{chunk-EL5GCMPU.cjs.map → chunk-2BMVBPC7.cjs.map} +1 -1
  3. package/dist/{chunk-OYXZIPNM.cjs → chunk-2NJ44RTT.cjs} +27 -27
  4. package/dist/{chunk-OYXZIPNM.cjs.map → chunk-2NJ44RTT.cjs.map} +1 -1
  5. package/dist/{chunk-R4CLIWAU.js → chunk-5FK7X3EE.js} +270 -172
  6. package/dist/chunk-5FK7X3EE.js.map +1 -0
  7. package/dist/{chunk-3SDBXXDP.cjs → chunk-5PELVUFT.cjs} +26 -26
  8. package/dist/{chunk-3SDBXXDP.cjs.map → chunk-5PELVUFT.cjs.map} +1 -1
  9. package/dist/{chunk-2V6RCQ5M.cjs → chunk-5R5OODNE.cjs} +40 -40
  10. package/dist/{chunk-2V6RCQ5M.cjs.map → chunk-5R5OODNE.cjs.map} +1 -1
  11. package/dist/{chunk-ODR6A6FC.js → chunk-6FHO73AP.js} +22 -10
  12. package/dist/{chunk-ODR6A6FC.js.map → chunk-6FHO73AP.js.map} +1 -1
  13. package/dist/{chunk-KJF7SRKH.js → chunk-B2U6INNO.js} +3 -3
  14. package/dist/{chunk-4F3X2AOB.js → chunk-C667P6LZ.js} +5 -5
  15. package/dist/{chunk-UC5GB255.cjs → chunk-CDJOKNCS.cjs} +17 -17
  16. package/dist/{chunk-UC5GB255.cjs.map → chunk-CDJOKNCS.cjs.map} +1 -1
  17. package/dist/{chunk-7NM7DEUK.js → chunk-CUQH4SHH.js} +2 -2
  18. package/dist/{chunk-ZLN6SM2U.js → chunk-DUIWR7RQ.js} +3 -3
  19. package/dist/{chunk-4XMYOZFO.js → chunk-E2YXRSDG.js} +5 -5
  20. package/dist/{chunk-AAK6IY6Y.cjs → chunk-FFP2A77V.cjs} +10 -10
  21. package/dist/{chunk-AAK6IY6Y.cjs.map → chunk-FFP2A77V.cjs.map} +1 -1
  22. package/dist/{chunk-Z5QIVHJW.js → chunk-HTYUZXQP.js} +5 -5
  23. package/dist/{chunk-LVOBI2M5.js → chunk-IXDTNQF4.js} +3 -3
  24. package/dist/{chunk-I6ZPGKZ2.cjs → chunk-JC5RN7ZS.cjs} +6 -6
  25. package/dist/{chunk-I6ZPGKZ2.cjs.map → chunk-JC5RN7ZS.cjs.map} +1 -1
  26. package/dist/{chunk-VJ4ZWD5G.cjs → chunk-MDLWEJAV.cjs} +1072 -974
  27. package/dist/chunk-MDLWEJAV.cjs.map +1 -0
  28. package/dist/{chunk-R2KT5GDD.js → chunk-N45M3TK3.js} +14 -4
  29. package/dist/chunk-N45M3TK3.js.map +1 -0
  30. package/dist/{chunk-EI4WALN2.cjs → chunk-OXOTKEYY.cjs} +39 -29
  31. package/dist/chunk-OXOTKEYY.cjs.map +1 -0
  32. package/dist/{chunk-7L22MF3U.cjs → chunk-PZZGDS5I.cjs} +17 -17
  33. package/dist/{chunk-7L22MF3U.cjs.map → chunk-PZZGDS5I.cjs.map} +1 -1
  34. package/dist/{chunk-VRSXJ5QJ.js → chunk-SLP4KXP6.js} +3 -2
  35. package/dist/chunk-SLP4KXP6.js.map +1 -0
  36. package/dist/{chunk-7EYWERFT.js → chunk-VK4B6UGU.js} +4 -4
  37. package/dist/{chunk-D6RK5YXX.cjs → chunk-Z6BK4XHH.cjs} +22 -10
  38. package/dist/chunk-Z6BK4XHH.cjs.map +1 -0
  39. package/dist/{chunk-Y4JNA4W6.cjs → chunk-ZHNL2IPK.cjs} +3 -2
  40. package/dist/chunk-ZHNL2IPK.cjs.map +1 -0
  41. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  42. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  43. package/dist/components/chat/embeddable-chat.d.ts +15 -0
  44. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  45. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -1
  46. package/dist/components/chat/index.cjs +7 -5
  47. package/dist/components/chat/index.cjs.map +1 -1
  48. package/dist/components/chat/index.d.ts +1 -0
  49. package/dist/components/chat/index.d.ts.map +1 -1
  50. package/dist/components/chat/index.js +6 -4
  51. package/dist/components/chat/remark-mention-chips.d.ts +30 -0
  52. package/dist/components/chat/remark-mention-chips.d.ts.map +1 -0
  53. package/dist/components/chat/types/api.types.d.ts +4 -0
  54. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  55. package/dist/components/chat/types/component.types.d.ts +24 -0
  56. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  57. package/dist/components/chat/types/context-item.types.d.ts +5 -0
  58. package/dist/components/chat/types/context-item.types.d.ts.map +1 -1
  59. package/dist/components/chat/types/processing.types.d.ts +4 -0
  60. package/dist/components/chat/types/processing.types.d.ts.map +1 -1
  61. package/dist/components/chat/utils/chunk-parser.d.ts.map +1 -1
  62. package/dist/components/chat/utils/nav-anchor-props.d.ts +8 -3
  63. package/dist/components/chat/utils/nav-anchor-props.d.ts.map +1 -1
  64. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  65. package/dist/components/contact/index.cjs +6 -6
  66. package/dist/components/contact/index.js +5 -5
  67. package/dist/components/docs/index.cjs +5 -5
  68. package/dist/components/docs/index.js +4 -4
  69. package/dist/components/embeds/index.cjs +6 -6
  70. package/dist/components/embeds/index.js +5 -5
  71. package/dist/components/faq/index.cjs +6 -6
  72. package/dist/components/faq/index.js +5 -5
  73. package/dist/components/features/index.cjs +5 -5
  74. package/dist/components/features/index.js +4 -4
  75. package/dist/components/features/paths-display.d.ts +1 -1
  76. package/dist/components/features/paths-display.d.ts.map +1 -1
  77. package/dist/components/index.cjs +178 -176
  78. package/dist/components/index.cjs.map +1 -1
  79. package/dist/components/index.js +13 -11
  80. package/dist/components/index.js.map +1 -1
  81. package/dist/components/navigation/index.cjs +5 -5
  82. package/dist/components/navigation/index.js +4 -4
  83. package/dist/components/onboarding-guides/index.cjs +24 -24
  84. package/dist/components/onboarding-guides/index.js +4 -4
  85. package/dist/components/related-content/index.cjs +6 -6
  86. package/dist/components/related-content/index.js +5 -5
  87. package/dist/components/tickets/index.cjs +63 -63
  88. package/dist/components/tickets/index.js +6 -6
  89. package/dist/components/ui/index.cjs +7 -5
  90. package/dist/components/ui/index.cjs.map +1 -1
  91. package/dist/components/ui/index.js +6 -4
  92. package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
  93. package/dist/components/ui/tag.d.ts +10 -1
  94. package/dist/components/ui/tag.d.ts.map +1 -1
  95. package/dist/index.cjs +7 -5
  96. package/dist/index.cjs.map +1 -1
  97. package/dist/index.js +6 -4
  98. package/dist/utils/index.cjs +21 -9
  99. package/dist/utils/index.cjs.map +1 -1
  100. package/dist/utils/index.js +21 -9
  101. package/dist/utils/index.js.map +1 -1
  102. package/dist/utils/scroll-into-view.d.ts +12 -0
  103. package/dist/utils/scroll-into-view.d.ts.map +1 -1
  104. package/package.json +1 -1
  105. package/src/components/chat/chat-message-enhanced.tsx +71 -9
  106. package/src/components/chat/chat-message-list.tsx +2 -0
  107. package/src/components/chat/embeddable-chat.tsx +50 -6
  108. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +1 -0
  109. package/src/components/chat/index.ts +1 -0
  110. package/src/components/chat/remark-mention-chips.ts +72 -0
  111. package/src/components/chat/types/api.types.ts +1 -1
  112. package/src/components/chat/types/component.types.ts +18 -0
  113. package/src/components/chat/types/context-item.types.ts +5 -0
  114. package/src/components/chat/types/processing.types.ts +8 -1
  115. package/src/components/chat/utils/chunk-parser.ts +11 -0
  116. package/src/components/chat/utils/nav-anchor-props.ts +22 -4
  117. package/src/components/chat/utils/process-historical-messages.ts +22 -0
  118. package/src/components/features/.paths-display.md +1 -1
  119. package/src/components/features/command-box.tsx +1 -1
  120. package/src/components/features/paths-display.tsx +13 -14
  121. package/src/components/ui/simple-markdown-renderer.tsx +14 -11
  122. package/src/components/ui/tag.tsx +12 -2
  123. package/src/utils/scroll-into-view.ts +51 -9
  124. package/dist/chunk-D6RK5YXX.cjs.map +0 -1
  125. package/dist/chunk-EI4WALN2.cjs.map +0 -1
  126. package/dist/chunk-R2KT5GDD.js.map +0 -1
  127. package/dist/chunk-R4CLIWAU.js.map +0 -1
  128. package/dist/chunk-VJ4ZWD5G.cjs.map +0 -1
  129. package/dist/chunk-VRSXJ5QJ.js.map +0 -1
  130. package/dist/chunk-Y4JNA4W6.cjs.map +0 -1
  131. /package/dist/{chunk-KJF7SRKH.js.map → chunk-B2U6INNO.js.map} +0 -0
  132. /package/dist/{chunk-4F3X2AOB.js.map → chunk-C667P6LZ.js.map} +0 -0
  133. /package/dist/{chunk-7NM7DEUK.js.map → chunk-CUQH4SHH.js.map} +0 -0
  134. /package/dist/{chunk-ZLN6SM2U.js.map → chunk-DUIWR7RQ.js.map} +0 -0
  135. /package/dist/{chunk-4XMYOZFO.js.map → chunk-E2YXRSDG.js.map} +0 -0
  136. /package/dist/{chunk-Z5QIVHJW.js.map → chunk-HTYUZXQP.js.map} +0 -0
  137. /package/dist/{chunk-LVOBI2M5.js.map → chunk-IXDTNQF4.js.map} +0 -0
  138. /package/dist/{chunk-7EYWERFT.js.map → chunk-VK4B6UGU.js.map} +0 -0
@@ -1,8 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import React from 'react'
4
- import { Copy } from 'lucide-react'
5
- import { Button } from '../ui/button'
4
+ import { Copy02Icon } from '../icons-v2-generated/documents/copy-02-icon'
6
5
  import { cn } from '../../utils/cn'
7
6
 
8
7
  export interface PathsDisplayProps {
@@ -37,7 +36,7 @@ export interface PathsDisplayProps {
37
36
  showCopyButtons?: boolean
38
37
 
39
38
  /**
40
- * Size of the copy icon (default: 'w-5 h-5')
39
+ * Size of the copy icon (default: 'w-6 h-6')
41
40
  */
42
41
  copyIconSize?: string
43
42
  }
@@ -78,7 +77,7 @@ export function PathsDisplay({
78
77
  description,
79
78
  className,
80
79
  showCopyButtons = true,
81
- copyIconSize = 'w-5 h-5'
80
+ copyIconSize = 'w-6 h-6'
82
81
  }: PathsDisplayProps) {
83
82
  if (!paths || paths.length === 0) {
84
83
  return null
@@ -87,12 +86,12 @@ export function PathsDisplay({
87
86
  return (
88
87
  <div className={cn('flex flex-col gap-3', className)}>
89
88
  {title && (
90
- <div className="text-ods-text-primary text-[16px] md:text-[18px]">
89
+ <div className="text-h4 text-ods-text-primary">
91
90
  {title}
92
91
  </div>
93
92
  )}
94
93
  {description && (
95
- <div className="text-ods-text-secondary text-[14px] md:text-[16px]">
94
+ <div className="text-h6 text-ods-text-secondary">
96
95
  {description}
97
96
  </div>
98
97
  )}
@@ -100,20 +99,20 @@ export function PathsDisplay({
100
99
  {paths.map((path) => (
101
100
  <div
102
101
  key={path}
103
- className="flex items-center justify-between p-4 border-b border-ods-border last:border-b-0"
102
+ className="flex items-center gap-4 p-4 border-b border-ods-border last:border-b-0"
104
103
  >
105
- <span className="text-ods-text-primary font-medium text-[14px] md:text-[16px] font-mono break-all">
104
+ <span className="flex-1 min-w-0 text-h4 text-ods-text-primary truncate">
106
105
  {path}
107
106
  </span>
108
107
  {showCopyButtons && onCopyPath && (
109
- <Button
110
- variant="transparent"
111
- size="small-legacy"
108
+ <button
109
+ type="button"
112
110
  onClick={() => onCopyPath(path)}
113
- className="ml-4 shrink-0"
111
+ aria-label={`Copy ${path}`}
112
+ className="shrink-0 rounded-md text-ods-text-secondary transition-colors hover:text-ods-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus"
114
113
  >
115
- <Copy className={copyIconSize} />
116
- </Button>
114
+ <Copy02Icon className={copyIconSize} />
115
+ </button>
117
116
  )}
118
117
  </div>
119
118
  ))}
@@ -156,25 +156,28 @@ function rehypeStripUnsafe() {
156
156
 
157
157
  /**
158
158
  * URL transformer that extends react-markdown's default safe-protocol
159
- * allowlist with `card://` the non-standard scheme `remarkCardLinks`
160
- * emits for inline chat-card markers.
159
+ * allowlist with the two internal schemes the chat remark plugins emit:
160
+ * - `card://` — `remarkCardLinks`, for inline chat-card markers.
161
+ * - `mention://` — `remarkMentionChips`, for inline `@marker:id` AI mentions.
161
162
  *
162
163
  * Without this, react-markdown 10's `defaultUrlTransform` strips the URL
163
164
  * to `""` before the `<a>` component override runs (the override's
164
- * `href.startsWith('card://')` check then fails and the marker leaks
165
- * through as literal text). All other URL schemes still go through the
166
- * default sanitizer `javascript:`, `vbscript:`, `data:` (non-image), etc.
167
- * remain blocked.
165
+ * `href.startsWith('card://')` / `'mention://'` check then fails and the
166
+ * marker leaks through as literal text, or as an empty-href link that the
167
+ * host's `NavLinkAnchor` resolves to a base URL). All other URL schemes still
168
+ * go through the default sanitizer — `javascript:`, `vbscript:`, `data:`
169
+ * (non-image), etc. remain blocked.
168
170
  *
169
- * Scope: `card://` is allowed ONLY for `href` attributes. If the LLM
171
+ * Scope: both schemes are allowed ONLY for `href` attributes. If the LLM
170
172
  * accidentally emits `![alt](card://type:id)` the URL still goes through
171
173
  * `defaultUrlTransform` (which strips it to `""`) so an `<img src="card://...">`
172
- * never reaches the DOM — broken request avoided. Per v6.1 §B.2.4: "the
173
- * `card://` scheme is internal — never network-fetched, never written to
174
- * attributes other than `href` for renderer dispatch."
174
+ * never reaches the DOM — broken request avoided. Per v6.1 §B.2.4: these
175
+ * schemes are internal — never network-fetched, never written to attributes
176
+ * other than `href` for renderer dispatch.
175
177
  */
176
178
  function cardAwareUrlTransform(url: string, key: string): string {
177
- if (key === 'href' && typeof url === 'string' && url.startsWith('card://')) return url;
179
+ if (key === 'href' && typeof url === 'string' && (url.startsWith('card://') || url.startsWith('mention://')))
180
+ return url;
178
181
  return defaultUrlTransform(url);
179
182
  }
180
183
 
@@ -72,6 +72,15 @@ export interface TagProps
72
72
  icon?: React.ReactNode
73
73
  onClose?: () => void
74
74
  disabled?: boolean
75
+ /**
76
+ * Root element. Defaults to `'div'`. Pass `'span'` to render an INLINE tag
77
+ * that is valid inside phrasing content (e.g. a markdown `<p>` — a block
78
+ * `<div>` there is invalid HTML and breaks hydration). The variant base is
79
+ * already `inline-flex`, so the span lays out identically. Note: `onClose`
80
+ * renders a `<button>`, which is fine inside a `<span>` but not inside an
81
+ * `<a>` — don't combine `as="span"` + `onClose` inside an anchor.
82
+ */
83
+ as?: 'div' | 'span'
75
84
  }
76
85
 
77
86
  function Tag({
@@ -82,10 +91,11 @@ function Tag({
82
91
  className,
83
92
  labelClassName,
84
93
  disabled,
94
+ as: Comp = 'div',
85
95
  ...props
86
96
  }: TagProps) {
87
97
  return (
88
- <div
98
+ <Comp
89
99
  className={cn(
90
100
  tagVariants({ variant }),
91
101
  disabled && disabledTagClasses,
@@ -117,7 +127,7 @@ function Tag({
117
127
  <XmarkCircleIcon className="size-4" />
118
128
  </button>
119
129
  )}
120
- </div>
130
+ </Comp>
121
131
  )
122
132
  }
123
133
 
@@ -33,6 +33,18 @@
33
33
  *
34
34
  * Honors `prefers-reduced-motion` (jumps instantly) and cancels on genuine user
35
35
  * scroll intent (wheel / touch) so we never fight the user.
36
+ *
37
+ * WINDOW *OR* A SCROLLABLE ANCESTOR: the helper is not hard-wired to the window
38
+ * scroller. It walks up from the target to the nearest ancestor that is an
39
+ * actual scroll container (`overflow-y: auto | scroll | overlay` AND
40
+ * `scrollHeight > clientHeight`) and drives THAT element; only when none exists
41
+ * does it fall back to `window`. This is what makes it work inside app shells
42
+ * that put page content in a fixed-height `<main class="overflow-y-auto">`
43
+ * (e.g. OpenFrame's `AppLayout`) where the document/window never scrolls — the
44
+ * old window-only version was a silent no-op there. Note `overflow: clip` /
45
+ * `hidden` are deliberately NOT treated as scroll containers, so a list wrapper
46
+ * that uses `overflow-clip` only to round its corners still bubbles the scroll
47
+ * up to the real container (matches the `<HelpCenterCard>` list intent).
36
48
  */
37
49
 
38
50
  export interface ScrollElementIntoViewOptions {
@@ -70,6 +82,23 @@ function cancelActiveScroll(): void {
70
82
 
71
83
  const easeOutCubic = (t: number): number => 1 - Math.pow(1 - t, 3)
72
84
 
85
+ /** Nearest ancestor that is a *real* scroll container, or `null` when the
86
+ * window/document is the scroller. Only `auto | scroll | overlay` count —
87
+ * `clip` / `hidden` are intentionally excluded (a wrapper using `overflow-clip`
88
+ * purely to round corners must let the scroll bubble to the page). */
89
+ function getScrollableAncestor(el: HTMLElement): HTMLElement | null {
90
+ for (let node = el.parentElement; node; node = node.parentElement) {
91
+ const overflowY = getComputedStyle(node).overflowY
92
+ if (
93
+ (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
94
+ node.scrollHeight > node.clientHeight
95
+ ) {
96
+ return node
97
+ }
98
+ }
99
+ return null
100
+ }
101
+
73
102
  /**
74
103
  * Scroll the page so `target` lands at the top of the viewport (below sticky
75
104
  * chrome via `headerOffset`). SSR-safe; `null`/`undefined` target is a no-op so
@@ -82,16 +111,29 @@ export function scrollElementIntoView(
82
111
  if (typeof window === 'undefined' || !target) return
83
112
  const { headerOffset = 0, behavior = 'smooth', adjustTargetY, durationMs = 320 } = options
84
113
 
114
+ // Pick the scroller ONCE: a fixed-height `<main overflow-y-auto>` shell scrolls
115
+ // the element, a plain document scrolls the window. The choice can't change
116
+ // mid-tween, so resolve it up front and route every read/write through it.
117
+ const container = getScrollableAncestor(target)
118
+ const readCurrent = (): number => (container ? container.scrollTop : window.scrollY)
119
+ const writeTo = (y: number): void => {
120
+ if (container) container.scrollTop = y
121
+ else window.scrollTo(0, y)
122
+ }
123
+
85
124
  // Target is recomputed every frame: the row's absolute position can move as
86
125
  // the page reflows (a sibling drawer collapsing) and the reachable max grows
87
126
  // as the just-opened drawer expands. Clamp to the LIVE max each frame.
88
127
  const computeTarget = (): number => {
89
- const raw = target.getBoundingClientRect().top + window.scrollY - headerOffset
128
+ const raw = container
129
+ ? container.scrollTop +
130
+ (target.getBoundingClientRect().top - container.getBoundingClientRect().top) -
131
+ headerOffset
132
+ : target.getBoundingClientRect().top + window.scrollY - headerOffset
90
133
  const adjusted = adjustTargetY ? adjustTargetY(raw) : raw
91
- const maxScroll = Math.max(
92
- 0,
93
- document.documentElement.scrollHeight - window.innerHeight,
94
- )
134
+ const maxScroll = container
135
+ ? Math.max(0, container.scrollHeight - container.clientHeight)
136
+ : Math.max(0, document.documentElement.scrollHeight - window.innerHeight)
95
137
  return Math.min(Math.max(0, adjusted), maxScroll)
96
138
  }
97
139
 
@@ -104,7 +146,7 @@ export function scrollElementIntoView(
104
146
 
105
147
  // Instant paths: a single synchronous write. No tween, no anchoring race.
106
148
  if (behavior === 'instant' || behavior === 'auto' || prefersReduced) {
107
- window.scrollTo(0, computeTarget())
149
+ writeTo(computeTarget())
108
150
  return
109
151
  }
110
152
 
@@ -125,18 +167,18 @@ export function scrollElementIntoView(
125
167
 
126
168
  const step = (now: number) => {
127
169
  if (startY === null) {
128
- startY = window.scrollY
170
+ startY = readCurrent()
129
171
  startTime = now
130
172
  }
131
173
  const targetY = computeTarget()
132
174
  const t = Math.min(1, (now - startTime) / durationMs)
133
175
  const y = startY + (targetY - startY) * easeOutCubic(t)
134
- window.scrollTo(0, y)
176
+ writeTo(y)
135
177
  if (t < 1) {
136
178
  activeRaf = requestAnimationFrame(step)
137
179
  } else {
138
180
  // Final exact write in case easing left a sub-pixel gap, then teardown.
139
- window.scrollTo(0, computeTarget())
181
+ writeTo(computeTarget())
140
182
  activeRaf = 0
141
183
  if (teardownActive) {
142
184
  teardownActive()