@done-coding/admin-core 0.30.0 → 0.30.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/es/bridge/badge.mjs +7 -1
  2. package/es/components/app-layout/AppPage.vue.mjs +1 -1
  3. package/es/components/app-layout/AppPage.vue2.mjs +15 -8
  4. package/es/components/app-layout/app-page-geometry.mjs +7 -3
  5. package/es/components/app-layout/use-slot-misuse-warn.mjs +40 -0
  6. package/es/components/data-view/DataGridView.vue.mjs +1 -1
  7. package/es/components/data-view/DataGridView.vue2.mjs +83 -32
  8. package/es/components/data-view/DataGridViewCard.vue.mjs +41 -0
  9. package/es/components/data-view/DataGridViewCard.vue2.mjs +4 -0
  10. package/es/components/data-view/InfiniteListView.vue.mjs +1 -1
  11. package/es/components/data-view/InfiniteListView.vue2.mjs +38 -11
  12. package/es/components/display/BadgeMark.vue.mjs +1 -1
  13. package/es/components/display/BadgeMark.vue2.mjs +31 -33
  14. package/es/components/display/use-badge.mjs +37 -33
  15. package/es/components/form/FormGroupTitle.vue.mjs +1 -1
  16. package/es/components/form/FormItem.vue.mjs +1 -1
  17. package/es/components/form/FormItemNestForm.vue.mjs +1 -1
  18. package/es/components/form/FormItemNestFormList.vue.mjs +1 -1
  19. package/es/components/form/FormTree.vue.mjs +5 -30
  20. package/es/components/form/FormTree.vue2.mjs +30 -1
  21. package/es/components/form/FormUpload.vue.mjs +1 -1
  22. package/es/components/modal/ModalPorter.vue.mjs +2 -0
  23. package/es/components/modal/use-slot-misuse-warn.mjs +22 -0
  24. package/es/components/page-layout/AppPageListDetailSplit.vue.mjs +1 -1
  25. package/es/components/page-layout/AppPageListDetailSplit.vue2.mjs +7 -7
  26. package/es/components/view-layout/ViewLayout.vue.mjs +1 -1
  27. package/es/components/view-layout/ViewLayout.vue2.mjs +71 -91
  28. package/es/components/view-layout/ViewLayoutToolbar.vue.mjs +7 -0
  29. package/es/components/view-layout/ViewLayoutToolbar.vue2.mjs +189 -0
  30. package/es/config/slot-region.mjs +23 -1
  31. package/es/hooks/use-custom-breakpoint.mjs +12 -2
  32. package/es/hooks/use-is-dev.mjs +16 -0
  33. package/es/hooks/use-theme-apply.mjs +2 -2
  34. package/es/index.mjs +90 -88
  35. package/es/style.css +138 -87
  36. package/package.json +2 -2
  37. package/src/bridge/docs/README.md +34 -4
  38. package/src/components/app-layout/docs/README-AppPage.md +68 -0
  39. package/src/components/data-view/docs/README-DataGridView.md +83 -1
  40. package/src/components/data-view/docs/README-DataListView.md +5 -2
  41. package/src/components/display/docs/README-BadgeMark.md +102 -41
  42. package/src/components/form/README.md +14 -0
  43. package/src/components/form/docs/README-FormItemNestForm.md +3 -0
  44. package/src/components/form/docs/README-FormItemNestFormList.md +3 -0
  45. package/src/components/form/docs/README-FormUpload.md +3 -0
  46. package/src/components/modal/docs/README-ModalPorter.md +26 -0
  47. package/src/components/page-layout/docs/README-AppPageListDetailLayout.md +1 -1
  48. package/src/components/view-layout/docs/README-ViewLayout.md +152 -9
  49. package/src/hooks/docs/README.md +37 -1
  50. package/types/bridge/badge.d.ts +38 -2
  51. package/types/components/app-layout/AppPage.vue.d.ts +16 -0
  52. package/types/components/app-layout/app-page-geometry.d.ts +26 -2
  53. package/types/components/app-layout/use-slot-misuse-warn.d.ts +19 -0
  54. package/types/components/data-view/DataGridView.vue.d.ts +9 -0
  55. package/types/components/data-view/DataGridViewCard.vue.d.ts +25 -0
  56. package/types/components/data-view/types.d.ts +63 -0
  57. package/types/components/display/BadgeMark.vue.d.ts +9 -8
  58. package/types/components/display/use-badge.d.ts +22 -14
  59. package/types/components/modal/use-slot-misuse-warn.d.ts +21 -0
  60. package/types/components/view-layout/ViewLayout.vue.d.ts +16 -0
  61. package/types/components/view-layout/ViewLayoutToolbar.vue.d.ts +52 -0
  62. package/types/components/view-layout/types.d.ts +56 -0
  63. package/types/config/slot-region.d.ts +12 -0
  64. package/types/hooks/use-custom-breakpoint.d.ts +1 -12
  65. package/types/hooks/use-is-dev.d.ts +24 -0
  66. package/types/injectInfo.json.d.ts +1 -1
