@rfdtech/components 0.3.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.
Files changed (79) hide show
  1. package/README.md +399 -0
  2. package/dist/components/app-switcher/AppSwitcher.d.ts +4 -0
  3. package/dist/components/app-switcher/AppSwitcher.d.ts.map +1 -0
  4. package/dist/components/app-switcher/AppSwitcher.test.d.ts +2 -0
  5. package/dist/components/app-switcher/AppSwitcher.test.d.ts.map +1 -0
  6. package/dist/components/app-switcher/AppSwitcherItem.d.ts +8 -0
  7. package/dist/components/app-switcher/AppSwitcherItem.d.ts.map +1 -0
  8. package/dist/components/app-switcher/GridIcon.d.ts +2 -0
  9. package/dist/components/app-switcher/GridIcon.d.ts.map +1 -0
  10. package/dist/components/app-switcher/SystemAppIcon.d.ts +6 -0
  11. package/dist/components/app-switcher/SystemAppIcon.d.ts.map +1 -0
  12. package/dist/components/app-switcher/api/fetchMeApps.d.ts +6 -0
  13. package/dist/components/app-switcher/api/fetchMeApps.d.ts.map +1 -0
  14. package/dist/components/app-switcher/api/fetchMeApps.test.d.ts +2 -0
  15. package/dist/components/app-switcher/api/fetchMeApps.test.d.ts.map +1 -0
  16. package/dist/components/app-switcher/api/mapMeAppToAppItem.d.ts +4 -0
  17. package/dist/components/app-switcher/api/mapMeAppToAppItem.d.ts.map +1 -0
  18. package/dist/components/app-switcher/api/mapMeAppToAppItem.test.d.ts +2 -0
  19. package/dist/components/app-switcher/api/mapMeAppToAppItem.test.d.ts.map +1 -0
  20. package/dist/components/app-switcher/api/meAppsClient.d.ts +3 -0
  21. package/dist/components/app-switcher/api/meAppsClient.d.ts.map +1 -0
  22. package/dist/components/app-switcher/api/meAppsClient.test.d.ts +2 -0
  23. package/dist/components/app-switcher/api/meAppsClient.test.d.ts.map +1 -0
  24. package/dist/components/app-switcher/hooks/useAppSwitcher.d.ts +3 -0
  25. package/dist/components/app-switcher/hooks/useAppSwitcher.d.ts.map +1 -0
  26. package/dist/components/app-switcher/hooks/useMeApps.d.ts +3 -0
  27. package/dist/components/app-switcher/hooks/useMeApps.d.ts.map +1 -0
  28. package/dist/components/app-switcher/hooks/useMeApps.test.d.ts +2 -0
  29. package/dist/components/app-switcher/hooks/useMeApps.test.d.ts.map +1 -0
  30. package/dist/components/app-switcher/index.d.ts +11 -0
  31. package/dist/components/app-switcher/index.d.ts.map +1 -0
  32. package/dist/components/bulk-import-modal/BulkImportModal.d.ts +4 -0
  33. package/dist/components/bulk-import-modal/BulkImportModal.d.ts.map +1 -0
  34. package/dist/components/bulk-import-modal/BulkImportModal.test.d.ts +2 -0
  35. package/dist/components/bulk-import-modal/BulkImportModal.test.d.ts.map +1 -0
  36. package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.d.ts +3 -0
  37. package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.d.ts.map +1 -0
  38. package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.test.d.ts +2 -0
  39. package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.test.d.ts.map +1 -0
  40. package/dist/components/bulk-import-modal/index.d.ts +12 -0
  41. package/dist/components/bulk-import-modal/index.d.ts.map +1 -0
  42. package/dist/components/bulk-import-modal/steps/MatchColumnsStep.d.ts +13 -0
  43. package/dist/components/bulk-import-modal/steps/MatchColumnsStep.d.ts.map +1 -0
  44. package/dist/components/bulk-import-modal/steps/SelectHeaderRowStep.d.ts +8 -0
  45. package/dist/components/bulk-import-modal/steps/SelectHeaderRowStep.d.ts.map +1 -0
  46. package/dist/components/bulk-import-modal/steps/UploadStep.d.ts +11 -0
  47. package/dist/components/bulk-import-modal/steps/UploadStep.d.ts.map +1 -0
  48. package/dist/components/bulk-import-modal/steps/ValidateDataStep.d.ts +16 -0
  49. package/dist/components/bulk-import-modal/steps/ValidateDataStep.d.ts.map +1 -0
  50. package/dist/components/bulk-import-modal/utils/mapRowsToRecords.d.ts +9 -0
  51. package/dist/components/bulk-import-modal/utils/mapRowsToRecords.d.ts.map +1 -0
  52. package/dist/components/bulk-import-modal/utils/mapRowsToRecords.test.d.ts +2 -0
  53. package/dist/components/bulk-import-modal/utils/mapRowsToRecords.test.d.ts.map +1 -0
  54. package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.d.ts +7 -0
  55. package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.d.ts.map +1 -0
  56. package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.test.d.ts +2 -0
  57. package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.test.d.ts.map +1 -0
  58. package/dist/components/bulk-import-modal/utils/validateFieldValue.d.ts +5 -0
  59. package/dist/components/bulk-import-modal/utils/validateFieldValue.d.ts.map +1 -0
  60. package/dist/components/bulk-import-modal/utils/validateFieldValue.test.d.ts +2 -0
  61. package/dist/components/bulk-import-modal/utils/validateFieldValue.test.d.ts.map +1 -0
  62. package/dist/components/bulk-import-modal/utils/validateMappedRows.d.ts +7 -0
  63. package/dist/components/bulk-import-modal/utils/validateMappedRows.d.ts.map +1 -0
  64. package/dist/components/bulk-import-modal/utils/validateMappedRows.test.d.ts +2 -0
  65. package/dist/components/bulk-import-modal/utils/validateMappedRows.test.d.ts.map +1 -0
  66. package/dist/index.cjs +38 -0
  67. package/dist/index.css +1 -0
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +22616 -0
  71. package/dist/test/fixtures.d.ts +4 -0
  72. package/dist/test/fixtures.d.ts.map +1 -0
  73. package/dist/test/setup.d.ts +2 -0
  74. package/dist/test/setup.d.ts.map +1 -0
  75. package/dist/types/app-switcher.d.ts +102 -0
  76. package/dist/types/app-switcher.d.ts.map +1 -0
  77. package/dist/types/bulk-import-modal.d.ts +92 -0
  78. package/dist/types/bulk-import-modal.d.ts.map +1 -0
  79. package/package.json +66 -0
