@expresscsv/react 0.1.17 → 0.1.18
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 +82 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
React hook for embedding the [ExpressCSV](https://expresscsv.com) CSV import widget. Wraps [`@expresscsv/sdk`](https://www.npmjs.com/package/@expresscsv/sdk) with automatic lifecycle management and reactive state.
|
|
7
7
|
|
|
8
|
+
If you want to define schemas in shared or backend code without any frontend dependencies, use [`@expresscsv/schemas`](https://www.npmjs.com/package/@expresscsv/schemas) for the schema definition itself, then pass that schema into `@expresscsv/react`.
|
|
9
|
+
|
|
8
10
|
## Installation
|
|
9
11
|
|
|
10
12
|
```bash
|
|
@@ -312,6 +314,8 @@ interface WebhookPayload {
|
|
|
312
314
|
}
|
|
313
315
|
```
|
|
314
316
|
|
|
317
|
+
When you already have a schema, prefer `InferWebhookPayload<typeof schema>` from `@expresscsv/schemas` instead of rewriting this object shape by hand.
|
|
318
|
+
|
|
315
319
|
Example payload:
|
|
316
320
|
|
|
317
321
|
```json
|
|
@@ -350,6 +354,25 @@ Your endpoint should return a **2xx** status code to acknowledge each chunk. Non
|
|
|
350
354
|
|
|
351
355
|
Chunks are delivered **serially** — the next chunk is only sent after the previous one succeeds.
|
|
352
356
|
|
|
357
|
+
If your schema lives in shared or backend code via `@expresscsv/schemas`, you can reuse the built-in webhook payload helper in your webhook handler:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
import express from "express";
|
|
361
|
+
import type { InferWebhookPayload } from "@expresscsv/schemas";
|
|
362
|
+
import { candidateSchema } from "../shared/candidate-schema";
|
|
363
|
+
|
|
364
|
+
const app = express();
|
|
365
|
+
app.use(express.json());
|
|
366
|
+
|
|
367
|
+
app.post("/webhooks/csv-import", async (req, res) => {
|
|
368
|
+
const payload = req.body as InferWebhookPayload<typeof candidateSchema>;
|
|
369
|
+
|
|
370
|
+
await importCandidates(payload.records);
|
|
371
|
+
|
|
372
|
+
res.status(200).json({ ok: true });
|
|
373
|
+
});
|
|
374
|
+
```
|
|
375
|
+
|
|
353
376
|
Below is a minimal Express.js example:
|
|
354
377
|
|
|
355
378
|
```typescript
|
|
@@ -566,6 +589,8 @@ interface WebhookConfig {
|
|
|
566
589
|
|
|
567
590
|
The `x` schema builder provides a type-safe, fluent API for defining your CSV structure.
|
|
568
591
|
|
|
592
|
+
For apps that share schemas with backend code or webhook receivers, prefer defining the schema in `@expresscsv/schemas` and importing it into your React app. That keeps schema authoring free of React and widget dependencies, while also giving your backend access to `InferWebhookPayload<typeof schema>`.
|
|
593
|
+
|
|
569
594
|
#### Field Types
|
|
570
595
|
|
|
571
596
|
```tsx
|
|
@@ -604,6 +629,63 @@ const schema = x.row({
|
|
|
604
629
|
});
|
|
605
630
|
```
|
|
606
631
|
|
|
632
|
+
#### Runtime-Built Schemas
|
|
633
|
+
|
|
634
|
+
For a fixed schema, keep it directly in `x.row(...)`:
|
|
635
|
+
|
|
636
|
+
```tsx
|
|
637
|
+
const schema = x.row({
|
|
638
|
+
email: x.string().email().label("Email"),
|
|
639
|
+
lifecycleStage: x
|
|
640
|
+
.select([
|
|
641
|
+
{ label: "Lead", value: "lead" },
|
|
642
|
+
{ label: "Customer", value: "customer" },
|
|
643
|
+
{ label: "Churned", value: "churned" },
|
|
644
|
+
])
|
|
645
|
+
.label("Lifecycle Stage"),
|
|
646
|
+
accountOwner: x.string().label("Account Owner").optional(),
|
|
647
|
+
contractValue: x.number().currency("USD").label("Contract Value").optional(),
|
|
648
|
+
});
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
`x.dynamicRow(...)` lets you build the row at runtime, which is useful when the schema depends on account data, user preferences, or enabled custom fields.
|
|
652
|
+
|
|
653
|
+
```tsx
|
|
654
|
+
import { x } from "@expresscsv/react";
|
|
655
|
+
|
|
656
|
+
function buildCustomerSchema(options: {
|
|
657
|
+
collectCrmId: boolean;
|
|
658
|
+
collectHealthScore: boolean;
|
|
659
|
+
collectSegment: boolean;
|
|
660
|
+
}) {
|
|
661
|
+
return x.dynamicRow({
|
|
662
|
+
email: x.string().email().label("Email"),
|
|
663
|
+
companyName: x.string().label("Company Name"),
|
|
664
|
+
...(options.collectCrmId ? { crmId: x.string().label("CRM ID") } : {}),
|
|
665
|
+
...(options.collectHealthScore
|
|
666
|
+
? { healthScore: x.number().label("Health Score") }
|
|
667
|
+
: {}),
|
|
668
|
+
...(options.collectSegment
|
|
669
|
+
? {
|
|
670
|
+
segment: x
|
|
671
|
+
.select([
|
|
672
|
+
{ label: "SMB", value: "smb" },
|
|
673
|
+
{ label: "Mid-Market", value: "mid-market" },
|
|
674
|
+
{ label: "Enterprise", value: "enterprise" },
|
|
675
|
+
])
|
|
676
|
+
.label("Segment"),
|
|
677
|
+
}
|
|
678
|
+
: {}),
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const schema = buildCustomerSchema({
|
|
683
|
+
collectCrmId: true,
|
|
684
|
+
collectHealthScore: true,
|
|
685
|
+
collectSegment: false,
|
|
686
|
+
});
|
|
687
|
+
```
|
|
688
|
+
|
|
607
689
|
#### Common Modifiers
|
|
608
690
|
|
|
609
691
|
All field types support:
|
package/dist/index.d.cts
CHANGED
|
@@ -3018,6 +3018,13 @@ declare class ExRow<T extends ExRowShape> extends ExType<{
|
|
|
3018
3018
|
* @returns A new ExRow instance
|
|
3019
3019
|
*/
|
|
3020
3020
|
static create<T extends ExRowShape>(shape: T): ExRow<T>;
|
|
3021
|
+
/**
|
|
3022
|
+
* Factory method for runtime-built row shapes.
|
|
3023
|
+
*
|
|
3024
|
+
* This intentionally widens the returned type to ExRow<ExRowShape> so callers
|
|
3025
|
+
* can assemble fields conditionally without relying on exact key inference.
|
|
3026
|
+
*/
|
|
3027
|
+
static createDynamic(shape: ExRowShape): ExRow<ExRowShape>;
|
|
3021
3028
|
/**
|
|
3022
3029
|
* Specifies columns that can be null/optional with conditional logic
|
|
3023
3030
|
*
|
|
@@ -3824,6 +3831,7 @@ export declare const x: {
|
|
|
3824
3831
|
time: typeof ExTime.create;
|
|
3825
3832
|
datetime: typeof ExDatetime.create;
|
|
3826
3833
|
row: typeof ExRow.create;
|
|
3834
|
+
dynamicRow: typeof ExRow.createDynamic;
|
|
3827
3835
|
select: typeof ExSelect.create;
|
|
3828
3836
|
multiselect: typeof ExMultiselect.create;
|
|
3829
3837
|
infer: <T extends ExType<unknown, ExBaseDef, unknown>>(_schema: T) => Infer<T>;
|
package/dist/index.d.mts
CHANGED
|
@@ -3018,6 +3018,13 @@ declare class ExRow<T extends ExRowShape> extends ExType<{
|
|
|
3018
3018
|
* @returns A new ExRow instance
|
|
3019
3019
|
*/
|
|
3020
3020
|
static create<T extends ExRowShape>(shape: T): ExRow<T>;
|
|
3021
|
+
/**
|
|
3022
|
+
* Factory method for runtime-built row shapes.
|
|
3023
|
+
*
|
|
3024
|
+
* This intentionally widens the returned type to ExRow<ExRowShape> so callers
|
|
3025
|
+
* can assemble fields conditionally without relying on exact key inference.
|
|
3026
|
+
*/
|
|
3027
|
+
static createDynamic(shape: ExRowShape): ExRow<ExRowShape>;
|
|
3021
3028
|
/**
|
|
3022
3029
|
* Specifies columns that can be null/optional with conditional logic
|
|
3023
3030
|
*
|
|
@@ -3824,6 +3831,7 @@ export declare const x: {
|
|
|
3824
3831
|
time: typeof ExTime.create;
|
|
3825
3832
|
datetime: typeof ExDatetime.create;
|
|
3826
3833
|
row: typeof ExRow.create;
|
|
3834
|
+
dynamicRow: typeof ExRow.createDynamic;
|
|
3827
3835
|
select: typeof ExSelect.create;
|
|
3828
3836
|
multiselect: typeof ExMultiselect.create;
|
|
3829
3837
|
infer: <T extends ExType<unknown, ExBaseDef, unknown>>(_schema: T) => Infer<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -3018,6 +3018,13 @@ declare class ExRow<T extends ExRowShape> extends ExType<{
|
|
|
3018
3018
|
* @returns A new ExRow instance
|
|
3019
3019
|
*/
|
|
3020
3020
|
static create<T extends ExRowShape>(shape: T): ExRow<T>;
|
|
3021
|
+
/**
|
|
3022
|
+
* Factory method for runtime-built row shapes.
|
|
3023
|
+
*
|
|
3024
|
+
* This intentionally widens the returned type to ExRow<ExRowShape> so callers
|
|
3025
|
+
* can assemble fields conditionally without relying on exact key inference.
|
|
3026
|
+
*/
|
|
3027
|
+
static createDynamic(shape: ExRowShape): ExRow<ExRowShape>;
|
|
3021
3028
|
/**
|
|
3022
3029
|
* Specifies columns that can be null/optional with conditional logic
|
|
3023
3030
|
*
|
|
@@ -3824,6 +3831,7 @@ export declare const x: {
|
|
|
3824
3831
|
time: typeof ExTime.create;
|
|
3825
3832
|
datetime: typeof ExDatetime.create;
|
|
3826
3833
|
row: typeof ExRow.create;
|
|
3834
|
+
dynamicRow: typeof ExRow.createDynamic;
|
|
3827
3835
|
select: typeof ExSelect.create;
|
|
3828
3836
|
multiselect: typeof ExMultiselect.create;
|
|
3829
3837
|
infer: <T extends ExType<unknown, ExBaseDef, unknown>>(_schema: T) => Infer<T>;
|