@@ -4,6 +4,7 @@ const BADGE_MASK_KINDS = [
4
4
  ];
5
5
  function createBridgeBadgeHook(init = {}) {
6
6
  const marks = shallowRef({ ...init.marks ?? {} });
7
+ const defaultVisible = shallowRef(init.defaultVisible ?? true);
7
8
  const setAll = (next) => {
8
9
  marks.value = { ...next };
9
10
  };
@@ -16,12 +17,17 @@ function createBridgeBadgeHook(init = {}) {
16
17
  delete next[key];
17
18
  marks.value = next;
18
19
  };
20
+ const setDefaultVisible = (visible) => {
21
+ defaultVisible.value = visible;
22
+ };
19
23
  return {
20
24
  badge: {
21
25
  marks: readonly(marks),
22
26
  setAll,
23
27
  set,
24
- remove
28
+ remove,
29
+ defaultVisible: readonly(defaultVisible),
30
+ setDefaultVisible
25
31
  }
26
32
  };
27
33
  }
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./AppPage.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const AppPage = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-facaf577"]]);
4
+ const AppPage = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-73e3d4a9"]]);
5
5
  export {
6
6
  AppPage as default
7
7
  };
@@ -4,6 +4,7 @@ import _sfc_main$1 from "../modal/ModalShelf.vue.mjs";
4
4
  import _sfc_main$2 from "../display/WatchSize.vue.mjs";
5
5
  import { computeAppPageReducedViewportHeight, computeAppPageReducedViewportWidth, computeAppPageContentInset, computeAppPageSlotStyles, computeAppPageSlotShimStyles } from "./app-page-geometry.mjs";
6
6
  import { useAppPageContentBox } from "./use-content-box.mjs";
7
+ import { useAppPageSlotMisuseWarn } from "./use-slot-misuse-warn.mjs";
7
8
  import { APP_PAGE_LIST_LAYOUT_RECOMMENDED } from "./app-page-recommended.mjs";
8
9
  import { BODY_CONTENT_VIEWPORT_RECT, APP_LAYOUT_BRIDGE_KEY, SCOPE_VIEWPORT_MAX_HEIGHT, BODY_CONTENT_VIEWPORT_HEIGHT, BODY_CONTENT_VIEWPORT_INSET, APP_PAGE_CONTENT_INSET } from "../../inject/key.mjs";
9
10
  import { useActivated } from "../../hooks/activated.mjs";
@@ -34,18 +35,20 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
34
35
  bottomObserveResize: { type: Boolean, default: false },
35
36
  leftObserveResize: { type: Boolean, default: false },
36
37
  rightObserveResize: { type: Boolean, default: false },
38
+ leftWidth: {},
39
+ rightWidth: {},
37
40
  contentCentered: { type: Boolean, default: false },
38
41
  contentMaxWidth: { default: 1200 }
39
42
  },
40
43
  setup(__props) {
41
44
  useCssVars((_ctx) => ({
42
- "v14c1dc69": pageCssVars.value.top,
43
- "v6d1cb697": pageCssVars.value.bottom,
44
- "f914311a": pageCssVars.value.left,
45
- "v28c52fa0": pageCssVars.value.right,
46
- "v2838584c": pageCssVars.value.width,
47
- "v76c7ad93": pageCssVars.value.height,
48
- "v9258c294": props.nextViewportMaxHeight
45
+ "v62d8191f": pageCssVars.value.top,
46
+ "v7adfb621": pageCssVars.value.bottom,
47
+ "v0fb17d06": pageCssVars.value.left,
48
+ "v0d174f66": pageCssVars.value.right,
49
+ "v0d5dbb10": pageCssVars.value.width,
50
+ "f6eaa5c6": pageCssVars.value.height,
51
+ "v4ad30b28": props.nextViewportMaxHeight
49
52
  }));
50
53
  const props = __props;
51
54
  const style = computed(() => {
@@ -167,6 +170,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
167
170
  }
168
171
  });
169
172
  }
