medos-sdk 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/client/MedosClient.d.ts +2 -4
- package/dist/client/MedosClient.js +4 -4
- package/dist/components/AppointmentCalender.js +43 -2
- package/dist/components/AppointmentDateTimeModal.js +45 -31
- package/dist/components/ContactInformationStep.d.ts +13 -0
- package/dist/components/ContactInformationStep.js +14 -0
- package/dist/components/ContactPreferenceStep.d.ts +9 -0
- package/dist/components/ContactPreferenceStep.js +16 -0
- package/dist/components/DoctorSelectModal.js +30 -17
- package/dist/components/EnquiryForm.d.ts +7 -0
- package/dist/components/EnquiryForm.js +212 -0
- package/dist/components/Icons/ConsultationType.js +1 -1
- package/dist/components/Icons/Date&TimeIcon.js +1 -1
- package/dist/components/Icons/MapIcon.js +1 -1
- package/dist/components/Icons/PaymentMethodIcon.js +1 -1
- package/dist/components/Icons/UserIcon.js +1 -1
- package/dist/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/components/InquiryDetailsStep.js +15 -0
- package/dist/components/PatientDetailsStep.js +9 -1
- package/dist/components/PhoneVerificationStep.js +22 -12
- package/dist/components/SuccessStep.d.ts +3 -1
- package/dist/components/SuccessStep.js +7 -15
- package/dist/components/custom-calendar.js +42 -24
- package/dist/components/theme-styles.d.ts +12 -0
- package/dist/components/theme-styles.js +319 -0
- package/dist/components/types.d.ts +0 -1
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +4 -0
- package/dist/core/theme/index.d.ts +3 -0
- package/dist/core/theme/index.js +3 -0
- package/dist/core/theme/themes.d.ts +8 -0
- package/dist/core/theme/themes.js +178 -0
- package/dist/core/theme/types.d.ts +106 -0
- package/dist/core/theme/types.js +1 -0
- package/dist/core/theme/utils.d.ts +8 -0
- package/dist/core/theme/utils.js +135 -0
- package/dist/enquiry-form/index.d.ts +4 -0
- package/dist/enquiry-form/index.js +4 -0
- package/dist/enquiry-form/provider.d.ts +3 -0
- package/dist/enquiry-form/provider.js +9 -0
- package/dist/enquiry-form/serialization.d.ts +4 -0
- package/dist/enquiry-form/serialization.js +57 -0
- package/dist/enquiry-form/types.d.ts +38 -0
- package/dist/enquiry-form/types.js +1 -0
- package/dist/enquiry-form/validation.d.ts +6 -0
- package/dist/enquiry-form/validation.js +21 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +7 -0
- package/dist/react/ThemeProvider.d.ts +18 -0
- package/dist/react/ThemeProvider.js +45 -0
- package/dist/react/hooks/useTheme.d.ts +1 -0
- package/dist/react/hooks/useTheme.js +1 -0
- package/dist/react/index.d.ts +5 -0
- package/dist/react/index.js +3 -0
- package/dist/services/EnquiryService.d.ts +5 -0
- package/dist/services/EnquiryService.js +30 -0
- package/dist/vanilla/AppointmentCalendarWidget.js +0 -2
- package/dist/vanilla/EnquiryFormWidget.d.ts +35 -0
- package/dist/vanilla/EnquiryFormWidget.js +425 -0
- package/dist/vanilla/client/MedosClient.d.ts +2 -4
- package/dist/vanilla/components/ContactInformationStep.d.ts +13 -0
- package/dist/vanilla/components/ContactPreferenceStep.d.ts +9 -0
- package/dist/vanilla/components/EnquiryForm.d.ts +7 -0
- package/dist/vanilla/components/InquiryDetailsStep.d.ts +10 -0
- package/dist/vanilla/components/SuccessStep.d.ts +3 -1
- package/dist/vanilla/components/theme-styles.d.ts +12 -0
- package/dist/vanilla/components/types.d.ts +0 -1
- package/dist/vanilla/core/index.d.ts +4 -0
- package/dist/vanilla/core/theme/index.d.ts +3 -0
- package/dist/vanilla/core/theme/themes.d.ts +8 -0
- package/dist/vanilla/core/theme/types.d.ts +106 -0
- package/dist/vanilla/core/theme/utils.d.ts +8 -0
- package/dist/vanilla/enquiry-form/index.d.ts +4 -0
- package/dist/vanilla/enquiry-form/provider.d.ts +3 -0
- package/dist/vanilla/enquiry-form/serialization.d.ts +4 -0
- package/dist/vanilla/enquiry-form/types.d.ts +38 -0
- package/dist/vanilla/enquiry-form/validation.d.ts +6 -0
- package/dist/vanilla/enquiry-widget.js +4650 -0
- package/dist/vanilla/index.d.ts +9 -0
- package/dist/vanilla/index.js +3 -1
- package/dist/vanilla/react/ThemeProvider.d.ts +18 -0
- package/dist/vanilla/react/hooks/useTheme.d.ts +1 -0
- package/dist/vanilla/react/index.d.ts +5 -0
- package/dist/vanilla/services/EnquiryService.d.ts +5 -0
- package/dist/vanilla/theme-injector.d.ts +6 -0
- package/dist/vanilla/theme-injector.js +44 -0
- package/dist/vanilla/vanilla/EnquiryFormWidget.d.ts +35 -0
- package/dist/vanilla/vanilla/index.d.ts +3 -1
- package/dist/vanilla/vanilla/theme-injector.d.ts +6 -0
- package/dist/vanilla/vanilla/widget.d.ts +6 -1
- package/dist/vanilla/widget.css +173 -0
- package/dist/vanilla/widget.d.ts +6 -1
- package/dist/vanilla/widget.js +489 -12
- package/package.json +1 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { defaultTheme } from "./themes";
|
|
2
|
+
function deepMerge(target, source) {
|
|
3
|
+
const result = { ...target };
|
|
4
|
+
for (const key in source) {
|
|
5
|
+
if (source.hasOwnProperty(key)) {
|
|
6
|
+
const sourceValue = source[key];
|
|
7
|
+
const targetValue = result[key];
|
|
8
|
+
if (sourceValue &&
|
|
9
|
+
typeof sourceValue === "object" &&
|
|
10
|
+
!Array.isArray(sourceValue) &&
|
|
11
|
+
targetValue &&
|
|
12
|
+
typeof targetValue === "object" &&
|
|
13
|
+
!Array.isArray(targetValue)) {
|
|
14
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
15
|
+
}
|
|
16
|
+
else if (sourceValue !== undefined) {
|
|
17
|
+
result[key] = sourceValue;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
export function mergeTheme(partialTheme) {
|
|
24
|
+
if (!partialTheme) {
|
|
25
|
+
return defaultTheme;
|
|
26
|
+
}
|
|
27
|
+
return deepMerge(defaultTheme, partialTheme);
|
|
28
|
+
}
|
|
29
|
+
function getCssVarName(prefix, category, key) {
|
|
30
|
+
return `--${prefix}-${category}-${key
|
|
31
|
+
.replace(/([A-Z])/g, "-$1")
|
|
32
|
+
.toLowerCase()}`;
|
|
33
|
+
}
|
|
34
|
+
export function generateCssVariables(theme, prefix = "medos") {
|
|
35
|
+
const vars = [];
|
|
36
|
+
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
37
|
+
vars.push(`${getCssVarName(prefix, "color", key)}: ${value};`);
|
|
38
|
+
});
|
|
39
|
+
Object.entries(theme.typography).forEach(([key, value]) => {
|
|
40
|
+
vars.push(`${getCssVarName(prefix, "typography", key)}: ${value};`);
|
|
41
|
+
});
|
|
42
|
+
Object.entries(theme.spacing).forEach(([key, value]) => {
|
|
43
|
+
vars.push(`${getCssVarName(prefix, "spacing", key)}: ${value};`);
|
|
44
|
+
});
|
|
45
|
+
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
46
|
+
vars.push(`${getCssVarName(prefix, "shadow", key)}: ${value};`);
|
|
47
|
+
});
|
|
48
|
+
Object.entries(theme.radii).forEach(([key, value]) => {
|
|
49
|
+
vars.push(`${getCssVarName(prefix, "radius", key)}: ${value};`);
|
|
50
|
+
});
|
|
51
|
+
Object.entries(theme.transitions).forEach(([key, value]) => {
|
|
52
|
+
vars.push(`${getCssVarName(prefix, "transition", key)}: ${value};`);
|
|
53
|
+
});
|
|
54
|
+
return vars.join("\n ");
|
|
55
|
+
}
|
|
56
|
+
export function generateCssVariablesObject(theme, prefix = "medos") {
|
|
57
|
+
const vars = {};
|
|
58
|
+
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
59
|
+
vars[getCssVarName(prefix, "color", key)] = value;
|
|
60
|
+
});
|
|
61
|
+
Object.entries(theme.typography).forEach(([key, value]) => {
|
|
62
|
+
vars[getCssVarName(prefix, "typography", key)] = value;
|
|
63
|
+
});
|
|
64
|
+
Object.entries(theme.spacing).forEach(([key, value]) => {
|
|
65
|
+
vars[getCssVarName(prefix, "spacing", key)] = value;
|
|
66
|
+
});
|
|
67
|
+
Object.entries(theme.shadows).forEach(([key, value]) => {
|
|
68
|
+
vars[getCssVarName(prefix, "shadow", key)] = value;
|
|
69
|
+
});
|
|
70
|
+
Object.entries(theme.radii).forEach(([key, value]) => {
|
|
71
|
+
vars[getCssVarName(prefix, "radius", key)] = value;
|
|
72
|
+
});
|
|
73
|
+
Object.entries(theme.transitions).forEach(([key, value]) => {
|
|
74
|
+
vars[getCssVarName(prefix, "transition", key)] = value;
|
|
75
|
+
});
|
|
76
|
+
return vars;
|
|
77
|
+
}
|
|
78
|
+
export function getCssVar(prefix, category, key, fallback) {
|
|
79
|
+
const varName = getCssVarName(prefix, category, key);
|
|
80
|
+
return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
|
|
81
|
+
}
|
|
82
|
+
export function injectCssVariables(theme, containerId, prefix = "medos") {
|
|
83
|
+
if (typeof document === "undefined") {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const container = document.getElementById(containerId);
|
|
87
|
+
if (!container) {
|
|
88
|
+
console.warn(`Container with id "${containerId}" not found`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const cssVars = generateCssVariablesObject(theme, prefix);
|
|
92
|
+
Object.entries(cssVars).forEach(([key, value]) => {
|
|
93
|
+
container.style.setProperty(key, value);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function createThemeStyleTag(theme, prefix = "medos", selector = ":root") {
|
|
97
|
+
if (typeof document === "undefined") {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const styleId = `${prefix}-theme-vars`;
|
|
101
|
+
const existingStyle = document.getElementById(styleId);
|
|
102
|
+
if (existingStyle) {
|
|
103
|
+
existingStyle.remove();
|
|
104
|
+
}
|
|
105
|
+
const styleElement = document.createElement("style");
|
|
106
|
+
styleElement.id = styleId;
|
|
107
|
+
styleElement.innerHTML = `
|
|
108
|
+
${selector} {
|
|
109
|
+
${generateCssVariables(theme, prefix)}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
document.head.appendChild(styleElement);
|
|
113
|
+
return styleElement;
|
|
114
|
+
}
|
|
115
|
+
export function validateTheme(theme) {
|
|
116
|
+
const errors = [];
|
|
117
|
+
if (!theme || typeof theme !== "object") {
|
|
118
|
+
errors.push("Theme must be an object");
|
|
119
|
+
return errors;
|
|
120
|
+
}
|
|
121
|
+
const requiredProps = [
|
|
122
|
+
"colors",
|
|
123
|
+
"typography",
|
|
124
|
+
"spacing",
|
|
125
|
+
"shadows",
|
|
126
|
+
"radii",
|
|
127
|
+
"transitions",
|
|
128
|
+
];
|
|
129
|
+
requiredProps.forEach((prop) => {
|
|
130
|
+
if (!theme[prop] || typeof theme[prop] !== "object") {
|
|
131
|
+
errors.push(`Theme.${prop} is required and must be an object`);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return errors;
|
|
135
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MedosClient } from "../client/MedosClient";
|
|
2
|
+
export const submitEnquiry = async (payload) => {
|
|
3
|
+
const response = await MedosClient.client.post("/enquiries", payload);
|
|
4
|
+
return response.data;
|
|
5
|
+
};
|
|
6
|
+
export const getEnquiry = async (enquiryId) => {
|
|
7
|
+
const response = await MedosClient.client.get(`/enquiries/${enquiryId}`);
|
|
8
|
+
return response.data;
|
|
9
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const serializeEnquiry = (enquiry) => {
|
|
2
|
+
if (!enquiry) {
|
|
3
|
+
throw new Error("Cannot serialize null or undefined enquiry");
|
|
4
|
+
}
|
|
5
|
+
try {
|
|
6
|
+
return JSON.stringify(enquiry);
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
throw new Error(`Failed to serialize enquiry: ${error instanceof Error ? error.message : String(error)}`);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const deserializeEnquiry = (jsonString) => {
|
|
13
|
+
if (!jsonString || typeof jsonString !== "string") {
|
|
14
|
+
throw new Error("Cannot deserialize null, undefined, or non-string value");
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(jsonString);
|
|
18
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
19
|
+
throw new Error("Deserialized value is not an object");
|
|
20
|
+
}
|
|
21
|
+
const requiredFields = [
|
|
22
|
+
"patientName",
|
|
23
|
+
"patientEmail",
|
|
24
|
+
"countryCode",
|
|
25
|
+
"patientPhone",
|
|
26
|
+
"inquirySubject",
|
|
27
|
+
"inquiryMessage",
|
|
28
|
+
"preferredContactMethod",
|
|
29
|
+
];
|
|
30
|
+
for (const field of requiredFields) {
|
|
31
|
+
if (!(field in parsed)) {
|
|
32
|
+
throw new Error(`Missing required field: ${field}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const validContactMethods = ["PHONE", "EMAIL", "BOTH"];
|
|
36
|
+
if (!validContactMethods.includes(parsed.preferredContactMethod)) {
|
|
37
|
+
throw new Error(`Invalid preferredContactMethod: ${parsed.preferredContactMethod}`);
|
|
38
|
+
}
|
|
39
|
+
if (parsed.status !== undefined && parsed.status !== null) {
|
|
40
|
+
const validStatuses = ["PENDING", "RESPONDED", "CLOSED"];
|
|
41
|
+
if (!validStatuses.includes(parsed.status)) {
|
|
42
|
+
throw new Error(`Invalid status: ${parsed.status}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
if (error instanceof SyntaxError) {
|
|
49
|
+
throw new Error(`Invalid JSON: ${error.message}`);
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export const roundTripEnquiry = (enquiry) => {
|
|
55
|
+
const serialized = serializeEnquiry(enquiry);
|
|
56
|
+
return deserializeEnquiry(serialized);
|
|
57
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Enquiry {
|
|
2
|
+
id?: string;
|
|
3
|
+
patientName: string;
|
|
4
|
+
patientEmail: string;
|
|
5
|
+
countryCode: string;
|
|
6
|
+
patientPhone: string;
|
|
7
|
+
inquirySubject: string;
|
|
8
|
+
inquiryMessage: string;
|
|
9
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
10
|
+
createdAt?: string;
|
|
11
|
+
status?: "PENDING" | "RESPONDED" | "CLOSED";
|
|
12
|
+
}
|
|
13
|
+
export interface EnquiryFormState {
|
|
14
|
+
step: number;
|
|
15
|
+
loading: boolean;
|
|
16
|
+
error: string | null;
|
|
17
|
+
patientName: string;
|
|
18
|
+
patientEmail: string;
|
|
19
|
+
countryCode: string;
|
|
20
|
+
patientPhone: string;
|
|
21
|
+
inquirySubject: string;
|
|
22
|
+
inquiryMessage: string;
|
|
23
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
24
|
+
submitted: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface EnquirySubmission {
|
|
27
|
+
patientName: string;
|
|
28
|
+
patientEmail: string;
|
|
29
|
+
countryCode: string;
|
|
30
|
+
patientPhone: string;
|
|
31
|
+
inquirySubject: string;
|
|
32
|
+
inquiryMessage: string;
|
|
33
|
+
preferredContactMethod: "PHONE" | "EMAIL" | "BOTH";
|
|
34
|
+
}
|
|
35
|
+
export interface ValidationResult {
|
|
36
|
+
isValid: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const validateName: (name: string) => boolean;
|
|
2
|
+
export declare const validateEmail: (email: string) => boolean;
|
|
3
|
+
export declare const validatePhoneNumber: (phone: string) => boolean;
|
|
4
|
+
export declare const validateSubject: (subject: string) => boolean;
|
|
5
|
+
export declare const validateMessage: (message: string) => boolean;
|
|
6
|
+
export declare const validateCountryCode: (code: string) => boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const validateName = (name) => {
|
|
2
|
+
return name.trim().length > 0;
|
|
3
|
+
};
|
|
4
|
+
export const validateEmail = (email) => {
|
|
5
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6
|
+
return emailRegex.test(email);
|
|
7
|
+
};
|
|
8
|
+
export const validatePhoneNumber = (phone) => {
|
|
9
|
+
const cleaned = phone.replace(/\D/g, "");
|
|
10
|
+
return cleaned.length >= 7 && cleaned.length <= 15;
|
|
11
|
+
};
|
|
12
|
+
export const validateSubject = (subject) => {
|
|
13
|
+
return subject.trim().length > 0;
|
|
14
|
+
};
|
|
15
|
+
export const validateMessage = (message) => {
|
|
16
|
+
const trimmed = message.trim();
|
|
17
|
+
return trimmed.length > 0 && trimmed.length <= 1000;
|
|
18
|
+
};
|
|
19
|
+
export const validateCountryCode = (code) => {
|
|
20
|
+
return /^\+[1-9]\d{0,3}$/.test(code);
|
|
21
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
export { MedosClient } from "./client/MedosClient";
|
|
2
|
+
export * from "./core/theme";
|
|
3
|
+
export { MedosThemeProvider } from "./react/ThemeProvider";
|
|
4
|
+
export type { MedosThemeProviderProps } from "./react/ThemeProvider";
|
|
5
|
+
export { defaultTheme, modernTheme } from "./core/theme/themes";
|
|
6
|
+
export { useTheme, useThemeContext, useCssVar } from "./react/hooks/useTheme";
|
|
2
7
|
export { AppointmentCalender } from "./components/AppointmentCalender";
|
|
8
|
+
export { EnquiryForm } from "./components/EnquiryForm";
|
|
9
|
+
export type { EnquiryFormProps } from "./components/EnquiryForm";
|
|
3
10
|
export * from "./appointments/provider";
|
|
4
11
|
export * from "./appointments/types";
|
|
5
12
|
export * from "./appointment-calendar/provider";
|
|
6
13
|
export * from "./appointment-calendar/types";
|
|
14
|
+
export * from "./enquiry-form/provider";
|
|
15
|
+
export * from "./enquiry-form/types";
|
|
7
16
|
export { PatientService, SendPhoneVerificationOtpPayload, VerifyPhoneVerificationOtpPayload, } from "./services/PatientService";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export { MedosClient } from "./client/MedosClient";
|
|
2
|
+
export * from "./core/theme";
|
|
3
|
+
export { MedosThemeProvider } from "./react/ThemeProvider";
|
|
4
|
+
export { defaultTheme, modernTheme } from "./core/theme/themes";
|
|
5
|
+
export { useTheme, useThemeContext, useCssVar } from "./react/hooks/useTheme";
|
|
2
6
|
export { AppointmentCalender } from "./components/AppointmentCalender";
|
|
7
|
+
export { EnquiryForm } from "./components/EnquiryForm";
|
|
3
8
|
export * from "./appointments/provider";
|
|
4
9
|
export * from "./appointments/types";
|
|
5
10
|
export * from "./appointment-calendar/provider";
|
|
6
11
|
export * from "./appointment-calendar/types";
|
|
12
|
+
export * from "./enquiry-form/provider";
|
|
13
|
+
export * from "./enquiry-form/types";
|
|
7
14
|
export { PatientService, } from "./services/PatientService";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { MedosTheme, PartialTheme } from "../core/theme/types";
|
|
3
|
+
import { ThemeName } from "../core/theme/themes";
|
|
4
|
+
interface ThemeContextValue {
|
|
5
|
+
theme: MedosTheme;
|
|
6
|
+
cssVars: Record<string, string>;
|
|
7
|
+
prefix: string;
|
|
8
|
+
}
|
|
9
|
+
export interface MedosThemeProviderProps {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
theme?: ThemeName | MedosTheme | PartialTheme;
|
|
12
|
+
cssVariablePrefix?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function MedosThemeProvider({ children, theme, cssVariablePrefix, }: MedosThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare function useThemeContext(): ThemeContextValue;
|
|
16
|
+
export declare function useTheme(): MedosTheme;
|
|
17
|
+
export declare function useCssVar(category: string, key: string, fallback?: string): string;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { createContext, useMemo } from "react";
|
|
3
|
+
import { defaultTheme, themes } from "../core/theme/themes";
|
|
4
|
+
import { mergeTheme, generateCssVariablesObject } from "../core/theme/utils";
|
|
5
|
+
const ThemeContext = createContext(undefined);
|
|
6
|
+
export function MedosThemeProvider({ children, theme, cssVariablePrefix = "medos", }) {
|
|
7
|
+
const resolvedTheme = useMemo(() => {
|
|
8
|
+
if (!theme) {
|
|
9
|
+
return defaultTheme;
|
|
10
|
+
}
|
|
11
|
+
if (typeof theme === "string") {
|
|
12
|
+
return themes[theme] || defaultTheme;
|
|
13
|
+
}
|
|
14
|
+
if ("name" in theme && "colors" in theme && "typography" in theme) {
|
|
15
|
+
return theme;
|
|
16
|
+
}
|
|
17
|
+
return mergeTheme(theme);
|
|
18
|
+
}, [theme]);
|
|
19
|
+
const cssVars = useMemo(() => generateCssVariablesObject(resolvedTheme, cssVariablePrefix), [resolvedTheme, cssVariablePrefix]);
|
|
20
|
+
const contextValue = useMemo(() => ({
|
|
21
|
+
theme: resolvedTheme,
|
|
22
|
+
cssVars,
|
|
23
|
+
prefix: cssVariablePrefix,
|
|
24
|
+
}), [resolvedTheme, cssVars, cssVariablePrefix]);
|
|
25
|
+
return (_jsx(ThemeContext.Provider, { value: contextValue, children: _jsx("div", { style: cssVars, children: children }) }));
|
|
26
|
+
}
|
|
27
|
+
export function useThemeContext() {
|
|
28
|
+
const context = React.useContext(ThemeContext);
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error("useThemeContext must be used within a MedosThemeProvider");
|
|
31
|
+
}
|
|
32
|
+
return context;
|
|
33
|
+
}
|
|
34
|
+
export function useTheme() {
|
|
35
|
+
const context = React.useContext(ThemeContext);
|
|
36
|
+
return context?.theme || defaultTheme;
|
|
37
|
+
}
|
|
38
|
+
export function useCssVar(category, key, fallback) {
|
|
39
|
+
const context = React.useContext(ThemeContext);
|
|
40
|
+
const prefix = context?.prefix || "medos";
|
|
41
|
+
const varName = `--${prefix}-${category}-${key
|
|
42
|
+
.replace(/([A-Z])/g, "-$1")
|
|
43
|
+
.toLowerCase()}`;
|
|
44
|
+
return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTheme, useThemeContext, useCssVar } from "../ThemeProvider";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTheme, useThemeContext, useCssVar } from "../ThemeProvider";
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export * from "../core";
|
|
2
|
+
export { MedosThemeProvider } from "./ThemeProvider";
|
|
3
|
+
export type { MedosThemeProviderProps } from "./ThemeProvider";
|
|
4
|
+
export { useTheme, useThemeContext, useCssVar } from "./hooks/useTheme";
|
|
2
5
|
export { AppointmentCalender } from "../components/AppointmentCalender";
|
|
6
|
+
export { EnquiryForm } from "../components/EnquiryForm";
|
|
7
|
+
export type { EnquiryFormProps } from "../components/EnquiryForm";
|
package/dist/react/index.js
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export * from "../core";
|
|
2
|
+
export { MedosThemeProvider } from "./ThemeProvider";
|
|
3
|
+
export { useTheme, useThemeContext, useCssVar } from "./hooks/useTheme";
|
|
2
4
|
export { AppointmentCalender } from "../components/AppointmentCalender";
|
|
5
|
+
export { EnquiryForm } from "../components/EnquiryForm";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { MedosClient } from "../client/MedosClient";
|
|
2
|
+
const EnquiryService = {
|
|
3
|
+
async submitEnquiry(payload) {
|
|
4
|
+
try {
|
|
5
|
+
const client = await MedosClient.ensureInitialized();
|
|
6
|
+
const enquiryData = {
|
|
7
|
+
patientName: payload.patientName,
|
|
8
|
+
patientEmail: payload.patientEmail,
|
|
9
|
+
countryCode: payload.countryCode,
|
|
10
|
+
patientPhone: payload.patientPhone,
|
|
11
|
+
inquirySubject: payload.inquirySubject,
|
|
12
|
+
inquiryMessage: payload.inquiryMessage,
|
|
13
|
+
preferredContactMethod: payload.preferredContactMethod,
|
|
14
|
+
};
|
|
15
|
+
const res = await client.post("/enquiries/submit", enquiryData, {
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
return res.data;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error instanceof Error) {
|
|
24
|
+
throw new Error(`Failed to submit enquiry: ${error.message}`);
|
|
25
|
+
}
|
|
26
|
+
throw new Error("Failed to submit enquiry: Unknown error");
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export { EnquiryService };
|
|
@@ -26,13 +26,11 @@ class AppointmentCalendarWidget {
|
|
|
26
26
|
if (this.options.apiKey) {
|
|
27
27
|
await MedosClient.init({
|
|
28
28
|
apiKey: this.options.apiKey,
|
|
29
|
-
baseURL: this.options.baseURL,
|
|
30
29
|
});
|
|
31
30
|
}
|
|
32
31
|
else if (this.options.sessionToken) {
|
|
33
32
|
await MedosClient.initWithSession({
|
|
34
33
|
sessionToken: this.options.sessionToken,
|
|
35
|
-
baseURL: this.options.baseURL,
|
|
36
34
|
});
|
|
37
35
|
}
|
|
38
36
|
else {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EnquirySubmission } from "../enquiry-form/types";
|
|
2
|
+
interface EnquiryFormWidgetOptions {
|
|
3
|
+
containerId: string;
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
sessionToken?: string;
|
|
6
|
+
baseURL?: string;
|
|
7
|
+
onError?: (err: Error) => void;
|
|
8
|
+
onSuccess?: (enquiry: EnquirySubmission) => void;
|
|
9
|
+
}
|
|
10
|
+
declare class EnquiryFormWidget {
|
|
11
|
+
private container;
|
|
12
|
+
private options;
|
|
13
|
+
private mounted;
|
|
14
|
+
private state;
|
|
15
|
+
constructor(container: HTMLElement | string, options: EnquiryFormWidgetOptions);
|
|
16
|
+
private init;
|
|
17
|
+
private validateContactStep;
|
|
18
|
+
private validateInquiryStep;
|
|
19
|
+
private goToNext;
|
|
20
|
+
private goBack;
|
|
21
|
+
private submitEnquiry;
|
|
22
|
+
private resetForm;
|
|
23
|
+
private setState;
|
|
24
|
+
private render;
|
|
25
|
+
private renderStep;
|
|
26
|
+
private renderStep0;
|
|
27
|
+
private renderStep1;
|
|
28
|
+
private renderStep2;
|
|
29
|
+
private renderStep3;
|
|
30
|
+
private attachEventListeners;
|
|
31
|
+
private escapeHtml;
|
|
32
|
+
destroy(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare function initEnquiryForm(options: EnquiryFormWidgetOptions): EnquiryFormWidget;
|
|
35
|
+
export { EnquiryFormWidget };
|