@mieweb/ui 0.2.1 → 0.2.4

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 (62) hide show
  1. package/README.md +28 -0
  2. package/dist/ag-grid.cjs +5 -5
  3. package/dist/ag-grid.js +1 -1
  4. package/dist/brands/bluehive.css +20 -0
  5. package/dist/brands/enterprise-health.css +32 -4
  6. package/dist/brands/index.d.cts +1 -1
  7. package/dist/brands/index.d.ts +1 -1
  8. package/dist/brands/mieweb.css +20 -0
  9. package/dist/brands/ozwell.css +20 -0
  10. package/dist/brands/waggleline.css +46 -0
  11. package/dist/brands/webchart.css +20 -0
  12. package/dist/{chunk-I7L6CQXR.cjs → chunk-377KAB4C.cjs} +52 -31
  13. package/dist/chunk-377KAB4C.cjs.map +1 -0
  14. package/dist/chunk-3K7QCDSV.js +3 -0
  15. package/dist/{chunk-K5T2PT4M.js.map → chunk-3K7QCDSV.js.map} +1 -1
  16. package/dist/chunk-EYH7OUX5.js +445 -0
  17. package/dist/chunk-EYH7OUX5.js.map +1 -0
  18. package/dist/{chunk-WN2FJE23.js → chunk-KWDTTGH2.js} +3 -3
  19. package/dist/{chunk-WN2FJE23.js.map → chunk-KWDTTGH2.js.map} +1 -1
  20. package/dist/{chunk-MKJDBXX4.cjs → chunk-PEH4ZOEM.cjs} +4 -4
  21. package/dist/{chunk-MKJDBXX4.cjs.map → chunk-PEH4ZOEM.cjs.map} +1 -1
  22. package/dist/{chunk-D3BUYVLN.cjs → chunk-QIOM5ZV2.cjs} +64 -8
  23. package/dist/{chunk-D3BUYVLN.cjs.map → chunk-QIOM5ZV2.cjs.map} +1 -1
  24. package/dist/chunk-SSKI6VTW.cjs +449 -0
  25. package/dist/chunk-SSKI6VTW.cjs.map +1 -0
  26. package/dist/{chunk-SD44QJIP.js → chunk-TCQ27C5M.js} +52 -31
  27. package/dist/chunk-TCQ27C5M.js.map +1 -0
  28. package/dist/{chunk-SN52QMRT.js → chunk-TPGT236K.js} +28 -24
  29. package/dist/chunk-TPGT236K.js.map +1 -0
  30. package/dist/{chunk-N5EKL4DH.js → chunk-VBHPXSCV.js} +4 -4
  31. package/dist/{chunk-N5EKL4DH.js.map → chunk-VBHPXSCV.js.map} +1 -1
  32. package/dist/{chunk-B7DA35BY.cjs → chunk-VZUVYJFU.cjs} +14 -14
  33. package/dist/{chunk-B7DA35BY.cjs.map → chunk-VZUVYJFU.cjs.map} +1 -1
  34. package/dist/{chunk-KMN7JX2X.cjs → chunk-WH6I7CMP.cjs} +28 -24
  35. package/dist/chunk-WH6I7CMP.cjs.map +1 -0
  36. package/dist/components/Button/index.cjs +3 -3
  37. package/dist/components/Button/index.js +1 -1
  38. package/dist/components/DateInput/index.cjs +3 -3
  39. package/dist/components/DateInput/index.js +2 -2
  40. package/dist/components/Modal/index.cjs +9 -9
  41. package/dist/components/Modal/index.js +1 -1
  42. package/dist/index.cjs +2991 -1281
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +257 -8
  45. package/dist/index.d.ts +257 -8
  46. package/dist/index.js +2761 -1058
  47. package/dist/index.js.map +1 -1
  48. package/dist/styles.css +2 -2
  49. package/dist/tailwind-preset.cjs +4 -4
  50. package/dist/tailwind-preset.js +1 -1
  51. package/dist/utils/index.cjs +9 -9
  52. package/dist/utils/index.js +1 -1
  53. package/package.json +42 -38
  54. package/dist/chunk-5YRTFJ7K.js +0 -247
  55. package/dist/chunk-5YRTFJ7K.js.map +0 -1
  56. package/dist/chunk-ERIGUDFS.cjs +0 -251
  57. package/dist/chunk-ERIGUDFS.cjs.map +0 -1
  58. package/dist/chunk-I7L6CQXR.cjs.map +0 -1
  59. package/dist/chunk-K5T2PT4M.js +0 -3
  60. package/dist/chunk-KMN7JX2X.cjs.map +0 -1
  61. package/dist/chunk-SD44QJIP.js.map +0 -1
  62. package/dist/chunk-SN52QMRT.js.map +0 -1
