numora-react 1.0.8 → 3.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.mjs CHANGED
@@ -1,67 +1,465 @@
1
- import { jsx } from 'react/jsx-runtime';
2
- import { forwardRef, useRef, useState, useEffect, useImperativeHandle } from 'react';
3
- import { FormatOn, handleOnChangeNumoraInput, handleOnKeyDownNumoraInput, handleOnPasteNumoraInput, ThousandStyle } from 'numora';
1
+ import require$$0, { forwardRef, useRef, useState, useLayoutEffect, useEffect, useCallback } from 'react';
2
+ import { handleOnChangeNumoraInput, handleOnKeyDownNumoraInput, handleOnPasteNumoraInput, FormatOn, formatValueForDisplay, ThousandStyle } from 'numora';
4
3
  export { FormatOn, ThousandStyle } from 'numora';
5
4
 
5
+ var jsxRuntime = {exports: {}};
6
+
7
+ var reactJsxRuntime_production = {};
8
+
9
+ /**
10
+ * @license React
11
+ * react-jsx-runtime.production.js
12
+ *
13
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ */
18
+
19
+ var hasRequiredReactJsxRuntime_production;
20
+
21
+ function requireReactJsxRuntime_production () {
22
+ if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
23
+ hasRequiredReactJsxRuntime_production = 1;
24
+ var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
25
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
26
+ function jsxProd(type, config, maybeKey) {
27
+ var key = null;
28
+ void 0 !== maybeKey && (key = "" + maybeKey);
29
+ void 0 !== config.key && (key = "" + config.key);
30
+ if ("key" in config) {
31
+ maybeKey = {};
32
+ for (var propName in config)
33
+ "key" !== propName && (maybeKey[propName] = config[propName]);
34
+ } else maybeKey = config;
35
+ config = maybeKey.ref;
36
+ return {
37
+ $$typeof: REACT_ELEMENT_TYPE,
38
+ type: type,
39
+ key: key,
40
+ ref: void 0 !== config ? config : null,
41
+ props: maybeKey
42
+ };
43
+ }
44
+ reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
45
+ reactJsxRuntime_production.jsx = jsxProd;
46
+ reactJsxRuntime_production.jsxs = jsxProd;
47
+ return reactJsxRuntime_production;
48
+ }
49
+
50
+ var reactJsxRuntime_development = {};
51
+
52
+ /**
53
+ * @license React
54
+ * react-jsx-runtime.development.js
55
+ *
56
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
57
+ *
58
+ * This source code is licensed under the MIT license found in the
59
+ * LICENSE file in the root directory of this source tree.
60
+ */
61
+
62
+ var hasRequiredReactJsxRuntime_development;
63
+
64
+ function requireReactJsxRuntime_development () {
65
+ if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
66
+ hasRequiredReactJsxRuntime_development = 1;
67
+ "production" !== process.env.NODE_ENV &&
68
+ (function () {
69
+ function getComponentNameFromType(type) {
70
+ if (null == type) return null;
71
+ if ("function" === typeof type)
72
+ return type.$$typeof === REACT_CLIENT_REFERENCE
73
+ ? null
74
+ : type.displayName || type.name || null;
75
+ if ("string" === typeof type) return type;
76
+ switch (type) {
77
+ case REACT_FRAGMENT_TYPE:
78
+ return "Fragment";
79
+ case REACT_PROFILER_TYPE:
80
+ return "Profiler";
81
+ case REACT_STRICT_MODE_TYPE:
82
+ return "StrictMode";
83
+ case REACT_SUSPENSE_TYPE:
84
+ return "Suspense";
85
+ case REACT_SUSPENSE_LIST_TYPE:
86
+ return "SuspenseList";
87
+ case REACT_ACTIVITY_TYPE:
88
+ return "Activity";
89
+ }
90
+ if ("object" === typeof type)
91
+ switch (
92
+ ("number" === typeof type.tag &&
93
+ console.error(
94
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
95
+ ),
96
+ type.$$typeof)
97
+ ) {
98
+ case REACT_PORTAL_TYPE:
99
+ return "Portal";
100
+ case REACT_CONTEXT_TYPE:
101
+ return type.displayName || "Context";
102
+ case REACT_CONSUMER_TYPE:
103
+ return (type._context.displayName || "Context") + ".Consumer";
104
+ case REACT_FORWARD_REF_TYPE:
105
+ var innerType = type.render;
106
+ type = type.displayName;
107
+ type ||
108
+ ((type = innerType.displayName || innerType.name || ""),
109
+ (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef"));
110
+ return type;
111
+ case REACT_MEMO_TYPE:
112
+ return (
113
+ (innerType = type.displayName || null),
114
+ null !== innerType
115
+ ? innerType
116
+ : getComponentNameFromType(type.type) || "Memo"
117
+ );
118
+ case REACT_LAZY_TYPE:
119
+ innerType = type._payload;
120
+ type = type._init;
121
+ try {
122
+ return getComponentNameFromType(type(innerType));
123
+ } catch (x) {}
124
+ }
125
+ return null;
126
+ }
127
+ function testStringCoercion(value) {
128
+ return "" + value;
129
+ }
130
+ function checkKeyStringCoercion(value) {
131
+ try {
132
+ testStringCoercion(value);
133
+ var JSCompiler_inline_result = !1;
134
+ } catch (e) {
135
+ JSCompiler_inline_result = true;
136
+ }
137
+ if (JSCompiler_inline_result) {
138
+ JSCompiler_inline_result = console;
139
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
140
+ var JSCompiler_inline_result$jscomp$0 =
141
+ ("function" === typeof Symbol &&
142
+ Symbol.toStringTag &&
143
+ value[Symbol.toStringTag]) ||
144
+ value.constructor.name ||
145
+ "Object";
146
+ JSCompiler_temp_const.call(
147
+ JSCompiler_inline_result,
148
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
149
+ JSCompiler_inline_result$jscomp$0
150
+ );
151
+ return testStringCoercion(value);
152
+ }
153
+ }
154
+ function getTaskName(type) {
155
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
156
+ if (
157
+ "object" === typeof type &&
158
+ null !== type &&
159
+ type.$$typeof === REACT_LAZY_TYPE
160
+ )
161
+ return "<...>";
162
+ try {
163
+ var name = getComponentNameFromType(type);
164
+ return name ? "<" + name + ">" : "<...>";
165
+ } catch (x) {
166
+ return "<...>";
167
+ }
168
+ }
169
+ function getOwner() {
170
+ var dispatcher = ReactSharedInternals.A;
171
+ return null === dispatcher ? null : dispatcher.getOwner();
172
+ }
173
+ function UnknownOwner() {
174
+ return Error("react-stack-top-frame");
175
+ }
176
+ function hasValidKey(config) {
177
+ if (hasOwnProperty.call(config, "key")) {
178
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
179
+ if (getter && getter.isReactWarning) return false;
180
+ }
181
+ return void 0 !== config.key;
182
+ }
183
+ function defineKeyPropWarningGetter(props, displayName) {
184
+ function warnAboutAccessingKey() {
185
+ specialPropKeyWarningShown ||
186
+ ((specialPropKeyWarningShown = true),
187
+ console.error(
188
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
189
+ displayName
190
+ ));
191
+ }
192
+ warnAboutAccessingKey.isReactWarning = true;
193
+ Object.defineProperty(props, "key", {
194
+ get: warnAboutAccessingKey,
195
+ configurable: true
196
+ });
197
+ }
198
+ function elementRefGetterWithDeprecationWarning() {
199
+ var componentName = getComponentNameFromType(this.type);
200
+ didWarnAboutElementRef[componentName] ||
201
+ ((didWarnAboutElementRef[componentName] = true),
202
+ console.error(
203
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
204
+ ));
205
+ componentName = this.props.ref;
206
+ return void 0 !== componentName ? componentName : null;
207
+ }
208
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
209
+ var refProp = props.ref;
210
+ type = {
211
+ $$typeof: REACT_ELEMENT_TYPE,
212
+ type: type,
213
+ key: key,
214
+ props: props,
215
+ _owner: owner
216
+ };
217
+ null !== (void 0 !== refProp ? refProp : null)
218
+ ? Object.defineProperty(type, "ref", {
219
+ enumerable: false,
220
+ get: elementRefGetterWithDeprecationWarning
221
+ })
222
+ : Object.defineProperty(type, "ref", { enumerable: false, value: null });
223
+ type._store = {};
224
+ Object.defineProperty(type._store, "validated", {
225
+ configurable: false,
226
+ enumerable: false,
227
+ writable: true,
228
+ value: 0
229
+ });
230
+ Object.defineProperty(type, "_debugInfo", {
231
+ configurable: false,
232
+ enumerable: false,
233
+ writable: true,
234
+ value: null
235
+ });
236
+ Object.defineProperty(type, "_debugStack", {
237
+ configurable: false,
238
+ enumerable: false,
239
+ writable: true,
240
+ value: debugStack
241
+ });
242
+ Object.defineProperty(type, "_debugTask", {
243
+ configurable: false,
244
+ enumerable: false,
245
+ writable: true,
246
+ value: debugTask
247
+ });
248
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
249
+ return type;
250
+ }
251
+ function jsxDEVImpl(
252
+ type,
253
+ config,
254
+ maybeKey,
255
+ isStaticChildren,
256
+ debugStack,
257
+ debugTask
258
+ ) {
259
+ var children = config.children;
260
+ if (void 0 !== children)
261
+ if (isStaticChildren)
262
+ if (isArrayImpl(children)) {
263
+ for (
264
+ isStaticChildren = 0;
265
+ isStaticChildren < children.length;
266
+ isStaticChildren++
267
+ )
268
+ validateChildKeys(children[isStaticChildren]);
269
+ Object.freeze && Object.freeze(children);
270
+ } else
271
+ console.error(
272
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
273
+ );
274
+ else validateChildKeys(children);
275
+ if (hasOwnProperty.call(config, "key")) {
276
+ children = getComponentNameFromType(type);
277
+ var keys = Object.keys(config).filter(function (k) {
278
+ return "key" !== k;
279
+ });
280
+ isStaticChildren =
281
+ 0 < keys.length
282
+ ? "{key: someKey, " + keys.join(": ..., ") + ": ...}"
283
+ : "{key: someKey}";
284
+ didWarnAboutKeySpread[children + isStaticChildren] ||
285
+ ((keys =
286
+ 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}"),
287
+ console.error(
288
+ 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
289
+ isStaticChildren,
290
+ children,
291
+ keys,
292
+ children
293
+ ),
294
+ (didWarnAboutKeySpread[children + isStaticChildren] = true));
295
+ }
296
+ children = null;
297
+ void 0 !== maybeKey &&
298
+ (checkKeyStringCoercion(maybeKey), (children = "" + maybeKey));
299
+ hasValidKey(config) &&
300
+ (checkKeyStringCoercion(config.key), (children = "" + config.key));
301
+ if ("key" in config) {
302
+ maybeKey = {};
303
+ for (var propName in config)
304
+ "key" !== propName && (maybeKey[propName] = config[propName]);
305
+ } else maybeKey = config;
306
+ children &&
307
+ defineKeyPropWarningGetter(
308
+ maybeKey,
309
+ "function" === typeof type
310
+ ? type.displayName || type.name || "Unknown"
311
+ : type
312
+ );
313
+ return ReactElement(
314
+ type,
315
+ children,
316
+ maybeKey,
317
+ getOwner(),
318
+ debugStack,
319
+ debugTask
320
+ );
321
+ }
322
+ function validateChildKeys(node) {
323
+ isValidElement(node)
324
+ ? node._store && (node._store.validated = 1)
325
+ : "object" === typeof node &&
326
+ null !== node &&
327
+ node.$$typeof === REACT_LAZY_TYPE &&
328
+ ("fulfilled" === node._payload.status
329
+ ? isValidElement(node._payload.value) &&
330
+ node._payload.value._store &&
331
+ (node._payload.value._store.validated = 1)
332
+ : node._store && (node._store.validated = 1));
333
+ }
334
+ function isValidElement(object) {
335
+ return (
336
+ "object" === typeof object &&
337
+ null !== object &&
338
+ object.$$typeof === REACT_ELEMENT_TYPE
339
+ );
340
+ }
341
+ var React = require$$0,
342
+ REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
343
+ REACT_PORTAL_TYPE = Symbol.for("react.portal"),
344
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
345
+ REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
346
+ REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
347
+ REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
348
+ REACT_CONTEXT_TYPE = Symbol.for("react.context"),
349
+ REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
350
+ REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
351
+ REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
352
+ REACT_MEMO_TYPE = Symbol.for("react.memo"),
353
+ REACT_LAZY_TYPE = Symbol.for("react.lazy"),
354
+ REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
355
+ REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
356
+ ReactSharedInternals =
357
+ React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
358
+ hasOwnProperty = Object.prototype.hasOwnProperty,
359
+ isArrayImpl = Array.isArray,
360
+ createTask = console.createTask
361
+ ? console.createTask
362
+ : function () {
363
+ return null;
364
+ };
365
+ React = {
366
+ react_stack_bottom_frame: function (callStackForError) {
367
+ return callStackForError();
368
+ }
369
+ };
370
+ var specialPropKeyWarningShown;
371
+ var didWarnAboutElementRef = {};
372
+ var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(
373
+ React,
374
+ UnknownOwner
375
+ )();
376
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
377
+ var didWarnAboutKeySpread = {};
378
+ reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
379
+ reactJsxRuntime_development.jsx = function (type, config, maybeKey) {
380
+ var trackActualOwner =
381
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
382
+ return jsxDEVImpl(
383
+ type,
384
+ config,
385
+ maybeKey,
386
+ false,
387
+ trackActualOwner
388
+ ? Error("react-stack-top-frame")
389
+ : unknownOwnerDebugStack,
390
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
391
+ );
392
+ };
393
+ reactJsxRuntime_development.jsxs = function (type, config, maybeKey) {
394
+ var trackActualOwner =
395
+ 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
396
+ return jsxDEVImpl(
397
+ type,
398
+ config,
399
+ maybeKey,
400
+ true,
401
+ trackActualOwner
402
+ ? Error("react-stack-top-frame")
403
+ : unknownOwnerDebugStack,
404
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
405
+ );
406
+ };
407
+ })();
408
+ return reactJsxRuntime_development;
409
+ }
410
+
411
+ var hasRequiredJsxRuntime;
412
+
413
+ function requireJsxRuntime () {
414
+ if (hasRequiredJsxRuntime) return jsxRuntime.exports;
415
+ hasRequiredJsxRuntime = 1;
416
+
417
+ if (process.env.NODE_ENV === 'production') {
418
+ jsxRuntime.exports = requireReactJsxRuntime_production();
419
+ } else {
420
+ jsxRuntime.exports = requireReactJsxRuntime_development();
421
+ }
422
+ return jsxRuntime.exports;
423
+ }
424
+
425
+ var jsxRuntimeExports = requireJsxRuntime();
426
+
6
427
  function handleNumoraOnChange(e, options) {
7
- handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
8
- const target = e.target;
9
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
10
- if (rawValue) {
11
- target.removeAttribute('data-raw-value');
12
- }
428
+ const { formatted, raw } = handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, options.caretPositionBeforeChange, options.formattingOptions);
13
429
  return {
14
- value: target.value,
15
- rawValue,
430
+ value: formatted,
431
+ rawValue: raw,
16
432
  };
17
433
  }
