@allxsmith/bestax-bulma 5.53.0 → 5.54.0

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 (59) hide show
  1. package/dist/esm/components/Avatars.js +7 -2
  2. package/dist/esm/components/Avatars.js.map +1 -1
  3. package/dist/esm/components/Badge.js +7 -2
  4. package/dist/esm/components/Badge.js.map +1 -1
  5. package/dist/esm/components/Command.js +19 -9
  6. package/dist/esm/components/Command.js.map +1 -1
  7. package/dist/esm/components/Pagination.js +9 -1
  8. package/dist/esm/components/Pagination.js.map +1 -1
  9. package/dist/esm/components/Steps.js +5 -1
  10. package/dist/esm/components/Steps.js.map +1 -1
  11. package/dist/esm/elements/RingProgress.js +6 -1
  12. package/dist/esm/elements/RingProgress.js.map +1 -1
  13. package/dist/esm/form/Autocomplete.js +4 -0
  14. package/dist/esm/form/Autocomplete.js.map +1 -1
  15. package/dist/esm/form/Combobox.js +7 -2
  16. package/dist/esm/form/Combobox.js.map +1 -1
  17. package/dist/esm/form/File.js +4 -1
  18. package/dist/esm/form/File.js.map +1 -1
  19. package/dist/esm/form/Rate.js +9 -1
  20. package/dist/esm/form/Rate.js.map +1 -1
  21. package/dist/esm/form/Slider.js +7 -4
  22. package/dist/esm/form/Slider.js.map +1 -1
  23. package/dist/esm/form/Taginput.js +9 -3
  24. package/dist/esm/form/Taginput.js.map +1 -1
  25. package/dist/esm/helpers/LocaleProvider.js +9 -6
  26. package/dist/esm/helpers/LocaleProvider.js.map +1 -1
  27. package/dist/esm/helpers/localeFormat.js +108 -0
  28. package/dist/esm/helpers/localeFormat.js.map +1 -0
  29. package/dist/index.cjs +435 -276
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/types/components/Avatars.d.ts +1 -1
  32. package/dist/types/components/Badge.d.ts +1 -1
  33. package/dist/types/components/Command.d.ts +4 -2
  34. package/dist/types/components/Pagination.d.ts +3 -0
  35. package/dist/types/components/Steps.d.ts +4 -1
  36. package/dist/types/elements/RingProgress.d.ts +3 -2
  37. package/dist/types/form/Autocomplete.d.ts +6 -1
  38. package/dist/types/form/Combobox.d.ts +3 -2
  39. package/dist/types/form/File.d.ts +2 -1
  40. package/dist/types/form/Rate.d.ts +4 -1
  41. package/dist/types/form/Slider.d.ts +9 -2
  42. package/dist/types/form/Taginput.d.ts +8 -2
  43. package/dist/types/helpers/LocaleProvider.d.ts +9 -6
  44. package/dist/types/helpers/localeFormat.d.ts +26 -0
  45. package/dist/types-cjs/components/Avatars.d.ts +1 -1
  46. package/dist/types-cjs/components/Badge.d.ts +1 -1
  47. package/dist/types-cjs/components/Command.d.ts +4 -2
  48. package/dist/types-cjs/components/Pagination.d.ts +3 -0
  49. package/dist/types-cjs/components/Steps.d.ts +4 -1
  50. package/dist/types-cjs/elements/RingProgress.d.ts +3 -2
  51. package/dist/types-cjs/form/Autocomplete.d.ts +6 -1
  52. package/dist/types-cjs/form/Combobox.d.ts +3 -2
  53. package/dist/types-cjs/form/File.d.ts +2 -1
  54. package/dist/types-cjs/form/Rate.d.ts +4 -1
  55. package/dist/types-cjs/form/Slider.d.ts +9 -2
  56. package/dist/types-cjs/form/Taginput.d.ts +8 -2
  57. package/dist/types-cjs/helpers/LocaleProvider.d.ts +9 -6
  58. package/dist/types-cjs/helpers/localeFormat.d.ts +26 -0
  59. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1792,6 +1792,360 @@ function flattenChildren(children, keyPrefix = '') {
1792
1792
  });
1793
1793
  }
1794
1794
 
