tudou-waterfall 0.1.8 → 0.1.10

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.cjs CHANGED
@@ -30,7 +30,8 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
30
30
  const measuredHeights = /* @__PURE__ */ new Map();
31
31
  const getColCount = () => {
32
32
  var _a, _b;
33
- if (props.cols > 0) return props.cols;
33
+ const colsNum = Number(props.cols);
34
+ if (colsNum > 0) return colsNum;
34
35
  const width = ((_a = containerRef.value) == null ? void 0 : _a.clientWidth) ?? window.innerWidth;
35
36
  const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth);
36
37
  return ((_b = sorted.find((bp) => width >= bp.minWidth)) == null ? void 0 : _b.cols) ?? props.defaultCols;
@@ -125,9 +126,16 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
125
126
  containerRo == null ? void 0 : containerRo.disconnect();
126
127
  itemRo.disconnect();
127
128
  });
128
- vue.watch(() => props.items.length, (newLen, oldLen) => {
129
+ vue.watch(() => {
130
+ var _a;
131
+ return ((_a = props.items) == null ? void 0 : _a.length) ?? 0;
132
+ }, (newLen, oldLen) => {
129
133
  if (newLen < oldLen) measuredHeights.clear();
130
134
  reflow();
135
+ }, { immediate: true });
136
+ vue.watch(() => props.cols, () => {
137
+ measuredHeights.clear();
138
+ reflow();
131
139
  });
132
140
  return (_ctx, _cache) => {
133
141
  return vue.openBlock(), vue.createElementBlock("div", {
@@ -169,7 +177,7 @@ const _export_sfc = (sfc, props) => {
169
177
  }
170
178
  return target;
171
179
  };
172
- const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-946f6fbc"]]);
180
+ const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ac5cd1d2"]]);
173
181
  function install(app) {
174
182
  app.component("TdWaterfall", Waterfall);
175
183
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/components/Waterfall.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\nexport interface WaterfallBreakpoint {\n minWidth: number\n cols: number\n}\n\nexport interface WaterfallProps {\n items: any[]\n cols?: number\n gap?: number\n estimatedHeight?: number\n overscan?: number\n /**\n * Responsive breakpoints. Sorted descending by minWidth at runtime.\n * Example: [{ minWidth: 1400, cols: 5 }, { minWidth: 900, cols: 3 }]\n * Falls back to defaultCols when no breakpoint matches.\n */\n breakpoints?: WaterfallBreakpoint[]\n /** Column count when no breakpoint matches (default: 2) */\n defaultCols?: number\n}\n\nconst props = withDefaults(defineProps<WaterfallProps>(), {\n cols: 0,\n gap: 15,\n estimatedHeight: 220,\n overscan: 600,\n breakpoints: () => [\n { minWidth: 1400, cols: 9 },\n { minWidth: 1200, cols: 8 },\n { minWidth: 900, cols: 7 },\n { minWidth: 700, cols: 6 },\n { minWidth: 500, cols: 5 },\n ],\n defaultCols: 2,\n})\n\nconst emit = defineEmits<{ (e: 'reflow'): void }>()\n\n// ─── types ────────────────────────────────────────────────────────────────────\n\ninterface PositionedItem {\n item: any\n globalIdx: number\n top: number\n height: number\n}\n\n// ─── state ────────────────────────────────────────────────────────────────────\n\nconst containerRef = ref<HTMLElement | null>(null)\nconst scrollTop = ref(0)\nconst viewportHeight = ref(0)\n\n// colPositions[colIdx] = sorted array of positioned items\nconst colPositions = ref<PositionedItem[][]>([])\n// colTotalHeight[colIdx] = total height of that column (for the spacer div)\nconst colTotalHeights = ref<number[]>([])\n\n// globalIdx -> measured height (updated after image load)\nconst measuredHeights = new Map<number, number>()\n\n// ─── column count ─────────────────────────────────────────────────────────────\n\nconst getColCount = () => {\n if (props.cols > 0) return props.cols\n const width = containerRef.value?.clientWidth ?? window.innerWidth\n const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth)\n return sorted.find(bp => width >= bp.minWidth)?.cols ?? props.defaultCols\n}\n\n// ─── full reflow: re-assign items to columns ──────────────────────────────────\n// Only called when items list changes or viewport width changes.\n// Does NOT re-assign on height updates to avoid item jumping between columns.\n\nconst reflow = async () => {\n await nextTick()\n const count = getColCount()\n const cols: PositionedItem[][] = Array.from({ length: count }, () => [])\n const colH = new Array(count).fill(0)\n\n props.items.forEach((item, i) => {\n const minIdx = colH.indexOf(Math.min(...colH))\n const h = measuredHeights.get(i) ?? props.estimatedHeight\n cols[minIdx].push({ item, globalIdx: i, top: colH[minIdx], height: h })\n colH[minIdx] += h + props.gap\n })\n\n colPositions.value = cols\n colTotalHeights.value = colH\n emit('reflow')\n}\n\n// ─── patch: update one item's height in-place, shift subsequent items ─────────\n// Called after an image loads. Avoids full reflow to prevent column reassignment.\n\nconst patchHeight = (globalIdx: number, newHeight: number) => {\n const old = measuredHeights.get(globalIdx) ?? props.estimatedHeight\n if (Math.abs(old - newHeight) < 2) return\n measuredHeights.set(globalIdx, newHeight)\n\n for (let ci = 0; ci < colPositions.value.length; ci++) {\n const col = colPositions.value[ci]\n const pos = col.findIndex(p => p.globalIdx === globalIdx)\n if (pos === -1) continue\n\n const delta = newHeight - col[pos].height\n col[pos].height = newHeight\n\n for (let j = pos + 1; j < col.length; j++) {\n col[j] = { ...col[j], top: col[j].top + delta }\n }\n\n colTotalHeights.value[ci] += delta\n break\n }\n}\n\n// ─── virtual visibility ───────────────────────────────────────────────────────\n\nconst visibleItems = computed(() => {\n const top = scrollTop.value - props.overscan\n const bottom = scrollTop.value + viewportHeight.value + props.overscan\n return colPositions.value.map(col =>\n col.filter(p => p.top + p.height >= top && p.top <= bottom)\n )\n})\n\n// ─── scroll listener ──────────────────────────────────────────────────────────\n\nlet scrollEl: Element | null = null\n\nconst findScrollParent = (el: Element): Element => {\n let cur: Element | null = el.parentElement\n while (cur) {\n const { overflow, overflowY } = getComputedStyle(cur)\n if (/auto|scroll/.test(overflow + overflowY)) return cur\n cur = cur.parentElement\n }\n return document.documentElement\n}\n\nconst onScroll = (e: Event) => {\n const st = (e.target as Element).scrollTop\n const containerOffset = containerRef.value\n ? (containerRef.value as HTMLElement).offsetTop\n : 0\n scrollTop.value = Math.max(0, st - containerOffset)\n}\n\n// ─── item resize observer ─────────────────────────────────────────────────────\n// One shared RO watches every .wf-item element.\n// el -> globalIdx mapping is stored in a WeakMap so we never leak.\n\nconst itemElMap = new WeakMap<Element, number>()\n\nconst itemRo = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const globalIdx = itemElMap.get(entry.target)\n if (globalIdx === undefined) continue\n const h = entry.contentRect.height\n if (h > 0) patchHeight(globalIdx, h)\n }\n})\n\nconst observeItem = (el: Element, globalIdx: number) => {\n itemElMap.set(el, globalIdx)\n itemRo.observe(el)\n}\n\nconst unobserveItem = (el: Element) => {\n itemRo.unobserve(el)\n itemElMap.delete(el)\n}\n\n// ─── resize observer (container) ─────────────────────────────────────────────\n\nlet containerRo: ResizeObserver | null = null\n\n// ─── lifecycle ────────────────────────────────────────────────────────────────\n\nonMounted(async () => {\n await nextTick()\n if (!containerRef.value) return\n\n scrollEl = findScrollParent(containerRef.value)\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n\n containerRo = new ResizeObserver(() => {\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n reflow()\n })\n containerRo.observe(containerRef.value)\n\n reflow()\n})\n\nonUnmounted(() => {\n scrollEl?.removeEventListener('scroll', onScroll)\n containerRo?.disconnect()\n itemRo.disconnect()\n})\n\nwatch(() => props.items.length, (newLen, oldLen) => {\n if (newLen < oldLen) measuredHeights.clear()\n reflow()\n})\n</script>\n\n<template>\n <div ref=\"containerRef\" class=\"wf-root\" :style=\"{ gap: `${gap}px` }\">\n <div\n v-for=\"(_col, ci) in colPositions\"\n :key=\"ci\"\n class=\"wf-col\"\n :style=\"{ height: `${colTotalHeights[ci]}px` }\"\n >\n <div\n v-for=\"{ item, globalIdx, top } in visibleItems[ci]\"\n :key=\"globalIdx\"\n :ref=\"(el) => { if (el) observeItem(el as Element, globalIdx) }\"\n class=\"wf-item\"\n :style=\"{ transform: `translateY(${top}px)` }\"\n @vue:unmounted=\"({ el }: any) => unobserveItem(el)\"\n >\n <slot :item=\"item\" />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wf-root {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n.wf-col {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n\n.wf-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n</style>\n","import type { App, Plugin } from 'vue'\n\nimport Waterfall from './components/Waterfall.vue'\n\nexport { Waterfall }\nexport type { WaterfallProps, WaterfallBreakpoint } from './components/Waterfall.vue'\n\nfunction install(app: App): void {\n app.component('TdWaterfall', Waterfall)\n}\n\nconst TudouWaterfall: Plugin = {\n install,\n}\n\nexport default TudouWaterfall\nexport { TudouWaterfall }\n"],"names":["ref","nextTick","computed","onMounted","onUnmounted","watch","_createElementBlock","_openBlock","_Fragment","_renderList","_normalizeStyle","_renderSlot"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/Waterfall.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\nexport interface WaterfallBreakpoint {\n minWidth: number\n cols: number\n}\n\nexport interface WaterfallProps {\n items: any[]\n cols?: number\n gap?: number\n estimatedHeight?: number\n overscan?: number\n /**\n * Responsive breakpoints. Sorted descending by minWidth at runtime.\n * Example: [{ minWidth: 1400, cols: 5 }, { minWidth: 900, cols: 3 }]\n * Falls back to defaultCols when no breakpoint matches.\n */\n breakpoints?: WaterfallBreakpoint[]\n /** Column count when no breakpoint matches (default: 2) */\n defaultCols?: number\n}\n\nconst props = withDefaults(defineProps<WaterfallProps>(), {\n cols: 0,\n gap: 15,\n estimatedHeight: 220,\n overscan: 600,\n breakpoints: () => [\n { minWidth: 1400, cols: 9 },\n { minWidth: 1200, cols: 8 },\n { minWidth: 900, cols: 7 },\n { minWidth: 700, cols: 6 },\n { minWidth: 500, cols: 5 },\n ],\n defaultCols: 2,\n})\n\nconst emit = defineEmits<{ (e: 'reflow'): void }>()\n\n// ─── types ────────────────────────────────────────────────────────────────────\n\ninterface PositionedItem {\n item: any\n globalIdx: number\n top: number\n height: number\n}\n\n// ─── state ────────────────────────────────────────────────────────────────────\n\nconst containerRef = ref<HTMLElement | null>(null)\nconst scrollTop = ref(0)\nconst viewportHeight = ref(0)\n\n// colPositions[colIdx] = sorted array of positioned items\nconst colPositions = ref<PositionedItem[][]>([])\n// colTotalHeight[colIdx] = total height of that column (for the spacer div)\nconst colTotalHeights = ref<number[]>([])\n\n// globalIdx -> measured height (updated after image load)\nconst measuredHeights = new Map<number, number>()\n\n// ─── column count ─────────────────────────────────────────────────────────────\n\nconst getColCount = () => {\n const colsNum = Number(props.cols)\n if (colsNum > 0) return colsNum\n const width = containerRef.value?.clientWidth ?? window.innerWidth\n const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth)\n return sorted.find(bp => width >= bp.minWidth)?.cols ?? props.defaultCols\n}\n\n// ─── full reflow: re-assign items to columns ──────────────────────────────────\n// Only called when items list changes or viewport width changes.\n// Does NOT re-assign on height updates to avoid item jumping between columns.\n\nconst reflow = async () => {\n await nextTick()\n const count = getColCount()\n const cols: PositionedItem[][] = Array.from({ length: count }, () => [])\n const colH = new Array(count).fill(0)\n\n props.items.forEach((item, i) => {\n const minIdx = colH.indexOf(Math.min(...colH))\n const h = measuredHeights.get(i) ?? props.estimatedHeight\n cols[minIdx].push({ item, globalIdx: i, top: colH[minIdx], height: h })\n colH[minIdx] += h + props.gap\n })\n\n colPositions.value = cols\n colTotalHeights.value = colH\n emit('reflow')\n}\n\n// ─── patch: update one item's height in-place, shift subsequent items ─────────\n// Called after an image loads. Avoids full reflow to prevent column reassignment.\n\nconst patchHeight = (globalIdx: number, newHeight: number) => {\n const old = measuredHeights.get(globalIdx) ?? props.estimatedHeight\n if (Math.abs(old - newHeight) < 2) return\n measuredHeights.set(globalIdx, newHeight)\n\n for (let ci = 0; ci < colPositions.value.length; ci++) {\n const col = colPositions.value[ci]\n const pos = col.findIndex(p => p.globalIdx === globalIdx)\n if (pos === -1) continue\n\n const delta = newHeight - col[pos].height\n col[pos].height = newHeight\n\n for (let j = pos + 1; j < col.length; j++) {\n col[j] = { ...col[j], top: col[j].top + delta }\n }\n\n colTotalHeights.value[ci] += delta\n break\n }\n}\n\n// ─── virtual visibility ───────────────────────────────────────────────────────\n\nconst visibleItems = computed(() => {\n const top = scrollTop.value - props.overscan\n const bottom = scrollTop.value + viewportHeight.value + props.overscan\n return colPositions.value.map(col =>\n col.filter(p => p.top + p.height >= top && p.top <= bottom)\n )\n})\n\n// ─── scroll listener ──────────────────────────────────────────────────────────\n\nlet scrollEl: Element | null = null\n\nconst findScrollParent = (el: Element): Element => {\n let cur: Element | null = el.parentElement\n while (cur) {\n const { overflow, overflowY } = getComputedStyle(cur)\n if (/auto|scroll/.test(overflow + overflowY)) return cur\n cur = cur.parentElement\n }\n return document.documentElement\n}\n\nconst onScroll = (e: Event) => {\n const st = (e.target as Element).scrollTop\n const containerOffset = containerRef.value\n ? (containerRef.value as HTMLElement).offsetTop\n : 0\n scrollTop.value = Math.max(0, st - containerOffset)\n}\n\n// ─── item resize observer ─────────────────────────────────────────────────────\n// One shared RO watches every .wf-item element.\n// el -> globalIdx mapping is stored in a WeakMap so we never leak.\n\nconst itemElMap = new WeakMap<Element, number>()\n\nconst itemRo = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const globalIdx = itemElMap.get(entry.target)\n if (globalIdx === undefined) continue\n const h = entry.contentRect.height\n if (h > 0) patchHeight(globalIdx, h)\n }\n})\n\nconst observeItem = (el: Element, globalIdx: number) => {\n itemElMap.set(el, globalIdx)\n itemRo.observe(el)\n}\n\nconst unobserveItem = (el: Element) => {\n itemRo.unobserve(el)\n itemElMap.delete(el)\n}\n\n// ─── resize observer (container) ─────────────────────────────────────────────\n\nlet containerRo: ResizeObserver | null = null\n\n// ─── lifecycle ────────────────────────────────────────────────────────────────\n\nonMounted(async () => {\n await nextTick()\n if (!containerRef.value) return\n\n scrollEl = findScrollParent(containerRef.value)\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n\n containerRo = new ResizeObserver(() => {\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n reflow()\n })\n containerRo.observe(containerRef.value)\n\n reflow()\n})\n\nonUnmounted(() => {\n scrollEl?.removeEventListener('scroll', onScroll)\n containerRo?.disconnect()\n itemRo.disconnect()\n})\n\nwatch(() => props.items?.length ?? 0, (newLen, oldLen) => {\n if (newLen < oldLen) measuredHeights.clear()\n reflow()\n}, { immediate: true })\n\nwatch(() => props.cols, () => {\n measuredHeights.clear()\n reflow()\n})\n</script>\n\n<template>\n <div ref=\"containerRef\" class=\"wf-root\" :style=\"{ gap: `${gap}px` }\">\n <div\n v-for=\"(_col, ci) in colPositions\"\n :key=\"ci\"\n class=\"wf-col\"\n :style=\"{ height: `${colTotalHeights[ci]}px` }\"\n >\n <div\n v-for=\"{ item, globalIdx, top } in visibleItems[ci]\"\n :key=\"globalIdx\"\n :ref=\"(el) => { if (el) observeItem(el as Element, globalIdx) }\"\n class=\"wf-item\"\n :style=\"{ transform: `translateY(${top}px)` }\"\n @vue:unmounted=\"({ el }: any) => unobserveItem(el)\"\n >\n <slot :item=\"item\" />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wf-root {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n.wf-col {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n\n.wf-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n</style>\n","import type { App, Plugin } from 'vue'\n\nimport Waterfall from './components/Waterfall.vue'\n\nexport { Waterfall }\nexport type { WaterfallProps, WaterfallBreakpoint } from './components/Waterfall.vue'\n\nfunction install(app: App): void {\n app.component('TdWaterfall', Waterfall)\n}\n\nconst TudouWaterfall: Plugin = {\n install,\n}\n\nexport default TudouWaterfall\nexport { TudouWaterfall }\n"],"names":["ref","nextTick","computed","onMounted","onUnmounted","watch","_createElementBlock","_openBlock","_Fragment","_renderList","_normalizeStyle","_renderSlot"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -28,7 +28,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
28
28
  const measuredHeights = /* @__PURE__ */ new Map();
29
29
  const getColCount = () => {
30
30
  var _a, _b;
31
- if (props.cols > 0) return props.cols;
31
+ const colsNum = Number(props.cols);
32
+ if (colsNum > 0) return colsNum;
32
33
  const width = ((_a = containerRef.value) == null ? void 0 : _a.clientWidth) ?? window.innerWidth;
33
34
  const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth);
34
35
  return ((_b = sorted.find((bp) => width >= bp.minWidth)) == null ? void 0 : _b.cols) ?? props.defaultCols;
@@ -123,9 +124,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
123
124
  containerRo == null ? void 0 : containerRo.disconnect();
124
125
  itemRo.disconnect();
125
126
  });
126
- watch(() => props.items.length, (newLen, oldLen) => {
127
+ watch(() => {
128
+ var _a;
129
+ return ((_a = props.items) == null ? void 0 : _a.length) ?? 0;
130
+ }, (newLen, oldLen) => {
127
131
  if (newLen < oldLen) measuredHeights.clear();
128
132
  reflow();
133
+ }, { immediate: true });
134
+ watch(() => props.cols, () => {
135
+ measuredHeights.clear();
136
+ reflow();
129
137
  });
130
138
  return (_ctx, _cache) => {
131
139
  return openBlock(), createElementBlock("div", {
@@ -167,7 +175,7 @@ const _export_sfc = (sfc, props) => {
167
175
  }
168
176
  return target;
169
177
  };
170
- const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-946f6fbc"]]);
178
+ const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ac5cd1d2"]]);
171
179
  function install(app) {
172
180
  app.component("TdWaterfall", Waterfall);
173
181
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/components/Waterfall.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\nexport interface WaterfallBreakpoint {\n minWidth: number\n cols: number\n}\n\nexport interface WaterfallProps {\n items: any[]\n cols?: number\n gap?: number\n estimatedHeight?: number\n overscan?: number\n /**\n * Responsive breakpoints. Sorted descending by minWidth at runtime.\n * Example: [{ minWidth: 1400, cols: 5 }, { minWidth: 900, cols: 3 }]\n * Falls back to defaultCols when no breakpoint matches.\n */\n breakpoints?: WaterfallBreakpoint[]\n /** Column count when no breakpoint matches (default: 2) */\n defaultCols?: number\n}\n\nconst props = withDefaults(defineProps<WaterfallProps>(), {\n cols: 0,\n gap: 15,\n estimatedHeight: 220,\n overscan: 600,\n breakpoints: () => [\n { minWidth: 1400, cols: 9 },\n { minWidth: 1200, cols: 8 },\n { minWidth: 900, cols: 7 },\n { minWidth: 700, cols: 6 },\n { minWidth: 500, cols: 5 },\n ],\n defaultCols: 2,\n})\n\nconst emit = defineEmits<{ (e: 'reflow'): void }>()\n\n// ─── types ────────────────────────────────────────────────────────────────────\n\ninterface PositionedItem {\n item: any\n globalIdx: number\n top: number\n height: number\n}\n\n// ─── state ────────────────────────────────────────────────────────────────────\n\nconst containerRef = ref<HTMLElement | null>(null)\nconst scrollTop = ref(0)\nconst viewportHeight = ref(0)\n\n// colPositions[colIdx] = sorted array of positioned items\nconst colPositions = ref<PositionedItem[][]>([])\n// colTotalHeight[colIdx] = total height of that column (for the spacer div)\nconst colTotalHeights = ref<number[]>([])\n\n// globalIdx -> measured height (updated after image load)\nconst measuredHeights = new Map<number, number>()\n\n// ─── column count ─────────────────────────────────────────────────────────────\n\nconst getColCount = () => {\n if (props.cols > 0) return props.cols\n const width = containerRef.value?.clientWidth ?? window.innerWidth\n const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth)\n return sorted.find(bp => width >= bp.minWidth)?.cols ?? props.defaultCols\n}\n\n// ─── full reflow: re-assign items to columns ──────────────────────────────────\n// Only called when items list changes or viewport width changes.\n// Does NOT re-assign on height updates to avoid item jumping between columns.\n\nconst reflow = async () => {\n await nextTick()\n const count = getColCount()\n const cols: PositionedItem[][] = Array.from({ length: count }, () => [])\n const colH = new Array(count).fill(0)\n\n props.items.forEach((item, i) => {\n const minIdx = colH.indexOf(Math.min(...colH))\n const h = measuredHeights.get(i) ?? props.estimatedHeight\n cols[minIdx].push({ item, globalIdx: i, top: colH[minIdx], height: h })\n colH[minIdx] += h + props.gap\n })\n\n colPositions.value = cols\n colTotalHeights.value = colH\n emit('reflow')\n}\n\n// ─── patch: update one item's height in-place, shift subsequent items ─────────\n// Called after an image loads. Avoids full reflow to prevent column reassignment.\n\nconst patchHeight = (globalIdx: number, newHeight: number) => {\n const old = measuredHeights.get(globalIdx) ?? props.estimatedHeight\n if (Math.abs(old - newHeight) < 2) return\n measuredHeights.set(globalIdx, newHeight)\n\n for (let ci = 0; ci < colPositions.value.length; ci++) {\n const col = colPositions.value[ci]\n const pos = col.findIndex(p => p.globalIdx === globalIdx)\n if (pos === -1) continue\n\n const delta = newHeight - col[pos].height\n col[pos].height = newHeight\n\n for (let j = pos + 1; j < col.length; j++) {\n col[j] = { ...col[j], top: col[j].top + delta }\n }\n\n colTotalHeights.value[ci] += delta\n break\n }\n}\n\n// ─── virtual visibility ───────────────────────────────────────────────────────\n\nconst visibleItems = computed(() => {\n const top = scrollTop.value - props.overscan\n const bottom = scrollTop.value + viewportHeight.value + props.overscan\n return colPositions.value.map(col =>\n col.filter(p => p.top + p.height >= top && p.top <= bottom)\n )\n})\n\n// ─── scroll listener ──────────────────────────────────────────────────────────\n\nlet scrollEl: Element | null = null\n\nconst findScrollParent = (el: Element): Element => {\n let cur: Element | null = el.parentElement\n while (cur) {\n const { overflow, overflowY } = getComputedStyle(cur)\n if (/auto|scroll/.test(overflow + overflowY)) return cur\n cur = cur.parentElement\n }\n return document.documentElement\n}\n\nconst onScroll = (e: Event) => {\n const st = (e.target as Element).scrollTop\n const containerOffset = containerRef.value\n ? (containerRef.value as HTMLElement).offsetTop\n : 0\n scrollTop.value = Math.max(0, st - containerOffset)\n}\n\n// ─── item resize observer ─────────────────────────────────────────────────────\n// One shared RO watches every .wf-item element.\n// el -> globalIdx mapping is stored in a WeakMap so we never leak.\n\nconst itemElMap = new WeakMap<Element, number>()\n\nconst itemRo = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const globalIdx = itemElMap.get(entry.target)\n if (globalIdx === undefined) continue\n const h = entry.contentRect.height\n if (h > 0) patchHeight(globalIdx, h)\n }\n})\n\nconst observeItem = (el: Element, globalIdx: number) => {\n itemElMap.set(el, globalIdx)\n itemRo.observe(el)\n}\n\nconst unobserveItem = (el: Element) => {\n itemRo.unobserve(el)\n itemElMap.delete(el)\n}\n\n// ─── resize observer (container) ─────────────────────────────────────────────\n\nlet containerRo: ResizeObserver | null = null\n\n// ─── lifecycle ────────────────────────────────────────────────────────────────\n\nonMounted(async () => {\n await nextTick()\n if (!containerRef.value) return\n\n scrollEl = findScrollParent(containerRef.value)\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n\n containerRo = new ResizeObserver(() => {\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n reflow()\n })\n containerRo.observe(containerRef.value)\n\n reflow()\n})\n\nonUnmounted(() => {\n scrollEl?.removeEventListener('scroll', onScroll)\n containerRo?.disconnect()\n itemRo.disconnect()\n})\n\nwatch(() => props.items.length, (newLen, oldLen) => {\n if (newLen < oldLen) measuredHeights.clear()\n reflow()\n})\n</script>\n\n<template>\n <div ref=\"containerRef\" class=\"wf-root\" :style=\"{ gap: `${gap}px` }\">\n <div\n v-for=\"(_col, ci) in colPositions\"\n :key=\"ci\"\n class=\"wf-col\"\n :style=\"{ height: `${colTotalHeights[ci]}px` }\"\n >\n <div\n v-for=\"{ item, globalIdx, top } in visibleItems[ci]\"\n :key=\"globalIdx\"\n :ref=\"(el) => { if (el) observeItem(el as Element, globalIdx) }\"\n class=\"wf-item\"\n :style=\"{ transform: `translateY(${top}px)` }\"\n @vue:unmounted=\"({ el }: any) => unobserveItem(el)\"\n >\n <slot :item=\"item\" />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wf-root {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n.wf-col {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n\n.wf-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n</style>\n","import type { App, Plugin } from 'vue'\n\nimport Waterfall from './components/Waterfall.vue'\n\nexport { Waterfall }\nexport type { WaterfallProps, WaterfallBreakpoint } from './components/Waterfall.vue'\n\nfunction install(app: App): void {\n app.component('TdWaterfall', Waterfall)\n}\n\nconst TudouWaterfall: Plugin = {\n install,\n}\n\nexport default TudouWaterfall\nexport { TudouWaterfall }\n"],"names":["_createElementBlock","_openBlock","_Fragment","_renderList","_normalizeStyle","_renderSlot"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/components/Waterfall.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\nexport interface WaterfallBreakpoint {\n minWidth: number\n cols: number\n}\n\nexport interface WaterfallProps {\n items: any[]\n cols?: number\n gap?: number\n estimatedHeight?: number\n overscan?: number\n /**\n * Responsive breakpoints. Sorted descending by minWidth at runtime.\n * Example: [{ minWidth: 1400, cols: 5 }, { minWidth: 900, cols: 3 }]\n * Falls back to defaultCols when no breakpoint matches.\n */\n breakpoints?: WaterfallBreakpoint[]\n /** Column count when no breakpoint matches (default: 2) */\n defaultCols?: number\n}\n\nconst props = withDefaults(defineProps<WaterfallProps>(), {\n cols: 0,\n gap: 15,\n estimatedHeight: 220,\n overscan: 600,\n breakpoints: () => [\n { minWidth: 1400, cols: 9 },\n { minWidth: 1200, cols: 8 },\n { minWidth: 900, cols: 7 },\n { minWidth: 700, cols: 6 },\n { minWidth: 500, cols: 5 },\n ],\n defaultCols: 2,\n})\n\nconst emit = defineEmits<{ (e: 'reflow'): void }>()\n\n// ─── types ────────────────────────────────────────────────────────────────────\n\ninterface PositionedItem {\n item: any\n globalIdx: number\n top: number\n height: number\n}\n\n// ─── state ────────────────────────────────────────────────────────────────────\n\nconst containerRef = ref<HTMLElement | null>(null)\nconst scrollTop = ref(0)\nconst viewportHeight = ref(0)\n\n// colPositions[colIdx] = sorted array of positioned items\nconst colPositions = ref<PositionedItem[][]>([])\n// colTotalHeight[colIdx] = total height of that column (for the spacer div)\nconst colTotalHeights = ref<number[]>([])\n\n// globalIdx -> measured height (updated after image load)\nconst measuredHeights = new Map<number, number>()\n\n// ─── column count ─────────────────────────────────────────────────────────────\n\nconst getColCount = () => {\n const colsNum = Number(props.cols)\n if (colsNum > 0) return colsNum\n const width = containerRef.value?.clientWidth ?? window.innerWidth\n const sorted = [...props.breakpoints].sort((a, b) => b.minWidth - a.minWidth)\n return sorted.find(bp => width >= bp.minWidth)?.cols ?? props.defaultCols\n}\n\n// ─── full reflow: re-assign items to columns ──────────────────────────────────\n// Only called when items list changes or viewport width changes.\n// Does NOT re-assign on height updates to avoid item jumping between columns.\n\nconst reflow = async () => {\n await nextTick()\n const count = getColCount()\n const cols: PositionedItem[][] = Array.from({ length: count }, () => [])\n const colH = new Array(count).fill(0)\n\n props.items.forEach((item, i) => {\n const minIdx = colH.indexOf(Math.min(...colH))\n const h = measuredHeights.get(i) ?? props.estimatedHeight\n cols[minIdx].push({ item, globalIdx: i, top: colH[minIdx], height: h })\n colH[minIdx] += h + props.gap\n })\n\n colPositions.value = cols\n colTotalHeights.value = colH\n emit('reflow')\n}\n\n// ─── patch: update one item's height in-place, shift subsequent items ─────────\n// Called after an image loads. Avoids full reflow to prevent column reassignment.\n\nconst patchHeight = (globalIdx: number, newHeight: number) => {\n const old = measuredHeights.get(globalIdx) ?? props.estimatedHeight\n if (Math.abs(old - newHeight) < 2) return\n measuredHeights.set(globalIdx, newHeight)\n\n for (let ci = 0; ci < colPositions.value.length; ci++) {\n const col = colPositions.value[ci]\n const pos = col.findIndex(p => p.globalIdx === globalIdx)\n if (pos === -1) continue\n\n const delta = newHeight - col[pos].height\n col[pos].height = newHeight\n\n for (let j = pos + 1; j < col.length; j++) {\n col[j] = { ...col[j], top: col[j].top + delta }\n }\n\n colTotalHeights.value[ci] += delta\n break\n }\n}\n\n// ─── virtual visibility ───────────────────────────────────────────────────────\n\nconst visibleItems = computed(() => {\n const top = scrollTop.value - props.overscan\n const bottom = scrollTop.value + viewportHeight.value + props.overscan\n return colPositions.value.map(col =>\n col.filter(p => p.top + p.height >= top && p.top <= bottom)\n )\n})\n\n// ─── scroll listener ──────────────────────────────────────────────────────────\n\nlet scrollEl: Element | null = null\n\nconst findScrollParent = (el: Element): Element => {\n let cur: Element | null = el.parentElement\n while (cur) {\n const { overflow, overflowY } = getComputedStyle(cur)\n if (/auto|scroll/.test(overflow + overflowY)) return cur\n cur = cur.parentElement\n }\n return document.documentElement\n}\n\nconst onScroll = (e: Event) => {\n const st = (e.target as Element).scrollTop\n const containerOffset = containerRef.value\n ? (containerRef.value as HTMLElement).offsetTop\n : 0\n scrollTop.value = Math.max(0, st - containerOffset)\n}\n\n// ─── item resize observer ─────────────────────────────────────────────────────\n// One shared RO watches every .wf-item element.\n// el -> globalIdx mapping is stored in a WeakMap so we never leak.\n\nconst itemElMap = new WeakMap<Element, number>()\n\nconst itemRo = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const globalIdx = itemElMap.get(entry.target)\n if (globalIdx === undefined) continue\n const h = entry.contentRect.height\n if (h > 0) patchHeight(globalIdx, h)\n }\n})\n\nconst observeItem = (el: Element, globalIdx: number) => {\n itemElMap.set(el, globalIdx)\n itemRo.observe(el)\n}\n\nconst unobserveItem = (el: Element) => {\n itemRo.unobserve(el)\n itemElMap.delete(el)\n}\n\n// ─── resize observer (container) ─────────────────────────────────────────────\n\nlet containerRo: ResizeObserver | null = null\n\n// ─── lifecycle ────────────────────────────────────────────────────────────────\n\nonMounted(async () => {\n await nextTick()\n if (!containerRef.value) return\n\n scrollEl = findScrollParent(containerRef.value)\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n\n containerRo = new ResizeObserver(() => {\n viewportHeight.value = scrollEl === document.documentElement\n ? window.innerHeight\n : (scrollEl as HTMLElement).clientHeight\n reflow()\n })\n containerRo.observe(containerRef.value)\n\n reflow()\n})\n\nonUnmounted(() => {\n scrollEl?.removeEventListener('scroll', onScroll)\n containerRo?.disconnect()\n itemRo.disconnect()\n})\n\nwatch(() => props.items?.length ?? 0, (newLen, oldLen) => {\n if (newLen < oldLen) measuredHeights.clear()\n reflow()\n}, { immediate: true })\n\nwatch(() => props.cols, () => {\n measuredHeights.clear()\n reflow()\n})\n</script>\n\n<template>\n <div ref=\"containerRef\" class=\"wf-root\" :style=\"{ gap: `${gap}px` }\">\n <div\n v-for=\"(_col, ci) in colPositions\"\n :key=\"ci\"\n class=\"wf-col\"\n :style=\"{ height: `${colTotalHeights[ci]}px` }\"\n >\n <div\n v-for=\"{ item, globalIdx, top } in visibleItems[ci]\"\n :key=\"globalIdx\"\n :ref=\"(el) => { if (el) observeItem(el as Element, globalIdx) }\"\n class=\"wf-item\"\n :style=\"{ transform: `translateY(${top}px)` }\"\n @vue:unmounted=\"({ el }: any) => unobserveItem(el)\"\n >\n <slot :item=\"item\" />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wf-root {\n display: flex;\n align-items: flex-start;\n width: 100%;\n}\n\n.wf-col {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n\n.wf-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n</style>\n","import type { App, Plugin } from 'vue'\n\nimport Waterfall from './components/Waterfall.vue'\n\nexport { Waterfall }\nexport type { WaterfallProps, WaterfallBreakpoint } from './components/Waterfall.vue'\n\nfunction install(app: App): void {\n app.component('TdWaterfall', Waterfall)\n}\n\nconst TudouWaterfall: Plugin = {\n install,\n}\n\nexport default TudouWaterfall\nexport { TudouWaterfall }\n"],"names":["_createElementBlock","_openBlock","_Fragment","_renderList","_normalizeStyle","_renderSlot"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -1,15 +1,15 @@
1
1
 
2
- .wf-root[data-v-946f6fbc] {
2
+ .wf-root[data-v-ac5cd1d2] {
3
3
  display: flex;
4
4
  align-items: flex-start;
5
5
  width: 100%;
6
6
  }
7
- .wf-col[data-v-946f6fbc] {
7
+ .wf-col[data-v-ac5cd1d2] {
8
8
  flex: 1;
9
9
  position: relative;
10
10
  min-width: 0;
11
11
  }
12
- .wf-item[data-v-946f6fbc] {
12
+ .wf-item[data-v-ac5cd1d2] {
13
13
  position: absolute;
14
14
  top: 0;
15
15
  left: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tudou-waterfall",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "A Vue 3 plugin with UI components, directives, and global methods",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",