<div id="app">
        <pages-nav></pages-nav>
       
        <div id='main-page' data-title='Color wheel'>
            <div id='demo-wrapper'>
                <h1>Demo </h1>
                <div class='demo-container' :data-hide-text="(hide_text == true) ? 'on' : 'off'">
                    <demo></demo>
                </div>
            </div>
            <div id='color-wheel-container'>
                <color-wheel></color-wheel>

                <div class='switch-mode'>
                    <color-theory-wheel :mode='selectedPickerMode' :static='true' wheel-style="white"
                        @click.native='modeSpinner()'> </color-theory-wheel>
                    <span class='mode-text'>{{(isCustom) ? "Custom" : pickerModeTitle}}</span>
                </div>
                <colors-display></colors-display>
            </div>
        </div>
        <div id='color-theory-page' data-title='Color theory'>

            <div class='inner-container'>
                <div class='title'>
                    <h1>Color Theory</h1>
                </div>
                <div class='mixing'>
                    <h4>Mixing Colors</h4>
                    <div class='mixing-wrapper'>
                        <div class='additive-wrapper'>

                            <div class='additive-mixing color-mixing'>
                                <span class='cyan'></span>
                                <span class='yellow'></span>
                                <span class='magenta'></span>
                            </div>
                            <h5>CMYK</h5>
                            <h6>Additive</h6>
                        </div>
                        <div class='subtractive-wrapper'>
                            <div class='subtractive-mixing color-mixing'>
                                <span class='red'></span>
                                <span class='blue'></span>
                                <span class='green'></span>
                            </div>
                            <h5>RGB</h5>
                            <h6>Subtractive</h6>
                        </div>
                    </div>
                </div>
                <div class='relationships'>
                    <h4>Relationships</h4>
                    <div class='color-relations-wrapper'>
                        <color-theory-wheel @click.native='wheel_mode = "primary"' mode='primary' title='Primary Colors'
                            :static='true'>
                        </color-theory-wheel>
                        <color-theory-wheel @click.native='wheel_mode = "secondary"' mode='secondary'
                            title='Secondary Colors' :static='true'>
                        </color-theory-wheel>
                        <color-theory-wheel @click.native='wheel_mode = "tertiary"' mode='tertiary'
                            title='Tertiary Colors' :static='true'>
                        </color-theory-wheel>
                        <color-theory-wheel @click.native='wheel_mode = "temperature"' mode='temperature'
                            title='Temperature' :static='true'>
                        </color-theory-wheel>
                    </div>
                </div>
                <div class='modes'>
                    <h4>Modes</h4>
                    <div class='color-modes-wrapper'>
                        <color-theory-wheel @click.native='wheel_mode = m.name' :title='m.title' :mode='m.name'
                            :static='true' v-for='m in modes'></color-theory-wheel>
                    </div>
                </div>
                <div class='wheel'>
                    <color-theory-wheel :static="isStatic" :mode='wheel_mode' title='' :static='true'
                        data-labels='on'>
                    </color-theory-wheel>
                </div>
            </div>
        </div>

        <div id='about-page' data-title='About'>
            <about></about>
        </div>
    </div>



    <template id='color-wheel-template'>
        <div id='color-wheel-wrapper'>
            <div id='color-wheel-lightness' :style='lightnessStyle' draggable="false">
                <div id='lightness-picker' draggable="false" :style='lightnessRotation'></div>
            </div>

            <div id='color-wheel' draggable="false" :data-moving='(pointerMoving) ? "yes" : "no"'>
                <pointer v-for='(p, i) in pointerCount' :key="'pointer-'+i"
                    :class='{selected: selectedPointerIndex == i}' :index='i' :color-wheel='color_wheel'></pointer>
            </div>
        </div>
    </template>

    <template id='pointer-template'>
        <div class='pointer' draggable="false" :data-index='index'
            :style="{left: left, top: top, background: background}" :class="{enlarge: enlarge == true}"></div>
    </template>

    <template id='colors-display-template'>
        <div id='colors-display'>
            <div class='colors-containers'>
                <div v-for='(c, i) in colors' class='color-container' :class="{selected:  selectedPointerIndex == i }">

                    <div class='color-bg' :class='{entered: entered == i}' :style="getBackground(i)" draggable="true"
                        @dragstart="dragstart(i, $event)" @dragend="dragend" @dragenter="dragenter(i)">
                        <i class="fas fa-grip-horizontal"></i>
                        <div class='color-grads'>
                            <div v-for='(g, i) in c.palette' :style="{'background-color': g}"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class='color-variations'>
                <span class='arrow' :style='arrowStyle'></span>
                <span class='title' @click='colorModelSpinner'>{{currentModel.name}} <i class="fas fa-sort"></i></span>
                <span class='color-value' id='color-value-to-copy'>{{currentModel.value}}</span>
                <span class='copy-value' data-clipboard-target="#color-value-to-copy" :data-copy-result='copy_message'
                    @mouseout="copy_message = ''" :data-message='(copy_message != "") ? "on" : "off"'>
                    <i class="far fa-copy"></i>
                </span>
            </div>
        </div>
    </template>

    <template id='color-theory-wheel-template'>
        <div class='color-theory-wheel' :data-mode='mode' :data-style='wheelStyle'>
            <div class='colors-wrapper'>
                <div class='colors-sections-wrapper'>
                    <div class='color-section' v-for='(c, i) in count' @mouseover='processHover(i)'
                        :class="{hover: highlightIndices.indexOf(i) > -1}"></div>
                </div>

                <div class='color-borders-wrapper'>
                    <div class='color-border' v-for='b in 6'></div>
                </div>
            </div>
            <div class='color-theory-wheel-title'>{{title}}</div>
        </div>
    </template>


    <template id='pages-nav-template'>
        <nav id='pages-nav'>
            <div class='page-dots'>
                <div class='page-dot' v-for='(d, i) in pages' @mouseover='dotHover(i, $event)' @click='current_page = i'
                    :class="{active: current_page == i}"></div>
            </div>
            <div class='page-title' :style="{top: title_position +'px'}">{{pageTitle}}</div>
        </nav>

    </template>

    <template id='about-template'>
        <div id='about-container'>
            <div class='color-wheel-title'>
                <div id='logo'>
                    <div class='beak'>
                        <span></span>
                    </div>
                    <div class='body'>
                    </div>
                    <div class='eye'></div>
                </div>
                <div class='title'>Toucan Palatte Generator</div>

            </div>
            <div class='info-wrapper'>
                <div class='about-container'>
                    <h4>About</h4>
                    <div class='about-wrapper'>
                        <p v-for='i in info'>{{i}}</p>
                    </div>
                </div>
                <div class='shortcuts-container'>
                    <h4>Shortcuts</h4>
                    <div class='shortcuts-wrapper'>
                        <div class='shortcut-row' v-for='s in shortcuts'>
                            <div class='shortcut-combination'>
                                <template v-for='(k, i) in s.keys'>
                                    <kbd class='shortcut-key'
                                        v-if='k.indexOf("mouse") == -1 && k != "+" && k != "/"'>{{k}}</kbd>
                                    <span class='shortcut-plus' v-if='k == "+"'>+</span>
                                    <span class='shortcut-plus' v-if='k == "/"'>/</span>
                                    <span class='shortcut-mouse' :class='k' v-if='k.indexOf("mouse") > -1'>
                                        <i></i>
                                    </span>
                                </template>
                            </div>
                            <div class='shortcut-desc'>{{s.desc}}</div>
                        </div>
                    </div>
                </div>
                <div class='made-with-container'>
                    <h4>Made with</h4>
                    <div class='made-with-wrapper'>
                        <a :href="l.link" target='_blank' v-for='l in made_with'>{{l.title}}</a>
                    </div>
                </div>
            </div>
        </div>

    </template>


    <template id='demo-template'>
        <div class="d-flex" id="demo" :style='getNewStyle()' :data-darkmode="(settings.darkmode) ? 'on' : 'off'" :data-hide-text="(settings.hide_text) ? 'on' : 'off'">
            <!-- Sidebar -->
            <div class="border-right d-flex flex-column" id="sidebar-wrapper">
                <div class="sidebar-heading">Dashboard </div>
                <div class="list-group list-group-flush d-flex flex-column flex-grow-1">
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="fas fa-home"></i><span>Home</span></a>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="fas fa-globe"></i>
                        <span>Overview</span></a>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="far fa-money-bill-alt"></i>
                        <span>Sales</span>
                        <span class="badge badge-primary badge-pill ml-auto">14</a>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="fas fa-user-circle"></i>
                        <span>Profile</span>
                    </a>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="fas fa-thermometer-quarter"></i>
                        <span>Status</span>
                        <span class="badge badge-success badge-pill ml-auto">2</span>
                    </a>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center">
                        <i class="fas fa-table"></i>
                        <span>Tabels</span></a>
                    <hr class='my3'>
                    <a href="#" class="list-group-item list-group-item-action d-flex align-items-center mt-auto">
                        <i class="fas fa-level-up-alt"></i>
                        <span>Upgrade</span>
                    </a>
                </div>


            </div>
            <!-- /#sidebar-wrapper -->

            <!-- Page Content -->
            <div id="page-content-wrapper">
                <nav class="navbar navbar-expand-lg navbar-light" id='top-navbar'>
                    <form class="form-inline  mr-auto">
                        <input class="form-control mr-sm-2" type="search" placeholder="Search">
                    </form>


                    <ul class="navbar-nav">
                        <li class="nav-item mx-2">
                            <a class="nav-link" href="#">
                                <i class="far fa-bell"></i>
                            </a>
                        </li>
                        <li class="nav-item mx-2">
                            <a class="nav-link" href="#"><i class="fas fa-th-large"></i></a>
                        </li>
                        <li class="nav-item mx-2">
                            <a class="nav-link" href="#"><i class="fas fa-user"></i></a>
                        </li>
                    </ul>

                </nav>

                <div class="header bg-primary pb-6">
                    <div class="container-fluid">
                        <div class="header-body">
                            <!-- Card stats -->
                            <div class="row">
                                <div class="col-xl-4 col-md-6" v-for='card in admin_cards'>
                                    <div class="card card-stats mb-4">
                                        <!-- Card body -->
                                        <div class="card-body">
                                            <div class="row">
                                                <div class="col">
                                                    <h5 class="card-title text-uppercase text-mute mb-0">{{card.title}}
                                                    </h5>
                                                    <div class="h2 font-weight-bold mb-0 mt-1">{{card.number}}</div>
                                                </div>
                                                <div class="col-auto">
                                                    <div class="icon icon-shape bg-gradient-red rounded-circle">
                                                        <i :class="card.icon_class"></i>
                                                    </div>
                                                </div>
                                            </div>
                                            <p class="mt-3 mb-0 text-sm">
                                                <span class="string-success mr-2"><i class="fa fa-arrow-up"></i>
                                                    {{card.percentage}}%</span>
                                                <span class="text-nowrap">Since last month</span>
                                            </p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- /header -->
                <div class="container-fluid">
                    <div class="row mb-4" id='graphs'>
                        <div class="col-xl-8">
                            <div class="card bg-default shadow-sm border-0">
                                <div class="card-header bg-transparent">
                                    <div class="row align-items-center">
                                        <div class="col">
                                            <h6 class="text-light text-uppercase ls-1 mb-1">Overview</h6>
                                            <h3 class="text-white mb-0">Visitors / Sale</h3>
                                        </div>
                                        <div class="col">
                                            <ul class="nav nav-pills justify-content-end">
                                                <li class="nav-item mr-2 mr-md-0" data-toggle="chart">
                                                    <a href="#" class="btn btn-primary btn-sm py-1 px-3"
                                                        data-toggle="tab" @click.stop.prevent='updateData("traffic")'
                                                        :class="{active: line_chart.source == 'traffic'}">
                                                        <span class="d-none d-md-block">Visitors</span>
                                                        <span class="d-md-none">V</span>
                                                    </a>
                                                </li>
                                                <li class="nav-item" data-toggle="chart">
                                                    <a href="#" class="btn btn-primary btn-sm py-1 px-3 mx-2"
                                                        data-toggle="tab" @click.stop.prevent="updateData('sales')"
                                                        :class="{active: line_chart.source == 'sales'}">
                                                        <span class="d-none d-md-block">Sales</span>
                                                        <span class="d-md-none">S</span>
                                                    </a>
                                                </li>
                                            </ul>
                                        </div>
                                    </div>
                                </div>

                                <div class="card-body">

                                    <!-- Chart -->
                                    <div class="chart">
                                        <div class="chartjs-size-monitor">
                                            <div class="chartjs-size-monitor-expand">
                                                <div class=""></div>
                                            </div>
                                            <div class="chartjs-size-monitor-shrink">
                                                <div class=""></div>
                                            </div>
                                        </div>

                                        <chart :datasets='linechartDataset' :labels="line_chart.labels"
                                            :options="line_chart.options"></chart>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="col-xl-4" id='dashboard-settings'>
                            <div class="card shadow-sm border-0">
                                <div class="card-header bg-transparent">
                                    <div class="row align-items-center">
                                        <div class="col">
                                            <h3 class="mb-0">Settings</h3>
                                        </div>
                                    </div>
                                </div>
                                <div class="card-body">
                                    <div class='settings-row'>
                                        <label class="switch">
                                            <input type="checkbox" v-model='settings.darkmode'>
                                            <span class='switch-toggle'></span>
                                            <span class="text">Darkmode</span>
                                        </label>
                                    </div>
                                    <div class='settings-row'>
                                        <label class="switch">
                                            <input type="checkbox" v-model='settings.default_sidebar_bg'>
                                            <span class='switch-toggle'></span>
                                            <span class="text">Default Sidebar Background</span>
                                        </label>
                                    </div>
                                     <div class='settings-row hide-text'>
                                        <label class="switch">
                                            <input type="checkbox" v-model='settings.hide_text'>
                                            <span class='switch-toggle'></span>
                                            <span class="text">Hide Text</span>
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </div>

                    </div>
                    <!-- /#graphs -->


                    <div class="row" id='stats'>
                        <div class="col-xl-7">
                            <div class="card border-0 shadow">
                                <div class="card-header border-0 bg-white">
                                    <div class="row align-items-center">
                                        <div class="col">
                                            <h3 class="mb-0 text-uppercase">Page visits</h3>
                                        </div>
                                        <div class="col text-right">
                                            <a href="#!" class="btn btn-sm btn-primary shadow-sm">See all</a>
                                        </div>
                                    </div>
                                </div>
                                <div class="table-responsive">
                                    <!-- Projects table -->
                                    <table class="table align-items-center table-flush">
                                        <thead class="thead-light">
                                            <tr>
                                                <th class='border-bottom-0' scope="col">Page name</th>
                                                <th class='border-bottom-0' scope="col">Visitors</th>
                                                <th class='border-bottom-0' scope="col">Unique users</th>
                                                <th class='border-bottom-0' scope="col">Bounce rate</th>
                                            </tr>
                                        </thead>
                                        <tbody>

                                            <tr v-for='row in page_visits'>
                                                <th scope="row"> {{row.name}} </th>
                                                <td> {{row.visitors}} </td>
                                                <td> {{row.unique}} </td>
                                                <td>
                                                    <i class="fas fa-arrow-up text-success mr-3"
                                                        v-if='row.direction == "up"'></i>
                                                    <i class="fas fa-arrow-down text-warning mr-3"
                                                        v-if='row.direction == "down"'></i>
                                                    {{row.rate}}
                                                </td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                        <div class="col-xl-5 social-ref">
                            <div class="card border-0 shadow">
                                <div class="card-header border-0 bg-white">
                                    <div class="row align-items-center">
                                        <div class="col">
                                            <h3 class="mb-0 text-uppercase">Social traffic</h3>
                                        </div>
                                        <div class="col text-right">
                                            <a href="#!" class="btn btn-sm btn-primary shadow-sm">See all</a>
                                        </div>
                                    </div>
                                </div>
                                <div class="table-responsive">
                                    <!-- Projects table -->
                                    <table class="table align-items-center table-flush">
                                        <thead class="thead-light">
                                            <tr>
                                                <th class='border-bottom-0' scope="col">Referral</th>
                                                <th class='border-bottom-0' scope="col">Visitors</th>
                                                <th class='border-bottom-0' scope="col"></th>
                                            </tr>
                                        </thead>
                                        <tbody>
                                            <tr v-for='row in social_ref'>
                                                <th scope="row">
                                                    {{row.name}}
                                                </th>
                                                <td>
                                                    {{row.visitors}}
                                                </td>
                                                <td>
                                                    <div class="d-flex align-items-center">

                                                        <div class="progress">
                                                            <div class="progress-bar" role="progressbar"
                                                                :style="{width: row.percentage + '%'}"
                                                                :aria-valuenow="row.percentage" aria-valuemin="0"
                                                                aria-valuemax="100">{{row.percentage}}%
                                                            </div>

                                                        </div>
                                                </td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- /#stats -->
                </div>

                <footer class="footer pt-0">
                    <div class="row align-items-center justify-content-lg-between">
                        <div class="col-lg-6">
                            <div class="copyright text-center  text-lg-left  text-muted">
                                © 2021 <a href="#" class="font-weight-bold ml-1" target="_blank">Color wheel</a>
                            </div>
                        </div>
                        <div class="col-lg-6">
                            <ul class="nav nav-footer justify-content-center justify-content-lg-end">
                                <li class="nav-item">
                                    <a href="#" class="nav-link" target="_blank">About Us</a>
                                </li>
                                <li class="nav-item">
                                    <a href="#" class="nav-link" target="_blank">Blog</a>
                                </li>
                                <li class="nav-item">
                                    <a href="#" class="nav-link" target="_blank">MIT License</a>
                                </li>
                            </ul>
                        </div>
                    </div>
                </footer>
            </div>
            <!-- /#page-content-wrapper -->

        </div>
    </template>
   
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Skranji:wght@400;700&display=swap");

