Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions packages/number-flow/src/lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import type { Plugin } from './plugins'

export { define } from './util/dom'
export { prefersReducedMotion } from './styles'
export { renderInnerHTML } from './ssr'
export { renderInnerHTML, renderFallback } from './ssr'
export * from './plugins'
export * from './formatter'

Expand Down Expand Up @@ -124,6 +124,10 @@ export default class NumberFlowLite extends ServerSafeHTMLElement implements Pro
* @internal
*/
set data(data: Data | undefined) {
// Always remove DSD template from light DOM to prevent accumulation on re-renders
// (e.g., when framework wrappers re-render with {@html renderInnerHTML()})
this.querySelector('template[shadowrootmode]')?.remove()

if (data == null) {
return
}
Expand All @@ -134,8 +138,13 @@ export default class NumberFlowLite extends ServerSafeHTMLElement implements Pro
if (!this.created) {
this._data = data

// This will overwrite the DSD if any:
this.attachShadow({ mode: 'open' })
// Reuse existing shadow root from DSD if available, otherwise create one
if (!this.shadowRoot) {
this.attachShadow({ mode: 'open' })
} else {
// Clear DSD content to rebuild with JavaScript
this.shadowRoot.innerHTML = ''
}

try {
this._internals ??= this.attachInternals()
Expand Down
12 changes: 7 additions & 5 deletions packages/number-flow/src/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ const renderPart = (part: KeyedNumberPart) =>
const renderSection = (section: KeyedNumberPart[], part: string) =>
`<span part="${part}">${section.reduce((str, p) => str + renderPart(p), '')}</span>`

export const renderFallback = (data: Data) =>
html`<span
style="font-kerning: none; display: inline-block; line-height: ${charHeight} !important; padding: ${maskHeight} 0;"
>${data.valueAsString}</span
>`

export const renderInnerHTML = (data: Data) =>
// shadowroot="open" non-standard attribute for old Chrome:
html`<template shadowroot="open" shadowrootmode="open"
><style>
${styles}</style
Expand All @@ -52,7 +57,4 @@ export const renderInnerHTML = (data: Data) =>
)}</span
>${renderSection(data.post, 'right')}</span
></template
><span
style="font-kerning: none; display: inline-block; line-height: ${charHeight} !important; padding: ${maskHeight} 0;"
>${data.valueAsString}</span
>` // ^ fallback for browsers that don't support DSD
>${renderFallback(data)}` // ^ fallback for browsers that don't support DSD
3 changes: 1 addition & 2 deletions packages/svelte/src/lib/NumberFlow.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import type { HTMLAttributes } from 'svelte/elements'
import { writable } from 'svelte/store'
import { getGroupContext } from './group.js'
import { BROWSER } from 'esm-env'

export let locales: Intl.LocalesArgument = undefined
export let format: Format | undefined = undefined
Expand Down Expand Up @@ -102,5 +101,5 @@
__svelte_digits={digits}
{data}
>
{@html BROWSER ? undefined : renderInnerHTML(data)}
{@html renderInnerHTML(data)}
</number-flow-svelte>