Web Inspector: Styles: variable swatch not shown for var() with a fallback
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / SpreadsheetStyleProperty.js
index 93d4d16..ed1d7b5 100644 (file)
@@ -53,6 +53,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
 
         if (!this._readOnly) {
             this._element.tabIndex = -1;
+            property.addEventListener(WI.CSSProperty.Event.ModifiedChanged, this.updateStatus, this);
 
             this._element.addEventListener("blur", (event) => {
                 // Keep selection after tabbing out of Web Inspector window and back.
@@ -72,8 +73,6 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
                 this._toggle();
                 this._select();
             }, this._element);
-
-            this._element.copyHandler = this;
         }
     }
 
@@ -137,6 +136,9 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
 
     remove(replacement = null)
     {
+        if (this._delegate && typeof this._delegate.spreadsheetStylePropertyWillRemove === "function")
+            this._delegate.spreadsheetStylePropertyWillRemove(this);
+
         this.element.remove();
 
         if (replacement)
@@ -145,9 +147,6 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
             this._property.remove();
 
         this.detached();
-
-        if (this._delegate && typeof this._delegate.spreadsheetStylePropertyRemoved === "function")
-            this._delegate.spreadsheetStylePropertyRemoved(this);
     }
 
     update()
@@ -312,7 +311,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         if (!this._property.enabled)
             classNames.push("disabled");
 
-        if (this._property.modified)
+        if (this._property.modified && this._property.name && this._property.rawValue)
             classNames.push("modified");
 
         if (this._selected)
@@ -335,11 +334,6 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         return matches;
     }
 
-    handleCopyEvent(event)
-    {
-        this._delegate.spreadsheetStylePropertyCopy(event, this);
-    }
-
     // SpreadsheetTextField delegate
 
     spreadsheetTextFieldWillStartEditing(textField)
@@ -358,16 +352,14 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
 
     spreadsheetTextFieldDidCommit(textField, {direction})
     {
-        let propertyName = this._nameTextField.value.trim();
-        let propertyValue = this._valueTextField.value.trim();
         let willRemoveProperty = false;
         let isEditingName = textField === this._nameTextField;
 
-        if (!propertyName || (!propertyValue && !isEditingName && direction === "forward"))
+        if (!this._property.name || (!this._property.rawValue && !isEditingName && direction === "forward"))
             willRemoveProperty = true;
 
         if (!isEditingName && !willRemoveProperty)
-            this._renderValue(propertyValue);
+            this._renderValue(this._property.rawValue);
 
         if (direction === "forward") {
             if (isEditingName && !willRemoveProperty) {
@@ -401,7 +393,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         }
 
         if (textField === this._valueTextField)
-            this._renderValue(this._valueElement.textContent);
+            this._renderValue(this._property.rawValue);
 
         if (typeof this._delegate.spreadsheetStylePropertyFocusMoved === "function")
             this._delegate.spreadsheetStylePropertyFocusMoved(this, {direction: null});
@@ -455,18 +447,8 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         const maxValueLength = 150;
         let tokens = WI.tokenizeCSSValue(value);
 
-        if (this._property.enabled) {
-            // FIXME: <https://webkit.org/b/178636> Web Inspector: Styles: Make inline widgets work with CSS functions (var(), calc(), etc.)
-
-            // CSS variables may contain color - display color picker for them.
-            if (this._property.variable || WI.CSSKeywordCompletions.isColorAwareProperty(this._property.name)) {
-                tokens = this._addGradientTokens(tokens);
-                tokens = this._addColorTokens(tokens);
-            }
-            tokens = this._addTimingFunctionTokens(tokens, "cubic-bezier");
-            tokens = this._addTimingFunctionTokens(tokens, "spring");
-            tokens = this._addVariableTokens(tokens);
-        }
+        if (this._property.enabled)
+            tokens = this._replaceSpecialTokens(tokens);
 
         tokens = tokens.map((token) => {
             if (token instanceof Element)
@@ -501,11 +483,18 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         this._valueElement.append(...tokens);
     }
 
-    _createInlineSwatch(type, text, valueObject)
+    _createInlineSwatch(type, contents, valueObject)
     {
         let tokenElement = document.createElement("span");
         let innerElement = document.createElement("span");
-        innerElement.textContent = text;
+        for (let item of contents) {
+            if (item instanceof Node)
+                innerElement.appendChild(item);
+            else if (typeof item === "object")
+                innerElement.append(item.value);
+            else
+                innerElement.append(item);
+        }
 
         let readOnly = !this._isEditable();
         let swatch = new WI.InlineSwatch(type, valueObject, readOnly);
@@ -522,6 +511,12 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
                 this._renderValue(this._property.rawValue);
         }, this);
 
+        if (type === WI.InlineSwatch.Type.Variable) {
+            swatch.value = () => {
+                return this._property.ownerStyle.nodeStyles.computedStyle.resolveVariableValue(innerElement.textContent);
+            };
+        }
+
         if (this._delegate && typeof this._delegate.stylePropertyInlineSwatchActivated === "function") {
             swatch.addEventListener(WI.InlineSwatch.Event.Activated, () => {
                 this._delegate.stylePropertyInlineSwatchActivated();
@@ -539,6 +534,25 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         return tokenElement;
     }
 
+    _replaceSpecialTokens(tokens)
+    {
+        // FIXME: <https://webkit.org/b/178636> Web Inspector: Styles: Make inline widgets work with CSS functions (var(), calc(), etc.)
+
+        tokens = this._addVariableTokens(tokens);
+
+        if (this._property.variable || WI.CSSKeywordCompletions.isColorAwareProperty(this._property.name)) {
+            tokens = this._addGradientTokens(tokens);
+            tokens = this._addColorTokens(tokens);
+        }
+
+        if (this._property.variable || WI.CSSKeywordCompletions.isTimingFunctionAwareProperty(this._property.name)) {
+            tokens = this._addTimingFunctionTokens(tokens, "cubic-bezier");
+            tokens = this._addTimingFunctionTokens(tokens, "spring");
+        }
+
+        return tokens;
+    }
+
     _addGradientTokens(tokens)
     {
         let gradientRegex = /^(repeating-)?(linear|radial)-gradient$/i;
@@ -564,7 +578,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
                 let text = rawTokens.map((token) => token.value).join("");
                 let gradient = WI.Gradient.fromString(text);
                 if (gradient)
-                    newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Gradient, text, gradient));
+                    newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Gradient, rawTokens, gradient));
                 else
                     newTokens.push(...rawTokens);
 
@@ -583,7 +597,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         let pushPossibleColorToken = (text, ...rawTokens) => {
             let color = WI.Color.fromString(text);
             if (color)
-                newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Color, text, color));
+                newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Color, rawTokens, color));
             else
                 newTokens.push(...rawTokens);
         };
