Skip to content
Snippets Groups Projects
App.vue 9.8 KiB
Newer Older
Julian's avatar
Julian committed
<script setup>
Julian's avatar
Julian committed
import DragGrid from "../../src/DragGrid.vue";
Julian's avatar
Julian committed
import CircularCard from "./components/CircularCard.vue";
import Example1Generic from "./Example1Generic.vue";
import Example2TicTacToe from "./Example2TicTacToe.vue";
import Example3Counters from "./Example3Counters.vue";
import Example4Lessons from "./Example4Lessons.vue";
Julian's avatar
Julian committed
</script>

<template>
  <div id="app">
Julian's avatar
Julian committed
    <h1><code>DragGrid</code> Examples</h1>
    <h2>Example 1</h2>
    <p>
      Grid with two programmatically blocked cells and one programmatically
      blocked item
    </p>
    <example1-generic></example1-generic>
Julian's avatar
Julian committed

    <h2>Example 2: "Tic-Tac-Toe"</h2>
    <p>
      A grid functioning as a playing field and another functioning as a
      container for playing pieces. You can drag as many pieces as you want from
      the container to the field.
    </p>

    <example2-tic-tac-toe></example2-tic-tac-toe>
Julian's avatar
Julian committed

    <h2>Example 3: Counters</h2>
    <p>
      Showcasing local and global state: The local state of the counter
      components doesn't change when moved inside one grid, but is cleared when
      moved to the other. The global state is in the <code>data</code> attribute
      of each item and gets transferred as well. Both grids have also custom
      highlights.
    </p>

    <example3-counters></example3-counters>
Julian's avatar
Julian committed

    <h2>Example 4: Dynamic lessons</h2>
    <p>
      These lessons are loaded from <code>computed</code> to simulate a
      non-editable source like an API. they are changed using the method
      <code>handleLessonMoved</code>. Try changing the sizes of Lesson1, the
      grid and the texts of the items! The lesson container on the side doesn't
      have a highlight and doesn't keep track of the item position. Try moving
      <code>item3</code> back and forth!
    </p>
    <example4-lessons></example4-lessons>
Julian's avatar
Julian committed

    <h2>Example 5: Dynamic colors</h2>
    <p>
      This example showcases the <code>rawItem</code> with the custom method
      <code>getColor</code>. Both grids on the outside call the method with
      <code>"red"</code> while the one in the middle uses <code>"green"</code>.
      We use arrays called <code>placedA</code>, <code>placedB</code> and
      <code>placedC</code> to save, which item is contained in which grid.
      Notice: the third grid doesn't save the item position, they are always
      positioned automatically.
    </p>
Julian's avatar
Julian committed
    <div class="ttt-container">
      <drag-grid
        :value="colorGrid"
        :cols="4"
        :rows="4"
        grid-id="gridA"
        context="colors"
        class="bordered color-grid"
        @itemChanged="handleColorItemChange"
      >
        <template #item="item">
          <div
            :style="{
              background: item.rawItem.getColor('red'),
              color: 'white',
            }"
          >
            {{ item.data.name }}
          </div>
        </template>
      </drag-grid>
      <drag-grid
        :value="colorGrid"
        :cols="4"
        :rows="4"
        grid-id="gridB"
        context="colors"
        class="bordered color-grid"
        @itemChanged="handleColorItemChange"
      >
        <template #item="item">
          <div
            :style="{
              background: item.rawItem.getColor('green'),
              color: 'black',
            }"
          >
            {{ item.data.name }}
          </div>
        </template>
      </drag-grid>
      <drag-grid
        :value="colorGrid"
        :cols="4"
        :rows="4"
        grid-id="gridC"
        context="colors"
        class="bordered color-grid"
        @itemChanged="handleColorItemChange"
      >
        <template #item="item">
          <div
            :style="{
              background: item.rawItem.getColor('red'),
              color: 'white',
            }"
          >
            {{ item.data.name }}
          </div>
        </template>
      </drag-grid>
    </div>
Julian's avatar
Julian committed

    <div class="ttt-container">
      <div>
        <h2>Example 6: Disabled grid</h2>
        <p>
          This uses the same data as the tic tac toe but is completely disabled.
          Notice how the items still move if the tic tac toe grid above is
          changed. Uncheck the checkbox to enable:
        </p>

        <label>
          <input type="checkbox" v-model="gridDisabled" />
          Grid disabled?
        </label>

        <drag-grid
          v-model="ticTacToe"
Julian's avatar
Julian committed
          :cols="3"
          :rows="3"
          :disabled="gridDisabled"
          class="tic-tac-toe"
          context="ticTacToe"
        >
          <template #item="item">
            <CircularCard>
              {{ item.key.startsWith("a") ? "X" : "O" }}
            </CircularCard>
          </template>
        </drag-grid>
      </div>
      <div>
        <h2>Example 7: Disabled fields and items with props</h2>