1795
+ // INTERNAL: deliberately not exported from src/index.ts. What a locale says
1796
+ // about its direction, read from `Intl.Locale` where the engine has the data,
1797
+ // and about its week, read from a copy of CLDR's week data.
1798
+ /**
1799
+ * Scripts written right to left: every script for which ICU's text info
1800
+ * says `rtl`, as Node reported it, and `Aran`, the Nastaliq form of Arabic
1801
+ * that WebKit fills in for Urdu. Read only where the engine has no text info
1802
+ * of its own, which includes Firefox before 153.
1803
+ */
1804
+ const RTL_SCRIPTS = ' Adlm Arab Aran Armi Avst Chrs Cprt Elym Gara Hatr Hebr Hung Khar Lydi ' +
1805
+ 'Mand Mani Mend Merc Mero Narb Nbat Nkoo Orkh Ougr Palm Phli Phlp Phnx ' +
1806
+ 'Prti Rohg Samr Sarb Sidt Sogd Sogo Syrc Thaa Yezi ';
1807
+ /**
1808
+ * Widely used languages whose usual script reads right to left, for an engine
1809
+ * that can't fill in a locale's script with `maximize()`.
1810
+ */
1811
+ const RTL_LANGUAGES = ' ar ckb dv fa he iw ji ks mzn nqo pnb ps sd syr ug ur yi ';
1812
+ /**
1813
+ * The regions whose week doesn't start on Monday, by the day it starts on
1814
+ * (0 = Sunday, 5 = Friday, 6 = Saturday), from CLDR 48's week data as Node
1815
+ * reported it. The library reads this rather than `Intl.Locale`'s week info
1816
+ * because engines disagree: Firefox before 153 has none, and WebKit's differs
1817
+ * from Node's, Chromium's and current Firefox's for China, Algeria, Jordan and
1818
+ * Iceland among others, so an inline calendar rendered on the server would
1819
+ * fail to hydrate there. With one table, the server and every browser agree.
1820
+ */
1821
+ const WEEK_STARTS = [
1822
+ [
1823
+ 0,
1824
+ ' AG AS BD BR BS BT BU BW BZ CA CO DM DO ET GT GU HK HN ID IL IN IS JM JP ' +
1825
+ 'KE KH KR LA MH MM MO MT MX MZ NI NP PA PE PH PK PR PT PY RH SA SG SV TH ' +
1826
+ 'TT TW UM US VE VI WS YD YE ZA ZW ',
1827
+ ],
1828
+ [5, ' MV '],
1829
+ [6, ' AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY '],
1830
+ ];
1831
+ /** Whether a space-separated list, padded with spaces, holds `code`. */
1832
+ const listed = (list, code) => list.includes(` ${code} `);
1833
+ /** The `-u-fw-` keyword's values, by the day they name. */
1834
+ const FW_DAYS = {
1835
+ sun: 0,
1836
+ mon: 1,
1837
+ tue: 2,
1838
+ wed: 3,
1839
+ thu: 4,
1840
+ fri: 5,
1841
+ sat: 6,
1842
+ };
1843
+ /**
1844
+ * The canonical form of a BCP 47 tag (`"en-us"` becomes `"en-US"`), or
1845
+ * `undefined` for an empty or missing one. Throws a `RangeError` for a tag
1846
+ * `Intl` refuses, as `Intl.DateTimeFormat` would.
1847
+ */
1848
+ function canonicalLocale(tag) {
1849
+ if (!tag)
1850
+ return undefined;
1851
+ return Intl.getCanonicalLocales(tag)[0];
1852
+ }
1853
+ /**
1854
+ * The direction a locale's script is written in: from `Intl.Locale`'s text
1855
+ * info, else from the script `maximize()` fills in, else from the language.
1856
+ *
1857
+ * @param locale - A canonical tag, as `canonicalLocale` returns.
1858
+ */
1859
+ function localeDirection(locale) {
1860
+ const intlLocale = new Intl.Locale(locale);
1861
+ const info = intlLocale;
1862
+ const direction = typeof info.getTextInfo === 'function'
1863
+ ? info.getTextInfo().direction
1864
+ : info.textInfo?.direction;
1865
+ if (direction === 'rtl' || direction === 'ltr')
1866
+ return direction;
1867
+ if (typeof intlLocale.maximize === 'function') {
1868
+ const script = intlLocale.maximize().script;
1869
+ return script && listed(RTL_SCRIPTS, script) ? 'rtl' : 'ltr';
1870
+ }
1871
+ return listed(RTL_LANGUAGES, intlLocale.language) ? 'rtl' : 'ltr';
1872
+ }
1873
+ /**
1874
+ * The day a locale's week starts on, 0 for Sunday, as `getWeekInfo()` reads
1875
+ * it: the tag's `-u-fw-` keyword, else the region its `-u-rg-` keyword names,
1876
+ * else its own region or the one `maximize()` fills in, looked up in CLDR's
1877
+ * week data, where a region not listed starts on Monday.
1878
+ *
1879
+ * @param locale - A canonical tag, as `canonicalLocale` returns.
1880
+ */
1881
+ function localeFirstDay(locale) {
1882
+ const fw = /-u(?:-[a-z0-9]{2,8})*?-fw-([a-z]{3})(?=-|$)/i.exec(locale);
1883
+ if (fw && fw[1].toLowerCase() in FW_DAYS)
1884
+ return FW_DAYS[fw[1].toLowerCase()];
1885
+ const rg = /-u(?:-[a-z0-9]{2,8})*?-rg-([a-z]{2})[a-z0-9]{1,4}(?=-|$)/i.exec(locale);
1886
+ const intlLocale = new Intl.Locale(locale);
1887
+ const region = rg
1888
+ ? rg[1].toUpperCase()
1889
+ : typeof intlLocale.maximize === 'function'
1890
+ ? intlLocale.maximize().region
1891
+ : intlLocale.region;
1892
+ if (region) {
1893
+ for (const [day, regions] of WEEK_STARTS) {
1894
+ if (listed(regions, region))
1895
+ return day;
1896
+ }
1897
+ }
1898
+ return 1;
1899
+ }
1900
+
1901
+ const LocaleContext = React.createContext(null);
1902
+ /** The nearest provider's wrapper element, for `LocalePortalScope` to test targets against. */
1903
+ const LocaleElementContext = React.createContext(null);
1904
+ /** A tag in canonical form, or `undefined`, warning about one `Intl` refuses. */
1905
+ function validLocale(tag) {
1906
+ try {
1907
+ return canonicalLocale(tag);
1908
+ }
1909
+ catch {
1910
+ warnOnce(`locale-provider-invalid:${tag}`, `[bestax-bulma] <LocaleProvider locale="${tag}">: not a language ` +
1911
+ 'tag Intl accepts, so it is ignored. Use a BCP 47 tag such as ' +
1912
+ '"en-US", with a hyphen rather than an underscore.');
1913
+ return undefined;
1914
+ }
1915
+ }
1916
+ /**
1917
+ * Sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.
1918
+ *
1919
+ * The wrapper carries `dir` and `lang`, so CSS and the components that read
1920
+ * the computed direction follow it, as they follow `<html dir>`. A `locale`
1921
+ * alone sets the direction of its script, and a `dir` sets the direction
1922
+ * whatever the locale. A nested provider keeps whatever it leaves unset.
1923
+ *
1924
+ * Inside it, the date and time pickers take its `locale` unless given their
1925
+ * own, and their week starts on the first day of the locale they use unless
1926
+ * `firstDayOfWeek` is set, and a picker with a `locale` of its own is read
1927
+ * like a nested provider. With a `locale`, the numbers the library writes,
1928
+ * such as page numbers and badge counts, follow it, and so does the
1929
+ * filtering in `Combobox`, `Autocomplete`, `Taginput` and `Command`, which then ignores
1930
+ * accents where the language treats letters as the same. The library's
1931
+ * portaled content, such as a `Popover` panel, a `Modal` with `portal`, a
1932
+ * `Toast` or a `Portal`'s children, keeps the same `dir` and `lang` though
1933
+ * it renders outside the wrapper: in a container outside the wrapper, it
1934
+ * sits in a `display: contents` element that carries them. Without a
1935
+ * provider none of this changes.
1936
+ *
1937
+ * @function
1938
+ * @param {LocaleProviderProps} props - Props for the LocaleProvider.
1939
+ * @returns {JSX.Element} The wrapper, inside the context.
1940
+ *
1941
+ * @example
1942
+ * <LocaleProvider locale="ar-EG">
1943
+ * <App />
1944
+ * </LocaleProvider>
1945
+ */
1946
+ const LocaleProvider = React.forwardRef(({ locale: localeProp, dir: dirProp, className, children, ...props }, ref) => {
1947
+ const outer = React.useContext(LocaleContext);
1948
+ const ownLocale = React.useMemo(() => validLocale(localeProp), [localeProp]);
1949
+ const ownLocaleDir = React.useMemo(() => (ownLocale ? localeDirection(ownLocale) : undefined), [ownLocale]);
1950
+ const locale = ownLocale || outer?.locale;
1951
+ const dir = dirProp || ownLocaleDir || outer?.dir;
1952
+ const value = React.useMemo(() => ({ locale, dir }), [locale, dir]);
1953
+ const { bulmaHelperClasses, rest } = useBulmaClasses(props);
1954
+ // The wrapper, for portaled content to tell whether its target is inside
1955
+ // it, and the caller's ref. A callback ref's cleanup is held and run on
1956
+ // detach, as Toast and Modal do, since React 18 discards the return value.
1957
+ const elementRef = React.useRef(null);
1958
+ const consumerCleanupRef = React.useRef(null);
1959
+ const setElement = React.useCallback((node) => {
1960
+ elementRef.current = node;
1961
+ if (typeof ref === 'function') {
1962
+ if (node === null) {
1963
+ const consumerCleanup = consumerCleanupRef.current;
1964
+ consumerCleanupRef.current = null;
1965
+ if (consumerCleanup)
1966
+ consumerCleanup();
1967
+ else
1968
+ ref(null);
1969
+ return;
1970
+ }
1971
+ const cleanup = ref(node);
1972
+ consumerCleanupRef.current =
1973
+ typeof cleanup === 'function' ? cleanup : null;
1974
+ }
1975
+ else if (ref) {
1976
+ ref.current = node;
1977
+ }
1978
+ }, [ref]);
1979
+ return (jsxRuntime.jsx(LocaleContext.Provider, { value: value, children: jsxRuntime.jsx(LocaleElementContext.Provider, { value: elementRef, children: jsxRuntime.jsx("div", { ref: setElement, className: classNames(bulmaHelperClasses, className) || undefined, ...rest, dir: dir, lang: locale, children: children }) }) }));
1980
+ });
1981
+ LocaleProvider.displayName = 'LocaleProvider';
1982
+ /** What `useLocale` returns outside a provider, the same object each time. */
1983
+ const noLocale = {};
1984
+ /**
1985
+ * The locale and direction the nearest `LocaleProvider` sets, for an app's own `Intl` calls or its own portaled content; both are `undefined` outside one.
1986
+ *
1987
+ * It isn't the page's direction: with no provider, or one that sets no
1988
+ * direction, the page's `<html dir>` still decides. To act on the direction
1989
+ * an element is laid out in, read `getComputedStyle(element).direction`, as
1990
+ * the library's components do.
1991
+ *
1992
+ * @function
1993
+ * @returns {LocaleContextValue} The nearest provider's `locale` and `dir`.
1994
+ *
1995
+ * @example
1996
+ * const { locale } = useLocale();
1997
+ * const price = new Intl.NumberFormat(locale, {
1998
+ * style: 'currency',
1999
+ * currency: 'EUR',
2000
+ * }).format(12.5);
2001
+ */
2002
+ function useLocale() {
2003
+ return React.useContext(LocaleContext) ?? noLocale;
2004
+ }
2005
+ /**
2006
+ * INTERNAL, deliberately not exported from `src/index.ts`. The nearest
2007
+ * provider's settings, or `null` outside any provider, so a caller can tell
2008
+ * "no provider" from "a provider that sets nothing".
2009
+ */
2010
+ function useLocaleScope() {
2011
+ return React.useContext(LocaleContext);
2012
+ }
2013
+ const displayContents = { display: 'contents' };
2014
+ /**
2015
+ * INTERNAL, deliberately not exported from `src/index.ts`. Keeps the `dir`
2016
+ * and `lang` of the nearest provider, or the `scope` given in their place,
2017
+ * on content the library portals into `target`, which has left the
2018
+ * provider's wrapper behind.
2019
+ *
2020
+ * A target inside the provider's own wrapper gets the content as it is: it
2021
+ * inherits from the wrapper, and follows it when the provider changes.
2022
+ * Content that must be its container's direct child, a `<tr>` portaled into
2023
+ * a `<tbody>` there, stays one. Any other target, `document.body` included,
2024
+ * gets the content inside a `display: contents` element carrying the
2025
+ * values, which adds no box. So does content with a `scope` of its own, a
2026
+ * picker's panel, since the provider's values aren't its own.
2027
+ *
2028
+ * Which of the two is decided once, when the content mounts, and kept while
2029
+ * it stays: switching between them would put a different element in its
2030
+ * place and remount everything inside, losing typed text, focus and timers.
2031
+ * A change of locale or direction updates the wrapper's attributes instead.
2032
+ * A target is never left bare because something else, such as `<html>`,
2033
+ * happens to carry the same values, since that can stop being true without
2034
+ * the content remounting. Outside a provider it renders the children alone,
2035
+ * so nothing changes there.
2036
+ */
2037
+ function LocalePortalScope({ children, target, scope, }) {
2038
+ const provider = React.useContext(LocaleContext);
2039
+ const element = React.useContext(LocaleElementContext);
2040
+ const [wrap] = React.useState(() => scope !== undefined || !element?.current?.contains(target));
2041
+ if (!provider || !wrap)
2042
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
2043
+ const values = scope ?? provider;
2044
+ return (jsxRuntime.jsx("div", { dir: values.dir, lang: values.locale, style: displayContents, children: children }));
2045
+ }
2046
+
2047
+ // INTERNAL: deliberately not exported from src/index.ts. Number formatting
2048
+ // and text matching in a LocaleProvider's locale. Both return `null` outside
2049
+ // a provider that gives a locale, so each caller keeps the formatting and the
2050
+ // matching it has always had there.
2051
+ /** A combining mark: an accent, a vowel sign or a point written on a letter. */
2052
+ const MARK = /\p{M}/u;
2053
+ /**
2054
+ * The locale a component formats and matches in: inside a `LocaleProvider`,
2055
+ * the component's own locale when it has one (a picker's `locale`), else the
2056
+ * provider's; outside a provider, none.
2057
+ */
2058
+ function useScopedLocale(own) {
2059
+ const scope = useLocaleScope();
2060
+ if (!scope)
2061
+ return undefined;
2062
+ return scope.locale;
2063
+ }
2064
+ /**
2065
+ * A formatter for numbers shown on screen, in the locale of the
2066
+ * `LocaleProvider` around the component, or `null` outside one that gives a
2067
+ * locale. Formatters are kept per set of options, since building one is the
2068
+ * expensive part.
2069
+ *
2070
+ * @param own - The component's own locale, such as a picker's `locale`,
2071
+ * which wins inside a provider.
2072
+ */
2073
+ function useNumberFormat(own) {
2074
+ const locale = useScopedLocale();
2075
+ return React.useMemo(() => {
2076
+ if (!locale)
2077
+ return null;
2078
+ const formats = new Map();
2079
+ return (value, options) => {
2080
+ const key = options ? JSON.stringify(options) : '';
2081
+ let format = formats.get(key);
2082
+ if (!format) {
2083
+ format = new Intl.NumberFormat(locale, options);
2084
+ formats.set(key, format);
2085
+ }
2086
+ return format.format(value);
2087
+ };
2088
+ }, [locale]);
2089
+ }
2090
+ /**
2091
+ * A matcher for filtering a list by what was typed, in the locale of the
2092
+ * `LocaleProvider` around the component, or `null` outside one that gives a
2093
+ * locale. It compares with `Intl.Collator` at `usage: 'search'` and
2094
+ * `sensitivity: 'base'`, so it ignores case and accents where the language
2095
+ * treats the letters as the same: "cafe" finds "Café", while in Swedish "a"
2096
+ * doesn't find "å", a letter of its own there. Marks the language ignores
2097
+ * count for nothing on either side, so in Arabic محمد finds مُحَمَّد and the
2098
+ * other way round. An empty query, or one of nothing but such marks,
2099
+ * matches everything.
2100
+ */
2101
+ function useLocaleMatcher() {
2102
+ const locale = useScopedLocale();
2103
+ return React.useMemo(() => {
2104
+ if (!locale)
2105
+ return null;
2106
+ const collator = new Intl.Collator(locale, {
2107
+ usage: 'search',
2108
+ sensitivity: 'base',
2109
+ });
2110
+ return (text, query) => {
2111
+ const needle = query.normalize('NFC');
2112
+ if (collator.compare(needle, '') === 0)
2113
+ return true;
2114
+ // Compared by code point, so a slice never splits a surrogate pair.
2115
+ const chars = Array.from(text.normalize('NFC'));
2116
+ const marks = chars.map(char => MARK.test(char));
2117
+ // A slice equal to the needle can be longer or shorter than it: the
2118
+ // marks the collator ignores, Arabic harakat or Hebrew niqqud, take
2119
+ // code points on one side and not the other, and the expansions the
2120
+ // collator makes, "ß" against "ss" or "æ" against "ae", turn one letter
2121
+ // into two. So each slice runs from a letter to just before the next
2122
+ // letter, never cutting a letter from its marks, and the slices from
2123
+ // one start grow until they hold twice the needle's letters, which
2124
+ // those expansions can't get past. That keeps the work proportional to
2125
+ // the text's length, however long a label is, rather than to its
2126
+ // square.
2127
+ const most = 2 * Array.from(needle).filter(char => !MARK.test(char)).length;
2128
+ for (let start = 0; start < chars.length; start++) {
2129
+ if (marks[start])
2130
+ continue;
2131
+ let letters = 0;
2132
+ for (let end = start + 1; end <= chars.length; end++) {
2133
+ if (!marks[end - 1])
2134
+ letters++;
2135
+ if (letters > most)
2136
+ break;
2137
+ if (marks[end])
2138
+ continue;
2139
+ if (collator.compare(chars.slice(start, end).join(''), needle) === 0) {
2140
+ return true;
2141
+ }
2142
+ }
2143
+ }
2144
+ return false;
2145
+ };
2146
+ }, [locale]);
2147
+ }
2148
+
1795
2149
  /**
1796
2150
  * The `Avatars` component renders an overlapping/stacked group of `Avatar`s, the "members" list pattern.
1797
2151
  *
@@ -1806,6 +2160,7 @@ function flattenChildren(children, keyPrefix = '') {
1806
2160
  */
