@arcgis/components-utils 4.32.0-next.7 → 4.32.0-next.71

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/dist/index.cjs CHANGED
@@ -33,6 +33,7 @@ __export(src_exports, {
33
33
  devToolsAwareTimeout: () => devToolsAwareTimeout,
34
34
  extractMinorVersion: () => extractMinorVersion,
35
35
  fetchT9nStringsBundle: () => fetchT9nStringsBundle,
36
+ focusElement: () => focusElement,
36
37
  generateGuid: () => generateGuid,
37
38
  getElementAttribute: () => getElementAttribute,
38
39
  getElementDir: () => getElementDir,
@@ -41,6 +42,7 @@ __export(src_exports, {
41
42
  getPreamble: () => getPreamble,
42
43
  hasSameOrigin: () => hasSameOrigin,
43
44
  identity: () => identity,
45
+ isEsriInternalEnv: () => isEsriInternalEnv,
44
46
  isNotNull: () => isNotNull,
45
47
  isNotUndefined: () => isNotUndefined,
46
48
  isURL: () => isURL,
@@ -205,16 +207,16 @@ function getElementAttribute(el, prop, fallbackValue) {
205
207
  function isElement(ref) {
206
208
  return ref.nodeType === Node.ELEMENT_NODE;
207
209
  }
208
- function isHTMLWithSetFocus(ref) {
209
- return "setFocus" in ref && typeof ref.setFocus === "function";
210
+ function hasSetFocus(ref) {
211
+ return typeof ref.setFocus === "function";
210
212
  }
211
213
  function setFocus(ref, selector = "") {
212
214
  if (!isElement(ref)) {
213
215
  return false;
214
216
  }
215
217
  if (ref.matches(selector)) {
216
- if (isHTMLWithSetFocus(ref)) {
217
- setTimeout(() => ref.setFocus(), 0);
218
+ if (hasSetFocus(ref)) {
219
+ setTimeout(() => void ref.setFocus(), 0);
218
220
  }
219
221
  return true;
220
222
  }
@@ -233,6 +235,16 @@ function setFocus(ref, selector = "") {
233
235
  }
234
236
  return false;
235
237
  }
238
+ async function focusElement(el) {
239
+ if (el == null) {
240
+ return;
241
+ }
242
+ if (hasSetFocus(el)) {
243
+ await el.setFocus();
244
+ } else {
245
+ el.focus();
246
+ }
247
+ }
236
248
  function setFocusOnElement(ref, selector) {
237
249
  if (!ref?.shadowRoot) {
238
250
  return;
@@ -241,17 +253,13 @@ function setFocusOnElement(ref, selector) {
241
253
  setFocus(ref, selector);
242
254
  return;
243
255
  }
244
- const mutationObserver = new MutationObserver(() => {
245
- mutationObserver.disconnect();
246
- setFocus(ref, selector);
247
- });
248
- mutationObserver.observe(ref, {
249
- attributes: true,
250
- attributeFilter: ["hydrated", "calcite-hydrated"]
251
- });
256
+ void Promise.resolve(ref.componentOnReady?.()).then(() => setFocus(ref, selector));
252
257
  }
253
258
 
254
259
  // src/errors.ts
260
+ function isEsriInternalEnv() {
261
+ return typeof globalThis.process === "object" && !!process.env.ESRI_INTERNAL;
262
+ }
255
263
  function safeCall(callback, thisContext, ...rest) {
256
264
  try {
257
265
  return callback?.call(thisContext, ...rest);
@@ -308,6 +316,7 @@ var supportedLocalesArray = [
308
316
  "lv",
309
317
  "nl",
310
318
  "nb",
319
+ "no",
311
320
  "pl",
312
321
  "pt-BR",
313
322
  "pt-PT",
@@ -325,13 +334,13 @@ var supportedLocalesArray = [
325
334
  "zh-HK",
326
335
  "zh-TW"
327
336
  ];
328
- var supportedLocales = new Set(supportedLocalesArray);
337
+ var supportedLocales = /* @__PURE__ */ new Set(supportedLocalesArray);
329
338
  var defaultLocale = "en";
330
339
  var localeEquivalencies = {
331
- // We use `pt-BR` as it will have the same translations as `pt`, which has no corresponding bundle
340
+ // We use `pt-PT` as it will have the same translations as `pt`, which has no corresponding bundle
332
341
  pt: "pt-PT",
333
- // We support both 'nb' and 'no' (BCP 47) for Norwegian but only `nb` has corresponding bundle
334
- no: "nb",
342
+ // We support both 'nb' and 'no' (BCP 47) for Norwegian but only `no` has corresponding bundle
343
+ nb: "no",
335
344
  // We use `zh-CN` as base translation for chinese locales which has no corresponding bundle.
336
345
  zh: "zh-CN"
337
346
  };
@@ -350,7 +359,19 @@ async function fetchBundle(locale, path) {
350
359
  return await response.json();
351
360
  }
352
361
  } catch (error) {
353
- console.error(error);
362
+ if (typeof process === "object" && process.env.NODE_ENV !== "production") {
363
+ const is404ViteFallback = String(error).includes(`Unexpected token '<', "<!doctype "... is not valid JSON`);
364
+ if (is404ViteFallback) {
365
+ if (filePath.includes("calcite")) {
366
+ return {};
367
+ }
368
+ console.error(`[404] Localization strings not found at ${filePath}`);
369
+ } else {
370
+ console.error(`Error fetching localization strings at ${filePath}`, error);
371
+ }
372
+ } else {
373
+ console.error(error);
374
+ }
354
375
  return {};
355
376
  }
356
377
  if (locale === defaultLocale) {
@@ -392,11 +413,15 @@ function startLocaleObserver(element, assetsPath, onUpdated, assetName) {
392
413
  async function updateComponentLocaleState(element, assetsPath, assetName = element.tagName.toLowerCase().split("-").slice(1).join("-")) {
393
414
  const { lang, t9nLocale } = getElementLocales(element);
394
415
  const t9nAssetsPath = `${assetsPath}/${assetName}/t9n`;
395
- const prefix = `${assetName}.t9n.`;
396
- const t9nStrings = (
416
+ const prefix = `messages.`;
417
+ let t9nStrings = (
397
418
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
398
419
  assetName === null ? {} : await fetchT9nStringsBundle(t9nLocale, t9nAssetsPath, prefix)
399
420
  );
421
+ if (assetName !== null && Object.keys(t9nStrings).length === 0) {
422
+ const prefix2 = `${assetName}.t9n.`;
423
+ t9nStrings = await fetchT9nStringsBundle(t9nLocale, t9nAssetsPath, prefix2);
424
+ }
400
425
  return { lang, t9nLocale, t9nStrings };
401
426
  }
402
427
 
@@ -535,6 +560,7 @@ function isURL(url) {
535
560
  devToolsAwareTimeout,
536
561
  extractMinorVersion,
537
562
  fetchT9nStringsBundle,
563
+ focusElement,
538
564
  generateGuid,
539
565
  getElementAttribute,
540
566
  getElementDir,
@@ -543,6 +569,7 @@ function isURL(url) {
543
569
  getPreamble,
544
570
  hasSameOrigin,
545
571
  identity,
572
+ isEsriInternalEnv,
546
573
  isNotNull,
547
574
  isNotUndefined,
548
575
  isURL,
package/dist/index.d.cts CHANGED
@@ -125,6 +125,10 @@ declare function getElementDir(el: HTMLElement): "ltr" | "rtl";
125
125
  * @returns The attribute value or the fallback value if the attribute is not found.
126
126
  */
127
127
  declare function getElementAttribute(el: Element, prop: string, fallbackValue: string): string;
128
+ interface FocusableElement extends HTMLElement {
129
+ setFocus?: () => Promise<void>;
130
+ }
131
+ declare function focusElement(el: FocusableElement | undefined): Promise<void>;
128
132
  /**
129
133
  * Set the focus on the element that matches the selector.
130
134
  * It will traverse the element's ancestors to find the target element.
@@ -134,9 +138,32 @@ declare function getElementAttribute(el: Element, prop: string, fallbackValue: s
134
138
  * @param ref The element to start the search from.
135
139
  * @param selector The selector to match.
136
140
  * @returns Returns true if the focus is set on the element.
141
+ *
142
+ * REFACTOR: this is doing too much. break it into separate find element and focus
143
+ * element utilities
137
144
  */
138
- declare function setFocusOnElement(ref: Element | null | undefined, selector: string): void;
145
+ declare function setFocusOnElement(ref: (Element & {
146
+ componentOnReady?: () => Promise<void>;
147
+ }) | null | undefined, selector: string): void;
139
148
 
149
+ /**
150
+ * Check whether the code is executing in an Esri internal environment (for
151
+ * example, Lumina dev server). When true, your code can enable extra validation
152
+ * to detect incorrect usages or do runtime bug detection.
153
+ *
154
+ * The call to isEsriInternalEnv() MUST always appear behind one of the
155
+ * following guards to ensure it is correctly eliminated in production bundles:
156
+ *
157
+ * - `typeof process === 'object' && process.env.NODE_ENV !== "production"`
158
+ * - `typeof process === 'object' && process.env.NODE_ENV === "development"`
159
+ * - `typeof process === 'object' && process.env.NODE_ENV === "test"`
160
+ *
161
+ * @remarks
162
+ * This function is primary for usage in support packages. In Lumina component
163
+ * packages, simpler alternatives are provided:
164
+ * https://qawebgis.esri.com/components/lumina/publishing#bundling-code-conditionally
165
+ */
166
+ declare function isEsriInternalEnv(): boolean;
140
167
  /**
141
168
  * Calls a sync method and catch any errors. Returns undefined if error occurred.
142
169
  *
@@ -162,11 +189,11 @@ declare function generateGuid(): string;
162
189
  interface GenericT9nStrings {
163
190
  [key: string]: GenericT9nStrings | string;
164
191
  }
165
- declare const supportedLocalesArray: readonly ["ar", "bg", "bs", "ca", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "he", "hr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nl", "nb", "pl", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-HK", "zh-TW"];
192
+ declare const supportedLocalesArray: readonly ["ar", "bg", "bs", "ca", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "he", "hr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nl", "nb", "no", "pl", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-HK", "zh-TW"];
166
193
  /**
167
194
  * The list of supported locales for ArcGIS Maps SDK for JavaScript components.
168
195
  */
169
- declare const supportedLocales: Set<"hr" | "th" | "tr" | "ar" | "bg" | "bs" | "ca" | "cs" | "da" | "de" | "el" | "en" | "es" | "et" | "fi" | "fr" | "he" | "hu" | "id" | "it" | "ja" | "ko" | "lt" | "lv" | "nl" | "nb" | "pl" | "pt-BR" | "pt-PT" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "uk" | "vi" | "zh-CN" | "zh-HK" | "zh-TW">;
196
+ declare const supportedLocales: Set<"hr" | "th" | "tr" | "ar" | "bg" | "bs" | "ca" | "cs" | "da" | "de" | "el" | "en" | "es" | "et" | "fi" | "fr" | "he" | "hu" | "id" | "it" | "ja" | "ko" | "lt" | "lv" | "nl" | "nb" | "no" | "pl" | "pt-BR" | "pt-PT" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "uk" | "vi" | "zh-CN" | "zh-HK" | "zh-TW">;
170
197
  type SupportedLocale = (typeof supportedLocalesArray)[number];
171
198
  declare const defaultLocale = "en";
172
199
  /**
@@ -180,7 +207,7 @@ declare const defaultLocale = "en";
180
207
  *
181
208
  * @example
182
209
  * ```ts
183
- * const t9nStrings = await fetchT9nStringsBundle("en", getAssetPath("./assets/coding-editor/t9n"), "coding-editor.t9n.");
210
+ * const t9nStrings = await fetchT9nStringsBundle("en", getAssetPath("./assets/coding-editor/t9n"), "messages.");
184
211
  * ```
185
212
  */
186
213
  declare function fetchT9nStringsBundle<Strings extends GenericT9nStrings>(
@@ -340,4 +367,4 @@ declare function hasSameOrigin(url1: string | null | undefined, url2: string | n
340
367
  */
341
368
  declare function isURL(url: string): boolean;
342
369
 
343
- export { Deferred, type GenericT9nStrings, type IHandle, type LocaleObserver, type Nil, type SupportedLocale, type Writable, addLTRMark, camelToHuman, camelToKebab, capitalize, classes, closestElement, createFilterExpression, debounce, defaultLocale, devToolsAwareTimeout, extractMinorVersion, fetchT9nStringsBundle, generateGuid, getElementAttribute, getElementDir, getElementLocales, getElementTheme, getPreamble, hasSameOrigin, identity, isNotNull, isNotUndefined, isURL, kebabToPascal, mappedFind, normalizeLocale, observeAncestorsMutation, quoteString, safeAsyncCall, safeCall, setFocusOnElement, setValuesInString, startLocaleObserver, supportedLocales, uncapitalize };
370
+ export { Deferred, type FocusableElement, type GenericT9nStrings, type IHandle, type LocaleObserver, type Nil, type SupportedLocale, type Writable, addLTRMark, camelToHuman, camelToKebab, capitalize, classes, closestElement, createFilterExpression, debounce, defaultLocale, devToolsAwareTimeout, extractMinorVersion, fetchT9nStringsBundle, focusElement, generateGuid, getElementAttribute, getElementDir, getElementLocales, getElementTheme, getPreamble, hasSameOrigin, identity, isEsriInternalEnv, isNotNull, isNotUndefined, isURL, kebabToPascal, mappedFind, normalizeLocale, observeAncestorsMutation, quoteString, safeAsyncCall, safeCall, setFocusOnElement, setValuesInString, startLocaleObserver, supportedLocales, uncapitalize };
package/dist/index.d.ts CHANGED
@@ -125,6 +125,10 @@ declare function getElementDir(el: HTMLElement): "ltr" | "rtl";
125
125
  * @returns The attribute value or the fallback value if the attribute is not found.
126
126
  */
127
127
  declare function getElementAttribute(el: Element, prop: string, fallbackValue: string): string;
128
+ interface FocusableElement extends HTMLElement {
129
+ setFocus?: () => Promise<void>;
130
+ }
131
+ declare function focusElement(el: FocusableElement | undefined): Promise<void>;
128
132
  /**
129
133
  * Set the focus on the element that matches the selector.
130
134
  * It will traverse the element's ancestors to find the target element.
@@ -134,9 +138,32 @@ declare function getElementAttribute(el: Element, prop: string, fallbackValue: s
134
138
  * @param ref The element to start the search from.
135
139
  * @param selector The selector to match.
136
140
  * @returns Returns true if the focus is set on the element.
141
+ *
142
+ * REFACTOR: this is doing too much. break it into separate find element and focus
143
+ * element utilities
137
144
  */
138
- declare function setFocusOnElement(ref: Element | null | undefined, selector: string): void;
145
+ declare function setFocusOnElement(ref: (Element & {
146
+ componentOnReady?: () => Promise<void>;
147
+ }) | null | undefined, selector: string): void;
139
148
 
149
+ /**
150
+ * Check whether the code is executing in an Esri internal environment (for
151
+ * example, Lumina dev server). When true, your code can enable extra validation
152
+ * to detect incorrect usages or do runtime bug detection.
153
+ *
154
+ * The call to isEsriInternalEnv() MUST always appear behind one of the
155
+ * following guards to ensure it is correctly eliminated in production bundles:
156
+ *
157
+ * - `typeof process === 'object' && process.env.NODE_ENV !== "production"`
158
+ * - `typeof process === 'object' && process.env.NODE_ENV === "development"`
159
+ * - `typeof process === 'object' && process.env.NODE_ENV === "test"`
160
+ *
161
+ * @remarks
162
+ * This function is primary for usage in support packages. In Lumina component
163
+ * packages, simpler alternatives are provided:
164
+ * https://qawebgis.esri.com/components/lumina/publishing#bundling-code-conditionally
165
+ */
166
+ declare function isEsriInternalEnv(): boolean;
140
167
  /**
141
168
  * Calls a sync method and catch any errors. Returns undefined if error occurred.
142
169
  *
@@ -162,11 +189,11 @@ declare function generateGuid(): string;
162
189
  interface GenericT9nStrings {
163
190
  [key: string]: GenericT9nStrings | string;
164
191
  }
165
- declare const supportedLocalesArray: readonly ["ar", "bg", "bs", "ca", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "he", "hr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nl", "nb", "pl", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-HK", "zh-TW"];
192
+ declare const supportedLocalesArray: readonly ["ar", "bg", "bs", "ca", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "he", "hr", "hu", "id", "it", "ja", "ko", "lt", "lv", "nl", "nb", "no", "pl", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-HK", "zh-TW"];
166
193
  /**
167
194
  * The list of supported locales for ArcGIS Maps SDK for JavaScript components.
168
195
  */
169
- declare const supportedLocales: Set<"hr" | "th" | "tr" | "ar" | "bg" | "bs" | "ca" | "cs" | "da" | "de" | "el" | "en" | "es" | "et" | "fi" | "fr" | "he" | "hu" | "id" | "it" | "ja" | "ko" | "lt" | "lv" | "nl" | "nb" | "pl" | "pt-BR" | "pt-PT" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "uk" | "vi" | "zh-CN" | "zh-HK" | "zh-TW">;
196
+ declare const supportedLocales: Set<"hr" | "th" | "tr" | "ar" | "bg" | "bs" | "ca" | "cs" | "da" | "de" | "el" | "en" | "es" | "et" | "fi" | "fr" | "he" | "hu" | "id" | "it" | "ja" | "ko" | "lt" | "lv" | "nl" | "nb" | "no" | "pl" | "pt-BR" | "pt-PT" | "ro" | "ru" | "sk" | "sl" | "sr" | "sv" | "uk" | "vi" | "zh-CN" | "zh-HK" | "zh-TW">;
170
197
  type SupportedLocale = (typeof supportedLocalesArray)[number];
171
198
  declare const defaultLocale = "en";
172
199
  /**
@@ -180,7 +207,7 @@ declare const defaultLocale = "en";
180
207
  *
181
208
  * @example
182
209
  * ```ts
183
- * const t9nStrings = await fetchT9nStringsBundle("en", getAssetPath("./assets/coding-editor/t9n"), "coding-editor.t9n.");
210
+ * const t9nStrings = await fetchT9nStringsBundle("en", getAssetPath("./assets/coding-editor/t9n"), "messages.");
184
211
  * ```
185
212
  */
186
213
  declare function fetchT9nStringsBundle<Strings extends GenericT9nStrings>(
@@ -340,4 +367,4 @@ declare function hasSameOrigin(url1: string | null | undefined, url2: string | n
340
367
  */
341
368
  declare function isURL(url: string): boolean;
342
369
 
343
- export { Deferred, type GenericT9nStrings, type IHandle, type LocaleObserver, type Nil, type SupportedLocale, type Writable, addLTRMark, camelToHuman, camelToKebab, capitalize, classes, closestElement, createFilterExpression, debounce, defaultLocale, devToolsAwareTimeout, extractMinorVersion, fetchT9nStringsBundle, generateGuid, getElementAttribute, getElementDir, getElementLocales, getElementTheme, getPreamble, hasSameOrigin, identity, isNotNull, isNotUndefined, isURL, kebabToPascal, mappedFind, normalizeLocale, observeAncestorsMutation, quoteString, safeAsyncCall, safeCall, setFocusOnElement, setValuesInString, startLocaleObserver, supportedLocales, uncapitalize };
370
+ export { Deferred, type FocusableElement, type GenericT9nStrings, type IHandle, type LocaleObserver, type Nil, type SupportedLocale, type Writable, addLTRMark, camelToHuman, camelToKebab, capitalize, classes, closestElement, createFilterExpression, debounce, defaultLocale, devToolsAwareTimeout, extractMinorVersion, fetchT9nStringsBundle, focusElement, generateGuid, getElementAttribute, getElementDir, getElementLocales, getElementTheme, getPreamble, hasSameOrigin, identity, isEsriInternalEnv, isNotNull, isNotUndefined, isURL, kebabToPascal, mappedFind, normalizeLocale, observeAncestorsMutation, quoteString, safeAsyncCall, safeCall, setFocusOnElement, setValuesInString, startLocaleObserver, supportedLocales, uncapitalize };
package/dist/index.js CHANGED
@@ -144,16 +144,16 @@ function getElementAttribute(el, prop, fallbackValue) {
144
144
  function isElement(ref) {
145
145
  return ref.nodeType === Node.ELEMENT_NODE;
146
146
  }
147
- function isHTMLWithSetFocus(ref) {
148
- return "setFocus" in ref && typeof ref.setFocus === "function";
147
+ function hasSetFocus(ref) {
148
+ return typeof ref.setFocus === "function";
149
149
  }
150
150
  function setFocus(ref, selector = "") {
151
151
  if (!isElement(ref)) {
152
152
  return false;
153
153
  }
154
154
  if (ref.matches(selector)) {
155
- if (isHTMLWithSetFocus(ref)) {
156
- setTimeout(() => ref.setFocus(), 0);
155
+ if (hasSetFocus(ref)) {
156
+ setTimeout(() => void ref.setFocus(), 0);
157
157
  }
158
158
  return true;
159
159
  }
@@ -172,6 +172,16 @@ function setFocus(ref, selector = "") {
172
172
  }
173
173
  return false;
174
174
  }
175
+ async function focusElement(el) {
176
+ if (el == null) {
177
+ return;
178
+ }
179
+ if (hasSetFocus(el)) {
180
+ await el.setFocus();
181
+ } else {
182
+ el.focus();
183
+ }
184
+ }
175
185
  function setFocusOnElement(ref, selector) {
176
186
  if (!ref?.shadowRoot) {
177
187
  return;
@@ -180,17 +190,13 @@ function setFocusOnElement(ref, selector) {
180
190
  setFocus(ref, selector);
181
191
  return;
182
192
  }
183
- const mutationObserver = new MutationObserver(() => {
184
- mutationObserver.disconnect();
185
- setFocus(ref, selector);
186
- });
187
- mutationObserver.observe(ref, {
188
- attributes: true,
189
- attributeFilter: ["hydrated", "calcite-hydrated"]
190
- });
193
+ void Promise.resolve(ref.componentOnReady?.()).then(() => setFocus(ref, selector));
191
194
  }
192
195
 
193
196
  // src/errors.ts
197
+ function isEsriInternalEnv() {
198
+ return typeof globalThis.process === "object" && !!process.env.ESRI_INTERNAL;
199
+ }
194
200
  function safeCall(callback, thisContext, ...rest) {
195
201
  try {
196
202
  return callback?.call(thisContext, ...rest);
@@ -247,6 +253,7 @@ var supportedLocalesArray = [
247
253
  "lv",
248
254
  "nl",
249
255
  "nb",
256
+ "no",
250
257
  "pl",
251
258
  "pt-BR",
252
259
  "pt-PT",
@@ -264,13 +271,13 @@ var supportedLocalesArray = [
264
271
  "zh-HK",
265
272
  "zh-TW"
266
273
  ];
267
- var supportedLocales = new Set(supportedLocalesArray);
274
+ var supportedLocales = /* @__PURE__ */ new Set(supportedLocalesArray);
268
275
  var defaultLocale = "en";
269
276
  var localeEquivalencies = {
270
- // We use `pt-BR` as it will have the same translations as `pt`, which has no corresponding bundle
277
+ // We use `pt-PT` as it will have the same translations as `pt`, which has no corresponding bundle
271
278
  pt: "pt-PT",
272
- // We support both 'nb' and 'no' (BCP 47) for Norwegian but only `nb` has corresponding bundle
273
- no: "nb",
279
+ // We support both 'nb' and 'no' (BCP 47) for Norwegian but only `no` has corresponding bundle
280
+ nb: "no",
274
281
  // We use `zh-CN` as base translation for chinese locales which has no corresponding bundle.
275
282
  zh: "zh-CN"
276
283
  };
@@ -289,7 +296,19 @@ async function fetchBundle(locale, path) {
289
296
  return await response.json();
290
297
  }
291
298
  } catch (error) {
292
- console.error(error);
299
+ if (typeof process === "object" && process.env.NODE_ENV !== "production") {
300
+ const is404ViteFallback = String(error).includes(`Unexpected token '<', "<!doctype "... is not valid JSON`);
301
+ if (is404ViteFallback) {
302
+ if (filePath.includes("calcite")) {
303
+ return {};
304
+ }
305
+ console.error(`[404] Localization strings not found at ${filePath}`);
306
+ } else {
307
+ console.error(`Error fetching localization strings at ${filePath}`, error);
308
+ }
309
+ } else {
310
+ console.error(error);
311
+ }
293
312
  return {};
294
313
  }
295
314
  if (locale === defaultLocale) {
@@ -331,11 +350,15 @@ function startLocaleObserver(element, assetsPath, onUpdated, assetName) {
331
350
  async function updateComponentLocaleState(element, assetsPath, assetName = element.tagName.toLowerCase().split("-").slice(1).join("-")) {
332
351
  const { lang, t9nLocale } = getElementLocales(element);
333
352
  const t9nAssetsPath = `${assetsPath}/${assetName}/t9n`;
334
- const prefix = `${assetName}.t9n.`;
335
- const t9nStrings = (
353
+ const prefix = `messages.`;
354
+ let t9nStrings = (
336
355
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
337
356
  assetName === null ? {} : await fetchT9nStringsBundle(t9nLocale, t9nAssetsPath, prefix)
338
357
  );
358
+ if (assetName !== null && Object.keys(t9nStrings).length === 0) {
359
+ const prefix2 = `${assetName}.t9n.`;
360
+ t9nStrings = await fetchT9nStringsBundle(t9nLocale, t9nAssetsPath, prefix2);
361
+ }
339
362
  return { lang, t9nLocale, t9nStrings };
340
363
  }
341
364
 
@@ -473,6 +496,7 @@ export {
473
496
  devToolsAwareTimeout,
474
497
  extractMinorVersion,
475
498
  fetchT9nStringsBundle,
499
+ focusElement,
476
500
  generateGuid,
477
501
  getElementAttribute,
478
502
  getElementDir,
@@ -481,6 +505,7 @@ export {
481
505
  getPreamble,
482
506
  hasSameOrigin,
483
507
  identity,
508
+ isEsriInternalEnv,
484
509
  isNotNull,
485
510
  isNotUndefined,
486
511
  isURL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcgis/components-utils",
3
- "version": "4.32.0-next.7",
3
+ "version": "4.32.0-next.71",
4
4
  "description": "Collection of common internal patterns and utilities for ArcGIS Maps SDK for JavaScript components.",
5
5
  "homepage": "https://developers.arcgis.com/javascript/latest/",
6
6
  "sideEffects": false,