From a044dc377e77aade4696984fb42f7aa5db8c2561 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Sep 2024 15:47:48 +0300
Subject: Massively upgraded shadow control, added sorting by specificity in
 themes3, added/fixed disabled inputs

---
 src/components/shadow_control/shadow_control.vue | 281 +++++++++--------------
 1 file changed, 106 insertions(+), 175 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index c3b956cd..77d7c15a 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -1,81 +1,92 @@
 <template>
   <div
-    class="shadow-control"
+    class="label shadow-control"
     :class="{ disabled: !present }"
   >
-    <div class="shadow-preview-container">
-      <div
+    <div class="shadow-preview">
+      <label
+        class="header"
+        :class="{ faint: !present }"
+      >
+        {{ $t('settings.style.shadows.offset') }}
+      </label>
+      <input
+        v-model="selected.y"
         :disabled="!present"
-        class="y-shift-control"
+        :class="{ disabled: !present }"
+        class="input input-number y-shift-number"
+        type="number"
+      >
+      <input
+        v-model="selected.y"
+        :disabled="!present"
+        :class="{ disabled: !present }"
+        class="input input-range y-shift-slider"
+        type="range"
+        max="20"
+        min="-20"
+      >
+      <div
+        class="preview-window"
+        :class="{ disabled: !present, '-light-grid': lightGrid }"
       >
-        <input
-          v-model="selected.y"
-          :disabled="!present"
-          class="input input-number"
-          type="number"
-        >
-        <div class="wrap">
-          <input
-            v-model="selected.y"
-            :disabled="!present"
-            class="input input-range"
-            type="range"
-            max="20"
-            min="-20"
-          >
-        </div>
-      </div>
-      <div class="preview-window">
         <div
           class="preview-block"
           :style="style"
         />
       </div>
-      <div
+      <input
+        v-model="selected.x"
         :disabled="!present"
-        class="x-shift-control"
+        :class="{ disabled: !present }"
+        class="input input-number x-shift-number"
+        type="number"
       >
-        <input
-          v-model="selected.x"
-          :disabled="!present"
-          class="input input-number"
-          type="number"
-        >
-        <div class="wrap">
-          <input
-            v-model="selected.x"
-            :disabled="!present"
-            class="input input-range"
-            type="range"
-            max="20"
-            min="-20"
-          >
-        </div>
-      </div>
-    </div>
+      <input
+        v-model="selected.x"
+        :disabled="!present"
+        :class="{ disabled: !present }"
+        class="input input-range x-shift-slider"
+        type="range"
+        max="20"
+        min="-20"
+      >
+      <Checkbox
+        id="inset"
+        v-model="lightGrid"
+        :disabled="!present"
+        name="lightGrid"
+        class="input-light-grid"
+      >
+        {{ $t('settings.style.shadows.light_grid') }}
+      </Checkbox>
 
-    <div class="shadow-tweak">
+    </div>
+    <div class="shadow-switcher">
+      <Select
+        class="shadow-list"
+        id="shadow-list"
+        v-model="selectedId"
+        size="10"
+        :disabled="!ready || usingFallback"
+      >
+        <option
+          v-for="(shadow, index) in cValue"
+          :value="index"
+          :class="{ '-active': index === Number(selectedId) }"
+          :key="index"
+        >
+          {{ shadow.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }}
+        </option>
+      </Select>
       <div
         :disabled="usingFallback"
-        class="id-control style-control"
+        class="id-control arrange-buttons"
       >