Julian's avatar
Julian committed
        <p>
          This is a grid with disabled fields and items. Red items are disabled
          and cannot be moved.
        </p>
        <drag-grid
          v-model="someDisabledItems"
          :cols="4"
          :rows="4"
          class="tic-tac-toe"
          :disabled-fields="disabledFields"
        >
          <template #item="{ rawItem }">
            <div
              class="container"
              :style="{ background: rawItem.disabled ? 'red' : 'green' }"
            ></div>
          </template>
          <template #disabledField
            ><div class="container">This field is disabled!</div></template
          >
        </drag-grid>
Julian's avatar
Julian committed
      </div>
    </div>
Julian's avatar
Julian committed
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
Julian's avatar
Julian committed
    contains(array, search) {
      return array.filter((obj) => obj === search).length > 0;
    },
    findAndRemove(array, element) {
      let index = array.findIndex((i) => {
        return i === element;
      });
      if (index >= 0) array.splice(index, 1);
    },
    handleColorItemChange(item) {
      this[item.key].x = item.x;
      this[item.key].y = item.y;

      if (item.gridId === item.originGridId) return;

      switch (item.gridId) {
        case "gridA":
          // Moved to gridA
          this.findAndRemove(
            item.originGridId === "gridB" ? this.placedB : this.placedC,
            item.key
          );
          this.placedA.push(item.key);
          break;
        case "gridB":
          // Moved to gridB
          this.findAndRemove(
            item.originGridId === "gridA" ? this.placedA : this.placedC,
            item.key
          );
          this.placedB.push(item.key);
          break;
        case "gridC":
          // Moved to gridC
          this.findAndRemove(
            item.originGridId === "gridB" ? this.placedB : this.placedA,
            item.key
          );
          this.placedC.push(item.key);
          break;
      }
    },
Julian's avatar
Julian committed
        { x: 1, y: 1, w: 1, h: 1, key: "a1", data: { text: "X" } },
        { x: 3, y: 3, w: 1, h: 1, key: "b1", data: { text: "O" } },
Julian's avatar
Julian committed
      ],
Julian's avatar
Julian committed
      placedA: ["item1", "item2"],
      placedB: ["item3", "item4"],
      placedC: ["item5", "item6"],
      item1: {
        x: 1,
        y: 1,
      },
      item2: {
        x: 2,
        y: 2,
      },
      item3: {
        x: 1,
        y: 1,
      },
      item4: {
        x: 3,
        y: 3,
      },
      item5: {
        x: 2,
        y: 4,
      },
      item6: {
        x: 4,
        y: 2,
      },
Julian's avatar
Julian committed
      gridDisabled: true,
Julian's avatar
Julian committed
      someDisabledItems: [
        { key: "key1", x: 1, y: 3, w: 1, h: 1, data: {} },
        { key: "key2", x: 2, y: 2, w: 1, h: 1, data: {} },
        { key: "key3", x: 3, y: 1, w: 1, h: 1, data: {}, disabled: true },
        { key: "key4", x: 1, y: 2, w: 1, h: 1, data: {}, disabled: true },
      ],
      disabledFields: [
        { x: 1, y: 1 },
        { x: 2, y: 3 },
      ],
  computed: {
Julian's avatar
Julian committed
    colorGrid() {
      let items = ["item1", "item2", "item3", "item4", "item5", "item6"];
      let greens = [
        "green",
        "seagreen",
        "greenyellow",
        "darkolivegreen",
        "limegreen",
        "palegreen",
      ];
      let reds = [
        "darkred",
        "indianred",
        "orangered",
        "red",
        "maroon",
        "firebrick",
      ];
      return items.map((itemName) => {
        return {
          key: itemName,
          x: (grid) => {
            if (grid.gridId === "gridA") {
              return this.contains(this.placedA, itemName)
                ? this[itemName].x
                : -1;
            } else if (grid.gridId === "gridB") {
              return this.contains(this.placedB, itemName)
                ? this[itemName].x
                : -1;
            } else {
              // gridC
              return this.contains(this.placedC, itemName) ? 0 : -1;
            }
          },
          y: (grid) => {
            if (grid.gridId === "gridA") {
              return this.contains(this.placedA, itemName)
                ? this[itemName].y
                : -1;
            } else if (grid.gridId === "gridB") {
              return this.contains(this.placedB, itemName)
                ? this[itemName].y
                : -1;
            } else {
              // gridC
              return this.contains(this.placedC, itemName) ? 0 : -1;
            }
          },
          w: 1,
          h: 1,
          data: {
            name: itemName,
          },
          getColor: (a) =>
            a === "red"
              ? reds[parseInt(itemName[4]) - 1]
              : greens[parseInt(itemName[4]) - 1],
        };
      });
    },
};
</script>

<style scoped>
.container {
  background: lightcoral;
  width: 100%;
  height: 100%;
}
Julian's avatar
Julian committed

.tic-tac-toe {
  max-width: 400px;
}

.ttt-container {
  display: flex;
  justify-content: space-between;
}

.bordered {
  border: 2px solid grey;
}
Julian's avatar
Julian committed

.color-grid {
  min-height: 11em;
  line-height: 2em;
  box-sizing: content-box;
}
Julian's avatar
Julian committed

h2 {
  padding-top: 1em;
}

h2 + p {
  padding-bottom: 0.5em;
}

code {
  background: lightgray;
  padding: 0.2em;
  border-radius: 3px;
}
</style>