@kanso-labs/react-native-kanso-ui 0.0.0-stage → 0.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.
Files changed (145) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +205 -2
  3. package/dist/button/index.d.ts +56 -0
  4. package/dist/button/index.js +169 -0
  5. package/dist/button/index.js.map +1 -0
  6. package/dist/button/palettes.js +47 -0
  7. package/dist/button/palettes.js.map +1 -0
  8. package/dist/chip/index.js +194 -0
  9. package/dist/chip/index.js.map +1 -0
  10. package/dist/chip/styles.js +36 -0
  11. package/dist/chip/styles.js.map +1 -0
  12. package/dist/clipboard/index.js +58 -0
  13. package/dist/clipboard/index.js.map +1 -0
  14. package/dist/components/avatar/index.d.ts +82 -0
  15. package/dist/components/avatar/index.js +62 -0
  16. package/dist/components/avatar/index.js.map +1 -0
  17. package/dist/components/button/index.d.ts +87 -0
  18. package/dist/components/button/index.js +377 -0
  19. package/dist/components/button/index.js.map +1 -0
  20. package/dist/components/card/index.d.ts +78 -0
  21. package/dist/components/card/index.js +315 -0
  22. package/dist/components/card/index.js.map +1 -0
  23. package/dist/components/checkbox/index.d.ts +76 -0
  24. package/dist/components/checkbox/index.js +360 -0
  25. package/dist/components/checkbox/index.js.map +1 -0
  26. package/dist/components/chip/index.d.ts +84 -0
  27. package/dist/components/chip/index.js +257 -0
  28. package/dist/components/chip/index.js.map +1 -0
  29. package/dist/components/chip-group/index.d.ts +143 -0
  30. package/dist/components/chip-group/index.js +669 -0
  31. package/dist/components/chip-group/index.js.map +1 -0
  32. package/dist/components/copy-field/index.d.ts +60 -0
  33. package/dist/components/copy-field/index.js +277 -0
  34. package/dist/components/copy-field/index.js.map +1 -0
  35. package/dist/components/currency/index.d.ts +69 -0
  36. package/dist/components/currency/index.js +162 -0
  37. package/dist/components/currency/index.js.map +1 -0
  38. package/dist/components/form/index.d.ts +84 -0
  39. package/dist/components/form/index.js +95 -0
  40. package/dist/components/form/index.js.map +1 -0
  41. package/dist/components/icon-button/index.d.ts +68 -0
  42. package/dist/components/icon-button/index.js +289 -0
  43. package/dist/components/icon-button/index.js.map +1 -0
  44. package/dist/components/link/index.d.ts +59 -0
  45. package/dist/components/link/index.js +191 -0
  46. package/dist/components/link/index.js.map +1 -0
  47. package/dist/components/number-field/index.d.ts +151 -0
  48. package/dist/components/number-field/index.js +832 -0
  49. package/dist/components/number-field/index.js.map +1 -0
  50. package/dist/components/product-icon/index.d.ts +70 -0
  51. package/dist/components/product-icon/index.js +60 -0
  52. package/dist/components/product-icon/index.js.map +1 -0
  53. package/dist/components/radio-group/index.d.ts +105 -0
  54. package/dist/components/radio-group/index.js +597 -0
  55. package/dist/components/radio-group/index.js.map +1 -0
  56. package/dist/components/search-field/index.d.ts +98 -0
  57. package/dist/components/search-field/index.js +521 -0
  58. package/dist/components/search-field/index.js.map +1 -0
  59. package/dist/components/segmented-button/index.d.ts +113 -0
  60. package/dist/components/segmented-button/index.js +937 -0
  61. package/dist/components/segmented-button/index.js.map +1 -0
  62. package/dist/components/separator/index.d.ts +45 -0
  63. package/dist/components/separator/index.js +109 -0
  64. package/dist/components/separator/index.js.map +1 -0
  65. package/dist/components/stack/index.d.ts +70 -0
  66. package/dist/components/stack/index.js +107 -0
  67. package/dist/components/stack/index.js.map +1 -0
  68. package/dist/components/switch/index.d.ts +76 -0
  69. package/dist/components/switch/index.js +591 -0
  70. package/dist/components/switch/index.js.map +1 -0
  71. package/dist/components/text/index.d.ts +44 -0
  72. package/dist/components/text/index.js +78 -0
  73. package/dist/components/text/index.js.map +1 -0
  74. package/dist/components/text-field/index.d.ts +146 -0
  75. package/dist/components/text-field/index.js +228 -0
  76. package/dist/components/text-field/index.js.map +1 -0
  77. package/dist/control/index.js +117 -0
  78. package/dist/control/index.js.map +1 -0
  79. package/dist/control/styles.js +36 -0
  80. package/dist/control/styles.js.map +1 -0
  81. package/dist/field/index.d.ts +13 -0
  82. package/dist/field/index.js +1007 -0
  83. package/dist/field/index.js.map +1 -0
  84. package/dist/field/styles.js +131 -0
  85. package/dist/field/styles.js.map +1 -0
  86. package/dist/form/index.d.ts +24 -0
  87. package/dist/form/index.js +209 -0
  88. package/dist/form/index.js.map +1 -0
  89. package/dist/glyphs/icon-style.d.ts +25 -0
  90. package/dist/glyphs/icon-style.js +22 -0
  91. package/dist/glyphs/icon-style.js.map +1 -0
  92. package/dist/glyphs/index.js +170 -0
  93. package/dist/glyphs/index.js.map +1 -0
  94. package/dist/glyphs/styles.js +7 -0
  95. package/dist/glyphs/styles.js.map +1 -0
  96. package/dist/hooks/useWindowSizeClass.d.ts +25 -0
  97. package/dist/hooks/useWindowSizeClass.js +39 -0
  98. package/dist/hooks/useWindowSizeClass.js.map +1 -0
  99. package/dist/index.d.ts +31 -0
  100. package/dist/index.js +27 -0
  101. package/dist/mark/image.js +61 -0
  102. package/dist/mark/image.js.map +1 -0
  103. package/dist/mark/index.d.ts +9 -0
  104. package/dist/mark/index.js +234 -0
  105. package/dist/mark/index.js.map +1 -0
  106. package/dist/mark/initials.js +65 -0
  107. package/dist/mark/initials.js.map +1 -0
  108. package/dist/mark/styles.d.ts +1 -0
  109. package/dist/mark/styles.js +73 -0
  110. package/dist/mark/styles.js.map +1 -0
  111. package/dist/number/parser.js +321 -0
  112. package/dist/number/parser.js.map +1 -0
  113. package/dist/number/state.js +235 -0
  114. package/dist/number/state.js.map +1 -0
  115. package/dist/overlay/host.js +111 -0
  116. package/dist/overlay/host.js.map +1 -0
  117. package/dist/press/index.js +350 -0
  118. package/dist/press/index.js.map +1 -0
  119. package/dist/press/styles.js +31 -0
  120. package/dist/press/styles.js.map +1 -0
  121. package/dist/router/index.d.ts +28 -0
  122. package/dist/router/index.js +82 -0
  123. package/dist/router/index.js.map +1 -0
  124. package/dist/theme/color.js +25 -0
  125. package/dist/theme/color.js.map +1 -0
  126. package/dist/theme/resolve.d.ts +6 -0
  127. package/dist/theme/resolve.js +310 -0
  128. package/dist/theme/resolve.js.map +1 -0
  129. package/dist/theme/scope.d.ts +42 -0
  130. package/dist/theme/scope.js +80 -0
  131. package/dist/theme/scope.js.map +1 -0
  132. package/dist/theme/styles.js +39 -0
  133. package/dist/theme/styles.js.map +1 -0
  134. package/dist/theme-scope.d.ts +56 -0
  135. package/dist/theme-scope.js +127 -0
  136. package/dist/theme-scope.js.map +1 -0
  137. package/dist/tokens/defaults.d.ts +407 -0
  138. package/dist/tokens/defaults.js +403 -0
  139. package/dist/tokens/defaults.js.map +1 -0
  140. package/dist/typography/fonts.js +84 -0
  141. package/dist/typography/fonts.js.map +1 -0
  142. package/dist/typography/roles.d.ts +10 -0
  143. package/dist/typography/roles.js +82 -0
  144. package/dist/typography/roles.js.map +1 -0
  145. package/package.json +132 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Ref","ImageProps","ImageSourcePropType","ImageStyle","StyleProp","TextStyle","ViewProps","ViewStyle","Image","Text","NativeText","View","ResolvedTheme","MarkSize","MarkTone","PersonGlyph","useTheme","composeStyles","useTypeRole","useImageLoadingStatus","initialOfThing","initialsOfPerson","DIAMETERS","GLYPH_SHARE","initialsStylesOf","markStyles","markStylesOf","MarkImageProps","Pick","MarkProps","Omit","decorative","imgProps","kind","KINDS","name","ref","showPersonIcon","size","src","style","tone","person","initials","resizeMode","shape","tintsFallback","thing","const","CONTENT","Readonly","Record","negative","positive","primary","secondary","tertiary","Mark","t0","$","_c","props","t1","t2","undefined","theme","label","handlersFor","previous","status","T0","initialsNode","t3","t4","t5","t6","t7","t8","own","text","t9","fallback","named","trim","showsPicture","t10","colors","initialsText","base","sourceOf","image","imagePending","t11","uri","_c","NativeText"],"sources":["../../src/mark/index.tsx"],"sourcesContent":["import type { Ref } from 'react'\nimport type {\n ImageProps,\n ImageSourcePropType,\n ImageStyle,\n StyleProp,\n TextStyle,\n ViewProps,\n ViewStyle,\n} from 'react-native'\n\nimport { Image, Text as NativeText, View } from 'react-native'\n\nimport type { ResolvedTheme } from '../theme/scope'\nimport type { MarkSize, MarkTone } from './styles'\n\nimport { PersonGlyph } from '../glyphs'\nimport { useTheme } from '../theme/scope'\nimport { composeStyles } from '../theme/styles'\nimport { useTypeRole } from '../typography/roles'\nimport { useImageLoadingStatus } from './image'\nimport { initialOfThing, initialsOfPerson } from './initials'\nimport {\n DIAMETERS,\n GLYPH_SHARE,\n initialsStylesOf,\n markStyles,\n markStylesOf,\n} from './styles'\n\n/** The native props a picture's own `Image` takes, as Avatar and ProductIcon take them. */\ntype MarkImageProps = Pick<\n ImageProps,\n | 'crossOrigin'\n | 'fadeDuration'\n | 'progressiveRenderingEnabled'\n | 'referrerPolicy'\n | 'resizeMethod'\n>\n\ntype MarkProps = Omit<ViewProps, 'children' | 'style'> & {\n /**\n * Hides the mark from screen readers, for one beside the name it stands\n * for, which would otherwise be announced twice.\n */\n readonly decorative?: boolean\n /** Props for the picture's own `Image`. */\n readonly imgProps?: MarkImageProps\n /** A person, which Avatar draws, or anything else, which ProductIcon does. */\n readonly kind: keyof typeof KINDS\n /** Supplies the fallback's initials, and the accessible name unless decorative. */\n readonly name: string\n readonly ref?: Ref<View>\n /**\n * Whether a person with no initials to take, a blank name, draws the\n * anonymous person, or an empty disc, as a loading skeleton wants.\n */\n readonly showPersonIcon?: boolean\n readonly size: MarkSize\n /** A picture to show in place of the initials once it has loaded. */\n readonly src?: string\n readonly style?: StyleProp<ViewStyle>\n readonly tone: MarkTone\n}\n\n// What each kind of mark is drawn as. The header of `./styles` says why the\n// two differ where they do; everything not in this table is the same for\n// both.\nconst KINDS = {\n person: {\n initials: initialsOfPerson,\n resizeMode: 'cover',\n shape: 'circle',\n tintsFallback: false,\n },\n thing: {\n initials: initialOfThing,\n resizeMode: 'contain',\n shape: 'square',\n tintsFallback: true,\n },\n} as const\n\n// The role each tone draws the anonymous person in.\nconst CONTENT: Readonly<Record<MarkTone, keyof ResolvedTheme['colors']>> = {\n negative: 'onNegativeContainer',\n positive: 'onPositiveContainer',\n primary: 'onPrimaryContainer',\n secondary: 'onSecondaryContainer',\n tertiary: 'onTertiaryContainer',\n}\n\n/**\n * The small identity mark Avatar and ProductIcon both render: a picture once\n * it has loaded, initials until then or if it fails, named for whoever or\n * whatever it stands for. Shared rather than written into each, so a fix to\n * one reaches both, as on web. Not a component of the library's own, and not\n * exported from the package.\n */\nfunction Mark({\n decorative = false,\n imgProps,\n kind,\n name,\n showPersonIcon = true,\n size,\n src,\n style,\n tone,\n ...props\n}: MarkProps) {\n const { initials, resizeMode, shape, tintsFallback } = KINDS[kind]\n const theme = useTheme()\n const label = useTypeRole('labelLarge')\n const { handlersFor, previous, status } = useImageLoadingStatus(src)\n\n const own = markStylesOf(theme)\n const text = initialsStylesOf(theme)\n const fallback = initials(name)\n\n // Announced as an image named for whoever or whatever it stands for,\n // rather than letting the initials be read: \"AL\" is not what anyone means\n // to announce. A blank name names nothing, so the mark is then a plain\n // view, which a screen reader passes over rather than reading as an image\n // with no name. A decorative mark is hidden outright, its initials with it.\n const named = !decorative && name.trim() !== ''\n\n // The initials while no picture shows: before the first loads, and once\n // one fails. They are left out under a picture rather than kept beneath\n // it, since a letterboxed logo would show them through its transparent\n // parts.\n const showsPicture = status === 'loaded' || previous !== undefined\n let initialsNode = null\n if (!showsPicture && kind === 'person' && fallback === '') {\n // A person with no initials to take, a blank name or one still loading,\n // draws Material Design's anonymous person in the tone's on-container\n // colour. The glyph hides itself from screen readers.\n initialsNode = showPersonIcon ? (\n <PersonGlyph\n color={theme.colors[CONTENT[tone]]}\n size={DIAMETERS[size] * GLYPH_SHARE}\n />\n ) : null\n } else if (!showsPicture) {\n // The initials keep their size whatever the device's text size asks\n // for: the mark is a fixed size and clips what runs past it, and the\n // name a screen reader reads is what they stand for.\n const initialsText = (\n <NativeText\n allowFontScaling={false}\n style={composeStyles<TextStyle>(label, text[size], text[tone])}\n >\n {fallback}\n </NativeText>\n )\n initialsNode = tintsFallback ? (\n <View style={composeStyles<ViewStyle>(markStyles.fallback, own[tone])}>\n {initialsText}\n </View>\n ) : (\n initialsText\n )\n }\n\n return (\n <View\n accessible={named ? true : undefined}\n aria-hidden={decorative ? true : undefined}\n aria-label={named ? name : undefined}\n role={named ? 'img' : undefined}\n {...props}\n style={composeStyles<ViewStyle>(\n own.base,\n own[shape],\n markStyles[size],\n tintsFallback ? undefined : own[tone],\n style,\n )}\n >\n {initialsNode}\n {/* Two pictures at most, laid over the initials. The one last loaded\n stays while a new `src` loads, and the new one is drawn on top of\n it from the start, hidden until it has loaded. Neither is inverted\n by the iOS Smart Invert setting, which is meant for interface\n colours rather than pictures. */}\n {previous === undefined ? null : (\n <Image\n accessibilityIgnoresInvertColors\n key={previous}\n resizeMode={resizeMode}\n source={sourceOf(previous)}\n style={markStyles.image}\n />\n )}\n {src === undefined || status === 'error' ? null : (\n <Image\n accessibilityIgnoresInvertColors\n key={src}\n {...imgProps}\n {...handlersFor(src)}\n resizeMode={resizeMode}\n source={sourceOf(src)}\n style={composeStyles<ImageStyle>(\n markStyles.image,\n status === 'loaded' ? undefined : markStyles.imagePending,\n )}\n />\n )}\n </View>\n )\n}\n\n// An address as the source `Image` takes. The compiler keeps the one it made\n// for as long as the address is the same, so a re-render hands the image the\n// object it already had.\nfunction sourceOf(uri: string): ImageSourcePropType {\n return { uri }\n}\n\nexport type { MarkImageProps, MarkProps }\n\nexport { Mark }\n"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ //#region src/mark/initials.ts
