@thx/controls 17.3.5 → 17.3.6
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/esm/date/DatePicker/styles.css.js +7 -0
- package/dist/esm/date/DatePicker/styles.css.js.map +1 -0
- package/dist/esm/date/LocalDatePicker/LocalDatePicker.js +151 -0
- package/dist/esm/date/LocalDatePicker/LocalDatePicker.js.map +1 -0
- package/dist/esm/date/LocalDatePicker/MaskedDateInput.js +22 -0
- package/dist/esm/date/LocalDatePicker/MaskedDateInput.js.map +1 -0
- package/dist/esm/date/LocalMonthSelect/LocalMonthSelect.js +43 -0
- package/dist/esm/date/LocalMonthSelect/LocalMonthSelect.js.map +1 -0
- package/dist/esm/date/LocalTimePicker/LocalTimePicker.js +96 -0
- package/dist/esm/date/LocalTimePicker/LocalTimePicker.js.map +1 -0
- package/dist/esm/date/LocalTimePicker/MaskedTimeInput.js +22 -0
- package/dist/esm/date/LocalTimePicker/MaskedTimeInput.js.map +1 -0
- package/dist/esm/date/MonthDayPicker/MonthDayPicker.js +86 -0
- package/dist/esm/date/MonthDayPicker/MonthDayPicker.js.map +1 -0
- package/dist/esm/date/MonthYearPicker/MonthYearPicker.js +73 -0
- package/dist/esm/date/MonthYearPicker/MonthYearPicker.js.map +1 -0
- package/dist/esm/date/YearSelect/YearSelect.js +62 -0
- package/dist/esm/date/YearSelect/YearSelect.js.map +1 -0
- package/dist/esm/external/style-inject/dist/style-inject.es.js +29 -0
- package/dist/esm/external/style-inject/dist/style-inject.es.js.map +1 -0
- package/dist/esm/form/TForm/TForm.js +29 -0
- package/dist/esm/form/TForm/TForm.js.map +1 -0
- package/dist/esm/form/TForm/useTForm.js +90 -0
- package/dist/esm/form/TForm/useTForm.js.map +1 -0
- package/dist/esm/index.js +34 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/inputs/CreditCardInput/CreditCardInput.js +71 -0
- package/dist/esm/inputs/CreditCardInput/CreditCardInput.js.map +1 -0
- package/dist/esm/inputs/CreditCardInput/CreditCardNumberInput.js +76 -0
- package/dist/esm/inputs/CreditCardInput/CreditCardNumberInput.js.map +1 -0
- package/dist/esm/inputs/CreditCardInput/styles.css.js +7 -0
- package/dist/esm/inputs/CreditCardInput/styles.css.js.map +1 -0
- package/dist/esm/inputs/MaskedInput/MaskedInput.js +26 -0
- package/dist/esm/inputs/MaskedInput/MaskedInput.js.map +1 -0
- package/dist/esm/inputs/MaskedInput/useMaskedInput.js +57 -0
- package/dist/esm/inputs/MaskedInput/useMaskedInput.js.map +1 -0
- package/dist/esm/inputs/PhoneInput/PhoneInput.js +59 -0
- package/dist/esm/inputs/PhoneInput/PhoneInput.js.map +1 -0
- package/dist/esm/inputs/RadioGroup/RadioGroup.js +25 -0
- package/dist/esm/inputs/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/esm/inputs/SinInput/SinInput.js +54 -0
- package/dist/esm/inputs/SinInput/SinInput.js.map +1 -0
- package/dist/esm/inputs/TableInput/CheckboxEditCell.js +32 -0
- package/dist/esm/inputs/TableInput/CheckboxEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/DropdownCell.js +26 -0
- package/dist/esm/inputs/TableInput/DropdownCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/HoverCell.js +20 -0
- package/dist/esm/inputs/TableInput/HoverCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/LocalDateCell.js +13 -0
- package/dist/esm/inputs/TableInput/LocalDateCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/LocalDateEditCell.js +33 -0
- package/dist/esm/inputs/TableInput/LocalDateEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/LocalTimeEditCell.js +31 -0
- package/dist/esm/inputs/TableInput/LocalTimeEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/MoneyCell.js +13 -0
- package/dist/esm/inputs/TableInput/MoneyCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/MoneyEditCell.js +37 -0
- package/dist/esm/inputs/TableInput/MoneyEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/MoneySumFooter.js +20 -0
- package/dist/esm/inputs/TableInput/MoneySumFooter.js.map +1 -0
- package/dist/esm/inputs/TableInput/NumberEditCell.js +35 -0
- package/dist/esm/inputs/TableInput/NumberEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/StringEditCell.js +34 -0
- package/dist/esm/inputs/TableInput/StringEditCell.js.map +1 -0
- package/dist/esm/inputs/TableInput/TableInput.js +79 -0
- package/dist/esm/inputs/TableInput/TableInput.js.map +1 -0
- package/dist/esm/inputs/TableInput/addRowOnTab.js +13 -0
- package/dist/esm/inputs/TableInput/addRowOnTab.js.map +1 -0
- package/dist/esm/money/MoneyCurrencyInput/MoneyCurrencyInput.js +51 -0
- package/dist/esm/money/MoneyCurrencyInput/MoneyCurrencyInput.js.map +1 -0
- package/dist/esm/money/MoneyInput/MoneyInput.js +31 -0
- package/dist/esm/money/MoneyInput/MoneyInput.js.map +1 -0
- package/dist/esm/money/useMoneyInput.js +75 -0
- package/dist/esm/money/useMoneyInput.js.map +1 -0
- package/dist/esm/step/FormStep.js +17 -0
- package/dist/esm/step/FormStep.js.map +1 -0
- package/dist/esm/step/Step.js +10 -0
- package/dist/esm/step/Step.js.map +1 -0
- package/dist/esm/step/StepProvider.js +95 -0
- package/dist/esm/step/StepProvider.js.map +1 -0
- package/dist/esm/step/stepContext.js +10 -0
- package/dist/esm/step/stepContext.js.map +1 -0
- package/dist/esm/step/useStep.js +10 -0
- package/dist/esm/step/useStep.js.map +1 -0
- package/dist/stats.html +2689 -0
- package/dist/stats.txt +92 -0
- package/dist/types/date/DatePicker/index.d.ts +3 -0
- package/dist/types/date/LocalDatePicker/LocalDatePicker.d.ts +20 -0
- package/dist/types/date/LocalDatePicker/MaskedDateInput.d.ts +13 -0
- package/dist/types/date/LocalDatePicker/index.d.ts +2 -0
- package/dist/types/date/LocalMonthSelect/LocalMonthSelect.d.ts +11 -0
- package/dist/types/date/LocalMonthSelect/index.d.ts +2 -0
- package/dist/types/date/LocalTimePicker/LocalTimePicker.d.ts +13 -0
- package/dist/types/date/LocalTimePicker/MaskedTimeInput.d.ts +12 -0
- package/dist/types/date/LocalTimePicker/index.d.ts +2 -0
- package/dist/types/date/MonthDayPicker/MonthDayPicker.d.ts +13 -0
- package/dist/types/date/MonthDayPicker/index.d.ts +2 -0
- package/dist/types/date/MonthYearPicker/MonthYearPicker.d.ts +15 -0
- package/dist/types/date/MonthYearPicker/index.d.ts +2 -0
- package/dist/types/date/YearSelect/YearSelect.d.ts +10 -0
- package/dist/types/date/YearSelect/index.d.ts +2 -0
- package/dist/types/form/TForm/TForm.d.ts +3 -0
- package/dist/types/form/TForm/index.d.ts +3 -0
- package/dist/types/form/TForm/types.d.ts +32 -0
- package/dist/types/form/TForm/useTForm.d.ts +57 -0
- package/dist/types/index.d.ts +32 -0
- package/dist/types/inputs/CreditCardInput/CreditCardInput.d.ts +15 -0
- package/dist/types/inputs/CreditCardInput/CreditCardNumberInput.d.ts +7 -0
- package/dist/types/inputs/CreditCardInput/index.d.ts +2 -0
- package/dist/types/inputs/MaskedInput/MaskedInput.d.ts +11 -0
- package/dist/types/inputs/MaskedInput/index.d.ts +3 -0
- package/dist/types/inputs/MaskedInput/useMaskedInput.d.ts +7 -0
- package/dist/types/inputs/PhoneInput/PhoneInput.d.ts +6 -0
- package/dist/types/inputs/PhoneInput/index.d.ts +2 -0
- package/dist/types/inputs/RadioGroup/RadioGroup.d.ts +7 -0
- package/dist/types/inputs/RadioGroup/index.d.ts +2 -0
- package/dist/types/inputs/SinInput/SinInput.d.ts +6 -0
- package/dist/types/inputs/SinInput/index.d.ts +2 -0
- package/dist/types/inputs/TableInput/CheckboxEditCell.d.ts +11 -0
- package/dist/types/inputs/TableInput/DropdownCell.d.ts +3 -0
- package/dist/types/inputs/TableInput/HoverCell.d.ts +6 -0
- package/dist/types/inputs/TableInput/LocalDateCell.d.ts +10 -0
- package/dist/types/inputs/TableInput/LocalDateEditCell.d.ts +3 -0
- package/dist/types/inputs/TableInput/LocalTimeEditCell.d.ts +3 -0
- package/dist/types/inputs/TableInput/MoneyCell.d.ts +8 -0
- package/dist/types/inputs/TableInput/MoneyEditCell.d.ts +10 -0
- package/dist/types/inputs/TableInput/MoneySumFooter.d.ts +6 -0
- package/dist/types/inputs/TableInput/NumberEditCell.d.ts +11 -0
- package/dist/types/inputs/TableInput/StringEditCell.d.ts +11 -0
- package/dist/types/inputs/TableInput/TableInput.d.ts +32 -0
- package/dist/types/inputs/TableInput/addRowOnTab.d.ts +10 -0
- package/dist/types/inputs/TableInput/index.d.ts +14 -0
- package/dist/types/money/MoneyCurrencyInput/MoneyCurrencyInput.d.ts +10 -0
- package/dist/types/money/MoneyCurrencyInput/index.d.ts +2 -0
- package/dist/types/money/MoneyInput/MoneyInput.d.ts +14 -0
- package/dist/types/money/MoneyInput/index.d.ts +2 -0
- package/dist/types/money/useMoneyInput.d.ts +13 -0
- package/dist/types/step/FormStep.d.ts +8 -0
- package/dist/types/step/Step.d.ts +8 -0
- package/dist/types/step/StepProvider.d.ts +9 -0
- package/dist/types/step/index.d.ts +4 -0
- package/dist/types/step/stepContext.d.ts +4 -0
- package/dist/types/step/useStep.d.ts +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function styleInject(css, ref) {
|
|
2
|
+
if ( ref === void 0 ) ref = {};
|
|
3
|
+
var insertAt = ref.insertAt;
|
|
4
|
+
|
|
5
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
6
|
+
|
|
7
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
8
|
+
var style = document.createElement('style');
|
|
9
|
+
style.type = 'text/css';
|
|
10
|
+
|
|
11
|
+
if (insertAt === 'top') {
|
|
12
|
+
if (head.firstChild) {
|
|
13
|
+
head.insertBefore(style, head.firstChild);
|
|
14
|
+
} else {
|
|
15
|
+
head.appendChild(style);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
head.appendChild(style);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (style.styleSheet) {
|
|
22
|
+
style.styleSheet.cssText = css;
|
|
23
|
+
} else {
|
|
24
|
+
style.appendChild(document.createTextNode(css));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { styleInject as default };
|
|
29
|
+
//# sourceMappingURL=style-inject.es.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-inject.es.js","sources":["../../../../../../../node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":"AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,KAAK,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;AACjC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAC9B;AACA,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,EAAE;AAC1D;AACA,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;AAC1B;AACA,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AAChD,KAAK,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC9B,KAAK;AACL,GAAG,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,GAAG;AACH;AACA,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC;AACnC,GAAG,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACpD,GAAG;AACH;;;;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useImperativeHandle, createElement, Children } from 'react';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import { isFunction, isEmptyChildren, FormikProvider } from 'formik';
|
|
4
|
+
import { useTForm } from './useTForm.js';
|
|
5
|
+
|
|
6
|
+
debug("thx.controls.form.TForm");
|
|
7
|
+
function TForm(props) {
|
|
8
|
+
const tbag = useTForm(props);
|
|
9
|
+
const { component, render, children, innerRef } = props;
|
|
10
|
+
useImperativeHandle(innerRef, () => tbag);
|
|
11
|
+
let child = null;
|
|
12
|
+
if (component) {
|
|
13
|
+
child = createElement(component, tbag);
|
|
14
|
+
} else if (render) {
|
|
15
|
+
child = render(tbag);
|
|
16
|
+
} else if (children) {
|
|
17
|
+
if (isFunction(children)) {
|
|
18
|
+
child = children(tbag);
|
|
19
|
+
} else if (!isEmptyChildren(children)) {
|
|
20
|
+
child = Children.only(children);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return /* @__PURE__ */ React.createElement(FormikProvider, {
|
|
24
|
+
value: tbag
|
|
25
|
+
}, child);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { TForm };
|
|
29
|
+
//# sourceMappingURL=TForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TForm.js","sources":["../../../../src/form/TForm/TForm.tsx"],"sourcesContent":["import debug from 'debug';\nimport {type FormikValues, isFunction, FormikProvider, isEmptyChildren} from 'formik';\nimport {useImperativeHandle, Children, createElement} from 'react';\nimport type {ReactNode} from 'react';\nimport type {TFormConfig, TFormProps} from './types';\nimport {useTForm} from './useTForm';\n\nconst d = debug('thx.controls.form.TForm');\n\nexport function TForm<Values extends FormikValues = FormikValues>(props: TFormConfig<Values>) {\n\tconst tbag = useTForm<Values>(props);\n\tconst {component, render, children, innerRef} = props;\n\n\t// This allows folks to pass a ref to <Formik />\n\tuseImperativeHandle(innerRef, () => tbag);\n\n\tlet child = null;\n\tif (component) {\n\t\t// @ts-ignore\n\t\tchild = createElement(component, tbag);\n\t} else if (render) {\n\t\tchild = render(tbag);\n\t} else if (children) {\n\t\tif (isFunction(children)) {\n\t\t\tchild = (children as (bag: TFormProps<Values>) => ReactNode)(tbag as TFormProps<Values>);\n\t\t} else if (!isEmptyChildren(children)) {\n\t\t\tchild = Children.only(children);\n\t\t}\n\t}\n\n\treturn <FormikProvider value={tbag}>{child}</FormikProvider>;\n}\n"],"names":[],"mappings":";;;;;AAOU,MAAM,yBAAyB,EAAA;AAElC,SAAA,KAAA,CAA2D,KAA4B,EAAA;AAC7F,EAAM,MAAA,IAAA,GAAO,SAAiB,KAAK,CAAA,CAAA;AACnC,EAAA,MAAM,EAAC,SAAA,EAAW,MAAQ,EAAA,QAAA,EAAU,QAAY,EAAA,GAAA,KAAA,CAAA;AAGhD,EAAoB,mBAAA,CAAA,QAAA,EAAU,MAAM,IAAI,CAAA,CAAA;AAExC,EAAA,IAAI,KAAQ,GAAA,IAAA,CAAA;AACZ,EAAA,IAAI,SAAW,EAAA;AAEd,IAAQ,KAAA,GAAA,aAAA,CAAc,WAAW,IAAI,CAAA,CAAA;AAAA,aAC3B,MAAQ,EAAA;AAClB,IAAA,KAAA,GAAQ,OAAO,IAAI,CAAA,CAAA;AAAA,aACT,QAAU,EAAA;AACpB,IAAI,IAAA,UAAA,CAAW,QAAQ,CAAG,EAAA;AACzB,MAAA,KAAA,GAAS,SAAoD,IAA0B,CAAA,CAAA;AAAA,KAC7E,MAAA,IAAA,CAAC,eAAgB,CAAA,QAAQ,CAAG,EAAA;AACtC,MAAQ,KAAA,GAAA,QAAA,CAAS,KAAK,QAAQ,CAAA,CAAA;AAAA,KAC/B;AAAA,GACD;AAEA,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA;AAAA,IAAe,KAAO,EAAA,IAAA;AAAA,GAAA,EAAO,KAAM,CAAA,CAAA;AAC5C;;;;"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import flatten from 'flat';
|
|
3
|
+
import { useFormik } from 'formik';
|
|
4
|
+
import { uniq, get, property } from 'lodash-es';
|
|
5
|
+
import { Message, Segment } from 'semantic-ui-react';
|
|
6
|
+
|
|
7
|
+
function useTForm(config) {
|
|
8
|
+
const { render, children, ...rest } = config;
|
|
9
|
+
const formik = useFormik(rest);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (config.onValidate)
|
|
12
|
+
config.onValidate(formik.isValid);
|
|
13
|
+
}, [formik.isValid, config.onValidate]);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (config.getSubmitFn)
|
|
16
|
+
config.getSubmitFn(formik.submitForm);
|
|
17
|
+
}, [formik.submitForm, config.getSubmitFn]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (config.onChange)
|
|
20
|
+
config.onChange(formik.values);
|
|
21
|
+
}, [formik.values]);
|
|
22
|
+
const [errorCleared, setErrorCleared] = useState(false);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (config.error && config.error.message && !formik.isSubmitting) {
|
|
25
|
+
setErrorCleared(true);
|
|
26
|
+
}
|
|
27
|
+
}, [formik.values, config.error]);
|
|
28
|
+
const flatWarnings = flatten(formik.errors);
|
|
29
|
+
const flatTouched = flatten(formik.touched);
|
|
30
|
+
const warnings = uniq(Object.keys(flatWarnings).reduce((memo, value) => {
|
|
31
|
+
const isTouched = flatTouched[value];
|
|
32
|
+
if (isTouched || formik.submitCount > 0) {
|
|
33
|
+
return [...memo, get(flatWarnings, value)];
|
|
34
|
+
}
|
|
35
|
+
return memo;
|
|
36
|
+
}, []));
|
|
37
|
+
let errors = [];
|
|
38
|
+
let errorHeader = "";
|
|
39
|
+
if (config.error && config.error.message) {
|
|
40
|
+
if (config.error.graphQLErrors) {
|
|
41
|
+
errors = config.error.graphQLErrors.reduce((memo, v) => {
|
|
42
|
+
if (v.message)
|
|
43
|
+
return [...memo, v.message];
|
|
44
|
+
return memo;
|
|
45
|
+
}, []);
|
|
46
|
+
} else {
|
|
47
|
+
const errorMessage = config.error.message.slice(config.error.message.indexOf(": ") + 1);
|
|
48
|
+
errors.push(errorMessage);
|
|
49
|
+
}
|
|
50
|
+
errorHeader = config.error.message.slice(0, config.error.message.indexOf(": "));
|
|
51
|
+
}
|
|
52
|
+
errors = uniq(errors);
|
|
53
|
+
const hasWarnings = !(formik.isValid || warnings.length === 0);
|
|
54
|
+
const hasErrors = errors.length > 0;
|
|
55
|
+
function renderWarnings() {
|
|
56
|
+
if (!hasWarnings && !hasErrors)
|
|
57
|
+
return null;
|
|
58
|
+
return /* @__PURE__ */ React.createElement(Message, {
|
|
59
|
+
warning: hasWarnings,
|
|
60
|
+
error: hasErrors && !hasWarnings
|
|
61
|
+
}, /* @__PURE__ */ React.createElement(Message.Header, null, hasWarnings ? "Some fields are not complete:" : `${errorHeader}:`), /* @__PURE__ */ React.createElement(Segment, {
|
|
62
|
+
style: { overflow: "auto", maxHeight: 100 }
|
|
63
|
+
}, (hasWarnings ? warnings : errors).map((msg) => /* @__PURE__ */ React.createElement("div", {
|
|
64
|
+
key: msg
|
|
65
|
+
}, msg))));
|
|
66
|
+
}
|
|
67
|
+
function fieldError(fieldName) {
|
|
68
|
+
return (!!property(fieldName)(formik.touched) || formik.submitCount > 0) && !!property(fieldName)(formik.errors);
|
|
69
|
+
}
|
|
70
|
+
function handleSubmit(e) {
|
|
71
|
+
setErrorCleared(false);
|
|
72
|
+
formik.handleSubmit(e);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...formik,
|
|
76
|
+
hasErrors: hasErrors && !errorCleared,
|
|
77
|
+
hasWarnings,
|
|
78
|
+
isValid: !hasWarnings,
|
|
79
|
+
loading: config.loading ? config.loading : false,
|
|
80
|
+
submitDisabled: hasWarnings || formik.isSubmitting,
|
|
81
|
+
errorMarkedCleared: errorCleared,
|
|
82
|
+
formError: hasErrors && !hasWarnings && !errorCleared && !formik.isSubmitting,
|
|
83
|
+
renderWarnings,
|
|
84
|
+
fieldError,
|
|
85
|
+
handleSubmit
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { useTForm };
|
|
90
|
+
//# sourceMappingURL=useTForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTForm.js","sources":["../../../../src/form/TForm/useTForm.tsx"],"sourcesContent":["import flatten from 'flat';\nimport {type FormikValues, useFormik, type FormikErrors, type FormikTouched} from 'formik';\nimport {get, property, uniq} from 'lodash-es';\nimport {type FormEvent, useEffect, useState} from 'react';\nimport {Message, Segment} from 'semantic-ui-react';\nimport type {TFormConfig} from './types';\n\nexport function useTForm<Values extends FormikValues = FormikValues, InitialValues = any>(config: TFormConfig<Values, InitialValues>) {\n\tconst {render, children, ...rest} = config;\n\t// @ts-ignore\n\tconst formik = useFormik(rest);\n\n\tuseEffect(() => {\n\t\tif (config.onValidate) config.onValidate(formik.isValid);\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [formik.isValid, config.onValidate]);\n\n\t// Get submit function\n\tuseEffect(() => {\n\t\tif (config.getSubmitFn) config.getSubmitFn(formik.submitForm);\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [formik.submitForm, config.getSubmitFn]);\n\n\t// On change event (if this ends up changing values it will cycle)\n\tuseEffect(() => {\n\t\tif (config.onChange) config.onChange(formik.values);\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [formik.values]);\n\n\t// Mark the error cleared if the form has been edited after an error\n\tconst [errorCleared, setErrorCleared] = useState(false);\n\tuseEffect(() => {\n\t\tif (config.error && config.error.message && !formik.isSubmitting) {\n\t\t\tsetErrorCleared(true);\n\t\t}\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [formik.values, config.error]);\n\n\t// Flatten the warnings (formik errors) and touch objects.\n\tconst flatWarnings = flatten<FormikErrors<Values>, {[key: string]: string}>(formik.errors);\n\tconst flatTouched = flatten<FormikTouched<Values>, {[key: string]: string}>(formik.touched);\n\n\t// Create an array of strings that are warnings (formik errors). If the submit count is greater than 0\n\t// then it will show all warnings. Otherwise only touched field warnings will be added to this array.\n\tconst warnings: string[] = uniq(\n\t\tObject.keys(flatWarnings).reduce<string[]>((memo, value) => {\n\t\t\tconst isTouched = flatTouched[value];\n\t\t\tif (isTouched || formik.submitCount > 0) {\n\t\t\t\treturn [...memo, get(flatWarnings, value)];\n\t\t\t}\n\t\t\treturn memo;\n\t\t}, []),\n\t);\n\n\t// Create an array of strings that are errors (graphql errors).\n\tlet errors: string[] = [];\n\tlet errorHeader = '';\n\tif (config.error && config.error.message) {\n\t\tif (config.error.graphQLErrors) {\n\t\t\terrors = config.error.graphQLErrors.reduce((memo, v) => {\n\t\t\t\tif (v.message) return [...memo, v.message];\n\t\t\t\treturn memo;\n\t\t\t}, [] as string[]);\n\t\t} else {\n\t\t\tconst errorMessage = config.error.message.slice(config.error.message.indexOf(': ') + 1);\n\t\t\terrors.push(errorMessage);\n\t\t}\n\t\terrorHeader = config.error.message.slice(0, config.error.message.indexOf(': '));\n\t}\n\terrors = uniq(errors);\n\n\t// Check if there are warnings or errors\n\tconst hasWarnings = !(formik.isValid || warnings.length === 0);\n\tconst hasErrors = errors.length > 0;\n\n\t// Render the warnings\n\tfunction renderWarnings() {\n\t\tif (!hasWarnings && !hasErrors) return null;\n\t\treturn (\n\t\t\t<Message warning={hasWarnings} error={hasErrors && !hasWarnings}>\n\t\t\t\t<Message.Header>{hasWarnings ? 'Some fields are not complete:' : `${errorHeader}:`}</Message.Header>\n\t\t\t\t{/* Put it in a segment to make sure the errorMessage isn't too big when there are a lot of errors */}\n\t\t\t\t<Segment style={{overflow: 'auto', maxHeight: 100}}>\n\t\t\t\t\t{(hasWarnings ? warnings : errors).map(msg => (\n\t\t\t\t\t\t<div key={msg}>{msg}</div>\n\t\t\t\t\t))}\n\t\t\t\t</Segment>\n\t\t\t</Message>\n\t\t);\n\t}\n\n\t// Returns true if the field has an error\n\tfunction fieldError(fieldName: keyof Values | string | number) {\n\t\treturn (!!property(fieldName)(formik.touched) || formik.submitCount > 0) && !!property(fieldName)(formik.errors);\n\t}\n\n\t// Handles the form submit\n\tfunction handleSubmit(e?: FormEvent<HTMLFormElement>) {\n\t\tsetErrorCleared(false);\n\t\tformik.handleSubmit(e);\n\t}\n\n\treturn {\n\t\t...formik,\n\t\thasErrors: hasErrors && !errorCleared,\n\t\thasWarnings,\n\t\tisValid: !hasWarnings,\n\t\tloading: config.loading ? config.loading : false,\n\t\tsubmitDisabled: hasWarnings || formik.isSubmitting,\n\t\terrorMarkedCleared: errorCleared,\n\t\tformError: hasErrors && !hasWarnings && !errorCleared && !formik.isSubmitting, // Convenience\n\t\trenderWarnings,\n\t\tfieldError,\n\t\thandleSubmit,\n\t};\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export { LocalDatePicker } from './date/LocalDatePicker/LocalDatePicker.js';
|
|
2
|
+
export { LocalMonthSelect } from './date/LocalMonthSelect/LocalMonthSelect.js';
|
|
3
|
+
export { LocalTimePicker } from './date/LocalTimePicker/LocalTimePicker.js';
|
|
4
|
+
export { MonthDayPicker } from './date/MonthDayPicker/MonthDayPicker.js';
|
|
5
|
+
export { MonthYearPicker } from './date/MonthYearPicker/MonthYearPicker.js';
|
|
6
|
+
export { YearSelect } from './date/YearSelect/YearSelect.js';
|
|
7
|
+
export { TForm } from './form/TForm/TForm.js';
|
|
8
|
+
export { useTForm } from './form/TForm/useTForm.js';
|
|
9
|
+
export { MaskedInput } from './inputs/MaskedInput/MaskedInput.js';
|
|
10
|
+
import './inputs/MaskedInput/useMaskedInput.js';
|
|
11
|
+
export { RadioGroup } from './inputs/RadioGroup/RadioGroup.js';
|
|
12
|
+
export { PhoneInput } from './inputs/PhoneInput/PhoneInput.js';
|
|
13
|
+
export { CreditCardInput } from './inputs/CreditCardInput/CreditCardInput.js';
|
|
14
|
+
export { SinInput } from './inputs/SinInput/SinInput.js';
|
|
15
|
+
export { TableInput } from './inputs/TableInput/TableInput.js';
|
|
16
|
+
export { MoneyCell } from './inputs/TableInput/MoneyCell.js';
|
|
17
|
+
export { MoneyEditCell } from './inputs/TableInput/MoneyEditCell.js';
|
|
18
|
+
export { LocalDateCell } from './inputs/TableInput/LocalDateCell.js';
|
|
19
|
+
export { CheckboxEditCell } from './inputs/TableInput/CheckboxEditCell.js';
|
|
20
|
+
export { LocalDateEditCell } from './inputs/TableInput/LocalDateEditCell.js';
|
|
21
|
+
export { LocalTimeEditCell } from './inputs/TableInput/LocalTimeEditCell.js';
|
|
22
|
+
export { MoneySumFooter } from './inputs/TableInput/MoneySumFooter.js';
|
|
23
|
+
export { NumberEditCell } from './inputs/TableInput/NumberEditCell.js';
|
|
24
|
+
export { StringEditCell } from './inputs/TableInput/StringEditCell.js';
|
|
25
|
+
export { DropdownCell } from './inputs/TableInput/DropdownCell.js';
|
|
26
|
+
export { HoverCell } from './inputs/TableInput/HoverCell.js';
|
|
27
|
+
export { addRowOnTab } from './inputs/TableInput/addRowOnTab.js';
|
|
28
|
+
export { MoneyInput } from './money/MoneyInput/MoneyInput.js';
|
|
29
|
+
export { MoneyCurrencyInput } from './money/MoneyCurrencyInput/MoneyCurrencyInput.js';
|
|
30
|
+
export { Step } from './step/Step.js';
|
|
31
|
+
export { useStep } from './step/useStep.js';
|
|
32
|
+
export { FormStep } from './step/FormStep.js';
|
|
33
|
+
export { StepProvider } from './step/StepProvider.js';
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { formatDate } from '@thx/date';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import CreditCards from 'react-credit-cards';
|
|
5
|
+
import 'react-credit-cards/es/styles-compiled.css';
|
|
6
|
+
import { Grid, Form, Input } from 'semantic-ui-react';
|
|
7
|
+
import { MonthYearPicker } from '../../date/MonthYearPicker/MonthYearPicker.js';
|
|
8
|
+
import { CreditCardNumberInput } from './CreditCardNumberInput.js';
|
|
9
|
+
import './styles.css.js';
|
|
10
|
+
|
|
11
|
+
const d = debug("thx.controls.inputs.CreditCardInput");
|
|
12
|
+
function CreditCardInput(props) {
|
|
13
|
+
const { onBlur, disabled, onChange, value } = props;
|
|
14
|
+
const { name, number, cvc, expiry } = value || {};
|
|
15
|
+
const [focus, setFocus] = useState("number");
|
|
16
|
+
return /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Column, {
|
|
17
|
+
width: 4
|
|
18
|
+
}, /* @__PURE__ */ React.createElement(Form, null, /* @__PURE__ */ React.createElement(Form.Group, null, /* @__PURE__ */ React.createElement(Form.Field, {
|
|
19
|
+
width: 9
|
|
20
|
+
}, /* @__PURE__ */ React.createElement("label", null, "Number"), /* @__PURE__ */ React.createElement(CreditCardNumberInput, {
|
|
21
|
+
onFocus: () => setFocus("number"),
|
|
22
|
+
onBlur,
|
|
23
|
+
onChange: (v) => {
|
|
24
|
+
onChange && onChange({ name, number: v, cvc, expiry });
|
|
25
|
+
},
|
|
26
|
+
disabled
|
|
27
|
+
})), /* @__PURE__ */ React.createElement(Form.Field, {
|
|
28
|
+
width: 4
|
|
29
|
+
}, /* @__PURE__ */ React.createElement("label", null, "CVC"), /* @__PURE__ */ React.createElement(Input, {
|
|
30
|
+
value: cvc || "",
|
|
31
|
+
onChange: (ev, v) => {
|
|
32
|
+
onChange && onChange({ name, number, cvc: v.value, expiry });
|
|
33
|
+
},
|
|
34
|
+
onFocus: () => setFocus("cvc"),
|
|
35
|
+
onBlur: () => setFocus("name"),
|
|
36
|
+
disabled
|
|
37
|
+
}))), /* @__PURE__ */ React.createElement(Form.Group, null, /* @__PURE__ */ React.createElement(Form.Field, {
|
|
38
|
+
width: 9
|
|
39
|
+
}, /* @__PURE__ */ React.createElement("label", null, "Name"), /* @__PURE__ */ React.createElement(Input, {
|
|
40
|
+
value: name || "",
|
|
41
|
+
onChange: (ev, v) => {
|
|
42
|
+
onChange && onChange({ name: v.value, number, cvc, expiry });
|
|
43
|
+
},
|
|
44
|
+
onFocus: () => setFocus("name"),
|
|
45
|
+
disabled,
|
|
46
|
+
fluid: true
|
|
47
|
+
})), /* @__PURE__ */ React.createElement(Form.Field, {
|
|
48
|
+
width: 6
|
|
49
|
+
}, /* @__PURE__ */ React.createElement("label", null, "Expiry"), /* @__PURE__ */ React.createElement(MonthYearPicker, {
|
|
50
|
+
value: expiry,
|
|
51
|
+
onChange: (v) => {
|
|
52
|
+
onChange && onChange({ name, number, cvc, expiry: v });
|
|
53
|
+
},
|
|
54
|
+
onFocus: () => setFocus("expiry"),
|
|
55
|
+
disabled
|
|
56
|
+
}))))), /* @__PURE__ */ React.createElement(Grid.Column, {
|
|
57
|
+
width: 12
|
|
58
|
+
}, /* @__PURE__ */ React.createElement(CreditCards, {
|
|
59
|
+
cvc: cvc || "",
|
|
60
|
+
expiry: formatDate(expiry, { format: "MMuu" }) || "",
|
|
61
|
+
name: name || "",
|
|
62
|
+
number: number || "",
|
|
63
|
+
focused: focus,
|
|
64
|
+
callback: (a, b) => {
|
|
65
|
+
d(a, b);
|
|
66
|
+
}
|
|
67
|
+
})));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { CreditCardInput };
|
|
71
|
+
//# sourceMappingURL=CreditCardInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreditCardInput.js","sources":["../../../../src/inputs/CreditCardInput/CreditCardInput.tsx"],"sourcesContent":["import type {LocalDate} from '@js-joda/core';\nimport {formatDate} from '@thx/date';\nimport debug from 'debug';\nimport {useState} from 'react';\nimport CreditCards, {type Focused} from 'react-credit-cards';\nimport 'react-credit-cards/es/styles-compiled.css';\nimport {Form, Grid, Input, type InputProps} from 'semantic-ui-react';\nimport {MonthYearPicker} from '../../date/MonthYearPicker';\nimport {CreditCardNumberInput} from './CreditCardNumberInput';\nimport './styles.css';\n\nconst d = debug('thx.controls.inputs.CreditCardInput');\n\nexport interface CreditCardData {\n\tnumber?: string;\n\tname?: string;\n\tcvc?: string;\n\texpiry?: LocalDate;\n}\n\nexport type CreditCardInputProps = {\n\tvalue?: CreditCardData;\n\tonChange?: (data: CreditCardData) => void;\n} & Pick<InputProps, 'disabled' | 'onBlur'>;\n\nexport function CreditCardInput(props: CreditCardInputProps) {\n\tconst {onBlur, disabled, onChange, value} = props;\n\tconst {name, number, cvc, expiry} = value || {};\n\n\tconst [focus, setFocus] = useState<Focused>('number');\n\n\treturn (\n\t\t<Grid>\n\t\t\t<Grid.Column width={4}>\n\t\t\t\t<Form>\n\t\t\t\t\t<Form.Group>\n\t\t\t\t\t\t<Form.Field width={9}>\n\t\t\t\t\t\t\t<label>Number</label>\n\t\t\t\t\t\t\t<CreditCardNumberInput\n\t\t\t\t\t\t\t\tonFocus={() => setFocus('number')}\n\t\t\t\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\t\t\t\tonChange={v => {\n\t\t\t\t\t\t\t\t\tonChange && onChange({name, number: v, cvc, expiry});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Form.Field>\n\t\t\t\t\t\t<Form.Field width={4}>\n\t\t\t\t\t\t\t<label>CVC</label>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tvalue={cvc || ''}\n\t\t\t\t\t\t\t\tonChange={(ev, v) => {\n\t\t\t\t\t\t\t\t\tonChange && onChange({name, number, cvc: v.value, expiry});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonFocus={() => setFocus('cvc')}\n\t\t\t\t\t\t\t\tonBlur={() => setFocus('name')}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Form.Field>\n\t\t\t\t\t</Form.Group>\n\t\t\t\t\t<Form.Group>\n\t\t\t\t\t\t<Form.Field width={9}>\n\t\t\t\t\t\t\t<label>Name</label>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tvalue={name || ''}\n\t\t\t\t\t\t\t\tonChange={(ev, v) => {\n\t\t\t\t\t\t\t\t\tonChange && onChange({name: v.value, number, cvc, expiry});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonFocus={() => setFocus('name')}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tfluid\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Form.Field>\n\t\t\t\t\t\t<Form.Field width={6}>\n\t\t\t\t\t\t\t<label>Expiry</label>\n\t\t\t\t\t\t\t<MonthYearPicker\n\t\t\t\t\t\t\t\tvalue={expiry}\n\t\t\t\t\t\t\t\tonChange={v => {\n\t\t\t\t\t\t\t\t\tonChange && onChange({name, number, cvc, expiry: v});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonFocus={() => setFocus('expiry')}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Form.Field>\n\t\t\t\t\t</Form.Group>\n\t\t\t\t</Form>\n\t\t\t</Grid.Column>\n\t\t\t<Grid.Column width={12}>\n\t\t\t\t<CreditCards\n\t\t\t\t\tcvc={cvc || ''}\n\t\t\t\t\texpiry={formatDate(expiry, {format: 'MMuu'}) || ''}\n\t\t\t\t\tname={name || ''}\n\t\t\t\t\tnumber={number || ''}\n\t\t\t\t\tfocused={focus}\n\t\t\t\t\tcallback={(a, b) => {\n\t\t\t\t\t\td(a, b);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</Grid.Column>\n\t\t</Grid>\n\t);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import creditCardType from 'credit-card-type';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { validate } from 'luhn';
|
|
5
|
+
import { Input, Icon } from 'semantic-ui-react';
|
|
6
|
+
import { useMaskedInput } from '../MaskedInput/useMaskedInput.js';
|
|
7
|
+
|
|
8
|
+
const d = debug("thx.controls.inputs.CreditCardInput.CreditCardNumberInput");
|
|
9
|
+
function getIcon(type) {
|
|
10
|
+
switch (type) {
|
|
11
|
+
case "visa":
|
|
12
|
+
return "cc visa";
|
|
13
|
+
case "mastercard":
|
|
14
|
+
return "cc mastercard";
|
|
15
|
+
case "american-express":
|
|
16
|
+
return "cc amex";
|
|
17
|
+
case "diners-club":
|
|
18
|
+
return "cc diners club";
|
|
19
|
+
case "jcb":
|
|
20
|
+
return "cc jcb";
|
|
21
|
+
default:
|
|
22
|
+
return "credit card";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function CreditCardNumberInput(props) {
|
|
26
|
+
const { value, onChange, ...rest } = props;
|
|
27
|
+
const [icon, setIcon] = useState("credit card");
|
|
28
|
+
const [color, setColor] = useState("black");
|
|
29
|
+
const checkValidation = useCallback((valueArray) => {
|
|
30
|
+
const num = valueArray.join("").replaceAll(/(_|\s)/g, "");
|
|
31
|
+
const typ = creditCardType(num);
|
|
32
|
+
const isValid = validate(num);
|
|
33
|
+
if (typ.length === 1) {
|
|
34
|
+
setIcon(getIcon(typ[0].type));
|
|
35
|
+
} else {
|
|
36
|
+
setIcon("credit card");
|
|
37
|
+
}
|
|
38
|
+
if (num.length > 0) {
|
|
39
|
+
if (isValid) {
|
|
40
|
+
setColor("green");
|
|
41
|
+
} else {
|
|
42
|
+
setColor("red");
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
setColor("black");
|
|
46
|
+
}
|
|
47
|
+
return isValid;
|
|
48
|
+
}, []);
|
|
49
|
+
const creditCardMask = useMemo(() => ({
|
|
50
|
+
mask: "9999 9999 9999 9999",
|
|
51
|
+
isComplete: checkValidation,
|
|
52
|
+
autoUnmask: true
|
|
53
|
+
}), [checkValidation]);
|
|
54
|
+
const cardNumberRef = useMaskedInput({
|
|
55
|
+
mask: creditCardMask,
|
|
56
|
+
value,
|
|
57
|
+
onChange: (v) => {
|
|
58
|
+
const typ = creditCardType(v || "");
|
|
59
|
+
d(v, typ);
|
|
60
|
+
onChange && onChange(v);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return /* @__PURE__ */ React.createElement(Input, {
|
|
64
|
+
...rest,
|
|
65
|
+
icon: true
|
|
66
|
+
}, /* @__PURE__ */ React.createElement("input", {
|
|
67
|
+
ref: cardNumberRef
|
|
68
|
+
}), /* @__PURE__ */ React.createElement(Icon, {
|
|
69
|
+
name: icon,
|
|
70
|
+
color,
|
|
71
|
+
size: "large"
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { CreditCardNumberInput };
|
|
76
|
+
//# sourceMappingURL=CreditCardNumberInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreditCardNumberInput.js","sources":["../../../../src/inputs/CreditCardInput/CreditCardNumberInput.tsx"],"sourcesContent":["import creditCardType from 'credit-card-type';\nimport debug from 'debug';\nimport {validate} from 'luhn';\nimport {useCallback, useMemo, useState} from 'react';\nimport {Icon, Input, type InputProps, type SemanticICONS, type SemanticCOLORS} from 'semantic-ui-react';\nimport type {MaskedInputProps} from '../MaskedInput';\nimport {useMaskedInput} from '../MaskedInput/useMaskedInput';\n\nconst d = debug('thx.controls.inputs.CreditCardInput.CreditCardNumberInput');\n\ninterface CreditCardNumberInputProps {\n\tonChange?: (value: string | undefined) => void;\n\tvalue?: string;\n}\n\nfunction getIcon(type: string): SemanticICONS {\n\tswitch (type) {\n\t\tcase 'visa':\n\t\t\treturn 'cc visa';\n\t\tcase 'mastercard':\n\t\t\treturn 'cc mastercard';\n\t\tcase 'american-express':\n\t\t\treturn 'cc amex';\n\t\tcase 'diners-club':\n\t\t\treturn 'cc diners club';\n\t\tcase 'jcb':\n\t\t\treturn 'cc jcb';\n\t\tdefault:\n\t\t\treturn 'credit card';\n\t}\n}\n\nexport function CreditCardNumberInput(props: CreditCardNumberInputProps & Omit<InputProps, 'onChange'>) {\n\tconst {value, onChange, ...rest} = props;\n\tconst [icon, setIcon] = useState<SemanticICONS>('credit card');\n\tconst [color, setColor] = useState<SemanticCOLORS>('black');\n\n\tconst checkValidation = useCallback((valueArray: string[]) => {\n\t\tconst num = valueArray.join('').replaceAll(/(_|\\s)/g, '');\n\t\tconst typ = creditCardType(num);\n\t\tconst isValid = validate(num);\n\n\t\tif (typ.length === 1) {\n\t\t\tsetIcon(getIcon(typ[0].type));\n\t\t} else {\n\t\t\tsetIcon('credit card');\n\t\t}\n\n\t\tif (num.length > 0) {\n\t\t\tif (isValid) {\n\t\t\t\tsetColor('green');\n\t\t\t} else {\n\t\t\t\tsetColor('red');\n\t\t\t}\n\t\t} else {\n\t\t\tsetColor('black');\n\t\t}\n\n\t\treturn isValid;\n\t}, []);\n\n\tconst creditCardMask: MaskedInputProps['mask'] = useMemo(\n\t\t() => ({\n\t\t\tmask: '9999 9999 9999 9999',\n\t\t\tisComplete: checkValidation,\n\t\t\tautoUnmask: true,\n\t\t}),\n\t\t[checkValidation],\n\t);\n\n\tconst cardNumberRef = useMaskedInput({\n\t\tmask: creditCardMask,\n\t\tvalue,\n\t\tonChange: v => {\n\t\t\tconst typ = creditCardType(v || '');\n\t\t\td(v, typ);\n\t\t\t// checkValidation([v || '']);\n\t\t\tonChange && onChange(v);\n\t\t},\n\t});\n\n\treturn (\n\t\t<Input {...rest} icon>\n\t\t\t<input ref={cardNumberRef} />\n\t\t\t<Icon name={icon} color={color} size=\"large\" />\n\t\t</Input>\n\t);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA,wBAAwB,uDAAyD;AACjF;AACA;AACA;AACA;AACA;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { forwardRef, useImperativeHandle } from 'react';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import { useMaskedInput } from './useMaskedInput.js';
|
|
4
|
+
|
|
5
|
+
debug("thx.controls.inputs.MaskedInput");
|
|
6
|
+
const MaskedInput = forwardRef((props, ref) => {
|
|
7
|
+
const { name, onBlur, disabled, onChange, mask, value } = props;
|
|
8
|
+
const inputRef = useMaskedInput({ mask, value, onChange });
|
|
9
|
+
useImperativeHandle(ref, () => ({
|
|
10
|
+
focus: () => {
|
|
11
|
+
inputRef.current?.focus();
|
|
12
|
+
},
|
|
13
|
+
select: () => {
|
|
14
|
+
inputRef.current?.select();
|
|
15
|
+
}
|
|
16
|
+
}), [inputRef]);
|
|
17
|
+
return /* @__PURE__ */ React.createElement("input", {
|
|
18
|
+
disabled,
|
|
19
|
+
name,
|
|
20
|
+
ref: inputRef,
|
|
21
|
+
onBlur
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export { MaskedInput };
|
|
26
|
+
//# sourceMappingURL=MaskedInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MaskedInput.js","sources":["../../../../src/inputs/MaskedInput/MaskedInput.tsx"],"sourcesContent":["import debug from 'debug';\nimport {forwardRef, useImperativeHandle} from 'react';\nimport type {InputProps} from 'semantic-ui-react';\nimport {useMaskedInput, type UseMaskedInputProps} from './useMaskedInput';\n\nconst d = debug('thx.controls.inputs.MaskedInput');\n\nexport interface MaskedInputRef {\n\tfocus: () => void;\n\tselect: () => void;\n}\n\nexport type MaskedInputProps = {\n\tname?: string;\n\tonBlur?: (event: any) => void;\n} & UseMaskedInputProps &\n\tOmit<InputProps, 'onChange'>;\n\nexport const MaskedInput = forwardRef<MaskedInputRef, MaskedInputProps>((props, ref) => {\n\tconst {name, onBlur, disabled, onChange, mask, value} = props;\n\n\tconst inputRef = useMaskedInput({mask, value, onChange});\n\n\tuseImperativeHandle(\n\t\tref,\n\t\t() => ({\n\t\t\tfocus: () => {\n\t\t\t\tinputRef.current?.focus();\n\t\t\t},\n\t\t\tselect: () => {\n\t\t\t\tinputRef.current?.select();\n\t\t\t},\n\t\t}),\n\t\t[inputRef],\n\t);\n\n\treturn <input disabled={disabled} name={name} ref={inputRef} onBlur={onBlur} />;\n});\n"],"names":[],"mappings":";;;;AAKU,MAAM,iCAAiC,EAAA;AAa1C,MAAM,WAAc,GAAA,UAAA,CAA6C,CAAC,KAAA,EAAO,GAAQ,KAAA;AACvF,EAAA,MAAM,EAAC,IAAM,EAAA,MAAA,EAAQ,QAAU,EAAA,QAAA,EAAU,MAAM,KAAS,EAAA,GAAA,KAAA,CAAA;AAExD,EAAA,MAAM,WAAW,cAAe,CAAA,EAAC,IAAM,EAAA,KAAA,EAAO,UAAS,CAAA,CAAA;AAEvD,EAAA,mBAAA,CACC,KACA,OAAO;AAAA,IACN,OAAO,MAAM;AACZ,MAAA,QAAA,CAAS,SAAS,KAAM,EAAA,CAAA;AAAA,KACzB;AAAA,IACA,QAAQ,MAAM;AACb,MAAA,QAAA,CAAS,SAAS,MAAO,EAAA,CAAA;AAAA,KAC1B;AAAA,GACD,CAAA,EACA,CAAC,QAAQ,CACV,CAAA,CAAA;AAEA,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA;AAAA,IAAM,QAAA;AAAA,IAAoB,IAAA;AAAA,IAAY,GAAK,EAAA,QAAA;AAAA,IAAU,MAAA;AAAA,GAAgB,CAAA,CAAA;AAC9E,CAAC;;;;"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
import InputmaskImport from 'inputmask';
|
|
3
|
+
import { useRef, useEffect } from 'react';
|
|
4
|
+
import useDeepCompareEffect from 'use-deep-compare-effect';
|
|
5
|
+
|
|
6
|
+
const d = debug("thx.controls.inputs.MaskedInput.useMaskedInput");
|
|
7
|
+
const Inputmask = InputmaskImport.default || InputmaskImport;
|
|
8
|
+
function useMaskedInput(props) {
|
|
9
|
+
const { value, onChange, onSet, mask } = props;
|
|
10
|
+
const inputElement = useRef(null);
|
|
11
|
+
const maskInstance = useRef(null);
|
|
12
|
+
useDeepCompareEffect(() => {
|
|
13
|
+
if (!inputElement.current)
|
|
14
|
+
throw new Error("Could not get input element");
|
|
15
|
+
d("Creating input mask instance");
|
|
16
|
+
maskInstance.current = new Inputmask({
|
|
17
|
+
...mask,
|
|
18
|
+
oncomplete() {
|
|
19
|
+
if (onChange)
|
|
20
|
+
onChange(inputElement.current?.value);
|
|
21
|
+
if (mask?.oncomplete)
|
|
22
|
+
mask.oncomplete();
|
|
23
|
+
},
|
|
24
|
+
oncleared() {
|
|
25
|
+
if (onChange)
|
|
26
|
+
onChange();
|
|
27
|
+
if (mask?.oncleared)
|
|
28
|
+
mask.oncleared();
|
|
29
|
+
},
|
|
30
|
+
onincomplete() {
|
|
31
|
+
if (onChange)
|
|
32
|
+
onChange(inputElement.current?.value);
|
|
33
|
+
if (mask?.onincomplete)
|
|
34
|
+
mask.onincomplete();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
maskInstance.current?.mask(inputElement.current);
|
|
38
|
+
return () => {
|
|
39
|
+
if (maskInstance.current) {
|
|
40
|
+
d("Cleaning up input mask instance");
|
|
41
|
+
maskInstance.current.remove();
|
|
42
|
+
maskInstance.current = null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}, [mask]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (inputElement.current && inputElement.current?.value !== value && value !== void 0) {
|
|
48
|
+
d("Value is changing:", value);
|
|
49
|
+
inputElement.current.value = value;
|
|
50
|
+
onSet && onSet(value);
|
|
51
|
+
}
|
|
52
|
+
}, [value]);
|
|
53
|
+
return inputElement;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { useMaskedInput };
|
|
57
|
+
//# sourceMappingURL=useMaskedInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMaskedInput.js","sources":["../../../../src/inputs/MaskedInput/useMaskedInput.ts"],"sourcesContent":["import debug from 'debug';\nimport InputmaskImport from 'inputmask';\nimport type InputmaskType from 'inputmask';\nimport {useEffect, useRef} from 'react';\nimport useDeepCompareEffect from 'use-deep-compare-effect';\n\nconst d = debug('thx.controls.inputs.MaskedInput.useMaskedInput');\n\n// @ts-ignore\nconst Inputmask = InputmaskImport.default || InputmaskImport;\n\nexport interface UseMaskedInputProps {\n\tvalue?: string;\n\tonChange?: (value?: string) => void;\n\tmask?: Inputmask.Options;\n\tonSet?: (value?: string) => void;\n}\n\nexport function useMaskedInput(props: UseMaskedInputProps) {\n\tconst {value, onChange, onSet, mask} = props;\n\n\tconst inputElement = useRef<HTMLInputElement | null>(null);\n\tconst maskInstance = useRef<InputmaskType.Instance | null>(null);\n\n\tuseDeepCompareEffect(() => {\n\t\tif (!inputElement.current) throw new Error('Could not get input element');\n\n\t\td('Creating input mask instance');\n\t\tmaskInstance.current = new Inputmask({\n\t\t\t...mask,\n\t\t\toncomplete() {\n\t\t\t\tif (onChange) onChange(inputElement.current?.value);\n\t\t\t\tif (mask?.oncomplete) mask.oncomplete();\n\t\t\t},\n\t\t\toncleared() {\n\t\t\t\tif (onChange) onChange();\n\t\t\t\tif (mask?.oncleared) mask.oncleared();\n\t\t\t},\n\t\t\tonincomplete() {\n\t\t\t\tif (onChange) onChange(inputElement.current?.value);\n\t\t\t\tif (mask?.onincomplete) mask.onincomplete();\n\t\t\t},\n\t\t});\n\t\tmaskInstance.current?.mask(inputElement.current);\n\n\t\treturn () => {\n\t\t\tif (maskInstance.current) {\n\t\t\t\td('Cleaning up input mask instance');\n\t\t\t\tmaskInstance.current.remove();\n\t\t\t\tmaskInstance.current = null;\n\t\t\t}\n\t\t};\n\t}, [mask]);\n\n\t// If we change the value prop we need to sync the DOM value to display the new value\n\tuseEffect(() => {\n\t\tif (inputElement.current && inputElement.current?.value !== value && value !== undefined) {\n\t\t\td('Value is changing:', value);\n\t\t\tinputElement.current.value = value;\n\t\t\tonSet && onSet(value);\n\t\t}\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [value]);\n\n\treturn inputElement;\n}\n"],"names":[],"mappings":";;;;;AAMA,MAAM,CAAA,GAAI,MAAM,gDAAgD,CAAA,CAAA;AAGhE,MAAM,SAAA,GAAY,gBAAgB,OAAW,IAAA,eAAA,CAAA;AAStC,SAAA,cAAA,CAAwB,KAA4B,EAAA;AAC1D,EAAA,MAAM,EAAC,KAAA,EAAO,QAAU,EAAA,KAAA,EAAO,IAAQ,EAAA,GAAA,KAAA,CAAA;AAEvC,EAAM,MAAA,YAAA,GAAe,OAAgC,IAAI,CAAA,CAAA;AACzD,EAAM,MAAA,YAAA,GAAe,OAAsC,IAAI,CAAA,CAAA;AAE/D,EAAA,oBAAA,CAAqB,MAAM;AAC1B,IAAA,IAAI,CAAC,YAAa,CAAA,OAAA;AAAS,MAAM,MAAA,IAAI,MAAM,6BAA6B,CAAA,CAAA;AAExE,IAAA,CAAA,CAAE,8BAA8B,CAAA,CAAA;AAChC,IAAa,YAAA,CAAA,OAAA,GAAU,IAAI,SAAU,CAAA;AAAA,MACjC,GAAA,IAAA;AAAA,MACH,UAAa,GAAA;AACZ,QAAI,IAAA,QAAA;AAAU,UAAS,QAAA,CAAA,YAAA,CAAa,SAAS,KAAK,CAAA,CAAA;AAClD,QAAA,IAAI,IAAM,EAAA,UAAA;AAAY,UAAA,IAAA,CAAK,UAAW,EAAA,CAAA;AAAA,OACvC;AAAA,MACA,SAAY,GAAA;AACX,QAAI,IAAA,QAAA;AAAU,UAAS,QAAA,EAAA,CAAA;AACvB,QAAA,IAAI,IAAM,EAAA,SAAA;AAAW,UAAA,IAAA,CAAK,SAAU,EAAA,CAAA;AAAA,OACrC;AAAA,MACA,YAAe,GAAA;AACd,QAAI,IAAA,QAAA;AAAU,UAAS,QAAA,CAAA,YAAA,CAAa,SAAS,KAAK,CAAA,CAAA;AAClD,QAAA,IAAI,IAAM,EAAA,YAAA;AAAc,UAAA,IAAA,CAAK,YAAa,EAAA,CAAA;AAAA,OAC3C;AAAA,KACA,CAAA,CAAA;AACD,IAAa,YAAA,CAAA,OAAA,EAAS,IAAK,CAAA,YAAA,CAAa,OAAO,CAAA,CAAA;AAE/C,IAAA,OAAO,MAAM;AACZ,MAAA,IAAI,aAAa,OAAS,EAAA;AACzB,QAAA,CAAA,CAAE,iCAAiC,CAAA,CAAA;AACnC,QAAA,YAAA,CAAa,QAAQ,MAAO,EAAA,CAAA;AAC5B,QAAA,YAAA,CAAa,OAAU,GAAA,IAAA,CAAA;AAAA,OACxB;AAAA,KACD,CAAA;AAAA,GACD,EAAG,CAAC,IAAI,CAAC,CAAA,CAAA;AAGT,EAAA,SAAA,CAAU,MAAM;AACf,IAAA,IAAI,aAAa,OAAW,IAAA,YAAA,CAAa,SAAS,KAAU,KAAA,KAAA,IAAS,UAAU,KAAW,CAAA,EAAA;AACzF,MAAA,CAAA,CAAE,sBAAsB,KAAK,CAAA,CAAA;AAC7B,MAAA,YAAA,CAAa,QAAQ,KAAQ,GAAA,KAAA,CAAA;AAC7B,MAAA,KAAA,IAAS,MAAM,KAAK,CAAA,CAAA;AAAA,KACrB;AAAA,GAED,EAAG,CAAC,KAAK,CAAC,CAAA,CAAA;AAEV,EAAO,OAAA,YAAA,CAAA;AACR;;;;"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import { Input } from 'semantic-ui-react';
|
|
4
|
+
import { MaskedInput } from '../MaskedInput/MaskedInput.js';
|
|
5
|
+
import '../MaskedInput/useMaskedInput.js';
|
|
6
|
+
|
|
7
|
+
debug("thx.controls.inputs.PhoneInput");
|
|
8
|
+
function PhoneInput(props) {
|
|
9
|
+
const {
|
|
10
|
+
value,
|
|
11
|
+
as,
|
|
12
|
+
action,
|
|
13
|
+
actionPosition,
|
|
14
|
+
className,
|
|
15
|
+
error,
|
|
16
|
+
fluid,
|
|
17
|
+
focus,
|
|
18
|
+
inverted,
|
|
19
|
+
label,
|
|
20
|
+
labelPosition,
|
|
21
|
+
loading,
|
|
22
|
+
size,
|
|
23
|
+
tabIndex,
|
|
24
|
+
transparent,
|
|
25
|
+
extension,
|
|
26
|
+
...rest
|
|
27
|
+
} = props;
|
|
28
|
+
const inputProps = {
|
|
29
|
+
as,
|
|
30
|
+
action,
|
|
31
|
+
actionPosition,
|
|
32
|
+
className: `${className || ""} icon`,
|
|
33
|
+
error,
|
|
34
|
+
focus,
|
|
35
|
+
fluid,
|
|
36
|
+
inverted,
|
|
37
|
+
label,
|
|
38
|
+
labelPosition,
|
|
39
|
+
loading,
|
|
40
|
+
size,
|
|
41
|
+
tabIndex,
|
|
42
|
+
transparent
|
|
43
|
+
};
|
|
44
|
+
const mask = {
|
|
45
|
+
mask: extension ? "((999) 999-9999[ x9999])|(+9 (999) 999-9999[ x9999])" : "((999) 999-9999)|( +9 (999) 999-9999)",
|
|
46
|
+
greedy: false,
|
|
47
|
+
autoUnmask: true
|
|
48
|
+
};
|
|
49
|
+
return /* @__PURE__ */ React.createElement(Input, {
|
|
50
|
+
...inputProps
|
|
51
|
+
}, /* @__PURE__ */ React.createElement(MaskedInput, {
|
|
52
|
+
...rest,
|
|
53
|
+
value,
|
|
54
|
+
mask
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { PhoneInput };
|
|
59
|
+
//# sourceMappingURL=PhoneInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneInput.js","sources":["../../../../src/inputs/PhoneInput/PhoneInput.tsx"],"sourcesContent":["import debug from 'debug';\nimport {Input} from 'semantic-ui-react';\nimport {MaskedInput, type MaskedInputProps} from '../MaskedInput';\n\nconst d = debug('thx.controls.inputs.PhoneInput');\n\nexport interface PhoneInputProps {\n\textension?: boolean;\n\tonChange?: (value?: string) => void;\n}\n\nexport function PhoneInput(props: PhoneInputProps & Omit<MaskedInputProps, 'mask' | 'onChange'>) {\n\tconst {\n\t\tvalue,\n\t\tas,\n\t\taction,\n\t\tactionPosition,\n\t\tclassName,\n\t\terror,\n\t\tfluid,\n\t\tfocus,\n\t\tinverted,\n\t\tlabel,\n\t\tlabelPosition,\n\t\tloading,\n\t\tsize,\n\t\ttabIndex,\n\t\ttransparent,\n\t\textension,\n\t\t...rest\n\t} = props;\n\n\tconst inputProps = {\n\t\tas,\n\t\taction,\n\t\tactionPosition,\n\t\tclassName: `${className || ''} icon`,\n\t\terror,\n\t\tfocus,\n\t\tfluid,\n\t\tinverted,\n\t\tlabel,\n\t\tlabelPosition,\n\t\tloading,\n\t\tsize,\n\t\ttabIndex,\n\t\ttransparent,\n\t};\n\n\tconst mask = {\n\t\tmask: extension ? '((999) 999-9999[ x9999])|(+9 (999) 999-9999[ x9999])' : '((999) 999-9999)|( +9 (999) 999-9999)',\n\t\tgreedy: false,\n\t\tautoUnmask: true,\n\t};\n\n\treturn (\n\t\t<Input {...inputProps}>\n\t\t\t<MaskedInput {...rest} value={value} mask={mask} />\n\t\t</Input>\n\t);\n}\n"],"names":[],"mappings":";;;;;;AAIU,MAAM,gCAAgC,EAAA;AAOzC,SAAA,UAAA,CAAoB,KAAsE,EAAA;AAChG,EAAM,MAAA;AAAA,IACL,KAAA;AAAA,IACA,EAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACG,GAAA,IAAA;AAAA,GACA,GAAA,KAAA,CAAA;AAEJ,EAAA,MAAM,UAAa,GAAA;AAAA,IAClB,EAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA,EAAW,GAAG,SAAa,IAAA,EAAA,CAAA,KAAA,CAAA;AAAA,IAC3B,KAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,GACD,CAAA;AAEA,EAAA,MAAM,IAAO,GAAA;AAAA,IACZ,IAAA,EAAM,YAAY,sDAAyD,GAAA,uCAAA;AAAA,IAC3E,MAAQ,EAAA,KAAA;AAAA,IACR,UAAY,EAAA,IAAA;AAAA,GACb,CAAA;AAEA,EAAA,uBACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAU,GAAA,UAAA;AAAA,GAAA,kBACT,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA;AAAA,IAAgB,GAAA,IAAA;AAAA,IAAM,KAAA;AAAA,IAAc,IAAA;AAAA,GAAY,CAClD,CAAA,CAAA;AAEF;;;;"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { Children, cloneElement } from 'react';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import { Form, FormRadio, Radio } from 'semantic-ui-react';
|
|
4
|
+
|
|
5
|
+
debug("thx.controls.inputs.RadioGroup");
|
|
6
|
+
function RadioGroup(props) {
|
|
7
|
+
const { children, onChange, value, ...rest } = props;
|
|
8
|
+
return /* @__PURE__ */ React.createElement(Form.Group, {
|
|
9
|
+
...rest
|
|
10
|
+
}, Children.map(props.children, (child) => {
|
|
11
|
+
if (child?.type === FormRadio || child?.type === Radio || child?.type === Form.Radio) {
|
|
12
|
+
return cloneElement(child, {
|
|
13
|
+
onChange: (ev, args) => {
|
|
14
|
+
if (onChange)
|
|
15
|
+
onChange(args.value);
|
|
16
|
+
},
|
|
17
|
+
checked: value === child.props.value
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return child;
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { RadioGroup };
|
|
25
|
+
//# sourceMappingURL=RadioGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioGroup.js","sources":["../../../../src/inputs/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import debug from 'debug';\nimport {Children, cloneElement} from 'react';\nimport {Form, Radio, FormRadio, type FormGroupProps} from 'semantic-ui-react';\n\nconst d = debug('thx.controls.inputs.RadioGroup');\n\nexport interface RadioGroupProps {\n\tchildren?: JSX.Element[] | JSX.Element;\n\tonChange?: (value?: string | number) => void;\n\tvalue?: string | number;\n}\n\nexport function RadioGroup(props: RadioGroupProps & Omit<FormGroupProps, 'children'>) {\n\tconst {children, onChange, value, ...rest} = props;\n\n\treturn (\n\t\t<Form.Group {...rest}>\n\t\t\t{Children.map(props.children, child => {\n\t\t\t\tif (child?.type === FormRadio || child?.type === Radio || child?.type === Form.Radio) {\n\t\t\t\t\treturn cloneElement(child, {\n\t\t\t\t\t\tonChange: (ev: any, args: {value?: string | number}) => {\n\t\t\t\t\t\t\tif (onChange) onChange(args.value);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tchecked: value === child.props.value,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn child;\n\t\t\t})}\n\t\t</Form.Group>\n\t);\n}\n"],"names":[],"mappings":";;;;AAIU,MAAM,gCAAgC,EAAA;AAQzC,SAAA,UAAA,CAAoB,KAA2D,EAAA;AACrF,EAAA,MAAM,EAAC,QAAA,EAAU,QAAU,EAAA,KAAA,EAAA,GAAU,IAAQ,EAAA,GAAA,KAAA,CAAA;AAE7C,EACC,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAK,KAAL,EAAA;AAAA,IAAe,GAAA,IAAA;AAAA,GAAA,EACd,QAAS,CAAA,GAAA,CAAI,KAAM,CAAA,QAAA,EAAU,CAAS,KAAA,KAAA;AACtC,IAAI,IAAA,KAAA,EAAO,SAAS,SAAa,IAAA,KAAA,EAAO,SAAS,KAAS,IAAA,KAAA,EAAO,IAAS,KAAA,IAAA,CAAK,KAAO,EAAA;AACrF,MAAA,OAAO,aAAa,KAAO,EAAA;AAAA,QAC1B,QAAA,EAAU,CAAC,EAAA,EAAS,IAAoC,KAAA;AACvD,UAAI,IAAA,QAAA;AAAU,YAAA,QAAA,CAAS,KAAK,KAAK,CAAA,CAAA;AAAA,SAClC;AAAA,QACA,OAAA,EAAS,KAAU,KAAA,KAAA,CAAM,KAAM,CAAA,KAAA;AAAA,OAC/B,CAAA,CAAA;AAAA,KACF;AACA,IAAO,OAAA,KAAA,CAAA;AAAA,GACP,CACF,CAAA,CAAA;AAEF;;;;"}
|