@optifye/dashboard-core 3.0.0 → 4.0.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 CHANGED
@@ -196,6 +196,87 @@ This CSS file includes:
196
196
 
197
197
  **Note:** You do NOT need to separately import `react-day-picker/dist/style.css` as these styles are already included in the package's global CSS.
198
198
 
199
+ ## Authentication Components
200
+
201
+ The package now includes built-in authentication components for a complete Supabase OTP-based authentication flow. See [AUTH_COMPONENTS_GUIDE.md](./AUTH_COMPONENTS_GUIDE.md) for detailed usage.
202
+
203
+ ### Quick Start
204
+
205
+ 1. **Copy the Optifye logo** from `node_modules/@optifye/dashboard-core/src/assets/optifye-logo.png` to your `public` folder.
206
+
207
+ 2. **Create login page**:
208
+ ```tsx
209
+ import { LoginPage } from '@optifye/dashboard-core';
210
+
211
+ export default function Login() {
212
+ return <LoginPage logoSrc="/optifye-logo.png" />;
213
+ }
214
+ ```
215
+
216
+ 3. **Create auth callback page**:
217
+ ```tsx
218
+ import { AuthCallback } from '@optifye/dashboard-core';
219
+
220
+ export default function AuthCallbackPage() {
221
+ return <AuthCallback />;
222
+ }
223
+ ```
224
+
225
+ ### Available Auth Components
226
+
227
+ - **LoginPage**: Full-featured login page with email OTP authentication
228
+ - **AuthCallback**: Handles Supabase authentication callbacks
229
+ - **DebugAuth**: Debug page for troubleshooting Supabase configuration
230
+ - **withAuth**: HOC for protecting routes (already documented)
231
+
232
+ ### Rate Limiting
233
+
234
+ The package includes built-in rate limiting utilities:
235
+
236
+ ```tsx
237
+ import { checkRateLimit } from '@optifye/dashboard-core';
238
+
239
+ // In your API route
240
+ const { allowed, retryAfter } = checkRateLimit(email, {
241
+ windowMs: 60000, // 1 minute
242
+ maxRequests: 3 // 3 attempts
243
+ });
244
+ ```
245
+
246
+ ## Mobile Responsiveness
247
+
248
+ All dashboard components are designed to be fully responsive and mobile-friendly:
249
+
250
+ ### Responsive Features
251
+
252
+ - **Adaptive Grid Layouts**: Workspace video grids automatically adjust to show 2x2 layout on mobile screens
253
+ - **Responsive Text Sizes**: Text sizes scale appropriately across different screen sizes
254
+ - **Touch-Optimized Controls**: Buttons and interactive elements are sized for touch interaction
255
+ - **Flexible KPI Cards**: KPI cards stack vertically on mobile screens for better readability
256
+ - **Mobile-First Navigation**: Compact headers and navigation elements on smaller screens
257
+
258
+ ### Breakpoint System
259
+
260
+ The dashboard uses Tailwind CSS breakpoints:
261
+ - Mobile: < 640px (default)
262
+ - Small (sm): ≥ 640px
263
+ - Medium (md): ≥ 768px
264
+ - Large (lg): ≥ 1024px
265
+ - Extra Large (xl): ≥ 1280px
266
+
267
+ ### Usage Example for Mobile View
268
+
269
+ ```tsx
270
+ // The dashboard automatically adapts to mobile screens
271
+ <HomeView
272
+ defaultLineId={defaultLineId}
273
+ factoryViewId={factoryViewId}
274
+ // ... other props
275
+ />
276
+ ```
277
+
278
+ Components handle responsive behavior internally, no additional configuration needed.
279
+
199
280
  ## Troubleshooting
200
281
 
201
282
  ### Next.js Module Resolution Error
@@ -702,4 +783,8 @@ The package repository field has been properly formatted for npm publishing stan
702
783
 
703
784
  ## License
704
785
 