1807
2161
  const AvatarsComponent = ({ className, max, size, shape, spacing = 'md', spaced = false, surplusLabel, style, children, ...props }) => {
1808
2162
  const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });
2163
+ const formatNumber = useNumberFormat();
1809
2164
  // A preset spacing maps to a class; a numeric spacing sets the CSS var inline
1810
2165
  // (mirrors Sidebar's inline --bulma-* width var).
1811
2166
  const isPresetSpacing = typeof spacing === 'string';
@@ -1837,11 +2192,14 @@ const AvatarsComponent = ({ className, max, size, shape, spacing = 'md', spaced
1837
2192
  React.cloneElement(child, {
1838
2193
  ...(size !== undefined ? { size } : {}),
1839
2194
  ...(shape !== undefined ? { shape } : {}),
1840
- })), overflowCount > 0 && (jsxRuntime.jsx(Avatar, { initials: `+${overflowCount}`, alt:
2195
+ })), overflowCount > 0 && (jsxRuntime.jsx(Avatar, { initials: formatNumber
2196
+ ? formatNumber(overflowCount, { signDisplay: 'always' })
2197
+ : `+${overflowCount}`, alt:
1841
2198
  // `||` (not a plain ternary): an empty string from surplusLabel
1842
2199
  // would make the bubble decorative (alt="") and hide the count
1843
2200
  // from assistive tech — fall back to the default label instead.
1844
- surplusLabel?.(overflowCount) || `${overflowCount} more`, size: size, shape: shape, className: surplusClass }))] }));
2201
+ surplusLabel?.(overflowCount) ||
2202
+ `${formatNumber ? formatNumber(overflowCount) : overflowCount} more`, size: size, shape: shape, className: surplusClass }))] }));
1845
2203
  };
