numora 3.5.0 → 4.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/types.d.ts CHANGED
@@ -8,15 +8,62 @@ export declare enum ThousandStyle {
8
8
  Lakh = "lakh",
9
9
  Wan = "wan"
10
10
  }
11
+ /**
12
+ * Named constants for the W3C InputEvent `inputType` strings used by NumoraInput's
13
+ * beforeinput/input handlers. Defined as an `as const` object (not a TS `enum`) to
14
+ * avoid a runtime artifact and to stay tree-shakable.
15
+ *
16
+ * Reference for the full set of `inputType` values:
17
+ * - MDN: https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/inputType
18
+ * - W3C Input Events spec: https://w3c.github.io/input-events/
19
+ */
20
+ export declare const InputType: {
21
+ readonly InsertText: "insertText";
22
+ readonly InsertFromPaste: "insertFromPaste";
23
+ readonly InsertFromDrop: "insertFromDrop";
24
+ readonly DeleteContentBackward: "deleteContentBackward";
25
+ readonly DeleteContentForward: "deleteContentForward";
26
+ readonly DeleteByCut: "deleteByCut";
27
+ readonly DeleteByDrag: "deleteByDrag";
28
+ readonly DeleteSoftLineBackward: "deleteSoftLineBackward";
29
+ readonly DeleteHardLineBackward: "deleteHardLineBackward";
30
+ readonly DeleteSoftLineForward: "deleteSoftLineForward";
31
+ readonly DeleteHardLineForward: "deleteHardLineForward";
32
+ readonly HistoryUndo: "historyUndo";
33
+ readonly HistoryRedo: "historyRedo";
34
+ };
35
+ export type InputType = (typeof InputType)[keyof typeof InputType];
11
36
  export interface FormattingOptions {
12
37
  formatOn?: FormatOn;
13
38
  thousandSeparator?: string;
14
- ThousandStyle?: ThousandStyle;
39
+ thousandStyle?: ThousandStyle;
15
40
  enableCompactNotation?: boolean;
16
41
  enableNegative?: boolean;
17
42
  enableLeadingZeros?: boolean;
43
+ /**
44
+ * When true, a bare leading decimal separator gets a `0` prepended (`.5` → `0.5`,
45
+ * `-.5` → `-0.5`). Useful for currency-style fields where leading-decimal entry is
46
+ * common but `0.` form is the canonical representation.
47
+ */
48
+ autoAddLeadingZero?: boolean;
18
49
  decimalSeparator?: string;
50
+ decimalMaxLength?: number;
19
51
  decimalMinLength?: number;
52
+ /**
53
+ * Maximum length of the raw (unformatted) value. Counts digits, the decimal separator,
54
+ * and a leading `-`. Thousand separators are NOT counted. Applied at the end of the
55
+ * sanitization pipeline and enforced at keystroke time so the user cannot type past it.
56
+ *
57
+ * Do not also pass `maxLength` as a native HTML attribute - that one counts formatted
58
+ * characters (commas included) and would double-count.
59
+ */
60
+ maxLength?: number;
61
+ /**
62
+ * Custom keystroke/paste validator. Called with the post-sanitization raw value the
63
+ * input would have after the user's action. Return false to reject the edit (no value
64
+ * change, no onChange fires, undo history is untouched).
65
+ */
66
+ isAllowed?: (rawValue: string) => boolean;
20
67
  rawValueMode?: boolean;
21
68
  }
