This is an automated email from the ASF dual-hosted git repository.

ovilia pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/echarts-theme-builder.git

commit 1f1d08b46385fc956a3941003616ea6d5ed60ded
Author: Ovilia <[email protected]>
AuthorDate: Wed Sep 24 15:06:16 2025 +0800

    feat: update theme
---
 src/components/ThemePanel.vue | 131 ++++++++++++++++++++++++++++++++++++++++--
 src/utils/themeGenerator.ts   |   6 +-
 2 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/src/components/ThemePanel.vue b/src/components/ThemePanel.vue
index 2e641af..a95d5cb 100644
--- a/src/components/ThemePanel.vue
+++ b/src/components/ThemePanel.vue
@@ -127,22 +127,22 @@
         <div class="panel-content">
           <van-field
             v-model="gridLeft"
-            :label="$t('grid.left')"
+            :label="$t('position.left')"
             @blur="validateGridValue('left')"
           />
           <van-field
             v-model="gridRight"
-            :label="$t('grid.right')"
+            :label="$t('position.right')"
             @blur="validateGridValue('right')"
           />
           <van-field
             v-model="gridTop"
-            :label="$t('grid.top')"
+            :label="$t('position.top')"
             @blur="validateGridValue('top')"
           />
           <van-field
             v-model="gridBottom"
-            :label="$t('grid.bottom')"
+            :label="$t('position.bottom')"
             @blur="validateGridValue('bottom')"
           />
         </div>
@@ -207,6 +207,28 @@
             v-model="theme.legendTextColor"
             :label="$t('colors.legendText')"
           />
+
+          <h4>{{ $t('panel.legendPosition') }}</h4>
+          <van-field
+            v-model="legendLeft"
+            :label="$t('position.left')"
+            @blur="validateLegendValue('left')"
+          />
+          <van-field
+            v-model="legendRight"
+            :label="$t('position.right')"
+            @blur="validateLegendValue('right')"
+          />
+          <van-field
+            v-model="legendTop"
+            :label="$t('position.top')"
+            @blur="validateLegendValue('top')"
+          />
+          <van-field
+            v-model="legendBottom"
+            :label="$t('position.bottom')"
+            @blur="validateLegendValue('bottom')"
+          />
         </div>
       </van-collapse-item>
 
@@ -457,7 +479,7 @@ interface Props {
 const props = defineProps<Props>()
 
 // Component state
-const activeNames = ref(['functions', 'basic', 'visualMap', 'grid'])  // 
Panels expanded by default
+const activeNames = ref(['functions', 'basic', 'visualMap', 'grid', 'legend']) 
 // Panels expanded by default
 const fileInput = ref<HTMLInputElement>()
 
 // Theme store
@@ -473,6 +495,105 @@ const gridRight = ref(String(theme.gridRight))
 const gridTop = ref(String(theme.gridTop))
 const gridBottom = ref(String(theme.gridBottom))
 
+// Legend position reactive properties
+const legendLeft = ref(String(theme.legendLeft))
+const legendRight = ref(String(theme.legendRight))
+const legendTop = ref(String(theme.legendTop))
+const legendBottom = ref(String(theme.legendBottom))
+
+// Legend value validation function
+const validateLegendValue = (position: 'left' | 'right' | 'top' | 'bottom') => 
{
+  let valueRef;
+
+  switch (position) {
+    case 'left':
+      valueRef = legendLeft;
+      break;
+    case 'right':
+      valueRef = legendRight;
+      break;
+    case 'top':
+      valueRef = legendTop;
+      break;
+    case 'bottom':
+      valueRef = legendBottom;
+      break;
+  }
+
+  const inputValue = valueRef.value.trim();
+
+  // Check if the value is a valid position value (number, percentage, or 
special value)
+  const isValid =
+    // Empty string - will be converted to auto in setOption
+    inputValue === '' ||
+    // Valid number
+    /^[0-9]+$/.test(inputValue) ||
+    // Valid percentage (e.g. 10%, 10.5%)
+    /^[0-9]+(\.[0-9]+)?%$/.test(inputValue) ||
+    // Special values for legend position
+    inputValue === 'auto' ||
+    inputValue === 'center' ||
+    inputValue === 'left' ||
+    inputValue === 'right' ||
+    inputValue === 'top' ||
+    inputValue === 'bottom';
+
+  if (isValid) {
+    // For numeric values, convert to number if it's a pure number
+    const finalValue = inputValue === '' ?
+                       position === 'bottom' ? 10 :
+                       position === 'left' ? 'center' : 'auto' :
+                       (/^[0-9]+$/.test(inputValue)) ? parseInt(inputValue, 
10) : inputValue;
+
+    // Update the corresponding theme property
+    switch (position) {
+      case 'left':
+        theme.legendLeft = finalValue;
+        break;
+      case 'right':
+        theme.legendRight = finalValue;
+        break;
+      case 'top':
+        theme.legendTop = finalValue;
+        break;
+      case 'bottom':
+        theme.legendBottom = finalValue;
+        break;
+    }
+  } else {
+    // If invalid, reset to default values
+    let defaultValue;
+    switch (position) {
+      case 'left':
+        defaultValue = 'center';
+        break;
+      case 'bottom':
+        defaultValue = 10;
+        break;
+      default:
+        defaultValue = 'auto';
+    }
+
+    valueRef.value = String(defaultValue);
+
+    // Set the theme property to default value
+    switch (position) {
+      case 'left':
+        theme.legendLeft = 'center';
+        break;
+      case 'right':
+        theme.legendRight = 'auto';
+        break;
+      case 'top':
+        theme.legendTop = 'auto';
+        break;
+      case 'bottom':
+        theme.legendBottom = 10;
+        break;
+    }
+  }
+}
+
 // Grid value validation function
 const validateGridValue = (position: 'left' | 'right' | 'top' | 'bottom') => {
   let valueRef;
diff --git a/src/utils/themeGenerator.ts b/src/utils/themeGenerator.ts
index 20b33c9..6ef822d 100644
--- a/src/utils/themeGenerator.ts
+++ b/src/utils/themeGenerator.ts
@@ -196,7 +196,11 @@ export function generateEChartsTheme(themeData: ThemeData, 
isToExport: boolean =
     legend: {
       textStyle: {
         color: themeData.legendTextColor
-      }
+      },
+      left: themeData.legendLeft === '' ? 'center' : themeData.legendLeft,
+      right: themeData.legendRight === '' ? 'auto' : themeData.legendRight,
+      top: themeData.legendTop === '' ? 'auto' : themeData.legendTop,
+      bottom: themeData.legendBottom === '' ? 10 : themeData.legendBottom
     },
     tooltip: {
       axisPointer: {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to