@@ -650,7 +664,7 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
                 }
 
                 if (valueObject)
-                    newTokens.push(this._createInlineSwatch(inlineSwatchType, text, valueObject));
+                    newTokens.push(this._createInlineSwatch(inlineSwatchType, rawTokens, valueObject));
                 else
                     newTokens.push(...rawTokens);
 
@@ -671,8 +685,10 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
         for (let i = 0; i < tokens.length; i++) {
             let token = tokens[i];
             if (token.value === "var" && token.type && token.type.includes("atom")) {
-                startIndex = i;
-                openParenthesis = 0;
+                if (isNaN(startIndex)) {
+                    startIndex = i;
+                    openParenthesis = 0;
+                }
             } else if (token.value === "(" && !isNaN(startIndex))
                 ++openParenthesis;
             else if (token.value === ")" && !isNaN(startIndex)) {
@@ -681,14 +697,22 @@ WI.SpreadsheetStyleProperty = class SpreadsheetStyleProperty extends WI.Object
                     continue;
 
                 let rawTokens = tokens.slice(startIndex, i + 1);
-                let tokenValues = rawTokens.map((token) => token.value);
-                let variableName = tokenValues.find((value, i) => value.startsWith("--") && /\bvariable-2\b/.test(rawTokens[i].type));
-
-                const dontCreateIfMissing = true;
-                let variableProperty = this._property.ownerStyle.nodeStyles.computedStyle.propertyForName(variableName, dontCreateIfMissing);
-                if (variableProperty) {
-                    let valueObject = variableProperty.value.trim();
-                    newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Variable, tokenValues.join(""), valueObject));
+                let variableNameIndex = rawTokens.findIndex((token) => token.value.startsWith("--") && /\bvariable-2\b/.test(token.type));
+                if (variableNameIndex !== -1) {
+                    let contents = [];
+                    let fallbackStartIndex = rawTokens.findIndex((value, i) => i > variableNameIndex + 1 && /\bm-css\b/.test(value.type));
+                    if (fallbackStartIndex !== -1) {
+                        contents = contents.concat(rawTokens.slice(0, fallbackStartIndex));
+                        contents = contents.concat(this._replaceSpecialTokens(rawTokens.slice(fallbackStartIndex, i)));
+                    } else
+                        contents = contents.concat(rawTokens.slice(0, i));
+                    contents.push(token);
+
+                    let text = rawTokens.reduce((accumulator, token) => accumulator + token.value, "");
+                    if (this._property.ownerStyle.nodeStyles.computedStyle.resolveVariableValue(text))
+                        newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Variable, contents));
+                    else
+                        newTokens = newTokens.concat(contents);
                 } else {
                     this._hasInvalidVariableValue = true;
                     newTokens.push(...rawTokens);