Last active
August 18, 2020 08:45
-
-
Save sploders101/e80c244310e1e7d8b996f7a98faee9be to your computer and use it in GitHub Desktop.
Revisions
-
sploders101 revised this gist
Jun 24, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -117,7 +117,7 @@ const order = this.getOrder(); // Use keys to sort data this.fields .sort((a, b) => order.indexOf(a[this.muurikey]) - order.indexOf(b[this.muurikey])); } -
sploders101 created this gist
Jun 24, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,194 @@ <template> <div ref="muuriel" class="muuri" > <div class="muuri-item" v-for="field in value" :muurikey="field[muurikey]" :key="field[muurikey]" > <slot :field="field" /> </div> </div> </template> <script lang="ts"> import { Component, Vue, Prop, PropSync, Ref, Watch, } from "vue-property-decorator"; import Muuri from "muuri"; import Options from "@/types/modules/muuri/options"; @Component({ }) export default class MuuriGridVue extends Vue { // ┌─────────────┐ // │ Props │ // └─────────────┘ @Prop() readonly muurikey!: string; @Prop({ default: () => ({}) }) readonly options!: Options; // ┌────────────┐ // │ Refs │ // └────────────┘ @Ref() readonly muuriel!: HTMLDivElement; // ┌────────────────────────────┐ // │ Value Sync (v-model) │ // └────────────────────────────┘ @Prop() readonly value!: any[]; get fields() { return this.value; } set fields(newVal: any[]) { this.$emit("input", newVal); } // ┌─────────────┐ // │ State │ // └─────────────┘ grid: Muuri | null = null; // ┌───────────────────────┐ // │ Lifecycle Hooks │ // └───────────────────────┘ beforeDestroy() { if(this.grid) { this.grid.destroy(false); } } // ┌────────────────────┐ // │ Grid Helpers │ // └────────────────────┘ @Watch("options", { immediate: true }) async init() { if(this.options !== null) { while(!this.muuriel) await this.$nextTick(); if(this.grid) this.grid.destroy(); this.grid = new Muuri(this.muuriel, this.options); this.grid.on("move", () => this.updateData()); } } layout() { if(this.grid) { this.grid.refreshItems(); this.grid.layout(); } } private getOrder() { if(this.grid) { return this.grid .getItems() .map((item) => item.getElement().getAttribute("muurikey")); } else return []; } // ┌─────────────────┐ // │ Data Sync │ // └─────────────────┘ updateData() { // If there's no grid, there's nothing to model the data after if(!this.grid) return; // Get data order by keys const order = this.getOrder(); // Use keys to sort data const fields = this.fields .sort((a, b) => order.indexOf(a[this.muurikey]) - order.indexOf(b[this.muurikey])); } @Watch("fields", { deep: true }) async updateGrid(newData: any[], oldData: any[]) { // If there's no grid, we don't need to update it if(!this.grid) return; // Map to what vue uses as keys (used to determine what to update/replace/reorder) const oldKeys = oldData.map((e) => e[this.muurikey]); const newKeys = newData.map((e) => e[this.muurikey]); // Get which keys (individual elements) were added/removed const added = newKeys.filter((key) => oldKeys.indexOf(key) === -1); const removed = oldKeys.filter((key) => newKeys.indexOf(key) === -1); // Deal with the removed tiles first removed.forEach((po) => { this.grid!.remove(this.getOrder().indexOf(po), { // Vue will take care of this removeElements: false, // We will be adding items too, so not quite yet layout: false, }); }); await this.$nextTick(); // Now add in the new ones this.grid.add( ([ // Wrap NodeList in array for extra methods ...this.muuriel.childNodes, ] as HTMLElement[]) // Filter out anything not in list of added orders .filter((el) => added.indexOf(el.getAttribute("muurikey")!) !== -1), { // We will be re-ordering, so wait a bit longer layout: false, }); // Re-order if needed const items = this.grid.getItems(); const newOrder = this.fields.map((field) => field[this.muurikey]); this.grid.sort((a, b) => { return newOrder.indexOf(a.getElement().getAttribute("muurikey")!) - newOrder.indexOf(b.getElement().getAttribute("muurikey")!); }); // Now we can start the layout this.layout(); } } </script> <style lang="scss" scoped> .muuri { position: relative; & > .muuri-item { display: block; position: absolute; &.muuri-item-dragging { z-index: 3; } &.muuri-item-releasing { z-index: 2; } &.muuri-item-hidden { z-index: 0; } } } </style>