@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 +378 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +485 -310
- package/dist/index.d.ts +485 -310
- package/dist/index.js +370 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,274 @@
|
|
|
1
|
-
import { createContext,
|
|
1
|
+
import { createContext, useRef, useState, useEffect, useLayoutEffect, useCallback, useContext, useMemo, useSyncExternalStore, useReducer, useId } from 'react';
|
|
2
2
|
import { Transport, AuthClient, PowerPortalsProClient, LoginResult, SwitchIdentityResult } from '@powerportalspro/core';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
|
-
// src/
|
|
5
|
+
// src/masking/reformat.ts
|
|
6
|
+
var MaskMode = {
|
|
7
|
+
/** No masking — value passes through unchanged. */
|
|
8
|
+
None: "none",
|
|
9
|
+
/**
|
|
10
|
+
* Per-character allow filter. Characters that don't match
|
|
11
|
+
* {@link MaskOptions.allowedPattern} are dropped as they're typed or pasted.
|
|
12
|
+
*/
|
|
13
|
+
Regex: "regex",
|
|
14
|
+
/**
|
|
15
|
+
* Slotted template (see {@link MaskOptions.pattern}) such as `(000) 000-0000`.
|
|
16
|
+
* `0` = digit, `A` = letter, `*` = alphanumeric; every other character is a
|
|
17
|
+
* literal inserted automatically.
|
|
18
|
+
*/
|
|
19
|
+
Pattern: "pattern",
|
|
20
|
+
/**
|
|
21
|
+
* Live numeric grouping driven by {@link MaskOptions.numeric} — thousands
|
|
22
|
+
* separators, an optional decimal portion, and an optional leading sign.
|
|
23
|
+
*/
|
|
24
|
+
Numeric: "numeric"
|
|
25
|
+
};
|
|
26
|
+
var DIGIT = /[0-9]/;
|
|
27
|
+
var LETTER = /[a-zA-Z]/;
|
|
28
|
+
var ALNUM = /[a-zA-Z0-9]/;
|
|
29
|
+
function isPatternLiteral(token) {
|
|
30
|
+
return token !== "0" && token !== "A" && token !== "*";
|
|
31
|
+
}
|
|
32
|
+
function patternTokenMatches(token, ch) {
|
|
33
|
+
if (token === "0") return DIGIT.test(ch);
|
|
34
|
+
if (token === "A") return LETTER.test(ch);
|
|
35
|
+
if (token === "*") return ALNUM.test(ch);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
function countSignificant(source, caret, isSignificant) {
|
|
39
|
+
let n = 0;
|
|
40
|
+
for (let i = 0; i < caret && i < source.length; i++) {
|
|
41
|
+
if (isSignificant(source.charAt(i))) n++;
|
|
42
|
+
}
|
|
43
|
+
return n;
|
|
44
|
+
}
|
|
45
|
+
function caretAfterSignificant(display, target, isSignificant) {
|
|
46
|
+
if (target <= 0) {
|
|
47
|
+
let i = 0;
|
|
48
|
+
while (i < display.length && !isSignificant(display.charAt(i))) i++;
|
|
49
|
+
return i;
|
|
50
|
+
}
|
|
51
|
+
let seen = 0;
|
|
52
|
+
for (let i = 0; i < display.length; i++) {
|
|
53
|
+
if (isSignificant(display.charAt(i))) {
|
|
54
|
+
seen++;
|
|
55
|
+
if (seen === target) return i + 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return display.length;
|
|
59
|
+
}
|
|
60
|
+
function reformatNumeric(value, caret, o) {
|
|
61
|
+
const sigChars = (c) => DIGIT.test(c) || c === o.decimalSeparator || o.allowNegative && c === "-";
|
|
62
|
+
const sigBefore = countSignificant(value, caret, sigChars);
|
|
63
|
+
const negative = o.allowNegative && value.trimStart().startsWith("-");
|
|
64
|
+
let intPart = "";
|
|
65
|
+
let fracPart = "";
|
|
66
|
+
let sawDecimal = false;
|
|
67
|
+
for (const ch of value) {
|
|
68
|
+
if (DIGIT.test(ch)) {
|
|
69
|
+
if (sawDecimal) fracPart += ch;
|
|
70
|
+
else intPart += ch;
|
|
71
|
+
} else if (o.allowDecimal && ch === o.decimalSeparator && !sawDecimal) {
|
|
72
|
+
sawDecimal = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
intPart = intPart.replace(/^0+(?=\d)/, "");
|
|
76
|
+
if (o.maxDecimals !== null && fracPart.length > o.maxDecimals) {
|
|
77
|
+
fracPart = fracPart.slice(0, o.maxDecimals);
|
|
78
|
+
}
|
|
79
|
+
const grouped = o.groupSeparator ? intPart.replace(/\B(?=(\d{3})+(?!\d))/g, o.groupSeparator) : intPart;
|
|
80
|
+
const sign = negative ? "-" : "";
|
|
81
|
+
let display = sign + grouped;
|
|
82
|
+
let raw = sign + intPart;
|
|
83
|
+
if (sawDecimal) {
|
|
84
|
+
display += o.decimalSeparator + fracPart;
|
|
85
|
+
raw += o.decimalSeparator + fracPart;
|
|
86
|
+
}
|
|
87
|
+
const newCaret = caretAfterSignificant(display, sigBefore, sigChars);
|
|
88
|
+
return { display, raw, caret: newCaret };
|
|
89
|
+
}
|
|
90
|
+
function reformatPattern(value, caret, pattern) {
|
|
91
|
+
const sourceChars = [];
|
|
92
|
+
for (const ch of value) {
|
|
93
|
+
if (DIGIT.test(ch) || LETTER.test(ch)) sourceChars.push(ch);
|
|
94
|
+
}
|
|
95
|
+
const sigBefore = countSignificant(value, caret, (c) => DIGIT.test(c) || LETTER.test(c));
|
|
96
|
+
let display = "";
|
|
97
|
+
let raw = "";
|
|
98
|
+
let si = 0;
|
|
99
|
+
for (let pi = 0; pi < pattern.length && si <= sourceChars.length; pi++) {
|
|
100
|
+
const token = pattern[pi];
|
|
101
|
+
if (isPatternLiteral(token)) {
|
|
102
|
+
if (si < sourceChars.length) display += token;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
while (si < sourceChars.length && !patternTokenMatches(token, sourceChars[si])) si++;
|
|
106
|
+
if (si < sourceChars.length) {
|
|
107
|
+
display += sourceChars[si];
|
|
108
|
+
raw += sourceChars[si];
|
|
109
|
+
si++;
|
|
110
|
+
} else {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const newCaret = caretAfterSignificant(display, sigBefore, (c) => DIGIT.test(c) || LETTER.test(c));
|
|
115
|
+
return { display, raw, caret: newCaret };
|
|
116
|
+
}
|
|
117
|
+
function reformatRegex(value, caret, allowedPattern) {
|
|
118
|
+
let re;
|
|
119
|
+
try {
|
|
120
|
+
re = new RegExp(allowedPattern);
|
|
121
|
+
} catch {
|
|
122
|
+
return { display: value, raw: value, caret };
|
|
123
|
+
}
|
|
124
|
+
const keep = (c) => re.test(c);
|
|
125
|
+
const sigBefore = countSignificant(value, caret, keep);
|
|
126
|
+
let display = "";
|
|
127
|
+
for (const ch of value) {
|
|
128
|
+
if (keep(ch)) display += ch;
|
|
129
|
+
}
|
|
130
|
+
const newCaret = caretAfterSignificant(display, sigBefore, keep);
|
|
131
|
+
return { display, raw: display, caret: newCaret };
|
|
132
|
+
}
|
|
133
|
+
function reformat(value, caret, options) {
|
|
134
|
+
switch (options.mode) {
|
|
135
|
+
case MaskMode.Numeric:
|
|
136
|
+
return options.numeric ? reformatNumeric(value, caret, options.numeric) : { display: value, raw: value, caret };
|
|
137
|
+
case MaskMode.Pattern:
|
|
138
|
+
return options.pattern ? reformatPattern(value, caret, options.pattern) : { display: value, raw: value, caret };
|
|
139
|
+
case MaskMode.Regex:
|
|
140
|
+
return options.allowedPattern ? reformatRegex(value, caret, options.allowedPattern) : { display: value, raw: value, caret };
|
|
141
|
+
default:
|
|
142
|
+
return { display: value, raw: value, caret };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function computeDisplay(value, options) {
|
|
146
|
+
if (value === null || value === void 0 || value === "") return "";
|
|
147
|
+
return reformat(value, value.length, options).display;
|
|
148
|
+
}
|
|
149
|
+
function computeReported(value, options) {
|
|
150
|
+
if (value === null || value === void 0 || value === "") return "";
|
|
151
|
+
const r = reformat(value, value.length, options);
|
|
152
|
+
return options.valueIncludesMask ? r.display : r.raw;
|
|
153
|
+
}
|
|
154
|
+
function useMaskedTextField(opts) {
|
|
155
|
+
const {
|
|
156
|
+
value,
|
|
157
|
+
onValueChange,
|
|
158
|
+
mode = MaskMode.None,
|
|
159
|
+
pattern = null,
|
|
160
|
+
allowedPattern = null,
|
|
161
|
+
numeric = null,
|
|
162
|
+
valueIncludesMask = false
|
|
163
|
+
} = opts;
|
|
164
|
+
const optionsRef = useRef({
|
|
165
|
+
mode,
|
|
166
|
+
pattern,
|
|
167
|
+
allowedPattern,
|
|
168
|
+
numeric,
|
|
169
|
+
valueIncludesMask
|
|
170
|
+
});
|
|
171
|
+
optionsRef.current = { mode, pattern, allowedPattern, numeric, valueIncludesMask };
|
|
172
|
+
const onValueChangeRef = useRef(onValueChange);
|
|
173
|
+
onValueChangeRef.current = onValueChange;
|
|
174
|
+
const elementRef = useRef(null);
|
|
175
|
+
const focusedRef = useRef(false);
|
|
176
|
+
const hasInputSinceFocusRef = useRef(false);
|
|
177
|
+
const lastReportedRef = useRef(null);
|
|
178
|
+
const pendingCaretRef = useRef(null);
|
|
179
|
+
const [displayValue, setDisplayValue] = useState(
|
|
180
|
+
() => computeDisplay(value, optionsRef.current)
|
|
181
|
+
);
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (focusedRef.current && hasInputSinceFocusRef.current) return;
|
|
184
|
+
const next = computeDisplay(value, optionsRef.current);
|
|
185
|
+
setDisplayValue(next);
|
|
186
|
+
lastReportedRef.current = computeReported(value, optionsRef.current);
|
|
187
|
+
}, [value]);
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
if (focusedRef.current && hasInputSinceFocusRef.current) return;
|
|
190
|
+
const next = computeDisplay(value, optionsRef.current);
|
|
191
|
+
setDisplayValue(next);
|
|
192
|
+
lastReportedRef.current = computeReported(value, optionsRef.current);
|
|
193
|
+
}, [mode, pattern, allowedPattern, numeric, valueIncludesMask]);
|
|
194
|
+
useLayoutEffect(() => {
|
|
195
|
+
const target = pendingCaretRef.current;
|
|
196
|
+
if (target === null) return;
|
|
197
|
+
const input = elementRef.current;
|
|
198
|
+
if (!input) return;
|
|
199
|
+
try {
|
|
200
|
+
input.setSelectionRange(target, target);
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
pendingCaretRef.current = null;
|
|
204
|
+
});
|
|
205
|
+
const onChange = useCallback(
|
|
206
|
+
(_event, data) => {
|
|
207
|
+
hasInputSinceFocusRef.current = true;
|
|
208
|
+
const o = optionsRef.current;
|
|
209
|
+
const input = elementRef.current;
|
|
210
|
+
const caret = input?.selectionStart ?? data.value.length;
|
|
211
|
+
const result = reformat(data.value, caret, o);
|
|
212
|
+
setDisplayValue(result.display);
|
|
213
|
+
pendingCaretRef.current = result.caret;
|
|
214
|
+
const reported = o.valueIncludesMask ? result.display : result.raw;
|
|
215
|
+
const empty = reported === "";
|
|
216
|
+
const next = empty ? null : reported;
|
|
217
|
+
if (reported !== lastReportedRef.current) {
|
|
218
|
+
lastReportedRef.current = reported;
|
|
219
|
+
onValueChangeRef.current(next);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
[]
|
|
223
|
+
);
|
|
224
|
+
const inputRef = useCallback((el) => {
|
|
225
|
+
const prev = elementRef.current;
|
|
226
|
+
if (prev && prev !== el) {
|
|
227
|
+
prev.removeEventListener("focus", handleFocusRef.current);
|
|
228
|
+
prev.removeEventListener("blur", handleBlurRef.current);
|
|
229
|
+
}
|
|
230
|
+
elementRef.current = el;
|
|
231
|
+
if (el) {
|
|
232
|
+
el.addEventListener("focus", handleFocusRef.current);
|
|
233
|
+
el.addEventListener("blur", handleBlurRef.current);
|
|
234
|
+
}
|
|
235
|
+
}, []);
|
|
236
|
+
const handleFocusRef = useRef(() => {
|
|
237
|
+
});
|
|
238
|
+
handleFocusRef.current = () => {
|
|
239
|
+
focusedRef.current = true;
|
|
240
|
+
hasInputSinceFocusRef.current = false;
|
|
241
|
+
};
|
|
242
|
+
const handleBlurRef = useRef(() => {
|
|
243
|
+
});
|
|
244
|
+
handleBlurRef.current = () => {
|
|
245
|
+
focusedRef.current = false;
|
|
246
|
+
if (!hasInputSinceFocusRef.current) {
|
|
247
|
+
const next = computeDisplay(value, optionsRef.current);
|
|
248
|
+
if (next !== displayValue) {
|
|
249
|
+
setDisplayValue(next);
|
|
250
|
+
lastReportedRef.current = computeReported(value, optionsRef.current);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const forceValue = useCallback((newValue) => {
|
|
255
|
+
const o = optionsRef.current;
|
|
256
|
+
if (newValue === null || newValue === "") {
|
|
257
|
+
setDisplayValue("");
|
|
258
|
+
lastReportedRef.current = "";
|
|
259
|
+
pendingCaretRef.current = 0;
|
|
260
|
+
onValueChangeRef.current(null);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const result = reformat(newValue, newValue.length, o);
|
|
264
|
+
setDisplayValue(result.display);
|
|
265
|
+
pendingCaretRef.current = result.display.length;
|
|
266
|
+
const reported = o.valueIncludesMask ? result.display : result.raw;
|
|
267
|
+
lastReportedRef.current = reported;
|
|
268
|
+
onValueChangeRef.current(reported === "" ? null : reported);
|
|
269
|
+
}, []);
|
|
270
|
+
return { displayValue, onChange, inputRef, forceValue };
|
|
271
|
+
}
|
|
6
272
|
var AuthStatus = {
|
|
7
273
|
Loading: "loading",
|
|
8
274
|
Anonymous: "anonymous",
|
|
@@ -76,19 +342,19 @@ var InMemoryViewMetadataCache = class {
|
|
|
76
342
|
this.cache.clear();
|
|
77
343
|
}
|
|
78
344
|
};
|
|
79
|
-
var
|
|
80
|
-
static KEY = "
|
|
345
|
+
var InMemoryOrganizationSettingsCache = class _InMemoryOrganizationSettingsCache {
|
|
346
|
+
static KEY = "organization-settings";
|
|
81
347
|
cache;
|
|
82
348
|
constructor(ppp) {
|
|
83
349
|
this.cache = new InMemoryCache(
|
|
84
|
-
() => ppp.
|
|
350
|
+
() => ppp.getOrganizationSettingsAsync()
|
|
85
351
|
);
|
|
86
352
|
}
|
|
87
353
|
getAsync() {
|
|
88
|
-
return this.cache.getAsync(
|
|
354
|
+
return this.cache.getAsync(_InMemoryOrganizationSettingsCache.KEY);
|
|
89
355
|
}
|
|
90
356
|
invalidate() {
|
|
91
|
-
this.cache.invalidate(
|
|
357
|
+
this.cache.invalidate(_InMemoryOrganizationSettingsCache.KEY);
|
|
92
358
|
}
|
|
93
359
|
};
|
|
94
360
|
var InMemoryViewsForTableCache = class {
|
|
@@ -255,6 +521,31 @@ function getLocaleFromUrlPath(pattern = DEFAULT_URL_LOCALE_PATTERN) {
|
|
|
255
521
|
const match = window.location.pathname.match(pattern);
|
|
256
522
|
return match?.[1] ?? null;
|
|
257
523
|
}
|
|
524
|
+
function shouldPrefixLocale(strategy, locale, defaultLocale) {
|
|
525
|
+
switch (strategy) {
|
|
526
|
+
case "CookieOnly":
|
|
527
|
+
return false;
|
|
528
|
+
case "PathPrefixAll":
|
|
529
|
+
return true;
|
|
530
|
+
default:
|
|
531
|
+
return locale.toLowerCase() !== defaultLocale.toLowerCase();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
function stripLocalePrefix(pathname, supportedLocales) {
|
|
535
|
+
const trimmed = pathname.replace(/^\/+/, "");
|
|
536
|
+
if (trimmed.length === 0) return "/";
|
|
537
|
+
const slash = trimmed.indexOf("/");
|
|
538
|
+
const first = slash < 0 ? trimmed : trimmed.slice(0, slash);
|
|
539
|
+
const isLocale = supportedLocales.some((l) => l.toLowerCase() === first.toLowerCase());
|
|
540
|
+
if (!isLocale) return pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
541
|
+
const rest = slash < 0 ? "" : trimmed.slice(slash);
|
|
542
|
+
return rest.length === 0 ? "/" : rest;
|
|
543
|
+
}
|
|
544
|
+
function buildLocalePath(options) {
|
|
545
|
+
const { strategy, locale, defaultLocale, pathname, supportedLocales } = options;
|
|
546
|
+
const cultureless = stripLocalePrefix(pathname, supportedLocales);
|
|
547
|
+
return shouldPrefixLocale(strategy, locale, defaultLocale) ? `/${locale}${cultureless}` : cultureless;
|
|
548
|
+
}
|
|
258
549
|
function detectLocale(options) {
|
|
259
550
|
const {
|
|
260
551
|
matchUrl = true,
|
|
@@ -309,6 +600,12 @@ var LocaleContext = createContext(null);
|
|
|
309
600
|
LocaleContext.displayName = "Locale";
|
|
310
601
|
var LocalizationManifestContext = createContext(null);
|
|
311
602
|
LocalizationManifestContext.displayName = "LocalizationManifest";
|
|
603
|
+
function useUrlCultureStrategy() {
|
|
604
|
+
return useContext(LocalizationManifestContext)?.urlCultureStrategy;
|
|
605
|
+
}
|
|
606
|
+
function useDefaultLocale() {
|
|
607
|
+
return useContext(LocalizationManifestContext)?.supportedLocales?.[0];
|
|
608
|
+
}
|
|
312
609
|
function useLocale() {
|
|
313
610
|
const ctx = useContext(LocaleContext);
|
|
314
611
|
return ctx ?? { locale: "en", setLocale: noopSetLocale };
|
|
@@ -356,6 +653,9 @@ function DefaultLocalizerProvider({
|
|
|
356
653
|
}) {
|
|
357
654
|
const [cache, setCache] = useState({});
|
|
358
655
|
const [supportedLocales, setSupportedLocales] = useState(void 0);
|
|
656
|
+
const [urlCultureStrategy, setUrlCultureStrategy] = useState(
|
|
657
|
+
void 0
|
|
658
|
+
);
|
|
359
659
|
const { locale } = useLocale();
|
|
360
660
|
const { ppp } = usePowerPortalsPro();
|
|
361
661
|
const localeRef = useRef(locale);
|
|
@@ -425,6 +725,7 @@ function DefaultLocalizerProvider({
|
|
|
425
725
|
const manifest = await pppRef.current.retrieveLocalizationBundleManifestAsync();
|
|
426
726
|
if (cancelled) return;
|
|
427
727
|
setSupportedLocales(manifest.supportedLocales);
|
|
728
|
+
setUrlCultureStrategy(manifest.urlCultureStrategy);
|
|
428
729
|
const resolvedLocale = manifest.supportedLocales.includes(locale) ? locale : manifest.supportedLocales[0] ?? locale;
|
|
429
730
|
const thumbs = await pppRef.current.retrieveLocalizationThumbprintsAsync(resolvedLocale);
|
|
430
731
|
if (cancelled) return;
|
|
@@ -613,8 +914,8 @@ function DefaultLocalizerProvider({
|
|
|
613
914
|
[flushPending]
|
|
614
915
|
);
|
|
615
916
|
const manifestContextValue = useMemo(
|
|
616
|
-
() => ({ supportedLocales }),
|
|
617
|
-
[supportedLocales]
|
|
917
|
+
() => ({ supportedLocales, urlCultureStrategy }),
|
|
918
|
+
[supportedLocales, urlCultureStrategy]
|
|
618
919
|
);
|
|
619
920
|
return /* @__PURE__ */ jsx(LocalizationManifestContext.Provider, { value: manifestContextValue, children: /* @__PURE__ */ jsx(LocalizationPrefetcherContext.Provider, { value: prefetcher, children: /* @__PURE__ */ jsx(LocalizerProvider, { value: localizer, children }) }) });
|
|
620
921
|
}
|
|
@@ -683,7 +984,7 @@ function PowerPortalsProProvider({
|
|
|
683
984
|
tableMetadataCache,
|
|
684
985
|
viewMetadataCache,
|
|
685
986
|
viewsForTableCache,
|
|
686
|
-
|
|
987
|
+
organizationSettingsCache
|
|
687
988
|
}) {
|
|
688
989
|
const transportRef = useRef(null);
|
|
689
990
|
if (transportRef.current === null) {
|
|
@@ -704,9 +1005,9 @@ function PowerPortalsProProvider({
|
|
|
704
1005
|
() => viewsForTableCache ?? new InMemoryViewsForTableCache(ppp),
|
|
705
1006
|
[ppp, viewsForTableCache]
|
|
706
1007
|
);
|
|
707
|
-
const
|
|
708
|
-
() =>
|
|
709
|
-
[ppp,
|
|
1008
|
+
const resolvedOrganizationSettingsCache = useMemo(
|
|
1009
|
+
() => organizationSettingsCache ?? new InMemoryOrganizationSettingsCache(ppp),
|
|
1010
|
+
[ppp, organizationSettingsCache]
|
|
710
1011
|
);
|
|
711
1012
|
const [authState, setAuthState] = useState({ status: AuthStatus.Loading });
|
|
712
1013
|
const refreshAuth = useCallback(async () => {
|
|
@@ -753,7 +1054,7 @@ function PowerPortalsProProvider({
|
|
|
753
1054
|
tableMetadataCache: resolvedTableMetadataCache,
|
|
754
1055
|
viewMetadataCache: resolvedViewMetadataCache,
|
|
755
1056
|
viewsForTableCache: resolvedViewsForTableCache,
|
|
756
|
-
|
|
1057
|
+
organizationSettingsCache: resolvedOrganizationSettingsCache,
|
|
757
1058
|
authState,
|
|
758
1059
|
refreshAuth,
|
|
759
1060
|
login,
|
|
@@ -767,7 +1068,7 @@ function PowerPortalsProProvider({
|
|
|
767
1068
|
resolvedTableMetadataCache,
|
|
768
1069
|
resolvedViewMetadataCache,
|
|
769
1070
|
resolvedViewsForTableCache,
|
|
770
|
-
|
|
1071
|
+
resolvedOrganizationSettingsCache,
|
|
771
1072
|
authState,
|
|
772
1073
|
refreshAuth,
|
|
773
1074
|
login,
|
|
@@ -802,7 +1103,7 @@ function CacheLocaleSync() {
|
|
|
802
1103
|
tableMetadataCache,
|
|
803
1104
|
viewMetadataCache,
|
|
804
1105
|
viewsForTableCache,
|
|
805
|
-
|
|
1106
|
+
organizationSettingsCache
|
|
806
1107
|
} = usePowerPortalsPro();
|
|
807
1108
|
const isFirstRun = useRef(true);
|
|
808
1109
|
useEffect(() => {
|
|
@@ -813,13 +1114,13 @@ function CacheLocaleSync() {
|
|
|
813
1114
|
tableMetadataCache.clear();
|
|
814
1115
|
viewMetadataCache.clear();
|
|
815
1116
|
viewsForTableCache.clear();
|
|
816
|
-
|
|
1117
|
+
organizationSettingsCache.invalidate();
|
|
817
1118
|
}, [
|
|
818
1119
|
locale,
|
|
819
1120
|
tableMetadataCache,
|
|
820
1121
|
viewMetadataCache,
|
|
821
1122
|
viewsForTableCache,
|
|
822
|
-
|
|
1123
|
+
organizationSettingsCache
|
|
823
1124
|
]);
|
|
824
1125
|
return null;
|
|
825
1126
|
}
|
|
@@ -1228,16 +1529,16 @@ function useViewsForTable(tableLogicalName, options) {
|
|
|
1228
1529
|
);
|
|
1229
1530
|
}
|
|
1230
1531
|
|
|
1231
|
-
// src/use-
|
|
1232
|
-
function
|
|
1233
|
-
const {
|
|
1532
|
+
// src/use-organization-settings.ts
|
|
1533
|
+
function useOrganizationSettings(options) {
|
|
1534
|
+
const { organizationSettingsCache } = usePowerPortalsPro();
|
|
1234
1535
|
const enabled = options?.enabled ?? true;
|
|
1235
1536
|
return useAsyncResource(
|
|
1236
1537
|
async () => {
|
|
1237
|
-
const result = await
|
|
1538
|
+
const result = await organizationSettingsCache.getAsync();
|
|
1238
1539
|
return result ?? void 0;
|
|
1239
1540
|
},
|
|
1240
|
-
[
|
|
1541
|
+
[organizationSettingsCache],
|
|
1241
1542
|
enabled
|
|
1242
1543
|
);
|
|
1243
1544
|
}
|
|
@@ -1621,10 +1922,8 @@ function valuesEqual(a, b) {
|
|
|
1621
1922
|
var GUID_PATTERN = /^\{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}?$/i;
|
|
1622
1923
|
function parseQueryDefault(metadata, rawValue) {
|
|
1623
1924
|
switch (metadata.$type) {
|
|
1624
|
-
// StringMetadata + MemoMetadata both ride on StringValue.
|
|
1625
|
-
//
|
|
1626
|
-
// pattern catches both; in TS the discriminators are distinct so we
|
|
1627
|
-
// list both arms.
|
|
1925
|
+
// StringMetadata + MemoMetadata both ride on StringValue. The TS
|
|
1926
|
+
// discriminators are distinct so we list both arms.
|
|
1628
1927
|
case 14:
|
|
1629
1928
|
case 7:
|
|
1630
1929
|
return { $type: 14, value: rawValue };
|
|
@@ -1755,7 +2054,7 @@ function RecordContextInner({
|
|
|
1755
2054
|
}, [resolvedId, propIsEmptyId]);
|
|
1756
2055
|
const isCreateMode = effectiveId === void 0;
|
|
1757
2056
|
const isSkipFetchMode = !isCreateMode && loadedRecordProp !== void 0;
|
|
1758
|
-
const { ppp } = usePowerPortalsPro();
|
|
2057
|
+
const { ppp, organizationSettingsCache } = usePowerPortalsPro();
|
|
1759
2058
|
const mainContext = useMainContext();
|
|
1760
2059
|
const validation = useValidationContext();
|
|
1761
2060
|
const isTopMost = mainContext === null;
|
|
@@ -1831,6 +2130,44 @@ function RecordContextInner({
|
|
|
1831
2130
|
(current) => current ? { ...current, properties: nextProperties } : current
|
|
1832
2131
|
);
|
|
1833
2132
|
}, [isCreateMode, queryParameterName, metadataQuery.data, loadedRecord]);
|
|
2133
|
+
useEffect(() => {
|
|
2134
|
+
if (!isCreateMode) return;
|
|
2135
|
+
if (!metadataQuery.data) return;
|
|
2136
|
+
if (!loadedRecord) return;
|
|
2137
|
+
if (pendingChangesRef.current.size > 0) return;
|
|
2138
|
+
if (loadedRecord.currency) return;
|
|
2139
|
+
let cancelled = false;
|
|
2140
|
+
(async () => {
|
|
2141
|
+
try {
|
|
2142
|
+
const settings = await organizationSettingsCache.getAsync();
|
|
2143
|
+
if (cancelled) return;
|
|
2144
|
+
const defaultCurrency = settings?.defaultCurrency;
|
|
2145
|
+
if (!defaultCurrency) return;
|
|
2146
|
+
const tableHasCurrencyLookup = metadataQuery.data.columns?.some((c) => c.columnName === "transactioncurrencyid") ?? false;
|
|
2147
|
+
setLoadedRecord((current) => {
|
|
2148
|
+
if (!current) return current;
|
|
2149
|
+
if (current.currency) return current;
|
|
2150
|
+
const nextProperties = {
|
|
2151
|
+
...current.properties ?? {}
|
|
2152
|
+
};
|
|
2153
|
+
if (tableHasCurrencyLookup && !nextProperties["transactioncurrencyid"]) {
|
|
2154
|
+
nextProperties["transactioncurrencyid"] = {
|
|
2155
|
+
$type: 6,
|
|
2156
|
+
// ColumnType.Lookup — matches the discriminator on LookupValue
|
|
2157
|
+
value: defaultCurrency.id,
|
|
2158
|
+
tableName: "transactioncurrency",
|
|
2159
|
+
name: defaultCurrency.name
|
|
2160
|
+
};
|
|
2161
|
+
}
|
|
2162
|
+
return { ...current, currency: defaultCurrency, properties: nextProperties };
|
|
2163
|
+
});
|
|
2164
|
+
} catch {
|
|
2165
|
+
}
|
|
2166
|
+
})();
|
|
2167
|
+
return () => {
|
|
2168
|
+
cancelled = true;
|
|
2169
|
+
};
|
|
2170
|
+
}, [isCreateMode, metadataQuery.data, loadedRecord, organizationSettingsCache]);
|
|
1834
2171
|
useEffect(() => {
|
|
1835
2172
|
if (!isSkipFetchMode || !loadedRecordProp) return;
|
|
1836
2173
|
setLoadedRecord(loadedRecordProp);
|
|
@@ -1903,10 +2240,10 @@ function RecordContextInner({
|
|
|
1903
2240
|
record: {
|
|
1904
2241
|
tableName: current.tableName,
|
|
1905
2242
|
// Include the client-pre-generated GUID. The seed effect writes
|
|
1906
|
-
// it into `_idForCreate
|
|
1907
|
-
//
|
|
1908
|
-
//
|
|
1909
|
-
//
|
|
2243
|
+
// it into `_idForCreate`; the server's in-batch resolver matches
|
|
2244
|
+
// AssociateRequest / child-FK references against either `id` or
|
|
2245
|
+
// `_idForCreate`, so a Create + Associate pair within one
|
|
2246
|
+
// `ExecuteMultiple` resolves to the same record.
|
|
1910
2247
|
// `id` is also forwarded when the consumer supplied an explicit
|
|
1911
2248
|
// one via `initialRecord` (rare — pre-assigned ids on data
|
|
1912
2249
|
// import).
|
|
@@ -2258,6 +2595,6 @@ function useUnsavedChangesGuard() {
|
|
|
2258
2595
|
// src/index.ts
|
|
2259
2596
|
var VERSION = "0.1.0";
|
|
2260
2597
|
|
|
2261
|
-
export { ASP_NET_CULTURE_COOKIE, AuthStatus, AuthorizedView, DEFAULT_URL_LOCALE_PATTERN, DefaultLocalizerProvider, DialogServiceProvider,
|
|
2598
|
+
export { ASP_NET_CULTURE_COOKIE, AuthStatus, AuthorizedView, DEFAULT_URL_LOCALE_PATTERN, DefaultLocalizerProvider, DialogServiceProvider, InMemoryOrganizationSettingsCache, InMemoryTableMetadataCache, InMemoryViewMetadataCache, InMemoryViewsForTableCache, LocaleProvider, LocalizerProvider, LookupRecordContext, MainContext, MainContextProvider, MaskMode, OverlayServiceProvider, PowerPortalsProContext, PowerPortalsProProvider, QueryStatus, RecordContext, UnsavedChangesRegistryProvider, VERSION, ValidationProvider, buildLocalePath, createLocalizer, detectLocale, flattenStrings, getAspNetCultureCookie, getLocaleFromUrlPath, interpolate, reformat, resolveLocalizationUrl, runWithOverlayAsync, setAspNetCultureCookie, shouldPrefixLocale, stripLocalePrefix, useAuth, useColumnMetadata, useColumnValidationErrors, useDefaultLocale, useDialogService, useFetchRecords, useGridData, useIsAnyDirty, useLocale, useLocalization, useLocalizationLoaded, useLocalizationPrefetcher, useLocalizer, useMainContext, useMaskedTextField, useOrganizationSettings, useOverlayForTarget, useOverlayService, useOverlayServiceState, usePowerPortalsPro, usePrefixedT, useQueryParam, useRecord, useRecordContext, useRecordContextOptional, useRunWithOverlay, useSupportedLocales, useT, useTableMetadata, useTablePermissions, useUnsavedChangesGuard, useUnsavedChangesRegistry, useUnsavedChangesWarning, useUrlCultureStrategy, useValidationContext, useViewDataSource, useViewMetadata, useViewsForTable, useWarnAboutUnsavedChanges, warnAboutUnsavedChangesAsync };
|
|
2262
2599
|
//# sourceMappingURL=index.js.map
|
|
2263
2600
|
//# sourceMappingURL=index.js.map
|