tudou-waterfall 0.1.9 → 0.1.11
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 +9 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +10 -5
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +3 -3
- package/package.json +1 -1
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
|
-
|
|
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,10 +126,13 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
125
126
|
containerRo == null ? void 0 : containerRo.disconnect();
|
|
126
127
|
itemRo.disconnect();
|
|
127
128
|
});
|
|
128
|
-
vue.watch(() =>
|
|
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();
|
|
131
|
-
});
|
|
135
|
+
}, { immediate: true });
|
|
132
136
|
vue.watch(() => props.cols, () => {
|
|
133
137
|
measuredHeights.clear();
|
|
134
138
|
reflow();
|
|
@@ -140,6 +144,7 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
140
144
|
class: "wf-root",
|
|
141
145
|
style: vue.normalizeStyle({ gap: `${__props.gap}px` })
|
|
142
146
|
}, [
|
|
147
|
+
vue.createTextVNode(vue.toDisplayString(colPositions.value) + " ", 1),
|
|
143
148
|
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(colPositions.value, (_col, ci) => {
|
|
144
149
|
return vue.openBlock(), vue.createElementBlock("div", {
|
|
145
150
|
key: ci,
|
|
@@ -173,7 +178,7 @@ const _export_sfc = (sfc, props) => {
|
|
|
173
178
|
}
|
|
174
179
|
return target;
|
|
175
180
|
};
|
|
176
|
-
const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
181
|
+
const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-98c25703"]]);
|
|
177
182
|
function install(app) {
|
|
178
183
|
app.component("TdWaterfall", Waterfall);
|
|
179
184
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -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\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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"}
|
|
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 {{ colPositions }}\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","_createTextVNode","_toDisplayString","_openBlock","_Fragment","_renderList","_normalizeStyle","_renderSlot"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, ref, computed, onMounted, nextTick, onUnmounted, watch, openBlock, createElementBlock, normalizeStyle, Fragment, renderList, renderSlot } from "vue";
|
|
1
|
+
import { defineComponent, ref, computed, onMounted, nextTick, onUnmounted, watch, openBlock, createElementBlock, normalizeStyle, createTextVNode, toDisplayString, Fragment, renderList, renderSlot } from "vue";
|
|
2
2
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
3
3
|
__name: "Waterfall",
|
|
4
4
|
props: {
|
|
@@ -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
|
-
|
|
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,10 +124,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
123
124
|
containerRo == null ? void 0 : containerRo.disconnect();
|
|
124
125
|
itemRo.disconnect();
|
|
125
126
|
});
|
|
126
|
-
watch(() =>
|
|
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();
|
|
129
|
-
});
|
|
133
|
+
}, { immediate: true });
|
|
130
134
|
watch(() => props.cols, () => {
|
|
131
135
|
measuredHeights.clear();
|
|
132
136
|
reflow();
|
|
@@ -138,6 +142,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
138
142
|
class: "wf-root",
|
|
139
143
|
style: normalizeStyle({ gap: `${__props.gap}px` })
|
|
140
144
|
}, [
|
|
145
|
+
createTextVNode(toDisplayString(colPositions.value) + " ", 1),
|
|
141
146
|
(openBlock(true), createElementBlock(Fragment, null, renderList(colPositions.value, (_col, ci) => {
|
|
142
147
|
return openBlock(), createElementBlock("div", {
|
|
143
148
|
key: ci,
|
|
@@ -171,7 +176,7 @@ const _export_sfc = (sfc, props) => {
|
|
|
171
176
|
}
|
|
172
177
|
return target;
|
|
173
178
|
};
|
|
174
|
-
const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
179
|
+
const Waterfall = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-98c25703"]]);
|
|
175
180
|
function install(app) {
|
|
176
181
|
app.component("TdWaterfall", Waterfall);
|
|
177
182
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -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\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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"}
|
|
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 {{ colPositions }}\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","_createTextVNode","_toDisplayString","_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-
|
|
2
|
+
.wf-root[data-v-98c25703] {
|
|
3
3
|
display: flex;
|
|
4
4
|
align-items: flex-start;
|
|
5
5
|
width: 100%;
|
|
6
6
|
}
|
|
7
|
-
.wf-col[data-v-
|
|
7
|
+
.wf-col[data-v-98c25703] {
|
|
8
8
|
flex: 1;
|
|
9
9
|
position: relative;
|
|
10
10
|
min-width: 0;
|
|
11
11
|
}
|
|
12
|
-
.wf-item[data-v-
|
|
12
|
+
.wf-item[data-v-98c25703] {
|
|
13
13
|
position: absolute;
|
|
14
14
|
top: 0;
|
|
15
15
|
left: 0;
|