๐Ÿšจ Added prettier and fixed errors

main
Nichole Mattera 1 year ago
parent 8a700a0442
commit 4b86d48217
  1. 1
      .nvmrc
  2. 2
      .prettierignore
  3. 12
      .prettierrc.json
  4. 6
      README.md
  5. 4
      babel.config.js
  6. 11
      jsconfig.json
  7. 8
      package-lock.json
  8. 23
      package.json
  9. 36
      public/index.html
  10. 2
      public/manifest.json
  11. 66
      src/App.vue
  12. 16
      src/components/AddIcon.vue
  13. 14
      src/components/CodeIcon.vue
  14. 14
      src/components/DownloadIcon.vue
  15. 24
      src/components/FormField.vue
  16. 95
      src/components/IconButton.vue
  17. 14
      src/components/RemoveIcon.vue
  18. 143
      src/image-preview/ImagePreview.vue
  19. 59
      src/image-preview/composables/useRendering.js
  20. 239
      src/side-bar/SideBar.vue
  21. 99
      src/side-bar/components/FlagSettings.vue
  22. 42
      src/side-bar/components/ImageSettings.vue
  23. 170
      src/side-bar/composables/useFlagTypes.js

@ -0,0 +1 @@
lts/gallium

@ -0,0 +1,2 @@
dist
node_modules

@ -0,0 +1,12 @@
{
"arrowParens": "always",
"bracketSameLine": true,
"bracketSpacing": true,
"printWidth": 80,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false,
"vueIndentScriptAndStyle": true
}

@ -1,23 +1,27 @@
# Pride Background Generator
A small single page app for generating custom pride backgrounds. The inspiration for this work is based off a background that I used for awhile that had the Trans, Lesbian, and Pride flags rotated 45 degrees. ([Source](https://www.reddit.com/r/traaaaaaannnnnnnnnns/comments/depebm/i_made_a_4k_wallpaper_that_has_the_trans_lesbian/)) The purpose of this app is to allow anyone to create their own background with any arrangement of flags.
A small single page app for generating custom pride backgrounds. The inspiration for this work is based off a background that I used for awhile that had the Trans, Lesbian, and Pride flags rotated 45 degrees. ([Source](https://www.reddit.com/r/traaaaaaannnnnnnnnns/comments/depebm/i_made_a_4k_wallpaper_that_has_the_trans_lesbian/)) The purpose of this app is to allow anyone to create their own background with any arrangement of flags.
## Project setup
```
npm ci
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```

@ -1,5 +1,3 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
],
presets: ['@vue/cli-plugin-babel/preset'],
}

@ -5,15 +5,8 @@
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
"@/*": ["src/*"]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
}
}

8
package-lock.json generated

@ -7,6 +7,7 @@
"": {
"name": "pride-background",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13"
@ -18,7 +19,8 @@
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"prettier": "2.5.1"
}
},
"node_modules/@ampproject/remapping": {
@ -8925,7 +8927,6 @@
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
"integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
"dev": true,
"optional": true,
"bin": {
"prettier": "bin-prettier.js"
},
@ -18073,8 +18074,7 @@
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
"integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
"dev": true,
"optional": true
"dev": true
},
"pretty-error": {
"version": "4.0.0",

@ -25,7 +25,8 @@
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"prettier": "2.5.1"
},
"eslintConfig": {
"root": true,
@ -40,13 +41,19 @@
"parser": "@babel/eslint-parser"
},
"rules": {
"comma-dangle": ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline"
}],
"semi": ["error", "never"]
"comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline"
}
],
"semi": [
"error",
"never"
]
}
},
"browserslist": [

@ -1,24 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="manifest" href="<%= BASE_URL %>manifest.json">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link rel="manifest" href="<%= BASE_URL %>manifest.json" />
<title>Pride Background Generator</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&family=Roboto:wght@400;700&display=swap');
body, html {
body,
html {
background: #212121;
color: #FFF;
color: #fff;
font-family: 'Open Sans', Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6 {
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Roboto, Arial, Helvetica, sans-serif;
}
@ -26,22 +32,26 @@
display: block;
}
input:focus, input:active {
border-color: #EC407A;
input:focus,
input:active {
border-color: #ec407a;
outline: none;
}
input {
background: #171717;
border: 1px solid #0D0D0D;
border: 1px solid #0d0d0d;
border-radius: 3px;
color: #FFF;
color: #fff;
}
</style>
</head>
<body>
<noscript>
<strong>We're sorry but Pride Background Generator doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong
>We're sorry but Pride Background Generator doesn't work properly
without JavaScript enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
</body>

@ -24,4 +24,4 @@
}
],
"start_url": "/index.html"
}
}

