@genesislcap/foundation-ui 14.482.0 → 14.482.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/dist/custom-elements.json +1162 -964
- package/dist/dts/number-field/number-field.d.ts +1 -0
- package/dist/dts/number-field/number-field.d.ts.map +1 -1
- package/dist/dts/number-field/utils.d.ts +13 -1
- package/dist/dts/number-field/utils.d.ts.map +1 -1
- package/dist/dts/react.d.ts +17 -17
- package/dist/esm/number-field/number-field.js +46 -18
- package/dist/esm/number-field/utils.js +152 -3
- package/dist/react.cjs +11 -11
- package/dist/react.mjs +9 -9
- package/package.json +19 -19
|
@@ -28,6 +28,7 @@ export declare class NumberField extends NumberField_base {
|
|
|
28
28
|
stepUp(): void;
|
|
29
29
|
stepDown(): void;
|
|
30
30
|
hasSeparatorWithoutDecimals(): RegExp;
|
|
31
|
+
private restoreControlToCommittedValue;
|
|
31
32
|
handleTextInput(): void;
|
|
32
33
|
valueChanged(previous: any, next: any): void;
|
|
33
34
|
handleBlur(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field.d.ts","sourceRoot":"","sources":["../../../src/number-field/number-field.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"number-field.d.ts","sourceRoot":"","sources":["../../../src/number-field/number-field.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;;;;;;;;;;AAoBrE;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAA2B;IACpD,YAAY,EAAE,MAAM,CAAS;IACnC,OAAO,CAAC,mBAAmB;IAKA,QAAQ,EAAE,OAAO,CAAS;IAQrD,KAAK,EAAE,MAAM,CAAM;IACQ,cAAc,EAAE,OAAO,CAAS;IACrD,MAAM,EAAE,MAAM,CAAW;IACJ,iBAAiB,EAAE,OAAO,CAAS;IACxD,qBAAqB,EAAE,MAAM,CAAuB;IAE1D,OAAO,EAAE,IAAI,CAAC,mBAAmB,CAG/B;IAEF,MAAM,IAAI,IAAI;IAuCd,QAAQ,IAAI,IAAI;IA0ChB,2BAA2B;IAK3B,OAAO,CAAC,8BAA8B;IAetC,eAAe,IAAI,IAAI;IA+DvB,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAqC5C,UAAU,IAAI,IAAI;CA4BnB;AAED,eAAO,MAAM,kCAAkC,EAAE,cAGhD,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;CAWpC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,oTAMhC,CAAC"}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
export declare const getSeparatorsFromParser: (value: string, locale: string) => {
|
|
2
2
|
decimalSeparator: string;
|
|
3
3
|
};
|
|
4
|
+
/**
|
|
5
|
+
* Strips locale grouping and normalizes the decimal separator to `.` without using `Number`
|
|
6
|
+
* (so integers beyond `Number.MAX_SAFE_INTEGER` keep every digit).
|
|
7
|
+
*/
|
|
8
|
+
export declare const normalizeLocaleNumberString: (inputVal: string, locale: string) => string;
|
|
9
|
+
/** Counts locale decimal separator characters in the raw control text (ignores grouping). */
|
|
10
|
+
export declare const countLocaleDecimalSeparators: (input: string, locale: string) => number;
|
|
11
|
+
export declare const hasMultipleDecimalSeparators: (input: string, locale: string) => boolean;
|
|
12
|
+
/** True when the committed value is a whole number already using the full significant-digit budget. */
|
|
13
|
+
export declare const isIntegerAtMaximumInputPrecision: (value: string, locale: string, precision: number) => boolean;
|
|
14
|
+
/** User typed a decimal separator while the integer part is already at max precision. */
|
|
15
|
+
export declare const rejectsDecimalAtMaximumIntegerPrecision: (committedValue: string, controlText: string, locale: string, precision: number) => boolean;
|
|
4
16
|
export declare const formatControlValue: (value: string, locale: string) => string;
|
|
5
17
|
export declare const sanitiseInputVal: (inputVal: string, locale: string) => string;
|
|
6
18
|
export declare const toIntlNumberFormat: (value: string, locale: string, options: Intl.NumberFormatOptions) => string;
|
|
@@ -22,7 +34,7 @@ export declare const preserveTrailingZerosAfterParse: (value: string, parsedValu
|
|
|
22
34
|
* @returns The validated and formatted value
|
|
23
35
|
*/
|
|
24
36
|
export declare const validateValue: (value: string | number, locale: string, withFormatting?: boolean, precision?: number) => string;
|
|
25
|
-
export declare const validateInput: (value: string, locale: string, precision?: number) => string;
|
|
37
|
+
export declare const validateInput: (value: string, locale: string, precision?: number, committedValue?: string) => string;
|
|
26
38
|
export declare const validateMinMax: (value: string, locale: string, withFormatting: boolean, min: number, max: number, precision?: number) => string;
|
|
27
39
|
/**
|
|
28
40
|
* Performs high precision addition using Pure JavaScript (NO BigInt needed!)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/number-field/utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,uBAAuB,GAClC,OAAO,MAAM,EACb,QAAQ,MAAM,KACb;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAI5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,MAWlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/number-field/utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,uBAAuB,GAClC,OAAO,MAAM,EACb,QAAQ,MAAM,KACb;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAI5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,KAAG,MAY9E,CAAC;AAEF,6FAA6F;AAC7F,eAAO,MAAM,4BAA4B,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,MAU5E,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,OAC5B,CAAC;AAElD,uGAAuG;AACvG,eAAO,MAAM,gCAAgC,GAC3C,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,OAMF,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,uCAAuC,GAClD,gBAAgB,MAAM,EACtB,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,OAEoD,CAAC;AAqFxD,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,MAWlE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,KAAG,MAOnE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,SAAS,IAAI,CAAC,mBAAmB,KAChC,MAQF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,GACtC,OAAO,MAAM,EACb,SAAS,IAAI,CAAC,mBAAmB,KAChC,MAyCF,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,OAAO,MAAM,EACb,aAAa,MAAM,EACnB,QAAQ,MAAM,KACb,MA+BF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,GAAG,MAAM,EACtB,QAAQ,MAAM,EACd,wBAAqB,EACrB,YAAY,MAAM,KACjB,MAkEF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,YAAY,MAAM,EAClB,iBAAiB,MAAM,KACtB,MAaF,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,uBAAqB,EACrB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,YAAY,MAAM,KACjB,MAyBF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAyBvD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAyB5D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,MAAM,MAAM,KAAG,MAgDnF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,MAAM,MAAM,KAAG,MA+CnF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GAAI,OAAO,MAAM,GAAG,MAAM,KAAG,MA8BnE,CAAC"}
|
package/dist/dts/react.d.ts
CHANGED
|
@@ -129,32 +129,23 @@ interface HTMLWCProps extends React.AriaAttributes {
|
|
|
129
129
|
onInput?(e: Event): void;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export declare const
|
|
133
|
-
React.PropsWithChildren<
|
|
134
|
-
Omit<PublicOf<AccordionItemWC>, 'children' | 'style'> &
|
|
135
|
-
HTMLWCProps & {
|
|
136
|
-
}
|
|
137
|
-
> & React.RefAttributes<AccordionItemWC>
|
|
138
|
-
>;
|
|
139
|
-
export type AccordionItemRef = AccordionItemWC;
|
|
140
|
-
|
|
141
|
-
export declare const Accordion: React.ForwardRefExoticComponent<
|
|
132
|
+
export declare const ActionsMenu: React.ForwardRefExoticComponent<
|
|
142
133
|
React.PropsWithChildren<
|
|
143
|
-
Omit<PublicOf<
|
|
134
|
+
Omit<PublicOf<ActionsMenuWC>, 'children' | 'style'> &
|
|
144
135
|
HTMLWCProps & {
|
|
145
136
|
}
|
|
146
|
-
> & React.RefAttributes<
|
|
137
|
+
> & React.RefAttributes<ActionsMenuWC>
|
|
147
138
|
>;
|
|
148
|
-
export type
|
|
139
|
+
export type ActionsMenuRef = ActionsMenuWC;
|
|
149
140
|
|
|
150
|
-
export declare const
|
|
141
|
+
export declare const AccordionItem: React.ForwardRefExoticComponent<
|
|
151
142
|
React.PropsWithChildren<
|
|
152
|
-
Omit<PublicOf<
|
|
143
|
+
Omit<PublicOf<AccordionItemWC>, 'children' | 'style'> &
|
|
153
144
|
HTMLWCProps & {
|
|
154
145
|
}
|
|
155
|
-
> & React.RefAttributes<
|
|
146
|
+
> & React.RefAttributes<AccordionItemWC>
|
|
156
147
|
>;
|
|
157
|
-
export type
|
|
148
|
+
export type AccordionItemRef = AccordionItemWC;
|
|
158
149
|
|
|
159
150
|
export declare const AiCriteriaSearch: React.ForwardRefExoticComponent<
|
|
160
151
|
React.PropsWithChildren<
|
|
@@ -176,6 +167,15 @@ export declare const AiIndicator: React.ForwardRefExoticComponent<
|
|
|
176
167
|
>;
|
|
177
168
|
export type AiIndicatorRef = AiIndicatorWC;
|
|
178
169
|
|
|
170
|
+
export declare const Accordion: React.ForwardRefExoticComponent<
|
|
171
|
+
React.PropsWithChildren<
|
|
172
|
+
Omit<PublicOf<AccordionWC>, 'children' | 'style'> &
|
|
173
|
+
HTMLWCProps & {
|
|
174
|
+
}
|
|
175
|
+
> & React.RefAttributes<AccordionWC>
|
|
176
|
+
>;
|
|
177
|
+
export type AccordionRef = AccordionWC;
|
|
178
|
+
|
|
179
179
|
export declare const Anchor: React.ForwardRefExoticComponent<
|
|
180
180
|
React.PropsWithChildren<
|
|
181
181
|
Omit<PublicOf<AnchorWC>, 'children' | 'style'> &
|
|
@@ -5,7 +5,7 @@ import { DOM, attr } from '@microsoft/fast-element';
|
|
|
5
5
|
import { AffixMixin } from '../_common';
|
|
6
6
|
import { foundationNumberFieldStyles as styles } from './number-field.styles';
|
|
7
7
|
import { foundationNumberFieldTemplate as template } from './number-field.template';
|
|
8
|
-
import { applyDecimalPrecisionLimits, calculateAutoStepPrecision, decrementWithPrecision, formatControlValue, incrementWithPrecision, toIntlNumberFormat, validateInput, validateMinMax, } from './utils';
|
|
8
|
+
import { applyDecimalPrecisionLimits, calculateAutoStepPrecision, decrementWithPrecision, formatControlValue, incrementWithPrecision, toIntlNumberFormat, validateInput, validateMinMax, hasMultipleDecimalSeparators, rejectsDecimalAtMaximumIntegerPrecision, } from './utils';
|
|
9
9
|
const MAX_DECIMAL_PLACES = 3;
|
|
10
10
|
const MAX_INPUT_PRECISION = 12;
|
|
11
11
|
/**
|
|
@@ -94,19 +94,50 @@ export class NumberField extends AffixMixin(FASTNumberField) {
|
|
|
94
94
|
const regexString = `[.]$`;
|
|
95
95
|
return new RegExp(regexString);
|
|
96
96
|
}
|
|
97
|
+
restoreControlToCommittedValue() {
|
|
98
|
+
if (!this.control)
|
|
99
|
+
return;
|
|
100
|
+
const previousValue = this.value;
|
|
101
|
+
if (!previousValue) {
|
|
102
|
+
this.control.value = '';
|
|
103
|
+
this['isUserInput'] = false;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.control.value =
|
|
107
|
+
this.withFormatting && previousValue
|
|
108
|
+
? toIntlNumberFormat(previousValue, this.locale, this.options)
|
|
109
|
+
: formatControlValue(String(previousValue), this.locale);
|
|
110
|
+
this['isUserInput'] = false;
|
|
111
|
+
}
|
|
97
112
|
handleTextInput() {
|
|
98
113
|
if (!this.control)
|
|
99
114
|
return;
|
|
100
115
|
if (this.control.value === '-' || this.control.value === '-0')
|
|
101
116
|
return;
|
|
117
|
+
if (hasMultipleDecimalSeparators(this.control.value, this.locale)) {
|
|
118
|
+
this.restoreControlToCommittedValue();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (rejectsDecimalAtMaximumIntegerPrecision(this.value, this.control.value, this.locale, this.maximumInputPrecision)) {
|
|
122
|
+
this.restoreControlToCommittedValue();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
102
125
|
this['isUserInput'] = true;
|
|
103
126
|
if (this.withFormatting && !new NumberParser(this.locale).hasSeparator(this.control.value)) {
|
|
104
127
|
DOM.queueUpdate(() => {
|
|
105
|
-
const
|
|
106
|
-
this.value
|
|
128
|
+
const previousValue = this.value;
|
|
129
|
+
const validValue = validateInput(this.control.value, this.locale, this.maximumInputPrecision, this.value);
|
|
130
|
+
if (!validValue && previousValue && this.control.value !== '') {
|
|
131
|
+
this.restoreControlToCommittedValue();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
107
134
|
if (this.control) {
|
|
108
|
-
this.
|
|
135
|
+
const displayValue = this.withFormatting && validValue !== ''
|
|
136
|
+
? toIntlNumberFormat(validValue, this.locale, this.options)
|
|
137
|
+
: formatControlValue(validValue, this.locale);
|
|
138
|
+
this.control.value = applyDecimalPrecisionLimits(displayValue, this.options);
|
|
109
139
|
}
|
|
140
|
+
this.value = applyDecimalPrecisionLimits(validValue, this.options);
|
|
110
141
|
this.$emit('input');
|
|
111
142
|
});
|
|
112
143
|
}
|
|
@@ -131,6 +162,9 @@ export class NumberField extends AffixMixin(FASTNumberField) {
|
|
|
131
162
|
if (!this['isUserInput']) {
|
|
132
163
|
this.value = validateMinMax(this.value, this.locale, false, this.min, this.max, this.maximumInputPrecision);
|
|
133
164
|
DOM.queueUpdate(() => {
|
|
165
|
+
if (this['isUserInput']) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
134
168
|
if (this.control) {
|
|
135
169
|
this.control.value =
|
|
136
170
|
this.withFormatting && this.value
|
|
@@ -140,19 +174,8 @@ export class NumberField extends AffixMixin(FASTNumberField) {
|
|
|
140
174
|
});
|
|
141
175
|
return;
|
|
142
176
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (!this.control)
|
|
146
|
-
return;
|
|
147
|
-
if (this.control.value === '' || this.value === '') {
|
|
148
|
-
this.control.value = value;
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
this.control.value = formatControlValue(String(value), this.locale);
|
|
152
|
-
this.value = this.withFormatting
|
|
153
|
-
? validateInput(this.control.value, this.locale, this.maximumInputPrecision)
|
|
154
|
-
: this.control.value;
|
|
155
|
-
});
|
|
177
|
+
// While the user is typing, handleTextInput (and handleBlur on exit) own value + display.
|
|
178
|
+
return;
|
|
156
179
|
}
|
|
157
180
|
}
|
|
158
181
|
handleBlur() {
|
|
@@ -181,7 +204,12 @@ __decorate([
|
|
|
181
204
|
attr({ mode: 'boolean' })
|
|
182
205
|
], NumberField.prototype, "hideStep", void 0);
|
|
183
206
|
__decorate([
|
|
184
|
-
attr
|
|
207
|
+
attr({
|
|
208
|
+
converter: {
|
|
209
|
+
fromView: (value) => (value === null || value === undefined ? '' : String(value)),
|
|
210
|
+
toView: (value) => value,
|
|
211
|
+
},
|
|
212
|
+
})
|
|
185
213
|
], NumberField.prototype, "value", void 0);
|
|
186
214
|
__decorate([
|
|
187
215
|
attr({ mode: 'boolean' })
|
|
@@ -9,6 +9,119 @@ export const getSeparatorsFromParser = (value, locale) => {
|
|
|
9
9
|
const decimalSeparator = ((_a = parts.find((d) => d.type === 'decimal')) === null || _a === void 0 ? void 0 : _a.value) || '.';
|
|
10
10
|
return { decimalSeparator };
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Strips locale grouping and normalizes the decimal separator to `.` without using `Number`
|
|
14
|
+
* (so integers beyond `Number.MAX_SAFE_INTEGER` keep every digit).
|
|
15
|
+
*/
|
|
16
|
+
export const normalizeLocaleNumberString = (inputVal, locale) => {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(FORMAT_TEST_NUMBER);
|
|
19
|
+
const groupChar = (_a = parts.find((d) => d.type === 'group')) === null || _a === void 0 ? void 0 : _a.value;
|
|
20
|
+
const decimalChar = (_c = (_b = parts.find((d) => d.type === 'decimal')) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : '.';
|
|
21
|
+
let normalized = inputVal.trim();
|
|
22
|
+
if (groupChar) {
|
|
23
|
+
normalized = normalized.split(groupChar).join('');
|
|
24
|
+
}
|
|
25
|
+
if (decimalChar !== '.') {
|
|
26
|
+
normalized = normalized.replace(decimalChar, '.');
|
|
27
|
+
}
|
|
28
|
+
return normalized;
|
|
29
|
+
};
|
|
30
|
+
/** Counts locale decimal separator characters in the raw control text (ignores grouping). */
|
|
31
|
+
export const countLocaleDecimalSeparators = (input, locale) => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(FORMAT_TEST_NUMBER);
|
|
34
|
+
const decimalChar = (_b = (_a = parts.find((d) => d.type === 'decimal')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '.';
|
|
35
|
+
let count = 0;
|
|
36
|
+
for (const ch of input) {
|
|
37
|
+
if (ch === decimalChar) {
|
|
38
|
+
count += 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return count;
|
|
42
|
+
};
|
|
43
|
+
export const hasMultipleDecimalSeparators = (input, locale) => countLocaleDecimalSeparators(input, locale) > 1;
|
|
44
|
+
/** True when the committed value is a whole number already using the full significant-digit budget. */
|
|
45
|
+
export const isIntegerAtMaximumInputPrecision = (value, locale, precision) => {
|
|
46
|
+
const normalized = normalizeLocaleNumberString(String(value !== null && value !== void 0 ? value : ''), locale);
|
|
47
|
+
if (!normalized || !/^-?\d+$/.test(normalized)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return normalized.replace(/^-/, '').length >= precision;
|
|
51
|
+
};
|
|
52
|
+
/** User typed a decimal separator while the integer part is already at max precision. */
|
|
53
|
+
export const rejectsDecimalAtMaximumIntegerPrecision = (committedValue, controlText, locale, precision) => isIntegerAtMaximumInputPrecision(committedValue, locale, precision) &&
|
|
54
|
+
countLocaleDecimalSeparators(controlText, locale) > 0;
|
|
55
|
+
const SAFE_INTEGER_DIGIT_COUNT = 15;
|
|
56
|
+
/** Sample integer used only to read locale grouping separator from Intl. */
|
|
57
|
+
const LOCALE_GROUPING_PROBE = 1234567;
|
|
58
|
+
const DIGITS_PER_GROUP = 3;
|
|
59
|
+
const formatLargeIntegerString = (value, locale) => {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
const negative = value.startsWith('-');
|
|
62
|
+
const digits = negative ? value.slice(1) : value;
|
|
63
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(LOCALE_GROUPING_PROBE);
|
|
64
|
+
const group = (_b = (_a = parts.find((p) => p.type === 'group')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ',';
|
|
65
|
+
const groups = [];
|
|
66
|
+
let rest = digits;
|
|
67
|
+
while (rest.length > DIGITS_PER_GROUP) {
|
|
68
|
+
groups.unshift(rest.slice(-DIGITS_PER_GROUP));
|
|
69
|
+
rest = rest.slice(0, -DIGITS_PER_GROUP);
|
|
70
|
+
}
|
|
71
|
+
groups.unshift(rest);
|
|
72
|
+
const formatted = groups.join(group);
|
|
73
|
+
return negative ? `-${formatted}` : formatted;
|
|
74
|
+
};
|
|
75
|
+
const hasLongIntegerPart = (value) => {
|
|
76
|
+
const unsigned = value.replace(/^-/, '');
|
|
77
|
+
const dotIndex = unsigned.indexOf('.');
|
|
78
|
+
const intPart = dotIndex === -1 ? unsigned : unsigned.slice(0, dotIndex);
|
|
79
|
+
return intPart.length > SAFE_INTEGER_DIGIT_COUNT;
|
|
80
|
+
};
|
|
81
|
+
const formatLongNumericStringForDisplay = (value, locale, options) => {
|
|
82
|
+
const negative = value.startsWith('-');
|
|
83
|
+
const unsigned = negative ? value.slice(1) : value;
|
|
84
|
+
const dotIndex = unsigned.indexOf('.');
|
|
85
|
+
const intDigits = dotIndex === -1 ? unsigned : unsigned.slice(0, dotIndex);
|
|
86
|
+
let decDigits = dotIndex === -1 ? '' : unsigned.slice(dotIndex + 1);
|
|
87
|
+
const minFractionDigits = options.minimumFractionDigits;
|
|
88
|
+
const maxFractionDigits = options.maximumFractionDigits;
|
|
89
|
+
if (maxFractionDigits !== undefined && decDigits.length > maxFractionDigits) {
|
|
90
|
+
decDigits = decDigits.slice(0, maxFractionDigits);
|
|
91
|
+
}
|
|
92
|
+
if (minFractionDigits !== undefined && decDigits.length < minFractionDigits) {
|
|
93
|
+
decDigits = decDigits.padEnd(minFractionDigits, '0');
|
|
94
|
+
}
|
|
95
|
+
const intValue = negative ? `-${intDigits}` : intDigits;
|
|
96
|
+
const formattedInt = formatLargeIntegerString(intValue, locale);
|
|
97
|
+
const { decimalSeparator } = getSeparatorsFromParser(value, locale);
|
|
98
|
+
if (dotIndex === -1) {
|
|
99
|
+
if (minFractionDigits !== undefined && minFractionDigits > 0) {
|
|
100
|
+
return `${formattedInt}${decimalSeparator}${'0'.repeat(minFractionDigits)}`;
|
|
101
|
+
}
|
|
102
|
+
return formattedInt;
|
|
103
|
+
}
|
|
104
|
+
if (maxFractionDigits === 0) {
|
|
105
|
+
return formattedInt;
|
|
106
|
+
}
|
|
107
|
+
return `${formattedInt}${decimalSeparator}${decDigits}`;
|
|
108
|
+
};
|
|
109
|
+
const clampIntegerStringToMinMax = (value, min, max) => {
|
|
110
|
+
let clamped = BigInt(value);
|
|
111
|
+
if (max !== undefined && !Number.isNaN(max)) {
|
|
112
|
+
const maxBig = BigInt(Math.trunc(max));
|
|
113
|
+
if (clamped > maxBig) {
|
|
114
|
+
clamped = maxBig;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (min !== undefined && !Number.isNaN(min)) {
|
|
118
|
+
const minBig = BigInt(Math.trunc(min));
|
|
119
|
+
if (clamped < minBig) {
|
|
120
|
+
clamped = minBig;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return clamped.toString();
|
|
124
|
+
};
|
|
12
125
|
export const formatControlValue = (value, locale) => {
|
|
13
126
|
// Get locale-specific decimal separator
|
|
14
127
|
const { decimalSeparator } = getSeparatorsFromParser(value, locale);
|
|
@@ -20,9 +133,20 @@ export const formatControlValue = (value, locale) => {
|
|
|
20
133
|
return value.replace(/\./g, decimalSeparator);
|
|
21
134
|
};
|
|
22
135
|
export const sanitiseInputVal = (inputVal, locale) => {
|
|
136
|
+
const normalized = normalizeLocaleNumberString(String(inputVal), locale);
|
|
137
|
+
const digitCount = normalized.replace(/^-/, '').replace('.', '').length;
|
|
138
|
+
if (/^-?\d+(\.\d+)?$/.test(normalized) && digitCount > SAFE_INTEGER_DIGIT_COUNT) {
|
|
139
|
+
return normalized;
|
|
140
|
+
}
|
|
23
141
|
return String(new NumberParser(locale).parse(String(inputVal)));
|
|
24
142
|
};
|
|
25
143
|
export const toIntlNumberFormat = (value, locale, options) => {
|
|
144
|
+
if (value === '') {
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
147
|
+
if (hasLongIntegerPart(value) && /^-?\d+(\.\d*)?$/.test(value)) {
|
|
148
|
+
return formatLongNumericStringForDisplay(value, locale, options);
|
|
149
|
+
}
|
|
26
150
|
return Intl.NumberFormat(locale, options).format(Number(value));
|
|
27
151
|
};
|
|
28
152
|
/**
|
|
@@ -110,6 +234,9 @@ export const validateValue = (value, locale, withFormatting = true, precision) =
|
|
|
110
234
|
}
|
|
111
235
|
const stringValue = typeof value === 'number' ? value.toString() : value;
|
|
112
236
|
const inputPrecision = precision !== null && precision !== void 0 ? precision : formattedInputPrecision;
|
|
237
|
+
if (hasMultipleDecimalSeparators(stringValue, locale)) {
|
|
238
|
+
return '';
|
|
239
|
+
}
|
|
113
240
|
let cleanValue;
|
|
114
241
|
if (withFormatting) {
|
|
115
242
|
cleanValue = sanitiseInputVal(stringValue, locale);
|
|
@@ -159,12 +286,34 @@ export const validateValue = (value, locale, withFormatting = true, precision) =
|
|
|
159
286
|
}
|
|
160
287
|
return cleanValue;
|
|
161
288
|
};
|
|
162
|
-
export const validateInput = (value, locale, precision) => {
|
|
163
|
-
|
|
289
|
+
export const validateInput = (value, locale, precision, committedValue) => {
|
|
290
|
+
if (precision !== undefined && countLocaleDecimalSeparators(value, locale) > 0) {
|
|
291
|
+
const normalized = normalizeLocaleNumberString(value, locale);
|
|
292
|
+
const dotIdx = normalized.indexOf('.');
|
|
293
|
+
const integerPart = dotIdx === -1 ? normalized : normalized.slice(0, dotIdx);
|
|
294
|
+
const committed = committedValue !== undefined ? committedValue : integerPart;
|
|
295
|
+
if (rejectsDecimalAtMaximumIntegerPrecision(committed, value, locale, precision)) {
|
|
296
|
+
return '';
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const parsedValue = validateValue(value, locale, true, precision);
|
|
164
300
|
return preserveTrailingZerosAfterParse(value, parsedValue, locale);
|
|
165
301
|
};
|
|
166
302
|
export const validateMinMax = (value, locale, withFormatting = true, min, max, precision) => {
|
|
167
|
-
|
|
303
|
+
const validatedString = validateValue(value, locale, withFormatting, precision);
|
|
304
|
+
if (!validatedString) {
|
|
305
|
+
return '';
|
|
306
|
+
}
|
|
307
|
+
const digitCount = validatedString.replace(/^-/, '').replace('.', '').length;
|
|
308
|
+
if (/^-?\d+$/.test(validatedString) && digitCount > SAFE_INTEGER_DIGIT_COUNT) {
|
|
309
|
+
try {
|
|
310
|
+
return clampIntegerStringToMinMax(validatedString, min, max);
|
|
311
|
+
}
|
|
312
|
+
catch (_a) {
|
|
313
|
+
return validatedString;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
let validValue = parseFloat(validatedString);
|
|
168
317
|
if (isNaN(validValue)) {
|
|
169
318
|
validValue = '';
|
|
170
319
|
}
|
package/dist/react.cjs
CHANGED
|
@@ -111,19 +111,14 @@ function _mergeRefs(...refs) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
const
|
|
115
|
-
const { children, ...rest } = props;
|
|
116
|
-
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
114
|
+
const ActionsMenu = React.forwardRef(function ActionsMenu(props, ref) {
|
|
120
115
|
const { children, ...rest } = props;
|
|
121
|
-
return React.createElement(customElements.getName(
|
|
116
|
+
return React.createElement(customElements.getName(ActionsMenuWC) ?? '%%prefix%%-actions-menu', { ...rest, ref }, children);
|
|
122
117
|
});
|
|
123
118
|
|
|
124
|
-
const
|
|
119
|
+
const AccordionItem = React.forwardRef(function AccordionItem(props, ref) {
|
|
125
120
|
const { children, ...rest } = props;
|
|
126
|
-
return React.createElement(customElements.getName(
|
|
121
|
+
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
127
122
|
});
|
|
128
123
|
|
|
129
124
|
const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props, ref) {
|
|
@@ -153,6 +148,11 @@ const AiIndicator = React.forwardRef(function AiIndicator(props, ref) {
|
|
|
153
148
|
return React.createElement(customElements.getName(AiIndicatorWC) ?? '%%prefix%%-ai-indicator', { ...rest, ref }, children);
|
|
154
149
|
});
|
|
155
150
|
|
|
151
|
+
const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
152
|
+
const { children, ...rest } = props;
|
|
153
|
+
return React.createElement(customElements.getName(AccordionWC) ?? '%%prefix%%-accordion', { ...rest, ref }, children);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
156
|
const Anchor = React.forwardRef(function Anchor(props, ref) {
|
|
157
157
|
const { children, ...rest } = props;
|
|
158
158
|
return React.createElement(customElements.getName(AnchorWC) ?? '%%prefix%%-anchor', { ...rest, ref }, children);
|
|
@@ -1078,11 +1078,11 @@ const WeeklyRecurrence = React.forwardRef(function WeeklyRecurrence(props, ref)
|
|
|
1078
1078
|
});
|
|
1079
1079
|
|
|
1080
1080
|
module.exports = {
|
|
1081
|
-
AccordionItem,
|
|
1082
|
-
Accordion,
|
|
1083
1081
|
ActionsMenu,
|
|
1082
|
+
AccordionItem,
|
|
1084
1083
|
AiCriteriaSearch,
|
|
1085
1084
|
AiIndicator,
|
|
1085
|
+
Accordion,
|
|
1086
1086
|
Anchor,
|
|
1087
1087
|
AnchoredRegion,
|
|
1088
1088
|
Avatar,
|
package/dist/react.mjs
CHANGED
|
@@ -109,19 +109,14 @@ function _mergeRefs(...refs) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
export const
|
|
113
|
-
const { children, ...rest } = props;
|
|
114
|
-
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
export const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
112
|
+
export const ActionsMenu = React.forwardRef(function ActionsMenu(props, ref) {
|
|
118
113
|
const { children, ...rest } = props;
|
|
119
|
-
return React.createElement(customElements.getName(
|
|
114
|
+
return React.createElement(customElements.getName(ActionsMenuWC) ?? '%%prefix%%-actions-menu', { ...rest, ref }, children);
|
|
120
115
|
});
|
|
121
116
|
|
|
122
|
-
export const
|
|
117
|
+
export const AccordionItem = React.forwardRef(function AccordionItem(props, ref) {
|
|
123
118
|
const { children, ...rest } = props;
|
|
124
|
-
return React.createElement(customElements.getName(
|
|
119
|
+
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
125
120
|
});
|
|
126
121
|
|
|
127
122
|
export const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props, ref) {
|
|
@@ -151,6 +146,11 @@ export const AiIndicator = React.forwardRef(function AiIndicator(props, ref) {
|
|
|
151
146
|
return React.createElement(customElements.getName(AiIndicatorWC) ?? '%%prefix%%-ai-indicator', { ...rest, ref }, children);
|
|
152
147
|
});
|
|
153
148
|
|
|
149
|
+
export const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
150
|
+
const { children, ...rest } = props;
|
|
151
|
+
return React.createElement(customElements.getName(AccordionWC) ?? '%%prefix%%-accordion', { ...rest, ref }, children);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
154
|
export const Anchor = React.forwardRef(function Anchor(props, ref) {
|
|
155
155
|
const { children, ...rest } = props;
|
|
156
156
|
return React.createElement(customElements.getName(AnchorWC) ?? '%%prefix%%-anchor', { ...rest, ref }, children);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/foundation-ui",
|
|
3
3
|
"description": "Genesis Foundation UI",
|
|
4
|
-
"version": "14.482.
|
|
4
|
+
"version": "14.482.1",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "SEE LICENSE IN license.txt",
|
|
7
7
|
"main": "dist/esm/index.js",
|
|
@@ -85,13 +85,13 @@
|
|
|
85
85
|
}
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@genesislcap/foundation-testing": "14.482.
|
|
89
|
-
"@genesislcap/genx": "14.482.
|
|
90
|
-
"@genesislcap/rollup-builder": "14.482.
|
|
91
|
-
"@genesislcap/ts-builder": "14.482.
|
|
92
|
-
"@genesislcap/uvu-playwright-builder": "14.482.
|
|
93
|
-
"@genesislcap/vite-builder": "14.482.
|
|
94
|
-
"@genesislcap/webpack-builder": "14.482.
|
|
88
|
+
"@genesislcap/foundation-testing": "14.482.1",
|
|
89
|
+
"@genesislcap/genx": "14.482.1",
|
|
90
|
+
"@genesislcap/rollup-builder": "14.482.1",
|
|
91
|
+
"@genesislcap/ts-builder": "14.482.1",
|
|
92
|
+
"@genesislcap/uvu-playwright-builder": "14.482.1",
|
|
93
|
+
"@genesislcap/vite-builder": "14.482.1",
|
|
94
|
+
"@genesislcap/webpack-builder": "14.482.1",
|
|
95
95
|
"copyfiles": "^2.4.1"
|
|
96
96
|
},
|
|
97
97
|
"dependencies": {
|
|
@@ -100,16 +100,16 @@
|
|
|
100
100
|
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
|
101
101
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
|
102
102
|
"@genesiscommunitysuccess/analyzer-import-alias-plugin": "^5.0.3",
|
|
103
|
-
"@genesislcap/expression-builder": "14.482.
|
|
104
|
-
"@genesislcap/foundation-ai": "14.482.
|
|
105
|
-
"@genesislcap/foundation-comms": "14.482.
|
|
106
|
-
"@genesislcap/foundation-criteria": "14.482.
|
|
107
|
-
"@genesislcap/foundation-errors": "14.482.
|
|
108
|
-
"@genesislcap/foundation-events": "14.482.
|
|
109
|
-
"@genesislcap/foundation-logger": "14.482.
|
|
110
|
-
"@genesislcap/foundation-notifications": "14.482.
|
|
111
|
-
"@genesislcap/foundation-user": "14.482.
|
|
112
|
-
"@genesislcap/foundation-utils": "14.482.
|
|
103
|
+
"@genesislcap/expression-builder": "14.482.1",
|
|
104
|
+
"@genesislcap/foundation-ai": "14.482.1",
|
|
105
|
+
"@genesislcap/foundation-comms": "14.482.1",
|
|
106
|
+
"@genesislcap/foundation-criteria": "14.482.1",
|
|
107
|
+
"@genesislcap/foundation-errors": "14.482.1",
|
|
108
|
+
"@genesislcap/foundation-events": "14.482.1",
|
|
109
|
+
"@genesislcap/foundation-logger": "14.482.1",
|
|
110
|
+
"@genesislcap/foundation-notifications": "14.482.1",
|
|
111
|
+
"@genesislcap/foundation-user": "14.482.1",
|
|
112
|
+
"@genesislcap/foundation-utils": "14.482.1",
|
|
113
113
|
"@microsoft/fast-colors": "5.3.1",
|
|
114
114
|
"@microsoft/fast-components": "2.30.6",
|
|
115
115
|
"@microsoft/fast-element": "1.14.0",
|
|
@@ -142,5 +142,5 @@
|
|
|
142
142
|
"require": "./dist/react.cjs"
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
|
-
"gitHead": "
|
|
145
|
+
"gitHead": "43a902838587d527b6786bbb41a5c3784c638e70"
|
|
146
146
|
}
|