-        <Select
-          id="shadow-switcher"
-          v-model="selectedId"
-          class="shadow-switcher"
-          :disabled="!ready || usingFallback"
-        >
-          <option
-            v-for="(shadow, index) in cValue"
-            :key="index"
-            :value="index"
-          >
-            {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
-          </option>
-        </Select>
         <button
           class="btn button-default"
           :disabled="!ready || !present"
+          :class="{ disabled: !present }"
           @click="del"
         >
           <FAIcon
@@ -86,6 +97,7 @@
         <button
           class="btn button-default"
           :disabled="!moveUpValid"
+          :class="{ disabled: !present }"
           @click="moveUp"
         >
           <FAIcon
@@ -105,7 +117,7 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="usingFallback"
+          :disabled="usingFallback || !present"
           @click="add"
         >
           <FAIcon
@@ -114,37 +126,54 @@
           />
         </button>
       </div>
+    </div>
+    <div class="shadow-tweak">
       <div
         :disabled="!present"
-        class="inset-control style-control"
+        :class="{ disabled: !present }"
+        class="name-control style-control"
       >
         <label
-          for="inset"
+          for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
-          {{ $t('settings.style.shadows.inset') }}
+          {{ $t('settings.style.shadows.name') }}
         </label>
         <input
+          id="name"
+          v-model="selected.name"
+          :disabled="!present"
+          :class="{ disabled: !present }"
+          name="name"
+          class="input input-string"
+        >
+      </div>
+      <div
+        :disabled="!present"
+        class="inset-control style-control"
+      >
+        <Checkbox
           id="inset"
           v-model="selected.inset"
           :disabled="!present"
           name="inset"
-          class="input -checkbox input-inset visible-for-screenreader-only"
-          type="checkbox"
+          class="input-inset input-boolean"
         >
-        <label
-          class="checkbox-label"
-          for="inset"
-          :aria-hidden="true"
-        />
+          <template #before>
+            {{ $t('settings.style.shadows.inset') }}
+          </template>
+        </Checkbox>
       </div>
       <div
         :disabled="!present"
+        :class="{ disabled: !present }"
         class="blur-control style-control"
       >
         <label
           for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
           {{ $t('settings.style.shadows.blur') }}
         </label>
@@ -152,6 +181,7 @@
           id="blur"
           v-model="selected.blur"
           :disabled="!present"
+          :class="{ disabled: !present }"
           name="blur"
           class="input input-range"
           type="range"
@@ -161,6 +191,7 @@
         <input
           v-model="selected.blur"
           :disabled="!present"
+          :class="{ disabled: !present }"
           class="input input-number"
           type="number"
           min="0"
@@ -169,10 +200,12 @@
       <div
         :disabled="!present"
         class="spread-control style-control"
+        :class="{ disabled: !present }"
       >
         <label
           for="spread"
           class="label"
+          :class="{ faint: !present }"
         >
           {{ $t('settings.style.shadows.spread') }}
         </label>
@@ -180,6 +213,7 @@
           id="spread"
           v-model="selected.spread"
           :disabled="!present"
+          :class="{ disabled: !present }"
           name="spread"
           class="input input-range"
           type="range"
@@ -189,6 +223,7 @@
         <input
           v-model="selected.spread"
           :disabled="!present"
+          :class="{ disabled: !present }"
           class="input input-number"
           type="number"
         >
@@ -208,6 +243,7 @@
       <i18n-t
         scope="global"
         keypath="settings.style.shadows.hintV3"
+        :class="{ faint: !present }"
         tag="p"
       >
         <code>--variable,mod</code>
@@ -218,109 +254,4 @@
 
 <script src="./shadow_control.js"></script>
 
-<style lang="scss">
-.shadow-control {
-  display: flex;
-  flex-wrap: wrap;
-  justify-content: center;
-  margin-bottom: 1em;
-
-  .shadow-preview-container,
-  .shadow-tweak {
-    margin: 5px 6px 0 0;
-  }
-
-  .shadow-preview-container {
-    flex: 0;
-    display: flex;
-    flex-wrap: wrap;
-
-    input[type="number"] {
-      width: 5em;
-      min-width: 2em;
-    }
-
-    .x-shift-control,
-    .y-shift-control {
-      display: flex;
-      flex: 0;
-
-      &[disabled="disabled"] * {
-        opacity: 0.5;
-      }
-    }
-
-    .x-shift-control {
-      align-items: flex-start;
-    }
-
-    .x-shift-control .wrap,
-    input[type="range"] {
-      margin: 0;
-      width: 15em;
-      height: 2em;
-    }
-
-    .y-shift-control {
-      flex-direction: column;
-      align-items: flex-end;
-
-      .wrap {
-        width: 2em;
-        height: 15em;
-      }
-
-      input[type="range"] {
-        transform-origin: 1em 1em;
-        transform: rotate(90deg);
-      }
-    }
-
-    .preview-window {
-      flex: 1;
-      background-color: #999;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background-image:
-        linear-gradient(45deg, #666 25%, transparent 25%),
-        linear-gradient(-45deg, #666 25%, transparent 25%),
-        linear-gradient(45deg, transparent 75%, #666 75%),
-        linear-gradient(-45deg, transparent 75%, #666 75%);
-      background-size: 20px 20px;
-      background-position: 0 0, 0 10px, 10px -10px, -10px 0;
-      border-radius: var(--roundness);
-
-      .preview-block {
-        width: 33%;
-        height: 33%;
-        border-radius: var(--roundness);
-      }
-    }
-  }
-
-  .shadow-tweak {
-    flex: 1;
-    min-width: 280px;
-
-    .id-control {
-      align-items: stretch;
-
-      .shadow-switcher {
-        flex: 1;
-      }
-
-      .shadow-switcher,
-      .btn {
-        min-width: 1px;
-        margin-right: 5px;
-      }
-
-      .btn {
-        padding: 0 0.4em;
-        margin: 0 0.1em;
-      }
-    }
-  }
-}
-</style>
+<style src="./shadow_control.scss" lang="scss"></style>
-- 
cgit v1.2.3-70-g09d2


From 2b9968eacd6f45dc5ad39796f1b2f488e2a22cbb Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Sep 2024 16:10:39 +0300
Subject: lint

---
 src/components/checkbox/checkbox.vue                       |  2 +-
 src/components/color_input/color_input.vue                 |  2 +-
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue | 11 +++++++----
 src/components/shadow_control/shadow_control.vue           |  5 ++---
 4 files changed, 11 insertions(+), 9 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue
index 494605cf..8ffcc63b 100644
--- a/src/components/checkbox/checkbox.vue
+++ b/src/components/checkbox/checkbox.vue
@@ -8,7 +8,7 @@
       class="label -before"
       :class="{ faint: disabled }"
     >
-      <slot name="before"/>
+      <slot name="before" />
     </span>
     <input
       type="checkbox"
diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index 200b8631..6725fcda 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -20,7 +20,7 @@
     <div
       class="input color-input-field"
       :class="{ disabled: !present || disabled }"
-      >
+    >
       <input
         :id="name + '-t'"
         class="textColor unstyled"
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index 4498c143..d975c61d 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -123,10 +123,13 @@
       </div>
     </div>
 
-    <!-- eslint-disable vue/no-v-text-v-html-on-component -->
-    <component :is="'style'" v-html="themeV3Preview"/>
-    <!-- eslint-enable vue/no-v-text-v-html-on-component -->
-    <preview id="theme-preview"/>
+    <!-- eslint-disable vue/no-v-html vue/no-v-text-v-html-on-component -->
+    <component
+      :is="'style'"
+      v-html="themeV3Preview"
+    />
+    <!-- eslint-enable vue/no-v-html vue/no-v-text-v-html-on-component -->
+    <preview id="theme-preview" />
 
     <div>
       <button
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 77d7c15a..b867d6e0 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -60,21 +60,20 @@
       >
         {{ $t('settings.style.shadows.light_grid') }}
       </Checkbox>
-
     </div>
     <div class="shadow-switcher">
       <Select
-        class="shadow-list"
         id="shadow-list"
         v-model="selectedId"
+        class="shadow-list"
         size="10"
         :disabled="!ready || usingFallback"
       >
         <option
           v-for="(shadow, index) in cValue"
+          :key="index"
           :value="index"
           :class="{ '-active': index === Number(selectedId) }"
-          :key="index"
         >
           {{ shadow.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }}
         </option>
-- 
cgit v1.2.3-70-g09d2


From aa7a3361833f4c88ec685c4a92ff7727ed7249a7 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Sep 2024 19:31:19 +0300
Subject: Updated shadow control to be able to handle "absolute null" situation

---
 .../settings_modal/tabs/theme_tab/theme_tab.js     |  14 ++-
 .../settings_modal/tabs/theme_tab/theme_tab.vue    |  46 +-------
 src/components/shadow_control/shadow_control.js    | 122 +++++++++++----------
 src/components/shadow_control/shadow_control.scss  |  17 ++-
 src/components/shadow_control/shadow_control.vue   | 103 +++++++++++++----
 src/i18n/en.json                                   |   1 +
 src/services/theme_data/theme_data.service.js      |   2 +-
 7 files changed, 179 insertions(+), 126 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index 25836559..a295e880 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -314,7 +314,18 @@ export default {
       },
       set (val) {
         if (val) {
-          this.shadowsLocal[this.shadowSelected] = this.currentShadowFallback.map(_ => Object.assign({}, _))
+          this.shadowsLocal[this.shadowSelected] = (this.currentShadowFallback || [])
+            .map(s => ({
+              name: null,
+              x: 0,
+              y: 0,
+              blur: 0,
+              spread: 0,
+              inset: false,
+              color: '#000000',
+              alpha: 1,
+              ...s
+            }))
         } else {
           delete this.shadowsLocal[this.shadowSelected]
         }
@@ -328,6 +339,7 @@ export default {
         return this.shadowsLocal[this.shadowSelected]
       },
       set (v) {
+        console.log('TT', v)
         this.shadowsLocal[this.shadowSelected] = v
       }
     },
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index d975c61d..00a55832 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -937,24 +937,14 @@
               </Select>
             </div>
             <div class="override">
-              <label
-                for="override"
-                class="label"
-              >
-                {{ $t('settings.style.shadows.override') }}
-              </label>
-              {{ ' ' }}
-              <input
+              <Checkbox
                 id="override"
                 v-model="currentShadowOverriden"
                 name="override"
                 class="input-override"
-                type="checkbox"
               >
-              <label
-                class="checkbox-label"
-                for="override"
-              />
+                {{ $t('settings.style.shadows.override') }}
+              </Checkbox>
             </div>
             <button
               class="btn button-default"
@@ -965,38 +955,10 @@
           </div>
           <ShadowControl
             v-model="currentShadow"
-            :ready="!!currentShadowFallback"
+            :separate-inset="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'"
             :fallback="currentShadowFallback"
           />
-          <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n-t
-              scope="global"
-              keypath="settings.style.shadows.filter_hint.always_drop_shadow"
-              tag="p"
-            >
-              <code>filter: drop-shadow()</code>
-            </i18n-t>
-            <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n-t
-              scope="global"
-              keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
-              tag="p"
-            >
-              <code>drop-shadow</code>
-              <code>spread-radius</code>
-              <code>inset</code>
-            </i18n-t>
-            <i18n-t
-              scope="global"
-              keypath="settings.style.shadows.filter_hint.inset_classic"
-              tag="p"
-            >
-              <code>box-shadow</code>
-            </i18n-t>
-            <p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p>
-          </div>
         </div>
-
         <div
           :label="$t('settings.style.fonts._tab_label')"
           class="fonts-container"
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index e653854a..4d26a539 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -1,8 +1,9 @@
-import ColorInput from '../color_input/color_input.vue'
-import OpacityInput from '../opacity_input/opacity_input.vue'
-import Select from '../select/select.vue'
-import Checkbox from '../checkbox/checkbox.vue'
-import { getCssShadow } from '../../services/theme_data/theme_data.service.js'
+import ColorInput from 'src/components/color_input/color_input.vue'
+import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
+import Select from 'src/components/select/select.vue'
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import Popover from 'src/components/popover/popover.vue'
+import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
@@ -31,12 +32,8 @@ const toModel = (object = {}) => ({
 })
 
 export default {
-  // 'modelValue' and 'Fallback' can be undefined, but if they are
-  // initially vue won't detect it when they become something else
-  // therefore i'm using "ready" which should be passed as true when
-  // data becomes available
   props: [
-    'modelValue', 'fallback', 'ready'
+    'modelValue', 'fallback', 'separateInset'
   ],
   emits: ['update:modelValue'],
   data () {
@@ -51,75 +48,86 @@ export default {
     ColorInput,
     OpacityInput,
     Select,
-    Checkbox
-  },
-  methods: {
-    add () {
-      this.cValue.push(toModel(this.selected))
-      this.selectedId = this.cValue.length - 1
-    },
-    del () {
-      this.cValue.splice(this.selectedId, 1)
-      this.selectedId = this.cValue.length === 0 ? undefined : Math.max(this.selectedId - 1, 0)
-    },
-    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
-    }
+    Checkbox,
+    Popover
   },
   beforeUpdate () {
-    this.cValue = this.modelValue || this.fallback
+    this.cValue = (this.modelValue || this.fallback || []).map(toModel)
   },
   computed: {
+    selected () {
+      const selected = this.cValue[this.selectedId]
+      if (selected) {
+        return { ...selected }
+      }
+      return null
+    },
+    present () {
+      return this.selected != null && !this.usingFallback
+    },
+    shadowsAreNull () {
+      return this.modelValue == null
+    },
     anyShadows () {
       return this.cValue.length > 0
     },
     anyShadowsFallback () {
       return this.fallback.length > 0
     },
-    selected () {
-      if (this.ready && this.anyShadows) {
-        return this.cValue[this.selectedId]
-      } else {
-        return toModel({})
-      }
-    },
     currentFallback () {
-      if (this.ready && this.anyShadowsFallback) {
-        return this.fallback[this.selectedId]
-      } else {
-        return toModel({})
-      }
+      return this.fallback?.[this.selectedId]
     },
     moveUpValid () {
-      return this.ready && this.selectedId > 0
+      return this.selectedId > 0
     },
     moveDnValid () {
-      return this.ready && this.selectedId < this.cValue.length - 1
-    },
-    present () {
-      return this.ready &&
-        typeof this.cValue[this.selectedId] !== 'undefined' &&
-        !this.usingFallback
+      return this.selectedId < this.cValue.length - 1
     },
     usingFallback () {
-      return typeof this.modelValue === 'undefined'
+      return this.modelValue == null
     },
     rgb () {
       return hex2rgb(this.selected.color)
     },
     style () {
-      return this.ready
-        ? {
-            boxShadow: getCssShadow(this.fallback)
-          }
-        : {}
+      if (!this.ready) return {}
+      if (this.separateInset) {
+        return {
+          filter: getCssShadowFilter(this.fallback),
+          boxShadow: getCssShadow(this.fallback, true)
+        }
+      }
+      return {
+        boxShadow: getCssShadow(this.fallback)
+      }
+    }
+  },
+  methods: {
+    updateProperty (prop, value) {
+      this.cValue[this.selectedId][prop] = value
+      this.$emit('update:modelValue', this.cValue)
+    },
+    add () {
+      this.cValue.push(toModel(this.selected))
+      this.selectedId = Math.max(this.cValue.length - 1, 0)
+      this.$emit('update:modelValue', this.cValue)
+    },
+    del () {
+      this.cValue.splice(this.selectedId, 1)
+      this.selectedId = this.cValue.length === 0 ? undefined : Math.max(this.selectedId - 1, 0)
+      this.$emit('update:modelValue', this.cValue)
+    },
+    moveUp () {
+      const movable = this.cValue.splice(this.selectedId, 1)[0]
+      this.cValue.splice(this.selectedId - 1, 0, movable)
+      this.selectedId -= 1
+      this.$emit('update:modelValue', this.cValue)
+    },
+    moveDn () {
+      const movable = this.cValue.splice(this.selectedId, 1)[0]
+      this.cValue.splice(this.selectedId + 1, 0, movable)
+      this.selectedId += 1
+      this.$emit('update:modelValue', this.cValue)
     }
   }
 }
diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss
index 0fba39f3..d7bc15c4 100644
--- a/src/components/shadow_control/shadow_control.scss
+++ b/src/components/shadow_control/shadow_control.scss
@@ -69,6 +69,16 @@
     }
   }
 
+  .inset-alert {
+    padding: 0.25em 0.5em;
+  }
+
+  &.disabled {
+    .inset-alert {
+      opacity: 0.2;
+    }
+  }
+
   .shadow-preview {
     order: 2;
     flex: 3 3 15em;
@@ -94,7 +104,7 @@
 
     .input-light-grid {
       grid-area: options;
-      justify-self: end;
+      justify-self: center;
     }
 
     .input-number {
@@ -176,3 +186,8 @@
     }
   }
 }
+
+.inset-tooltip {
+  padding: 0.5em;
+  max-width: 30em;
+}
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index b867d6e0..8e2133ee 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -11,20 +11,22 @@
         {{ $t('settings.style.shadows.offset') }}
       </label>
       <input
-        v-model="selected.y"
+        :value="selected?.y"
         :disabled="!present"
         :class="{ disabled: !present }"
         class="input input-number y-shift-number"
         type="number"
+        @input="e => updateProperty('y', e.target.value)"
       >
       <input
-        v-model="selected.y"
+        :value="selected?.y"
         :disabled="!present"
         :class="{ disabled: !present }"
         class="input input-range y-shift-slider"
         type="range"
         max="20"
         min="-20"
+        @input="e => updateProperty('y', e.target.value)"
       >
       <div
         class="preview-window"
@@ -36,20 +38,22 @@
         />
       </div>
       <input
-        v-model="selected.x"
+        :value="selected?.x"
         :disabled="!present"
         :class="{ disabled: !present }"
         class="input input-number x-shift-number"
         type="number"
+        @input="e => updateProperty('x', e.target.value)"
       >
       <input
-        v-model="selected.x"
+        :value="selected?.x"
         :disabled="!present"
         :class="{ disabled: !present }"
         class="input input-range x-shift-slider"
         type="range"
         max="20"
         min="-20"
+        @input="e => updateProperty('x', e.target.value)"
       >
       <Checkbox
         id="inset"
@@ -67,7 +71,7 @@
         v-model="selectedId"
         class="shadow-list"
         size="10"
-        :disabled="!ready || usingFallback"
+        :disabled="shadowsAreNull"
       >
         <option
           v-for="(shadow, index) in cValue"
@@ -75,28 +79,26 @@
           :value="index"
           :class="{ '-active': index === Number(selectedId) }"
         >
-          {{ shadow.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }}
+          {{ shadow?.name ?? $t('settings.style.shadows.shadow_id', { value: index }) }}
         </option>
       </Select>
       <div
-        :disabled="usingFallback"
         class="id-control arrange-buttons"
       >
         <button
           class="btn button-default"
-          :disabled="!ready || !present"
-          :class="{ disabled: !present }"
-          @click="del"
+          :disabled="shadowsAreNull"
+          @click="add"
         >
           <FAIcon
             fixed-width
-            icon="times"
+            icon="plus"
           />
         </button>
         <button
           class="btn button-default"
           :disabled="!moveUpValid"
-          :class="{ disabled: !present }"
+          :class="{ disabled: !moveUpValid }"
           @click="moveUp"
         >
           <FAIcon
@@ -107,6 +109,7 @@
         <button
           class="btn button-default"
           :disabled="!moveDnValid"
+          :class="{ disabled: !moveDnValid }"
           @click="moveDn"
         >
           <FAIcon
@@ -116,12 +119,13 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="usingFallback || !present"
-          @click="add"
+          :disabled="!present"
+          :class="{ disabled: !present }"
+          @click="del"
         >
           <FAIcon
             fixed-width
-            icon="plus"
+            icon="times"
           />
         </button>
       </div>
@@ -141,11 +145,12 @@
         </label>
         <input
           id="name"
-          v-model="selected.name"
+          :value="selected?.name"
           :disabled="!present"
           :class="{ disabled: !present }"
           name="name"
           class="input input-string"
+          @input="e => updateProperty('name', e.target.value)"
         >
       </div>
       <div
@@ -154,10 +159,11 @@
       >
         <Checkbox
           id="inset"
-          v-model="selected.inset"
+          :value="selected?.inset"
           :disabled="!present"
           name="inset"
           class="input-inset input-boolean"
+          @input="e => updateProperty('inset', e.target.value)"
         >
           <template #before>
             {{ $t('settings.style.shadows.inset') }}
@@ -178,7 +184,7 @@
         </label>
         <input
           id="blur"
-          v-model="selected.blur"
+          :value="selected?.blur"
           :disabled="!present"
           :class="{ disabled: !present }"
           name="blur"
@@ -186,14 +192,16 @@
           type="range"
           max="20"
           min="0"
+          @input="e => updateProperty('blur', e.target.value)"
         >
         <input
-          v-model="selected.blur"
+          :value="selected?.blur"
           :disabled="!present"
           :class="{ disabled: !present }"
           class="input input-number"
           type="number"
           min="0"
+          @input="e => updateProperty('blur', e.target.value)"
         >
       </div>
       <div
@@ -210,7 +218,7 @@
         </label>
         <input
           id="spread"
-          v-model="selected.spread"
+          :value="selected?.spread"
           :disabled="!present"
           :class="{ disabled: !present }"
           name="spread"
@@ -218,26 +226,30 @@
           type="range"
           max="20"
           min="-20"
+          @input="e => updateProperty('spread', e.target.value)"
         >
         <input
-          v-model="selected.spread"
+          :value="selected?.spread"
           :disabled="!present"
           :class="{ disabled: !present }"
           class="input input-number"
           type="number"
+          @input="e => updateProperty('spread', e.target.value)"
         >
       </div>
       <ColorInput
-        v-model="selected.color"
+        :modelValue="selected?.color"
         :disabled="!present"
         :label="$t('settings.style.common.color')"
-        :fallback="currentFallback.color"
+        :fallback="currentFallback?.color"
         :show-optional-tickbox="false"
         name="shadow"
+        @update:modelValue="e => updateProperty('color', e.target.value)"
       />
       <OpacityInput
-        v-model="selected.alpha"
+        :modelValue="selected?.alpha"
         :disabled="!present"
+        @update:modelValue="e => updateProperty('alpha', e.target.value)"
       />
       <i18n-t
         scope="global"
@@ -247,6 +259,49 @@
       >
         <code>--variable,mod</code>
       </i18n-t>
+      <Popover
+        trigger="hover"
+        v-if="separateInset"
+      >
+        <template #trigger>
+          <div
+            class="inset-alert alert warning"
+          >
+            <FAIcon icon="exclamation-triangle" />
+            &nbsp;
+            {{ $t('settings.style.shadows.filter_hint.avatar_inset_short') }}
+          </div>
+        </template>
+        <template #content>
+          <div class="inset-tooltip">
+            <i18n-t
+              scope="global"
+              keypath="settings.style.shadows.filter_hint.always_drop_shadow"
+              tag="p"
+            >
+              <code>filter: drop-shadow()</code>
+            </i18n-t>
+            <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
+            <i18n-t
+              scope="global"
+              keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
+              tag="p"
+            >
+              <code>drop-shadow</code>
+              <code>spread-radius</code>
+              <code>inset</code>
+            </i18n-t>
+            <i18n-t
+              scope="global"
+              keypath="settings.style.shadows.filter_hint.inset_classic"
+              tag="p"
+            >
+              <code>box-shadow</code>
+            </i18n-t>
+            <p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p>
+          </div>
+        </template>
+      </Popover>
     </div>
   </div>
 </template>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index b27c36d7..1b67d4f7 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -880,6 +880,7 @@
         "filter_hint": {
           "always_drop_shadow": "Warning, this shadow always uses {0} when browser supports it.",
           "drop_shadow_syntax": "{0} does not support {1} parameter and {2} keyword.",
+          "avatar_inset_short": "Separate inset shadow",
           "avatar_inset": "Please note that combining both inset and non-inset shadows on avatars might give unexpected results with transparent avatars.",
           "spread_zero": "Shadows with spread > 0 will appear as if it was set to zero",
           "inset_classic": "Inset shadows will be using {0}"
diff --git a/src/services/theme_data/theme_data.service.js b/src/services/theme_data/theme_data.service.js
index 2dddfa04..ef7ec645 100644
--- a/src/services/theme_data/theme_data.service.js
+++ b/src/services/theme_data/theme_data.service.js
@@ -452,7 +452,7 @@ export const getCssShadow = (input, usesDropShadow) => {
     ]).join(' ')).join(', ')
 }
 