:root {
  --bg-color: #ecf0f1;
  --dark-accent: rgba(180, 180, 180, 0.2);
  --darker-accent: lightgray;
  --light-accent: rgba(180, 180, 180, 0.5);
  --light-color: white;
  --dark-color: black;

  --site-main-color: #21749a;
  --scrollbar-foreground: #b3cde0;
  --scrolbar-background: rgba(255, 255, 255, 0);
}

:root {
  --demo-bg-color: white;
  --demo-sidebar-bg: white;
  --demo-sidebar-hover: #{rgba(gray, 0.1)};
  --demo-sidebar-hover-color: black;

  --demo-primary-bg: #5e72e4;
  --demo-primary-color: white;
  --demo-sidebar-text-color: black;

  --demo-btn-border: #465cda;
  --demo-btn-bg: #{lighten(#5e72e4, 5%)};
  --demo-btn-color: black;
  --demo-btn-active-color: #fff;
  --demo-btn-active: #{lighten(#5e72e4, 10%)};
  --demo-btn-active-border: #{darken(#5e72e4, 10%)};

  --demo-header-card: white;
  --demo-header-card-text: #8898aa;

  --demo-text-success: #28a745;

  --demo-scrollbar-foreground: #b3cde0;
  --demo-scrolbar-background: rgba(255, 255, 255, 0);
}

body {
  background-color: var(--bg-color);
}

@mixin scrollbars(
  $size: 4px,
  $foreground-color: var(--scrollbar-foreground),
  $background-color: var(--scrollbar-background)
) {
  // For Google Chrome
  &::-webkit-scrollbar {
    width: $size;
    height: $size;
  }

  &::-webkit-scrollbar-thumb {
    background: $foreground-color;
    border-radius: 0.3rem;
  }

  &::-webkit-scrollbar-track {
    background: $background-color;
  }

  // For Internet Explorer
  & {
    scrollbar-face-color: $foreground-color;
    scrollbar-track-color: $background-color;
    // firefox
    scrollbar-width: thin;
    scrollbar-color: $foreground-color $background-color;
  }
}

@mixin ribbon($size: 0.4em) {
  padding-bottom: 0.6em;
  background-color: #21749a;
  padding: 0.4em 2.3em;
  font-size: 1.3rem;
  color: white;
  width: 70%;
  margin-left: -0.5em;
  margin-bottom: 1.2em;
  margin-top: 0.6em;
  position: relative;
  white-space: nowrap;
}

