-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.ts
More file actions
137 lines (129 loc) · 4.21 KB
/
Copy pathindex.ts
File metadata and controls
137 lines (129 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import {
cloneElement,
createElement,
isValidElement,
type PropsWithChildren,
type ReactElement,
type ReactNode,
} from 'react';
import type { Disallow, Named, NumeralOptions, SelectOptions } from 'saykit';
import { Renderer } from '~/components/renderer.js';
import { type PropsWithJSXSafeKeys, resolveValuePropKeys } from '~/types.js';
declare function GET_SAY(): import('saykit').ReadonlySay;
/**
* Render the translation for a descriptor.
*
* @param descriptor Descriptor to render the translation for
* @returns The translation node for the descriptor
* @remark This is a macro and must be used with the relevant saykit plugin
*/
// @ts-expect-error macro
export function Say(
props: PropsWithChildren<Disallow<{ context?: string; whitespace?: boolean }, 'id'>>,
): ReactElement;
export function Say(props: { id: string; whitespace?: boolean; [match: string]: unknown }) {
if (!('id' in props))
throw new Error("'Say' is a macro and must be used with the relevant saykit plugin", {
cause: new Error("The 'id' property is required for a descriptor"),
});
const say = GET_SAY();
const { id, whitespace, ...rest } = props;
const values = resolveValuePropKeys(rest);
return createElement(Renderer, {
// The props go through still prefixed: `Say#call` does the single strip for
// every caller, so there is nowhere for it to happen twice. The id is
// merged in last, so a message free to name a value `id` still cannot
// displace the message being looked up.
html: say.call({ ...rest, id }),
whitespace,
components(tag?: string) {
if (tag && tag in values && isValidElement(values[tag])) {
const element = values[tag]! as ReactElement;
return (props) => cloneElement(element, { ...(element.props as object), ...props });
} else {
return tag;
}
},
});
}
export namespace Say {
// ===== Macros ===== //
/**
* Define a pluralised message.
*
* @example
* ```tsx
* <Say.Plural
* _={count}
* one="You have 1 item"
* other="You have # items"
* />
* ```
*
* @param props._ Number to determine the plural form of
* @param props Options pluralisation rules keyed by CLDR categories or specific numbers
* @returns The plural form of the number, as a React node
* @remark This is a macro and must be used with the relevant saykit plugin
*/
export function Plural(
props: { _: number | Named<number> } & PropsWithJSXSafeKeys<
Disallow<NumeralOptions, 'id' | 'context'>
>,
): ReactNode {
void props;
throw new Error("'Say.Plural' is a macro and must be used with the relevant saykit plugin");
}
/**
* Define an ordinal message (e.g. "1st", "2nd", "3rd").
*
* @example
* ```tsx
* <Say.Ordinal
* _={position}
* 1="#st"
* 2="#nd"
* 3="#rd"
* other="#th"
* />
* ```
*
* @param props._ Number to determine the ordinal form of
* @param props Options ordinal rules keyed by CLDR categories or specific numbers
* @returns The ordinal form of the number, as a React node
* @remark This is a macro and must be used with the relevant saykit plugin
*/
export function Ordinal(
props: { _: number | Named<number> } & PropsWithJSXSafeKeys<
Disallow<NumeralOptions, 'id' | 'context'>
>,
): ReactNode {
void props;
throw new Error("'Say.Ordinal' is a macro and must be used with the relevant saykit plugin");
}
/**
* Define a select message, useful for handling gender, status, or other categories.
*
* @example
* ```tsx
* <Say.Select
* _={gender}
* male="He"
* female="She"
* other="They"
* />
* ```
*
* @param props._ Selector value to determine which option is chosen
* @param props Options a mapping of possible selector values to message strings
* @returns The select form of the value, as a React node
* @remark This is a macro and must be used with the relevant saykit plugin
*/
export function Select(
props: { _: string | Named<string> } & PropsWithJSXSafeKeys<
Disallow<SelectOptions, 'id' | 'context'>
>,
): ReactNode {
void props;
throw new Error("'Say.Select' is a macro and must be used with the relevant saykit plugin");
}
}