@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.
- package/README.md +399 -0
- package/dist/components/app-switcher/AppSwitcher.d.ts +4 -0
- package/dist/components/app-switcher/AppSwitcher.d.ts.map +1 -0
- package/dist/components/app-switcher/AppSwitcher.test.d.ts +2 -0
- package/dist/components/app-switcher/AppSwitcher.test.d.ts.map +1 -0
- package/dist/components/app-switcher/AppSwitcherItem.d.ts +8 -0
- package/dist/components/app-switcher/AppSwitcherItem.d.ts.map +1 -0
- package/dist/components/app-switcher/GridIcon.d.ts +2 -0
- package/dist/components/app-switcher/GridIcon.d.ts.map +1 -0
- package/dist/components/app-switcher/SystemAppIcon.d.ts +6 -0
- package/dist/components/app-switcher/SystemAppIcon.d.ts.map +1 -0
- package/dist/components/app-switcher/api/fetchMeApps.d.ts +6 -0
- package/dist/components/app-switcher/api/fetchMeApps.d.ts.map +1 -0
- package/dist/components/app-switcher/api/fetchMeApps.test.d.ts +2 -0
- package/dist/components/app-switcher/api/fetchMeApps.test.d.ts.map +1 -0
- package/dist/components/app-switcher/api/mapMeAppToAppItem.d.ts +4 -0
- package/dist/components/app-switcher/api/mapMeAppToAppItem.d.ts.map +1 -0
- package/dist/components/app-switcher/api/mapMeAppToAppItem.test.d.ts +2 -0
- package/dist/components/app-switcher/api/mapMeAppToAppItem.test.d.ts.map +1 -0
- package/dist/components/app-switcher/api/meAppsClient.d.ts +3 -0
- package/dist/components/app-switcher/api/meAppsClient.d.ts.map +1 -0
- package/dist/components/app-switcher/api/meAppsClient.test.d.ts +2 -0
- package/dist/components/app-switcher/api/meAppsClient.test.d.ts.map +1 -0
- package/dist/components/app-switcher/hooks/useAppSwitcher.d.ts +3 -0
- package/dist/components/app-switcher/hooks/useAppSwitcher.d.ts.map +1 -0
- package/dist/components/app-switcher/hooks/useMeApps.d.ts +3 -0
- package/dist/components/app-switcher/hooks/useMeApps.d.ts.map +1 -0
- package/dist/components/app-switcher/hooks/useMeApps.test.d.ts +2 -0
- package/dist/components/app-switcher/hooks/useMeApps.test.d.ts.map +1 -0
- package/dist/components/app-switcher/index.d.ts +11 -0
- package/dist/components/app-switcher/index.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/BulkImportModal.d.ts +4 -0
- package/dist/components/bulk-import-modal/BulkImportModal.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/BulkImportModal.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/BulkImportModal.test.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.d.ts +3 -0
- package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/hooks/useBulkImportFlow.test.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/index.d.ts +12 -0
- package/dist/components/bulk-import-modal/index.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/steps/MatchColumnsStep.d.ts +13 -0
- package/dist/components/bulk-import-modal/steps/MatchColumnsStep.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/steps/SelectHeaderRowStep.d.ts +8 -0
- package/dist/components/bulk-import-modal/steps/SelectHeaderRowStep.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/steps/UploadStep.d.ts +11 -0
- package/dist/components/bulk-import-modal/steps/UploadStep.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/steps/ValidateDataStep.d.ts +16 -0
- package/dist/components/bulk-import-modal/steps/ValidateDataStep.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/mapRowsToRecords.d.ts +9 -0
- package/dist/components/bulk-import-modal/utils/mapRowsToRecords.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/mapRowsToRecords.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/utils/mapRowsToRecords.test.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.d.ts +7 -0
- package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/utils/parseSpreadsheetFile.test.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/validateFieldValue.d.ts +5 -0
- package/dist/components/bulk-import-modal/utils/validateFieldValue.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/validateFieldValue.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/utils/validateFieldValue.test.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/validateMappedRows.d.ts +7 -0
- package/dist/components/bulk-import-modal/utils/validateMappedRows.d.ts.map +1 -0
- package/dist/components/bulk-import-modal/utils/validateMappedRows.test.d.ts +2 -0
- package/dist/components/bulk-import-modal/utils/validateMappedRows.test.d.ts.map +1 -0
- package/dist/index.cjs +38 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22616 -0
- package/dist/test/fixtures.d.ts +4 -0
- package/dist/test/fixtures.d.ts.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/types/app-switcher.d.ts +102 -0
- package/dist/types/app-switcher.d.ts.map +1 -0
- package/dist/types/bulk-import-modal.d.ts +92 -0
- package/dist/types/bulk-import-modal.d.ts.map +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"GridIcon.d.ts","sourceRoot":"","sources":["../../../src/components/app-switcher/GridIcon.tsx"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,gCAoBvB"}
|
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"fetchMeApps.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/fetchMeApps.test.ts"],"names":[],"mappings":""}
|
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"mapMeAppToAppItem.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/mapMeAppToAppItem.test.ts"],"names":[],"mappings":""}
|
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"meAppsClient.test.d.ts","sourceRoot":"","sources":["../../../../src/components/app-switcher/api/meAppsClient.test.ts"],"names":[],"mappings":""}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"BulkImportModal.test.d.ts","sourceRoot":"","sources":["../../../src/components/bulk-import-modal/BulkImportModal.test.tsx"],"names":[],"mappings":""}
|
|
@@ -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 @@
|
|
|
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"}
|