aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/color_input/color_input.vue8
-rw-r--r--src/components/opacity_input/opacity_input.vue6
-rw-r--r--src/components/shadow_control/shadow_control.js76
-rw-r--r--src/components/shadow_control/shadow_control.vue249
-rw-r--r--src/components/style_switcher/style_switcher.js18
-rw-r--r--src/components/style_switcher/style_switcher.vue11
-rw-r--r--src/services/style_setter/style_setter.js29
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