173
+ useAppPageSlotMisuseWarn({ root: () => appPageRef.value });
170
174
  const reducedViewportWidth = computed(
171
175
  () => computeAppPageReducedViewportWidth(
172
176
  pageBoxWidth.value,
@@ -211,7 +215,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
211
215
  };
212
216
  });
213
217
  const slotStyles = computed(
214
- () => computeAppPageSlotStyles(rectInset.value, slotSizes.value, outerGap.value)
218
+ () => computeAppPageSlotStyles(rectInset.value, slotSizes.value, {
219
+ outerGap: outerGap.value,
220
+ sideWidth: { left: props.leftWidth, right: props.rightWidth }
221
+ })
215
222
  );
216
223
  const shimStyles = computed(() => {
217
224
  const base = computeAppPageSlotShimStyles();
@@ -23,7 +23,8 @@ function computeAppPageContentInset(appInset, slotSizes, gap) {
23
23
  };
24
24
  }
25
25
  const APP_PAGE_SLOT_Z_INDEX = 1;
26
- function computeAppPageSlotStyles(rect, slotSizes, outerGap) {
26
+ function computeAppPageSlotStyles(rect, slotSizes, options) {
27
+ const { outerGap, sideWidth = {} } = options;
27
28
  const z = APP_PAGE_SLOT_Z_INDEX;
28
29
  const { topH, bottomH } = slotSizes;
29
30
  const midTop = `calc(${rect.top} + ${appPageSlotInset(topH, outerGap)}px)`;
@@ -51,14 +52,17 @@ function computeAppPageSlotStyles(rect, slotSizes, outerGap) {
51
52
  left: rect.left,
52
53
  top: midTop,
53
54
  bottom: midBottom,
54
- zIndex: z
55
+ zIndex: z,
56
+ // 缺省不写 width ⇒ 保持 shrink-to-fit(老行为逐字不变)
57
+ ...sideWidth.left ? { width: sideWidth.left } : {}
55
58
  },
56
59
  right: {
57
60
  position: "fixed",
58
61
  right: rect.right,
59
62
  top: midTop,
60
63
  bottom: midBottom,
61
- zIndex: z
64
+ zIndex: z,
65
+ ...sideWidth.right ? { width: sideWidth.right } : {}
62
66
  }
63
67
  };
64
68
  }
@@ -0,0 +1,40 @@
1
+ import { useIsDev } from "../../hooks/use-is-dev.mjs";
2
+ import { useActivated } from "../../hooks/activated.mjs";
3
+ import { APP_PAGE_SIDE_SLOTS } from "../../config/slot-region.mjs";
4
+ const occupiesLayout = (host) => Array.from(host.childNodes).some(
5
+ (node) => {
6
+ var _a;
7
+ return node.nodeType === 1 || node.nodeType === 3 && !!((_a = node.nodeValue) == null ? void 0 : _a.trim());
8
+ }
9
+ );
10
+ const findSlotShim = (root, slot) => {
11
+ var _a;
12
+ return ((_a = Array.from(root.children).find(
13
+ (el) => el.classList.contains(`app-page-slot--${slot}`)
14
+ )) == null ? void 0 : _a.firstElementChild) ?? void 0;
15
+ };
16
+ const useAppPageSlotMisuseWarn = (options) => {
17
+ const isDev = useIsDev();
18
+ const reported = /* @__PURE__ */ new Set();
19
+ useActivated((info) => {
20
+ if (!info.isActivated) return;
21
+ if (!isDev()) return;
22
+ const root = options.root();
23
+ if (!root) return;
24
+ for (const slot of APP_PAGE_SIDE_SLOTS) {
25
+ if (reported.has(slot)) continue;
26
+ const shim = findSlotShim(root, slot);
27
+ if (!shim || occupiesLayout(shim)) continue;
28
+ reported.add(slot);
29
+ console.error(
30
+ `[AppPage] #${slot} 槽里没有占版面的内容,但槽本身照样渲染(fixed + padding + 背景)并从默认内容里扣掉让位 —— 白占一条。
31
+ · 若放的是 ModalPorter:移到**默认槽**(page 架子就住在默认槽里,与 AppPage 并列同样够不到,evoke() 一样恒为 null);
32
+ · 若放的是自己 teleport 走、不需要 page 架子的弹窗:移到默认槽或与 AppPage 并列均可;
33
+ · 若是 v-if 条件渲染的内容:此刻恰好为空,忽略本条。`
34
+ );
35
+ }
36
+ });
37
+ };
38
+ export {
39
+ useAppPageSlotMisuseWarn
40
+ };
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./DataGridView.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const DataGridView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-136078cd"]]);
4
+ const DataGridView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-b4c213bc"]]);
5
5
  export {
6
6
  DataGridView as default
7
7
  };
@@ -1,9 +1,11 @@
1
- import { defineComponent, useCssVars, unref, useModel, shallowRef, ref, computed, onMounted, onActivated, watch, openBlock, createElementBlock, normalizeClass, createBlock, withCtx, createVNode, mergeProps, createCommentVNode, createElementVNode, toDisplayString, createTextVNode, normalizeStyle, Fragment, renderList, renderSlot, resolveDynamicComponent, mergeModels } from "vue";
1
+ import { defineComponent, useCssVars, unref, useModel, shallowRef, ref, computed, watch, nextTick, onMounted, onActivated, openBlock, createElementBlock, normalizeClass, createBlock, withCtx, createVNode, mergeProps, createCommentVNode, createElementVNode, toDisplayString, createTextVNode, normalizeStyle, renderSlot, normalizeProps, guardReactiveProps, Fragment, renderList, mergeModels } from "vue";
2
2
  import { ElButton } from "element-plus";
3
3
  import TableToolbar from "../table/TableToolbar.vue.mjs";
4
4
  import _sfc_main$2 from "../table/TableEmpty.vue.mjs";
5
5
  import TableSkeleton from "../table/TableSkeleton.vue.mjs";
6
+ import { useObserveSize } from "../../hooks/use-observe-size.mjs";
6
7
  import { useDataViewGridLayout } from "./use-grid-layout.mjs";
8
+ import _sfc_main$3 from "./DataGridViewCard.vue.mjs";
7
9
  import { useSurface } from "../../hooks/use-surface.mjs";
8
10
  import _sfc_main$1 from "../display/WatchSize.vue.mjs";
9
11
  import _cloneDeep from "lodash/cloneDeep";
@@ -18,10 +20,8 @@ import { pickExportColumns } from "../../utils/export.mjs";
18
20
  import { useChannelViewportHeight } from "../../hooks/use-channel-viewport-height.mjs";
19
21
  import { APP_API_LIST_MODEL_KEY_CONFIG } from "../../config/list-model.mjs";
20
22
  const _hoisted_1 = ["onClick"];
21
- const _hoisted_2 = { class: "data-grid-view__card" };
22
- const _hoisted_3 = { class: "data-grid-view__field-label" };
23
- const _hoisted_4 = { class: "data-grid-view__field-value" };
24
- const _hoisted_5 = {
23
+ const _hoisted_2 = ["onClick"];
24
+ const _hoisted_3 = {
25
25
  key: 0,
26
26
  class: "data-grid-view__empty-error"
27
27
  };
@@ -36,6 +36,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
36
36
  gridColumns: { default: 4 },
37
37
  gap: {},
38
38
  card: { type: Boolean, default: true },
39
+ masonry: { type: Boolean },
40
+ estimateItemHeight: {},
39
41
  surface: { type: Boolean, default: void 0 },
40
42
  itemCard: { type: Boolean, default: void 0 },
41
43
  maxHeight: { default: "100vh" },
@@ -65,7 +67,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
65
67
  emits: /* @__PURE__ */ mergeModels(["pageChange", "pageSizeChange", "dataChange", "selectionChange", "loadingChange", "pageInfoChange"], ["update:isAutoRefresh", "update:refreshInterval", "update:activeId", "update:activeData"]),
66
68
  setup(__props, { expose: __expose, emit: __emit }) {
67
69
  useCssVars((_ctx) => ({
68
- "e2a8f6ae": unref(surfacePadCss)
70
+ "v081d8ea3": unref(surfacePadCss)
69
71
  }));
70
72
  const props = __props;
71
73
  const emits = __emit;
@@ -226,6 +228,40 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
226
228
  const gridColumnsFinal = computed(
227
229
  () => resolveGridColumnsByBreakpoint(props.gridColumns, activeBreakpoint.value)
228
230
  );
231
+ const masonryActive = computed(
232
+ () => !!props.masonry && !!props.estimateItemHeight && typeof props.gridColumns !== "object"
233
+ );
234
+ const gridBoxRef = shallowRef();
235
+ const gridBoxWidth = ref(0);
236
+ const measureGridBox = () => {
237
+ const el = gridBoxRef.value;
238
+ if (el) gridBoxWidth.value = el.clientWidth;
239
+ };
240
+ useObserveSize({
241
+ getTarget: () => gridBoxRef.value,
242
+ onResize: measureGridBox,
243
+ enabled: () => masonryActive.value
244
+ });
245
+ watch(masonryActive, (on) => on && nextTick(measureGridBox), {
246
+ immediate: true
247
+ });
248
+ const columnWidth = computed(() => {
249
+ const cols = gridColumnsFinal.value;
250
+ const inner = gridBoxWidth.value - (cols - 1) * gridGap.value;
251
+ return cols > 0 ? Math.max(0, inner / cols) : 0;
252
+ });
253
+ const estimateSizeAt = (index) => {
254
+ const row = store.value[index];
255
+ if (!row || !props.estimateItemHeight) return 0;
256
+ return props.estimateItemHeight(row, columnWidth.value);
257
+ };
258
+ const virtualData = computed(
259
+ () => masonryActive.value ? store.value : gridRows.value
260
+ );
261
+ const asRow = (item) => item;
262
+ const virtualItemKey = computed(
263
+ () => masonryActive.value ? (row) => keyOf(row) : (row) => rowKeyOfRow(row)
264
+ );
229
265
  const gridRows = computed(() => {
230
266
  const rows = [];
231
267
  const cols = gridColumnsFinal.value;
@@ -392,6 +428,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
392
428
  });
393
429
  return (_ctx, _cache) => {
394
430
  return openBlock(), createElementBlock("div", {
431
+ ref_key: "gridBoxRef",
432
+ ref: gridBoxRef,
395
433
  class: normalizeClass(["dc-data-grid-view data-grid-view", {
396
434
  "data-grid-view_surface": unref(surfaceActive),
397
435
  "data-grid-view_surface-bg": unref(surfaceBgActive)
@@ -428,8 +466,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
428
466
  key: 2,
429
467
  ref_key: "infiniteList",
430
468
  ref: infiniteList,
431
- data: gridRows.value,
432
- "item-key": rowKeyOfRow,
469
+ data: virtualData.value,
470
+ "item-key": virtualItemKey.value,
471
+ lanes: masonryActive.value ? gridColumnsFinal.value : 1,
472
+ "lane-gap": masonryActive.value ? unref(gridGap) : 0,
473
+ "item-gap": masonryActive.value ? unref(gridGap) : 0,
474
+ "estimate-size-at": masonryActive.value ? estimateSizeAt : void 0,
433
475
  loading: loading.value && !store.value.length,
434
476
  "loading-more": loadingMore.value,
435
477
  error: error.value && store.value.length ? error.value : null,
@@ -440,11 +482,29 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
440
482
  onRetry
441
483
  }), {
442
484
  item: withCtx(({ item, index }) => [
443
- createElementVNode("div", {
485
+ masonryActive.value ? (openBlock(), createElementBlock("div", {
486
+ key: 0,
487
+ class: normalizeClass(["data-grid-view__cell", { "is-active": unref(isActive)(item), "is-card": __props.card }]),
488
+ style: normalizeStyle(cellStyle.value),
489
+ onClick: ($event) => unref(setActive)(item)
490
+ }, [
491
+ renderSlot(_ctx.$slots, "custom-view-item", normalizeProps(guardReactiveProps(assertItemScope(item, index))), () => [
492
+ createVNode(_sfc_main$3, {
493
+ row: item,
494
+ index,
495
+ columns: __props.columns,
496
+ "field-component-map": unref(fieldComponentMap),
497
+ "field-key-of": fieldKeyOf,
498
+ "is-selected": isSelected,
499
+ "toggle-select": toggleSelect
500
+ }, null, 8, ["row", "index", "columns", "field-component-map"])
501
+ ], true)
502
+ ], 14, _hoisted_1)) : (openBlock(), createElementBlock("div", {
503
+ key: 1,
444
504
  class: "data-grid-view__grid",
445
505
  style: normalizeStyle(gridContainerStyle.value)
446
506
  }, [
447
- (openBlock(true), createElementBlock(Fragment, null, renderList(item, (row, colIndex) => {
507
+ (openBlock(true), createElementBlock(Fragment, null, renderList(asRow(item), (row, colIndex) => {
448
508
  return openBlock(), createElementBlock("div", {
449
509
  key: keyOf(row),
450
510
  class: normalizeClass(["data-grid-view__cell", { "is-active": unref(isActive)(row), "is-card": __props.card }]),
@@ -452,31 +512,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
452
512
  onClick: ($event) => unref(setActive)(row)
453
513
  }, [
454
514
  renderSlot(_ctx.$slots, "custom-view-item", mergeProps({ ref_for: true }, assertItemScope(row, index * gridColumnsFinal.value + colIndex)), () => [
455
- createElementVNode("div", _hoisted_2, [
456
- (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (column) => {
457
- return openBlock(), createElementBlock("div", {
458
- key: column.prop ?? column.type,
459
- class: "data-grid-view__field"
460
- }, [
461
- createElementVNode("span", _hoisted_3, toDisplayString(column.label ?? column.prop) + ":", 1),
462
- createElementVNode("span", _hoisted_4, [
463
- (openBlock(), createBlock(resolveDynamicComponent(unref(fieldComponentMap)[fieldKeyOf(column)]), {
464
- row,
465
- index: index * gridColumnsFinal.value + colIndex,
466
- selected: isSelected(row),
467
- "toggle-select": () => toggleSelect(row)
468
- }, null, 8, ["row", "index", "selected", "toggle-select"]))
469
- ])
470
- ]);
471
- }), 128))
472
- ])
515
+ createVNode(_sfc_main$3, {
516
+ row,
517
+ index: index * gridColumnsFinal.value + colIndex,
518
+ columns: __props.columns,
519
+ "field-component-map": unref(fieldComponentMap),
520
+ "field-key-of": fieldKeyOf,
521
+ "is-selected": isSelected,
522
+ "toggle-select": toggleSelect
523
+ }, null, 8, ["row", "index", "columns", "field-component-map"])
473
524
  ], true)
474
- ], 14, _hoisted_1);
525
+ ], 14, _hoisted_2);
475
526
  }), 128))
476
- ], 4)
527
+ ], 4))
477
528
  ]),
478
529
  empty: withCtx(() => [
479
- error.value && !store.value.length ? (openBlock(), createElementBlock("div", _hoisted_5, [
530
+ error.value && !store.value.length ? (openBlock(), createElementBlock("div", _hoisted_3, [
480
531
  createElementVNode("span", null, toDisplayString(errorText.value), 1),
481
532
  createVNode(unref(ElButton), {
482
533
  size: "small",
@@ -494,7 +545,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
494
545
  }, null, 8, ["loading", "has-requested"]))
495
546
  ]),
496
547
  _: 3
497
- }, 16, ["data", "loading", "loading-more", "error", "finished", "max-height"]))
548
+ }, 16, ["data", "item-key", "lanes", "lane-gap", "item-gap", "estimate-size-at", "loading", "loading-more", "error", "finished", "max-height"]))
498
549
  ], 2);
499
550
  };
500
551
  }
@@ -0,0 +1,41 @@
1
+ import { defineComponent, openBlock, createElementBlock, Fragment, renderList, createElementVNode, toDisplayString, createBlock, resolveDynamicComponent } from "vue";
2
+ const _hoisted_1 = { class: "data-grid-view__card" };
3
+ const _hoisted_2 = { class: "data-grid-view__field-label" };
4
+ const _hoisted_3 = { class: "data-grid-view__field-value" };
5
+ const _sfc_main = /* @__PURE__ */ defineComponent({
6
+ __name: "DataGridViewCard",
7
+ props: {
8
+ row: {},
9
+ index: {},
10
+ columns: {},
11
+ fieldComponentMap: {},
12
+ fieldKeyOf: { type: Function },
13
+ isSelected: { type: Function },
14
+ toggleSelect: { type: Function }
15
+ },
16
+ setup(__props) {
17
+ return (_ctx, _cache) => {
18
+ return openBlock(), createElementBlock("div", _hoisted_1, [
19
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.columns, (column) => {
20
+ return openBlock(), createElementBlock("div", {
21
+ key: column.prop ?? column.type,
22
+ class: "data-grid-view__field"
23
+ }, [
24
+ createElementVNode("span", _hoisted_2, toDisplayString(column.label ?? column.prop) + ":", 1),
25
+ createElementVNode("span", _hoisted_3, [
26
+ (openBlock(), createBlock(resolveDynamicComponent(__props.fieldComponentMap[__props.fieldKeyOf(column)]), {
27
+ row: __props.row,
28
+ index: __props.index,
29
+ selected: __props.isSelected(__props.row),
30
+ "toggle-select": () => __props.toggleSelect(__props.row)
31
+ }, null, 8, ["row", "index", "selected", "toggle-select"]))
32
+ ])
33
+ ]);
34
+ }), 128))
35
+ ]);
36
+ };
37
+ }
38
+ });
39
+ export {
40
+ _sfc_main as default
41
+ };
@@ -0,0 +1,4 @@
1
+ import _sfc_main from "./DataGridViewCard.vue.mjs";
2
+ export {
3
+ _sfc_main as default
4
+ };
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./InfiniteListView.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const InfiniteListView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a62d17f9"]]);
4
+ const InfiniteListView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4f0267ce"]]);
5
5
  export {
6
6
  InfiniteListView as default
7
7
  };