-const getCssShadowFilter = (input) => {
+export const getCssShadowFilter = (input) => {
   if (input.length === 0) {
     return 'none'
   }
-- 
cgit v1.2.3-70-g09d2


From a0c303efb6ea422289aff8c295d288a13b0699d0 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 16 Sep 2024 00:03:40 +0300
Subject: fixed shadow preview, added more safeguards for spread on
 separateInset shadows

---
 changelog.d/better-shadow-control.fix              |  1 +
 src/components/color_input/color_input.vue         | 12 ++++++--
 src/components/select/select.vue                   | 23 +++++++++++----
 .../settings_modal/tabs/theme_tab/theme_tab.js     |  1 -
 src/components/shadow_control/shadow_control.js    | 31 +++++++++-----------
 src/components/shadow_control/shadow_control.scss  |  1 -
 src/components/shadow_control/shadow_control.vue   | 34 ++++++++++------------
 7 files changed, 56 insertions(+), 47 deletions(-)
 create mode 100644 changelog.d/better-shadow-control.fix

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/changelog.d/better-shadow-control.fix b/changelog.d/better-shadow-control.fix
new file mode 100644
index 00000000..585ef6d2
--- /dev/null
+++ b/changelog.d/better-shadow-control.fix
@@ -0,0 +1 @@
+Updated shadow editor, hopefully fixed long-standing bugs, added ability to specify shadow's name.
diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index 6725fcda..b6e84629 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -15,7 +15,7 @@
       :model-value="present"
       :disabled="disabled"
       class="opt"
-      @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
+      @update:modelValue="update(typeof modelValue === 'undefined' ? fallback : undefined)"
     />
     <div
       class="input color-input-field"
@@ -28,7 +28,7 @@
         type="text"
         :value="modelValue || fallback"
         :disabled="!present || disabled"
-        @input="$emit('update:modelValue', $event.target.value)"
+        @input="updateValue($event.target.value)"
       >
       <div
         v-if="validColor"
@@ -57,7 +57,7 @@
           :value="modelValue || fallback"
           :disabled="!present || disabled"
           :class="{ disabled: !present || disabled }"
-          @input="$emit('update:modelValue', $event.target.value)"
+          @input="updateValue($event.target.value)"
         >
       </label>
     </div>
@@ -66,6 +66,7 @@
 <script>
 import Checkbox from '../checkbox/checkbox.vue'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
+import { throttle } from 'lodash'
 
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
@@ -131,6 +132,11 @@ export default {
     computedColor () {
       return this.modelValue && this.modelValue.startsWith('--')
     }
+  },
+  methods: {
+    updateValue: throttle(function (value) {
+      this.$emit('update:modelValue', value)
+    }, 100)
   }
 }
 </script>
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
index 7494f7d3..39d3ca64 100644
--- a/src/components/select/select.vue
+++ b/src/components/select/select.vue
@@ -27,11 +27,6 @@
 label.Select {
   padding: 0;
 
-  &.disabled,
-  &:disabled {
-    background-color: var(--background);
-  }
-
   select {
     appearance: none;
     background: transparent;
@@ -52,7 +47,7 @@ label.Select {
       padding: 0.2em;
 
       option {
-        background: transparent;
+        background-color: transparent;
 
         &.-active {
           color: var(--selectionText);
@@ -62,6 +57,22 @@ label.Select {
     }
   }
 
+  &.disabled,
+  &:disabled {
+    background-color: var(--background);
+    opacity: 1; /* override browser */
+
+    select {
+      &[multiple],
+      &[size] {
+        option.-active {
+          color: var(--text);
+          background: transparent;
+        }
+      }
+    }
+  }
+
   .select-down-icon {
     position: absolute;
     top: 0;
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index a295e880..64de28bc 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -339,7 +339,6 @@ export default {
         return this.shadowsLocal[this.shadowSelected]
       },
       set (v) {
-        console.log('TT', v)
         this.shadowsLocal[this.shadowSelected] = v
       }
     },
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index 4d26a539..ab1df53c 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -4,8 +4,8 @@ import Select from 'src/components/select/select.vue'
 import Checkbox from 'src/components/checkbox/checkbox.vue'
 import Popover from 'src/components/popover/popover.vue'
 import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js'
-import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
+import { throttle } from 'lodash'
 import {
   faTimes,
   faChevronDown,
@@ -41,7 +41,7 @@ export default {
       lightGrid: false,
       selectedId: 0,
       // TODO there are some bugs regarding display of array (it's not getting updated when deleting for some reason)
-      cValue: (this.modelValue || this.fallback || []).map(toModel)
+      cValue: (this.modelValue ?? this.fallback ?? []).map(toModel)
     }
   },
   components: {
@@ -52,7 +52,7 @@ export default {
     Popover
   },
   beforeUpdate () {
-    this.cValue = (this.modelValue || this.fallback || []).map(toModel)
+    this.cValue = (this.modelValue ?? this.fallback ?? []).map(toModel)
   },
   computed: {
     selected () {
@@ -68,12 +68,6 @@ export default {
     shadowsAreNull () {
       return this.modelValue == null
     },
-    anyShadows () {
-      return this.cValue.length > 0
-    },
-    anyShadowsFallback () {
-      return this.fallback.length > 0
-    },
     currentFallback () {
       return this.fallback?.[this.selectedId]
     },
@@ -86,27 +80,28 @@ export default {
     usingFallback () {
       return this.modelValue == null
     },
-    rgb () {
-      return hex2rgb(this.selected.color)
-    },
     style () {
-      if (!this.ready) return {}
+      console.log(this.separateInset)
       if (this.separateInset) {
         return {
-          filter: getCssShadowFilter(this.fallback),
-          boxShadow: getCssShadow(this.fallback, true)
+          filter: getCssShadowFilter(this.cValue),
+          boxShadow: getCssShadow(this.cValue, true)
         }
       }
       return {
-        boxShadow: getCssShadow(this.fallback)
+        boxShadow: getCssShadow(this.cValue)
       }
     }
   },
   methods: {
-    updateProperty (prop, value) {
+    updateProperty: throttle(function (prop, value) {
+      console.log(prop, value)
       this.cValue[this.selectedId][prop] = value
+      if (prop === 'inset' && value === false && this.separateInset) {
+        this.cValue[this.selectedId].spread = 0
+      }
       this.$emit('update:modelValue', this.cValue)
-    },
+    }, 100),
     add () {
       this.cValue.push(toModel(this.selected))
       this.selectedId = Math.max(this.cValue.length - 1, 0)
diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss
index d7bc15c4..19009a3d 100644
--- a/src/components/shadow_control/shadow_control.scss
+++ b/src/components/shadow_control/shadow_control.scss
@@ -22,7 +22,6 @@
       display: grid;
       grid-auto-columns: 1fr;
       grid-auto-flow: column;
-      grid-gap: 0.125em;
       margin-top: 0.25em;
 
       .button-default {
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 8e2133ee..6a7829c5 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -56,7 +56,7 @@
         @input="e => updateProperty('x', e.target.value)"
       >
       <Checkbox
-        id="inset"
+        id="lightGrid"
         v-model="lightGrid"
         :disabled="!present"
         name="lightGrid"
@@ -83,7 +83,7 @@
         </option>
       </Select>
       <div
-        class="id-control arrange-buttons"
+        class="id-control btn-group arrange-buttons"
       >
         <button
           class="btn button-default"
@@ -132,12 +132,11 @@
     </div>
     <div class="shadow-tweak">
       <div
-        :disabled="!present"
         :class="{ disabled: !present }"
         class="name-control style-control"
       >
         <label
-          for="spread"
+          for="name"
           class="label"
           :class="{ faint: !present }"
         >
@@ -163,7 +162,7 @@
           :disabled="!present"
           name="inset"
           class="input-inset input-boolean"
-          @input="e => updateProperty('inset', e.target.value)"
+          @input="e => updateProperty('inset', e.target.checked)"
         >
           <template #before>
             {{ $t('settings.style.shadows.inset') }}
@@ -176,7 +175,7 @@
         class="blur-control style-control"
       >
         <label
-          for="spread"
+          for="blur"
           class="label"
           :class="{ faint: !present }"
         >
@@ -205,22 +204,21 @@
         >
       </div>
       <div
-        :disabled="!present"
         class="spread-control style-control"
-        :class="{ disabled: !present }"
+        :class="{ disabled: !present || (separateInset && !selected?.inset) }"
       >
         <label
           for="spread"
           class="label"
-          :class="{ faint: !present }"
+          :class="{ faint: !present || (separateInset && !selected?.inset) }"
         >
           {{ $t('settings.style.shadows.spread') }}
         </label>
         <input
           id="spread"
           :value="selected?.spread"
-          :disabled="!present"
-          :class="{ disabled: !present }"
+          :disabled="!present || (separateInset && !selected?.inset)"
+          :class="{ disabled: !present || (separateInset && !selected?.inset) }"
           name="spread"
           class="input input-range"
           type="range"
@@ -230,26 +228,26 @@
         >
         <input
           :value="selected?.spread"
-          :disabled="!present"
-          :class="{ disabled: !present }"
+          :disabled="{ disabled: !present || (separateInset && !selected?.inset) }"
+          :class="{ disabled: !present || (separateInset && !selected?.inset) }"
           class="input input-number"
           type="number"
           @input="e => updateProperty('spread', e.target.value)"
         >
       </div>
       <ColorInput
-        :modelValue="selected?.color"
+        :model-value="selected?.color"
         :disabled="!present"
         :label="$t('settings.style.common.color')"
         :fallback="currentFallback?.color"
         :show-optional-tickbox="false"
         name="shadow"
-        @update:modelValue="e => updateProperty('color', e.target.value)"
+        @update:modelValue="e => updateProperty('color', e)"
       />
       <OpacityInput
-        :modelValue="selected?.alpha"
+        :model-value="selected?.alpha"
         :disabled="!present"
-        @update:modelValue="e => updateProperty('alpha', e.target.value)"
+        @update:modelValue="e => updateProperty('alpha', e)"
       />
       <i18n-t
         scope="global"
@@ -260,8 +258,8 @@
         <code>--variable,mod</code>
       </i18n-t>
       <Popover
-        trigger="hover"
         v-if="separateInset"
+        trigger="hover"
       >
         <template #trigger>
           <div
-- 
cgit v1.2.3-70-g09d2


From 735433beb48764ec560d852a58a8e2ed954220f6 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 24 Sep 2024 19:19:53 +0300
Subject: separate shadow preview into its own component, needed for themes3
 editor

---
 .../component_preview/component_preview.vue        | 195 +++++++++++++++++++++
 src/components/shadow_control/shadow_control.js    |   5 +-
 src/components/shadow_control/shadow_control.scss  |  99 -----------
 src/components/shadow_control/shadow_control.vue   |  69 +-------
 4 files changed, 205 insertions(+), 163 deletions(-)
 create mode 100644 src/components/component_preview/component_preview.vue

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/component_preview/component_preview.vue b/src/components/component_preview/component_preview.vue
new file mode 100644
index 00000000..087f48ea
--- /dev/null
+++ b/src/components/component_preview/component_preview.vue
@@ -0,0 +1,195 @@
+<template>
+<div class="ComponentPreview">
+  <label
+    class="header"
+    v-show="shadowControl"
+    :class="{ faint: disabled }"
+  >
+    {{ $t('settings.style.shadows.offset') }}
+  </label>
+  <input
+    v-show="shadowControl"
+    :value="shadow?.y"
+    :disabled="disabled"
+    :class="{ disabled }"
+    class="input input-number y-shift-number"
+    type="number"
+    @input="e => updateProperty('y', e.target.value)"
+  >
+  <input
+    v-show="shadowControl"
+    :value="shadow?.y"
+    :disabled="disabled"
+    :class="{ disabled }"
+    class="input input-range y-shift-slider"
+    type="range"
+    max="20"
+    min="-20"
+    @input="e => updateProperty('y', e.target.value)"
+  >
+  <div
+    class="preview-window"
+    :class="{ disabled: disabled && shadowControl, '-light-grid': lightGrid }"
+  >
+    <div
+      class="preview-block"
+      :style="previewStyle"
+    />
+  </div>
+  <input
+    v-show="shadowControl"
+    :value="shadow?.x"
+    :disabled="disabled"
+    :class="{ disabled }"
+    class="input input-number x-shift-number"
+    type="number"
+    @input="e => updateProperty('x', e.target.value)"
+  >
+  <input
+    v-show="shadowControl"
+    :value="shadow?.x"
+    :disabled="disabled"
+    :class="{ disabled }"
+    class="input input-range x-shift-slider"
+    type="range"
+    max="20"
+    min="-20"
+    @input="e => updateProperty('x', e.target.value)"
+  >
+  <Checkbox
+    id="lightGrid"
+    v-model="lightGrid"
+    :disabled="shadow == null"
+    name="lightGrid"
+    class="input-light-grid"
+  >
+    {{ $t('settings.style.shadows.light_grid') }}
+  </Checkbox>
+</div>
+</template>
+
+<style lang="scss">
+.ComponentPreview {
+  display: grid;
+  grid-template-columns: 3em 1fr 3em;
+  grid-template-rows: 2em 1fr 2em;
+  grid-template-areas:
+    ".       header  y-num  "
+    ".       preview y-slide"
+    "x-num   x-slide .      "
+    "options options options";
+  grid-gap: 0.5em;
+
+  .header {
+    grid-area: header;
+    justify-self: center;
+    align-self: baseline;
+    line-height: 2;
+  }
+
+  .input-light-grid {
+    grid-area: options;
+    justify-self: center;
+  }
+
+  .input-number {
+    min-width: 2em;
+  }
+
+  .x-shift-number {
+    grid-area: x-num;
+  }
+
+  .x-shift-slider {
+    grid-area: x-slide;
+    height: auto;
+    align-self: start;
+    min-width: 10em;
+  }
+
+  .y-shift-number {
+    grid-area: y-num;
+  }
+
+  .y-shift-slider {
+    grid-area: y-slide;
+    writing-mode: vertical-lr;
+    justify-self: left;
+    min-height: 10em;
+  }
+
+  .x-shift-slider,
+  .y-shift-slider {
+    padding: 0;
+  }
+
+  .preview-window {
+    --__grid-color1: rgb(102 102 102);
+    --__grid-color2: rgb(153 153 153);
+    --__grid-color1-disabled: rgba(102 102 102 / 20%);
+    --__grid-color2-disabled: rgba(153 153 153 / 20%);
+
+    &.-light-grid {
+      --__grid-color1: rgb(205 205 205);
+      --__grid-color2: rgb(255 255 255);
+      --__grid-color1-disabled: rgba(205 205 205 / 20%);
+      --__grid-color2-disabled: rgba(255 255 255 / 20%);
+    }
+
+    grid-area: preview;
+    aspect-ratio: 1;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    min-width: 10em;
+    min-height: 10em;
+    background-color: var(--__grid-color2);
+    background-image:
+      linear-gradient(45deg, var(--__grid-color1) 25%, transparent 25%),
+      linear-gradient(-45deg, var(--__grid-color1) 25%, transparent 25%),
+      linear-gradient(45deg, transparent 75%, var(--__grid-color1) 75%),
+      linear-gradient(-45deg, transparent 75%, var(--__grid-color1) 75%);
+    background-size: 20px 20px;
+    background-position: 0 0, 0 10px, 10px -10px, -10px 0;
+    border-radius: var(--roundness);
+
+    &.disabled {
+      background-color: var(--__grid-color2-disabled);
+      background-image:
+        linear-gradient(45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+        linear-gradient(-45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+        linear-gradient(45deg, transparent 75%, var(--__grid-color1-disabled) 75%),
+        linear-gradient(-45deg, transparent 75%, var(--__grid-color1-disabled) 75%);
+    }
+
+    .preview-block {
+      width: 33%;
+      height: 33%;
+      border-radius: var(--roundness);
+      background: var(--background);
+    }
+  }
+}
+</style>
+<script>
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+
+export default {
+  props: [
+    'shadow',
+    'shadowControl',
+    'previewClass',
+    'previewStyle',
+    'disabled'
+  ],
+  emits: ['update:shadow'],
+  components: {
+    Checkbox
+  },
+  methods: {
+    update (axis, value) {
+      this.$emit('update:shadow', { ...this.shadowControl, [axis]: value })
+    }
+  }
+}
+</script>
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index ab1df53c..c9a04e4d 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -3,6 +3,7 @@ import OpacityInput from 'src/components/opacity_input/opacity_input.vue'
 import Select from 'src/components/select/select.vue'
 import Checkbox from 'src/components/checkbox/checkbox.vue'
 import Popover from 'src/components/popover/popover.vue'
+import ComponentPreview from 'src/components/component_preview/component_preview.vue'
 import { getCssShadow, getCssShadowFilter } from '../../services/theme_data/theme_data.service.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import { throttle } from 'lodash'
@@ -49,7 +50,8 @@ export default {
     OpacityInput,
     Select,
     Checkbox,
-    Popover
+    Popover,
+    ComponentPreview
   },
   beforeUpdate () {
     this.cValue = (this.modelValue ?? this.fallback ?? []).map(toModel)
@@ -81,7 +83,6 @@ export default {
       return this.modelValue == null
     },
     style () {
-      console.log(this.separateInset)
       if (this.separateInset) {
         return {
           filter: getCssShadowFilter(this.cValue),
diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss
index 19009a3d..cdaefa88 100644
--- a/src/components/shadow_control/shadow_control.scss
+++ b/src/components/shadow_control/shadow_control.scss
@@ -82,107 +82,8 @@
     order: 2;
     flex: 3 3 15em;
     min-width: 10em;
-    display: grid;
     margin-left: 0.125em;
     align-self: start;
-    grid-template-columns: 3em 1fr 3em;
-    grid-template-rows: 2em 1fr 2em;
-    grid-template-areas:
-      ".       header  y-num  "
-      ".       preview y-slide"
-      "x-num   x-slide .      "
-      "options options options";
-    grid-gap: 0.5em;
-
-    .header {
-      grid-area: header;
-      justify-self: center;
-      align-self: baseline;
-      line-height: 2;
-    }
-
-    .input-light-grid {
-      grid-area: options;
-      justify-self: center;
-    }
-
-    .input-number {
-      min-width: 2em;
-    }
-
-    .x-shift-number {
-      grid-area: x-num;
-    }
-
-    .x-shift-slider {
-      grid-area: x-slide;
-      height: auto;
-      align-self: start;
-      min-width: 10em;
-    }
-
-    .y-shift-number {
-      grid-area: y-num;
-    }
-
-    .y-shift-slider {
-      grid-area: y-slide;
-      writing-mode: vertical-lr;
-      justify-self: left;
-      min-height: 10em;
-    }
-
-    .x-shift-slider,
-    .y-shift-slider {
-      padding: 0;
-    }
-
-    .preview-window {
-      --__grid-color1: rgb(102 102 102);
-      --__grid-color2: rgb(153 153 153);
-      --__grid-color1-disabled: rgba(102 102 102 / 20%);
-      --__grid-color2-disabled: rgba(153 153 153 / 20%);
-
-      &.-light-grid {
-        --__grid-color1: rgb(205 205 205);
-        --__grid-color2: rgb(255 255 255);
-        --__grid-color1-disabled: rgba(205 205 205 / 20%);
-        --__grid-color2-disabled: rgba(255 255 255 / 20%);
-      }
-
-      grid-area: preview;
-      aspect-ratio: 1;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      min-width: 10em;
-      min-height: 10em;
-      background-color: var(--__grid-color2);
-      background-image:
-        linear-gradient(45deg, var(--__grid-color1) 25%, transparent 25%),
-        linear-gradient(-45deg, var(--__grid-color1) 25%, transparent 25%),
-        linear-gradient(45deg, transparent 75%, var(--__grid-color1) 75%),
-        linear-gradient(-45deg, transparent 75%, var(--__grid-color1) 75%);
-      background-size: 20px 20px;
-      background-position: 0 0, 0 10px, 10px -10px, -10px 0;
-      border-radius: var(--roundness);
-
-      &.disabled {
-        background-color: var(--__grid-color2-disabled);
-        background-image:
-          linear-gradient(45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
-          linear-gradient(-45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
-          linear-gradient(45deg, transparent 75%, var(--__grid-color1-disabled) 75%),
-          linear-gradient(-45deg, transparent 75%, var(--__grid-color1-disabled) 75%);
-      }
-
-      .preview-block {
-        width: 33%;
-        height: 33%;
-        border-radius: var(--roundness);
-        background: var(--background);
-      }
-    }
   }
 }
 
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 6a7829c5..0305b55c 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -3,68 +3,13 @@
     class="label shadow-control"
     :class="{ disabled: !present }"
   >
-    <div class="shadow-preview">
-      <label
-        class="header"
-        :class="{ faint: !present }"
-      >
-        {{ $t('settings.style.shadows.offset') }}
-      </label>
-      <input
-        :value="selected?.y"
-        :disabled="!present"
-        :class="{ disabled: !present }"
-        class="input input-number y-shift-number"
-        type="number"
-        @input="e => updateProperty('y', e.target.value)"
-      >
-      <input
-        :value="selected?.y"
-        :disabled="!present"
-        :class="{ disabled: !present }"
-        class="input input-range y-shift-slider"
-        type="range"
-        max="20"
-        min="-20"
-        @input="e => updateProperty('y', e.target.value)"
-      >
-      <div
-        class="preview-window"
-        :class="{ disabled: !present, '-light-grid': lightGrid }"
-      >
-        <div
-          class="preview-block"
-          :style="style"
-        />
-      </div>
-      <input
-        :value="selected?.x"
-        :disabled="!present"
-        :class="{ disabled: !present }"
-        class="input input-number x-shift-number"
-        type="number"
-        @input="e => updateProperty('x', e.target.value)"
-      >
-      <input
-        :value="selected?.x"
-        :disabled="!present"
-        :class="{ disabled: !present }"
-        class="input input-range x-shift-slider"
-        type="range"
-        max="20"
-        min="-20"
-        @input="e => updateProperty('x', e.target.value)"
-      >
-      <Checkbox
-        id="lightGrid"
-        v-model="lightGrid"
-        :disabled="!present"
-        name="lightGrid"
-        class="input-light-grid"
-      >
-        {{ $t('settings.style.shadows.light_grid') }}
-      </Checkbox>
-    </div>
+    <ComponentPreview
+      class="shadow-preview"
+      :shadow-control="true"
+      :shadow="selected"
+      :preview-style="style"
+      :disabled="!present"
+    />
     <div class="shadow-switcher">
       <Select
         id="shadow-list"
-- 
cgit v1.2.3-70-g09d2


From d2a9653ecb027ecabd78a2fb8608b4e1f9e64187 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 24 Sep 2024 19:32:08 +0300
Subject: forgot something again

---
 src/components/component_preview/component_preview.vue | 4 ++--
 src/components/shadow_control/shadow_control.vue       | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/component_preview/component_preview.vue b/src/components/component_preview/component_preview.vue
index 087f48ea..f29284c8 100644
--- a/src/components/component_preview/component_preview.vue
+++ b/src/components/component_preview/component_preview.vue
@@ -187,8 +187,8 @@ export default {
     Checkbox
   },
   methods: {
-    update (axis, value) {
-      this.$emit('update:shadow', { ...this.shadowControl, [axis]: value })
+    updateProperty (axis, value) {
+      this.$emit('update:shadow', { axis, value })
     }
   }
 }
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 0305b55c..8c37e82d 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -9,6 +9,7 @@
       :shadow="selected"
       :preview-style="style"
       :disabled="!present"
+      @update:shadow="({ axis, value }) => updateProperty(axis, value)"
     />
     <div class="shadow-switcher">
       <Select
-- 
cgit v1.2.3-70-g09d2


From 22cc96705ab3af42a6373ccab6df473ba1243fed Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 25 Sep 2024 17:56:34 +0300
Subject: no preview support for shadow control (for themes 3 editor)

---
 src/components/shadow_control/shadow_control.js   | 3 +--
 src/components/shadow_control/shadow_control.scss | 8 ++++++++
 src/components/shadow_control/shadow_control.vue  | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index c9a04e4d..9b946e90 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -34,12 +34,11 @@ const toModel = (object = {}) => ({
 
 export default {
   props: [
-    'modelValue', 'fallback', 'separateInset'
+    'modelValue', 'fallback', 'separateInset', 'noPreview'
   ],
   emits: ['update:modelValue'],
   data () {
     return {
-      lightGrid: false,
       selectedId: 0,
       // TODO there are some bugs regarding display of array (it's not getting updated when deleting for some reason)
       cValue: (this.modelValue ?? this.fallback ?? []).map(toModel)
diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss
index cdaefa88..a374184b 100644
--- a/src/components/shadow_control/shadow_control.scss
+++ b/src/components/shadow_control/shadow_control.scss
@@ -68,6 +68,14 @@
     }
   }
 
+  &.-no-preview {
+    .shadow-tweak {
+      order: 0;
+      flex: 2 0 20em;
+      max-width: 100%;
+    }
+  }
+
   .inset-alert {
     padding: 0.25em 0.5em;
   }
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 8c37e82d..050cf820 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -1,9 +1,10 @@
 <template>
   <div
     class="label shadow-control"
-    :class="{ disabled: !present }"
+    :class="{ disabled: !present, '-no-preview': noPreview }"
   >
     <ComponentPreview
+      v-if="!noPreview"
       class="shadow-preview"
       :shadow-control="true"
       :shadow="selected"
-- 
cgit v1.2.3-70-g09d2


From d234ad8672bd927b4f1147ee57c08be81e637b4c Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sat, 28 Sep 2024 20:20:51 +0300
Subject: properly support "disabled" state of contoller

---
 src/components/shadow_control/shadow_control.js  |  2 +-
 src/components/shadow_control/shadow_control.vue | 68 ++++++++++++------------
 2 files changed, 35 insertions(+), 35 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index 9b946e90..451180f4 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -34,7 +34,7 @@ const toModel = (object = {}) => ({
 
 export default {
   props: [
-    'modelValue', 'fallback', 'separateInset', 'noPreview'
+    'modelValue', 'fallback', 'separateInset', 'noPreview', 'disabled'
   ],
   emits: ['update:modelValue'],
   data () {
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 050cf820..af24f15a 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -1,7 +1,7 @@
 <template>
   <div
     class="label shadow-control"
-    :class="{ disabled: !present, '-no-preview': noPreview }"
+    :class="{ disabled: disabled || !present, '-no-preview': noPreview }"
   >
     <ComponentPreview
       v-if="!noPreview"
@@ -9,7 +9,7 @@
       :shadow-control="true"
       :shadow="selected"
       :preview-style="style"
-      :disabled="!present"
+      :disabled="disabled || !present"
       @update:shadow="({ axis, value }) => updateProperty(axis, value)"
     />
     <div class="shadow-switcher">
@@ -34,7 +34,7 @@
       >
         <button
           class="btn button-default"
-          :disabled="shadowsAreNull"
+          :disabled="disabled || shadowsAreNull"
           @click="add"
         >
           <FAIcon
@@ -44,8 +44,8 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="!moveUpValid"
-          :class="{ disabled: !moveUpValid }"
+          :disabled="disabled || !moveUpValid"
+          :class="{ disabled: disabled || !moveUpValid }"
           @click="moveUp"
         >
           <FAIcon
@@ -55,8 +55,8 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="!moveDnValid"
-          :class="{ disabled: !moveDnValid }"
+          :disabled="disabled || !moveDnValid"
+          :class="{ disabled: disabled || !moveDnValid }"
           @click="moveDn"
         >
           <FAIcon
@@ -66,8 +66,8 @@
         </button>
         <button
           class="btn button-default"
-          :disabled="!present"
-          :class="{ disabled: !present }"
+          :disabled="disabled || !present"
+          :class="{ disabled: disabled || !present }"
           @click="del"
         >
           <FAIcon
@@ -79,34 +79,34 @@
     </div>
     <div class="shadow-tweak">
       <div
-        :class="{ disabled: !present }"
+        :class="{ disabled: disabled || !present }"
         class="name-control style-control"
       >
         <label
           for="name"
           class="label"
-          :class="{ faint: !present }"
+          :class="{ faint: disabled || !present }"
         >
           {{ $t('settings.style.shadows.name') }}
         </label>
         <input
           id="name"
           :value="selected?.name"
-          :disabled="!present"
-          :class="{ disabled: !present }"
+          :disabled="disabled || !present"
+          :class="{ disabled: disabled || !present }"
           name="name"
           class="input input-string"
           @input="e => updateProperty('name', e.target.value)"
         >
       </div>
       <div
-        :disabled="!present"
+        :disabled="disabled || !present"
         class="inset-control style-control"
       >
         <Checkbox
           id="inset"
           :value="selected?.inset"
-          :disabled="!present"
+          :disabled="disabled || !present"
           name="inset"
           class="input-inset input-boolean"
           @input="e => updateProperty('inset', e.target.checked)"
@@ -117,22 +117,22 @@
         </Checkbox>
       </div>
       <div
-        :disabled="!present"
-        :class="{ disabled: !present }"
+        :disabled="disabled || !present"
+        :class="{ disabled: disabled || !present }"
         class="blur-control style-control"
       >
         <label
           for="blur"
           class="label"
-          :class="{ faint: !present }"
+          :class="{ faint: disabled || !present }"
         >
           {{ $t('settings.style.shadows.blur') }}
         </label>
         <input
           id="blur"
           :value="selected?.blur"
-          :disabled="!present"
-          :class="{ disabled: !present }"
+          :disabled="disabled || !present"
+          :class="{ disabled: disabled || !present }"
           name="blur"
           class="input input-range"
           type="range"
@@ -142,9 +142,9 @@
         >
         <input
           :value="selected?.blur"
-          :disabled="!present"
-          :class="{ disabled: !present }"
-          class="input input-number"
+          class="input input-number -small"
+          :disabled="disabled || !present"
+          :class="{ disabled: disabled || !present }"
           type="number"
           min="0"
           @input="e => updateProperty('blur', e.target.value)"
@@ -152,22 +152,22 @@
       </div>
       <div
         class="spread-control style-control"
-        :class="{ disabled: !present || (separateInset && !selected?.inset) }"
+        :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
       >
         <label
           for="spread"
           class="label"
-          :class="{ faint: !present || (separateInset && !selected?.inset) }"
+          :class="{ faint: disabled || !present || (separateInset && !selected?.inset) }"
         >
           {{ $t('settings.style.shadows.spread') }}
         </label>
         <input
           id="spread"
           :value="selected?.spread"
-          :disabled="!present || (separateInset && !selected?.inset)"
-          :class="{ disabled: !present || (separateInset && !selected?.inset) }"
+          :disabled="disabled || !present || (separateInset && !selected?.inset)"
+          :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
           name="spread"
-          class="input input-range"
+          class="input input-number -small"
           type="range"
           max="20"
           min="-20"
@@ -175,16 +175,16 @@
         >
         <input
           :value="selected?.spread"
-          :disabled="{ disabled: !present || (separateInset && !selected?.inset) }"
-          :class="{ disabled: !present || (separateInset && !selected?.inset) }"
-          class="input input-number"
+          class="input input-number -small"
+          :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
+          :disabled="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
           type="number"
           @input="e => updateProperty('spread', e.target.value)"
         >
       </div>
       <ColorInput
         :model-value="selected?.color"
-        :disabled="!present"
+        :disabled="disabled || !present"
         :label="$t('settings.style.common.color')"
         :fallback="currentFallback?.color"
         :show-optional-tickbox="false"
@@ -193,13 +193,13 @@
       />
       <OpacityInput
         :model-value="selected?.alpha"
-        :disabled="!present"
+        :disabled="disabled || !present"
         @update:modelValue="e => updateProperty('alpha', e)"
       />
       <i18n-t
         scope="global"
         keypath="settings.style.shadows.hintV3"
-        :class="{ faint: !present }"
+        :class="{ faint: disabled || !present }"
         tag="p"
       >
         <code>--variable,mod</code>
-- 
cgit v1.2.3-70-g09d2


From 0cec6dc35641c406b22e997f4106b81d33bfc96c Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sat, 28 Sep 2024 20:33:30 +0300
Subject: better small shadow-tweak styles

---
 src/components/shadow_control/shadow_control.scss | 6 +++++-
 src/components/shadow_control/shadow_control.vue  | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

(limited to 'src/components/shadow_control/shadow_control.vue')

diff --git a/src/components/shadow_control/shadow_control.scss b/src/components/shadow_control/shadow_control.scss
index a374184b..dd049023 100644
--- a/src/components/shadow_control/shadow_control.scss
+++ b/src/components/shadow_control/shadow_control.scss
@@ -71,9 +71,13 @@
   &.-no-preview {
     .shadow-tweak {
       order: 0;
-      flex: 2 0 20em;
+      flex: 2 0 8em;
       max-width: 100%;
     }
+
+    .input-range {
+      min-width: 5em;
+    }
   }
 
   .inset-alert {
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index af24f15a..e1d20191 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -167,7 +167,7 @@
           :disabled="disabled || !present || (separateInset && !selected?.inset)"
           :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
           name="spread"
-          class="input input-number -small"
+          class="input input-range"
           type="range"
           max="20"
           min="-20"
-- 
cgit v1.2.3-70-g09d2