#app {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: 100%;
  overflow: auto;
  box-sizing: border-box;
  font-family: "Open Sans", sans-serif;
  user-select: none;
  overflow: hidden;

  > div {
    height: inherit;
    width: inherit;
    border-bottom: 1px solid;
    box-sizing: border-box;
    overflow: auto;
    position: relative;
    background: url("https://www.toptal.com/designers/subtlepatterns/patterns/frenchstucco.png");
  }

  #pages-nav {
    position: fixed;
    left: 0;
    // border: 1px solid;
    top: 50%;
    z-index: 10;
    transform: translateY(-50%);
    margin-left: 0.4rem;

    .page-dots:hover + .page-title {
      opacity: 1;
    }

    .page-dot {
      width: 0.5rem;
      height: 0.5rem;
      background-color: purple;
      border-radius: 50%;
      margin-bottom: 0.5rem;
      cursor: pointer;
      transition: all 0.3s;
      opacity: 0.8;

      &:hover {
        opacity: 1;
      }

      &.active {
        height: 1rem;
        border-radius: 0.2rem;
      }
    }

    .page-title {
      position: absolute;
      top: 0;
      left: 1rem;
      border-radius: 0.3em;
      padding: 0.2em 1em;
      background-color: purple;
      color: white;
      transform: translateY(-50%);
      font-size: 0.7rem;
      pointer-events: none;
      transition: all 0.3s;
      white-space: nowrap;
      opacity: 0;
    }
  }

  #main-page {
    #color-wheel-container {
      position: absolute;
      top: 50%;
      right: 3%;
      transform: translateY(-50%);
      border-radius: 0.3rem;
      background-color: white;
      //background-color: rgba(180, 180, 180, 0.2);
      padding: 2rem;
      box-shadow: 0 0 1em 0 rgba(0, 0, 0, 0.3);

      .color-theory-wheel {
        margin: 0;
        width: auto;
        left: initial;
        top: initial;

        .colors-wrapper {
          height: 2rem;
          width: 2rem;
          border-radius: 50%;
        }
      }

      .switch-mode {
        padding: 0.2em 0.5em 0.2em 1em;
        border-radius: 0.2em;
        margin: 1em 0;
        display: flex;
        font-size: 1rem;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        position: absolute;
        top: 1%;
        right: 2%;

        &:hover {
          .mode-text {
            opacity: 1;
            bottom: 115%;
          }
        }

        .mode-text {
          font-size: 0.6rem;
          position: absolute;
          bottom: 95%;
          padding: 0.2rem 0.5rem;
          background-color: lightgray;
          border-radius: 0.2rem;
          white-space: nowrap;
          pointer-events: none;
          transition: all 0.3s;
          opacity: 0;

          &::before {
            top: 100%;
            left: 50%;
            height: 0.5rem;
            width: 0.5rem;
            background-color: lightgray;
            transform: translate(-50%, -70%) rotate(45deg);
            content: "";
            position: absolute;
          }
        }
      }
    }

    #colors-display {
      display: flex;
      flex-direction: column;
      margin-top: 2rem;

      .colors-containers {
        display: flex;

        > div {
          flex-grow: 1;
          min-width: 20%;
          height: 2em;
          position: relative;

          .color-bg {
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: flex-end;

            color: rgba(black, 0.5);

            transition: opacity 0.3s;
            box-sizing: border-box;

            &.entered {
              border: 0.1em dashed gray;
              opacity: 0.5;
            }

            &:hover i {
              opacity: 1;
            }

            i {
              opacity: 0;
              transition: all 0.3s;
              position: absolute;
              bottom: 100%;
              left: 50%;
              transform: translate(-50%, -10%);
              cursor: grab;
            }

            .color-grads {
              display: flex;
              height: 30%;
              width: 100%;

              div {
                display: block;
                width: 25%;
                height: 100%;
              }
            }
          }
        }
      }

      .color-variations {
        display: flex;

        font-size: 0.7rem;
        margin-top: 2em;

        background-color: var(--dark-accent);
        border-radius: 0.3em;
        position: relative;
        color: var(--dark-color);

        .arrow {
          position: absolute;
          bottom: 100%;
          left: 50%;
          transform: translateX(-50%);
          height: 0;
          width: 0;
          border-bottom: solid 0.6rem var(--dark-accent);
          border-left: solid 0.6rem transparent;
          border-right: solid 0.6rem transparent;
        }

        .title {
          width: 25%;
          display: block;
          padding: 1em;
          text-transform: uppercase;
          cursor: pointer;
        }

        .color-value {
          padding: 1em 0;
          user-select: all;
        }

        .copy-value {
          display: flex;
          justify-content: center;
          align-items: center;
          font-size: 1.1em;
          margin-left: auto;
          cursor: pointer;
          transition: all 0.3s;
          padding: 1em;
          background-color: var(--dark-accent);
          position: relative;

          &:hover {
            background-color: var(--light-accent);
          }

          &[data-message="on"] {
            &::after,
            &::before {
              opacity: 1;
            }
          }

          &::after {
            content: attr(data-copy-result);
            padding: 0.5em 1em;
            white-space: nowrap;
            position: absolute;
            top: 120%;
            left: 50%;
            transform: translatex(-50%);
            background-color: var(--darker-accent);

            pointer-events: none;
            border-radius: 0.3em;
            font-size: 0.7rem;
            opacity: 0;
          }

          &::before {
            content: "";
            position: absolute;
            top: 115%;
            left: 50%;
            transform: translatex(-50%) rotate(45deg);
            background-color: var(--darker-accent);

            pointer-events: none;
            height: 1em;
            width: 1em;
            opacity: 0;
          }
        }
      }
    }
  }

  #color-theory-page {
    display: flex;
    justify-content: center;
    align-items: center;

    flex-direction: column;

    h1 {
      text-transform: uppercase;
      font-weight: bold;
      margin: 1.6em 0;
      font-family: "Skranji", cursive;
      line-height: 0;
    }

    .inner-container {
      max-width: 1200px;
      display: grid;
      grid-template-columns: 0.7fr 1.3fr;
      grid-template-areas:
        "title title"
        "mixing wheel"
        "relationships wheel "
        "modes wheel";
      grid-row-gap: 1em;

      h4 {
        @include ribbon;
        margin-bottom: 0.6em;
      }

      > div:not(.wheel):not(.title) {
        font-size: 0.4em;

        .color-theory-wheel {
          cursor: pointer;
        }
      }

      .title {
        grid-area: title;
        font-size: 1.5em;
        font-weight: bold;
        text-align: center;
        text-transform: uppercase;
      }

      .mixing {
        grid-area: mixing;
        background-color: white;
        border-radius: 0.3em;
        box-shadow: 0 0 0.6em 0 rgba(180, 180, 180, 0.8);

        .mixing-wrapper {
          justify-content: space-around;

          > div {
            justify-content: center;
            display: flex;
            flex-direction: column;
            align-items: center;
          }

          h5 {
            font-weight: bold;
            margin: 0;
          }

          h6 {
            font-size: 1.6em;
            margin: 0;
          }
        }
      }

      .relationships {
        grid-area: relationships;
        background-color: white;
        border-radius: 0.3em;
        box-shadow: 0 0 0.6em 0 rgba(180, 180, 180, 0.8);
      }

      .modes {
        grid-area: modes;
        background-color: white;
        border-radius: 0.3em;
        box-shadow: 0 0 0.6em 0 rgba(180, 180, 180, 0.8);
      }

      .terms {
        grid-area: terms;
      }

      .meaning {
        grid-area: meaning;
      }

      .wheel {
        grid-area: wheel;
        font-size: 3em;

        display: flex;
        flex-direction: column;
      }

      .mixing-wrapper,
      .color-modes-wrapper,
      .color-relations-wrapper {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
      }

      .color-mixing {
        height: 12em;
        width: 12em;
        position: relative;
        isolation: isolate;

        span {
          border-radius: 50%;
          height: inherit;
          width: inherit;
          display: block;
          position: absolute;
          left: 50%;
          top: 50%;
          width: 50%;
          height: 50%;

          transform: translate(-50%, -50%);
          mix-blend-mode: screen;
        }

        &.subtractive-mixing span {
          &.green {
            background-color: lime;
            transform: translate(-20%, -30%);
          }

          &.red {
            background-color: red;
            transform: translate(-50%, -70%);
          }

          &.blue {
            background-color: blue;
            transform: translate(-80%, -30%);
          }
        }

        &.additive-mixing span {
          mix-blend-mode: multiply;

          &.cyan {
            background-color: cyan;
            transform: translate(-20%, -30%);
          }

          &.magenta {
            background-color: magenta;
            transform: translate(-50%, -70%);
          }

          &.yellow {
            background-color: yellow;
            transform: translate(-80%, -30%);
          }
        }
      }
    }
  }

  #about-page {
    #about-container {
      margin: 0 auto;
      padding: 0 2em;
      max-width: 1350px;
    }

    .color-wheel-title {
      display: flex;
      justify-content: center;
      padding: 2rem;
      margin: 3rem 0;

      .title {
        font-size: 2.6rem;
        font-weight: bold;
        font-family: "Skranji", cursive;
      }
    }

    .info-wrapper {
      $shortcut-color: #888888;

      display: flex;
      justify-content: space-around;

      > div {
        font-size: 0.8em;
        line-height: 2;
        text-align: justify;
        background-color: white;
        box-shadow: 0 0 0.3em 0 rgba(128, 128, 128, 0.45098039215686275);
        border-radius: 0.3em;

        h4 {
          @include ribbon;
        }

        > div {
          padding: 0 3em;
        }
      }

      .shortcuts-container {
        width: 45%;
        font-size: 0.9em;

        .shortcut-row {
          margin-bottom: 1em;
          display: flex;

          .shortcut-combination {
            width: 35%;
            display: flex;
            align-items: center;
            margin-right: 1em;
            justify-content: flex-start;

            .shortcut-key {
              color: $shortcut-color;

              box-shadow: 0.05em 0.05em 0 rgba(0, 0, 0, 0.2);
              border: 1px solid #ccc;
              margin: 0 0.1em;
              padding: 0.1em 0.5em;
              border-radius: 0.25em;
              background: #f3f3f3;
              min-height: 2em;
              min-width: 2em;
              display: flex;
              justify-content: center;
              align-items: center;
            }
          }

          .shortcut-desc {
            font-size: 0.8em;
          }
        }

        .shortcut-plus {
          color: $shortcut-color;
          margin: 0 0.4em;
        }

        .shortcut-mouse {
          height: 0.5rem;
          width: 0.5rem;
          border-radius: 50%;
          background: darken(#d2d2d2, 5%);
          position: relative;

          &::after,
          &:before {
            position: absolute;
            bottom: 105%;
            left: 50%;
            transform: translateX(-50%) rotate(45deg);
            border: 0.1em solid transparent;
            border-left: 0.1em solid $shortcut-color;
            border-top: 0.1em solid $shortcut-color;
            height: 0.35em;
            width: 0.35em;
          }

          &::after {
            top: 105%;
            transform: translateX(-50%) rotate(225deg);
          }

          &.mouse-wheel-up {
            &::before {
              content: "";
            }
          }

          &.mouse-wheel {
            &::after,
            &::before {
              content: "";
            }
          }

          &.mouse-click-left {
            height: 1.5em;
            width: 0.8em;
            border-radius: 0.3em;
            overflow: hidden;

            &::before {
              content: "";
              top: 0;
              transform: unset;
              left: 0;
              border: 0;
              background-color: $shortcut-color;
              border-radius: 0 0 0.2em 0;
            }
          }
        }
      }

      .made-with-container {
        width: 20%;

        a {
          display: block;
          font-size: 1.1em;
          color: rgba(0, 0, 0, 0.7);
          margin-bottom: 1em;
          text-decoration: none;
          padding: 0.3em;
          position: relative;
          transition: all 0.3s;

          &::before {
            position: absolute;
            top: 100%;
            width: 0;
            transition: all 0.5s ease-in-out;
            content: "";
            height: 0.3em;
            background-color: rgba(180, 180, 180, 0.2);
          }

          &:hover {
            color: black;

            &::before {
              width: 100%;
            }
          }
        }
      }

      .about-container {
        width: 25%;
      }
    }

    #logo {
      height: 7em;
      width: 7em;
      position: relative;
      font-size: 0.4em;
      $dark: #000923;
      margin: 0 3em;

      .beak {
        height: 30%;
        width: 60%;
        position: absolute;
        right: 0;
        border-radius: 50% 51% 100% 0% / 0% 100% 0% 0%;
        background-color: #fa9c21;
        background-image: radial-gradient(circle at 80% 80%, #ed3027, #fa9c21);
        overflow: hidden;

        span {
          position: absolute;
          bottom: 0;
          right: 0;
          border-radius: 50%;
          background-color: $dark;
          height: 2em;
          width: 2em;
          transform: translate(50%, 50%);
        }
      }

      .body {
        height: 100%;
        width: 40%;
        position: absolute;
        left: 0;
        top: 0;
        border-radius: 100% 0% 100% 0% / 40% 60% 50% 60%;

        background-image: linear-gradient($dark, lighten($dark, 10%));
      }

      .eye {
        border-radius: 2em 0 0 2em;
        background-color: #525252;
        position: absolute;
        top: 0%;
        right: 60%;
        height: 30%;
        width: 20%;
      }
    }
  }
}

