@powerportalspro/react 5.0.0-beta.3 → 5.0.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.
package/dist/index.cjs CHANGED
@@ -4,7 +4,273 @@ var react = require('react');
4
4
  var core = require('@powerportalspro/core');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
- // src/context.ts
7
+ // src/masking/reformat.ts
8
+ var MaskMode = {
9
+ /** No masking — value passes through unchanged. */
10
+ None: "none",
11
+ /**
12
+ * Per-character allow filter. Characters that don't match
13
+ * {@link MaskOptions.allowedPattern} are dropped as they're typed or pasted.
14
+ */
15
+ Regex: "regex",
16
+ /**
17
+ * Slotted template (see {@link MaskOptions.pattern}) such as `(000) 000-0000`.
18
+ * `0` = digit, `A` = letter, `*` = alphanumeric; every other character is a
19
+ * literal inserted automatically.
20
+ */
21
+ Pattern: "pattern",
22
+ /**
23
+ * Live numeric grouping driven by {@link MaskOptions.numeric} — thousands
24
+ * separators, an optional decimal portion, and an optional leading sign.
25
+ */
26
+ Numeric: "numeric"
27
+ };
28
+ var DIGIT = /[0-9]/;
29
+ var LETTER = /[a-zA-Z]/;
30
+ var ALNUM = /[a-zA-Z0-9]/;
31
+ function isPatternLiteral(token) {
32
+ return token !== "0" && token !== "A" && token !== "*";
33
+ }
34
+ function patternTokenMatches(token, ch) {
35
+ if (token === "0") return DIGIT.test(ch);
36
+ if (token === "A") return LETTER.test(ch);
37
+ if (token === "*") return ALNUM.test(ch);
38
+ return false;
39
+ }
40
+ function countSignificant(source, caret, isSignificant) {
41
+ let n = 0;
42
+ for (let i = 0; i < caret && i < source.length; i++) {
43
+ if (isSignificant(source.charAt(i))) n++;
44
+ }
45
+ return n;
46
+ }
47
+ function caretAfterSignificant(display, target, isSignificant) {
48
+ if (target <= 0) {
49
+ let i = 0;
50
+ while (i < display.length && !isSignificant(display.charAt(i))) i++;
51
+ return i;
52
+ }
53
+ let seen = 0;
54
+ for (let i = 0; i < display.length; i++) {
55
+ if (isSignificant(display.charAt(i))) {
56
+ seen++;
57
+ if (seen === target) return i + 1;
58
+ }
59
+ }
60
+ return display.length;
61
+ }
62
+ function reformatNumeric(value, caret, o) {
63
+ const sigChars = (c) => DIGIT.test(c) || c === o.decimalSeparator || o.allowNegative && c === "-";
64
+ const sigBefore = countSignificant(value, caret, sigChars);
65
+ const negative = o.allowNegative && value.trimStart().startsWith("-");
66
+ let intPart = "";
67
+ let fracPart = "";
68
+ let sawDecimal = false;
69
+ for (const ch of value) {
70
+ if (DIGIT.test(ch)) {
71
+ if (sawDecimal) fracPart += ch;
72
+ else intPart += ch;
73
+ } else if (o.allowDecimal && ch === o.decimalSeparator && !sawDecimal) {
74
+ sawDecimal = true;
75
+ }
76
+ }
77
+ intPart = intPart.replace(/^0+(?=\d)/, "");
78
+ if (o.maxDecimals !== null && fracPart.length > o.maxDecimals) {
79
+ fracPart = fracPart.slice(0, o.maxDecimals);
80
+ }
81
+ const grouped = o.groupSeparator ? intPart.replace(/\B(?=(\d{3})+(?!\d))/g, o.groupSeparator) : intPart;
82
+ const sign = negative ? "-" : "";
83
+ let display = sign + grouped;
84
+ let raw = sign + intPart;
85
+ if (sawDecimal) {
86
+ display += o.decimalSeparator + fracPart;
87
+ raw += o.decimalSeparator + fracPart;
88
+ }
89
+ const newCaret = caretAfterSignificant(display, sigBefore, sigChars);
90
+ return { display, raw, caret: newCaret };
91
+ }
92
+ function reformatPattern(value, caret, pattern) {
93
+ const sourceChars = [];
94
+ for (const ch of value) {
95
+ if (DIGIT.test(ch) || LETTER.test(ch)) sourceChars.push(ch);
96
+ }
97
+ const sigBefore = countSignificant(value, caret, (c) => DIGIT.test(c) || LETTER.test(c));
98
+ let display = "";
99
+ let raw = "";
100
+ let si = 0;
101
+ for (let pi = 0; pi < pattern.length && si <= sourceChars.length; pi++) {
102
+ const token = pattern[pi];
103
+ if (isPatternLiteral(token)) {
104
+ if (si < sourceChars.length) display += token;
105
+ continue;
106
+ }
107
+ while (si < sourceChars.length && !patternTokenMatches(token, sourceChars[si])) si++;
108
+ if (si < sourceChars.length) {
109
+ display += sourceChars[si];
110
+ raw += sourceChars[si];
111
+ si++;
112
+ } else {
113
+ break;
114
+ }
115
+ }
116
+ const newCaret = caretAfterSignificant(display, sigBefore, (c) => DIGIT.test(c) || LETTER.test(c));
117
+ return { display, raw, caret: newCaret };
118
+ }
119
+ function reformatRegex(value, caret, allowedPattern) {
120
+ let re;
121
+ try {
122
+ re = new RegExp(allowedPattern);
123
+ } catch {
124
+ return { display: value, raw: value, caret };
125
+ }
126
+ const keep = (c) => re.test(c);
127
+ const sigBefore = countSignificant(value, caret, keep);
128
+ let display = "";
129
+ for (const ch of value) {
130
+ if (keep(ch)) display += ch;
131
+ }
132
+ const newCaret = caretAfterSignificant(display, sigBefore, keep);
133
+ return { display, raw: display, caret: newCaret };
134
+ }
135
+ function reformat(value, caret, options) {
136
+ switch (options.mode) {
137
+ case MaskMode.Numeric:
138
+ return options.numeric ? reformatNumeric(value, caret, options.numeric) : { display: value, raw: value, caret };
139
+ case MaskMode.Pattern:
140
+ return options.pattern ? reformatPattern(value, caret, options.pattern) : { display: value, raw: value, caret };
141
+ case MaskMode.Regex:
142
+ return options.allowedPattern ? reformatRegex(value, caret, options.allowedPattern) : { display: value, raw: value, caret };
143
+ default:
144
+ return { display: value, raw: value, caret };
145
+ }
146
+ }
147
+ function computeDisplay(value, options) {
148
+ if (value === null || value === void 0 || value === "") return "";
149
+ return reformat(value, value.length, options).display;
150
+ }
151
+ function computeReported(value, options) {
152
+ if (value === null || value === void 0 || value === "") return "";
153
+ const r = reformat(value, value.length, options);
154
+ return options.valueIncludesMask ? r.display : r.raw;
155
+ }
156
+ function useMaskedTextField(opts) {
157
+ const {
158
+ value,
159
+ onValueChange,
160
+ mode = MaskMode.None,
161
+ pattern = null,
162
+ allowedPattern = null,
163
+ numeric = null,
164
+ valueIncludesMask = false
165
+ } = opts;
166
+ const optionsRef = react.useRef({
167
+ mode,
168
+ pattern,
169
+ allowedPattern,
170
+ numeric,
171
+ valueIncludesMask
172
+ });
173
+ optionsRef.current = { mode, pattern, allowedPattern, numeric, valueIncludesMask };
174
+ const onValueChangeRef = react.useRef(onValueChange);
175
+ onValueChangeRef.current = onValueChange;
176
+ const elementRef = react.useRef(null);
177
+ const focusedRef = react.useRef(false);
178
+ const hasInputSinceFocusRef = react.useRef(false);
179
+ const lastReportedRef = react.useRef(null);
180
+ const pendingCaretRef = react.useRef(null);
181
+ const [displayValue, setDisplayValue] = react.useState(
182
+ () => computeDisplay(value, optionsRef.current)
183
+ );
184
+ react.useEffect(() => {
185
+ if (focusedRef.current && hasInputSinceFocusRef.current) return;
186
+ const next = computeDisplay(value, optionsRef.current);
187
+ setDisplayValue(next);
188
+ lastReportedRef.current = computeReported(value, optionsRef.current);
189
+ }, [value]);
190
+ react.useEffect(() => {
191
+ if (focusedRef.current && hasInputSinceFocusRef.current) return;
192
+ const next = computeDisplay(value, optionsRef.current);
193
+ setDisplayValue(next);
194
+ lastReportedRef.current = computeReported(value, optionsRef.current);
195
+ }, [mode, pattern, allowedPattern, numeric, valueIncludesMask]);
196
+ react.useLayoutEffect(() => {
197
+ const target = pendingCaretRef.current;
198
+ if (target === null) return;
199
+ const input = elementRef.current;
200
+ if (!input) return;
201
+ try {
202
+ input.setSelectionRange(target, target);
203
+ } catch {
204
+ }
205
+ pendingCaretRef.current = null;
206
+ });
207
+ const onChange = react.useCallback(
208
+ (_event, data) => {
209
+ hasInputSinceFocusRef.current = true;
210
+ const o = optionsRef.current;
211
+ const input = elementRef.current;
212
+ const caret = input?.selectionStart ?? data.value.length;
213
+ const result = reformat(data.value, caret, o);
214
+ setDisplayValue(result.display);
215
+ pendingCaretRef.current = result.caret;
216
+ const reported = o.valueIncludesMask ? result.display : result.raw;
217
+ const empty = reported === "";
218
+ const next = empty ? null : reported;
219
+ if (reported !== lastReportedRef.current) {
220
+ lastReportedRef.current = reported;
221
+ onValueChangeRef.current(next);
222
+ }
223
+ },
224
+ []
225
+ );
226
+ const inputRef = react.useCallback((el) => {
227
+ const prev = elementRef.current;
228
+ if (prev && prev !== el) {
229
+ prev.removeEventListener("focus", handleFocusRef.current);
230
+ prev.removeEventListener("blur", handleBlurRef.current);
231
+ }
232
+ elementRef.current = el;
233
+ if (el) {
234
+ el.addEventListener("focus", handleFocusRef.current);
235
+ el.addEventListener("blur", handleBlurRef.current);
236
+ }
237
+ }, []);
238
+ const handleFocusRef = react.useRef(() => {
239
+ });
240
+ handleFocusRef.current = () => {
241
+ focusedRef.current = true;
242
+ hasInputSinceFocusRef.current = false;
243
+ };
244
+ const handleBlurRef = react.useRef(() => {
245
+ });
246
+ handleBlurRef.current = () => {
247
+ focusedRef.current = false;
248
+ if (!hasInputSinceFocusRef.current) {
249
+ const next = computeDisplay(value, optionsRef.current);
250
+ if (next !== displayValue) {
251
+ setDisplayValue(next);
252
+ lastReportedRef.current = computeReported(value, optionsRef.current);
253
+ }
254
+ }
255
+ };
256
+ const forceValue = react.useCallback((newValue) => {
257
+ const o = optionsRef.current;
258
+ if (newValue === null || newValue === "") {
259
+ setDisplayValue("");
260
+ lastReportedRef.current = "";
261
+ pendingCaretRef.current = 0;
262
+ onValueChangeRef.current(null);
263
+ return;
264
+ }
265
+ const result = reformat(newValue, newValue.length, o);
266
+ setDisplayValue(result.display);
267
+ pendingCaretRef.current = result.display.length;
268
+ const reported = o.valueIncludesMask ? result.display : result.raw;
269
+ lastReportedRef.current = reported;
270
+ onValueChangeRef.current(reported === "" ? null : reported);
271
+ }, []);
272
+ return { displayValue, onChange, inputRef, forceValue };
273
+ }
8
274
  var AuthStatus = {
9
275
  Loading: "loading",
10
276
  Anonymous: "anonymous",
@@ -78,19 +344,19 @@ var InMemoryViewMetadataCache = class {
78
344
  this.cache.clear();
79
345
  }
80
346
  };
