@uxf/form 11.100.1 → 11.102.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.
@@ -1,16 +1,62 @@
1
1
  "use strict";
2
2
  "use client";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
6
36
  Object.defineProperty(exports, "__esModule", { value: true });
7
37
  exports.NumberInput = NumberInput;
8
38
  const translations_1 = require("@uxf/core-react/translations");
39
+ const is_not_empty_1 = require("@uxf/core/utils/is-not-empty");
9
40
  const is_not_nil_1 = require("@uxf/core/utils/is-not-nil");
10
41
  const text_input_1 = require("@uxf/ui/text-input");
11
- const react_1 = __importDefault(require("react"));
42
+ const react_1 = __importStar(require("react"));
12
43
  const react_hook_form_1 = require("react-hook-form");
13
44
  const form_context_1 = require("../form-id-context/form-context");
45
+ function normalizeInputValue(value) {
46
+ let result = value;
47
+ const lastComma = result.lastIndexOf(",");
48
+ const lastDot = result.lastIndexOf(".");
49
+ /* this normalizes comma delimiter to dot and then handle other comma/dots separators */
50
+ if (lastComma !== -1 && lastDot < lastComma) {
51
+ const beforeComma = result.slice(0, lastComma).replaceAll(",", "").replaceAll(".", "");
52
+ const afterComma = result.slice(lastComma + 1);
53
+ result = `${beforeComma}.${afterComma}`;
54
+ }
55
+ /* this handles case with dot as delimiter and commas as separators */
56
+ result = result.replaceAll(",", "");
57
+ /* this trim all spaces */
58
+ return result.replace(/\s/g, "");
59
+ }
14
60
  function NumberInput(props) {
15
61
  var _a, _b, _c, _d, _e, _f;
16
62
  const formContext = (0, form_context_1.useFormContext)();
@@ -50,15 +96,58 @@ function NumberInput(props) {
50
96
  },
51
97
  shouldUnregister: props.shouldUnregister,
52
98
  });