1846
2204
  const Avatars = withSubComponents(AvatarsComponent, { Avatar }, 'Avatars');
1847
2205
 
@@ -1891,15 +2249,19 @@ const Badge = ({ className, badgeClassName, content, max = 99, dot = false, show
1891
2249
  // A negative or non-integer max is nonsensical; fall back to the default
1892
2250
  // rather than render e.g. "-1+" (mirrors Avatars' max sanitization).
1893
2251
  const sanitizedMax = Number.isInteger(max) && max >= 0 ? max : 99;
2252
+ const formatNumber = useNumberFormat();
1894
2253
  const displayValue = React.useMemo(() => {
1895
2254
  if (dot || !hasContent)
1896
2255
  return undefined;
1897
2256
  // max only applies to numeric content; any other node renders verbatim.
1898
2257
  if (typeof content === 'number') {
1899
- return content > sanitizedMax ? `${sanitizedMax}+` : String(content);
2258
+ const write = formatNumber ?? String;
2259
+ return content > sanitizedMax
2260
+ ? `${write(sanitizedMax)}+`
2261
+ : write(content);
1900
2262
  }
1901
2263
  return content;
1902
- }, [dot, hasContent, content, sanitizedMax]);
2264
+ }, [dot, hasContent, content, sanitizedMax, formatNumber]);
1903
2265
  // Only primitive content produces a meaningful aria-label; a custom node
1904
2266
  // supplies its own accessible text, so we leave role="status" unlabeled.
1905
2267
  const ariaLabel = typeof displayValue === 'string' || typeof displayValue === 'number'
@@ -3909,255 +4271,6 @@ function useIsHydrated() {
3909
4271
  return React.useSyncExternalStore(subscribeToNothing, getClientSnapshot, getServerSnapshot);
3910
4272
  }
3911
4273
 