package/README.md CHANGED
@@ -18,6 +18,7 @@ A themeable, accessible React component library built with Tailwind CSS 4.
18
18
  - [Installation](#installation)
19
19
  - [Quick Start](#quick-start)
20
20
  - [Development](#development)
21
+ - [Date & Time Standard](#date--time-standard)
21
22
  - [Storybook](#storybook)
22
23
  - [Using in Other Projects](#using-in-other-projects)
23
24
  - [Brand System](#brand-system)
@@ -140,6 +141,33 @@ This will watch for changes and rebuild the library automatically.
140
141
  | `npm run test` | Run tests |
141
142
  | `npm run test:watch` | Run tests in watch mode |
142
143
 
144
+ ## Date & Time Standard
145
+
146
+ For UI/UX date and time behavior, this project uses **Luxon** as the preferred library.
147
+
148
+ ### Guidelines
149
+
150
+ - Use `DateTime` from `luxon` for all new date/time parsing, formatting, and comparisons.
151
+ - Keep timezone explicit when logic depends on business rules (for example: office hours, “open now”, appointment windows).
152
+ - Use IANA timezone identifiers (for example: `America/New_York`) instead of abbreviations.
153
+ - Prefer storing/transmitting ISO-8601 values and convert for display at the component edge.
154
+ - Avoid adding new date logic with raw `Date` math unless there is a clear performance or compatibility reason.
155
+
156
+ ### Examples
157
+
158
+ ```ts
159
+ import { DateTime } from 'luxon';
160
+
161
+ const localDisplay = DateTime.fromISO(timestamp).toFormat('LLL d, yyyy h:mm a');
162
+
163
+ const inProviderZone = DateTime.fromISO(timestamp, {
164
+ zone: 'America/New_York',
165
+ });
166
+
167
+ const isOpen = DateTime.now().setZone('America/New_York') <
168
+ inProviderZone.plus({ hours: 1 });
169
+ ```
170
+
143
171
  ## Storybook
144
172
 
145
173
  Storybook provides interactive documentation and a component playground where you can explore all components with different props and themes.
package/dist/ag-grid.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkD3BUYVLN_cjs = require('./chunk-D3BUYVLN.cjs');
3
+ var chunkQIOM5ZV2_cjs = require('./chunk-QIOM5ZV2.cjs');
4
4
  var chunkOR5DRJCW_cjs = require('./chunk-OR5DRJCW.cjs');
5
5
  var React = require('react');
6
6
  var agGridReact = require('ag-grid-react');
@@ -413,7 +413,7 @@ function EmailRenderer(props) {
413
413
  className: "text-primary-600 dark:text-primary-400 inline-flex items-center gap-1.5 hover:underline",
414
414
  onClick: (e) => e.stopPropagation(),
415
415
  children: [
416
- /* @__PURE__ */ jsxRuntime.jsx(chunkD3BUYVLN_cjs.Mail, { className: "h-3 w-3 opacity-60" }),
416
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQIOM5ZV2_cjs.Mail, { className: "h-3 w-3 opacity-60" }),
417
417
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: value })
418
418
  ]
419
419
  }
@@ -430,7 +430,7 @@ function PhoneRenderer(props) {
430
430
  className: "text-foreground hover:text-primary-600 dark:hover:text-primary-400 inline-flex items-center gap-1.5",
431
431
  onClick: (e) => e.stopPropagation(),
432
432
  children: [
433
- /* @__PURE__ */ jsxRuntime.jsx(chunkD3BUYVLN_cjs.Phone, { className: "h-3 w-3 text-green-500 opacity-70" }),
433
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQIOM5ZV2_cjs.Phone, { className: "h-3 w-3 text-green-500 opacity-70" }),
434
434
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: displayValue })
435
435
  ]
436
436
  }
@@ -450,7 +450,7 @@ function DomainRenderer(props) {
450
450
  className: "text-primary-600 dark:text-primary-400 inline-flex items-center gap-1.5 hover:underline",
451
451
  onClick: (e) => e.stopPropagation(),
452
452
  children: [
453
- /* @__PURE__ */ jsxRuntime.jsx(chunkD3BUYVLN_cjs.Globe, { className: "h-3 w-3 opacity-60" }),
453
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQIOM5ZV2_cjs.Globe, { className: "h-3 w-3 opacity-60" }),
454
454
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: displayDomain })
455
455
  ]
456
456
  }
@@ -547,7 +547,7 @@ function BooleanRenderer(props) {
547
547
  isTrue ? "bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400" : "bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-400"
548
548
  ),
