Symbols

by artur_arseniev

HTML

<script src="https://unpkg.com/grapesjs"></script>
<script src="https://unpkg.com/grapesjs-blocks-basic"></script>
<link rel="stylesheet" href="https://unpkg.com/grapesjs/dist/css/grapes.min.css">
<div class="app-wrapper">
  <div class="vue-app">
    <button @click="createSymbol">Create Symbol</button>
    <div class="symbols-wrp gjs-one-bg gjs-two-color">
      <div v-if="symbols.length">Click on symbol to append</div>
      <div class="symbols">
        <div v-for="symbol in symbols" class="gjs-block symbol" @click="createInstance(symbol)" :key="symbol.getId()">
          Name: {{ symbol.getName() }}
          Instances: {{ getInstancesLength(symbol) }}
        </div>
      </div>
    </div>
  </div>
  <div id="gjs"></div>
</div>

SCSS

.app-wrapper {
  height: 100vh;
  display: flex;
  flex-direction: column;
}
.vue-app {
  padding: 10px 0;
  display: flex;
  gap: 10px;
}
.symbols-wrp {
  display: flex;
  gap: 10px;
  width: 100%;
  padding: 10px;
  flex-direction: column;
  border-radius: 3px;
}
.symbols {
  display: flex;
  gap: 10px;
  width: 100%;
}
.symbol {
  cursor: pointer;
  flex-basis: 100px;
  text-align: left;
  margin: 0;
}

Babel + JSX

const editor = grapesjs.init({
  container: '#gjs',
  storageManager: false,
  components: `<div style="display: flex; font-family: system-ui; padding: 10px">
    <article class="card" style="max-width: 300px; padding: 20px">
      <img src="https://placehold.co/600x400/000000/FFF" style="max-width: 100%"/>
      <h1>Title</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>
    </article>
  </div>`,
  plugins: ['gjs-blocks-basic'],
  selectorManager: { componentFirst: true },
});

const { Components } = editor;

const app = new Vue({
  el: '.vue-app',
  data: { symbols: [] },
  mounted() {
    editor.on('symbol', this.updateMainSymbolsList);
  },
  destroyed() {
    editor.off('symbol', this.updateMainSymbolsList);
  },
  methods: {
    updateMainSymbolsList() {
      this.symbols = Components.getSymbols();
    },
    createSymbol() {
      const selected = editor.getSelected();
      if (!selected) return alert('Select a component first!');

      const info = Components.getSymbolInfo(selected);
      if (info.isSymbol) return alert('Selected component is already a symbol!');

      Components.addSymbol(selected);
    },
    getInstancesLength(symbolMain) {
      return Components.getSymbolInfo(symbolMain).instances.length;
    },
    createInstance(symbolMain) {
      const instance = Components.addSymbol(symbolMain);
      editor.getWrapper().append(instance, { at: 0 });
    }
  }
});