package/README.md ADDED
@@ -0,0 +1,399 @@
1
+ # GSL Components
2
+
3
+ Shared React component library for Ghana School of Law (GSL) projects.
4
+
5
+ Requires React 18+ and a bundler. Styles are included automatically when you import from `@rfdtech/components` — no separate CSS import is needed.
6
+
7
+ ## Shared theming
8
+
9
+ All components share design tokens defined in [`src/styles/theme.css`](src/styles/theme.css). Tokens are applied on `:root` when a component is imported.
10
+
11
+ | Token | Default | Use |
12
+ |-------|---------|-----|
13
+ | `--gsl-primary` | `#dc2626` | Buttons, focus rings, accents |
14
+ | `--gsl-primary-light` | `#fef2f2` | Selected rows, hover fills |
15
+ | `--gsl-bg` | `#ffffff` | Surfaces |
16
+ | `--gsl-text` | `#3c4043` | Body text |
17
+ | `--gsl-text-secondary` | `#5f6368` | Labels, muted UI |
18
+ | `--gsl-border` | `#dadce0` | Borders |
19
+ | `--gsl-hover` | `#f1f3f4` | Row/cell hover |
20
+ | `--gsl-error` / `--gsl-error-bg` | `#dc2626` / `#fef2f2` | Errors |
21
+ | `--gsl-success` | `#16a34a` | Success states |
22
+ | `--gsl-warning` | `#eab308` | Warnings |
23
+
24
+ Override on a component root or any ancestor:
25
+
26
+ ```css
27
+ .my-app {
28
+ --gsl-primary: #1d4ed8;
29
+ --gsl-primary-light: #eff6ff;
30
+ }
31
+ ```
32
+
33
+ `BulkImportModal` also accepts legacy aliases (`--gsl-bulk-import-primary`, etc.) that map to the shared tokens.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ npm install @rfdtech/components react react-dom
39
+ ```
40
+
41
+ ## AppSwitcher
42
+
43
+ Google Apps–style 9-dot launcher for switching between GSL systems. Drop it into your header to let users jump between products.
44
+
45
+ ### Usage
46
+
47
+ **Remote fetch** — loads systems from `GET {baseUrl}/v1/me/apps` with a bearer token:
48
+
49
+ ```tsx
50
+ import { AppSwitcher } from "@rfdtech/components";
51
+
52
+ function Header({ baseUrl, accessToken }: { baseUrl: string; accessToken: string }) {
53
+ return (
54
+ <AppSwitcher
55
+ baseUrl={baseUrl}
56
+ accessToken={accessToken}
57
+ title="System directory"
58
+ onAppSelect={(app) => console.log(app.name, app.metadata)}
59
+ />
60
+ );
61
+ }
62
+ ```
63
+
64
+ Expected API response:
65
+
66
+ ```json
67
+ {
68
+ "success": true,
69
+ "message": "Available systems retrieved.",
70
+ "data": {
71
+ "apps": [
72
+ {
73
+ "system_id": "gov-portal",
74
+ "system_name": "Governance Portal",
75
+ "system_code": "GOV-123456",
76
+ "frontend_url": "http://178.105.154.224:3001",
77
+ "role": "registrar",
78
+ "permissions": ["cases:review"]
79
+ }
80
+ ]
81
+ },
82
+ "meta": { "count": 1 }
83
+ }
84
+ ```
85
+
86
+ **Static apps** — pass a list directly instead of fetching:
87
+
88
+ ```tsx
89
+ const apps = [
90
+ {
91
+ id: "mail",
92
+ name: "Mail",
93
+ icon: "https://example.com/mail.png",
94
+ href: "https://mail.example.com",
95
+ },
96
+ ];
97
+
98
+ <AppSwitcher apps={apps} title="System directory" />
99
+ ```
100
+
101
+ ### Props
102
+
103
+ | Prop | Type | Default | Description |
104
+ |------|------|---------|-------------|
105
+ | `apps` | `AppItem[]` | — | Static apps to show in the grid |
106
+ | `baseUrl` | `string` | required* | API base URL, e.g. `https://api.example.com` |
107
+ | `accessToken` | `string` | required* | Bearer access token |
108
+ | `columns` | `number` | `3` | Number of grid columns |
109
+ | `open` | `boolean` | — | Controlled open state |
110
+ | `onOpenChange` | `(open: boolean) => void` | — | Open state callback |
111
+ | `onAppSelect` | `(app: AppItem) => void` | — | Called when an app is selected |
112
+ | `triggerLabel` | `string` | `"Open app switcher"` | Accessible label for trigger |
113
+ | `trigger` | `ReactNode` | 9-dot icon | Custom trigger element |
114
+ | `title` | `string` | — | Panel header title |
115
+ | `footer` | `ReactNode` | — | Footer content below the grid |
116
+ | `placement` | `"bottom-end" \| "bottom-start" \| "bottom"` | `"bottom-end"` | Panel position |
117
+ | `closeOnSelect` | `boolean` | `true` | Close panel after selection |
118
+ | `className` | `string` | — | Root CSS class |
119
+ | `style` | `CSSProperties` | — | Root inline styles |
120
+
121
+ \* Required when `apps` is not provided.
122
+
123
+ ### Types
124
+
125
+ All types are exported from `@rfdtech/components`.
126
+
127
+ ```ts
128
+ interface AppItem {
129
+ id: string;
130
+ name: string;
131
+ icon: ReactNode | string;
132
+ href?: string;
133
+ onClick?: (app: AppItem) => void;
134
+ disabled?: boolean;
135
+ badge?: string;
136
+ metadata?: MeApp;
137
+ }
138
+
139
+ interface MeApp {
140
+ system_id: string;
141
+ system_name: string;
142
+ system_code: string;
143
+ frontend_url: string;
144
+ role: string;
145
+ permissions: string[];
146
+ }
147
+
148
+ interface MeAppsResponse {
149
+ success: boolean;
150
+ message: string;
151
+ data: { apps: MeApp[] };
152
+ meta: { count: number };
153
+ }
154
+ ```
155
+
156
+ Also exported: `AppSwitcherProps`, `UseMeAppsOptions`, `UseMeAppsReturn`, `UseAppSwitcherOptions`, `UseAppSwitcherReturn`.
157
+
158
+ ### Hooks
159
+
160
+ **`useMeApps`** — fetch and map systems from `/v1/me/apps`:
161
+
162
+ ```tsx
163
+ import { useMeApps } from "@rfdtech/components";
164
+
165
+ const { apps, loading, error, refetch } = useMeApps({
166
+ baseUrl: "https://api.example.com",
167
+ accessToken: "<token>",
168
+ });
169
+ ```
170
+
171
+ **`useAppSwitcher`** — headless open/close state for custom UI:
172
+
173
+ ```tsx
174
+ import { useAppSwitcher } from "@rfdtech/components";
175
+
176
+ const { open, toggle, close, triggerRef, panelRef } = useAppSwitcher();
177
+ ```
178
+
179
+ ### Utilities
180
+
181
+ ```tsx
182
+ import {
183
+ buildMeAppsUrl,
184
+ createMeAppsRequestInit,
185
+ fetchMeApps,
186
+ mapMeAppToAppItem,
187
+ mapMeAppsToAppItems,
188
+ MeAppsFetchError,
189
+ } from "@rfdtech/components";
190
+
191
+ const url = buildMeAppsUrl("https://api.example.com");
192
+ const init = createMeAppsRequestInit("<token>");
193
+ const response = await fetchMeApps(url, init);
194
+ const apps = mapMeAppsToAppItems(response.data.apps);
195
+ ```
196
+
197
+ | Export | Description |
198
+ |--------|-------------|
199
+ | `buildMeAppsUrl(baseUrl)` | Builds `{baseUrl}/v1/me/apps`, or `/v1/me/apps` when `baseUrl` is empty |
200
+ | `createMeAppsRequestInit(accessToken)` | Returns fetch options with `Authorization: Bearer ...` |
201
+ | `fetchMeApps(url, init?)` | Fetches and validates the API response; throws `MeAppsFetchError` on failure |
202
+ | `mapMeAppToAppItem(app)` | Maps one `MeApp` to an `AppItem` |
203
+ | `mapMeAppsToAppItems(apps)` | Maps an array of `MeApp` values to `AppItem[]` |
204
+ | `MeAppsFetchError` | Error thrown when the HTTP request fails or `success` is `false` |
205
+
206
+ ### Subcomponents
207
+
208
+ Also exported for custom layouts:
209
+
210
+ - `AppSwitcherItem` — single app grid cell
211
+ - `GridIcon` — default 9-dot trigger icon
212
+ - `SystemAppIcon` — initials avatar for API-fetched apps
213
+
214
+ ### Theming
215
+
216
+ Override shared tokens on `.gsl-app-switcher` (see [Shared theming](#shared-theming)). `--gsl-focus` aliases to `--gsl-primary`.
217
+
218
+ ```css
219
+ .my-switcher {
220
+ --gsl-primary: #dc2626;
221
+ --gsl-hover: #f1f3f4;
222
+ --gsl-columns: 4;
223
+ }
224
+ ```
225
+
226
+ ### CORS
227
+
228
+ When fetching from a remote `baseUrl` in the browser, the API must allow the host application's origin. Configure CORS on your backend or proxy `/v1` through your dev server during local development.
229
+
230
+ ## BulkImportModal
231
+
232
+ Four-step modal wizard for importing spreadsheet data (.xlsx, .xls, .csv). Parsing and validation run entirely in the browser.
233
+
234
+ ### Usage
235
+
236
+ ```tsx
237
+ import { BulkImportModal } from "@rfdtech/components";
238
+
239
+ const fields = [
240
+ { key: "email", label: "Email", required: true },
241
+ { key: "full_name", label: "Full name", required: true },
242
+ { key: "student_id", label: "Student ID" },
243
+ ];
244
+
245
+ <BulkImportModal
246
+ open={open}
247
+ onOpenChange={setOpen}
248
+ title="Import students"
249
+ fields={fields}
250
+ onComplete={(result) => {
251
+ console.log(result.rows, result.errors);
252
+ }}
253
+ />
254
+ ```
255
+
256
+ ### Steps
257
+
258
+ 1. **Upload Document** — preview expected columns, then upload `.xlsx`, `.xls`, or `.csv`
259
+ 2. **Select header row** — choose the header row with radio buttons
260
+ 3. **Match Columns** — map each uploaded column to a target field (`Your table` → `Will become`)
261
+ 4. **Validate data** — review rows in a table, discard invalid rows, then **Confirm**
262
+
263
+ The first worksheet is used for multi-sheet workbooks. Discarded rows are excluded from `onComplete`.
264
+
265
+ ### Props
266
+
267
+ | Prop | Type | Default | Description |
268
+ |------|------|---------|-------------|
269
+ | `open` | `boolean` | required | Controlled open state |
270
+ | `onOpenChange` | `(open: boolean) => void` | required | Open state callback |
271
+ | `fields` | `BulkImportField[]` | required | Target field schema for column matching |
272
+ | `onComplete` | `(result: BulkImportResult) => void` | required | Called with mapped rows on import |
273
+ | `title` | `string` | `"Bulk import"` | Modal title |
274
+ | `maxFileSizeBytes` | `number` | `5242880` | Maximum upload size (5 MB) |
275
+ | `allowImportWithWarnings` | `boolean` | `false` | Allow import when only warnings exist |
276
+ | `className` | `string` | — | Root CSS class |
277
+
278
+ ### Field schema
279
+
280
+ Each item in `fields` defines how a column is matched and validated:
281
+
282
+ ```ts
283
+ type BulkImportFieldType =
284
+ | "string"
285
+ | "email"
286
+ | "number"
287
+ | "integer"
288
+ | "date"
289
+ | "boolean"
290
+ | "url"
291
+ | "phone";
292
+
293
+ interface BulkImportField {
294
+ key: string;
295
+ label: string;
296
+ required?: boolean;
297
+ type?: BulkImportFieldType;
298
+ pattern?: string | RegExp;
299
+ patternMessage?: string;
300
+ minLength?: number;
301
+ maxLength?: number;
302
+ min?: number;
303
+ max?: number;
304
+ options?: string[];
305
+ optionsIgnoreCase?: boolean;
306
+ optionsMessage?: string;
307
+ description?: string;
308
+ example?: string;
309
+ trim?: boolean;
310
+ validate?: (value: string) => string | null;
311
+ }
312
+ ```
313
+
314
+ Example:
315
+
316
+ ```tsx
317
+ const fields = [
318
+ {
319
+ key: "email",
320
+ label: "Email",
321
+ required: true,
322
+ type: "email",
323
+ description: "Student email address",
324
+ example: "student@gsl.edu.gh",
325
+ },
326
+ {
327
+ key: "student_id",
328
+ label: "Student ID",
329
+ pattern: "^STU-\\d{4}$",
330
+ patternMessage: "Use format STU-1234",
331
+ example: "STU-0042",
332
+ },
333
+ {
334
+ key: "status",
335
+ label: "Status",
336
+ options: ["active", "inactive"],
337
+ },
338
+ ];
339
+ ```
340
+
341
+ Schema rules run before any custom `validate` function. Step 1 uses `example` when set; otherwise it derives preview values from `options`, `type`, `min`, and `patternMessage`. Step 3 maps each uploaded column to a target field and supports excluding columns with **×**.
342
+
343
+ ### Types
344
+
345
+ ```ts
346
+ interface BulkImportResult {
347
+ rows: Record<string, string>[];
348
+ errors: BulkImportValidationError[];
349
+ warnings: BulkImportValidationError[];
350
+ }
351
+ ```
352
+
353
+ Also exported: `useBulkImportFlow`, step components, and utilities (`parseSpreadsheetFile`, `mapRowsToRecords`, `validateMappedRows`, `validateFieldValue`, `getFieldExampleValue`, `getFieldHint`, `autoMatchSourceColumns`).
354
+
355
+ ### Theming
356
+
357
+ The modal uses a **near full-viewport** layout with a compulsory gutter on all sides (24px desktop, 16px mobile), enforced by overlay padding. Override shared tokens on `.gsl-bulk-import` via the `className` prop (see [Shared theming](#shared-theming)):
358
+
359
+ ```css
360
+ .my-import {
361
+ --gsl-primary: #dc2626;
362
+ --gsl-primary-light: #fef2f2;
363
+ --gsl-success: #16a34a;
364
+ --gsl-error-bg: #fef2f2;
365
+ }
366
+ ```
367
+
368
+ Legacy aliases (`--gsl-bulk-import-primary`, `--gsl-bulk-import-primary-light`, etc.) still work and map to the shared tokens.
369
+
370
+ To change the gutter size, override `--gsl-bulk-import-gutter` on `.gsl-bulk-import__overlay` in your app CSS (do not override modal width/height — the dialog always fills the padded overlay area):
371
+
372
+ ```css
373
+ .gsl-bulk-import__overlay {
374
+ --gsl-bulk-import-gutter: 32px;
375
+ }
376
+ ```
377
+
378
+ ## Development
379
+
380
+ ```bash
381
+ npm install
382
+ npm run demo # Start demo at http://localhost:5173
383
+ npm run test # Run unit and component tests
384
+ npm run test:watch # Run tests in watch mode
385
+ npm run build # Build library to dist/
386
+ npm run typecheck
387
+ ```
388
+
389
+ The demo reads credentials from environment variables:
390
+
391
+ ```bash
392
+ VITE_API_BASE_URL=https://api.example.com VITE_ACCESS_TOKEN=<token> npm run demo
393
+ ```
394
+
395
+ Leave `VITE_API_BASE_URL` unset to use the built-in mock API at `/v1/me/apps`.
396
+
397
+ ## License
398
+
399
+ MIT
@@ -0,0 +1,4 @@
1
+ import type { AppSwitcherProps } from "../../types/app-switcher";
2
+ import "./styles/app-switcher.css";
3
+ export declare function AppSwitcher({ apps: appsProp, baseUrl, accessToken, open: controlledOpen, onOpenChange, onAppSelect, columns, triggerLabel, trigger, title, footer, className, style, placement, closeOnSelect, }: AppSwitcherProps): import("react").JSX.Element;
4
+ //# sourceMappingURL=AppSwitcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSwitcher.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/AppSwitcher.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG1E,OAAO,2BAA2B,CAAC;AAEnC,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EAAE,QAAQ,EACd,OAAO,EACP,WAAW,EACX,IAAI,EAAE,cAAc,EACpB,YAAY,EACZ,WAAW,EACX,OAAW,EACX,YAAkC,EAClC,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,SAAwB,EACxB,aAAoB,GACrB,EAAE,gBAAgB,+BA6GlB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=AppSwitcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSwitcher.test.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/AppSwitcher.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { AppItem } from "../../types/app-switcher";
2
+ interface AppSwitcherItemProps {
3
+ app: AppItem;
4
+ onSelect: (app: AppItem) => void;
5
+ }
6
+ export declare function AppSwitcherItem({ app, onSelect }: AppSwitcherItemProps): import("react").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=AppSwitcherItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSwitcherItem.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/AppSwitcherItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD,UAAU,oBAAoB;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAClC;AAYD,wBAAgB,eAAe,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,oBAAoB,+BA8DtE"}
@@ -0,0 +1,2 @@
1
+ export declare function GridIcon(): import("react").JSX.Element;
2
+ //# sourceMappingURL=GridIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GridIcon.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/GridIcon.tsx"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,gCAoBvB"}
@@ -0,0 +1,6 @@
1
+ interface SystemAppIconProps {
2
+ name: string;
3
+ }
4
+ export declare function SystemAppIcon({ name }: SystemAppIconProps): import("react").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=SystemAppIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SystemAppIcon.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/SystemAppIcon.tsx"],"names":[],"mappings":"AAAA,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAgBD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE,kBAAkB,+BAMzD"}
@@ -0,0 +1,6 @@
1
+ import type { MeAppsResponse } from "../../../types/app-switcher";
2
+ export declare class MeAppsFetchError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare function fetchMeApps(url?: string, init?: RequestInit): Promise<MeAppsResponse>;
6
+ //# sourceMappingURL=fetchMeApps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchMeApps.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/fetchMeApps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAsB,WAAW,CAC/B,GAAG,SAAgB,EACnB,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,cAAc,CAAC,CAczB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fetchMeApps.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchMeApps.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/fetchMeApps.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { AppItem, MeApp } from "../../../types/app-switcher";
2
+ export declare function mapMeAppToAppItem(app: MeApp): AppItem;
3
+ export declare function mapMeAppsToAppItems(apps: MeApp[]): AppItem[];
4
+ //# sourceMappingURL=mapMeAppToAppItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapMeAppToAppItem.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/mapMeAppToAppItem.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAElE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAUrD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAE5D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mapMeAppToAppItem.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapMeAppToAppItem.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/mapMeAppToAppItem.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export declare function buildMeAppsUrl(baseUrl: string): string;
2
+ export declare function createMeAppsRequestInit(accessToken: string): RequestInit;
3
+ //# sourceMappingURL=meAppsClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meAppsClient.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/meAppsClient.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,UAG7C;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAMxE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=meAppsClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meAppsClient.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/meAppsClient.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { UseAppSwitcherOptions, UseAppSwitcherReturn } from "../../../types/app-switcher";
2
+ export declare function useAppSwitcher(options?: UseAppSwitcherOptions): UseAppSwitcherReturn;
3
+ //# sourceMappingURL=useAppSwitcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAppSwitcher.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/hooks/useAppSwitcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AAErC,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA8DtB"}
@@ -0,0 +1,3 @@
1
+ import type { UseMeAppsOptions, UseMeAppsReturn } from "../../../types/app-switcher";
2
+ export declare function useMeApps(options: UseMeAppsOptions): UseMeAppsReturn;
3
+ //# sourceMappingURL=useMeApps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMeApps.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/hooks/useMeApps.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAErF,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CA2DpE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useMeApps.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMeApps.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/hooks/useMeApps.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ export { AppSwitcher } from "./AppSwitcher";
2
+ export { AppSwitcherItem } from "./AppSwitcherItem";
3
+ export { GridIcon } from "./GridIcon";
4
+ export { SystemAppIcon } from "./SystemAppIcon";
5
+ export { fetchMeApps, MeAppsFetchError } from "./api/fetchMeApps";
6
+ export { buildMeAppsUrl, createMeAppsRequestInit, } from "./api/meAppsClient";
7
+ export { mapMeAppToAppItem, mapMeAppsToAppItems, } from "./api/mapMeAppToAppItem";
8
+ export { useAppSwitcher } from "./hooks/useAppSwitcher";
9
+ export { useMeApps } from "./hooks/useMeApps";
10
+ export type { AppItem, AppSwitcherProps, MeApp, MeAppsResponse, UseMeAppsOptions, UseMeAppsReturn, UseAppSwitcherOptions, UseAppSwitcherReturn, } from "../../types/app-switcher";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EACL,cAAc,EACd,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,YAAY,EACV,OAAO,EACP,gBAAgB,EAChB,KAAK,EACL,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { BulkImportModalProps } from "../../types/bulk-import-modal";
2
+ import "./styles/bulk-import-modal.css";
3
+ export declare function BulkImportModal({ open, onOpenChange, fields, onComplete, title, maxFileSizeBytes, allowImportWithWarnings, className, }: BulkImportModalProps): import("react").ReactPortal | null;
4
+ //# sourceMappingURL=BulkImportModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulkImportModal.d.ts","sourceRoot":"","sources":["../../../src/components/bulk-import-modal/BulkImportModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAO1E,OAAO,gCAAgC,CAAC;AAgCxC,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,UAAU,EACV,KAAqB,EACrB,gBAAwC,EACxC,uBAA+B,EAC/B,SAAS,GACV,EAAE,oBAAoB,sCAyOtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BulkImportModal.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulkImportModal.test.d.ts","sourceRoot":"","sources":["../../../src/components/bulk-import-modal/BulkImportModal.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { UseBulkImportFlowOptions, UseBulkImportFlowReturn } from "../../../types/bulk-import-modal";
2
+ export declare function useBulkImportFlow(options: UseBulkImportFlowOptions): UseBulkImportFlowReturn;
3
+ //# sourceMappingURL=useBulkImportFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBulkImportFlow.d.ts","sourceRoot":"","sources":["../../../../src/components/bulk-import-modal/hooks/useBulkImportFlow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,kCAAkC,CAAC;AAmB1C,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAuPzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useBulkImportFlow.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBulkImportFlow.test.d.ts","sourceRoot":"","sources":["../../../../src/components/bulk-import-modal/hooks/useBulkImportFlow.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export { BulkImportModal } from "./BulkImportModal";
2
+ export { UploadStep } from "./steps/UploadStep";
3
+ export { SelectHeaderRowStep } from "./steps/SelectHeaderRowStep";
4
+ export { MatchColumnsStep } from "./steps/MatchColumnsStep";
5
+ export { ValidateDataStep } from "./steps/ValidateDataStep";
6
+ export { useBulkImportFlow } from "./hooks/useBulkImportFlow";
7
+ export { BulkImportParseError, isAcceptedSpreadsheetFile, parseSpreadsheetFile, } from "./utils/parseSpreadsheetFile";
8
+ export { autoMatchSourceColumns, buildAllSourceColumns, buildSourceColumns, createEmptySourceMapping, getMappedFieldKeys, isRequiredMappingComplete, mapRowsToRecords, } from "./utils/mapRowsToRecords";
9
+ export { splitValidationIssues, validateMappedRows, } from "./utils/validateMappedRows";
10
+ export { getFieldExampleValue, getFieldHint, validateFieldValue, } from "./utils/validateFieldValue";
11
+ export type { BulkImportField, BulkImportFieldType, BulkImportModalProps, BulkImportResult, BulkImportStep, BulkImportValidationError, ColumnMapping, ParsedSpreadsheet, SourceColumn, SourceColumnMapping, UseBulkImportFlowOptions, UseBulkImportFlowReturn, } from "../../types/bulk-import-modal";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/bulk-import-modal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { BulkImportField, SourceColumn, SourceColumnMapping } from "../../../types/bulk-import-modal";
2
+ interface MatchColumnsStepProps {
3
+ fields: BulkImportField[];
4
+ allSourceColumns: SourceColumn[];
5
+ previewRows: string[][];
6
+ sourceColumnMapping: SourceColumnMapping;
7
+ excludedColumns: number[];
8
+ onSourceMappingChange: (sourceIndex: number, fieldKey: string | null) => void;
9
+ onToggleExcludedColumn: (sourceIndex: number) => void;
10
+ }
11
+ export declare function MatchColumnsStep({ fields, allSourceColumns, previewRows, sourceColumnMapping, excludedColumns, onSourceMappingChange, onToggleExcludedColumn, }: MatchColumnsStepProps): import("react").JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=MatchColumnsStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatchColumnsStep.d.ts","sourceRoot":"","sources":["../../../../src/components/bulk-import-modal/steps/MatchColumnsStep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,mBAAmB,EACpB,MAAM,kCAAkC,CAAC;AAE1C,UAAU,qBAAqB;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;IACxB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,qBAAqB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9E,sBAAsB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAgBD,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,GACvB,EAAE,qBAAqB,+BA8EvB"}
@@ -0,0 +1,8 @@
1
+ interface SelectHeaderRowStepProps {
2
+ rows: string[][];
3
+ headerRowIndex: number | null;
4
+ onSelectHeaderRow: (index: number) => void;
5
+ }
6
+ export declare function SelectHeaderRowStep({ rows, headerRowIndex, onSelectHeaderRow, }: SelectHeaderRowStepProps): import("react").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=SelectHeaderRowStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectHeaderRowStep.d.ts","sourceRoot":"","sources":["../../../../src/components/bulk-import-modal/steps/SelectHeaderRowStep.tsx"],"names":[],"mappings":"AAAA,UAAU,wBAAwB;IAChC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAID,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,cAAc,EACd,iBAAiB,GAClB,EAAE,wBAAwB,+BA8C1B"}
@@ -0,0 +1,11 @@
1
+ import type { BulkImportField } from "../../../types/bulk-import-modal";
2
+ interface UploadStepProps {
3
+ fields: BulkImportField[];
4
+ fileName: string | null;
5
+ parseError: string | null;
6
+ isParsing: boolean;
7
+ onFileSelected: (file: File) => void;
8
+ }
9
+ export declare function UploadStep({ fields, fileName, parseError, isParsing, onFileSelected, }: UploadStepProps): import("react").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=UploadStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UploadStep.d.ts","sourceRoot":"","sources":["../../../../src/components/bulk-import-modal/steps/UploadStep.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGxE,UAAU,eAAe;IACvB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACtC;AAED,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,cAAc,GACf,EAAE,eAAe,+BAiFjB"}