18
434
  function handleNumoraOnPaste(e, options) {
19
- const value = handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
20
- const target = e.target;
21
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
22
- if (rawValue) {
23
- target.removeAttribute('data-raw-value');
24
- }
435
+ const { formatted, raw } = handleOnPasteNumoraInput(e.nativeEvent, options.decimalMaxLength, options.formattingOptions);
25
436
  return {
26
- value,
27
- rawValue,
437
+ value: formatted,
438
+ rawValue: raw,
28
439
  };
29
440
  }
30
441
  function handleNumoraOnKeyDown(e, formattingOptions) {
31
442
  return handleOnKeyDownNumoraInput(e.nativeEvent, formattingOptions);
32
443
  }
33
444
  function handleNumoraOnBlur(e, options) {
34
- // If formatOn is blur, force formatting on blur by invoking change handler logic
35
445
  if (options.formattingOptions.formatOn === FormatOn.Blur) {
36
- handleOnChangeNumoraInput(e.nativeEvent, options.decimalMaxLength, undefined, { ...options.formattingOptions, formatOn: FormatOn.Change });
37
- }
38
- const target = e.target;
39
- const rawValue = target.getAttribute('data-raw-value') ?? undefined;
40
- if (rawValue) {
41
- target.removeAttribute('data-raw-value');
446
+ const { formatted, raw } = formatValueForDisplay(e.target.value, options.decimalMaxLength, { ...options.formattingOptions, formatOn: FormatOn.Change });
447
+ return {
448
+ value: formatted,
449
+ rawValue: raw,
450
+ };
42
451
  }
43
452
  return {
44
- value: target.value,
45
- rawValue,
453
+ value: e.target.value,
454
+ rawValue: undefined,
46
455
  };
47
456
  }
