This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new ec59d62ba7c Edge3 inherit core UI Theme (#60417)
ec59d62ba7c is described below
commit ec59d62ba7c96ace05b3b0d9f95c524bf1cc4262
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Mon Jan 26 17:59:53 2026 +0100
Edge3 inherit core UI Theme (#60417)
---
.../providers/edge3/plugins/www/dist/main.umd.cjs | 16 +++++++--------
.../providers/edge3/plugins/www/src/global.d.ts | 24 ++++++++++++++++++++++
.../providers/edge3/plugins/www/src/main.tsx | 7 ++++++-
.../providers/edge3/plugins/www/src/theme.ts | 2 +-
providers/edge3/www-hash.txt | 2 +-
5 files changed, 40 insertions(+), 11 deletions(-)
diff --git
a/providers/edge3/src/airflow/providers/edge3/plugins/www/dist/main.umd.cjs
b/providers/edge3/src/airflow/providers/edge3/plugins/www/dist/main.umd.cjs
index 28f9386de0d..78d3433fc76 100644
--- a/providers/edge3/src/airflow/providers/edge3/plugins/www/dist/main.umd.cjs
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/dist/main.umd.cjs
@@ -1,14 +1,14 @@
-(function(h,S){typeof exports=="object"&&typeof
module<"u"?module.exports=S(require("react/jsx-runtime"),require("react"),require("react-router-dom"),require("react-dom")):typeof
define=="function"&&define.amd?define(["react/jsx-runtime","react","react-router-dom","react-dom"],S):(h=typeof
globalThis<"u"?globalThis:h||self,h.AirflowPlugin=S(h.ReactJSXRuntime,h.React,h.ReactRouterDOM,h.ReactDOM))})(this,(function(h,S,st,yo){"use
strict";function pm(e){const t=Object.create(null,{[Symbol.t [...]
+(function(h,S){typeof exports=="object"&&typeof
module<"u"?module.exports=S(require("react/jsx-runtime"),require("react"),require("react-router-dom"),require("react-dom")):typeof
define=="function"&&define.amd?define(["react/jsx-runtime","react","react-router-dom","react-dom"],S):(h=typeof
globalThis<"u"?globalThis:h||self,h.AirflowPlugin=S(h.ReactJSXRuntime,h.React,h.ReactRouterDOM,h.ReactDOM))})(this,(function(h,S,st,yo){"use
strict";function gm(e){const t=Object.create(null,{[Symbol.t [...]
<svg width="46" height="15" style="left: -15.5px; position: absolute;
top: 0; filter: drop-shadow(rgba(0, 0, 0, 0.4) 0px 1px 1.1px);">
<g transform="translate(2 3)">
<path fill-rule="evenodd" d="M 15 4.5L 15 2L 11.5 5.5L 15 9L 15 6.5L
31 6.5L 31 9L 34.5 5.5L 31 2L 31 4.5Z" style="stroke-width: 2px; stroke:
white;"></path>
<path fill-rule="evenodd" d="M 15 4.5L 15 2L 11.5 5.5L 15 9L 15 6.5L
31 6.5L 31 9L 34.5 5.5L 31 2L 31 4.5Z"></path>
</g>
- </svg>`,r.body.appendChild(n)};function
PC(e,t){if(!(!e||!t.isActiveElement(e)))try{const{selectionStart:r,selectionEnd:n,value:o}=e;return
r==null||n==null?void 0:{start:r,end:n,value:o}}catch{return}}function
NC(e,t,r){if(!(!e||!r.isActiveElement(e))){if(!t){const
n=e.value.length;e.setSelectionRange(n,n);return}try{const
n=e.value,{start:o,end:i,value:s}=t;if(n===s){e.setSelectionRange(o,i);return}const
a=ah(s,n,o),l=o===i?a:ah(s,n,i),c=Math.max(0,Math.min(a,n.length)),d=Math.ma
[...]
+ </svg>`,r.body.appendChild(n)};function
TC(e,t){if(!(!e||!t.isActiveElement(e)))try{const{selectionStart:r,selectionEnd:n,value:o}=e;return
r==null||n==null?void 0:{start:r,end:n,value:o}}catch{return}}function
PC(e,t,r){if(!(!e||!r.isActiveElement(e))){if(!t){const
n=e.value.length;e.setSelectionRange(n,n);return}try{const
n=e.value,{start:o,end:i,value:s}=t;if(n===s){e.setSelectionRange(o,i);return}const
a=ah(s,n,o),l=o===i?a:ah(s,n,i),c=Math.max(0,Math.min(a,n.length)),d=Math.ma
[...]
)+\\(\\s*max(-device)?-${e}`,"i"),min:new
RegExp(`\\(\\s*min(-device)?-${e}`,"i"),maxMin:new
RegExp(`(!?\\(\\s*max(-device)?-${e})(.|
-)+\\(\\s*min(-device)?-${e}`,"i"),max:new
RegExp(`\\(\\s*max(-device)?-${e}`,"i")}),lw=lf("width"),cw=lf("height"),cf=e=>({isMin:pf(e.minMax,e.maxMin,e.min),isMax:pf(e.maxMin,e.minMax,e.max)}),{isMin:Ua,isMax:df}=cf(lw),{isMin:Ga,isMax:uf}=cf(cw),hf=/print/i,ff=/^print$/i,dw=/(-?\d*\.?\d+)(ch|em|ex|px|rem)/,uw=/(\d)/,no=Number.MAX_VALUE,hw={ch:8.8984375,em:16,rem:16,ex:8.296875,px:1};function
gf(e){const t=dw.exec(e)||(Ua(e)||Ga(e)?uw.exec(e):null);if(!t)return
no;if(t[0]==="0")return 0; [...]
-`).forEach(function(s){o=s.indexOf(":"),r=s.substring(0,o).trim().toLowerCase(),n=s.substring(o+1).trim(),!(!r||t[r]&&sP[r])&&(r==="set-cookie"?t[r]?t[r].push(n):t[r]=[n]:t[r]=t[r]?t[r]+",
"+n:n)}),t},hp=Symbol("internals");function go(e){return
e&&String(e).trim().toLowerCase()}function ji(e){return
e===!1||e==null?e:I.isArray(e)?e.map(ji):String(e)}function lP(e){const
t=Object.create(null),r=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let
n;for(;n=r.exec(e);)t[n[1]]=n[2];return t}const cP=e=>/ [...]
-`)}getSetCookie(){return
this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static
from(t){return t instanceof this?t:new this(t)}static concat(t,...r){const
n=new this(t);return r.forEach(o=>n.set(o)),n}static accessor(t){const
n=(this[hp]=this[hp]={accessors:{}}).accessors,o=this.prototype;function
i(s){const a=go(s);n[a]||(uP(o,s),n[a]=!0)}return
I.isArray(t)?t.forEach(i):i(t),this}};Ye.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-A
[...]
-`+s.map(Op).join(`
-`):" "+Op(s[0]):"as no adapter specified";throw new G("There is no suitable
adapter to dispatch the request "+a,"ERR_NOT_SUPPORT")}return o}const
Ip={getAdapter:TP,adapters:Sl};function
Cl(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw
new yn(null,e)}function Tp(e){return
Cl(e),e.headers=Ye.from(e.headers),e.data=xl.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded"
[...]
-`+i):n.stack=i}catch{}}throw n}}_request(t,r){typeof
t=="string"?(r=r||{},r.url=t):r=t||{},r=Wr(this.defaults,r);const{transitional:n,paramsSerializer:o,headers:i}=r;n!==void
0&&Ki.assertOptions(n,{silentJSONParsing:Ot.transitional(Ot.boolean),forcedJSONParsing:Ot.transitional(Ot.boolean),clarifyTimeoutError:Ot.transitional(Ot.boolean)},!1),o!=null&&(I.isFunction(o)?r.paramsSerializer={serialize:o}:Ki.assertOptions(o,{encode:Ot.function,serialize:Ot.function},!0)),r.allowAbsoluteUrls!==v
[...]
+)+\\(\\s*min(-device)?-${e}`,"i"),max:new
RegExp(`\\(\\s*max(-device)?-${e}`,"i")}),aw=lf("width"),lw=lf("height"),cf=e=>({isMin:pf(e.minMax,e.maxMin,e.min),isMax:pf(e.maxMin,e.minMax,e.max)}),{isMin:ja,isMax:df}=cf(aw),{isMin:Ga,isMax:uf}=cf(lw),hf=/print/i,ff=/^print$/i,cw=/(-?\d*\.?\d+)(ch|em|ex|px|rem)/,dw=/(\d)/,ro=Number.MAX_VALUE,uw={ch:8.8984375,em:16,rem:16,ex:8.296875,px:1};function
gf(e){const t=cw.exec(e)||(ja(e)||Ga(e)?dw.exec(e):null);if(!t)return
ro;if(t[0]==="0")return 0; [...]
+`).forEach(function(s){o=s.indexOf(":"),r=s.substring(0,o).trim().toLowerCase(),n=s.substring(o+1).trim(),!(!r||t[r]&&iP[r])&&(r==="set-cookie"?t[r]?t[r].push(n):t[r]=[n]:t[r]=t[r]?t[r]+",
"+n:n)}),t},dp=Symbol("internals");function fo(e){return
e&&String(e).trim().toLowerCase()}function Ui(e){return
e===!1||e==null?e:I.isArray(e)?e.map(Ui):String(e)}function aP(e){const
t=Object.create(null),r=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let
n;for(;n=r.exec(e);)t[n[1]]=n[2];return t}const lP=e=>/ [...]
+`)}getSetCookie(){return
this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static
from(t){return t instanceof this?t:new this(t)}static concat(t,...r){const
n=new this(t);return r.forEach(o=>n.set(o)),n}static accessor(t){const
n=(this[dp]=this[dp]={accessors:{}}).accessors,o=this.prototype;function
i(s){const a=fo(s);n[a]||(dP(o,s),n[a]=!0)}return
I.isArray(t)?t.forEach(i):i(t),this}};Ye.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-A
[...]
+`+s.map(wp).join(`
+`):" "+wp(s[0]):"as no adapter specified";throw new j("There is no suitable
adapter to dispatch the request "+a,"ERR_NOT_SUPPORT")}return o}const
Ep={getAdapter:IP,adapters:Sl};function
Cl(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw
new go(null,e)}function Op(e){return
Cl(e),e.headers=Ye.from(e.headers),e.data=xl.call(e,e.transformRequest),["post","put","patch"].indexOf(e.method)!==-1&&e.headers.setContentType("application/x-www-form-urlencoded"
[...]
+`+i):n.stack=i}catch{}}throw n}}_request(t,r){typeof
t=="string"?(r=r||{},r.url=t):r=t||{},r=Wr(this.defaults,r);const{transitional:n,paramsSerializer:o,headers:i}=r;n!==void
0&&Ki.assertOptions(n,{silentJSONParsing:Ot.transitional(Ot.boolean),forcedJSONParsing:Ot.transitional(Ot.boolean),clarifyTimeoutError:Ot.transitional(Ot.boolean)},!1),o!=null&&(I.isFunction(o)?r.paramsSerializer={serialize:o}:Ki.assertOptions(o,{encode:Ot.function,serialize:Ot.function},!0)),r.allowAbsoluteUrls!==v
[...]
diff --git
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/global.d.ts
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/global.d.ts
new file mode 100644
index 00000000000..bd915e81c1a
--- /dev/null
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/global.d.ts
@@ -0,0 +1,24 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export type global = object;
+
+declare global {
+ var ChakraUISystem: SystemContext | undefined;
+}
diff --git
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/main.tsx
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/main.tsx
index 1178a206892..60cca732e88 100644
--- a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/main.tsx
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/main.tsx
@@ -24,7 +24,7 @@ import { FC } from "react";
import { ColorModeProvider } from "src/context/colorMode";
import { EdgeLayout } from "src/layouts/EdgeLayout";
-import { system } from "./theme";
+import { localSystem } from "./theme";
export type PluginComponentProps = object;
@@ -37,6 +37,11 @@ const PluginComponent: FC<PluginComponentProps> = () => {
const baseUrl = new URL(baseHref, globalThis.location.origin);
OpenAPI.BASE = baseUrl.pathname.replace(/\/$/, ""); // Remove trailing slash
+ // Use the globalChakraUISystem provided by the Airflow Core UI,
+ // so the plugin has a consistent theming with the host Airflow UI,
+ // fallback to localSystem for local development.
+ const system = globalThis.ChakraUISystem ?? localSystem;
+
const queryClient = new QueryClient({
defaultOptions: {
queries: {
diff --git
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/theme.ts
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/theme.ts
index 53191d0d49c..836593e97a8 100644
--- a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/theme.ts
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/theme.ts
@@ -394,7 +394,7 @@ export const customConfig = defineConfig({
},
});
-export const system = createSystem(defaultConfig, customConfig);
+export const localSystem = createSystem(defaultConfig, customConfig);
// Utility function to resolve CSS variables to their computed values
// See: https://github.com/chakra-ui/panda/discussions/2200
diff --git a/providers/edge3/www-hash.txt b/providers/edge3/www-hash.txt
index 5a4297299ba..8af5dc5e2e7 100644
--- a/providers/edge3/www-hash.txt
+++ b/providers/edge3/www-hash.txt
@@ -1 +1 @@
-291c7da0301e5e0b27520fb7cfeb0bdcbfe4c70e45237ffce5cb7b4cbb247539
+266c0ab94927b8af245ff13702284b5bf316788cd314da1ee93cca1e21987ad5