#color-wheel-wrapper {
  height: 15rem;
  width: 15rem;
  position: relative;

  #color-wheel-lightness {
    --selected-color: gray;

    position: absolute;
    bottom: 0;
    height: 100%;
    width: 100%;
    background-color: green;
    z-index: 0;
    border-radius: 50%;
    box-shadow: 0 0 1em 0.1em rgba(180, 180, 180, 0.5);

    #lightness-picker {
      height: 100%;
      width: 100%;

      &::before {
        content: "";
        position: absolute;
        bottom: 100%;
        left: 50%;
        transform: translateX(-50%);
        height: 0;
        width: 0;

        border-top: solid 0.5rem black;
        border-left: solid 0.5rem transparent;
        border-right: solid 0.5rem transparent;
      }
    }
  }

  #color-wheel {
    border-radius: 50%;
    height: calc(98% - 0.5em);
    width: calc(98% - 0.5em);
    position: absolute;
    left: calc(1% + 0.25em);
    top: calc(1% + 0.25em);
    z-index: 1;
    box-sizing: border-box;
    box-shadow: 0 0 0 0.1em white;
    overflow: hidden;

    --level: 50%;
    background-image: linear-gradient(red, transparent var(--level)),
      linear-gradient(240deg, yellow, transparent var(--level)),
      linear-gradient(-60deg, green, transparent var(--level)),
      linear-gradient(0deg, cyan, transparent var(--level)),
      linear-gradient(60deg, blue, transparent var(--level)),
      linear-gradient(120deg, magenta, transparent var(--level)),
      radial-gradient(gray, white 70%);

    &[data-moving="yes"] {
      cursor: none !important;

      .pointer {
        cursor: none !important;

        &.selected {
          height: 8%;
          width: 8%;
        }
      }
    }

    .pointer {
      border-radius: 50%;
      height: 3%;
      width: 3%;
      position: absolute;
      left: 50%;
      top: 50%;
      box-shadow: inset 0 0 5px 5px white;
      cursor: pointer;
      z-index: 0;
      transition: width 0.2s, height 0.2s;
      transform: translate(-50%, -50%);

      &.selected {
        box-shadow: inset 0 0 0 3px white, 0 0 0px 2px rgba(black, 0.5);
        z-index: 1;
        height: 6%;
        width: 6%;
      }

      &.enlarge {
        width: 15%;
        height: 15%;
        box-shadow: inset 0 0 0 1px rgba(white, 0.5),
          0 0 0px 1px rgba(black, 0.1);
      }
    }
  }
}

.color-theory-wheel {
  left: 10%;
  top: 10%;
  margin: 2em;
  width: 10em;

  .color-theory-wheel-title {
    color: gray;
    font-size: 1.3em;
    text-align: center;
  }

  .colors-wrapper {
    height: 10em;
    width: 10em;
    border-radius: 50%;
    background-color: white;
    position: relative;
    border: 1px solid gray;

    &::before {
      background-color: white;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      content: "";
      height: 15%;
      width: 15%;
      border-radius: 50%;
      z-index: 5;
    }
  }

  .color-borders-wrapper {
    width: 98%;
    height: 98%;
    position: relative;
    position: absolute;
    top: 1%;
    left: 1%;
    overflow: hidden;
    border-radius: 50%;
    pointer-events: none;

    .color-border {
      position: absolute;
      height: 110%;
      width: 0.05em;
      background-color: white;
      top: 50%;
      left: 50%;
      z-index: 3;
      transform: rotate(15deg);

      @for $i from 1 through 6 {
        &:nth-child(#{$i}) {
          $rotate: $i * 30deg + 15;
          transform: translate(-50%, -50%) rotate($rotate);
        }
      }
    }
  }

  &[data-mode="mono"] .color-section.hover::after {
    content: "";
    position: absolute;
    top: 0%;
    left: 50%;
    transform: translateX(-50%);
    background-image: repeating-radial-gradient(
      circle at 50% 50%,
      rgba(white, 0.5) 0 35%,
      rgba(white, 0.3) 30% 53%,
      transparent 50% 100%
    );
    height: 200%;
    width: 373%;
    border-radius: 50%;
  }

  &[data-style="white"] {
    .colors-wrapper {
      background-color: white;
      position: relative;
      border: 0;
      box-shadow: 0 0 0.5rem 0 rgba(gray, 0.6);
    }

    .color-section {
      &:not(.hover) {
        background-color: #eee !important;

        &::before {
          content: unset;
        }
      }

      &.hover {
        background-color: lightgray !important;
      }
    }

    .colors-wrapper::before {
      content: unset;
    }
  }

  &[data-mode="temperature"] .color-border:nth-child(5) {
    width: 0.3em;
    z-index: 5;

    &::after {
      content: "";
      height: 100%;
      width: 54%;
      border-right: 0.05em dashed gray;
      position: absolute;
      left: 0;
      top: 0;
      box-sizing: border-box;
    }
  }

  &[data-labels="on"] .color-section.hover::after {
    opacity: 1;
  }

  .colors-sections-wrapper {
    width: 98%;
    height: 98%;
    position: relative;
    position: absolute;
    top: 1%;
    left: 1%;
    overflow: hidden;
    border-radius: 50%;

    .color-section {
      height: 50%;
      width: 27%;
      position: absolute;
      left: 50%;
      bottom: 50%;
      transform-origin: bottom center;
      transition: background-color 0.3s;
      overflow: hidden;
      box-sizing: border-box;
      clip-path: polygon(50% 100%, 0 0, 100% 0);

      &::before {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        content: "";
        transition: all 0.3s;
        background-image: linear-gradient(
          0deg,
          rgba(lightgray, 0.3),
          rgba(90, 90, 90, 0.2)
        );
      }

      &::after {
        position: absolute;
        top: 0;
        padding: 1em;
        border-radius: 0.3em;
        left: 50%;
        transform: translateX(-50%) rotate(90deg);
        height: 50%;
        font-size: 1rem;
        display: flex;
        justify-content: center;
        align-items: center;
        white-space: pre;
        color: white;
        text-shadow: 0 0 0.2em gray;
        text-transform: capitalize;
        opacity: 0;
        transition: all 0.3s;
      }

      $colors: 0 22 33 49 59 81 117 181 245 266 293 314;
      $light: 50 50 50 50 50 50 41 33 42 50 43 48;
      $names: (
        "red",
        "red-orange",
        "orange",
        "yellow-orange",
        "yellow",
        "yellow-green",
        "green",
        "blue-green",
        "blue",
        "blue-violet",
        "violet",
        "red-violet"
      );

      @for $i from 0 through 11 {
        &:nth-child(#{$i + 1}) {
          $rotate: $i * 30deg;
          $hue: nth($colors, $i + 1);
          $lightness: nth($light, $i + 1);

          transform: translateX(-50%) rotate($rotate);
          background-color: hsla($hue, 100%, 50%, 0.2);

          &.hover {
            background-color: hsla($hue, 100%, $lightness, 1);
          }

          &::after {
            content: nth($names, $i + 1);

            @if ($i < 6) {
              transform: translateX(-50%) rotate(270deg);
            }
          }
        }
      }
    }
  }
}

#demo-wrapper {
  height: 90vh;
  width: 75vw;
  left: 5vw;
  top: 5vh;
  position: relative;
  background-color: white;
  border-radius: 0.2em;
  max-width: 1200px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 0 0.9em 0 rgba(180, 180, 180, 0.6);

  .demo-container {
    padding: 2em;
    overflow: auto;
  }

  h1 {
    display: flex;
    align-items: center;
    @include ribbon();
  }
}

