table-generator / src / components / CustomizeTable.vue
CustomizeTable.vue
Raw
<template>
  <section class="customize-table">
    <h2>Customization Options</h2>
    <details open>
      <summary>
        <h3>Main Settings</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="checkbox" label="Use a transparent background?" path="useTransparentBackground" for="settings" />
        <StyleInput v-if="!settings.useTransparentBackground" type="color" label="Text Color" path="color" />
        <StyleInput v-if="!settings.useTransparentBackground" type="color" label="Background Color" path="backgroundColor" />
        <StyleInput type="checkbox" label="Set a max height?" for="settings" path="useMaxHeight"
          instructions="Will create a scrollbar if the post text gets taller than the height you set!" />
        <StyleInput v-if="settings.useMaxHeight" type="number" unit="px" label="Max Height" path="maxHeight"
          for="settings" :attributes="{
            step: 50,
            min: 300,
            max: 700
          }" />
      </div>
    </details>

    <details>
      <summary>
        <h3>Custom Font</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="textarea" label="Google Font" path="customFont" for="settings"
          instructions='The embed code given when you select a font on <a href="https://fonts.google.com/">Google Fonts</a>.' />
      </div>
    </details>

    <details open>
      <summary>
        <h3>Main Text</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="text" label="Font Family" path="fontFamily" />
        <StyleInput type="number" label="Font Size" path="fontSize" unit="px" :attributes="{
          min: 16
        }" />
        <StyleInput type="select" label="Font Weight" path="fontWeight" :options="[
          { label: 'light', value: '200' },
          { label: 'normal', value: 'normal'},
          { label: 'thicker', value: '600'},
          { label: 'bold', value: 'bold'},
          { label: 'bolder', value: '900'}
        ]" 
          instructions="Some options not make a difference depending on which weights are available in your font!"
        />
        <StyleInput type="select" label="Font Style" path="fontStyle" :options="[
          { value: 'normal' },
          { value: 'italic' }
        ]" />
        <StyleInput type="number" label="Line Height" path="lineHeight" :attributes="{
          step: '0.25',
          min: '0.75',
          max: 2
        }" />
        <StyleInput type="number" label="Letter Spacing" path="letterSpacing" unit="px" :attributes="{
          min: 0,
          max: 2,
          step: 1
        }" 
          instructions="If you set this here, it will affect the whole table; override it away on the other sections if desired!"
        />
        <StyleInput type="select" label="Text Alignment" path="textAlign" :options="[
          { value: 'left' },
          { value: 'justify'}
        ]"
        />
      </div>
    </details>

    <details open>
      <summary>
        <h3>Speech Text</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="color" label="Speech Text Color" path="color" for="speech" />
        <StyleInput type="text" label="Font Family" path="fontFamily" for="speech" />
        <StyleInput type="number" label="Font Size" path="fontSize" unit="px" for="speech" :attributes="{
          min: 16
        }" />
        <StyleInput type="number" label="Line Height" path="lineHeight" :attributes="{
          step: '0.25',
          min: '0.75',
          max: 2
        }" for="speech" />
        <StyleInput type="number" label="Letter Spacing" path="letterSpacing" for="speech" unit="px" :attributes="{
          min: 0,
          max: 2,
          step: 1
        }" />
        <StyleInput type="select" label="Font Weight" path="fontWeight" for="speech" :options="[
          { label: 'light', value: '200' },
          { label: 'normal', value: 'normal'},
          { label: 'thicker', value: '600'},
          { label: 'bold', value: 'bold'},
          { label: 'bolder', value: '900'}
        ]" 
          instructions="Some options not make a difference depending on which weights are available in your font!"
        />
        <StyleInput type="select" label="Font Style" path="fontStyle" :options="[
          { value: 'normal' },
          { value: 'italic' }
        ]" for="speech" />
      </div>
    </details>

    <details open>
      <summary>
        <h3>Spacing</h3>
      </summary>
      <div class="inputs">
        <div class="field-group">
          <label class="set-all-input" for="setAllPaddingTo">
            Set all padding to
          </label>
          <input type="number" name="setAllPaddingTo" v-model="setAllPaddingToValue" />
          <button @click="setAllPaddingTo(setAllPaddingToValue)">Set</button>
        </div>
        <StyleInput type="number" label="Padding Top" path="paddingTop" unit="px" :attributes="{
          min: 0
        }" />
        <StyleInput type="number" label="Padding Right" path="paddingRight" unit="px" :attributes="{
          min: 0
        }" />
        <StyleInput type="number" label="Padding Bottom" path="paddingBottom" unit="px" :attributes="{
          min: 0
        }" />
        <StyleInput type="number" label="Padding Left" path="paddingLeft" unit="px" :attributes="{
          min: 0
        }" />

      </div>
    </details>

    <details>
      <summary>
        <h3>Background Image</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="text" label="Background Image" path="backgroundImage" />
        <StyleInput type="select" label="Background Position" path="backgroundPosition" :options="[
          { value: 'top' },
          { value: 'left' },
          { value: 'center' },
          { value: 'right' },
          { value: 'bottom' }
        ]" />
        <StyleInput type="select" label="Background Size" path="backgroundSize" :options="[
          { value: 'cover' },
          { value: 'contain' },
          { value: '100%' },
          { value: 'auto' },
          { value: 'unset' }
        ]" />
        <StyleInput type="select" label="Background Repeat" path="backgroundRepeat" :options="[
          { label: 'Repeat', value: 'repeat' },
          { label: 'Don\'t Repeat', value: 'no-repeat' }
        ]" />
      </div>
    </details>

    <details v-if="!settings.useTransparentBackground">
      <summary>
        <h3>Inner Content Section</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="checkbox" label="Use an inner background layer around the content?" path="useInnerContentArea" for="settings" />
        <template
          v-if="settings.useInnerContentArea"
        >
          <div class="field-group">
            <StyleInput type="color" label="Background Color" for="settings" path="innerContentBackgroundColor" />
            <StyleInput type="number" label="Background Opacity" for="settings" path="innerContentBackgroundOpacity" :attributes="{
              min: 0,
              max: 100,
              step: 5
            }" />
            <label class="set-all-input" for="setAllPaddingTo">
              Set all padding to
            </label>
            <input type="number" name="setAllPaddingTo" v-model="setAllPaddingToValue" />
            <button @click="setAllPaddingTo(setAllPaddingToValue)">Set</button>
          </div>
          <StyleInput type="number" label="Padding Top" path="paddingTop" for="innerContentStyles" unit="px" :attributes="{
          min: 0
          }" />
          <StyleInput type="number" label="Padding Right" path="paddingRight" for="innerContentStyles" unit="px" :attributes="{
            min: 0
          }" />
          <StyleInput type="number" label="Padding Bottom" path="paddingBottom" for="innerContentStyles" unit="px" :attributes="{
            min: 0
          }" />
          <StyleInput type="number" label="Padding Left" path="paddingLeft" for="innerContentStyles" unit="px" :attributes="{
            min: 0
          }" />
          <StyleInput type="number" label="Border Width" path="borderWidth" for="innerContentStyles" unit="px" :attributes="{
            min: 0,
            max: 100
          }" />
          <StyleInput type="color" label="Border Color" for="innerContentStyles" path="borderColor" />
          <StyleInput type="select" label="Border Style" for="innerContentStyles" path="borderStyle" :options="[
            { value: 'solid' },
            { value: 'dotted' },
            { value: 'dashed' }
          ]" />
        </template>
        
      </div>
    </details>

    <details>
      <summary>
        <h3>Additional Image</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="text" label="Image URL" path="imageSrc" for="settings" />
        <template
          v-if="settings.imageSrc"
        >
          <StyleInput type="checkbox" label="Wrap the table text around image?" path="wrapText" for="settings" />
          <StyleInput type="number" label="Image Width (%)" path="imageWidthPercent" unit="%" for="settings"
            instructions="The maximum % of the table width the image should take up. For example, half would be 50%. Between this and the px amount, it will choose whichever is larger."
            :attributes="{
              min: 0
            }" />
          <StyleInput type="number" label="Image Width (px)" path="imageWidthPixels" unit="px" for="settings" :attributes="{
            step: 50,
            min: 0,
            max: 350
          }" />
          <StyleInput type="select" label="Image goes which side?" path="imageSide" for="settings"
            :options="imageSideOptions" />
          <StyleInput type="number" label="Space between image and text" path="imageSpacing" unit="px" for="settings"
            :attributes="{
              min: 0
            }" />
          <StyleInput v-if="!settings.wrapText" type="select" :label="`Image Alignment`" path="imageAlignment" unit="px"
            for="settings"
            instructions="If image is on the left or the right, this will determine its vertical spacing. If it's on the top or bottom, this will determine its horizontal spacing."
            :options="[
              { value: 'center' },
              { value: 'start' },
              { value: 'end' }
            ]" />
        </template>
        
      </div>
    </details>

    <details>
      <summary><h3>Additional Text (#1)</h3></summary>
      <div class="inputs">
        <StyleInput type="text" label="Custom Text" path="textOne" for="settings" />
        <template v-if="settings.textOne">
          <StyleInput type="color" label="Text Color" path="color" for="textOne" />
          <StyleInput type="select" label="Text Position" path="textOnePosition" for="settings" :options="[
            { value: 'top' },
            { value: 'bottom'}
          ]"
          />
          <StyleInput type="text" label="Font Family" path="fontFamily" for="textOne" />
          <StyleInput type="number" label="Font Size" path="fontSize" unit="px" for="textOne" />
          <StyleInput type="select" label="Font Weight" path="fontWeight" for="textOne" :options="[
            { label: 'light', value: '200' },
            { label: 'normal', value: 'normal'},
            { label: 'thicker', value: '600'},
            { label: 'bold', value: 'bold'},
            { label: 'bolder', value: '900'}
          ]" 
            instructions="Some options not make a difference depending on which weights are available in your font!"
          />
          <StyleInput type="select" label="Font Style" path="fontStyle" for="textOne" :options="[
            { value: 'normal' },
            { value: 'italic' }
          ]" />
          <StyleInput type="number" label="Line Height" path="lineHeight" for="textOne" :attributes="{
            step: '0.25',
            min: '0.25',
            max: 2
          }" />
          <StyleInput type="number" label="Letter Spacing" path="letterSpacing" for="textOne" unit="px" :attributes="{
            min: 0,
            max: 10,
            step: 1
          }" />
          <StyleInput type="select" label="Text Alignment" path="textAlign" for="textOne" :options="[
            { value: 'left' },
            { value: 'right'},
            { value: 'justify'},
            { value: 'center'}
          ]"
          />
        </template>
      </div>
    </details>

    <details>
      <summary><h3>Additional Text (#2)</h3></summary>
      <div class="inputs">
        <StyleInput type="text" label="Custom Text" path="textTwo" for="settings" />
        <template
          v-if="settings.textTwo"
        >
          <StyleInput type="color" label="Text Color" path="color" for="textTwo" />
          <StyleInput type="select" label="Text Position" path="textTwoPosition" for="settings" :options="[
            { value: 'top' },
            { value: 'bottom'}
          ]"
          />
          <StyleInput type="text" label="Font Family" path="fontFamily" for="textTwo" />
          <StyleInput type="number" label="Font Size" path="fontSize" unit="px" for="textTwo" />
          <StyleInput type="select" label="Font Weight" path="fontWeight" for="textTwo" :options="[
            { label: 'light', value: '200' },
            { label: 'normal', value: 'normal'},
            { label: 'thicker', value: '600'},
            { label: 'bold', value: 'bold'},
            { label: 'bolder', value: '900'}
          ]" 
            instructions="Some options not make a difference depending on which weights are available in your font!"
          />
          <StyleInput type="select" label="Font Style" path="fontStyle" for="textTwo" :options="[
            { value: 'normal' },
            { value: 'italic' }
          ]" />
          <StyleInput type="number" label="Line Height" path="lineHeight" for="textTwo" :attributes="{
            step: '0.25',
            min: '0.25',
            max: 2
          }" />
          <StyleInput type="number" label="Letter Spacing" path="letterSpacing" for="textTwo" unit="px" :attributes="{
            min: 0,
            max: 10,
            step: 1
          }" />
          <StyleInput type="select" label="Text Alignment" path="textAlign" for="textTwo" :options="[
            { value: 'left' },
            { value: 'right'},
            { value: 'justify'},
            { value: 'center'}
          ]"
          />
        </template>
      </div>
    </details>

    <details>
      <summary>
        <h3>Border</h3>
      </summary>
      <div class="inputs">
        <StyleInput type="number" label="Border Width" path="borderWidth" unit="px" :attributes="{
          min: 0,
          max: 100
        }" />
        <StyleInput type="color" label="Border Color" path="borderColor" />
        <StyleInput type="select" label="Border Style" path="borderStyle" :options="[
          { value: 'solid' },
          { value: 'dotted' },
          { value: 'dashed' }
        ]" />
      </div>
    </details>
  </section>
</template>

<script>
import { mapWritableState, mapActions, storeToRefs } from 'pinia';
import { useTableSettingsStore } from '@/stores/tableSettings';
import StyleInput from './StyleInput.vue';

export default {
  components: {
    StyleInput
  },
  data() {
    return {
      setAllPaddingToValue: 0
    }
  },
  computed: {
    ...mapWritableState(useTableSettingsStore, ['tableStyles', 'imageStyles', 'innerContentStyles', 'settings']),
    imageSideOptions() {
      const options = [
        { value: 'left' },
        { value: 'right' }
      ]
      if (!this.settings.wrapText) {
        options.push({ value: 'top' })
        options.push({ value: 'bottom' })
      }

      return options
    },
    wrapText() {
      return this.settings.wrapText
    },
  },
  methods: {
    ...mapActions(useTableSettingsStore, ['setAllPaddingTo'])
  },
  watch: {
    wrapText: {
      handler(newValue, oldValue) {
        if (newValue !== oldValue) {
          this.settings.imageSide = 'left'
        }
      }
    }
  },

  mounted() {

  }
}</script>