@kanso-labs/react-native-kanso-ui 0.11.24 → 0.11.26
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/README.md +27 -0
- package/dist/calendar/index.js +105 -41
- package/dist/calendar/index.js.map +1 -1
- package/dist/calendar/styles.js +7 -0
- package/dist/calendar/styles.js.map +1 -1
- package/dist/components/calendar/index.d.ts +2 -2
- package/dist/components/calendar/index.js.map +1 -1
- package/dist/components/carousel/index.d.ts +24 -3
- package/dist/components/carousel/index.js +58 -35
- package/dist/components/carousel/index.js.map +1 -1
- package/dist/components/color-picker/index.js +98 -93
- package/dist/components/color-picker/index.js.map +1 -1
- package/dist/components/dialog/index.js +7 -2
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/range-calendar/index.d.ts +2 -2
- package/dist/components/range-calendar/index.js.map +1 -1
- package/dist/components/search-view/index.js.map +1 -1
- package/dist/components/segmented-button/index.js +108 -88
- package/dist/components/segmented-button/index.js.map +1 -1
- package/dist/components/sheet/index.js +8 -4
- package/dist/components/sheet/index.js.map +1 -1
- package/dist/components/table/index.js +1 -0
- package/dist/components/table/index.js.map +1 -1
- package/dist/field/index.d.ts +1 -1
- package/dist/field/index.js +112 -161
- package/dist/field/index.js.map +1 -1
- package/dist/field/styles.js +4 -0
- package/dist/field/styles.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/number/parser.js +3 -3
- package/dist/number/parser.js.map +1 -1
- package/dist/overlay/keyboard.js +100 -27
- package/dist/overlay/keyboard.js.map +1 -1
- package/dist/segments/index.js +1 -1
- package/dist/segments/index.js.map +1 -1
- package/package.json +15 -11
|
@@ -1 +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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"}
|
|
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","reverse","key","Object","entries","sort","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 ).reverse()\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 .sort(([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 ].sort((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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"}
|
package/dist/overlay/keyboard.js
CHANGED
|
@@ -1,56 +1,129 @@
|
|
|
1
1
|
import { c } from "react/compiler-runtime";
|
|
2
|
-
import { Keyboard, Platform } from "react-native";
|
|
2
|
+
import { Dimensions, Keyboard, Platform } from "react-native";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
// src/overlay/keyboard.ts
|
|
5
|
+
let loading;
|
|
6
|
+
function currentTop() {
|
|
7
|
+
return Platform.OS === "web" ? null : topOf(Keyboard.metrics());
|
|
8
|
+
}
|
|
9
|
+
async function load() {
|
|
10
|
+
try {
|
|
11
|
+
return await import(
|
|
12
|
+
/* @vite-ignore */
|
|
13
|
+
"react-native-keyboard-controller"
|
|
14
|
+
);
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function loadController() {
|
|
20
|
+
loading ??= load();
|
|
21
|
+
return loading;
|
|
22
|
+
}
|
|
5
23
|
function topOf(metrics) {
|
|
6
24
|
return metrics === void 0 || metrics === null || metrics.height === 0 ? null : metrics.screenY;
|
|
7
25
|
}
|
|
8
26
|
/**
|
|
9
|
-
*
|
|
10
|
-
* while no keyboard is shown
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* put the bottom of the list under the keys.
|
|
27
|
+
* How far the software keyboard reaches up over a window that fills the
|
|
28
|
+
* screen, in dp, or 0 while no keyboard is shown. A sheet or a dialog pads
|
|
29
|
+
* its content's bottom by this much, so what it holds stays above the
|
|
30
|
+
* keyboard. `enabled` false watches nothing and answers 0.
|
|
14
31
|
*/
|
|
15
|
-
function
|
|
32
|
+
function useKeyboardInset(t0) {
|
|
16
33
|
const $ = c(2);
|
|
17
|
-
const
|
|
18
|
-
let t0;
|
|
34
|
+
const top = useKeyboardTop(t0 === void 0 ? true : t0);
|
|
19
35
|
let t1;
|
|
20
|
-
if ($[0]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
$[0] = t0;
|
|
36
|
+
if ($[0] !== top) {
|
|
37
|
+
t1 = top === null ? 0 : Math.max(0, Dimensions.get("screen").height - top);
|
|
38
|
+
$[0] = top;
|
|
24
39
|
$[1] = t1;
|
|
40
|
+
} else t1 = $[1];
|
|
41
|
+
return t1;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Where the software keyboard's top edge is on the screen, in dp, or null
|
|
45
|
+
* while no keyboard is shown. `enabled` false watches nothing and answers
|
|
46
|
+
* null.
|
|
47
|
+
*/
|
|
48
|
+
function useKeyboardTop(t0) {
|
|
49
|
+
const $ = c(5);
|
|
50
|
+
const enabled = t0 === void 0 ? true : t0;
|
|
51
|
+
let t1;
|
|
52
|
+
if ($[0] !== enabled) {
|
|
53
|
+
t1 = () => enabled ? currentTop() : null;
|
|
54
|
+
$[0] = enabled;
|
|
55
|
+
$[1] = t1;
|
|
56
|
+
} else t1 = $[1];
|
|
57
|
+
const [top, setTop] = useState(t1);
|
|
58
|
+
const [watching, setWatching] = useState(enabled);
|
|
59
|
+
if (watching !== enabled) {
|
|
60
|
+
setWatching(enabled);
|
|
61
|
+
setTop(enabled ? currentTop() : null);
|
|
62
|
+
}
|
|
63
|
+
let t2;
|
|
64
|
+
let t3;
|
|
65
|
+
if ($[2] !== enabled) {
|
|
66
|
+
t2 = () => enabled ? watchKeyboard(setTop) : void 0;
|
|
67
|
+
t3 = [enabled];
|
|
68
|
+
$[2] = enabled;
|
|
69
|
+
$[3] = t2;
|
|
70
|
+
$[4] = t3;
|
|
25
71
|
} else {
|
|
26
|
-
|
|
27
|
-
|
|
72
|
+
t2 = $[3];
|
|
73
|
+
t3 = $[4];
|
|
28
74
|
}
|
|
29
|
-
useEffect(
|
|
75
|
+
useEffect(t2, t3);
|
|
30
76
|
return top;
|
|
31
77
|
}
|
|
32
78
|
/**
|
|
33
|
-
* Hands `listener` where the software keyboard's top edge is
|
|
34
|
-
* time the keyboard moves, and returns what stops it. iOS
|
|
35
|
-
* the keyboard starts to move, and Android once it has
|
|
36
|
-
*
|
|
37
|
-
* and
|
|
79
|
+
* Hands `listener` where the software keyboard's top edge is on the screen,
|
|
80
|
+
* or null, each time the keyboard moves, and returns what stops it. iOS
|
|
81
|
+
* reports a frame as the keyboard starts to move, and Android once it has
|
|
82
|
+
* arrived or gone. On Android react-native-keyboard-controller reports it as
|
|
83
|
+
* well, from whichever window holds the focused field, and where both report
|
|
84
|
+
* a keyboard the higher edge wins. React Native Web has no keyboard to
|
|
85
|
+
* report, and reports nothing.
|
|
38
86
|
*/
|
|
39
|
-
function _temp() {
|
|
40
|
-
return Platform.OS === "web" ? null : topOf(Keyboard.metrics());
|
|
41
|
-
}
|
|
42
87
|
function watchKeyboard(listener) {
|
|
88
|
+
let native = null;
|
|
89
|
+
let controlled = null;
|
|
90
|
+
let stopped = false;
|
|
91
|
+
const report = () => {
|
|
92
|
+
const tops = [native, controlled].filter((top) => top !== null);
|
|
93
|
+
listener(tops.length === 0 ? null : Math.min(...tops));
|
|
94
|
+
};
|
|
43
95
|
const moved = (event) => {
|
|
44
|
-
|
|
96
|
+
native = topOf(event.endCoordinates);
|
|
97
|
+
report();
|
|
45
98
|
};
|
|
46
99
|
const hidden = () => {
|
|
47
|
-
|
|
100
|
+
native = null;
|
|
101
|
+
report();
|
|
48
102
|
};
|
|
49
103
|
const subscriptions = Platform.OS === "ios" ? [Keyboard.addListener("keyboardWillChangeFrame", moved), Keyboard.addListener("keyboardWillHide", hidden)] : [Keyboard.addListener("keyboardDidShow", moved), Keyboard.addListener("keyboardDidHide", hidden)];
|
|
104
|
+
const shown = ({ height }) => {
|
|
105
|
+
controlled = height > 0 ? Dimensions.get("screen").height - height : null;
|
|
106
|
+
native = controlled === null ? null : native;
|
|
107
|
+
report();
|
|
108
|
+
};
|
|
109
|
+
const gone = () => {
|
|
110
|
+
controlled = null;
|
|
111
|
+
native = null;
|
|
112
|
+
report();
|
|
113
|
+
};
|
|
114
|
+
const listen = async () => {
|
|
115
|
+
const controller = await loadController();
|
|
116
|
+
if (controller === null || stopped) return;
|
|
117
|
+
try {
|
|
118
|
+
subscriptions.push(controller.KeyboardEvents.addListener("keyboardWillShow", shown), controller.KeyboardEvents.addListener("keyboardDidShow", shown), controller.KeyboardEvents.addListener("keyboardWillHide", gone), controller.KeyboardEvents.addListener("keyboardDidHide", gone));
|
|
119
|
+
} catch {}
|
|
120
|
+
};
|
|
121
|
+
if (Platform.OS === "android") listen();
|
|
50
122
|
return () => {
|
|
123
|
+
stopped = true;
|
|
51
124
|
for (const subscription of subscriptions) subscription.remove();
|
|
52
125
|
};
|
|
53
126
|
}
|
|
54
|
-
export { useKeyboardTop, watchKeyboard };
|
|
127
|
+
export { useKeyboardInset, useKeyboardTop, watchKeyboard };
|
|
55
128
|
|
|
56
129
|
//# sourceMappingURL=keyboard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.js","names":["KeyboardEvent","KeyboardMetrics","useEffect","useState","Keyboard","Platform","topOf","metrics","undefined","height","screenY","
|
|
1
|
+
{"version":3,"file":"keyboard.js","names":["KeyboardEvent","KeyboardMetrics","useEffect","useState","Dimensions","Keyboard","Platform","Controller","loading","Promise","currentTop","OS","topOf","metrics","load","loadController","undefined","height","screenY","useKeyboardInset","t0","$","_c","enabled","top","useKeyboardTop","t1","Math","max","get","setTop","watching","setWatching","t2","t3","watchKeyboard","listener","native","controlled","stopped","report","tops","filter","length","min","moved","event","endCoordinates","hidden","subscriptions","addListener","shown","gone","listen","controller","push","KeyboardEvents","subscription","remove","_c"],"sources":["../../src/overlay/keyboard.ts"],"sourcesContent":["import type { KeyboardEvent, KeyboardMetrics } from 'react-native'\n\nimport { useEffect, useState } from 'react'\nimport { Dimensions, Keyboard, Platform } from 'react-native'\n\ntype Controller = typeof import('react-native-keyboard-controller')\n\n// Android reports the keyboard to React Native's `Keyboard` only from the\n// app's own window, and a sheet, a dialog or a popover is a `Modal`, which is\n// a window of its own: a field focused there moves the keyboard and reports\n// nothing. react-native-keyboard-controller reports it from every window,\n// once the app mounts its `KeyboardProvider`. It is an optional peer, so it\n// is imported where its absence can be caught, as src/clipboard/index.ts\n// imports expo-clipboard, and an app without it keeps React Native's reports\n// alone. The import settles once, and to `null` once it has failed.\nlet loading: Promise<Controller | null> | undefined\n\n// Where the keyboard's top edge is now, as far as React Native has heard.\nfunction currentTop(): null | number {\n return Platform.OS === 'web' ? null : topOf(Keyboard.metrics())\n}\n\nasync function load(): Promise<Controller | null> {\n try {\n return await import(/* @vite-ignore */ 'react-native-keyboard-controller')\n } catch {\n return null\n }\n}\n\nasync function loadController(): Promise<Controller | null> {\n loading ??= load()\n return loading\n}\n\n// A keyboard reported with no height covers nothing.\nfunction topOf(metrics: KeyboardMetrics | null | undefined): null | number {\n return metrics === undefined || metrics === null || metrics.height === 0\n ? null\n : metrics.screenY\n}\n\n/**\n * How far the software keyboard reaches up over a window that fills the\n * screen, in dp, or 0 while no keyboard is shown. A sheet or a dialog pads\n * its content's bottom by this much, so what it holds stays above the\n * keyboard. `enabled` false watches nothing and answers 0.\n */\nfunction useKeyboardInset(enabled = true): number {\n const top = useKeyboardTop(enabled)\n\n return top === null ? 0 : Math.max(0, Dimensions.get('screen').height - top)\n}\n\n/**\n * Where the software keyboard's top edge is on the screen, in dp, or null\n * while no keyboard is shown. `enabled` false watches nothing and answers\n * null.\n */\nfunction useKeyboardTop(enabled = true): null | number {\n const [top, setTop] = useState(() => (enabled ? currentTop() : null))\n const [watching, setWatching] = useState(enabled)\n\n // Nothing is heard while it is not watched, so it starts again from where\n // the keyboard is now.\n if (watching !== enabled) {\n setWatching(enabled)\n setTop(enabled ? currentTop() : null)\n }\n\n useEffect(() => (enabled ? watchKeyboard(setTop) : undefined), [enabled])\n\n return top\n}\n\n/**\n * Hands `listener` where the software keyboard's top edge is on the screen,\n * or null, each time the keyboard moves, and returns what stops it. iOS\n * reports a frame as the keyboard starts to move, and Android once it has\n * arrived or gone. On Android react-native-keyboard-controller reports it as\n * well, from whichever window holds the focused field, and where both report\n * a keyboard the higher edge wins. React Native Web has no keyboard to\n * report, and reports nothing.\n */\nfunction watchKeyboard(listener: (top: null | number) => void): () => void {\n let native: null | number = null\n let controlled: null | number = null\n let stopped = false\n\n const report = () => {\n const tops = [native, controlled].filter((top) => top !== null)\n listener(tops.length === 0 ? null : Math.min(...tops))\n }\n const moved = (event: KeyboardEvent) => {\n native = topOf(event.endCoordinates)\n report()\n }\n const hidden = () => {\n native = null\n report()\n }\n const subscriptions =\n Platform.OS === 'ios'\n ? [\n Keyboard.addListener('keyboardWillChangeFrame', moved),\n Keyboard.addListener('keyboardWillHide', hidden),\n ]\n : [\n Keyboard.addListener('keyboardDidShow', moved),\n Keyboard.addListener('keyboardDidHide', hidden),\n ]\n\n // The controller sees every window, so its keyboard going away is the\n // keyboard gone, whatever React Native last heard from the app's own.\n const shown = ({ height }: { readonly height: number }) => {\n controlled = height > 0 ? Dimensions.get('screen').height - height : null\n native = controlled === null ? null : native\n report()\n }\n const gone = () => {\n controlled = null\n native = null\n report()\n }\n const listen = async () => {\n const controller = await loadController()\n\n if (controller === null || stopped) {\n return\n }\n\n // A controller installed without its native half throws as it is read,\n // which leaves React Native's reports alone.\n try {\n subscriptions.push(\n controller.KeyboardEvents.addListener('keyboardWillShow', shown),\n controller.KeyboardEvents.addListener('keyboardDidShow', shown),\n controller.KeyboardEvents.addListener('keyboardWillHide', gone),\n controller.KeyboardEvents.addListener('keyboardDidHide', gone),\n )\n } catch {\n // Nothing to watch.\n }\n }\n\n if (Platform.OS === 'android') {\n void listen()\n }\n\n return () => {\n stopped = true\n\n for (const subscription of subscriptions) {\n subscription.remove()\n }\n }\n}\n\nexport { useKeyboardInset, useKeyboardTop, watchKeyboard }\n"],"mappings":"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"}
|
package/dist/segments/index.js
CHANGED