#demo {
  height: 100%;
  width: 100%;
  left: 0;
  top: 0;
  position: relative;
  overflow: hidden;
  border: 1px solid lightgray;
  border-radius: 0.3em;
  background-color: var(--demo-bg-color);
  color: var(--demo-text-color);

  &[data-hide-text="on"] {
    text-indent: -2000px;

    .settings-row.hide-text {
      text-indent: initial;
    }
  }

  &[data-darkmode="on"] {
    --demo-bg-color: #282b34;
    --demo-sidebar-bg: #282b34;
    --demo-sidebar-hover: #{rgba(white, 0.1)};
    --demo-sidebar-hover-color: white;
    --demo-text-color: white;
    --demo-sidebar-text-color: white;

    --demo-card-bg: #1e1e1e;

    .container-fluid {
      .card {
        background-color: var(--demo-card-bg);
        box-shadow: 0 0.125rem 0.25rem rgba(lightgray, 0.1);
      }

      .bg-white {
        background-color: var(--demo-card-bg) !important;
      }

      thead th {
        background-color: var(--demo-card-bg) !important;
      }
    }

    .table th,
    .table td,
    .border-right {
      border-color: rgba(white, 0.2) !important;
    }
  }

  .bg-primary {
    background-color: var(--demo-primary-bg) !important;
  }

  .btn-primary,
  .progress-bar {
    background-color: var(--demo-btn-bg);
    color: var(--demo-btn-color);
  }

  .btn-primary {
    border-color: var(--demo-btn-border);

    &:focus {
      box-shadow: unset !important;
    }

    &.active {
      background-color: var(--demo-btn-active);
      border-color: var(--demo-btn-active-border);
      color: var(--demo-btn-active-color);
    }
  }

  #dashboard-settings {
    .settings-row {
      font-size: 0.8rem;

      .switch {
        display: flex;
        align-items: center;
        cursor: pointer;

        .switch-toggle {
          border-radius: 1rem;
          width: 1.5rem;
          height: 0.8rem;
          background-color: #b0bec5;
          transition: all 0.3s;
          position: relative;
          margin-right: 0.4em;

          &::before {
            width: 0.4rem;
            height: 0.4rem;
            position: absolute;
            left: 0.2rem;
            top: 0.2rem;
            content: "";
            border-radius: 50%;
            background-color: rgba(white, 0.5);
            transition: all 0.3s;
          }
        }

        input[type="checkbox"] {
          display: none;

          &:checked + .switch-toggle {
            background-color: #1976d2;

            &::before {
              left: 100%;
              transform: translateX(calc(-100% - 0.2rem));
              background-color: rgba(white, 0.5);
            }
          }
        }
      }
    }
  }

  #sidebar-wrapper {
    margin-left: -15rem;
    transition: margin 0.25s ease-out;
    background-color: white;
    padding: 0em;
    background-color: var(--demo-sidebar-bg);
    color: var(--demo-sidebar-text-color);

    .sidebar-heading {
      padding: 0;
      font-size: 1.2rem;
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 2em 0;
    }

    .list-group {
      width: 14em;
      font-size: 0.9rem;
      padding: 0.5em;

      .list-group-item {
        padding: 0.7em 1em 0.7em 0.2em;
        background-color: transparent;
        color: var(--demo-sidebar-text-color);
      }

      > a {
        border: 0;
        border-radius: 0.3rem;
        transition: background-color 0.3s;
        font-weight: normal;

        &:hover {
          background-color: var(--demo-sidebar-hover);
          color: var(--demo-sidebar-hover-color);
        }

        i {
          width: 2.5em;
          text-align: center;
          font-size: 1rem;
          margin-right: 0.5rem;
        }
      }
    }
  }

  #page-content-wrapper {
    min-width: 100vw;

    overflow: auto;
    @include scrollbars(
      4px,
      var(--demo-scrollbar-foreground),
      var(--demo-scrollbar-background)
    );

    #top-navbar {
      padding: 1.3em 2em;
      background-color: var(--demo-primary-bg) !important;

      input[type="search"] {
        border-radius: 0.6em;
        outline: 0;
        transition: all 0.3s;
        border: 0;
        background-color: rgba(white, 0.6);

        &:focus {
          width: 20em;
          background-color: white;
        }
      }

      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }

    .nav-link {
      color: var(--demo-primary-color);
    }

    .string-success {
      color: var(--demo-text-success);
    }

    .container-fluid {
      padding: 2em 2em 8em 2em;

      .header-body {
        .card {
          border-radius: 0.375rem;
          background-color: var(--demo-header-card);
          border: 0;
          color: var(--demo-header-card-text-1);

          .text-mute {
            color: var(--demo-header-card-text-2);
          }

          .card-title,
          p {
            font-size: 0.8rem;
          }

          .h2 {
            font-size: 1.5rem;
          }

          .icon {
            height: 3rem;
            width: 3rem;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2em;
            background-color: rgba(gray, 0.1);
          }
        }
      }

      h6 {
        font-size: 0.7rem;
      }

      h3 {
        font-size: 1rem !important;
      }

      h5 {
        font-size: 0.7rem !important;
      }

      .btn-sm {
        font-size: 0.75rem;
      }

      .text-mute {
        color: #8898aa;
      }

      .bg-default {
        background-color: #172b4d !important;
      }

      #graphs {
        margin-top: -7em;
      }

      #stats {
        font-size: 0.8rem;

        thead th {
          color: #8898aa;
          background-color: #f6f9fc;
          font-weight: normal;
          text-transform: uppercase;
          font-size: 0.8em;
        }

        .progress {
          width: 100%;
          font-size: 0.7em;
        }

        .social-ref td:last-child {
          width: 50%;
        }
      }
    }

    footer {
      padding: 2em;
      font-size: 0.8rem;

      a {
        color: inherit;
      }
    }
  }
}

@media (min-width: 768px) {
  #demo {
    #sidebar-wrapper {
      margin-left: 0;
    }

    #page-content-wrapper {
      min-width: 0;
      width: 100%;
    }
  }
}

@media (max-width: 700px) {
  html {
    font-size: 12px;
  }
  #app{
    h1, .color-wheel-title .title{
      font-size: 2rem !important;
    }
  #color-wheel-wrapper {
    height: 12rem;
    width: 12rem;
  }

   #color-theory-page {
     h5{
       font-size: 1.4em;
     }
     
     .color-theory-wheel-title{
       font-size: 1.7em;
     }
    .inner-container {
      max-width: 100%;

      grid-template-columns: 1fr 1fr 1fr;
      grid-template-areas:
        "title title title"
        "wheel wheel wheel"
        "mixing relationships modes";
      grid-row-gap: 0.5em;

      .color-theory-wheel {
        margin: 1em auto;
      }
      
      .modes, .relationships{
        .color-theory-wheel{
          margin: 1em 4em;
        }
      }
    }
  }
  
  #about-page{
    .info-wrapper{
      display: block;
      > .about-container, .shortcuts-container, .made-with-container{
        width: 100%;
      }
      > div > div{
        padding: 1em 2em;
      }
    }
  }
}
}
View Compiled
/**
 * Uitlity method to map state from observable to components.
 * The methods will convert snake_case keys to camelCase
 * @param Array state  arary of state keys to be mapped
 */
const mapState = function (state) {
    let returnState = {};
    if (!Array.isArray(state))
        return returnState;

    state.forEach(s => {
        let key = s.split("_").map((k, i) => {
            let replaceKey = k.replace(/^./, (m) => m.toUpperCase());
            return (i > 0) ? replaceKey : k;
        }).join("");

        returnState[key] = function () {
            return store[s];
        }
    });

    return returnState;
}
/**
 * Utility methods to map mutations to compoenent
 * @param Array methods array of methods keys to be mapped
 */
const mapMethods = function (methods) {
    let returnMethods = {};
    if (!Array.isArray(methods))
        return returnMethods;

    methods.forEach(m => {
        returnMethods[m] = mutations[m];
    });

    return returnMethods;
}

/**
 * Observable is used in place to Vuex as a simple state management alterantive
 */
let store = Vue.observable({
    picker_modes: [{
        name: "comple",
        title: "Complementary"
    }, {
        name: "split",
        title: "Split Complementary"
    }, {
        name: "mono",
        title: "Monochromatic"
    }, {
        name: "analog",
        title: "Analogous"
    }, {
        name: "tri",
        title: "Triadic"
    }, {
        name: "square",
        title: "Square"
    }, {
        name: "tetra",
        title: "Tetradic"
    }],
    selected_picker_mode: "single",
    is_custom: false,
    picker_mode_title: function () {
        const currentMode = Object.values(this.picker_modes).filter(m => {
            if (m.name == this.selected_picker_mode && m.name != "custom")
                return m.title;
        });

        if (currentMode[0] == undefined)
            return "";

        return currentMode[0].title;
    },
    pointer_count: function () {
        const mode = this.selected_picker_mode;
        let count = 0;

        switch (mode) {
            case "single":
                count = 1;
                break;

            case "comple":
                count = 2;
                break;

            case "split":
            case "analog":
            case "mono":
            case "tri":
                count = 3;
                break;

            case "square":
            case "tetra":
                count = 4;
                break;

        }
        return count;
    },
    pointer_sepration: {
        "comple": [180, 180],
        "split": [140, 140, 80],
        "analog": [40, 40, 280],
        "mono": [
            [0.3, 0.3, 0.6],
            [-0.3, 0.3, 0.3],
            [-0.6, -0.3, 0.3]
        ],
        "tri": [120, 120, 120],
        "square": [90, 90, 90, 90],
        "tetra": [120, 60, 120, 60],
    },
    wheel_demo_indices: {
        "comple": [0, 6],
        "analog": [0, 1, 11],
        "mono": [0],
        "split": [0, 5, 7],
        "tri": [0, 4, 8],
        "tetra": [0, 4, 6, 10],
        "square": [0, 3, 6, 9],
        "temperature": [...Array(12).keys()],
        "primary": [0, 4, 8],
        "secondary": [2, 6, 10],
        "tertiary": [1, 3, 5, 7, 9, 11]
    },
    selected_pointer_index: 0,
    colors: [{
        degrees: 80,
        saturation: 100,
        lightness: 50,
        lightnessRotate: 90,
        left: 0,
        top: 0,
        palette: {
            darkest: "",
            darker: "",
            lighter: "",
            lightest: ""
        }
    }],
    ctrl_pressed: false,
    pointer_moving: false
});

let mutations = {
    updateMode: function (mode) {
        if (mode == 'custom') {
            store.is_custom = true;
        } else {
            store.is_custom = false;
            store.selected_picker_mode = mode;
            store.selected_pointer_index = 0;
        }
    },
    updateColor: function (index, newColors) {
        const currentColors = store.colors[index];
        const updatedColor = Object.assign({}, currentColors, newColors);
        const {
            degrees: h,
            saturation: s,
            lightness: l
        } = updatedColor;

        const color = tinycolor(`hsl(${h}, ${s}%, ${l}%)`);

        updatedColor.palette = {
            darkest: color.clone().darken(30).toHslString(),
            darker: color.clone().darken(15).toHslString(),
            lighter: color.clone().lighten(15).toHslString(),
            lightest: color.clone().lighten(30).toHslString(),
        }

        updatedColor.hsl = color.toHslString();

        Vue.set(store.colors, index, updatedColor);
    },
    removeColor: function (start) {
        store.colors.splice(start);
    },
    swapColors: function (from, to) {
        const a = store.colors[from];
        const b = store.colors[to];

        Vue.set(store.colors, from, b);
        Vue.set(store.colors, to, a);
    },
    updatePointerIndex: function (newIndex) {
        store.selected_pointer_index = parseInt(newIndex);
    },
    updateCtrl: function (newValue) {
        store.ctrl_pressed = newValue;
    },
    updateWheelMode: function (index) {
        store.picker_modes[index];
        store.wheel_demo_mode = mode;
    },
    updateMoving: function (isMoving) {
        store.pointer_moving = isMoving;
    }
};

