diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/color_input/color_input.vue | 8 | ||||
| -rw-r--r-- | src/components/opacity_input/opacity_input.vue | 6 | ||||
| -rw-r--r-- | src/components/shadow_control/shadow_control.js | 76 | ||||
| -rw-r--r-- | src/components/shadow_control/shadow_control.vue | 249 | ||||
| -rw-r--r-- | src/components/style_switcher/style_switcher.js | 18 | ||||
| -rw-r--r-- | src/components/style_switcher/style_switcher.vue | 11 | ||||
| -rw-r--r-- | src/services/style_setter/style_setter.js | 29 |
7 files changed, 389 insertions, 8 deletions
diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue index 60a62fa8..ea9fb3c4 100644 --- a/src/components/color_input/color_input.vue +++ b/src/components/color_input/color_input.vue @@ -1,5 +1,5 @@ <template> -<div class="color-control" :class="{ disabled: !present }"> +<div class="color-control" :class="{ disabled: !present || disabled }"> <label :for="name" class="label"> {{label}} </label> @@ -17,7 +17,7 @@ class="color-input" type="color" :value="value || fallback" - :disabled="!present" + :disabled="!present || disabled" @input="$emit('input', $event.target.value)" > <input @@ -25,7 +25,7 @@ class="text-input" type="text" :value="value || fallback" - :disabled="!present" + :disabled="!present || disabled" @input="$emit('input', $event.target.value)" > </div> @@ -34,7 +34,7 @@ <script> export default { props: [ - 'name', 'label', 'value', 'fallback' + 'name', 'label', 'value', 'fallback', 'disabled' ], computed: { present () { diff --git a/src/components/opacity_input/opacity_input.vue b/src/components/opacity_input/opacity_input.vue index 4057dcca..91c4f5e9 100644 --- a/src/components/opacity_input/opacity_input.vue +++ b/src/components/opacity_input/opacity_input.vue @@ -1,5 +1,5 @@ <template> -<div class="opacity-control" :class="{ disabled: !present }"> +<div class="opacity-control" :class="{ disabled: !present || disabled }"> <label :for="name" class="label"> {{$t('settings.opacity')}} </label> @@ -17,7 +17,7 @@ class="input-number" type="number" :value="value || fallback" - :disabled="!present" + :disabled="!present || disabled" @input="$emit('input', $event.target.value)" max="1" min="0" @@ -28,7 +28,7 @@ <script> export default { props: [ - 'name', 'value', 'fallback' + 'name', 'value', 'fallback', 'disabled' ], computed: { present () { diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js new file mode 100644 index 00000000..c357581d --- /dev/null +++ b/src/components/shadow_control/shadow_control.js @@ -0,0 +1,76 @@ +import ColorInput from '../color_input/color_input.vue' +import OpacityInput from '../opacity_input/opacity_input.vue' +import StyleSetter from '../../services/style_setter/style_setter.js' +import { hex2rgb } from '../../services/color_convert/color_convert.js' +import { set } from 'vue' + +export default { + props: [ + 'value', 'fallback' + ], + data () { + return { + selectedId: 0, + cValue: this.value || this.fallback + } + }, + components: { + ColorInput, + OpacityInput + }, + methods: { + add () { + this.cValue.push(Object.assign({}, this.selected)) + this.selectedId = this.cValue.length - 1 + }, + del () { + this.cValue.splice(this.selectedId, 1) + this.selectedId = this.cValue.length === 0 ? undefined : this.selectedId - 1 + }, + moveUp () { + const movable = this.cValue.splice(this.selectedId, 1)[0] + this.cValue.splice(this.selectedId - 1, 0, movable) + this.selectedId -= 1 + }, + moveDn () { + const movable = this.cValue.splice(this.selectedId, 1)[0] + this.cValue.splice(this.selectedId + 1, 0, movable) + this.selectedId += 1 + } + }, + computed: { + selected () { + return this.cValue[this.selectedId] || { + x: 0, + y: 0, + blur: 0, + spread: 0, + inset: false, + color: '#000000', + alpha: 1 + } + }, + moveUpValid () { + return this.selectedId > 0 + }, + moveDnValid () { + return this.selectedId < this.cValue.length - 1 + }, + present () { + return typeof this.cValue[this.selectedId] !== 'undefined' && + !this.usingFallback + }, + usingFallback () { + return typeof this.value === 'undefined' + }, + rgb () { + return hex2rgb(this.selected.color) + }, + style () { + console.log(StyleSetter.generateShadow(this.cValue)) + return { + boxShadow: StyleSetter.generateShadow(this.cValue) + } + } + } +} diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue new file mode 100644 index 00000000..24439449 --- /dev/null +++ b/src/components/shadow_control/shadow_control.vue @@ -0,0 +1,249 @@ +<template> +<div class="shadow-control" :class="{ disabled: !present }"> + <div class="shadow-preview-container"> + <div :disabled="!present" class="y-shift-control"> + <input + v-model="selected.y" + :disabled="!present" + class="input-number" + type="number"> + <div class="wrap"> + <input + v-model="selected.y" + :disabled="!present" + class="input-range" + type="range" + max="20" + min="-20"> + </div> + </div> + <div class="preview-window"> + <div class="preview-block" :style="style"></div> + </div> + <div :disabled="!present" class="x-shift-control"> + <input + v-model="selected.x" + :disabled="!present" + class="input-number" + type="number"> + <div class="wrap"> + <input + v-model="selected.x" + :disabled="!present" + class="input-range" + type="range" + max="20" + min="-20"> + </div> + </div> + </div> + + <div class="shadow-tweak"> + <div :disabled="usingFallback" class="id-control"> + <label for="id" class="label"> + Shadow id + </label> + <input + v-model="selectedId" + :disabled="usingFallback" + class="input-number" + type="number" + min="0" + :max="cValue.length - 1"> + <button class="btn btn-default" :disabled="!present" @click="del"> + <i class="icon-cancel"/> + </button> + <button class="btn btn-default" :disabled="!moveUpValid" @click="moveUp"> + <i class="icon-up-open"/> + </button> + <button class="btn btn-default" :disabled="!moveDnValid" @click="moveDn"> + <i class="icon-down-open"/> + </button> + <button class="btn btn-default" @click="add"> + <i class="icon-plus"/> + </button> + </div> + <div :disabled="!present" class="inset-control"> + <label for="inset" class="label"> + Inset + </label> + <input + v-model="selected.inset" + :disabled="!present" + name="inset" + id="inset" + class="input-inset" + type="checkbox"> + <label class="checkbox-label" for="inset"></label> + </div> + <div :disabled="!present" class="blur-control"> + <label for="spread" class="label"> + Blur + </label> + <input + v-model="selected.blur" + :disabled="!present" + name="blur" + id="blur" + class="input-range" + type="range" + max="20" + min="0"> + <input + v-model="selected.blur" + :disabled="!present" + class="input-number" + type="number" + min="0"> + </div> + <div :disabled="!present" class="spread-control"> + <label for="spread" class="label"> + Spread + </label> + <input + v-model="selected.spread" + :disabled="!present" + name="spread" + id="spread" + class="input-range" + type="range" + max="20" + min="-20"> + <input + v-model="selected.spread" + :disabled="!present" + class="input-number" + type="number"> + </div> + <ColorInput + v-model="selected.color" + :disabled="!present" + label="Color" + name="shadow"/> + <OpacityInput + v-model="selected.alpha" + :disabled="!present"/> + </div> +</div> +</template> + +<script src="./shadow_control.js" ></script> + +<style lang="scss"> +@import '../../_variables.scss'; +.shadow-control { + display: flex; + flex-wrap: wrap; + justify-content: center; + + .shadow-preview-container { + flex: 0; + display: flex; + flex-wrap: wrap; + + $side: 15em; + + input[type=number] { + width: 5em; + min-width: 2em; + } + .x-shift-control, + .y-shift-control { + display: flex; + flex: 0; + + &[disabled=disabled] *{ + opacity: .5 + } + + } + + .x-shift-control { + align-items: flex-start; + } + + .x-shift-control .wrap, + input[type=range] { + margin: 0; + width: $side; + height: 2em; + } + .y-shift-control { + flex-direction: column; + align-items: flex-end; + .wrap { + width: 2em; + height: $side; + } + input[type=range] { + transform-origin: 1em 1em; + transform: rotate(90deg); + } + } + .preview-window { + flex: 1; + background-color: white; + display: flex; + align-items: center; + justify-content: center; + background-image: + linear-gradient(45deg, #808080 25%, transparent 25%), + linear-gradient(-45deg, #808080 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #808080 75%), + linear-gradient(-45deg, transparent 75%, #808080 75%); + background-size: 20px 20px; + background-position:0 0, 0 10px, 10px -10px, -10px 0; + + border-radius: $fallback--inputRadius; + border-radius: var(--inputRadius, $fallback--inputRadius); + + .preview-block { + width: 33%; + height: 33%; + background-color: $fallback--bg; + background-color: var(--bg, $fallback--bg); + border-radius: $fallback--panelRadius; + border-radius: var(--panelRadius, $fallback--panelRadius); + } + } + } + + .shadow-tweak { + .label { + flex: 1; + min-width: 3em; + } + + .inset-control { + justify-content: flex-end; + label { + flex: 0 + } + } + + .blur-control, + .id-control, + .inset-control, + .spread-control { + display: flex; + align-items: baseline; + max-width: 100%; + + &[disabled=disabled] *{ + opacity: .5 + } + + .input-range { + flex: 1; + align-self: center; + } + + .input-number { + width: 4em; + min-width: 4em; + flex: 0; + } + } + } +} +</style> diff --git a/src/components/style_switcher/style_switcher.js b/src/components/style_switcher/style_switcher.js index f4f9331f..8e344eb1 100644 --- a/src/components/style_switcher/style_switcher.js +++ b/src/components/style_switcher/style_switcher.js @@ -1,5 +1,6 @@ import { rgb2hex, hex2rgb, getContrastRatio, alphaBlend } from '../../services/color_convert/color_convert.js' import ColorInput from '../color_input/color_input.vue' +import ShadowControl from '../shadow_control/shadow_control.vue' import ContrastRatio from '../contrast_ratio/contrast_ratio.vue' import OpacityInput from '../opacity_input/opacity_input.vue' import StyleSetter from '../../services/style_setter/style_setter.js' @@ -51,6 +52,9 @@ export default { faintOpacityLocal: undefined, faintLinkColorLocal: undefined, + shadowSelected: undefined, + shadowsLocal: {}, + cRedColorLocal: '', cBlueColorLocal: '', cGreenColorLocal: '', @@ -225,12 +229,23 @@ export default { previewRules () { if (!this.preview.colorRules) return '' return [this.preview.colorRules, this.preview.radiiRules, 'color: var(--text)'].join(';') + }, + shadowsAvailable () { + return Object.keys(this.preview.theme.shadows) + }, + currentShadow () { + const fallback = this.preview.theme.shadows[this.shadowSelected]; + return fallback ? { + fallback, + value: this.shadowsLocal[this.shadowSelected] + } : undefined } }, components: { ColorInput, OpacityInput, ContrastRatio, + ShadowControl, TabSwitcher }, methods: { @@ -340,6 +355,7 @@ export default { const colors = input.colors || input const radii = input.radii || input const opacity = input.opacity || input + const shadows = input.shadows || {} if (version === 0) { if (input.version) version = input.version @@ -384,6 +400,8 @@ export default { this.tooltipRadiusLocal = radii.tooltipRadius || 2 this.attachmentRadiusLocal = radii.attachmentRadius || 5 + this.shadowsLocal = shadows + Object.entries(opacity).forEach(([k, v]) => { if (typeof v === 'undefined' || v === null || Number.isNaN(v)) return this[k + 'OpacityLocal'] = v diff --git a/src/components/style_switcher/style_switcher.vue b/src/components/style_switcher/style_switcher.vue index 5bc38318..0352f546 100644 --- a/src/components/style_switcher/style_switcher.vue +++ b/src/components/style_switcher/style_switcher.vue @@ -170,6 +170,17 @@ <input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal"> </div> </div> + <div label="Shadow Realm" class="shadow-container"> + <div class="shadow-selector"> + <select id="style-switcher" v-model="shadowSelected" class="style-switcher"> + <option v-for="shadow in shadowsAvailable" + :value="shadow"> + {{shadow}} + </option> + </select> + </div> + <shadow-control v-if="currentShadow" :value="currentShadow.value" :fallback="currentShadow.fallback"/> + </div> </tab-switcher> <div class="apply-container"> diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index 907de586..3840e215 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -92,6 +92,19 @@ const setColors = (input, commit) => { commit('setOption', { name: 'colors', value: theme.colors }) } +const generateShadow = (input) => { + // >shad + return input.map((shad) => [ + shad.x, + shad.y, + shad.blur, + shad.spread + ].map(_ => _ + 'px').concat([ + rgb2rgba({...(hex2rgb(shad.color)), a: shad.alpha}), + shad.inset ? 'inset' : '' + ]).join(' ')).join(', ') +} + const generatePreset = (input) => { const radii = input.radii || { btnRadius: input.btnRadius, @@ -102,6 +115,17 @@ const generatePreset = (input) => { tooltipRadius: input.tooltipRadius, attachmentRadius: input.attachmentRadius } + const shadows = { + panel: [{ + x: 1, + y: 1, + blur: 4, + spread: 0, + color: '#000000', + alpha: 0.6 + }], + ...(input.shadows || {}) + } const colors = {} const opacity = Object.assign({ alert: 0.5, @@ -194,8 +218,10 @@ const generatePreset = (input) => { return { colorRules: Object.entries(htmlColors.complete).filter(([k, v]) => v).map(([k, v]) => `--${k}: ${v}`).join(';'), radiiRules: Object.entries(radii).filter(([k, v]) => v).map(([k, v]) => `--${k}: ${v}px`).join(';'), + shadowRules: Object.entries(shadows).filter(([k, v]) => v).map(([k, v]) => `--${k}-shadow: ${generateShadow(v)}`).join(';'), theme: { colors: htmlColors.solid, + shadows, opacity, radii } @@ -245,7 +271,8 @@ const StyleSetter = { setPreset, setColors, getTextColor, - generatePreset + generatePreset, + generateShadow } export default StyleSetter |