81
- var InMemoryEnvironmentFileSettingsCache = class _InMemoryEnvironmentFileSettingsCache {
82
- static KEY = "environment-file-settings";
347
+ var InMemoryOrganizationSettingsCache = class _InMemoryOrganizationSettingsCache {
348
+ static KEY = "organization-settings";
83
349
  cache;
84
350
  constructor(ppp) {
85
351
  this.cache = new InMemoryCache(
86
- () => ppp.getEnvironmentFileSettingsAsync()
352
+ () => ppp.getOrganizationSettingsAsync()
87
353
  );
88
354
  }
89
355
  getAsync() {
90
- return this.cache.getAsync(_InMemoryEnvironmentFileSettingsCache.KEY);
356
+ return this.cache.getAsync(_InMemoryOrganizationSettingsCache.KEY);
91
357
  }
92
358
  invalidate() {
93
- this.cache.invalidate(_InMemoryEnvironmentFileSettingsCache.KEY);
359
+ this.cache.invalidate(_InMemoryOrganizationSettingsCache.KEY);
94
360
  }
95
361
  };
96
362
  var InMemoryViewsForTableCache = class {
@@ -257,6 +523,31 @@ function getLocaleFromUrlPath(pattern = DEFAULT_URL_LOCALE_PATTERN) {
257
523
  const match = window.location.pathname.match(pattern);
258
524
  return match?.[1] ?? null;
259
525
  }
526
+ function shouldPrefixLocale(strategy, locale, defaultLocale) {
527
+ switch (strategy) {
528
+ case "CookieOnly":
529
+ return false;
530
+ case "PathPrefixAll":
531
+ return true;
532
+ default:
533
+ return locale.toLowerCase() !== defaultLocale.toLowerCase();
534
+ }
535
+ }
536
+ function stripLocalePrefix(pathname, supportedLocales) {
537
+ const trimmed = pathname.replace(/^\/+/, "");
538
+ if (trimmed.length === 0) return "/";
539
+ const slash = trimmed.indexOf("/");
540
+ const first = slash < 0 ? trimmed : trimmed.slice(0, slash);
541
+ const isLocale = supportedLocales.some((l) => l.toLowerCase() === first.toLowerCase());
542
+ if (!isLocale) return pathname.startsWith("/") ? pathname : `/${pathname}`;
543
+ const rest = slash < 0 ? "" : trimmed.slice(slash);
544
+ return rest.length === 0 ? "/" : rest;
545
+ }
546
+ function buildLocalePath(options) {
547
+ const { strategy, locale, defaultLocale, pathname, supportedLocales } = options;
548
+ const cultureless = stripLocalePrefix(pathname, supportedLocales);
549
+ return shouldPrefixLocale(strategy, locale, defaultLocale) ? `/${locale}${cultureless}` : cultureless;
550
+ }
260
551
  function detectLocale(options) {
261
552
  const {
262
553
  matchUrl = true,
@@ -311,6 +602,12 @@ var LocaleContext = react.createContext(null);
311
602
  LocaleContext.displayName = "Locale";
312
603
  var LocalizationManifestContext = react.createContext(null);
313
604
  LocalizationManifestContext.displayName = "LocalizationManifest";
605
+ function useUrlCultureStrategy() {
606
+ return react.useContext(LocalizationManifestContext)?.urlCultureStrategy;
607
+ }
608
+ function useDefaultLocale() {
609
+ return react.useContext(LocalizationManifestContext)?.supportedLocales?.[0];
610
+ }
314
611
  function useLocale() {
315
612
  const ctx = react.useContext(LocaleContext);
316
613
  return ctx ?? { locale: "en", setLocale: noopSetLocale };
@@ -358,6 +655,9 @@ function DefaultLocalizerProvider({
358
655
  }) {
359
656
  const [cache, setCache] = react.useState({});
360
657
  const [supportedLocales, setSupportedLocales] = react.useState(void 0);
658
+ const [urlCultureStrategy, setUrlCultureStrategy] = react.useState(
659
+ void 0
660
+ );
361
661
  const { locale } = useLocale();
362
662
  const { ppp } = usePowerPortalsPro();
363
663
  const localeRef = react.useRef(locale);
@@ -427,6 +727,7 @@ function DefaultLocalizerProvider({
427
727
  const manifest = await pppRef.current.retrieveLocalizationBundleManifestAsync();
428
728
  if (cancelled) return;
429
729
  setSupportedLocales(manifest.supportedLocales);
730
+ setUrlCultureStrategy(manifest.urlCultureStrategy);
430
731
  const resolvedLocale = manifest.supportedLocales.includes(locale) ? locale : manifest.supportedLocales[0] ?? locale;
431
732
  const thumbs = await pppRef.current.retrieveLocalizationThumbprintsAsync(resolvedLocale);
432
733
  if (cancelled) return;
@@ -615,8 +916,8 @@ function DefaultLocalizerProvider({
615
916
  [flushPending]
616
917
  );
617
918
  const manifestContextValue = react.useMemo(
618
- () => ({ supportedLocales }),
619
- [supportedLocales]
919
+ () => ({ supportedLocales, urlCultureStrategy }),
920
+ [supportedLocales, urlCultureStrategy]
620
921
  );
621
922
  return /* @__PURE__ */ jsxRuntime.jsx(LocalizationManifestContext.Provider, { value: manifestContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(LocalizationPrefetcherContext.Provider, { value: prefetcher, children: /* @__PURE__ */ jsxRuntime.jsx(LocalizerProvider, { value: localizer, children }) }) });
622
923
  }
@@ -685,7 +986,7 @@ function PowerPortalsProProvider({
685
986
  tableMetadataCache,
686
987
  viewMetadataCache,
687
988
  viewsForTableCache,
688
- environmentFileSettingsCache
989
+ organizationSettingsCache
689
990
  }) {
690
991
  const transportRef = react.useRef(null);
691
992
  if (transportRef.current === null) {
@@ -706,9 +1007,9 @@ function PowerPortalsProProvider({
706
1007
  () => viewsForTableCache ?? new InMemoryViewsForTableCache(ppp),
707
1008
  [ppp, viewsForTableCache]
708
1009
  );
709
- const resolvedEnvironmentFileSettingsCache = react.useMemo(
710
- () => environmentFileSettingsCache ?? new InMemoryEnvironmentFileSettingsCache(ppp),
711
- [ppp, environmentFileSettingsCache]
1010
+ const resolvedOrganizationSettingsCache = react.useMemo(
1011
+ () => organizationSettingsCache ?? new InMemoryOrganizationSettingsCache(ppp),
1012
+ [ppp, organizationSettingsCache]
712
1013
  );
713
1014
  const [authState, setAuthState] = react.useState({ status: AuthStatus.Loading });
714
1015
  const refreshAuth = react.useCallback(async () => {
@@ -755,7 +1056,7 @@ function PowerPortalsProProvider({
755
1056
  tableMetadataCache: resolvedTableMetadataCache,
756
1057
  viewMetadataCache: resolvedViewMetadataCache,
757
1058
  viewsForTableCache: resolvedViewsForTableCache,
758
- environmentFileSettingsCache: resolvedEnvironmentFileSettingsCache,
1059
+ organizationSettingsCache: resolvedOrganizationSettingsCache,
759
1060
  authState,
760
1061
  refreshAuth,
761
1062
  login,
@@ -769,7 +1070,7 @@ function PowerPortalsProProvider({
769
1070
  resolvedTableMetadataCache,
770
1071
  resolvedViewMetadataCache,
771
1072
  resolvedViewsForTableCache,
772
- resolvedEnvironmentFileSettingsCache,
1073
+ resolvedOrganizationSettingsCache,
773
1074
  authState,
774
1075
  refreshAuth,
775
1076
  login,
@@ -804,7 +1105,7 @@ function CacheLocaleSync() {
804
1105
  tableMetadataCache,
805
1106
  viewMetadataCache,
806
1107
  viewsForTableCache,
807
- environmentFileSettingsCache
1108
+ organizationSettingsCache
808
1109
  } = usePowerPortalsPro();
809
1110
  const isFirstRun = react.useRef(true);
810
1111
  react.useEffect(() => {
@@ -815,13 +1116,13 @@ function CacheLocaleSync() {
815
1116
  tableMetadataCache.clear();
816
1117
  viewMetadataCache.clear();
817
1118
  viewsForTableCache.clear();
818
- environmentFileSettingsCache.invalidate();
1119
+ organizationSettingsCache.invalidate();
819
1120
  }, [
820
1121
  locale,
821
1122
  tableMetadataCache,
822
1123
  viewMetadataCache,
823
1124
  viewsForTableCache,
824
- environmentFileSettingsCache
1125
+ organizationSettingsCache
825
1126
  ]);
826
1127
  return null;
827
1128
  }
@@ -1230,16 +1531,16 @@ function useViewsForTable(tableLogicalName, options) {
1230
1531
  );
1231
1532
  }
1232
1533
 
1233
- // src/use-environment-file-settings.ts
1234
- function useEnvironmentFileSettings(options) {
1235
- const { environmentFileSettingsCache } = usePowerPortalsPro();
1534
+ // src/use-organization-settings.ts
1535
+ function useOrganizationSettings(options) {
1536
+ const { organizationSettingsCache } = usePowerPortalsPro();
1236
1537
  const enabled = options?.enabled ?? true;
1237
1538
  return useAsyncResource(
1238
1539
  async () => {
1239
- const result = await environmentFileSettingsCache.getAsync();
1540
+ const result = await organizationSettingsCache.getAsync();
1240
1541
  return result ?? void 0;
1241
1542
  },
1242
- [environmentFileSettingsCache],
1543
+ [organizationSettingsCache],
1243
1544
  enabled
1244
1545
  );
1245
1546
  }
@@ -1623,10 +1924,8 @@ function valuesEqual(a, b) {
1623
1924
  var GUID_PATTERN = /^\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?$/i;
1624
1925
  function parseQueryDefault(metadata, rawValue) {
1625
1926
  switch (metadata.$type) {
1626
- // StringMetadata + MemoMetadata both ride on StringValue. In Blazor
1627
- // MemoMetadata derives from StringMetadata so a single `StringMetadata`
1628
- // pattern catches both; in TS the discriminators are distinct so we
1629
- // list both arms.
1927
+ // StringMetadata + MemoMetadata both ride on StringValue. The TS
1928
+ // discriminators are distinct so we list both arms.
1630
1929
  case 14:
1631
1930
  case 7:
1632
1931
  return { $type: 14, value: rawValue };
@@ -1757,7 +2056,7 @@ function RecordContextInner({
1757
2056
  }, [resolvedId, propIsEmptyId]);
1758
2057
  const isCreateMode = effectiveId === void 0;
1759
2058
  const isSkipFetchMode = !isCreateMode && loadedRecordProp !== void 0;
1760
- const { ppp } = usePowerPortalsPro();
2059
+ const { ppp, organizationSettingsCache } = usePowerPortalsPro();
1761
2060
  const mainContext = useMainContext();
1762
2061
  const validation = useValidationContext();
1763
2062
  const isTopMost = mainContext === null;
@@ -1833,6 +2132,44 @@ function RecordContextInner({
1833
2132
  (current) => current ? { ...current, properties: nextProperties } : current
1834
2133
  );
1835
2134
  }, [isCreateMode, queryParameterName, metadataQuery.data, loadedRecord]);
2135
+ react.useEffect(() => {
2136
+ if (!isCreateMode) return;
2137
+ if (!metadataQuery.data) return;
2138
+ if (!loadedRecord) return;
2139
+ if (pendingChangesRef.current.size > 0) return;
2140
+ if (loadedRecord.currency) return;
2141
+ let cancelled = false;
2142
+ (async () => {
2143
+ try {
2144
+ const settings = await organizationSettingsCache.getAsync();
2145
+ if (cancelled) return;
2146
+ const defaultCurrency = settings?.defaultCurrency;
2147
+ if (!defaultCurrency) return;
2148
+ const tableHasCurrencyLookup = metadataQuery.data.columns?.some((c) => c.columnName === "transactioncurrencyid") ?? false;
2149
+ setLoadedRecord((current) => {
2150
+ if (!current) return current;
2151
+ if (current.currency) return current;
2152
+ const nextProperties = {
2153
+ ...current.properties ?? {}
2154
+ };
2155
+ if (tableHasCurrencyLookup && !nextProperties["transactioncurrencyid"]) {
2156
+ nextProperties["transactioncurrencyid"] = {
2157
+ $type: 6,
2158
+ // ColumnType.Lookup — matches the discriminator on LookupValue
2159
+ value: defaultCurrency.id,
2160
+ tableName: "transactioncurrency",
2161
+ name: defaultCurrency.name
2162
+ };
2163
+ }
2164
+ return { ...current, currency: defaultCurrency, properties: nextProperties };
2165
+ });
2166
+ } catch {
2167
+ }
2168
+ })();
2169
+ return () => {
2170
+ cancelled = true;
2171
+ };
2172
+ }, [isCreateMode, metadataQuery.data, loadedRecord, organizationSettingsCache]);
1836
2173
  react.useEffect(() => {
1837
2174
  if (!isSkipFetchMode || !loadedRecordProp) return;
1838
2175
  setLoadedRecord(loadedRecordProp);
@@ -1905,10 +2242,10 @@ function RecordContextInner({
1905
2242
  record: {
1906
2243
  tableName: current.tableName,
1907
2244
  // Include the client-pre-generated GUID. The seed effect writes
1908
- // it into `_idForCreate` (Blazor parity); the server's in-batch
1909
- // resolver matches AssociateRequest / child-FK references
1910
- // against either `id` or `_idForCreate`, so a Create + Associate
1911
- // pair within one `ExecuteMultiple` resolves to the same record.
2245
+ // it into `_idForCreate`; the server's in-batch resolver matches
2246
+ // AssociateRequest / child-FK references against either `id` or
2247
+ // `_idForCreate`, so a Create + Associate pair within one
2248
+ // `ExecuteMultiple` resolves to the same record.
1912
2249
  // `id` is also forwarded when the consumer supplied an explicit
1913
2250
  // one via `initialRecord` (rare — pre-assigned ids on data
1914
2251
  // import).
@@ -2266,7 +2603,7 @@ exports.AuthorizedView = AuthorizedView;
2266
2603
  exports.DEFAULT_URL_LOCALE_PATTERN = DEFAULT_URL_LOCALE_PATTERN;
2267
2604
  exports.DefaultLocalizerProvider = DefaultLocalizerProvider;
2268
2605
  exports.DialogServiceProvider = DialogServiceProvider;
2269
- exports.InMemoryEnvironmentFileSettingsCache = InMemoryEnvironmentFileSettingsCache;
2606
+ exports.InMemoryOrganizationSettingsCache = InMemoryOrganizationSettingsCache;
2270
2607
  exports.InMemoryTableMetadataCache = InMemoryTableMetadataCache;
2271
2608
  exports.InMemoryViewMetadataCache = InMemoryViewMetadataCache;
2272
2609
  exports.InMemoryViewsForTableCache = InMemoryViewsForTableCache;
@@ -2275,6 +2612,7 @@ exports.LocalizerProvider = LocalizerProvider;
2275
2612
  exports.LookupRecordContext = LookupRecordContext;
2276
2613
  exports.MainContext = MainContext;
2277
2614
  exports.MainContextProvider = MainContextProvider;
2615
+ exports.MaskMode = MaskMode;
2278
2616
  exports.OverlayServiceProvider = OverlayServiceProvider;
2279
2617
  exports.PowerPortalsProContext = PowerPortalsProContext;
2280
2618
  exports.PowerPortalsProProvider = PowerPortalsProProvider;
@@ -2283,20 +2621,24 @@ exports.RecordContext = RecordContext;
2283
2621
  exports.UnsavedChangesRegistryProvider = UnsavedChangesRegistryProvider;
2284
2622
  exports.VERSION = VERSION;
2285
2623
  exports.ValidationProvider = ValidationProvider;
2624
+ exports.buildLocalePath = buildLocalePath;
2286
2625
  exports.createLocalizer = createLocalizer;
2287
2626
  exports.detectLocale = detectLocale;
2288
2627
  exports.flattenStrings = flattenStrings;
2289
2628
  exports.getAspNetCultureCookie = getAspNetCultureCookie;
2290
2629
  exports.getLocaleFromUrlPath = getLocaleFromUrlPath;
2291
2630
  exports.interpolate = interpolate;
2631
+ exports.reformat = reformat;
2292
2632
  exports.resolveLocalizationUrl = resolveLocalizationUrl;
2293
2633
  exports.runWithOverlayAsync = runWithOverlayAsync;
2294
2634
  exports.setAspNetCultureCookie = setAspNetCultureCookie;
2635
+ exports.shouldPrefixLocale = shouldPrefixLocale;
2636
+ exports.stripLocalePrefix = stripLocalePrefix;
2295
2637
  exports.useAuth = useAuth;
2296
2638
  exports.useColumnMetadata = useColumnMetadata;
2297
2639
  exports.useColumnValidationErrors = useColumnValidationErrors;
2640
+ exports.useDefaultLocale = useDefaultLocale;
2298
2641
  exports.useDialogService = useDialogService;
2299
- exports.useEnvironmentFileSettings = useEnvironmentFileSettings;
2300
2642
  exports.useFetchRecords = useFetchRecords;
2301
2643
  exports.useGridData = useGridData;
2302
2644
  exports.useIsAnyDirty = useIsAnyDirty;
@@ -2306,6 +2648,8 @@ exports.useLocalizationLoaded = useLocalizationLoaded;
2306
2648
  exports.useLocalizationPrefetcher = useLocalizationPrefetcher;
2307
2649
  exports.useLocalizer = useLocalizer;
2308
2650
  exports.useMainContext = useMainContext;
2651
+ exports.useMaskedTextField = useMaskedTextField;
2652
+ exports.useOrganizationSettings = useOrganizationSettings;
2309
2653
  exports.useOverlayForTarget = useOverlayForTarget;
2310
2654
  exports.useOverlayService = useOverlayService;
2311
2655
  exports.useOverlayServiceState = useOverlayServiceState;
@@ -2323,6 +2667,7 @@ exports.useTablePermissions = useTablePermissions;
2323
2667
  exports.useUnsavedChangesGuard = useUnsavedChangesGuard;
2324
2668
  exports.useUnsavedChangesRegistry = useUnsavedChangesRegistry;
2325
2669
  exports.useUnsavedChangesWarning = useUnsavedChangesWarning;
2670
+ exports.useUrlCultureStrategy = useUrlCultureStrategy;
2326
2671
  exports.useValidationContext = useValidationContext;
2327
2672
  exports.useViewDataSource = useViewDataSource;
2328
2673
  exports.useViewMetadata = useViewMetadata;