549
549
  children: [
550
- isTrue ? /* @__PURE__ */ jsxRuntime.jsx(chunkD3BUYVLN_cjs.CheckCircle, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntime.jsx(chunkD3BUYVLN_cjs.Clock, { className: "h-3 w-3" }),
550
+ isTrue ? /* @__PURE__ */ jsxRuntime.jsx(chunkQIOM5ZV2_cjs.CheckCircle, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntime.jsx(chunkQIOM5ZV2_cjs.Clock, { className: "h-3 w-3" }),
551
551
  isTrue ? "Yes" : "No"
552
552
  ]
553
553
  }
package/dist/ag-grid.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Mail, Phone, Globe, CheckCircle, Clock } from './chunk-K5T2PT4M.js';
1
+ import { Mail, Phone, Globe, CheckCircle, Clock } from './chunk-3K7QCDSV.js';
2
2
  import { cn } from './chunk-F3SOEIN2.js';
3
3
  import * as React from 'react';
4
4
  import { memo } from 'react';
@@ -44,6 +44,16 @@
44
44
  --mieweb-success-foreground: #ffffff;
45
45
  --mieweb-warning: #f59e0b;
46
46
  --mieweb-warning-foreground: #ffffff;
47
+ --mieweb-info: #0ea5e9;
48
+ --mieweb-info-foreground: #ffffff;
49
+ --mieweb-secondary-foreground: #ffffff;
50
+
51
+ /* Chart / Data Visualization */
52
+ --mieweb-chart-1: #27aae1;
53
+ --mieweb-chart-2: #22c55e;
54
+ --mieweb-chart-3: #f59e0b;
55
+ --mieweb-chart-4: #ef4444;
56
+ --mieweb-chart-5: #6366f1;
47
57
 
48
58
  /* Typography */
49
59
  --mieweb-font-sans: 'Nunito', ui-sans-serif, system-ui, sans-serif;
@@ -85,6 +95,16 @@
85
95
  --mieweb-success-foreground: #fafafa;
86
96
  --mieweb-warning: #d97706;
87
97
  --mieweb-warning-foreground: #fafafa;
98
+ --mieweb-info: #0284c7;
99
+ --mieweb-info-foreground: #fafafa;
100
+ --mieweb-secondary-foreground: #fafafa;
101
+
102
+ /* Chart */
103
+ --mieweb-chart-1: #38bdf8;
104
+ --mieweb-chart-2: #4ade80;
105
+ --mieweb-chart-3: #fbbf24;
106
+ --mieweb-chart-4: #f87171;
107
+ --mieweb-chart-5: #818cf8;
88
108
  }
89
109
 
90
110
  /* ============================================
@@ -41,10 +41,19 @@
41
41
  --mieweb-primary-900: #42193d;
42
42
  --mieweb-primary-950: #280e25;
43
43
 
44
- /* Secondary Color - Deep Teal Blue (for gradients) */
45
- --mieweb-secondary: #00497a;
46
- --mieweb-secondary-light: #006ba8;
47
- --mieweb-secondary-dark: #003658;
44
+ /* Secondary Color Scale - Deep Teal Blue */
45
+ --mieweb-secondary-50: #e6f3fa;
46
+ --mieweb-secondary-100: #b3dcf0;
47
+ --mieweb-secondary-200: #80c5e6;
48
+ --mieweb-secondary-300: #4daedc;
49
+ --mieweb-secondary-400: #2697d2;
50
+ --mieweb-secondary-500: #00497a;
51
+ --mieweb-secondary-600: #003d68;
52
+ --mieweb-secondary-700: #003658;
53
+ --mieweb-secondary-800: #002a45;
54
+ --mieweb-secondary-900: #001e33;
55
+ --mieweb-secondary-950: #001120;
56
+ --mieweb-secondary-foreground: #ffffff;
48
57
 
49
58
  /* Accent Color - Gold/Yellow (logo) */
50
59
  --mieweb-accent: #f8b700;
@@ -71,6 +80,15 @@
71
80
  --mieweb-success-foreground: #ffffff;
72
81
  --mieweb-warning: #f8b700;
73
82
  --mieweb-warning-foreground: #222326;
83
+ --mieweb-info: #0ea5e9;
84
+ --mieweb-info-foreground: #ffffff;
85
+
86
+ /* Chart / Data Visualization */
87
+ --mieweb-chart-1: #6e2b68;
88
+ --mieweb-chart-2: #00497a;
89
+ --mieweb-chart-3: #f8b700;
90
+ --mieweb-chart-4: #dc2626;
91
+ --mieweb-chart-5: #22c55e;
74
92
 
75
93
  /* Typography - Jost is the Enterprise Health font */
76
94
  --mieweb-font-sans: 'Jost', ui-sans-serif, system-ui, sans-serif;
@@ -115,6 +133,16 @@
115
133
  --mieweb-success-foreground: #fafafa;
116
134
  --mieweb-warning: #f8b700;
117
135
  --mieweb-warning-foreground: #222326;
136
+ --mieweb-info: #0284c7;
137
+ --mieweb-info-foreground: #fafafa;
138
+ --mieweb-secondary-foreground: #fafafa;
139
+
140
+ /* Chart */
141
+ --mieweb-chart-1: #c95ab8;
142
+ --mieweb-chart-2: #006ba8;
143
+ --mieweb-chart-3: #ffc933;
144
+ --mieweb-chart-4: #f87171;
145
+ --mieweb-chart-5: #4ade80;
118
146
 
