@operato/data-grist 9.0.0-beta.54 → 9.0.0-beta.56

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +337 -44
  3. package/dist/src/data-grist.d.ts +12 -0
  4. package/dist/src/data-grist.js +42 -0
  5. package/dist/src/data-grist.js.map +1 -1
  6. package/dist/stories/accumulator-format.stories.js +1 -1
  7. package/dist/stories/accumulator-format.stories.js.map +1 -1
  8. package/dist/stories/append-position.stories.d.ts +8 -0
  9. package/dist/stories/append-position.stories.js +183 -0
  10. package/dist/stories/append-position.stories.js.map +1 -0
  11. package/dist/stories/barcode-input-filter.stories.js +1 -1
  12. package/dist/stories/barcode-input-filter.stories.js.map +1 -1
  13. package/dist/stories/bounded-select-filters.stories.js +1 -1
  14. package/dist/stories/bounded-select-filters.stories.js.map +1 -1
  15. package/dist/stories/bounded-select-record.stories.js +1 -1
  16. package/dist/stories/bounded-select-record.stories.js.map +1 -1
  17. package/dist/stories/click-event-custom.stories.js +1 -1
  18. package/dist/stories/click-event-custom.stories.js.map +1 -1
  19. package/dist/stories/click-event.stories.js +1 -1
  20. package/dist/stories/click-event.stories.js.map +1 -1
  21. package/dist/stories/creatable-only-column.stories.js +1 -1
  22. package/dist/stories/creatable-only-column.stories.js.map +1 -1
  23. package/dist/stories/default-filters.stories.js +1 -1
  24. package/dist/stories/default-filters.stories.js.map +1 -1
  25. package/dist/stories/dynamic-editable.stories.js +1 -1
  26. package/dist/stories/dynamic-editable.stories.js.map +1 -1
  27. package/dist/stories/empty-sorters.stories.js +1 -1
  28. package/dist/stories/empty-sorters.stories.js.map +1 -1
  29. package/dist/stories/explicit-fetch.stories.js +1 -1
  30. package/dist/stories/explicit-fetch.stories.js.map +1 -1
  31. package/dist/stories/fixed-column.stories.js +1 -1
  32. package/dist/stories/fixed-column.stories.js.map +1 -1
  33. package/dist/stories/grid-setting.stories.js +1 -1
  34. package/dist/stories/grid-setting.stories.js.map +1 -1
  35. package/dist/stories/grist-modes.stories.js +1 -1
  36. package/dist/stories/grist-modes.stories.js.map +1 -1
  37. package/dist/stories/group-header.stories.js +1 -1
  38. package/dist/stories/group-header.stories.js.map +1 -1
  39. package/dist/stories/record-view.stories.js +1 -1
  40. package/dist/stories/record-view.stories.js.map +1 -1
  41. package/dist/stories/textarea.stories.js +1 -1
  42. package/dist/stories/textarea.stories.js.map +1 -1
  43. package/dist/stories/tree-column-with-checkbox.stories.js +1 -1
  44. package/dist/stories/tree-column-with-checkbox.stories.js.map +1 -1
  45. package/dist/stories/tree-column.stories.js +1 -1
  46. package/dist/stories/tree-column.stories.js.map +1 -1
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -3,6 +3,24 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [9.0.0-beta.56](https://github.com/hatiolab/operato/compare/v9.0.0-beta.55...v9.0.0-beta.56) (2025-03-30)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * add addRecordToTop method into ox-grist ([57851b0](https://github.com/hatiolab/operato/commit/57851b0847e8f591a059345950da39b94e8d5122))
12
+ * title for ox-grist stories and README.md ([38476a5](https://github.com/hatiolab/operato/commit/38476a5994b142f29205014aa0238a1724fd7de1))
13
+
14
+
15
+
16
+ ## [9.0.0-beta.55](https://github.com/hatiolab/operato/compare/v9.0.0-beta.54...v9.0.0-beta.55) (2025-03-05)
17
+
18
+ **Note:** Version bump only for package @operato/data-grist
19
+
20
+
21
+
22
+
23
+
6
24
  ## [9.0.0-beta.54](https://github.com/hatiolab/operato/compare/v9.0.0-beta.53...v9.0.0-beta.54) (2025-03-04)
7
25
 
8
26
  **Note:** Version bump only for package @operato/data-grist
package/README.md CHANGED
@@ -1,95 +1,388 @@
1
- # \<data-grist>
1
+ # Data-Grist
2
2
 
3
- This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.
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 i data-grist
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/data-grist.js';
27
+ import '@operato/data-grist/ox-grist.js'
16
28
  </script>
17
29
 
18
- <data-grist></data-grist>
30
+ <ox-grist
31
+ .mode=${'GRID'}
32
+ .config=${gridConfig}
33
+ .fetchHandler=${fetchDataFunction}
34
+ ></ox-grist>
19
35
  ```
20
36
 
21
- ## Linting with ESLint, Prettier, and Types
37
+ ## Modes
22
38
 
23
- To scan the project for linting errors, run
39
+ Data-Grist supports three display modes:
24
40
 
25
- ```bash
26
- npm run lint
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
- You can lint with ESLint and Prettier individually as well
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
- ```bash
32
- npm run lint:eslint
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
- ```bash
36
- npm run lint:prettier
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
- To automatically fix many linting errors, run
155
+ ## Record Manipulation API
40
156
 
41
- ```bash
42
- npm run format
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
- You can format using ESLint and Prettier individually as well
173
+ ### Record Selection
46
174
 
47
- ```bash
48
- npm run format:eslint
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
- ```bash
52
- npm run format:prettier
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
- ## Testing with Web Test Runner
199
+ ## Events
56
200
 
57
- To run the suite of Web Test Runner tests, run
201
+ Data-Grist triggers various events.
58
202
 
59
- ```bash
60
- npm run test
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
- To run the tests in watch mode (for &lt;abbr title=&#34;test driven development&#34;&gt;TDD&lt;/abbr&gt;, for example), run
223
+ ## Advanced Features
64
224
 
65
- ```bash
66
- npm run test:watch
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
- ## Demoing with Storybook
236
+ ### Tree Structure Data
70
237
 
71
- To run a local instance of Storybook for your component, run
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
- ```bash
74
- npm run storybook
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
- To build a production version of Storybook, run
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
- ```bash
80
- npm run storybook:build
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
- ## Tooling configs
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
- For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.
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
- If you customize the configuration a lot, you can consider moving them to individual files.
358
+ ### Editable Grid
88
359
 
89
- ## Local Demo with `web-dev-server`
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
- ```bash
92
- npm start
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
- To run a local development server that serves the basic demo located in `demo/index.html`
386
+ ## License
387
+
388
+ MIT
@@ -324,6 +324,18 @@ export declare class DataGrist extends LitElement implements DataConsumer {
324
324
  * an empty record with the `__dirty__` flag set to '+' will be added.
325
325
  */
326
326
  addRecord(record?: GristRecord): void;
327
+ /**
328
+ * Adds a new record to the top of the data grid. The added record is marked as newly created
329
+ * by setting the `__dirty__` flag to '+'. This flag indicates that the record
330
+ * is in a "new" state and hasn't been committed to the main data yet.
331
+ *
332
+ * This method is useful when you need to add new records at the top of the grid
333
+ * without changing the default behavior of the appendable row.
334
+ *
335
+ * @param {GristRecord} [record] - An optional record to add. If no record is provided,
336
+ * an empty record with the `__dirty__` flag set to '+' will be added.
337
+ */
338
+ addRecordToTop(record?: GristRecord): void;
327
339
  /**
328
340
  * Retrieves the search text used for filtering records.
329
341
  *
@@ -830,6 +830,48 @@ let DataGrist = class DataGrist extends LitElement {
830
830
  ]
831
831
  };
832
832
  }
833
+ /**
834
+ * Adds a new record to the top of the data grid. The added record is marked as newly created
835
+ * by setting the `__dirty__` flag to '+'. This flag indicates that the record
836
+ * is in a "new" state and hasn't been committed to the main data yet.
837
+ *
838
+ * This method is useful when you need to add new records at the top of the grid
839
+ * without changing the default behavior of the appendable row.
840
+ *
841
+ * @param {GristRecord} [record] - An optional record to add. If no record is provided,
842
+ * an empty record with the `__dirty__` flag set to '+' will be added.
843
+ */
844
+ addRecordToTop(record) {
845
+ const newRecord = {
846
+ ...record,
847
+ __dirty__: '+'
848
+ };
849
+ this._data = {
850
+ ...this._data,
851
+ records: [newRecord, ...this.dirtyData.records]
852
+ };
853
+ // 새 레코드에 포커스 및 스크롤 처리
854
+ setTimeout(() => {
855
+ // 그리드가 있는 경우 첫 번째 행에 포커스 설정
856
+ if (this.grist) {
857
+ // 포커스를 첫 번째 행으로 설정 (첫 번째 편집 가능한 셀로)
858
+ const focusableColumns = this.compiledConfig.columns.filter(column => column.type !== 'gutter' && !column.hidden && column.record.editable);
859
+ if (focusableColumns.length > 0) {
860
+ const columnIndex = this.compiledConfig.columns.indexOf(focusableColumns[0]);
861
+ this.grist.dispatchEvent(new CustomEvent('focus-change', {
862
+ bubbles: true,
863
+ composed: true,
864
+ detail: {
865
+ row: 0,
866
+ column: columnIndex
867
+ }
868
+ }));
869
+ }
870
+ // 스크롤을 맨 위로 이동
871
+ this.grist.scrollTop = 0;
872
+ }
873
+ }, 0);
874
+ }
833
875
  /**
834
876
  * Retrieves the search text used for filtering records.
835
877
  *