Vue.component('pointer', {
    template: "#pointer-template",
    props: ['index', 'color-wheel'],
    data: () => {
        return {
            pointer_clicked: false,
            enlarge: false,
            enlargeTimeout: null
        }
    },
    created: function () {
        if (this.index == this.selectedPointerIndex) {
            window.addEventListener('keydown', event => {
                switch (event.code) {
                    case "ArrowUp":
                    case "ArrowDown":
                        this.changeSaturation(event.code);
                        event.preventDefault();
                        break;

                    case "ArrowLeft":
                    case "ArrowRight":
                        this.changeHue(event.code);
                        event.preventDefault();
                        break;
                }
            });
        }

        // check if lightness change and update class for 1 seconds
        this.$parent.$on("lightnessChange", () => {
            if (this.index == this.selectedPointerIndex) {
                this.enlarge = true;
                clearTimeout(this.enlargeTimeout);
                this.enlargeTimeout = setTimeout(() => {
                    this.enlarge = false;
                }, 700);
            }
        });
    },
    mounted: function () {
        // Create object for the current element
        let newObject = {
            degrees: 260,
            saturation: 100,
            lightness: 50,
            light: 90,
            palette: {
                darkest: "",
                darker: "",
                lighter: "",
                lightest: ""
            }
        }

        // update or add new color item if required
        this.updateColor(this.index, newObject);

        // assign events
        document.addEventListener("mousedown", this.mouseDown);
        document.addEventListener("mouseup", e => this.pointer_clicked = false);
        document.addEventListener("mousemove", this.movePointer);

        // this event is needed when picker  mode changes
        this.$parent.$on('updateFirstPointer', data => {
            if (this.index == 0) {
                const coord = this.getPointerPosition(this.colors[0]);
                const firstColor = Object.assign(this.colors[0], coord);
                this.updateColor(this.index, firstColor);
            }
        });

        this.$parent.$on('updateOtherPointers', data => {
            if (this.isCustom != true)
                this.getstyle();
        });
    },
    methods: {
        ...mapMethods(["updateColor", "removeColor", "updatePointerIndex", "updateMode", "updateMoving"]),
        mouseDown: function (e) {
            if (e.target.id == 'color-wheel') {
                this.pointer_clicked = true;
                if (this.ctrlPressed)
                    this.updateMode("custom");
                else
                    this.updatePointerIndex(0);
            }

            if (e.target.classList.contains("pointer")) {
                this.pointer_clicked = true;
                const pointerIndex = e.target.getAttribute("data-index");
                this.updatePointerIndex(pointerIndex);

                if (this.ctrlPressed)
                    this.updateMode("custom");
            }

        },
        changeSaturation: function (direction) {
            // increase or decrease by 5 if ctrl is pressed, otherwise jsut 1
            let factor = 1;
            if (this.ctrlPressed == true)
                factor = 5;

            // Get current color and update saturation accordingly.
            const currentColor = this.colors[this.selectedPointerIndex];
            let newSaturation = (direction == "ArrowDown") ? currentColor.saturation + factor : currentColor.saturation - factor;

            // value can only be betwen 0 and 100, no need to loop
            newSaturation = Math.max(0, Math.min(100, newSaturation));

            // merge new values with old current and overwrite degrees
            let newColor = Object.assign(currentColor, {
                saturation: newSaturation
            });

            // get position for the new values
            newColor = Object.assign(newColor, this.getPointerPosition(newColor));

            // update color picker then update other pickers
            this.updateColor(this.selectedPointerIndex, newColor);
            
            this.$parent.$emit('updateOtherPointers');
        },
        changeHue: function (direction) {
            // increase or decrease by 5 if ctrl is pressed, otherwise jsut 1
            let factor = 1;
            if (this.ctrlPressed == true)
                factor = 5;

            // Get current color and update hue accordingly.
            const currentColor = this.colors[this.selectedPointerIndex];

            let newHue = (direction == "ArrowLeft") ? currentColor.degrees + factor : currentColor.degrees - factor;

            // value can only be betwen 0 and 360
            if (newHue > 360)
                newHue = 0;

            if (newHue < 0)
                newHue = 360;

            // merge new values with old current and overwrite degrees
            let newColor = Object.assign(currentColor, {
                degrees: newHue
            });

            // get position for the new values
            newColor = Object.assign(newColor, this.getPointerPosition(newColor));

            // update current color  then update other colors
            this.updateColor(this.selectedPointerIndex, newColor);
            this.$parent.$emit('updateOtherPointers');
        },
        getPointerPosition: function (currentColor) {

            const wheel_radius = this.colorWheel.radius;
            const angle = currentColor.degrees;
            const distance = currentColor.saturation * wheel_radius / 100;

            // radians start from right center turing count clockwis.
            // hsl degress start top center turning clockwise.
            // we need to adujst the angle to provide the right measuerments
            const radians = (angle - 90) * (Math.PI / 180);
            const left = wheel_radius + distance * Math.cos(radians);
            const top = wheel_radius + distance * Math.sin(radians);

            return {
                top: top.toFixed(2),
                left: left.toFixed(2)
            }
        },
        movePointer: function (e) {
            if (!this.pointer_clicked || this.index != this.selectedPointerIndex)
                return;

            const wheel = this.colorWheel;
            let left = e.clientX - wheel.x;
            let top = e.clientY - wheel.y;

            // calcuate distance of the picker dot from color wheel
            const dx = wheel.radius - left;
            const dy = wheel.radius - top;
            let distance = Math.sqrt(dx * dx + dy * dy);

            // get angle so we can get coords once mouse outside color wheel
            let angle = Math.atan2(dy, dx);

            angle = angle < 0 ? (angle += Math.PI * 2) : angle;

            if (distance > wheel.radius) {
                left = wheel.radius - wheel.radius * Math.cos(angle);
                top = wheel.radius - wheel.radius * Math.sin(angle);
            }

            // Dont make distance greater than radius
            if (distance >= wheel.radius)
                distance = wheel.radius;

            let saturation = distance * 100 / wheel.radius;

            // -90 is to start from top center to avoid discrepancy between circle start point
            // and HSL start point
            let hslDegree = angle * 180 / Math.PI - 90;

            // after 270 degrees hsl will be a negative value starting from -90 to 0
            if (hslDegree < 0)
                hslDegree = 270 + (90 - Math.abs(hslDegree));

            let color = {
                degrees: Math.round(hslDegree),
                saturation: Math.round(saturation),
                lightness: 50,
                left: left.toFixed(2),
                top: top.toFixed(2)
            }

            this.updateColor(this.selectedPointerIndex, color);
            
            this.$parent.$emit('updateOtherPointers');
        },
        getstyle: function () {
            if (this.colors[this.index] == undefined)
                return;

            const mode = this.selectedPickerMode;
            const selectedIndex = this.selectedPointerIndex;
            const anchorColor = this.colors[selectedIndex];
            const pointer = this.index;
            const separation = this.pointerSepration[mode];

            // We need to loop through the array values. i.e if we reach the end start again to get all values
            let separationValues = [];
            if (this.index < selectedIndex)
                separationValues = [...separation.slice(selectedIndex + 1), ...separation.slice(0, this.index + 1)];
            else
                separationValues = this.pointerSepration[mode].slice(selectedIndex + 1, this.index + 1);

            // Calculate hue degree by accumlating previous values in array
            let seprationDegree = 0;
            if (separationValues.length != 0)
                seprationDegree = separationValues.reduce((acc, value) => acc + value);

            if (pointer != selectedIndex) {

                let newColor = {};
                newColor.seprationDegree = seprationDegree;

                if (mode != 'mono') {
                    // change hue degree and keep within 360 for tinyscript
                    let degrees = anchorColor.degrees + seprationDegree;
                    if (degrees > 360)
                        degrees = degrees - 360;

                    newColor.degrees = degrees;
                    newColor.saturation = anchorColor.saturation;

                } else {
                    // for monochrome change saturation other change hue degree
                    let newSaturation = anchorColor.saturation
                    if (selectedIndex != 0)
                        newSaturation = 100 - anchorColor.saturation;
                    // For mono colors, the factor is third. Once we get it we can subtract 
                    // from anchor color to get new one. (factor is negative to move forward when subtracting
                    // and backgward when positive)
                    const third = newSaturation * separation[selectedIndex][pointer];
                    let saturation = anchorColor.saturation - (third);

                    // Saturation can not exceed 100% or be less than 0
                    if (saturation > 100)
                        saturation = 100;
                    if (saturation < 0)
                        saturation = 0;

                    newColor.degrees = anchorColor.degrees;
                    newColor.saturation = saturation;
                }

                newColor.lightness = this.colors[pointer].lightness;


                let coord = this.getPointerPosition(newColor);
                newColor = Object.assign(newColor, coord);

                this.updateColor(pointer, newColor);
            }
        },
    },
    computed: {
        ...mapState(["selected_picker_mode", "pointer_count", "pointer_sepration", "colors", "ctrl_pressed", "is_custom", "selected_pointer_index"]),
        selectedColor: function () {
            return this.colors[this.selectedPointerIndex];
        },
        left: function () {
            if (this.colors[this.index] == undefined)
                return 0;

            return this.colors[this.index].left + "px";
        },
        top: function () {
            if (this.colors[this.index] == undefined)
                return 0;
            return this.colors[this.index].top + "px";
        },
        background: function () {
            if (this.enlarge == false)
                return '';

            let c = this.selectedColor;
            return `hsl(${c.degrees}, ${c.saturation}%, ${c.lightness}%)`
        }

    },
    watch: {
        selectedPickerMode: function () {
            this.$parent.$emit('updateOtherPointers');
            this.$parent.$emit('updateFirstPointer');
        },
        pointer_clicked: function(isClicked){
            this.updateMoving(isClicked);
        }
    },
    destroyed: function () {
        this.removeColor(this.index);
    }
});

