react-bootstrap-plugins 2.3.0 → 2.4.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/README.md +8 -3
- package/dist/DatePicker.cjs +1 -1
- package/dist/DatePicker.d.cts +2 -0
- package/dist/DatePicker.d.ts +2 -0
- package/dist/DatePicker.js +1 -1
- package/dist/chunk-LWCY2GIT.js +2 -0
- package/dist/chunk-ZOXIZM63.cjs +2 -0
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +76 -1
- package/dist/index.d.ts +76 -1
- package/dist/index.js +2 -2
- package/docs/DATEPICKER.md +19 -0
- package/docs/INPUTCURRENCY.md +180 -0
- package/package.json +19 -4
- package/dist/chunk-GCPYN7WB.js +0 -2
- package/dist/chunk-R5OO66VE.cjs +0 -2
package/dist/index.d.cts
CHANGED
|
@@ -5,4 +5,79 @@ export { TableLoading, TableLoadingProps } from './TableLoading.cjs';
|
|
|
5
5
|
export { AutoTextarea, AutoTextareaProps } from './AutoTextarea.cjs';
|
|
6
6
|
export { NavPill, NavPills, NavPillsProps } from './NavPills.cjs';
|
|
7
7
|
export { AutoDisplay, AutoDisplayProps } from './AutoDisplay.cjs';
|
|
8
|
-
import 'react';
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
|
|
10
|
+
interface InputCurrencyProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
11
|
+
/**
|
|
12
|
+
* Numeric value to display. Accepts `number` or `string` (the component
|
|
13
|
+
* coerces to `Number` internally). Pass `undefined` / `null` / `''` for
|
|
14
|
+
* an empty field.
|
|
15
|
+
*/
|
|
16
|
+
value?: number | string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Called with a synthetic input change event. `e.target.value` is
|
|
19
|
+
* replaced by the parsed numeric value — a `number` when the input
|
|
20
|
+
* holds a valid figure, or `''` when the field is cleared.
|
|
21
|
+
* `e.target.name` is preserved so the parent can identify the field.
|
|
22
|
+
*/
|
|
23
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
24
|
+
/** ISO 4217 currency code (default `'UGX'`) */
|
|
25
|
+
currency?: string;
|
|
26
|
+
/** BCP 47 locale tag for formatting (default `'en-UG'`) */
|
|
27
|
+
locale?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Number of decimal places.
|
|
30
|
+
* UGX = 0, USD = 2, JPY = 0, etc. (default `0`)
|
|
31
|
+
*/
|
|
32
|
+
decimals?: number;
|
|
33
|
+
/**
|
|
34
|
+
* When `true`, formatting omits the currency symbol and outputs a plain
|
|
35
|
+
* locale-formatted number (e.g. `'150,000'` instead of `'UGX 150,000'`).
|
|
36
|
+
* Useful for non-monetary numeric inputs that still benefit from
|
|
37
|
+
* thousand-separator formatting.
|
|
38
|
+
*/
|
|
39
|
+
plain?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Controlled currency input for financial forms.
|
|
43
|
+
*
|
|
44
|
+
* **Data contract**: numbers in, numbers out. The component manages a
|
|
45
|
+
* locale-formatted display internally — the consumer never sees commas
|
|
46
|
+
* or currency symbols in its state.
|
|
47
|
+
*
|
|
48
|
+
* **Editing UX**: while the field is focused, the raw number is shown so
|
|
49
|
+
* the user can type without commas / symbols fighting their keystrokes.
|
|
50
|
+
* On blur (or when the external `value` prop changes from above), the
|
|
51
|
+
* display snaps back to the locale-formatted string.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // UGX — zero decimal places, symbol shown
|
|
55
|
+
* <InputCurrency
|
|
56
|
+
* value={150000}
|
|
57
|
+
* name="fee"
|
|
58
|
+
* onChange={(e) => setFee(e.target.value)}
|
|
59
|
+
* />
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // USD with cents
|
|
63
|
+
* <InputCurrency
|
|
64
|
+
* value={99.99}
|
|
65
|
+
* currency="USD"
|
|
66
|
+
* locale="en-US"
|
|
67
|
+
* decimals={2}
|
|
68
|
+
* name="price"
|
|
69
|
+
* onChange={(e) => setPrice(e.target.value)}
|
|
70
|
+
* />
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Plain locale number — no currency symbol
|
|
74
|
+
* <InputCurrency
|
|
75
|
+
* value={50000}
|
|
76
|
+
* plain
|
|
77
|
+
* name="count"
|
|
78
|
+
* onChange={(e) => setCount(e.target.value)}
|
|
79
|
+
* />
|
|
80
|
+
*/
|
|
81
|
+
declare const InputCurrency: React.ForwardRefExoticComponent<InputCurrencyProps & React.RefAttributes<HTMLInputElement>>;
|
|
82
|
+
|
|
83
|
+
export { InputCurrency, type InputCurrencyProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,79 @@ export { TableLoading, TableLoadingProps } from './TableLoading.js';
|
|
|
5
5
|
export { AutoTextarea, AutoTextareaProps } from './AutoTextarea.js';
|
|
6
6
|
export { NavPill, NavPills, NavPillsProps } from './NavPills.js';
|
|
7
7
|
export { AutoDisplay, AutoDisplayProps } from './AutoDisplay.js';
|
|
8
|
-
import 'react';
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
|
|
10
|
+
interface InputCurrencyProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
|
|
11
|
+
/**
|
|
12
|
+
* Numeric value to display. Accepts `number` or `string` (the component
|
|
13
|
+
* coerces to `Number` internally). Pass `undefined` / `null` / `''` for
|
|
14
|
+
* an empty field.
|
|
15
|
+
*/
|
|
16
|
+
value?: number | string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Called with a synthetic input change event. `e.target.value` is
|
|
19
|
+
* replaced by the parsed numeric value — a `number` when the input
|
|
20
|
+
* holds a valid figure, or `''` when the field is cleared.
|
|
21
|
+
* `e.target.name` is preserved so the parent can identify the field.
|
|
22
|
+
*/
|
|
23
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
24
|
+
/** ISO 4217 currency code (default `'UGX'`) */
|
|
25
|
+
currency?: string;
|
|
26
|
+
/** BCP 47 locale tag for formatting (default `'en-UG'`) */
|
|
27
|
+
locale?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Number of decimal places.
|
|
30
|
+
* UGX = 0, USD = 2, JPY = 0, etc. (default `0`)
|
|
31
|
+
*/
|
|
32
|
+
decimals?: number;
|
|
33
|
+
/**
|
|
34
|
+
* When `true`, formatting omits the currency symbol and outputs a plain
|
|
35
|
+
* locale-formatted number (e.g. `'150,000'` instead of `'UGX 150,000'`).
|
|
36
|
+
* Useful for non-monetary numeric inputs that still benefit from
|
|
37
|
+
* thousand-separator formatting.
|
|
38
|
+
*/
|
|
39
|
+
plain?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Controlled currency input for financial forms.
|
|
43
|
+
*
|
|
44
|
+
* **Data contract**: numbers in, numbers out. The component manages a
|
|
45
|
+
* locale-formatted display internally — the consumer never sees commas
|
|
46
|
+
* or currency symbols in its state.
|
|
47
|
+
*
|
|
48
|
+
* **Editing UX**: while the field is focused, the raw number is shown so
|
|
49
|
+
* the user can type without commas / symbols fighting their keystrokes.
|
|
50
|
+
* On blur (or when the external `value` prop changes from above), the
|
|
51
|
+
* display snaps back to the locale-formatted string.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* // UGX — zero decimal places, symbol shown
|
|
55
|
+
* <InputCurrency
|
|
56
|
+
* value={150000}
|
|
57
|
+
* name="fee"
|
|
58
|
+
* onChange={(e) => setFee(e.target.value)}
|
|
59
|
+
* />
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // USD with cents
|
|
63
|
+
* <InputCurrency
|
|
64
|
+
* value={99.99}
|
|
65
|
+
* currency="USD"
|
|
66
|
+
* locale="en-US"
|
|
67
|
+
* decimals={2}
|
|
68
|
+
* name="price"
|
|
69
|
+
* onChange={(e) => setPrice(e.target.value)}
|
|
70
|
+
* />
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Plain locale number — no currency symbol
|
|
74
|
+
* <InputCurrency
|
|
75
|
+
* value={50000}
|
|
76
|
+
* plain
|
|
77
|
+
* name="count"
|
|
78
|
+
* onChange={(e) => setCount(e.target.value)}
|
|
79
|
+
* />
|
|
80
|
+
*/
|
|
81
|
+
declare const InputCurrency: React.ForwardRefExoticComponent<InputCurrencyProps & React.RefAttributes<HTMLInputElement>>;
|
|
82
|
+
|
|
83
|
+
export { InputCurrency, type InputCurrencyProps };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{a as DatePicker}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJpbmRleC5qcyJ9
|
|
1
|
+
export{a as DatePicker}from'./chunk-LWCY2GIT.js';export{a as SearchSelect}from'./chunk-ZCAQ7S2A.js';export{a as Label}from'./chunk-HYB5IGJK.js';export{a as TableLoading}from'./chunk-7LXLWNUR.js';export{a as AutoTextarea}from'./chunk-KKWFIJKN.js';export{a as NavPills}from'./chunk-KVUHNUBG.js';import {a}from'./chunk-RR7TBRGI.js';export{a as AutoDisplay}from'./chunk-2UX7JYM3.js';import*as n from'react';import {jsx}from'react/jsx-runtime';var y=n.forwardRef(({value:r,onChange:b,className:h,name:p,id:C,disabled:P=false,readOnly:I=false,placeholder:N,currency:i="UGX",locale:c="en-UG",decimals:a$1=0,plain:m=false,onBlur:R,onFocus:L,...D},T)=>{let s=n.useCallback(e=>{if(e==null||e==="")return "";let t=Number(e);if(Number.isNaN(t))return "";let o=a$1>0?{minimumFractionDigits:a$1,maximumFractionDigits:a$1}:{minimumFractionDigits:0,maximumFractionDigits:0};return m?t.toLocaleString(c,o):t.toLocaleString(c,{style:"currency",currency:i,...o})},[i,c,a$1,m]),l=n.useCallback(e=>{if(!e)return "";let t=e.replace(/[^0-9.\-]/g,"");if(t==="-"||t===""||t===".")return "";let o=Number(t);return Number.isNaN(o)?"":a$1===0?Math.round(o):o},[a$1]),[f,g]=n.useState(false),[E,u]=n.useState(()=>s(r)),d=n.useRef(r);return n.useEffect(()=>{!f&&r!==d.current&&u(s(r)),d.current=r;},[r,f,s]),jsx("input",{ref:T,type:"text",id:C??p,name:p,value:E,onChange:e=>{let t=e.target.value;u(t);let o=l(t);e.target.value=o,b?.(e);},onFocus:e=>{g(true),r!=null&&r!==""&&u(String(r)),L?.(e);},onBlur:e=>{g(false);let t=l(e.target.value);u(s(t)),R?.(e);},disabled:P,readOnly:I,placeholder:N,inputMode:"decimal",autoComplete:"off",className:a("form-control",h),...D})});y.displayName="InputCurrency";export{y as InputCurrency};//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21wb25lbnRzL0lucHV0Q3VycmVuY3kudHN4Il0sIm5hbWVzIjpbIklucHV0Q3VycmVuY3kiLCJ2YWx1ZSIsIm9uQ2hhbmdlIiwiY2xhc3NOYW1lIiwibmFtZSIsImlkIiwiZGlzYWJsZWQiLCJyZWFkT25seSIsInBsYWNlaG9sZGVyIiwiY3VycmVuY3kiLCJsb2NhbGUiLCJkZWNpbWFscyIsInBsYWluIiwib25CbHVyIiwib25Gb2N1cyIsInJlc3QiLCJyZWYiLCJmb3JtYXREaXNwbGF5IiwidmFsIiwibnVtIiwiZnJhY3Rpb25EaWdpdHMiLCJwYXJzZU51bWVyaWMiLCJyYXciLCJjbGVhbmVkIiwiZm9jdXNlZCIsInNldEZvY3VzZWQiLCJpbm5lciIsInNldElubmVyIiwicHJldlZhbHVlUmVmIiwianN4IiwibnVtZXJpYyIsImNuIl0sIm1hcHBpbmdzIjoidWJBb0ZBLElBQU1BLENBQUFBLENBQXNCLENBQUEsQ0FBQSxVQUFBLENBQzFCLENBQ0UsQ0FDRSxLQUFBLENBQUFDLENBQUFBLENBQ0EsUUFBQSxDQUFBQyxDQUFBQSxDQUNBLFVBQUFDLENBQUFBLENBQ0EsSUFBQSxDQUFBQyxDQUFBQSxDQUNBLEVBQUEsQ0FBQUMsRUFDQSxRQUFBLENBQUFDLENBQUFBLENBQVcsS0FBQSxDQUNYLFFBQUEsQ0FBQUMsRUFBVyxLQUFBLENBQ1gsV0FBQSxDQUFBQyxDQUFBQSxDQUNBLFFBQUEsQ0FBQUMsRUFBVyxLQUFBLENBQ1gsTUFBQSxDQUFBQyxDQUFBQSxDQUFTLE9BQUEsQ0FDVCxTQUFBQyxHQUFBQSxDQUFXLENBQUEsQ0FDWCxLQUFBLENBQUFDLENBQUFBLENBQVEsS0FBQSxDQUNSLE1BQUEsQ0FBQUMsQ0FBQUEsQ0FDQSxPQUFBLENBQUFDLEVBQ0EsR0FBR0MsQ0FDTCxDQUFBLENBQ0FDLENBQUFBLEdBQ0csQ0FPSCxJQUFNQyxDQUFBQSxDQUFzQixDQUFBLENBQUEsV0FBQSxDQUN6QkMsQ0FBQUEsRUFBb0QsQ0FDbkQsR0FBSUEsQ0FB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QU8xQixDQUFLLENBQUMsQ0FBQSxDQUV4QmEsQ0FBQUEsR0FBVSxDQUFDLEVBQ2IsQ0FBQSxDQXFCSSxNQUFBLENBbkJnQixDQUFBLEVBQTBDLENBQzVEVyxFQUFXLEtBQUssQ0FBQSxDQUVoQixJQUFNSyxDQUFBQSxDQUFVVCxDQUFBQSxDQUFhLENBQUEsQ0FBRSxNQUFBLENBQU8sS0FBSyxFQUMzQ00sQ0FBQUEsQ0FBU1YsQ0FBQUEsQ0FBY2EsQ0FBTyxDQUFDLEVBQy9CakIsQ0FBQUEsR0FBUyxDQUFDLEVBQ1osQ0FBQSxDQWNJLFNBQVVQLENBQUFBLENBQ1YsUUFBQSxDQUFVQyxDQUFBQSxDQUNWLFdBQUEsQ0FBYUMsRUFDYixTQUFBLENBQVUsU0FBQSxDQUNWLFlBQUEsQ0FBYSxLQUFBLENBQ2IsVUFBV3VCLENBQUFBLENBQUcsY0FBQSxDQUFnQjVCLENBQVMsQ0FBQSxDQUN0QyxHQUFHWSxDQUFBQSxDQUNOLENBRUosQ0FDRixFQUVBZixFQUFjLFdBQUEsQ0FBYyxlQUFBIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBjbiB9IGZyb20gJy4uL2xpYi9jbi5qcydcblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4vKiAgVHlwZXMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuZXhwb3J0IGludGVyZmFjZSBJbnB1dEN1cnJlbmN5UHJvcHNcbiAgZXh0ZW5kcyBPbWl0PFJlYWN0LklucHV0SFRNTEF0dHJpYnV0ZXM8SFRNTElucHV0RWxlbWVudD4sICd2YWx1ZScgfCAnb25DaGFuZ2UnIHwgJ3R5cGUnPiB7XG4gIC8qKlxuICAgKiBOdW1lcmljIHZhbHVlIHRvIGRpc3BsYXkuIEFjY2VwdHMgYG51bWJlcmAgb3IgYHN0cmluZ2AgKHRoZSBjb21wb25lbnRcbiAgICogY29lcmNlcyB0byBgTnVtYmVyYCBpbnRlcm5hbGx5KS4gUGFzcyBgdW5kZWZpbmVkYCAvIGBudWxsYCAvIGAnJ2AgZm9yXG4gICAqIGFuIGVtcHR5IGZpZWxkLlxuICAgKi9cbiAgdmFsdWU/OiBudW1iZXIgfCBzdHJpbmcgfCBudWxsXG4gIC8qKlxuICAgKiBDYWxsZWQgd2l0aCBhIHN5bnRoZXRpYyBpbnB1dCBjaGFuZ2UgZXZlbnQuIGBlLnRhcmdldC52YWx1ZWAgaXNcbiAgICogcmVwbGFjZWQgYnkgdGhlIHBhcnNlZCBudW1lcmljIHZhbHVlIOKAlCBhIGBudW1iZXJgIHdoZW4gdGhlIGlucHV0XG4gICAqIGhvbGRzIGEgdmFsaWQgZmlndXJlLCBvciBgJydgIHdoZW4gdGhlIGZpZWxkIGlzIGNsZWFyZWQuXG4gICAqIGBlLnRhcmdldC5uYW1lYCBpcyBwcmVzZXJ2ZWQgc28gdGhlIHBhcmVudCBjYW4gaWRlbnRpZnkgdGhlIGZpZWxkLlxuICAgKi9cbiAgb25DaGFuZ2U/OiAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHZvaWRcbiAgLyoqIElTTyA0MjE3IGN1cnJlbmN5IGNvZGUgKGRlZmF1bHQgYCdVR1gnYCkgKi9cbiAgY3VycmVuY3k/OiBzdHJpbmdcbiAgLyoqIEJDUCA0NyBsb2NhbGUgdGFnIGZvciBmb3JtYXR0aW5nIChkZWZhdWx0IGAnZW4tVUcnYCkgKi9cbiAgbG9jYWxlPzogc3RyaW5nXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMuXG4gICAqIFVHWCA9IDAsIFVTRCA9IDIsIEpQWSA9IDAsIGV0Yy4gKGRlZmF1bHQgYDBgKVxuICAgKi9cbiAgZGVjaW1hbHM/OiBudW1iZXJcbiAgLyoqXG4gICAqIFdoZW4gYHRydWVgLCBmb3JtYXR0aW5nIG9taXRzIHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIG91dHB1dHMgYSBwbGFpblxuICAgKiBsb2NhbGUtZm9ybWF0dGVkIG51bWJlciAoZS5nLiBgJzE1MCwwMDAnYCBpbnN0ZWFkIG9mIGAnVUdYIDE1MCwwMDAnYCkuXG4gICAqIFVzZWZ1bCBmb3Igbm9uLW1vbmV0YXJ5IG51bWVyaWMgaW5wdXRzIHRoYXQgc3RpbGwgYmVuZWZpdCBmcm9tXG4gICAqIHRob3VzYW5kLXNlcGFyYXRvciBmb3JtYXR0aW5nLlxuICAgKi9cbiAgcGxhaW4/OiBib29sZWFuXG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuLyogIElucHV0Q3VycmVuY3kgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKlxuICogQ29udHJvbGxlZCBjdXJyZW5jeSBpbnB1dCBmb3IgZmluYW5jaWFsIGZvcm1zLlxuICpcbiAqICoqRGF0YSBjb250cmFjdCoqOiBudW1iZXJzIGluLCBudW1iZXJzIG91dC4gVGhlIGNvbXBvbmVudCBtYW5hZ2VzIGFcbiAqIGxvY2FsZS1mb3JtYXR0ZWQgZGlzcGxheSBpbnRlcm5hbGx5IOKAlCB0aGUgY29uc3VtZXIgbmV2ZXIgc2VlcyBjb21tYXNcbiAqIG9yIGN1cnJlbmN5IHN5bWJvbHMgaW4gaXRzIHN0YXRlLlxuICpcbiAqICoqRWRpdGluZyBVWCoqOiB3aGlsZSB0aGUgZmllbGQgaXMgZm9jdXNlZCwgdGhlIHJhdyBudW1iZXIgaXMgc2hvd24gc29cbiAqIHRoZSB1c2VyIGNhbiB0eXBlIHdpdGhvdXQgY29tbWFzIC8gc3ltYm9scyBmaWdodGluZyB0aGVpciBrZXlzdHJva2VzLlxuICogT24gYmx1ciAob3Igd2hlbiB0aGUgZXh0ZXJuYWwgYHZhbHVlYCBwcm9wIGNoYW5nZXMgZnJvbSBhYm92ZSksIHRoZVxuICogZGlzcGxheSBzbmFwcyBiYWNrIHRvIHRoZSBsb2NhbGUtZm9ybWF0dGVkIHN0cmluZy5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gVUdYIOKAlCB6ZXJvIGRlY2ltYWwgcGxhY2VzLCBzeW1ib2wgc2hvd25cbiAqIDxJbnB1dEN1cnJlbmN5XG4gKiAgIHZhbHVlPXsxNTAwMDB9XG4gKiAgIG5hbWU9XCJmZWVcIlxuICogICBvbkNoYW5nZT17KGUpID0+IHNldEZlZShlLnRhcmdldC52YWx1ZSl9XG4gKiAvPlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBVU0Qgd2l0aCBjZW50c1xuICogPElucHV0Q3VycmVuY3lcbiAqICAgdmFsdWU9ezk5Ljk5fVxuICogICBjdXJyZW5jeT1cIlVTRFwiXG4gKiAgIGxvY2FsZT1cImVuLVVTXCJcbiAqICAgZGVjaW1hbHM9ezJ9XG4gKiAgIG5hbWU9XCJwcmljZVwiXG4gKiAgIG9uQ2hhbmdlPXsoZSkgPT4gc2V0UHJpY2UoZS50YXJnZXQudmFsdWUpfVxuICogLz5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gUGxhaW4gbG9jYWxlIG51bWJlciDigJQgbm8gY3VycmVuY3kgc3ltYm9sXG4gKiA8SW5wdXRDdXJyZW5jeVxuICogICB2YWx1ZT17NTAwMDB9XG4gKiAgIHBsYWluXG4gKiAgIG5hbWU9XCJjb3VudFwiXG4gKiAgIG9uQ2hhbmdlPXsoZSkgPT4gc2V0Q291bnQoZS50YXJnZXQudmFsdWUpfVxuICogLz5cbiAqL1xuY29uc3QgSW5wdXRDdXJyZW5jeSA9IFJlYWN0LmZvcndhcmRSZWY8SFRNTElucHV0RWxlbWVudCwgSW5wdXRDdXJyZW5jeVByb3BzPihcbiAgKFxuICAgIHtcbiAgICAgIHZhbHVlLFxuICAgICAgb25DaGFuZ2UsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBuYW1lLFxuICAgICAgaWQsXG4gICAgICBkaXNhYmxlZCA9IGZhbHNlLFxuICAgICAgcmVhZE9ubHkgPSBmYWxzZSxcbiAgICAgIHBsYWNlaG9sZGVyLFxuICAgICAgY3VycmVuY3kgPSAnVUdYJyxcbiAgICAgIGxvY2FsZSA9ICdlbi1VRycsXG4gICAgICBkZWNpbWFscyA9IDAsXG4gICAgICBwbGFpbiA9IGZhbHNlLFxuICAgICAgb25CbHVyLFxuICAgICAgb25Gb2N1cyxcbiAgICAgIC4uLnJlc3RcbiAgICB9LFxuICAgIHJlZixcbiAgKSA9PiB7XG4gICAgLyogLS0tLSBoZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgICAvKipcbiAgICAgKiBOdW1iZXIg4oaSIGxvY2FsZS1mb3JtYXR0ZWQgZGlzcGxheSBzdHJpbmcuXG4gICAgICogUmV0dXJucyBgJydgIGZvciBudWxsIC8gdW5kZWZpbmVkIC8gTmFOIHNvIHRoZSBpbnB1dCBzaG93cyB0aGUgcGxhY2Vob2xkZXIuXG4gICAgICovXG4gICAgY29uc3QgZm9ybWF0RGlzcGxheSA9IFJlYWN0LnVzZUNhbGxiYWNrKFxuICAgICAgKHZhbDogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyA9PiB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgdmFsID09PSAnJykgcmV0dXJuICcnXG4gICAgICAgIGNvbnN0IG51bSA9IE51bWJlcih2YWwpXG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4obnVtKSkgcmV0dXJuICcnXG5cbiAgICAgICAgY29uc3QgZnJhY3Rpb25EaWdpdHM6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyA9XG4gICAgICAgICAgZGVjaW1hbHMgPiAwXG4gICAgICAgICAgICA/IHsgbWluaW11bUZyYWN0aW9uRGlnaXRzOiBkZWNpbWFscywgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBkZWNpbWFscyB9XG4gICAgICAgICAgICA6IHsgbWluaW11bUZyYWN0aW9uRGlnaXRzOiAwLCBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDAgfVxuXG4gICAgICAgIHJldHVybiBwbGFpblxuICAgICAgICAgID8gbnVtLnRvTG9jYWxlU3RyaW5nKGxvY2FsZSwgZnJhY3Rpb25EaWdpdHMpXG4gICAgICAgICAgOiBudW0udG9Mb2NhbGVTdHJpbmcobG9jYWxlLCB7IHN0eWxlOiAnY3VycmVuY3knLCBjdXJyZW5jeSwgLi4uZnJhY3Rpb25EaWdpdHMgfSlcbiAgICAgIH0sXG4gICAgICBbY3VycmVuY3ksIGxvY2FsZSwgZGVjaW1hbHMsIHBsYWluXSxcbiAgICApXG5cbiAgICAvKipcbiAgICAgKiBSYXcgaW5wdXQgc3RyaW5nIOKGkiBudW1lcmljIHZhbHVlIChgbnVtYmVyIHwgJydgKS5cbiAgICAgKiBTdHJpcHMgZm9ybWF0dGluZyBjaGFyYWN0ZXJzLCBoYW5kbGVzIGVkZ2UgY2FzZXMgbGlrZSBsb25lIGBcIi5cImAgb3IgYFwiLVwiYC5cbiAgICAgKi9cbiAgICBjb25zdCBwYXJzZU51bWVyaWMgPSBSZWFjdC51c2VDYWxsYmFjayhcbiAgICAgIChyYXc6IHN0cmluZyk6IG51bWJlciB8ICcnID0+IHtcbiAgICAgICAgaWYgKCFyYXcpIHJldHVybiAnJ1xuICAgICAgICAvLyBSZW1vdmUgZXZlcnl0aGluZyBleGNlcHQgZGlnaXRzLCBkZWNpbWFsIHBvaW50LCBhbmQgbGVhZGluZyBtaW51c1xuICAgICAgICBjb25zdCBjbGVhbmVkID0gcmF3LnJlcGxhY2UoL1teMC05LlxcLV0vZywgJycpXG4gICAgICAgIC8vIEd1YXJkIGFnYWluc3QgXCItXCIgYWxvbmVcbiAgICAgICAgaWYgKGNsZWFuZWQgPT09ICctJyB8fCBjbGVhbmVkID09PSAnJykgcmV0dXJuICcnXG4gICAgICAgIC8vIEd1YXJkIGFnYWluc3QgbG9uZSBcIi5cIlxuICAgICAgICBpZiAoY2xlYW5lZCA9PT0gJy4nKSByZXR1cm4gJydcbiAgICAgICAgY29uc3QgbnVtID0gTnVtYmVyKGNsZWFuZWQpXG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4obnVtKSkgcmV0dXJuICcnXG4gICAgICAgIHJldHVybiBkZWNpbWFscyA9PT0gMCA/IE1hdGgucm91bmQobnVtKSA6IG51bVxuICAgICAgfSxcbiAgICAgIFtkZWNpbWFsc10sXG4gICAgKVxuXG4gICAgLyogLS0tLSBkZXJpdmVkIHN0YXRlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgICBjb25zdCBbZm9jdXNlZCwgc2V0Rm9jdXNlZF0gPSBSZWFjdC51c2VTdGF0ZShmYWxzZSlcblxuICAgIC8vIFRoZSBzdHJpbmcgc2hvd24gaW5zaWRlIHRoZSBgPGlucHV0PmAuIFdoaWxlIHRoZSB1c2VyIGlzIGVkaXRpbmcgd2Ugc2hvd1xuICAgIC8vIHRoZSByYXcgbnVtYmVyIHNvIGNvbW1hcyAvIHN5bWJvbHMgZG9uJ3QgZmlnaHQgdGhlaXIga2V5c3Ryb2tlcy4gV2hlblxuICAgIC8vIHRoZXkgbGVhdmUgdGhlIGZpZWxkIChvciB0aGUgZXh0ZXJuYWwgdmFsdWUgY2hhbmdlcyBmcm9tIGFib3ZlKSB3ZVxuICAgIC8vIHJlZm9ybWF0LlxuICAgIGNvbnN0IFtpbm5lciwgc2V0SW5uZXJdID0gUmVhY3QudXNlU3RhdGU8c3RyaW5nPigoKSA9PiBmb3JtYXREaXNwbGF5KHZhbHVlKSlcblxuICAgIC8vIEtlZXAgdGhlIGRpc3BsYXkgaW4gc3luYyB3aGVuIHRoZSBwYXJlbnQgcHVzaGVzIGEgbmV3IHZhbHVlIHdoaWxlIHRoZVxuICAgIC8vIGZpZWxkIGlzIE5PVCBmb2N1c2VkIChlLmcuIGFmdGVyIGEgc3VjY2Vzc2Z1bCBBUEkgY2FsbCB0aGF0IHJlc2V0cyB0aGVcbiAgICAvLyBmb3JtLCBvciBzd2l0Y2hpbmcgYmV0d2VlbiByZWNvcmRzKS5cbiAgICBjb25zdCBwcmV2VmFsdWVSZWYgPSBSZWFjdC51c2VSZWYodmFsdWUpXG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgIGlmICghZm9jdXNlZCAmJiB2YWx1ZSAhPT0gcHJldlZhbHVlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgc2V0SW5uZXIoZm9ybWF0RGlzcGxheSh2YWx1ZSkpXG4gICAgICB9XG4gICAgICBwcmV2VmFsdWVSZWYuY3VycmVudCA9IHZhbHVlXG4gICAgfSwgW3ZhbHVlLCBmb2N1c2VkLCBmb3JtYXREaXNwbGF5XSlcblxuICAgIC8qIC0tLS0gZXZlbnQgaGFuZGxlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gICAgY29uc3QgaGFuZGxlQ2hhbmdlID0gKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgICBjb25zdCByYXcgPSBlLnRhcmdldC52YWx1ZVxuICAgICAgc2V0SW5uZXIocmF3KSAvLyBsZXQgdGhlIHVzZXIgc2VlIHdoYXQgdGhleSdyZSB0eXBpbmdcblxuICAgICAgY29uc3QgbnVtZXJpYyA9IHBhcnNlTnVtZXJpYyhyYXcpO1xuICAgICAgKGUudGFyZ2V0IGFzIHVua25vd24gYXMgeyB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIH0pLnZhbHVlID0gbnVtZXJpY1xuICAgICAgb25DaGFuZ2U/LihlKVxuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZUZvY3VzID0gKGU6IFJlYWN0LkZvY3VzRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICAgIHNldEZvY3VzZWQodHJ1ZSlcbiAgICAgIC8vIFN3aXRjaCBkaXNwbGF5IHRvIHJhdyBudW1iZXIgc28gdGhlIHVzZXIgY2FuIGVkaXQgd2l0aG91dCBmcmljdGlvblxuICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgIHNldElubmVyKFN0cmluZyh2YWx1ZSkpXG4gICAgICB9XG4gICAgICBvbkZvY3VzPy4oZSlcbiAgICB9XG5cbiAgICBjb25zdCBoYW5kbGVCbHVyID0gKGU6IFJlYWN0LkZvY3VzRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICAgIHNldEZvY3VzZWQoZmFsc2UpXG4gICAgICAvLyBSZS1mb3JtYXQgYmVmb3JlIHRoZSB1c2VyIHNlZXMgdGhlIGZpZWxkIGFnYWluXG4gICAgICBjb25zdCBudW1lcmljID0gcGFyc2VOdW1lcmljKGUudGFyZ2V0LnZhbHVlKVxuICAgICAgc2V0SW5uZXIoZm9ybWF0RGlzcGxheShudW1lcmljKSlcbiAgICAgIG9uQmx1cj8uKGUpXG4gICAgfVxuXG4gICAgLyogLS0tLSByZW5kZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgICByZXR1cm4gKFxuICAgICAgPGlucHV0XG4gICAgICAgIHJlZj17cmVmfVxuICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgIGlkPXtpZCA/PyBuYW1lfVxuICAgICAgICBuYW1lPXtuYW1lfVxuICAgICAgICB2YWx1ZT17aW5uZXJ9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uRm9jdXM9e2hhbmRsZUZvY3VzfVxuICAgICAgICBvbkJsdXI9e2hhbmRsZUJsdXJ9XG4gICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgcmVhZE9ubHk9e3JlYWRPbmx5fVxuICAgICAgICBwbGFjZWhvbGRlcj17cGxhY2Vob2xkZXJ9XG4gICAgICAgIGlucHV0TW9kZT1cImRlY2ltYWxcIlxuICAgICAgICBhdXRvQ29tcGxldGU9XCJvZmZcIlxuICAgICAgICBjbGFzc05hbWU9e2NuKCdmb3JtLWNvbnRyb2wnLCBjbGFzc05hbWUpfVxuICAgICAgICB7Li4ucmVzdH1cbiAgICAgIC8+XG4gICAgKVxuICB9LFxuKVxuXG5JbnB1dEN1cnJlbmN5LmRpc3BsYXlOYW1lID0gJ0lucHV0Q3VycmVuY3knXG5cbmV4cG9ydCB7IElucHV0Q3VycmVuY3kgfVxuZXhwb3J0IGRlZmF1bHQgSW5wdXRDdXJyZW5jeVxuIl19
|
package/docs/DATEPICKER.md
CHANGED
|
@@ -49,6 +49,7 @@ function MyForm() {
|
|
|
49
49
|
| Prop | Type | Default | Description |
|
|
50
50
|
|---|---|---|---|
|
|
51
51
|
| `mode` | `'date'` \| `'time'` \| `'datetime'` | `'date'` | Picker mode |
|
|
52
|
+
| `calendar` | `boolean` | `false` | When `true`, renders the calendar inline without an input field or time picker. Ideal for embedding a date picker directly in a form or dashboard. |
|
|
52
53
|
| `value` | `Date` \| `string` \| `null` | — | Currently selected value |
|
|
53
54
|
| `selected` | `Date` \| `null` | — | Alias for `value` |
|
|
54
55
|
| `onChange` | `(e) => void` | — | Synthetic event; `e.target.value` is formatted string, `e.target.name` is the input name |
|
|
@@ -107,6 +108,24 @@ function MyForm() {
|
|
|
107
108
|
// e.target.value → "29/06/2026 02:30 PM"
|
|
108
109
|
```
|
|
109
110
|
|
|
111
|
+
### Inline Calendar mode
|
|
112
|
+
|
|
113
|
+
When `calendar` is `true`, the picker renders as an inline calendar card — no input field, no popover, no time picker. The calendar is always visible, making it ideal for dashboards, date-range selectors, or any layout where you want the calendar embedded directly in the page.
|
|
114
|
+
|
|
115
|
+
```jsx
|
|
116
|
+
<DatePicker
|
|
117
|
+
calendar
|
|
118
|
+
name="eventDate"
|
|
119
|
+
value={eventDate}
|
|
120
|
+
onChange={(e) => setEventDate(e.target.value)}
|
|
121
|
+
minDate={new Date()}
|
|
122
|
+
/>
|
|
123
|
+
// e.target.value → "2026-07-22"
|
|
124
|
+
// Renders as an inline card with the full calendar grid
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The component applies the `datepicker-calendar-inline` CSS class alongside `card`, `border`, and `shadow-sm` for the wrapper. Any `className` you pass is merged onto the wrapper div.
|
|
128
|
+
|
|
110
129
|
### Linked pickers (start date bounds end date)
|
|
111
130
|
|
|
112
131
|
`minDate`/`maxDate` accept the formatted string another picker emits, so linking two pickers needs no conversion:
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# InputCurrency
|
|
2
|
+
|
|
3
|
+
> Bootstrap 5 controlled currency input for financial forms. Numbers in, numbers out — the component manages locale-formatted display internally. Zero dependencies.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// Default import (recommended for single-component tree-shaking)
|
|
11
|
+
import InputCurrency from 'react-bootstrap-plugins/InputCurrency'
|
|
12
|
+
|
|
13
|
+
// Named import from individual entry point
|
|
14
|
+
import { InputCurrency } from 'react-bootstrap-plugins/InputCurrency'
|
|
15
|
+
|
|
16
|
+
// Barrel import
|
|
17
|
+
import { InputCurrency } from 'react-bootstrap-plugins'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Basic Usage
|
|
23
|
+
|
|
24
|
+
```jsx
|
|
25
|
+
import { useState } from 'react'
|
|
26
|
+
import { InputCurrency } from 'react-bootstrap-plugins'
|
|
27
|
+
|
|
28
|
+
function FeeForm() {
|
|
29
|
+
const [fee, setFee] = useState(150000)
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<InputCurrency
|
|
33
|
+
name="fee"
|
|
34
|
+
value={fee}
|
|
35
|
+
onChange={(e) => setFee(e.target.value)}
|
|
36
|
+
placeholder="Enter fee amount"
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The input displays `UGX 150,000` but the component state holds `150000` (a number). While focused, the raw number `150000` is shown for frictionless editing. On blur, it snaps back to `UGX 150,000`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Data Contract
|
|
47
|
+
|
|
48
|
+
| Direction | Type | Example |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `value` prop (in) | `number` | `150000` |
|
|
51
|
+
| `onChange` → `e.target.value` (out) | `number \| ''` | `150000` or `''` (when cleared) |
|
|
52
|
+
| Display (internal) | `string` | `"UGX 150,000"` |
|
|
53
|
+
|
|
54
|
+
The parent component never sees commas or currency symbols — it works entirely with numbers.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Editing UX
|
|
59
|
+
|
|
60
|
+
- **Focused**: raw number shown (`150000`) — no commas or symbols fighting keystrokes
|
|
61
|
+
- **Blurred**: locale-formatted currency (`UGX 150,000`) — clean, readable display
|
|
62
|
+
- **External value change**: if the parent pushes a new `value` while the field is not focused, the display updates immediately (e.g. after a successful API call that resets the form)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Currency & Locale
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
// UGX — zero decimal places (default)
|
|
70
|
+
<InputCurrency value={50000} name="tuition" onChange={handleChange} />
|
|
71
|
+
|
|
72
|
+
// USD with cents
|
|
73
|
+
<InputCurrency
|
|
74
|
+
value={99.99}
|
|
75
|
+
currency="USD"
|
|
76
|
+
locale="en-US"
|
|
77
|
+
decimals={2}
|
|
78
|
+
name="price"
|
|
79
|
+
onChange={handleChange}
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
// Kenyan Shillings
|
|
83
|
+
<InputCurrency
|
|
84
|
+
value={25000}
|
|
85
|
+
currency="KES"
|
|
86
|
+
locale="en-KE"
|
|
87
|
+
decimals={0}
|
|
88
|
+
name="fee"
|
|
89
|
+
onChange={handleChange}
|
|
90
|
+
/>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Plain Number Mode
|
|
96
|
+
|
|
97
|
+
When `plain` is `true`, formatting omits the currency symbol and outputs a plain locale-formatted number. Useful for non-monetary numeric inputs that still benefit from thousand-separator formatting:
|
|
98
|
+
|
|
99
|
+
```jsx
|
|
100
|
+
<InputCurrency
|
|
101
|
+
value={50000}
|
|
102
|
+
plain
|
|
103
|
+
name="studentCount"
|
|
104
|
+
onChange={(e) => setCount(e.target.value)}
|
|
105
|
+
placeholder="Number of students"
|
|
106
|
+
/>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Displays `150,000` instead of `UGX 150,000`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Props
|
|
114
|
+
|
|
115
|
+
Accepts all standard `<input>` props (except `value`, `onChange`, and `type`, which are managed internally), plus:
|
|
116
|
+
|
|
117
|
+
| Prop | Type | Default | Description |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| `value` | `number \| string \| null` | — | Numeric value to display. Pass `undefined`/`null`/`''` for an empty field |
|
|
120
|
+
| `onChange` | `(e: ChangeEvent) => void` | — | Called with a synthetic event where `e.target.value` is the parsed `number` (or `''` when cleared). `e.target.name` is preserved |
|
|
121
|
+
| `currency` | `string` | `'UGX'` | ISO 4217 currency code |
|
|
122
|
+
| `locale` | `string` | `'en-UG'` | BCP 47 locale tag for formatting |
|
|
123
|
+
| `decimals` | `number` | `0` | Number of decimal places. UGX/JYP = 0, USD/EUR = 2, etc. |
|
|
124
|
+
| `plain` | `boolean` | `false` | When `true`, omits the currency symbol and outputs a plain locale-formatted number |
|
|
125
|
+
| `name` | `string` | — | Input name attribute. Accessible in `onChange` via `e.target.name` |
|
|
126
|
+
| `id` | `string` | — | Input id attribute. Falls back to `name` if omitted |
|
|
127
|
+
| `className` | `string` | — | Additional classes merged with `form-control` |
|
|
128
|
+
| `placeholder` | `string` | — | Placeholder text shown when the field is empty |
|
|
129
|
+
| `disabled` | `boolean` | `false` | Disables the input |
|
|
130
|
+
| `readOnly` | `boolean` | `false` | Makes the input read-only |
|
|
131
|
+
| `autoComplete` | `string` | `'off'` | Defaults to `'off'` for financial inputs |
|
|
132
|
+
|
|
133
|
+
A `ref` is forwarded to the underlying `<input>` element.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Edge Cases Handled
|
|
138
|
+
|
|
139
|
+
| Input | Display | Value |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| Empty / cleared | Placeholder shown | `''` |
|
|
142
|
+
| `null` / `undefined` | Empty field | `''` |
|
|
143
|
+
| `"150000"` (string) | Formatted currency | `150000` (number) |
|
|
144
|
+
| `"-"` alone | Raw `-` shown while typing | `''` (not emitted) |
|
|
145
|
+
| `"."` alone | Raw `.` shown while typing | `''` (not emitted) |
|
|
146
|
+
| `"abc123"` | `123` while focused → formatted on blur | `123` |
|
|
147
|
+
| Letters only | Empty → formatted to `''` | `''` |
|
|
148
|
+
| Negative numbers | `-50000` → `UGX -50,000` | `-50000` |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Accessibility
|
|
153
|
+
|
|
154
|
+
- `inputMode="decimal"` — brings up the numeric keypad on mobile
|
|
155
|
+
- `type="text"` — avoids browser number-input quirks (spinners, locale-specific formatting)
|
|
156
|
+
- `autoComplete="off"` — prevents unwanted autofill on financial fields
|
|
157
|
+
- `id` falls back to `name` when omitted — always ensure a label association
|
|
158
|
+
- Ref forwarding for programmatic focus management
|
|
159
|
+
- All standard ARIA attributes spread through via `...rest`
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Dark Mode
|
|
164
|
+
|
|
165
|
+
Uses Bootstrap's `form-control` class, which adapts automatically. Set `data-bs-theme="dark"` on any parent element.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Bundle Size
|
|
170
|
+
|
|
171
|
+
~0.6 KB (min+gzip).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## See Also
|
|
176
|
+
|
|
177
|
+
- [AutoTextarea](./AUTOTEXTAREA.md) — Auto-resizing textarea
|
|
178
|
+
- [SearchSelect](./SEARCHSELECT.md) — Filterable, searchable select dropdown
|
|
179
|
+
- [Label](./LABEL.md) — Bootstrap-styled form label with required indicator
|
|
180
|
+
- [Main README](../README.md) — Package overview, installation, and general info
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-bootstrap-plugins",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Production-grade Bootstrap 5 UI plugins for React — DatePicker, SearchSelect, Label, TableLoading, and more. Zero runtime dependencies beyond React.",
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "Production-grade Bootstrap 5 UI plugins for React — DatePicker, SearchSelect, Label, TableLoading, InputCurrency, and more. Zero runtime dependencies beyond React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Tumwesigye Robert",
|
|
@@ -82,6 +82,16 @@
|
|
|
82
82
|
"default": "./dist/AutoDisplay.cjs"
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
|
+
"./InputCurrency": {
|
|
86
|
+
"import": {
|
|
87
|
+
"types": "./dist/InputCurrency.d.ts",
|
|
88
|
+
"default": "./dist/InputCurrency.js"
|
|
89
|
+
},
|
|
90
|
+
"require": {
|
|
91
|
+
"types": "./dist/InputCurrency.d.ts",
|
|
92
|
+
"default": "./dist/InputCurrency.cjs"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
85
95
|
"./NavPills": {
|
|
86
96
|
"import": {
|
|
87
97
|
"types": "./dist/NavPills.d.ts",
|
|
@@ -117,7 +127,7 @@
|
|
|
117
127
|
"prepublishOnly": "pnpm run build",
|
|
118
128
|
"lint": "echo 'Lint passed'",
|
|
119
129
|
"test": "echo 'Tests passed'",
|
|
120
|
-
"push
|
|
130
|
+
"push": "npm publish --no-git-checks"
|
|
121
131
|
},
|
|
122
132
|
"keywords": [
|
|
123
133
|
"react",
|
|
@@ -141,7 +151,12 @@
|
|
|
141
151
|
"react-bootstrap",
|
|
142
152
|
"form-controls",
|
|
143
153
|
"tree-shakeable",
|
|
144
|
-
"zero-dependencies"
|
|
154
|
+
"zero-dependencies",
|
|
155
|
+
"input-currency",
|
|
156
|
+
"currency-input",
|
|
157
|
+
"currency-formatter",
|
|
158
|
+
"number-input",
|
|
159
|
+
"financial-input"
|
|
145
160
|
],
|
|
146
161
|
"repository": {
|
|
147
162
|
"type": "git",
|