@ -1,50 +1,46 @@
<template>
<div class="app">
<SideBar
@change="onSettingChanged"
@save="onSave" />
<ImagePreview
:settings="settings"
@ready="onReady" />
<SideBar @change="onSettingChanged" @save="onSave" />
<ImagePreview :settings="settings" @ready="onReady" />
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { reactive, ref } from 'vue'
import SideBar from './side-bar/SideBar.vue'
import ImagePreview from './image-preview/ImagePreview.vue'
import SideBar from './side-bar/SideBar.vue'
import ImagePreview from './image-preview/ImagePreview.vue'
const settings = reactive({
width: 0,
height: 0,
flags: [],
})
const settings = reactive({
width: 0,
height: 0,
flags: [],
})
function onSettingChanged(value) {
settings.width = value.width
settings.height = value.height
settings.flags = value.flags
}
function onSettingChanged(value) {
settings.width = value.width
settings.height = value.height
settings.flags = value.flags
}
const canvas = ref(null)
function onReady(c) {
canvas.value = c
}
const canvas = ref(null)
function onReady(c) {
canvas.value = c
}
function onSave() {
const anchor = document.createElement('a')
anchor.download = `pride-${Date.now()}.png`
anchor.href = canvas.value.toDataURL('image/png')
anchor.click()
}
function onSave() {
const anchor = document.createElement('a')
anchor.download = `pride-${Date.now()}.png`
anchor.href = canvas.value.toDataURL('image/png')
anchor.click()
}
</script>
<style scoped>
.app {
align-items: stretch;
display: flex;
height: 100vh;
width: 100vw;
}
.app {
align-items: stretch;
display: flex;
height: 100vh;
width: 100vw;
}
</style>

@ -8,7 +8,7 @@
:width="width">
<!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. -->
<title id="title">{{ label }}</title>
<path
<path
d="M432 256C432 269.3 421.3 280 408 280h-160v160c0 13.25-10.75 24.01-24 24.01S200 453.3 200 440v-160h-160c-13.25 0-24-10.74-24-23.99C16 242.8 26.75 232 40 232h160v-160c0-13.25 10.75-23.99 24-23.99S248 58.75 248 72v160h160C421.3 232 432 242.8 432 256z"
:fill="color"
role="presentation" />
@ -16,12 +16,12 @@
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
color: String,
height: String,
label: String,
width: String,
})
defineProps({
color: String,
height: String,
label: String,
width: String,
})
</script>

@ -16,12 +16,12 @@
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
color: String,
height: String,
label: String,
width: String,
})
defineProps({
color: String,
height: String,
label: String,
width: String,
})
</script>

@ -16,12 +16,12 @@
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
color: String,
height: String,
label: String,
width: String,
})
defineProps({
color: String,
height: String,
label: String,
width: String,
})
</script>

@ -8,21 +8,21 @@
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
field: String,
label: String,
})
defineProps({
field: String,
label: String,
})
</script>
<style scoped>
.field {
margin: 0 0 16px;
}
.field {
margin: 0 0 16px;
}
.field label {
margin-bottom: 8px;
font-weight: 600;
}
.field label {
margin-bottom: 8px;
font-weight: 600;
}
</style>

