react-intl 6.0.6 → 6.1.1
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/index.d.ts +43 -0
- package/index.d.ts.map +1 -0
- package/index.js +51 -0
- package/lib/index.d.ts +43 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +26 -0
- package/lib/src/components/createFormattedComponent.d.ts +29 -0
- package/lib/src/components/createFormattedComponent.d.ts.map +1 -0
- package/lib/src/components/createFormattedComponent.js +62 -0
- package/lib/src/components/dateTimeRange.d.ts +11 -0
- package/lib/src/components/dateTimeRange.d.ts.map +1 -0
- package/lib/src/components/dateTimeRange.js +15 -0
- package/lib/src/components/injectIntl.d.ts +22 -0
- package/lib/src/components/injectIntl.d.ts.map +1 -0
- package/lib/src/components/injectIntl.js +29 -0
- package/lib/src/components/message.d.ts +12 -0
- package/lib/src/components/message.d.ts.map +1 -0
- package/lib/src/components/message.js +35 -0
- package/lib/src/components/plural.d.ts +15 -0
- package/lib/src/components/plural.d.ts.map +1 -0
- package/lib/src/components/plural.js +26 -0
- package/lib/src/components/provider.d.ts +35 -0
- package/lib/src/components/provider.d.ts.map +1 -0
- package/lib/src/components/provider.js +112 -0
- package/lib/src/components/relative.d.ts +12 -0
- package/lib/src/components/relative.d.ts.map +1 -0
- package/lib/src/components/relative.js +129 -0
- package/lib/src/components/useIntl.d.ts +3 -0
- package/lib/src/components/useIntl.d.ts.map +1 -0
- package/lib/src/components/useIntl.js +8 -0
- package/lib/src/types.d.ts +12 -0
- package/lib/src/types.d.ts.map +1 -0
- package/lib/src/types.js +1 -0
- package/lib/src/utils.d.ts +14 -0
- package/lib/src/utils.d.ts.map +1 -0
- package/lib/src/utils.js +43 -0
- package/package.json +10 -10
- package/react-intl.iife.js +4688 -0
- package/src/components/createFormattedComponent.d.ts +29 -0
- package/src/components/createFormattedComponent.d.ts.map +1 -0
- package/src/components/createFormattedComponent.js +69 -0
- package/src/components/dateTimeRange.d.ts +11 -0
- package/src/components/dateTimeRange.d.ts.map +1 -0
- package/src/components/dateTimeRange.js +17 -0
- package/src/components/injectIntl.d.ts +22 -0
- package/src/components/injectIntl.d.ts.map +1 -0
- package/src/components/injectIntl.js +33 -0
- package/src/components/message.d.ts +12 -0
- package/src/components/message.d.ts.map +1 -0
- package/src/components/message.js +37 -0
- package/src/components/plural.d.ts +15 -0
- package/src/components/plural.d.ts.map +1 -0
- package/src/components/plural.js +29 -0
- package/src/components/provider.d.ts +35 -0
- package/src/components/provider.d.ts.map +1 -0
- package/src/components/provider.js +116 -0
- package/src/components/relative.d.ts +12 -0
- package/src/components/relative.d.ts.map +1 -0
- package/src/components/relative.js +131 -0
- package/src/components/useIntl.d.ts +3 -0
- package/src/components/useIntl.d.ts.map +1 -0
- package/src/components/useIntl.js +12 -0
- package/src/types.d.ts +12 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js +2 -0
- package/src/utils.d.ts +14 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.js +49 -0
- package/BUILD +0 -130
- package/CHANGELOG.md +0 -1384
- package/example-sandboxes/rescripts/.rescriptsrc.js +0 -28
- package/example-sandboxes/rescripts/package-lock.json +0 -18035
- package/example-sandboxes/rescripts/package.json +0 -35
- package/example-sandboxes/rescripts/public/index.html +0 -42
- package/example-sandboxes/rescripts/src/App.tsx +0 -16
- package/example-sandboxes/rescripts/src/index.tsx +0 -5
- package/example-sandboxes/rescripts/src/react-app-env.d.ts +0 -1
- package/example-sandboxes/rescripts/src/styles.css +0 -4
- package/example-sandboxes/rescripts/tsconfig.json +0 -20
- package/example-sandboxes/strict-locale-type/.env +0 -1
- package/example-sandboxes/strict-locale-type/package-lock.json +0 -14595
- package/example-sandboxes/strict-locale-type/package.json +0 -35
- package/example-sandboxes/strict-locale-type/src/App.tsx +0 -48
- package/example-sandboxes/strict-locale-type/src/index.html +0 -28
- package/example-sandboxes/strict-locale-type/src/index.tsx +0 -7
- package/example-sandboxes/strict-locale-type/src/styles.css +0 -4
- package/example-sandboxes/strict-locale-type/tsconfig.json +0 -7
- package/example-sandboxes/strict-message-types/.env +0 -1
- package/example-sandboxes/strict-message-types/package-lock.json +0 -14596
- package/example-sandboxes/strict-message-types/package.json +0 -35
- package/example-sandboxes/strict-message-types/src/App.tsx +0 -31
- package/example-sandboxes/strict-message-types/src/index.html +0 -28
- package/example-sandboxes/strict-message-types/src/index.tsx +0 -7
- package/example-sandboxes/strict-message-types/src/styles.css +0 -4
- package/example-sandboxes/strict-message-types/tsconfig.json +0 -7
- package/examples/BUILD +0 -70
- package/examples/Bug2727.tsx +0 -37
- package/examples/HandleChange.tsx +0 -48
- package/examples/Hooks.tsx +0 -126
- package/examples/Injected.tsx +0 -41
- package/examples/Messages.tsx +0 -82
- package/examples/StaticTypeSafetyAndCodeSplitting/StaticTypeSafetyAndCodeSplitting.tsx +0 -44
- package/examples/StaticTypeSafetyAndCodeSplitting/en.json +0 -3
- package/examples/StaticTypeSafetyAndCodeSplitting/intlHelpers.tsx +0 -39
- package/examples/StaticTypeSafetyAndCodeSplitting/it.json +0 -3
- package/examples/TimeZone.tsx +0 -44
- package/examples/advanced/Advanced.tsx +0 -68
- package/examples/advanced/compiled-lang/en.json +0 -77
- package/examples/advanced/compiled-lang/fr.json +0 -77
- package/examples/index.html +0 -20
- package/examples/index.tsx +0 -44
- package/examples/package.json +0 -20
- package/index.ts +0 -127
- package/jest.config.js +0 -27
- package/src/components/createFormattedComponent.tsx +0 -123
- package/src/components/dateTimeRange.tsx +0 -26
- package/src/components/injectIntl.tsx +0 -111
- package/src/components/message.tsx +0 -73
- package/src/components/plural.tsx +0 -45
- package/src/components/provider.tsx +0 -196
- package/src/components/relative.tsx +0 -192
- package/src/components/useIntl.ts +0 -10
- package/src/types.ts +0 -29
- package/src/utils.ts +0 -77
- package/tests/functional/index.ts +0 -18
- package/tests/functional/support/build.ts +0 -16
- package/tests/functional/support/format.tsx +0 -112
- package/tests/perf/index.tsx +0 -196
- package/tests/setup.js +0 -10
- package/tests/unit/components/__snapshots__/displayName.tsx.snap +0 -19
- package/tests/unit/components/__snapshots__/message.tsx.snap +0 -41
- package/tests/unit/components/__snapshots__/relative.tsx.snap +0 -11
- package/tests/unit/components/__snapshots__/useIntl.tsx.snap +0 -25
- package/tests/unit/components/date.tsx +0 -233
- package/tests/unit/components/dateTimeRange.tsx +0 -103
- package/tests/unit/components/displayName.tsx +0 -57
- package/tests/unit/components/message.tsx +0 -509
- package/tests/unit/components/number.tsx +0 -198
- package/tests/unit/components/plural.tsx +0 -116
- package/tests/unit/components/provider.tsx +0 -215
- package/tests/unit/components/relative.tsx +0 -263
- package/tests/unit/components/time.tsx +0 -242
- package/tests/unit/components/useIntl.tsx +0 -64
- package/tests/unit/components/withIntl.tsx +0 -66
- package/tests/unit/react-intl.ts +0 -88
- package/tests/unit/testUtils.tsx +0 -42
- package/tsconfig.json +0 -5
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import hoistNonReactStatics from 'hoist-non-react-statics'
|
|
3
|
-
import {invariantIntlContext} from '../utils'
|
|
4
|
-
import {IntlShape} from '../types'
|
|
5
|
-
|
|
6
|
-
function getDisplayName(Component: React.ComponentType<any>): string {
|
|
7
|
-
return Component.displayName || Component.name || 'Component'
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// TODO: We should provide initial value here
|
|
11
|
-
const IntlContext = React.createContext<IntlShape>(null as any)
|
|
12
|
-
const {Consumer: IntlConsumer, Provider: IntlProvider} = IntlContext
|
|
13
|
-
|
|
14
|
-
export const Provider = IntlProvider
|
|
15
|
-
export const Context = IntlContext
|
|
16
|
-
|
|
17
|
-
export interface Opts<
|
|
18
|
-
IntlPropName extends string = 'intl',
|
|
19
|
-
ForwardRef extends boolean = false
|
|
20
|
-
> {
|
|
21
|
-
intlPropName?: IntlPropName
|
|
22
|
-
forwardRef?: ForwardRef
|
|
23
|
-
enforceContext?: boolean
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type WrappedComponentProps<IntlPropName extends string = 'intl'> = {
|
|
27
|
-
[k in IntlPropName]: IntlShape
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type WithIntlProps<P> = Omit<P, keyof WrappedComponentProps> & {
|
|
31
|
-
forwardedRef?: React.Ref<any>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// TODO: type hoisted static methods.
|
|
35
|
-
// Non ref forwarding overload
|
|
36
|
-
export default function injectIntl<
|
|
37
|
-
IntlPropName extends string = 'intl',
|
|
38
|
-
P extends WrappedComponentProps<IntlPropName> = WrappedComponentProps<any>
|
|
39
|
-
>(
|
|
40
|
-
WrappedComponent: React.ComponentType<P>,
|
|
41
|
-
options?: Opts<IntlPropName, false>
|
|
42
|
-
): React.FC<WithIntlProps<P>> & {
|
|
43
|
-
WrappedComponent: React.ComponentType<P>
|
|
44
|
-
}
|
|
45
|
-
// Ref forwarding overload.
|
|
46
|
-
export default function injectIntl<
|
|
47
|
-
IntlPropName extends string = 'intl',
|
|
48
|
-
P extends WrappedComponentProps<IntlPropName> = WrappedComponentProps<any>,
|
|
49
|
-
T extends React.ComponentType<P> = any
|
|
50
|
-
>(
|
|
51
|
-
WrappedComponent: React.ComponentType<P>,
|
|
52
|
-
options?: Opts<IntlPropName, true>
|
|
53
|
-
): React.ForwardRefExoticComponent<
|
|
54
|
-
React.PropsWithoutRef<WithIntlProps<React.PropsWithChildren<P>>> &
|
|
55
|
-
React.RefAttributes<T>
|
|
56
|
-
> & {
|
|
57
|
-
WrappedComponent: React.ComponentType<P>
|
|
58
|
-
}
|
|
59
|
-
export default function injectIntl<
|
|
60
|
-
IntlPropName extends string = 'intl',
|
|
61
|
-
P extends WrappedComponentProps<IntlPropName> = WrappedComponentProps<any>,
|
|
62
|
-
ForwardRef extends boolean = false,
|
|
63
|
-
T extends React.ComponentType<P> = any
|
|
64
|
-
>(
|
|
65
|
-
WrappedComponent: React.ComponentType<P>,
|
|
66
|
-
options?: Opts<IntlPropName, ForwardRef>
|
|
67
|
-
): React.ForwardRefExoticComponent<
|
|
68
|
-
React.PropsWithoutRef<WithIntlProps<P>> & React.RefAttributes<T>
|
|
69
|
-
> & {
|
|
70
|
-
WrappedComponent: React.ComponentType<P>
|
|
71
|
-
} {
|
|
72
|
-
const {
|
|
73
|
-
intlPropName = 'intl',
|
|
74
|
-
forwardRef = false,
|
|
75
|
-
enforceContext = true,
|
|
76
|
-
} = options || {}
|
|
77
|
-
|
|
78
|
-
const WithIntl: React.FC<P & {forwardedRef?: React.Ref<any>}> & {
|
|
79
|
-
WrappedComponent: React.ComponentType<P>
|
|
80
|
-
} = props => (
|
|
81
|
-
<IntlConsumer>
|
|
82
|
-
{(intl): React.ReactNode => {
|
|
83
|
-
if (enforceContext) {
|
|
84
|
-
invariantIntlContext(intl)
|
|
85
|
-
}
|
|
86
|
-
const intlProp = {[intlPropName]: intl}
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<WrappedComponent
|
|
90
|
-
{...props}
|
|
91
|
-
{...intlProp}
|
|
92
|
-
ref={forwardRef ? props.forwardedRef : null}
|
|
93
|
-
/>
|
|
94
|
-
)
|
|
95
|
-
}}
|
|
96
|
-
</IntlConsumer>
|
|
97
|
-
)
|
|
98
|
-
WithIntl.displayName = `injectIntl(${getDisplayName(WrappedComponent)})`
|
|
99
|
-
WithIntl.WrappedComponent = WrappedComponent
|
|
100
|
-
|
|
101
|
-
if (forwardRef) {
|
|
102
|
-
return hoistNonReactStatics(
|
|
103
|
-
React.forwardRef<T, P>((props: P, ref) => (
|
|
104
|
-
<WithIntl {...props} forwardedRef={ref} />
|
|
105
|
-
)),
|
|
106
|
-
WrappedComponent
|
|
107
|
-
) as any
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return hoistNonReactStatics(WithIntl, WrappedComponent) as any
|
|
111
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2015, Yahoo Inc.
|
|
3
|
-
* Copyrights licensed under the New BSD License.
|
|
4
|
-
* See the accompanying LICENSE file for terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as React from 'react'
|
|
8
|
-
import type {
|
|
9
|
-
FormatXMLElementFn,
|
|
10
|
-
Options as IntlMessageFormatOptions,
|
|
11
|
-
PrimitiveType,
|
|
12
|
-
} from 'intl-messageformat'
|
|
13
|
-
|
|
14
|
-
import {MessageDescriptor} from '@formatjs/intl'
|
|
15
|
-
import useIntl from './useIntl'
|
|
16
|
-
import {shallowEqual} from '../utils'
|
|
17
|
-
|
|
18
|
-
export interface Props<
|
|
19
|
-
V extends Record<string, any> = Record<
|
|
20
|
-
string,
|
|
21
|
-
| React.ReactNode
|
|
22
|
-
| PrimitiveType
|
|
23
|
-
| FormatXMLElementFn<React.ReactNode, React.ReactNode>
|
|
24
|
-
>
|
|
25
|
-
> extends MessageDescriptor {
|
|
26
|
-
values?: V
|
|
27
|
-
tagName?: React.ElementType<any>
|
|
28
|
-
children?(nodes: React.ReactNode[]): React.ReactElement | null
|
|
29
|
-
ignoreTag?: IntlMessageFormatOptions['ignoreTag']
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function areEqual(prevProps: Props, nextProps: Props): boolean {
|
|
33
|
-
const {values, ...otherProps} = prevProps
|
|
34
|
-
const {values: nextValues, ...nextOtherProps} = nextProps
|
|
35
|
-
return (
|
|
36
|
-
shallowEqual(nextValues, values) &&
|
|
37
|
-
shallowEqual(otherProps as any, nextOtherProps)
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function FormattedMessage(props: Props) {
|
|
42
|
-
const intl = useIntl()
|
|
43
|
-
const {formatMessage, textComponent: Text = React.Fragment} = intl
|
|
44
|
-
const {
|
|
45
|
-
id,
|
|
46
|
-
description,
|
|
47
|
-
defaultMessage,
|
|
48
|
-
values,
|
|
49
|
-
children,
|
|
50
|
-
tagName: Component = Text,
|
|
51
|
-
ignoreTag,
|
|
52
|
-
} = props
|
|
53
|
-
|
|
54
|
-
const descriptor = {id, description, defaultMessage}
|
|
55
|
-
let nodes: React.ReactNode = formatMessage(descriptor, values, {
|
|
56
|
-
ignoreTag,
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
if (typeof children === 'function') {
|
|
60
|
-
return children(Array.isArray(nodes) ? nodes : [nodes])
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (Component) {
|
|
64
|
-
return <Component>{React.Children.toArray(nodes)}</Component>
|
|
65
|
-
}
|
|
66
|
-
return <>{nodes}</>
|
|
67
|
-
}
|
|
68
|
-
FormattedMessage.displayName = 'FormattedMessage'
|
|
69
|
-
|
|
70
|
-
const MemoizedFormattedMessage = React.memo<Props>(FormattedMessage, areEqual)
|
|
71
|
-
MemoizedFormattedMessage.displayName = 'MemoizedFormattedMessage'
|
|
72
|
-
|
|
73
|
-
export default MemoizedFormattedMessage
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2015, Yahoo Inc.
|
|
3
|
-
* Copyrights licensed under the New BSD License.
|
|
4
|
-
* See the accompanying LICENSE file for terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as React from 'react'
|
|
8
|
-
import {FormatPluralOptions} from '@formatjs/intl'
|
|
9
|
-
import useIntl from './useIntl'
|
|
10
|
-
|
|
11
|
-
interface Props extends FormatPluralOptions {
|
|
12
|
-
value: number
|
|
13
|
-
other: React.ReactNode
|
|
14
|
-
zero?: React.ReactNode
|
|
15
|
-
one?: React.ReactNode
|
|
16
|
-
two?: React.ReactNode
|
|
17
|
-
few?: React.ReactNode
|
|
18
|
-
many?: React.ReactNode
|
|
19
|
-
children?(value: React.ReactNode): React.ReactElement | null
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const FormattedPlural: React.FC<Props> = props => {
|
|
23
|
-
const {formatPlural, textComponent: Text} = useIntl()
|
|
24
|
-
const {value, other, children} = props
|
|
25
|
-
|
|
26
|
-
const pluralCategory = formatPlural(value, props)
|
|
27
|
-
const formattedPlural = props[pluralCategory as 'one'] || other
|
|
28
|
-
|
|
29
|
-
if (typeof children === 'function') {
|
|
30
|
-
return children(formattedPlural)
|
|
31
|
-
}
|
|
32
|
-
if (Text) {
|
|
33
|
-
return <Text>{formattedPlural}</Text>
|
|
34
|
-
}
|
|
35
|
-
// Work around @types/react where React.FC cannot return string
|
|
36
|
-
return formattedPlural as any
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
FormattedPlural.defaultProps = {
|
|
40
|
-
type: 'cardinal',
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
FormattedPlural.displayName = 'FormattedPlural'
|
|
44
|
-
|
|
45
|
-
export default FormattedPlural
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2015, Yahoo Inc.
|
|
3
|
-
* Copyrights licensed under the New BSD License.
|
|
4
|
-
* See the accompanying LICENSE file for terms.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as React from 'react'
|
|
8
|
-
import {Provider} from './injectIntl'
|
|
9
|
-
import {
|
|
10
|
-
DEFAULT_INTL_CONFIG,
|
|
11
|
-
invariantIntlContext,
|
|
12
|
-
assignUniqueKeysToParts,
|
|
13
|
-
shallowEqual,
|
|
14
|
-
} from '../utils'
|
|
15
|
-
import type {IntlConfig, IntlShape, ResolvedIntlConfig} from '../types'
|
|
16
|
-
import {
|
|
17
|
-
formatMessage as coreFormatMessage,
|
|
18
|
-
IntlCache,
|
|
19
|
-
createIntl as coreCreateIntl,
|
|
20
|
-
CreateIntlFn,
|
|
21
|
-
createIntlCache,
|
|
22
|
-
FormatMessageFn,
|
|
23
|
-
} from '@formatjs/intl'
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
PrimitiveType,
|
|
27
|
-
FormatXMLElementFn,
|
|
28
|
-
isFormatXMLElementFn,
|
|
29
|
-
} from 'intl-messageformat'
|
|
30
|
-
|
|
31
|
-
interface State {
|
|
32
|
-
/**
|
|
33
|
-
* Explicit intl cache to prevent memory leaks
|
|
34
|
-
*/
|
|
35
|
-
cache: IntlCache
|
|
36
|
-
/**
|
|
37
|
-
* Intl object we created
|
|
38
|
-
*/
|
|
39
|
-
intl?: IntlShape
|
|
40
|
-
/**
|
|
41
|
-
* list of memoized config we care about.
|
|
42
|
-
* This is important since creating intl is
|
|
43
|
-
* very expensive
|
|
44
|
-
*/
|
|
45
|
-
prevConfig: IntlConfig
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function processIntlConfig<P extends IntlConfig = IntlConfig>(
|
|
49
|
-
config: P
|
|
50
|
-
): IntlConfig {
|
|
51
|
-
return {
|
|
52
|
-
locale: config.locale,
|
|
53
|
-
timeZone: config.timeZone,
|
|
54
|
-
fallbackOnEmptyString: config.fallbackOnEmptyString,
|
|
55
|
-
formats: config.formats,
|
|
56
|
-
textComponent: config.textComponent,
|
|
57
|
-
messages: config.messages,
|
|
58
|
-
defaultLocale: config.defaultLocale,
|
|
59
|
-
defaultFormats: config.defaultFormats,
|
|
60
|
-
onError: config.onError,
|
|
61
|
-
onWarn: config.onWarn,
|
|
62
|
-
wrapRichTextChunksInFragment: config.wrapRichTextChunksInFragment,
|
|
63
|
-
defaultRichTextElements: config.defaultRichTextElements,
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function assignUniqueKeysToFormatXMLElementFnArgument<
|
|
68
|
-
T extends Record<
|
|
69
|
-
string,
|
|
70
|
-
| PrimitiveType
|
|
71
|
-
| React.ReactNode
|
|
72
|
-
| FormatXMLElementFn<React.ReactNode, React.ReactNode>
|
|
73
|
-
> = Record<
|
|
74
|
-
string,
|
|
75
|
-
| PrimitiveType
|
|
76
|
-
| React.ReactNode
|
|
77
|
-
| FormatXMLElementFn<React.ReactNode, React.ReactNode>
|
|
78
|
-
>
|
|
79
|
-
>(values?: T): T | undefined {
|
|
80
|
-
if (!values) {
|
|
81
|
-
return values
|
|
82
|
-
}
|
|
83
|
-
return Object.keys(values).reduce((acc: T, k) => {
|
|
84
|
-
const v = values[k]
|
|
85
|
-
;(acc as any)[k] = isFormatXMLElementFn<React.ReactNode>(v)
|
|
86
|
-
? assignUniqueKeysToParts(v)
|
|
87
|
-
: v
|
|
88
|
-
return acc
|
|
89
|
-
}, {} as T)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const formatMessage: FormatMessageFn<React.ReactNode> = (
|
|
93
|
-
config,
|
|
94
|
-
formatters,
|
|
95
|
-
descriptor,
|
|
96
|
-
rawValues,
|
|
97
|
-
...rest
|
|
98
|
-
) => {
|
|
99
|
-
const values = assignUniqueKeysToFormatXMLElementFnArgument(rawValues)
|
|
100
|
-
const chunks = coreFormatMessage(
|
|
101
|
-
config,
|
|
102
|
-
formatters,
|
|
103
|
-
descriptor,
|
|
104
|
-
values as any,
|
|
105
|
-
...rest
|
|
106
|
-
)
|
|
107
|
-
if (Array.isArray(chunks)) {
|
|
108
|
-
return React.Children.toArray(chunks)
|
|
109
|
-
}
|
|
110
|
-
return chunks as any
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Create intl object
|
|
115
|
-
* @param config intl config
|
|
116
|
-
* @param cache cache for formatter instances to prevent memory leak
|
|
117
|
-
*/
|
|
118
|
-
export const createIntl: CreateIntlFn<
|
|
119
|
-
React.ReactNode,
|
|
120
|
-
IntlConfig,
|
|
121
|
-
IntlShape
|
|
122
|
-
> = (
|
|
123
|
-
{defaultRichTextElements: rawDefaultRichTextElements, ...config},
|
|
124
|
-
cache
|
|
125
|
-
) => {
|
|
126
|
-
const defaultRichTextElements = assignUniqueKeysToFormatXMLElementFnArgument(
|
|
127
|
-
rawDefaultRichTextElements
|
|
128
|
-
)
|
|
129
|
-
const coreIntl = coreCreateIntl<React.ReactNode>(
|
|
130
|
-
{
|
|
131
|
-
...DEFAULT_INTL_CONFIG,
|
|
132
|
-
...config,
|
|
133
|
-
defaultRichTextElements,
|
|
134
|
-
},
|
|
135
|
-
cache
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
const resolvedConfig: ResolvedIntlConfig = {
|
|
139
|
-
locale: coreIntl.locale,
|
|
140
|
-
timeZone: coreIntl.timeZone,
|
|
141
|
-
fallbackOnEmptyString: coreIntl.fallbackOnEmptyString,
|
|
142
|
-
formats: coreIntl.formats,
|
|
143
|
-
defaultLocale: coreIntl.defaultLocale,
|
|
144
|
-
defaultFormats: coreIntl.defaultFormats,
|
|
145
|
-
messages: coreIntl.messages,
|
|
146
|
-
onError: coreIntl.onError,
|
|
147
|
-
defaultRichTextElements,
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
...coreIntl,
|
|
152
|
-
// @ts-expect-error fix this
|
|
153
|
-
formatMessage: formatMessage.bind(
|
|
154
|
-
null,
|
|
155
|
-
resolvedConfig,
|
|
156
|
-
coreIntl.formatters
|
|
157
|
-
),
|
|
158
|
-
// @ts-expect-error fix this
|
|
159
|
-
$t: formatMessage.bind(null, resolvedConfig, coreIntl.formatters),
|
|
160
|
-
} as any
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export default class IntlProvider extends React.PureComponent<
|
|
164
|
-
// Exporting children props so it is composable with other HOCs.
|
|
165
|
-
// See: https://github.com/formatjs/formatjs/issues/1697
|
|
166
|
-
React.PropsWithChildren<IntlConfig>,
|
|
167
|
-
State
|
|
168
|
-
> {
|
|
169
|
-
static displayName = 'IntlProvider'
|
|
170
|
-
static defaultProps = DEFAULT_INTL_CONFIG
|
|
171
|
-
private cache: IntlCache = createIntlCache()
|
|
172
|
-
state: State = {
|
|
173
|
-
cache: this.cache,
|
|
174
|
-
intl: createIntl(processIntlConfig(this.props), this.cache),
|
|
175
|
-
prevConfig: processIntlConfig(this.props),
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
static getDerivedStateFromProps(
|
|
179
|
-
props: Readonly<IntlConfig>,
|
|
180
|
-
{prevConfig, cache}: State
|
|
181
|
-
): Partial<State> | null {
|
|
182
|
-
const config = processIntlConfig(props)
|
|
183
|
-
if (!shallowEqual(prevConfig, config)) {
|
|
184
|
-
return {
|
|
185
|
-
intl: createIntl(config, cache),
|
|
186
|
-
prevConfig: config,
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return null
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
render(): JSX.Element {
|
|
193
|
-
invariantIntlContext(this.state.intl)
|
|
194
|
-
return <Provider value={this.state.intl}>{this.props.children}</Provider>
|
|
195
|
-
}
|
|
196
|
-
}
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2015, Yahoo Inc.
|
|
3
|
-
* Copyrights licensed under the New BSD License.
|
|
4
|
-
* See the accompanying LICENSE file for terms.
|
|
5
|
-
*/
|
|
6
|
-
import * as React from 'react'
|
|
7
|
-
import {
|
|
8
|
-
invariant,
|
|
9
|
-
RelativeTimeFormatSingularUnit,
|
|
10
|
-
} from '@formatjs/ecma402-abstract'
|
|
11
|
-
import {FormatRelativeTimeOptions} from '@formatjs/intl'
|
|
12
|
-
import useIntl from './useIntl'
|
|
13
|
-
|
|
14
|
-
const MINUTE = 60
|
|
15
|
-
const HOUR = 60 * 60
|
|
16
|
-
const DAY = 60 * 60 * 24
|
|
17
|
-
|
|
18
|
-
function selectUnit(seconds: number): RelativeTimeFormatSingularUnit {
|
|
19
|
-
const absValue = Math.abs(seconds)
|
|
20
|
-
|
|
21
|
-
if (absValue < MINUTE) {
|
|
22
|
-
return 'second'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (absValue < HOUR) {
|
|
26
|
-
return 'minute'
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (absValue < DAY) {
|
|
30
|
-
return 'hour'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return 'day'
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function getDurationInSeconds(unit?: RelativeTimeFormatSingularUnit): number {
|
|
37
|
-
switch (unit) {
|
|
38
|
-
case 'second':
|
|
39
|
-
return 1
|
|
40
|
-
case 'minute':
|
|
41
|
-
return MINUTE
|
|
42
|
-
case 'hour':
|
|
43
|
-
return HOUR
|
|
44
|
-
default:
|
|
45
|
-
return DAY
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function valueToSeconds(
|
|
50
|
-
value?: number,
|
|
51
|
-
unit?: RelativeTimeFormatSingularUnit
|
|
52
|
-
): number {
|
|
53
|
-
if (!value) {
|
|
54
|
-
return 0
|
|
55
|
-
}
|
|
56
|
-
switch (unit) {
|
|
57
|
-
case 'second':
|
|
58
|
-
return value
|
|
59
|
-
case 'minute':
|
|
60
|
-
return value * MINUTE
|
|
61
|
-
default:
|
|
62
|
-
return value * HOUR
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface Props extends FormatRelativeTimeOptions {
|
|
67
|
-
value?: number
|
|
68
|
-
unit?: RelativeTimeFormatSingularUnit
|
|
69
|
-
updateIntervalInSeconds?: number
|
|
70
|
-
children?(value: string): React.ReactElement | null
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const INCREMENTABLE_UNITS: RelativeTimeFormatSingularUnit[] = [
|
|
74
|
-
'second',
|
|
75
|
-
'minute',
|
|
76
|
-
'hour',
|
|
77
|
-
]
|
|
78
|
-
function canIncrement(
|
|
79
|
-
unit: RelativeTimeFormatSingularUnit = 'second'
|
|
80
|
-
): boolean {
|
|
81
|
-
return INCREMENTABLE_UNITS.indexOf(unit) > -1
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const SimpleFormattedRelativeTime: React.FC<
|
|
85
|
-
Omit<Props, 'updateIntervalInSeconds'>
|
|
86
|
-
> = props => {
|
|
87
|
-
const {formatRelativeTime, textComponent: Text} = useIntl()
|
|
88
|
-
const {children, value, unit, ...otherProps} = props
|
|
89
|
-
|
|
90
|
-
const formattedRelativeTime = formatRelativeTime(value || 0, unit, otherProps)
|
|
91
|
-
|
|
92
|
-
if (typeof children === 'function') {
|
|
93
|
-
return children(formattedRelativeTime)
|
|
94
|
-
}
|
|
95
|
-
if (Text) {
|
|
96
|
-
return <Text>{formattedRelativeTime}</Text>
|
|
97
|
-
}
|
|
98
|
-
return <>{formattedRelativeTime}</>
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const FormattedRelativeTime: React.FC<Props> = ({
|
|
102
|
-
value,
|
|
103
|
-
unit,
|
|
104
|
-
updateIntervalInSeconds,
|
|
105
|
-
...otherProps
|
|
106
|
-
}) => {
|
|
107
|
-
invariant(
|
|
108
|
-
!updateIntervalInSeconds ||
|
|
109
|
-
!!(updateIntervalInSeconds && canIncrement(unit)),
|
|
110
|
-
'Cannot schedule update with unit longer than hour'
|
|
111
|
-
)
|
|
112
|
-
const [prevUnit, setPrevUnit] = React.useState<
|
|
113
|
-
RelativeTimeFormatSingularUnit | undefined
|
|
114
|
-
>()
|
|
115
|
-
const [prevValue, setPrevValue] = React.useState<number>(0)
|
|
116
|
-
const [currentValueInSeconds, setCurrentValueInSeconds] =
|
|
117
|
-
React.useState<number>(0)
|
|
118
|
-
let updateTimer: number
|
|
119
|
-
|
|
120
|
-
if (unit !== prevUnit || value !== prevValue) {
|
|
121
|
-
setPrevValue(value || 0)
|
|
122
|
-
setPrevUnit(unit)
|
|
123
|
-
setCurrentValueInSeconds(
|
|
124
|
-
canIncrement(unit) ? valueToSeconds(value, unit) : 0
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
React.useEffect(() => {
|
|
129
|
-
function clearUpdateTimer() {
|
|
130
|
-
clearTimeout(updateTimer)
|
|
131
|
-
}
|
|
132
|
-
clearUpdateTimer()
|
|
133
|
-
// If there's no interval and we cannot increment this unit, do nothing
|
|
134
|
-
if (!updateIntervalInSeconds || !canIncrement(unit)) {
|
|
135
|
-
return clearUpdateTimer
|
|
136
|
-
}
|
|
137
|
-
// Figure out the next interesting time
|
|
138
|
-
const nextValueInSeconds = currentValueInSeconds - updateIntervalInSeconds
|
|
139
|
-
const nextUnit = selectUnit(nextValueInSeconds)
|
|
140
|
-
// We've reached the max auto incrementable unit, don't schedule another update
|
|
141
|
-
if (nextUnit === 'day') {
|
|
142
|
-
return clearUpdateTimer
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const unitDuration = getDurationInSeconds(nextUnit)
|
|
146
|
-
const remainder = nextValueInSeconds % unitDuration
|
|
147
|
-
const prevInterestingValueInSeconds = nextValueInSeconds - remainder
|
|
148
|
-
const nextInterestingValueInSeconds =
|
|
149
|
-
prevInterestingValueInSeconds >= currentValueInSeconds
|
|
150
|
-
? prevInterestingValueInSeconds - unitDuration
|
|
151
|
-
: prevInterestingValueInSeconds
|
|
152
|
-
const delayInSeconds = Math.abs(
|
|
153
|
-
nextInterestingValueInSeconds - currentValueInSeconds
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
if (currentValueInSeconds !== nextInterestingValueInSeconds) {
|
|
157
|
-
updateTimer = setTimeout(
|
|
158
|
-
() => setCurrentValueInSeconds(nextInterestingValueInSeconds),
|
|
159
|
-
delayInSeconds * 1e3
|
|
160
|
-
) as unknown as number
|
|
161
|
-
}
|
|
162
|
-
return clearUpdateTimer
|
|
163
|
-
}, [currentValueInSeconds, updateIntervalInSeconds, unit])
|
|
164
|
-
|
|
165
|
-
let currentValue = value || 0
|
|
166
|
-
let currentUnit = unit
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
canIncrement(unit) &&
|
|
170
|
-
typeof currentValueInSeconds === 'number' &&
|
|
171
|
-
updateIntervalInSeconds
|
|
172
|
-
) {
|
|
173
|
-
currentUnit = selectUnit(currentValueInSeconds)
|
|
174
|
-
const unitDuration = getDurationInSeconds(currentUnit)
|
|
175
|
-
currentValue = Math.round(currentValueInSeconds / unitDuration)
|
|
176
|
-
}
|
|
177
|
-
return (
|
|
178
|
-
<SimpleFormattedRelativeTime
|
|
179
|
-
value={currentValue}
|
|
180
|
-
unit={currentUnit}
|
|
181
|
-
{...otherProps}
|
|
182
|
-
/>
|
|
183
|
-
)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
FormattedRelativeTime.displayName = 'FormattedRelativeTime'
|
|
187
|
-
FormattedRelativeTime.defaultProps = {
|
|
188
|
-
value: 0,
|
|
189
|
-
unit: 'second',
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export default FormattedRelativeTime
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import {Context} from './injectIntl'
|
|
3
|
-
import {invariantIntlContext} from '../utils'
|
|
4
|
-
import {IntlShape} from '../types'
|
|
5
|
-
|
|
6
|
-
export default function useIntl(): IntlShape {
|
|
7
|
-
const intl = React.useContext(Context)
|
|
8
|
-
invariantIntlContext(intl)
|
|
9
|
-
return intl
|
|
10
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2015, Yahoo Inc.
|
|
3
|
-
* Copyrights licensed under the New BSD License.
|
|
4
|
-
* See the accompanying LICENSE file for terms.
|
|
5
|
-
*/
|
|
6
|
-
import * as React from 'react'
|
|
7
|
-
import {
|
|
8
|
-
ResolvedIntlConfig as CoreResolvedIntlConfig,
|
|
9
|
-
IntlFormatters,
|
|
10
|
-
Formatters,
|
|
11
|
-
} from '@formatjs/intl'
|
|
12
|
-
import {DEFAULT_INTL_CONFIG} from './utils'
|
|
13
|
-
export type IntlConfig = Omit<
|
|
14
|
-
ResolvedIntlConfig,
|
|
15
|
-
keyof typeof DEFAULT_INTL_CONFIG
|
|
16
|
-
> &
|
|
17
|
-
Partial<typeof DEFAULT_INTL_CONFIG>
|
|
18
|
-
|
|
19
|
-
export interface ResolvedIntlConfig
|
|
20
|
-
extends CoreResolvedIntlConfig<React.ReactNode> {
|
|
21
|
-
textComponent?: React.ComponentType | keyof React.ReactHTML
|
|
22
|
-
wrapRichTextChunksInFragment?: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface IntlShape
|
|
26
|
-
extends ResolvedIntlConfig,
|
|
27
|
-
IntlFormatters<React.ReactNode> {
|
|
28
|
-
formatters: Formatters
|
|
29
|
-
}
|