@vmscloud/moz-ui-grid-vue 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { onBeforeUnmount, inject, ref, watch, nextTick, shallowRef, defineComponent, createElementBlock, openBlock, computed, provide, reactive, createApp, h, getCurrentInstance, mergeModels, useModel, useSlots, onMounted, toRef, Fragment, createElementVNode, renderSlot, createBlock, createCommentVNode, normalizeStyle, mergeProps, toHandlers, unref, createSlots, withCtx, normalizeProps, guardReactiveProps } from "vue";
5
- import { Popup, radio, select, button, GridChrome, WRAPPER_EXTRA_KEYS } from "@vmscloud/moz-ui-grid-wrapper";
5
+ import { stampPresetVersion, migrateGridPreset, applyPresetCoreConfig, Popup, radio, select, button, GridChrome, WRAPPER_EXTRA_KEYS } from "@vmscloud/moz-ui-grid-wrapper";
6
6
  import { u as useGridNotificationStore } from "./chunks/notification.contract-BTOch6ed.js";
7
7
  import { G, p } from "./chunks/notification.contract-BTOch6ed.js";
8
8
  import { html, nothing } from "lit-html";
@@ -98,41 +98,55 @@ const useUserLayoutModule = () => inject(USER_LAYOUT_PROVIDER_KEY, {
98
98
  currentPreset: ref(null)
99
99
  });