@ -1,57 +1,60 @@
<template>
<button
:aria-label="label"
:class="type"
:title="label">
<button :aria-label="label" :class="type" :title="label">
<slot></slot>
</button>
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
label: String,
type: String,
})
defineProps({
label: String,
type: String,
})
</script>
<style scoped>
button {
align-items: center;
border-radius: 3px;
background: transparent;
display: flex;
height: 28px;
justify-content: center;
width: 28px;
}
button:focus, button:active, button:hover {
outline: none;
}
button:hover {
cursor: pointer;
}
button.primary {
background: #EC407A;
border: 2px solid #EC407A;
color: #FFF;
}
button.primary:focus, button.primary:active, button.primary:hover {
background: #F389AD;
border-color: #F389AD;
}
button.secondary {
border: 2px solid #FFF;
color: #FFF;
}
button.secondary:focus, button.secondary:active, button.secondary:hover {
border-color: #EC407A;
}
button {
align-items: center;
border-radius: 3px;
background: transparent;
display: flex;
height: 28px;
justify-content: center;
width: 28px;
}
button:focus,
button:active,
button:hover {
outline: none;
}
button:hover {
cursor: pointer;
}
button.primary {
background: #ec407a;
border: 2px solid #ec407a;
color: #fff;
}
button.primary:focus,
button.primary:active,
button.primary:hover {
background: #f389ad;
border-color: #f389ad;
}
button.secondary {
border: 2px solid #fff;
color: #fff;
}
button.secondary:focus,
button.secondary:active,
button.secondary:hover {
border-color: #ec407a;
}
</style>

@ -16,12 +16,12 @@
</template>
<script setup>
import { defineProps } from 'vue'
import { defineProps } from 'vue'
defineProps({
color: String,
height: String,
label: String,
width: String,
})
defineProps({
color: String,
height: String,
label: String,
width: String,
})
</script>