2
+ const INITIAL = /^[\p{L}\p{N}\p{Extended_Pictographic}\p{Regional_Indicator}]/u;
3
+ const JOINING = /^[\p{Script=Arabic}\p{Script=Syriac}\p{Script=Mongolian}\p{Script=Nko}\p{Script=Adlam}\p{Script=Mandaic}\p{Script=Manichaean}\p{Script=Psalter_Pahlavi}\p{Script=Hanifi_Rohingya}\p{Script=Sogdian}\p{Script=Old_Uyghur}]/u;
4
+ const ZERO_WIDTH_NON_JOINER = "‌";
5
+ const TITLE = /^\p{L}{2,4}\.$/u;
6
+ const SUFFIX = /^(?:jr|sr|ii|iii|iv|\d+(?:st|nd|rd|th))\.?,?$/iu;
7
+ const TRAILING_ASIDE = /\s*[([{][^)\]}]*[)\]}]\s*$/u;
8
+ const GRAPHEME = /\p{Regional_Indicator}{2}|\P{M}(?:[\u094D\u09CD\u0ACD\u0B4D\u0C4D\u0D4D]\u200D?\p{L}|[\p{M}\p{Emoji_Modifier}]|\u200D\P{M})*/gu;
9
+ const segmenters = /* @__PURE__ */ new Map();
10
+ function graphemesOf(text, locale) {
11
+ if (typeof Intl.Segmenter !== "function") return text.match(GRAPHEME) ?? [];
12
+ const key = locale ?? "";
13
+ let segmenter = segmenters.get(key);
14
+ if (segmenter === void 0) {
15
+ segmenter = new Intl.Segmenter(locale, { granularity: "grapheme" });
16
+ segmenters.set(key, segmenter);
17
+ }
18
+ return Array.from(segmenter.segment(text), ({ segment }) => segment);
19
+ }
20
+ /**
21
+ * The character that stands for `word`: its first grapheme that is a letter,
22
+ * a number or a picture, or its first grapheme where it has none of those,
23
+ * so something always shows. Upper-cased in the locale, and then one
24
+ * grapheme of that, since upper-casing can lengthen it: "ß" is "SS".
25
+ */
26
+ function initialOf(word, locale) {
27
+ const graphemes = graphemesOf(word, locale);
28
+ return graphemesOf((graphemes.find((grapheme) => INITIAL.test(grapheme)) ?? graphemes.at(0) ?? "").toLocaleUpperCase(locale), locale).at(0) ?? "";
29
+ }
30
+ /**
31
+ * One letter, where a person takes two. A person has a first name and a last
32
+ * name to initialise; a thing usually has neither, so the same rule applied
33
+ * to "Second item" would produce "SI", a pair of initials for something that
34
+ * was never two words in that sense.
35
+ *
36
+ * `locale` is the device's when left out, which is what a product icon
37
+ * passes.
38
+ */
39
+ function initialOfThing(name, locale) {
40
+ return initialOf(name.trim(), locale);
41
+ }
42
+ /**
43
+ * The initials of the first and the last word, which handles both "Ada" and
44
+ * "Ada Lovelace" without a separate prop for how many to take. What a
45
+ * display name carries around the name itself is left out first: a title
46
+ * before it, a generational suffix after it, and an aside in brackets at its
47
+ * end. A name written without spaces between its words — Japanese, Chinese —
48
+ * is one word to this, and takes one initial.
49
+ *
50
+ * `locale` is the device's when left out, which is what an avatar passes.
51
+ */
52
+ function initialsOfPerson(name, locale) {
53
+ let words = name.replace(TRAILING_ASIDE, "").split(/\s+/u).filter(Boolean);
54
+ if (words.length > 1 && TITLE.test(words[0] ?? "")) words = words.slice(1);
55
+ if (words.length > 1 && SUFFIX.test(words.at(-1) ?? "")) words = words.slice(0, -1);
56
+ if (words.length === 0) return "";
57
+ const first = initialOf(words[0] ?? "", locale);
58
+ if (words.length === 1) return first;
59
+ const last = initialOf(words.at(-1) ?? "", locale);
60
+ return `${first}${JOINING.test(first) && JOINING.test(last) ? ZERO_WIDTH_NON_JOINER : ""}${last}`;
61
+ }
62
+ //#endregion
63
+ export { initialOfThing, initialsOfPerson };
64
+
65
+ //# sourceMappingURL=initials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initials.js","names":["INITIAL","JOINING","ZERO_WIDTH_NON_JOINER","TITLE","SUFFIX","TRAILING_ASIDE","GRAPHEME","segmenters","Map","Intl","Segmenter","graphemesOf","text","locale","match","key","segmenter","get","undefined","granularity","set","Array","from","segment","initialOf","word","graphemes","chosen","find","grapheme","test","at","toLocaleUpperCase","initialOfThing","name","trim","initialsOfPerson","words","replace","split","filter","Boolean","length","slice","first","last","between"],"sources":["../../src/mark/initials.ts"],"sourcesContent":["// What a mark shows while it has no picture: the initials of a person's\n// name, or the initial of a thing's. Copied from kanso-ui's\n// `src/mark/initials.ts` rather than shared through a package, so the two\n// read a name the same way and each can be read without the other.\n//\n// It works in graphemes, what a reader sees as one character, in the\n// device's locale. A code point drops an accent written as a combining mark,\n// splits an Indic conjunct and cuts a flag or a joined emoji in half;\n// upper-casing without the locale turns a Turkish \"i\" into \"I\" rather than\n// \"İ\".\n//\n// Graphemes come from `Intl.Segmenter` where the engine has it, as browsers\n// and Node do. Hermes's Intl has no Segmenter, only a collator and the date\n// and number formats, so on a device `GRAPHEME` stands in: a\n// character with the marks and emoji modifiers after it, a pair of regional\n// indicators as one flag, a sequence joined by a zero-width joiner, and the\n// consonants Unicode joins through a virama into one conjunct. It has no rule\n// for the rest of Unicode's, so it splits a Hangul syllable written as\n// separate jamo, which a name typed on a phone is not.\n\n// What a word's initial can be: a letter, a number, or a picture — an emoji,\n// or a flag, which is a pair of regional indicators. A word opening with\n// anything else — a bracket, a quote, the @ of a handle, the # of a channel\n// — is initialised by the first of these inside it.\nconst INITIAL = /^[\\p{L}\\p{N}\\p{Extended_Pictographic}\\p{Regional_Indicator}]/u\n\n// The scripts whose letters join to the next one. Two initials in one of\n// them, written side by side, shape into a single connected word rather than\n// two letters, so a zero-width non-joiner goes between them.\nconst JOINING =\n /^[\\p{Script=Arabic}\\p{Script=Syriac}\\p{Script=Mongolian}\\p{Script=Nko}\\p{Script=Adlam}\\p{Script=Mandaic}\\p{Script=Manichaean}\\p{Script=Psalter_Pahlavi}\\p{Script=Hanifi_Rohingya}\\p{Script=Sogdian}\\p{Script=Old_Uyghur}]/u\n\nconst ZERO_WIDTH_NON_JOINER = '\\u200C'\n\n// A title before a name — \"Dr.\", \"Mrs.\", \"Prof.\" — which is not one of its\n// words. Two letters at least, so a first initial written \"J.\" is kept.\nconst TITLE = /^\\p{L}{2,4}\\.$/u\n\n// A generational suffix after a name — \"Jr.\", \"Sr\", \"III\", \"3rd\" — which is\n// not its last word either. The numerals are the generational ones only, so\n// a surname that reads as a numeral, \"Xi\" say, is kept.\nconst SUFFIX = /^(?:jr|sr|ii|iii|iv|\\d+(?:st|nd|rd|th))\\.?,?$/iu\n\n// Something said about the name rather than part of it, in brackets at its\n// end: \"(she/her)\", \"[away]\".\nconst TRAILING_ASIDE = /\\s*[([{][^)\\]}]*[)\\]}]\\s*$/u\n\n// One grapheme, where the engine has no `Intl.Segmenter`: a flag, or a\n// character followed by what attaches to it. The viramas are the six Unicode\n// joins the next consonant through, in Devanagari, Bengali, Gujarati, Oriya,\n// Telugu and Malayalam, and they are tried before the plain mark they also\n// are, so the consonant after one stays in the grapheme.\nconst GRAPHEME =\n /\\p{Regional_Indicator}{2}|\\P{M}(?:[\\u094D\\u09CD\\u0ACD\\u0B4D\\u0C4D\\u0D4D]\\u200D?\\p{L}|[\\p{M}\\p{Emoji_Modifier}]|\\u200D\\P{M})*/gu\n\nconst segmenters = new Map<string, Intl.Segmenter>()\n\nfunction graphemesOf(text: string, locale: string | undefined) {\n // Asked on every call rather than once, so a test can take it away.\n if (typeof Intl.Segmenter !== 'function') {\n return text.match(GRAPHEME) ?? []\n }\n\n const key = locale ?? ''\n let segmenter = segmenters.get(key)\n if (segmenter === undefined) {\n segmenter = new Intl.Segmenter(locale, { granularity: 'grapheme' })\n segmenters.set(key, segmenter)\n }\n return Array.from(segmenter.segment(text), ({ segment }) => segment)\n}\n\n/**\n * The character that stands for `word`: its first grapheme that is a letter,\n * a number or a picture, or its first grapheme where it has none of those,\n * so something always shows. Upper-cased in the locale, and then one\n * grapheme of that, since upper-casing can lengthen it: \"ß\" is \"SS\".\n */\nfunction initialOf(word: string, locale: string | undefined) {\n const graphemes = graphemesOf(word, locale)\n const chosen =\n graphemes.find((grapheme) => INITIAL.test(grapheme)) ??\n graphemes.at(0) ??\n ''\n return graphemesOf(chosen.toLocaleUpperCase(locale), locale).at(0) ?? ''\n}\n\n/**\n * One letter, where a person takes two. A person has a first name and a last\n * name to initialise; a thing usually has neither, so the same rule applied\n * to \"Second item\" would produce \"SI\", a pair of initials for something that\n * was never two words in that sense.\n *\n * `locale` is the device's when left out, which is what a product icon\n * passes.\n */\nfunction initialOfThing(name: string, locale?: string) {\n return initialOf(name.trim(), locale)\n}\n\n/**\n * The initials of the first and the last word, which handles both \"Ada\" and\n * \"Ada Lovelace\" without a separate prop for how many to take. What a\n * display name carries around the name itself is left out first: a title\n * before it, a generational suffix after it, and an aside in brackets at its\n * end. A name written without spaces between its words — Japanese, Chinese —\n * is one word to this, and takes one initial.\n *\n * `locale` is the device's when left out, which is what an avatar passes.\n */\nfunction initialsOfPerson(name: string, locale?: string) {\n let words = name.replace(TRAILING_ASIDE, '').split(/\\s+/u).filter(Boolean)\n if (words.length > 1 && TITLE.test(words[0] ?? '')) {\n words = words.slice(1)\n }\n if (words.length > 1 && SUFFIX.test(words.at(-1) ?? '')) {\n words = words.slice(0, -1)\n }\n if (words.length === 0) {\n return ''\n }\n const first = initialOf(words[0] ?? '', locale)\n if (words.length === 1) {\n return first\n }\n const last = initialOf(words.at(-1) ?? '', locale)\n const between =\n JOINING.test(first) && JOINING.test(last) ? ZERO_WIDTH_NON_JOINER : ''\n return `${first}${between}${last}`\n}\n\nexport { initialOfThing, initialsOfPerson }\n"],"mappings":";AAwBA,MAAMA,UAAU;AAKhB,MAAMC,UACJ;AAEF,MAAMC,wBAAwB;AAI9B,MAAMC,QAAQ;AAKd,MAAMC,SAAS;AAIf,MAAMC,iBAAiB;AAOvB,MAAMC,WACJ;AAEF,MAAMC,6BAAa,IAAIC,IAA4B;AAEnD,SAASG,YAAYC,MAAcC,QAA4B;CAE7D,IAAI,OAAOJ,KAAKC,cAAc,YAC5B,OAAOE,KAAKE,MAAMR,QAAQ,KAAK,CAAA;CAGjC,MAAMS,MAAMF,UAAU;CACtB,IAAIG,YAAYT,WAAWU,IAAIF,GAAG;CAClC,IAAIC,cAAcE,KAAAA,GAAW;EAC3BF,YAAY,IAAIP,KAAKC,UAAUG,QAAQ,EAAEM,aAAa,WAAW,CAAC;EAClEZ,WAAWa,IAAIL,KAAKC,SAAS;CAC/B;CACA,OAAOK,MAAMC,KAAKN,UAAUO,QAAQX,IAAI,IAAI,EAAEW,cAAcA,OAAO;AACrE;;;;;;;AAQA,SAASC,UAAUC,MAAcZ,QAA4B;CAC3D,MAAMa,YAAYf,YAAYc,MAAMZ,MAAM;CAK1C,OAAOF,aAHLe,UAAUE,MAAMC,aAAa7B,QAAQ8B,KAAKD,QAAQ,CAAC,KACnDH,UAAUK,GAAG,CAAC,KACd,GAAA,CACwBC,kBAAkBnB,MAAM,GAAGA,MAAM,CAAC,CAACkB,GAAG,CAAC,KAAK;AACxE;;;;;;;;;;AAWA,SAASE,eAAeC,MAAcrB,QAAiB;CACrD,OAAOW,UAAUU,KAAKC,KAAK,GAAGtB,MAAM;AACtC;;;;;;;;;;;AAYA,SAASuB,iBAAiBF,MAAcrB,QAAiB;CACvD,IAAIwB,QAAQH,KAAKI,QAAQjC,gBAAgB,EAAE,CAAC,CAACkC,MAAM,MAAM,CAAC,CAACC,OAAOC,OAAO;CACzE,IAAIJ,MAAMK,SAAS,KAAKvC,MAAM2B,KAAKO,MAAM,MAAM,EAAE,GAC/CA,QAAQA,MAAMM,MAAM,CAAC;CAEvB,IAAIN,MAAMK,SAAS,KAAKtC,OAAO0B,KAAKO,MAAMN,GAAG,EAAE,KAAK,EAAE,GACpDM,QAAQA,MAAMM,MAAM,GAAG,EAAE;CAE3B,IAAIN,MAAMK,WAAW,GACnB,OAAO;CAET,MAAME,QAAQpB,UAAUa,MAAM,MAAM,IAAIxB,MAAM;CAC9C,IAAIwB,MAAMK,WAAW,GACnB,OAAOE;CAET,MAAMC,OAAOrB,UAAUa,MAAMN,GAAG,EAAE,KAAK,IAAIlB,MAAM;CAGjD,OAAO,GAAG+B,QADR3C,QAAQ6B,KAAKc,KAAK,KAAK3C,QAAQ6B,KAAKe,IAAI,IAAI3C,wBAAwB,KAC1C2C;AAC9B"}
@@ -0,0 +1 @@
1
+ import "../index.js";
@@ -0,0 +1,73 @@
1
+ import { themedStyles } from "../theme/styles.js";
2
+ import { StyleSheet } from "react-native";
3
+ //#region src/mark/styles.ts
4
+ const DIAMETERS = {
5
+ lg: 56,
6
+ md: 40,
7
+ sm: 36
8
+ };
9
+ const GLYPH_SHARE = .6;
10
+ const markStylesOf = themedStyles(({ colors, radii }) => StyleSheet.create({
11
+ base: {
12
+ alignItems: "center",
13
+ flexShrink: 0,
14
+ justifyContent: "center",
15
+ overflow: "hidden"
16
+ },
17
+ circle: { borderRadius: radii.circle },
18
+ negative: { backgroundColor: colors.negativeContainer },
19
+ positive: { backgroundColor: colors.positiveContainer },
20
+ primary: { backgroundColor: colors.primaryContainer },
21
+ secondary: { backgroundColor: colors.secondaryContainer },
22
+ square: { borderRadius: radii.sm },
23
+ tertiary: { backgroundColor: colors.tertiaryContainer }
24
+ }));
25
+ const initialsStylesOf = themedStyles(({ colors, typography }) => StyleSheet.create({
26
+ lg: {
27
+ fontSize: typography.bodyLargeSize,
28
+ lineHeight: typography.bodyLargeLineHeight
29
+ },
30
+ md: {
31
+ fontSize: typography.labelLargeSize,
32
+ lineHeight: typography.labelLargeLineHeight
33
+ },
34
+ negative: { color: colors.onNegativeContainer },
35
+ positive: { color: colors.onPositiveContainer },
36
+ primary: { color: colors.onPrimaryContainer },
37
+ secondary: { color: colors.onSecondaryContainer },
38
+ sm: {
39
+ fontSize: typography.labelMediumSize,
40
+ lineHeight: typography.labelMediumLineHeight
41
+ },
42
+ tertiary: { color: colors.onTertiaryContainer }
43
+ }));
44
+ const markStyles = StyleSheet.create({
45
+ fallback: {
46
+ alignItems: "center",
47
+ height: "100%",
48
+ justifyContent: "center",
49
+ width: "100%"
50
+ },
51
+ image: {
52
+ ...StyleSheet.absoluteFill,
53
+ height: "100%",
54
+ width: "100%"
55
+ },
56
+ imagePending: { opacity: 0 },
57
+ lg: {
58
+ height: DIAMETERS.lg,
59
+ width: DIAMETERS.lg
60
+ },
61
+ md: {
62
+ height: DIAMETERS.md,
63
+ width: DIAMETERS.md
64
+ },
65
+ sm: {
66
+ height: DIAMETERS.sm,
67
+ width: DIAMETERS.sm
68
+ }
69
+ });
70
+ //#endregion
71
+ export { DIAMETERS, GLYPH_SHARE, initialsStylesOf, markStyles, markStylesOf };
72
+
73
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","names":["StyleSheet","themedStyles","MarkSize","MarkTone","DIAMETERS","Readonly","Record","lg","md","sm","GLYPH_SHARE","markStylesOf","colors","radii","create","base","alignItems","flexShrink","justifyContent","overflow","circle","borderRadius","negative","backgroundColor","negativeContainer","positive","positiveContainer","primary","primaryContainer","secondary","secondaryContainer","square","tertiary","tertiaryContainer","initialsStylesOf","typography","fontSize","bodyLargeSize","lineHeight","bodyLargeLineHeight","labelLargeSize","labelLargeLineHeight","color","onNegativeContainer","onPositiveContainer","onPrimaryContainer","onSecondaryContainer","labelMediumSize","labelMediumLineHeight","onTertiaryContainer","markStyles","fallback","height","width","image","absoluteFill","imagePending","opacity"],"sources":["../../src/mark/styles.ts"],"sourcesContent":["import { StyleSheet } from 'react-native'\n\nimport { themedStyles } from '../theme/styles'\n\n// The box Avatar and ProductIcon draw in, as kanso-ui's `src/mark/styles.ts`\n// draws it, shared so a person and a thing stay the same three sizes in the\n// same five tones, and so either can fill a leading slot without moving what\n// sits beside it. They differ in the two ways that matter for a mark rather\n// than a face, and those are the keys a kind picks between in `./index.tsx`.\n//\n// A person is a circle with the photo cropped to fill it; a thing is a\n// rounded square with its mark letterboxed. A logo is drawn to its own\n// bounding box, so a circle crops the corners it was composed with, and\n// cropping a face loses nothing anyone minds where cropping a wordmark loses\n// the word. The cost of `contain` is letterboxing, a wide mark leaving space\n// above and below, and that is the right trade for a mark whose whole job is\n// to be recognised.\n//\n// That cost is also why a thing's tone tints the fallback rather than the\n// root. A mark letterboxed into the square does not cover it, and neither\n// does one drawn with transparency, so a tint on the root would show as a\n// coloured box around every logo that is not an opaque square. On the\n// fallback it is seen exactly when it is meant to be: while there is no mark,\n// or none has loaded. A photo covers the whole circle, so a person's tone\n// stays on the root.\n//\n// Tones are container and on-container pairs rather than one colour each, so\n// the initials are always a role's own foreground.\n//\n// Sizes carry their own type size but not their own weight or family: the\n// label large role's face and weight hold across all three, so a large mark\n// is bigger initials rather than differently styled ones.\n//\n// No Material Design page gives a measurement for one, so the three are\n// web's, stated against the scale the library already has. `md` is 40dp,\n// Button's and IconButton's own `md` height, so a mark and a control line up\n// in a row. `lg` is 56dp. `sm` is 36dp, for a row that wants a person smaller\n// than the button beside it.\n\ntype MarkSize = 'lg' | 'md' | 'sm'\n\ntype MarkTone = 'negative' | 'positive' | 'primary' | 'secondary' | 'tertiary'\n\nconst DIAMETERS: Readonly<Record<MarkSize, number>> = { lg: 56, md: 40, sm: 36 }\n\n// The anonymous person is three fifths of the disc: 24dp in the 40dp avatar,\n// as Material Design draws its placeholder, and the same share of the other\n// two.\nconst GLYPH_SHARE = 0.6\n\nconst markStylesOf = themedStyles(({ colors, radii }) =>\n StyleSheet.create({\n // Clips the picture to the shape, so one of any aspect ratio can be\n // handed over without the call site having to crop it first.\n base: {\n alignItems: 'center',\n flexShrink: 0,\n justifyContent: 'center',\n overflow: 'hidden',\n },\n circle: {\n borderRadius: radii.circle,\n },\n negative: { backgroundColor: colors.negativeContainer },\n positive: { backgroundColor: colors.positiveContainer },\n primary: { backgroundColor: colors.primaryContainer },\n secondary: { backgroundColor: colors.secondaryContainer },\n square: {\n borderRadius: radii.sm,\n },\n tertiary: { backgroundColor: colors.tertiaryContainer },\n }),\n)\n\nconst initialsStylesOf = themedStyles(({ colors, typography }) =>\n StyleSheet.create({\n lg: {\n fontSize: typography.bodyLargeSize,\n lineHeight: typography.bodyLargeLineHeight,\n },\n md: {\n fontSize: typography.labelLargeSize,\n lineHeight: typography.labelLargeLineHeight,\n },\n negative: { color: colors.onNegativeContainer },\n positive: { color: colors.onPositiveContainer },\n primary: { color: colors.onPrimaryContainer },\n secondary: { color: colors.onSecondaryContainer },\n sm: {\n fontSize: typography.labelMediumSize,\n lineHeight: typography.labelMediumLineHeight,\n },\n tertiary: { color: colors.onTertiaryContainer },\n }),\n)\n\nconst markStyles = StyleSheet.create({\n // Fills the root, so a thing's tint is the whole square rather than a box\n // behind its initial.\n fallback: {\n alignItems: 'center',\n height: '100%',\n justifyContent: 'center',\n width: '100%',\n },\n // Laid over the initials and over the picture before it, filling the\n // mark, so a new picture can load in place without moving anything.\n image: {\n ...StyleSheet.absoluteFill,\n height: '100%',\n width: '100%',\n },\n // Loading: present, so the platform fetches it, and invisible until it has\n // loaded.\n imagePending: {\n opacity: 0,\n },\n lg: { height: DIAMETERS.lg, width: DIAMETERS.lg },\n md: { height: DIAMETERS.md, width: DIAMETERS.md },\n sm: { height: DIAMETERS.sm, width: DIAMETERS.sm },\n})\n\nexport type { MarkSize, MarkTone }\n\nexport { DIAMETERS, GLYPH_SHARE, initialsStylesOf, markStyles, markStylesOf }\n"],"mappings":";;;AA2CA,MAAMI,YAAgD;CAAEG,IAAI;CAAIC,IAAI;CAAIC,IAAI;AAAG;AAK/E,MAAMC,cAAc;AAEpB,MAAMC,eAAeV,cAAc,EAAEW,QAAQC,YAC3Cb,WAAWc,OAAO;CAGhBC,MAAM;EACJC,YAAY;EACZC,YAAY;EACZC,gBAAgB;EAChBC,UAAU;CACZ;CACAC,QAAQ,EACNC,cAAcR,MAAMO,OACtB;CACAE,UAAU,EAAEC,iBAAiBX,OAAOY,kBAAkB;CACtDC,UAAU,EAAEF,iBAAiBX,OAAOc,kBAAkB;CACtDC,SAAS,EAAEJ,iBAAiBX,OAAOgB,iBAAiB;CACpDC,WAAW,EAAEN,iBAAiBX,OAAOkB,mBAAmB;CACxDC,QAAQ,EACNV,cAAcR,MAAMJ,GACtB;CACAuB,UAAU,EAAET,iBAAiBX,OAAOqB,kBAAkB;AACxD,CAAC,CACH;AAEA,MAAMC,mBAAmBjC,cAAc,EAAEW,QAAQuB,iBAC/CnC,WAAWc,OAAO;CAChBP,IAAI;EACF6B,UAAUD,WAAWE;EACrBC,YAAYH,WAAWI;CACzB;CACA/B,IAAI;EACF4B,UAAUD,WAAWK;EACrBF,YAAYH,WAAWM;CACzB;CACAnB,UAAU,EAAEoB,OAAO9B,OAAO+B,oBAAoB;CAC9ClB,UAAU,EAAEiB,OAAO9B,OAAOgC,oBAAoB;CAC9CjB,SAAS,EAAEe,OAAO9B,OAAOiC,mBAAmB;CAC5ChB,WAAW,EAAEa,OAAO9B,OAAOkC,qBAAqB;CAChDrC,IAAI;EACF2B,UAAUD,WAAWY;EACrBT,YAAYH,WAAWa;CACzB;CACAhB,UAAU,EAAEU,OAAO9B,OAAOqC,oBAAoB;AAChD,CAAC,CACH;AAEA,MAAMC,aAAalD,WAAWc,OAAO;CAGnCqC,UAAU;EACRnC,YAAY;EACZoC,QAAQ;EACRlC,gBAAgB;EAChBmC,OAAO;CACT;CAGAC,OAAO;EACL,GAAGtD,WAAWuD;EACdH,QAAQ;EACRC,OAAO;CACT;CAGAG,cAAc,EACZC,SAAS,EACX;CACAlD,IAAI;EAAE6C,QAAQhD,UAAUG;EAAI8C,OAAOjD,UAAUG;CAAG;CAChDC,IAAI;EAAE4C,QAAQhD,UAAUI;EAAI6C,OAAOjD,UAAUI;CAAG;CAChDC,IAAI;EAAE2C,QAAQhD,UAAUK;EAAI4C,OAAOjD,UAAUK;CAAG;AAClD,CAAC"}
@@ -0,0 +1,321 @@
1
+ //#region src/number/parser.ts
2
+ const CURRENCY_SIGN_REGEX = /^.*\(.*\).*$/u;
3
+ const NUMBERING_SYSTEMS = [
4
+ "latn",
5
+ "arab",
6
+ "hanidec",
7
+ "deva",
8
+ "beng",
9
+ "fullwide"
10
+ ];
11
+ const PLURAL_NUMBERS = [
12
+ 0,
13
+ 4,
14
+ 2,
15
+ 1,
16
+ 11,
17
+ 20,
18
+ 3,
19
+ 7,
20
+ 100,
21
+ 21,
22
+ .1,
23
+ 1.1
24
+ ];
25
+ const PROBE = 12345.67;
26
+ const PROBE_DIGITS = "1234567";
27
+ const SPACING = "\\s\\u0085\\u00ad\\u0600-\\u0605\\u061c\\u06dd\\u070f\\u0890\\u0891\\u08e2\\u180e\\u200b-\\u200f\\u202a-\\u202e\\u2060-\\u2064\\u2066-\\u206f\\ufeff\\ufff9-\\ufffb";
28
+ const SPACING_RUN = new RegExp(`[${SPACING}]+`, "u");
29
+ const SPACING_ANY = new RegExp(`[${SPACING}]`, "gu");
30
+ const SYSTEMS_BY_ZERO = /* @__PURE__ */ new Map([
31
+ ["0", "latn"],
32
+ ["٠", "arab"],
33
+ ["۰", "arabext"],
34
+ ["〇", "hanidec"],
35
+ ["०", "deva"],
36
+ ["০", "beng"],
37
+ ["0", "fullwide"]
38
+ ]);
39
+ const parserCache = /* @__PURE__ */ new Map();
40
+ /**
41
+ * Parses a number in a locale and a format, as @internationalized/number's
42
+ * `NumberParser` does, without `formatToParts`.
43
+ */
44
+ var NumberParser = class {
45
+ locale;
46
+ options;
47
+ constructor(locale, options = {}) {
48
+ this.locale = locale;
49
+ this.options = options;
50
+ }
51
+ /**
52
+ * The numbering system the value reads in, in the locale, or the locale's
53
+ * own when none matches. `undefined` is the locale's own, on a runtime
54
+ * that does not name it.
55
+ */
56
+ getNumberingSystem(value) {
57
+ return numberParserFor(this.locale, this.options, value).numberingSystem;
58
+ }
59
+ /**
60
+ * Whether the value could be the start of a number, which is how input is
61
+ * checked as it is typed. A minus sign counts only where `minValue` is
62
+ * below zero, and a plus sign only where `maxValue` is above it.
63
+ */
64
+ isValidPartialNumber(value, minValue, maxValue) {
65
+ return numberParserFor(this.locale, this.options, value).isValidPartialNumber(value, minValue, maxValue);
66
+ }
67
+ /** The number the value reads as, or `NaN` when it reads as none. */
68
+ parse(value) {
69
+ return numberParserFor(this.locale, this.options, value).parse(value);
70
+ }
71
+ };
72
+ var NumberParserImpl = class {
73
+ numberingSystem;
74
+ formatter;
75
+ locale;
76
+ options;
77
+ symbols;
78
+ constructor(locale, given = {}) {
79
+ this.locale = locale;
80
+ const options = withRoundingIncrement(given);
81
+ this.formatter = new Intl.NumberFormat(locale, options);
82
+ this.options = this.formatter.resolvedOptions();
83
+ this.symbols = symbolsOf(locale, this.options, options);
84
+ this.numberingSystem = optionalString(this.options.numberingSystem) ?? SYSTEMS_BY_ZERO.get(this.symbols.numerals[0] ?? "");
85
+ }
86
+ isValidPartialNumber(value, minValue = -Infinity, maxValue = Infinity) {
87
+ const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping);
88
+ const { decimal, group, minusSign, numeral, plusSign } = this.symbols;
89
+ let rest = this.sanitize(value);
90
+ if (minusSign !== "" && rest.startsWith(minusSign) && minValue < 0) rest = rest.slice(minusSign.length);
91
+ else if (plusSign !== void 0 && rest.startsWith(plusSign) && maxValue > 0) rest = rest.slice(plusSign.length);
92
+ if (decimal !== void 0 && rest.includes(decimal) && this.options.maximumFractionDigits === 0) return false;
93
+ if (group !== void 0 && groupAllowed) rest = rest.replaceAll(group, "");
94
+ rest = rest.replace(numeral, "");
95
+ if (decimal !== void 0) rest = rest.replace(decimal, "");
96
+ return rest.length === 0;
97
+ }
98
+ parse(value) {
99
+ const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping);
100
+ const { decimal, group, index, minusSign, numeral } = this.symbols;
101
+ let plain = this.sanitize(value);
102
+ if (!groupAllowed && group !== void 0 && plain.includes(group)) return NaN;
103
+ else if (group !== void 0) plain = plain.replaceAll(group, "");
104
+ if (decimal !== void 0) plain = plain.replace(decimal, ".");
105
+ plain = plain.replace(minusSign, "-");
106
+ plain = plain.replace(numeral, index);
107
+ if (this.options.style === "percent") plain = percentOf(plain);
108
+ const parsed = plain === "" ? NaN : Number(plain);
109
+ if (Number.isNaN(parsed)) return NaN;
110
+ if (this.options.style === "percent") {
111
+ const options = {
112
+ ...this.options,
113
+ maximumFractionDigits: Math.min((this.options.maximumFractionDigits ?? 0) + 2, 20),
114
+ minimumFractionDigits: Math.min((this.options.minimumFractionDigits ?? 0) + 2, 20),
115
+ style: "decimal"
116
+ };
117
+ return new NumberParser(this.locale, options).parse(new Intl.NumberFormat(this.locale, options).format(parsed));
118
+ }
119
+ if (this.options.currencySign === "accounting" && CURRENCY_SIGN_REGEX.test(value)) return -1 * parsed;
120
+ return parsed;
121
+ }
122
+ sanitize(value) {
123
+ const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping);
124
+ const { decimal, group, literals, minusSign, noNumeralUnits } = this.symbols;
125
+ const spelled = noNumeralUnits.find((entry) => entry.unit === value);
126
+ if (spelled !== void 0) return String(spelled.value);
127
+ let rest = value.replace(literals, "");
128
+ rest = rest.replace("-", minusSign);
129
+ if (this.numberingSystem === "arab") {
130
+ if (decimal !== void 0) {
131
+ rest = rest.replaceAll(",", decimal);
132
+ rest = rest.replaceAll("،", decimal);
133
+ }
134
+ if (group !== void 0 && groupAllowed) rest = rest.replaceAll(".", group);
135
+ }
136
+ if (group === "’" && rest.includes("'") && groupAllowed) rest = rest.replaceAll("'", group);
137
+ if (group === "'" && rest.includes("’") && groupAllowed) rest = rest.replaceAll("’", group);
138
+ if (this.options.locale === "fr-FR" && group !== void 0 && groupAllowed) {
139
+ rest = rest.replaceAll(" ", group);
140
+ rest = rest.replaceAll("\xA0", group);
141
+ }
142
+ return rest;
143
+ }
144
+ };
145
+ function differenceOf(from, to) {
146
+ const fromChars = Array.from(from);
147
+ const toChars = Array.from(to);
148
+ let start = 0;
149
+ while (start < fromChars.length && start < toChars.length && fromChars[start] === toChars[start]) start += 1;
150
+ let end = 0;
151
+ while (end < fromChars.length - start && end < toChars.length - start && fromChars[fromChars.length - 1 - end] === toChars[toChars.length - 1 - end]) end += 1;
152
+ return {
153
+ added: toChars.slice(start, toChars.length - end).join(""),
154
+ rest: `${toChars.slice(0, start).join("")} ${toChars.slice(toChars.length - end).join("")}`
155
+ };
156
+ }
157
+ function escapeRegex(text) {
158
+ return text.replaceAll(/[$()*+.?[\\\]^{|}]/gu, "\\$&");
159
+ }
160
+ function numberParserFor(locale, options, value) {
161
+ const parser = parserOf(locale, options);
162
+ if (!locale.includes("-nu-") && !parser.isValidPartialNumber(value)) {
163
+ for (const system of NUMBERING_SYSTEMS) if (system !== parser.numberingSystem) {
164
+ const other = parserOf(`${locale}${locale.includes("-u-") ? "-nu-" : "-u-nu-"}${system}`, options);
165
+ if (other.isValidPartialNumber(value)) return other;
166
+ }
167
+ }
168
+ return parser;
169
+ }
170
+ function numeralsOf(locale, numberingSystem) {
171
+ return Array.from(new Intl.NumberFormat(locale, {
172
+ numberingSystem,
173
+ useGrouping: false
174
+ }).format(9876543210)).toReversed();
175
+ }
176
+ function optionalString(value) {
177
+ return typeof value === "string" ? value : void 0;
178
+ }
179
+ function parserOf(locale, options) {
180
+ const key = locale + Object.entries(options).toSorted(([a], [b]) => a < b ? -1 : 1).join();
181
+ const cached = parserCache.get(key);
182
+ if (cached !== void 0) return cached;
183
+ const parser = new NumberParserImpl(locale, options);
184
+ parserCache.set(key, parser);
185
+ return parser;
186
+ }
187
+ function percentOf(plain) {
188
+ const negative = plain.includes("-");
189
+ let digits = plain.replace("-", "").replace("+", "");
190
+ let point = digits.indexOf(".");
191
+ if (point === -1) point = digits.length;
192
+ digits = digits.replace(".", "");
193
+ const moved = point - 2 === 0 ? `0.${digits}` : point - 2 === -1 ? `0.0${digits}` : point - 2 === -2 ? "0.00" : `${digits.slice(0, point - 2)}.${digits.slice(point - 2)}`;
194
+ return negative ? `-${moved}` : moved;
195
+ }
196
+ function probeOptionsOf(resolved, extra) {
197
+ return {
198
+ ...resolved,
199
+ maximumSignificantDigits: void 0,
200
+ minimumSignificantDigits: void 0,
201
+ notation: "standard",
202
+ roundingIncrement: 1,
203
+ roundingMode: "halfExpand",
204
+ roundingPriority: "auto",
205
+ signDisplay: "auto",
206
+ trailingZeroDisplay: "auto",
207
+ useGrouping: true,
208
+ ...extra
209
+ };
210
+ }
211
+ function signOf(text) {
212
+ return text.replace(SPACING_ANY, "");
213
+ }
214
+ function spansOf(text, digitOf) {
215
+ const chars = Array.from(text);
216
+ let digits = "";
217
+ const gaps = [];
218
+ let prefix = "";
219
+ let gap = "";
220
+ for (const char of chars) {
221
+ const digit = digitOf.get(char);
222
+ if (digit === void 0) gap += char;
223
+ else {
224
+ if (digits === "") prefix = gap;
225
+ else gaps.push(gap);
226
+ gap = "";
227
+ digits += String(digit);
228
+ }
229
+ }
230
+ return {
231
+ digits,
232
+ gaps,
233
+ prefix,
234
+ suffix: digits === "" ? "" : gap
235
+ };
236
+ }
237
+ function symbolsOf(locale, resolved, options) {
238
+ const numberingSystem = optionalString(resolved.numberingSystem);
239
+ const numerals = numeralsOf(resolved.locale, numberingSystem);
240
+ const digitOf = new Map(numerals.map((numeral, digit) => [numeral, digit]));
241
+ const scale = resolved.style === "percent" ? 100 : 1;
242
+ const probe = new Intl.NumberFormat(locale, probeOptionsOf(resolved, {
243
+ maximumFractionDigits: 2,
244
+ minimumFractionDigits: 2
245
+ }));
246
+ const positive = spansOf(probe.format(PROBE / scale), digitOf);
247
+ const negative = spansOf(probe.format(-12345.67 / scale), digitOf);
248
+ const read = positive.digits === PROBE_DIGITS ? positive : void 0;
249
+ const decimal = read?.gaps[4] === "" ? void 0 : read?.gaps[4];
250
+ const group = read?.gaps[1] === "" ? void 0 : read?.gaps[1];
251
+ const before = differenceOf(positive.prefix, negative.prefix);
252
+ const after = differenceOf(positive.suffix, negative.suffix);
253
+ const signedBefore = before.added !== "" && after.added === "";
254
+ const signedAfter = after.added !== "" && before.added === "";
255
+ const minusSign = signOf(signedBefore ? before.added : signedAfter ? after.added : "") || "-";
256
+ let plusSign;
257
+ if (options.signDisplay === "always" || options.signDisplay === "exceptZero") {
258
+ const signed = spansOf(new Intl.NumberFormat(locale, probeOptionsOf(resolved, {
259
+ maximumFractionDigits: 2,
260
+ minimumFractionDigits: 2,
261
+ signDisplay: "always"
262
+ })).format(PROBE / scale), digitOf);
263
+ const plusBefore = differenceOf(positive.prefix, signed.prefix).added;
264
+ const plusAfter = differenceOf(positive.suffix, signed.suffix).added;
265
+ plusSign = signOf(plusBefore === "" ? plusAfter : plusBefore) || "+";
266
+ }
267
+ const plurals = new Intl.NumberFormat(locale, probeOptionsOf(resolved, {
268
+ maximumFractionDigits: 3,
269
+ minimumFractionDigits: 0
270
+ }));
271
+ const pluralTexts = PLURAL_NUMBERS.map((value) => plurals.format(value));
272
+ const noNumeralUnits = pluralTexts.map((text, at) => ({
273
+ text: text.trim(),
274
+ value: PLURAL_NUMBERS[at] ?? 0
275
+ })).filter(({ text }) => !Array.from(text).some((char) => digitOf.has(char))).map(({ text, value }) => ({
276
+ unit: text,
277
+ value
278
+ }));
279
+ const around = [
280
+ positive.prefix,
281
+ positive.suffix,
282
+ before.rest,
283
+ after.rest,
284
+ ...signedBefore || signedAfter ? [] : [before.added, after.added],
285
+ ...pluralTexts.flatMap((text) => {
286
+ const spans = spansOf(text, digitOf);
287
+ return spans.digits === "" ? [] : [spans.prefix, spans.suffix];
288
+ })
289
+ ];
290
+ const pieces = [...new Set(around.flatMap((text) => text.split(SPACING_RUN)).filter((piece) => piece !== "" && piece !== minusSign).map(escapeRegex))].toSorted((a, b) => b.length - a.length);
291
+ const literals = new RegExp([...pieces, `[${SPACING}]`].join("|"), "gu");
292
+ const indexes = new Map(numerals.map((numeral, digit) => [numeral, digit]));
293
+ return {
294
+ decimal,
295
+ group,
296
+ index: (numeral) => String(indexes.get(numeral)),
297
+ literals,
298
+ minusSign,
299
+ noNumeralUnits,
300
+ numeral: new RegExp(`[${numerals.join("")}]`, "gu"),
301
+ numerals,
302
+ plusSign
303
+ };
304
+ }
305
+ function withRoundingIncrement(given) {
306
+ const options = { ...given };
307
+ if (options.roundingIncrement !== 1 && options.roundingIncrement != null) {
308
+ if (options.maximumFractionDigits == null && options.minimumFractionDigits == null) {
309
+ options.maximumFractionDigits = 0;
310
+ options.minimumFractionDigits = 0;
311
+ } else {
312
+ options.maximumFractionDigits ??= options.minimumFractionDigits;
313
+ options.minimumFractionDigits ??= options.maximumFractionDigits;
314
+ }
315
+ }
316
+ return options;
317
+ }
318
+ //#endregion
319
+ export { NumberParser };
320
+
321
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","names":["NumberFormatOptions","NoNumeralUnit","unit","value","Spans","digits","gaps","prefix","suffix","Symbols","decimal","group","index","numeral","literals","RegExp","minusSign","noNumeralUnits","numerals","plusSign","CURRENCY_SIGN_REGEX","NUMBERING_SYSTEMS","PLURAL_NUMBERS","PROBE","PROBE_DIGITS","SPACING","SPACING_RUN","SPACING_ANY","SYSTEMS_BY_ZERO","Map","parserCache","NumberParserImpl","NumberParser","locale","options","constructor","getNumberingSystem","numberParserFor","numberingSystem","isValidPartialNumber","minValue","maxValue","parse","formatter","Intl","NumberFormat","ResolvedNumberFormatOptions","symbols","given","withRoundingIncrement","resolvedOptions","symbolsOf","optionalString","get","Infinity","groupAllowed","Boolean","useGrouping","rest","sanitize","startsWith","slice","length","undefined","includes","maximumFractionDigits","replaceAll","replace","plain","Number","NaN","style","percentOf","parsed","isNaN","Math","min","minimumFractionDigits","format","currencySign","test","spelled","find","entry","String","differenceOf","from","to","fromChars","Array","toChars","start","end","added","join","escapeRegex","text","parser","parserOf","system","other","numeralsOf","toReversed","key","Object","entries","toSorted","a","b","cached","set","negative","point","indexOf","moved","probeOptionsOf","resolved","extra","maximumSignificantDigits","minimumSignificantDigits","notation","roundingIncrement","roundingMode","roundingPriority","signDisplay","trailingZeroDisplay","signOf","spansOf","digitOf","ReadonlyMap","chars","gap","char","digit","push","map","scale","probe","positive","read","before","after","signedBefore","signedAfter","signed","plusBefore","plusAfter","plurals","pluralTexts","at","trim","filter","some","has","around","flatMap","spans","pieces","Set","split","piece","indexes"],"sources":["../../src/number/parser.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n *\n * Modified by Kanso Labs: ported from @internationalized/number's NumberParser\n * to find the locale's symbols with `format` rather than `formatToParts`.\n */\n\nimport type { NumberFormatOptions } from '@internationalized/number'\n\n// Reading back a number a person typed, in the locale and the format the\n// field shows it in: the parser web's NumberField reads its value with,\n// through React Stately, which is @internationalized/number's NumberParser.\n//\n// **It finds the locale's symbols with `format` alone.** The parser it ports\n// asks `formatToParts` for them, the minus sign, the decimal and group\n// separators, and the currency, percent and unit text around the digits, and\n// Hermes defines no `formatToParts` for `Intl.NumberFormat` on iOS, so it\n// throws on the first character typed there. `format` is what every runtime\n// React Native runs on has. So a known number is formatted, its digits found\n// by the locale's own numerals, and each symbol read off where it falls: the\n// group separator between the second and third digits of 12,345.67, the\n// decimal between the fifth and sixth, the minus where the negative differs\n// from the positive, and the rest of the text around the digits as what the\n// parser strips. Everything after that is the parser it ports, line for\n// line, and the tests compare the two across locales and formats on a\n// runtime that has both.\n\ntype NoNumeralUnit = {\n readonly unit: string\n readonly value: number\n}\n\n// Where a formatted number's digits fall: the digits themselves, as ASCII, the\n// text between each and the next, and the text before and after them.\ntype Spans = {\n readonly digits: string\n readonly gaps: readonly string[]\n readonly prefix: string\n readonly suffix: string\n}\n\ntype Symbols = {\n readonly decimal: string | undefined\n readonly group: string | undefined\n readonly index: (numeral: string) => string\n readonly literals: RegExp\n readonly minusSign: string\n readonly noNumeralUnits: readonly NoNumeralUnit[]\n readonly numeral: RegExp\n readonly numerals: readonly string[]\n readonly plusSign: string | undefined\n}\n\nconst CURRENCY_SIGN_REGEX = /^.*\\(.*\\).*$/u\n\n// The numbering systems a value is tried in when it does not read in the\n// locale's own, as the parser it ports tries them.\nconst NUMBERING_SYSTEMS = [\n 'latn',\n 'arab',\n 'hanidec',\n 'deva',\n 'beng',\n 'fullwide',\n]\n\n// Every number whose plural form a unit or a currency name can take in some\n// locale, from the parser it ports.\nconst PLURAL_NUMBERS = [0, 4, 2, 1, 11, 20, 3, 7, 100, 21, 0.1, 1.1]\n\n// 12,345.67: a group separator after its second digit in every locale that\n// groups, and the decimal separator after its fifth.\nconst PROBE = 12_345.67\nconst PROBE_DIGITS = '1234567'\n\n// White space and the formatting characters, Unicode's `White_Space` and\n// `Cf`, which the parser it ports strips as `\\p{White_Space}|\\p{Cf}`. Spelled\n// out rather than as property escapes, so the expression means the same\n// wherever it is compiled. These are the characters in the Basic\n// Multilingual Plane, which is every one a number format writes.\nconst SPACING =\n '\\\\s\\\\u0085\\\\u00ad\\\\u0600-\\\\u0605\\\\u061c\\\\u06dd\\\\u070f\\\\u0890\\\\u0891\\\\u08e2\\\\u180e\\\\u200b-\\\\u200f\\\\u202a-\\\\u202e\\\\u2060-\\\\u2064\\\\u2066-\\\\u206f\\\\ufeff\\\\ufff9-\\\\ufffb'\nconst SPACING_RUN = new RegExp(`[${SPACING}]+`, 'u')\nconst SPACING_ANY = new RegExp(`[${SPACING}]`, 'gu')\n\n// The numbering system a locale's zero belongs to, for a runtime whose\n// resolved options do not name one: Hermes on iOS names none. These are the\n// systems a value is tried in, and Persian's. A locale writing any other is\n// left unnamed, which a formatter reads as the locale's own system, and\n// that is the one it writes.\nconst SYSTEMS_BY_ZERO = new Map([\n ['0', 'latn'],\n ['٠', 'arab'],\n ['۰', 'arabext'],\n ['〇', 'hanidec'],\n ['०', 'deva'],\n ['০', 'beng'],\n ['0', 'fullwide'],\n])\n\nconst parserCache = new Map<string, NumberParserImpl>()\n\n/**\n * Parses a number in a locale and a format, as @internationalized/number's\n * `NumberParser` does, without `formatToParts`.\n */\nclass NumberParser {\n private readonly locale: string\n private readonly options: NumberFormatOptions\n\n constructor(locale: string, options: NumberFormatOptions = {}) {\n this.locale = locale\n this.options = options\n }\n\n /**\n * The numbering system the value reads in, in the locale, or the locale's\n * own when none matches. `undefined` is the locale's own, on a runtime\n * that does not name it.\n */\n getNumberingSystem(value: string): string | undefined {\n return numberParserFor(this.locale, this.options, value).numberingSystem\n }\n\n /**\n * Whether the value could be the start of a number, which is how input is\n * checked as it is typed. A minus sign counts only where `minValue` is\n * below zero, and a plus sign only where `maxValue` is above it.\n */\n isValidPartialNumber(\n value: string,\n minValue?: number,\n maxValue?: number,\n ): boolean {\n return numberParserFor(\n this.locale,\n this.options,\n value,\n ).isValidPartialNumber(value, minValue, maxValue)\n }\n\n /** The number the value reads as, or `NaN` when it reads as none. */\n parse(value: string): number {\n return numberParserFor(this.locale, this.options, value).parse(value)\n }\n}\n\nclass NumberParserImpl {\n readonly numberingSystem: string | undefined\n private readonly formatter: Intl.NumberFormat\n private readonly locale: string\n private readonly options: Intl.ResolvedNumberFormatOptions\n private readonly symbols: Symbols\n\n constructor(locale: string, given: NumberFormatOptions = {}) {\n this.locale = locale\n const options = withRoundingIncrement(given)\n this.formatter = new Intl.NumberFormat(locale, options)\n this.options = this.formatter.resolvedOptions()\n this.symbols = symbolsOf(locale, this.options, options)\n this.numberingSystem =\n optionalString(this.options.numberingSystem) ??\n SYSTEMS_BY_ZERO.get(this.symbols.numerals[0] ?? '')\n }\n\n isValidPartialNumber(\n value: string,\n minValue = -Infinity,\n maxValue = Infinity,\n ) {\n const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping)\n const { decimal, group, minusSign, numeral, plusSign } = this.symbols\n let rest = this.sanitize(value)\n\n // A sign comes first.\n if (minusSign !== '' && rest.startsWith(minusSign) && minValue < 0) {\n rest = rest.slice(minusSign.length)\n } else if (\n plusSign !== undefined &&\n rest.startsWith(plusSign) &&\n maxValue > 0\n ) {\n rest = rest.slice(plusSign.length)\n }\n\n // A format with no fraction takes no decimal separator.\n if (\n decimal !== undefined &&\n rest.includes(decimal) &&\n this.options.maximumFractionDigits === 0\n ) {\n return false\n }\n\n if (group !== undefined && groupAllowed) {\n rest = rest.replaceAll(group, '')\n }\n rest = rest.replace(numeral, '')\n if (decimal !== undefined) {\n rest = rest.replace(decimal, '')\n }\n\n return rest.length === 0\n }\n\n parse(value: string): number {\n const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping)\n const { decimal, group, index, minusSign, numeral } = this.symbols\n let plain = this.sanitize(value)\n\n if (!groupAllowed && group !== undefined && plain.includes(group)) {\n return Number.NaN\n } else if (group !== undefined) {\n plain = plain.replaceAll(group, '')\n }\n if (decimal !== undefined) {\n plain = plain.replace(decimal, '.')\n }\n plain = plain.replace(minusSign, '-')\n plain = plain.replace(numeral, index)\n\n if (this.options.style === 'percent') {\n plain = percentOf(plain)\n }\n\n const parsed = plain === '' ? Number.NaN : Number(plain)\n if (Number.isNaN(parsed)) {\n return Number.NaN\n }\n\n if (this.options.style === 'percent') {\n // Rounded as the field's formatter would show it.\n const options = {\n ...this.options,\n maximumFractionDigits: Math.min(\n (this.options.maximumFractionDigits ?? 0) + 2,\n 20,\n ),\n minimumFractionDigits: Math.min(\n (this.options.minimumFractionDigits ?? 0) + 2,\n 20,\n ),\n style: 'decimal',\n } satisfies NumberFormatOptions\n return new NumberParser(this.locale, options).parse(\n new Intl.NumberFormat(this.locale, options).format(parsed),\n )\n }\n\n // An accounting format writes a negative in brackets, which the literals\n // have already stripped.\n if (\n this.options.currencySign === 'accounting' &&\n CURRENCY_SIGN_REGEX.test(value)\n ) {\n return -1 * parsed\n }\n\n return parsed\n }\n\n private sanitize(value: string) {\n const groupAllowed = Boolean(this.formatter.resolvedOptions().useGrouping)\n const { decimal, group, literals, minusSign, noNumeralUnits } = this.symbols\n\n // A unit some plural forms write with no numeral, such as a day spelled\n // out, stands for its number.\n const spelled = noNumeralUnits.find((entry) => entry.unit === value)\n if (spelled !== undefined) {\n return String(spelled.value)\n }\n\n let rest = value.replace(literals, '')\n\n // The ASCII hyphen stands for the locale's minus, which a keyboard may\n // not have.\n rest = rest.replace('-', minusSign)\n\n // Arabic's decimal separator is on few keyboards, which type a comma or\n // the Arabic comma instead, and a full stop for its group separator.\n if (this.numberingSystem === 'arab') {\n if (decimal !== undefined) {\n rest = rest.replaceAll(',', decimal)\n rest = rest.replaceAll('،', decimal)\n }\n if (group !== undefined && groupAllowed) {\n rest = rest.replaceAll('.', group)\n }\n }\n\n // A right single quotation mark groups digits in some formats, Swiss\n // currency among them, where a keyboard types an apostrophe, and newer\n // data writes the apostrophe where older wrote the quotation mark.\n if (group === '’' && rest.includes(\"'\") && groupAllowed) {\n rest = rest.replaceAll(\"'\", group)\n }\n if (group === \"'\" && rest.includes('’') && groupAllowed) {\n rest = rest.replaceAll('’', group)\n }\n\n // French groups with a narrow no-break space, which no French keyboard\n // has, so a space and a no-break space group too.\n if (\n this.options.locale === 'fr-FR' &&\n group !== undefined &&\n groupAllowed\n ) {\n rest = rest.replaceAll(' ', group)\n rest = rest.replaceAll(' ', group)\n }\n\n return rest\n }\n}\n\n// What `from` became in `to`: the text `to` has between the start and the end\n// the two share, and `to` with a space in its place.\nfunction differenceOf(from: string, to: string) {\n const fromChars = Array.from(from)\n const toChars = Array.from(to)\n let start = 0\n while (\n start < fromChars.length &&\n start < toChars.length &&\n fromChars[start] === toChars[start]\n ) {\n start += 1\n }\n let end = 0\n while (\n end < fromChars.length - start &&\n end < toChars.length - start &&\n fromChars[fromChars.length - 1 - end] === toChars[toChars.length - 1 - end]\n ) {\n end += 1\n }\n\n return {\n added: toChars.slice(start, toChars.length - end).join(''),\n rest: `${toChars.slice(0, start).join('')} ${toChars.slice(toChars.length - end).join('')}`,\n }\n}\n\nfunction escapeRegex(text: string) {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, '\\\\$&')\n}\n\n// The parser for a value: the locale's own numbering system, or the first of\n// the others the value reads in, unless the locale names one.\nfunction numberParserFor(\n locale: string,\n options: NumberFormatOptions,\n value: string,\n) {\n const parser = parserOf(locale, options)\n\n if (!locale.includes('-nu-') && !parser.isValidPartialNumber(value)) {\n for (const system of NUMBERING_SYSTEMS) {\n if (system !== parser.numberingSystem) {\n const other = parserOf(\n `${locale}${locale.includes('-u-') ? '-nu-' : '-u-nu-'}${system}`,\n options,\n )\n if (other.isValidPartialNumber(value)) {\n return other\n }\n }\n }\n }\n\n return parser\n}\n\n// The numerals a locale writes, zero first.\nfunction numeralsOf(locale: string, numberingSystem: string | undefined) {\n return Array.from(\n new Intl.NumberFormat(locale, {\n numberingSystem,\n useGrouping: false,\n }).format(9_876_543_210),\n ).toReversed()\n}\n\nfunction optionalString(value: unknown) {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction parserOf(locale: string, options: NumberFormatOptions) {\n const key =\n locale +\n Object.entries(options)\n .toSorted(([a], [b]) => (a < b ? -1 : 1))\n .join()\n const cached = parserCache.get(key)\n if (cached !== undefined) {\n return cached\n }\n\n const parser = new NumberParserImpl(locale, options)\n parserCache.set(key, parser)\n return parser\n}\n\n// A percent's digits moved two places left on the string rather than divided\n// by 100, which keeps the figures it was written with.\nfunction percentOf(plain: string) {\n const negative = plain.includes('-')\n let digits = plain.replace('-', '').replace('+', '')\n let point = digits.indexOf('.')\n if (point === -1) {\n point = digits.length\n }\n digits = digits.replace('.', '')\n\n const moved =\n point - 2 === 0\n ? `0.${digits}`\n : point - 2 === -1\n ? `0.0${digits}`\n : point - 2 === -2\n ? '0.00'\n : `${digits.slice(0, point - 2)}.${digits.slice(point - 2)}`\n\n return negative ? `-${moved}` : moved\n}\n\n// The options a symbol is read with: the format's own, so its currency,\n// percent or unit text is the text read, at the fraction digits given,\n// grouped, and with the rounding, the notation and the sign at their\n// defaults, so the digits come out whole.\nfunction probeOptionsOf(\n resolved: Intl.ResolvedNumberFormatOptions,\n extra: NumberFormatOptions,\n): NumberFormatOptions {\n return {\n ...resolved,\n maximumSignificantDigits: undefined,\n minimumSignificantDigits: undefined,\n notation: 'standard',\n roundingIncrement: 1,\n roundingMode: 'halfExpand',\n roundingPriority: 'auto',\n signDisplay: 'auto',\n trailingZeroDisplay: 'auto',\n useGrouping: true,\n ...extra,\n }\n}\n\n// The text a number's sign is, with the white space and direction marks\n// around it left out, as `formatToParts` leaves them out of its sign.\nfunction signOf(text: string) {\n return text.replace(SPACING_ANY, '')\n}\n\n// Where a formatted number's digits fall, read by the numerals given.\nfunction spansOf(text: string, digitOf: ReadonlyMap<string, number>): Spans {\n const chars = Array.from(text)\n let digits = ''\n const gaps: string[] = []\n let prefix = ''\n let gap = ''\n\n for (const char of chars) {\n const digit = digitOf.get(char)\n if (digit === undefined) {\n gap += char\n } else {\n if (digits === '') {\n prefix = gap\n } else {\n gaps.push(gap)\n }\n gap = ''\n digits += String(digit)\n }\n }\n\n return { digits, gaps, prefix, suffix: digits === '' ? '' : gap }\n}\n\n// The symbols of a locale's format, found with `format` alone.\nfunction symbolsOf(\n locale: string,\n resolved: Intl.ResolvedNumberFormatOptions,\n options: NumberFormatOptions,\n): Symbols {\n const numberingSystem = optionalString(resolved.numberingSystem)\n const numerals = numeralsOf(resolved.locale, numberingSystem)\n const digitOf = new Map(numerals.map((numeral, digit) => [numeral, digit]))\n const scale = resolved.style === 'percent' ? 100 : 1\n\n // 12,345.67 and its negative, in the format's style.\n const probe = new Intl.NumberFormat(\n locale,\n probeOptionsOf(resolved, {\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n }),\n )\n const positive = spansOf(probe.format(PROBE / scale), digitOf)\n const negative = spansOf(probe.format(-PROBE / scale), digitOf)\n const read = positive.digits === PROBE_DIGITS ? positive : undefined\n const decimal = read?.gaps[4] === '' ? undefined : read?.gaps[4]\n const group = read?.gaps[1] === '' ? undefined : read?.gaps[1]\n\n // The sign is what the negative adds on one side of the digits. Added on\n // both, it is an accounting format's brackets, which are text around the\n // number rather than a sign.\n const before = differenceOf(positive.prefix, negative.prefix)\n const after = differenceOf(positive.suffix, negative.suffix)\n const signedBefore = before.added !== '' && after.added === ''\n const signedAfter = after.added !== '' && before.added === ''\n const minusSign =\n signOf(signedBefore ? before.added : signedAfter ? after.added : '') || '-'\n\n // A plus sign, where the format writes one.\n let plusSign: string | undefined\n if (\n options.signDisplay === 'always' ||\n options.signDisplay === 'exceptZero'\n ) {\n const signed = spansOf(\n new Intl.NumberFormat(\n locale,\n probeOptionsOf(resolved, {\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n signDisplay: 'always',\n }),\n ).format(PROBE / scale),\n digitOf,\n )\n const plusBefore = differenceOf(positive.prefix, signed.prefix).added\n const plusAfter = differenceOf(positive.suffix, signed.suffix).added\n plusSign = signOf(plusBefore === '' ? plusAfter : plusBefore) || '+'\n }\n\n // The plural forms of the format, whose text can differ from one number to\n // the next: \"1 day\" and \"2 days\".\n const plurals = new Intl.NumberFormat(\n locale,\n probeOptionsOf(resolved, {\n maximumFractionDigits: 3,\n minimumFractionDigits: 0,\n }),\n )\n const pluralTexts = PLURAL_NUMBERS.map((value) => plurals.format(value))\n const noNumeralUnits = pluralTexts\n .map((text, at) => ({ text: text.trim(), value: PLURAL_NUMBERS[at] ?? 0 }))\n .filter(({ text }) => !Array.from(text).some((char) => digitOf.has(char)))\n .map(({ text, value }) => ({ unit: text, value }))\n\n // Everything around the digits that is not a sign, in pieces between white\n // space, as `formatToParts` hands it over in parts. An accounting format's\n // brackets are pieces of their own, apart from the currency beside them.\n const around = [\n positive.prefix,\n positive.suffix,\n before.rest,\n after.rest,\n ...(signedBefore || signedAfter ? [] : [before.added, after.added]),\n ...pluralTexts.flatMap((text) => {\n const spans = spansOf(text, digitOf)\n return spans.digits === '' ? [] : [spans.prefix, spans.suffix]\n }),\n ]\n const pieces = [\n ...new Set(\n around\n .flatMap((text) => text.split(SPACING_RUN))\n .filter((piece) => piece !== '' && piece !== minusSign)\n .map(escapeRegex),\n ),\n ].toSorted((a, b) => b.length - a.length)\n const literals = new RegExp([...pieces, `[${SPACING}]`].join('|'), 'gu')\n\n const indexes = new Map(numerals.map((numeral, digit) => [numeral, digit]))\n\n return {\n decimal,\n group,\n index: (numeral) => String(indexes.get(numeral)),\n literals,\n minusSign,\n noNumeralUnits,\n numeral: new RegExp(`[${numerals.join('')}]`, 'gu'),\n numerals,\n plusSign,\n }\n}\n\n// A rounding increment needs the fraction digits it rounds to on both\n// sides, which the parser it ports fills in where they are left out.\nfunction withRoundingIncrement(\n given: NumberFormatOptions,\n): NumberFormatOptions {\n const options = { ...given }\n if (options.roundingIncrement !== 1 && options.roundingIncrement != null) {\n if (\n options.maximumFractionDigits == null &&\n options.minimumFractionDigits == null\n ) {\n options.maximumFractionDigits = 0\n options.minimumFractionDigits = 0\n } else {\n options.maximumFractionDigits ??= options.minimumFractionDigits\n options.minimumFractionDigits ??= options.maximumFractionDigits\n }\n }\n return options\n}\n\nexport { NumberParser }\n"],"mappings":"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"}