@licklist/design 0.78.12 → 0.78.15
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/bitbucket-pipelines.yml +1 -1
- package/dist/CustomDatePicker/CustomDatePicker.d.ts +10 -0
- package/dist/CustomDatePicker/CustomDatePicker.d.ts.map +1 -0
- package/dist/customRadioButton/RadioButton.d.ts +11 -0
- package/dist/customRadioButton/RadioButton.d.ts.map +1 -0
- package/dist/customRadioButton/RadioButton.js +93 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/sales/guest-profile/profile/Profile.d.ts.map +1 -1
- package/dist/sales/guest-profile/profile/Profile.js +2 -1
- package/package.json +1 -1
- package/src/CustomDatePicker/CustomDatePicker.tsx +258 -0
- package/src/customRadioButton/RadioButton.tsx +84 -0
- package/src/index.ts +1 -0
- package/src/sales/guest-profile/profile/Profile.tsx +2 -5
- package/dist/CustomAlertTypes/AlertBox.d.ts +0 -22
- package/dist/CustomAlertTypes/AlertBox.d.ts.map +0 -1
- package/dist/CustomAlertTypes/AlertRender.d.ts +0 -21
- package/dist/CustomAlertTypes/AlertRender.d.ts.map +0 -1
- package/dist/CustomAlertTypes/alertThemes.d.ts +0 -41
- package/dist/CustomAlertTypes/alertThemes.d.ts.map +0 -1
- package/dist/CustomAlertTypes/utils/textWrapperUtils.d.ts +0 -8
- package/dist/CustomAlertTypes/utils/textWrapperUtils.d.ts.map +0 -1
- package/src/CustomAlertTypes/AlertBox.tsx +0 -87
- package/src/CustomAlertTypes/AlertRender.ts +0 -283
- package/src/CustomAlertTypes/alertThemes.ts +0 -72
- package/src/CustomAlertTypes/utils/textWrapperUtils.ts +0 -26
- package/yarn.lock +0 -22280
package/bitbucket-pipelines.yml
CHANGED
|
@@ -62,7 +62,7 @@ pipelines:
|
|
|
62
62
|
name: Publish to NPM
|
|
63
63
|
script:
|
|
64
64
|
- printf "//`node -p \"require('url').parse(process.env.NPM_REGISTRY_URL || 'https://registry.npmjs.org').host\"`/:_authToken=${NPM_TOKEN}\nregistry=${NPM_REGISTRY_URL:-https://registry.npmjs.org}\n" >> ~/.npmrc
|
|
65
|
-
- pipe: atlassian/npm-publish:
|
|
65
|
+
- pipe: atlassian/npm-publish:1.1.1
|
|
66
66
|
variables:
|
|
67
67
|
NPM_TOKEN: $NPM_TOKEN
|
|
68
68
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type CustomDatePickerProps = {
|
|
2
|
+
name: string;
|
|
3
|
+
error?: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
showAge?: boolean;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function CustomDatePicker({ name, error, showAge, required }: CustomDatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=CustomDatePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CustomDatePicker.d.ts","sourceRoot":"","sources":["../../src/CustomDatePicker/CustomDatePicker.tsx"],"names":[],"mappings":"AAMA,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,KAAK,EACL,OAAc,EACd,QAAe,EAChB,EAAE,qBAAqB,2CA8OvB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface RadioButtonProps {
|
|
3
|
+
name: string;
|
|
4
|
+
value: string;
|
|
5
|
+
checked: boolean;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
label?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const RadioButton: React.FC<RadioButtonProps>;
|
|
10
|
+
export default RadioButton;
|
|
11
|
+
//# sourceMappingURL=RadioButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioButton.d.ts","sourceRoot":"","sources":["../../src/customRadioButton/RadioButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAuE3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import 'react';
|
|
3
|
+
|
|
4
|
+
var RadioButton = function(param) {
|
|
5
|
+
var name = param.name, value = param.value, checked = param.checked, onChange = param.onChange, label = param.label;
|
|
6
|
+
// Generate a stable id so label could be connected if needed
|
|
7
|
+
var id = "".concat(name, "-").concat(value);
|
|
8
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
9
|
+
className: "tw-flex tw-items-center tw-space-x-3",
|
|
10
|
+
style: {
|
|
11
|
+
display: 'flex',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
gap: 12
|
|
14
|
+
},
|
|
15
|
+
children: [
|
|
16
|
+
/*#__PURE__*/ jsxs("div", {
|
|
17
|
+
className: "tw-relative tw-cursor-pointer",
|
|
18
|
+
style: {
|
|
19
|
+
position: 'relative',
|
|
20
|
+
cursor: 'pointer'
|
|
21
|
+
},
|
|
22
|
+
onClick: function() {
|
|
23
|
+
return onChange(value);
|
|
24
|
+
},
|
|
25
|
+
children: [
|
|
26
|
+
/*#__PURE__*/ jsx("input", {
|
|
27
|
+
id: id,
|
|
28
|
+
type: "radio",
|
|
29
|
+
name: name,
|
|
30
|
+
value: value,
|
|
31
|
+
checked: checked,
|
|
32
|
+
onChange: function() {
|
|
33
|
+
return onChange(value);
|
|
34
|
+
},
|
|
35
|
+
className: "tw-sr-only",
|
|
36
|
+
style: {
|
|
37
|
+
position: 'absolute',
|
|
38
|
+
opacity: 0,
|
|
39
|
+
pointerEvents: 'none',
|
|
40
|
+
width: 0,
|
|
41
|
+
height: 0
|
|
42
|
+
}
|
|
43
|
+
}),
|
|
44
|
+
/*#__PURE__*/ jsx("div", {
|
|
45
|
+
className: "tw-w-[47px] tw-h-[47px] tw-border-[3px] tw-border-black tw-rounded-full tw-bg-white tw-flex tw-items-center tw-justify-center tw-transition-all tw-duration-200 hover:tw-shadow-sm",
|
|
46
|
+
style: {
|
|
47
|
+
width: 52,
|
|
48
|
+
height: 52,
|
|
49
|
+
borderWidth: 3,
|
|
50
|
+
borderStyle: 'solid',
|
|
51
|
+
borderColor: '#000',
|
|
52
|
+
borderRadius: 9999,
|
|
53
|
+
background: '#fff',
|
|
54
|
+
display: 'flex',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'center',
|
|
57
|
+
transition: 'all 200ms'
|
|
58
|
+
},
|
|
59
|
+
children: checked && /*#__PURE__*/ jsx("div", {
|
|
60
|
+
className: "tw-w-[30px] tw-h-[30px] tw-bg-slate-900 tw-rounded-full",
|
|
61
|
+
style: {
|
|
62
|
+
width: 30,
|
|
63
|
+
height: 30,
|
|
64
|
+
background: '#0f172a',
|
|
65
|
+
borderRadius: 9999
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
}),
|
|
71
|
+
label && /*#__PURE__*/ jsx("label", {
|
|
72
|
+
htmlFor: id,
|
|
73
|
+
className: "tw-cursor-pointer tw-text-gray-700 tw-select-none tw-flex tw-items-center tw-leading-none",
|
|
74
|
+
style: {
|
|
75
|
+
cursor: 'pointer',
|
|
76
|
+
color: '#374151',
|
|
77
|
+
userSelect: 'none',
|
|
78
|
+
display: 'inline-flex',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
lineHeight: 1,
|
|
81
|
+
position: 'relative',
|
|
82
|
+
top: 5
|
|
83
|
+
},
|
|
84
|
+
onClick: function() {
|
|
85
|
+
return onChange(value);
|
|
86
|
+
},
|
|
87
|
+
children: label
|
|
88
|
+
})
|
|
89
|
+
]
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export { RadioButton as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -43,4 +43,5 @@ export * from './availability-indicator';
|
|
|
43
43
|
export * from './number-of-people-input';
|
|
44
44
|
export * from './fullscreen-loader';
|
|
45
45
|
export * from './pages';
|
|
46
|
+
export { default as RadioButton } from './customRadioButton/RadioButton';
|
|
46
47
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AACtB,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,oBAAoB,CAAA;AAClC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,SAAS,CAAA;AACvB,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,iCAAiC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -205,6 +205,7 @@ export { useFullscreenLoader } from './fullscreen-loader/useFullscreenLoader.js'
|
|
|
205
205
|
export { FullscreenLoaderContext } from './fullscreen-loader/context.js';
|
|
206
206
|
export { PrivacyComponent } from './pages/PrivacyComponent.js';
|
|
207
207
|
export { TermsComponent } from './pages/TermsComponent.js';
|
|
208
|
+
export { default as RadioButton } from './customRadioButton/RadioButton.js';
|
|
208
209
|
export { default as CountrySelect } from './static/CountrySelect.js';
|
|
209
210
|
export { default as FormCard } from './static/FormCard.js';
|
|
210
211
|
export { default as Image } from './static/Image.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../../../src/sales/guest-profile/profile/Profile.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,sDAAsD,CAAA;AAO5E,KAAK,YAAY,GAAG;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAGrB,CAAA;AAED,eAAO,MAAM,OAAO,aAAc,YAAY,
|
|
1
|
+
{"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../../../src/sales/guest-profile/profile/Profile.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,sDAAsD,CAAA;AAO5E,KAAK,YAAY,GAAG;IAClB,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAGrB,CAAA;AAED,eAAO,MAAM,OAAO,aAAc,YAAY,4CA6C7C,CAAA"}
|
|
@@ -10,7 +10,8 @@ var Profile = function(param) {
|
|
|
10
10
|
if (!user) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
|
-
var firstName = user.firstName, lastName = user.lastName,
|
|
13
|
+
var firstName = user.firstName, lastName = user.lastName, userDetail = user.userDetail;
|
|
14
|
+
var gender = userDetail === null || userDetail === void 0 ? void 0 : userDetail.gender;
|
|
14
15
|
return /*#__PURE__*/ jsx("div", {
|
|
15
16
|
className: "profile",
|
|
16
17
|
children: /*#__PURE__*/ jsxs("div", {
|
package/package.json
CHANGED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { TextInput } from '@mantine/core'
|
|
2
|
+
import { useEffect, useState } from 'react'
|
|
3
|
+
import { Controller, useFormContext } from 'react-hook-form'
|
|
4
|
+
import { DateTime } from 'luxon'
|
|
5
|
+
import { useTranslation } from 'react-i18next'
|
|
6
|
+
|
|
7
|
+
type CustomDatePickerProps = {
|
|
8
|
+
name: string
|
|
9
|
+
error?: string
|
|
10
|
+
label?: string
|
|
11
|
+
showAge?: boolean
|
|
12
|
+
required?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function CustomDatePicker({
|
|
16
|
+
name,
|
|
17
|
+
error,
|
|
18
|
+
showAge = true,
|
|
19
|
+
required = true
|
|
20
|
+
}: CustomDatePickerProps) {
|
|
21
|
+
const { t } = useTranslation()
|
|
22
|
+
const { control, setValue, watch, getValues, trigger, formState } = useFormContext()
|
|
23
|
+
const [age, setAge] = useState<number | null>(null)
|
|
24
|
+
const [localError, setLocalError] = useState<string | null>(null)
|
|
25
|
+
|
|
26
|
+
// Get current field values
|
|
27
|
+
const day = watch(`${name}_day`) || ''
|
|
28
|
+
const month = watch(`${name}_month`) || ''
|
|
29
|
+
const year = watch(`${name}_year`) || ''
|
|
30
|
+
|
|
31
|
+
// Initialize values from existing date
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const existingDate = getValues(name)
|
|
34
|
+
|
|
35
|
+
if (existingDate instanceof Date && !day && !month && !year) {
|
|
36
|
+
const dateTime = DateTime.fromJSDate(existingDate)
|
|
37
|
+
if (dateTime.isValid) {
|
|
38
|
+
setValue(`${name}_day`, dateTime.day.toString().padStart(2, '0'))
|
|
39
|
+
setValue(`${name}_month`, dateTime.month.toString().padStart(2, '0'))
|
|
40
|
+
setValue(`${name}_year`, dateTime.year.toString())
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, [name, setValue, getValues, day, month, year])
|
|
44
|
+
|
|
45
|
+
// Check for empty fields after submit attempt
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (formState.isSubmitted && required) {
|
|
48
|
+
const hasEmptyFields = !day || !month || !year
|
|
49
|
+
|
|
50
|
+
if (hasEmptyFields) {
|
|
51
|
+
setLocalError(t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') }))
|
|
52
|
+
// Set the main field to null to trigger form validation
|
|
53
|
+
setValue(name, null, { shouldValidate: true })
|
|
54
|
+
} else {
|
|
55
|
+
setLocalError(null)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}, [formState.isSubmitted, day, month, year, required, name, setValue, t])
|
|
59
|
+
|
|
60
|
+
// Calculate age and validate date when all fields are filled
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (day && month && year) {
|
|
63
|
+
try {
|
|
64
|
+
// Create a date object
|
|
65
|
+
const dateObj = DateTime.fromObject({
|
|
66
|
+
day: parseInt(day, 10),
|
|
67
|
+
month: parseInt(month, 10),
|
|
68
|
+
year: parseInt(year, 10)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Only proceed if date is valid
|
|
72
|
+
if (dateObj.isValid) {
|
|
73
|
+
// Set the main field value
|
|
74
|
+
setValue(name, dateObj.toJSDate(), { shouldValidate: true })
|
|
75
|
+
setLocalError(null)
|
|
76
|
+
|
|
77
|
+
// Calculate age
|
|
78
|
+
if (showAge) {
|
|
79
|
+
const now = DateTime.now()
|
|
80
|
+
const diff = now.diff(dateObj, 'years')
|
|
81
|
+
setAge(Math.floor(diff.years))
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
setLocalError(t('Validation:fieldInvalid', { attribute: t('App:dateOfBirth') }))
|
|
85
|
+
setValue(name, null, { shouldValidate: true })
|
|
86
|
+
setAge(null)
|
|
87
|
+
}
|
|
88
|
+
} catch (err) {
|
|
89
|
+
// If any parsing fails, just reset the age display
|
|
90
|
+
setLocalError(t('Validation:fieldInvalid', { attribute: t('App:dateOfBirth') }))
|
|
91
|
+
setValue(name, null, { shouldValidate: true })
|
|
92
|
+
setAge(null)
|
|
93
|
+
}
|
|
94
|
+
} else if (formState.isSubmitted && required) {
|
|
95
|
+
// If form was submitted and fields are required but not all filled
|
|
96
|
+
setLocalError(t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') }))
|
|
97
|
+
setValue(name, null, { shouldValidate: true })
|
|
98
|
+
setAge(null)
|
|
99
|
+
} else {
|
|
100
|
+
// Reset if not all fields are filled but not submitted yet
|
|
101
|
+
setValue(name, null, { shouldValidate: false })
|
|
102
|
+
setAge(null)
|
|
103
|
+
}
|
|
104
|
+
}, [day, month, year, name, setValue, showAge, formState.isSubmitted, required, t])
|
|
105
|
+
|
|
106
|
+
// After user completes all fields, validate the form
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (day && month && year) {
|
|
109
|
+
trigger(name)
|
|
110
|
+
}
|
|
111
|
+
}, [day, month, year, name, trigger])
|
|
112
|
+
|
|
113
|
+
// Display either the form error or our local error
|
|
114
|
+
const displayError = error || localError
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="tw-w-full">
|
|
118
|
+
<div className="tw-flex tw-flex-col">
|
|
119
|
+
<div className="tw-mb-2 tw-flex tw-items-center tw-justify-between">
|
|
120
|
+
<label className="tw-font-semibold">
|
|
121
|
+
{t('App:dateOfBirth')}
|
|
122
|
+
{required && <span className="tw-ml-1 tw-text-red-500"></span>}
|
|
123
|
+
</label>
|
|
124
|
+
{age !== null && (
|
|
125
|
+
<span className="tw-text-sm tw-text-gray-600">
|
|
126
|
+
{t('App:Age')}: {age}
|
|
127
|
+
</span>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div className="tw-flex tw-flex-row tw-gap-4">
|
|
132
|
+
<div className="tw-w-1/3">
|
|
133
|
+
<label className="tw-mb-1 tw-block tw-text-sm">{t('App:Day')}</label>
|
|
134
|
+
<Controller
|
|
135
|
+
control={control}
|
|
136
|
+
name={`${name}_day`}
|
|
137
|
+
defaultValue=""
|
|
138
|
+
render={({ field }) => (
|
|
139
|
+
<TextInput
|
|
140
|
+
{...field}
|
|
141
|
+
value={field.value || ''}
|
|
142
|
+
placeholder="DD"
|
|
143
|
+
maxLength={2}
|
|
144
|
+
error={!!displayError}
|
|
145
|
+
classNames={{ input: 'tw-placeholder-[#626A90]' }}
|
|
146
|
+
styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
|
|
147
|
+
onChange={(e) => {
|
|
148
|
+
const value = e.target.value.replace(/[^0-9]/g, '')
|
|
149
|
+
field.onChange(value)
|
|
150
|
+
}}
|
|
151
|
+
onBlur={(e) => {
|
|
152
|
+
// Validate and format on blur
|
|
153
|
+
let value = e.target.value.replace(/[^0-9]/g, '')
|
|
154
|
+
if (value) {
|
|
155
|
+
const num = parseInt(value, 10)
|
|
156
|
+
if (num < 1) value = '01'
|
|
157
|
+
else if (num > 31) value = '31'
|
|
158
|
+
else value = num.toString().padStart(2, '0')
|
|
159
|
+
}
|
|
160
|
+
field.onChange(value)
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
164
|
+
/>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<div className="tw-w-1/3">
|
|
168
|
+
<label className="tw-mb-1 tw-block tw-text-sm">{t('App:Month')}</label>
|
|
169
|
+
<Controller
|
|
170
|
+
control={control}
|
|
171
|
+
name={`${name}_month`}
|
|
172
|
+
defaultValue=""
|
|
173
|
+
render={({ field }) => (
|
|
174
|
+
<TextInput
|
|
175
|
+
{...field}
|
|
176
|
+
value={field.value || ''}
|
|
177
|
+
placeholder="MM"
|
|
178
|
+
maxLength={2}
|
|
179
|
+
error={!!displayError}
|
|
180
|
+
classNames={{ input: 'tw-placeholder-[#626A90]' }}
|
|
181
|
+
styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
|
|
182
|
+
onChange={(e) => {
|
|
183
|
+
const value = e.target.value.replace(/[^0-9]/g, '')
|
|
184
|
+
field.onChange(value)
|
|
185
|
+
}}
|
|
186
|
+
onBlur={(e) => {
|
|
187
|
+
// Validate and format on blur
|
|
188
|
+
let value = e.target.value.replace(/[^0-9]/g, '')
|
|
189
|
+
if (value) {
|
|
190
|
+
const num = parseInt(value, 10)
|
|
191
|
+
if (num < 1) value = '01'
|
|
192
|
+
else if (num > 12) value = '12'
|
|
193
|
+
else value = num.toString().padStart(2, '0')
|
|
194
|
+
}
|
|
195
|
+
field.onChange(value)
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
)}
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div className="tw-w-1/3">
|
|
203
|
+
<label className="tw-mb-1 tw-block tw-text-sm">{t('App:Year')}</label>
|
|
204
|
+
<Controller
|
|
205
|
+
control={control}
|
|
206
|
+
name={`${name}_year`}
|
|
207
|
+
defaultValue=""
|
|
208
|
+
render={({ field }) => (
|
|
209
|
+
<TextInput
|
|
210
|
+
{...field}
|
|
211
|
+
value={field.value || ''}
|
|
212
|
+
placeholder="YYYY"
|
|
213
|
+
maxLength={4}
|
|
214
|
+
error={!!displayError}
|
|
215
|
+
classNames={{ input: 'tw-placeholder-[#626A90]' }}
|
|
216
|
+
styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
|
|
217
|
+
onChange={(e) => {
|
|
218
|
+
const value = e.target.value.replace(/[^0-9]/g, '')
|
|
219
|
+
field.onChange(value)
|
|
220
|
+
}}
|
|
221
|
+
onBlur={(e) => {
|
|
222
|
+
// Validate on blur
|
|
223
|
+
const value = e.target.value.replace(/[^0-9]/g, '')
|
|
224
|
+
if (value) {
|
|
225
|
+
const num = parseInt(value, 10)
|
|
226
|
+
const currentYear = new Date().getFullYear()
|
|
227
|
+
if (num > currentYear) {
|
|
228
|
+
field.onChange(currentYear.toString())
|
|
229
|
+
} else if (num < 1900) {
|
|
230
|
+
field.onChange('1900')
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}}
|
|
234
|
+
/>
|
|
235
|
+
)}
|
|
236
|
+
/>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
{/* Hidden field to store the actual date value */}
|
|
242
|
+
<Controller
|
|
243
|
+
control={control}
|
|
244
|
+
name={name}
|
|
245
|
+
defaultValue={null}
|
|
246
|
+
rules={{
|
|
247
|
+
validate: value => {
|
|
248
|
+
if (required && !value) {
|
|
249
|
+
return t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') })
|
|
250
|
+
}
|
|
251
|
+
return true
|
|
252
|
+
}
|
|
253
|
+
}}
|
|
254
|
+
render={() => <input type="hidden" />}
|
|
255
|
+
/>
|
|
256
|
+
</div>
|
|
257
|
+
)
|
|
258
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface RadioButtonProps {
|
|
4
|
+
name: string;
|
|
5
|
+
value: string;
|
|
6
|
+
checked: boolean;
|
|
7
|
+
onChange: (value: string) => void;
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const RadioButton: React.FC<RadioButtonProps> = ({
|
|
12
|
+
name,
|
|
13
|
+
value,
|
|
14
|
+
checked,
|
|
15
|
+
onChange,
|
|
16
|
+
label
|
|
17
|
+
}) => {
|
|
18
|
+
// Generate a stable id so label could be connected if needed
|
|
19
|
+
const id = `${name}-${value}`;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div
|
|
23
|
+
className="tw-flex tw-items-center tw-space-x-3"
|
|
24
|
+
style={{ display: 'flex', alignItems: 'center', gap: 12 }}
|
|
25
|
+
>
|
|
26
|
+
<div
|
|
27
|
+
className="tw-relative tw-cursor-pointer"
|
|
28
|
+
style={{ position: 'relative', cursor: 'pointer' }}
|
|
29
|
+
onClick={() => onChange(value)}
|
|
30
|
+
>
|
|
31
|
+
{/* Hidden native radio input for accessibility */}
|
|
32
|
+
<input
|
|
33
|
+
id={id}
|
|
34
|
+
type="radio"
|
|
35
|
+
name={name}
|
|
36
|
+
value={value}
|
|
37
|
+
checked={checked}
|
|
38
|
+
onChange={() => onChange(value)}
|
|
39
|
+
className="tw-sr-only"
|
|
40
|
+
style={{ position: 'absolute', opacity: 0, pointerEvents: 'none', width: 0, height: 0 }}
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
{/* Custom radio button circle */}
|
|
44
|
+
<div
|
|
45
|
+
className="tw-w-[47px] tw-h-[47px] tw-border-[3px] tw-border-black tw-rounded-full tw-bg-white tw-flex tw-items-center tw-justify-center tw-transition-all tw-duration-200 hover:tw-shadow-sm"
|
|
46
|
+
style={{
|
|
47
|
+
width: 52,
|
|
48
|
+
height: 52,
|
|
49
|
+
borderWidth: 3,
|
|
50
|
+
borderStyle: 'solid',
|
|
51
|
+
borderColor: '#000',
|
|
52
|
+
borderRadius: 9999,
|
|
53
|
+
background: '#fff',
|
|
54
|
+
display: 'flex',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'center',
|
|
57
|
+
transition: 'all 200ms',
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
{/* Inner filled circle when selected */}
|
|
61
|
+
{checked && (
|
|
62
|
+
<div
|
|
63
|
+
className="tw-w-[30px] tw-h-[30px] tw-bg-slate-900 tw-rounded-full"
|
|
64
|
+
style={{ width: 30, height: 30, background: '#0f172a', borderRadius: 9999 }}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{label && (
|
|
71
|
+
<label
|
|
72
|
+
htmlFor={id}
|
|
73
|
+
className="tw-cursor-pointer tw-text-gray-700 tw-select-none tw-flex tw-items-center tw-leading-none"
|
|
74
|
+
style={{ cursor: 'pointer', color: '#374151', userSelect: 'none', display: 'inline-flex', alignItems: 'center', lineHeight: 1, position: 'relative', top: 5 }}
|
|
75
|
+
onClick={() => onChange(value)}
|
|
76
|
+
>
|
|
77
|
+
{label}
|
|
78
|
+
</label>
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default RadioButton;
|
package/src/index.ts
CHANGED
|
@@ -16,11 +16,8 @@ export const Profile = ({ user }: ProfileProps) => {
|
|
|
16
16
|
return null
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const {
|
|
20
|
-
|
|
21
|
-
lastName,
|
|
22
|
-
userDetail: { gender },
|
|
23
|
-
} = user
|
|
19
|
+
const { firstName, lastName, userDetail } = user
|
|
20
|
+
const gender = userDetail?.gender
|
|
24
21
|
|
|
25
22
|
return (
|
|
26
23
|
<div className='profile'>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { alertThemes } from "./alertThemes";
|
|
2
|
-
export interface AlertConfig {
|
|
3
|
-
type: keyof typeof alertThemes;
|
|
4
|
-
title?: string;
|
|
5
|
-
subTitle?: string;
|
|
6
|
-
message?: string | string[];
|
|
7
|
-
description?: string;
|
|
8
|
-
actionText?: string;
|
|
9
|
-
secondaryActionText?: string;
|
|
10
|
-
onAction?: (() => void) | null;
|
|
11
|
-
onSecondaryAction?: (() => void) | null;
|
|
12
|
-
timeout?: number;
|
|
13
|
-
closable?: boolean;
|
|
14
|
-
titleColor?: string;
|
|
15
|
-
subTitleColor?: string;
|
|
16
|
-
showArrow?: boolean;
|
|
17
|
-
showSecondaryArrow?: boolean;
|
|
18
|
-
alignActionsRight?: boolean;
|
|
19
|
-
mount?: "container" | "global";
|
|
20
|
-
}
|
|
21
|
-
export declare function showAlert(config: AlertConfig): void;
|
|
22
|
-
//# sourceMappingURL=AlertBox.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AlertBox.d.ts","sourceRoot":"","sources":["../../src/CustomAlertTypes/AlertBox.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,OAAO,WAAW,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;CAChC;AAqDD,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,QAW5C"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { AlertConfig } from './AlertBox';
|
|
3
|
-
export declare class AlertRenderer {
|
|
4
|
-
static createAlert(config: AlertConfig, onClose: () => void): React.DetailedReactHTMLElement<{
|
|
5
|
-
style: {
|
|
6
|
-
backgroundColor: string;
|
|
7
|
-
border: string;
|
|
8
|
-
borderRadius: string;
|
|
9
|
-
padding: string;
|
|
10
|
-
width: string;
|
|
11
|
-
maxWidth: string;
|
|
12
|
-
margin: string;
|
|
13
|
-
pointerEvents: "auto";
|
|
14
|
-
fontFamily: string;
|
|
15
|
-
position: "relative";
|
|
16
|
-
overflow: "hidden";
|
|
17
|
-
boxSizing: "border-box";
|
|
18
|
-
};
|
|
19
|
-
}, HTMLElement>;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=AlertRender.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AlertRender.d.ts","sourceRoot":"","sources":["../../src/CustomAlertTypes/AlertRender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,qBAAa,aAAa;IACxB,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,IAAI;;;;;;;;;;;;;;;;CAoR5D"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export declare const ErrorIcon: () => React.ReactSVGElement;
|
|
3
|
-
export declare const SuccessIcon: () => React.ReactSVGElement;
|
|
4
|
-
export declare const InfoIcon: () => React.ReactSVGElement;
|
|
5
|
-
export declare const WarningIcon: () => React.ReactSVGElement;
|
|
6
|
-
export declare const commonStyle: {
|
|
7
|
-
fontFamily: string;
|
|
8
|
-
color: string;
|
|
9
|
-
borderRad: string;
|
|
10
|
-
};
|
|
11
|
-
export declare const alertThemes: {
|
|
12
|
-
error: {
|
|
13
|
-
bg: string;
|
|
14
|
-
border: string;
|
|
15
|
-
icon: string;
|
|
16
|
-
IconComponent: () => React.ReactSVGElement;
|
|
17
|
-
defaultTitle: string;
|
|
18
|
-
};
|
|
19
|
-
success: {
|
|
20
|
-
bg: string;
|
|
21
|
-
border: string;
|
|
22
|
-
icon: string;
|
|
23
|
-
IconComponent: () => React.ReactSVGElement;
|
|
24
|
-
defaultTitle: string;
|
|
25
|
-
};
|
|
26
|
-
warning: {
|
|
27
|
-
bg: string;
|
|
28
|
-
border: string;
|
|
29
|
-
icon: string;
|
|
30
|
-
IconComponent: () => React.ReactSVGElement;
|
|
31
|
-
defaultTitle: string;
|
|
32
|
-
};
|
|
33
|
-
info: {
|
|
34
|
-
bg: string;
|
|
35
|
-
border: string;
|
|
36
|
-
icon: string;
|
|
37
|
-
IconComponent: () => React.ReactSVGElement;
|
|
38
|
-
defaultTitle: string;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
//# sourceMappingURL=alertThemes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"alertThemes.d.ts","sourceRoot":"","sources":["../../src/CustomAlertTypes/alertThemes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AA8B1B,eAAO,MAAM,SAAS,6BAA0C,CAAC;AACjE,eAAO,MAAM,WAAW,6BAA4C,CAAC;AACrE,eAAO,MAAM,QAAQ,6BAAyC,CAAC;AAC/D,eAAO,MAAM,WAAW,6BAA4C,CAAC;AAErE,eAAO,MAAM,WAAW;;;;CAIvB,CAAA;AAGD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BvB,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wraps text into multiple lines by word count limit.
|
|
3
|
-
* @param text - The input string
|
|
4
|
-
* @param limit - Max characters per line
|
|
5
|
-
* @returns Wrapped text as a single string with newlines
|
|
6
|
-
*/
|
|
7
|
-
export declare function wrapText(text: string, limit: number): string;
|
|
8
|
-
//# sourceMappingURL=textWrapperUtils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"textWrapperUtils.d.ts","sourceRoot":"","sources":["../../../src/CustomAlertTypes/utils/textWrapperUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAmB5D"}
|