@@ -33,12 +33,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
33
33
  surface: { type: Boolean, default: void 0 },
34
34
  itemCard: { type: Boolean },
35
35
  maxHeight: { default: void 0 },
36
- pullRefresh: { type: Boolean, default: false }
36
+ pullRefresh: { type: Boolean, default: false },
37
+ lanes: { default: 1 },
38
+ estimateSizeAt: {},
39
+ laneGap: { default: 0 },
40
+ itemGap: { default: 0 }
37
41
  },
38
42
  emits: ["loadMore", "retry", "refresh"],
39
43
  setup(__props, { expose: __expose, emit: __emit }) {
40
44
  useCssVars((_ctx) => ({
41
- "v9e087332": unref(surfacePadCss)
45
+ "v407ba190": unref(surfacePadCss)
42
46
  }));
43
47
  const props = __props;
44
48
  const emits = __emit;
@@ -57,10 +61,39 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
57
61
  computed(() => ({
58
62
  count: props.data.length,
59
63
  getScrollElement: () => scrollContainer.value ?? null,
60
- estimateSize: () => props.estimateSize,
61
- overscan: props.overscan
64
+ // 逐项估高优先;没给就退回常量估值(= prop 引入前的行为)
65
+ estimateSize: (index) => {
66
+ var _a;
67
+ return ((_a = props.estimateSizeAt) == null ? void 0 : _a.call(props, index)) ?? props.estimateSize;
68
+ },
69
+ overscan: props.overscan,
70
+ // 🔴 多列即**瀑布流装箱**:virtual-core 前 `lanes` 项按 `i % lanes` 铺满首行
71
+ // (顺序行优先),之后逐项落 end 最小的列。[MUST NOT] 自己写这段。
72
+ lanes: props.lanes,
73
+ // 同列相邻项的纵向间距(virtual-core 把它算进 measurements,总高与位置都正确;
74
+ // [MUST NOT] 改用项自身的 margin —— measureElement 量的是 borderBox、吃不到 margin)
75
+ gap: props.itemGap,
76
+ // `"estimate"`(默认)= **列归属按估值定下来就缓存**,卡片不会在量准后跳到另一列。
77
+ // 🔴 [MUST NOT] 改 `"measured"`:那会让首屏卡片换列,比一点留白刺眼得多。
78
+ laneAssignmentMode: "estimate"
62
79
  }))
63
80
  );
