@ews-admin/global-design-system 1.1.1 → 1.1.5

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.
Files changed (43) hide show
  1. package/dist/components/ThemeToggle/ThemeToggle.d.ts +6 -0
  2. package/dist/components/ThemeToggle/ThemeToggle.d.ts.map +1 -0
  3. package/dist/components/ThemeToggle/index.d.ts +3 -0
  4. package/dist/components/ThemeToggle/index.d.ts.map +1 -0
  5. package/dist/icons/DoctorIcon.d.ts +4 -0
  6. package/dist/icons/DoctorIcon.d.ts.map +1 -0
  7. package/dist/icons/Icon.d.ts +18 -0
  8. package/dist/icons/Icon.d.ts.map +1 -1
  9. package/dist/icons/PatientIcon.d.ts +4 -0
  10. package/dist/icons/PatientIcon.d.ts.map +1 -0
  11. package/dist/icons/UserIcon.d.ts +4 -0
  12. package/dist/icons/UserIcon.d.ts.map +1 -0
  13. package/dist/icons/index.d.ts +4 -1
  14. package/dist/icons/index.d.ts.map +1 -1
  15. package/dist/index.css +3 -2
  16. package/dist/index.d.ts +62 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.esm.css +3 -2
  19. package/dist/index.esm.js +156 -20
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/index.js +160 -18
  22. package/dist/index.js.map +1 -1
  23. package/dist/theme/ThemeProvider.d.ts +10 -0
  24. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  25. package/dist/theme/themeConfig.d.ts +8 -0
  26. package/dist/theme/themeConfig.d.ts.map +1 -0
  27. package/dist/types/theme.d.ts +23 -0
  28. package/dist/types/theme.d.ts.map +1 -0
  29. package/package.json +7 -3
  30. package/src/components/ThemeToggle/ThemeToggle.tsx +43 -0
  31. package/src/components/ThemeToggle/index.ts +2 -0
  32. package/src/icons/DoctorIcon.tsx +14 -0
  33. package/src/icons/Icon.tsx +20 -0
  34. package/src/icons/PatientIcon.tsx +12 -0
  35. package/src/icons/UserIcon.tsx +12 -0
  36. package/src/icons/index.ts +6 -1
  37. package/src/index.ts +17 -2
  38. package/src/styles/index.css +162 -8
  39. package/src/styles/theme-variables.css +47 -0
  40. package/src/theme/ThemeProvider.tsx +69 -0
  41. package/src/theme/themeConfig.ts +40 -0
  42. package/src/types/theme.ts +24 -0
  43. package/tailwind.preset.js +166 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/types/theme.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;CAC1B"}
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@ews-admin/global-design-system",
3
- "version": "1.1.1",
3
+ "version": "1.1.5",
4
4
  "description": "EWS Global Design System - Reusable components for EWS applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "dist",
10
- "src"
10
+ "src",
11
+ "tailwind.preset.js"
11
12
  ],
12
13
  "keywords": [
13
14
  "design-system",
@@ -80,6 +81,9 @@
80
81
  "version:major": "pnpm version major",
81
82
  "view": "pnpm view @ews-admin/global-design-system",
82
83
  "clean": "rm -rf dist",
83
- "rebuild": "pnpm clean && pnpm build"
84
+ "rebuild": "pnpm clean && pnpm build",
85
+ "link": "pnpm build && pnpm link --global",
86
+ "unlink": "pnpm unlink --global",
87
+ "dev:watch": "pnpm build && pnpm dev"
84
88
  }