119
147
  --mieweb-glass-background: rgba(255, 255, 255, 0.1);
120
148
  }
@@ -1,6 +1,6 @@
1
1
  import { BrandConfig } from './types.cjs';
2
2
  export { BrandBorderRadius, BrandBoxShadow, BrandColors, BrandTypography, ColorScale, SemanticColors, createBrandPreset, generateBrandCSS, generateTailwindTheme } from './types.cjs';
3
- export { default as bluehiveBrand } from './bluehive.cjs';
3
+ export { bluehiveBrand } from './bluehive.cjs';
4
4
  export { ozwellBrand } from './ozwell.cjs';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import { BrandConfig } from './types.js';
2
2
  export { BrandBorderRadius, BrandBoxShadow, BrandColors, BrandTypography, ColorScale, SemanticColors, createBrandPreset, generateBrandCSS, generateTailwindTheme } from './types.js';
3
- export { default as bluehiveBrand } from './bluehive.js';
3
+ export { bluehiveBrand } from './bluehive.js';
4
4
  export { ozwellBrand } from './ozwell.js';
5
5
 
6
6
  /**
@@ -44,6 +44,16 @@
44
44
  --mieweb-success-foreground: #ffffff;
45
45
  --mieweb-warning: #f59e0b;
46
46
  --mieweb-warning-foreground: #ffffff;
47
+ --mieweb-info: #0ea5e9;
48
+ --mieweb-info-foreground: #ffffff;
49
+ --mieweb-secondary-foreground: #ffffff;
50
+
51
+ /* Chart / Data Visualization */
52
+ --mieweb-chart-1: #27ae60;
53
+ --mieweb-chart-2: #0ea5e9;
54
+ --mieweb-chart-3: #f59e0b;
55
+ --mieweb-chart-4: #ef4444;
56
+ --mieweb-chart-5: #6366f1;
47
57
 
48
58
  /* Typography */
49
59
  --mieweb-font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
@@ -85,6 +95,16 @@
85
95
  --mieweb-success-foreground: #fafafa;
86
96
  --mieweb-warning: #d97706;
87
97
  --mieweb-warning-foreground: #fafafa;
98
+ --mieweb-info: #0284c7;
99
+ --mieweb-info-foreground: #fafafa;
100
+ --mieweb-secondary-foreground: #fafafa;
101
+
102
+ /* Chart */
103
+ --mieweb-chart-1: #4ade80;
104
+ --mieweb-chart-2: #38bdf8;
105
+ --mieweb-chart-3: #fbbf24;
106
+ --mieweb-chart-4: #f87171;
107
+ --mieweb-chart-5: #818cf8;
88
108
  }
89
109
 
90
110
  /* ============================================
@@ -53,6 +53,16 @@
53
53
  --mieweb-success-foreground: #ffffff;
54
54
  --mieweb-warning: #f59e0b;
55
55
  --mieweb-warning-foreground: #ffffff;
56
+ --mieweb-info: #0ea5e9;
57
+ --mieweb-info-foreground: #ffffff;
58
+ --mieweb-secondary-foreground: #ffffff;
59
+
60
+ /* Chart / Data Visualization */
61
+ --mieweb-chart-1: #27aae1;
62
+ --mieweb-chart-2: #22c55e;
63
+ --mieweb-chart-3: #f59e0b;
64
+ --mieweb-chart-4: #ef4444;
65
+ --mieweb-chart-5: #6366f1;
56
66
 
57
67
  /* Typography */
58
68
  --mieweb-font-sans: 'Nunito', ui-sans-serif, system-ui, sans-serif;
@@ -94,6 +104,16 @@
94
104
  --mieweb-success-foreground: #fafafa;
95
105
  --mieweb-warning: #d97706;
96
106
  --mieweb-warning-foreground: #fafafa;
107
+ --mieweb-info: #0284c7;
108
+ --mieweb-info-foreground: #fafafa;
109
+ --mieweb-secondary-foreground: #fafafa;
110
+
111
+ /* Chart */
112
+ --mieweb-chart-1: #38bdf8;
113
+ --mieweb-chart-2: #4ade80;
114
+ --mieweb-chart-3: #fbbf24;
115
+ --mieweb-chart-4: #f87171;
116
+ --mieweb-chart-5: #818cf8;
97
117
  }
98
118
 