3912
- // INTERNAL: deliberately not exported from src/index.ts. What a locale says
3913
- // about its direction, read from `Intl.Locale` where the engine has the data,
3914
- // and about its week, read from a copy of CLDR's week data.
3915
- /**
3916
- * Scripts written right to left: every script for which ICU's text info
3917
- * says `rtl`, as Node reported it, and `Aran`, the Nastaliq form of Arabic
3918
- * that WebKit fills in for Urdu. Read only where the engine has no text info
3919
- * of its own, which includes Firefox before 153.
3920
- */
3921
- const RTL_SCRIPTS = ' Adlm Arab Aran Armi Avst Chrs Cprt Elym Gara Hatr Hebr Hung Khar Lydi ' +
3922
- 'Mand Mani Mend Merc Mero Narb Nbat Nkoo Orkh Ougr Palm Phli Phlp Phnx ' +
3923
- 'Prti Rohg Samr Sarb Sidt Sogd Sogo Syrc Thaa Yezi ';
3924
- /**
3925
- * Widely used languages whose usual script reads right to left, for an engine
3926
- * that can't fill in a locale's script with `maximize()`.
3927
- */
3928
- const RTL_LANGUAGES = ' ar ckb dv fa he iw ji ks mzn nqo pnb ps sd syr ug ur yi ';
3929
- /**
3930
- * The regions whose week doesn't start on Monday, by the day it starts on
3931
- * (0 = Sunday, 5 = Friday, 6 = Saturday), from CLDR 48's week data as Node
3932
- * reported it. The library reads this rather than `Intl.Locale`'s week info
3933
- * because engines disagree: Firefox before 153 has none, and WebKit's differs
3934
- * from Node's, Chromium's and current Firefox's for China, Algeria, Jordan and
3935
- * Iceland among others, so an inline calendar rendered on the server would
3936
- * fail to hydrate there. With one table, the server and every browser agree.
3937
- */
3938
- const WEEK_STARTS = [
3939
- [
3940
- 0,
3941
- ' AG AS BD BR BS BT BU BW BZ CA CO DM DO ET GT GU HK HN ID IL IN IS JM JP ' +
3942
- 'KE KH KR LA MH MM MO MT MX MZ NI NP PA PE PH PK PR PT PY RH SA SG SV TH ' +
3943
- 'TT TW UM US VE VI WS YD YE ZA ZW ',
3944
- ],
3945
- [5, ' MV '],
3946
- [6, ' AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY '],
3947
- ];
3948
- /** Whether a space-separated list, padded with spaces, holds `code`. */
3949
- const listed = (list, code) => list.includes(` ${code} `);
3950
- /** The `-u-fw-` keyword's values, by the day they name. */
3951
- const FW_DAYS = {
3952
- sun: 0,
3953
- mon: 1,
3954
- tue: 2,
3955
- wed: 3,
3956
- thu: 4,
3957
- fri: 5,
3958
- sat: 6,
3959
- };
3960
- /**
3961
- * The canonical form of a BCP 47 tag (`"en-us"` becomes `"en-US"`), or
3962
- * `undefined` for an empty or missing one. Throws a `RangeError` for a tag
3963
- * `Intl` refuses, as `Intl.DateTimeFormat` would.
3964
- */
3965
- function canonicalLocale(tag) {
3966
- if (!tag)
3967
- return undefined;
3968
- return Intl.getCanonicalLocales(tag)[0];
3969
- }
3970
- /**
3971
- * The direction a locale's script is written in: from `Intl.Locale`'s text
3972
- * info, else from the script `maximize()` fills in, else from the language.
3973
- *
3974
- * @param locale - A canonical tag, as `canonicalLocale` returns.
3975
- */
3976
- function localeDirection(locale) {
3977
- const intlLocale = new Intl.Locale(locale);
3978
- const info = intlLocale;
3979
- const direction = typeof info.getTextInfo === 'function'
3980
- ? info.getTextInfo().direction
3981
- : info.textInfo?.direction;
3982
- if (direction === 'rtl' || direction === 'ltr')
3983
- return direction;
3984
- if (typeof intlLocale.maximize === 'function') {
3985
- const script = intlLocale.maximize().script;
3986
- return script && listed(RTL_SCRIPTS, script) ? 'rtl' : 'ltr';
3987
- }
3988
- return listed(RTL_LANGUAGES, intlLocale.language) ? 'rtl' : 'ltr';
3989
- }
3990
- /**
3991
- * The day a locale's week starts on, 0 for Sunday, as `getWeekInfo()` reads
3992
- * it: the tag's `-u-fw-` keyword, else the region its `-u-rg-` keyword names,
3993
- * else its own region or the one `maximize()` fills in, looked up in CLDR's
3994
- * week data, where a region not listed starts on Monday.
3995
- *
3996
- * @param locale - A canonical tag, as `canonicalLocale` returns.
3997
- */
3998
- function localeFirstDay(locale) {
3999
- const fw = /-u(?:-[a-z0-9]{2,8})*?-fw-([a-z]{3})(?=-|$)/i.exec(locale);
4000
- if (fw && fw[1].toLowerCase() in FW_DAYS)
4001
- return FW_DAYS[fw[1].toLowerCase()];
4002
- const rg = /-u(?:-[a-z0-9]{2,8})*?-rg-([a-z]{2})[a-z0-9]{1,4}(?=-|$)/i.exec(locale);
4003
- const intlLocale = new Intl.Locale(locale);
4004
- const region = rg
4005
- ? rg[1].toUpperCase()
4006
- : typeof intlLocale.maximize === 'function'
4007
- ? intlLocale.maximize().region
4008
- : intlLocale.region;
4009
- if (region) {
4010
- for (const [day, regions] of WEEK_STARTS) {
4011
- if (listed(regions, region))
4012
- return day;
4013
- }
4014
- }
4015
- return 1;
4016
- }
4017
-
4018
- const LocaleContext = React.createContext(null);
4019
- /** The nearest provider's wrapper element, for `LocalePortalScope` to test targets against. */
4020
- const LocaleElementContext = React.createContext(null);
4021
- /** A tag in canonical form, or `undefined`, warning about one `Intl` refuses. */
4022
- function validLocale(tag) {
4023
- try {
4024
- return canonicalLocale(tag);
4025
- }
4026
- catch {
4027
- warnOnce(`locale-provider-invalid:${tag}`, `[bestax-bulma] <LocaleProvider locale="${tag}">: not a language ` +
4028
- 'tag Intl accepts, so it is ignored. Use a BCP 47 tag such as ' +
4029
- '"en-US", with a hyphen rather than an underscore.');
4030
- return undefined;
4031
- }
4032
- }
4033
- /**
4034
- * Sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.
4035
- *
4036
- * The wrapper carries `dir` and `lang`, so CSS and the components that read
4037
- * the computed direction follow it, as they follow `<html dir>`. A `locale`
4038
- * alone sets the direction of its script, and a `dir` sets the direction
4039
- * whatever the locale. A nested provider keeps whatever it leaves unset.
4040
- *
4041
- * Inside it, the date and time pickers take its `locale` unless given their
4042
- * own, and their week starts on the first day of the locale they use unless
4043
- * `firstDayOfWeek` is set, and a picker with a `locale` of its own is read
4044
- * like a nested provider. The library's portaled content, such as a
4045
- * `Popover` panel, a `Modal` with `portal`, a `Toast` or a `Portal`'s
4046
- * children, keeps the same `dir` and `lang` though it renders outside the
4047
- * wrapper: in a container outside the wrapper, it sits in a
4048
- * `display: contents` element that carries them. Without a provider none of
4049
- * this changes.
4050
- *
4051
- * @function
4052
- * @param {LocaleProviderProps} props - Props for the LocaleProvider.
4053
- * @returns {JSX.Element} The wrapper, inside the context.
4054
- *
4055
- * @example
4056
- * <LocaleProvider locale="ar-EG">
4057
- * <App />
4058
- * </LocaleProvider>
4059
- */
4060
- const LocaleProvider = React.forwardRef(({ locale: localeProp, dir: dirProp, className, children, ...props }, ref) => {
4061
- const outer = React.useContext(LocaleContext);
4062
- const ownLocale = React.useMemo(() => validLocale(localeProp), [localeProp]);
4063
- const ownLocaleDir = React.useMemo(() => (ownLocale ? localeDirection(ownLocale) : undefined), [ownLocale]);
4064
- const locale = ownLocale || outer?.locale;
4065
- const dir = dirProp || ownLocaleDir || outer?.dir;
4066
- const value = React.useMemo(() => ({ locale, dir }), [locale, dir]);
4067
- const { bulmaHelperClasses, rest } = useBulmaClasses(props);
4068
- // The wrapper, for portaled content to tell whether its target is inside
4069
- // it, and the caller's ref. A callback ref's cleanup is held and run on
4070
- // detach, as Toast and Modal do, since React 18 discards the return value.
4071
- const elementRef = React.useRef(null);
4072
- const consumerCleanupRef = React.useRef(null);
4073
- const setElement = React.useCallback((node) => {
4074
- elementRef.current = node;
4075
- if (typeof ref === 'function') {
4076
- if (node === null) {
4077
- const consumerCleanup = consumerCleanupRef.current;
4078
- consumerCleanupRef.current = null;
4079
- if (consumerCleanup)
4080
- consumerCleanup();
4081
- else
4082
- ref(null);
4083
- return;
4084
- }
4085
- const cleanup = ref(node);
4086
- consumerCleanupRef.current =
4087
- typeof cleanup === 'function' ? cleanup : null;
4088
- }
4089
- else if (ref) {
4090
- ref.current = node;
4091
- }
4092
- }, [ref]);
4093
- return (jsxRuntime.jsx(LocaleContext.Provider, { value: value, children: jsxRuntime.jsx(LocaleElementContext.Provider, { value: elementRef, children: jsxRuntime.jsx("div", { ref: setElement, className: classNames(bulmaHelperClasses, className) || undefined, ...rest, dir: dir, lang: locale, children: children }) }) }));
4094
- });
4095
- LocaleProvider.displayName = 'LocaleProvider';
4096
- /** What `useLocale` returns outside a provider, the same object each time. */
4097
- const noLocale = {};
4098
- /**
4099
- * The locale and direction the nearest `LocaleProvider` sets, for an app's own `Intl` calls or its own portaled content; both are `undefined` outside one.
4100
- *
4101
- * It isn't the page's direction: with no provider, or one that sets no
4102
- * direction, the page's `<html dir>` still decides. To act on the direction
4103
- * an element is laid out in, read `getComputedStyle(element).direction`, as
4104
- * the library's components do.
4105
- *
4106
- * @function
4107
- * @returns {LocaleContextValue} The nearest provider's `locale` and `dir`.
4108
- *
4109
- * @example
4110
- * const { locale } = useLocale();
4111
- * const price = new Intl.NumberFormat(locale, {
4112
- * style: 'currency',
4113
- * currency: 'EUR',
4114
- * }).format(12.5);
4115
- */
4116
- function useLocale() {
4117
- return React.useContext(LocaleContext) ?? noLocale;
4118
- }
4119
- /**
4120
- * INTERNAL, deliberately not exported from `src/index.ts`. The nearest
4121
- * provider's settings, or `null` outside any provider, so a caller can tell
4122
- * "no provider" from "a provider that sets nothing".
4123
- */
4124
- function useLocaleScope() {
4125
- return React.useContext(LocaleContext);
4126
- }
4127
- const displayContents = { display: 'contents' };
4128
- /**
4129
- * INTERNAL, deliberately not exported from `src/index.ts`. Keeps the `dir`
4130
- * and `lang` of the nearest provider, or the `scope` given in their place,
4131
- * on content the library portals into `target`, which has left the
4132
- * provider's wrapper behind.
4133
- *
4134
- * A target inside the provider's own wrapper gets the content as it is: it
4135
- * inherits from the wrapper, and follows it when the provider changes.
4136
- * Content that must be its container's direct child, a `<tr>` portaled into
4137
- * a `<tbody>` there, stays one. Any other target, `document.body` included,
4138
- * gets the content inside a `display: contents` element carrying the
4139
- * values, which adds no box. So does content with a `scope` of its own, a
4140
- * picker's panel, since the provider's values aren't its own.
4141
- *
4142
- * Which of the two is decided once, when the content mounts, and kept while
4143
- * it stays: switching between them would put a different element in its
4144
- * place and remount everything inside, losing typed text, focus and timers.
4145
- * A change of locale or direction updates the wrapper's attributes instead.
4146
- * A target is never left bare because something else, such as `<html>`,
4147
- * happens to carry the same values, since that can stop being true without
4148
- * the content remounting. Outside a provider it renders the children alone,
4149
- * so nothing changes there.
4150
- */
4151
- function LocalePortalScope({ children, target, scope, }) {
4152
- const provider = React.useContext(LocaleContext);
4153
- const element = React.useContext(LocaleElementContext);
4154
- const [wrap] = React.useState(() => scope !== undefined || !element?.current?.contains(target));
4155
- if (!provider || !wrap)
4156
- return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
4157
- const values = scope ?? provider;
4158
- return (jsxRuntime.jsx("div", { dir: values.dir, lang: values.locale, style: displayContents, children: children }));
4159
- }
4160
-
4161
4274
  /**
4162
4275
  * Resolves a portal target: an `HTMLElement` is used directly, a non-empty
4163
4276
  * `string` is treated as a `document.querySelector` selector (falling back to
@@ -5583,6 +5696,7 @@ const PaginationComponent = ({ color, textColor, bgColor, size, align, rounded,
5583
5696
  backgroundColor: bgColor,
5584
5697
  ...props,
5585
5698
  });
5699
+ const formatNumber = useNumberFormat();
5586
5700
  // Generate Bulma classes with prefix
5587
5701
  const bulmaClasses = usePrefixedClassNames('pagination', {
5588
5702
  [`is-${color}`]: color,
@@ -5625,7 +5739,13 @@ const PaginationComponent = ({ color, textColor, bgColor, size, align, rounded,
5625
5739
  });
5626
5740
  const atStart = disabled || page <= 1;
5627
5741
  const atEnd = disabled || page >= pages;
5628
- content = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PaginationPrevious, { disabled: atStart, ...linkTo(page - 1, atStart), children: previousLabel }), jsxRuntime.jsx(PaginationNext, { disabled: atEnd, ...linkTo(page + 1, atEnd), children: nextLabel }), jsxRuntime.jsx(PaginationList, { children: pageItems(pages, page, whole(siblingCount, 1), whole(boundaryCount, 1)).map(item => typeof item === 'number' ? (jsxRuntime.jsx(PaginationLink, { "aria-label": getPageLabel ? getPageLabel(item) : `Page ${item}`, active: item === page, disabled: disabled, ...linkTo(item, Boolean(disabled)), children: item }, item)) : (jsxRuntime.jsx(PaginationEllipsis, {}, item))) })] }));
5742
+ content = (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PaginationPrevious, { disabled: atStart, ...linkTo(page - 1, atStart), children: previousLabel }), jsxRuntime.jsx(PaginationNext, { disabled: atEnd, ...linkTo(page + 1, atEnd), children: nextLabel }), jsxRuntime.jsx(PaginationList, { children: pageItems(pages, page, whole(siblingCount, 1), whole(boundaryCount, 1)).map(item => {
5743
+ if (typeof item !== 'number') {
5744
+ return jsxRuntime.jsx(PaginationEllipsis, {}, item);
5745
+ }
5746
+ const shown = formatNumber ? formatNumber(item) : item;
5747
+ return (jsxRuntime.jsx(PaginationLink, { "aria-label": getPageLabel ? getPageLabel(item) : `Page ${shown}`, active: item === page, disabled: disabled, ...linkTo(item, Boolean(disabled)), children: shown }, item));
5748
+ }) })] }));
5629
5749
  }
5630
5750
  return (jsxRuntime.jsx("nav", { className: paginationClasses, role: "navigation", "aria-label": "pagination", ...rest, children: content }));
5631
5751
  };
@@ -8330,6 +8450,7 @@ const ContextMenu = withSubComponents(ContextMenuComponent, {
8330
8450
  */