85
89
  }
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import { useTheme } from "../../theme/ThemeProvider";
3
+ import { Theme } from "../../types/theme";
4
+
5
+ export interface ThemeToggleProps {
6
+ className?: string;
7
+ }
8
+
9
+ export const ThemeToggle: React.FC<ThemeToggleProps> = ({ className }) => {
10
+ const { theme, setTheme } = useTheme();
11
+
12
+ const handleThemeChange = (newTheme: Theme) => {
13
+ setTheme(newTheme);
14
+ };
15
+
16
+ return (
17
+ <div className={`flex items-center space-x-2 ${className || ""}`}>
18
+ <span className="text-sm font-medium text-gray-700">Theme:</span>
19
+ <div className="flex bg-gray-100 rounded-lg p-1">
20
+ <button
21
+ onClick={() => handleThemeChange("PROMED")}
22
+ className={`px-3 py-1 text-xs font-medium rounded-md transition-colors ${
23
+ theme === "PROMED"
24
+ ? "bg-ews-primary text-white"
25
+ : "text-gray-600 hover:text-gray-900"
26
+ }`}
27
+ >
28
+ PROMED
29
+ </button>
30
+ <button
31
+ onClick={() => handleThemeChange("MED")}
32
+ className={`px-3 py-1 text-xs font-medium rounded-md transition-colors ${
33
+ theme === "MED"
34
+ ? "bg-ews-primary text-white"
35
+ : "text-gray-600 hover:text-gray-900"
36
+ }`}
37
+ >
38
+ MED
39
+ </button>
40
+ </div>
41
+ </div>
42
+ );
43
+ };
@@ -0,0 +1,2 @@
1
+ export { ThemeToggle } from "./ThemeToggle";
2
+ export type { ThemeToggleProps } from "./ThemeToggle";
@@ -0,0 +1,14 @@
1
+ import { Stethoscope } from "lucide-react";
2
+ import React from "react";
3
+ import { SimpleIconProps } from "./Icon";
4
+
5
+ export const DoctorIcon: React.FC<SimpleIconProps> = ({
6
+ size = 24,
7
+ color = "currentColor",
8
+ className = "",
9
+ ...props
10
+ }) => {
11
+ return (
12
+ <Stethoscope size={size} color={color} className={className} {...props} />
13
+ );
14
+ };
@@ -12,6 +12,26 @@ export interface IconProps extends Omit<LucideProps, "size"> {
12
12
  icon: React.ComponentType<LucideProps>;
13
13
  }
14
14
 