Vue.component('color-wheel', {
    template: "#color-wheel-template",
    data: () => {
        return {
            color_wheel: {},
            lightness_picker_el: null,
            timeout: null
        }
    },
    created: function () {
        // attach events to move picker inside color wheel
        document.addEventListener("mousedown", e => {
            if (e.target.id == 'lightness-picker')
                this.lightness_clicked = true;
        });

        document.addEventListener("mouseup", e => this.lightness_clicked = false);
        document.addEventListener("mousemove", this.moveLightness);

        // update wheel position and size on window resize
        window.addEventListener("resize", this.updateWheelPosition);

        // update selected index when number is pressed
        window.addEventListener('keydown', event => {
            switch (event.code) {
                case "Digit1":
                case "Digit2":
                case "Digit3":
                case "Digit4":
                    const index = parseInt(event.key);

                    if (index <= this.pointerCount)
                        this.updatePointerIndex(index - 1);
                    break;
            }
        });
    },
    mounted: function () {

        // get color wheel dimensions, position and radius
        this.color_wheel = this.$el.querySelector("#color-wheel").getBoundingClientRect();
        this.color_wheel.radius = this.color_wheel.height / 2;

        this.updateMode("comple");

        this.lightness_picker_el = this.$el.querySelector("#lightness-picker");


        this.$el.addEventListener('wheel', this.changeLightness);

        document.querySelector("#app").addEventListener("scroll", this.updateWheelPosition);
    },
    methods: {
        ...mapMethods(["updateColor", "updatePointerIndex", "initColors", "updateMode", "removeColor"]),
        changeLightness: function (e) {
            let rotate = this.currentColor.lightnessRotate;
            let factor = (this.ctrlPressed) ? 5 : 1;

            let newRotate = 0;

            if (e.deltaY < 0)
                newRotate = rotate + factor;
            else
                newRotate = rotate - factor;


            if (newRotate < 0)
                newRotate = 360;

            if (newRotate > 360)
                newRotate = 0;

            // get lightness percentage. if over 180
            const lightnessRotate = (newRotate > 180) ? 360 - newRotate : newRotate;

            const lightness = lightnessRotate * 100 / 180;


            this.updateColor(this.selectedPointerIndex, {
                lightness: Math.round(lightness),
                lightnessRotate: Math.round(newRotate)
            });

            // emit event to enlarge picker
            this.$emit('lightnessChange');

            e.preventDefault();
        },
        moveLightness: function (e) {
            if (!this.lightness_clicked)
                return;

            let left = e.clientX - this.color_wheel.x;
            let top = e.clientY - this.color_wheel.y;

            const dx = this.color_wheel.radius - left;
            const dy = this.color_wheel.radius - top;

            // get angle 
            let angle = Math.atan2(dy, dx);

            // -90 to start from from top center
            let degrees = angle * 180 / Math.PI - 90;

            // the first quarter will be over positive and the rest of the circle will negative degrees.
            // Adjust for that case
            if (degrees < 0)
                degrees = 360 - Math.abs(degrees);

            // get lightness percentage. if over 180
            const lightnessRotate = (degrees > 180) ? 360 - degrees : degrees;

            const lightness = lightnessRotate * 100 / 180;

            // emit event to enlarge picker
            this.$emit('lightnessChange');
            this.updateColor(this.selectedPointerIndex, {
                lightness: Math.round(lightness),
                lightnessRotate: Math.round(degrees)
            });
        },
        updateWheelPosition: function (e) {
            clearTimeout(this.timeout);
            this.timeout = setTimeout(() => {
                this.color_wheel = this.$el.querySelector("#color-wheel").getBoundingClientRect();
                this.color_wheel.radius = this.color_wheel.height / 2;
            }, 500);

        }
    },
    computed: {
        ...mapState(["colors", "pointer_count", "selected_pointer_index", "selected_picker_mode", "ctrl_pressed", "pointer_moving"]),
        currentColor() {
            return this.colors[this.selectedPointerIndex];
        },
        lightnessStyle: function () {
            let c = this.currentColor;

            const start = `hsl(${c.degrees}, ${c.saturation}%, 0%)`;
            const middle = `hsl(${c.degrees}, ${c.saturation}%, 50%)`;
            const end = `hsl(${c.degrees}, ${c.saturation}%, 90%)`;

            return {
                backgroundImage: `linear-gradient(180deg, ${start}, ${middle}, ${end})`
            }
        },
        lightnessRotation: function () {

            const rotate = this.currentColor.lightnessRotate;
            //const rotate = lightness * 180 / 100;
            return {
                transform: `rotate(${rotate}deg)`
            }
        },
        pointerCount() {
            return store.pointer_count();
        }
    }

});

Vue.component('color-theory-wheel', {
    template: "#color-theory-wheel-template",
    props: {
        mode: "split",
        title: "",
        static: false,
        wheelStyle: ""
    },
    data: () => {
        return {
            current_hover: 0,
            count: 12
        }
    },
    methods: {
        processHover: function (index) {
            if (this.static == true)
                return [];

            this.current_hover = index;
        }
    },
    computed: {
        ...mapState(["wheel_demo_indices"]),
        modeIndices: function () {
            return this.wheelDemoIndices[this.mode];
        },
        highlightIndices: function () {
            if (this.modeIndices == undefined)
                return [];

            return this.modeIndices.map(i => {
                let newCount = this.current_hover + i
                if (newCount >= this.count)
                    newCount = newCount - this.count;

                return newCount;
            })
        }
    },
    watch: {
        mode: function (newMode) {
            switch (newMode) {
                case "primary":
                case "secondary":
                case "tertiary":
                case "tempreature":
                    this.current_hover = 0;
                    break;
            }
        }
    }
});

Vue.component('colors-display', {
    template: "#colors-display-template",
    data: () => {
        return {
            entered: -1,
            dragged: -1,
            colors_models: [{
                name: "hsl",
                value: ""
            }, {
                name: "rgb",
                value: ""
            }, {
                name: "hex",
                value: ""
            }, {
                name: "hsv",
                value: ""
            }],
            current_model_index: 0,
            copy_message: ""
        }
    },
    mounted: function () {
        const clipboard = new ClipboardJS('.copy-value');

        clipboard.on('success', e => {
            this.copy_message = "copied!"

            e.clearSelection();
        });

        clipboard.on('error', e => {
            this.copy_message = "fAILED!"
        });
    },
    methods: {
        ...mapMethods(['swapColors']),
        getBackground: function (index) {
            const c = this.colors[index];

            return {
                "background-color": c.hsl
            }
        },

        dragstart: function (index, e) {
            this.dragged = index;
            e.dataTransfer.setData('text/plain', 'dummy');
        },
        dragend: function () {
            this.swapColors(this.dragged, this.entered);
            this.entered = -1;
        },
        dragenter: function (index) {
            this.entered = index;
        },
        colorModelSpinner: function () {
            const currentIndex = this.current_model_index;
            const models = this.colors_models;

            let nextIndex = currentIndex + 1;
            if (nextIndex > models.length - 1)
                nextIndex = 0;

            this.current_model_index = nextIndex;
        },
    },
    computed: {
        ...mapState(["colors", "selected_pointer_index", ]),
        tinycolor: function () {
            const c = this.colors[this.selectedPointerIndex];

            return tinycolor(`hsl(${c.degrees}, ${c.saturation}%, ${c.lightness}%)`);
        },
        currentModel: function () {
            const model_index = this.current_model_index;
            return this.colorsModelsValues[model_index];
        },
        colorsModelsValues: function () {
            //const colorObject = {};
            return this.colors_models.map(c => {
                return {
                    name: c.name,
                    value: this[c.name]
                };
            });
        },
        hsl: function () {
            return this.tinycolor.toHslString();
        },
        rgb: function () {
            return this.tinycolor.toRgbString();
        },
        hex: function () {
            return this.tinycolor.toHexString();
        },
        hsv: function () {
            return this.tinycolor.toHsvString();
        },
        pointerCount: function () {
            return store.pointer_count();
        },
        arrowStyle: function () {
            const pointer = this.selectedPointerIndex;
            const width = 100 / this.pointerCount;
            const left = (width * pointer) + (width / 2);

            return {
                left: `${left}%`
            }
        }
    }
});

Vue.component('pages-nav', {
    template: '#pages-nav-template',
    data() {
        return {
            current_page: 0,
            pages: [],
            hovered_dot_index: -1,
            hovered_dot_position: null,
            title_position: 0,
            container: null
        };
    },
    created: function () {
        window.addEventListener('keydown', event => {
            switch (event.code) {
                case "PageUp":
                    if(this.current_page > 0)
                        this.current_page--;

                    event.preventDefault();
                    break;

                case "PageDown":
                    if(this.current_page < 2)
                        this.current_page++;
                    event.preventDefault();
                    break;
            }
        });
    },
    mounted() {
        this.container = document.querySelector("#app");
        let divs = document.querySelectorAll("#app > div");

        for (i = 0; i < divs.length; ++i) {
            let element = divs[i];
            const obj = {
                index: i,
                title: element.getAttribute("data-title"),
                element: element
            }
            this.pages.push(obj);
        }

        
    },
    methods: {
        dotHover: function (index, event) {
            this.hovered_dot_index = index;

            const offsetTop = event.target.offsetTop;
            const height = event.target.getBoundingClientRect().height;

            this.title_position = offsetTop + (height / 2);
        }
    },
    computed: {
        pageTitle: function () {
            if (this.hovered_dot_index == -1)
                return "";

            return this.pages[this.hovered_dot_index].title;
        }
    },
    watch: {
        current_page: function (newVal) {
            let height = this.container.getBoundingClientRect().height;
            this.container.scrollTo({
                top: height * newVal,
                left: 0,
                behavior: 'smooth'
            });
        }
    }
});

Vue.component('about', {
    template: '#about-template',
    data() {
        return {
            info: ['This project provides a complete, easy and intuitive palette generator. Using the color wheel, you can create any type of palette and with live preview you can see how colors would match (or not) on a real website.',
                'In addition, keyboard shortcuts and mouse wheel are used to fine-tune selection and provide greater control over the end results.',
                'I have added a color theory summary to provide a general understanding of how colors are used.'
            ],
            shortcuts: [{
                    keys: ['up', '/', 'down'],
                    desc: "Decrease / Increase saturation by 1%"
                },
                {
                    keys: ['left', '/', 'right'],
                    desc: "Increase / Decrease hue by 1 degree"
                },
                {
                    keys: ['ctrl', '+', 'up', '/', 'down'],
                    desc: "Decrease / Increase saturation by 5%"
                },
                {
                    keys: ['ctrl', '+', 'left', '/', 'right'],
                    desc: "Increase / Decrease hue by 5 degrees"
                },
                {
                    keys: ["mouse-wheel"],
                    desc: "Increase / decrease lightness by 1 degree"
                },
                {
                    keys: ["Ctrl", "+", "mouse-wheel"],
                    desc: "Increase / decrease lightness by 5 degrees"
                },
                {
                    keys: ["1", "2", "3", "4"],
                    desc: "Select color pointer"
                },
                {
                    keys: ["ctrl", "+", "mouse-click-left"],
                    desc: "Custom color mode"
                },
                {
                    keys: ["page down", "/", "page up"],
                    desc: "Move between sections"
                },
                {
                    keys: ["ctrl", "+", "m"],
                    desc: "Cycle between color modes"
                }
            ],
            made_with: [{
                    title: "vue.js",
                    link: "https://vuejs.org/"
                },
                {
                    title: "Bootstrap",
                    link: "https://getbootstrap.com/"
                },
                {
                    title: "TinyColor",
                    link: "https://bgrins.github.io/TinyColor/"
                },
                {
                    title: "Charts.js",
                    link: "https://www.chartjs.org/"
                },
                {
                    title: "clipboard.js",
                    link: "https://clipboardjs.com/"
                },
                {
                    title: "Font Awesome",
                    link: "https://fontawesome.com/"
                },
                {
                    title: "Google fonts",
                    link: "https://fonts.google.com/"
                }
            ]
        };
    },

    mounted() {

    },
    methods: {

    },
    computed: {

    }
});