81
+ const rowStyle = (item) => {
82
+ const base = {
83
+ position: "absolute",
84
+ top: 0,
85
+ left: 0,
86
+ transform: `translateY(${item.start}px)`
87
+ };
88
+ if (props.lanes <= 1) return { ...base, width: "100%" };
89
+ const gapTotal = `${(props.lanes - 1) * props.laneGap}px`;
90
+ const colWidth = `calc((100% - ${gapTotal}) / ${props.lanes})`;
91
+ return {
92
+ ...base,
93
+ width: colWidth,
94
+ left: `calc((${colWidth} + ${props.laneGap}px) * ${item.lane})`
95
+ };
96
+ };
64
97
  const virtualItems = computed(() => virtualizer.value.getVirtualItems());
65
98
  const totalSize = computed(() => virtualizer.value.getTotalSize());
66
99
  const measureElementRef = (el) => {
@@ -165,13 +198,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
165
198
  ref: measureElementRef,
166
199
  class: "infinite-list-view__row",
167
200
  "data-index": item.index,
168
- style: normalizeStyle({
169
- position: "absolute",
170
- top: 0,
171
- left: 0,
172
- width: "100%",
173
- transform: `translateY(${item.start}px)`
174
- })
201
+ style: normalizeStyle(rowStyle(item))
175
202
  }, [
176
203
  renderSlot(_ctx.$slots, "item", {
177
204
  item: __props.data[item.index],
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./BadgeMark.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const BadgeMark = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-9eb89306"]]);
4
+ const BadgeMark = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-64f0421b"]]);
5
5
  export {
6
6
  BadgeMark as default
7
7
  };
@@ -1,8 +1,11 @@
1
- import { defineComponent, computed, useTemplateRef, openBlock, createBlock, unref, normalizeProps, createSlots, withCtx, renderSlot, createVNode, normalizeStyle, resolveDynamicComponent } from "vue";
2
- import { ElBadge, ElTooltip, ElIcon } from "element-plus";
3
- import { useBadgeHit, badgeResolveDisplay } from "./use-badge.mjs";
1
+ import { defineComponent, inject, computed, useTemplateRef, openBlock, createBlock, unref, normalizeProps, createSlots, withCtx, renderSlot, createElementVNode, toDisplayString } from "vue";
2
+ import { ElBadge } from "element-plus";
3
+ import { useIsDev } from "../../hooks/use-is-dev.mjs";
4
+ import { useBadgeHit, badgeResolveDisplay, badgeWarnHideRefused } from "./use-badge.mjs";
4
5
  import { useBadgeMask } from "./use-badge-mask.mjs";
6
+ import { CORE_BRIDGE_KEY } from "../../inject/key.mjs";
5
7
  import { BADGE_KEY_ATTR } from "../../config/badge-attr.mjs";
8
+ const _hoisted_1 = { "aria-hidden": "true" };
6
9
  const _sfc_main = /* @__PURE__ */ defineComponent({
7
10
  __name: "BadgeMark",
8
11
  props: {
@@ -12,15 +15,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
12
15
  setup(__props) {
13
16
  const props = __props;
14
17
  const hit = useBadgeHit(() => props.badgeKey);
15
- const resolved = computed(() => {
16
- var _a;
17
- return badgeResolveDisplay((_a = hit.value) == null ? void 0 : _a.entry);
18
- });
19
- const iconStyle = computed(() => {
20
- var _a;
21
- const scale = (_a = resolved.value) == null ? void 0 : _a.iconScale;
22
- return scale === void 0 ? void 0 : { fontSize: `${scale}em` };
23
- });
18
+ const bridge = inject(CORE_BRIDGE_KEY, void 0);
19
+ const isDev = useIsDev();
20
+ const resolved = computed(
21
+ () => {
22
+ var _a;
23
+ return badgeResolveDisplay(
24
+ (_a = hit.value) == null ? void 0 : _a.entry,
25
+ (bridge == null ? void 0 : bridge.badge.defaultVisible.value) ?? true,
26
+ // 遮挡档挡回隐藏请求 ⇒ dev 下点名一次(静默忽略 = 消费方以为设了其实没设)。
27
+ // 闸在调用侧、不在纯函数里:`badgeResolveDisplay` [MUST] 保持无副作用可直测。
28
+ () => {
29
+ if (!isDev()) return;
30
+ const h = hit.value;
31
+ if (h) badgeWarnHideRefused(h.key, h.entry.kind);
32
+ }
33
+ );
34
+ }
35
+ );
24
36
  const badgeRef = useTemplateRef("badgeRef");
25
37
  useBadgeMask(
26
38
  () => {
@@ -38,8 +50,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
38
50
  key: 0,
39
51
  ref_key: "badgeRef",
40
52
  ref: badgeRef,
41
- class: ["dc-badge-mark badge-mark", `badge-mark_${__props.align ?? "middle"}`],
42
- hidden: resolved.value.hidden,
53
+ class: ["dc-badge-mark badge-mark", [
54
+ `badge-mark_${__props.align ?? "middle"}`,
55
+ { "badge-mark_hidden": resolved.value.hidden }
56
+ ]],
43
57
  value: resolved.value.value,
44
58
  max: resolved.value.max,
45
59
  type: resolved.value.type,
@@ -50,30 +64,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
50
64
  ]),
51
65
  _: 2
52
66
  }, [
53
- resolved.value.icon ? {
67
+ resolved.value.hidden ? {
54
68
  name: "content",
55
69
  fn: withCtx(() => [
56
- createVNode(unref(ElTooltip), {
57
- content: resolved.value.label,
58
- placement: "top"
59
- }, {
60
- default: withCtx(() => [
61
- createVNode(unref(ElIcon), {
62
- class: "badge-mark__icon",
63
- style: normalizeStyle(iconStyle.value)
64
- }, {
65
- default: withCtx(() => [
66
- (openBlock(), createBlock(resolveDynamicComponent(resolved.value.icon)))
67
- ]),
68
- _: 1
69
- }, 8, ["style"])
70
- ]),
71
- _: 1
72
- }, 8, ["content"])
70
+ createElementVNode("span", _hoisted_1, toDisplayString(resolved.value.value), 1)
73
71
  ]),
74
72
  key: "0"
75
73
  } : void 0
76
- ]), 1040, ["class", "hidden", "value", "max", "type"])) : renderSlot(_ctx.$slots, "default", { key: 1 }, void 0, true);
74
+ ]), 1040, ["class", "value", "max", "type"])) : renderSlot(_ctx.$slots, "default", { key: 1 }, void 0, true);
77
75
  };
78
76
  }
79
77
  });