15
+ // Simple icon props for individual icon components
16
+ export interface SimpleIconProps {
17
+ /**
18
+ * Icon size in pixels
19
+ */
20
+ size?: number;
21
+ /**
22
+ * Icon color (can be hex, rgb, or Tailwind class)
23
+ */
24
+ color?: string;
25
+ /**
26
+ * Additional CSS classes (supports Tailwind classes)
27
+ */
28
+ className?: string;
29
+ /**
30
+ * Other props passed to the underlying icon
31
+ */
32
+ [key: string]: any;
33
+ }
34
+
15
35
  const Icon = React.forwardRef<SVGSVGElement, IconProps>(
16
36
  ({ size = "md", icon: IconComponent, className, ...props }, ref) => {
17
37
  const sizes = {
@@ -0,0 +1,12 @@
1
+ import { Heart } from "lucide-react";
2
+ import React from "react";
3
+ import { SimpleIconProps } from "./Icon";
4
+
5
+ export const PatientIcon: React.FC<SimpleIconProps> = ({
6
+ size = 24,
7
+ color = "currentColor",
8
+ className = "",
9
+ ...props
10
+ }) => {
11
+ return <Heart size={size} color={color} className={className} {...props} />;
12
+ };
@@ -0,0 +1,12 @@
1
+ import { User } from "lucide-react";
2
+ import React from "react";
3
+ import { SimpleIconProps } from "./Icon";
4
+
5
+ export const UserIcon: React.FC<SimpleIconProps> = ({
6
+ size = 24,
7
+ color = "currentColor",
8
+ className = "",
9
+ ...props
10
+ }) => {
11
+ return <User size={size} color={color} className={className} {...props} />;
12
+ };
@@ -38,4 +38,9 @@ export {
38
38
 
39
39
  // Keep our custom Icon component for backward compatibility
40
40
  export { Icon } from "./Icon";
41
- export type { IconProps } from "./Icon";
41
+ export type { IconProps, SimpleIconProps } from "./Icon";
42
+
43
+ // Custom EWS Icons
44
+ export { DoctorIcon } from "./DoctorIcon";
45
+ export { PatientIcon } from "./PatientIcon";
46
+ export { UserIcon } from "./UserIcon";
package/src/index.ts CHANGED
@@ -16,13 +16,24 @@ export type { ErrorField, ErrorObject, ModalProps } from "./components/Modal";
16
16
  export { Logo } from "./components/Logo";
17
17
  export type { LogoProps } from "./components/Logo";
18
18
 
19
+ export { ThemeToggle } from "./components/ThemeToggle";
20
+ export type { ThemeToggleProps } from "./components/ThemeToggle";
21
+
19
22
  // Molecules
20
23
  export { SpecialtySearchAutocomplete } from "./molecules";
21
24
  export type { Specialty, SpecialtySearchAutocompleteProps } from "./molecules";
22
25
 
23
26
  // Icons
24
- export { ArrowRight, Check, Icon, Search } from "./icons";
25
- export type { IconProps } from "./icons";
27
+ export {
28
+ ArrowRight,
29
+ Check,
30
+ DoctorIcon,
31
+ Icon,
32
+ PatientIcon,
33
+ Search,
34
+ UserIcon,
35
+ } from "./icons";
36
+ export type { IconProps, SimpleIconProps } from "./icons";
26
37
 
27
38
  // Utils
28
39
  export { cn, debounce, formatCurrency, formatDate, generateId } from "./utils";
@@ -30,6 +41,10 @@ export { cn, debounce, formatCurrency, formatDate, generateId } from "./utils";
30
41
  // Hooks
31
42
  export { useDebounce, useDebouncedCallback } from "./hooks";
32
43
 
44
+ // Theme
45
+ export { ThemeProvider, useTheme } from "./theme/ThemeProvider";
46
+ export type { Theme, ThemeConfig, ThemeContextType } from "./types/theme";
47
+
33
48
  // Styles
34
49
  import "./styles/index.css";
35
50
  import "./styles/tailwind.css";
@@ -1,4 +1,5 @@
1
1
  /* EWS Global Design System - Base Styles */
2
+ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap");
2
3
  @tailwind base;
3
4
  @tailwind components;
4
5
  @tailwind utilities;
@@ -73,15 +74,14 @@
73
74
  }
74
75
 
75
76
  /* Reset and Base Styles */
76
- * {
77
- box-sizing: border-box;
78
- }
77
+ @layer base {
78
+ html {
79
+ font-family: "Inter", system-ui, sans-serif;
80
+ }
79
81
 
80
- body {
81
- font-family: var(--ews-font-sans);
82
- line-height: 1.5;
83
- color: var(--ews-gray-900);
84
- background-color: var(--ews-white);
82
+ body {
83
+ @apply bg-neutral-50 text-neutral-900;
84
+ }
85
85
  }
86
86
 
87
87
  /* Utility Classes */
@@ -96,3 +96,157 @@ body {
96
96
  white-space: nowrap;
97
97
  border: 0;
98
98
  }
99
+ @layer base {
100
+ html {
101
+ font-family: "Inter", system-ui, sans-serif;
102
+ }
103
+
104
+ body {
105
+ @apply bg-neutral-50 text-neutral-900;
106
+ }
107
+ }
108
+ @layer utilities {
109
+ /* Custom shadow utilities */
110
+ .shadow-soft {
111
+ box-shadow: 0 2px 15px -3px rgba(0, 0, 0, 0.07),
112
+ 0 10px 20px -2px rgba(0, 0, 0, 0.04);
113
+ }
114
+
115
+ .shadow-medium {
116
+ box-shadow: 0 4px 25px -5px rgba(0, 0, 0, 0.1),
117
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04);
118
+ }
119
+
120
+ .shadow-large {
121
+ box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.15),
122
+ 0 2px 10px -2px rgba(0, 0, 0, 0.05);
123
+ }
124
+ }
125
+
126
+ @layer components {
127
+ /* Custom scrollbar */
128
+ ::-webkit-scrollbar {
129
+ width: 6px;
130
+ }
131
+ ::-webkit-scrollbar-track {
132
+ @apply bg-neutral-100;
133
+ }
134
+
135
+ ::-webkit-scrollbar-thumb {
136
+ @apply rounded-full bg-neutral-300;
137
+ }
138
+
139
+ ::-webkit-scrollbar-thumb:hover {
140
+ @apply bg-neutral-400;
141
+ }
142
+
143
+ /* Card base styles */
144
+ .card-base {
145
+ @apply bg-white rounded-xl border shadow-soft border-neutral-200;
146
+ }
147
+
148
+ /* Sidebar navigation styles */
149
+ .sidebar-item {
150
+ @apply relative transition-all duration-200;
151
+ }
152
+
153
+ .sidebar-item-active {
154
+ @apply border-l-4 shadow-sm bg-primary-50 text-primary-700 border-l-primary-500;
155
+ }
156
+
157
+ .sidebar-item-hover {
158
+ @apply hover:bg-neutral-50 hover:text-neutral-900 hover:border-l-4 hover:border-l-neutral-300;
159
+ }
160
+
161
+ .sidebar-item-icon {
162
+ @apply transition-colors duration-200;
163
+ }
164
+
165
+ .sidebar-item-icon-active {
166
+ @apply text-primary-600;
167
+ }
168
+
169
+ .sidebar-item-icon-inactive {
170
+ @apply text-neutral-500;
171
+ }
172
+
173
+ /* Dashboard animations */
174
+ @keyframes fadeIn {
175
+ from {
176
+ opacity: 0;
177
+ transform: translateY(20px);
178
+ }
179
+ to {
180
+ opacity: 1;
181
+ transform: translateY(0);
182
+ }
183
+ }
184
+
185
+ @keyframes slideInFromLeft {
186
+ from {
187
+ opacity: 0;
188
+ transform: translateX(-20px);
189
+ }
190
+ to {
191
+ opacity: 1;
192
+ transform: translateX(0);
193
+ }
194
+ }
195
+
196
+ @keyframes slideInFromRight {
197
+ from {
198
+ opacity: 0;
199
+ transform: translateX(20px);
200
+ }
201
+ to {
202
+ opacity: 1;
203
+ transform: translateX(0);
204
+ }
205
+ }
206
+
207
+ @keyframes scaleIn {
208
+ from {
209
+ opacity: 0;
210
+ transform: scale(0.9);
211
+ }
212
+ to {
213
+ opacity: 1;
214
+ transform: scale(1);
215
+ }
216
+ }
217
+
218
+ .animate-fadeIn {
219
+ animation: fadeIn 0.6s ease-out;
220
+ }
221
+
222
+ .animate-slideInLeft {
223
+ animation: slideInFromLeft 0.6s ease-out;
224
+ }
225
+
226
+ .animate-slideInRight {
227
+ animation: slideInFromRight 0.6s ease-out;
228
+ }
229
+
230
+ .animate-scaleIn {
231
+ animation: scaleIn 0.6s ease-out;
232
+ }
233
+
234
+ /* Hover animations */
235
+ .hover-lift {
236
+ transition: transform 0.2s ease-out, box-shadow 0.2s ease-out;
237
+ }
238
+
239
+ .hover-lift:hover {
240
+ transform: translateY(-2px);
241
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1),
242
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04);
243
+ }
244
+
245
+ .hover-scale {
246
+ transition: transform 0.2s ease-out;
247
+ }
248
+
249
+ .hover-scale:hover {
250
+ transform: scale(1.02);
251
+ }
252
+ }
@@ -0,0 +1,47 @@
1
+ /* EWS Design System - Theme CSS Variables */
2
+ /* This file should be imported in consuming applications */
3
+
4
+ :root {
5
+ /* PROMED Theme (Default) - Professional theme for doctors/managers */
6
+ --ews-primary: #21596c;
7
+ --ews-primary-hover: #1a4756;
8
+ --ews-primary-light: #c0d0d4;
9
+ --ews-secondary: #3ba1a1;
10
+ --ews-secondary-hover: #308181;
11
+ --ews-success: #059669;
12
+ --ews-success-hover: #047857;
13
+ --ews-warning: #d97706;
14
+ --ews-warning-hover: #b45309;
15
+ --ews-error: #dc2626;
16
+ --ews-error-hover: #b91c1c;
17
+ }
18
+
19
+ /* MED Theme - Patient-friendly theme */
20
+ [data-theme="MED"] {
21
+ --ews-primary: #3ba1a1;
22
+ --ews-primary-hover: #308181;
23
+ --ews-primary-light: #a8d5d5;
24
+ --ews-secondary: #6b73ff;
25
+ --ews-secondary-hover: #5a61e6;
26
+ --ews-success: #059669;
27
+ --ews-success-hover: #047857;
28
+ --ews-warning: #d97706;
29
+ --ews-warning-hover: #b45309;
30
+ --ews-error: #dc2626;
31
+ --ews-error-hover: #b91c1c;
32
+ }
33
+
34
+ /* PROMED Theme - Professional theme */
35
+ [data-theme="PROMED"] {
36
+ --ews-primary: #21596c;
37
+ --ews-primary-hover: #1a4756;
38
+ --ews-primary-light: #c0d0d4;
39
+ --ews-secondary: #3ba1a1;
40
+ --ews-secondary-hover: #308181;
41
+ --ews-success: #059669;
42
+ --ews-success-hover: #047857;
43
+ --ews-warning: #d97706;
44
+ --ews-warning-hover: #b45309;
45
+ --ews-error: #dc2626;
46
+ --ews-error-hover: #b91c1c;
47
+ }
@@ -0,0 +1,69 @@
1
+ import React, {
2
+ createContext,
3
+ ReactNode,
4
+ useContext,
5
+ useEffect,
6
+ useState,
7
+ } from "react";
8
+ import { Theme, ThemeContextType } from "../types/theme";
9
+ import { THEMES } from "./themeConfig";
10
+
11
+ const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
12
+
13
+ interface ThemeProviderProps {
14
+ children: ReactNode;
15
+ defaultTheme?: Theme;
16
+ }
17
+
18
+ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
19
+ children,
20
+ defaultTheme = "PROMED",
21
+ }) => {
22
+ const [theme, setTheme] = useState<Theme>(defaultTheme);
23
+ const [themeConfig, setThemeConfig] = useState(THEMES[defaultTheme]);
24
+
25
+ // Update theme config when theme changes
26
+ useEffect(() => {
27
+ setThemeConfig(THEMES[theme]);
28
+
29
+ // Update data-theme attribute for CSS variable switching
30
+ const root = document.documentElement;
31
+ root.setAttribute("data-theme", theme);
32
+
33
+ // Also update CSS custom properties for backward compatibility
34
+ const colors = THEMES[theme].colors;
35
+ root.style.setProperty("--ews-primary", colors.primary);
36
+ root.style.setProperty("--ews-primary-hover", colors.primaryHover);
37
+ root.style.setProperty("--ews-primary-light", colors.primaryLight);
38
+ root.style.setProperty("--ews-secondary", colors.secondary);
39
+ root.style.setProperty("--ews-secondary-hover", colors.secondaryHover);
40
+ root.style.setProperty("--ews-success", colors.success);
41
+ root.style.setProperty("--ews-success-hover", colors.successHover);
42
+ root.style.setProperty("--ews-warning", colors.warning);
43
+ root.style.setProperty("--ews-warning-hover", colors.warningHover);
44
+ root.style.setProperty("--ews-error", colors.error);
45
+ root.style.setProperty("--ews-error-hover", colors.errorHover);
46
+ }, [theme]);
47
+
48
+ const handleSetTheme = (newTheme: Theme) => {
49
+ setTheme(newTheme);
50
+ };
51
+
52
+ const value: ThemeContextType = {
53
+ theme,
54
+ setTheme: handleSetTheme,
55
+ themeConfig,
56
+ };
57
+
58
+ return (
59
+ <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
60
+ );
61
+ };
62
+
63
+ export const useTheme = (): ThemeContextType => {
64
+ const context = useContext(ThemeContext);
65
+ if (context === undefined) {
66
+ throw new Error("useTheme must be used within a ThemeProvider");
67
+ }
68
+ return context;
69
+ };
@@ -0,0 +1,40 @@
1
+ import { ThemeConfig } from "../types/theme";
2
+
3
+ export const PROMED_THEME: ThemeConfig = {
4
+ name: "PROMED",
5
+ colors: {
6
+ primary: "#21596C",
7
+ secondary: "#3BA1A1",
8
+ primaryHover: "#1a4756",
9
+ secondaryHover: "#308181",
10
+ primaryLight: "#c0d0d4",
11
+ success: "#059669",
12
+ successHover: "#047857",
13
+ warning: "#d97706",
14
+ warningHover: "#b45309",
15
+ error: "#dc2626",
16
+ errorHover: "#b91c1c",
17
+ },
18
+ };
19
+
20
+ export const MED_THEME: ThemeConfig = {
21
+ name: "MED",
22
+ colors: {
23
+ primary: "#3BA1A1", // Teal for patients (calming, trustworthy)
24
+ secondary: "#6B73FF", // Soft purple-blue (suggested secondary for MED)
25
+ primaryHover: "#308181",
26
+ secondaryHover: "#5a61e6",
27
+ primaryLight: "#a8d5d5",
28
+ success: "#059669",
29
+ successHover: "#047857",
30
+ warning: "#d97706",
31
+ warningHover: "#b45309",
32
+ error: "#dc2626",
33
+ errorHover: "#b91c1c",
34
+ },
35
+ };
36
+
37
+ export const THEMES = {
38
+ PROMED: PROMED_THEME,
39
+ MED: MED_THEME,
40
+ } as const;
@@ -0,0 +1,24 @@
1
+ export type Theme = "PROMED" | "MED";
2
+
3
+ export interface ThemeConfig {
4
+ name: Theme;
5
+ colors: {
6
+ primary: string;
7
+ secondary: string;
8
+ primaryHover: string;
9
+ secondaryHover: string;
10
+ primaryLight: string;
11
+ success: string;
12
+ successHover: string;
13
+ warning: string;
14
+ warningHover: string;
15
+ error: string;
16
+ errorHover: string;
17
+ };
18
+ }
19
+
20
+ export interface ThemeContextType {
21
+ theme: Theme;
22
+ setTheme: (theme: Theme) => void;
23
+ themeConfig: ThemeConfig;
24
+ }