Skip to content

Commit

Permalink
Merge branch 'svelte'
Browse files Browse the repository at this point in the history
  • Loading branch information
barvian committed Oct 27, 2024
2 parents 47def28 + 388e93c commit b8f36c3
Show file tree
Hide file tree
Showing 155 changed files with 2,658 additions and 1,306 deletions.
5 changes: 5 additions & 0 deletions .changeset/cuddly-numbers-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@number-flow/vue': minor
---

use lowercase event names
5 changes: 5 additions & 0 deletions .changeset/fresh-swans-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@number-flow/react': patch
---

fix animation handler types
8 changes: 8 additions & 0 deletions .changeset/fuzzy-waves-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'number-flow': patch
'@number-flow/svelte': minor
'@number-flow/react': minor
'@number-flow/vue': minor
---

Rename number-flow element to avoid conflicts between wrappers
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
"playwright": "^1.48.0",
"prettier": "^3.3.3",
"prettier-plugin-astro": "^0.14.0",
"prettier-plugin-svelte": "^3.2.7",
"prettier-plugin-tailwindcss": "^0.6.5",
"typescript": "^5.6.2"
},
"scripts": {
"build": "pnpm -r build",
"build:packages": "pnpm -r --filter=\"./packages/*\" build",
"test": "pnpm -r test --workspace-concurrency=1",
"test": "pnpm -r --workspace-concurrency=1 test",
"format": "prettier --write .",
"version": "changeset version && git add --all",
"release": "pnpm build:packages && changeset publish"
Expand Down
20 changes: 3 additions & 17 deletions packages/number-flow/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import styles, {
widthDeltaVar,
deltaVar
} from './styles'
import { BROWSER } from './util/env'
import { max } from './util/math'
export { define } from './util/dom'

export { prefersReducedMotion } from './styles'
export { render, type RenderProps } from './ssr'
Expand All @@ -43,7 +43,6 @@ export interface Props {
spinTiming: EffectTiming | undefined
opacityTiming: EffectTiming
animated: boolean
manual: boolean
respectMotionPreference: boolean
trend: RawTrend
continuous: boolean
Expand All @@ -61,31 +60,16 @@ export class NumberFlowLite extends ServerSafeHTMLElement implements Props {
spinTiming: undefined,
opacityTiming: { duration: 450, easing: 'ease-out' },
animated: true,
manual: false,
trend: true,
continuous: false,
respectMotionPreference: true
}

static define() {
if (!BROWSER) return
const RegisteredElement = customElements.get('number-flow')
if (
RegisteredElement &&
!(RegisteredElement === this || RegisteredElement.prototype instanceof this)
) {
console.error('An element has already been defined under the name `number-flow`.')
} else if (!RegisteredElement) {
customElements.define('number-flow', this)
}
}

// Kinda gross but can't do e.g. Object.assign in constructor because TypeScript
// can't determine if they're definitively assigned that way:
transformTiming = (this.constructor as typeof NumberFlowLite).defaultProps.transformTiming
spinTiming = (this.constructor as typeof NumberFlowLite).defaultProps.spinTiming
opacityTiming = (this.constructor as typeof NumberFlowLite).defaultProps.opacityTiming
manual = (this.constructor as typeof NumberFlowLite).defaultProps.manual
respectMotionPreference = (this.constructor as typeof NumberFlowLite).defaultProps
.respectMotionPreference
trend = (this.constructor as typeof NumberFlowLite).defaultProps.trend
Expand Down Expand Up @@ -124,6 +108,8 @@ export class NumberFlowLite extends ServerSafeHTMLElement implements Props {

#parts?: PartitionedParts

manual = false

set parts(parts: PartitionedParts | undefined) {
if (parts == null) {
return
Expand Down
10 changes: 10 additions & 0 deletions packages/number-flow/src/util/dom.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { BROWSER } from './env'

type ExcludeReadonly<T> = {
-readonly [K in keyof T as T[K] extends Readonly<any> ? never : K]: T[K]
}
Expand Down Expand Up @@ -32,3 +34,11 @@ export const offset = (el: HTMLElement, justify: Justify) => {
}

export const visible = (el: HTMLElement) => el.offsetWidth > 0 && el.offsetHeight > 0

// HMR-safe customElements.define
export const define = (name: string, constructor: CustomElementConstructor) => {
if (!BROWSER) return
const RegisteredElement = customElements.get(name)
if (RegisteredElement === constructor) return
return customElements.define(name, constructor)
}
35 changes: 18 additions & 17 deletions packages/react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@ import {
type PartitionedParts,
NumberFlowLite,
prefersReducedMotion,
canAnimate as _canAnimate
canAnimate as _canAnimate,
define
} from 'number-flow'
export type { Value, Format, Trend } from 'number-flow'

const isReact19 = React.version.startsWith('19.')
const REACT_MAJOR = parseInt(React.version.match(/^(\d+)\./)?.[1]!)
const isReact19 = REACT_MAJOR >= 19

// Can't wait to not have to do this in React 19:
const OBSERVED_ATTRIBUTES = ['parts'] as const
type ObservedAttribute = (typeof OBSERVED_ATTRIBUTES)[number]
export class NumberFlowElement extends NumberFlowLite {
static observedAttributes = OBSERVED_ATTRIBUTES
static observedAttributes = isReact19 ? [] : OBSERVED_ATTRIBUTES
attributeChangedCallback(attr: ObservedAttribute, _oldValue: string, newValue: string) {
this[attr] = JSON.parse(newValue)
}
}

NumberFlowElement.define()

type NonPartsProps = Omit<Props, 'manual'>
define('number-flow-react', NumberFlowElement)

type BaseProps = React.HTMLAttributes<NumberFlowElement> &
Partial<NonPartsProps> & {
Partial<Props> & {
isolate?: boolean
willChange?: boolean
onAnimationsStart?: () => void
onAnimationsFinish?: () => void
onAnimationsStart?: (e: CustomEvent<undefined>) => void
onAnimationsFinish?: (e: CustomEvent<undefined>) => void
}

type NumberFlowImplProps = BaseProps & {
Expand All @@ -51,9 +51,7 @@ const formatters: Record<string, Intl.NumberFormat> = {}
// Tiny workaround to support React 19 until it's released:
const serializeParts = isReact19 ? (p: PartitionedParts) => p : JSON.stringify

function splitProps<T extends Record<string, any>>(
props: T
): [NonPartsProps, Omit<T, keyof NonPartsProps>] {
function splitProps<T extends Record<string, any>>(props: T): [Props, Omit<T, keyof Props>] {
const {
transformTiming,
spinTiming,
Expand Down Expand Up @@ -105,14 +103,17 @@ class NumberFlowImpl extends React.Component<
)

if (prevProps?.onAnimationsStart)
this.#el.removeEventListener('animationsstart', prevProps.onAnimationsStart)
this.#el.removeEventListener('animationsstart', prevProps.onAnimationsStart as EventListener)
if (this.props.onAnimationsStart)
this.#el.addEventListener('animationsstart', this.props.onAnimationsStart)
this.#el.addEventListener('animationsstart', this.props.onAnimationsStart as EventListener)

if (prevProps?.onAnimationsFinish)
this.#el.removeEventListener('animationsfinish', prevProps.onAnimationsFinish)
this.#el.removeEventListener(
'animationsfinish',
prevProps.onAnimationsFinish as EventListener
)
if (this.props.onAnimationsFinish)
this.#el.addEventListener('animationsfinish', this.props.onAnimationsFinish)
this.#el.addEventListener('animationsfinish', this.props.onAnimationsFinish as EventListener)
}

override componentDidMount() {
Expand Down Expand Up @@ -155,7 +156,7 @@ class NumberFlowImpl extends React.Component<

return (
// @ts-expect-error missing types
<number-flow
<number-flow-react
ref={this.handleRef}
data-will-change={willChange ? '' : undefined}
// Have to rename this:
Expand Down
46 changes: 41 additions & 5 deletions packages/react/test/apps/react-18/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
'use client'

import * as React from 'react'
import NumberFlow from '@number-flow/react'
import NumberFlow, { NumberFlowElement } from '@number-flow/react'
import { flushSync } from 'react-dom'

export default function Page() {
const [value, setValue] = React.useState(123)
const [value, setValue] = React.useState(42)
const ref = React.useRef<NumberFlowElement>(null)
return (
<>
<div>
Text node
<NumberFlow value={value} />
Text node{' '}
<NumberFlow
ref={ref}
value={value}
format={{ style: 'currency', currency: 'USD' }}
locales="fr-FR"
trend="increasing"
continuous
onAnimationsStart={() => console.log('start')}
onAnimationsFinish={() => console.log('finish')}
transformTiming={{ easing: 'linear', duration: 500 }}
spinTiming={{ easing: 'linear', duration: 800 }}
opacityTiming={{ easing: 'linear', duration: 500 }}
/>
</div>
<button onClick={() => setValue(234)}>Change</button>
<button
onClick={() => {
flushSync(() => {
setValue(152)
})
ref.current?.shadowRoot?.getAnimations().forEach((a) => {
a.pause()
a.currentTime = 300
})
}}
>
Change and pause
</button>
<br />
<button
onClick={() => {
ref.current?.shadowRoot?.getAnimations().forEach((a) => {
a.play()
})
}}
>
Resume
</button>
</>
)
}
4 changes: 2 additions & 2 deletions packages/react/test/apps/react-18/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {}

export default nextConfig;
export default nextConfig
10 changes: 5 additions & 5 deletions packages/react/test/apps/react-18/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
plugins: {
tailwindcss: {}
}
}

export default config;
export default config
1 change: 1 addition & 0 deletions packages/react/test/apps/react-18/tests
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10 changes: 0 additions & 10 deletions packages/react/test/apps/react-18/tests/update.test.ts

This file was deleted.

48 changes: 24 additions & 24 deletions packages/react/test/apps/react-18/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
Loading

0 comments on commit b8f36c3

Please sign in to comment.