99
119
  /* ============================================
@@ -51,6 +51,42 @@
51
51
  --mieweb-success-foreground: #ffffff;
52
52
  --mieweb-warning: #ffd200;
53
53
  --mieweb-warning-foreground: #1a1a1a;
54
+ --mieweb-info: #0ea5e9;
55
+ --mieweb-info-foreground: #ffffff;
56
+ --mieweb-secondary-foreground: #ffffff;
57
+
58
+ /* Waggleline Custom Success Scale (brand green #009C4E) */
59
+ --mieweb-success-50: #ecfdf5;
60
+ --mieweb-success-100: #d1fae5;
61
+ --mieweb-success-200: #a7f3d0;
62
+ --mieweb-success-300: #6ee7b7;
63
+ --mieweb-success-400: #34d399;
64
+ --mieweb-success-500: #009c4e;
65
+ --mieweb-success-600: #008542;
66
+ --mieweb-success-700: #006e37;
67
+ --mieweb-success-800: #00572b;
68
+ --mieweb-success-900: #004020;
69
+ --mieweb-success-950: #002914;
70
+
71
+ /* Waggleline Custom Warning Scale (brand yellow #FFD200) */
72
+ --mieweb-warning-50: #fffde6;
73
+ --mieweb-warning-100: #fff9b3;
74
+ --mieweb-warning-200: #fff580;
75
+ --mieweb-warning-300: #fff14d;
76
+ --mieweb-warning-400: #ffeb26;
77
+ --mieweb-warning-500: #ffd200;
78
+ --mieweb-warning-600: #d4af00;
79
+ --mieweb-warning-700: #aa8c00;
80
+ --mieweb-warning-800: #806900;
81
+ --mieweb-warning-900: #554600;
82
+ --mieweb-warning-950: #332a00;
83
+
84
+ /* Chart / Data Visualization */
85
+ --mieweb-chart-1: #17aeed;
86
+ --mieweb-chart-2: #009c4e;
87
+ --mieweb-chart-3: #ffd200;
88
+ --mieweb-chart-4: #e04501;
89
+ --mieweb-chart-5: #8b5cf6;
54
90
 
55
91
  /* Typography */
56
92
  --mieweb-font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
@@ -99,6 +135,16 @@
99
135
  --mieweb-success-foreground: #f9fafb;
100
136
  --mieweb-warning: #ffd200;
101
137
  --mieweb-warning-foreground: #1a1a1a;
138
+ --mieweb-info: #0284c7;
139
+ --mieweb-info-foreground: #f9fafb;
140
+ --mieweb-secondary-foreground: #f9fafb;
141
+
142
+ /* Chart */
143
+ --mieweb-chart-1: #38bdf8;
144
+ --mieweb-chart-2: #34d399;
145
+ --mieweb-chart-3: #ffeb26;
146
+ --mieweb-chart-4: #f87171;
147
+ --mieweb-chart-5: #a78bfa;
102
148
  }
103
149
 
104
150
  /* ============================================
@@ -44,6 +44,16 @@
44
44
  --mieweb-success-foreground: #ffffff;
45
45
  --mieweb-warning: #f59e0b;
46
46
  --mieweb-warning-foreground: #ffffff;
47
+ --mieweb-info: #0ea5e9;
48
+ --mieweb-info-foreground: #ffffff;
49
+ --mieweb-secondary-foreground: #ffffff;
50
+
51
+ /* Chart / Data Visualization */
52
+ --mieweb-chart-1: #f5841f;
53
+ --mieweb-chart-2: #22c55e;
54
+ --mieweb-chart-3: #0ea5e9;
55
+ --mieweb-chart-4: #ef4444;
56
+ --mieweb-chart-5: #6366f1;
47
57
 
48
58
  /* Typography */
49
59
  --mieweb-font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
@@ -85,6 +95,16 @@
85
95
  --mieweb-success-foreground: #fafafa;
86
96
  --mieweb-warning: #d97706;
87
97
  --mieweb-warning-foreground: #fafafa;
98
+ --mieweb-info: #0284c7;
99
+ --mieweb-info-foreground: #fafafa;
100
+ --mieweb-secondary-foreground: #fafafa;
101
+
102
+ /* Chart */
103
+ --mieweb-chart-1: #fb923c;
104
+ --mieweb-chart-2: #4ade80;
105
+ --mieweb-chart-3: #38bdf8;
106
+ --mieweb-chart-4: #f87171;
107
+ --mieweb-chart-5: #818cf8;
88
108
  }
89
109
 
