mirror of
				https://github.com/kevinveenbirkenbach/roulette-wheel.git
				synced 2025-11-04 02:58:01 +00:00 
			
		
		
		
	add wheel & colors change & delete items fix & add item animation
This commit is contained in:
		
							
								
								
									
										120
									
								
								app.css
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								app.css
									
									
									
									
									
								
							@@ -1,60 +1,42 @@
 | 
			
		||||
html {
 | 
			
		||||
    font-family: 'Courier New', Courier, monospace;
 | 
			
		||||
body {
 | 
			
		||||
  background-color: #121212;
 | 
			
		||||
  color: snow;
 | 
			
		||||
  transition-duration: 3s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
canvas{
 | 
			
		||||
  margin-left: 5rem;
 | 
			
		||||
  height: 50rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
  font-family: "Courier New", Courier, monospace;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input {
 | 
			
		||||
  height: 1.5rem;
 | 
			
		||||
  width: 15rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ul {
 | 
			
		||||
    list-style-type: none;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
li {
 | 
			
		||||
  padding: 0.75rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.open-close-menu{
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: right;
 | 
			
		||||
ul {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  list-style-type: none;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.open-close-arrow {
 | 
			
		||||
    width: 1rem;
 | 
			
		||||
    height: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.item-delete {
 | 
			
		||||
    width: 1rem;
 | 
			
		||||
    height: 1rem;
 | 
			
		||||
    float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.decreasing {
 | 
			
		||||
    width: 0.1rem;
 | 
			
		||||
    transition-duration: 3s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.normal {
 | 
			
		||||
    width: 20rem;
 | 
			
		||||
    transition-duration: 3s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu {
 | 
			
		||||
    height: 100vh;
 | 
			
		||||
    width: 20rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.new-item-button {
 | 
			
		||||
.add-item-button {
 | 
			
		||||
  height: 2rem;
 | 
			
		||||
    width: 10rem;
 | 
			
		||||
  width: 15.5rem;
 | 
			
		||||
  margin-top: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#menu-item {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
.close-arrow {
 | 
			
		||||
  width: 1rem;
 | 
			
		||||
  height: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.counter {
 | 
			
		||||
@@ -62,4 +44,60 @@ li {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.light-dark-mode {
 | 
			
		||||
  float: right;
 | 
			
		||||
  padding: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.remove-all-items-button {
 | 
			
		||||
  width: 5.4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.roulette-wheel {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 50%;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  transform: translate(-50%, -50%);
 | 
			
		||||
  z-index: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu {
 | 
			
		||||
  width: 24rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu-item-list {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.moon-sun {
 | 
			
		||||
  width: 3rem;
 | 
			
		||||
  height: 3rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.item-delete {
 | 
			
		||||
  width: 1rem;
 | 
			
		||||
  height: 1rem;
 | 
			
		||||
  float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.open-close-menu {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media screen and (max-width: 940px) {
 | 
			
		||||
  canvas{
 | 
			
		||||
    margin-top: 5rem;
 | 
			
		||||
    height: 30rem;
 | 
			
		||||
    margin: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .roulette-wheel {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    transform: translate(0, 0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								index.html
									
									
									
									
									
								
							@@ -9,17 +9,22 @@
 | 
			
		||||
    <link rel="stylesheet" href="app.css" />
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <div class="light-dark-mode">
 | 
			
		||||
      <img class="moon-sun" src='static/moon.png' alt="mode">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="menu">
 | 
			
		||||
      <div class="open-close-menu">
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="counter">
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="item-menu">
 | 
			
		||||
      <!-- <div class="open-close-menu">
 | 
			
		||||
        <img class="close-arrow" src="static/right-arrow.png" alt="close menu" />
 | 
			
		||||
      </div> -->
 | 
			
		||||
      <p class="counter"></p>
 | 
			
		||||
      <label for="new-item">Item name</label>
 | 
			
		||||
        <input name="new-item" minlength="1" maxlength="32">
 | 
			
		||||
        <button class="new-item-button">Add</button>
 | 
			
		||||
      <input name="new-item" minlength="1" maxlength="32" />
 | 
			
		||||
      <button class="add-item-button">Add</button>
 | 
			
		||||
      <button class="remove-all-items-button">Remove all</button>
 | 
			
		||||
      <ul class="menu-item-list"></ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="roulette-wheel">
 | 
			
		||||
      <canvas></canvas>
 | 
			
		||||
    </div>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										473
									
								
								src/app.ts
									
									
									
									
									
								
							
							
						
						
									
										473
									
								
								src/app.ts
									
									
									
									
									
								
							@@ -1,202 +1,377 @@
 | 
			
		||||
// import { MenuItem } from "./components/menu-item";
 | 
			
		||||
import { CounterItem } from "./components/counter-item";
 | 
			
		||||
import { MenuItem } from "./components/menu-item";
 | 
			
		||||
import { MenuItemList } from "./components/menu-item-list";
 | 
			
		||||
import { OpenCloseArrow } from "./components/open-close-arrow";
 | 
			
		||||
import { Counter } from "./model/counter";
 | 
			
		||||
import { Item } from "./model/item";
 | 
			
		||||
import { avaliableIds, initializeIdsPool } from "./utils/item-id-pool";
 | 
			
		||||
import { ItemList } from "./model/item-list";
 | 
			
		||||
import { IdPool } from "./utils/item-id-pool";
 | 
			
		||||
import { LightDarkMode } from "./utils/light-dark-mode";
 | 
			
		||||
import { avaliableRGBs } from "./utils/utils";
 | 
			
		||||
// import { OpenCloseArrow } from "./components/open-close-arrow";
 | 
			
		||||
 | 
			
		||||
const addButtonEl = document.getElementsByClassName(
 | 
			
		||||
  "add-item-button"
 | 
			
		||||
)[0]! as HTMLButtonElement;
 | 
			
		||||
const inputEl = document.querySelector("input")! as HTMLInputElement;
 | 
			
		||||
const itemListEl = document.getElementsByClassName(
 | 
			
		||||
  "menu-item-list"
 | 
			
		||||
)[0]! as HTMLUListElement;
 | 
			
		||||
const counterEl = document.getElementsByClassName(
 | 
			
		||||
  "counter"
 | 
			
		||||
)[0]! as HTMLDivElement;
 | 
			
		||||
const itemMenuEl = document.getElementsByClassName(
 | 
			
		||||
  "item-menu"
 | 
			
		||||
)[0]! as HTMLDivElement;
 | 
			
		||||
const openCloseMenuEl = document.getElementsByClassName(
 | 
			
		||||
  "open-close-menu"
 | 
			
		||||
)[0]! as HTMLDivElement;
 | 
			
		||||
const inputEl = document.querySelector("input")! as HTMLInputElement;
 | 
			
		||||
const addButtonEl = document.getElementsByClassName(
 | 
			
		||||
  "new-item-button"
 | 
			
		||||
)[0]! as HTMLButtonElement;
 | 
			
		||||
)[0]! as HTMLParagraphElement;
 | 
			
		||||
const removeAllItemsButtonEl = document.getElementsByClassName(
 | 
			
		||||
  "remove-all-items-button"
 | 
			
		||||
)[0]! as HTMLButtonElement;
 | 
			
		||||
HTMLUL
 | 
			
		||||
const lightDarkModeEl = document.getElementsByClassName('light-dark-mode')[0]! as HTMLDivElement;
 | 
			
		||||
const canvasEl = document.querySelector('canvas')! as HTMLCanvasElement;
 | 
			
		||||
const ctx = canvasEl.getContext('2d')!;
 | 
			
		||||
const bodyEl = document.querySelector('body')! as HTMLBodyElement;
 | 
			
		||||
const modeEl = lightDarkModeEl.querySelector('img')! as HTMLImageElement;
 | 
			
		||||
const canvasWrapper = document.getElementsByClassName('roulette-wheel')[0]! as HTMLDivElement;
 | 
			
		||||
 | 
			
		||||
const MIN_ITEMS = 0;
 | 
			
		||||
const MAX_ITEMS = 16;
 | 
			
		||||
 | 
			
		||||
const openCloseItem = new OpenCloseArrow();
 | 
			
		||||
openCloseMenuEl.appendChild(openCloseItem.el);
 | 
			
		||||
 | 
			
		||||
const counterItem = new CounterItem(MIN_ITEMS, MAX_ITEMS);
 | 
			
		||||
counterEl.appendChild(counterItem.el);
 | 
			
		||||
 | 
			
		||||
const counter = counterItem.getCounter;
 | 
			
		||||
 | 
			
		||||
const items: MenuItemList = new MenuItemList();
 | 
			
		||||
itemMenuEl.appendChild(items.el);
 | 
			
		||||
const MAXIMUM_SIZE = 16;
 | 
			
		||||
 | 
			
		||||
counterEl.textContent = `0/${MAXIMUM_SIZE}`;
 | 
			
		||||
 | 
			
		||||
const itemsList = new ItemList(MAXIMUM_SIZE);
 | 
			
		||||
const items: MenuItem[] = [];
 | 
			
		||||
 | 
			
		||||
configure();
 | 
			
		||||
 | 
			
		||||
function configure() {
 | 
			
		||||
  initializeIdsPool(MAX_ITEMS);
 | 
			
		||||
  LightDarkMode.currentMode = 'dark';
 | 
			
		||||
  IdPool.initializeIdsPool(MAXIMUM_SIZE);
 | 
			
		||||
  addRemoveItem();
 | 
			
		||||
  addItemByEnter();
 | 
			
		||||
  removeAllItems();
 | 
			
		||||
  lightDarkMode();
 | 
			
		||||
  drawRouletteWheel();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function addRemoveItem() {
 | 
			
		||||
  addButtonEl.addEventListener("click", () => {
 | 
			
		||||
  const id = avaliableIds.pop();
 | 
			
		||||
    const name = inputEl.value;
 | 
			
		||||
  if (id) {
 | 
			
		||||
    if (name) {
 | 
			
		||||
      if (counter.increment()) {
 | 
			
		||||
        const item = new MenuItem(id, name, avaliableRGBs[MAX_ITEMS % Counter.value]);
 | 
			
		||||
        console.log(item.deleteItem);
 | 
			
		||||
        item.deleteItem.el.addEventListener('click', () => {
 | 
			
		||||
          if(counter.decrement()){
 | 
			
		||||
            avaliableIds.push(item.el.id)
 | 
			
		||||
            items.removeItem(item);
 | 
			
		||||
            counterItem.updateContent();
 | 
			
		||||
    const id = IdPool.getAnId();
 | 
			
		||||
    if (name && id) {
 | 
			
		||||
      const color = avaliableRGBs[id % avaliableRGBs.length];
 | 
			
		||||
 | 
			
		||||
      const item = new Item(id, name, color);
 | 
			
		||||
      const menuItem = new MenuItem(id, name, color);
 | 
			
		||||
 | 
			
		||||
      menuItem.deleteItem.el.addEventListener("click", () => {
 | 
			
		||||
        menuItem.el.remove();
 | 
			
		||||
        items.splice(items.indexOf(menuItem), 1);
 | 
			
		||||
        itemsList.remove(item);
 | 
			
		||||
        IdPool.addId(item.id);
 | 
			
		||||
        updateCounter();
 | 
			
		||||
        drawRouletteWheel();
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      registerChangeColorByClick(item, menuItem);
 | 
			
		||||
 | 
			
		||||
      itemsList.add(item);
 | 
			
		||||
      items.push(menuItem);
 | 
			
		||||
      itemListEl.appendChild(menuItem.el);
 | 
			
		||||
      updateCounter();
 | 
			
		||||
      drawRouletteWheel();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function addItemByEnter(){
 | 
			
		||||
  bodyEl.addEventListener('keyup', (event: KeyboardEvent) => {
 | 
			
		||||
    if(event.key !== 'Enter'){
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    addButtonEl.click();
 | 
			
		||||
  })
 | 
			
		||||
        items.addItem(item);
 | 
			
		||||
        counterItem.updateContent();
 | 
			
		||||
}
 | 
			
		||||
    } else {
 | 
			
		||||
      alert("Item name cannot be empty!");
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    alert("Maxium number of elements!");
 | 
			
		||||
 | 
			
		||||
function registerChangeColorByClick(item: Item, menuItem: MenuItem) {
 | 
			
		||||
  menuItem.el.addEventListener('click', () => {
 | 
			
		||||
      const actualColorIndex = avaliableRGBs.indexOf(menuItem.el.style.backgroundColor);
 | 
			
		||||
      if(actualColorIndex !== -1){
 | 
			
		||||
          const color = avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length];
 | 
			
		||||
          menuItem.el.style.backgroundColor = color;
 | 
			
		||||
          item.color = color;
 | 
			
		||||
          drawRouletteWheel();
 | 
			
		||||
      }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function removeAllItems() {
 | 
			
		||||
  removeAllItemsButtonEl.addEventListener("click", () => {
 | 
			
		||||
  initializeIdsPool(MAX_ITEMS);
 | 
			
		||||
  items.clear();
 | 
			
		||||
  counter.clear();
 | 
			
		||||
  counterItem.updateContent();
 | 
			
		||||
    if (items.length > 0) {
 | 
			
		||||
      items.forEach((menuItem) => menuItem.el.remove());
 | 
			
		||||
      items.length = 0;
 | 
			
		||||
      itemsList.clear();
 | 
			
		||||
      IdPool.initializeIdsPool(MAXIMUM_SIZE);
 | 
			
		||||
      updateCounter();
 | 
			
		||||
      drawRouletteWheel();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateCounter() {
 | 
			
		||||
  counterEl.textContent = `${itemsList.items.length}/${MAXIMUM_SIZE}`;
 | 
			
		||||
  animateCounter();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function animateCounter() {
 | 
			
		||||
  counterEl.animate(
 | 
			
		||||
    [{ transform: "scale(1.25)" }, { transform: "scale(1.00)" }],
 | 
			
		||||
    {
 | 
			
		||||
      duration: 500,
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function lightDarkMode(){
 | 
			
		||||
  lightDarkModeEl.addEventListener('click', () => {
 | 
			
		||||
    modeEl.animate(
 | 
			
		||||
      [
 | 
			
		||||
        { transform: 'rotate(360deg)' }
 | 
			
		||||
      ],
 | 
			
		||||
      {
 | 
			
		||||
        duration: 500
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if(LightDarkMode.currentMode == 'dark'){
 | 
			
		||||
      modeEl.src = 'static/sun.png';
 | 
			
		||||
      bodyEl.style.backgroundColor = 'snow';
 | 
			
		||||
      bodyEl.style.color = 'black';
 | 
			
		||||
    }else{
 | 
			
		||||
      modeEl.src = 'static/moon.png';
 | 
			
		||||
      bodyEl.style.backgroundColor = '#121212';
 | 
			
		||||
      bodyEl.style.color = 'white';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LightDarkMode.changeMode();
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function drawRouletteWheel(){
 | 
			
		||||
  ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
 | 
			
		||||
  canvasEl.width = canvasWrapper.offsetWidth;
 | 
			
		||||
  canvasEl.height = canvasWrapper.offsetHeight;
 | 
			
		||||
  const x = canvasEl.width / 2;
 | 
			
		||||
  const y = canvasEl.height / 2;
 | 
			
		||||
  const radius = canvasEl.height / 2;
 | 
			
		||||
  let startAngle = 0;
 | 
			
		||||
  ctx.beginPath();
 | 
			
		||||
  ctx.arc(x, y, radius, 0, Math.PI * 2, true);
 | 
			
		||||
  ctx.stroke();
 | 
			
		||||
  const segmentWidth = 360 / items.length;
 | 
			
		||||
  let endAngle = segmentWidth;
 | 
			
		||||
  console.log(items.length);
 | 
			
		||||
  for(let i = 0; i < items.length; i++){
 | 
			
		||||
    ctx.beginPath();
 | 
			
		||||
    if(i === 1){
 | 
			
		||||
      ctx.lineTo(x, y);
 | 
			
		||||
    }
 | 
			
		||||
    ctx.arc(x, y, radius, (startAngle * Math.PI / 180), (endAngle * Math.PI / 180), false);
 | 
			
		||||
    ctx.lineTo(x, y);
 | 
			
		||||
    ctx.fillStyle = itemsList.items[i].color;
 | 
			
		||||
    ctx.fill();
 | 
			
		||||
    ctx.stroke();
 | 
			
		||||
    startAngle += segmentWidth;
 | 
			
		||||
    endAngle += segmentWidth;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// // import { MenuItem } from "./components/menu-item";
 | 
			
		||||
// import { CounterItem } from "./components/counter-item";
 | 
			
		||||
// import { MenuItem } from "./components/menu-item";
 | 
			
		||||
// import { MenuItemList } from "./components/menu-item-list";
 | 
			
		||||
// import { OpenCloseArrow } from "./components/open-close-arrow";
 | 
			
		||||
// import { Counter } from "./model/counter";
 | 
			
		||||
// import { Item } from "./model/item";
 | 
			
		||||
// import { avaliableIds, initializeIdsPool } from "./utils/item-id-pool";
 | 
			
		||||
// import { avaliableRGBs } from "./utils/utils";
 | 
			
		||||
// // import { OpenCloseArrow } from "./components/open-close-arrow";
 | 
			
		||||
 | 
			
		||||
// const counterEl = document.getElementsByClassName(
 | 
			
		||||
//   "counter"
 | 
			
		||||
// )[0]! as HTMLDivElement;
 | 
			
		||||
// const itemMenuEl = document.getElementsByClassName(
 | 
			
		||||
//   "item-menu"
 | 
			
		||||
// )[0]! as HTMLDivElement;
 | 
			
		||||
// const openCloseMenuEl = document.getElementsByClassName(
 | 
			
		||||
//   "open-close-menu"
 | 
			
		||||
// )[0]! as HTMLDivElement;
 | 
			
		||||
// const inputEl = document.querySelector("input")! as HTMLInputElement;
 | 
			
		||||
// const addButtonEl = document.getElementsByClassName(
 | 
			
		||||
//   "new-item-button"
 | 
			
		||||
// )[0]! as HTMLButtonElement;
 | 
			
		||||
// const removeAllItemsButtonEl = document.getElementsByClassName(
 | 
			
		||||
//   "remove-all-items-button"
 | 
			
		||||
// )[0]! as HTMLButtonElement;
 | 
			
		||||
 | 
			
		||||
// const itemNameInput = document.querySelector("input")! as HTMLInputElement;
 | 
			
		||||
// const MIN_ITEMS = 0;
 | 
			
		||||
// const MAX_ITEMS = 16;
 | 
			
		||||
 | 
			
		||||
// const newItemButtonEl = document.getElementById(
 | 
			
		||||
//   "newItemButton"
 | 
			
		||||
// )! as HTMLButtonElement;
 | 
			
		||||
// const openCloseItem = new OpenCloseArrow();
 | 
			
		||||
// openCloseMenuEl.appendChild(openCloseItem.el);
 | 
			
		||||
 | 
			
		||||
// const removeAllItemsButtonEl = document.getElementById(
 | 
			
		||||
//   "removeAllItemsButton"
 | 
			
		||||
// )! as HTMLButtonElement;
 | 
			
		||||
// const counterItem = new CounterItem(MIN_ITEMS, MAX_ITEMS);
 | 
			
		||||
// counterEl.appendChild(counterItem.el);canvasEl
 | 
			
		||||
 | 
			
		||||
// // const newItemMenu = document.getElementById('new-item-menu')! as HTMLDivElement;
 | 
			
		||||
// const counter = counterItem.getCounter;
 | 
			
		||||
 | 
			
		||||
// menuEl.appendChild(items.el);
 | 
			
		||||
// openCloseMenuEl.appendChild(new OpenCloseArrow().el);
 | 
			
		||||
// const items: MenuItemList = new MenuItemList();
 | 
			
		||||
// itemMenuEl.appendChild(items.el);
 | 
			
		||||
 | 
			
		||||
// const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];
 | 
			
		||||
// const bgOpacity = 0.5;
 | 
			
		||||
// let nextColor = avaliableRGBs[0];
 | 
			
		||||
// configure();
 | 
			
		||||
 | 
			
		||||
// const idsPool: number[] = [];
 | 
			
		||||
// initalizeIdsPool();
 | 
			
		||||
// function configure() {
 | 
			
		||||
//   initializeIdsPool(MAX_ITEMS);
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// function addNewItem() {
 | 
			
		||||
//   if (itemNameInput.value.length > 0 && itemNameInput.value.length <= 32) {
 | 
			
		||||
//     if (counter < maxItems && idsPool.length > 0) {
 | 
			
		||||
//       const item = new MenuItem(
 | 
			
		||||
//         idsPool.pop()!,
 | 
			
		||||
//         itemNameInput.value,
 | 
			
		||||
//         `rgba(${nextColor}, ${bgOpacity})`
 | 
			
		||||
//       );
 | 
			
		||||
 | 
			
		||||
//       item.deleteItem.el.addEventListener("click", () => {
 | 
			
		||||
//         const itemElId = calculateItemElId(item);
 | 
			
		||||
//         idsPool.push(itemElId);
 | 
			
		||||
//         setNextColor();
 | 
			
		||||
// addButtonEl.addEventListener("click", () => {
 | 
			
		||||
//   const id = avaliableIds.pop();
 | 
			
		||||
//   const name = inputEl.value;
 | 
			
		||||
//   if (id) {
 | 
			
		||||
//     if (name) {
 | 
			
		||||
//       if (counter.increment()) {
 | 
			
		||||
//         const item = new MenuItem(id, name, avaliableRGBs[MAX_ITEMS % Counter.value]);
 | 
			
		||||
//         console.log(item.deleteItem);
 | 
			
		||||
//         item.deleteItem.el.addEventListener('click', () => {
 | 
			
		||||
//           if(counter.decrement()){
 | 
			
		||||
//             avaliableIds.push(item.el.id)
 | 
			
		||||
//             items.removeItem(item);
 | 
			
		||||
//         counter--;
 | 
			
		||||
//         updateCounter();
 | 
			
		||||
//             counterItem.updateContent();
 | 
			
		||||
//           }
 | 
			
		||||
//         })
 | 
			
		||||
//         items.addItem(item);
 | 
			
		||||
//         counterItem.updateContent();
 | 
			
		||||
//       }
 | 
			
		||||
//     } else {
 | 
			
		||||
//       alert("Item name cannot be empty!");
 | 
			
		||||
//     }
 | 
			
		||||
//   } else {
 | 
			
		||||
//     alert("Maxium number of elements!");
 | 
			
		||||
//   }
 | 
			
		||||
// });
 | 
			
		||||
 | 
			
		||||
//       items.addItem(item);
 | 
			
		||||
//       counter++;
 | 
			
		||||
//       updateCounter();
 | 
			
		||||
//       setNextColor();
 | 
			
		||||
//     } else {
 | 
			
		||||
//       alert("Maximum number of items!");
 | 
			
		||||
//     }
 | 
			
		||||
//   }
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// function removeAllItems() {
 | 
			
		||||
//   if (items.itemsLength > 0) {
 | 
			
		||||
// removeAllItemsButtonEl.addEventListener("click", () => {
 | 
			
		||||
//   initializeIdsPool(MAX_ITEMS);
 | 
			
		||||
//   items.clear();
 | 
			
		||||
//     counter = 0;
 | 
			
		||||
//     initalizeIdsPool();
 | 
			
		||||
//     nextColor = avaliableRGBs[0];
 | 
			
		||||
//     updateCounter();
 | 
			
		||||
//   } else {
 | 
			
		||||
//     alert("Nothing to clear!");
 | 
			
		||||
//   }
 | 
			
		||||
// }
 | 
			
		||||
//   counter.clear();
 | 
			
		||||
//   counterItem.updateContent();
 | 
			
		||||
// });
 | 
			
		||||
 | 
			
		||||
// function updateCounter() {
 | 
			
		||||
//   counterEl.textContent = `${counter}/${maxItems}`;
 | 
			
		||||
//   counterEl.animate([
 | 
			
		||||
//     { transform: 'scale(1.25)'},
 | 
			
		||||
//     { transform: 'scale(1.00)'}
 | 
			
		||||
//   ],
 | 
			
		||||
//   {
 | 
			
		||||
//     duration: 500
 | 
			
		||||
//   }
 | 
			
		||||
//   );
 | 
			
		||||
// }
 | 
			
		||||
// // const openCloseMenuEl = document.getElementsByClassName(
 | 
			
		||||
// //   "open-close-menu"
 | 
			
		||||
// // )[0]! as HTMLDivElement;
 | 
			
		||||
 | 
			
		||||
// function setNextColor() {
 | 
			
		||||
//   nextColor = avaliableRGBs[counter % avaliableRGBs.length];
 | 
			
		||||
// }
 | 
			
		||||
// // const itemNameInput = document.querySelector("input")! as HTMLInputElement;
 | 
			
		||||
 | 
			
		||||
// function calculateItemElId(item: MenuItem) {
 | 
			
		||||
//   return +item.el.id.slice(0, item.el.id.indexOf("-"));
 | 
			
		||||
// }
 | 
			
		||||
// // const newItemButtonEl = document.getElementById(
 | 
			
		||||
// //   "newItemButton"
 | 
			
		||||
// // )! as HTMLButtonElement;
 | 
			
		||||
 | 
			
		||||
// const openCloseArrow = document.getElementById("open-close-arrow")!;
 | 
			
		||||
// let open = true;
 | 
			
		||||
// // const removeAllItemsButtonEl = document.getElementById(
 | 
			
		||||
// //   "removeAllItemsButton"
 | 
			
		||||
// // )! as HTMLButtonElement;
 | 
			
		||||
 | 
			
		||||
// function rotateOpenCloseArrow() {
 | 
			
		||||
//   openCloseArrow.animate([
 | 
			
		||||
//     { transform: 'rotate(180deg)' }
 | 
			
		||||
//   ],
 | 
			
		||||
//   {
 | 
			
		||||
//     duration: 500,
 | 
			
		||||
// // // const newItemMenu = document.getElementById('new-item-menu')! as HTMLDivElement;
 | 
			
		||||
 | 
			
		||||
//   }
 | 
			
		||||
//   );
 | 
			
		||||
//   if(open){
 | 
			
		||||
//     menuEl.className = 'decreasing';
 | 
			
		||||
//     open = false;
 | 
			
		||||
//   }else{
 | 
			
		||||
//     menuEl.className = 'normal';
 | 
			
		||||
//     open = true;
 | 
			
		||||
//   }
 | 
			
		||||
// // menuEl.appendChild(items.el);
 | 
			
		||||
// // openCloseMenuEl.appendChild(new OpenCloseArrow().el);
 | 
			
		||||
 | 
			
		||||
// }
 | 
			
		||||
// // const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];
 | 
			
		||||
// // const bgOpacity = 0.5;
 | 
			
		||||
// // let nextColor = avaliableRGBs[0];
 | 
			
		||||
 | 
			
		||||
// function initalizeIdsPool() {
 | 
			
		||||
//   idsPool.length = 0;
 | 
			
		||||
//   for (let i = 0; i < maxItems; i++) {
 | 
			
		||||
//     idsPool.push(i);
 | 
			
		||||
//   }
 | 
			
		||||
// }
 | 
			
		||||
// // const idsPool: number[] = [];
 | 
			
		||||
// // initalizeIdsPool();
 | 
			
		||||
 | 
			
		||||
// newItemButtonEl.addEventListener("click", addNewItem);
 | 
			
		||||
// removeAllItemsButtonEl.addEventListener("click", removeAllItems);
 | 
			
		||||
// openCloseArrow.addEventListener("click", rotateOpenCloseArrow);
 | 
			
		||||
// // function addNewItem() {
 | 
			
		||||
// //   if (itemNameInput.value.length > 0 && itemNameInput.value.length <= 32) {
 | 
			
		||||
// //     if (counter < maxItems && idsPool.length > 0) {
 | 
			
		||||
// //       const item = new MenuItem(
 | 
			
		||||
// //         idsPool.pop()!,
 | 
			
		||||
// //         itemNameInput.value,
 | 
			
		||||
// //         `rgba(${nextColor}, ${bgOpacity})`
 | 
			
		||||
// //       );
 | 
			
		||||
 | 
			
		||||
// //       item.deleteItem.el.addEventListener("click", () => {
 | 
			
		||||
// //         const itemElId = calculateItemElId(item);
 | 
			
		||||
// //         idsPool.push(itemElId);
 | 
			
		||||
// //         setNextColor();
 | 
			
		||||
// //         items.removeItem(item);
 | 
			
		||||
// //         counter--;
 | 
			
		||||
// //         updateCounter();
 | 
			
		||||
// //       });
 | 
			
		||||
 | 
			
		||||
// //       items.addItem(item);
 | 
			
		||||
// //       counter++;
 | 
			
		||||
// //       updateCounter();
 | 
			
		||||
// //       setNextColor();
 | 
			
		||||
// //     } else {
 | 
			
		||||
// //       alert("Maximum number of items!");
 | 
			
		||||
// //     }
 | 
			
		||||
// //   }
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // function removeAllItems() {
 | 
			
		||||
// //   if (items.itemsLength > 0) {
 | 
			
		||||
// //     items.clear();
 | 
			
		||||
// //     counter = 0;
 | 
			
		||||
// //     initalizeIdsPool();
 | 
			
		||||
// //     nextColor = avaliableRGBs[0];
 | 
			
		||||
// //     updateCounter();
 | 
			
		||||
// //   } else {
 | 
			
		||||
// //     alert("Nothing to clear!");
 | 
			
		||||
// //   }
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // function updateCounter() {
 | 
			
		||||
// //   counterEl.textContent = `${counter}/${maxItems}`;
 | 
			
		||||
// //   counterEl.animate([
 | 
			
		||||
// //     { transform: 'scale(1.25)'},
 | 
			
		||||
// //     { transform: 'scale(1.00)'}
 | 
			
		||||
// //   ],
 | 
			
		||||
// //   {
 | 
			
		||||
// //     duration: 500
 | 
			
		||||
// //   }
 | 
			
		||||
// //   );
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // function setNextColor() {
 | 
			
		||||
// //   nextColor = avaliableRGBs[counter % avaliableRGBs.length];
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // function calculateItemElId(item: MenuItem) {
 | 
			
		||||
// //   return +item.el.id.slice(0, item.el.id.indexOf("-"));
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // const openCloseArrow = document.getElementById("open-close-arrow")!;
 | 
			
		||||
// // let open = true;
 | 
			
		||||
 | 
			
		||||
// // function rotateOpenCloseArrow() {
 | 
			
		||||
// //   openCloseArrow.animate([
 | 
			
		||||
// //     { transform: 'rotate(180deg)' }
 | 
			
		||||
// //   ],
 | 
			
		||||
// //   {
 | 
			
		||||
// //     duration: 500,
 | 
			
		||||
 | 
			
		||||
// //   }
 | 
			
		||||
// //   );
 | 
			
		||||
// //   if(open){
 | 
			
		||||
// //     menuEl.className = 'decreasing';
 | 
			
		||||
// //     open = false;
 | 
			
		||||
// //   }else{
 | 
			
		||||
// //     menuEl.className = 'normal';
 | 
			
		||||
// //     open = true;
 | 
			
		||||
// //   }
 | 
			
		||||
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // function initalizeIdsPool() {
 | 
			
		||||
// //   idsPool.length = 0;
 | 
			
		||||
// //   for (let i = 0; i < maxItems; i++) {
 | 
			
		||||
// //     idsPool.push(i);
 | 
			
		||||
// //   }
 | 
			
		||||
// // }
 | 
			
		||||
 | 
			
		||||
// // newItemButtonEl.addEventListener("click", addNewItem);
 | 
			
		||||
// // removeAllItemsButtonEl.addEventListener("click", removeAllItems);
 | 
			
		||||
// // openCloseArrow.addEventListener("click", rotateOpenCloseArrow);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +1,35 @@
 | 
			
		||||
import { Counter } from "../model/counter";
 | 
			
		||||
import { Component } from "./base-component";
 | 
			
		||||
 | 
			
		||||
export class CounterItem extends Component<HTMLElement>{
 | 
			
		||||
    private counter: Counter;
 | 
			
		||||
// import { Component } from "./base-component";
 | 
			
		||||
 | 
			
		||||
    constructor(min: number, max: number){
 | 
			
		||||
        const counterEl = document.createElement('p');
 | 
			
		||||
        counterEl.textContent = `${min}/${max}`;
 | 
			
		||||
        counterEl.className = 'counter-item';
 | 
			
		||||
        super(counterEl);
 | 
			
		||||
        this.counter = new Counter(min, max);
 | 
			
		||||
    }
 | 
			
		||||
// export class CounterItem extends Component<HTMLElement>{
 | 
			
		||||
//     private counter: Counter;
 | 
			
		||||
 | 
			
		||||
    get getCounter(){
 | 
			
		||||
        return this.counter;
 | 
			
		||||
    }
 | 
			
		||||
//     constructor(min: number, max: number){
 | 
			
		||||
//         const counterEl = document.createElement('p');
 | 
			
		||||
//         counterEl.textContent = `${min}/${max}`;
 | 
			
		||||
//         counterEl.className = 'counter-item';
 | 
			
		||||
//         super(counterEl);
 | 
			
		||||
//         this.counter = new Counter(min, max);
 | 
			
		||||
//     }
 | 
			
		||||
 | 
			
		||||
    updateContent(){
 | 
			
		||||
        this.el.textContent = `${Counter.value}/${this.counter.max}`
 | 
			
		||||
        this.animate();
 | 
			
		||||
    }
 | 
			
		||||
//     get getCounter(){
 | 
			
		||||
//         return this.counter;
 | 
			
		||||
//     }
 | 
			
		||||
 | 
			
		||||
    private animate(): void{
 | 
			
		||||
        this.el.animate(
 | 
			
		||||
            [
 | 
			
		||||
                { transform: 'scale(1.25)'},
 | 
			
		||||
                { transform: 'scale(1.00)'}
 | 
			
		||||
            ],
 | 
			
		||||
            {
 | 
			
		||||
                duration: 500
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
//     updateContent(){
 | 
			
		||||
//         this.el.textContent = `${Counter.value}/${this.counter.max}`
 | 
			
		||||
//         this.animate();
 | 
			
		||||
//     }
 | 
			
		||||
 | 
			
		||||
//     private animate(): void{
 | 
			
		||||
//         this.el.animate(
 | 
			
		||||
//             [
 | 
			
		||||
//                 { transform: 'scale(1.25)'},
 | 
			
		||||
//                 { transform: 'scale(1.00)'}
 | 
			
		||||
//             ],
 | 
			
		||||
//             {
 | 
			
		||||
//                 duration: 500
 | 
			
		||||
//             }
 | 
			
		||||
//         );
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
@@ -5,15 +5,35 @@ export class MenuItem extends Component<HTMLLIElement> {
 | 
			
		||||
 | 
			
		||||
    deleteItem: ItemRemoval;
 | 
			
		||||
 | 
			
		||||
    constructor(id: number, value: string, color: string){
 | 
			
		||||
    constructor(id: number, name: string, color: string){
 | 
			
		||||
        const deleteItem = new ItemRemoval(id);
 | 
			
		||||
        const el = document.createElement('li');
 | 
			
		||||
        el.className = 'menu-item';
 | 
			
		||||
        el.id = `${id}-item`;
 | 
			
		||||
        el.textContent = value;
 | 
			
		||||
        el.textContent = name;
 | 
			
		||||
        el.style.backgroundColor = color;
 | 
			
		||||
        el.appendChild(deleteItem.el);
 | 
			
		||||
        super(el);
 | 
			
		||||
        this.deleteItem = deleteItem;
 | 
			
		||||
        this.appearAnimation();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // registerChangeColorListener(){
 | 
			
		||||
    //     this.el.addEventListener('click', () => {
 | 
			
		||||
    //         const actualColorIndex = avaliableRGBs.indexOf(this.el.style.backgroundColor);
 | 
			
		||||
    //         if(actualColorIndex !== -1){
 | 
			
		||||
    //             const color = avaliableRGBs[(actualColorIndex + 1) % avaliableRGBs.length];
 | 
			
		||||
    //             this.el.style.backgroundColor = color;
 | 
			
		||||
    //         }
 | 
			
		||||
    //     });
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    appearAnimation(){
 | 
			
		||||
        this.el.animate(
 | 
			
		||||
            [{ transform: "scale(1.25)" }, { transform: "scale(1.00)" }],
 | 
			
		||||
            {
 | 
			
		||||
              duration: 500,
 | 
			
		||||
            }
 | 
			
		||||
          );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
export class Counter {
 | 
			
		||||
    static value: number;
 | 
			
		||||
    min: number;
 | 
			
		||||
    max: number;
 | 
			
		||||
 | 
			
		||||
    constructor(min: number, max: number){
 | 
			
		||||
        Counter.value = min;
 | 
			
		||||
        this.min = min;
 | 
			
		||||
        this.max = max;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    increment(){
 | 
			
		||||
        if(!this.isMax()){
 | 
			
		||||
            Counter.value++;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    decrement(){
 | 
			
		||||
        if(!this.isMin()){
 | 
			
		||||
            Counter.value--;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clear(){
 | 
			
		||||
        Counter.value = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private isMax(){
 | 
			
		||||
        return this.max === Counter.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private isMin(){
 | 
			
		||||
        return this.min === Counter.value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/model/item-list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/model/item-list.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
import { Item } from "./item";
 | 
			
		||||
import { List } from "./list";
 | 
			
		||||
 | 
			
		||||
export class ItemList implements List<Item> {
 | 
			
		||||
    items: Item[];
 | 
			
		||||
    maximumSize: number;
 | 
			
		||||
 | 
			
		||||
    constructor(maxSize: number){
 | 
			
		||||
        this.items = [];
 | 
			
		||||
        this.maximumSize = maxSize;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add(item: Item){
 | 
			
		||||
        if(this.items.length < this.maximumSize)
 | 
			
		||||
            this.items.push(item);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeById(id: number){
 | 
			
		||||
        const toRemove = this.items.find(e => e.id === id);
 | 
			
		||||
        if(toRemove){
 | 
			
		||||
            this.remove(toRemove);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    remove(item: Item){
 | 
			
		||||
        this.items.splice(this.items.indexOf(item), 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clear(){
 | 
			
		||||
        this.items = [];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/model/list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/model/list.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
export interface List<T> {
 | 
			
		||||
    items: T[];
 | 
			
		||||
    
 | 
			
		||||
    add(item: T): void; 
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,22 @@
 | 
			
		||||
export const avaliableIds: number[] = [];
 | 
			
		||||
export abstract class IdPool {
 | 
			
		||||
  static avaliableIds: number[] = [];
 | 
			
		||||
 | 
			
		||||
export function initializeIdsPool(numberOfElements: number){
 | 
			
		||||
  static initializeIdsPool(numberOfElements: number) {
 | 
			
		||||
    for (let i = 1; i <= numberOfElements; i++) {
 | 
			
		||||
        avaliableIds[i] = i;
 | 
			
		||||
      IdPool.avaliableIds[i] = i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static getAnId() {
 | 
			
		||||
    const id = this.avaliableIds.pop();
 | 
			
		||||
    if (!id) {
 | 
			
		||||
      alert("Maxiumum number of items!");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static addId(id: number){
 | 
			
		||||
    this.avaliableIds.push(id);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/utils/light-dark-mode.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/utils/light-dark-mode.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
type mode = 'dark' | 'light';
 | 
			
		||||
 | 
			
		||||
export abstract class LightDarkMode{
 | 
			
		||||
    static currentMode: mode;
 | 
			
		||||
 | 
			
		||||
    static changeMode(){
 | 
			
		||||
        if(this.currentMode == 'light'){
 | 
			
		||||
            this.currentMode = 'dark';
 | 
			
		||||
        }else{
 | 
			
		||||
            this.currentMode = 'light';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,2 +1 @@
 | 
			
		||||
export const avaliableRGBs = ["255, 0, 0", "0, 255, 0", "0, 0, 255"];
 | 
			
		||||
 | 
			
		||||
export const avaliableRGBs = ["rgba(255, 0, 0, 0.5)", "rgba(0, 255, 0, 0.5)", "rgba(0, 0, 255, 0.5)", "rgba(255, 255, 0, 0.5)"];
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								static/moon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/moon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 38 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								static/sun.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/sun.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 25 KiB  | 
		Reference in New Issue
	
	Block a user