22
69
  export interface CaretPositionInfo {
@@ -1,45 +1,60 @@
1
1
  import { type FormattingOptions, type CaretPositionInfo } from '@/types';
2
2
  /**
3
- * Handles the beforeinput event to format the value before it is applied to the DOM.
3
+ * Outcome of `handleOnBeforeInputNumoraInput`. Pure: the helper does not mutate the
4
+ * input or the event. The caller decides what to do based on the variant:
4
5
  *
5
- * Returns null for paste events so the dedicated paste handler can process them.
6
+ * - `handled`: caller should preventDefault, write `formatted` to the input via an
7
+ * undo-preserving write, set caret to `cursorPos`, and notify listeners.
8
+ * - `reject`: caller should preventDefault. The input value is left untouched.
9
+ * - `skip`: caller should NOT preventDefault. Includes paste/drop (handled by the
10
+ * dedicated paste listener) and any unrecognized inputType.
11
+ */
12
+ export type BeforeInputResult = {
13
+ type: 'handled';
14
+ formatted: string;
15
+ raw: string;
16
+ cursorPos: number;
17
+ } | {
18
+ type: 'reject';
19
+ } | {
20
+ type: 'skip';
21
+ };
22
+ /**
23
+ * Computes the formatted value, raw value, and target cursor position for a
24
+ * `beforeinput` event without mutating the input or the event.
25
+ *
26
+ * Callers are responsible for `preventDefault()` and applying the result to the DOM.
6
27
  *
7
28
  * @param e - The InputEvent (beforeinput)
8
29
  * @param decimalMaxLength - The maximum number of decimal places allowed
9
30
  * @param formattingOptions - Optional formatting options
10
- * @returns Object with formatted and raw values, or null if the event should be handled natively
31
+ * @returns A tagged result describing what the caller should do
11
32
  */
12
- export declare function handleOnBeforeInputNumoraInput(e: InputEvent, decimalMaxLength: number, formattingOptions?: FormattingOptions): {
13
- formatted: string;
14
- raw: string;
15
- } | null;
33
+ export declare function handleOnBeforeInputNumoraInput(e: InputEvent, decimalMaxLength: number, formattingOptions?: FormattingOptions): BeforeInputResult;
16
34
  /**
17
- * Handles the keydown event to prevent the user from entering a second decimal point.
18
- * Also tracks selection info for Delete/Backspace keys to enable proper cursor positioning.
19
- * In 'change' mode with formatting, skips cursor over thousand separators on delete/backspace.
20
- *
21
- * @param e - The keyboard event triggered by the input.
22
- * @param formattingOptions - Optional formatting options for separator skipping
23
- * @returns Caret position info if Delete/Backspace was pressed, undefined otherwise
35
+ * Skips the cursor over thousand separators on Delete/Backspace and returns the caret
36
+ * info the change handler needs to disambiguate Delete-forward (`endOffset: 1`) from
37
+ * Backspace or non-deletion keys (`endOffset: 0`). Returns undefined for keys that
38
+ * aren't Delete/Backspace so the caller can null out the stored caret info.
24
39
  */
25
40
  export declare function handleOnKeyDownNumoraInput(e: KeyboardEvent, formattingOptions?: FormattingOptions): CaretPositionInfo | undefined;
26
41
  /**
27
- * Handles the input change event to ensure the value does not exceed the maximum number of decimal places,
28
- * replaces commas with dots, and removes invalid non-numeric characters.
29
- * Also handles cursor positioning for Delete/Backspace keys.
30
- * Optionally formats with thousand separators in real-time if formatOn is 'change'.
42
+ * Outcome of `handleOnPasteNumoraInput`. The caller always calls preventDefault on the
43
+ * paste event; the variant says whether to apply a write or leave the input untouched.
31
44
  *
32
- * @param e - The event triggered by the input.
33
- * @param decimalMaxLength - The maximum number of decimal places allowed.
34
- * @param caretPositionBeforeChange - Optional caret position info from keydown handler
35
- * @param formattingOptions - Optional formatting options for real-time formatting
36
- * @returns Object with formatted value and raw value
45
+ * - `handled`: write `formatted` via an undo-preserving write, set caret to `cursorPos`.
46
+ * - `reject`: do nothing further (input is unchanged).
37
47
  */
38
- export declare function handleOnChangeNumoraInput(e: Event, decimalMaxLength: number, caretPositionBeforeChange?: CaretPositionInfo, formattingOptions?: FormattingOptions): {
39
- formatted: string;
40
- raw: string;
41
- };
42
- export declare function handleOnPasteNumoraInput(e: ClipboardEvent, decimalMaxLength: number, formattingOptions?: FormattingOptions): {
48
+ export type PasteResult = {
49
+ type: 'handled';
43
50
  formatted: string;
44
51
  raw: string;
52
+ cursorPos: number;
53
+ } | {
54
+ type: 'reject';
45
55
  };
56
+ /**
57
+ * Computes the formatted value and cursor position for a paste event without mutating
58
+ * the input or the event. The caller owns `preventDefault()` and the DOM write.
59
+ */
60
+ export declare function handleOnPasteNumoraInput(e: ClipboardEvent, decimalMaxLength: number, formattingOptions?: FormattingOptions): PasteResult;
@@ -9,32 +9,5 @@
9
9
  * @param pattern - The regex pattern string
10
10
  * @param flags - Optional regex flags (default: 'g')
11
11
  * @returns A cached RegExp object
12
- *
13
- * @example
14
- * // Instead of: new RegExp(escapeRegExp(separator), 'g')
15
- * getCachedRegex(escapeRegExp(separator), 'g')
16
12
  */
17
13
  export declare function getCachedRegex(pattern: string, flags?: string): RegExp;
18
- /**
19
- * Gets a cached RegExp for a separator character.
20
- * Handles escaping of special regex characters automatically.
21
- *
22
- * @param separator - The separator character to match
23
- * @param flags - Optional regex flags (default: 'g')
24
- * @returns A cached RegExp object that matches the separator
25
- *
26
- * @example
27
- * getCachedSeparatorRegex(',') // Returns cached /,/g
28
- * getCachedSeparatorRegex('.') // Returns cached /\./g (escaped)
29
- */
30
- export declare function getCachedSeparatorRegex(separator: string, flags?: string): RegExp;
31
- /**
32
- * Clears the regex cache.
33
- * Useful for testing or when separator configuration changes significantly.
34
- */
35
- export declare function clearRegexCache(): void;
36
- /**
37
- * Gets the current size of the regex cache.
38
- * Useful for debugging and monitoring.
39
- */
40
- export declare function getRegexCacheSize(): number;
@@ -0,0 +1,32 @@
1
+ import type { FormattingOptions } from '@/types';
2
+ export interface SetNumoraInputValueOptions {
3
+ /** Maximum number of decimal places. Defaults to `DEFAULT_DECIMAL_MAX_LENGTH`. */
4
+ maxDecimals?: number;
5
+ /** Formatting options (separators, locale, etc.). */
6
+ formattingOptions?: FormattingOptions;
7
+ /**
8
+ * When true (default), routes the write through `setRangeText` so the browser's
9
+ * undo/redo history stays intact. Set to false only when the new value should *replace*
10
+ * the entire undo history (e.g. form reset).
11
+ */
12
+ undoable?: boolean;
13
+ /**
14
+ * When true (default), dispatches a synthetic `input` event after the write so React's
15
+ * `_valueTracker` and other listeners stay in sync.
16
+ */
17
+ dispatchEvent?: boolean;
18
+ }
19
+ /**
20
+ * Programmatically sets the value of a Numora-managed `<input>` element.
21
+ *
22
+ * Use this when you have a direct DOM reference (e.g. `ref.current` in React) and want
23
+ * to apply a value without going through React's controlled-state machinery. The helper
24
+ * formats the value through the same pipeline used by typing, preserves the undo stack
25
+ * by default, and dispatches a synthetic `input` event so listeners see the change.
26
+ *
27
+ * @returns The formatted display string and the raw numeric string actually written.
28
+ */
29
+ export declare function setNumoraInputValue(el: HTMLInputElement, value: string, options?: SetNumoraInputValueOptions): {
30
+ formatted: string;
31
+ raw: string;
32
+ };
@@ -9,6 +9,9 @@ export interface NumoraInputValidationOptions {
9
9
  enableCompactNotation?: boolean;
10
10
  enableNegative?: boolean;
11
11
  enableLeadingZeros?: boolean;
12
+ autoAddLeadingZero?: boolean;
13
+ maxLength?: number;
14
+ isAllowed?: (rawValue: string) => boolean;
12
15
  rawValueMode?: boolean;
13
16
  onChange?: (value: string) => void;
14
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numora",
3
- "version": "3.5.0",
3
+ "version": "4.0.0",
4
4
  "description": "Framework-agnostic numeric input library for DeFi and financial apps",
5
5
  "homepage": "https://numora.xyz/",
6
6
  "main": "dist/index.js",