Vue.component('chart', {
    template: '<canvas ref="myChart" :width="width" :height="height"></canvas>',
    data() {
        return {
            chart: null
        };
    },
    props: {
        type: {
            type: String,
            default: "line"
        },
        width: {
            type: Number,
            validator: value => value > 0,
            default: 651
        },
        height: {
            type: Number,
            validator: value => value > 0,
            default: 350
        },
        labels: Array,
        datasets: {
            type: Array,
            required: true
        },
        options: Object
    },
    mounted() {
        this.chart = new Chart(this.$refs.myChart, {
            type: this.type,
            data: {
                labels: this.labels,
                datasets: this.datasets
            },
            options: this.options,

        });
    },
    beforeDestroy() {
        if (this.chart) {
            this.chart.destroy()
        }
    },
    watch: {
        datasets(newDatasets) {
            this.chart.data.datasets = newDatasets;
            this.chart.update();
        }
    },
});

Vue.component('demo', {
    template: "#demo-template",
    data: () => {
        return {
            settings: {
                darkmode: false,
                default_sidebar_bg: false,
                hide_text: false
            },
            chart: null,
            admin_cards: [{
                    title: "Total traffic",
                    number: "214,126",
                    percentage: "5.1",
                    icon_class: "fas fa-eye"
                },
                {
                    title: "New users",
                    number: "12,186",
                    percentage: "2.6",
                    icon_class: "fas fa-users"
                },
                {
                    title: "Sales",
                    number: "3,186",
                    percentage: "8.1",
                    icon_class: "fas fa-dollar-sign"
                }
            ],
            page_visits: [{
                name: "/color-wheel/",
                visitors: "7,548",
                unique: "657",
                rate: "31,85%",
                direction: "up"
            }, {
                name: "/color-wheel/theory.html",
                visitors: "4,548",
                unique: "201",
                rate: "40,25%",
                direction: "down"
            }, {
                name: "/color-wheel/index.html",
                visitors: "3,268",
                unique: "321",
                rate: "35,25%",
                direction: "up"
            }, {
                name: "/color-wheel/about.html",
                visitors: "2,548",
                unique: "186",
                rate: "42,25%",
                direction: "down"
            }, ],
            social_ref: [{
                name: "facebook",
                visitors: "7,548",
                percentage: "60"
            }, {
                name: "codepen",
                visitors: "10,548",
                percentage: "70"
            }, {
                name: "google",
                visitors: "6,548",
                percentage: "40"
            }, {
                name: "instagram",
                visitors: "2,548",
                percentage: "25"
            }],
            line_chart: {
                source: "traffic",
                labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
                traffic_chart: [{
                    label: 'Visitors',
                    fill: false,
                    data: [131800, 131150, 141004, 151042, 161074, 141878, 161768, 175987, 181897, 192872, 203224, 214126],
                    borderColor: "white",
                    borderWidth: 5,
                    pointRadius: 0,
                    borderCapStyle: "round"
                }],
                sales_chart: [{
                    label: 'Sales',
                    fill: false,
                    data: [2015, 45897, 4598, 15042, 16074, 45987, 12356, 78971, 87865, 12587, 14963, 12008],
                    borderColor: "white",
                    borderWidth: 5,
                    pointRadius: 0,
                    borderCapStyle: "round"
                }],
                options: {
                    tooltips: {
                        mode: 'index',
                        intersect: false
                    },
                    legend: {
                        display: false
                    },
                    animation: {
                        onComplete: function (ss) {
                            //console.log(ss);
                        }
                    },
                    scales: {
                        yAxes: [{
                            ticks: {
                                callback: function (value, index, values) {
                                    if (value == 0)
                                        return 0;


                                    return value.toString().slice(0, -3) + 'k';
                                },
                                padding: 10,
                                fontColor: "lightgray"
                            },
                            gridLines: {
                                borderDash: [2, 4],
                                zeroLineWidth: 0,
                                drawBorder: false,

                            }
                        }],
                        xAxes: [{
                            ticks: {
                                fontColor: "lightgray"
                            }
                        }]
                    }
                }
            }
        }
    },
    mounted: function () {
        this.style = document.documentElement.style;
    },
    methods: {
        updateData: function (type) {
            Vue.set(this.line_chart, "source", type);
        },
        mostReadable: function (color, grades) {
            const matchAgainst = Object.values(grades);
            return tinycolor.mostReadable(color, matchAgainst).toHslString();
        },
        getNewStyle: function () {
            if (this.selectedPickerMode == "single" || this.colors.length < 2)
                return;

            const newColors = {};
            const first = this.colors[0];
            const second = this.colors[1];
            const third = this.colors[2] || {};
            const fourth = this.colors[3] || {};

            let firstColor = tinycolor(first.hsl);

            // Header bg color and text color
            newColors['--demo-primary-bg'] = first.hsl;
            newColors['--demo-primary-color'] = this.mostReadable(first.hsl, first.palette);

            // Button colors (active, hover, .. etc)
            newColors['--demo-btn-bg'] = first.palette.darker;
            newColors['--demo-btn-border'] = first.palette.darkest;
            newColors['--demo-btn-color'] = (firstColor.isDark()) ? "white" : "black";
            newColors['--demo-btn-active-color'] = this.mostReadable(first.palette.lighter, first.palette);
            newColors['--demo-btn-active'] = first.palette.lighter;
            newColors['--demo-btn-active-border'] = first.palette.darkest;

            // header color
            newColors['--demo-header-card'] = second.hsl;
            newColors['--demo-header-card-text-1'] = this.mostReadable(second.hsl, second.palette);
            newColors['--demo-header-card-text-2'] = this.mostReadable(second.hsl, second.palette);
            newColors['--demo-text-success'] = this.mostReadable(second.hsl, first.palette);

            switch (this.selectedPickerMode) {
                case "comple":
                    if (this.settings.default_sidebar_bg == false) {
                        const sidebarHover = this.mostReadable(first.hsl, first.palette);
                        newColors['--demo-sidebar-bg'] = first.palette.lighter;
                        newColors['--demo-sidebar-hover'] = sidebarHover;
                        newColors['--demo-sidebar-hover-color'] = this.mostReadable(sidebarHover, first.palette);
                        newColors['--demo-sidebar-text-color'] = (firstColor.isDark()) ? "white" : "black";
                    }
                    break;

                case "square":
                case "tetra":
                    if(this.colors.length < 4)
                        return;

                    newColors['--demo-scrollbar-foreground'] = fourth.palette.darkest;
                    newColors['--demo-scrollbar-background'] = fourth.palette.lighter;


                case "split":
                case "analog":
                case "mono":
                case "tri":
                case "square":
                case "tetra":
                    if(this.colors.length < 3)
                        return;

                    const thirdColor = tinycolor(third.hsl);

                    if (this.settings.default_sidebar_bg == false) {
                        const sidebarHover = this.mostReadable(third.hsl, second.palette);
                        newColors['--demo-sidebar-bg'] = third.palette.lighter;
                        newColors['--demo-sidebar-hover'] = this.mostReadable(third.hsl, third.palette);
                        newColors['--demo-sidebar-hover-color'] = this.mostReadable(sidebarHover, third.palette);
                        newColors['--demo-sidebar-text-color'] = (thirdColor.isDark()) ? "white" : "black";
                    }

                    break;
            }

            return newColors
        }
    },
    computed: {
        ...mapState(["colors", "selected_picker_mode"]),
        linechartDataset: function () {
            if (this.line_chart.source == 'traffic')
                return this.line_chart.traffic_chart

            return this.line_chart.sales_chart;
        },

    }
});

new Vue({
    el: "#app",
    data: {
        wheel_mode: "comple",
        hide_text: false
    },
    created: function () {
        
        window.addEventListener('keyup', e => {
            this.updateCtrl(false);
        });

        window.addEventListener('keydown', e => {
            if (e.ctrlKey == true)
                this.updateCtrl(true);
        });

        window.addEventListener('keydown', e => {
            if (e.code == 'KeyM' && this.ctrlPressed)
               this.modeSpinner();
            
        });
    },
    methods: {
        updateMode: mutations.updateMode,
        updateCtrl: mutations.updateCtrl,

        modeSpinner: function () {

            if (this.isCustom == true) {
                this.updateMode(this.selectedPickerMode)
                return;
            }

            const currentMode = this.selectedPickerMode;
            const modeIndex = this.modes.findIndex(m => m.name == currentMode);
            const nextIndex = (modeIndex + 1 > this.modes.length - 1) ? 0 : modeIndex + 1;
            const nextMode = this.modes[nextIndex].name;

            this.updateMode(nextMode);
        },
        cancelCustom: function () {
            this.updateMode(this.selectedPickerMode);
        }
    },

    computed: {
        ...mapState(["picker_modes", "selected_picker_mode", "colors", "selected_pointer_index", "is_custom", "ctrl_pressed"]),
        modes() {
            let modes = [];
            this.pickerModes.map(m => {
                modes.push(m);
            });

            if (modes.length == 0)
                return [];

            return modes;
        },

        endColor: function () {

            const c = this.colors[this.selectedPointerIndex];

            return {
                "background-color": `hsl(${c.degrees}, ${c.saturation}%, ${c.lightness}%)`
            }
        },
        isStatic: function () {
            let static = false;
            switch (this.wheel_mode) {
                case "primary":
                case "secondary":
                case "tertiary":
                case "tempreature":
                    static = true;
                    break;
            }

            return static;
        },
        pickerModeTitle: function () {
            return store.picker_mode_title();
        }
    }
})

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css
  2. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.6/clipboard.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js
  4. https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.1/tinycolor.min.js