@g1cloud/open-bluesea-grid 1.0.0-alpha.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.
@@ -0,0 +1,3315 @@
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vue"), require("dayjs"), require("@g1cloud/open-bluesea-core")) : typeof define === "function" && define.amd ? define(["exports", "vue", "dayjs", "@g1cloud/open-bluesea-core"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.OpenBlueseaGrid = {}, global.Vue, global.dayjs, global.OpenBlueseaCore));
3
+ })(this, (function(exports2, vue, dayjs, openBlueseaCore) {
4
+ "use strict";
5
+ class AbstractFilter {
6
+ type;
7
+ constructor(type) {
8
+ this.type = type;
9
+ }
10
+ serialize() {
11
+ return void 0;
12
+ }
13
+ isEmpty() {
14
+ return true;
15
+ }
16
+ }
17
+ class AndFilter extends AbstractFilter {
18
+ filters;
19
+ constructor(filters) {
20
+ super("AND");
21
+ this.filters = filters;
22
+ }
23
+ toString() {
24
+ return this.filters.map((filter) => `(${filter.toString()})`).join(" AND ");
25
+ }
26
+ serialize() {
27
+ const values = this.filters.map((f) => f.serialize()).filter(openBlueseaCore.notNull);
28
+ return ["AN", null, ...values];
29
+ }
30
+ isEmpty() {
31
+ return this.filters.length === 0 || !this.filters.find((child) => !child.isEmpty());
32
+ }
33
+ }
34
+ class OrFilter extends AbstractFilter {
35
+ filters;
36
+ constructor(filters) {
37
+ super("OR");
38
+ this.filters = filters;
39
+ }
40
+ toString() {
41
+ return this.filters.map((filter) => `(${filter.toString()})`).join(" OR ");
42
+ }
43
+ serialize() {
44
+ const values = this.filters.map((f) => f.serialize()).filter(openBlueseaCore.notNull);
45
+ return ["OR", null, ...values];
46
+ }
47
+ isEmpty() {
48
+ return this.filters.length === 0 || !this.filters.find((child) => !child.isEmpty());
49
+ }
50
+ }
51
+ class NotFilter extends AbstractFilter {
52
+ filter;
53
+ constructor(filter) {
54
+ super("NOT");
55
+ this.filter = filter;
56
+ }
57
+ toString() {
58
+ return `NOT(${this.filter.toString()})`;
59
+ }
60
+ serialize() {
61
+ return ["NT", this.filter.serialize()];
62
+ }
63
+ isEmpty() {
64
+ return this.filter.isEmpty();
65
+ }
66
+ }
67
+ class InFilter extends AbstractFilter {
68
+ names;
69
+ values;
70
+ ignoreCase;
71
+ constructor(names, values, ignoreCase) {
72
+ super("IN");
73
+ this.names = names;
74
+ this.values = values;
75
+ this.ignoreCase = ignoreCase;
76
+ }
77
+ toString() {
78
+ const names = this.names.join(",");
79
+ const values = this.values.join(",");
80
+ return `${names} IN (${values})`;
81
+ }
82
+ serialize() {
83
+ if (this.names.length === 1) {
84
+ return ["IN", this.names, ...this.values];
85
+ } else if (this.names.length > 1) {
86
+ const filters = this.names.map((name) => inFilter([name], this.values, this.ignoreCase));
87
+ return orFilter(filters).serialize();
88
+ }
89
+ }
90
+ getFilterValueString() {
91
+ return this.values.map((value) => String(value));
92
+ }
93
+ isEmpty() {
94
+ return this.names.length === 0 || this.values.length === 0;
95
+ }
96
+ }
97
+ class LikeFilter extends AbstractFilter {
98
+ names;
99
+ value;
100
+ prefix;
101
+ suffix;
102
+ ignoreCase;
103
+ constructor(names, value, prefix, suffix, ignoreCase = true) {
104
+ super("LIKE");
105
+ this.names = names;
106
+ this.value = value;
107
+ this.prefix = prefix;
108
+ this.suffix = suffix;
109
+ this.ignoreCase = ignoreCase;
110
+ }
111
+ toString() {
112
+ const names = this.names.join(",");
113
+ return `${names} LIKE ${this.value}`;
114
+ }
115
+ serialize() {
116
+ if (this.names.length === 1) {
117
+ const result = ["LI", this.names[0], this.value, this.prefix ? 1 : 0, this.suffix ? 1 : 0];
118
+ if (!this.ignoreCase)
119
+ result.push(0);
120
+ return result;
121
+ } else if (this.names.length > 1) {
122
+ const filters = this.names.map((name) => likeFilter([name], this.value, this.prefix, this.suffix, this.ignoreCase));
123
+ return orFilter(filters).serialize();
124
+ }
125
+ }
126
+ getFilterValueString() {
127
+ return this.value;
128
+ }
129
+ isEmpty() {
130
+ return this.names.length === 0 || !this.value;
131
+ }
132
+ }
133
+ class EqualFilter extends AbstractFilter {
134
+ names;
135
+ value;
136
+ ignoreCase;
137
+ constructor(names, value, ignoreCase) {
138
+ super("EQ");
139
+ this.names = names;
140
+ this.value = value;
141
+ this.ignoreCase = ignoreCase;
142
+ }
143
+ toString() {
144
+ const names = this.names.join(",");
145
+ return `${names} = ${this.value}`;
146
+ }
147
+ serialize() {
148
+ if (this.names.length === 1) {
149
+ const result = ["EQ", this.names[0], this.value];
150
+ if (this.ignoreCase)
151
+ result.push(1);
152
+ return result;
153
+ } else if (this.names.length > 1) {
154
+ const filters = this.names.map((name) => equalFilter([name], this.value, this.ignoreCase));
155
+ return orFilter(filters).serialize();
156
+ }
157
+ }
158
+ getFilterValueString() {
159
+ return String(this.value);
160
+ }
161
+ isEmpty() {
162
+ return this.names.length === 0 || this.value === void 0 || this.value === "";
163
+ }
164
+ }
165
+ class BetweenFilter extends AbstractFilter {
166
+ name;
167
+ fromValue;
168
+ toValue;
169
+ constructor(name, fromValue, toValue) {
170
+ super("BT_V");
171
+ this.name = name;
172
+ this.fromValue = fromValue;
173
+ this.toValue = toValue;
174
+ }
175
+ toString() {
176
+ return `${this.name} BETWEEN ${this.fromValue} AND ${this.toValue}`;
177
+ }
178
+ serialize() {
179
+ return ["BT", this.name, this.fromValue, this.toValue];
180
+ }
181
+ isEmpty() {
182
+ return !this.name || (this.fromValue === void 0 || this.fromValue === "") && (this.toValue === void 0 || this.toValue === "");
183
+ }
184
+ }
185
+ class BetweenDateFilter extends AbstractFilter {
186
+ name;
187
+ fromValue;
188
+ toValue;
189
+ constructor(name, fromValue, toValue) {
190
+ super("BT_D");
191
+ this.name = name;
192
+ this.fromValue = fromValue;
193
+ this.toValue = toValue;
194
+ }
195
+ toString() {
196
+ const from = this.fromValue ? dayjs(this.fromValue).toISOString() : "undefined";
197
+ const to = this.toValue ? dayjs(this.toValue).toISOString() : "undefined";
198
+ return `${this.name} BETWEEN ${from} AND ${to}`;
199
+ }
200
+ serialize() {
201
+ const from = this.fromValue ? dayjs(this.fromValue).toISOString() : null;
202
+ const to = this.toValue ? dayjs(this.toValue).toISOString() : null;
203
+ return ["BT", this.name, from, to];
204
+ }
205
+ isEmpty() {
206
+ return !this.name || (this.fromValue === void 0 || this.fromValue === "") && (this.toValue === void 0 || this.toValue === "");
207
+ }
208
+ }
209
+ class IsNullFilter extends AbstractFilter {
210
+ names;
211
+ constructor(names) {
212
+ super("NU");
213
+ this.names = names;
214
+ }
215
+ toString() {
216
+ const names = this.names.join(",");
217
+ return `${names} IS NULL`;
218
+ }
219
+ serialize() {
220
+ if (this.names.length === 1) {
221
+ return ["NU", this.names[0]];
222
+ } else if (this.names.length > 1) {
223
+ const filters = this.names.map((name) => isNullFilter([name]));
224
+ return orFilter(filters).serialize();
225
+ }
226
+ }
227
+ getFilterValueString() {
228
+ return String();
229
+ }
230
+ isEmpty() {
231
+ return this.names.length === 0;
232
+ }
233
+ }
234
+ class IsNotNullFilter extends AbstractFilter {
235
+ names;
236
+ constructor(names) {
237
+ super("NN");
238
+ this.names = names;
239
+ }
240
+ toString() {
241
+ const names = this.names.join(",");
242
+ return `${names} IS NOT NULL`;
243
+ }
244
+ serialize() {
245
+ if (this.names.length === 1) {
246
+ return ["NN", this.names[0]];
247
+ } else if (this.names.length > 1) {
248
+ const filters = this.names.map((name) => isNotNullFilter([name]));
249
+ return orFilter(filters).serialize();
250
+ }
251
+ }
252
+ getFilterValueString() {
253
+ return String();
254
+ }
255
+ isEmpty() {
256
+ return this.names.length === 0;
257
+ }
258
+ }
259
+ const andFilter = (filters) => {
260
+ return new AndFilter(filters);
261
+ };
262
+ const orFilter = (filters) => {
263
+ return new OrFilter(filters);
264
+ };
265
+ const notFilter = (filter) => {
266
+ return new NotFilter(filter);
267
+ };
268
+ const inFilter = (names, values, ignoreCase) => {
269
+ return new InFilter(names, values, ignoreCase);
270
+ };
271
+ const likeFilter = (names, value, prefix, suffix, ignoreCase) => {
272
+ return new LikeFilter(names, value, prefix, suffix, ignoreCase);
273
+ };
274
+ const equalFilter = (names, value, ignoreCase) => {
275
+ return new EqualFilter(names, value, ignoreCase);
276
+ };
277
+ const betweenFilter = (name, fromValue, toValue) => {
278
+ return new BetweenFilter(name, fromValue, toValue);
279
+ };
280
+ const betweenDateFilter = (name, fromValue, toValue) => {
281
+ return new BetweenDateFilter(name, fromValue, toValue);
282
+ };
283
+ const isNullFilter = (names) => {
284
+ return new IsNullFilter(names);
285
+ };
286
+ const isNotNullFilter = (names) => {
287
+ return new IsNotNullFilter(names);
288
+ };
289
+ const acceptFilter = (filter, visit) => {
290
+ const result = visit(filter);
291
+ if (result === void 0 || result) {
292
+ if ("filters" in filter) {
293
+ const children = filter.filters;
294
+ if (children && Array.isArray(children)) {
295
+ children.forEach((child) => acceptFilter(child, visit));
296
+ }
297
+ }
298
+ }
299
+ };
300
+ const valueToFilter = (filters) => {
301
+ return Object.keys(filters).map((filterName) => {
302
+ const filter = filters[filterName];
303
+ if (filter instanceof AbstractFilter) {
304
+ return filter;
305
+ } else if (["string", "number", "boolean"].includes(typeof filter)) {
306
+ return equalFilter([filterName], filter);
307
+ } else if (Array.isArray(filter)) {
308
+ return inFilter([filterName], filter);
309
+ } else {
310
+ if (filter !== void 0)
311
+ console.warn("Unsupported filter value: " + filter);
312
+ return void 0;
313
+ }
314
+ }).filter(openBlueseaCore.notNull);
315
+ };
316
+ const serializeFilter = (filters) => {
317
+ if (filters.length === 0)
318
+ return void 0;
319
+ else if (filters.length === 1)
320
+ return JSON.stringify(filters[0].serialize());
321
+ else
322
+ return JSON.stringify(andFilter(filters).serialize());
323
+ };
324
+ const serializeSort = (sorts) => {
325
+ if (sorts && sorts.length > 0) {
326
+ return sorts.map((sort) => {
327
+ const dir = sort.ascending ? "" : "-";
328
+ const propertyId = encodeURIComponent(sort.propertyId);
329
+ const nulls = sort.nullHandling || "";
330
+ return `${dir}${propertyId}${nulls ? ` ${nulls}` : ""}`;
331
+ }).join(",");
332
+ }
333
+ };
334
+ class SearchParam {
335
+ offset;
336
+ limit;
337
+ gridFilter = {};
338
+ lookupFilter = [];
339
+ defaultFilter = [];
340
+ sorts;
341
+ toQueryMap() {
342
+ const filters = [...this.defaultFilter, ...this.lookupFilter, ...valueToFilter(this.gridFilter)];
343
+ return {
344
+ filter: serializeFilter(filters),
345
+ sort: serializeSort(this.sorts),
346
+ offset: this.offset,
347
+ limit: this.limit
348
+ };
349
+ }
350
+ }
351
+ class PaginatedList {
352
+ data = [];
353
+ totalCount = 0;
354
+ offset = 0;
355
+ limit = 0;
356
+ static of(data = [], totalCount = void 0, offset = 0, limit = void 0) {
357
+ const paginatedList = new PaginatedList();
358
+ paginatedList.data = data ? data.slice() : [];
359
+ paginatedList.totalCount = Math.max(0, totalCount || paginatedList.data.length);
360
+ paginatedList.offset = Math.max(0, offset);
361
+ paginatedList.limit = Math.max(0, limit || paginatedList.data.length);
362
+ return paginatedList;
363
+ }
364
+ /**
365
+ * `AxiosResponse` 등의 http response 로부터 `PaginatedList` 를 생성한다.
366
+ * @param response
367
+ * @param converter
368
+ */
369
+ static fromAxiosResponse(response, converter) {
370
+ return PaginatedList.fromAxiosHeader(response.headers, response.data, converter);
371
+ }
372
+ /**
373
+ * Axios Header 와 response data 로부터 `PaginatedList` 를 생성한다.
374
+ * @param headers
375
+ * @param data
376
+ * @param converter
377
+ */
378
+ static fromAxiosHeader(headers, data, converter) {
379
+ const actualConverter = converter ? converter : ((item) => item);
380
+ const convertedData = data && data.length ? data.map((item) => actualConverter(item)) : [];
381
+ return PaginatedList.of(convertedData, Number(headers["x-total-count"]) || void 0, Number(headers["x-offset"]) || 0, Number(headers["x-limit"] || void 0));
382
+ }
383
+ /**
384
+ * @return 로딩된 데이터가 비어있으면 true
385
+ */
386
+ isEmpty() {
387
+ return this.data.length === 0;
388
+ }
389
+ }
390
+ const DEFAULT_GRID_COLUMN_WIDTH = 100;
391
+ const nameFilterCreator = (maxIndex = 4) => {
392
+ return (propertyId, keyword) => {
393
+ const names = Array.from({ length: Math.max(1, Math.min(maxIndex, 4)) }).map((_, index) => `${propertyId}.name${index + 1}`);
394
+ return [likeFilter(names, keyword)];
395
+ };
396
+ };
397
+ class EditingRows {
398
+ keyProvider;
399
+ rows = [];
400
+ constructor(keyProvider) {
401
+ this.keyProvider = keyProvider;
402
+ }
403
+ addEditingRow(row) {
404
+ this.rows.push(row);
405
+ }
406
+ addRow(row) {
407
+ this.rows.push({ row });
408
+ }
409
+ rowEquals(a, b) {
410
+ return a === b || !!(this.keyProvider && this.keyProvider(a) === this.keyProvider(b));
411
+ }
412
+ removeRow(row) {
413
+ const index = this.rows.findIndex((editing) => this.rowEquals(editing.row, row));
414
+ if (index >= 0)
415
+ this.rows.splice(index, 1);
416
+ }
417
+ clear() {
418
+ this.rows.splice(0, this.rows.length);
419
+ }
420
+ getEditingRow(row) {
421
+ return this.rows.find((editing) => this.rowEquals(editing.row, row));
422
+ }
423
+ isEditingRow(row) {
424
+ return !!this.getEditingRow(row);
425
+ }
426
+ getRows() {
427
+ return this.rows;
428
+ }
429
+ getModifiedRows() {
430
+ return this.rows.filter((row) => row.savePoint?.isModified());
431
+ }
432
+ }
433
+ const createPageGridHandler = (option) => {
434
+ const handler = option.editable ? new EditablePageGridHandlerImpl(option) : new PageGridHandlerImpl(option);
435
+ handler.loadPreference();
436
+ return handler;
437
+ };
438
+ class PageGridHandlerImpl {
439
+ option;
440
+ searchParam = vue.markRaw(new SearchParam());
441
+ selectDeleteSupport;
442
+ grid;
443
+ gridEventListener;
444
+ control;
445
+ controlEventListener;
446
+ lookup;
447
+ lookupEventListener;
448
+ preferenceLoader;
449
+ constructor(option) {
450
+ this.option = vue.markRaw(option);
451
+ this.searchParam.offset = 0;
452
+ this.searchParam.limit = option.limit || option.limitItems?.[0] || 100;
453
+ this.searchParam.defaultFilter = option.defaultFilter || [];
454
+ this.searchParam.sorts = [...option.defaultSorts || []];
455
+ this.grid = vue.reactive({
456
+ gridId: option.gridId,
457
+ pageInfo: {
458
+ offset: 0,
459
+ limit: this.searchParam.limit,
460
+ totalCount: 0
461
+ },
462
+ sorts: this.searchParam.sorts,
463
+ data: [],
464
+ loading: false,
465
+ keyProvider: (row) => option.getRowKey(row),
466
+ editable: false
467
+ });
468
+ if (option.isRowSelectable) {
469
+ this.grid.rowSelectPolicy = (row) => option.isRowSelectable?.(row) || false;
470
+ }
471
+ this.gridEventListener = {
472
+ "offsetChanged": async (offset, _pageInfo) => {
473
+ this.searchParam.offset = offset;
474
+ await this.loadGridData();
475
+ },
476
+ "update:sorts": async (sorts) => {
477
+ if (this.option.defaultSorts && this.option.defaultSorts.length > 0) {
478
+ this.searchParam.sorts = [...sorts, ...this.option.defaultSorts];
479
+ }
480
+ await this.loadGridData(0);
481
+ },
482
+ settingChanged: async (columnSettings, fixedColumnCount) => {
483
+ await gridColumnSettingChanged(this.grid, this.control, option.gridId, columnSettings, fixedColumnCount);
484
+ }
485
+ };
486
+ this.control = vue.reactive({
487
+ gridId: option.gridId,
488
+ limit: this.searchParam.limit,
489
+ limitItems: option.limitItems || [100, 300, 500],
490
+ totalCount: 0
491
+ });
492
+ this.controlEventListener = {
493
+ "update:limit": async (limit) => {
494
+ this.searchParam.limit = limit;
495
+ if (this.grid.pageInfo)
496
+ this.grid.pageInfo.limit = limit;
497
+ await this.loadGridData(0);
498
+ },
499
+ refresh: async () => {
500
+ await this.loadGridData();
501
+ },
502
+ clearFilter: async () => {
503
+ this.searchParam.gridFilter = {};
504
+ await this.loadGridData(0);
505
+ },
506
+ settingChanged: (columnSettings, fixedColumnCount) => {
507
+ gridColumnSettingChanged(this.grid, this.control, option.gridId, columnSettings, fixedColumnCount);
508
+ }
509
+ };
510
+ this.lookup = vue.reactive({
511
+ gridId: option.gridId,
512
+ modelValue: []
513
+ });
514
+ this.lookupEventListener = {
515
+ "update:modelValue": (filters) => {
516
+ this.lookup.modelValue = this.searchParam.lookupFilter = filters;
517
+ },
518
+ search: async () => {
519
+ this.searchParam.gridFilter = {};
520
+ await this.loadGridData(0);
521
+ }
522
+ };
523
+ this.selectDeleteSupport = new GridHandlerSelectDeleteSupport(this.grid, this.control, this.controlEventListener, option.removeRowHandler, () => this.updateCounts());
524
+ }
525
+ get preferenceLoaded() {
526
+ return this.preferenceLoader?.preferenceLoaded.value ?? true;
527
+ }
528
+ getSelectedRows() {
529
+ return this.selectDeleteSupport.selectedRows;
530
+ }
531
+ getEditingRows() {
532
+ return this.grid.editingRows;
533
+ }
534
+ getAddedRows() {
535
+ return [];
536
+ }
537
+ getModifiedRows() {
538
+ return [];
539
+ }
540
+ getDeletedRows() {
541
+ return this.selectDeleteSupport.deletedRows;
542
+ }
543
+ isAddedRow(_row) {
544
+ return false;
545
+ }
546
+ addNewRow(_newRow) {
547
+ return -1;
548
+ }
549
+ isGridModified() {
550
+ return this.getAddedRows().length > 0 || this.getModifiedRows().length > 0 || this.getDeletedRows().length > 0;
551
+ }
552
+ /**
553
+ *
554
+ * @param offset
555
+ */
556
+ async loadGridData(offset) {
557
+ await this.preferenceLoader?.waitForLoaded();
558
+ this.grid.loading = true;
559
+ if (offset !== void 0)
560
+ this.searchParam.offset = offset;
561
+ const result = await this.option.getGridData(this.searchParam);
562
+ this.doSetSearchResult(result);
563
+ this.grid.loading = false;
564
+ }
565
+ loadPreference() {
566
+ if (this.option.gridId) {
567
+ this.preferenceLoader = new GridPreferenceLoader(this.option.gridId, this);
568
+ this.preferenceLoader.loadGridPreference();
569
+ }
570
+ }
571
+ doSetSearchResult(result) {
572
+ this.selectDeleteSupport.clear();
573
+ if (this.grid.pageInfo)
574
+ this.grid.pageInfo.offset = result.offset;
575
+ if (this.grid.pageInfo)
576
+ this.grid.pageInfo.totalCount = result.totalCount;
577
+ this.grid.data = result.data;
578
+ this.control.totalCount = result.totalCount;
579
+ }
580
+ updateCounts() {
581
+ this.control.totalCount = this.grid.data.length;
582
+ }
583
+ }
584
+ class EditablePageGridHandlerImpl extends PageGridHandlerImpl {
585
+ editableSupport;
586
+ constructor(option) {
587
+ super(option);
588
+ this.grid.rowEditPolicy = option.isRowEditable;
589
+ this.editableSupport = new GridHandlerEditableSupport(this.grid, this.gridEventListener, this.controlEventListener, option.getRowKey, option.newRowCreator, option.addRowToLast, () => this.updateCounts());
590
+ this.selectDeleteSupport.isAddedRow = (row) => this.editableSupport.isAddedRow(row);
591
+ this.selectDeleteSupport.removeIfAddedRow = (row) => this.editableSupport.removeIfAddedRow(row);
592
+ }
593
+ getModifiedRows() {
594
+ return this.editableSupport.getModifiedRows();
595
+ }
596
+ getAddedRows() {
597
+ return this.editableSupport.getAddedRows();
598
+ }
599
+ isAddedRow(row) {
600
+ return this.editableSupport.isAddedRow(row);
601
+ }
602
+ addNewRow(newRow) {
603
+ return this.editableSupport.addNewRow(newRow);
604
+ }
605
+ doSetSearchResult(result) {
606
+ super.doSetSearchResult(result);
607
+ this.editableSupport.clearAddedRows();
608
+ }
609
+ }
610
+ const createInputGridHandler = (option) => {
611
+ const handler = option.editable ? new EditableInputGridHandlerImpl(option) : new InputGridHandlerImpl(option);
612
+ handler.loadPreference();
613
+ return handler;
614
+ };
615
+ class InputGridHandlerImpl {
616
+ option;
617
+ selectDeleteSupport;
618
+ grid;
619
+ gridEventListener;
620
+ control;
621
+ controlEventListener;
622
+ gridFilter = vue.reactive({});
623
+ preferenceLoader;
624
+ constructor(option) {
625
+ this.option = vue.markRaw(option);
626
+ this.grid = vue.reactive({
627
+ gridId: option.gridId,
628
+ data: [],
629
+ keyProvider: (row) => option.getRowKey(row),
630
+ editable: false,
631
+ rowDisplayPolicy: (row) => this.applyGridFilter(row)
632
+ });
633
+ if (option.isRowSelectable) {
634
+ this.grid.rowSelectPolicy = (row) => option.isRowSelectable?.(row) || false;
635
+ }
636
+ this.gridEventListener = {
637
+ settingChanged: async (columnSettings, fixedColumnCount) => {
638
+ await gridColumnSettingChanged(this.grid, this.control, option.gridId, columnSettings, fixedColumnCount);
639
+ }
640
+ };
641
+ this.control = vue.reactive({
642
+ gridId: option.gridId,
643
+ totalCount: 0
644
+ });
645
+ this.controlEventListener = {
646
+ clearFilter: () => {
647
+ Object.keys(this.gridFilter).forEach((key) => delete this.gridFilter[key]);
648
+ },
649
+ settingChanged: async (columnSettings, fixedColumnCount) => {
650
+ await gridColumnSettingChanged(this.grid, this.control, option.gridId, columnSettings, fixedColumnCount);
651
+ }
652
+ };
653
+ this.selectDeleteSupport = new GridHandlerSelectDeleteSupport(this.grid, this.control, this.controlEventListener, option.removeRowHandler, () => this.updateCounts());
654
+ }
655
+ get preferenceLoaded() {
656
+ return this.preferenceLoader?.preferenceLoaded.value ?? true;
657
+ }
658
+ setGridData(data) {
659
+ this.grid.loading = data === void 0;
660
+ this.grid.data = data ?? [];
661
+ this.control.totalCount = data?.length ?? 0;
662
+ this.selectDeleteSupport.clear();
663
+ }
664
+ getSelectedRows() {
665
+ return this.selectDeleteSupport.selectedRows;
666
+ }
667
+ getEditingRows() {
668
+ return this.grid.editingRows;
669
+ }
670
+ getDeletedRows() {
671
+ return this.selectDeleteSupport.deletedRows;
672
+ }
673
+ getAddedRows() {
674
+ return [];
675
+ }
676
+ getModifiedRows() {
677
+ return [];
678
+ }
679
+ isAddedRow(_row) {
680
+ return false;
681
+ }
682
+ addNewRow(_newRow) {
683
+ return -1;
684
+ }
685
+ isGridModified() {
686
+ return this.getAddedRows().length > 0 || this.getModifiedRows().length > 0 || this.getDeletedRows().length > 0;
687
+ }
688
+ loadPreference() {
689
+ if (this.option.gridId) {
690
+ this.preferenceLoader = new GridPreferenceLoader(this.option.gridId, this);
691
+ this.preferenceLoader.loadGridPreference();
692
+ }
693
+ }
694
+ updateCounts() {
695
+ this.control.totalCount = this.grid.data.length;
696
+ }
697
+ applyGridFilter(row) {
698
+ const mismatch = Object.keys(this.gridFilter).filter((key) => this.gridFilter[key] !== void 0).find((key) => {
699
+ const filter = this.gridFilter[key];
700
+ if (typeof filter === "function") {
701
+ return !filter(row);
702
+ } else if (Array.isArray(filter)) {
703
+ return filter.length > 0 && !filter.find((item) => row[key] === item);
704
+ } else {
705
+ return row[key] !== filter;
706
+ }
707
+ });
708
+ return !mismatch;
709
+ }
710
+ }
711
+ class EditableInputGridHandlerImpl extends InputGridHandlerImpl {
712
+ editableSupport;
713
+ constructor(option) {
714
+ super(option);
715
+ this.grid.rowEditPolicy = option.isRowEditable;
716
+ this.editableSupport = new GridHandlerEditableSupport(this.grid, this.gridEventListener, this.controlEventListener, option.getRowKey, option.newRowCreator, option.addRowToLast, () => this.updateCounts());
717
+ this.selectDeleteSupport.isAddedRow = (row) => this.editableSupport.isAddedRow(row);
718
+ this.selectDeleteSupport.removeIfAddedRow = (row) => this.editableSupport.removeIfAddedRow(row);
719
+ }
720
+ setGridData(data) {
721
+ GridHandlerEditableSupport.cleanUpData(data);
722
+ super.setGridData(data);
723
+ this.editableSupport.clearAddedRows();
724
+ }
725
+ getModifiedRows() {
726
+ return this.editableSupport.getModifiedRows();
727
+ }
728
+ getAddedRows() {
729
+ return this.editableSupport.getAddedRows();
730
+ }
731
+ isAddedRow(row) {
732
+ return this.editableSupport.isAddedRow(row);
733
+ }
734
+ addNewRow(newRow) {
735
+ return this.editableSupport.addNewRow(newRow);
736
+ }
737
+ }
738
+ class GridHandlerSelectDeleteSupport {
739
+ grid;
740
+ control;
741
+ controlEventListener;
742
+ removeRowHandler;
743
+ listener;
744
+ selectedRows = vue.reactive(/* @__PURE__ */ new Set());
745
+ deletedRows = [];
746
+ isAddedRow;
747
+ removeIfAddedRow;
748
+ constructor(grid, control, controlEventListener, removeRowHandler, listener) {
749
+ this.grid = grid;
750
+ this.control = control;
751
+ this.controlEventListener = controlEventListener;
752
+ this.removeRowHandler = removeRowHandler;
753
+ this.listener = listener;
754
+ grid.selectedRows = this.selectedRows;
755
+ control.selectedRows = this.selectedRows;
756
+ controlEventListener["clickRemove"] = () => this.removeSelectedRows();
757
+ }
758
+ removeSelectedRows() {
759
+ if (this.selectedRows.size > 0) {
760
+ if (!this.removeRowHandler || !this.removeRowHandler(this.selectedRows)) {
761
+ const keyProvider = this.grid.keyProvider;
762
+ this.selectedRows.forEach((row) => {
763
+ const index = this.grid.data.findIndex((item) => keyProvider(item) === keyProvider(row));
764
+ if (index >= 0) {
765
+ const item = this.grid.data[index];
766
+ this.grid.editingRows?.removeRow(item);
767
+ if (this.isAddedRow?.(item))
768
+ this.removeIfAddedRow?.(item);
769
+ else {
770
+ const deleted = this.grid.data.splice(index, 1);
771
+ this.deletedRows.push(deleted[0]);
772
+ }
773
+ }
774
+ });
775
+ this.selectedRows.clear();
776
+ this.listener?.("selectedRowsChanged");
777
+ }
778
+ }
779
+ }
780
+ clear() {
781
+ this.selectedRows.clear();
782
+ this.listener?.("selectedRowsChanged");
783
+ this.deletedRows.splice(0, this.deletedRows.length);
784
+ }
785
+ }
786
+ let lastAddedRowIndex = 0;
787
+ const GRID_NEW_ROW_KEY = "_new_row_key_";
788
+ class GridHandlerEditableSupport {
789
+ grid;
790
+ gridEventListener;
791
+ controlEventListener;
792
+ newRowCreator;
793
+ addRowToLast;
794
+ listener;
795
+ addedRows = [];
796
+ constructor(grid, gridEventListener, controlEventListener, getRowKey, newRowCreator, addRowToLast, listener) {
797
+ this.grid = grid;
798
+ this.gridEventListener = gridEventListener;
799
+ this.controlEventListener = controlEventListener;
800
+ this.newRowCreator = newRowCreator;
801
+ this.addRowToLast = addRowToLast;
802
+ this.listener = listener;
803
+ grid.editable = true;
804
+ const keyProvider = (row) => {
805
+ const key = this.getNewRowKey(row);
806
+ return key ? key : getRowKey(row);
807
+ };
808
+ grid.keyProvider = keyProvider;
809
+ grid.editingRows = vue.reactive(new EditingRows(keyProvider));
810
+ gridEventListener.changeEditingRow = (row, editing) => {
811
+ if (!editing) {
812
+ this.removeIfAddedRow(row);
813
+ }
814
+ };
815
+ controlEventListener.clickAdd = () => this.createAndAddNewRow();
816
+ }
817
+ static cleanUpData(data) {
818
+ data?.forEach((row) => {
819
+ if (row && row[GRID_NEW_ROW_KEY])
820
+ delete row[GRID_NEW_ROW_KEY];
821
+ });
822
+ }
823
+ getModifiedRows() {
824
+ const addedKeys = this.addedRows.map((row) => row[GRID_NEW_ROW_KEY]);
825
+ return this.grid.editingRows?.getModifiedRows().map((editing) => editing.row).filter((row) => !addedKeys.includes(row[GRID_NEW_ROW_KEY])) || [];
826
+ }
827
+ getAddedRows() {
828
+ return this.addedRows;
829
+ }
830
+ clearAddedRows() {
831
+ this.addedRows.splice(0, this.addedRows.length);
832
+ }
833
+ isAddedRow(row) {
834
+ return !!this.getNewRowKey(row);
835
+ }
836
+ getNewRowKey(row) {
837
+ return row[GRID_NEW_ROW_KEY];
838
+ }
839
+ setNewRowKey(row) {
840
+ row[GRID_NEW_ROW_KEY] = `_ADDED_${++lastAddedRowIndex}`;
841
+ }
842
+ removeIfAddedRow(row) {
843
+ if (this.isAddedRow(row)) {
844
+ const keyProvider = this.grid.keyProvider;
845
+ const index = this.grid.data.findIndex((item) => keyProvider(item) === keyProvider(row));
846
+ if (index >= 0)
847
+ this.grid.data.splice(index, 1);
848
+ const rowIndex = this.addedRows.findIndex((item) => keyProvider(item) === keyProvider(row));
849
+ if (rowIndex >= 0)
850
+ this.addedRows.splice(rowIndex, 1);
851
+ this.listener?.("rowRemoved");
852
+ return true;
853
+ } else {
854
+ return false;
855
+ }
856
+ }
857
+ addNewRow(newRow) {
858
+ this.setNewRowKey(newRow);
859
+ this.appendAddedRow(newRow);
860
+ let index = 0;
861
+ if (this.addRowToLast) {
862
+ this.grid.data.push(newRow);
863
+ index = this.grid.data.length;
864
+ } else {
865
+ this.grid.data.unshift(newRow);
866
+ index = 0;
867
+ }
868
+ this.listener?.("rowAdded");
869
+ return index;
870
+ }
871
+ appendAddedRow(row) {
872
+ this.addedRows.push(row);
873
+ this.grid.editingRows?.addRow(row);
874
+ }
875
+ createAndAddNewRow() {
876
+ if (this.newRowCreator) {
877
+ const newRow = this.newRowCreator();
878
+ if (newRow)
879
+ this.addNewRow(newRow);
880
+ } else {
881
+ console.error("newRowCreator is missing.");
882
+ }
883
+ }
884
+ }
885
+ const gridColumnSettingChanged = async (grid, control, gridId, columnSettings, fixedColumnCount) => {
886
+ if (grid) {
887
+ grid.columnSettings = columnSettings;
888
+ grid.fixedColumnCount = fixedColumnCount;
889
+ }
890
+ if (control) {
891
+ control.columnSettings = columnSettings;
892
+ control.fixedColumnCount = fixedColumnCount;
893
+ }
894
+ await storeGridColumnSettingPreference();
895
+ };
896
+ class GridPreferenceLoader {
897
+ gridId;
898
+ handler;
899
+ preferenceLoaded = vue.ref(true);
900
+ loadPromise = void 0;
901
+ constructor(gridId, handler) {
902
+ this.gridId = gridId;
903
+ this.handler = handler;
904
+ }
905
+ async loadGridPreference() {
906
+ console.log(this.gridId, this.handler);
907
+ }
908
+ async waitForLoaded() {
909
+ if (this.loadPromise)
910
+ await Promise.any([this.loadPromise, openBlueseaCore.waitDuring(1e3)]);
911
+ }
912
+ }
913
+ class LocalStorageGridPreferenceStore {
914
+ async storePreference(gridId, preference) {
915
+ localStorage.setItem(`bs-pref-${gridId}`, JSON.stringify(preference));
916
+ }
917
+ async loadPreference(gridId) {
918
+ const json = localStorage.getItem(`bs-pref-${gridId}`);
919
+ return json ? JSON.parse(json) : void 0;
920
+ }
921
+ async removePreference(gridId) {
922
+ localStorage.removeItem(`bs-pref-${gridId}`);
923
+ }
924
+ }
925
+ const storeGridColumnSettingPreference = async (_gridId, _columnSettings, _fixedColumnCount) => {
926
+ };
927
+ const getCellText = (cell) => {
928
+ return cell?.textContent?.trim() || "";
929
+ };
930
+ const mergeSameValueVertical = (propertyIds, table) => {
931
+ if (table) {
932
+ propertyIds.forEach((propertyId) => {
933
+ const cells = table.querySelectorAll(`tbody tr > td[data-property-id="${propertyId}"]`);
934
+ for (let idx = 0; idx < cells.length; idx++) {
935
+ const value = getCellText(cells[idx]);
936
+ if (!value)
937
+ continue;
938
+ let count = 0;
939
+ for (let idxNext = idx + 1; idxNext < cells.length; idxNext++) {
940
+ const next = getCellText(cells[idxNext]);
941
+ if (!next || next !== value)
942
+ break;
943
+ count++;
944
+ }
945
+ if (count > 0) {
946
+ const cell = cells[idx];
947
+ cell.setAttribute("rowspan", `${count + 1}`);
948
+ cell.classList.add("bs-grid-merged-cell");
949
+ for (let hide = idx + 1; hide < idx + count + 1; hide++) {
950
+ cells[hide].style.display = "none";
951
+ }
952
+ }
953
+ idx += count;
954
+ }
955
+ });
956
+ }
957
+ };
958
+ const defaultCellFormatter = (column, value) => {
959
+ if (column.cellType === "NUMBER") {
960
+ return openBlueseaCore.formatUtil.formatNumber(Number(value));
961
+ } else if (column.cellType === "PERCENTAGE") {
962
+ return openBlueseaCore.formatUtil.formatPercent(Number(value));
963
+ } else {
964
+ return value;
965
+ }
966
+ };
967
+ const setFixedCellLeftStyle = async (table) => {
968
+ if (table) {
969
+ await vue.nextTick();
970
+ const header = table.querySelector("tr.header-row");
971
+ if (header) {
972
+ const widths = [];
973
+ const headerCells = header.querySelectorAll("th.fixed");
974
+ headerCells.forEach((th) => {
975
+ const width = th.getBoundingClientRect().width;
976
+ widths.push(Math.floor(width));
977
+ });
978
+ let acc = 0;
979
+ for (let idx = 0; idx < widths.length; ++idx) {
980
+ widths[idx] = acc += widths[idx];
981
+ }
982
+ widths.unshift(0);
983
+ headerCells.forEach((th, idx) => th.style.left = `${widths[idx]}px`);
984
+ table.querySelectorAll("tr.data-row").forEach((tr) => {
985
+ tr.querySelectorAll("td.fixed").forEach((td, idx) => td.style.left = `${widths[idx]}px`);
986
+ });
987
+ header.querySelectorAll("th:not(.fixed)").forEach((th) => th.style.left = "auto");
988
+ }
989
+ }
990
+ };
991
+ const styleCssToObject = (style) => {
992
+ const result = {};
993
+ style?.split(";").forEach((item) => {
994
+ const [key, value] = item.split(":");
995
+ if (key && value)
996
+ result[key.trim()] = value.trim();
997
+ });
998
+ return result;
999
+ };
1000
+ const styleClassToObject = (style) => {
1001
+ const result = {};
1002
+ style?.split(/\s/).filter((item) => item).forEach((item) => {
1003
+ result[item] = true;
1004
+ });
1005
+ return result;
1006
+ };
1007
+ const filterSlotName = (column) => {
1008
+ return `${column.propertyId}Filter`;
1009
+ };
1010
+ const editComponentSlotName = (column) => {
1011
+ return `${column.propertyId}Edit`;
1012
+ };
1013
+ const mergeColumnSettings = (columns, settings) => {
1014
+ const newSettings = settings.filter((col) => columns.find((baseCol) => baseCol.propertyId === col.propertyId));
1015
+ const added = columns.filter((baseCol) => !newSettings.find((col) => col.propertyId === baseCol.propertyId));
1016
+ added.forEach((addedCol) => {
1017
+ const addedColSetting = {
1018
+ propertyId: addedCol.propertyId,
1019
+ width: addedCol.width
1020
+ };
1021
+ const index = columns.findIndex((col) => col.propertyId === addedCol.propertyId);
1022
+ if (index === 0) {
1023
+ newSettings.splice(0, 0, addedColSetting);
1024
+ } else if (index > 0) {
1025
+ const prev = columns[index - 1];
1026
+ const prevIndex = newSettings.findIndex((col) => col.propertyId === prev.propertyId);
1027
+ if (prevIndex >= 0) {
1028
+ newSettings.splice(prevIndex + 1, 0, addedColSetting);
1029
+ } else {
1030
+ newSettings.push(addedColSetting);
1031
+ }
1032
+ } else {
1033
+ newSettings.push(addedColSetting);
1034
+ }
1035
+ });
1036
+ return newSettings;
1037
+ };
1038
+ const COLUMN_MIN_WIDTH = 24;
1039
+ const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
1040
+ __name: "BSGridHeaderCellResizeHandle",
1041
+ props: {
1042
+ column: {}
1043
+ },
1044
+ emits: ["columnResized"],
1045
+ setup(__props, { emit: __emit }) {
1046
+ const props = __props;
1047
+ const emit = __emit;
1048
+ let startPosition = void 0;
1049
+ let deltaX = vue.ref(0);
1050
+ let startWidth = 0;
1051
+ const resizeGuideHeight = vue.ref();
1052
+ const startResize = (event) => {
1053
+ const target = event.target;
1054
+ target.setPointerCapture(event.pointerId);
1055
+ startWidth = props.column.render.width;
1056
+ startPosition = { x: event.clientX };
1057
+ resizeGuideHeight.value = `${getTableWrapHeight() || 30}px`;
1058
+ window.addEventListener("pointerup", endResize);
1059
+ };
1060
+ const doResize = (event) => {
1061
+ if (startPosition) {
1062
+ const min = COLUMN_MIN_WIDTH - startWidth;
1063
+ deltaX.value = Math.max(min, event.clientX - startPosition.x);
1064
+ }
1065
+ };
1066
+ const endResize = (event) => {
1067
+ if (startPosition) {
1068
+ const target = event.target;
1069
+ target.releasePointerCapture(event.pointerId);
1070
+ const newWidth = startWidth + (event.clientX - startPosition.x);
1071
+ const normalized = Math.max(COLUMN_MIN_WIDTH, Math.ceil(newWidth));
1072
+ if (props.column.render.width !== normalized) {
1073
+ props.column.render.width = normalized;
1074
+ }
1075
+ startPosition = void 0;
1076
+ deltaX.value = 0;
1077
+ emit("columnResized", props.column);
1078
+ }
1079
+ window.removeEventListener("pointerup", endResize);
1080
+ };
1081
+ const resizeHandle = vue.ref();
1082
+ const getTableWrapHeight = () => {
1083
+ if (resizeHandle.value) {
1084
+ let el = resizeHandle.value;
1085
+ while (el && !el.classList.contains("table-wrap")) {
1086
+ el = el.parentElement;
1087
+ }
1088
+ if (el) return el.offsetHeight;
1089
+ }
1090
+ };
1091
+ return (_ctx, _cache) => {
1092
+ return vue.openBlock(), vue.createElementBlock("div", {
1093
+ ref_key: "resizeHandle",
1094
+ ref: resizeHandle,
1095
+ class: "resize-handle",
1096
+ onPointerdown: startResize,
1097
+ onPointermove: doResize,
1098
+ onPointerup: endResize
1099
+ }, [
1100
+ vue.withDirectives(vue.createElementVNode("div", {
1101
+ style: vue.normalizeStyle({ transform: `translateX(${vue.unref(deltaX)}px)`, height: resizeGuideHeight.value }),
1102
+ class: "resize-guide"
1103
+ }, null, 4), [
1104
+ [vue.vShow, vue.unref(startPosition)]
1105
+ ])
1106
+ ], 544);
1107
+ };
1108
+ }
1109
+ });
1110
+ const _export_sfc = (sfc, props) => {
1111
+ const target = sfc.__vccOpts || sfc;
1112
+ for (const [key, val] of props) {
1113
+ target[key] = val;
1114
+ }
1115
+ return target;
1116
+ };
1117
+ const BSGridHeaderCellResizeHandle = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["__scopeId", "data-v-3bda3a20"]]);
1118
+ const _hoisted_1$d = ["data-property-id"];
1119
+ const _hoisted_2$8 = { class: "bs-layout-horizontal align-items-center" };
1120
+ const _hoisted_3$4 = ["textContent"];
1121
+ const _hoisted_4$4 = ["textContent"];
1122
+ const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
1123
+ __name: "BSGridHeaderCell",
1124
+ props: {
1125
+ column: {},
1126
+ columns: {},
1127
+ sorts: {},
1128
+ gridId: {},
1129
+ extensionHandler: {}
1130
+ },
1131
+ emits: ["sort", "columnResized", "toggleColumnFixed", "hideColumn", "restoreAllColumnSettings"],
1132
+ setup(__props, { emit: __emit }) {
1133
+ const props = __props;
1134
+ const emit = __emit;
1135
+ const thStyleCss = vue.computed(() => {
1136
+ return {
1137
+ minWidth: `${props.column.render.width}px`,
1138
+ maxWidth: `${props.column.render.width}px`
1139
+ // left 는 BSGrid 의 onMounted 에서 설정함
1140
+ };
1141
+ });
1142
+ const styleCss = vue.computed(() => {
1143
+ return styleCssToObject(props.column.headerCellStyleCss);
1144
+ });
1145
+ const styleClass = vue.computed(() => {
1146
+ return styleClassToObject(props.column.headerCellStyleClass);
1147
+ });
1148
+ const ascending = vue.computed(() => {
1149
+ const sortPropertyId = props.column.sortPropertyId || props.column.propertyId;
1150
+ const sort2 = props.sorts?.find((sort3) => sort3.propertyId === sortPropertyId);
1151
+ return sort2 ? sort2.ascending : void 0;
1152
+ });
1153
+ const sort = () => emit("sort", props.column, !ascending.value);
1154
+ const columnResized = (column) => emit("columnResized", column);
1155
+ const slots = vue.useSlots();
1156
+ const hasFilter = vue.computed(() => !!slots.filter);
1157
+ const contextMenu = openBlueseaCore.useContextMenu();
1158
+ const showContextMenu = (event) => {
1159
+ const menus = [
1160
+ {
1161
+ type: "menu",
1162
+ caption: "Fixed",
1163
+ handler: () => emit("toggleColumnFixed", props.column.propertyId)
1164
+ },
1165
+ {
1166
+ type: "menu",
1167
+ caption: "Hide Column",
1168
+ handler: () => emit("hideColumn", props.column.propertyId)
1169
+ },
1170
+ { type: "separator" },
1171
+ {
1172
+ type: "menu",
1173
+ caption: "Restore All",
1174
+ handler: () => emit("restoreAllColumnSettings")
1175
+ }
1176
+ ];
1177
+ const param = {
1178
+ type: "HeaderCell",
1179
+ column: props.column
1180
+ };
1181
+ const extMenus = props.extensionHandler?.handleExtendsContextMenu(
1182
+ event,
1183
+ param
1184
+ );
1185
+ if (extMenus) {
1186
+ menus.push({ type: "separator" });
1187
+ menus.push(...extMenus);
1188
+ }
1189
+ contextMenu.showContextMenu(event, menus);
1190
+ };
1191
+ return (_ctx, _cache) => {
1192
+ return vue.openBlock(), vue.createElementBlock("th", {
1193
+ class: vue.normalizeClass({ fixed: __props.column.render.fixed, "has-filter": hasFilter.value }),
1194
+ "data-property-id": __props.column.propertyId,
1195
+ style: vue.normalizeStyle(thStyleCss.value),
1196
+ onContextmenu: vue.withModifiers(showContextMenu, ["prevent", "stop"])
1197
+ }, [
1198
+ vue.createElementVNode("div", {
1199
+ class: vue.normalizeClass([styleClass.value, "position-relative"]),
1200
+ style: vue.normalizeStyle(styleCss.value)
1201
+ }, [
1202
+ vue.createElementVNode("div", _hoisted_2$8, [
1203
+ vue.createElementVNode("span", {
1204
+ textContent: vue.toDisplayString(__props.column.caption),
1205
+ class: "grow text-truncate"
1206
+ }, null, 8, _hoisted_3$4),
1207
+ __props.column.sortable ? (vue.openBlock(), vue.createElementBlock("span", {
1208
+ key: 0,
1209
+ class: vue.normalizeClass([{
1210
+ "text-gray-400": ascending.value === void 0,
1211
+ descending: !ascending.value
1212
+ }, "sort-icon font-icon bs-clickable"]),
1213
+ onClick: sort,
1214
+ textContent: vue.toDisplayString(ascending.value === void 0 ? "swap_vert" : "straight")
1215
+ }, null, 10, _hoisted_4$4)) : vue.createCommentVNode("", true)
1216
+ ]),
1217
+ vue.renderSlot(_ctx.$slots, "filter", {}, void 0, true),
1218
+ vue.createVNode(BSGridHeaderCellResizeHandle, {
1219
+ column: __props.column,
1220
+ onColumnResized: columnResized
1221
+ }, null, 8, ["column"])
1222
+ ], 6)
1223
+ ], 46, _hoisted_1$d);
1224
+ };
1225
+ }
1226
+ });
1227
+ const BSGridHeaderCell = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["__scopeId", "data-v-e140e95e"]]);
1228
+ const _hoisted_1$c = { class: "checkbox bs-clickable" };
1229
+ const _hoisted_2$7 = { class: "font-icon" };
1230
+ const _sfc_main$f = /* @__PURE__ */ vue.defineComponent({
1231
+ __name: "BSGridHeaderCellCheckbox",
1232
+ props: {
1233
+ selectedRowCount: {}
1234
+ },
1235
+ emits: ["click"],
1236
+ setup(__props, { emit: __emit }) {
1237
+ const props = __props;
1238
+ const emit = __emit;
1239
+ const checked = vue.computed(() => props.selectedRowCount > 0);
1240
+ return (_ctx, _cache) => {
1241
+ return vue.openBlock(), vue.createElementBlock("th", {
1242
+ class: vue.normalizeClass([{ checked: checked.value }, "fixed func-cell"]),
1243
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("click"))
1244
+ }, [
1245
+ vue.createElementVNode("div", _hoisted_1$c, [
1246
+ vue.createElementVNode("span", _hoisted_2$7, vue.toDisplayString(checked.value ? "check_box" : "check_box_outline_blank"), 1)
1247
+ ])
1248
+ ], 2);
1249
+ };
1250
+ }
1251
+ });
1252
+ const _sfc_main$e = {};
1253
+ const _hoisted_1$b = { class: "fixed func-cell serial-no min-w-48" };
1254
+ function _sfc_render(_ctx, _cache) {
1255
+ return vue.openBlock(), vue.createElementBlock("th", _hoisted_1$b, [..._cache[0] || (_cache[0] = [
1256
+ vue.createElementVNode("div", null, [
1257
+ vue.createElementVNode("span", { class: "font-icon" }, "numbers")
1258
+ ], -1)
1259
+ ])]);
1260
+ }
1261
+ const BSGridHeaderCellSerialNo = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render]]);
1262
+ const _hoisted_1$a = ["data-property-id"];
1263
+ const _sfc_main$d = /* @__PURE__ */ vue.defineComponent({
1264
+ __name: "BSGridCell",
1265
+ props: {
1266
+ column: {},
1267
+ columns: {},
1268
+ row: {},
1269
+ editing: { type: Boolean },
1270
+ selectOnClick: { type: Boolean },
1271
+ disableSelection: { type: Boolean }
1272
+ },
1273
+ emits: ["toggleSelection"],
1274
+ setup(__props, { emit: __emit }) {
1275
+ const props = __props;
1276
+ const emit = __emit;
1277
+ const slots = vue.useSlots();
1278
+ const tdStyleCss = vue.computed(() => {
1279
+ return {
1280
+ minWidth: `${props.column.render.width}px`,
1281
+ maxWidth: `${props.column.render.width}px`
1282
+ // left 는 BSGrid 의 onMounted 에서 설정함
1283
+ };
1284
+ });
1285
+ const tdStyleClass = vue.computed(() => {
1286
+ return {
1287
+ fixed: props.column.render.fixed,
1288
+ "text-right": ["NUMBER", "MONEY", "PERCENTAGE"].includes(
1289
+ props.column.cellType || ""
1290
+ ),
1291
+ editing: props.editing && slots[`${props.column.templateId}Edit`],
1292
+ "cursor-pointer": props.selectOnClick
1293
+ };
1294
+ });
1295
+ const cellValue = vue.computed(() => {
1296
+ const properties = props.column.propertyId.split(".");
1297
+ let value = props.row;
1298
+ for (let index = 0; index < properties.length; ++index) {
1299
+ if (!value || typeof value !== "object" || !(properties[index] in value)) {
1300
+ return "";
1301
+ }
1302
+ value = value[properties[index]];
1303
+ }
1304
+ return value ?? "";
1305
+ });
1306
+ const formattedCellValue = vue.computed(() => {
1307
+ return defaultCellFormatter(props.column, cellValue.value);
1308
+ });
1309
+ const clickTd = () => {
1310
+ if (props.selectOnClick && !props.disableSelection) {
1311
+ emit("toggleSelection", props.column);
1312
+ }
1313
+ };
1314
+ const cellDiv = vue.ref();
1315
+ const tooltipText = vue.ref();
1316
+ vue.watch(
1317
+ () => props.column.render.width,
1318
+ async () => {
1319
+ await vue.nextTick();
1320
+ if (!props.editing && cellDiv.value && cellDiv.value.scrollWidth > cellDiv.value.clientWidth) {
1321
+ if (props.column.tooltipProvider) {
1322
+ tooltipText.value = props.column.tooltipProvider(props.row);
1323
+ } else {
1324
+ tooltipText.value = cellDiv.value.innerText;
1325
+ }
1326
+ } else {
1327
+ tooltipText.value = void 0;
1328
+ }
1329
+ },
1330
+ { immediate: true }
1331
+ );
1332
+ return (_ctx, _cache) => {
1333
+ return vue.openBlock(), vue.createElementBlock("td", {
1334
+ class: vue.normalizeClass(tdStyleClass.value),
1335
+ "data-property-id": __props.column.propertyId,
1336
+ style: vue.normalizeStyle(tdStyleCss.value),
1337
+ onClick: clickTd
1338
+ }, [
1339
+ vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", {
1340
+ ref_key: "cellDiv",
1341
+ ref: cellDiv,
1342
+ class: vue.normalizeClass([__props.column.cellStyleClass, "text-nowrap text-ellipsis"]),
1343
+ style: vue.normalizeStyle(__props.column.cellStyleCss)
1344
+ }, [
1345
+ __props.editing ? vue.renderSlot(_ctx.$slots, `${__props.column.templateId}Edit`, {
1346
+ key: 0,
1347
+ cell: cellValue.value,
1348
+ propertyId: __props.column.propertyId,
1349
+ row: __props.row
1350
+ }, () => [
1351
+ vue.renderSlot(_ctx.$slots, __props.column.templateId, {
1352
+ cell: cellValue.value,
1353
+ propertyId: __props.column.propertyId,
1354
+ row: __props.row
1355
+ }, () => [
1356
+ vue.createTextVNode(vue.toDisplayString(formattedCellValue.value), 1)
1357
+ ])
1358
+ ]) : vue.renderSlot(_ctx.$slots, __props.column.templateId, {
1359
+ key: 1,
1360
+ cell: cellValue.value,
1361
+ propertyId: __props.column.propertyId,
1362
+ row: __props.row
1363
+ }, () => [
1364
+ vue.createTextVNode(vue.toDisplayString(formattedCellValue.value), 1)
1365
+ ])
1366
+ ], 6)), [
1367
+ [vue.unref(openBlueseaCore.vTooltip), { content: tooltipText.value }]
1368
+ ])
1369
+ ], 14, _hoisted_1$a);
1370
+ };
1371
+ }
1372
+ });
1373
+ const _hoisted_1$9 = { class: "fixed func-cell serial-no" };
1374
+ const _sfc_main$c = /* @__PURE__ */ vue.defineComponent({
1375
+ __name: "BSGridCellSerialNo",
1376
+ props: {
1377
+ serialNo: {}
1378
+ },
1379
+ setup(__props) {
1380
+ return (_ctx, _cache) => {
1381
+ return vue.openBlock(), vue.createElementBlock("td", _hoisted_1$9, [
1382
+ vue.createElementVNode("div", null, vue.toDisplayString(__props.serialNo), 1)
1383
+ ]);
1384
+ };
1385
+ }
1386
+ });
1387
+ const _hoisted_1$8 = { class: "font-icon" };
1388
+ const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
1389
+ __name: "BSGridCellCheckbox",
1390
+ props: {
1391
+ checked: { type: Boolean },
1392
+ disabled: { type: Boolean }
1393
+ },
1394
+ emits: ["click"],
1395
+ setup(__props, { emit: __emit }) {
1396
+ const props = __props;
1397
+ const emit = __emit;
1398
+ const toggleCheckbox = () => {
1399
+ if (!props.disabled) emit("click");
1400
+ };
1401
+ return (_ctx, _cache) => {
1402
+ return vue.openBlock(), vue.createElementBlock("td", {
1403
+ class: vue.normalizeClass([{ checked: __props.checked, disabled: __props.disabled }, "fixed func-cell"]),
1404
+ onClick: toggleCheckbox
1405
+ }, [
1406
+ vue.createElementVNode("div", {
1407
+ class: vue.normalizeClass([{ "bs-clickable": !__props.disabled }, "checkbox"])
1408
+ }, [
1409
+ vue.createElementVNode("div", _hoisted_1$8, vue.toDisplayString(__props.checked ? "check_box" : "check_box_outline_blank"), 1)
1410
+ ], 2)
1411
+ ], 2);
1412
+ };
1413
+ }
1414
+ });
1415
+ const BSGridCellCheckbox = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-0211159f"]]);
1416
+ const _hoisted_1$7 = { class: "fixed func-cell cursor-pointer" };
1417
+ const _hoisted_2$6 = { class: "font-icon" };
1418
+ const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
1419
+ __name: "BSGridCellEdit",
1420
+ props: {
1421
+ isEditing: { type: Boolean },
1422
+ showEditIcon: { type: Boolean }
1423
+ },
1424
+ emits: ["toggleEditMode"],
1425
+ setup(__props, { emit: __emit }) {
1426
+ const emit = __emit;
1427
+ return (_ctx, _cache) => {
1428
+ return vue.openBlock(), vue.createElementBlock("td", _hoisted_1$7, [
1429
+ __props.showEditIcon ? (vue.openBlock(), vue.createElementBlock("div", {
1430
+ key: 0,
1431
+ onClick: _cache[0] || (_cache[0] = vue.withModifiers(($event) => emit("toggleEditMode"), ["stop"]))
1432
+ }, [
1433
+ vue.createElementVNode("span", _hoisted_2$6, vue.toDisplayString(__props.isEditing ? "replay" : "stylus"), 1)
1434
+ ])) : vue.createCommentVNode("", true)
1435
+ ]);
1436
+ };
1437
+ }
1438
+ });
1439
+ let dndContext;
1440
+ const vDragSupport = {
1441
+ mounted: (el, binding) => {
1442
+ const draggable = binding.value.draggable;
1443
+ const sourceElement = binding.value.sourceProvider ? binding.value.sourceProvider(el) : el;
1444
+ const keyProvider = binding.value.keyProvider;
1445
+ const sourceType = binding.value.sourceType;
1446
+ const dropEffect = binding.value.dropEffect || "move";
1447
+ if (draggable) {
1448
+ el.draggable = true;
1449
+ el.ondragstart = (event) => {
1450
+ if (event.dataTransfer) {
1451
+ event.dataTransfer.dropEffect = dropEffect;
1452
+ event.dataTransfer.setDragImage(sourceElement, 0, 0);
1453
+ }
1454
+ dndContext = {
1455
+ sourceElement,
1456
+ key: keyProvider?.(sourceElement),
1457
+ sourceType
1458
+ };
1459
+ event.stopPropagation();
1460
+ };
1461
+ el.ondragend = () => {
1462
+ if (dndContext) {
1463
+ dndContext.dropPosition?.remove();
1464
+ dndContext = void 0;
1465
+ }
1466
+ };
1467
+ }
1468
+ }
1469
+ };
1470
+ const vDropSupport = {
1471
+ mounted: (el, binding) => {
1472
+ const droppable = binding.value.droppable;
1473
+ const isDroppable = binding.value.isDroppable;
1474
+ const createDropPosition = binding.value.createDropPosition || defaultCreateDropPosition;
1475
+ const locateDropPosition = binding.value.locateDropPosition || defaultLocateDropPosition;
1476
+ const dropHandler = binding.value.dropHandler;
1477
+ const direction = binding.value.direction || "vertical";
1478
+ if (droppable) {
1479
+ el.ondragover = (event) => {
1480
+ if (dndContext) {
1481
+ const target = event.currentTarget;
1482
+ if (!isDroppable || isDroppable(dndContext, target)) {
1483
+ const beforeOrAfter = direction === "horizontal" ? checkLeftOrRight(target, event) : checkUpOrDown(target, event);
1484
+ if (!dndContext.dropPosition) {
1485
+ dndContext.dropPosition = createDropPosition(dndContext, target, direction);
1486
+ }
1487
+ locateDropPosition(dndContext, target, dndContext.dropPosition, beforeOrAfter, direction);
1488
+ event.preventDefault();
1489
+ event.stopPropagation();
1490
+ }
1491
+ }
1492
+ };
1493
+ el.ondragleave = (event) => {
1494
+ const target = event.currentTarget;
1495
+ if (dndContext && dndContext.dropPosition && !openBlueseaCore.componentUtil.isCursorInElement(event, target) && !openBlueseaCore.componentUtil.isCursorInElement(event, dndContext.dropPosition)) {
1496
+ dndContext.dropPosition.remove();
1497
+ }
1498
+ event.preventDefault();
1499
+ event.stopPropagation();
1500
+ };
1501
+ el.ondrop = (event) => {
1502
+ if (dndContext) {
1503
+ const target = event.currentTarget;
1504
+ if (!isDroppable || isDroppable(dndContext, target)) {
1505
+ const beforeOrAfter = direction === "horizontal" ? checkLeftOrRight(target, event) : checkUpOrDown(target, event);
1506
+ dropHandler?.(dndContext, target, beforeOrAfter);
1507
+ }
1508
+ }
1509
+ };
1510
+ }
1511
+ }
1512
+ };
1513
+ const defaultCreateDropPosition = (_dndContext, target, direction) => {
1514
+ const div = target.ownerDocument.createElement("DIV");
1515
+ div.className = `bs-drop-position ${direction}`;
1516
+ return div;
1517
+ };
1518
+ const defaultLocateDropPosition = (_dndContext, target, dropPosition, beforeOrAfter) => {
1519
+ target.appendChild(dropPosition);
1520
+ dropPosition.classList.remove("before", "after");
1521
+ dropPosition.classList.add(beforeOrAfter);
1522
+ };
1523
+ const checkLeftOrRight = (target, event) => {
1524
+ const targetRect = target.getBoundingClientRect();
1525
+ const x = event.clientX - targetRect.left;
1526
+ return x < targetRect.width / 2 ? "before" : "after";
1527
+ };
1528
+ const checkUpOrDown = (target, event) => {
1529
+ const targetRect = target.getBoundingClientRect();
1530
+ const y = event.clientY - targetRect.top;
1531
+ return y < targetRect.height / 2 ? "before" : "after";
1532
+ };
1533
+ const _hoisted_1$6 = {
1534
+ class: "fixed func-cell drag-handle",
1535
+ draggable: "true"
1536
+ };
1537
+ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
1538
+ __name: "BSGridCellDragHandle",
1539
+ props: {
1540
+ rowIndex: {}
1541
+ },
1542
+ setup(__props) {
1543
+ return (_ctx, _cache) => {
1544
+ return vue.withDirectives((vue.openBlock(), vue.createElementBlock("td", _hoisted_1$6, [..._cache[0] || (_cache[0] = [
1545
+ vue.createElementVNode("div", { class: "font-icon" }, "drag_handle", -1)
1546
+ ])])), [
1547
+ [vue.unref(vDragSupport), {
1548
+ draggable: true,
1549
+ sourceProvider: (td) => td.parentElement,
1550
+ keyProvider: () => __props.rowIndex,
1551
+ sourceType: "grid-row"
1552
+ }]
1553
+ ]);
1554
+ };
1555
+ }
1556
+ });
1557
+ const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
1558
+ __name: "BSGridRow",
1559
+ props: {
1560
+ row: {},
1561
+ rowIndex: {},
1562
+ rowKey: {},
1563
+ allRows: {},
1564
+ columns: {},
1565
+ visibleColumns: {},
1566
+ fixedColumns: {},
1567
+ pageInfo: {},
1568
+ showSerial: { type: Boolean },
1569
+ showCheckbox: { type: Boolean },
1570
+ showDragHandle: { type: Boolean },
1571
+ selectedRows: {},
1572
+ editable: { type: Boolean },
1573
+ rowEditable: { type: Boolean },
1574
+ hideEditIcon: { type: Boolean },
1575
+ editingRow: {},
1576
+ isEditing: { type: Boolean },
1577
+ selectOnClick: { type: Boolean },
1578
+ disableSelection: { type: Boolean },
1579
+ disableUnselectedRowsSelection: { type: Boolean }
1580
+ },
1581
+ emits: ["toggleSelection", "enterEditMode", "cancelEditMode", "rowMoved"],
1582
+ setup(__props, { emit: __emit }) {
1583
+ const props = __props;
1584
+ const emit = __emit;
1585
+ const isRowSelected = vue.computed(() => props.selectedRows.has(props.row));
1586
+ const toggleSelection = () => {
1587
+ emit("toggleSelection", props.row);
1588
+ };
1589
+ const enterEditMode = () => {
1590
+ if (props.editable && props.rowEditable) emit("enterEditMode", props.row, savePoint);
1591
+ };
1592
+ const toggleEditMode = () => {
1593
+ if (props.editable && props.rowEditable) {
1594
+ props.isEditing ? emit("cancelEditMode", props.row) : enterEditMode();
1595
+ }
1596
+ };
1597
+ const savePoint = openBlueseaCore.provideSavePoint();
1598
+ vue.watch(
1599
+ () => props.isEditing,
1600
+ async () => {
1601
+ if (props.isEditing) {
1602
+ await savePoint.setNextTick();
1603
+ if (props.editingRow && !props.editingRow.savePoint) {
1604
+ props.editingRow.savePoint = savePoint;
1605
+ }
1606
+ } else {
1607
+ savePoint.rollback();
1608
+ }
1609
+ },
1610
+ { immediate: true }
1611
+ );
1612
+ openBlueseaCore.provideFieldContext({
1613
+ iteration: {
1614
+ componentName: "BSGrid",
1615
+ record: props.row,
1616
+ recordKey: props.rowKey,
1617
+ recordIndex: props.rowIndex,
1618
+ data: props.allRows
1619
+ }
1620
+ });
1621
+ const isDroppable = (dndContext2, target) => {
1622
+ const src = dndContext2.sourceElement;
1623
+ return src.tagName === "TR" && src.parentElement === target.parentElement;
1624
+ };
1625
+ const dropHandler = (dndContext2, _target, beforeOrAfter) => {
1626
+ const srcIndex = dndContext2.key;
1627
+ if (srcIndex !== void 0) {
1628
+ emit("rowMoved", srcIndex, props.rowIndex, beforeOrAfter === "before");
1629
+ }
1630
+ };
1631
+ return (_ctx, _cache) => {
1632
+ return vue.withDirectives((vue.openBlock(), vue.createElementBlock("tr", {
1633
+ class: vue.normalizeClass([{ selected: isRowSelected.value }, "data-row"]),
1634
+ onDblclick: vue.withModifiers(enterEditMode, ["stop"])
1635
+ }, [
1636
+ __props.showDragHandle ? (vue.openBlock(), vue.createBlock(_sfc_main$9, {
1637
+ key: 0,
1638
+ "row-index": __props.rowIndex
1639
+ }, null, 8, ["row-index"])) : vue.createCommentVNode("", true),
1640
+ __props.showCheckbox ? (vue.openBlock(), vue.createBlock(BSGridCellCheckbox, {
1641
+ key: 1,
1642
+ checked: isRowSelected.value,
1643
+ disabled: __props.disableSelection || __props.disableUnselectedRowsSelection && !isRowSelected.value,
1644
+ onClick: toggleSelection
1645
+ }, null, 8, ["checked", "disabled"])) : vue.createCommentVNode("", true),
1646
+ __props.editable && !__props.hideEditIcon ? (vue.openBlock(), vue.createBlock(_sfc_main$a, {
1647
+ key: 2,
1648
+ "is-editing": __props.isEditing,
1649
+ "show-edit-icon": __props.rowEditable,
1650
+ onToggleEditMode: toggleEditMode
1651
+ }, null, 8, ["is-editing", "show-edit-icon"])) : vue.createCommentVNode("", true),
1652
+ __props.showSerial ? (vue.openBlock(), vue.createBlock(_sfc_main$c, {
1653
+ key: 3,
1654
+ "serial-no": __props.rowIndex + (__props.pageInfo?.offset || 0) + 1
1655
+ }, null, 8, ["serial-no"])) : vue.createCommentVNode("", true),
1656
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.visibleColumns, (column) => {
1657
+ return vue.openBlock(), vue.createBlock(_sfc_main$d, {
1658
+ key: `${column.propertyId}${__props.isEditing ? "Edit" : ""}`,
1659
+ column,
1660
+ columns: __props.columns,
1661
+ "disable-selection": __props.disableSelection,
1662
+ editing: __props.isEditing,
1663
+ row: __props.row,
1664
+ "select-on-click": __props.selectOnClick,
1665
+ onToggleSelection: toggleSelection
1666
+ }, vue.createSlots({ _: 2 }, [
1667
+ _ctx.$slots[column.templateId] ? {
1668
+ name: column.templateId,
1669
+ fn: vue.withCtx(({ row, cell, propertyId }) => [
1670
+ vue.renderSlot(_ctx.$slots, column.templateId, {
1671
+ cell,
1672
+ propertyId,
1673
+ row
1674
+ })
1675
+ ]),
1676
+ key: "0"
1677
+ } : void 0,
1678
+ _ctx.$slots[`${column.templateId}Edit`] ? {
1679
+ name: `${column.templateId}Edit`,
1680
+ fn: vue.withCtx(({ row, cell, propertyId }) => [
1681
+ vue.renderSlot(_ctx.$slots, `${column.templateId}Edit`, {
1682
+ cell,
1683
+ propertyId,
1684
+ row
1685
+ })
1686
+ ]),
1687
+ key: "1"
1688
+ } : void 0
1689
+ ]), 1032, ["column", "columns", "disable-selection", "editing", "row", "select-on-click"]);
1690
+ }), 128))
1691
+ ], 34)), [
1692
+ [vue.unref(vDropSupport), { droppable: __props.showDragHandle, isDroppable, dropHandler }]
1693
+ ]);
1694
+ };
1695
+ }
1696
+ });
1697
+ const _hoisted_1$5 = { class: "table-wrap" };
1698
+ const _hoisted_2$5 = { class: "header-row" };
1699
+ const _hoisted_3$3 = {
1700
+ key: 0,
1701
+ class: "fixed func-cell"
1702
+ };
1703
+ const _hoisted_4$3 = {
1704
+ key: 2,
1705
+ class: "fixed func-cell edit-icon"
1706
+ };
1707
+ const _hoisted_5$2 = { key: 0 };
1708
+ const _hoisted_6$1 = { key: 1 };
1709
+ const _hoisted_7$1 = ["textContent"];
1710
+ const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
1711
+ __name: "BSGrid",
1712
+ props: {
1713
+ gridId: {},
1714
+ columns: { default: () => [] },
1715
+ data: {},
1716
+ pageInfo: {},
1717
+ sorts: {},
1718
+ loading: { type: Boolean },
1719
+ width: { default: "100%" },
1720
+ height: { default: "auto" },
1721
+ fixedColumnCount: { default: 0 },
1722
+ showSerial: { type: Boolean },
1723
+ showCheckbox: { type: Boolean },
1724
+ showDragHandle: { type: Boolean },
1725
+ showPageNavigation: { type: Boolean },
1726
+ selectOnClick: { type: Boolean },
1727
+ maxSelectCount: {},
1728
+ singleSelect: { type: Boolean },
1729
+ keyProvider: { type: Function, default: () => openBlueseaCore.emptyKeyProvider },
1730
+ selectedRows: {},
1731
+ editable: { type: Boolean },
1732
+ hideEditIcon: { type: Boolean },
1733
+ editingRows: {},
1734
+ rowEditPolicy: {},
1735
+ rowSelectPolicy: {},
1736
+ alwaysEditing: { type: Boolean },
1737
+ rowDisplayPolicy: {},
1738
+ columnSettings: {},
1739
+ extensions: {},
1740
+ emptyMessage: {}
1741
+ },
1742
+ emits: ["offsetChanged", "update:selectedRows", "changeSelectedRows", "update:editingRows", "changeEditingRow", "update:sorts", "settingChanged", "tableChanged"],
1743
+ setup(__props, { emit: __emit }) {
1744
+ const props = __props;
1745
+ const emit = __emit;
1746
+ const internalColumns = vue.computed(() => {
1747
+ const visibleColumns = props.columnSettings ? mergeColumnSettings(props.columns, props.columnSettings).filter((col) => !col.hidden).map((col) => {
1748
+ const orig = props.columns.find(
1749
+ (column) => column.propertyId === col.propertyId
1750
+ );
1751
+ return { ...orig, width: col.width || orig?.width };
1752
+ }).filter((col) => col.propertyId) : props.columns;
1753
+ return visibleColumns.map((col, index) => ({
1754
+ ...col,
1755
+ templateId: col.templateId || col.propertyId,
1756
+ // templateId 가 없으면 propertyId 를 사용한다.
1757
+ render: vue.reactive({
1758
+ width: col.width || DEFAULT_GRID_COLUMN_WIDTH,
1759
+ fixed: index < props.fixedColumnCount
1760
+ })
1761
+ }));
1762
+ });
1763
+ const fixedColumns = vue.computed(() => props.fixedColumnCount);
1764
+ vue.watch(
1765
+ () => [JSON.stringify(props.columnSettings), props.fixedColumnCount],
1766
+ async () => {
1767
+ await setFixedCellLeftStyle(table.value);
1768
+ if (props.data) emit("tableChanged", table.value);
1769
+ }
1770
+ );
1771
+ const internalSelectedRows = props.selectedRows || vue.reactive(/* @__PURE__ */ new Set());
1772
+ const disableUnselectedRowsSelection = vue.computed(
1773
+ () => !!(props.maxSelectCount && internalSelectedRows.size >= props.maxSelectCount)
1774
+ );
1775
+ const toggleSelection = (row) => {
1776
+ if (internalSelectedRows.has(row)) {
1777
+ internalSelectedRows.delete(row);
1778
+ emit("changeSelectedRows", {
1779
+ allRows: false,
1780
+ targetRows: [row],
1781
+ selected: false
1782
+ });
1783
+ } else {
1784
+ if (props.singleSelect) internalSelectedRows.clear();
1785
+ internalSelectedRows.add(row);
1786
+ emit("changeSelectedRows", {
1787
+ allRows: false,
1788
+ targetRows: [row],
1789
+ selected: true
1790
+ });
1791
+ }
1792
+ emit("update:selectedRows", internalSelectedRows);
1793
+ };
1794
+ const toggleAllSelection = () => {
1795
+ if (internalSelectedRows.size > 0) {
1796
+ internalSelectedRows.clear();
1797
+ emit("changeSelectedRows", { allRows: true, selected: false });
1798
+ } else {
1799
+ if (props.singleSelect) {
1800
+ if (props.data[0]) {
1801
+ internalSelectedRows.add(props.data[0]);
1802
+ emit("changeSelectedRows", {
1803
+ allRows: false,
1804
+ targetRows: [props.data[0]],
1805
+ selected: true
1806
+ });
1807
+ }
1808
+ } else {
1809
+ const selectable = props.rowSelectPolicy ? props.data.filter((item) => props.rowSelectPolicy(item)) : props.data;
1810
+ const data = props.maxSelectCount ? selectable.slice(0, props.maxSelectCount) : selectable;
1811
+ data.forEach((row) => internalSelectedRows.add(row));
1812
+ emit("changeSelectedRows", { allRows: true, selected: true });
1813
+ }
1814
+ }
1815
+ emit("update:selectedRows", internalSelectedRows);
1816
+ };
1817
+ const clearSelection = () => {
1818
+ if (internalSelectedRows.size > 0) {
1819
+ internalSelectedRows.clear();
1820
+ emit("changeSelectedRows", { allRows: true, selected: false });
1821
+ emit("update:selectedRows", internalSelectedRows);
1822
+ }
1823
+ };
1824
+ const table = vue.ref();
1825
+ const handleOffsetChange = (offset, currentPageInfo) => {
1826
+ emit("offsetChanged", offset, currentPageInfo);
1827
+ };
1828
+ const internalEditingRows = props.editingRows || vue.reactive(new EditingRows(props.keyProvider));
1829
+ const enterEditMode = async (row, savePoint) => {
1830
+ if (!internalEditingRows.isEditingRow(row)) {
1831
+ internalEditingRows.addEditingRow({ row, savePoint });
1832
+ emit("update:editingRows", internalEditingRows);
1833
+ emit("changeEditingRow", row, true);
1834
+ await setFixedCellLeftStyle(table.value);
1835
+ emit("tableChanged", table.value);
1836
+ }
1837
+ };
1838
+ const cancelEditMode = async (row) => {
1839
+ if (internalEditingRows.isEditingRow(row)) {
1840
+ if (props.alwaysEditing) {
1841
+ internalEditingRows.removeRow(row);
1842
+ emit("changeEditingRow", row, false);
1843
+ await vue.nextTick();
1844
+ internalEditingRows.addEditingRow({ row });
1845
+ emit("changeEditingRow", row, true);
1846
+ } else {
1847
+ internalEditingRows.removeRow(row);
1848
+ emit("update:editingRows", internalEditingRows);
1849
+ emit("changeEditingRow", row, false);
1850
+ await setFixedCellLeftStyle(table.value);
1851
+ emit("tableChanged", table.value);
1852
+ }
1853
+ }
1854
+ };
1855
+ const clearEditing = async () => {
1856
+ if (internalEditingRows.getRows().length > 0) {
1857
+ const rows = internalEditingRows.getRows().map((row) => row.row);
1858
+ internalEditingRows.clear();
1859
+ emit("update:editingRows", internalEditingRows);
1860
+ rows.forEach((row) => emit("changeEditingRow", row, false));
1861
+ await setFixedCellLeftStyle(table.value);
1862
+ emit("tableChanged", table.value);
1863
+ }
1864
+ };
1865
+ const initEditing = () => {
1866
+ if (props.alwaysEditing) {
1867
+ props.data.forEach((row) => {
1868
+ if ((!props.rowEditPolicy || props.rowEditPolicy(row, internalEditingRows)) && !internalEditingRows.isEditingRow(row)) {
1869
+ internalEditingRows.addEditingRow({ row });
1870
+ }
1871
+ });
1872
+ }
1873
+ };
1874
+ vue.watch(
1875
+ () => [props.alwaysEditing, props.data.length],
1876
+ () => initEditing(),
1877
+ { immediate: true }
1878
+ );
1879
+ const internalSorts = props.sorts || vue.reactive([]);
1880
+ const changeSort = (column, ascending) => {
1881
+ internalSorts.splice(0, internalSorts.length);
1882
+ if (ascending !== void 0) {
1883
+ internalSorts.push({
1884
+ propertyId: column.sortPropertyId || column.propertyId,
1885
+ ascending
1886
+ });
1887
+ }
1888
+ emit("update:sorts", internalSorts);
1889
+ };
1890
+ const rowMoved = (srcIndex, destIndex, before) => {
1891
+ if (srcIndex !== destIndex) {
1892
+ const dest = destIndex - (srcIndex < destIndex ? 1 : 0) + (before ? 0 : 1);
1893
+ const src = props.data.splice(srcIndex, 1)[0];
1894
+ props.data.splice(dest, 0, src);
1895
+ }
1896
+ };
1897
+ vue.watch(
1898
+ () => [props.data, props.loading],
1899
+ async () => {
1900
+ await clearEditing();
1901
+ clearSelection();
1902
+ initEditing();
1903
+ await setFixedCellLeftStyle(table.value);
1904
+ },
1905
+ { immediate: true }
1906
+ );
1907
+ vue.watchEffect(async () => {
1908
+ if (props.data.length > 0) await setFixedCellLeftStyle(table.value);
1909
+ emit("tableChanged", table.value);
1910
+ });
1911
+ const columnResized = async (column) => {
1912
+ setColumnWidth(column.propertyId, column.render.width);
1913
+ if (column.render.fixed) await setFixedCellLeftStyle(table.value);
1914
+ };
1915
+ const parentSavePoint = openBlueseaCore.useSavePoint();
1916
+ if (parentSavePoint) {
1917
+ const childSavePoint = {
1918
+ set() {
1919
+ },
1920
+ rollback() {
1921
+ },
1922
+ isModified() {
1923
+ return !!internalEditingRows.getRows().find((row) => row.savePoint?.isModified());
1924
+ }
1925
+ };
1926
+ parentSavePoint.addChild(childSavePoint);
1927
+ vue.onBeforeUnmount(() => parentSavePoint.removeChild(childSavePoint));
1928
+ openBlueseaCore.cancelProvidedSavePoint();
1929
+ }
1930
+ const scrolledHorizontally = vue.ref(false);
1931
+ const scrolledVertically = vue.ref(false);
1932
+ vue.onMounted(() => {
1933
+ table.value?.parentElement?.addEventListener("scroll", setScrollStyle, {
1934
+ passive: true
1935
+ });
1936
+ });
1937
+ const setScrollStyle = () => {
1938
+ scrolledHorizontally.value = (table.value?.parentElement?.scrollLeft || 0) > 0;
1939
+ scrolledVertically.value = (table.value?.parentElement?.scrollTop || 0) > 0;
1940
+ };
1941
+ const getColumnSettings = () => {
1942
+ return props.columnSettings || props.columns.map((col) => ({ propertyId: col.propertyId }));
1943
+ };
1944
+ const toggleColumnFixed = (propertyId) => {
1945
+ const index = internalColumns.value.findIndex(
1946
+ (col) => col.propertyId === propertyId
1947
+ );
1948
+ const newValue = props.fixedColumnCount === index + 1 ? 0 : index + 1;
1949
+ emit("settingChanged", props.columnSettings, newValue);
1950
+ };
1951
+ const hideColumn = (propertyId) => {
1952
+ const settings = getColumnSettings();
1953
+ const column = settings.find((col) => col.propertyId === propertyId);
1954
+ if (column) column.hidden = true;
1955
+ emit("settingChanged", settings, props.fixedColumnCount);
1956
+ };
1957
+ const restoreAllColumnSettings = () => {
1958
+ emit("settingChanged", void 0, void 0);
1959
+ };
1960
+ const setColumnWidth = (propertyId, width) => {
1961
+ const settings = getColumnSettings();
1962
+ const column = settings.find((col) => col.propertyId === propertyId);
1963
+ const orig = props.columns.find((col) => col.propertyId === propertyId);
1964
+ if (column) column.width = width === orig?.width ? void 0 : width;
1965
+ emit("settingChanged", settings, props.fixedColumnCount);
1966
+ };
1967
+ const extensionHandler = {
1968
+ handleExtendsContextMenu: (event, param) => {
1969
+ const context = {
1970
+ gridId: props.gridId,
1971
+ table: table.value || void 0
1972
+ };
1973
+ return props.extensions?.flatMap((ext) => ext.extendsContextMenu?.(event, param, context)).filter(openBlueseaCore.notNull);
1974
+ }
1975
+ };
1976
+ return (_ctx, _cache) => {
1977
+ return vue.openBlock(), vue.createElementBlock("div", {
1978
+ class: vue.normalizeClass([{
1979
+ "h-scrolled": scrolledHorizontally.value,
1980
+ "v-scrolled": scrolledVertically.value
1981
+ }, "bs-grid min-h-128"]),
1982
+ style: vue.normalizeStyle({ width: __props.width, height: __props.height })
1983
+ }, [
1984
+ vue.createElementVNode("div", _hoisted_1$5, [
1985
+ vue.createElementVNode("table", {
1986
+ ref_key: "table",
1987
+ ref: table
1988
+ }, [
1989
+ vue.createElementVNode("thead", null, [
1990
+ vue.createElementVNode("tr", _hoisted_2$5, [
1991
+ __props.showDragHandle ? (vue.openBlock(), vue.createElementBlock("th", _hoisted_3$3, [..._cache[0] || (_cache[0] = [
1992
+ vue.createElementVNode("div", null, null, -1)
1993
+ ])])) : vue.createCommentVNode("", true),
1994
+ __props.showCheckbox ? (vue.openBlock(), vue.createBlock(_sfc_main$f, {
1995
+ key: 1,
1996
+ "selected-row-count": vue.unref(internalSelectedRows).size,
1997
+ onClick: toggleAllSelection
1998
+ }, null, 8, ["selected-row-count"])) : vue.createCommentVNode("", true),
1999
+ __props.editable && !__props.hideEditIcon ? (vue.openBlock(), vue.createElementBlock("th", _hoisted_4$3, [..._cache[1] || (_cache[1] = [
2000
+ vue.createElementVNode("div", null, null, -1)
2001
+ ])])) : vue.createCommentVNode("", true),
2002
+ __props.showSerial ? (vue.openBlock(), vue.createBlock(BSGridHeaderCellSerialNo, { key: 3 })) : vue.createCommentVNode("", true),
2003
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(internalColumns.value, (column) => {
2004
+ return vue.openBlock(), vue.createBlock(BSGridHeaderCell, {
2005
+ key: column.propertyId,
2006
+ column,
2007
+ columns: internalColumns.value,
2008
+ "extension-handler": extensionHandler,
2009
+ "grid-id": __props.gridId,
2010
+ sorts: vue.unref(internalSorts),
2011
+ onSort: changeSort,
2012
+ onColumnResized: columnResized,
2013
+ onToggleColumnFixed: toggleColumnFixed,
2014
+ onHideColumn: hideColumn,
2015
+ onRestoreAllColumnSettings: restoreAllColumnSettings
2016
+ }, vue.createSlots({ _: 2 }, [
2017
+ _ctx.$slots[vue.unref(filterSlotName)(column)] ? {
2018
+ name: "filter",
2019
+ fn: vue.withCtx(() => [
2020
+ vue.renderSlot(_ctx.$slots, vue.unref(filterSlotName)(column))
2021
+ ]),
2022
+ key: "0"
2023
+ } : void 0
2024
+ ]), 1032, ["column", "columns", "grid-id", "sorts"]);
2025
+ }), 128))
2026
+ ])
2027
+ ]),
2028
+ vue.createElementVNode("tbody", null, [
2029
+ __props.loading ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_5$2, [
2030
+ vue.createElementVNode("td", null, [
2031
+ vue.createVNode(vue.unref(openBlueseaCore.BSLoadingIcon), { class: "position-absolute pa-8" })
2032
+ ])
2033
+ ])) : __props.data && __props.data.length === 0 ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_6$1, [
2034
+ vue.createElementVNode("td", null, [
2035
+ vue.createElementVNode("div", {
2036
+ textContent: vue.toDisplayString(__props.emptyMessage),
2037
+ class: "position-absolute text-nowrap pa-8"
2038
+ }, null, 8, _hoisted_7$1)
2039
+ ])
2040
+ ])) : __props.data ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 2 }, vue.renderList(__props.data, (row, index) => {
2041
+ return vue.openBlock(), vue.createBlock(_sfc_main$8, {
2042
+ key: __props.keyProvider(row) || index,
2043
+ "all-rows": __props.data,
2044
+ columns: internalColumns.value,
2045
+ "disable-selection": __props.rowSelectPolicy && !__props.rowSelectPolicy(row),
2046
+ "disable-unselected-rows-selection": disableUnselectedRowsSelection.value,
2047
+ editable: __props.editable,
2048
+ "editing-row": __props.editingRows?.getEditingRow(row),
2049
+ "fixed-columns": fixedColumns.value,
2050
+ "hide-edit-icon": __props.hideEditIcon,
2051
+ "is-editing": vue.unref(internalEditingRows).isEditingRow(row),
2052
+ "page-info": __props.pageInfo,
2053
+ row,
2054
+ "row-editable": !__props.rowEditPolicy || __props.rowEditPolicy(row, vue.unref(internalEditingRows)),
2055
+ "row-index": index,
2056
+ "row-key": __props.keyProvider(row),
2057
+ "select-on-click": __props.selectOnClick,
2058
+ "selected-rows": vue.unref(internalSelectedRows),
2059
+ "show-checkbox": __props.showCheckbox,
2060
+ "show-drag-handle": __props.showDragHandle,
2061
+ "show-serial": __props.showSerial,
2062
+ style: vue.normalizeStyle({
2063
+ display: __props.rowDisplayPolicy?.(row) === false ? "none" : void 0
2064
+ }),
2065
+ "visible-columns": internalColumns.value,
2066
+ onToggleSelection: toggleSelection,
2067
+ onEnterEditMode: enterEditMode,
2068
+ onCancelEditMode: cancelEditMode,
2069
+ onRowMoved: rowMoved
2070
+ }, vue.createSlots({ _: 2 }, [
2071
+ vue.renderList(Object.keys(_ctx.$slots), (slot, _index) => {
2072
+ return {
2073
+ name: slot,
2074
+ fn: vue.withCtx(({ row: row2, cell, propertyId }) => [
2075
+ vue.renderSlot(_ctx.$slots, slot, {
2076
+ cell,
2077
+ propertyId,
2078
+ row: row2
2079
+ })
2080
+ ])
2081
+ };
2082
+ })
2083
+ ]), 1032, ["all-rows", "columns", "disable-selection", "disable-unselected-rows-selection", "editable", "editing-row", "fixed-columns", "hide-edit-icon", "is-editing", "page-info", "row", "row-editable", "row-index", "row-key", "select-on-click", "selected-rows", "show-checkbox", "show-drag-handle", "show-serial", "style", "visible-columns"]);
2084
+ }), 128)) : vue.createCommentVNode("", true)
2085
+ ])
2086
+ ], 512)
2087
+ ]),
2088
+ __props.showPageNavigation ? (vue.openBlock(), vue.createBlock(vue.unref(openBlueseaCore.BSPageNavigation), {
2089
+ key: 0,
2090
+ limit: __props.pageInfo?.limit || 10,
2091
+ offset: __props.pageInfo?.offset || 0,
2092
+ "total-count": __props.pageInfo?.totalCount || 0,
2093
+ "visible-page-count": 20,
2094
+ onOffsetChanged: handleOffsetChange
2095
+ }, null, 8, ["limit", "offset", "total-count"])) : vue.createCommentVNode("", true)
2096
+ ], 6);
2097
+ };
2098
+ }
2099
+ });
2100
+ const _hoisted_1$4 = { class: "text-center" };
2101
+ const _hoisted_2$4 = { class: "text-center" };
2102
+ const _hoisted_3$2 = { class: "bs-layout-horizontal" };
2103
+ const _hoisted_4$2 = { class: "bs-layout-horizontal grow justify-content-end gap-8" };
2104
+ const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
2105
+ __name: "BSGridColumnSettingModal",
2106
+ props: {
2107
+ columns: {},
2108
+ columnSettings: {},
2109
+ fixedColumnCount: {},
2110
+ columnSettingTitle: { default: "Column Settings" }
2111
+ },
2112
+ emits: ["settingChanged"],
2113
+ setup(__props, { emit: __emit }) {
2114
+ const props = __props;
2115
+ const emit = __emit;
2116
+ const settingColumns = [
2117
+ {
2118
+ propertyId: "caption",
2119
+ caption: "Caption",
2120
+ width: 200
2121
+ },
2122
+ { propertyId: "visible", caption: "Visible", width: 60 },
2123
+ { propertyId: "fixed", caption: "Fixed", width: 60 },
2124
+ { propertyId: "width", caption: "Width", width: 100 }
2125
+ ];
2126
+ const gridHandler = createInputGridHandler({
2127
+ getRowKey: (row) => row.propertyId
2128
+ });
2129
+ const editingColumns = vue.ref([]);
2130
+ const margeColumnSettingsAndOrigColumns = (columnSettings, columns) => {
2131
+ const origColumns = [...columns || []];
2132
+ const result = columnSettings.map((col) => {
2133
+ const origIndex = origColumns.findIndex(
2134
+ (orig) => orig.propertyId === col.propertyId
2135
+ );
2136
+ if (origIndex >= 0) {
2137
+ const orig = origColumns.splice(origIndex, 1)[0];
2138
+ return { ...orig, hidden: col.hidden, width: col.width || orig.width };
2139
+ } else {
2140
+ return void 0;
2141
+ }
2142
+ }).filter(openBlueseaCore.notNull);
2143
+ origColumns.forEach((orig) => {
2144
+ result.push({ ...orig, width: orig.width });
2145
+ });
2146
+ return result;
2147
+ };
2148
+ vue.onMounted(() => {
2149
+ const columns = props.columnSettings ? margeColumnSettingsAndOrigColumns(props.columnSettings, props.columns) : props.columns?.map((orig) => ({ ...orig })) || [];
2150
+ editingColumns.value = columns.map((col, idx) => ({
2151
+ ...col,
2152
+ fixed: idx < (props.fixedColumnCount || 0)
2153
+ }));
2154
+ gridHandler.setGridData(editingColumns.value);
2155
+ });
2156
+ const updateFixedColumn = async (value, row) => {
2157
+ const rowIndex = editingColumns.value.indexOf(row);
2158
+ const oldFixedIndex = editingColumns.value.findLastIndex((col) => col.fixed) + 1;
2159
+ await vue.nextTick();
2160
+ const fixedIndex = !value && oldFixedIndex === 0 && rowIndex === 0 ? -1 : rowIndex;
2161
+ editingColumns.value.forEach((col, idx) => col.fixed = idx <= fixedIndex);
2162
+ };
2163
+ const modalHandle = openBlueseaCore.useModalHandle();
2164
+ const save = () => {
2165
+ const columnSettings = editingColumns.value.map((col) => {
2166
+ const orig = props.columns?.find((c) => c.propertyId === col.propertyId);
2167
+ return {
2168
+ propertyId: col.propertyId,
2169
+ hidden: col.hidden ? true : void 0,
2170
+ width: col.width !== orig?.width ? col.width : void 0
2171
+ };
2172
+ });
2173
+ const fixedColumnCount = editingColumns.value.findLastIndex((col) => col.fixed) + 1;
2174
+ emit("settingChanged", columnSettings, fixedColumnCount);
2175
+ modalHandle.close();
2176
+ };
2177
+ const close = () => {
2178
+ modalHandle.close();
2179
+ };
2180
+ const restore = () => {
2181
+ emit("settingChanged", void 0, void 0);
2182
+ modalHandle.close();
2183
+ };
2184
+ modalHandle.setDefaultStyle({
2185
+ maxWidth: "600px",
2186
+ maxHeight: "80%"
2187
+ });
2188
+ return (_ctx, _cache) => {
2189
+ return vue.openBlock(), vue.createBlock(vue.unref(openBlueseaCore.BSModalFrame), { title: __props.columnSettingTitle }, {
2190
+ default: vue.withCtx(() => [
2191
+ vue.createVNode(_sfc_main$7, vue.mergeProps({
2192
+ columns: settingColumns,
2193
+ height: "100%",
2194
+ "show-drag-handle": "",
2195
+ "show-serial": ""
2196
+ }, vue.unref(gridHandler).grid, vue.toHandlers(vue.unref(gridHandler).gridEventListener)), {
2197
+ visible: vue.withCtx(({ row }) => [
2198
+ vue.createElementVNode("div", _hoisted_1$4, [
2199
+ vue.createVNode(vue.unref(openBlueseaCore.BSCheckbox), {
2200
+ "model-value": !row.hidden,
2201
+ class: "reverted",
2202
+ "onUpdate:modelValue": (value) => row.hidden = !value
2203
+ }, null, 8, ["model-value", "onUpdate:modelValue"])
2204
+ ])
2205
+ ]),
2206
+ fixed: vue.withCtx(({ row }) => [
2207
+ vue.createElementVNode("div", _hoisted_2$4, [
2208
+ vue.createVNode(vue.unref(openBlueseaCore.BSCheckbox), {
2209
+ modelValue: row.fixed,
2210
+ "onUpdate:modelValue": [($event) => row.fixed = $event, ($event) => updateFixedColumn($event, row)],
2211
+ class: "reverted"
2212
+ }, null, 8, ["modelValue", "onUpdate:modelValue"])
2213
+ ])
2214
+ ]),
2215
+ width: vue.withCtx(({ row }) => [
2216
+ vue.createVNode(vue.unref(openBlueseaCore.BSNumberInput), {
2217
+ modelValue: row.width,
2218
+ "onUpdate:modelValue": ($event) => row.width = $event,
2219
+ width: "100%"
2220
+ }, null, 8, ["modelValue", "onUpdate:modelValue"])
2221
+ ]),
2222
+ _: 1
2223
+ }, 16)
2224
+ ]),
2225
+ buttons: vue.withCtx(() => [
2226
+ vue.createElementVNode("div", _hoisted_3$2, [
2227
+ vue.createElementVNode("div", null, [
2228
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2229
+ caption: "Restore Settings",
2230
+ "button-color": "gray",
2231
+ onClick: restore
2232
+ })
2233
+ ]),
2234
+ vue.createElementVNode("div", _hoisted_4$2, [
2235
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2236
+ caption: "Cancel",
2237
+ onClick: close
2238
+ }),
2239
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2240
+ caption: "OK",
2241
+ "button-color": "blue",
2242
+ onClick: save
2243
+ })
2244
+ ])
2245
+ ])
2246
+ ]),
2247
+ _: 1
2248
+ }, 8, ["title"]);
2249
+ };
2250
+ }
2251
+ });
2252
+ const BSGridColumnSettingModal = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2253
+ __proto__: null,
2254
+ default: _sfc_main$6
2255
+ }, Symbol.toStringTag, { value: "Module" }));
2256
+ const _hoisted_1$3 = { class: "bs-grid-control" };
2257
+ const _hoisted_2$3 = { key: 0 };
2258
+ const _hoisted_3$1 = { key: 1 };
2259
+ const _hoisted_4$1 = { key: 2 };
2260
+ const _hoisted_5$1 = { key: 3 };
2261
+ const _hoisted_6 = { key: 4 };
2262
+ const _hoisted_7 = ["textContent"];
2263
+ const _hoisted_8 = { key: 5 };
2264
+ const _hoisted_9 = ["textContent"];
2265
+ const _hoisted_10 = { key: 6 };
2266
+ const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
2267
+ __name: "BSGridControl",
2268
+ props: {
2269
+ gridId: {},
2270
+ showSetting: { type: Boolean },
2271
+ showRefresh: { type: Boolean },
2272
+ showClearFilter: { type: Boolean },
2273
+ showFilter: { type: Boolean },
2274
+ showLimit: { type: Boolean },
2275
+ showAddButton: { type: Boolean },
2276
+ showRemoveButton: { type: Boolean },
2277
+ columns: {},
2278
+ columnSettings: {},
2279
+ fixedColumnCount: {},
2280
+ limitItems: { default: () => [100, 300, 500] },
2281
+ limit: { default: 100 },
2282
+ totalCount: {},
2283
+ selectedRows: {},
2284
+ gridFilters: {}
2285
+ },
2286
+ emits: ["update:limit", "refresh", "clearFilter", "clickAdd", "clickRemove", "settingChanged"],
2287
+ setup(__props, { emit: __emit }) {
2288
+ const props = __props;
2289
+ const emit = __emit;
2290
+ const limitValue = vue.ref(props.limit || props.limitItems?.[0] || 100);
2291
+ const selectedCount = vue.computed(() => props.selectedRows?.size || 0);
2292
+ const formattedTotalCount = vue.computed(
2293
+ () => openBlueseaCore.formatUtil.formatNumber(props.totalCount) || ""
2294
+ );
2295
+ const formattedSelectedCount = vue.computed(
2296
+ () => openBlueseaCore.formatUtil.formatNumber(selectedCount.value) || ""
2297
+ );
2298
+ const changeLimit = (limit) => {
2299
+ emit("update:limit", Math.max(1, limit || 0));
2300
+ };
2301
+ const refreshGrid = () => {
2302
+ emit("refresh");
2303
+ };
2304
+ const clearGridFilter = () => {
2305
+ emit("clearFilter");
2306
+ };
2307
+ const modal = openBlueseaCore.useModal();
2308
+ const openSettingModal = () => {
2309
+ modal.openModal({
2310
+ component: vue.defineAsyncComponent(
2311
+ () => Promise.resolve().then(() => BSGridColumnSettingModal)
2312
+ ),
2313
+ bind: {
2314
+ columns: props.columns,
2315
+ columnSettings: props.columnSettings,
2316
+ fixedColumnCount: props.fixedColumnCount
2317
+ },
2318
+ on: {
2319
+ settingChanged: (columnSettings, fixedColumnCount) => emit("settingChanged", columnSettings, fixedColumnCount)
2320
+ }
2321
+ });
2322
+ };
2323
+ return (_ctx, _cache) => {
2324
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
2325
+ __props.showSetting ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$3, [
2326
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2327
+ caption: "Column Settings",
2328
+ "data-id": "columnSettingBtn",
2329
+ "left-icon": "data_table",
2330
+ onClick: openSettingModal
2331
+ })
2332
+ ])) : vue.createCommentVNode("", true),
2333
+ __props.showRefresh ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1, [
2334
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2335
+ caption: "Refresh",
2336
+ "data-id": "refreshBtn",
2337
+ "left-icon": "sync",
2338
+ onClick: refreshGrid
2339
+ })
2340
+ ])) : vue.createCommentVNode("", true),
2341
+ __props.showClearFilter ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$1, [
2342
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2343
+ caption: "Clear Settings",
2344
+ "data-id": "clearSettingBtn",
2345
+ "left-icon": "filter_alt_off",
2346
+ onClick: clearGridFilter
2347
+ })
2348
+ ])) : vue.createCommentVNode("", true),
2349
+ __props.showAddButton ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5$1, [
2350
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2351
+ caption: "Add Row",
2352
+ "data-id": "addRowBtn",
2353
+ "left-icon": "add",
2354
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("clickAdd"))
2355
+ })
2356
+ ])) : vue.createCommentVNode("", true),
2357
+ __props.showRemoveButton ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, [
2358
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
2359
+ caption: "Remove Row",
2360
+ "data-id": "removeRowBtn",
2361
+ "left-icon": "remove",
2362
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("clickRemove"))
2363
+ })
2364
+ ])) : vue.createCommentVNode("", true),
2365
+ vue.createElementVNode("div", null, [
2366
+ _cache[3] || (_cache[3] = vue.createElementVNode("span", { textContent: "Total" }, null, -1)),
2367
+ _cache[4] || (_cache[4] = vue.createTextVNode(": ", -1)),
2368
+ vue.createElementVNode("span", {
2369
+ "data-id": "totalCount",
2370
+ textContent: vue.toDisplayString(formattedTotalCount.value)
2371
+ }, null, 8, _hoisted_7)
2372
+ ]),
2373
+ selectedCount.value > 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8, [
2374
+ _cache[5] || (_cache[5] = vue.createElementVNode("span", { textContent: "Selected" }, null, -1)),
2375
+ _cache[6] || (_cache[6] = vue.createTextVNode(": ", -1)),
2376
+ vue.createElementVNode("span", {
2377
+ "data-id": "selectedCount",
2378
+ textContent: vue.toDisplayString(formattedSelectedCount.value)
2379
+ }, null, 8, _hoisted_9)
2380
+ ])) : vue.createCommentVNode("", true),
2381
+ __props.showLimit ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10, [
2382
+ vue.createVNode(vue.unref(openBlueseaCore.BSSelect), {
2383
+ modelValue: limitValue.value,
2384
+ "onUpdate:modelValue": [
2385
+ _cache[2] || (_cache[2] = ($event) => limitValue.value = $event),
2386
+ changeLimit
2387
+ ],
2388
+ items: __props.limitItems,
2389
+ class: "page-length",
2390
+ "data-id": "limitSelect"
2391
+ }, null, 8, ["modelValue", "items"])
2392
+ ])) : vue.createCommentVNode("", true)
2393
+ ]);
2394
+ };
2395
+ }
2396
+ });
2397
+ const _hoisted_1$2 = { class: "bs-text-filter" };
2398
+ const _hoisted_2$2 = { class: "input-wrap" };
2399
+ const _hoisted_3 = { class: "textarea-wrap" };
2400
+ const _hoisted_4 = {
2401
+ class: "filter-caption text-nowrap",
2402
+ "data-id": "filterCaption"
2403
+ };
2404
+ const _hoisted_5 = ["textContent"];
2405
+ const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
2406
+ __name: "BSTextFilter",
2407
+ props: {
2408
+ textFilterItems: { default: () => [] },
2409
+ modelValue: {},
2410
+ keyword: {}
2411
+ },
2412
+ emits: ["update:modelValue", "search"],
2413
+ setup(__props, { emit: __emit }) {
2414
+ const props = __props;
2415
+ const emit = __emit;
2416
+ const likeTextFilterItems = vue.computed(() => props.textFilterItems);
2417
+ const inTextFilterItems = vue.computed(() => props.textFilterItems.filter((filter) => filter.allowMultiLineFilter));
2418
+ const hasTextAreaFilterItem = vue.computed(() => inTextFilterItems.value.length > 0);
2419
+ const filterMode = vue.ref("INPUT");
2420
+ const changeFilterMode = (mode) => filterMode.value = mode;
2421
+ const likeFilterItems = vue.computed(() => likeTextFilterItems.value.filter((item) => !item.filterCreator && item.filterType !== "NUMBER"));
2422
+ const equalFilterItemPropertyIds = vue.computed(() => likeTextFilterItems.value.filter((item) => !item.filterCreator && item.filterType === "NUMBER").map((item) => item.propertyId));
2423
+ const customFilterItems = vue.computed(() => likeTextFilterItems.value.filter((item) => item.filterCreator));
2424
+ const inFilterItemPropertyIds = vue.computed(() => inTextFilterItems.value.map((filter) => filter.propertyId));
2425
+ const getFilterKeyword = (filter) => {
2426
+ const actualFilter = filter instanceof OrFilter ? filter.filters[0] : filter;
2427
+ if (actualFilter && "getFilterValueString" in actualFilter) {
2428
+ const value = actualFilter.getFilterValueString();
2429
+ return Array.isArray(value) ? value.join("\n") : value;
2430
+ }
2431
+ return "";
2432
+ };
2433
+ const inputText = vue.ref(getFilterKeyword(props.modelValue));
2434
+ vue.watch(
2435
+ () => props.modelValue,
2436
+ () => inputText.value = getFilterKeyword(props.modelValue)
2437
+ );
2438
+ const inputTextChanged = async () => {
2439
+ inputText.value = inputText.value.trim();
2440
+ const filter = await createFilter(inputText.value);
2441
+ if (props.modelValue?.toString() !== filter?.toString()) {
2442
+ emit("update:modelValue", filter, likeTextFilterItems.value);
2443
+ }
2444
+ };
2445
+ const textareaText = vue.ref(getFilterKeyword(props.modelValue));
2446
+ const textareaTextChanged = async () => {
2447
+ textareaText.value = textareaText.value.trim();
2448
+ const filter = await createFilter(textareaText.value);
2449
+ if (props.modelValue?.toString() !== filter?.toString()) {
2450
+ emit("update:modelValue", filter, inTextFilterItems.value);
2451
+ }
2452
+ };
2453
+ const makeLikeFilters = (items, keyword) => {
2454
+ if (items.length === 0) return [];
2455
+ const prefixSuffix = items.map((item) => (item.prefix === false ? "f" : "t") + (item.suffix === false ? "f" : "t"));
2456
+ if (prefixSuffix.every((val) => val === prefixSuffix[0])) {
2457
+ const likeNames = likeFilterItems.value.map((item) => item.propertyId);
2458
+ const first = items[0];
2459
+ return [likeFilter(likeNames, keyword, first.prefix !== false, first.suffix !== false, true)];
2460
+ } else {
2461
+ return items.map((item) => likeFilter([item.propertyId], keyword, item.prefix !== false, item.suffix !== false, true));
2462
+ }
2463
+ };
2464
+ const createFilter = async (text) => {
2465
+ const keyword = text?.trim();
2466
+ if (!keyword) return void 0;
2467
+ if (filterMode.value === "INPUT") {
2468
+ const like = makeLikeFilters(likeFilterItems.value, keyword);
2469
+ const equalNames = equalFilterItemPropertyIds.value;
2470
+ const equal = equalNames.length > 0 && !Number.isNaN(Number(keyword)) ? equalFilter(equalNames, Number(keyword), true) : void 0;
2471
+ const customFilters = (await Promise.all(customFilterItems.value.map(async (item) => {
2472
+ let created = item.filterCreator?.(item.propertyId, keyword);
2473
+ if (created && created instanceof Promise) {
2474
+ created = await created;
2475
+ }
2476
+ return created || [];
2477
+ }))).flatMap((item) => item);
2478
+ const allFilters = [...like, equal, ...customFilters].filter(openBlueseaCore.notNull);
2479
+ if (allFilters.length >= 2) return orFilter(allFilters);
2480
+ else return allFilters[0];
2481
+ } else if (filterMode.value === "TEXTAREA") {
2482
+ const names = inFilterItemPropertyIds.value;
2483
+ const keywords = keyword.split("\n");
2484
+ return inFilter(names, keywords, true);
2485
+ }
2486
+ };
2487
+ vue.watch(
2488
+ () => props.keyword,
2489
+ () => {
2490
+ inputText.value = props.keyword || "";
2491
+ inputTextChanged();
2492
+ },
2493
+ { immediate: true }
2494
+ );
2495
+ return (_ctx, _cache) => {
2496
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
2497
+ vue.withDirectives(vue.createElementVNode("div", _hoisted_2$2, [
2498
+ vue.withDirectives(vue.createElementVNode("input", {
2499
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => inputText.value = $event),
2500
+ "data-id": "textFilterInput",
2501
+ type: "text",
2502
+ onChange: inputTextChanged,
2503
+ onKeyup: _cache[1] || (_cache[1] = vue.withKeys(vue.withModifiers(() => {
2504
+ }, ["prevent", "stop"]), ["enter"]))
2505
+ }, null, 544), [
2506
+ [vue.vModelText, inputText.value]
2507
+ ]),
2508
+ hasTextAreaFilterItem.value ? (vue.openBlock(), vue.createElementBlock("span", {
2509
+ key: 0,
2510
+ class: "filter-mode-btn font-icon bs-clickable mr-4 mt-5",
2511
+ onClick: _cache[2] || (_cache[2] = ($event) => changeFilterMode("TEXTAREA"))
2512
+ }, "south")) : vue.createCommentVNode("", true)
2513
+ ], 512), [
2514
+ [vue.vShow, filterMode.value === "INPUT"]
2515
+ ]),
2516
+ vue.withDirectives(vue.createElementVNode("div", _hoisted_3, [
2517
+ vue.withDirectives(vue.createElementVNode("textarea", {
2518
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => textareaText.value = $event),
2519
+ "data-id": "textFilterTextarea",
2520
+ onChange: textareaTextChanged
2521
+ }, null, 544), [
2522
+ [vue.vModelText, textareaText.value]
2523
+ ]),
2524
+ vue.createElementVNode("span", {
2525
+ class: "font-icon bs-clickable mr-4 mt-5",
2526
+ onClick: _cache[4] || (_cache[4] = ($event) => changeFilterMode("INPUT"))
2527
+ }, "north")
2528
+ ], 512), [
2529
+ [vue.vShow, filterMode.value === "TEXTAREA"]
2530
+ ]),
2531
+ vue.createElementVNode("div", _hoisted_4, [
2532
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(filterMode.value === "INPUT" ? likeTextFilterItems.value : inTextFilterItems.value, (item) => {
2533
+ return vue.openBlock(), vue.createElementBlock("span", {
2534
+ key: item.propertyId,
2535
+ textContent: vue.toDisplayString(item.caption)
2536
+ }, null, 8, _hoisted_5);
2537
+ }), 128))
2538
+ ])
2539
+ ]);
2540
+ };
2541
+ }
2542
+ });
2543
+ function getDefaultExportFromCjs(x) {
2544
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
2545
+ }
2546
+ var utc$2 = { exports: {} };
2547
+ var utc$1 = utc$2.exports;
2548
+ var hasRequiredUtc;
2549
+ function requireUtc() {
2550
+ if (hasRequiredUtc) return utc$2.exports;
2551
+ hasRequiredUtc = 1;
2552
+ (function(module2, exports3) {
2553
+ !(function(t, i) {
2554
+ module2.exports = i();
2555
+ })(utc$1, (function() {
2556
+ var t = "minute", i = /[+-]\d\d(?::?\d\d)?/g, e = /([+-]|\d\d)/g;
2557
+ return function(s, f, n) {
2558
+ var u = f.prototype;
2559
+ n.utc = function(t2) {
2560
+ var i2 = { date: t2, utc: true, args: arguments };
2561
+ return new f(i2);
2562
+ }, u.utc = function(i2) {
2563
+ var e2 = n(this.toDate(), { locale: this.$L, utc: true });
2564
+ return i2 ? e2.add(this.utcOffset(), t) : e2;
2565
+ }, u.local = function() {
2566
+ return n(this.toDate(), { locale: this.$L, utc: false });
2567
+ };
2568
+ var r = u.parse;
2569
+ u.parse = function(t2) {
2570
+ t2.utc && (this.$u = true), this.$utils().u(t2.$offset) || (this.$offset = t2.$offset), r.call(this, t2);
2571
+ };
2572
+ var o = u.init;
2573
+ u.init = function() {
2574
+ if (this.$u) {
2575
+ var t2 = this.$d;
2576
+ this.$y = t2.getUTCFullYear(), this.$M = t2.getUTCMonth(), this.$D = t2.getUTCDate(), this.$W = t2.getUTCDay(), this.$H = t2.getUTCHours(), this.$m = t2.getUTCMinutes(), this.$s = t2.getUTCSeconds(), this.$ms = t2.getUTCMilliseconds();
2577
+ } else o.call(this);
2578
+ };
2579
+ var a = u.utcOffset;
2580
+ u.utcOffset = function(s2, f2) {
2581
+ var n2 = this.$utils().u;
2582
+ if (n2(s2)) return this.$u ? 0 : n2(this.$offset) ? a.call(this) : this.$offset;
2583
+ if ("string" == typeof s2 && (s2 = (function(t2) {
2584
+ void 0 === t2 && (t2 = "");
2585
+ var s3 = t2.match(i);
2586
+ if (!s3) return null;
2587
+ var f3 = ("" + s3[0]).match(e) || ["-", 0, 0], n3 = f3[0], u3 = 60 * +f3[1] + +f3[2];
2588
+ return 0 === u3 ? 0 : "+" === n3 ? u3 : -u3;
2589
+ })(s2), null === s2)) return this;
2590
+ var u2 = Math.abs(s2) <= 16 ? 60 * s2 : s2;
2591
+ if (0 === u2) return this.utc(f2);
2592
+ var r2 = this.clone();
2593
+ if (f2) return r2.$offset = u2, r2.$u = false, r2;
2594
+ var o2 = this.$u ? this.toDate().getTimezoneOffset() : -1 * this.utcOffset();
2595
+ return (r2 = this.local().add(u2 + o2, t)).$offset = u2, r2.$x.$localOffset = o2, r2;
2596
+ };
2597
+ var h = u.format;
2598
+ u.format = function(t2) {
2599
+ var i2 = t2 || (this.$u ? "YYYY-MM-DDTHH:mm:ss[Z]" : "");
2600
+ return h.call(this, i2);
2601
+ }, u.valueOf = function() {
2602
+ var t2 = this.$utils().u(this.$offset) ? 0 : this.$offset + (this.$x.$localOffset || this.$d.getTimezoneOffset());
2603
+ return this.$d.valueOf() - 6e4 * t2;
2604
+ }, u.isUTC = function() {
2605
+ return !!this.$u;
2606
+ }, u.toISOString = function() {
2607
+ return this.toDate().toISOString();
2608
+ }, u.toString = function() {
2609
+ return this.toDate().toUTCString();
2610
+ };
2611
+ var l = u.toDate;
2612
+ u.toDate = function(t2) {
2613
+ return "s" === t2 && this.$offset ? n(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate() : l.call(this);
2614
+ };
2615
+ var c = u.diff;
2616
+ u.diff = function(t2, i2, e2) {
2617
+ if (t2 && this.$u === t2.$u) return c.call(this, t2, i2, e2);
2618
+ var s2 = this.local(), f2 = n(t2).local();
2619
+ return c.call(s2, f2, i2, e2);
2620
+ };
2621
+ };
2622
+ }));
2623
+ })(utc$2);
2624
+ return utc$2.exports;
2625
+ }
2626
+ var utcExports = requireUtc();
2627
+ const utc = /* @__PURE__ */ getDefaultExportFromCjs(utcExports);
2628
+ var timezone$2 = { exports: {} };
2629
+ var timezone$1 = timezone$2.exports;
2630
+ var hasRequiredTimezone;
2631
+ function requireTimezone() {
2632
+ if (hasRequiredTimezone) return timezone$2.exports;
2633
+ hasRequiredTimezone = 1;
2634
+ (function(module2, exports3) {
2635
+ !(function(t, e) {
2636
+ module2.exports = e();
2637
+ })(timezone$1, (function() {
2638
+ var t = { year: 0, month: 1, day: 2, hour: 3, minute: 4, second: 5 }, e = {};
2639
+ return function(n, i, o) {
2640
+ var r, a = function(t2, n2, i2) {
2641
+ void 0 === i2 && (i2 = {});
2642
+ var o2 = new Date(t2), r2 = (function(t3, n3) {
2643
+ void 0 === n3 && (n3 = {});
2644
+ var i3 = n3.timeZoneName || "short", o3 = t3 + "|" + i3, r3 = e[o3];
2645
+ return r3 || (r3 = new Intl.DateTimeFormat("en-US", { hour12: false, timeZone: t3, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", timeZoneName: i3 }), e[o3] = r3), r3;
2646
+ })(n2, i2);
2647
+ return r2.formatToParts(o2);
2648
+ }, u = function(e2, n2) {
2649
+ for (var i2 = a(e2, n2), r2 = [], u2 = 0; u2 < i2.length; u2 += 1) {
2650
+ var f2 = i2[u2], s2 = f2.type, m = f2.value, c = t[s2];
2651
+ c >= 0 && (r2[c] = parseInt(m, 10));
2652
+ }
2653
+ var d = r2[3], l = 24 === d ? 0 : d, h = r2[0] + "-" + r2[1] + "-" + r2[2] + " " + l + ":" + r2[4] + ":" + r2[5] + ":000", v = +e2;
2654
+ return (o.utc(h).valueOf() - (v -= v % 1e3)) / 6e4;
2655
+ }, f = i.prototype;
2656
+ f.tz = function(t2, e2) {
2657
+ void 0 === t2 && (t2 = r);
2658
+ var n2, i2 = this.utcOffset(), a2 = this.toDate(), u2 = a2.toLocaleString("en-US", { timeZone: t2 }), f2 = Math.round((a2 - new Date(u2)) / 1e3 / 60), s2 = 15 * -Math.round(a2.getTimezoneOffset() / 15) - f2;
2659
+ if (!Number(s2)) n2 = this.utcOffset(0, e2);
2660
+ else if (n2 = o(u2, { locale: this.$L }).$set("millisecond", this.$ms).utcOffset(s2, true), e2) {
2661
+ var m = n2.utcOffset();
2662
+ n2 = n2.add(i2 - m, "minute");
2663
+ }
2664
+ return n2.$x.$timezone = t2, n2;
2665
+ }, f.offsetName = function(t2) {
2666
+ var e2 = this.$x.$timezone || o.tz.guess(), n2 = a(this.valueOf(), e2, { timeZoneName: t2 }).find((function(t3) {
2667
+ return "timezonename" === t3.type.toLowerCase();
2668
+ }));
2669
+ return n2 && n2.value;
2670
+ };
2671
+ var s = f.startOf;
2672
+ f.startOf = function(t2, e2) {
2673
+ if (!this.$x || !this.$x.$timezone) return s.call(this, t2, e2);
2674
+ var n2 = o(this.format("YYYY-MM-DD HH:mm:ss:SSS"), { locale: this.$L });
2675
+ return s.call(n2, t2, e2).tz(this.$x.$timezone, true);
2676
+ }, o.tz = function(t2, e2, n2) {
2677
+ var i2 = n2 && e2, a2 = n2 || e2 || r, f2 = u(+o(), a2);
2678
+ if ("string" != typeof t2) return o(t2).tz(a2);
2679
+ var s2 = (function(t3, e3, n3) {
2680
+ var i3 = t3 - 60 * e3 * 1e3, o2 = u(i3, n3);
2681
+ if (e3 === o2) return [i3, e3];
2682
+ var r2 = u(i3 -= 60 * (o2 - e3) * 1e3, n3);
2683
+ return o2 === r2 ? [i3, o2] : [t3 - 60 * Math.min(o2, r2) * 1e3, Math.max(o2, r2)];
2684
+ })(o.utc(t2, i2).valueOf(), f2, a2), m = s2[0], c = s2[1], d = o(m).utcOffset(c);
2685
+ return d.$x.$timezone = a2, d;
2686
+ }, o.tz.guess = function() {
2687
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
2688
+ }, o.tz.setDefault = function(t2) {
2689
+ r = t2;
2690
+ };
2691
+ };
2692
+ }));
2693
+ })(timezone$2);
2694
+ return timezone$2.exports;
2695
+ }
2696
+ var timezoneExports = requireTimezone();
2697
+ const timezone = /* @__PURE__ */ getDefaultExportFromCjs(timezoneExports);
2698
+ dayjs.extend(utc);
2699
+ dayjs.extend(timezone);
2700
+ const createDateRangeFromPreset = (value, timeZone) => {
2701
+ const from = value.from ? resolveMoment(value.from, true, timeZone) : void 0;
2702
+ const to = value.to ? resolveMoment(value.to, false, timeZone) : void 0;
2703
+ return { from: from?.toISOString(), to: to?.toISOString() };
2704
+ };
2705
+ const resolveMoment = (setting, from, timeZone, baseDate) => {
2706
+ switch (setting.type) {
2707
+ case "TODAY":
2708
+ return resolveToday(from, timeZone, baseDate);
2709
+ case "THIS_WEEK":
2710
+ return resolveThisWeek(from, timeZone, baseDate);
2711
+ case "THIS_MONTH":
2712
+ return resolveThisMonth(from, timeZone, baseDate);
2713
+ case "THIS_YEAR":
2714
+ return resolveThisYear(from, timeZone, baseDate);
2715
+ case "LAST_HOURS":
2716
+ return resolveLastHours(setting.value || 0, from, timeZone, baseDate);
2717
+ case "LAST_DAYS":
2718
+ return resolveLastDays(setting.value || 0, from, timeZone, baseDate);
2719
+ case "DAYS_AGO":
2720
+ return resolveDaysAgo(setting.value || 0, from, timeZone, baseDate);
2721
+ case "WEEKS_AGO":
2722
+ return resolveWeeksAgo(setting.value || 0, from, timeZone, baseDate);
2723
+ case "MONTHS_AGO":
2724
+ return resolveMonthsAgo(setting.value || 0, from, timeZone, baseDate);
2725
+ case "YEARS_AGO":
2726
+ return resolveYearsAgo(setting.value || 0, from, timeZone, baseDate);
2727
+ }
2728
+ };
2729
+ const resolveToday = (from, timeZone, baseDate) => {
2730
+ const today = (baseDate || dayjs()).tz(timeZone);
2731
+ return from ? today.startOf("day") : today.endOf("day");
2732
+ };
2733
+ const resolveThisWeek = (from, timeZone, baseDate) => {
2734
+ const today = (baseDate || dayjs()).tz(timeZone);
2735
+ return from ? today.startOf("week") : today.endOf("week");
2736
+ };
2737
+ const resolveThisMonth = (from, timeZone, baseDate) => {
2738
+ const today = (baseDate || dayjs()).tz(timeZone);
2739
+ return from ? today.startOf("month") : today.endOf("month");
2740
+ };
2741
+ const resolveThisYear = (from, timeZone, baseDate) => {
2742
+ const today = (baseDate || dayjs()).tz(timeZone);
2743
+ return from ? today.startOf("year") : today.endOf("year");
2744
+ };
2745
+ const resolveLastHours = (hours, from, timeZone, baseDate) => {
2746
+ const today = (baseDate || dayjs()).tz(timeZone);
2747
+ return from ? today.add(-hours, "hour").startOf("minute") : today.endOf("minute");
2748
+ };
2749
+ const resolveLastDays = (days, from, timeZone, baseDate) => {
2750
+ const today = (baseDate || dayjs()).tz(timeZone);
2751
+ return from ? today.add(-days, "day").startOf("day") : today.endOf("day");
2752
+ };
2753
+ const resolveDaysAgo = (days, from, timeZone, baseDate) => {
2754
+ const today = (baseDate || dayjs()).tz(timeZone);
2755
+ return from ? today.add(-days, "day").startOf("day") : today.add(-days, "day").endOf("day");
2756
+ };
2757
+ const resolveWeeksAgo = (weeks, from, timeZone, baseDate) => {
2758
+ const today = (baseDate || dayjs()).tz(timeZone);
2759
+ return from ? today.add(-weeks, "week").startOf("week") : today.add(-weeks, "week").endOf("week");
2760
+ };
2761
+ const resolveMonthsAgo = (months, from, timeZone, baseDate) => {
2762
+ const today = (baseDate || dayjs()).tz(timeZone);
2763
+ return from ? today.add(-months, "month").startOf("month") : today.add(-months, "month").endOf("month");
2764
+ };
2765
+ const resolveYearsAgo = (years, from, timeZone, baseDate) => {
2766
+ const today = (baseDate || dayjs()).tz(timeZone);
2767
+ return from ? today.add(-years, "year").startOf("year") : today.add(-years, "year").endOf("year");
2768
+ };
2769
+ const serializeMomentSetting = (setting) => {
2770
+ if (!setting)
2771
+ return "";
2772
+ const value = setting.value === void 0 ? "" : `:${setting.value}`;
2773
+ return `${setting.type}${value}`;
2774
+ };
2775
+ const convertDateRangePresetKey = (preset) => {
2776
+ if (preset.from === void 0 && preset.to === void 0)
2777
+ return "";
2778
+ return `${serializeMomentSetting(preset.from)}~${serializeMomentSetting(preset.to)}`;
2779
+ };
2780
+ const findPreset = (presetKey, candidatePresets) => {
2781
+ if (!presetKey)
2782
+ return void 0;
2783
+ return candidatePresets?.find((preset) => convertDateRangePresetKey(preset) === presetKey);
2784
+ };
2785
+ class BetweenDateFilterWithPreset extends BetweenDateFilter {
2786
+ name;
2787
+ fromValue;
2788
+ toValue;
2789
+ presetKey;
2790
+ constructor(name, fromValue, toValue, preset) {
2791
+ super(name, fromValue, toValue);
2792
+ this.name = name;
2793
+ this.fromValue = fromValue;
2794
+ this.toValue = toValue;
2795
+ this.presetKey = preset ? convertDateRangePresetKey(preset) : void 0;
2796
+ }
2797
+ // candidatePresets 중 presetKey 에 해당하는 preset 을 찾아, fromValue, toValue 를 설정한다.
2798
+ // preset 을 찾을 수 없으면 undefined 를 리턴한다.
2799
+ static createFromPresetKey(name, presetKey, candidatePresets, timeZone) {
2800
+ const preset = findPreset(presetKey, candidatePresets);
2801
+ const range = preset ? createDateRangeFromPreset(preset, timeZone) : void 0;
2802
+ return range ? new BetweenDateFilterWithPreset(name, range.from, range.to, preset) : void 0;
2803
+ }
2804
+ }
2805
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
2806
+ __name: "BSDateRangePresets",
2807
+ props: {
2808
+ modelValue: {},
2809
+ presets: { default: () => [] },
2810
+ timeZone: {}
2811
+ },
2812
+ emits: ["update:modelValue"],
2813
+ setup(__props, { emit: __emit }) {
2814
+ const props = __props;
2815
+ const emit = __emit;
2816
+ const blueseaConfig = openBlueseaCore.useBlueseaConfig();
2817
+ const actualTimeZone = vue.computed(() => props.timeZone || blueseaConfig.timeZone);
2818
+ const currentPreset = vue.ref();
2819
+ const presetSelected = (value) => {
2820
+ const range = value ? createDateRangeFromPreset(value, actualTimeZone.value) : void 0;
2821
+ emit("update:modelValue", range, value);
2822
+ };
2823
+ const findPreset2 = (range) => {
2824
+ return props.presets.find((preset) => {
2825
+ const presetValue = createDateRangeFromPreset(preset, actualTimeZone.value);
2826
+ return range?.from === presetValue.from && range?.to === presetValue.to;
2827
+ });
2828
+ };
2829
+ vue.watch(
2830
+ () => props.modelValue,
2831
+ () => {
2832
+ currentPreset.value = findPreset2(props.modelValue);
2833
+ },
2834
+ { immediate: true }
2835
+ );
2836
+ return (_ctx, _cache) => {
2837
+ return __props.presets && __props.presets.length > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(openBlueseaCore.BSRadioButtonGroup), {
2838
+ key: 0,
2839
+ modelValue: currentPreset.value,
2840
+ "onUpdate:modelValue": [
2841
+ _cache[0] || (_cache[0] = ($event) => currentPreset.value = $event),
2842
+ presetSelected
2843
+ ],
2844
+ items: __props.presets,
2845
+ "label-provider": (item) => item.caption,
2846
+ class: "button-group-style nowrap",
2847
+ name: "dateRangePreset"
2848
+ }, null, 8, ["modelValue", "items", "label-provider"])) : vue.createCommentVNode("", true);
2849
+ };
2850
+ }
2851
+ });
2852
+ const _hoisted_1$1 = {
2853
+ key: 0,
2854
+ class: "date-filters .bs-layout-vertical mr-16"
2855
+ };
2856
+ const _hoisted_2$1 = ["onClick"];
2857
+ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
2858
+ __name: "BSDateRangeFilters",
2859
+ props: {
2860
+ dateFilter: {},
2861
+ modelValue: {},
2862
+ captionMinWidth: { default: "140px" },
2863
+ dateFormat: {},
2864
+ popupDateFormat: {},
2865
+ popupStartYear: {},
2866
+ popupEndYear: {},
2867
+ filterWidth: {},
2868
+ presets: {},
2869
+ resolution: {}
2870
+ },
2871
+ emits: ["update:modelValue"],
2872
+ setup(__props, { emit: __emit }) {
2873
+ const props = __props;
2874
+ const emit = __emit;
2875
+ const dateFilterValues = vue.ref([]);
2876
+ const resetDateFilter = () => {
2877
+ const items = props.dateFilter?.filterItems;
2878
+ if (items && items.length > 0) {
2879
+ let values = void 0;
2880
+ if (props.modelValue && props.modelValue.filters.length > 0) {
2881
+ const validPropertyIds = items.map((item) => item.propertyId);
2882
+ values = props.modelValue.filters.filter((filter) => filter instanceof BetweenDateFilter).map((filter) => filter).map((filter) => ({
2883
+ propertyId: filter.name,
2884
+ value: {
2885
+ from: filter.fromValue ? String(filter.fromValue) : void 0,
2886
+ // string 타입으로 가정함
2887
+ to: filter.toValue ? String(filter.toValue) : void 0
2888
+ // string 타입으로 가정함
2889
+ }
2890
+ })).filter((value) => validPropertyIds.includes(value.propertyId));
2891
+ }
2892
+ if (!values || values.length === 0) {
2893
+ values = [
2894
+ {
2895
+ propertyId: items[0].propertyId,
2896
+ value: {}
2897
+ }
2898
+ ];
2899
+ }
2900
+ if (JSON.stringify(values) !== JSON.stringify(dateFilterValues.value)) {
2901
+ dateFilterValues.value = values;
2902
+ }
2903
+ }
2904
+ };
2905
+ vue.watch(
2906
+ () => props.modelValue,
2907
+ () => resetDateFilter(),
2908
+ { immediate: true }
2909
+ );
2910
+ const setDateFilterPropertyId = (index, propertyId) => {
2911
+ const item = dateFilterValues.value[index];
2912
+ if (propertyId) item.propertyId = propertyId;
2913
+ emitValue();
2914
+ };
2915
+ const setDateFilterValue = (index, value, preset) => {
2916
+ const item = dateFilterValues.value[index];
2917
+ item.value = value || {};
2918
+ item.preset = preset;
2919
+ emitValue();
2920
+ };
2921
+ const addDateFilter = () => {
2922
+ const dateFilterItems = props.dateFilter?.filterItems || [];
2923
+ if (dateFilterValues.value.length < dateFilterItems.length) {
2924
+ const selectedPropertyIds = dateFilterValues.value.map(
2925
+ (value) => value.propertyId
2926
+ );
2927
+ const notSelected = dateFilterItems.filter(
2928
+ (item) => !selectedPropertyIds.includes(item.propertyId)
2929
+ );
2930
+ if (notSelected.length > 0) {
2931
+ dateFilterValues.value.push({
2932
+ propertyId: notSelected[0].propertyId,
2933
+ value: {}
2934
+ });
2935
+ }
2936
+ }
2937
+ };
2938
+ const removeDateFilter = (index) => {
2939
+ if (index >= 0 && index < dateFilterValues.value.length) {
2940
+ dateFilterValues.value.splice(index, 1);
2941
+ emitValue();
2942
+ }
2943
+ };
2944
+ const emitValue = () => {
2945
+ const filters = dateFilterValues.value.map(
2946
+ (item) => new BetweenDateFilterWithPreset(
2947
+ item.propertyId,
2948
+ item.value.from,
2949
+ item.value.to,
2950
+ item.preset
2951
+ )
2952
+ );
2953
+ const and = filters.length > 0 ? andFilter(filters) : void 0;
2954
+ if (props.modelValue?.toString() !== and?.toString()) {
2955
+ emit("update:modelValue", and);
2956
+ }
2957
+ };
2958
+ const dateFormatOfFilterItem = (propertyId) => {
2959
+ return props.dateFilter.filterItems.find((item) => item.propertyId === propertyId)?.dateFormat || props.dateFormat;
2960
+ };
2961
+ const popupDateFormatOfFilterItem = (propertyId) => {
2962
+ return props.dateFilter.filterItems.find((item) => item.propertyId === propertyId)?.popupDateFormat || props.popupDateFormat;
2963
+ };
2964
+ const timeZoneOfFilterItem = (propertyId) => {
2965
+ return props.dateFilter.filterItems.find(
2966
+ (item) => item.propertyId === propertyId
2967
+ )?.timeZone;
2968
+ };
2969
+ const filterWidthOfFilterItem = (propertyId) => {
2970
+ return props.dateFilter.filterItems.find((item) => item.propertyId === propertyId)?.filterWidth || props.filterWidth;
2971
+ };
2972
+ return (_ctx, _cache) => {
2973
+ const _component_BSDateRangeFilter = vue.resolveComponent("BSDateRangeFilter");
2974
+ return __props.dateFilter.filterItems ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
2975
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(dateFilterValues.value, (item, index) => {
2976
+ return vue.openBlock(), vue.createElementBlock("div", {
2977
+ key: index,
2978
+ class: "bs-layout-horizontal mb-4 flex-align-center"
2979
+ }, [
2980
+ index === 0 ? (vue.openBlock(), vue.createElementBlock("span", {
2981
+ key: 0,
2982
+ class: vue.normalizeClass([{
2983
+ disabled: dateFilterValues.value.length >= __props.dateFilter.filterItems.length
2984
+ }, "font-icon bs-clickable mr-4"]),
2985
+ "data-id": "addDateFilterBtn",
2986
+ onClick: addDateFilter
2987
+ }, "add", 2)) : (vue.openBlock(), vue.createElementBlock("span", {
2988
+ key: 1,
2989
+ class: "font-icon bs-clickable mr-4",
2990
+ "data-id": "removeDateFilterBtn",
2991
+ onClick: ($event) => removeDateFilter(index)
2992
+ }, "remove", 8, _hoisted_2$1)),
2993
+ vue.createVNode(vue.unref(openBlueseaCore.BSSelect), {
2994
+ items: __props.dateFilter.filterItems,
2995
+ "label-provider": (filter) => filter.caption,
2996
+ "model-value": item.propertyId,
2997
+ style: vue.normalizeStyle({ minWidth: __props.captionMinWidth }),
2998
+ "value-provider": (filter) => filter.propertyId,
2999
+ class: "mr-4",
3000
+ "data-id": "filterItemSelect",
3001
+ "onUpdate:modelValue": ($event) => setDateFilterPropertyId(index, $event)
3002
+ }, null, 8, ["items", "label-provider", "model-value", "style", "value-provider", "onUpdate:modelValue"]),
3003
+ vue.createVNode(_component_BSDateRangeFilter, {
3004
+ "display-format": dateFormatOfFilterItem(item.propertyId),
3005
+ "from-id": `${item.propertyId}From`,
3006
+ "model-value": item.value,
3007
+ "name-from": `${item.propertyId}From`,
3008
+ "name-to": `${item.propertyId}To`,
3009
+ "popup-display-format": popupDateFormatOfFilterItem(item.propertyId),
3010
+ "popup-end-year": __props.popupEndYear,
3011
+ "popup-start-year": __props.popupStartYear,
3012
+ resolution: __props.resolution,
3013
+ "time-zone": timeZoneOfFilterItem(item.propertyId),
3014
+ "to-id": `${item.propertyId}To`,
3015
+ width: filterWidthOfFilterItem(item.propertyId),
3016
+ "onUpdate:modelValue": ($event) => setDateFilterValue(index, $event)
3017
+ }, null, 8, ["display-format", "from-id", "model-value", "name-from", "name-to", "popup-display-format", "popup-end-year", "popup-start-year", "resolution", "time-zone", "to-id", "width", "onUpdate:modelValue"]),
3018
+ vue.createVNode(_sfc_main$3, {
3019
+ modelValue: item.value,
3020
+ "onUpdate:modelValue": [
3021
+ ($event) => item.value = $event,
3022
+ (value, preset) => setDateFilterValue(index, value, preset)
3023
+ ],
3024
+ presets: __props.presets,
3025
+ "time-zone": timeZoneOfFilterItem(item.propertyId),
3026
+ class: "ml-4"
3027
+ }, null, 8, ["modelValue", "onUpdate:modelValue", "presets", "time-zone"])
3028
+ ]);
3029
+ }), 128))
3030
+ ])) : vue.createCommentVNode("", true);
3031
+ };
3032
+ }
3033
+ });
3034
+ const _hoisted_1 = { class: "bs-grid-lookup bs-layout-horizontal flex-align-start" };
3035
+ const _hoisted_2 = { class: "text-nowrap" };
3036
+ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
3037
+ __name: "BSGridLookup",
3038
+ props: {
3039
+ gridId: {},
3040
+ config: {},
3041
+ modelValue: {},
3042
+ dateRangePresets: {},
3043
+ dateFilterCaptionMinWidth: {},
3044
+ dateFilterDateFormat: { default: "YYYY-MM-DD HH:mm" },
3045
+ dateFilterResolution: { default: "DAY" },
3046
+ dateFilterPopupDateFormat: {},
3047
+ dateFilterWidth: {},
3048
+ dateFilterPopupStartYear: {},
3049
+ dateFilterPopupEndYear: {},
3050
+ keyword: {},
3051
+ gridPreferenceDateFilterValues: {}
3052
+ },
3053
+ emits: ["update:modelValue", "search"],
3054
+ setup(__props, { emit: __emit }) {
3055
+ const props = __props;
3056
+ const emit = __emit;
3057
+ const textFilterValue = vue.ref();
3058
+ const dateFilterValue = vue.ref();
3059
+ const makeFilters = () => {
3060
+ const filters = [];
3061
+ if (textFilterValue.value) filters.push(textFilterValue.value);
3062
+ if (dateFilterValue.value) {
3063
+ dateFilterValue.value.filters.filter((filter) => !filter.isEmpty()).forEach((filter) => filters.push(filter));
3064
+ }
3065
+ return filters;
3066
+ };
3067
+ const emitUpdateModelValue = () => {
3068
+ emit("update:modelValue", makeFilters());
3069
+ };
3070
+ const emitSearch = () => {
3071
+ emit("search", makeFilters());
3072
+ };
3073
+ const emitUpdateModelValueAndSearch = () => {
3074
+ emitUpdateModelValue();
3075
+ emitSearch();
3076
+ };
3077
+ const blueseaConfig = openBlueseaCore.useBlueseaConfig();
3078
+ const findDateFilterTimeZone = (name, dateFilter) => {
3079
+ return dateFilter?.filterItems.find((f) => f.propertyId === name)?.timeZone || blueseaConfig.timeZone;
3080
+ };
3081
+ vue.watch(
3082
+ () => props.gridPreferenceDateFilterValues,
3083
+ () => {
3084
+ if (props.gridPreferenceDateFilterValues && props.gridPreferenceDateFilterValues.filters && props.gridPreferenceDateFilterValues.filters.length > 0) {
3085
+ const filters = props.gridPreferenceDateFilterValues.filters.map((filter) => {
3086
+ const f = filter;
3087
+ if (f.name && (f.fromValue || f.toValue)) {
3088
+ if (f.presetKey) {
3089
+ const presets = props.dateRangePresets || //blueseaConfig.componentConfig.gridLookup?.dateRangePresets ||
3090
+ [];
3091
+ const timeZone = findDateFilterTimeZone(
3092
+ f.name,
3093
+ props.config?.dateFilter
3094
+ );
3095
+ return BetweenDateFilterWithPreset.createFromPresetKey(
3096
+ f.name,
3097
+ f.presetKey,
3098
+ presets,
3099
+ timeZone
3100
+ );
3101
+ } else {
3102
+ return new BetweenDateFilterWithPreset(
3103
+ f.name,
3104
+ f.fromValue,
3105
+ f.toValue
3106
+ );
3107
+ }
3108
+ }
3109
+ }).filter(openBlueseaCore.notNull);
3110
+ if (filters.length > 0) {
3111
+ dateFilterValue.value = andFilter(filters);
3112
+ emitUpdateModelValue();
3113
+ }
3114
+ }
3115
+ }
3116
+ );
3117
+ const saveSearchCondition = async () => {
3118
+ };
3119
+ const resetSearchCondition = () => {
3120
+ textFilterValue.value = void 0;
3121
+ dateFilterValue.value = void 0;
3122
+ emitUpdateModelValueAndSearch();
3123
+ };
3124
+ return (_ctx, _cache) => {
3125
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
3126
+ __props.config?.textFilter ? (vue.openBlock(), vue.createBlock(_sfc_main$4, {
3127
+ key: 0,
3128
+ modelValue: textFilterValue.value,
3129
+ "onUpdate:modelValue": [
3130
+ _cache[0] || (_cache[0] = ($event) => textFilterValue.value = $event),
3131
+ emitUpdateModelValueAndSearch
3132
+ ],
3133
+ keyword: __props.keyword,
3134
+ "text-filter-items": __props.config.textFilter.filterItems,
3135
+ class: "mr-16"
3136
+ }, null, 8, ["modelValue", "keyword", "text-filter-items"])) : vue.createCommentVNode("", true),
3137
+ __props.config?.dateFilter ? (vue.openBlock(), vue.createBlock(_sfc_main$2, {
3138
+ key: 1,
3139
+ modelValue: dateFilterValue.value,
3140
+ "onUpdate:modelValue": [
3141
+ _cache[1] || (_cache[1] = ($event) => dateFilterValue.value = $event),
3142
+ emitUpdateModelValueAndSearch
3143
+ ],
3144
+ "caption-min-width": __props.dateFilterCaptionMinWidth,
3145
+ "date-filter": __props.config.dateFilter,
3146
+ "date-format": __props.dateFilterDateFormat,
3147
+ "filter-width": __props.dateFilterWidth,
3148
+ "popup-date-format": __props.dateFilterPopupDateFormat,
3149
+ "popup-end-year": __props.dateFilterPopupEndYear,
3150
+ "popup-start-year": __props.dateFilterPopupStartYear,
3151
+ presets: __props.dateRangePresets,
3152
+ resolution: __props.dateFilterResolution
3153
+ }, null, 8, ["modelValue", "caption-min-width", "date-filter", "date-format", "filter-width", "popup-date-format", "popup-end-year", "popup-start-year", "presets", "resolution"])) : vue.createCommentVNode("", true),
3154
+ vue.createElementVNode("div", _hoisted_2, [
3155
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
3156
+ caption: "Search",
3157
+ class: "blue",
3158
+ "left-icon": "search",
3159
+ onClick: emitSearch
3160
+ }),
3161
+ __props.config?.dateFilter ? (vue.openBlock(), vue.createBlock(vue.unref(openBlueseaCore.BSButton), {
3162
+ key: 0,
3163
+ caption: "Save",
3164
+ class: "ml-4",
3165
+ onClick: saveSearchCondition
3166
+ })) : vue.createCommentVNode("", true),
3167
+ vue.createVNode(vue.unref(openBlueseaCore.BSButton), {
3168
+ caption: "Reset",
3169
+ class: "ml-4",
3170
+ onClick: resetSearchCondition
3171
+ })
3172
+ ])
3173
+ ]);
3174
+ };
3175
+ }
3176
+ });
3177
+ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
3178
+ __name: "BSDateRangeFilter",
3179
+ props: {
3180
+ idFrom: {},
3181
+ idTo: {},
3182
+ nameFrom: {},
3183
+ nameTo: {},
3184
+ modelValue: {},
3185
+ disabled: { type: Boolean },
3186
+ width: { default: "300px" },
3187
+ resolution: { default: "DAY" },
3188
+ displayFormat: {},
3189
+ popupDisplayFormat: {},
3190
+ popupStartYear: {},
3191
+ popupEndYear: {},
3192
+ timeZone: {}
3193
+ },
3194
+ emits: ["update:modelValue"],
3195
+ setup(__props, { emit: __emit }) {
3196
+ const props = __props;
3197
+ const emit = __emit;
3198
+ const fromValue = vue.ref();
3199
+ const toValue = vue.ref();
3200
+ vue.watch(
3201
+ () => props.modelValue,
3202
+ () => {
3203
+ fromValue.value = props.modelValue?.from;
3204
+ toValue.value = props.modelValue?.to;
3205
+ },
3206
+ { immediate: true }
3207
+ );
3208
+ const emitValue = () => {
3209
+ const value = {
3210
+ from: fromValue.value,
3211
+ to: toValue.value
3212
+ };
3213
+ emit("update:modelValue", value);
3214
+ };
3215
+ return (_ctx, _cache) => {
3216
+ return vue.openBlock(), vue.createBlock(vue.unref(openBlueseaCore.BSDateRange), {
3217
+ "from-value": fromValue.value,
3218
+ "onUpdate:fromValue": [
3219
+ _cache[0] || (_cache[0] = ($event) => fromValue.value = $event),
3220
+ emitValue
3221
+ ],
3222
+ "to-value": toValue.value,
3223
+ "onUpdate:toValue": [
3224
+ _cache[1] || (_cache[1] = ($event) => toValue.value = $event),
3225
+ emitValue
3226
+ ],
3227
+ "disabled-from": __props.disabled,
3228
+ "disabled-to": __props.disabled,
3229
+ "display-format": __props.displayFormat,
3230
+ "id-from": __props.idFrom,
3231
+ "id-to": __props.idTo,
3232
+ "name-from": __props.nameFrom,
3233
+ "name-to": __props.nameTo,
3234
+ "popup-display-format": __props.popupDisplayFormat,
3235
+ "popup-end-year": __props.popupEndYear,
3236
+ "popup-start-year": __props.popupStartYear,
3237
+ resolution: __props.resolution,
3238
+ "time-zone": __props.timeZone,
3239
+ "validate-date-order": false,
3240
+ width: __props.width,
3241
+ "hide-extra-date": ""
3242
+ }, null, 8, ["from-value", "to-value", "disabled-from", "disabled-to", "display-format", "id-from", "id-to", "name-from", "name-to", "popup-display-format", "popup-end-year", "popup-start-year", "resolution", "time-zone", "width"]);
3243
+ };
3244
+ }
3245
+ });
3246
+ exports2.AbstractFilter = AbstractFilter;
3247
+ exports2.AndFilter = AndFilter;
3248
+ exports2.BSDateRangeFilter = _sfc_main;
3249
+ exports2.BSDateRangeFilters = _sfc_main$2;
3250
+ exports2.BSDateRangePresets = _sfc_main$3;
3251
+ exports2.BSGrid = _sfc_main$7;
3252
+ exports2.BSGridCell = _sfc_main$d;
3253
+ exports2.BSGridCellCheckbox = BSGridCellCheckbox;
3254
+ exports2.BSGridCellDragHandle = _sfc_main$9;
3255
+ exports2.BSGridCellEdit = _sfc_main$a;
3256
+ exports2.BSGridCellSerialNo = _sfc_main$c;
3257
+ exports2.BSGridColumnSettingModal = _sfc_main$6;
3258
+ exports2.BSGridControl = _sfc_main$5;
3259
+ exports2.BSGridHeaderCell = BSGridHeaderCell;
3260
+ exports2.BSGridHeaderCellCheckbox = _sfc_main$f;
3261
+ exports2.BSGridHeaderCellResizeHandle = BSGridHeaderCellResizeHandle;
3262
+ exports2.BSGridHeaderCellSerialNo = BSGridHeaderCellSerialNo;
3263
+ exports2.BSGridLookup = _sfc_main$1;
3264
+ exports2.BSGridRow = _sfc_main$8;
3265
+ exports2.BSTextFilter = _sfc_main$4;
3266
+ exports2.BetweenDateFilter = BetweenDateFilter;
3267
+ exports2.BetweenDateFilterWithPreset = BetweenDateFilterWithPreset;
3268
+ exports2.BetweenFilter = BetweenFilter;
3269
+ exports2.DEFAULT_GRID_COLUMN_WIDTH = DEFAULT_GRID_COLUMN_WIDTH;
3270
+ exports2.EditableInputGridHandlerImpl = EditableInputGridHandlerImpl;
3271
+ exports2.EditablePageGridHandlerImpl = EditablePageGridHandlerImpl;
3272
+ exports2.EditingRows = EditingRows;
3273
+ exports2.EqualFilter = EqualFilter;
3274
+ exports2.GridHandlerEditableSupport = GridHandlerEditableSupport;
3275
+ exports2.GridHandlerSelectDeleteSupport = GridHandlerSelectDeleteSupport;
3276
+ exports2.InFilter = InFilter;
3277
+ exports2.InputGridHandlerImpl = InputGridHandlerImpl;
3278
+ exports2.IsNotNullFilter = IsNotNullFilter;
3279
+ exports2.IsNullFilter = IsNullFilter;
3280
+ exports2.LikeFilter = LikeFilter;
3281
+ exports2.LocalStorageGridPreferenceStore = LocalStorageGridPreferenceStore;
3282
+ exports2.NotFilter = NotFilter;
3283
+ exports2.OrFilter = OrFilter;
3284
+ exports2.PageGridHandlerImpl = PageGridHandlerImpl;
3285
+ exports2.PaginatedList = PaginatedList;
3286
+ exports2.SearchParam = SearchParam;
3287
+ exports2.acceptFilter = acceptFilter;
3288
+ exports2.andFilter = andFilter;
3289
+ exports2.betweenDateFilter = betweenDateFilter;
3290
+ exports2.betweenFilter = betweenFilter;
3291
+ exports2.convertDateRangePresetKey = convertDateRangePresetKey;
3292
+ exports2.createDateRangeFromPreset = createDateRangeFromPreset;
3293
+ exports2.createInputGridHandler = createInputGridHandler;
3294
+ exports2.createPageGridHandler = createPageGridHandler;
3295
+ exports2.defaultCellFormatter = defaultCellFormatter;
3296
+ exports2.editComponentSlotName = editComponentSlotName;
3297
+ exports2.equalFilter = equalFilter;
3298
+ exports2.filterSlotName = filterSlotName;
3299
+ exports2.inFilter = inFilter;
3300
+ exports2.isNotNullFilter = isNotNullFilter;
3301
+ exports2.isNullFilter = isNullFilter;
3302
+ exports2.likeFilter = likeFilter;
3303
+ exports2.mergeColumnSettings = mergeColumnSettings;
3304
+ exports2.mergeSameValueVertical = mergeSameValueVertical;
3305
+ exports2.nameFilterCreator = nameFilterCreator;
3306
+ exports2.notFilter = notFilter;
3307
+ exports2.orFilter = orFilter;
3308
+ exports2.resolveMoment = resolveMoment;
3309
+ exports2.setFixedCellLeftStyle = setFixedCellLeftStyle;
3310
+ exports2.styleClassToObject = styleClassToObject;
3311
+ exports2.styleCssToObject = styleCssToObject;
3312
+ exports2.vDragSupport = vDragSupport;
3313
+ exports2.vDropSupport = vDropSupport;
3314
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
3315
+ }));