Reorganize HoudiniIntl
This commit is contained in:
parent
0fe9810f1b
commit
cba2acfe55
4 changed files with 51 additions and 22 deletions
|
@ -1,11 +1,10 @@
|
||||||
// License: LGPL-3.0-or-later
|
// License: LGPL-3.0-or-later
|
||||||
import { createHoudiniIntl, FormatMoneyOptions } from "./HoudiniIntl";
|
import { createHoudiniIntl, FormatMoneyOptions } from "./";
|
||||||
import { Money } from "../../common/money";
|
import { Money } from "../../common/money";
|
||||||
const NBSP = '\xa0';
|
const NBSP = '\xa0';
|
||||||
|
|
||||||
let tests:Array<[Money, FormatMoneyOptions, string]>;
|
let tests:Array<[Money, FormatMoneyOptions, string]>;
|
||||||
|
|
||||||
|
|
||||||
describe('formatMoney', () => {
|
describe('formatMoney', () => {
|
||||||
describe('en', () => {
|
describe('en', () => {
|
||||||
const intl = createHoudiniIntl({locale: 'en'});
|
const intl = createHoudiniIntl({locale: 'en'});
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
// License: LGPL-3.0-or-later
|
// License: LGPL-3.0-or-later
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useIntl, FormatNumberOptions, IntlShape, IntlProvider, createIntl} from "react-intl";
|
import { useIntl, IntlShape, IntlProvider, createIntl} from "react-intl";
|
||||||
import { Money } from "../../common/money";
|
import { Money } from "../../common/money";
|
||||||
|
import { HoudiniIntlContext } from "../../hooks/useHoudiniIntl";
|
||||||
export declare type FormatMoneyOptions = Omit<FormatNumberOptions,'style'|'unit'|'unitDisplay'|'currency'>;
|
import type {HoudiniIntlShape, FormatMoneyOptions} from '../../hooks/useHoudiniIntl';
|
||||||
|
|
||||||
export declare type HoudiniIntlShape = IntlShape & {formatMoney:(amount:Money, opts?:FormatMoneyOptions) => string}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const HoudiniIntlContext = React.createContext<HoudiniIntlShape>(null as any);
|
|
||||||
|
|
||||||
function rawFormatMoney(intl:IntlShape, amount:Money, opts?:FormatMoneyOptions) : string {
|
function rawFormatMoney(intl:IntlShape, amount:Money, opts?:FormatMoneyOptions) : string {
|
||||||
const formatter = intl.formatters.getNumberFormat(intl.locale, {...opts,
|
const formatter = intl.formatters.getNumberFormat(intl.locale, {...opts,
|
||||||
|
@ -21,12 +16,16 @@ function rawFormatMoney(intl:IntlShape, amount:Money, opts?:FormatMoneyOptions)
|
||||||
return formatter.format(adjustedAmount);
|
return formatter.format(adjustedAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useHoudiniIntl() : HoudiniIntlShape {
|
/**
|
||||||
const context = React.useContext(HoudiniIntlContext);
|
* Use this to scope a context to a tree of components.
|
||||||
return context;
|
* Works like [IntlProvider}(https://formatjs.io/docs/react-intl/components#intlprovider)
|
||||||
}
|
* But includes support for formatting money based on the current locale.
|
||||||
|
*
|
||||||
export function HoudiniIntlProvider(props:ConstructorParameters<typeof IntlProvider>[0]) : JSX.Element {
|
* @export
|
||||||
|
* @param {ConstructorParameters<typeof IntlProvider>[0]} props
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
|
export default function HoudiniIntlProvider(props:ConstructorParameters<typeof IntlProvider>[0]) : JSX.Element {
|
||||||
return <IntlProvider {...props}>
|
return <IntlProvider {...props}>
|
||||||
<InnerProvider>
|
<InnerProvider>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -34,8 +33,7 @@ export function HoudiniIntlProvider(props:ConstructorParameters<typeof IntlProvi
|
||||||
</IntlProvider>;
|
</IntlProvider>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
function InnerProvider({children}:{children:React.ReactNode}) : JSX.Element {
|
||||||
function InnerProvider({children}:React.PropsWithChildren<{}>) : JSX.Element {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const formatMoney = React.useCallback((amount:Money, opts?:FormatMoneyOptions) => {
|
const formatMoney = React.useCallback((amount:Money, opts?:FormatMoneyOptions) => {
|
||||||
return rawFormatMoney(intl, amount, opts);
|
return rawFormatMoney(intl, amount, opts);
|
||||||
|
@ -47,9 +45,7 @@ function InnerProvider({children}:React.PropsWithChildren<{}>) : JSX.Element {
|
||||||
</HoudiniIntlContext.Provider>;
|
</HoudiniIntlContext.Provider>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function createHoudiniIntl(...props:Parameters<typeof createIntl>) : HoudiniIntlShape {
|
export function createHoudiniIntl(...props:Parameters<typeof createIntl>) : HoudiniIntlShape {
|
||||||
|
|
||||||
const intl = createIntl(...props);
|
const intl = createIntl(...props);
|
||||||
const formatMoney = (amount:Money, opts?:FormatMoneyOptions) => rawFormatMoney(intl, amount, opts);
|
const formatMoney = (amount:Money, opts?:FormatMoneyOptions) => rawFormatMoney(intl, amount, opts);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
// License: LGPL-3.0-or-later
|
// License: LGPL-3.0-or-later
|
||||||
export {useHoudiniIntl, HoudiniIntlProvider} from './HoudiniIntl';
|
import useHoudiniIntlDefault from '../../hooks/useHoudiniIntl';
|
||||||
export type {HoudiniIntlShape} from './HoudiniIntl';
|
import HoudiniIntlProviderDefault from './HoudiniIntl';
|
||||||
|
export const useHoudiniIntl = useHoudiniIntlDefault;
|
||||||
|
export const HoudiniIntlProvider = HoudiniIntlProviderDefault;
|
||||||
|
export type {HoudiniIntlShape, FormatMoneyOptions} from '../../hooks/useHoudiniIntl';
|
||||||
|
export {createHoudiniIntl} from './HoudiniIntl';
|
||||||
|
|
30
app/javascript/hooks/useHoudiniIntl.ts
Normal file
30
app/javascript/hooks/useHoudiniIntl.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// License: LGPL-3.0-or-later
|
||||||
|
import * as React from "react";
|
||||||
|
import type { FormatNumberOptions, IntlShape } from "react-intl";
|
||||||
|
import { Money } from "../common/money";
|
||||||
|
|
||||||
|
export declare type FormatMoneyOptions = Omit<FormatNumberOptions,'style'|'unit'|'unitDisplay'|'currency'>;
|
||||||
|
|
||||||
|
export declare type HoudiniIntlShape = IntlShape & {
|
||||||
|
/**
|
||||||
|
* Format a monetary value as a string given the locale
|
||||||
|
*
|
||||||
|
* @param {Money} amount the monetary value to convert to a string
|
||||||
|
* @param {FormatMoneyOptions} [opts] options for controlling how the string should be formatted
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
formatMoney(amount: Money, opts?: FormatMoneyOptions): string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HoudiniIntlContext = React.createContext<HoudiniIntlShape>(null as HoudiniIntlShape);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use just like `useIntl` for getting strings for the current locale.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @returns {HoudiniIntlShape}
|
||||||
|
*/
|
||||||
|
export default function useHoudiniIntl() : HoudiniIntlShape {
|
||||||
|
const context = React.useContext(HoudiniIntlContext);
|
||||||
|
return context;
|
||||||
|
}
|
Loading…
Reference in a new issue