53
- const onBlur = (event) => {
99
+ const isPasting = (0, react_1.useRef)(false);
100
+ /* this prevents plus/minus sign inside number and duplicate sign at start */
101
+ const handleBeforeInput = (event) => {
102
+ if ((0, is_not_nil_1.isNotNil)(event.nativeEvent.data) && /[+-]/.test(event.nativeEvent.data)) {
103
+ if ((0, is_not_empty_1.isNotEmpty)(event.currentTarget.value) || event.currentTarget.validity.badInput) {
104
+ event.preventDefault();
105
+ }
106
+ }
107
+ };
108
+ const handleBlur = (event) => {
54
109
  var _a;
55
110
  field.onBlur();
56
111
  (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
57
112
  };
58
- const onKeyDown = (event) => {
113
+ const handleChange = (value, event) => {
114
+ var _a;
115
+ // normalize delimiter, trim spaces
116
+ let rawValue = normalizeInputValue(value);
117
+ // trim extraneous decimal places if specified
118
+ if ((0, is_not_nil_1.isNotNil)(props.decimalPlaces)) {
119
+ const [integers, decimals] = rawValue.split(".");
120
+ if ((0, is_not_nil_1.isNotNil)(decimals) && decimals.length > props.decimalPlaces) {
121
+ if (isPasting.current) {
122
+ // Round on paste
123
+ rawValue = parseFloat(rawValue).toFixed(props.decimalPlaces);
124
+ }
125
+ else {
126
+ // Trim on type
127
+ rawValue = `${integers}.${decimals.slice(0, props.decimalPlaces)}`;
128
+ }
129
+ }
130
+ }
131
+ isPasting.current = false;
132
+ const parsedValue = (0, is_not_nil_1.isNotNil)(props.decimalPlaces) ? parseFloat(rawValue) : parseInt(rawValue, 10);
133
+ const returnValue = isNaN(parsedValue) ? null : parsedValue;
134
+ field.onChange(returnValue);
135
+ (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, returnValue, event);
136
+ };
137
+ const handleKeyDown = (event) => {
59
138
  var _a;
60
139
  // Allow special keys
61
- const specialKeys = ["Backspace", "Delete", "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Tab"];
140
+ const specialKeys = [
141
+ "Backspace",
142
+ "Delete",
143
+ "ArrowLeft",
144
+ "ArrowRight",
145
+ "ArrowUp",
146
+ "ArrowDown",
147
+ "Tab",
148
+ "Home",
149
+ "End",
150
+ ];
62
151
  // Allow keys for copy/paste/select/cut
63
152
  const controlKeys = ["v", "V", "c", "C", "x", "X", "a", "A"];
64
153
  // Allow digits and decimal point (.,)
@@ -73,15 +162,16 @@ function NumberInput(props) {
73
162
  }
74
163
  (_a = props.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(props, event);
75
164
  };
76
- const onChange = (value, event) => {
77
- var _a;
78
- const parsedValue = props.decimalPlaces
79
- ? parseFloat(parseFloat(value.replace(" ", "")).toFixed(props.decimalPlaces))
80
- : parseInt(value.replace(" ", ""), 10);
81
- const returnValue = isNaN(parsedValue) ? null : parsedValue;
82
- field.onChange(returnValue);
83
- (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, returnValue, event);
165
+ // rAF resets the flag if onChange never fires (e.g. browser rejects invalid paste)
166
+ const handlePaste = () => {
167
+ isPasting.current = true;
168
+ requestAnimationFrame(() => {
169
+ isPasting.current = false;
170
+ });
84
171
  };
85
- return (react_1.default.createElement(text_input_1.TextInput, { autoComplete: props.autoComplete, autoFocus: props.autoFocus, className: props.className, enterKeyHint: props.enterKeyHint, form: props.form, helperText: (_e = (_d = fieldState.error) === null || _d === void 0 ? void 0 : _d.message) !== null && _e !== void 0 ? _e : props.helperText, hiddenLabel: props.hiddenLabel, id: id, inputMode: props.decimalPlaces ? "decimal" : "numeric", isDisabled: formContext.isFormDisabled || props.isDisabled, isInvalid: (0, is_not_nil_1.isNotNil)(fieldState.error), isReadOnly: formContext.isFormReadOnly || props.isReadOnly, isRequired: props.isRequired, label: props.label, leftAddon: props.leftAddon, leftElement: props.leftElement, max: props.max, min: props.min, name: field.name, onBlur: onBlur, onChange: onChange, onFocus: props.onFocus, onKeyDown: onKeyDown, pattern: props.pattern, placeholder: props.placeholder, ref: field.ref, rightAddon: props.rightAddon, rightElement: props.rightElement, size: props.size, step: props.decimalPlaces ? Number(0).toFixed(props.decimalPlaces - 1) + "1" : props.step, style: props.style, type: "number", value: (_f = field.value) !== null && _f !== void 0 ? _f : "", variant: props.variant }));
172
+ const step = props.decimalPlaces
173
+ ? (1 / Math.pow(10, Math.trunc(props.decimalPlaces))).toString() // trunc is for float>int conversion
174
+ : props.step;
175
+ return (react_1.default.createElement(text_input_1.TextInput, { autoComplete: props.autoComplete, autoFocus: props.autoFocus, className: props.className, enterKeyHint: props.enterKeyHint, form: props.form, helperText: (_e = (_d = fieldState.error) === null || _d === void 0 ? void 0 : _d.message) !== null && _e !== void 0 ? _e : props.helperText, hiddenLabel: props.hiddenLabel, id: id, inputMode: props.decimalPlaces ? "decimal" : "numeric", isDisabled: formContext.isFormDisabled || props.isDisabled, isInvalid: (0, is_not_nil_1.isNotNil)(fieldState.error), isReadOnly: formContext.isFormReadOnly || props.isReadOnly, isRequired: props.isRequired, label: props.label, leftAddon: props.leftAddon, leftElement: props.leftElement, max: props.max, min: props.min, name: field.name, onBeforeInput: handleBeforeInput, onBlur: handleBlur, onChange: handleChange, onFocus: props.onFocus, onKeyDown: handleKeyDown, onPaste: handlePaste, pattern: props.pattern, placeholder: props.placeholder, ref: field.ref, rightAddon: props.rightAddon, rightElement: props.rightElement, size: props.size, step: step, style: props.style, type: "number", value: (_f = field.value) !== null && _f !== void 0 ? _f : "", variant: props.variant }));
86
176
  }
87
177
  NumberInput.displayName = "UxfFormNumberInput";
@@ -16,7 +16,7 @@ function Default() {
16
16
  const storyFormNumberInputs = (control) => (react_1.default.createElement("div", { className: "light mb-4 space-y-4 p-4" },
17
17
  react_1.default.createElement(number_input_1.NumberInput, { control: control, label: "Default input", name: "default" }),
18
18
  react_1.default.createElement(number_input_1.NumberInput, { control: control, isRequired: true, label: "Required input", name: "required" }),
19
- react_1.default.createElement(number_input_1.NumberInput, { control: control, decimalPlaces: 3, label: "Dec\u00EDmal input", name: "decimal" }),
19
+ react_1.default.createElement(number_input_1.NumberInput, { control: control, decimalPlaces: 3, label: "Decimal input", name: "decimal" }),
20
20
  react_1.default.createElement(number_input_1.NumberInput, { control: control, label: "max50 input", max: 50, name: "max50" }),
21
21
  react_1.default.createElement(button_1.Button, { type: "submit" }, "Submit")));
22
22
  return (react_1.default.createElement(storybook_form_1.StorybookForm, null, ({ control }) => (react_1.default.createElement("div", { className: "flex flex-col lg:flex-row" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxf/form",
3
- "version": "11.100.1",
3
+ "version": "11.102.0",
4
4
  "description": "",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,7 +18,7 @@
18
18
  "dependencies": {
19
19
  "@uxf/core": "11.100.0",
20
20
  "@uxf/core-react": "11.100.0",
21
- "@uxf/ui": "11.100.1",
21
+ "@uxf/ui": "11.102.0",
22
22
  "coordinate-parser": "1.0.7",
23
23
  "dayjs": "1.11.19",
24
24
  "react-hook-form": "7.71.1"