@equinor/eds-data-grid-react 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Equinor ASA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # EDS Data Grid
2
+
3
+ This component is the result of a contribution by MSS in collaboration with the EDS Core Team.
@@ -0,0 +1,345 @@
1
+ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
+ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
3
+ import { getCoreRowModel, getSortedRowModel, getFacetedRowModel, getFacetedUniqueValues, getFacetedMinMaxValues, getFilteredRowModel, getPaginationRowModel, useReactTable } from '@tanstack/react-table';
4
+ import { useEds, Table, Pagination } from '@equinor/eds-core-react';
5
+ import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
6
+ import { TableHeaderRow } from './components/TableHeaderRow.js';
7
+ import { TableRow } from './components/TableRow.js';
8
+ import { TableProvider } from './EdsDataGridContext.js';
9
+ import { useVirtualizer } from '@tanstack/react-virtual';
10
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
+
12
+ function EdsDataGrid(_ref) {
13
+ var rows = _ref.rows,
14
+ columns = _ref.columns,
15
+ columnResizeMode = _ref.columnResizeMode,
16
+ pageSize = _ref.pageSize,
17
+ rowSelection = _ref.rowSelection,
18
+ selectedRows = _ref.selectedRows,
19
+ enableColumnFiltering = _ref.enableColumnFiltering,
20
+ debug = _ref.debug,
21
+ enablePagination = _ref.enablePagination,
22
+ enableSorting = _ref.enableSorting,
23
+ stickyHeader = _ref.stickyHeader,
24
+ onSelectRow = _ref.onSelectRow,
25
+ caption = _ref.caption,
26
+ enableVirtual = _ref.enableVirtual,
27
+ virtualHeight = _ref.virtualHeight,
28
+ columnVisibility = _ref.columnVisibility,
29
+ columnVisibilityChange = _ref.columnVisibilityChange,
30
+ emptyMessage = _ref.emptyMessage,
31
+ columnOrder = _ref.columnOrder,
32
+ cellClass = _ref.cellClass,
33
+ cellStyle = _ref.cellStyle,
34
+ rowClass = _ref.rowClass,
35
+ rowStyle = _ref.rowStyle,
36
+ headerClass = _ref.headerClass,
37
+ headerStyle = _ref.headerStyle;
38
+ var _useState = useState([]),
39
+ _useState2 = _slicedToArray(_useState, 2),
40
+ sorting = _useState2[0],
41
+ setSorting = _useState2[1];
42
+ var _useState3 = useState(selectedRows !== null && selectedRows !== void 0 ? selectedRows : {}),
43
+ _useState4 = _slicedToArray(_useState3, 2),
44
+ selection = _useState4[0],
45
+ setSelection = _useState4[1];
46
+ var _useState5 = useState([]),
47
+ _useState6 = _slicedToArray(_useState5, 2),
48
+ columnFilters = _useState6[0],
49
+ setColumnFilters = _useState6[1];
50
+ var _useState7 = useState(columnVisibility !== null && columnVisibility !== void 0 ? columnVisibility : {}),
51
+ _useState8 = _slicedToArray(_useState7, 2),
52
+ visible = _useState8[0],
53
+ setVisible = _useState8[1];
54
+ var _useState9 = useState(''),
55
+ _useState10 = _slicedToArray(_useState9, 2),
56
+ globalFilter = _useState10[0],
57
+ setGlobalFilter = _useState10[1];
58
+ var _useState11 = useState([]),
59
+ _useState12 = _slicedToArray(_useState11, 2),
60
+ columnOrderState = _useState12[0],
61
+ setColumnOrderState = _useState12[1];
62
+ var _useState13 = useState({
63
+ pageIndex: 0,
64
+ pageSize: pageSize !== null && pageSize !== void 0 ? pageSize : 25
65
+ }),
66
+ _useState14 = _slicedToArray(_useState13, 2),
67
+ page = _useState14[0],
68
+ setPage = _useState14[1];
69
+ useEffect(function () {
70
+ setVisible(columnVisibility !== null && columnVisibility !== void 0 ? columnVisibility : {});
71
+ }, [columnVisibility, setVisible]);
72
+ useEffect(function () {
73
+ setSelection(selectedRows !== null && selectedRows !== void 0 ? selectedRows : {});
74
+ }, [selectedRows]);
75
+
76
+ /**
77
+ * By default, the filter-function accepts single-value filters. This adds multi-filter functionality out of the box.
78
+ */
79
+ var _columns = useMemo(function () {
80
+ return columns.map(function (column) {
81
+ if (column.filterFn || column.enableColumnFilter === false) {
82
+ return column;
83
+ }
84
+ /* istanbul ignore next */
85
+ return _objectSpread(_objectSpread({}, column), {}, {
86
+ filterFn: function filterFn(row, columnId, filterValue) {
87
+ var _row$getValue;
88
+ if (debug) {
89
+ console.log('filterFn', row, columnId, filterValue);
90
+ }
91
+ if (!filterValue || (Array.isArray(filterValue) || typeof filterValue === 'string') && filterValue.length === 0) {
92
+ return true;
93
+ }
94
+ var value = (_row$getValue = row.getValue(columnId)) !== null && _row$getValue !== void 0 ? _row$getValue : 'NULL_OR_UNDEFINED';
95
+ if (Array.isArray(filterValue)) {
96
+ var numeric = filterValue.some(function (v) {
97
+ return typeof v === 'number';
98
+ });
99
+ if (numeric) {
100
+ var _ref2 = filterValue,
101
+ _ref3 = _slicedToArray(_ref2, 2),
102
+ start = _ref3[0],
103
+ end = _ref3[1];
104
+ return value >= (isNaN(start) ? 0 : start) && value <= (!end || isNaN(end) ? Infinity : end);
105
+ } else {
106
+ var validFilterValue = filterValue.filter(function (v) {
107
+ return !!v;
108
+ });
109
+ if (validFilterValue.length === 0) return true;
110
+ return filterValue.includes(value);
111
+ }
112
+ }
113
+ return value === filterValue;
114
+ }
115
+ });
116
+ });
117
+ }, [debug, columns]);
118
+
119
+ /**
120
+ * Set up default table options
121
+ */
122
+ var options = {
123
+ data: rows,
124
+ columns: _columns,
125
+ columnResizeMode: columnResizeMode,
126
+ state: {
127
+ sorting: sorting,
128
+ rowSelection: selection,
129
+ columnOrder: columnOrderState
130
+ },
131
+ onSortingChange: setSorting,
132
+ enableColumnFilters: !!enableColumnFiltering,
133
+ enableFilters: !!enableColumnFiltering,
134
+ enableSorting: enableSorting !== null && enableSorting !== void 0 ? enableSorting : false,
135
+ enableColumnResizing: !!columnResizeMode,
136
+ getCoreRowModel: getCoreRowModel(),
137
+ getSortedRowModel: getSortedRowModel(),
138
+ debugTable: debug,
139
+ debugHeaders: debug,
140
+ debugColumns: debug,
141
+ enableRowSelection: rowSelection !== null && rowSelection !== void 0 ? rowSelection : false
142
+ };
143
+ useEffect(function () {
144
+ if (columnOrder && columnOrder.length > 0) {
145
+ setColumnOrderState(columnOrder !== null && columnOrder !== void 0 ? columnOrder : []);
146
+ }
147
+ }, [columnOrder]);
148
+
149
+ /**
150
+ * Set up handlers for rowSelection
151
+ */
152
+ if (rowSelection !== null && rowSelection !== void 0 ? rowSelection : false) {
153
+ options.onRowSelectionChange = function (updaterOrValue) {
154
+ if (onSelectRow) {
155
+ onSelectRow(updaterOrValue);
156
+ }
157
+ setSelection(updaterOrValue);
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Set up config for column filtering
163
+ */
164
+ if (enableColumnFiltering) {
165
+ options.state.columnFilters = columnFilters;
166
+ options.state.globalFilter = globalFilter;
167
+ options.onColumnFiltersChange = setColumnFilters;
168
+ options.onGlobalFilterChange = setGlobalFilter;
169
+ options.getFacetedRowModel = getFacetedRowModel();
170
+ options.getFacetedUniqueValues = getFacetedUniqueValues();
171
+ options.getFacetedMinMaxValues = getFacetedMinMaxValues();
172
+ options.getFilteredRowModel = getFilteredRowModel();
173
+ }
174
+
175
+ /**
176
+ * Set up config for pagination
177
+ */
178
+ if (enablePagination !== null && enablePagination !== void 0 ? enablePagination : false) {
179
+ options.state.pagination = page;
180
+ options.getPaginationRowModel = getPaginationRowModel();
181
+ }
182
+
183
+ /**
184
+ * Set up config to handle column visibility controls
185
+ */
186
+ if (columnVisibility) {
187
+ options.state.columnVisibility = visible;
188
+ options.onColumnVisibilityChange = function (vis) {
189
+ var updated;
190
+ if (typeof vis === 'function') {
191
+ updated = vis(visible);
192
+ } else {
193
+ updated = vis;
194
+ }
195
+ if (columnVisibilityChange) columnVisibilityChange(updated);
196
+ setVisible(updated);
197
+ };
198
+ }
199
+ useEffect(function () {
200
+ setPage(function (prev) {
201
+ return _objectSpread(_objectSpread({}, prev), {}, {
202
+ pageSize: pageSize !== null && pageSize !== void 0 ? pageSize : 25
203
+ });
204
+ });
205
+ }, [pageSize]);
206
+ var table = useReactTable(options);
207
+ var parentRefStyle = {};
208
+
209
+ /**
210
+ * Style the parent container to enable virtualization.
211
+ * By not setting this, the virtual-scroll will always render every row, reducing computational overhead if turned off.
212
+ */
213
+ if (enableVirtual) {
214
+ parentRefStyle = {
215
+ height: virtualHeight !== null && virtualHeight !== void 0 ? virtualHeight : 500,
216
+ overflow: 'auto',
217
+ position: 'relative'
218
+ };
219
+ }
220
+ var parentRef = useRef(null);
221
+
222
+ /**
223
+ * Virtualization setup
224
+ */
225
+ var _useEds = useEds(),
226
+ density = _useEds.density;
227
+ var estimateSize = useCallback(function () {
228
+ return density === 'compact' ? 32 : 48;
229
+ }, [density]);
230
+ var virtualizer = useVirtualizer({
231
+ count: table.getRowModel().rows.length,
232
+ getScrollElement: function getScrollElement() {
233
+ return parentRef.current;
234
+ },
235
+ estimateSize: estimateSize
236
+ });
237
+ var virtualRows = virtualizer.getVirtualItems();
238
+ var paddingTop = virtualRows.length ? virtualRows[0].start : 0;
239
+ var paddingBottom = virtualRows.length ? virtualizer.getTotalSize() - virtualRows[virtualRows.length - 1].end : 0;
240
+
241
+ // These classes are primarily used to allow for feature-detection in the test-suite
242
+ var classList = {
243
+ 'sticky-header': !!stickyHeader,
244
+ virtual: !!enableVirtual,
245
+ paging: !!enablePagination
246
+ };
247
+ return /*#__PURE__*/jsxs(TableProvider, {
248
+ cellClass: cellClass,
249
+ cellStyle: cellStyle,
250
+ rowClass: rowClass,
251
+ rowStyle: rowStyle,
252
+ headerClass: headerClass,
253
+ headerStyle: headerStyle,
254
+ table: table,
255
+ enableSorting: !!enableSorting,
256
+ enableColumnFiltering: !!enableColumnFiltering,
257
+ stickyHeader: !!stickyHeader,
258
+ children: [/*#__PURE__*/jsxs("div", {
259
+ className: "table-wrapper",
260
+ style: parentRefStyle,
261
+ ref: parentRef,
262
+ children: [/*#__PURE__*/jsxs(Table, {
263
+ className: Object.entries(classList).filter(function (_ref4) {
264
+ var _ref5 = _slicedToArray(_ref4, 2),
265
+ k = _ref5[1];
266
+ return k;
267
+ }).map(function (_ref6) {
268
+ var _ref7 = _slicedToArray(_ref6, 1),
269
+ k = _ref7[0];
270
+ return k;
271
+ }).join(' '),
272
+ style: {
273
+ width: table.getTotalSize()
274
+ },
275
+ children: [caption && /*#__PURE__*/jsx(Table.Caption, {
276
+ children: caption
277
+ }), /*#__PURE__*/jsx(Table.Head, {
278
+ sticky: stickyHeader,
279
+ children: table.getHeaderGroups().map(function (headerGroup) {
280
+ return /*#__PURE__*/jsx(TableHeaderRow, {
281
+ table: table,
282
+ headerGroup: headerGroup,
283
+ columnResizeMode: columnResizeMode,
284
+ deltaOffset: table.getState().columnSizingInfo.deltaOffset
285
+ }, headerGroup.id);
286
+ })
287
+ }), /*#__PURE__*/jsxs(Table.Body, {
288
+ children: [table.getRowModel().rows.length === 0 && emptyMessage && /*#__PURE__*/jsx(Table.Row, {
289
+ children: /*#__PURE__*/jsx(Table.Cell, {
290
+ colSpan: table.getHeaderGroups().length,
291
+ children: emptyMessage
292
+ })
293
+ }), enableVirtual && /*#__PURE__*/jsxs(Fragment, {
294
+ children: [/*#__PURE__*/jsx(Table.Row, {
295
+ "data-testid": "virtual-padding-top",
296
+ className: 'virtual-padding-top',
297
+ children: /*#__PURE__*/jsx(Table.Cell, {
298
+ style: {
299
+ height: "".concat(paddingTop, "px")
300
+ }
301
+ })
302
+ }), virtualRows.map(function (row) {
303
+ return /*#__PURE__*/jsx(TableRow, {
304
+ row: table.getRowModel().rows[row.index]
305
+ }, row.index);
306
+ }), /*#__PURE__*/jsx(Table.Row, {
307
+ "data-testid": "virtual-padding-bottom",
308
+ className: 'virtual-padding-bottom',
309
+ children: /*#__PURE__*/jsx(Table.Cell, {
310
+ style: {
311
+ height: "".concat(paddingBottom, "px")
312
+ }
313
+ })
314
+ })]
315
+ }), !enableVirtual && table.getRowModel().rows.map(function (row) {
316
+ return /*#__PURE__*/jsx(TableRow, {
317
+ row: row
318
+ }, row.id);
319
+ })]
320
+ })]
321
+ }), enablePagination && /*#__PURE__*/jsx("div", {
322
+ style: {
323
+ maxWidth: "".concat(table.getTotalSize(), "px")
324
+ },
325
+ children: /*#__PURE__*/jsx(Pagination, {
326
+ totalItems: table.getFilteredRowModel().rows.length,
327
+ withItemIndicator: true,
328
+ itemsPerPage: page.pageSize,
329
+ onChange: function onChange(e, p) {
330
+ return setPage(function (s) {
331
+ return _objectSpread(_objectSpread({}, s), {}, {
332
+ pageIndex: p - 1
333
+ });
334
+ });
335
+ },
336
+ defaultPage: 1
337
+ })
338
+ })]
339
+ }), debug && enableVirtual && /*#__PURE__*/jsxs("span", {
340
+ children: ["Visible items: ", virtualizer.range.startIndex, " -", ' ', virtualizer.range.endIndex, " / ", rows.length]
341
+ })]
342
+ });
343
+ }
344
+
345
+ export { EdsDataGrid };
@@ -0,0 +1,25 @@
1
+ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
2
+ import { createContext, useContext } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var _excluded = ["children"];
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ var EdsDataGridContext = /*#__PURE__*/createContext({
8
+ enableSorting: false,
9
+ stickyHeader: false,
10
+ enableColumnFiltering: false,
11
+ table: null
12
+ });
13
+ function TableProvider(_ref) {
14
+ var children = _ref.children,
15
+ props = _objectWithoutProperties(_ref, _excluded);
16
+ return /*#__PURE__*/jsx(EdsDataGridContext.Provider, {
17
+ value: props,
18
+ children: children
19
+ });
20
+ }
21
+ var useTableContext = function useTableContext() {
22
+ return useContext(EdsDataGridContext);
23
+ };
24
+
25
+ export { EdsDataGridContext, TableProvider, useTableContext };
@@ -0,0 +1,61 @@
1
+ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
2
+ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
3
+ import { useState, useEffect } from 'react';
4
+ import { EdsProvider, Input, Autocomplete } from '@equinor/eds-core-react';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ var _excluded = ["value", "values", "onChange", "debounce"];
8
+ // File ignored, as relevant actions are covered via Filter.test.tsx
9
+ function DebouncedInput(_ref) {
10
+ var _props$placeholder, _props$placeholder2;
11
+ var initialValue = _ref.value,
12
+ values = _ref.values,
13
+ onChange = _ref.onChange,
14
+ _ref$debounce = _ref.debounce,
15
+ debounce = _ref$debounce === void 0 ? 500 : _ref$debounce,
16
+ props = _objectWithoutProperties(_ref, _excluded);
17
+ var _useState = useState(initialValue),
18
+ _useState2 = _slicedToArray(_useState, 2),
19
+ value = _useState2[0],
20
+ setValue = _useState2[1];
21
+ useEffect(function () {
22
+ setValue(initialValue);
23
+ }, [initialValue]);
24
+ useEffect(function () {
25
+ var timeout = setTimeout(function () {
26
+ onChange(value);
27
+ }, debounce);
28
+ return function () {
29
+ return clearTimeout(timeout);
30
+ };
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ }, [value]);
33
+ return /*#__PURE__*/jsx(EdsProvider, {
34
+ density: "compact",
35
+ children: props.type === 'number' ? /*#__PURE__*/jsx(Input, {
36
+ type: 'number',
37
+ placeholder: (_props$placeholder = props.placeholder) !== null && _props$placeholder !== void 0 ? _props$placeholder : 'Search',
38
+ value: value,
39
+ onChange: function onChange(e) {
40
+ return setValue(e.target.valueAsNumber);
41
+ }
42
+ }) : /*#__PURE__*/jsx(Autocomplete, {
43
+ options: values,
44
+ multiple: true,
45
+ optionComponent: function optionComponent(opt) {
46
+ return opt === 'NULL_OR_UNDEFINED' ? '<Blank>' : opt;
47
+ },
48
+ "data-testid": 'autocomplete'
49
+ /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
50
+ // @ts-ignore
51
+ ,
52
+ label: null,
53
+ placeholder: (_props$placeholder2 = props.placeholder) !== null && _props$placeholder2 !== void 0 ? _props$placeholder2 : 'Search',
54
+ onOptionsChange: function onOptionsChange(c) {
55
+ return setValue(c.selectedItems);
56
+ }
57
+ })
58
+ });
59
+ }
60
+
61
+ export { DebouncedInput };
@@ -0,0 +1,58 @@
1
+ import { useMemo } from 'react';
2
+ import { DebouncedInput } from './DebouncedInput.js';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ /* istanbul ignore file */
6
+
7
+ function Filter(_ref) {
8
+ var _table$getPreFiltered, _column$getFacetedMin, _column$getFacetedMin2, _column$getFacetedMin3, _column$getFacetedMin4, _, _column$getFacetedMin5, _column$getFacetedMin6, _column$getFacetedMin7, _column$getFacetedMin8, _column$getFacetedMin9, _column$getFacetedMin10, _2, _column$getFacetedMin11, _column$getFacetedMin12;
9
+ var column = _ref.column,
10
+ table = _ref.table;
11
+ var firstValue = (_table$getPreFiltered = table.getPreFilteredRowModel().flatRows[0]) === null || _table$getPreFiltered === void 0 ? void 0 : _table$getPreFiltered.getValue(column.id);
12
+ var columnFilterValue = column.getFilterValue();
13
+ var sortedUniqueValues = useMemo(function () {
14
+ return typeof firstValue === 'number' ? [] : Array.from(column.getFacetedUniqueValues().keys()).sort().map(function (v) {
15
+ return v !== null && v !== void 0 ? v : 'NULL_OR_UNDEFINED';
16
+ });
17
+ },
18
+ // eslint-disable-next-line react-hooks/exhaustive-deps
19
+ [column.getFacetedUniqueValues()]);
20
+ return typeof firstValue === 'number' ? /*#__PURE__*/jsxs("div", {
21
+ children: [/*#__PURE__*/jsx(DebouncedInput, {
22
+ type: "number",
23
+ values: sortedUniqueValues,
24
+ min: Number((_column$getFacetedMin = (_column$getFacetedMin2 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin2 === void 0 ? void 0 : _column$getFacetedMin2[0]) !== null && _column$getFacetedMin !== void 0 ? _column$getFacetedMin : ''),
25
+ max: Number((_column$getFacetedMin3 = (_column$getFacetedMin4 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin4 === void 0 ? void 0 : _column$getFacetedMin4[1]) !== null && _column$getFacetedMin3 !== void 0 ? _column$getFacetedMin3 : ''),
26
+ value: (_ = columnFilterValue === null || columnFilterValue === void 0 ? void 0 : columnFilterValue[0]) !== null && _ !== void 0 ? _ : '',
27
+ onChange: function onChange(value) {
28
+ return column.setFilterValue(function (old) {
29
+ return [value, old === null || old === void 0 ? void 0 : old[1]];
30
+ });
31
+ },
32
+ placeholder: "Min ".concat((_column$getFacetedMin5 = column.getFacetedMinMaxValues()) !== null && _column$getFacetedMin5 !== void 0 && _column$getFacetedMin5[0] ? "(".concat((_column$getFacetedMin6 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin6 === void 0 ? void 0 : _column$getFacetedMin6[0], ")") : '')
33
+ }), /*#__PURE__*/jsx(DebouncedInput, {
34
+ type: "number",
35
+ values: sortedUniqueValues,
36
+ min: Number((_column$getFacetedMin7 = (_column$getFacetedMin8 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin8 === void 0 ? void 0 : _column$getFacetedMin8[0]) !== null && _column$getFacetedMin7 !== void 0 ? _column$getFacetedMin7 : ''),
37
+ max: Number((_column$getFacetedMin9 = (_column$getFacetedMin10 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin10 === void 0 ? void 0 : _column$getFacetedMin10[1]) !== null && _column$getFacetedMin9 !== void 0 ? _column$getFacetedMin9 : ''),
38
+ value: (_2 = columnFilterValue === null || columnFilterValue === void 0 ? void 0 : columnFilterValue[1]) !== null && _2 !== void 0 ? _2 : '',
39
+ onChange: function onChange(value) {
40
+ return column.setFilterValue(function (old) {
41
+ return [old === null || old === void 0 ? void 0 : old[0], value];
42
+ });
43
+ },
44
+ placeholder: "Max ".concat((_column$getFacetedMin11 = column.getFacetedMinMaxValues()) !== null && _column$getFacetedMin11 !== void 0 && _column$getFacetedMin11[1] ? "(".concat((_column$getFacetedMin12 = column.getFacetedMinMaxValues()) === null || _column$getFacetedMin12 === void 0 ? void 0 : _column$getFacetedMin12[1], ")") : '')
45
+ })]
46
+ }) : /*#__PURE__*/jsx(DebouncedInput, {
47
+ type: "text",
48
+ values: sortedUniqueValues,
49
+ value: columnFilterValue !== null && columnFilterValue !== void 0 ? columnFilterValue : '',
50
+ onChange: function onChange(value) {
51
+ return column.setFilterValue(value);
52
+ },
53
+ placeholder: "Search (".concat(column.getFacetedUniqueValues().size, ")"),
54
+ list: column.id + 'list'
55
+ });
56
+ }
57
+
58
+ export { Filter };
@@ -0,0 +1,32 @@
1
+ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
+ import { flexRender } from '@tanstack/react-table';
3
+ import { Table, Typography } from '@equinor/eds-core-react';
4
+ import { useTableContext } from '../EdsDataGridContext.js';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ function TableBodyCell(_ref) {
8
+ var _cellStyle;
9
+ var cell = _ref.cell;
10
+ var _useTableContext = useTableContext(),
11
+ cellClass = _useTableContext.cellClass,
12
+ cellStyle = _useTableContext.cellStyle;
13
+ return /*#__PURE__*/jsx(Table.Cell, {
14
+ className: cellClass ? cellClass(cell.row, cell.column.id) : '',
15
+ key: cell.id,
16
+ style: _objectSpread({
17
+ width: cell.column.getSize(),
18
+ maxWidth: cell.column.getSize(),
19
+ overflow: 'hidden',
20
+ whiteSpace: 'nowrap',
21
+ textOverflow: 'ellipsis'
22
+ }, (_cellStyle = cellStyle === null || cellStyle === void 0 ? void 0 : cellStyle(cell.row, cell.column.id)) !== null && _cellStyle !== void 0 ? _cellStyle : {}),
23
+ children: /*#__PURE__*/jsx(Typography, {
24
+ as: "span",
25
+ group: "table",
26
+ variant: "cell_text",
27
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
28
+ })
29
+ });
30
+ }
31
+
32
+ export { TableBodyCell };
@@ -0,0 +1,97 @@
1
+ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
+ import { flexRender } from '@tanstack/react-table';
3
+ import { Table, Icon } from '@equinor/eds-core-react';
4
+ import { arrow_up, arrow_down } from '@equinor/eds-icons';
5
+ import { useTableContext } from '../EdsDataGridContext.js';
6
+ import { Filter } from './Filter.js';
7
+ import styled from 'styled-components';
8
+ import { tokens } from '@equinor/eds-tokens';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+
11
+ var getSortLabel = function getSortLabel(sorted) {
12
+ if (sorted) {
13
+ return "".concat(sorted, "ending");
14
+ }
15
+ return 'none';
16
+ };
17
+ var Resizer = styled.div.withConfig({
18
+ displayName: "TableHeaderCell__Resizer",
19
+ componentId: "sc-1n0j3v0-0"
20
+ })(["transform:", ";opacity:", ";position:absolute;right:0;top:0;height:100%;width:5px;cursor:col-resize;user-select:none;touch-action:none;"], function (props) {
21
+ return props.columnResizeMode === 'onEnd' ? 'translateX(0px)' : 'none';
22
+ }, function (props) {
23
+ return props.isResizing ? 1 : 0;
24
+ });
25
+ var Cell = styled(Table.Cell).withConfig({
26
+ displayName: "TableHeaderCell__Cell",
27
+ componentId: "sc-1n0j3v0-1"
28
+ })(["font-weight:bold;height:30px;position:", ";&:hover ", "{background:", ";opacity:1;}"], function (p) {
29
+ return p.sticky ? 'sticky' : 'relative';
30
+ }, Resizer, tokens.colors.interactive.primary__hover.rgba);
31
+ function TableHeaderCell(_ref) {
32
+ var _asc$desc;
33
+ var header = _ref.header,
34
+ columnResizeMode = _ref.columnResizeMode;
35
+ var ctx = useTableContext();
36
+ var table = ctx.table;
37
+ return header.isPlaceholder ? /*#__PURE__*/jsx(Cell, {
38
+ sticky: ctx.stickyHeader,
39
+ className: ctx.headerClass ? ctx.headerClass(header.column) : '',
40
+ style: ctx.headerStyle ? ctx.headerStyle(header.column) : {},
41
+ "aria-hidden": true
42
+ }) : /*#__PURE__*/jsxs(Cell, {
43
+ sticky: ctx.stickyHeader,
44
+ className: ctx.headerClass ? ctx.headerClass(header.column) : '',
45
+ "aria-sort": getSortLabel(header.column.getIsSorted()),
46
+ onClick: header.column.getToggleSortingHandler(),
47
+ key: header.id,
48
+ colSpan: header.colSpan,
49
+ style: _objectSpread({
50
+ width: header.getSize(),
51
+ verticalAlign: ctx.enableColumnFiltering ? 'baseline' : 'middle'
52
+ }, ctx.headerStyle ? ctx.headerStyle(header.column) : {}),
53
+ children: [/*#__PURE__*/jsxs(Fragment, {
54
+ children: [/*#__PURE__*/jsxs("div", {
55
+ style: {
56
+ display: 'flex',
57
+ flexDirection: 'column'
58
+ },
59
+ children: [/*#__PURE__*/jsx("span", {
60
+ className: "table-header-cell-label",
61
+ children: flexRender(header.column.columnDef.header, header.getContext())
62
+ }), header.column.getCanFilter() ?
63
+ /*#__PURE__*/
64
+ // Supressing this warning - div is not interactive, but prevents propagation of events to avoid unintended sorting
65
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
66
+ jsx("div", {
67
+ onClick: function onClick(e) {
68
+ return e.stopPropagation();
69
+ },
70
+ children: /*#__PURE__*/jsx(Filter, {
71
+ column: header.column,
72
+ table: table
73
+ })
74
+ }) : null]
75
+ }), (_asc$desc = {
76
+ asc: /*#__PURE__*/jsx(Icon, {
77
+ data: arrow_up
78
+ }),
79
+ desc: /*#__PURE__*/jsx(Icon, {
80
+ data: arrow_down
81
+ })
82
+ }[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
83
+ }), columnResizeMode && /*#__PURE__*/jsx(Resizer, {
84
+ onClick: function onClick(e) {
85
+ return e.stopPropagation();
86
+ },
87
+ onMouseDown: header.getResizeHandler(),
88
+ onTouchStart: header.getResizeHandler(),
89
+ isResizing: header.column.getIsResizing(),
90
+ columnResizeMode: columnResizeMode,
91
+ className: 'resize-handle',
92
+ "data-testid": 'resize-handle'
93
+ })]
94
+ });
95
+ }
96
+
97
+ export { TableHeaderCell };
@@ -0,0 +1,22 @@
1
+ import { Table } from '@equinor/eds-core-react';
2
+ import { TableHeaderCell } from './TableHeaderCell.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ function TableHeaderRow(_ref) {
6
+ var headerGroup = _ref.headerGroup,
7
+ columnResizeMode = _ref.columnResizeMode,
8
+ deltaOffset = _ref.deltaOffset,
9
+ table = _ref.table;
10
+ return /*#__PURE__*/jsx(Table.Row, {
11
+ children: headerGroup.headers.map(function (header) {
12
+ return /*#__PURE__*/jsx(TableHeaderCell, {
13
+ header: header,
14
+ table: table,
15
+ columnResizeMode: columnResizeMode,
16
+ deltaOffset: deltaOffset
17
+ }, header.id);
18
+ })
19
+ });
20
+ }
21
+
22
+ export { TableHeaderRow };
@@ -0,0 +1,29 @@
1
+ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
2
+ import { Table } from '@equinor/eds-core-react';
3
+ import { TableBodyCell } from './TableBodyCell.js';
4
+ import { useTableContext } from '../EdsDataGridContext.js';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ function TableRow(_ref) {
8
+ var _rowStyle;
9
+ var row = _ref.row;
10
+ var _useTableContext = useTableContext(),
11
+ rowClass = _useTableContext.rowClass,
12
+ rowStyle = _useTableContext.rowStyle;
13
+ return /*#__PURE__*/jsx(Table.Row, {
14
+ style: _objectSpread({
15
+ cursor: row.getCanSelect() ? 'pointer' : 'inherit'
16
+ }, (_rowStyle = rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle(row)) !== null && _rowStyle !== void 0 ? _rowStyle : {}),
17
+ className: "".concat(row.getIsSelected() ? 'selected' : '', " ").concat(rowClass === null || rowClass === void 0 ? void 0 : rowClass(row)),
18
+ onClick: function onClick() {
19
+ return row.getCanSelect() ? row.toggleSelected() : null;
20
+ },
21
+ children: row.getVisibleCells().map(function (cell) {
22
+ return /*#__PURE__*/jsx(TableBodyCell, {
23
+ cell: cell
24
+ }, cell.id);
25
+ })
26
+ });
27
+ }
28
+
29
+ export { TableRow };
@@ -0,0 +1 @@
1
+ export { EdsDataGrid } from './EdsDataGrid.js';
@@ -0,0 +1,133 @@
1
+ import { Column, ColumnDef, ColumnResizeMode, OnChangeFn, Row, RowSelectionState } from '@tanstack/react-table';
2
+ import { CSSProperties, ReactElement } from 'react';
3
+ export type EdsDataGridProps<T> = {
4
+ /**
5
+ * The rows to display in the table
6
+ */
7
+ rows: Array<T>;
8
+ /**
9
+ * Definition of the columns to display in the table
10
+ */
11
+ columns: ColumnDef<T>[];
12
+ /**
13
+ * The mode of column resizing. If not set, column resizing is disabled.
14
+ * Can be either 'onChange' or 'onEnd'
15
+ * @default undefined
16
+ */
17
+ columnResizeMode?: ColumnResizeMode;
18
+ /**
19
+ * Set this to enable rowSelection. If a function is provided, it will be called for each row to determine if it is selectable.
20
+ * @default false
21
+ */
22
+ rowSelection?: boolean | ((row: Row<T>) => boolean);
23
+ /**
24
+ * Callback for when row-selection changes
25
+ */
26
+ onSelectRow?: OnChangeFn<RowSelectionState>;
27
+ /**
28
+ * Enable debug mode. See https://tanstack.com/table/v8/docs/api/core/table#debugall
29
+ * @default false
30
+ */
31
+ debug?: boolean;
32
+ /**
33
+ * Enable sorting.
34
+ * @default false
35
+ */
36
+ enableSorting?: boolean;
37
+ /**
38
+ * Make the table header sticky
39
+ * @default false
40
+ */
41
+ stickyHeader?: boolean;
42
+ /**
43
+ * Element to display in Table.Caption
44
+ * @default undefined
45
+ */
46
+ caption?: ReactElement;
47
+ /**
48
+ * Whether to enable column filtering, adding inputs to the header cells
49
+ * Individual columns can be configured to disable filtering
50
+ * @default false
51
+ */
52
+ enableColumnFiltering?: boolean;
53
+ /**
54
+ * Whether pagination should be enabled.
55
+ * @default false
56
+ */
57
+ enablePagination?: boolean;
58
+ /**
59
+ * The number of rows per page
60
+ * Only used if enablePagination is true
61
+ * @default 25
62
+ */
63
+ pageSize?: number;
64
+ /**
65
+ * The message to display when there are no rows
66
+ * @default undefined
67
+ */
68
+ emptyMessage?: string;
69
+ /**
70
+ * The currently selected rows
71
+ * @default {}
72
+ */
73
+ selectedRows?: Record<string | number, boolean>;
74
+ /**
75
+ * Whether to enable virtualization. This will render only the visible rows currently in view.
76
+ * @default false
77
+ */
78
+ enableVirtual?: boolean;
79
+ /**
80
+ * The height of the virtualized table in pixels.
81
+ * @default 500
82
+ */
83
+ virtualHeight?: number;
84
+ /**
85
+ * Which columns are visible. If not set, all columns are visible. undefined means that the column is visible.
86
+ * @default undefined
87
+ */
88
+ columnVisibility?: Record<string, boolean>;
89
+ /**
90
+ * Callback for when column visibility changes. Only called if columnVisibility is set.
91
+ * @param columnVisibility
92
+ */
93
+ columnVisibilityChange?: (columnVisibility: Record<string, boolean>) => void;
94
+ /**
95
+ * An array of the columnIds in the order they should be displayed.
96
+ */
97
+ columnOrder?: Array<string>;
98
+ /**
99
+ * Function that can be used to set custom css on a cell
100
+ * @param row
101
+ * @param columnId
102
+ */
103
+ cellStyle?: (row: Row<T>, columnId: string) => CSSProperties;
104
+ /**
105
+ * Function that can be used to set a custom class on a cell
106
+ * @param row
107
+ * @param columnId
108
+ * @returns string with list of classes
109
+ */
110
+ cellClass?: (row: Row<T>, columnId: string) => string;
111
+ /**
112
+ * Function that can be used to set a custom class on a row
113
+ * @param row
114
+ * @returns string with list of classes
115
+ */
116
+ rowClass?: (row: Row<T>) => string;
117
+ /**
118
+ * Function that can be used to set custom css on a row
119
+ * @param row
120
+ */
121
+ rowStyle?: (row: Row<T>) => CSSProperties;
122
+ /**
123
+ * Function that can be used to set custom classes on a header cell
124
+ * @param column
125
+ */
126
+ headerClass?: (column: Column<T>) => string;
127
+ /**
128
+ * Function that can be used to set custom styles on a header cell
129
+ * @param column
130
+ */
131
+ headerStyle?: (column: Column<T>) => CSSProperties;
132
+ };
133
+ export declare function EdsDataGrid<T>({ rows, columns, columnResizeMode, pageSize, rowSelection, selectedRows, enableColumnFiltering, debug, enablePagination, enableSorting, stickyHeader, onSelectRow, caption, enableVirtual, virtualHeight, columnVisibility, columnVisibilityChange, emptyMessage, columnOrder, cellClass, cellStyle, rowClass, rowStyle, headerClass, headerStyle, }: EdsDataGridProps<T>): JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { CSSProperties, ReactElement } from 'react';
2
+ import { Column, Row, Table as TanStackTable } from '@tanstack/react-table';
3
+ type Context<T> = {
4
+ enableSorting: boolean;
5
+ stickyHeader: boolean;
6
+ enableColumnFiltering: boolean;
7
+ table: TanStackTable<T> | null;
8
+ cellClass?: (row: Row<T>, columnId: string) => string;
9
+ rowClass?: (row: Row<T>) => string;
10
+ cellStyle?: (row: Row<T>, columnId: string) => CSSProperties;
11
+ rowStyle?: (row: Row<T>) => CSSProperties;
12
+ headerClass?: (column: Column<T>) => string;
13
+ headerStyle?: (column: Column<T>) => CSSProperties;
14
+ };
15
+ export declare const EdsDataGridContext: import("react").Context<Context<any>>;
16
+ export declare function TableProvider<T>({ children, ...props }: Context<T> & {
17
+ children: ReactElement | Array<ReactElement>;
18
+ }): JSX.Element;
19
+ export declare const useTableContext: () => Context<any>;
20
+ export {};
@@ -0,0 +1,9 @@
1
+ import { InputHTMLAttributes } from 'react';
2
+ type Value = string | number | Array<string | number>;
3
+ export declare function DebouncedInput({ value: initialValue, values, onChange, debounce, ...props }: {
4
+ value: Value;
5
+ values: Array<string | number>;
6
+ onChange: (value: Value) => void;
7
+ debounce?: number;
8
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>): JSX.Element;
9
+ export {};
@@ -0,0 +1,7 @@
1
+ import { Column, Table as TanStackTable } from '@tanstack/react-table';
2
+ type FilterProps<T = unknown> = {
3
+ column: Column<T>;
4
+ table: TanStackTable<T>;
5
+ };
6
+ export declare function Filter<T = unknown>({ column, table }: FilterProps<T>): JSX.Element;
7
+ export {};
@@ -0,0 +1,6 @@
1
+ import { Cell } from '@tanstack/react-table';
2
+ type Props<T> = {
3
+ cell: Cell<T, unknown>;
4
+ };
5
+ export declare function TableBodyCell<T>({ cell }: Props<T>): JSX.Element;
6
+ export {};
@@ -0,0 +1,9 @@
1
+ import { ColumnResizeMode, Header, Table as TanStackTable } from '@tanstack/react-table';
2
+ type Props<T> = {
3
+ header: Header<T, unknown>;
4
+ columnResizeMode: ColumnResizeMode | null | undefined;
5
+ deltaOffset: number | null;
6
+ table: TanStackTable<T>;
7
+ };
8
+ export declare function TableHeaderCell<T>({ header, columnResizeMode }: Props<T>): JSX.Element;
9
+ export {};
@@ -0,0 +1,9 @@
1
+ import { ColumnResizeMode, HeaderGroup, Table as TanStackTable } from '@tanstack/react-table';
2
+ type Props<T> = {
3
+ headerGroup: HeaderGroup<T>;
4
+ columnResizeMode?: ColumnResizeMode | null;
5
+ deltaOffset: number | null;
6
+ table: TanStackTable<T>;
7
+ };
8
+ export declare function TableHeaderRow<T>({ headerGroup, columnResizeMode, deltaOffset, table, }: Props<T>): JSX.Element;
9
+ export {};
@@ -0,0 +1,7 @@
1
+ import { Row } from '@tanstack/react-table';
2
+ import { HTMLAttributes } from 'react';
3
+ type Props<T> = {
4
+ row: Row<T>;
5
+ } & HTMLAttributes<HTMLTableRowElement>;
6
+ export declare function TableRow<T>({ row }: Props<T>): JSX.Element;
7
+ export {};
@@ -0,0 +1 @@
1
+ export * from './EdsDataGrid';
@@ -0,0 +1,10 @@
1
+ import { ColumnDef } from '@tanstack/react-table';
2
+ type Data = {
3
+ qty: number;
4
+ cargoId: string;
5
+ status: string;
6
+ parcels: Array<string>;
7
+ carrier: string;
8
+ };
9
+ export declare const columns: Array<ColumnDef<Data>>;
10
+ export {};
@@ -0,0 +1,8 @@
1
+ export type Data = {
2
+ qty: number;
3
+ cargoId: string;
4
+ status: string;
5
+ parcels: Array<string>;
6
+ carrier: string;
7
+ };
8
+ export declare const data: Data[];
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@equinor/eds-data-grid-react",
3
+ "version": "0.0.1",
4
+ "description": "A feature-rich data-grid written in React, implementing the Equinor Design System",
5
+ "license": "MIT",
6
+ "exports": "./dist/esm/index.js",
7
+ "type": "module",
8
+ "types": "dist/types/index.d.ts",
9
+ "files": [
10
+ "dist/*"
11
+ ],
12
+ "author": {
13
+ "name": "EDS Core Team",
14
+ "email": "fg_eds@equinor.com"
15
+ },
16
+ "peerDependencies": {
17
+ "react": ">=16.8",
18
+ "react-dom": ">=16.8",
19
+ "styled-components": ">=4.2"
20
+ },
21
+ "dependencies": {
22
+ "@tanstack/react-table": "^8.8.5",
23
+ "@tanstack/react-virtual": "^3.0.0-beta.54",
24
+ "@equinor/eds-core-react": "0.32.0",
25
+ "@equinor/eds-tokens": "0.9.2",
26
+ "@equinor/eds-icons": "0.19.2",
27
+ "@equinor/eds-utils": "0.8.0"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "~4.9.5",
31
+ "ts-jest": "29.0.5",
32
+ "ts-node": "10.9.1",
33
+ "@types/node": "18.14.2",
34
+ "jest": "29.4.3",
35
+ "jest-environment-jsdom": "29.4.3",
36
+ "@testing-library/jest-dom": "^5.16.5",
37
+ "@testing-library/react": "14.0.0",
38
+ "@testing-library/user-event": "^14.4.3",
39
+ "react": "^18.2.0",
40
+ "react-dom": "^18.2.0",
41
+ "@types/jest": "^29.5.0",
42
+ "@types/react": "^18.0.21",
43
+ "@types/react-dom": "^18.0.10",
44
+ "@types/styled-components": "^5.1.26",
45
+ "rollup": "^3.25.1",
46
+ "rollup-plugin-delete": "^2.0.0",
47
+ "rollup-plugin-postcss": "^4.0.2",
48
+ "storybook": "^7.0.11",
49
+ "styled-components": "5.3.9",
50
+ "@mdx-js/react": "1.6.22",
51
+ "@rollup/plugin-babel": "^6.0.3",
52
+ "@rollup/plugin-commonjs": "^25.0.1",
53
+ "@rollup/plugin-node-resolve": "^15.1.0",
54
+ "@storybook/addon-a11y": "^7.0.11",
55
+ "@storybook/addon-actions": "^7.0.11",
56
+ "@storybook/addon-docs": "^7.0.11",
57
+ "@storybook/addon-essentials": "^7.0.11",
58
+ "@storybook/addon-links": "^7.0.11",
59
+ "@storybook/blocks": "^7.0.11",
60
+ "@storybook/builder-vite": "^7.0.11",
61
+ "@storybook/client-api": "^7.0.11",
62
+ "@storybook/react": "^7.0.11",
63
+ "@storybook/react-vite": "^7.0.11",
64
+ "@testing-library/dom": "^9.2.0",
65
+ "@types/ramda": "^0.28.24",
66
+ "@types/testing-library__jest-dom": "^5.14.5",
67
+ "babel-loader": "^9.1.2",
68
+ "babel-plugin-styled-components": "^2.1.1",
69
+ "jest-styled-components": "^7.1.1",
70
+ "js-file-download": "^0.4.12",
71
+ "postcss": "^8.4.21",
72
+ "ramda": "^0.29.0",
73
+ "react-hook-form": "^7.43.9",
74
+ "remark-gfm": "^3.0.1",
75
+ "tsc-watch": "^6.0.0"
76
+ },
77
+ "homepage": "https://eds.equinor.com",
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "https://github.com/equinor/design-system",
81
+ "directory": "packages/eds-core-react"
82
+ },
83
+ "bugs": {
84
+ "url": "https://github.com/equinor/design-system/issues"
85
+ },
86
+ "keywords": [
87
+ "eds",
88
+ "design system",
89
+ "equinor",
90
+ "react",
91
+ "data grid"
92
+ ],
93
+ "engines": {
94
+ "pnpm": ">=4",
95
+ "node": ">=10.0.0"
96
+ },
97
+ "browserslist": "defaults, not IE 11",
98
+ "scripts": {
99
+ "build": "rollup -c --bundleConfigAsCjs && tsc -p tsconfig.build.json",
100
+ "test": "tsc -p tsconfig.spec.json && jest",
101
+ "test:watch": "tsc-watch -p tsconfig.test.json --onFirstSuccess \"jest --watch\"",
102
+ "test:update-snapshots": "jest --updateSnapshot",
103
+ "storybook": "storybook dev -p 9000 --ci",
104
+ "build:storybook": "storybook build -o storybook-build",
105
+ "types": "tsc -p tsconfig.build.json"
106
+ }
107
+ }