8331
8451
  const Step = ({ isActive = false, isCompleted = false, label, icon, clickable = false, onClick, stepNumber, completedIcon, className, children, ...props }) => {
8332
8452
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
8453
+ const formatNumber = useNumberFormat();
8333
8454
  const stepClasses = classNames(usePrefixedClassNames('steps-segment', {
8334
8455
  'is-active': isActive,
8335
8456
  'is-completed': isCompleted,
@@ -8342,7 +8463,9 @@ const Step = ({ isActive = false, isCompleted = false, label, icon, clickable =
8342
8463
  const markerContent = icon ||
8343
8464
  (isCompleted && resolvedCompletedIcon
8344
8465
  ? resolvedCompletedIcon
8345
- : (stepNumber ?? null));
8466
+ : stepNumber == null || !formatNumber
8467
+ ? (stepNumber ?? null)
8468
+ : formatNumber(stepNumber));
8346
8469
  const title = label || children;
8347
8470
  const current = isActive ? 'step' : undefined;
8348
8471
  // The step stays a list item, and a real button inside it does the
@@ -12621,20 +12744,26 @@ function setRefs$1(node, own, forwarded) {
12621
12744
  /**
12622
12745
  * The default filter: the actions whose label, keywords or description hold
12623
12746
  * the search, ignoring case and the spaces around it, label matches first and
12624
- * the order otherwise kept. An empty search keeps them all.
12747
+ * the order otherwise kept. An empty search keeps them all. `matchText`, a
12748
+ * `LocaleProvider`'s locale-aware matcher, replaces the lowercased
12749
+ * comparison when there is one.
12625
12750
  */
12626
- const filterActions = (query, actions) => {
12627
- const term = query.trim().toLowerCase();
12628
- if (term === '')
12751
+ const filterActions = (query, actions, matchText) => {
12752
+ const search = query.trim();
12753
+ if (search === '')
12629
12754
  return actions;
12755
+ const term = search.toLowerCase();
12756
+ const holds = matchText
12757
+ ? (text) => matchText(text, search)
12758
+ : (text) => text.toLowerCase().includes(term);
12630
12759
  const byLabel = [];
12631
12760
  const byOther = [];
12632
12761
  for (const action of actions) {
12633
- if (action.label.toLowerCase().includes(term)) {
12762
+ if (holds(action.label)) {
12634
12763
  byLabel.push(action);
12635
12764
  }
12636
- else if (action.description?.toLowerCase().includes(term) ||
12637
- action.keywords?.some(keyword => keyword.toLowerCase().includes(term))) {
12765
+ else if ((action.description !== undefined && holds(action.description)) ||
12766
+ action.keywords?.some(holds)) {
12638
12767
  byOther.push(action);
12639
12768
  }
12640
12769
  }
@@ -12870,9 +12999,12 @@ CommandEmpty.displayName = 'CommandEmpty';
12870
12999
  * The field, and the actions that match the search, grouped, or the empty
12871
13000
  * message. The search is the parts root's, read from its context.
12872
13001
  */
12873
- const CommandActionsContent = ({ actions, filter = filterActions, placeholder, empty, }) => {
13002
+ const CommandActionsContent = ({ actions, filter, placeholder, empty, }) => {
12874
13003
  const { query } = useCommand();
12875
- const shown = filter(query, actions);
13004
+ const matchText = useLocaleMatcher();
13005
+ const shown = filter
13006
+ ? filter(query, actions)
13007
+ : filterActions(query, actions, matchText);
12876
13008
  // Each group where the matches first name it, and the actions with none
12877
13009
  // together where the first of them is, so the best match stays on top.
12878
13010
  const sections = new Map();
@@ -14169,13 +14301,17 @@ const RingProgress = React.forwardRef(({ className, textColor, bgColor, value, m
14169
14301
  const labelClass = usePrefixedClassNames('ring-progress-label');
14170
14302
  // A section's color class, prefixed like the rest.
14171
14303
  const classPrefix = useClassPrefix();
14304
+ const formatNumber = useNumberFormat();
14305
+ const writeShare = (share) => formatNumber
14306
+ ? formatNumber(share / 100, { style: 'percent' })
14307
+ : `${share}%`;
14172
14308
  const roleProps = sections
14173
14309
  ? {
14174
14310
  role: 'img',
14175
14311
  'aria-label': [
14176
14312
  label || rest['aria-label'],
14177
14313
  sections
14178
- .map((section, i) => `${section.label} ${Math.round(arcs[i].length)}%`)
14314
+ .map((section, i) => `${section.label} ${writeShare(Math.round(arcs[i].length))}`)
14179
14315
  .join(', '),
14180
14316
  ]
14181
14317
  .filter(Boolean)
@@ -14922,10 +15058,12 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
14922
15058
  : undefined);
14923
15059
  onChange?.(event);
14924
15060
  };
15061
+ const formatNumber = useNumberFormat();
14925
15062
  const pickedText = picked &&
14926
15063
  (picked.count === 1
14927
15064
  ? picked.firstName
14928
- : (pickedFilesLabel?.(picked.count) ?? `${picked.count} files`));
15065
+ : (pickedFilesLabel?.(picked.count) ??
15066
+ `${formatNumber ? formatNumber(picked.count) : picked.count} files`));
14929
15067
  const shownName = fileName ?? pickedText;
14930
15068
  const insideField = useInsideField();
14931
15069
  const insideControl = useInsideControl();
@@ -15517,11 +15655,13 @@ const Slider = React.forwardRef((props, ref) => {
15517
15655
  : 0;
15518
15656
  // Scale helper
15519
15657
  const scaleValue = React.useCallback((v) => (scale ? scale(v) : v), [scale]);
15520
- // Format helper
15658
+ // Format helper: the caller's, else the locale's, else the number as is.
15659
+ const formatNumber = useNumberFormat();
15660
+ const writeNumber = React.useCallback((v) => (formatNumber ? formatNumber(v) : v.toString()), [formatNumber]);
15521
15661
  const formatValue = React.useCallback((v) => {
15522
15662
  const scaled = scaleValue(v);
15523
- return formatOutput ? formatOutput(scaled) : scaled.toString();
15524
- }, [formatOutput, scaleValue]);
15663
+ return formatOutput ? formatOutput(scaled) : writeNumber(scaled);
15664
+ }, [formatOutput, scaleValue, writeNumber]);
15525
15665
  // --- Handlers ---
15526
15666
  const handleSingleChange = React.useCallback((e) => {
15527
15667
  const newValue = parseFloat(e.target.value);
@@ -15641,7 +15781,7 @@ const Slider = React.forwardRef((props, ref) => {
15641
15781
  ariaProps['aria-valuetext'] = getAriaValueText(value);
15642
15782
  }
15643
15783
  else if (scale) {
15644
- ariaProps['aria-valuetext'] = scaleValue(value).toString();
15784
+ ariaProps['aria-valuetext'] = writeNumber(scaleValue(value));
15645
15785
  }
15646
15786
  return ariaProps;
15647
15787
  };
@@ -16255,6 +16395,7 @@ const Rate = React.forwardRef(({ label, labelSize, labelProps, horizontal, messa
16255
16395
  callerProps: props,
16256
16396
  });
16257
16397
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
16398
+ const formatNumber = useNumberFormat();
16258
16399
  const starBaseId = React.useId();
16259
16400
  const [internalValue, setInternalValue] = React.useState(defaultValue);
16260
16401
  const [hoverValue, setHoverValue] = React.useState(null);
@@ -16363,7 +16504,13 @@ const Rate = React.forwardRef(({ label, labelSize, labelProps, horizontal, messa
16363
16504
  };
16364
16505
  // Format score display
16365
16506
  const getScoreDisplay = () => {
16366
- if (precision < 1 && currentValue % 1 !== 0) {
16507
+ const fractional = precision < 1 && currentValue % 1 !== 0;
16508
+ if (formatNumber) {
16509
+ return formatNumber(currentValue, fractional
16510
+ ? { minimumFractionDigits: 1, maximumFractionDigits: 1 }
16511
+ : undefined);
16512
+ }
16513
+ if (fractional) {
16367
16514
  return currentValue.toFixed(1);
16368
16515
  }
16369
16516
  return currentValue;
@@ -16527,6 +16674,7 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
16527
16674
  needsLabelId: true,
16528
16675
  });
16529
16676
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
16677
+ const matchText = useLocaleMatcher();
16530
16678
  const { classPrefix } = useConfig();
16531
16679
  const containerRef = React.useRef(null);
16532
16680
  const inputRef = React.useRef(null);
@@ -16556,6 +16704,8 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
16556
16704
  // Filter data based on input
16557
16705
  const filteredData = data.filter(item => {
16558
16706
  const displayValue = getDisplayValue(item);
16707
+ if (matchText)
16708
+ return matchText(displayValue, inputValue);
16559
16709
  return displayValue.toLowerCase().includes(inputValue.toLowerCase());
16560
16710
  });
16561
16711
  // The dropdown shows the options or, when nothing matches, the `empty`
@@ -17262,6 +17412,7 @@ const ComboboxFromData = React.forwardRef((props, ref) => {
17262
17412
  };
17263
17413
  const controlled = value !== undefined;
17264
17414
  const [ownValue, setOwnValue] = React.useState(() => asList(defaultValue));
17415
+ const matchText = useLocaleMatcher();
17265
17416
  const picked = controlled ? asList(value) : ownValue;
17266
17417
  const change = (next) => {
17267
17418
  if (!controlled)
@@ -17289,8 +17440,11 @@ const ComboboxFromData = React.forwardRef((props, ref) => {
17289
17440
  }
17290
17441
  setQuery(null);
17291
17442
  };
17292
- const term = (query ?? '').trim().toLowerCase();
17293
- const shown = items.filter(item => labelOf(item).toLowerCase().includes(term));
17443
+ const typed = (query ?? '').trim();
17444
+ const term = typed.toLowerCase();
17445
+ const shown = items.filter(item => matchText
17446
+ ? matchText(labelOf(item), typed)
17447
+ : labelOf(item).toLowerCase().includes(term));
17294
17448
  const inputRef = React.useRef(null);
17295
17449
  const select = (pick) => {
17296
17450
  onSelect?.(pick);
@@ -17449,6 +17603,8 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
17449
17603
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
17450
17604
  const { classPrefix } = useConfig();
17451
17605
  const defaultIconLibrary = useIconLibrary();
17606
+ const formatNumber = useNumberFormat();
17607
+ const matchText = useLocaleMatcher();
17452
17608
  const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';
17453
17609
  const pcn = (...args) => prefixedClassNames(classPrefix, ...args);
17454
17610
  const containerRef = React.useRef(null);
@@ -17490,7 +17646,9 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
17490
17646
  // Filter autocomplete data
17491
17647
  const filteredData = data.filter(item => {
17492
17648
  const displayValue = item.toLowerCase();
17493
- const matchesInput = displayValue.includes(inputValue.toLowerCase());
17649
+ const matchesInput = matchText
17650
+ ? matchText(item, inputValue)
17651
+ : displayValue.includes(inputValue.toLowerCase());
17494
17652
  const notAlreadyAdded = allowDuplicates ||
17495
17653
  !tags.some(tag => getDisplayValue(tag).toLowerCase() === displayValue);
17496
17654
  const hasInput = inputValue || (openOnFocus && isActive);
@@ -17740,10 +17898,11 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
17740
17898
  const combinedClasses = classNames(taginputClasses, bulmaHelperClasses, className);
17741
17899
  // Counter text
17742
17900
  const showCounter = hasCounter && (maxTags !== undefined || maxlength !== undefined);
17901
+ const write = formatNumber ?? String;
17743
17902
  const counterText = maxTags !== undefined
17744
- ? `${tags.length} / ${maxTags}`
17903
+ ? `${write(tags.length)} / ${write(maxTags)}`
17745
17904
  : maxlength !== undefined
17746
- ? `${inputValue.length} / ${maxlength}`
17905
+ ? `${write(inputValue.length)} / ${write(maxlength)}`
17747
17906
  : '';
17748
17907
  const counterClasses = pcn('help', 'counter');
17749
17908
  const tagsClasses = pcn('tags');