@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.
- package/dist/{chunk-EL5GCMPU.cjs → chunk-2BMVBPC7.cjs} +9 -9
- package/dist/{chunk-EL5GCMPU.cjs.map → chunk-2BMVBPC7.cjs.map} +1 -1
- package/dist/{chunk-OYXZIPNM.cjs → chunk-2NJ44RTT.cjs} +27 -27
- package/dist/{chunk-OYXZIPNM.cjs.map → chunk-2NJ44RTT.cjs.map} +1 -1
- package/dist/{chunk-R4CLIWAU.js → chunk-5FK7X3EE.js} +270 -172
- package/dist/chunk-5FK7X3EE.js.map +1 -0
- package/dist/{chunk-3SDBXXDP.cjs → chunk-5PELVUFT.cjs} +26 -26
- package/dist/{chunk-3SDBXXDP.cjs.map → chunk-5PELVUFT.cjs.map} +1 -1
- package/dist/{chunk-2V6RCQ5M.cjs → chunk-5R5OODNE.cjs} +40 -40
- package/dist/{chunk-2V6RCQ5M.cjs.map → chunk-5R5OODNE.cjs.map} +1 -1
- package/dist/{chunk-ODR6A6FC.js → chunk-6FHO73AP.js} +22 -10
- package/dist/{chunk-ODR6A6FC.js.map → chunk-6FHO73AP.js.map} +1 -1
- package/dist/{chunk-KJF7SRKH.js → chunk-B2U6INNO.js} +3 -3
- package/dist/{chunk-4F3X2AOB.js → chunk-C667P6LZ.js} +5 -5
- package/dist/{chunk-UC5GB255.cjs → chunk-CDJOKNCS.cjs} +17 -17
- package/dist/{chunk-UC5GB255.cjs.map → chunk-CDJOKNCS.cjs.map} +1 -1
- package/dist/{chunk-7NM7DEUK.js → chunk-CUQH4SHH.js} +2 -2
- package/dist/{chunk-ZLN6SM2U.js → chunk-DUIWR7RQ.js} +3 -3
- package/dist/{chunk-4XMYOZFO.js → chunk-E2YXRSDG.js} +5 -5
- package/dist/{chunk-AAK6IY6Y.cjs → chunk-FFP2A77V.cjs} +10 -10
- package/dist/{chunk-AAK6IY6Y.cjs.map → chunk-FFP2A77V.cjs.map} +1 -1
- package/dist/{chunk-Z5QIVHJW.js → chunk-HTYUZXQP.js} +5 -5
- package/dist/{chunk-LVOBI2M5.js → chunk-IXDTNQF4.js} +3 -3
- package/dist/{chunk-I6ZPGKZ2.cjs → chunk-JC5RN7ZS.cjs} +6 -6
- package/dist/{chunk-I6ZPGKZ2.cjs.map → chunk-JC5RN7ZS.cjs.map} +1 -1
- package/dist/{chunk-VJ4ZWD5G.cjs → chunk-MDLWEJAV.cjs} +1072 -974
- package/dist/chunk-MDLWEJAV.cjs.map +1 -0
- package/dist/{chunk-R2KT5GDD.js → chunk-N45M3TK3.js} +14 -4
- package/dist/chunk-N45M3TK3.js.map +1 -0
- package/dist/{chunk-EI4WALN2.cjs → chunk-OXOTKEYY.cjs} +39 -29
- package/dist/chunk-OXOTKEYY.cjs.map +1 -0
- package/dist/{chunk-7L22MF3U.cjs → chunk-PZZGDS5I.cjs} +17 -17
- package/dist/{chunk-7L22MF3U.cjs.map → chunk-PZZGDS5I.cjs.map} +1 -1
- package/dist/{chunk-VRSXJ5QJ.js → chunk-SLP4KXP6.js} +3 -2
- package/dist/chunk-SLP4KXP6.js.map +1 -0
- package/dist/{chunk-7EYWERFT.js → chunk-VK4B6UGU.js} +4 -4
- package/dist/{chunk-D6RK5YXX.cjs → chunk-Z6BK4XHH.cjs} +22 -10
- package/dist/chunk-Z6BK4XHH.cjs.map +1 -0
- package/dist/{chunk-Y4JNA4W6.cjs → chunk-ZHNL2IPK.cjs} +3 -2
- package/dist/chunk-ZHNL2IPK.cjs.map +1 -0
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +15 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +7 -5
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +1 -0
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +6 -4
- package/dist/components/chat/remark-mention-chips.d.ts +30 -0
- package/dist/components/chat/remark-mention-chips.d.ts.map +1 -0
- package/dist/components/chat/types/api.types.d.ts +4 -0
- package/dist/components/chat/types/api.types.d.ts.map +1 -1
- package/dist/components/chat/types/component.types.d.ts +24 -0
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/chat/types/context-item.types.d.ts +5 -0
- package/dist/components/chat/types/context-item.types.d.ts.map +1 -1
- package/dist/components/chat/types/processing.types.d.ts +4 -0
- package/dist/components/chat/types/processing.types.d.ts.map +1 -1
- package/dist/components/chat/utils/chunk-parser.d.ts.map +1 -1
- package/dist/components/chat/utils/nav-anchor-props.d.ts +8 -3
- package/dist/components/chat/utils/nav-anchor-props.d.ts.map +1 -1
- package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +6 -6
- package/dist/components/contact/index.js +5 -5
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +6 -6
- package/dist/components/embeds/index.js +5 -5
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +5 -5
- package/dist/components/features/index.js +4 -4
- package/dist/components/features/paths-display.d.ts +1 -1
- package/dist/components/features/paths-display.d.ts.map +1 -1
- package/dist/components/index.cjs +178 -176
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +13 -11
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +5 -5
- package/dist/components/navigation/index.js +4 -4
- package/dist/components/onboarding-guides/index.cjs +24 -24
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +6 -6
- package/dist/components/related-content/index.js +5 -5
- package/dist/components/tickets/index.cjs +63 -63
- package/dist/components/tickets/index.js +6 -6
- package/dist/components/ui/index.cjs +7 -5
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +6 -4
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/components/ui/tag.d.ts +10 -1
- package/dist/components/ui/tag.d.ts.map +1 -1
- package/dist/index.cjs +7 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -4
- package/dist/utils/index.cjs +21 -9
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js +21 -9
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/scroll-into-view.d.ts +12 -0
- package/dist/utils/scroll-into-view.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/chat/chat-message-enhanced.tsx +71 -9
- package/src/components/chat/chat-message-list.tsx +2 -0
- package/src/components/chat/embeddable-chat.tsx +50 -6
- package/src/components/chat/hooks/use-realtime-chunk-processor.ts +1 -0
- package/src/components/chat/index.ts +1 -0
- package/src/components/chat/remark-mention-chips.ts +72 -0
- package/src/components/chat/types/api.types.ts +1 -1
- package/src/components/chat/types/component.types.ts +18 -0
- package/src/components/chat/types/context-item.types.ts +5 -0
- package/src/components/chat/types/processing.types.ts +8 -1
- package/src/components/chat/utils/chunk-parser.ts +11 -0
- package/src/components/chat/utils/nav-anchor-props.ts +22 -4
- package/src/components/chat/utils/process-historical-messages.ts +22 -0
- package/src/components/features/.paths-display.md +1 -1
- package/src/components/features/command-box.tsx +1 -1
- package/src/components/features/paths-display.tsx +13 -14
- package/src/components/ui/simple-markdown-renderer.tsx +14 -11
- package/src/components/ui/tag.tsx +12 -2
- package/src/utils/scroll-into-view.ts +51 -9
- package/dist/chunk-D6RK5YXX.cjs.map +0 -1
- package/dist/chunk-EI4WALN2.cjs.map +0 -1
- package/dist/chunk-R2KT5GDD.js.map +0 -1
- package/dist/chunk-R4CLIWAU.js.map +0 -1
- package/dist/chunk-VJ4ZWD5G.cjs.map +0 -1
- package/dist/chunk-VRSXJ5QJ.js.map +0 -1
- package/dist/chunk-Y4JNA4W6.cjs.map +0 -1
- /package/dist/{chunk-KJF7SRKH.js.map → chunk-B2U6INNO.js.map} +0 -0
- /package/dist/{chunk-4F3X2AOB.js.map → chunk-C667P6LZ.js.map} +0 -0
- /package/dist/{chunk-7NM7DEUK.js.map → chunk-CUQH4SHH.js.map} +0 -0
- /package/dist/{chunk-ZLN6SM2U.js.map → chunk-DUIWR7RQ.js.map} +0 -0
- /package/dist/{chunk-4XMYOZFO.js.map → chunk-E2YXRSDG.js.map} +0 -0
- /package/dist/{chunk-Z5QIVHJW.js.map → chunk-HTYUZXQP.js.map} +0 -0
- /package/dist/{chunk-LVOBI2M5.js.map → chunk-IXDTNQF4.js.map} +0 -0
- /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 {
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
102
|
+
className="flex items-center gap-4 p-4 border-b border-ods-border last:border-b-0"
|
|
104
103
|
>
|
|
105
|
-
<span className="
|
|
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
|
-
<
|
|
110
|
-
|
|
111
|
-
size="small-legacy"
|
|
108
|
+
<button
|
|
109
|
+
type="button"
|
|
112
110
|
onClick={() => onCopyPath(path)}
|
|
113
|
-
|
|
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
|
-
<
|
|
116
|
-
</
|
|
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
|
|
160
|
-
*
|
|
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
|
|
165
|
-
* through as literal text
|
|
166
|
-
*
|
|
167
|
-
*
|
|
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:
|
|
171
|
+
* Scope: both schemes are allowed ONLY for `href` attributes. If the LLM
|
|
170
172
|
* accidentally emits `` 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:
|
|
173
|
-
*
|
|
174
|
-
*
|
|
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://')
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
181
|
+
writeTo(computeTarget())
|
|
140
182
|
activeRaf = 0
|
|
141
183
|
if (teardownActive) {
|
|
142
184
|
teardownActive()
|