90
110
  /* ============================================
@@ -33,7 +33,7 @@ var scrollLockState = {
33
33
  originalOverflow: null};
34
34
  var modalOverlayVariants = classVarianceAuthority.cva(
35
35
  [
36
- "fixed inset-0 z-50",
36
+ "fixed inset-0",
37
37
  "bg-black/50 backdrop-blur-sm",
38
38
  "data-[state=open]:animate-in data-[state=open]:fade-in-0",
39
39
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0"
@@ -45,10 +45,17 @@ var modalOverlayVariants = classVarianceAuthority.cva(
45
45
  );
46
46
  var modalContentVariants = classVarianceAuthority.cva(
47
47
  [
48
- "fixed left-1/2 top-1/2 z-50",
49
- "-translate-x-1/2 -translate-y-1/2",
50
- "w-full bg-card text-card-foreground",
51
- "border border-border rounded-xl shadow-lg",
48
+ "relative w-full bg-card text-card-foreground",
49
+ "border border-border shadow-lg",
50
+ // Full-screen on mobile, rounded on larger screens
51
+ "rounded-none sm:rounded-xl",
52
+ "flex flex-col",
53
+ // Full viewport height on mobile, constrained on larger screens
54
+ "max-h-dvh sm:max-h-[calc(100dvh-2rem)]",
55
+ "min-h-dvh sm:min-h-0",
56
+ // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),
57
+ // make it participate in the flex column layout so overflow constraints work.
58
+ "[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0",
52
59
  "focus:outline-none",
53
60
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
54
61
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
@@ -57,13 +64,13 @@ var modalContentVariants = classVarianceAuthority.cva(
57
64
  {
58
65
  variants: {
59
66
  size: {
60
- sm: "max-w-sm",
61
- md: "max-w-md",
62
- lg: "max-w-lg",
63
- xl: "max-w-xl",
64
- "2xl": "max-w-2xl",
65
- "3xl": "max-w-3xl",
66
- "4xl": "max-w-4xl",
67
+ sm: "sm:max-w-sm",
68
+ md: "sm:max-w-md",
69
+ lg: "sm:max-w-lg",
70
+ xl: "sm:max-w-xl",
71
+ "2xl": "sm:max-w-2xl",
72
+ "3xl": "sm:max-w-3xl",
73
+ "4xl": "sm:max-w-4xl",
67
74
  full: "max-w-[calc(100vw-2rem)]"
68
75
  }
69
76
  },
@@ -129,26 +136,33 @@ function Modal({
129
136
  {
130
137
  className: chunkOR5DRJCW_cjs.cn(modalOverlayVariants()),
131
138
  "data-state": open ? "open" : "closed",
132
- onClick: handleOverlayClick,
133
139
  "aria-hidden": "true"
134
140
  }
135
141
  ),
136
- /* @__PURE__ */ jsxRuntime.jsx(
142
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
137
143
  "div",
138
144
  {
139
- ref: focusTrapRef,
140
- role: "dialog",
141
- "aria-modal": "true",
142
- "aria-label": ariaLabel,
143
- "aria-labelledby": ariaLabelledBy || `${modalId}-title`,
144
- "aria-describedby": ariaDescribedBy,
145
- id: modalId,
146
- tabIndex: -1,
147
- "data-state": open ? "open" : "closed",
148
- className: chunkOR5DRJCW_cjs.cn(modalContentVariants({ size }), className),
149
- children
145
+ className: "flex min-h-full items-center justify-center p-0 sm:p-4",
146
+ onClick: handleOverlayClick,
147
+ children: /* @__PURE__ */ jsxRuntime.jsx(
148
+ "div",
149
+ {
150
+ ref: focusTrapRef,
151
+ role: "dialog",
152
+ "aria-modal": "true",
153
+ "aria-label": ariaLabel,
154
+ "aria-labelledby": ariaLabelledBy || `${modalId}-title`,
155
+ "aria-describedby": ariaDescribedBy,
156
+ id: modalId,
157
+ tabIndex: -1,
158
+ "data-state": open ? "open" : "closed",
159
+ className: chunkOR5DRJCW_cjs.cn(modalContentVariants({ size }), className),
160
+ onClick: (e) => e.stopPropagation(),
161
+ children
162
+ }
163
+ )
150
164
  }
151
- )
165
+ ) })
152
166
  ] })
153
167
  }
154
168
  );
@@ -170,7 +184,7 @@ var ModalHeader = React__namespace.forwardRef(
170
184
  {
171
185
  ref,
172
186
  className: chunkOR5DRJCW_cjs.cn(
173
- "flex items-center justify-between",
187
+ "flex shrink-0 items-center justify-between",
174
188
  "border-border border-b px-6 py-4",
175
189
  className
176
190
  ),
@@ -232,7 +246,14 @@ var ModalClose = React__namespace.forwardRef(
232
246
  );
233
247
  ModalClose.displayName = "ModalClose";
234
248
  var ModalBody = React__namespace.forwardRef(
235
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: chunkOR5DRJCW_cjs.cn("px-6 py-4", className), ...props })
249
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
250
+ "div",
251
+ {
252
+ ref,
253
+ className: chunkOR5DRJCW_cjs.cn("min-h-0 flex-1 overflow-y-auto px-6 py-4", className),
254
+ ...props
255
+ }
256
+ )
236
257
  );
237
258
  ModalBody.displayName = "ModalBody";
