@genesislcap/foundation-ui 14.482.1-alpha-c9fc44ab6.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 +1012 -814
- 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 +16 -16
- package/dist/esm/number-field/number-field.js +46 -18
- package/dist/esm/number-field/utils.js +152 -3
- package/dist/react.cjs +10 -10
- package/dist/react.mjs +8 -8
- 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,23 +129,23 @@ interface HTMLWCProps extends React.AriaAttributes {
|
|
|
129
129
|
onInput?(e: Event): void;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export declare const
|
|
132
|
+
export declare const ActionsMenu: React.ForwardRefExoticComponent<
|
|
133
133
|
React.PropsWithChildren<
|
|
134
|
-
Omit<PublicOf<
|
|
134
|
+
Omit<PublicOf<ActionsMenuWC>, 'children' | 'style'> &
|
|
135
135
|
HTMLWCProps & {
|
|
136
136
|
}
|
|
137
|
-
> & React.RefAttributes<
|
|
137
|
+
> & React.RefAttributes<ActionsMenuWC>
|
|
138
138
|
>;
|
|
139
|
-
export type
|
|
139
|
+
export type ActionsMenuRef = ActionsMenuWC;
|
|
140
140
|
|
|
141
|
-
export declare const
|
|
141
|
+
export declare const AccordionItem: React.ForwardRefExoticComponent<
|
|
142
142
|
React.PropsWithChildren<
|
|
143
|
-
Omit<PublicOf<
|
|
143
|
+
Omit<PublicOf<AccordionItemWC>, 'children' | 'style'> &
|
|
144
144
|
HTMLWCProps & {
|
|
145
145
|
}
|
|
146
|
-
> & React.RefAttributes<
|
|
146
|
+
> & React.RefAttributes<AccordionItemWC>
|
|
147
147
|
>;
|
|
148
|
-
export type
|
|
148
|
+
export type AccordionItemRef = AccordionItemWC;
|
|
149
149
|
|
|
150
150
|
export declare const AiCriteriaSearch: React.ForwardRefExoticComponent<
|
|
151
151
|
React.PropsWithChildren<
|
|
@@ -158,23 +158,23 @@ export declare const AiCriteriaSearch: React.ForwardRefExoticComponent<
|
|
|
158
158
|
>;
|
|
159
159
|
export type AiCriteriaSearchRef = AiCriteriaSearchWC;
|
|
160
160
|
|
|
161
|
-
export declare const
|
|
161
|
+
export declare const AiIndicator: React.ForwardRefExoticComponent<
|
|
162
162
|
React.PropsWithChildren<
|
|
163
|
-
Omit<PublicOf<
|
|
163
|
+
Omit<PublicOf<AiIndicatorWC>, 'children' | 'style'> &
|
|
164
164
|
HTMLWCProps & {
|
|
165
165
|
}
|
|
166
|
-
> & React.RefAttributes<
|
|
166
|
+
> & React.RefAttributes<AiIndicatorWC>
|
|
167
167
|
>;
|
|
168
|
-
export type
|
|
168
|
+
export type AiIndicatorRef = AiIndicatorWC;
|
|
169
169
|
|
|
170
|
-
export declare const
|
|
170
|
+
export declare const Accordion: React.ForwardRefExoticComponent<
|
|
171
171
|
React.PropsWithChildren<
|
|
172
|
-
Omit<PublicOf<
|
|
172
|
+
Omit<PublicOf<AccordionWC>, 'children' | 'style'> &
|
|
173
173
|
HTMLWCProps & {
|
|
174
174
|
}
|
|
175
|
-
> & React.RefAttributes<
|
|
175
|
+
> & React.RefAttributes<AccordionWC>
|
|
176
176
|
>;
|
|
177
|
-
export type
|
|
177
|
+
export type AccordionRef = AccordionWC;
|
|
178
178
|
|
|
179
179
|
export declare const Anchor: React.ForwardRefExoticComponent<
|
|
180
180
|
React.PropsWithChildren<
|
|
@@ -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,14 +111,14 @@ function _mergeRefs(...refs) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
const
|
|
114
|
+
const ActionsMenu = React.forwardRef(function ActionsMenu(props, ref) {
|
|
115
115
|
const { children, ...rest } = props;
|
|
116
|
-
return React.createElement(customElements.getName(
|
|
116
|
+
return React.createElement(customElements.getName(ActionsMenuWC) ?? '%%prefix%%-actions-menu', { ...rest, ref }, children);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
const
|
|
119
|
+
const AccordionItem = React.forwardRef(function AccordionItem(props, ref) {
|
|
120
120
|
const { children, ...rest } = props;
|
|
121
|
-
return React.createElement(customElements.getName(
|
|
121
|
+
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props, ref) {
|
|
@@ -143,14 +143,14 @@ const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props, ref)
|
|
|
143
143
|
return React.createElement(customElements.getName(AiCriteriaSearchWC) ?? '%%prefix%%-ai-criteria-search', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
const
|
|
146
|
+
const AiIndicator = React.forwardRef(function AiIndicator(props, ref) {
|
|
147
147
|
const { children, ...rest } = props;
|
|
148
|
-
return React.createElement(customElements.getName(
|
|
148
|
+
return React.createElement(customElements.getName(AiIndicatorWC) ?? '%%prefix%%-ai-indicator', { ...rest, ref }, children);
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
-
const
|
|
151
|
+
const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
152
152
|
const { children, ...rest } = props;
|
|
153
|
-
return React.createElement(customElements.getName(
|
|
153
|
+
return React.createElement(customElements.getName(AccordionWC) ?? '%%prefix%%-accordion', { ...rest, ref }, children);
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
const Anchor = React.forwardRef(function Anchor(props, ref) {
|
|
@@ -1078,11 +1078,11 @@ const WeeklyRecurrence = React.forwardRef(function WeeklyRecurrence(props, ref)
|
|
|
1078
1078
|
});
|
|
1079
1079
|
|
|
1080
1080
|
module.exports = {
|
|
1081
|
-
AccordionItem,
|
|
1082
1081
|
ActionsMenu,
|
|
1082
|
+
AccordionItem,
|
|
1083
1083
|
AiCriteriaSearch,
|
|
1084
|
-
Accordion,
|
|
1085
1084
|
AiIndicator,
|
|
1085
|
+
Accordion,
|
|
1086
1086
|
Anchor,
|
|
1087
1087
|
AnchoredRegion,
|
|
1088
1088
|
Avatar,
|
package/dist/react.mjs
CHANGED
|
@@ -109,14 +109,14 @@ function _mergeRefs(...refs) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
export const
|
|
112
|
+
export const ActionsMenu = React.forwardRef(function ActionsMenu(props, ref) {
|
|
113
113
|
const { children, ...rest } = props;
|
|
114
|
-
return React.createElement(customElements.getName(
|
|
114
|
+
return React.createElement(customElements.getName(ActionsMenuWC) ?? '%%prefix%%-actions-menu', { ...rest, ref }, children);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
export const
|
|
117
|
+
export const AccordionItem = React.forwardRef(function AccordionItem(props, ref) {
|
|
118
118
|
const { children, ...rest } = props;
|
|
119
|
-
return React.createElement(customElements.getName(
|
|
119
|
+
return React.createElement(customElements.getName(AccordionItemWC) ?? '%%prefix%%-accordion-item', { ...rest, ref }, children);
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
export const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props, ref) {
|
|
@@ -141,14 +141,14 @@ export const AiCriteriaSearch = React.forwardRef(function AiCriteriaSearch(props
|
|
|
141
141
|
return React.createElement(customElements.getName(AiCriteriaSearchWC) ?? '%%prefix%%-ai-criteria-search', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);
|
|
142
142
|
});
|
|
143
143
|
|
|
144
|
-
export const
|
|
144
|
+
export const AiIndicator = React.forwardRef(function AiIndicator(props, ref) {
|
|
145
145
|
const { children, ...rest } = props;
|
|
146
|
-
return React.createElement(customElements.getName(
|
|
146
|
+
return React.createElement(customElements.getName(AiIndicatorWC) ?? '%%prefix%%-ai-indicator', { ...rest, ref }, children);
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
export const
|
|
149
|
+
export const Accordion = React.forwardRef(function Accordion(props, ref) {
|
|
150
150
|
const { children, ...rest } = props;
|
|
151
|
-
return React.createElement(customElements.getName(
|
|
151
|
+
return React.createElement(customElements.getName(AccordionWC) ?? '%%prefix%%-accordion', { ...rest, ref }, children);
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
export const Anchor = React.forwardRef(function Anchor(props, ref) {
|
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.1
|
|
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.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
|
|
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.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
|
|
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
|
}
|