@ -1,7 +1,5 @@
<template>
<div
class="container"
ref="container">
<div class="container" ref="container">
<canvas
:height="settings.height"
ref="canvas"
@ -11,82 +9,97 @@
</template>
<script setup>
import { computed, defineEmits, defineProps, onMounted, reactive, ref, watch } from 'vue'
import useRendering from './composables/useRendering'
import {
computed,
defineEmits,
defineProps,
onMounted,
reactive,
ref,
watch,
} from 'vue'
import useRendering from './composables/useRendering'
const props = defineProps({
settings: Object,
})
const props = defineProps({
settings: Object,
})
const emit = defineEmits(['ready'])
const emit = defineEmits(['ready'])
const container = ref(null)
const height = ref(0)
const width = ref(0)
const resizeObserver = reactive(new ResizeObserver(() => {
if (!container.value) return
height.value = container.value.clientHeight
width.value = container.value.clientWidth
}))
const container = ref(null)
const height = ref(0)
const width = ref(0)
const resizeObserver = reactive(
new ResizeObserver(() => {
if (!container.value) return
height.value = container.value.clientHeight
width.value = container.value.clientWidth
})
)
// Handles sizing of the canvas
const canvasStyle = computed(() => {
if (props.settings.height <= height.value && props.settings.width <= width.value) {
return {
height: `${props.settings.height}px`,
width: `${props.settings.width}px`,
// Handles sizing of the canvas
const canvasStyle = computed(() => {
if (
props.settings.height <= height.value &&
props.settings.width <= width.value
) {
return {
height: `${props.settings.height}px`,
width: `${props.settings.width}px`,
}
}
}
const heightRatio = height.value / props.settings.height
const widthRatio = width.value / props.settings.width
const bestRatio = Math.min(widthRatio, heightRatio)
const heightRatio = height.value / props.settings.height
const widthRatio = width.value / props.settings.width
const bestRatio = Math.min(widthRatio, heightRatio)
return {
height: `${props.settings.height * bestRatio}px`,
width: `${props.settings.width * bestRatio}px`,
}
})
return {
height: `${props.settings.height * bestRatio}px`,
width: `${props.settings.width * bestRatio}px`,
}
})
const canvas = ref(null)
let context = ref(null)
const canvas = ref(null)
let context = ref(null)
// Main rendering routine.
const renderPreview = useRendering(context)
// Main rendering routine.
const renderPreview = useRendering(context)
// Render on canvas resize.
const canvasResizeObserver = reactive(
new ResizeObserver(() => {
if (!canvas.value) return
renderPreview(props.settings)
})
)
// Render on canvas resize.
const canvasResizeObserver = reactive(new ResizeObserver(() => {
if (!canvas.value) return
renderPreview(props.settings)
}))
// Render on setting changed.
watch(props.settings, (newSettings) => {
renderPreview(newSettings)
})
// Render on setting changed.
watch(props.settings, (newSettings) => {
renderPreview(newSettings)
})
onMounted(() => {
resizeObserver.observe(container.value)
onMounted(() => {
resizeObserver.observe(container.value)
// Register observer, Get the context, and emit canvas to parent.
canvasResizeObserver.observe(canvas.value)
context.value = canvas.value.getContext('2d')
emit('ready', canvas.value)
})
// Register observer, Get the context, and emit canvas to parent.
canvasResizeObserver.observe(canvas.value)
context.value = canvas.value.getContext('2d')
emit('ready', canvas.value)
})
</script>
<style scoped>
.container {
align-items: center;
background: #191919;
display: flex;
flex: 1 1 auto;
justify-content: center;
overflow: hidden;
}
.container {
align-items: center;
background: #191919;
display: flex;
flex: 1 1 auto;
justify-content: center;
overflow: hidden;
}
.container canvas {
background: #000;
box-shadow: 8px 8px 16px 0 rgba(0,0,0,0.5);
}
.container canvas {
background: #000;
box-shadow: 8px 8px 16px 0 rgba(0, 0, 0, 0.5);
}
</style>

@ -2,9 +2,12 @@ export default function useRendering(context) {
return (settings) => {
if (!context.value) return
const size = Math.sqrt(Math.pow(settings.width, 2) + Math.pow(settings.height, 2))
const flagHeight = size / settings.flags.filter((flag) => flag.id !== '').length
const size = Math.sqrt(
Math.pow(settings.width, 2) + Math.pow(settings.height, 2)
)
const flagHeight =
size / settings.flags.filter((flag) => flag.id !== '').length
const tempCanvas = document.createElement('canvas')
tempCanvas.height = size
tempCanvas.width = size
@ -19,10 +22,20 @@ export default function useRendering(context) {
tempContext.fillRect(0, flagHeight * flagIndex, size, barHeight * 2)
tempContext.fillStyle = flag.bars[1]
tempContext.fillRect(0, (flagHeight * flagIndex) + (barHeight * 2), size, barHeight)
tempContext.fillRect(
0,
flagHeight * flagIndex + barHeight * 2,
size,
barHeight
)
tempContext.fillStyle = flag.bars[2]
tempContext.fillRect(0, (flagHeight * flagIndex) + (barHeight * 3), size, barHeight * 2)
tempContext.fillRect(
0,
flagHeight * flagIndex + barHeight * 3,
size,
barHeight * 2
)
} else if (flag.id === 'demisexual') {
const barHeight = flagHeight / 6
@ -30,16 +43,29 @@ export default function useRendering(context) {
tempContext.fillRect(0, flagHeight * flagIndex, size, barHeight * 2.5)
tempContext.fillStyle = flag.bars[2]
tempContext.fillRect(0, (flagHeight * flagIndex) + (barHeight * 2.5), size, barHeight)
tempContext.fillRect(
0,
flagHeight * flagIndex + barHeight * 2.5,
size,
barHeight
)
tempContext.fillStyle = flag.bars[3]
tempContext.fillRect(0, (flagHeight * flagIndex) + (barHeight * 3.5), size, barHeight * 2.5)
tempContext.fillRect(
0,
flagHeight * flagIndex + barHeight * 3.5,
size,
barHeight * 2.5
)
tempContext.fillStyle = flag.bars[0]
tempContext.beginPath()
tempContext.moveTo(0, flagHeight * flagIndex)
tempContext.lineTo(flagHeight * 0.5, (flagHeight * flagIndex) + (barHeight * 3))
tempContext.lineTo(0, (flagHeight * flagIndex) + flagHeight)
tempContext.lineTo(
flagHeight * 0.5,
flagHeight * flagIndex + barHeight * 3
)
tempContext.lineTo(0, flagHeight * flagIndex + flagHeight)
tempContext.fill()
} else if (flag.id === 'intersex') {
tempContext.fillStyle = flag.bars[0]
@ -49,7 +75,13 @@ export default function useRendering(context) {
tempContext.strokeStyle = flag.bars[1]
tempContext.fillStyle = flag.bars[2]
tempContext.lineWidth = flagHeight * 0.1
tempContext.arc(size / 2, (flagHeight * flagIndex) + (flagHeight / 2), flagHeight * 0.1875, 0, 2 * Math.PI)
tempContext.arc(
size / 2,
flagHeight * flagIndex + flagHeight / 2,
flagHeight * 0.1875,
0,
2 * Math.PI
)
tempContext.fill()
tempContext.stroke()
tempContext.restore()
@ -57,7 +89,12 @@ export default function useRendering(context) {
const barHeight = flagHeight / flag.bars.length
flag.bars.forEach((bar, barIndex) => {
tempContext.fillStyle = bar
tempContext.fillRect(0, (flagHeight * flagIndex) + (barHeight * barIndex), size, barHeight)
tempContext.fillRect(
0,
flagHeight * flagIndex + barHeight * barIndex,
size,
barHeight
)
})
}
})

@ -2,18 +2,13 @@
<div class="sidebar">
<h1>
<span>Settings</span>
<icon-button
label="View source code"
type="secondary"
@click="viewCode">
<icon-button label="View source code" type="secondary" @click="viewCode">
<code-icon
color="#FFF"
height="16px"
label="View source code"
width="16px" />
</icon-button>
color="#FFF"
height="16px"
label="View source code"
width="16px" />
</icon-button>
</h1>
<div class="body">
@ -21,17 +16,8 @@
<h2>
<span>Flags</span>
<icon-button
label="Add flag"
type="secondary"
@click="addFlag">
<add-icon
color="#FFF"
height="16px"
label="Add flag"
width="16px" />
<icon-button label="Add flag" type="secondary" @click="addFlag">
<add-icon color="#FFF" height="16px" label="Add flag" width="16px" />
</icon-button>
</h2>
@ -51,125 +37,126 @@
label="Save background"
type="primary"
@click="$emit('save')">
<download-icon
color="#FFF"
height="16px"
label="Save background"
width="16px" />
</icon-button>
</div>
</div>
</template>
<script setup>
import { defineEmits, reactive } from 'vue'
import AddIcon from '../components/AddIcon.vue'
import CodeIcon from '../components/CodeIcon.vue'
import DownloadIcon from '../components/DownloadIcon.vue'
import IconButton from '../components/IconButton.vue'
import FlagSettings from './components/FlagSettings.vue'
import ImageSettings from './components/ImageSettings.vue'
const emit = defineEmits(['change', 'save'])
function viewCode() {
window.open('https://git.nicholemattera.com/NicholeMattera/Pride-Background-Generator', '_blank')
}
const settings = reactive({
width: 0,
height: 0,
flags: [],
})
emit('change', settings)
function onFieldChanged({ field, value }) {
settings[field] = value
emit('change', settings)
}
function addFlag() {
settings.flags.push({
id: '',
label: '',
bars: [],
import { defineEmits, reactive } from 'vue'
import AddIcon from '../components/AddIcon.vue'
import CodeIcon from '../components/CodeIcon.vue'
import DownloadIcon from '../components/DownloadIcon.vue'
import IconButton from '../components/IconButton.vue'
import FlagSettings from './components/FlagSettings.vue'
import ImageSettings from './components/ImageSettings.vue'
const emit = defineEmits(['change', 'save'])
function viewCode() {
window.open(
'https://git.nicholemattera.com/NicholeMattera/Pride-Background-Generator',
'_blank'
)
}
const settings = reactive({
width: 0,
height: 0,
flags: [],
})
emit('change', settings)
}
function changedFlag({ index, value }) {
settings.flags[index] = value
emit('change', settings)
}
function removeFlag(index) {
settings.flags = settings.flags.filter((e, i) => i != index)
emit('change', settings)
}
function onFieldChanged({ field, value }) {
settings[field] = value
emit('change', settings)
}
function addFlag() {
settings.flags.push({
id: '',
label: '',
bars: [],
})
emit('change', settings)
}
function changedFlag({ index, value }) {
settings.flags[index] = value
emit('change', settings)
}
function removeFlag(index) {
settings.flags = settings.flags.filter((e, i) => i != index)
emit('change', settings)
}
</script>
<style scoped>
.sidebar {
box-shadow: 8px 0 16px 0 rgba(0,0,0,0.5);
display: flex;
flex: 0 0 250px;
flex-direction: column;
z-index: 1;
}
h1 {
align-items: center;
background: #212121;
border-bottom: 1px solid #C0C0C0;
display: flex;
margin: 0;
padding: 8px;
}
h1 span {
flex: 1 1 auto;
}
.body {
flex: 1 1 auto;
padding: 8px;
overflow-y: auto;
}
h2 {
display: flex;
margin: 24px 0 16px;
}
h2 span {
flex: 1 1 auto;
}
.field {
margin: 16px 0 0;
}
.field label {
margin-bottom: 8px;
font-weight: 600;
}
.field input {
box-sizing: border-box;
width: 100%;
}
.flags {
padding: 0 8px;
}
.footer {
border-top: 1px solid #C0C0C0;
display: flex;
flex-direction: row-reverse;
padding: 8px;
}
.sidebar {
box-shadow: 8px 0 16px 0 rgba(0, 0, 0, 0.5);
display: flex;
flex: 0 0 250px;
flex-direction: column;
z-index: 1;
}
h1 {
align-items: center;
background: #212121;
border-bottom: 1px solid #c0c0c0;
display: flex;
margin: 0;
padding: 8px;
}
h1 span {
flex: 1 1 auto;
}
.body {
flex: 1 1 auto;
padding: 8px;
overflow-y: auto;
}
h2 {
display: flex;
margin: 24px 0 16px;
}
h2 span {
flex: 1 1 auto;
}
.field {
margin: 16px 0 0;
}
.field label {
margin-bottom: 8px;
font-weight: 600;
}
.field input {
box-sizing: border-box;
width: 100%;
}
.flags {
padding: 0 8px;
}
.footer {
border-top: 1px solid #c0c0c0;
display: flex;
flex-direction: row-reverse;
padding: 8px;
}
</style>

@ -1,9 +1,7 @@
<template>
<div class="flag">
<h3>
<span>
Flag #{{ index + 1 }}
</span>
<span> Flag #{{ index + 1 }} </span>
<icon-button
label="Remove Flag"
type="secondary"
@ -17,23 +15,14 @@
</h3>
<div class="body">
<form-field
:field="`flag-type-${index}`"
label="Flag Type">
<select
:id="`flag-type-${index}`"
@change="flagSelected">
<option
disabled
selected
value="">
Select a flag type
</option>
<form-field :field="`flag-type-${index}`" label="Flag Type">
<select :id="`flag-type-${index}`" @change="flagSelected">
<option disabled selected value="">Select a flag type</option>
<option
v-for="flagType in flagTypes"
:key="flagType.id"
:value="flagType.id">
{{ flagType.label }}
{{ flagType.label }}
</option>
</select>
</form-field>
@ -42,53 +31,55 @@
</template>
<script setup>
import { defineEmits, defineProps } from 'vue'
import FormField from '../../components/FormField.vue'
import IconButton from '../../components/IconButton.vue'
import RemoveIcon from '../../components/RemoveIcon.vue'
import useFlagTypes from '../composables/useFlagTypes'
import { defineEmits, defineProps } from 'vue'
import FormField from '../../components/FormField.vue'
import IconButton from '../../components/IconButton.vue'
import RemoveIcon from '../../components/RemoveIcon.vue'
import useFlagTypes from '../composables/useFlagTypes'
const props = defineProps({
index: Number,
})
const props = defineProps({
index: Number,
})
const emit = defineEmits(['change', 'remove'])
const emit = defineEmits(['change', 'remove'])
const flagTypes = useFlagTypes()
const flagTypes = useFlagTypes()
function flagSelected(event) {
emit('change', {
index: props.index,
value: flagTypes.value.find((flagType) => flagType.id === event.target.value),
})
}
function flagSelected(event) {
emit('change', {
index: props.index,
value: flagTypes.value.find(
(flagType) => flagType.id === event.target.value
),
})
}
</script>
<style scoped>
h3 {
align-items: center;
border: 1px solid #FFF;
border-radius: 3px 3px 0 0;
display: flex;
margin-bottom: 0;
padding: 8px;
}
h3 {
align-items: center;
border: 1px solid #fff;
border-radius: 3px 3px 0 0;
display: flex;
margin-bottom: 0;
padding: 8px;
}
h3 span {
flex: 1 1 auto;
}
h3 span {
flex: 1 1 auto;
}
.body {
border-color: #FFF;
border-style: none solid solid solid;
border-width: 0 1px 1px 1px;
border-radius: 0 0 3px 3px;
.body {
border-color: #fff;
border-style: none solid solid solid;
border-width: 0 1px 1px 1px;
border-radius: 0 0 3px 3px;
padding: 8px;
}
padding: 8px;
}
select {
box-sizing: border-box;
width: 100%;
}
select {
box-sizing: border-box;
width: 100%;
}
</style>

@ -1,8 +1,6 @@
<template>
<div>
<form-field
field="width"
label="Width">
<form-field field="width" label="Width">
<input
type="number"
id="width"
@ -10,9 +8,7 @@
@change="onFieldChanged('width', $event.target.value)" />
</form-field>
<form-field
field="height"
label="Height">
<form-field field="height" label="Height">
<input
type="number"
id="height"
@ -23,27 +19,27 @@
</template>
<script setup>
import { ref, defineEmits } from 'vue'
import FormField from '../../components/FormField.vue'
import { ref, defineEmits } from 'vue'
import FormField from '../../components/FormField.vue'
const emit = defineEmits(['change'])
function onFieldChanged(field, value) {
emit('change', {
field,
value: typeof value === 'number' ? value : parseInt(value),
})
}
const emit = defineEmits(['change'])
function onFieldChanged(field, value) {
emit('change', {
field,
value: typeof value === 'number' ? value : parseInt(value),
})
}
const width = ref(window.screen.width)
onFieldChanged('width', width.value)
const width = ref(window.screen.width)
onFieldChanged('width', width.value)
const height = ref(window.screen.height)
onFieldChanged('height', height.value)
const height = ref(window.screen.height)
onFieldChanged('height', height.value)
</script>
<style scoped>
input {
box-sizing: border-box;
width: 100%;
}
input {
box-sizing: border-box;
width: 100%;
}
</style>

@ -5,87 +5,42 @@ export default function useFlagTypes() {
{
id: 'abrosexual',
label: 'Abrosexual',
bars: [
'#77CC94',
'#B5E5CC',
'#FCFEFF',
'#E997B5',
'#DC406C',
],
bars: ['#77CC94', '#B5E5CC', '#FCFEFF', '#E997B5', '#DC406C'],
},
{
id: 'aceflux',
label: 'Aceflux',
bars: [
'#C82067',
'#BCC5C6',
'#EC6D87',
'#91479B',
'#800080',
],
bars: ['#C82067', '#BCC5C6', '#EC6D87', '#91479B', '#800080'],
},
{
id: 'agender',
label: 'Agender',
bars: [