705
- (License information, e.g., MIT, would go here.)
786
+ (License information, e.g., MIT, would go here.)
787
+
788
+ ---
789
+
790
+ *Last updated for v4.0.0 - Published to npm*
package/dist/index.css ADDED
@@ -0,0 +1,389 @@
1
+ /* src/global.css */
2
+ *,
3
+ ::before,
4
+ ::after {
5
+ --tw-border-spacing-x: 0;
6
+ --tw-border-spacing-y: 0;
7
+ --tw-translate-x: 0;
8
+ --tw-translate-y: 0;
9
+ --tw-rotate: 0;
10
+ --tw-skew-x: 0;
11
+ --tw-skew-y: 0;
12
+ --tw-scale-x: 1;
13
+ --tw-scale-y: 1;
14
+ --tw-pan-x: ;
15
+ --tw-pan-y: ;
16
+ --tw-pinch-zoom: ;
17
+ --tw-scroll-snap-strictness: proximity;
18
+ --tw-gradient-from-position: ;
19
+ --tw-gradient-via-position: ;
20
+ --tw-gradient-to-position: ;
21
+ --tw-ordinal: ;
22
+ --tw-slashed-zero: ;
23
+ --tw-numeric-figure: ;
24
+ --tw-numeric-spacing: ;
25
+ --tw-numeric-fraction: ;
26
+ --tw-ring-inset: ;
27
+ --tw-ring-offset-width: 0px;
28
+ --tw-ring-offset-color: #fff;
29
+ --tw-ring-color: rgb(59 130 246 / 0.5);
30
+ --tw-ring-offset-shadow: 0 0 #0000;
31
+ --tw-ring-shadow: 0 0 #0000;
32
+ --tw-shadow: 0 0 #0000;
33
+ --tw-shadow-colored: 0 0 #0000;
34
+ --tw-blur: ;
35
+ --tw-brightness: ;
36
+ --tw-contrast: ;
37
+ --tw-grayscale: ;
38
+ --tw-hue-rotate: ;
39
+ --tw-invert: ;
40
+ --tw-saturate: ;
41
+ --tw-sepia: ;
42
+ --tw-drop-shadow: ;
43
+ --tw-backdrop-blur: ;
44
+ --tw-backdrop-brightness: ;
45
+ --tw-backdrop-contrast: ;
46
+ --tw-backdrop-grayscale: ;
47
+ --tw-backdrop-hue-rotate: ;
48
+ --tw-backdrop-invert: ;
49
+ --tw-backdrop-opacity: ;
50
+ --tw-backdrop-saturate: ;
51
+ --tw-backdrop-sepia: ;
52
+ --tw-contain-size: ;
53
+ --tw-contain-layout: ;
54
+ --tw-contain-paint: ;
55
+ --tw-contain-style: ;
56
+ }
57
+ ::backdrop {
58
+ --tw-border-spacing-x: 0;
59
+ --tw-border-spacing-y: 0;
60
+ --tw-translate-x: 0;
61
+ --tw-translate-y: 0;
62
+ --tw-rotate: 0;
63
+ --tw-skew-x: 0;
64
+ --tw-skew-y: 0;
65
+ --tw-scale-x: 1;
66
+ --tw-scale-y: 1;
67
+ --tw-pan-x: ;
68
+ --tw-pan-y: ;
69
+ --tw-pinch-zoom: ;
70
+ --tw-scroll-snap-strictness: proximity;
71
+ --tw-gradient-from-position: ;
72
+ --tw-gradient-via-position: ;
73
+ --tw-gradient-to-position: ;
74
+ --tw-ordinal: ;
75
+ --tw-slashed-zero: ;
76
+ --tw-numeric-figure: ;
77
+ --tw-numeric-spacing: ;
78
+ --tw-numeric-fraction: ;
79
+ --tw-ring-inset: ;
80
+ --tw-ring-offset-width: 0px;
81
+ --tw-ring-offset-color: #fff;
82
+ --tw-ring-color: rgb(59 130 246 / 0.5);
83
+ --tw-ring-offset-shadow: 0 0 #0000;
84
+ --tw-ring-shadow: 0 0 #0000;
85
+ --tw-shadow: 0 0 #0000;
86
+ --tw-shadow-colored: 0 0 #0000;
87
+ --tw-blur: ;
88
+ --tw-brightness: ;
89
+ --tw-contrast: ;
90
+ --tw-grayscale: ;
91
+ --tw-hue-rotate: ;
92
+ --tw-invert: ;
93
+ --tw-saturate: ;
94
+ --tw-sepia: ;
95
+ --tw-drop-shadow: ;
96
+ --tw-backdrop-blur: ;
97
+ --tw-backdrop-brightness: ;
98
+ --tw-backdrop-contrast: ;
99
+ --tw-backdrop-grayscale: ;
100
+ --tw-backdrop-hue-rotate: ;
101
+ --tw-backdrop-invert: ;
102
+ --tw-backdrop-opacity: ;
103
+ --tw-backdrop-saturate: ;
104
+ --tw-backdrop-sepia: ;
105
+ --tw-contain-size: ;
106
+ --tw-contain-layout: ;
107
+ --tw-contain-paint: ;
108
+ --tw-contain-style: ;
109
+ }
110
+ *,
111
+ ::before,
112
+ ::after {
113
+ box-sizing: border-box;
114
+ border-width: 0;
115
+ border-style: solid;
116
+ border-color: #e5e7eb;
117
+ }
118
+ ::before,
119
+ ::after {
120
+ --tw-content: "";
121
+ }
122
+ html,
123
+ :host {
124
+ line-height: 1.5;
125
+ -webkit-text-size-adjust: 100%;
126
+ -moz-tab-size: 4;
127
+ -o-tab-size: 4;
128
+ tab-size: 4;
129
+ font-family:
130
+ ui-sans-serif,
131
+ system-ui,
132
+ sans-serif,
133
+ "Apple Color Emoji",
134
+ "Segoe UI Emoji",
135
+ "Segoe UI Symbol",
136
+ "Noto Color Emoji";
137
+ font-feature-settings: normal;
138
+ font-variation-settings: normal;
139
+ -webkit-tap-highlight-color: transparent;
140
+ }
141
+ body {
142
+ margin: 0;
143
+ line-height: inherit;
144
+ }
145
+ hr {
146
+ height: 0;
147
+ color: inherit;
148
+ border-top-width: 1px;
149
+ }
150
+ abbr:where([title]) {
151
+ -webkit-text-decoration: underline dotted;
152
+ text-decoration: underline dotted;
153
+ }
154
+ h1,
155
+ h2,
156
+ h3,
157
+ h4,
158
+ h5,
159
+ h6 {
160
+ font-size: inherit;
161
+ font-weight: inherit;
162
+ }
163
+ a {
164
+ color: inherit;
165
+ text-decoration: inherit;
166
+ }
167
+ b,
168
+ strong {
169
+ font-weight: bolder;
170
+ }
171
+ code,
172
+ kbd,
173
+ samp,
174
+ pre {
175
+ font-family:
176
+ ui-monospace,
177
+ SFMono-Regular,
178
+ Menlo,
179
+ Monaco,
180
+ Consolas,
181
+ "Liberation Mono",
182
+ "Courier New",
183
+ monospace;
184
+ font-feature-settings: normal;
185
+ font-variation-settings: normal;
186
+ font-size: 1em;
187
+ }
188
+ small {
189
+ font-size: 80%;
190
+ }
191
+ sub,
192
+ sup {
193
+ font-size: 75%;
194
+ line-height: 0;
195
+ position: relative;
196
+ vertical-align: baseline;
197
+ }
198
+ sub {
199
+ bottom: -0.25em;
200
+ }
201
+ sup {
202
+ top: -0.5em;
203
+ }
204
+ table {
205
+ text-indent: 0;
206
+ border-color: inherit;
207
+ border-collapse: collapse;
208
+ }
209
+ button,
210
+ input,
211
+ optgroup,
212
+ select,
213
+ textarea {
214
+ font-family: inherit;
215
+ font-feature-settings: inherit;
216
+ font-variation-settings: inherit;
217
+ font-size: 100%;
218
+ font-weight: inherit;
219
+ line-height: inherit;
220
+ letter-spacing: inherit;
221
+ color: inherit;
222
+ margin: 0;
223
+ padding: 0;
224
+ }
225
+ button,
226
+ select {
227
+ text-transform: none;
228
+ }
229
+ button,
230
+ input:where([type=button]),
231
+ input:where([type=reset]),
232
+ input:where([type=submit]) {
233
+ -webkit-appearance: button;
234
+ background-color: transparent;
235
+ background-image: none;
236
+ }
237
+ :-moz-focusring {
238
+ outline: auto;
239
+ }
240
+ :-moz-ui-invalid {
241
+ box-shadow: none;
242
+ }
243
+ progress {
244
+ vertical-align: baseline;
245
+ }
246
+ ::-webkit-inner-spin-button,
247
+ ::-webkit-outer-spin-button {
248
+ height: auto;
249
+ }
250
+ [type=search] {
251
+ -webkit-appearance: textfield;
252
+ outline-offset: -2px;
253
+ }
254
+ ::-webkit-search-decoration {
255
+ -webkit-appearance: none;
256
+ }
257
+ ::-webkit-file-upload-button {
258
+ -webkit-appearance: button;
259
+ font: inherit;
260
+ }
261
+ summary {
262
+ display: list-item;
263
+ }
264
+ blockquote,
265
+ dl,
266
+ dd,
267
+ h1,
268
+ h2,
269
+ h3,
270
+ h4,
271
+ h5,
272
+ h6,
273
+ hr,
274
+ figure,
275
+ p,
276
+ pre {
277
+ margin: 0;
278
+ }
279
+ fieldset {
280
+ margin: 0;
281
+ padding: 0;
282
+ }
283
+ legend {
284
+ padding: 0;
285
+ }
286
+ ol,
287
+ ul,
288
+ menu {
289
+ list-style: none;
290
+ margin: 0;
291
+ padding: 0;
292
+ }
293
+ dialog {
294
+ padding: 0;
295
+ }
296
+ textarea {
297
+ resize: vertical;
298
+ }
299
+ input::-moz-placeholder,
300
+ textarea::-moz-placeholder {
301
+ opacity: 1;
302
+ color: #9ca3af;
303
+ }
304
+ input::placeholder,
305
+ textarea::placeholder {
306
+ opacity: 1;
307
+ color: #9ca3af;
308
+ }
309
+ button,
310
+ [role=button] {
311
+ cursor: pointer;
312
+ }
313
+ :disabled {
314
+ cursor: default;
315
+ }
316
+ img,
317
+ svg,
318
+ video,
319
+ canvas,
320
+ audio,
321
+ iframe,
322
+ embed,
323
+ object {
324
+ display: block;
325
+ vertical-align: middle;
326
+ }
327
+ img,
328
+ video {
329
+ max-width: 100%;
330
+ height: auto;
331
+ }
332
+ [hidden]:where(:not([hidden=until-found])) {
333
+ display: none;
334
+ }
335
+ :root {
336
+ --radius: 0.5rem;
337
+ }
338
+ body {
339
+ --tw-bg-opacity: 1;
340
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
341
+ --tw-text-opacity: 1;
342
+ color: rgb(17 24 39 / var(--tw-text-opacity, 1));
343
+ }
344
+ input[type=range] {
345
+ -webkit-appearance: none;
346
+ -moz-appearance: none;
347
+ appearance: none;
348
+ width: 100%;
349
+ cursor: pointer;
350
+ touch-action: manipulation;
351
+ }
352
+ input[type=range]::-webkit-slider-runnable-track {
353
+ height: 6px;
354
+ background-color: rgba(255, 255, 255, 0.3);
355
+ border-radius: 9999px;
356
+ }
357
+ input[type=range]::-webkit-slider-thumb {
358
+ -webkit-appearance: none;
359
+ appearance: none;
360
+ width: 18px;
361
+ height: 18px;
362
+ background: white;
363
+ border-radius: 50%;
364
+ margin-top: -6px;
365
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
366
+ -webkit-transition: transform 0.1s ease;
367
+ transition: transform 0.1s ease;
368
+ }
369
+ input[type=range]::-moz-range-track {
370
+ height: 6px;
371
+ background-color: rgba(255, 255, 255, 0.3);
372
+ border-radius: 9999px;
373
+ }
374
+ input[type=range]::-moz-range-thumb {
375
+ width: 18px;
376
+ height: 18px;
377
+ background: white;
378
+ border-radius: 50%;
379
+ border: none;
380
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
381
+ -moz-transition: transform 0.1s ease;
382
+ transition: transform 0.1s ease;
383
+ }
384
+ input[type=range]:active::-webkit-slider-thumb {
385
+ transform: scale(1.2);
386
+ }
387
+ input[type=range]:active::-moz-range-thumb {
388
+ transform: scale(1.2);
389
+ }