48
457
 
49
458
  const NumoraInput = forwardRef((props, ref) => {
50
459
  const { maxDecimals = 2, onChange, onPaste, onBlur, onKeyDown, formatOn = FormatOn.Blur, thousandSeparator = ',', thousandStyle = ThousandStyle.Thousand, decimalSeparator = '.', decimalMinLength, enableCompactNotation = false, enableNegative = false, enableLeadingZeros = false, rawValueMode = false, value: controlledValue, defaultValue, ...rest } = props;
51
- const inputRef = useRef(null);
460
+ const internalInputRef = useRef(null);
52
461
  const caretInfoRef = useRef(undefined);
53
- const [internalValue, setInternalValue] = useState(controlledValue !== undefined
54
- ? String(controlledValue)
55
- : defaultValue !== undefined
56
- ? String(defaultValue)
57
- : '');
58
- // Keep internal state in sync when controlled
59
- useEffect(() => {
60
- if (controlledValue !== undefined) {
61
- setInternalValue(String(controlledValue));
62
- }
63
- }, [controlledValue]);
64
- useImperativeHandle(ref, () => inputRef.current, []);
462
+ const lastCaretPosRef = useRef(null);
65
463
  const formattingOptions = {
66
464
  formatOn,
67
465
  thousandSeparator,
@@ -73,88 +471,119 @@ const NumoraInput = forwardRef((props, ref) => {
73
471
  enableLeadingZeros,
74
472
  rawValueMode,
75
473
  };
76
- const formatValueWithCore = (value) => {
77
- const el = inputRef.current ?? document.createElement('input');
78
- el.value = value;
79
- const fakeEvent = { target: el };
80
- handleOnChangeNumoraInput(fakeEvent, maxDecimals, undefined, formattingOptions);
81
- return el.value;
474
+ const getInitialValue = () => {
475
+ const valueToFormat = controlledValue !== undefined ? controlledValue : defaultValue;
476
+ if (valueToFormat !== undefined) {
477
+ const { formatted } = formatValueForDisplay(String(valueToFormat), maxDecimals, formattingOptions);
478
+ return formatted;
479
+ }
480
+ return '';
82
481
  };
83
- // When controlled value changes, normalize/format it for display
482
+ const [displayValue, setDisplayValue] = useState(getInitialValue);
483
+ // Sync external ref with internal ref
484
+ useLayoutEffect(() => {
485
+ if (!ref)
486
+ return;
487
+ if (typeof ref === 'function') {
488
+ ref(internalInputRef.current);
489
+ }
490
+ else {
491
+ ref.current = internalInputRef.current;
492
+ }
493
+ }, [ref]);
494
+ // When controlled value changes from outside, update display value
84
495
  useEffect(() => {
85
496
  if (controlledValue !== undefined) {
86
- const formatted = formatValueWithCore(String(controlledValue));
87
- setInternalValue(formatted);
497
+ const { formatted } = formatValueForDisplay(String(controlledValue), maxDecimals, formattingOptions);
498
+ if (formatted !== displayValue) {
499
+ setDisplayValue(formatted);
500
+ }
88
501
  }
89
- }, [controlledValue, formatOn, thousandSeparator, thousandStyle, decimalSeparator, decimalMinLength, enableCompactNotation, enableNegative, enableLeadingZeros, rawValueMode, maxDecimals]);
90
- const handleChange = (e) => {
502
+ }, [controlledValue, maxDecimals, formattingOptions]);
503
+ // Restore cursor position after render
504
+ useLayoutEffect(() => {
505
+ if (internalInputRef.current && lastCaretPosRef.current !== null) {
506
+ const input = internalInputRef.current;
507
+ const pos = lastCaretPosRef.current;
508
+ input.setSelectionRange(pos, pos);
509
+ lastCaretPosRef.current = null;
510
+ }
511
+ });
512
+ const handleChange = useCallback((e) => {
91
513
  const { value, rawValue } = handleNumoraOnChange(e, {
92
514
  decimalMaxLength: maxDecimals,
93
515
  caretPositionBeforeChange: caretInfoRef.current,
94
516
  formattingOptions,
95
517
  });
96
- caretInfoRef.current = undefined;
97
- if (controlledValue === undefined) {
98
- setInternalValue(value);
99
- }
100
- else {
101
- setInternalValue(value);
518
+ // Store cursor position AFTER core library has calculated and set it
519
+ // The core library modifies the DOM element directly during handleNumoraOnChange
520
+ // Read from the input ref (which is the same element) to get the position set by the core library
521
+ if (internalInputRef.current) {
522
+ const cursorPos = internalInputRef.current.selectionStart;
523
+ if (cursorPos !== null && cursorPos !== undefined) {
524
+ lastCaretPosRef.current = cursorPos;
525
+ }
102
526
  }
527
+ caretInfoRef.current = undefined;
528
+ // Add rawValue to the event object without overriding 'value' property
529
+ e.target.rawValue = rawValue;
530
+ setDisplayValue(value);
103
531
  if (onChange) {
104
532
  onChange(e);
105
533
  }
106
- // Optionally expose rawValue via a custom event attribute if needed later
107
- if (rawValue && e.target && rawValueMode) {
108
- // Keep the raw value on the input for consumers that read it directly
109
- e.target.setAttribute('data-raw-value', rawValue);
534
+ }, [maxDecimals, formattingOptions, onChange]);
535
+ const handleKeyDown = useCallback((e) => {
536
+ const coreCaretInfo = handleNumoraOnKeyDown(e, formattingOptions);
537
+ // Always capture cursor position info, even if core library doesn't return it
538
+ // This is needed for cursor position calculation during normal typing (not just Delete/Backspace)
539
+ if (!coreCaretInfo && internalInputRef.current) {
540
+ const selectionStart = internalInputRef.current.selectionStart ?? 0;
541
+ const selectionEnd = internalInputRef.current.selectionEnd ?? 0;
542
+ caretInfoRef.current = {
543
+ selectionStart,
544
+ selectionEnd,
545
+ };
110
546
  }
111
- };
112
- const handlePaste = (e) => {
547
+ else {
548
+ caretInfoRef.current = coreCaretInfo;
549
+ }
550
+ if (onKeyDown) {
551
+ onKeyDown(e);
552
+ }
553
+ }, [formattingOptions, onKeyDown]);
554
+ const handlePaste = useCallback((e) => {
113
555
  const { value, rawValue } = handleNumoraOnPaste(e, {
114
556
  decimalMaxLength: maxDecimals,
115
557
  formattingOptions,
116
558
  });
117
- if (controlledValue === undefined) {
118
- setInternalValue(value);
119
- }
120
- else {
121
- setInternalValue(value);
122
- }
559
+ // For paste, we often want to move cursor to the end of pasted content
560
+ // handleNumoraOnPaste already handles DOM value and cursor, but React will overwrite it.
561
+ // So we capture where the core logic set the cursor.
562
+ lastCaretPosRef.current = e.target.selectionStart;
563
+ e.target.rawValue = rawValue;
564
+ setDisplayValue(value);
123
565
  if (onPaste) {
124
566
  onPaste(e);
125
567
  }
568
+ // Trigger onChange manually because paste event doesn't always trigger a ChangeEvent in all React versions
569
+ // when we preventDefault.
126
570
  if (onChange) {
127
- onChange(e);
128
- }
129
- if (rawValue && e.target && rawValueMode) {
130
- e.target.setAttribute('data-raw-value', rawValue);
131
- }
132
- };
133
- const handleKeyDown = (e) => {
134
- caretInfoRef.current = handleNumoraOnKeyDown(e, formattingOptions);
135
- if (onKeyDown) {
136
- onKeyDown(e);
571
+ const changeEvent = e;
572
+ onChange(changeEvent);
137
573
  }
138
- };
139
- const handleBlur = (e) => {
574
+ }, [maxDecimals, formattingOptions, onPaste, onChange]);
575
+ const handleBlur = useCallback((e) => {
140
576
  const { value, rawValue } = handleNumoraOnBlur(e, {
141
577
  decimalMaxLength: maxDecimals,
142
578
  formattingOptions,
143
579
  });
144
- if (controlledValue === undefined) {
145
- setInternalValue(value);
146
- }
147
- else {
148
- setInternalValue(value);
149
- }
580
+ e.target.rawValue = rawValue;
581
+ setDisplayValue(value);
150
582
  if (onBlur) {
151
583
  onBlur(e);
152
584
  }
153
- if (rawValue && e.target && rawValueMode) {
154
- e.target.setAttribute('data-raw-value', rawValue);
155
- }
156
- };
157
- return (jsx("input", { ...rest, ref: inputRef, value: internalValue, onChange: handleChange, onPaste: handlePaste, onKeyDown: handleKeyDown, onBlur: handleBlur, type: "text", inputMode: "decimal" }));
585
+ }, [maxDecimals, formattingOptions, onBlur]);
586
+ return (jsxRuntimeExports.jsx("input", { ...rest, ref: internalInputRef, value: displayValue, onChange: handleChange, onKeyDown: handleKeyDown, onPaste: handlePaste, onBlur: handleBlur, type: "text", inputMode: "decimal", spellCheck: false, autoComplete: "off" }));
158
587
  });
159
588
  NumoraInput.displayName = 'NumoraInput';
160
589