238
259
  var ModalFooter = React__namespace.forwardRef(
@@ -241,7 +262,7 @@ var ModalFooter = React__namespace.forwardRef(
241
262
  {
242
263
  ref,
243
264
  className: chunkOR5DRJCW_cjs.cn(
244
- "flex items-center justify-end gap-3",
265
+ "flex shrink-0 items-center justify-end gap-3",
245
266
  "border-border border-t px-6 py-4",
246
267
  className
247
268
  ),
@@ -280,5 +301,5 @@ exports.ModalHeader = ModalHeader;
280
301
  exports.ModalTitle = ModalTitle;
281
302
  exports.modalContentVariants = modalContentVariants;
282
303
  exports.modalOverlayVariants = modalOverlayVariants;
283
- //# sourceMappingURL=chunk-I7L6CQXR.cjs.map
284
- //# sourceMappingURL=chunk-I7L6CQXR.cjs.map
304
+ //# sourceMappingURL=chunk-377KAB4C.cjs.map
305
+ //# sourceMappingURL=chunk-377KAB4C.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Modal/Modal.tsx"],"names":["cva","React","useFocusTrap","useEscapeKey","isStorybookDocsMode","jsx","jsxs","cn"],"mappings":"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","file":"chunk-377KAB4C.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isStorybookDocsMode } from '../../utils/environment';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\n\n/**\n * Modal scroll lock state manager.\n * Uses a singleton pattern with ref-like storage to track open modals\n * and manage body scroll locking across multiple modal instances.\n * Includes reset capability for testing environments.\n */\nconst scrollLockState = {\n count: 0,\n originalOverflow: null as string | null,\n reset() {\n this.count = 0;\n this.originalOverflow = null;\n },\n};\n\n// Export for testing environments\nexport const __resetScrollLockState = () => scrollLockState.reset();\n\nconst modalOverlayVariants = cva(\n [\n 'fixed inset-0',\n 'bg-black/50 backdrop-blur-sm',\n 'data-[state=open]:animate-in data-[state=open]:fade-in-0',\n 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0',\n ],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\nconst modalContentVariants = cva(\n [\n 'relative w-full bg-card text-card-foreground',\n 'border border-border shadow-lg',\n // Full-screen on mobile, rounded on larger screens\n 'rounded-none sm:rounded-xl',\n 'flex flex-col',\n // Full viewport height on mobile, constrained on larger screens\n 'max-h-dvh sm:max-h-[calc(100dvh-2rem)]',\n 'min-h-dvh sm:min-h-0',\n // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),\n // make it participate in the flex column layout so overflow constraints work.\n '[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0',\n 'focus:outline-none',\n 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',\n 'duration-200',\n ],\n {\n variants: {\n size: {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n full: 'max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface ModalProps extends VariantProps<typeof modalContentVariants> {\n /** Whether the modal is open */\n open: boolean;\n /** Callback when the modal should close */\n onOpenChange: (open: boolean) => void;\n /** Modal content */\n children: React.ReactNode;\n /** Whether to close when clicking the overlay */\n closeOnOverlayClick?: boolean;\n /** Whether to close when pressing Escape */\n closeOnEscape?: boolean;\n /** Additional class name for the modal content */\n className?: string;\n /** ID for the modal, used for accessibility */\n id?: string;\n /** Accessible label for the modal */\n 'aria-label'?: string;\n /** ID of the element that labels the modal */\n 'aria-labelledby'?: string;\n /** ID of the element that describes the modal */\n 'aria-describedby'?: string;\n}\n\n/**\n * An accessible modal/dialog component.\n *\n * @example\n * ```tsx\n * <Modal open={isOpen} onOpenChange={setIsOpen} size=\"lg\">\n * <ModalHeader>\n * <ModalTitle>Confirm Action</ModalTitle>\n * <ModalClose />\n * </ModalHeader>\n * <ModalBody>\n * Are you sure you want to continue?\n * </ModalBody>\n * <ModalFooter>\n * <Button variant=\"secondary\" onClick={() => setIsOpen(false)}>Cancel</Button>\n * <Button onClick={handleConfirm}>Confirm</Button>\n * </ModalFooter>\n * </Modal>\n * ```\n */\nfunction Modal({\n open,\n onOpenChange,\n children,\n size,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}: ModalProps) {\n const generatedId = React.useId();\n const modalId = id || generatedId;\n\n // Focus trap (only active when modal is open)\n const focusTrapRef = useFocusTrap<HTMLDivElement>(open);\n\n // Handle escape key\n useEscapeKey(() => {\n if (closeOnEscape && open) {\n onOpenChange(false);\n }\n }, open);\n\n // Handle overlay click\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onOpenChange(false);\n }\n },\n [closeOnOverlayClick, onOpenChange]\n );\n\n // Prevent body scroll when modal is open (handles multiple modals)\n // Skip scroll lock in Storybook docs mode where multiple stories render inline\n React.useEffect(() => {\n // Skip scroll lock entirely in Storybook docs mode\n if (!open || isStorybookDocsMode()) {\n return undefined;\n }\n\n scrollLockState.count++;\n // Only capture and set overflow when first modal opens\n if (scrollLockState.count === 1) {\n scrollLockState.originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n scrollLockState.count--;\n // Only restore overflow when last modal closes\n if (\n scrollLockState.count === 0 &&\n scrollLockState.originalOverflow !== null\n ) {\n document.body.style.overflow = scrollLockState.originalOverflow;\n scrollLockState.originalOverflow = null;\n }\n };\n }, [open]);\n\n if (!open) return null;\n\n return (\n <ModalContext.Provider\n value={{ onClose: () => onOpenChange(false), modalId }}\n >\n {/* Portal to body */}\n <div className=\"fixed inset-0 z-50\">\n {/* Overlay backdrop */}\n <div\n className={cn(modalOverlayVariants())}\n data-state={open ? 'open' : 'closed'}\n aria-hidden=\"true\"\n />\n {/* Scrollable centering container — click outside to close */}\n <div className=\"fixed inset-0 overflow-y-auto\">\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}\n <div\n className=\"flex min-h-full items-center justify-center p-0 sm:p-4\"\n onClick={handleOverlayClick}\n >\n {/* Content */}\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */}\n <div\n ref={focusTrapRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy || `${modalId}-title`}\n aria-describedby={ariaDescribedBy}\n id={modalId}\n tabIndex={-1}\n data-state={open ? 'open' : 'closed'}\n className={cn(modalContentVariants({ size }), className)}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </div>\n </div>\n </div>\n </div>\n </ModalContext.Provider>\n );\n}\n\nModal.displayName = 'Modal';\n\n// ============================================================================\n// Modal Context\n// ============================================================================\n\ninterface ModalContextValue {\n onClose: () => void;\n modalId: string;\n}\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\nfunction useModalContext() {\n const context = React.useContext(ModalContext);\n if (!context) {\n throw new Error('Modal components must be used within a Modal');\n }\n return context;\n}\n\n// ============================================================================\n// Modal Header\n// ============================================================================\n\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Header section of a Modal.\n */\nconst ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex shrink-0 items-center justify-between',\n 'border-border border-b px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalHeader.displayName = 'ModalHeader';\n\n// ============================================================================\n// Modal Title\n// ============================================================================\n\nexport type ModalTitleProps = React.HTMLAttributes<HTMLHeadingElement>;\n\n/**\n * Title for a Modal.\n */\nconst ModalTitle = React.forwardRef<HTMLHeadingElement, ModalTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { modalId } = useModalContext();\n return (\n <h2\n ref={ref}\n id={`${modalId}-title`}\n className={cn(\n 'text-lg leading-none font-semibold tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </h2>\n );\n }\n);\n\nModalTitle.displayName = 'ModalTitle';\n\n// ============================================================================\n// Modal Close Button\n// ============================================================================\n\nexport type ModalCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for a Modal.\n */\nconst ModalClose = React.forwardRef<HTMLButtonElement, ModalCloseProps>(\n ({ className, children, onClick, ...props }, ref) => {\n const { onClose } = useModalContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (!e.defaultPrevented) {\n onClose();\n }\n },\n [onClick, onClose]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleClick}\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-lg',\n 'text-muted-foreground hover:text-foreground',\n 'hover:bg-muted transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n className\n )}\n aria-label=\"Close\"\n {...props}\n >\n {children || <CloseIcon />}\n </button>\n );\n }\n);\n\nModalClose.displayName = 'ModalClose';\n\n// ============================================================================\n// Modal Body\n// ============================================================================\n\nexport type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Main content area of a Modal.\n */\nconst ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4', className)}\n {...props}\n />\n )\n);\n\nModalBody.displayName = 'ModalBody';\n\n// ============================================================================\n// Modal Footer\n// ============================================================================\n\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Footer section of a Modal, typically for action buttons.\n */\nconst ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex shrink-0 items-center justify-end gap-3',\n 'border-border border-t px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalFooter.displayName = 'ModalFooter';\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nfunction CloseIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n modalContentVariants,\n modalOverlayVariants,\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { AlertCircle, ArrowLeft, Bell, Calendar, Camera, Check, CheckCircle, ChevronDown, ClipboardCheck, ClipboardList, ClipboardPlus, Clock, Download, ExternalLink, FileCheck, FileHeart, FilePlus, FileText, Globe, HeartPulse, Image, Mail, MoreHorizontal, MoreVertical, Paperclip, Pencil, Phone, Pill, Plus, Printer, RefreshCw, Scan, ScanLine, Send, Share, Stethoscope, Trash2, Upload, User, Users, Wheat, X } from 'lucide-react';
2
+ //# sourceMappingURL=chunk-3K7QCDSV.js.map
3
+ //# sourceMappingURL=chunk-3K7QCDSV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-K5T2PT4M.js","sourcesContent":[]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-3K7QCDSV.js","sourcesContent":[]}