@cdc/editor 4.22.10-alpha.1 → 4.22.11
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 +8 -7
- package/dist/cdceditor.js +42 -42
- package/example/data-horizontal-filters.json +5 -6
- package/example/data-horizontal-multiseries-filters.json +13 -15
- package/example/data-horizontal-multiseries.json +4 -5
- package/example/data-horizontal.json +2 -3
- package/example/data-vertical-filters.json +7 -8
- package/example/data-vertical-multiseries-filters.json +13 -15
- package/example/data-vertical-multiseries-multirow-filters.json +49 -52
- package/example/data-vertical-multiseries-multirow.json +11 -11
- package/example/data-vertical-multiseries.json +4 -5
- package/example/data-vertical.json +4 -5
- package/example/private/city-state.json +434 -0
- package/example/private/example-city-state.json +86 -0
- package/example/private/map-issue.csv +11 -0
- package/example/private/test.html +26 -1
- package/example/region-map.json +32 -32
- package/example/valid-county-data.json +3047 -3047
- package/package.json +8 -8
- package/src/CdcEditor.js +72 -72
- package/src/components/ChooseTab.js +67 -88
- package/src/components/ConfigureTab.js +51 -51
- package/src/components/DataImport.js +248 -246
- package/src/components/PreviewDataTable.js +130 -149
- package/src/components/TabPane.js +3 -3
- package/src/components/Tabs.js +20 -27
- package/src/components/modal/Confirmation.js +16 -13
- package/src/components/modal/Modal.js +23 -35
- package/src/components/modal/UseModal.js +8 -8
- package/src/context.js +4 -4
- package/src/index.html +1 -4
- package/src/index.js +6 -7
- package/src/scss/_data-table.scss +1 -1
- package/src/scss/_variables.scss +1 -1
- package/src/scss/choose-vis-tab.scss +63 -63
- package/src/scss/configure-tab.scss +17 -17
- package/src/scss/data-import.scss +177 -177
- package/src/scss/main.scss +31 -32
|
@@ -1,121 +1,105 @@
|
|
|
1
|
-
import React, { useState, useContext, useMemo, useCallback, useEffect, memo } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
useGlobalFilter,
|
|
6
|
-
useSortBy,
|
|
7
|
-
useResizeColumns,
|
|
8
|
-
usePagination
|
|
9
|
-
} from 'react-table';
|
|
10
|
-
import GlobalState from '../context';
|
|
11
|
-
import { useDebounce } from 'use-debounce';
|
|
1
|
+
import React, { useState, useContext, useMemo, useCallback, useEffect, memo } from 'react'
|
|
2
|
+
import { useTable, useBlockLayout, useGlobalFilter, useSortBy, useResizeColumns, usePagination } from 'react-table'
|
|
3
|
+
import GlobalState from '../context'
|
|
4
|
+
import { useDebounce } from 'use-debounce'
|
|
12
5
|
|
|
13
6
|
// Core
|
|
14
|
-
import validateFipsCodeLength from '@cdc/core/helpers/validateFipsCodeLength'
|
|
7
|
+
import validateFipsCodeLength from '@cdc/core/helpers/validateFipsCodeLength'
|
|
15
8
|
|
|
16
|
-
const TableFilter = memo(({globalFilter, setGlobalFilter, disabled = false}) => {
|
|
17
|
-
const [filterValue, setFilterValue
|
|
9
|
+
const TableFilter = memo(({ globalFilter, setGlobalFilter, disabled = false }) => {
|
|
10
|
+
const [filterValue, setFilterValue] = useState(globalFilter)
|
|
18
11
|
|
|
19
|
-
const [
|
|
12
|
+
const [debouncedValue] = useDebounce(filterValue, 200)
|
|
20
13
|
|
|
21
14
|
useEffect(() => {
|
|
22
|
-
if('string' === typeof debouncedValue && debouncedValue !== globalFilter
|
|
15
|
+
if ('string' === typeof debouncedValue && debouncedValue !== globalFilter) {
|
|
23
16
|
setGlobalFilter(debouncedValue ?? '')
|
|
24
17
|
}
|
|
25
18
|
}, [debouncedValue])
|
|
26
19
|
|
|
27
|
-
const onChange =
|
|
28
|
-
setFilterValue(e.target.value)
|
|
20
|
+
const onChange = e => {
|
|
21
|
+
setFilterValue(e.target.value)
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
className="filter"
|
|
34
|
-
value={filterValue}
|
|
35
|
-
onChange={onChange}
|
|
36
|
-
type="search"
|
|
37
|
-
placeholder='Filter...'
|
|
38
|
-
disabled={disabled}
|
|
39
|
-
/>
|
|
40
|
-
)
|
|
41
|
-
});
|
|
24
|
+
return <input className='filter' value={filterValue} onChange={onChange} type='search' placeholder='Filter...' disabled={disabled} />
|
|
25
|
+
})
|
|
42
26
|
|
|
43
|
-
const Header = memo(({ globalFilter, data, setGlobalFilter}) => (
|
|
44
|
-
<header className=
|
|
27
|
+
const Header = memo(({ globalFilter, data, setGlobalFilter }) => (
|
|
28
|
+
<header className='data-table-header'>
|
|
45
29
|
<h2>Data Preview</h2>
|
|
46
30
|
<TableFilter globalFilter={globalFilter || ''} setGlobalFilter={setGlobalFilter} disabled={null === data} />
|
|
47
31
|
</header>
|
|
48
32
|
))
|
|
49
33
|
|
|
50
|
-
const Footer = memo(({previousPage, nextPage, canPreviousPage, canNextPage, pageNumber, totalPages}) => (
|
|
51
|
-
<footer className=
|
|
34
|
+
const Footer = memo(({ previousPage, nextPage, canPreviousPage, canNextPage, pageNumber, totalPages }) => (
|
|
35
|
+
<footer className='data-table-pagination'>
|
|
52
36
|
<ul>
|
|
53
37
|
<li>
|
|
54
|
-
<button onClick={() => previousPage()} className=
|
|
38
|
+
<button onClick={() => previousPage()} className='btn btn-prev' disabled={!canPreviousPage} title='Previous Page'></button>
|
|
55
39
|
</li>
|
|
56
40
|
<li>
|
|
57
|
-
<button onClick={() => nextPage()} className=
|
|
41
|
+
<button onClick={() => nextPage()} className='btn btn-next' disabled={!canNextPage} title='Next Page'></button>
|
|
58
42
|
</li>
|
|
59
43
|
</ul>
|
|
60
44
|
<span>
|
|
61
|
-
Page
|
|
45
|
+
Page {pageNumber} of {totalPages}
|
|
62
46
|
</span>
|
|
63
47
|
</footer>
|
|
64
48
|
))
|
|
65
49
|
|
|
66
50
|
const PreviewDataTable = ({ data }) => {
|
|
67
|
-
const [tableData, setTableData] = useState(data ?? [])
|
|
68
|
-
const {setErrors, errorMessages, config} = useContext(GlobalState)
|
|
51
|
+
const [tableData, setTableData] = useState(data ?? [])
|
|
52
|
+
const { setErrors, errorMessages, config } = useContext(GlobalState)
|
|
69
53
|
|
|
70
54
|
const tableColumns = useMemo(() => {
|
|
71
|
-
const columns = tableData.columns ?? []
|
|
72
|
-
if (
|
|
55
|
+
const columns = tableData.columns ?? []
|
|
56
|
+
if (columns.length > 0 && columns.includes('')) {
|
|
73
57
|
// todo find a way to call the errors. Currently they are in DataImport.js
|
|
74
58
|
// maybe these can be moved to a file? but then we need a way to add settings like size...
|
|
75
|
-
setErrors([errorMessages.emptyCols])
|
|
59
|
+
setErrors([errorMessages.emptyCols])
|
|
76
60
|
}
|
|
77
|
-
|
|
78
|
-
return columns.map((columnName, idx) => {
|
|
79
|
-
const columnConfig = {
|
|
80
|
-
id: `column-${columnName}`,
|
|
81
|
-
accessor: row => row[columnName],
|
|
82
|
-
Header: columnName,
|
|
83
|
-
width: 250
|
|
84
|
-
};
|
|
85
61
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
return columns.map((columnName, idx) => {
|
|
63
|
+
const columnConfig = {
|
|
64
|
+
id: `column-${columnName}`,
|
|
65
|
+
accessor: row => row[columnName],
|
|
66
|
+
Header: columnName,
|
|
67
|
+
width: 250
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return columnConfig
|
|
71
|
+
})
|
|
72
|
+
}, [tableData])
|
|
89
73
|
|
|
90
74
|
// This adds a columns property just like the D3 function for JSON parsing.
|
|
91
|
-
const generateColumns = useCallback(
|
|
75
|
+
const generateColumns = useCallback(data => {
|
|
92
76
|
let columns = []
|
|
93
77
|
|
|
94
|
-
data.forEach(
|
|
95
|
-
Object.keys(rowObj).forEach(
|
|
96
|
-
if(false === columns.includes(columnHeading)) {
|
|
78
|
+
data.forEach(rowObj => {
|
|
79
|
+
Object.keys(rowObj).forEach(columnHeading => {
|
|
80
|
+
if (false === columns.includes(columnHeading)) {
|
|
97
81
|
columns.push(columnHeading)
|
|
98
82
|
}
|
|
99
83
|
})
|
|
100
84
|
})
|
|
101
85
|
|
|
102
86
|
// D3 uses a weird quirk where it attaches a named property to an array. Replicating here.
|
|
103
|
-
const newData = [...data]
|
|
87
|
+
const newData = [...data]
|
|
104
88
|
|
|
105
|
-
if(Array.isArray(newData)) {
|
|
106
|
-
newData.columns = columns
|
|
107
|
-
return newData
|
|
89
|
+
if (Array.isArray(newData)) {
|
|
90
|
+
newData.columns = columns
|
|
91
|
+
return newData
|
|
108
92
|
}
|
|
109
93
|
}, [])
|
|
110
94
|
|
|
111
95
|
useEffect(() => {
|
|
112
|
-
if(!data) {
|
|
113
|
-
return
|
|
96
|
+
if (!data) {
|
|
97
|
+
return
|
|
114
98
|
}
|
|
115
99
|
|
|
116
|
-
let newData = [...data]
|
|
100
|
+
let newData = [...data]
|
|
117
101
|
|
|
118
|
-
newData = generateColumns(newData)
|
|
102
|
+
newData = generateColumns(newData)
|
|
119
103
|
validateFipsCodeLength(newData)
|
|
120
104
|
setTableData(newData)
|
|
121
105
|
}, [data, generateColumns])
|
|
@@ -132,11 +116,11 @@ const PreviewDataTable = ({ data }) => {
|
|
|
132
116
|
canNextPage,
|
|
133
117
|
pageOptions,
|
|
134
118
|
nextPage,
|
|
135
|
-
previousPage
|
|
136
|
-
} = useTable({ columns: tableColumns, data: tableData, initialState: { pageSize: 25 } }, useBlockLayout, useGlobalFilter, useSortBy, useResizeColumns, usePagination)
|
|
119
|
+
previousPage
|
|
120
|
+
} = useTable({ columns: tableColumns, data: tableData, initialState: { pageSize: 25 } }, useBlockLayout, useGlobalFilter, useSortBy, useResizeColumns, usePagination)
|
|
137
121
|
|
|
138
122
|
const NoData = () => (
|
|
139
|
-
<section className=
|
|
123
|
+
<section className='no-data-message'>
|
|
140
124
|
<section>
|
|
141
125
|
<h3>No Data</h3>
|
|
142
126
|
<p>Import data to preview</p>
|
|
@@ -146,121 +130,118 @@ const PreviewDataTable = ({ data }) => {
|
|
|
146
130
|
|
|
147
131
|
const PlaceholderTable = () => {
|
|
148
132
|
return (
|
|
149
|
-
<section className=
|
|
133
|
+
<section className='no-data'>
|
|
150
134
|
<NoData />
|
|
151
|
-
<div className=
|
|
152
|
-
<table className=
|
|
153
|
-
|
|
154
|
-
<tr role=
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
135
|
+
<div className='table-container'>
|
|
136
|
+
<table className='editor data-table' role='table'>
|
|
137
|
+
<thead>
|
|
138
|
+
<tr role='row'>
|
|
139
|
+
<th scope='col' colSpan='1' role='columnheader'></th>
|
|
140
|
+
<th scope='col' colSpan='1' role='columnheader'></th>
|
|
141
|
+
<th scope='col' colSpan='1' role='columnheader'></th>
|
|
142
|
+
</tr>
|
|
143
|
+
</thead>
|
|
144
|
+
<tbody>
|
|
145
|
+
<tr role='row'>
|
|
146
|
+
<td role='cell'></td>
|
|
147
|
+
<td role='cell'></td>
|
|
148
|
+
<td role='cell'></td>
|
|
149
|
+
</tr>
|
|
150
|
+
<tr role='row'>
|
|
151
|
+
<td role='cell'></td>
|
|
152
|
+
<td role='cell'></td>
|
|
153
|
+
<td role='cell'></td>
|
|
154
|
+
</tr>
|
|
155
|
+
<tr role='row'>
|
|
156
|
+
<td role='cell'></td>
|
|
157
|
+
<td role='cell'></td>
|
|
158
|
+
<td role='cell'></td>
|
|
161
159
|
</tr>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<td role=
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
<td role=
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<td role=
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<td role=
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
<td role=
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
<td role=
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
<td role=
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
<tr role="row">
|
|
200
|
-
<td role="cell"></td>
|
|
201
|
-
<td role="cell"></td>
|
|
202
|
-
<td role="cell"></td>
|
|
203
|
-
</tr>
|
|
204
|
-
<tr role="row">
|
|
205
|
-
<td role="cell"></td>
|
|
206
|
-
<td role="cell"></td>
|
|
207
|
-
<td role="cell"></td>
|
|
208
|
-
</tr>
|
|
209
|
-
<tr role="row">
|
|
210
|
-
<td role="cell"></td>
|
|
211
|
-
<td role="cell"></td>
|
|
212
|
-
<td role="cell"></td>
|
|
213
|
-
</tr>
|
|
214
|
-
</tbody>
|
|
215
|
-
</table>
|
|
160
|
+
<tr role='row'>
|
|
161
|
+
<td role='cell'></td>
|
|
162
|
+
<td role='cell'></td>
|
|
163
|
+
<td role='cell'></td>
|
|
164
|
+
</tr>
|
|
165
|
+
<tr role='row'>
|
|
166
|
+
<td role='cell'></td>
|
|
167
|
+
<td role='cell'></td>
|
|
168
|
+
<td role='cell'></td>
|
|
169
|
+
</tr>
|
|
170
|
+
<tr role='row'>
|
|
171
|
+
<td role='cell'></td>
|
|
172
|
+
<td role='cell'></td>
|
|
173
|
+
<td role='cell'></td>
|
|
174
|
+
</tr>
|
|
175
|
+
<tr role='row'>
|
|
176
|
+
<td role='cell'></td>
|
|
177
|
+
<td role='cell'></td>
|
|
178
|
+
<td role='cell'></td>
|
|
179
|
+
</tr>
|
|
180
|
+
<tr role='row'>
|
|
181
|
+
<td role='cell'></td>
|
|
182
|
+
<td role='cell'></td>
|
|
183
|
+
<td role='cell'></td>
|
|
184
|
+
</tr>
|
|
185
|
+
<tr role='row'>
|
|
186
|
+
<td role='cell'></td>
|
|
187
|
+
<td role='cell'></td>
|
|
188
|
+
<td role='cell'></td>
|
|
189
|
+
</tr>
|
|
190
|
+
<tr role='row'>
|
|
191
|
+
<td role='cell'></td>
|
|
192
|
+
<td role='cell'></td>
|
|
193
|
+
<td role='cell'></td>
|
|
194
|
+
</tr>
|
|
195
|
+
</tbody>
|
|
196
|
+
</table>
|
|
216
197
|
</div>
|
|
217
198
|
</section>
|
|
218
199
|
)
|
|
219
200
|
}
|
|
220
201
|
|
|
221
|
-
if(!data) return [<Header key=
|
|
202
|
+
if (!data) return [<Header key='header' />, <PlaceholderTable key='table' />]
|
|
222
203
|
|
|
223
|
-
const footerProps = {previousPage, nextPage, canPreviousPage, canNextPage, pageNumber: pageIndex + 1, totalPages: pageOptions.length}
|
|
204
|
+
const footerProps = { previousPage, nextPage, canPreviousPage, canNextPage, pageNumber: pageIndex + 1, totalPages: pageOptions.length }
|
|
224
205
|
|
|
225
206
|
const Table = () => (
|
|
226
207
|
<>
|
|
227
|
-
<section className=
|
|
228
|
-
<div className=
|
|
229
|
-
<table className=
|
|
208
|
+
<section className='data-table-container'>
|
|
209
|
+
<div className='table-container'>
|
|
210
|
+
<table className='data-table' {...getTableProps()} aria-hidden='true'>
|
|
230
211
|
<thead>
|
|
231
|
-
{headerGroups.map(
|
|
212
|
+
{headerGroups.map(headerGroup => (
|
|
232
213
|
<tr {...headerGroup.getHeaderGroupProps()}>
|
|
233
|
-
{headerGroup.headers.map(
|
|
234
|
-
<th scope=
|
|
214
|
+
{headerGroup.headers.map(column => (
|
|
215
|
+
<th scope='col' {...column.getHeaderProps(column.getSortByToggleProps())} className={column.isSorted ? (column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc') : ''} title={column.Header}>
|
|
235
216
|
{column.render('Header')}
|
|
236
|
-
<div {...column.getResizerProps()} className=
|
|
217
|
+
<div {...column.getResizerProps()} className='resizer' />
|
|
237
218
|
</th>
|
|
238
219
|
))}
|
|
239
220
|
</tr>
|
|
240
221
|
))}
|
|
241
222
|
</thead>
|
|
242
223
|
<tbody {...getTableBodyProps()}>
|
|
243
|
-
{page.map(
|
|
244
|
-
prepareRow(row)
|
|
224
|
+
{page.map(row => {
|
|
225
|
+
prepareRow(row)
|
|
245
226
|
return (
|
|
246
227
|
<tr {...row.getRowProps()}>
|
|
247
|
-
{row.cells.map(
|
|
228
|
+
{row.cells.map(cell => (
|
|
248
229
|
<td {...cell.getCellProps()} title={cell.value}>
|
|
249
230
|
{cell.render('Cell')}
|
|
250
231
|
</td>
|
|
251
232
|
))}
|
|
252
233
|
</tr>
|
|
253
|
-
)
|
|
234
|
+
)
|
|
254
235
|
})}
|
|
255
236
|
</tbody>
|
|
256
237
|
</table>
|
|
257
238
|
</div>
|
|
258
239
|
</section>
|
|
259
240
|
<Footer {...footerProps} />
|
|
260
|
-
|
|
241
|
+
</>
|
|
261
242
|
)
|
|
262
243
|
|
|
263
|
-
return [<Header key=
|
|
264
|
-
}
|
|
244
|
+
return [<Header key='header' data={data} setGlobalFilter={setGlobalFilter} globalFilter={globalFilter} />, <Table key='table' />]
|
|
245
|
+
}
|
|
265
246
|
|
|
266
|
-
export default PreviewDataTable
|
|
247
|
+
export default PreviewDataTable
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React from 'react'
|
|
2
2
|
|
|
3
|
-
const TabPane = ({ children, className = '' }) => <div className={`tab-content ${className}`}>{children}</div
|
|
3
|
+
const TabPane = ({ children, className = '' }) => <div className={`tab-content ${className}`}>{children}</div>
|
|
4
4
|
|
|
5
|
-
export default TabPane
|
|
5
|
+
export default TabPane
|
package/src/components/Tabs.js
CHANGED
|
@@ -1,62 +1,55 @@
|
|
|
1
|
-
import React, { useState, useContext, useEffect } from 'react'
|
|
1
|
+
import React, { useState, useContext, useEffect } from 'react'
|
|
2
2
|
|
|
3
3
|
const Tabs = ({ children, startingTab = 0, className, changeTab = null }) => {
|
|
4
|
-
const [active, setActive] = useState(startingTab)
|
|
4
|
+
const [active, setActive] = useState(startingTab)
|
|
5
5
|
|
|
6
|
-
let containerClassName = 'tabs'
|
|
6
|
+
let containerClassName = 'tabs'
|
|
7
7
|
|
|
8
|
-
if(className) {
|
|
9
|
-
containerClassName = `tabs ${className}
|
|
8
|
+
if (className) {
|
|
9
|
+
containerClassName = `tabs ${className}`
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const setActiveTab = (disabled, index) => {
|
|
13
|
-
if(false === disabled) {
|
|
13
|
+
if (false === disabled) {
|
|
14
14
|
setActive(index)
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
useEffect(() => {
|
|
19
|
-
if(startingTab > -1) {
|
|
19
|
+
if (startingTab > -1) {
|
|
20
20
|
setActive(startingTab)
|
|
21
21
|
}
|
|
22
22
|
}, [startingTab])
|
|
23
23
|
|
|
24
|
-
const tabs = children.map(({props}, i) => {
|
|
25
|
-
|
|
24
|
+
const tabs = children.map(({ props }, i) => {
|
|
26
25
|
let classes = 'nav-item'
|
|
27
26
|
|
|
28
27
|
let disabled = props.disableRule || false
|
|
29
28
|
|
|
30
|
-
if(disabled) {
|
|
31
|
-
classes += ' disabled'
|
|
29
|
+
if (disabled) {
|
|
30
|
+
classes += ' disabled'
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
if(i === active) {
|
|
35
|
-
classes += ' active'
|
|
33
|
+
if (i === active) {
|
|
34
|
+
classes += ' active'
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
return (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
>
|
|
44
|
-
{props.icon}
|
|
45
|
-
{props.title}
|
|
46
|
-
</li>
|
|
38
|
+
<li onClick={() => setActiveTab(disabled, i)} key={props.title} className={classes}>
|
|
39
|
+
{props.icon}
|
|
40
|
+
{props.title}
|
|
41
|
+
</li>
|
|
47
42
|
)
|
|
48
43
|
})
|
|
49
44
|
|
|
50
45
|
return (
|
|
51
46
|
<>
|
|
52
47
|
<nav className={containerClassName}>
|
|
53
|
-
<ul className=
|
|
54
|
-
{tabs}
|
|
55
|
-
</ul>
|
|
48
|
+
<ul className='nav nav-fill'>{tabs}</ul>
|
|
56
49
|
</nav>
|
|
57
50
|
{children[active]}
|
|
58
51
|
</>
|
|
59
|
-
)
|
|
60
|
-
}
|
|
52
|
+
)
|
|
53
|
+
}
|
|
61
54
|
|
|
62
|
-
export default Tabs
|
|
55
|
+
export default Tabs
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React from 'react'
|
|
2
2
|
|
|
3
|
-
export const ConfirmationModal
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
export const ConfirmationModal = props => {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<p className='message'>{props.message}</p>
|
|
7
|
+
<div className='confirmation-buttons'>
|
|
8
|
+
<div className='btn btn-inline' onClick={props.onCancel}>
|
|
9
|
+
No
|
|
10
|
+
</div>
|
|
11
|
+
<div className='btn btn-inline' onClick={props.onConfirm}>
|
|
12
|
+
Yes
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -1,51 +1,39 @@
|
|
|
1
|
-
import React, { useEffect } from
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
2
|
// import FocusLock from "react-focus-lock";
|
|
3
|
-
import ReactDOM from
|
|
4
|
-
import CloseIcon from '../../assets/icons/close.svg'
|
|
3
|
+
import ReactDOM from 'react-dom'
|
|
4
|
+
import CloseIcon from '../../assets/icons/close.svg'
|
|
5
5
|
|
|
6
|
-
export const Modal = ({
|
|
7
|
-
|
|
8
|
-
hide,
|
|
9
|
-
modalContent,
|
|
10
|
-
headerText
|
|
11
|
-
}) => {
|
|
12
|
-
const onKeyDown = (event) => {
|
|
6
|
+
export const Modal = ({ isShown, hide, modalContent, headerText }) => {
|
|
7
|
+
const onKeyDown = event => {
|
|
13
8
|
if (event.keyCode === 27 && isShown) {
|
|
14
|
-
hide()
|
|
9
|
+
hide()
|
|
15
10
|
}
|
|
16
|
-
}
|
|
11
|
+
}
|
|
17
12
|
|
|
18
13
|
useEffect(() => {
|
|
19
|
-
isShown
|
|
20
|
-
|
|
21
|
-
: (document.body.style.overflow = "unset");
|
|
22
|
-
document.addEventListener("keydown", onKeyDown, false);
|
|
14
|
+
isShown ? (document.body.style.overflow = 'hidden') : (document.body.style.overflow = 'unset')
|
|
15
|
+
document.addEventListener('keydown', onKeyDown, false)
|
|
23
16
|
return () => {
|
|
24
|
-
document.removeEventListener(
|
|
25
|
-
}
|
|
26
|
-
}, [isShown])
|
|
17
|
+
document.removeEventListener('keydown', onKeyDown, false)
|
|
18
|
+
}
|
|
19
|
+
}, [isShown])
|
|
27
20
|
|
|
28
21
|
const modal = (
|
|
29
22
|
<>
|
|
30
|
-
<div className=
|
|
23
|
+
<div className='modal-backdrop' onClick={hide} />
|
|
31
24
|
{/* <FocusLock> */}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
>
|
|
38
|
-
<div className="modal">
|
|
39
|
-
<div className="modal-header">
|
|
40
|
-
<strong>{headerText}</strong>
|
|
41
|
-
<CloseIcon className="modal-close" onClick={hide} />
|
|
42
|
-
</div>
|
|
43
|
-
<div className="modal-content">{modalContent}</div>
|
|
25
|
+
<div className='modal-wrapper' aria-modal aria-labelledby={headerText} tabIndex={-1} role='dialog'>
|
|
26
|
+
<div className='modal'>
|
|
27
|
+
<div className='modal-header'>
|
|
28
|
+
<strong>{headerText}</strong>
|
|
29
|
+
<CloseIcon className='modal-close' onClick={hide} />
|
|
44
30
|
</div>
|
|
31
|
+
<div className='modal-content'>{modalContent}</div>
|
|
45
32
|
</div>
|
|
33
|
+
</div>
|
|
46
34
|
{/* </FocusLock> */}
|
|
47
35
|
</>
|
|
48
|
-
)
|
|
36
|
+
)
|
|
49
37
|
|
|
50
|
-
return isShown ? ReactDOM.createPortal(modal, document.body) : null
|
|
51
|
-
}
|
|
38
|
+
return isShown ? ReactDOM.createPortal(modal, document.body) : null
|
|
39
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useState } from 'react'
|
|
1
|
+
import { useState } from 'react'
|
|
2
2
|
|
|
3
3
|
export const useModal = () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
4
|
+
const [isShown, setIsShown] = useState(false)
|
|
5
|
+
const toggle = () => setIsShown(!isShown)
|
|
6
|
+
return {
|
|
7
|
+
isShown,
|
|
8
|
+
toggle
|
|
9
|
+
}
|
|
10
|
+
}
|
package/src/context.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createContext } from 'react'
|
|
1
|
+
import { createContext } from 'react'
|
|
2
2
|
|
|
3
|
-
const GlobalState = createContext()
|
|
3
|
+
const GlobalState = createContext()
|
|
4
4
|
|
|
5
|
-
GlobalState.displayName = 'GlobalState'
|
|
5
|
+
GlobalState.displayName = 'GlobalState'
|
|
6
6
|
|
|
7
|
-
export default GlobalState
|
|
7
|
+
export default GlobalState
|
package/src/index.html
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
|
-
<meta
|
|
6
|
-
name="viewport"
|
|
7
|
-
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
8
|
-
/>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
9
6
|
<style type="text/css">
|
|
10
7
|
body {
|
|
11
8
|
margin: 0;
|
package/src/index.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import ReactDOM from 'react-dom'
|
|
3
|
-
import CdcEditor from './CdcEditor'
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import ReactDOM from 'react-dom'
|
|
3
|
+
import CdcEditor from './CdcEditor'
|
|
4
4
|
|
|
5
5
|
// Allow URL query to preselect a tab in standalone mode
|
|
6
|
-
const standaloneParams = new URLSearchParams(window.location.search)
|
|
6
|
+
const standaloneParams = new URLSearchParams(window.location.search)
|
|
7
7
|
|
|
8
|
-
let activeTab = Number.parseInt(
|
|
8
|
+
let activeTab = Number.parseInt(standaloneParams.get('active')) - 1 || null
|
|
9
9
|
const domContainer = document.querySelector('.react-container')
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
ReactDOM.render(
|
|
13
12
|
<React.StrictMode>
|
|
14
13
|
<CdcEditor startingTab={activeTab} containerEl={domContainer} />
|
|
15
14
|
</React.StrictMode>,
|
|
16
15
|
document.querySelector('.react-container')
|
|
17
|
-
)
|
|
16
|
+
)
|