@operato/data-grist 9.0.0-beta.7 → 9.0.0-beta.85
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/CHANGELOG.md +285 -0
- package/README.md +337 -44
- package/dist/src/data-grid/data-grid-body.js +39 -27
- package/dist/src/data-grid/data-grid-body.js.map +1 -1
- package/dist/src/data-grid/data-grid-header.js +9 -0
- package/dist/src/data-grid/data-grid-header.js.map +1 -1
- package/dist/src/data-grist.d.ts +13 -1
- package/dist/src/data-grist.js +42 -0
- package/dist/src/data-grist.js.map +1 -1
- package/dist/src/data-report.js +4 -4
- package/dist/src/data-report.js.map +1 -1
- package/dist/src/editors/ox-grist-editor-json5.d.ts +8 -0
- package/dist/src/editors/ox-grist-editor-json5.js +66 -0
- package/dist/src/editors/ox-grist-editor-json5.js.map +1 -0
- package/dist/src/editors/ox-popup-code-input.d.ts +14 -0
- package/dist/src/editors/ox-popup-code-input.js +78 -0
- package/dist/src/editors/ox-popup-code-input.js.map +1 -0
- package/dist/src/editors/registry.js +3 -1
- package/dist/src/editors/registry.js.map +1 -1
- package/dist/src/filters/filter-select.js +2 -1
- package/dist/src/filters/filter-select.js.map +1 -1
- package/dist/src/formatters/registry.d.ts +1 -1
- package/dist/src/gutters/registry.d.ts +1 -1
- package/dist/src/handlers/registry.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -14
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/stories/accumulator-format.stories.d.ts +0 -41
- package/dist/stories/accumulator-format.stories.js +0 -237
- package/dist/stories/accumulator-format.stories.js.map +0 -1
- package/dist/stories/barcode-input-filter.stories.d.ts +0 -33
- package/dist/stories/barcode-input-filter.stories.js +0 -185
- package/dist/stories/barcode-input-filter.stories.js.map +0 -1
- package/dist/stories/bounded-select-filters.stories.d.ts +0 -25
- package/dist/stories/bounded-select-filters.stories.js +0 -283
- package/dist/stories/bounded-select-filters.stories.js.map +0 -1
- package/dist/stories/bounded-select-record.stories.d.ts +0 -25
- package/dist/stories/bounded-select-record.stories.js +0 -286
- package/dist/stories/bounded-select-record.stories.js.map +0 -1
- package/dist/stories/click-event-custom.stories.d.ts +0 -45
- package/dist/stories/click-event-custom.stories.js +0 -248
- package/dist/stories/click-event-custom.stories.js.map +0 -1
- package/dist/stories/click-event.stories.d.ts +0 -45
- package/dist/stories/click-event.stories.js +0 -243
- package/dist/stories/click-event.stories.js.map +0 -1
- package/dist/stories/creatable-only-column.stories.d.ts +0 -29
- package/dist/stories/creatable-only-column.stories.js +0 -232
- package/dist/stories/creatable-only-column.stories.js.map +0 -1
- package/dist/stories/default-filters.stories.d.ts +0 -26
- package/dist/stories/default-filters.stories.js +0 -219
- package/dist/stories/default-filters.stories.js.map +0 -1
- package/dist/stories/dynamic-editable.stories.d.ts +0 -25
- package/dist/stories/dynamic-editable.stories.js +0 -293
- package/dist/stories/dynamic-editable.stories.js.map +0 -1
- package/dist/stories/empty-sorters.stories.d.ts +0 -25
- package/dist/stories/empty-sorters.stories.js +0 -162
- package/dist/stories/empty-sorters.stories.js.map +0 -1
- package/dist/stories/explicit-fetch.stories.d.ts +0 -25
- package/dist/stories/explicit-fetch.stories.js +0 -166
- package/dist/stories/explicit-fetch.stories.js.map +0 -1
- package/dist/stories/fixed-column.stories.d.ts +0 -26
- package/dist/stories/fixed-column.stories.js +0 -383
- package/dist/stories/fixed-column.stories.js.map +0 -1
- package/dist/stories/grid-setting.stories.d.ts +0 -47
- package/dist/stories/grid-setting.stories.js +0 -453
- package/dist/stories/grid-setting.stories.js.map +0 -1
- package/dist/stories/grist-modes.stories.d.ts +0 -37
- package/dist/stories/grist-modes.stories.js +0 -416
- package/dist/stories/grist-modes.stories.js.map +0 -1
- package/dist/stories/group-header.stories.d.ts +0 -26
- package/dist/stories/group-header.stories.js +0 -410
- package/dist/stories/group-header.stories.js.map +0 -1
- package/dist/stories/record-view.stories.d.ts +0 -24
- package/dist/stories/record-view.stories.js +0 -125
- package/dist/stories/record-view.stories.js.map +0 -1
- package/dist/stories/textarea.stories.d.ts +0 -37
- package/dist/stories/textarea.stories.js +0 -229
- package/dist/stories/textarea.stories.js.map +0 -1
- package/dist/stories/tree-column-with-checkbox.stories.d.ts +0 -26
- package/dist/stories/tree-column-with-checkbox.stories.js +0 -267
- package/dist/stories/tree-column-with-checkbox.stories.js.map +0 -1
- package/dist/stories/tree-column.stories.d.ts +0 -26
- package/dist/stories/tree-column.stories.js +0 -266
- package/dist/stories/tree-column.stories.js.map +0 -1
- package/index.ts +0 -1
package/README.md
CHANGED
@@ -1,95 +1,388 @@
|
|
1
|
-
#
|
1
|
+
# Data-Grist
|
2
2
|
|
3
|
-
|
3
|
+
Data-Grist is a powerful web component for displaying and manipulating data. It can present data in Grid, List, or Card formats and provides various features such as data sorting, filtering, editing, and more.
|
4
|
+
|
5
|
+
## Key Features
|
6
|
+
|
7
|
+
- **Multiple Display Modes**: Flexibly display the same data in grid, list, or card formats
|
8
|
+
- **Data Manipulation**: Add, modify, and delete records
|
9
|
+
- **Sorting and Filtering**: Single/multi-column sorting, various filtering options
|
10
|
+
- **Editing Capabilities**: Inline cell editing, validation
|
11
|
+
- **Pagination**: Standard paging and infinite scroll support
|
12
|
+
- **Selection**: Single/multiple record selection
|
13
|
+
- **State Tracking**: Track changed (dirty) records
|
14
|
+
- **Customization**: Support for various renderers, editors, and event handlers
|
15
|
+
- **Mobile Responsive**: Responsive design support
|
4
16
|
|
5
17
|
## Installation
|
6
18
|
|
7
19
|
```bash
|
8
|
-
npm
|
20
|
+
npm install @operato/data-grist
|
9
21
|
```
|
10
22
|
|
11
|
-
## Usage
|
23
|
+
## Basic Usage
|
12
24
|
|
13
25
|
```html
|
14
26
|
<script type="module">
|
15
|
-
import 'data-grist/
|
27
|
+
import '@operato/data-grist/ox-grist.js'
|
16
28
|
</script>
|
17
29
|
|
18
|
-
<
|
30
|
+
<ox-grist
|
31
|
+
.mode=${'GRID'}
|
32
|
+
.config=${gridConfig}
|
33
|
+
.fetchHandler=${fetchDataFunction}
|
34
|
+
></ox-grist>
|
19
35
|
```
|
20
36
|
|
21
|
-
##
|
37
|
+
## Modes
|
22
38
|
|
23
|
-
|
39
|
+
Data-Grist supports three display modes:
|
24
40
|
|
25
|
-
|
26
|
-
|
41
|
+
- **GRID**: Tabular data display (default)
|
42
|
+
- **LIST**: Mobile-friendly list format display
|
43
|
+
- **CARD**: Card format display
|
44
|
+
|
45
|
+
```javascript
|
46
|
+
// Set mode
|
47
|
+
gristElement.mode = 'GRID' // or 'LIST', 'CARD'
|
27
48
|
```
|
28
49
|
|
29
|
-
|
50
|
+
## Configuration (Config)
|
51
|
+
|
52
|
+
Data-Grist provides various configuration options.
|
53
|
+
|
54
|
+
```javascript
|
55
|
+
const config = {
|
56
|
+
columns: [
|
57
|
+
{
|
58
|
+
type: 'string',
|
59
|
+
name: 'name',
|
60
|
+
header: 'Name',
|
61
|
+
record: {
|
62
|
+
editable: true
|
63
|
+
},
|
64
|
+
sortable: true,
|
65
|
+
width: 150
|
66
|
+
}
|
67
|
+
// More columns...
|
68
|
+
],
|
69
|
+
rows: {
|
70
|
+
appendable: true, // Allow adding new records
|
71
|
+
editable: true, // Allow editing records
|
72
|
+
selectable: {
|
73
|
+
// Record selection settings
|
74
|
+
multiple: true // Allow multiple selections
|
75
|
+
}
|
76
|
+
},
|
77
|
+
pagination: {
|
78
|
+
infinite: false, // Use paging instead of infinite scroll
|
79
|
+
page: 1, // Starting page
|
80
|
+
limit: 20 // Records per page
|
81
|
+
}
|
82
|
+
// Additional settings...
|
83
|
+
}
|
84
|
+
```
|
30
85
|
|
31
|
-
|
32
|
-
|
86
|
+
### Column Types
|
87
|
+
|
88
|
+
```javascript
|
89
|
+
// String column
|
90
|
+
{
|
91
|
+
type: 'string',
|
92
|
+
name: 'firstName',
|
93
|
+
header: 'First Name'
|
94
|
+
}
|
95
|
+
|
96
|
+
// Number column
|
97
|
+
{
|
98
|
+
type: 'number',
|
99
|
+
name: 'age',
|
100
|
+
header: 'Age',
|
101
|
+
record: {
|
102
|
+
align: 'right'
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
// Boolean column
|
107
|
+
{
|
108
|
+
type: 'boolean',
|
109
|
+
name: 'isActive',
|
110
|
+
header: 'Active'
|
111
|
+
}
|
112
|
+
|
113
|
+
// Link column
|
114
|
+
{
|
115
|
+
type: 'link',
|
116
|
+
name: 'website',
|
117
|
+
header: 'Website',
|
118
|
+
record: {
|
119
|
+
options: {
|
120
|
+
href: (column, record) => record.url,
|
121
|
+
target: '_blank'
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
// Gutter column (row number, checkbox, button, etc.)
|
127
|
+
{
|
128
|
+
type: 'gutter',
|
129
|
+
gutterName: 'sequence' // 'row-selector', 'button', 'dirty', etc.
|
130
|
+
}
|
33
131
|
```
|
34
132
|
|
35
|
-
|
36
|
-
|
133
|
+
## Fetching Data
|
134
|
+
|
135
|
+
Data can be retrieved through the `fetchHandler` function.
|
136
|
+
|
137
|
+
```javascript
|
138
|
+
const fetchHandler = async params => {
|
139
|
+
const { page, limit, sorters, filters } = params
|
140
|
+
|
141
|
+
// Fetch data from server
|
142
|
+
const response = await fetch(`/api/data?page=${page}&limit=${limit}`)
|
143
|
+
const data = await response.json()
|
144
|
+
|
145
|
+
return {
|
146
|
+
total: data.total,
|
147
|
+
records: data.items
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
// Configure the grist
|
152
|
+
gristElement.fetchHandler = fetchHandler
|
37
153
|
```
|
38
154
|
|
39
|
-
|
155
|
+
## Record Manipulation API
|
40
156
|
|
41
|
-
|
42
|
-
|
157
|
+
### Adding Records
|
158
|
+
|
159
|
+
```javascript
|
160
|
+
// Add record at the end (default)
|
161
|
+
gristElement.addRecord({
|
162
|
+
name: 'John Doe',
|
163
|
+
age: 30
|
164
|
+
})
|
165
|
+
|
166
|
+
// Add record at the top
|
167
|
+
gristElement.addRecordToTop({
|
168
|
+
name: 'Jane Smith',
|
169
|
+
age: 25
|
170
|
+
})
|
43
171
|
```
|
44
172
|
|
45
|
-
|
173
|
+
### Record Selection
|
46
174
|
|
47
|
-
```
|
48
|
-
|
175
|
+
```javascript
|
176
|
+
// Get all selected records
|
177
|
+
const selectedRecords = gristElement.selected
|
178
|
+
|
179
|
+
// Set selection
|
180
|
+
gristElement.selected = [record1, record2]
|
181
|
+
|
182
|
+
// Select records using a selector function
|
183
|
+
gristElement.select(record => record.age > 30)
|
49
184
|
```
|
50
185
|
|
51
|
-
|
52
|
-
|
186
|
+
### Tracking Changed Records
|
187
|
+
|
188
|
+
```javascript
|
189
|
+
// Get modified records
|
190
|
+
const dirtyRecords = gristElement.dirtyRecords
|
191
|
+
|
192
|
+
// Check for changes
|
193
|
+
gristElement.checkDirties()
|
194
|
+
|
195
|
+
// Export changes as patches
|
196
|
+
const patches = gristElement.exportPatchList()
|
53
197
|
```
|
54
198
|
|
55
|
-
##
|
199
|
+
## Events
|
56
200
|
|
57
|
-
|
201
|
+
Data-Grist triggers various events.
|
58
202
|
|
59
|
-
```
|
60
|
-
|
203
|
+
```javascript
|
204
|
+
// Record selection change event
|
205
|
+
gristElement.addEventListener('select-record-change', e => {
|
206
|
+
const { records, added, removed } = e.detail
|
207
|
+
console.log('Selected records:', records)
|
208
|
+
})
|
209
|
+
|
210
|
+
// Field change event
|
211
|
+
gristElement.addEventListener('field-change', e => {
|
212
|
+
const { after, before, column, record, row } = e.detail
|
213
|
+
console.log('Changed field:', column.name, 'from', before, 'to', after)
|
214
|
+
})
|
215
|
+
|
216
|
+
// Record change event
|
217
|
+
gristElement.addEventListener('record-change', e => {
|
218
|
+
const { before, after, column, row } = e.detail
|
219
|
+
console.log('Record changed:', row)
|
220
|
+
})
|
61
221
|
```
|
62
222
|
|
63
|
-
|
223
|
+
## Advanced Features
|
64
224
|
|
65
|
-
|
66
|
-
|
225
|
+
### Column Accumulation Feature (Accumulator)
|
226
|
+
|
227
|
+
```javascript
|
228
|
+
{
|
229
|
+
type: 'number',
|
230
|
+
name: 'amount',
|
231
|
+
header: 'Amount',
|
232
|
+
accumulator: 'sum' // 'avg', 'count', 'min', 'max' or custom function
|
233
|
+
}
|
67
234
|
```
|
68
235
|
|
69
|
-
|
236
|
+
### Tree Structure Data
|
70
237
|
|
71
|
-
|
238
|
+
```javascript
|
239
|
+
const config = {
|
240
|
+
// ...
|
241
|
+
tree: {
|
242
|
+
childrenProperty: 'children', // Property name where child nodes are stored
|
243
|
+
expanded: true // Initial tree expansion state
|
244
|
+
}
|
245
|
+
}
|
246
|
+
```
|
72
247
|
|
73
|
-
|
74
|
-
|
248
|
+
### Grouped Headers
|
249
|
+
|
250
|
+
```javascript
|
251
|
+
const config = {
|
252
|
+
columns: [
|
253
|
+
// ...
|
254
|
+
{
|
255
|
+
type: 'string',
|
256
|
+
name: 'firstName',
|
257
|
+
header: 'First Name',
|
258
|
+
group: 'personalInfo'
|
259
|
+
},
|
260
|
+
{
|
261
|
+
type: 'string',
|
262
|
+
name: 'lastName',
|
263
|
+
header: 'Last Name',
|
264
|
+
group: 'personalInfo'
|
265
|
+
}
|
266
|
+
],
|
267
|
+
// ...
|
268
|
+
rows: {
|
269
|
+
// ...
|
270
|
+
groups: [
|
271
|
+
{
|
272
|
+
name: 'personalInfo',
|
273
|
+
title: 'Personal Information'
|
274
|
+
}
|
275
|
+
]
|
276
|
+
}
|
277
|
+
}
|
75
278
|
```
|
76
279
|
|
77
|
-
|
280
|
+
### User Settings Storage
|
281
|
+
|
282
|
+
```javascript
|
283
|
+
// Configure user settings provider
|
284
|
+
gristElement.personalConfigProvider = {
|
285
|
+
async load() {
|
286
|
+
// Load saved settings
|
287
|
+
return JSON.parse(localStorage.getItem('userGristConfig'))
|
288
|
+
},
|
289
|
+
async save(preference) {
|
290
|
+
// Save user settings
|
291
|
+
localStorage.setItem('userGristConfig', JSON.stringify(preference))
|
292
|
+
}
|
293
|
+
}
|
294
|
+
```
|
78
295
|
|
79
|
-
|
80
|
-
|
296
|
+
## Styling
|
297
|
+
|
298
|
+
Data-Grist can be styled through CSS variables.
|
299
|
+
|
300
|
+
```css
|
301
|
+
ox-grist {
|
302
|
+
--grid-header-background-color: #f5f5f5;
|
303
|
+
--grid-record-background-color: white;
|
304
|
+
--grid-record-odd-background-color: #f9f9f9;
|
305
|
+
--grid-header-color: #333;
|
306
|
+
--grid-record-hover-background-color: #e9e9e9;
|
307
|
+
}
|
81
308
|
```
|
82
309
|
|
83
|
-
##
|
310
|
+
## API Reference
|
311
|
+
|
312
|
+
### Properties
|
313
|
+
|
314
|
+
| Property | Type | Description |
|
315
|
+
| ----------------- | -------- | ------------------------------------- |
|
316
|
+
| `mode` | string | Display mode ('GRID', 'LIST', 'CARD') |
|
317
|
+
| `config` | object | Grist configuration object |
|
318
|
+
| `data` | object | Data to display |
|
319
|
+
| `selectedRecords` | array | Array of selected records |
|
320
|
+
| `explicitFetch` | boolean | Enable explicit data fetching |
|
321
|
+
| `fetchHandler` | function | Data fetching function |
|
322
|
+
| `fetchOptions` | object | Data fetching options |
|
323
|
+
| `filters` | array | Array of filters |
|
324
|
+
| `sorters` | array | Array of sorters |
|
325
|
+
| `pagination` | object | Pagination settings |
|
326
|
+
|
327
|
+
### Methods
|
328
|
+
|
329
|
+
| Method | Description |
|
330
|
+
| ------------------------------ | ------------------------------- |
|
331
|
+
| `fetch(reset)` | Fetch data |
|
332
|
+
| `addRecord(record)` | Add a record |
|
333
|
+
| `addRecordToTop(record)` | Add a record at the top |
|
334
|
+
| `deleteSelectedRecords(dirty)` | Delete selected records |
|
335
|
+
| `cloneSelectedRecords()` | Clone selected records |
|
336
|
+
| `checkDirties()` | Check for modified records |
|
337
|
+
| `undo()` | Undo last action |
|
338
|
+
| `redo()` | Redo undone action |
|
339
|
+
| `reset()` | Reset data |
|
340
|
+
| `commit()` | Commit changes |
|
341
|
+
| `select(selector, reset)` | Select records using a function |
|
342
|
+
| `exportPatchList(options)` | Export list of change patches |
|
343
|
+
| `exportRecords(options)` | Export record data |
|
344
|
+
|
345
|
+
## Examples
|
346
|
+
|
347
|
+
### Basic Grid
|
84
348
|
|
85
|
-
|
349
|
+
```html
|
350
|
+
<ox-grist
|
351
|
+
.mode=${'GRID'}
|
352
|
+
.config=${gridConfig}
|
353
|
+
.fetchHandler=${fetchData}
|
354
|
+
@record-change=${handleRecordChange}
|
355
|
+
></ox-grist>
|
356
|
+
```
|
86
357
|
|
87
|
-
|
358
|
+
### Editable Grid
|
88
359
|
|
89
|
-
|
360
|
+
```html
|
361
|
+
<ox-grist
|
362
|
+
.mode=${'GRID'}
|
363
|
+
.config=${{
|
364
|
+
columns: [/* column definitions */],
|
365
|
+
rows: {
|
366
|
+
appendable: true,
|
367
|
+
editable: true,
|
368
|
+
selectable: { multiple: true }
|
369
|
+
}
|
370
|
+
}}
|
371
|
+
.data=${{ records: initialData }}
|
372
|
+
></ox-grist>
|
373
|
+
```
|
90
374
|
|
91
|
-
|
92
|
-
|
375
|
+
### Add Row to Top Button
|
376
|
+
|
377
|
+
```html
|
378
|
+
<button @click="${() => gristRef.addRecordToTop()}">Add Row to Top</button>
|
379
|
+
<ox-grist id="my-grist"></ox-grist>
|
380
|
+
|
381
|
+
<script>
|
382
|
+
const gristRef = document.getElementById('my-grist')
|
383
|
+
</script>
|
93
384
|
```
|
94
385
|
|
95
|
-
|
386
|
+
## License
|
387
|
+
|
388
|
+
MIT
|
@@ -459,40 +459,43 @@ let DataGridBody = class DataGridBody extends LitElement {
|
|
459
459
|
}
|
460
460
|
const cells = record.querySelectorAll('td');
|
461
461
|
cells.forEach((item, columnIndex) => {
|
462
|
-
var _a;
|
463
462
|
const targetColumn = columns[column + columnIndex];
|
464
|
-
|
463
|
+
let value = item.textContent;
|
464
|
+
// let value = item.textContent?.trim() as any
|
465
465
|
let type = targetColumn.type || item.getAttribute('type') || 'string';
|
466
466
|
type = type.includes('object') ? 'object' : type; // 오브젝트 타입 예외처리
|
467
467
|
let { editable } = targetColumn.record;
|
468
468
|
if (typeof editable === 'function') {
|
469
469
|
editable = editable.call(this, value, targetColumn, targetRecord, row, this);
|
470
470
|
}
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
471
|
+
if (value) {
|
472
|
+
switch (type) {
|
473
|
+
case 'object':
|
474
|
+
case 'parameters':
|
475
|
+
try {
|
476
|
+
value = JSON.parse(value || 'null');
|
477
|
+
}
|
478
|
+
catch (err) { }
|
479
|
+
break;
|
480
|
+
case 'boolean':
|
481
|
+
case 'checkbox':
|
482
|
+
value = !!value && !!String(value).match(/true/i);
|
483
|
+
break;
|
484
|
+
case 'number':
|
485
|
+
case 'float':
|
486
|
+
case 'integer':
|
487
|
+
case 'progress':
|
488
|
+
value = parseToNumberOrNull(value);
|
489
|
+
break;
|
490
|
+
default:
|
491
|
+
try {
|
492
|
+
value = JSON.parse(value);
|
493
|
+
}
|
494
|
+
catch (err) { }
|
495
|
+
}
|
496
|
+
}
|
497
|
+
else {
|
498
|
+
value = undefined; /* default value 로 설정되도록 하기위해서 undefined로 설정. */
|
496
499
|
}
|
497
500
|
if (targetColumn && !targetColumn.gutterName && editable) {
|
498
501
|
this.dispatchEvent(new CustomEvent('field-change', {
|
@@ -618,6 +621,15 @@ DataGridBody.styles = [
|
|
618
621
|
ox-grid-accum-field[fixed] {
|
619
622
|
background-color: var(--md-sys-color-primary-container);
|
620
623
|
}
|
624
|
+
|
625
|
+
@media (max-width: 768px) {
|
626
|
+
/* 모바일에서는 그리드에서 고정된 열 해제 */
|
627
|
+
[fixed] {
|
628
|
+
position: static;
|
629
|
+
z-index: 0;
|
630
|
+
box-shadow: none !important;
|
631
|
+
}
|
632
|
+
}
|
621
633
|
`
|
622
634
|
];
|
623
635
|
__decorate([
|