100
100
  function useGridPreset(options) {
101
+ if (options.usePreset === false) return;
101
102
  const { register } = useUserLayoutModule();
102
103
  const exportDef = () => {
103
104
  var _a, _b;
104
105
  const grid = options.gridInstance.value;
105
106
  if (!grid) return null;
106
- return {
107
- ...grid.getConfig(),
107
+ const def = {
108
+ ...stampPresetVersion(grid.getConfig()),
108
109
  customCellConfig: ((_a = options.getCustomCellState) == null ? void 0 : _a.call(options)) ?? null,
109
110
  columnFormatConfig: ((_b = options.getColumnFormatState) == null ? void 0 : _b.call(options)) ?? null
110
111
  };
112
+ if (options.getViewOptionsState) def.viewOptionsConfig = options.getViewOptionsState() ?? null;
113
+ return def;
114
+ };
115
+ const applyExtra = (set, value) => {
116
+ if (value !== void 0) set == null ? void 0 : set(value);
111
117
  };
112
- const importDef = async (preset) => {
113
- var _a, _b, _c, _d;
118
+ const applyPreset = async (preset) => {
114
119
  const grid = options.gridInstance.value;
115
120
  if (!grid) return;
116
- if (!preset) {
117
- const defaultDef = layoutInstance.default;
118
- if (defaultDef) {
119
- await grid.applyConfig(defaultDef);
120
- if (defaultDef.customCellConfig) {
121
- (_a = options.setCustomCellState) == null ? void 0 : _a.call(options, defaultDef.customCellConfig);
122
- }
123
- if (defaultDef.columnFormatConfig) {
124
- (_b = options.setColumnFormatState) == null ? void 0 : _b.call(options, defaultDef.columnFormatConfig);
125
- }
126
- }
127
- return;
128
- }
129
- await grid.applyConfig(preset);
130
- if (preset.customCellConfig) {
131
- (_c = options.setCustomCellState) == null ? void 0 : _c.call(options, preset.customCellConfig);
132
- }
133
- if (preset.columnFormatConfig) {
134
- (_d = options.setColumnFormatState) == null ? void 0 : _d.call(options, preset.columnFormatConfig);
121
+ const baseline = layoutInstance.default ?? null;
122
+ const migrated = migrateGridPreset(preset ?? baseline, {
123
+ grid,
124
+ getSourceFields: options.getSourceFields,
125
+ baseline
126
+ });
127
+ if (migrated.diagnostics.length) {
128
+ if (options.onImportDiagnostics) options.onImportDiagnostics(migrated.diagnostics);
129
+ else console.warn("[Grid preset compatibility]", migrated.diagnostics);
135
130
  }
131
+ if (migrated.config) await applyPresetCoreConfig(grid, migrated.config, migrated.missing);
132
+ applyExtra(options.setColumnFormatState, migrated.columnFormatConfig);
133
+ applyExtra(options.setCustomCellState, migrated.customCellConfig);
134
+ applyExtra(options.setViewOptionsState, migrated.viewOptionsConfig);
135
+ };
136
+ let latestRequest = 0;
137
+ let queue = Promise.resolve();
138
+ const importDef = (preset) => {
139
+ const token = ++latestRequest;
140
+ const run = queue.then(async () => {
141
+ if (token !== latestRequest) return;
142
+ try {
143
+ await applyPreset(preset);
144
+ } catch (error) {
145
+ console.error("[Grid preset] import failed", error);
146
+ }
147
+ });
148
+ queue = run;
149
+ return run;
136
150
  };
137
151
  const layoutInstance = new UserLayoutInstance({
138
152
  id: options.name.value,
@@ -213,6 +227,8 @@ async function runClientExport(grid, config, notificationStore) {
213
227
  suggestedName: fileName,
214
228
  fallbackToDownload: true,
215
229
  sheetSplit: "auto",
230
+ // 화면에 보이는 그대로 — 고정 행을 화면 순서로 포함(core 기본값 false). clientExportOptions 로 끌 수 있음.
231
+ includePinnedRows: true,
216
232
  onProgress: (p2) => {
217
233
  if (!notificationStore) return;
218
234
  const target = notificationStore.eventMessages.find(
@@ -992,6 +1008,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
992
1008
  useMultipleChart: { type: Boolean },
993
1009
  chartIncludeGrandTotal: { type: Boolean },
994
1010
  chartMap: {},
1011
+ chartConfig: {},
995
1012
  useRowGroupSettings: { type: Boolean, default: true },
996
1013
  useFieldSettings: { type: Boolean, default: true },
997
1014
  useFormatSettings: { type: Boolean, default: true },
@@ -1009,7 +1026,9 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1009
1026
  useChart: { type: Boolean },
1010
1027
  loading: { type: Boolean },
1011
1028
  useBuiltinTooltip: { type: Boolean, default: true },
1012
- name: {}
1029
+ toolbarConfig: {},
1030
+ name: {},
1031
+ usePreset: { type: Boolean, default: true }
1013
1032
  }, {
1014
1033
  "coreConfig": { default: () => ({}) },
1015
1034
  "coreConfigModifiers": {}
@@ -1144,12 +1163,13 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1144
1163
  return { height: typeof h2 === "number" ? `${h2}px` : h2, width: "100%" };
1145
1164
  });
1146
1165
  function slotRenderer(name) {
1147
- return (container) => {
1166
+ return (container, ctx) => {
1148
1167
  const slotComponent = {
1149
1168
  // tool-items 는 toolItemsProps(ref)를 스코프 슬롯 props 로 — render 에서 .value 읽어 반응형 갱신.
1169
+ // option-menu-items 는 크롬이 넘긴 { close, mode }(WrapperOptionMenuItemsProps)를 스코프 슬롯 props 로.
1150
1170
  render: () => {
1151
- var _a, _b;
1152
- return (name === "tool-items" ? (_a = slots[name]) == null ? void 0 : _a.call(slots, toolItemsProps.value) : (_b = slots[name]) == null ? void 0 : _b.call(slots)) ?? null;
1171
+ var _a, _b, _c;
1172
+ return (name === "tool-items" ? (_a = slots[name]) == null ? void 0 : _a.call(slots, toolItemsProps.value) : name === "option-menu-items" ? (_b = slots[name]) == null ? void 0 : _b.call(slots, ctx.props) : (_c = slots[name]) == null ? void 0 : _c.call(slots)) ?? null;
1153
1173
  }
1154
1174
  };
1155
1175
  const key = `slot:${name}`;
@@ -1175,7 +1195,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1175
1195
  return core;
1176
1196
  }
1177
1197
  function buildChromeOptions() {
1178
- const CHROME_SLOTS = ["tool-left", "tool-items", "option-popup", "tool-bottom", "notification", "footer", "empty-state"];
1198
+ const CHROME_SLOTS = ["tool-left", "tool-items", "option-popup", "tool-bottom", "notification", "footer", "empty-state", "option-menu-items"];
1179
1199
  const slotMap = {};
1180
1200
  for (const name of CHROME_SLOTS) {
1181
1201
  if (slots[name]) slotMap[name] = slotRenderer(name);
@@ -1197,9 +1217,11 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1197
1217
  useFormatSettings: props.useFormatSettings,
1198
1218
  useLayoutSettings: props.useLayoutSettings,
1199
1219
  useAggregateSettings: props.useAggregateSettings,
1220
+ toolbarConfig: props.toolbarConfig,
1200
1221
  useMultipleChart: props.useMultipleChart,
1201
1222
  chartIncludeGrandTotal: props.chartIncludeGrandTotal,
1202
1223
  chartMap: props.chartMap,
1224
+ chartConfig: props.chartConfig,
1203
1225
  loading: props.loading,
1204
1226
  locale: resolvedLocale.value,
1205
1227
  sourceFields: props.sourceFields,
@@ -1332,23 +1354,33 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1332
1354
  { deep: true }
1333
1355
  );
1334
1356
  watch(
1335
- () => ({
1336
- useToolBox: props.useToolBox,
1337
- useToolBoxSetting: props.useToolBoxSetting,
1338
- useExtendFooter: props.useExtendFooter,
1339
- useSummaryFooter: props.useSummaryFooter,
1340
- useSort: props.useSort,
1341
- useCustomCell: props.useCustomCell,
1342
- useContextMenu: props.useContextMenu,
1343
- useBuiltinTooltip: props.useBuiltinTooltip,
1344
- usePivot: props.usePivot,
1345
- usePivotBar: props.usePivotBar,
1346
- useRowGroupSettings: props.useRowGroupSettings,
1347
- useFieldSettings: props.useFieldSettings,
1348
- useFormatSettings: props.useFormatSettings,
1349
- useLayoutSettings: props.useLayoutSettings,
1350
- useAggregateSettings: props.useAggregateSettings
1351
- }),
1357
+ () => {
1358
+ var _a, _b, _c, _d;
1359
+ return {
1360
+ useToolBox: props.useToolBox,
1361
+ useToolBoxSetting: props.useToolBoxSetting,
1362
+ useExtendFooter: props.useExtendFooter,
1363
+ useSummaryFooter: props.useSummaryFooter,
1364
+ useSort: props.useSort,
1365
+ useCustomCell: props.useCustomCell,
1366
+ useContextMenu: props.useContextMenu,
1367
+ useBuiltinTooltip: props.useBuiltinTooltip,
1368
+ usePivot: props.usePivot,
1369
+ usePivotBar: props.usePivotBar,
1370
+ useRowGroupSettings: props.useRowGroupSettings,
1371
+ useFieldSettings: props.useFieldSettings,
1372
+ useFormatSettings: props.useFormatSettings,
1373
+ useLayoutSettings: props.useLayoutSettings,
1374
+ useAggregateSettings: props.useAggregateSettings,
1375
+ // 툴바 필터 버튼 — 중첩 값을 직접 읽어 reactive 객체의 필드 변경도 추적(크롬이 값으로 비교).
1376
+ toolbarConfig: {
1377
+ filter: {
1378
+ disabled: (_b = (_a = props.toolbarConfig) == null ? void 0 : _a.filter) == null ? void 0 : _b.disabled,
1379
+ hidden: (_d = (_c = props.toolbarConfig) == null ? void 0 : _c.filter) == null ? void 0 : _d.hidden
1380
+ }
1381
+ }
1382
+ };
1383
+ },
1352
1384
  (next) => chrome == null ? void 0 : chrome.setUIOptions(next)
1353
1385
  );
1354
1386
  watch(
@@ -1366,6 +1398,14 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1366
1398
  (cfg) => chrome == null ? void 0 : chrome.setContextMenuConfig(cfg),
1367
1399
  { deep: true }
1368
1400
  );
1401
+ watch(
1402
+ () => props.chartConfig,
1403
+ (cfg) => {
1404
+ var _a;
1405
+ return (_a = chrome == null ? void 0 : chrome.setChartConfig) == null ? void 0 : _a.call(chrome, cfg);
1406
+ },
1407
+ { deep: true }
1408
+ );
1369
1409
  });
1370
1410
  onBeforeUnmount(() => {
1371
1411
  clearChromeUnsubs();
@@ -1375,17 +1415,35 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1375
1415
  vueRenderer.unmountAll();
1376
1416
  });
1377
1417
  useGridPreset({
1418
+ usePreset: props.usePreset,
1378
1419
  name: toRef(props, "name"),
1379
1420
  type: coreConfig.value.mode === "pivot" ? "mozPivotGrid" : "mozFlatGrid",
1380
1421
  gridInstance,
1422
+ // 피벗 카탈로그(AvailableField)에는 컬럼 id 가 없다 — 선언 fields 의 field→id 로 실제 id 를 되찾는다.
1423
+ // (id 를 f.field 로 채우면 id≠field 그리드에서 Wijmo flat 변환·customCell 대상이 없는 id 로 해석된다.)
1424
+ getSourceFields: () => {
1425
+ const declared = coreConfig.value.fields ?? [];
1426
+ const idByField = new Map(declared.map((d2) => [d2.field ?? d2.id, d2.id]));
1427
+ return ((chrome == null ? void 0 : chrome.pivot.sourceFields) ?? []).map((f) => ({ id: idByField.get(f.field) ?? f.field, field: f.field, header: f.header, dataType: f.dataType }));
1428
+ },
1381
1429
  getCustomCellState: () => (chrome == null ? void 0 : chrome.customCell.getCustomCell()) ?? null,
1430
+ // null = 빈 상태로 초기화(프리셋 null 저장본·기본 보기 — F03). 컨트롤러 setter 가 null 을 빈 상태로 받는다.
1382
1431
  setCustomCellState: (s) => {
1383
- if (s && chrome) chrome.customCell.setCustomCell(s);
1432
+ chrome == null ? void 0 : chrome.customCell.setCustomCell(s ?? null);
1384
1433
  },
1385
1434
  // 컬럼 옵션 시각 서식(ColumnFormatController) — core getConfig 에 없는 wrapper 전용 상태라 별도 직렬화.
1386
1435
  getColumnFormatState: () => (chrome == null ? void 0 : chrome.columnFormat.getConfig()) ?? null,
1387
1436
  setColumnFormatState: (s) => {
1388
- if (s && chrome) chrome.columnFormat.setConfig(s);
1437
+ chrome == null ? void 0 : chrome.columnFormat.setConfig(s ?? null);
1438
+ },
1439
+ // 보기 설정 토글(툴바 펼침/푸터/그룹 패널) + 피벗 옵션 바 표시 — wrapper 소유 보기 상태.
1440
+ getViewOptionsState: () => {
1441
+ var _a;
1442
+ return ((_a = chrome == null ? void 0 : chrome.getPresetViewState) == null ? void 0 : _a.call(chrome)) ?? null;
1443
+ },
1444
+ setViewOptionsState: (s) => {
1445
+ var _a;
1446
+ (_a = chrome == null ? void 0 : chrome.setPresetViewState) == null ? void 0 : _a.call(chrome, s);
1389
1447
  }
1390
1448
  });
1391
1449
  const exposed = new Proxy({}, {
@@ -1422,7 +1480,7 @@ const _export_sfc = (sfc, props) => {
1422
1480
  }
1423
1481
  return target;
1424
1482
  };
1425
- const MozGrid = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-a719186c"]]);
1483
+ const MozGrid = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-ecaeb65f"]]);
1426
1484
  const CellTemplate = defineComponent({
1427
1485
  name: "CellTemplate",
1428
1486
  props: {
@@ -1566,6 +1624,8 @@ const DetailTemplate = defineComponent({
1566
1624
  return () => null;
1567
1625
  }
1568
1626
  });
1627
+ const GROUP_TEMPLATE_DISPOSE_EVENT = "ps-group-template-dispose";
1628
+ const GROUP_TEMPLATE_HOST_CLASS = "ps-group-template-host";
1569
1629
  const GroupTemplate = defineComponent({
1570
1630
  name: "GroupTemplate",
1571
1631
  setup() {
@@ -1576,16 +1636,21 @@ const GroupTemplate = defineComponent({
1576
1636
  console.warn("[MozGridVue] GroupTemplate은 MozGridVue 내부에서 사용해야 합니다.");
1577
1637
  return () => null;
1578
1638
  }
1579
- onMounted(() => {
1580
- const grid = gridRef.value;
1581
- if (!grid || !slots.default) return;
1639
+ const instances = /* @__PURE__ */ new Map();
1640
+ const dispose = (container) => {
1641
+ const instance2 = instances.get(container);
1642
+ if (!instance2) return;
1643
+ instances.delete(container);
1644
+ instance2.destroy();
1645
+ };
1646
+ const register = (grid) => {
1647
+ if (!slots.default) return;
1582
1648
  const slot = slots.default;
1583
1649
  grid.formatRow.addHandler("_groupTemplate", (info) => {
1584
1650
  if (info.type !== "group-row") return;
1585
1651
  const ctx = info.ctx;
1586
1652
  const container = ctx.element;
1587
1653
  if (!container) return;
1588
- const key = `group:${ctx.viewIndex}`;
1589
1654
  const slotProps = {
1590
1655
  groupKey: ctx.column,
1591
1656
  groupValue: ctx.value,
@@ -1593,17 +1658,35 @@ const GroupTemplate = defineComponent({
1593
1658
  count: ctx.itemCount,
1594
1659
  isExpanded: !ctx.collapsed
1595
1660
  };
1596
- renderer.mount(key, container, {
1597
- render() {
1598
- return slot(slotProps);
1599
- }
1600
- }, slotProps);
1661
+ const existing = instances.get(container);
1662
+ if (existing && container.classList.contains(GROUP_TEMPLATE_HOST_CLASS)) {
1663
+ existing.update(slotProps);
1664
+ return;
1665
+ }
1666
+ if (existing) dispose(container);
1667
+ const instance2 = renderer.mountInstance(
1668
+ container,
1669
+ (props) => slot(props),
1670
+ slotProps
1671
+ );
1672
+ instances.set(container, instance2);
1673
+ container.addEventListener(GROUP_TEMPLATE_DISPOSE_EVENT, () => dispose(container), { once: true });
1601
1674
  });
1602
- });
1675
+ };
1676
+ const unregister = (grid) => {
1677
+ grid == null ? void 0 : grid.formatRow.removeHandler("_groupTemplate");
1678
+ for (const container of [...instances.keys()]) dispose(container);
1679
+ };
1680
+ let registeredGrid = null;
1681
+ watch(gridRef, (grid) => {
1682
+ if (grid === registeredGrid) return;
1683
+ unregister(registeredGrid);
1684
+ registeredGrid = grid ?? null;
1685
+ if (grid) register(grid);
1686
+ }, { immediate: true });
1603
1687
  onBeforeUnmount(() => {
1604
- var _a;
1605
- renderer == null ? void 0 : renderer.unmountByPrefix("group:");
1606
- (_a = gridRef.value) == null ? void 0 : _a.formatRow.removeHandler("_groupTemplate");
1688
+ unregister(registeredGrid);
1689
+ registeredGrid = null;
1607
1690
  });
1608
1691
  return () => null;
1609
1692
  }