unifyedx-storybook-syncfusion 0.4.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/claude-skill/SKILL.md +219 -0
- package/dist/components/CustomDataGrid/CustomDataGrid.d.ts +2 -0
- package/dist/components/CustomDatePicker/CustomDatePicker.d.ts +107 -0
- package/dist/components/CustomGridToolbar/CustomGridToolbar.d.ts +35 -0
- package/dist/index.d.ts +4 -0
- package/dist/syncfusion.css +49 -0
- package/dist/unifyedx-storybook-syncfusion.css +1 -0
- package/dist/unifyedx-storybook-syncfusion.css.br +0 -0
- package/dist/unifyedx-storybook-syncfusion.css.gz +0 -0
- package/dist/unifyedx-storybook-syncfusion.es.js +2018 -0
- package/dist/unifyedx-storybook-syncfusion.es.js.br +0 -0
- package/dist/unifyedx-storybook-syncfusion.es.js.gz +0 -0
- package/dist/utils/registerSyncfusionLicense.d.ts +8 -0
- package/package.json +75 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: storybook-syncfusion-components
|
|
3
|
+
description: Use CustomDataGrid, CustomGridToolbar and CustomDatePicker from unifyedx-storybook-syncfusion instead of building data tables, grid toolbars or Syncfusion date/time pickers by hand. Covers install, licence registration, CSS, the server-controlled grid state contract and the grid API ref.
|
|
4
|
+
paths:
|
|
5
|
+
- "**/*.jsx"
|
|
6
|
+
- "**/*.tsx"
|
|
7
|
+
- "**/*.js"
|
|
8
|
+
- "**/*.ts"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# UnifyedX Syncfusion Components (`unifyedx-storybook-syncfusion`)
|
|
12
|
+
|
|
13
|
+
Package version: 0.4.x | Last updated: 2026-09-15
|
|
14
|
+
|
|
15
|
+
> **Install this skill** in a consuming app by copying
|
|
16
|
+
> `node_modules/unifyedx-storybook-syncfusion/claude-skill/SKILL.md` to
|
|
17
|
+
> `.claude/skills/storybook-syncfusion-components/SKILL.md`.
|
|
18
|
+
> Pair it with the `storybook-components` skill from `unifyedx-storybook-new`.
|
|
19
|
+
|
|
20
|
+
## 1. When to use this package — and when not to
|
|
21
|
+
|
|
22
|
+
This package holds the **only** Syncfusion-backed UnifyedX components. It was split
|
|
23
|
+
out of `unifyedx-storybook-new` in 0.4.0 so that apps without a data grid do not
|
|
24
|
+
download the Syncfusion runtime (~1.3 GB installed) or its ~1.9 MB stylesheet.
|
|
25
|
+
|
|
26
|
+
| Need | Use |
|
|
27
|
+
|---|---|
|
|
28
|
+
| A server-paged data table | `CustomDataGrid` (this package) |
|
|
29
|
+
| Title / search / filter / export bar above that table | `CustomGridToolbar` (this package) |
|
|
30
|
+
| Date **range**, **datetime** or **datetime range** picker | `CustomDatePicker` (this package) |
|
|
31
|
+
| A plain date or time field that returns a `Date` | `DateField` / `TimeField` from **`unifyedx-storybook-new`** — do NOT pull in Syncfusion for this |
|
|
32
|
+
| A numeric range slider | `RangeSlider` from **`unifyedx-storybook-new`** |
|
|
33
|
+
| Page numbers without a grid | `Pagination` from **`unifyedx-storybook-new`** |
|
|
34
|
+
|
|
35
|
+
**Rule:** only add this package if the app renders `CustomDataGrid`, `CustomGridToolbar`
|
|
36
|
+
or a range/datetime `CustomDatePicker`. Otherwise use the core package alone.
|
|
37
|
+
|
|
38
|
+
## 2. Install & setup
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm i unifyedx-storybook-syncfusion unifyedx-storybook-new \
|
|
42
|
+
@syncfusion/ej2-base@32.1.19 @syncfusion/ej2-react-base@32.1.19 \
|
|
43
|
+
@syncfusion/ej2-react-grids@32.1.19 @syncfusion/ej2-react-calendars@32.1.19 \
|
|
44
|
+
@syncfusion/ej2-react-inputs@32.1.19
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
All Syncfusion packages are **peer dependencies pinned to 32.1.19**. Declare them in
|
|
48
|
+
the app's own `package.json` — do not rely on hoisting. Mixing Syncfusion majors on
|
|
49
|
+
one page breaks `ej2-base`.
|
|
50
|
+
|
|
51
|
+
```jsx
|
|
52
|
+
// main.jsx — once, before rendering
|
|
53
|
+
import 'unifyedx-storybook-new/style.css';
|
|
54
|
+
import 'unifyedx-storybook-syncfusion/syncfusion.css'; // Syncfusion theme + component styles
|
|
55
|
+
import { registerSyncfusionLicense } from 'unifyedx-storybook-syncfusion';
|
|
56
|
+
|
|
57
|
+
registerSyncfusionLicense(import.meta.env.VITE_APP_SYNCFUSION_LICENSE_KEY);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- `registerSyncfusionLicense` is idempotent; calling it twice is harmless.
|
|
61
|
+
- Import it from **this** package so the licence registers on the same `ej2-base` instance the components use.
|
|
62
|
+
- Never hardcode the licence key in source; read it from env.
|
|
63
|
+
|
|
64
|
+
## 3. Imports
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
import { CustomDataGrid, CustomGridToolbar, CustomDatePicker } from 'unifyedx-storybook-syncfusion';
|
|
68
|
+
import { UnifyedCoreButton, GenericFilter, notify } from 'unifyedx-storybook-new';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
These three were removed from `unifyedx-storybook-new` in 0.4.0 — importing them from there fails.
|
|
72
|
+
|
|
73
|
+
## 4. CustomDataGrid
|
|
74
|
+
|
|
75
|
+
A lean, **server-controlled** Syncfusion grid. It cancels client-side data operations:
|
|
76
|
+
the parent fetches one page and passes `data` + `totalCount`.
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
data=[] totalCount={0} columns=[] uniqueId="grid" height="600"
|
|
80
|
+
pageIndex={1} (1-based) pageSize={20}
|
|
81
|
+
allowPaging={true} allowSorting={true} allowReordering={true} allowResizing={true}
|
|
82
|
+
allowFiltering={false} allowGrouping={false} allowExcelExport={false} allowPdfExport={false}
|
|
83
|
+
showColumnChooser={false} enableSearchApi={false} enableCheckbox={false} selectionSettings
|
|
84
|
+
onGridStateChange(state, rawArgs) onRowSelected onRowDeselected onRowDoubleClick
|
|
85
|
+
allowEditing={false} editSettings onCellSave
|
|
86
|
+
apiRef tableId gridProps={} ariaLabel ariaLabelledBy ariaDescribedBy
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### State contract — `onGridStateChange(state)`
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
{
|
|
93
|
+
reason: "paging" | "sorting" | "searching" | "filtering" | "grouping" | "reorder" | "columnstate" | "other",
|
|
94
|
+
page: { index, size, skip, take }, // index is 1-based; skip/take ready for the API
|
|
95
|
+
sort: [{ field, dir: "asc" | "desc" }],
|
|
96
|
+
search: "",
|
|
97
|
+
filters: [],
|
|
98
|
+
rawEvent, // the original Syncfusion args
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```jsx
|
|
103
|
+
const [rows, setRows] = useState([]);
|
|
104
|
+
const [total, setTotal] = useState(0);
|
|
105
|
+
const apiRef = useRef(null);
|
|
106
|
+
|
|
107
|
+
const load = useCallback(async ({ page, sort, search }) => {
|
|
108
|
+
const res = await axiosGet(`/api/users?skip=${page.skip}&take=${page.take}` +
|
|
109
|
+
`&sort=${sort[0]?.field ?? ''}&dir=${sort[0]?.dir ?? ''}&q=${encodeURIComponent(search)}`);
|
|
110
|
+
setRows(res.data.items); setTotal(res.data.total);
|
|
111
|
+
}, []);
|
|
112
|
+
|
|
113
|
+
<CustomDataGrid
|
|
114
|
+
data={rows}
|
|
115
|
+
totalCount={total}
|
|
116
|
+
columns={columns}
|
|
117
|
+
apiRef={apiRef}
|
|
118
|
+
tableId="users"
|
|
119
|
+
onGridStateChange={load}
|
|
120
|
+
/>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Never** pass the full dataset for client paging — fetch per page.
|
|
124
|
+
|
|
125
|
+
### Columns
|
|
126
|
+
|
|
127
|
+
Syncfusion column objects: `{ field, headerText, width, textAlign, template, allowSorting, allowEditing, isPrimaryKey, freeze }`.
|
|
128
|
+
A column whose `headerText` is `"Action"`/`"Actions"` gets the Freeze service injected automatically (use `freeze: "Right"` to pin it).
|
|
129
|
+
Mark one column `isPrimaryKey` when `enableCheckbox` / `persistSelection` is on, or Syncfusion logs *PRIMARY KEY MISSING*.
|
|
130
|
+
|
|
131
|
+
### `apiRef` methods
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
getInstance() refresh() getSelectedRecords() getSelectedRowIndexes() clearSelection()
|
|
135
|
+
selectRow(i) selectRows([i]) deselectByPrimaryKey(k) deselectByPrimaryKeys([k])
|
|
136
|
+
search(text) // needs enableSearchApi
|
|
137
|
+
print()
|
|
138
|
+
excelExport(opts) // needs allowExcelExport
|
|
139
|
+
pdfExport(opts) // needs allowPdfExport
|
|
140
|
+
openColumnChooser(x, y) // needs showColumnChooser
|
|
141
|
+
getColumns() getFilteredRecords() autoFitColumns(fields)
|
|
142
|
+
```
|
|
143
|
+
Calling a gated method without its `allow*` / `show*` prop logs a warning and does nothing.
|
|
144
|
+
|
|
145
|
+
### Inline editing
|
|
146
|
+
|
|
147
|
+
`allowEditing`, `editSettings` and `onCellSave` are wired to the grid (fixed in 0.4.0 —
|
|
148
|
+
before that they were accepted but ignored). Defaults: `mode: "Batch"`, no add/delete,
|
|
149
|
+
no confirm dialogs. Override any default via `editSettings`.
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
onCellSave({ field, columnName, value, previousValue, rowData, cancel(), originalEvent })
|
|
153
|
+
// call cancel() to reject the edit (e.g. validation failed)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### State persistence
|
|
157
|
+
|
|
158
|
+
Pass a stable `tableId` (or omit it to derive one from the route; `false`/`null` opts out).
|
|
159
|
+
Page, page size and sort restore through `useTablePreferences` / `useRestoredGridState`
|
|
160
|
+
from `unifyedx-storybook-new`. Use the **same** `tableId` on `CustomGridToolbar` and
|
|
161
|
+
`GenericFilter` so search and filters restore alongside.
|
|
162
|
+
|
|
163
|
+
## 5. CustomGridToolbar
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
heading="Data Grid" subheading="" totalCount={0} apiRef (or legacy gridRef) tableId
|
|
167
|
+
showSearch={true} showDelete={true} showColumnChooser={true}
|
|
168
|
+
showFilter={false} showPrint={false} showExcel={false} showPdf={false} showRefresh={false} showAdd={false}
|
|
169
|
+
onAdd addBtnText="Add" onFilterOpen filterCount
|
|
170
|
+
iSelectedRecords={0} selectedRecords searchPlaceholder="Search..."
|
|
171
|
+
handleSearchChange handleDeleteClick handleRefreshClick
|
|
172
|
+
excelFileName pdfFileName actionButtons=[]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`actionButtons` entries by `type`:
|
|
176
|
+
- `"button"` (default) — a `UnifyedCoreButton`, or an `IconButton` when `iconOnly: true` and `icon` are set
|
|
177
|
+
- `"segmented"` — `{ id, value, options:[{key,label}], onChange, ariaLabel }` renders a `SegmentedControl`
|
|
178
|
+
- `"multioptions"` — a `UnifyedCoreButton` with a dropdown menu
|
|
179
|
+
- `"custom"` — `{ id, render: () => <YourNode/> }`
|
|
180
|
+
|
|
181
|
+
```jsx
|
|
182
|
+
<CustomGridToolbar
|
|
183
|
+
heading="Users" totalCount={total} apiRef={apiRef} tableId="users"
|
|
184
|
+
showAdd addBtnText="Invite" onAdd={openInvite}
|
|
185
|
+
showFilter filterCount={countActiveFilters(filters)} onFilterOpen={() => setFilterOpen(true)}
|
|
186
|
+
showExcel excelFileName="users.xlsx"
|
|
187
|
+
/>
|
|
188
|
+
<CustomDataGrid apiRef={apiRef} tableId="users" allowExcelExport ... />
|
|
189
|
+
```
|
|
190
|
+
Export/print/column-chooser buttons call the grid through `apiRef`, so the grid must have the matching `allow*` prop.
|
|
191
|
+
|
|
192
|
+
## 6. CustomDatePicker
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
mode="date" | "daterange" | "time" | "datetime" | "datetimerange"
|
|
196
|
+
value onChange min max format placeholder step={30} (minutes)
|
|
197
|
+
label required errorMessage disabled readOnly showClearButton={true}
|
|
198
|
+
strictMode={false} typeable={true} openOnFocus={false} weekNumber firstDayOfWeek
|
|
199
|
+
width cssClass id name ariaLabel ariaLabelledBy ariaDescribedBy
|
|
200
|
+
daterange: startDate endDate separator="-" presets startPlaceholder endPlaceholder
|
|
201
|
+
datetimerange: startValue endValue onStartChange onEndChange
|
|
202
|
+
events: onOpen onClose onFocus onBlur onNavigated onRenderDayCell onCleared
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- Single modes: `onChange({ value: Date, event })`.
|
|
206
|
+
- `daterange`: `onChange({ startDate, endDate, ... })`.
|
|
207
|
+
- `datetimerange`: separate `onStartChange` / `onEndChange`, each `{ value }`.
|
|
208
|
+
|
|
209
|
+
**Prefer the core package** for `mode="date"` and `mode="time"`: `DateField` and
|
|
210
|
+
`TimeField` in `unifyedx-storybook-new` emit the identical `{ value: Date }` and need
|
|
211
|
+
no Syncfusion. Reach for `CustomDatePicker` only for range and datetime modes.
|
|
212
|
+
|
|
213
|
+
## 7. Gotchas
|
|
214
|
+
|
|
215
|
+
1. **CSS order**: import `unifyedx-storybook-syncfusion/syncfusion.css` once. It already contains the Syncfusion theme followed by the component overrides — do not import individual `@syncfusion/*/styles` files too, or the overrides lose.
|
|
216
|
+
2. **One `unifyedx-storybook-new` instance**: this package imports core as a peer. If `npm ls unifyedx-storybook-new` shows two copies, hooks break with *Invalid hook call*. Keep both packages on the same version.
|
|
217
|
+
3. **Peers must be explicit**: several older apps imported `CustomDataGrid` without declaring `@syncfusion/ej2-react-grids` and worked only via hoisting. Declare every peer in section 2.
|
|
218
|
+
4. **Migrating from ≤0.3.x**: change the import specifier from `unifyedx-storybook-new` to `unifyedx-storybook-syncfusion`, add the package + peers, and add the `syncfusion.css` import. Nothing else changes.
|
|
219
|
+
5. **Accessibility**: pass `label` or `ariaLabel` to every picker and `ariaLabel` to the grid; UnifyedX targets WCAG 2.0 AAA.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CustomDatePicker — a unified Syncfusion-based date/time picker.
|
|
3
|
+
*
|
|
4
|
+
* Modes:
|
|
5
|
+
* - "date" → single date
|
|
6
|
+
* - "daterange" → start + end date
|
|
7
|
+
* - "time" → time only
|
|
8
|
+
* - "datetime" → single date + time
|
|
9
|
+
* - "datetimerange" → start + end date-time (two DateTimePickers)
|
|
10
|
+
*/
|
|
11
|
+
export function CustomDatePicker({ mode, value, onChange, min, max, format, placeholder, disabled, readOnly, showClearButton, floatLabelType, strictMode, typeable, openOnFocus, cssClass, width, step, weekNumber, firstDayOfWeek, label, labelId, ariaLabel, ariaLabelledBy, ariaDescribedBy, required, errorMessage, startDate, endDate, separator, presets, startPlaceholder, endPlaceholder, startValue, endValue, onStartChange, onEndChange, onOpen, onClose, onFocus, onBlur, onNavigated, onRenderDayCell, onCleared, id, name, htmlAttributes, ...rest }: {
|
|
12
|
+
[x: string]: any;
|
|
13
|
+
mode?: string;
|
|
14
|
+
value: any;
|
|
15
|
+
onChange: any;
|
|
16
|
+
min: any;
|
|
17
|
+
max: any;
|
|
18
|
+
format: any;
|
|
19
|
+
placeholder: any;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
readOnly?: boolean;
|
|
22
|
+
showClearButton?: boolean;
|
|
23
|
+
floatLabelType?: string;
|
|
24
|
+
strictMode?: boolean;
|
|
25
|
+
typeable?: boolean;
|
|
26
|
+
openOnFocus?: boolean;
|
|
27
|
+
cssClass?: string;
|
|
28
|
+
width: any;
|
|
29
|
+
step?: number;
|
|
30
|
+
weekNumber?: boolean;
|
|
31
|
+
firstDayOfWeek: any;
|
|
32
|
+
label: any;
|
|
33
|
+
labelId: any;
|
|
34
|
+
ariaLabel: any;
|
|
35
|
+
ariaLabelledBy: any;
|
|
36
|
+
ariaDescribedBy: any;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
errorMessage: any;
|
|
39
|
+
startDate: any;
|
|
40
|
+
endDate: any;
|
|
41
|
+
separator?: string;
|
|
42
|
+
presets: any;
|
|
43
|
+
startPlaceholder: any;
|
|
44
|
+
endPlaceholder: any;
|
|
45
|
+
startValue: any;
|
|
46
|
+
endValue: any;
|
|
47
|
+
onStartChange: any;
|
|
48
|
+
onEndChange: any;
|
|
49
|
+
onOpen: any;
|
|
50
|
+
onClose: any;
|
|
51
|
+
onFocus: any;
|
|
52
|
+
onBlur: any;
|
|
53
|
+
onNavigated: any;
|
|
54
|
+
onRenderDayCell: any;
|
|
55
|
+
onCleared: any;
|
|
56
|
+
id: any;
|
|
57
|
+
name: any;
|
|
58
|
+
htmlAttributes: any;
|
|
59
|
+
}): React.JSX.Element;
|
|
60
|
+
export namespace CustomDatePicker {
|
|
61
|
+
namespace propTypes {
|
|
62
|
+
let mode: any;
|
|
63
|
+
let value: any;
|
|
64
|
+
let onChange: any;
|
|
65
|
+
let min: any;
|
|
66
|
+
let max: any;
|
|
67
|
+
let format: any;
|
|
68
|
+
let placeholder: any;
|
|
69
|
+
let disabled: any;
|
|
70
|
+
let readOnly: any;
|
|
71
|
+
let showClearButton: any;
|
|
72
|
+
let floatLabelType: any;
|
|
73
|
+
let strictMode: any;
|
|
74
|
+
let typeable: any;
|
|
75
|
+
let openOnFocus: any;
|
|
76
|
+
let cssClass: any;
|
|
77
|
+
let width: any;
|
|
78
|
+
let step: any;
|
|
79
|
+
let weekNumber: any;
|
|
80
|
+
let firstDayOfWeek: any;
|
|
81
|
+
let label: any;
|
|
82
|
+
let labelId: any;
|
|
83
|
+
let required: any;
|
|
84
|
+
let errorMessage: any;
|
|
85
|
+
let startDate: any;
|
|
86
|
+
let endDate: any;
|
|
87
|
+
let separator: any;
|
|
88
|
+
let presets: any;
|
|
89
|
+
let startPlaceholder: any;
|
|
90
|
+
let endPlaceholder: any;
|
|
91
|
+
let startValue: any;
|
|
92
|
+
let endValue: any;
|
|
93
|
+
let onStartChange: any;
|
|
94
|
+
let onEndChange: any;
|
|
95
|
+
let onOpen: any;
|
|
96
|
+
let onClose: any;
|
|
97
|
+
let onFocus: any;
|
|
98
|
+
let onBlur: any;
|
|
99
|
+
let onNavigated: any;
|
|
100
|
+
let onRenderDayCell: any;
|
|
101
|
+
let onCleared: any;
|
|
102
|
+
let id: any;
|
|
103
|
+
let name: any;
|
|
104
|
+
let htmlAttributes: any;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
import React from "react";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function CustomGridToolbar({ heading, subheading, totalCount, gridRef, apiRef, onAdd, onFilterOpen, addBtnText, showSearch, showDelete, showColumnChooser, showFilter, showPrint, showExcel, showPdf, showRefresh, showAdd, iSelectedRecords, selectedRecords, searchPlaceholder, handleRefreshClick, handleSearchChange, handleDeleteClick, excelFileName, pdfFileName, searchIconSize, searchIconClass, inputStyle, filterCount, actionButtons, tableId: tableIdProp, ...props }: {
|
|
2
|
+
[x: string]: any;
|
|
3
|
+
heading?: string;
|
|
4
|
+
subheading?: string;
|
|
5
|
+
totalCount?: number;
|
|
6
|
+
gridRef: any;
|
|
7
|
+
apiRef: any;
|
|
8
|
+
onAdd: any;
|
|
9
|
+
onFilterOpen: any;
|
|
10
|
+
addBtnText?: string;
|
|
11
|
+
showSearch?: boolean;
|
|
12
|
+
showDelete?: boolean;
|
|
13
|
+
showColumnChooser?: boolean;
|
|
14
|
+
showFilter?: boolean;
|
|
15
|
+
showPrint?: boolean;
|
|
16
|
+
showExcel?: boolean;
|
|
17
|
+
showPdf?: boolean;
|
|
18
|
+
showRefresh?: boolean;
|
|
19
|
+
showAdd?: boolean;
|
|
20
|
+
iSelectedRecords?: number;
|
|
21
|
+
selectedRecords: any;
|
|
22
|
+
searchPlaceholder?: string;
|
|
23
|
+
handleRefreshClick?: () => void;
|
|
24
|
+
handleSearchChange?: () => void;
|
|
25
|
+
handleDeleteClick?: () => void;
|
|
26
|
+
excelFileName: any;
|
|
27
|
+
pdfFileName: any;
|
|
28
|
+
searchIconSize: any;
|
|
29
|
+
searchIconClass: any;
|
|
30
|
+
inputStyle: any;
|
|
31
|
+
filterCount: any;
|
|
32
|
+
actionButtons?: any[];
|
|
33
|
+
tableId: any;
|
|
34
|
+
}): React.JSX.Element;
|
|
35
|
+
import React from "react";
|
package/dist/index.d.ts
ADDED