@nanahoshi/mona-ui 0.23.3 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-button-group.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-calendar.mjs +13 -11
- package/fesm2022/nanahoshi-mona-ui-card.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-chart.mjs +4 -2
- package/fesm2022/nanahoshi-mona-ui-chip.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-common.mjs +265 -159
- package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-dialog.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-editor.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-filter.mjs +3 -1
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-BSVlcB9_.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-CnPhVIr4.mjs} +2 -2
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-B2pBOuLa.mjs → nanahoshi-mona-ui-grid-grid-list.component-DxY6bfTX.mjs} +4 -4
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-Buf4evf5.mjs → nanahoshi-mona-ui-grid-grid-row.component-CaO5Lae6.mjs} +3 -3
- package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-1RdqLEa9.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-jNYtqg5B.mjs} +4 -4
- package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-DeRc_QcP.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-9FtfCutf.mjs} +12 -10
- package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
- package/fesm2022/nanahoshi-mona-ui-i18n-icu.mjs +888 -0
- package/fesm2022/nanahoshi-mona-ui-i18n.mjs +337 -104
- package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-list-box.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-locales-ar-sa.mjs +401 -0
- package/fesm2022/nanahoshi-mona-ui-locales-de-de.mjs +399 -0
- package/fesm2022/nanahoshi-mona-ui-locales-es-es.mjs +399 -0
- package/fesm2022/nanahoshi-mona-ui-locales-fr-fr.mjs +399 -0
- package/fesm2022/nanahoshi-mona-ui-locales-id-id.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales-it-it.mjs +399 -0
- package/fesm2022/nanahoshi-mona-ui-locales-ja-jp.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales-ko-kr.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales-pt-br.mjs +399 -0
- package/fesm2022/nanahoshi-mona-ui-locales-ru-ru.mjs +401 -0
- package/fesm2022/nanahoshi-mona-ui-locales-tr-tr.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales-zh-cn.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales-zh-tw.mjs +397 -0
- package/fesm2022/nanahoshi-mona-ui-locales.mjs +76 -5060
- package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-notification.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +299 -167
- package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-pager.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-rating.mjs +4 -2
- package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +5 -3
- package/fesm2022/nanahoshi-mona-ui-sheet.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-slider.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-spinner.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-split-button.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-splitter.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-stepper.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-tabs.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-text-box.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-window.mjs +2 -0
- package/i18n/catalogs/en-US.messages.json +373 -0
- package/i18n/icu/package.json +4 -0
- package/locales/ar-sa/ar-sa.messages.json +373 -0
- package/locales/ar-sa/package.json +4 -0
- package/locales/de-de/de-de.messages.json +373 -0
- package/locales/de-de/package.json +4 -0
- package/locales/es-es/es-es.messages.json +373 -0
- package/locales/es-es/package.json +4 -0
- package/locales/fr-fr/fr-fr.messages.json +373 -0
- package/locales/fr-fr/package.json +4 -0
- package/locales/id-id/id-id.messages.json +373 -0
- package/locales/id-id/package.json +4 -0
- package/locales/it-it/it-it.messages.json +373 -0
- package/locales/it-it/package.json +4 -0
- package/locales/ja-jp/ja-jp.messages.json +373 -0
- package/locales/ja-jp/package.json +4 -0
- package/locales/ko-kr/ko-kr.messages.json +373 -0
- package/locales/ko-kr/package.json +4 -0
- package/locales/pt-br/package.json +4 -0
- package/locales/pt-br/pt-br.messages.json +373 -0
- package/locales/ru-ru/package.json +4 -0
- package/locales/ru-ru/ru-ru.messages.json +373 -0
- package/locales/tr-tr/package.json +4 -0
- package/locales/tr-tr/tr-tr.messages.json +373 -0
- package/locales/zh-cn/package.json +4 -0
- package/locales/zh-cn/zh-cn.messages.json +373 -0
- package/locales/zh-tw/package.json +4 -0
- package/locales/zh-tw/zh-tw.messages.json +373 -0
- package/package.json +111 -53
- package/types/nanahoshi-mona-ui-common.d.ts +116 -73
- package/types/nanahoshi-mona-ui-i18n-icu.d.ts +74 -0
- package/types/nanahoshi-mona-ui-i18n.d.ts +108 -6
- package/types/nanahoshi-mona-ui-locales-ar-sa.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-de-de.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-es-es.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-fr-fr.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-id-id.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-it-it.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-ja-jp.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-ko-kr.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-pt-br.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-ru-ru.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-tr-tr.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-zh-cn.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales-zh-tw.d.ts +379 -0
- package/types/nanahoshi-mona-ui-locales.d.ts +30 -4915
- package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +113 -37
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, signal, computed, Injectable, isDevMode, ElementRef, DestroyRef, makeEnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, signal, computed, Injectable, isDevMode, ElementRef, DestroyRef, afterNextRender, Injector, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';
|
|
3
3
|
import { Directionality } from '@angular/cdk/bidi';
|
|
4
4
|
import { DateTime } from 'luxon';
|
|
5
5
|
|
|
@@ -83,19 +83,36 @@ function mergeMessages(fallback, localeMessages, overrideMessages) {
|
|
|
83
83
|
|
|
84
84
|
class MonaI18nService {
|
|
85
85
|
#config;
|
|
86
|
+
#loadError;
|
|
87
|
+
#loadedLocales;
|
|
88
|
+
#loadingLocaleId;
|
|
86
89
|
#locale;
|
|
87
90
|
#localeOverrides;
|
|
88
91
|
#overrides;
|
|
92
|
+
/** Incremented by every `load()` and `use()`, so only the latest request changes the locale. */
|
|
93
|
+
#localeRequest;
|
|
89
94
|
constructor() {
|
|
90
95
|
this.#config = inject(MONA_I18N_CONFIG);
|
|
96
|
+
this.#loadError = signal(null, /* @ts-ignore */
|
|
97
|
+
...(ngDevMode ? [{ debugName: "#loadError" }] : /* istanbul ignore next */ []));
|
|
98
|
+
this.#loadedLocales = new Map();
|
|
99
|
+
this.#loadingLocaleId = signal(null, /* @ts-ignore */
|
|
100
|
+
...(ngDevMode ? [{ debugName: "#loadingLocaleId" }] : /* istanbul ignore next */ []));
|
|
91
101
|
this.#locale = signal(this.#config.locale ?? MONA_DEFAULT_LOCALE, /* @ts-ignore */
|
|
92
102
|
...(ngDevMode ? [{ debugName: "#locale" }] : /* istanbul ignore next */ []));
|
|
93
103
|
this.#localeOverrides = signal(createLocaleOverrides(this.#config.localeMessages), /* @ts-ignore */
|
|
94
104
|
...(ngDevMode ? [{ debugName: "#localeOverrides" }] : /* istanbul ignore next */ []));
|
|
95
105
|
this.#overrides = signal(this.#config.messages ?? {}, /* @ts-ignore */
|
|
96
106
|
...(ngDevMode ? [{ debugName: "#overrides" }] : /* istanbul ignore next */ []));
|
|
107
|
+
/** Incremented by every `load()` and `use()`, so only the latest request changes the locale. */
|
|
108
|
+
this.#localeRequest = 0;
|
|
97
109
|
this.direction = computed(() => this.#locale().direction, /* @ts-ignore */
|
|
98
110
|
...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
|
|
111
|
+
/** The error of the latest `load()` when it failed, otherwise `null`. */
|
|
112
|
+
this.loadError = this.#loadError.asReadonly();
|
|
113
|
+
/** Whether a `load()` is in progress and has not been superseded. */
|
|
114
|
+
this.loading = computed(() => this.#loadingLocaleId() != null, /* @ts-ignore */
|
|
115
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
99
116
|
this.locale = this.#locale.asReadonly();
|
|
100
117
|
/**
|
|
101
118
|
* Canonical BCP 47 id of the active locale. POSIX ids such as `en_US` are converted to `en-US`,
|
|
@@ -131,6 +148,51 @@ class MonaI18nService {
|
|
|
131
148
|
return mergeTwo(merged, localeOverrideMessages);
|
|
132
149
|
});
|
|
133
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Loads a locale with the `loadLocale` function configured in `provideMonaI18n` and switches to it.
|
|
153
|
+
*
|
|
154
|
+
* - Ids are canonicalized, and each locale is loaded once: later calls reuse it, and concurrent calls for the
|
|
155
|
+
* same id share one request.
|
|
156
|
+
* - The latest `load()` or `use()` wins. When a newer one starts before this one finishes, this one resolves
|
|
157
|
+
* without switching.
|
|
158
|
+
* - When loading fails, the current locale stays, `loadError` is set and the promise rejects. The failed
|
|
159
|
+
* locale is not cached, so a later call retries it.
|
|
160
|
+
*/
|
|
161
|
+
async load(localeId) {
|
|
162
|
+
const loadLocale = this.#config.loadLocale;
|
|
163
|
+
if (loadLocale == null) {
|
|
164
|
+
throw new Error("[mona-ui] MonaI18nService.load() needs a loader: provideMonaI18n({ loadLocale: loadMonaLocale }).");
|
|
165
|
+
}
|
|
166
|
+
const canonicalId = canonicalizeLocaleId(localeId);
|
|
167
|
+
const request = ++this.#localeRequest;
|
|
168
|
+
this.#loadingLocaleId.set(canonicalId);
|
|
169
|
+
this.#loadError.set(null);
|
|
170
|
+
let pending = this.#loadedLocales.get(canonicalId);
|
|
171
|
+
if (pending == null) {
|
|
172
|
+
pending = Promise.resolve().then(() => loadLocale(canonicalId));
|
|
173
|
+
this.#loadedLocales.set(canonicalId, pending);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const locale = await pending;
|
|
177
|
+
if (request === this.#localeRequest) {
|
|
178
|
+
this.#applyLocale(locale);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (this.#loadedLocales.get(canonicalId) === pending) {
|
|
183
|
+
this.#loadedLocales.delete(canonicalId);
|
|
184
|
+
}
|
|
185
|
+
if (request === this.#localeRequest) {
|
|
186
|
+
this.#loadError.set(error);
|
|
187
|
+
}
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
if (request === this.#localeRequest) {
|
|
192
|
+
this.#loadingLocaleId.set(null);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
134
196
|
/**
|
|
135
197
|
* Merges overrides into the existing ones. With `options.locale`, they apply only while that locale is
|
|
136
198
|
* active, so overrides patched for German do not show after switching to English.
|
|
@@ -154,7 +216,14 @@ class MonaI18nService {
|
|
|
154
216
|
const localeId = canonicalizeLocaleId(options.locale);
|
|
155
217
|
this.#localeOverrides.update(current => new Map(current).set(localeId, messages));
|
|
156
218
|
}
|
|
219
|
+
/** Switches to a locale that is already loaded. It supersedes a `load()` still in progress. */
|
|
157
220
|
use(locale) {
|
|
221
|
+
this.#localeRequest++;
|
|
222
|
+
this.#loadingLocaleId.set(null);
|
|
223
|
+
this.#loadError.set(null);
|
|
224
|
+
this.#applyLocale(locale);
|
|
225
|
+
}
|
|
226
|
+
#applyLocale(locale) {
|
|
158
227
|
warnOnInvalidLocaleId(locale.id);
|
|
159
228
|
this.#locale.set(locale);
|
|
160
229
|
}
|
|
@@ -241,39 +310,94 @@ function resolveComponentDirection(hostElement, directionality) {
|
|
|
241
310
|
}
|
|
242
311
|
return "ltr";
|
|
243
312
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
313
|
+
/**
|
|
314
|
+
* One `dir` attribute observer per observed root (the document element, a shadow root, or the top of a detached
|
|
315
|
+
* tree), shared by every direction-aware instance under it. A mutation only invalidates the instances it can affect,
|
|
316
|
+
* so a `dir` written on an overlay pane does not re-resolve every component on the page.
|
|
317
|
+
*/
|
|
318
|
+
const directionRegistries = new WeakMap();
|
|
319
|
+
function isShadowRoot(node) {
|
|
320
|
+
return node.nodeType === 11 && "host" in node;
|
|
321
|
+
}
|
|
322
|
+
function getComposedParent(node) {
|
|
323
|
+
if (node.parentNode) {
|
|
324
|
+
return node.parentNode;
|
|
325
|
+
}
|
|
326
|
+
return isShadowRoot(node) ? node.host : null;
|
|
327
|
+
}
|
|
328
|
+
function composedContains(ancestor, node) {
|
|
329
|
+
for (let current = node; current; current = getComposedParent(current)) {
|
|
330
|
+
if (current === ancestor) {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* A `dir` change affects an instance when it lands on the instance's element or one of its ancestors, or anywhere
|
|
338
|
+
* inside the `dir="auto"` root it resolves against (a nested explicit direction changes which text counts).
|
|
339
|
+
*/
|
|
340
|
+
function isAffectedByDirChange(subscriber, targets) {
|
|
341
|
+
for (let current = subscriber.element; current; current = getComposedParent(current)) {
|
|
342
|
+
if (targets.has(current)) {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const autoRoot = subscriber.autoRoot;
|
|
347
|
+
if (autoRoot) {
|
|
348
|
+
for (const target of targets) {
|
|
349
|
+
if (composedContains(autoRoot, target)) {
|
|
350
|
+
return true;
|
|
252
351
|
}
|
|
253
|
-
});
|
|
254
|
-
if (doc.documentElement) {
|
|
255
|
-
observer.observe(doc.documentElement, {
|
|
256
|
-
attributes: true,
|
|
257
|
-
attributeFilter: ["dir"],
|
|
258
|
-
subtree: true
|
|
259
|
-
});
|
|
260
352
|
}
|
|
261
|
-
entry = { refCount: 0, observer, callbacks };
|
|
262
|
-
documentObservers.set(doc, entry);
|
|
263
353
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
function getObservedRoots(element) {
|
|
357
|
+
const roots = [];
|
|
358
|
+
let root = element.getRootNode?.() ?? null;
|
|
359
|
+
while (root && isShadowRoot(root)) {
|
|
360
|
+
roots.push(root);
|
|
361
|
+
root = root.host.getRootNode?.() ?? null;
|
|
362
|
+
}
|
|
363
|
+
// The top of a detached tree, so a host that is not attached yet still sees its own subtree change.
|
|
364
|
+
if (root && root !== element && root.nodeType === 1) {
|
|
365
|
+
roots.push(root);
|
|
366
|
+
}
|
|
367
|
+
const documentElement = element.ownerDocument?.documentElement;
|
|
368
|
+
if (documentElement && !roots.includes(documentElement)) {
|
|
369
|
+
roots.push(documentElement);
|
|
370
|
+
}
|
|
371
|
+
return roots;
|
|
372
|
+
}
|
|
373
|
+
function registerDirectionSubscriber(observedRoot, subscriber) {
|
|
374
|
+
let registry = directionRegistries.get(observedRoot);
|
|
375
|
+
if (!registry) {
|
|
376
|
+
const subscribers = new Set();
|
|
377
|
+
const observer = new MutationObserver(records => {
|
|
378
|
+
const targets = new Set();
|
|
379
|
+
for (const record of records) {
|
|
380
|
+
targets.add(record.target);
|
|
381
|
+
}
|
|
382
|
+
for (const candidate of Array.from(subscribers)) {
|
|
383
|
+
if (subscribers.has(candidate) && isAffectedByDirChange(candidate, targets)) {
|
|
384
|
+
candidate.invalidate();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
observer.observe(observedRoot, { attributes: true, attributeFilter: ["dir"], subtree: true });
|
|
389
|
+
registry = { observer, subscribers };
|
|
390
|
+
directionRegistries.set(observedRoot, registry);
|
|
391
|
+
}
|
|
392
|
+
const activeRegistry = registry;
|
|
393
|
+
activeRegistry.subscribers.add(subscriber);
|
|
267
394
|
return () => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (entry.refCount <= 0) {
|
|
275
|
-
entry.observer.disconnect();
|
|
276
|
-
documentObservers.delete(doc);
|
|
395
|
+
activeRegistry.subscribers.delete(subscriber);
|
|
396
|
+
if (activeRegistry.subscribers.size === 0) {
|
|
397
|
+
activeRegistry.observer.disconnect();
|
|
398
|
+
if (directionRegistries.get(observedRoot) === activeRegistry) {
|
|
399
|
+
directionRegistries.delete(observedRoot);
|
|
400
|
+
}
|
|
277
401
|
}
|
|
278
402
|
};
|
|
279
403
|
}
|
|
@@ -320,46 +444,61 @@ function observeAutoDirectionChanges(autoRoot, callback) {
|
|
|
320
444
|
}
|
|
321
445
|
};
|
|
322
446
|
}
|
|
447
|
+
/** The nearest `dir="auto"` ancestor-or-self, unless an explicit `ltr`/`rtl` comes first. */
|
|
448
|
+
function findAutoRoot(element) {
|
|
449
|
+
for (let current = element; current; current = current.parentElement) {
|
|
450
|
+
const rawDir = current.getAttribute?.("dir")?.trim().toLowerCase();
|
|
451
|
+
if (rawDir === "auto") {
|
|
452
|
+
return current;
|
|
453
|
+
}
|
|
454
|
+
if (rawDir === "rtl" || rawDir === "ltr") {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
323
460
|
function observeComponentDirection(hostElement, directionality, onChange) {
|
|
324
461
|
const element = hostElement instanceof ElementRef ? hostElement.nativeElement : hostElement;
|
|
462
|
+
const canObserve = typeof MutationObserver !== "undefined" && !!element;
|
|
325
463
|
let currentDir = resolveComponentDirection(element, directionality);
|
|
326
464
|
let unobserveAuto = null;
|
|
327
|
-
|
|
465
|
+
const rootSubscriptions = new Map();
|
|
466
|
+
const subscriber = element
|
|
467
|
+
? { autoRoot: null, element, invalidate: () => check() }
|
|
468
|
+
: null;
|
|
328
469
|
const updateAutoContentObserver = () => {
|
|
329
|
-
if (
|
|
470
|
+
if (!canObserve || !subscriber) {
|
|
330
471
|
return;
|
|
331
472
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const rawDir = current.getAttribute?.("dir")?.trim().toLowerCase();
|
|
336
|
-
if (rawDir === "auto") {
|
|
337
|
-
autoRoot = current;
|
|
338
|
-
break;
|
|
339
|
-
}
|
|
340
|
-
if (rawDir === "rtl" || rawDir === "ltr") {
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
current = current.parentElement;
|
|
473
|
+
const autoRoot = findAutoRoot(subscriber.element);
|
|
474
|
+
if (autoRoot === subscriber.autoRoot) {
|
|
475
|
+
return;
|
|
344
476
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
477
|
+
unobserveAuto?.();
|
|
478
|
+
unobserveAuto = autoRoot ? observeAutoDirectionChanges(autoRoot, () => check()) : null;
|
|
479
|
+
subscriber.autoRoot = autoRoot;
|
|
480
|
+
};
|
|
481
|
+
// Re-registers with the roots the host is under now: it may have been created in a detached view and inserted
|
|
482
|
+
// into the document or a shadow root later.
|
|
483
|
+
const syncObservedRoots = () => {
|
|
484
|
+
if (!canObserve || !subscriber) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const roots = getObservedRoots(subscriber.element);
|
|
488
|
+
for (const [root, unsubscribe] of rootSubscriptions) {
|
|
489
|
+
if (!roots.includes(root)) {
|
|
490
|
+
unsubscribe();
|
|
491
|
+
rootSubscriptions.delete(root);
|
|
352
492
|
}
|
|
353
493
|
}
|
|
354
|
-
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
unobserveAuto = null;
|
|
358
|
-
observedAutoElement = null;
|
|
494
|
+
for (const root of roots) {
|
|
495
|
+
if (!rootSubscriptions.has(root)) {
|
|
496
|
+
rootSubscriptions.set(root, registerDirectionSubscriber(root, subscriber));
|
|
359
497
|
}
|
|
360
498
|
}
|
|
361
499
|
};
|
|
362
500
|
const check = () => {
|
|
501
|
+
syncObservedRoots();
|
|
363
502
|
updateAutoContentObserver();
|
|
364
503
|
const nextDir = resolveComponentDirection(element, directionality);
|
|
365
504
|
if (nextDir !== currentDir) {
|
|
@@ -377,27 +516,24 @@ function observeComponentDirection(hostElement, directionality, onChange) {
|
|
|
377
516
|
});
|
|
378
517
|
cleanupFns.push(() => sub.unsubscribe());
|
|
379
518
|
}
|
|
380
|
-
if (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const root = element.getRootNode?.();
|
|
386
|
-
if (root && root !== element && root !== element.ownerDocument) {
|
|
387
|
-
const rootObserver = new MutationObserver(() => check());
|
|
388
|
-
rootObserver.observe(root, { attributes: true, attributeFilter: ["dir"], subtree: true });
|
|
389
|
-
cleanupFns.push(() => rootObserver.disconnect());
|
|
390
|
-
}
|
|
391
|
-
if (element.ownerDocument) {
|
|
392
|
-
cleanupFns.push(observeDocumentDirChanges(element.ownerDocument, check));
|
|
393
|
-
}
|
|
394
|
-
}
|
|
519
|
+
if (canObserve && element) {
|
|
520
|
+
// The host's own dir, which the shared root observers miss while the host is outside them (detached or moved).
|
|
521
|
+
const hostObserver = new MutationObserver(() => check());
|
|
522
|
+
hostObserver.observe(element, { attributes: true, attributeFilter: ["dir"] });
|
|
523
|
+
cleanupFns.push(() => hostObserver.disconnect());
|
|
395
524
|
}
|
|
525
|
+
syncObservedRoots();
|
|
526
|
+
cleanupFns.push(() => {
|
|
527
|
+
for (const unsubscribe of rootSubscriptions.values()) {
|
|
528
|
+
unsubscribe();
|
|
529
|
+
}
|
|
530
|
+
rootSubscriptions.clear();
|
|
531
|
+
});
|
|
396
532
|
cleanupFns.push(() => {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
533
|
+
unobserveAuto?.();
|
|
534
|
+
unobserveAuto = null;
|
|
535
|
+
if (subscriber) {
|
|
536
|
+
subscriber.autoRoot = null;
|
|
401
537
|
}
|
|
402
538
|
});
|
|
403
539
|
const handle = Object.assign(() => {
|
|
@@ -416,17 +552,17 @@ function injectComponentDirection(hostElementRef) {
|
|
|
416
552
|
const destroyRef = inject(DestroyRef, { optional: true });
|
|
417
553
|
const domVersion = signal(0, /* @ts-ignore */
|
|
418
554
|
...(ngDevMode ? [{ debugName: "domVersion" }] : /* istanbul ignore next */ []));
|
|
419
|
-
let updateAutoObserverFn = () => { };
|
|
420
555
|
if (destroyRef) {
|
|
421
|
-
const
|
|
556
|
+
const handle = observeComponentDirection(hostRef, directionality, () => {
|
|
422
557
|
domVersion.update(v => v + 1);
|
|
423
558
|
});
|
|
424
|
-
|
|
425
|
-
|
|
559
|
+
destroyRef.onDestroy(() => handle());
|
|
560
|
+
// A host can be moved under a different `dir="auto"` root after it is created; re-check once it has rendered.
|
|
561
|
+
afterNextRender(() => handle.check(), { injector: inject(Injector) });
|
|
426
562
|
}
|
|
563
|
+
// Pure: observers are managed by the handle above, never during signal evaluation.
|
|
427
564
|
return computed(() => {
|
|
428
565
|
domVersion();
|
|
429
|
-
updateAutoObserverFn();
|
|
430
566
|
return resolveComponentDirection(hostRef, directionality);
|
|
431
567
|
});
|
|
432
568
|
}
|
|
@@ -452,11 +588,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
|
|
|
452
588
|
}] });
|
|
453
589
|
|
|
454
590
|
function provideMonaI18n(config = {}) {
|
|
591
|
+
const initialLocale = config.initialLocale;
|
|
455
592
|
return makeEnvironmentProviders([
|
|
456
593
|
{
|
|
457
594
|
provide: MONA_I18N_CONFIG,
|
|
458
595
|
useValue: config
|
|
459
|
-
}
|
|
596
|
+
},
|
|
597
|
+
...(initialLocale == null
|
|
598
|
+
? []
|
|
599
|
+
: [
|
|
600
|
+
// A failed load must not stop the application from starting: it keeps the configured locale.
|
|
601
|
+
provideAppInitializer(() => inject(MonaI18nService)
|
|
602
|
+
.load(initialLocale)
|
|
603
|
+
.catch((error) => console.error(`[mona-ui] Could not load the initial locale "${initialLocale}".`, error)))
|
|
604
|
+
])
|
|
460
605
|
]);
|
|
461
606
|
}
|
|
462
607
|
|
|
@@ -601,7 +746,12 @@ function getNumberFormatter(locale, options) {
|
|
|
601
746
|
}
|
|
602
747
|
return formatter;
|
|
603
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* Formats a number for the locale. A decimal string, such as one returned by {@link parseLocalizedDecimal}, is
|
|
751
|
+
* formatted exactly, without converting it to a `number` first.
|
|
752
|
+
*/
|
|
604
753
|
function formatNumber(value, locale, options) {
|
|
754
|
+
// Intl.NumberFormat formats decimal strings exactly (Intl.NumberFormat v3); the ES2022 lib types only declare numbers.
|
|
605
755
|
return getNumberFormatter(locale, options).format(value);
|
|
606
756
|
}
|
|
607
757
|
/**
|
|
@@ -676,7 +826,52 @@ function getEditDecimalSeparators(symbols) {
|
|
|
676
826
|
}
|
|
677
827
|
return separators;
|
|
678
828
|
}
|
|
829
|
+
const MAX_SAFE_INTEGER_DIGITS = String(Number.MAX_SAFE_INTEGER);
|
|
830
|
+
/** The most significant digits a double reproduces exactly when converted from decimal text and back. */
|
|
831
|
+
const MAX_EXACT_SIGNIFICANT_DIGITS = 15;
|
|
832
|
+
/** Whether ASCII integer and fraction digits survive conversion to a `number` unchanged. */
|
|
833
|
+
function isRepresentableAsNumber(intDigits, fracDigits) {
|
|
834
|
+
const integer = intDigits.replace(/^0+/, "");
|
|
835
|
+
const fraction = fracDigits.replace(/0+$/, "");
|
|
836
|
+
if (fraction === "") {
|
|
837
|
+
return (integer.length < MAX_SAFE_INTEGER_DIGITS.length ||
|
|
838
|
+
(integer.length === MAX_SAFE_INTEGER_DIGITS.length && integer <= MAX_SAFE_INTEGER_DIGITS));
|
|
839
|
+
}
|
|
840
|
+
return (integer + fraction).replace(/^0+/, "").length <= MAX_EXACT_SIGNIFICANT_DIGITS;
|
|
841
|
+
}
|
|
842
|
+
function partsToNumber(parts) {
|
|
843
|
+
if (!isRepresentableAsNumber(parts.integer, parts.fraction)) {
|
|
844
|
+
return "precision";
|
|
845
|
+
}
|
|
846
|
+
return Number((parts.negative ? "-" : "") + parts.integer + (parts.fraction ? "." + parts.fraction : ""));
|
|
847
|
+
}
|
|
848
|
+
/** Leading zeros, trailing fraction zeros and the sign of zero are dropped: `"-0012.500"` becomes `"-12.5"`. */
|
|
849
|
+
function partsToDecimal(parts) {
|
|
850
|
+
const integer = parts.integer.replace(/^0+(?=\d)/, "") || "0";
|
|
851
|
+
const fraction = parts.fraction.replace(/0+$/, "");
|
|
852
|
+
const digits = fraction ? `${integer}.${fraction}` : integer;
|
|
853
|
+
return parts.negative && /[1-9]/.test(digits) ? `-${digits}` : digits;
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Parses localized text to a number. Returns `null` when the text is not a number in the locale, or when a
|
|
857
|
+
* `number` cannot hold it exactly (see {@link LocalizedNumberInvalidReason}); it never rounds silently.
|
|
858
|
+
* Use {@link parseLocalizedDecimal} for values that need more precision.
|
|
859
|
+
*/
|
|
679
860
|
function parseLocalizedNumber(text, localeId, options) {
|
|
861
|
+
const parts = parseLocalizedNumberParts(text, localeId, options);
|
|
862
|
+
const value = parts === null ? null : partsToNumber(parts);
|
|
863
|
+
return value === "precision" ? null : value;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Parses localized text with the same rules as {@link parseLocalizedNumber}, but returns a canonical decimal string
|
|
867
|
+
* (`"-1234.5"`: ASCII digits, `.` as the decimal separator, no grouping, exponent, leading zeros or trailing
|
|
868
|
+
* fraction zeros) and has no precision limit. Returns `null` when the text is not a number in the locale.
|
|
869
|
+
*/
|
|
870
|
+
function parseLocalizedDecimal(text, localeId, options) {
|
|
871
|
+
const parts = parseLocalizedNumberParts(text, localeId, options);
|
|
872
|
+
return parts === null ? null : partsToDecimal(parts);
|
|
873
|
+
}
|
|
874
|
+
function parseLocalizedNumberParts(text, localeId, options) {
|
|
680
875
|
if (text == null) {
|
|
681
876
|
return null;
|
|
682
877
|
}
|
|
@@ -819,9 +1014,7 @@ function parseLocalizedNumber(text, localeId, options) {
|
|
|
819
1014
|
}
|
|
820
1015
|
}
|
|
821
1016
|
}
|
|
822
|
-
|
|
823
|
-
const num = Number(normalizedStr);
|
|
824
|
-
return Number.isFinite(num) ? num : null;
|
|
1017
|
+
return { fraction: fracPart ?? "", integer: intPart, negative: sign === "-" };
|
|
825
1018
|
}
|
|
826
1019
|
else {
|
|
827
1020
|
// mode === "edit": editor buffer grammar with exactly one decimal separator (locale primary or alternate)
|
|
@@ -875,11 +1068,7 @@ function parseLocalizedNumber(text, localeId, options) {
|
|
|
875
1068
|
intPart = cleaned;
|
|
876
1069
|
fracPart = "";
|
|
877
1070
|
}
|
|
878
|
-
|
|
879
|
-
(intPart.length > 0 ? intPart : "0") +
|
|
880
|
-
(fracPart.length > 0 ? "." + fracPart : cleaned.endsWith(foundSep ?? "") ? "" : "");
|
|
881
|
-
const num = Number(normalizedStr);
|
|
882
|
-
return Number.isFinite(num) ? num : null;
|
|
1071
|
+
return { fraction: fracPart, integer: intPart.length > 0 ? intPart : "0", negative: sign === "-" };
|
|
883
1072
|
}
|
|
884
1073
|
}
|
|
885
1074
|
function validateLocalizedNumber(text, localeId, options) {
|
|
@@ -891,9 +1080,13 @@ function validateLocalizedNumber(text, localeId, options) {
|
|
|
891
1080
|
return { value: null, valid: true, fractionDigits: 0 };
|
|
892
1081
|
}
|
|
893
1082
|
const mode = options?.mode ?? "locale";
|
|
894
|
-
const
|
|
1083
|
+
const parts = parseLocalizedNumberParts(trimmed, localeId, { mode });
|
|
1084
|
+
const parsed = parts === null ? null : partsToNumber(parts);
|
|
1085
|
+
if (parsed === "precision") {
|
|
1086
|
+
return { value: null, valid: false, fractionDigits: 0, reason: "precision" };
|
|
1087
|
+
}
|
|
895
1088
|
if (parsed === null || !Number.isFinite(parsed)) {
|
|
896
|
-
return { value: null, valid: false, fractionDigits: 0 };
|
|
1089
|
+
return { value: null, valid: false, fractionDigits: 0, reason: "syntax" };
|
|
897
1090
|
}
|
|
898
1091
|
// Determine the number of fraction digits from the source string
|
|
899
1092
|
const symbols = getNumberSymbols(localeId);
|
|
@@ -952,11 +1145,42 @@ function validateLocalizedNumber(text, localeId, options) {
|
|
|
952
1145
|
}
|
|
953
1146
|
}
|
|
954
1147
|
if (options?.decimals !== undefined && fractionDigits > options.decimals) {
|
|
955
|
-
return { value: parsed, valid: false, fractionDigits };
|
|
1148
|
+
return { value: parsed, valid: false, fractionDigits, reason: "decimals" };
|
|
956
1149
|
}
|
|
957
1150
|
return { value: parsed, valid: true, fractionDigits };
|
|
958
1151
|
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Validates localized text like {@link validateLocalizedNumber}, but returns a canonical decimal string and has no
|
|
1154
|
+
* precision limit, so `reason` is never `"precision"`.
|
|
1155
|
+
*/
|
|
1156
|
+
function validateLocalizedDecimal(text, localeId, options) {
|
|
1157
|
+
const trimmed = text == null ? "" : String(text).trim();
|
|
1158
|
+
if (trimmed === "" || trimmed === "-" || trimmed === "+") {
|
|
1159
|
+
return { fractionDigits: 0, valid: true, value: null };
|
|
1160
|
+
}
|
|
1161
|
+
const parts = parseLocalizedNumberParts(trimmed, localeId, { mode: options?.mode ?? "locale" });
|
|
1162
|
+
if (parts === null) {
|
|
1163
|
+
return { fractionDigits: 0, reason: "syntax", valid: false, value: null };
|
|
1164
|
+
}
|
|
1165
|
+
const value = partsToDecimal(parts);
|
|
1166
|
+
const fractionDigits = parts.fraction.length;
|
|
1167
|
+
if (options?.decimals !== undefined && fractionDigits > options.decimals) {
|
|
1168
|
+
return { fractionDigits, reason: "decimals", valid: false, value };
|
|
1169
|
+
}
|
|
1170
|
+
return { fractionDigits, valid: true, value };
|
|
1171
|
+
}
|
|
1172
|
+
const EDIT_SYNTAX_ERROR = { complete: false, reason: "syntax", valid: false, value: null };
|
|
959
1173
|
function validateLocalizedNumberEdit(text, localeId, options) {
|
|
1174
|
+
return validateEditInput(text, localeId, options, partsToNumber);
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Validates text while it is typed, like {@link validateLocalizedNumberEdit}, but returns a canonical decimal string
|
|
1178
|
+
* and has no precision limit.
|
|
1179
|
+
*/
|
|
1180
|
+
function validateLocalizedDecimalEdit(text, localeId, options) {
|
|
1181
|
+
return validateEditInput(text, localeId, options, partsToDecimal);
|
|
1182
|
+
}
|
|
1183
|
+
function validateEditInput(text, localeId, options, convert) {
|
|
960
1184
|
if (text == null) {
|
|
961
1185
|
return { valid: true, complete: false, value: null };
|
|
962
1186
|
}
|
|
@@ -966,7 +1190,7 @@ function validateLocalizedNumberEdit(text, localeId, options) {
|
|
|
966
1190
|
}
|
|
967
1191
|
// Reject control or whitespace characters in interactive typing
|
|
968
1192
|
if (/[\s\u00A0\u202F]/.test(raw)) {
|
|
969
|
-
return
|
|
1193
|
+
return EDIT_SYNTAX_ERROR;
|
|
970
1194
|
}
|
|
971
1195
|
const symbols = getNumberSymbols(localeId);
|
|
972
1196
|
// Normalize minus signs and bidi controls
|
|
@@ -977,12 +1201,12 @@ function validateLocalizedNumberEdit(text, localeId, options) {
|
|
|
977
1201
|
const allowSign = options?.allowSign ?? true;
|
|
978
1202
|
if (normalized.startsWith("-") || normalized.startsWith("+")) {
|
|
979
1203
|
if (!allowSign) {
|
|
980
|
-
return
|
|
1204
|
+
return EDIT_SYNTAX_ERROR;
|
|
981
1205
|
}
|
|
982
1206
|
normalized = normalized.slice(1);
|
|
983
1207
|
}
|
|
984
1208
|
if (normalized.includes("-") || normalized.includes("+")) {
|
|
985
|
-
return
|
|
1209
|
+
return EDIT_SYNTAX_ERROR;
|
|
986
1210
|
}
|
|
987
1211
|
// If input was just "-" or "+"
|
|
988
1212
|
if (normalized === "") {
|
|
@@ -997,7 +1221,7 @@ function validateLocalizedNumberEdit(text, localeId, options) {
|
|
|
997
1221
|
if (normalized.startsWith(sep, i)) {
|
|
998
1222
|
if (foundSep !== null) {
|
|
999
1223
|
// More than one separator is rejected in edit mode
|
|
1000
|
-
return
|
|
1224
|
+
return EDIT_SYNTAX_ERROR;
|
|
1001
1225
|
}
|
|
1002
1226
|
foundSep = sep;
|
|
1003
1227
|
sepIndex = i;
|
|
@@ -1010,23 +1234,28 @@ function validateLocalizedNumberEdit(text, localeId, options) {
|
|
|
1010
1234
|
if (foundSep !== null) {
|
|
1011
1235
|
if (decimals === 0) {
|
|
1012
1236
|
// No decimal point permitted when decimals === 0
|
|
1013
|
-
return { valid: false, complete: false, value: null };
|
|
1237
|
+
return { valid: false, complete: false, value: null, reason: "decimals" };
|
|
1014
1238
|
}
|
|
1015
1239
|
const intPart = normalized.slice(0, sepIndex);
|
|
1016
1240
|
const fracPart = normalized.slice(sepIndex + foundSep.length);
|
|
1017
1241
|
// Integer part before separator must consist purely of ASCII digits (or empty, e.g. ".5")
|
|
1018
1242
|
if (intPart.length > 0 && !/^\d+$/.test(intPart)) {
|
|
1019
|
-
return
|
|
1243
|
+
return EDIT_SYNTAX_ERROR;
|
|
1020
1244
|
}
|
|
1021
1245
|
// Fractional part after separator must consist purely of ASCII digits (or empty, e.g. "12.")
|
|
1022
1246
|
if (fracPart.length > 0 && !/^\d+$/.test(fracPart)) {
|
|
1023
|
-
return
|
|
1247
|
+
return EDIT_SYNTAX_ERROR;
|
|
1024
1248
|
}
|
|
1025
1249
|
// Count fraction digits using normalized ASCII characters (safe against UTF-16 astral splitting)
|
|
1026
1250
|
if (fracPart.length > decimals) {
|
|
1027
|
-
return { valid: false, complete: false, value: null };
|
|
1251
|
+
return { valid: false, complete: false, value: null, reason: "decimals" };
|
|
1252
|
+
}
|
|
1253
|
+
const parts = parseLocalizedNumberParts(raw, localeId, { mode: "edit" });
|
|
1254
|
+
const parsed = parts === null ? null : convert(parts);
|
|
1255
|
+
// Refuse the keystroke that would make the value too precise for the target type, instead of rounding it.
|
|
1256
|
+
if (parsed === "precision") {
|
|
1257
|
+
return { valid: false, complete: false, value: null, reason: "precision" };
|
|
1028
1258
|
}
|
|
1029
|
-
const parsed = parseLocalizedNumber(raw, localeId, { mode: "edit" });
|
|
1030
1259
|
const complete = fracPart.length > 0 && (intPart.length > 0 || fracPart.length > 0);
|
|
1031
1260
|
return {
|
|
1032
1261
|
valid: true,
|
|
@@ -1036,9 +1265,13 @@ function validateLocalizedNumberEdit(text, localeId, options) {
|
|
|
1036
1265
|
}
|
|
1037
1266
|
// No separator found: must be purely ASCII digits
|
|
1038
1267
|
if (!/^\d+$/.test(normalized)) {
|
|
1039
|
-
return
|
|
1268
|
+
return EDIT_SYNTAX_ERROR;
|
|
1269
|
+
}
|
|
1270
|
+
const parts = parseLocalizedNumberParts(raw, localeId, { mode: "edit" });
|
|
1271
|
+
const parsed = parts === null ? null : convert(parts);
|
|
1272
|
+
if (parsed === "precision") {
|
|
1273
|
+
return { valid: false, complete: false, value: null, reason: "precision" };
|
|
1040
1274
|
}
|
|
1041
|
-
const parsed = parseLocalizedNumber(raw, localeId, { mode: "edit" });
|
|
1042
1275
|
return {
|
|
1043
1276
|
valid: true,
|
|
1044
1277
|
complete: true,
|
|
@@ -4979,5 +5212,5 @@ function generatePseudoLocale(catalogs, options) {
|
|
|
4979
5212
|
* Generated bundle index. Do not edit.
|
|
4980
5213
|
*/
|
|
4981
5214
|
|
|
4982
|
-
export { BIDI_CONTROL_REGEX, MONA_DEFAULT_LOCALE, MONA_I18N_CONFIG, MonaDirectionService, MonaI18nService, formatGregorianDateToLocaleString, formatNumber, generatePseudoLocale, getEditDecimalSeparators, getLocaleDateInputFormat, getLocaleDateTimeInputFormat, getLocaleFirstDayOfWeek, getLocaleTimeInputFormat, getNumberFormatter, getNumberGroupingPattern, getNumberSymbols, gregorianDateTime, gregorianDateTimeFromObject, injectComponentDirection, mergeMessages, mergeTwo, normalizeGregorianLocale, normalizeLocalizedDigits, normalizeLocalizedInput, normalizeLocalizedMinus, observeComponentDirection, parseGregorianDate, parseLocalizedNumber, provideMonaI18n, pseudoLocalize, pseudoLocalizeCatalog, resolveComponentDirection, sanitizeDateText, stripBidiControls, validateLocalizedNumber, validateLocalizedNumberEdit };
|
|
5215
|
+
export { BIDI_CONTROL_REGEX, MONA_DEFAULT_LOCALE, MONA_FALLBACK_LOCALE_ID, MONA_I18N_CONFIG, MonaDirectionService, MonaI18nService, canonicalizeLocaleId, formatGregorianDateToLocaleString, formatNumber, generatePseudoLocale, getEditDecimalSeparators, getLocaleDateInputFormat, getLocaleDateTimeInputFormat, getLocaleFirstDayOfWeek, getLocaleTimeInputFormat, getNumberFormatter, getNumberGroupingPattern, getNumberSymbols, gregorianDateTime, gregorianDateTimeFromObject, injectComponentDirection, mergeMessages, mergeTwo, normalizeGregorianLocale, normalizeLocalizedDigits, normalizeLocalizedInput, normalizeLocalizedMinus, observeComponentDirection, parseGregorianDate, parseLocalizedDecimal, parseLocalizedNumber, provideMonaI18n, pseudoLocalize, pseudoLocalizeCatalog, resolveComponentDirection, sanitizeDateText, stripBidiControls, tryCanonicalizeLocaleId, validateLocalizedDecimal, validateLocalizedDecimalEdit, validateLocalizedNumber, validateLocalizedNumberEdit };
|
|
4983
5216
|
//# sourceMappingURL=nanahoshi-mona-ui-i18n.mjs.map
|
|
@@ -14,6 +14,8 @@ import { v4 } from 'uuid';
|
|
|
14
14
|
import { cva } from 'class-variance-authority';
|
|
15
15
|
import { CheckboxDirective } from '@nanahoshi/mona-ui/check-box';
|
|
16
16
|
|
|
17
|
+
// Generated from i18n/catalogs/en-US.messages.json by scripts/generate-locale-catalogs.ts. Do not edit.
|
|
18
|
+
// Edit the JSON file and run `npm run generate:locale-catalogs`.
|
|
17
19
|
const LIST_DEFAULT_MESSAGES = {
|
|
18
20
|
filterList: "Filter list",
|
|
19
21
|
noData: "No data"
|
|
@@ -1352,6 +1352,8 @@ const treeNodeExpanderThemeVariants = cva(`
|
|
|
1352
1352
|
cursor-pointer text-sm text-foreground
|
|
1353
1353
|
`);
|
|
1354
1354
|
|
|
1355
|
+
// Generated from i18n/catalogs/en-US.messages.json by scripts/generate-locale-catalogs.ts. Do not edit.
|
|
1356
|
+
// Edit the JSON file and run `npm run generate:locale-catalogs`.
|
|
1355
1357
|
const TREE_DEFAULT_MESSAGES = {
|
|
1356
1358
|
collapse: "Collapse",
|
|
1357
1359
|
expand: "Expand",
|