@temboplus/frontend-react-core 0.1.3-beta.0 → 0.1.3-beta.2
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/InfoCircleOutlined-B7d2aRfV.js +7 -0
- package/dist/InfoCircleOutlined-B7d2aRfV.js.map +1 -0
- package/dist/InfoCircleOutlined-DYs90hdV.js +7 -0
- package/dist/InfoCircleOutlined-DYs90hdV.js.map +1 -0
- package/dist/ZoomOutOutlined-BL6A5RSq.js +2 -0
- package/dist/ZoomOutOutlined-BL6A5RSq.js.map +1 -0
- package/dist/ZoomOutOutlined-BY_CCwq7.js +2 -0
- package/dist/ZoomOutOutlined-BY_CCwq7.js.map +1 -0
- package/dist/alerts/index.cjs.js +2 -0
- package/dist/alerts/index.cjs.js.map +1 -0
- package/dist/alerts/index.d.ts +1 -0
- package/dist/alerts/index.js +2 -0
- package/dist/alerts/index.js.map +1 -0
- package/dist/dialogs/index.cjs.js +2 -0
- package/dist/dialogs/index.cjs.js.map +1 -0
- package/dist/dialogs/index.d.ts +1 -0
- package/dist/dialogs/index.js +2 -0
- package/dist/dialogs/index.js.map +1 -0
- package/dist/features/alerts/alert.d.ts +12 -0
- package/dist/features/alerts/alert.js +95 -0
- package/dist/features/alerts/index.d.ts +1 -0
- package/dist/features/alerts/index.js +1 -0
- package/dist/features/dialogs/index.d.ts +1 -0
- package/dist/features/dialogs/index.js +1 -0
- package/dist/features/dialogs/modal-provider.d.ts +3 -0
- package/dist/features/dialogs/modal-provider.js +6 -0
- package/dist/features/dialogs/tembo-confirm.d.ts +63 -0
- package/dist/features/dialogs/tembo-confirm.js +111 -0
- package/dist/features/input-validation/account-name-validator.d.ts +13 -0
- package/dist/features/input-validation/account-name-validator.js +28 -0
- package/dist/features/input-validation/account-number-validator.d.ts +13 -0
- package/dist/features/input-validation/account-number-validator.js +65 -0
- package/dist/{antd-validators.d.ts → features/input-validation/amount-validator.d.ts} +1 -62
- package/dist/features/input-validation/amount-validator.js +100 -0
- package/dist/features/input-validation/index.d.ts +5 -0
- package/dist/features/input-validation/index.js +5 -0
- package/dist/features/input-validation/phone-number-validator.d.ts +25 -0
- package/dist/features/input-validation/phone-number-validator.js +79 -0
- package/dist/features/input-validation/swift-code-validator.d.ts +13 -0
- package/dist/features/input-validation/swift-code-validator.js +38 -0
- package/dist/features/notifications/index.d.ts +3 -0
- package/dist/features/notifications/index.js +3 -0
- package/dist/features/notifications/tembo-notify.d.ts +124 -0
- package/dist/features/notifications/tembo-notify.js +149 -0
- package/dist/features/notifications/toast-config.d.ts +15 -0
- package/dist/features/notifications/toast-config.js +53 -0
- package/dist/features/notifications/toast-container.d.ts +9 -0
- package/dist/features/notifications/toast-container.js +18 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/notifications/index.cjs.js +2 -0
- package/dist/notifications/index.cjs.js.map +1 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.js +2 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/providers.d.ts +37 -0
- package/dist/providers.js +32 -0
- package/dist/tembo-notify-C-QGduBt.js +2 -0
- package/dist/tembo-notify-C-QGduBt.js.map +1 -0
- package/dist/tembo-notify-D-uOV3t0.js +2 -0
- package/dist/tembo-notify-D-uOV3t0.js.map +1 -0
- package/dist/theme/colors.d.ts +246 -0
- package/dist/theme/colors.js +138 -0
- package/dist/theme/constants.d.ts +143 -0
- package/dist/theme/constants.js +82 -0
- package/dist/theme/index.cjs.js +2 -0
- package/dist/theme/index.cjs.js.map +1 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-provider.d.ts +87 -0
- package/dist/theme/theme-provider.js +398 -0
- package/dist/theme-provider-D_oV1J_K.js +11 -0
- package/dist/theme-provider-D_oV1J_K.js.map +1 -0
- package/dist/theme-provider-Dqvy24OD.js +11 -0
- package/dist/theme-provider-Dqvy24OD.js.map +1 -0
- package/dist/validation/index.cjs.js +2 -0
- package/dist/validation/index.cjs.js.map +1 -0
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +2 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +31 -7
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Amount } from "@temboplus/frontend-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a validator for monetary amounts using the Amount class.
|
|
4
|
+
* Validates format, currency, and range constraints with currency-specific defaults.
|
|
5
|
+
* Only allows positive amounts (including zero).
|
|
6
|
+
*
|
|
7
|
+
* **Default Range Constraints by Currency:**
|
|
8
|
+
* - **TZS (Tanzanian Shilling)**: Min: 1,000 TZS, Max: 1,000,000 TZS
|
|
9
|
+
* - **KES (Kenyan Shilling)**: Min: 40 KES, Max: 40,000,000 KES
|
|
10
|
+
* - **Other Currencies**: Min: 1, Max: 1,000,000 (in respective currency units)
|
|
11
|
+
*
|
|
12
|
+
* These defaults are applied only when `min` and/or `max` options are not explicitly provided.
|
|
13
|
+
* You can override these defaults by providing explicit `min` and `max` values in the options.
|
|
14
|
+
* Set `min` or `max` to `null` to completely disable that constraint.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Configuration options for amount validation
|
|
17
|
+
* @returns Validator function for AntD form rules
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Basic validation with TZS currency (uses default min: 1,000 TZS, max: 1,000,000 TZS)
|
|
21
|
+
* rules: [{ required: true, validator: AMOUNT_VALIDATOR() }]
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Basic validation with KES currency (uses default min: 40 KES, max: 40,000,000 KES)
|
|
25
|
+
* rules: [{ required: true, validator: AMOUNT_VALIDATOR({ currencyCode: 'KES' }) }]
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Override default ranges with custom min/max values
|
|
29
|
+
* rules: [{
|
|
30
|
+
* required: true,
|
|
31
|
+
* validator: AMOUNT_VALIDATOR({
|
|
32
|
+
* currencyCode: 'USD',
|
|
33
|
+
* min: 1, // Custom minimum (overrides default)
|
|
34
|
+
* max: 10000, // Custom maximum (overrides default)
|
|
35
|
+
* })
|
|
36
|
+
* }]
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Disable range validation by setting min and max to null
|
|
40
|
+
* rules: [{
|
|
41
|
+
* required: true,
|
|
42
|
+
* validator: AMOUNT_VALIDATOR({
|
|
43
|
+
* currencyCode: 'USD',
|
|
44
|
+
* min: null, // No minimum constraint
|
|
45
|
+
* max: null, // No maximum constraint
|
|
46
|
+
* })
|
|
47
|
+
* }]
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Disable only minimum constraint, keep maximum
|
|
51
|
+
* rules: [{
|
|
52
|
+
* required: true,
|
|
53
|
+
* validator: AMOUNT_VALIDATOR({
|
|
54
|
+
* currencyCode: 'TZS',
|
|
55
|
+
* min: null, // No minimum constraint
|
|
56
|
+
* // max uses default (1,000,000 TZS)
|
|
57
|
+
* })
|
|
58
|
+
* }]
|
|
59
|
+
*/
|
|
60
|
+
export const AMOUNT_VALIDATOR = (options = {}) => {
|
|
61
|
+
const { currencyCode = "TZS", invalidFormatMessage, minMessage, maxMessage, } = options;
|
|
62
|
+
const { min: defaultMin, max: defaultMax } = Amount.getTransactionLimits(currencyCode);
|
|
63
|
+
// Use provided values, or fall back to currency-specific defaults
|
|
64
|
+
// If explicitly set to null, no constraint will be applied
|
|
65
|
+
const min = options.min !== undefined ? options.min : defaultMin;
|
|
66
|
+
const max = options.max !== undefined ? options.max : defaultMax;
|
|
67
|
+
return (rule, value) => {
|
|
68
|
+
// Convert value to string for processing
|
|
69
|
+
const amountString = value === null || value === void 0 ? void 0 : value.toString().trim();
|
|
70
|
+
// If field is empty/undefined/null
|
|
71
|
+
if (!amountString) {
|
|
72
|
+
if (rule.required) {
|
|
73
|
+
return Promise.reject(new Error("Amount is required."));
|
|
74
|
+
}
|
|
75
|
+
return Promise.resolve(undefined);
|
|
76
|
+
}
|
|
77
|
+
// Try to create Amount instance
|
|
78
|
+
const amountInstance = Amount.from(amountString, currencyCode);
|
|
79
|
+
if (!amountInstance) {
|
|
80
|
+
return Promise.reject(new Error(invalidFormatMessage ||
|
|
81
|
+
`Invalid amount format. Please enter a valid monetary amount (e.g., "1000", "1,234.56").`));
|
|
82
|
+
}
|
|
83
|
+
// Reject negative amounts (always not allowed)
|
|
84
|
+
if (amountInstance.isNegative()) {
|
|
85
|
+
return Promise.reject(new Error("Negative amounts are not allowed. Please enter a positive amount."));
|
|
86
|
+
}
|
|
87
|
+
// Check minimum constraint (only if min is not null)
|
|
88
|
+
if (min !== null && amountInstance.lessThan(min)) {
|
|
89
|
+
return Promise.reject(new Error(minMessage ||
|
|
90
|
+
`Amount must be at least ${(defaultMin === null || defaultMin === void 0 ? void 0 : defaultMin.label) || min}. Please enter a higher amount.`));
|
|
91
|
+
}
|
|
92
|
+
// Check maximum constraint (only if max is not null)
|
|
93
|
+
if (max !== null && amountInstance.greaterThan(max)) {
|
|
94
|
+
return Promise.reject(new Error(maxMessage ||
|
|
95
|
+
`Amount must not exceed ${(defaultMax === null || defaultMax === void 0 ? void 0 : defaultMax.label) || max}. Please enter a lower amount.`));
|
|
96
|
+
}
|
|
97
|
+
// Return the formatted numeric value (normalized)
|
|
98
|
+
return Promise.resolve(amountInstance.formattedNumericValue);
|
|
99
|
+
};
|
|
100
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ISO2CountryCode } from "@temboplus/frontend-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a validator for general phone numbers that validates format and country.
|
|
4
|
+
* Uses PhoneNumberFactory.canCreate() for validation.
|
|
5
|
+
*
|
|
6
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
7
|
+
* @returns Validator function for AntD form rules
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // In form rules
|
|
11
|
+
* rules: [{ required: true, validator: PHONE_NUMBER_VALIDATOR('TZ') }]
|
|
12
|
+
*/
|
|
13
|
+
export declare const PHONE_NUMBER_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a validator for mobile phone numbers eligible for payout operations.
|
|
16
|
+
* Uses PhoneNumberFactory.checkPayoutEligibility() for validation.
|
|
17
|
+
*
|
|
18
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
19
|
+
* @returns Validator function for AntD form rules
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // In form rules
|
|
23
|
+
* rules: [{ required: true, validator: MOBILE_PHONE_VALIDATOR('TZ') }]
|
|
24
|
+
*/
|
|
25
|
+
export declare const MOBILE_PHONE_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Country, PhoneNumberFactory } from "@temboplus/frontend-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a validator for general phone numbers that validates format and country.
|
|
4
|
+
* Uses PhoneNumberFactory.canCreate() for validation.
|
|
5
|
+
*
|
|
6
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
7
|
+
* @returns Validator function for AntD form rules
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // In form rules
|
|
11
|
+
* rules: [{ required: true, validator: PHONE_NUMBER_VALIDATOR('TZ') }]
|
|
12
|
+
*/
|
|
13
|
+
export const PHONE_NUMBER_VALIDATOR = (countryCode) => {
|
|
14
|
+
return (rule, value) => {
|
|
15
|
+
var _a;
|
|
16
|
+
const phoneString = value === null || value === void 0 ? void 0 : value.toString().trim();
|
|
17
|
+
// If field is empty/undefined/null
|
|
18
|
+
if (!phoneString) {
|
|
19
|
+
if (rule.required) {
|
|
20
|
+
return Promise.reject(new Error("Phone number is required."));
|
|
21
|
+
}
|
|
22
|
+
return Promise.resolve(undefined);
|
|
23
|
+
}
|
|
24
|
+
const isValid = PhoneNumberFactory.canCreate(phoneString, {
|
|
25
|
+
defaultCountry: countryCode,
|
|
26
|
+
});
|
|
27
|
+
if (isValid) {
|
|
28
|
+
// Return normalized phone number
|
|
29
|
+
const phoneInstance = PhoneNumberFactory.create(phoneString, {
|
|
30
|
+
defaultCountry: countryCode,
|
|
31
|
+
});
|
|
32
|
+
return Promise.resolve((phoneInstance === null || phoneInstance === void 0 ? void 0 : phoneInstance.e164Format) || phoneString);
|
|
33
|
+
}
|
|
34
|
+
if (countryCode) {
|
|
35
|
+
const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
|
|
36
|
+
return Promise.reject(new Error(`Invalid ${countryName} phone number format. Please enter a valid ${countryName} phone number.`));
|
|
37
|
+
}
|
|
38
|
+
return Promise.reject(new Error("This phone number is invalid."));
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Creates a validator for mobile phone numbers eligible for payout operations.
|
|
43
|
+
* Uses PhoneNumberFactory.checkPayoutEligibility() for validation.
|
|
44
|
+
*
|
|
45
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
46
|
+
* @returns Validator function for AntD form rules
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // In form rules
|
|
50
|
+
* rules: [{ required: true, validator: MOBILE_PHONE_VALIDATOR('TZ') }]
|
|
51
|
+
*/
|
|
52
|
+
export const MOBILE_PHONE_VALIDATOR = (countryCode) => {
|
|
53
|
+
return (rule, value) => {
|
|
54
|
+
var _a;
|
|
55
|
+
const phoneString = value === null || value === void 0 ? void 0 : value.toString().trim();
|
|
56
|
+
// If field is empty/undefined/null
|
|
57
|
+
if (!phoneString) {
|
|
58
|
+
if (rule.required) {
|
|
59
|
+
return Promise.reject(new Error("Mobile phone number is required."));
|
|
60
|
+
}
|
|
61
|
+
return Promise.resolve(undefined);
|
|
62
|
+
}
|
|
63
|
+
const phoneInstance = PhoneNumberFactory.create(phoneString, {
|
|
64
|
+
defaultCountry: countryCode,
|
|
65
|
+
});
|
|
66
|
+
if (!phoneInstance) {
|
|
67
|
+
return Promise.reject(new Error("This phone number is invalid."));
|
|
68
|
+
}
|
|
69
|
+
const isEligibleForPayout = PhoneNumberFactory.checkPayoutEligibility(phoneInstance);
|
|
70
|
+
if (isEligibleForPayout) {
|
|
71
|
+
return Promise.resolve((phoneInstance === null || phoneInstance === void 0 ? void 0 : phoneInstance.e164Format) || phoneString);
|
|
72
|
+
}
|
|
73
|
+
if (countryCode) {
|
|
74
|
+
const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
|
|
75
|
+
return Promise.reject(new Error(`Invalid ${countryName} phone number format. Please enter a valid ${countryName} phone number.`));
|
|
76
|
+
}
|
|
77
|
+
return Promise.reject(new Error("This phone number is invalid."));
|
|
78
|
+
};
|
|
79
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ISO2CountryCode } from "@temboplus/frontend-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a validator for SWIFT/BIC codes specific to a country.
|
|
4
|
+
* Uses BankValidation.validateSwiftCode() for validation.
|
|
5
|
+
*
|
|
6
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
7
|
+
* @returns Validator function for AntD form rules
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // In form rules
|
|
11
|
+
* rules: [{ required: true, validator: SWIFT_CODE_VALIDATOR('TZ') }]
|
|
12
|
+
*/
|
|
13
|
+
export declare const SWIFT_CODE_VALIDATOR: (countryCode?: ISO2CountryCode) => (rule: any, value: string | null | undefined) => Promise<string | undefined>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BankValidation, Country } from "@temboplus/frontend-core";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a validator for SWIFT/BIC codes specific to a country.
|
|
4
|
+
* Uses BankValidation.validateSwiftCode() for validation.
|
|
5
|
+
*
|
|
6
|
+
* @param countryCode - The ISO2 country code for validation context
|
|
7
|
+
* @returns Validator function for AntD form rules
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // In form rules
|
|
11
|
+
* rules: [{ required: true, validator: SWIFT_CODE_VALIDATOR('TZ') }]
|
|
12
|
+
*/
|
|
13
|
+
export const SWIFT_CODE_VALIDATOR = (countryCode) => {
|
|
14
|
+
return (rule, value) => {
|
|
15
|
+
var _a;
|
|
16
|
+
const swiftCodeString = value === null || value === void 0 ? void 0 : value.toString().trim().toUpperCase();
|
|
17
|
+
// If field is empty/undefined/null
|
|
18
|
+
if (!swiftCodeString) {
|
|
19
|
+
if (rule.required) {
|
|
20
|
+
return Promise.reject(new Error("SWIFT code is required."));
|
|
21
|
+
}
|
|
22
|
+
return Promise.resolve(undefined);
|
|
23
|
+
}
|
|
24
|
+
if (countryCode) {
|
|
25
|
+
const isValid = BankValidation.validateSwiftCode(swiftCodeString, countryCode);
|
|
26
|
+
if (isValid) {
|
|
27
|
+
return Promise.resolve(swiftCodeString);
|
|
28
|
+
}
|
|
29
|
+
const countryName = (_a = Country.from(countryCode)) === null || _a === void 0 ? void 0 : _a.name;
|
|
30
|
+
return Promise.reject(new Error(`Invalid ${countryName} SWIFT code. Please enter a valid ${countryName} bank SWIFT/BIC code.`));
|
|
31
|
+
}
|
|
32
|
+
const isValid = BankValidation.validateSwiftCodeForAnyCountry(swiftCodeString);
|
|
33
|
+
if (isValid) {
|
|
34
|
+
return Promise.resolve(swiftCodeString);
|
|
35
|
+
}
|
|
36
|
+
return Promise.reject(new Error(`Invalid SWIFT code. Please enter a valid supported bank SWIFT/BIC code.`));
|
|
37
|
+
};
|
|
38
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ToastOptions, ToastContent, Id } from 'react-toastify';
|
|
2
|
+
import { TemboColorPalette, TemboUIConstants } from '../../theme/index.js';
|
|
3
|
+
export interface NotifyOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Duration in milliseconds before auto-closing (default: 4000 for most, 6000 for errors)
|
|
6
|
+
* Set to false to prevent auto-close
|
|
7
|
+
*/
|
|
8
|
+
duration?: number | false;
|
|
9
|
+
/**
|
|
10
|
+
* Custom position for the notification
|
|
11
|
+
*/
|
|
12
|
+
position?: ToastOptions['position'];
|
|
13
|
+
/**
|
|
14
|
+
* Callback when notification is clicked
|
|
15
|
+
*/
|
|
16
|
+
onClick?: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Callback when notification is closed
|
|
19
|
+
*/
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* TemboNotify - Unified notification system
|
|
24
|
+
*
|
|
25
|
+
* Wraps react-toastify with consistent styling and behavior
|
|
26
|
+
* aligned with Tembo's design system.
|
|
27
|
+
*
|
|
28
|
+
* Note: This class needs to be initialized with theme tokens before use.
|
|
29
|
+
* Call TemboNotify.init(colors, constants) in your app setup.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* // In your app setup (e.g., App.tsx)
|
|
34
|
+
* const { colors, constants } = useTemboTheme();
|
|
35
|
+
* useEffect(() => {
|
|
36
|
+
* TemboNotify.init(colors, constants);
|
|
37
|
+
* }, [colors, constants]);
|
|
38
|
+
*
|
|
39
|
+
* // Then use anywhere in your app
|
|
40
|
+
* TemboNotify.success('Payment sent successfully!');
|
|
41
|
+
*
|
|
42
|
+
* // With options
|
|
43
|
+
* TemboNotify.error('Payment failed', {
|
|
44
|
+
* duration: 8000,
|
|
45
|
+
* onClick: () => console.log('Error clicked')
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* // Loading with promise
|
|
49
|
+
* const loadingId = TemboNotify.loading('Processing payment...');
|
|
50
|
+
* await processPayment();
|
|
51
|
+
* TemboNotify.success('Payment complete!', { id: loadingId });
|
|
52
|
+
*
|
|
53
|
+
* // Promise-based
|
|
54
|
+
* TemboNotify.promise(
|
|
55
|
+
* apiCall(),
|
|
56
|
+
* {
|
|
57
|
+
* pending: 'Processing...',
|
|
58
|
+
* success: 'Done!',
|
|
59
|
+
* error: 'Failed!'
|
|
60
|
+
* }
|
|
61
|
+
* );
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare class TemboNotify {
|
|
65
|
+
private static configs;
|
|
66
|
+
/**
|
|
67
|
+
* Initialize TemboNotify with theme tokens
|
|
68
|
+
* Must be called before using any notification methods
|
|
69
|
+
*/
|
|
70
|
+
static init(colors: TemboColorPalette, constants: TemboUIConstants): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get current toast configs, throws if not initialized
|
|
73
|
+
*/
|
|
74
|
+
private static getConfigs;
|
|
75
|
+
/**
|
|
76
|
+
* Display a success notification
|
|
77
|
+
*/
|
|
78
|
+
static success(message: ToastContent, options?: NotifyOptions): Id;
|
|
79
|
+
/**
|
|
80
|
+
* Display an error notification
|
|
81
|
+
*/
|
|
82
|
+
static error(message: ToastContent, options?: NotifyOptions): Id;
|
|
83
|
+
/**
|
|
84
|
+
* Display a warning notification
|
|
85
|
+
*/
|
|
86
|
+
static warning(message: ToastContent, options?: NotifyOptions): Id;
|
|
87
|
+
/**
|
|
88
|
+
* Display an info notification
|
|
89
|
+
*/
|
|
90
|
+
static info(message: ToastContent, options?: NotifyOptions): Id;
|
|
91
|
+
/**
|
|
92
|
+
* Display a loading notification
|
|
93
|
+
* Returns an ID that can be used to update/dismiss it
|
|
94
|
+
*/
|
|
95
|
+
static loading(message: ToastContent, options?: Omit<NotifyOptions, 'duration'>): Id;
|
|
96
|
+
/**
|
|
97
|
+
* Update an existing notification
|
|
98
|
+
*/
|
|
99
|
+
static update(id: Id, options: {
|
|
100
|
+
type?: 'success' | 'error' | 'warning' | 'info';
|
|
101
|
+
message?: ToastContent;
|
|
102
|
+
autoClose?: number | false;
|
|
103
|
+
}): void;
|
|
104
|
+
/**
|
|
105
|
+
* Dismiss a specific notification by ID
|
|
106
|
+
*/
|
|
107
|
+
static dismiss(id: Id): void;
|
|
108
|
+
/**
|
|
109
|
+
* Dismiss all notifications
|
|
110
|
+
*/
|
|
111
|
+
static dismissAll(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a notification is active
|
|
114
|
+
*/
|
|
115
|
+
static isActive(id: Id): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Handle promise-based operations with notifications
|
|
118
|
+
*/
|
|
119
|
+
static promise<T>(promise: Promise<T>, messages: {
|
|
120
|
+
pending: ToastContent;
|
|
121
|
+
success: ToastContent<T>;
|
|
122
|
+
error: ToastContent | ((error: any) => ToastContent);
|
|
123
|
+
}, options?: NotifyOptions): Promise<T>;
|
|
124
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { toast } from 'react-toastify';
|
|
2
|
+
import { buildToastConfigs } from './toast-config.js';
|
|
3
|
+
/**
|
|
4
|
+
* TemboNotify - Unified notification system
|
|
5
|
+
*
|
|
6
|
+
* Wraps react-toastify with consistent styling and behavior
|
|
7
|
+
* aligned with Tembo's design system.
|
|
8
|
+
*
|
|
9
|
+
* Note: This class needs to be initialized with theme tokens before use.
|
|
10
|
+
* Call TemboNotify.init(colors, constants) in your app setup.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // In your app setup (e.g., App.tsx)
|
|
15
|
+
* const { colors, constants } = useTemboTheme();
|
|
16
|
+
* useEffect(() => {
|
|
17
|
+
* TemboNotify.init(colors, constants);
|
|
18
|
+
* }, [colors, constants]);
|
|
19
|
+
*
|
|
20
|
+
* // Then use anywhere in your app
|
|
21
|
+
* TemboNotify.success('Payment sent successfully!');
|
|
22
|
+
*
|
|
23
|
+
* // With options
|
|
24
|
+
* TemboNotify.error('Payment failed', {
|
|
25
|
+
* duration: 8000,
|
|
26
|
+
* onClick: () => console.log('Error clicked')
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Loading with promise
|
|
30
|
+
* const loadingId = TemboNotify.loading('Processing payment...');
|
|
31
|
+
* await processPayment();
|
|
32
|
+
* TemboNotify.success('Payment complete!', { id: loadingId });
|
|
33
|
+
*
|
|
34
|
+
* // Promise-based
|
|
35
|
+
* TemboNotify.promise(
|
|
36
|
+
* apiCall(),
|
|
37
|
+
* {
|
|
38
|
+
* pending: 'Processing...',
|
|
39
|
+
* success: 'Done!',
|
|
40
|
+
* error: 'Failed!'
|
|
41
|
+
* }
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class TemboNotify {
|
|
46
|
+
/**
|
|
47
|
+
* Initialize TemboNotify with theme tokens
|
|
48
|
+
* Must be called before using any notification methods
|
|
49
|
+
*/
|
|
50
|
+
static init(colors, constants) {
|
|
51
|
+
this.configs = buildToastConfigs(colors, constants);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get current toast configs, throws if not initialized
|
|
55
|
+
*/
|
|
56
|
+
static getConfigs() {
|
|
57
|
+
if (!this.configs) {
|
|
58
|
+
throw new Error('TemboNotify not initialized. Call TemboNotify.init(colors, constants) before using notifications.');
|
|
59
|
+
}
|
|
60
|
+
return this.configs;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Display a success notification
|
|
64
|
+
*/
|
|
65
|
+
static success(message, options) {
|
|
66
|
+
var _a;
|
|
67
|
+
const configs = this.getConfigs();
|
|
68
|
+
return toast.success(message, Object.assign(Object.assign({}, configs.successConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.successConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Display an error notification
|
|
72
|
+
*/
|
|
73
|
+
static error(message, options) {
|
|
74
|
+
var _a;
|
|
75
|
+
const configs = this.getConfigs();
|
|
76
|
+
return toast.error(message, Object.assign(Object.assign({}, configs.errorConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.errorConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Display a warning notification
|
|
80
|
+
*/
|
|
81
|
+
static warning(message, options) {
|
|
82
|
+
var _a;
|
|
83
|
+
const configs = this.getConfigs();
|
|
84
|
+
return toast.warning(message, Object.assign(Object.assign({}, configs.warningConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.warningConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Display an info notification
|
|
88
|
+
*/
|
|
89
|
+
static info(message, options) {
|
|
90
|
+
var _a;
|
|
91
|
+
const configs = this.getConfigs();
|
|
92
|
+
return toast.info(message, Object.assign(Object.assign({}, configs.infoConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.infoConfig.autoClose, position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Display a loading notification
|
|
96
|
+
* Returns an ID that can be used to update/dismiss it
|
|
97
|
+
*/
|
|
98
|
+
static loading(message, options) {
|
|
99
|
+
const configs = this.getConfigs();
|
|
100
|
+
return toast.loading(message, Object.assign(Object.assign({}, configs.loadingConfig), { position: options === null || options === void 0 ? void 0 : options.position, onClick: options === null || options === void 0 ? void 0 : options.onClick, onClose: options === null || options === void 0 ? void 0 : options.onClose }));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Update an existing notification
|
|
104
|
+
*/
|
|
105
|
+
static update(id, options) {
|
|
106
|
+
var _a;
|
|
107
|
+
const configs = this.getConfigs();
|
|
108
|
+
const config = options.type ? {
|
|
109
|
+
success: configs.successConfig,
|
|
110
|
+
error: configs.errorConfig,
|
|
111
|
+
warning: configs.warningConfig,
|
|
112
|
+
info: configs.infoConfig,
|
|
113
|
+
}[options.type] : undefined;
|
|
114
|
+
toast.update(id, Object.assign({ render: options.message, type: options.type, isLoading: false, autoClose: (_a = options.autoClose) !== null && _a !== void 0 ? _a : config === null || config === void 0 ? void 0 : config.autoClose }, config));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Dismiss a specific notification by ID
|
|
118
|
+
*/
|
|
119
|
+
static dismiss(id) {
|
|
120
|
+
toast.dismiss(id);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Dismiss all notifications
|
|
124
|
+
*/
|
|
125
|
+
static dismissAll() {
|
|
126
|
+
toast.dismiss();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if a notification is active
|
|
130
|
+
*/
|
|
131
|
+
static isActive(id) {
|
|
132
|
+
return toast.isActive(id);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Handle promise-based operations with notifications
|
|
136
|
+
*/
|
|
137
|
+
static promise(promise, messages, options) {
|
|
138
|
+
var _a, _b;
|
|
139
|
+
const configs = this.getConfigs();
|
|
140
|
+
return toast.promise(promise, {
|
|
141
|
+
pending: Object.assign({ render: messages.pending }, configs.loadingConfig),
|
|
142
|
+
success: Object.assign(Object.assign({ render: messages.success }, configs.successConfig), { autoClose: (_a = options === null || options === void 0 ? void 0 : options.duration) !== null && _a !== void 0 ? _a : configs.successConfig.autoClose }),
|
|
143
|
+
error: Object.assign(Object.assign({ render: messages.error }, configs.errorConfig), { autoClose: (_b = options === null || options === void 0 ? void 0 : options.duration) !== null && _b !== void 0 ? _b : configs.errorConfig.autoClose }),
|
|
144
|
+
}, {
|
|
145
|
+
position: options === null || options === void 0 ? void 0 : options.position,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
TemboNotify.configs = null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ToastOptions } from 'react-toastify';
|
|
2
|
+
import { TemboColorPalette, TemboUIConstants } from '../../theme/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build toast configurations from theme tokens
|
|
5
|
+
* This function is called with theme values to generate toast configs
|
|
6
|
+
*/
|
|
7
|
+
export declare const buildToastConfigs: (colors: TemboColorPalette, constants: TemboUIConstants) => {
|
|
8
|
+
loadingConfig: ToastOptions<unknown>;
|
|
9
|
+
infoConfig: ToastOptions<unknown>;
|
|
10
|
+
warningConfig: ToastOptions<unknown>;
|
|
11
|
+
errorConfig: ToastOptions<unknown>;
|
|
12
|
+
successConfig: ToastOptions<unknown>;
|
|
13
|
+
baseConfig: ToastOptions<unknown>;
|
|
14
|
+
};
|
|
15
|
+
export type ToastConfigs = ReturnType<typeof buildToastConfigs>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { CheckCircleOutlined, CloseCircleOutlined, ExclamationCircleOutlined, InfoCircleOutlined, } from '@ant-design/icons';
|
|
3
|
+
/**
|
|
4
|
+
* Build toast configurations from theme tokens
|
|
5
|
+
* This function is called with theme values to generate toast configs
|
|
6
|
+
*/
|
|
7
|
+
export const buildToastConfigs = (colors, constants) => {
|
|
8
|
+
/**
|
|
9
|
+
* Common toast configuration aligned with Tembo theme
|
|
10
|
+
*/
|
|
11
|
+
const baseConfig = {
|
|
12
|
+
position: 'top-right',
|
|
13
|
+
autoClose: 4000,
|
|
14
|
+
hideProgressBar: false,
|
|
15
|
+
closeOnClick: true,
|
|
16
|
+
pauseOnHover: true,
|
|
17
|
+
draggable: true,
|
|
18
|
+
progress: undefined,
|
|
19
|
+
style: {
|
|
20
|
+
fontFamily: constants.typography.fontFamily,
|
|
21
|
+
fontSize: constants.typography.fontSize.base,
|
|
22
|
+
borderRadius: constants.radius.base,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Success notification configuration
|
|
27
|
+
*/
|
|
28
|
+
const successConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(CheckCircleOutlined, { style: { fontSize: 20, color: colors.success.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.success.border}` }) });
|
|
29
|
+
/**
|
|
30
|
+
* Error notification configuration
|
|
31
|
+
*/
|
|
32
|
+
const errorConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(CloseCircleOutlined, { style: { fontSize: 20, color: colors.error.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.error.border}` }), autoClose: 6000 });
|
|
33
|
+
/**
|
|
34
|
+
* Warning notification configuration
|
|
35
|
+
*/
|
|
36
|
+
const warningConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(ExclamationCircleOutlined, { style: { fontSize: 20, color: colors.warning.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.warning.border}` }) });
|
|
37
|
+
/**
|
|
38
|
+
* Info notification configuration
|
|
39
|
+
*/
|
|
40
|
+
const infoConfig = Object.assign(Object.assign({}, baseConfig), { icon: _jsx(InfoCircleOutlined, { style: { fontSize: 20, color: colors.info.main } }), style: Object.assign(Object.assign({}, baseConfig.style), { border: `1px solid ${colors.info.border}` }) });
|
|
41
|
+
/**
|
|
42
|
+
* Loading notification configuration
|
|
43
|
+
*/
|
|
44
|
+
const loadingConfig = Object.assign(Object.assign({}, baseConfig), { autoClose: false, closeButton: false });
|
|
45
|
+
return {
|
|
46
|
+
loadingConfig,
|
|
47
|
+
infoConfig,
|
|
48
|
+
warningConfig,
|
|
49
|
+
errorConfig,
|
|
50
|
+
successConfig,
|
|
51
|
+
baseConfig,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ToastContainerProps as RTToastContainerProps } from 'react-toastify';
|
|
3
|
+
export type TemboToastContainerProps = RTToastContainerProps;
|
|
4
|
+
/**
|
|
5
|
+
* Toast container that automatically initializes TemboNotify with current theme
|
|
6
|
+
* Reinitializes when theme changes to respect color/constant overrides
|
|
7
|
+
*/
|
|
8
|
+
declare const TemboToastContainer: React.FC<TemboToastContainerProps>;
|
|
9
|
+
export default TemboToastContainer;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { ToastContainer } from 'react-toastify';
|
|
4
|
+
import { useTemboTheme } from '../../theme/index.js';
|
|
5
|
+
import { TemboNotify } from './tembo-notify.js';
|
|
6
|
+
/**
|
|
7
|
+
* Toast container that automatically initializes TemboNotify with current theme
|
|
8
|
+
* Reinitializes when theme changes to respect color/constant overrides
|
|
9
|
+
*/
|
|
10
|
+
const TemboToastContainer = (props) => {
|
|
11
|
+
const { colors, constants } = useTemboTheme();
|
|
12
|
+
// Initialize/update TemboNotify whenever theme changes
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
TemboNotify.init(colors, constants);
|
|
15
|
+
}, [colors, constants]);
|
|
16
|
+
return _jsx(ToastContainer, Object.assign({}, props));
|
|
17
|
+
};
|
|
18
|
+
export default TemboToastContainer;
|