codeant-ai-for-open-source[bot] commented on code in PR #37805:
URL: https://github.com/apache/superset/pull/37805#discussion_r2783028241


##########
superset-frontend/src/features/themes/AccessibilityScore.tsx:
##########
@@ -0,0 +1,534 @@
+/**
+ * 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.
+ */
+
+import { useMemo, useState, useCallback } from 'react';
+import { t } from '@apache-superset/core';
+import { css, styled, useTheme } from '@apache-superset/core/ui';
+import {
+  Progress,
+  Collapse,
+  Tooltip,
+  Button,
+} from '@superset-ui/core/components';
+import { Icons } from '@superset-ui/core/components/Icons';
+import { Typography } from '@superset-ui/core/components/Typography';
+import {
+  analyzeThemeAccessibility,
+  formatContrastRatio,
+  getScoreColor,
+  type AccessibilityAnalysis,
+  type ContrastIssue,
+  WCAG_REQUIREMENTS,
+} from 'src/theme/accessibility';
+
+interface AccessibilityScoreProps {
+  /** JSON string of the theme configuration */
+  themeJson: string | undefined;
+}
+
+const StyledContainer = styled.div`
+  ${({ theme }) => css`
+    margin-top: ${theme.sizeUnit * 4}px;
+    padding: ${theme.sizeUnit * 3}px;
+    background: ${theme.colorBgContainer};
+    border: 1px solid ${theme.colorBorderSecondary};
+    border-radius: ${theme.borderRadius}px;
+  `}
+`;
+
+const StyledHeader = styled.div`
+  ${({ theme }) => css`
+    display: flex;
+    align-items: center;
+    gap: ${theme.sizeUnit * 2}px;
+    margin-bottom: ${theme.sizeUnit * 2}px;
+
+    .header-icon {
+      font-size: ${theme.fontSizeLG}px;
+    }
+
+    .score-text {
+      font-weight: ${theme.fontWeightStrong};
+    }
+
+    .level-badge {
+      padding: 0 ${theme.sizeUnit}px;
+      border-radius: ${theme.borderRadiusSM}px;
+      font-size: ${theme.fontSizeSM}px;
+      font-weight: ${theme.fontWeightStrong};
+
+      &.level-aaa {
+        background: ${theme.colorSuccessBg};
+        color: ${theme.colorSuccess};
+      }
+      &.level-aa {
+        background: ${theme.colorSuccessBg};
+        color: ${theme.colorSuccess};
+      }
+      &.level-a {
+        background: ${theme.colorWarningBg};
+        color: ${theme.colorWarning};
+      }
+      &.level-fail {
+        background: ${theme.colorErrorBg};
+        color: ${theme.colorError};
+      }
+    }
+  `}
+`;
+
+const StyledProgressWrapper = styled.div`
+  ${({ theme }) => css`
+    margin-bottom: ${theme.sizeUnit * 2}px;
+  `}
+`;
+
+const StyledIssuesList = styled.div`
+  ${({ theme }) => css`
+    .issue-item {
+      display: flex;
+      align-items: flex-start;
+      gap: ${theme.sizeUnit}px;
+      padding: ${theme.sizeUnit}px 0;
+      font-size: ${theme.fontSizeSM}px;
+
+      &:not(:last-child) {
+        border-bottom: 1px solid ${theme.colorBorderSecondary};
+      }
+
+      .issue-icon {
+        flex-shrink: 0;
+        margin-top: 2px;
+      }
+
+      .issue-icon-error {
+        color: ${theme.colorError};
+      }
+
+      .issue-icon-warning {
+        color: ${theme.colorWarning};
+      }
+
+      .issue-content {
+        flex: 1;
+      }
+
+      .issue-tokens {
+        font-family: ${theme.fontFamilyCode};
+        color: ${theme.colorTextSecondary};
+      }
+
+      .issue-ratio {
+        font-weight: ${theme.fontWeightStrong};
+        color: ${theme.colorError};
+      }
+
+      .issue-required {
+        color: ${theme.colorTextTertiary};
+      }
+
+      .color-swatch {
+        display: inline-block;
+        width: 12px;
+        height: 12px;
+        border-radius: 2px;
+        border: 1px solid ${theme.colorBorder};
+        vertical-align: middle;
+        margin: 0 2px;
+      }
+    }
+
+    .ant-collapse {
+      background: transparent;
+      border: none;
+    }
+
+    .ant-collapse-item {
+      border: none !important;
+    }
+
+    .ant-collapse-header {
+      padding: ${theme.sizeUnit}px 0 !important;
+      color: ${theme.colorText} !important;
+    }
+
+    .ant-collapse-content {
+      border: none !important;
+    }
+
+    .ant-collapse-content-box {
+      padding: 0 !important;
+    }
+  `}
+`;
+
+const StyledEmptyState = styled.div`
+  ${({ theme }) => css`
+    text-align: center;
+    color: ${theme.colorTextSecondary};
+    padding: ${theme.sizeUnit * 2}px;
+  `}
+`;
+
+/**
+ * Renders a single contrast issue item
+ */
+function IssueItem({ issue }: { issue: ContrastIssue }) {
+  const IconComponent =
+    issue.severity === 'error'
+      ? Icons.CloseCircleOutlined
+      : Icons.ExclamationCircleOutlined;
+
+  return (
+    <div className="issue-item">
+      <IconComponent
+        className={`issue-icon issue-icon-${issue.severity}`}
+        iconSize="s"
+      />
+      <div className="issue-content">
+        <div>
+          <span className="issue-tokens">
+            {issue.foreground}
+            <span
+              className="color-swatch"
+              style={{ backgroundColor: issue.foregroundColor }}
+              title={issue.foregroundColor}
+            />
+          </span>
+          {' vs '}
+          <span className="issue-tokens">
+            {issue.background}
+            <span
+              className="color-swatch"
+              style={{ backgroundColor: issue.backgroundColor }}
+              title={issue.backgroundColor}
+            />
+          </span>
+        </div>
+        <div>
+          <span className="issue-ratio">
+            {formatContrastRatio(issue.ratio)}
+          </span>
+          <span className="issue-required">
+            {' '}
+            ({t('need')} {formatContrastRatio(issue.required)})
+          </span>
+        </div>
+        <Typography.Text type="secondary">{issue.description}</Typography.Text>
+      </div>
+    </div>
+  );
+}
+
+/**
+ * Checks if a key looks like a color token.
+ */
+function isColorKey(key: string): boolean {
+  return (
+    key.startsWith('color') ||
+    key.startsWith('colorBg') ||
+    key.startsWith('colorText')
+  );
+}
+
+/**
+ * Checks if a theme config has any meaningful color tokens defined.
+ * Returns false for empty objects or objects with no color-related tokens.
+ * Searches recursively through nested objects.
+ */
+function hasColorTokens(themeConfig: Record<string, unknown>): boolean {
+  // Check if there's a token object with any color-related keys
+  const token = themeConfig.token as Record<string, unknown> | undefined;
+  if (token && typeof token === 'object') {
+    const colorKeys = Object.keys(token).filter(isColorKey);
+    if (colorKeys.length > 0) {
+      return true;
+    }
+  }
+
+  // Check root level for color keys
+  const rootColorKeys = Object.keys(themeConfig).filter(isColorKey);
+  if (rootColorKeys.length > 0) {
+    return true;
+  }
+
+  // Check nested objects (e.g., neutrals, brand, semantic)
+  for (const value of Object.values(themeConfig)) {
+    if (value && typeof value === 'object' && !Array.isArray(value)) {
+      const nestedObj = value as Record<string, unknown>;
+      const nestedColorKeys = Object.keys(nestedObj).filter(isColorKey);
+      if (nestedColorKeys.length > 0) {

Review Comment:
   **Suggestion:** The helper that detects whether a theme has color tokens 
only inspects one nesting level of child objects, even though the comment 
claims it searches recursively. This means themes that store color tokens 
deeper than one level will be misclassified as having no colors, disabling 
contrast analysis and causing "No contrast pairs found" messages incorrectly. 
Refactor the nested-object loop to call `hasColorTokens` recursively so 
arbitrarily nested color tokens are detected. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Contrast analysis disabled for deeply nested custom theme tokens.
   - ⚠️ Theme designers misled that themes lack analyzable color data.
   ```
   </details>
   
   ```suggestion
     // Recursively check nested objects (e.g., neutrals, brand, semantic)
     for (const value of Object.values(themeConfig)) {
       if (value && typeof value === 'object' && !Array.isArray(value)) {
         if (hasColorTokens(value as Record<string, unknown>)) {
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Use the theme editor / accessibility tooling that relies on the 
`useThemeAnalysis` hook
   exported from 
`superset-frontend/src/features/themes/AccessibilityScore.tsx:322-352` (this
   is the hook backing the "Analyze Contrast" feature described in the PR).
   
   2. Provide a custom theme JSON where all `color*` tokens are nested deeper 
than one level
   and not under `token`, for example:
   
      
`{"groups":{"neutrals":{"light":{"colorText":"#000000"},"background":{"colorBgBase":"#ffffff"}}}}`.
   
      In this structure, the top-level object and its immediate children do not 
themselves
      have keys starting with `color`.
   
   3. When `useThemeAnalysis(themeJson)` runs, it calls `parseThemeJson()` at
   `AccessibilityScore.tsx:296-316`, which in turn calls `hasColorTokens()` at
   `AccessibilityScore.tsx:255-283` to compute `hasColors`.
   
   4. Inside `hasColorTokens`, only the root object, `themeConfig.token`, and 
the first
   nesting level of child objects are checked for keys matching `isColorKey`. 
Because the
   `colorText` and `colorBgBase` keys live two levels deeper, 
`hasColorTokens()` returns
   `false`, `parseThemeJson()` sets `hasColors: false`, and 
`useThemeAnalysis.runAnalysis()`
   exits early without calling `analyzeThemeAccessibility()`. As a result, the
   AccessibilityScore-based contrast analysis for that theme never runs even 
though valid
   color tokens are present.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/features/themes/AccessibilityScore.tsx
   **Line:** 271:276
   **Comment:**
        *Logic Error: The helper that detects whether a theme has color tokens 
only inspects one nesting level of child objects, even though the comment 
claims it searches recursively. This means themes that store color tokens 
deeper than one level will be misclassified as having no colors, disabling 
contrast analysis and causing "No contrast pairs found" messages incorrectly. 
Refactor the nested-object loop to call `hasColorTokens` recursively so 
arbitrarily nested color tokens are detected.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=c8a96f45a4b3511fa3cb5ec31c38af352353a49c14416d88a6f32ce9e56ee942&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=c8a96f45a4b3511fa3cb5ec31c38af352353a49c14416d88a6f32ce9e56ee942&reaction=dislike'>👎</a>



##########
superset/config.py:
##########
@@ -961,6 +961,86 @@ class D3TimeFormat(TypedDict, total=False):
     "algorithm": "dark",
 }
 
+# Built-in accessibility themes for color vision deficiency
+# These themes are automatically seeded to the database on startup
+# and available for selection in the theme UI
+BUILT_IN_ACCESSIBILITY_THEMES: dict[str, Theme] = {
+    "ACCESSIBILITY_IBM_CARBON": {
+        "token": {
+            **THEME_DEFAULT["token"],
+            # IBM Carbon Design System - WCAG AAA compliant
+            "colorPrimary": "#0F62FE",
+            "colorLink": "#0F62FE",
+            "colorError": "#DA1E28",
+            "colorWarning": "#F1C21B",
+            "colorSuccess": "#24A148",
+            "colorInfo": "#0043CE",
+            "colorText": "#161616",
+            "colorTextSecondary": "#525252",
+            "colorBgBase": "#FFFFFF",
+            "colorBgContainer": "#F4F4F4",
+            "colorBorder": "#8D8D8D",
+            "borderRadius": 4,
+            "fontFamily": "IBM Plex Sans, Inter, Helvetica, Arial, sans-serif",
+            "fontSize": 14,
+            "fontSizeLG": 16,
+            "fontSizeSM": 12,
+            "fontWeightStrong": "600",
+            "colorFillSecondary": "#E8F0FE",
+            "colorBgTextHover": "#E5F0FF",
+            "colorTextDisabled": "#A8A8A8",
+        },
+        "algorithm": "default",
+    },
+    "ACCESSIBILITY_OKABE_ITO": {
+        "token": {
+            **THEME_DEFAULT["token"],
+            # Okabe-Ito palette - optimized for deuteranopia and protanopia
+            "colorBgBase": "#FFFFFF",
+            "colorBgContainer": "#FFFFFF",
+            "colorBgElevated": "#FFFFFF",
+            "colorText": "#000000",
+            "colorTextSecondary": "#1A1A1A",
+            "colorTextTertiary": "#333333",
+            "colorBorder": "#666666",
+            "colorBorderSecondary": "#999999",
+            "colorPrimary": "#0072B2",
+            "colorLink": "#0072B2",
+            "colorInfo": "#56B4E9",
+            "colorSuccess": "#009E73",
+            "colorWarning": "#E69F00",
+            "colorError": "#D55E00",
+            "controlHeight": 32,
+            "borderRadius": 4,
+        },
+        "algorithm": "default",
+    },
+    "ACCESSIBILITY_PAUL_TOL_BRIGHT": {
+        "token": {
+            **THEME_DEFAULT["token"],
+            # Paul Tol's Bright palette - scientifically validated for CVD
+            "colorPrimary": "#4477AA",
+            "colorLink": "#4477AA",
+            "colorError": "#EE6677",
+            "colorWarning": "#CCBB44",
+            "colorSuccess": "#228833",
+            "colorInfo": "#66CCEE",
+            "colorTextBase": "#000000",
+            "colorBgBase": "#FFFFFF",

Review Comment:
   **Suggestion:** In the Paul Tol Bright accessibility theme the primary text 
color is set under a `colorTextBase` key, but the base theme and other themes 
use `colorText`, so this value is likely ignored and the theme will inherit the 
default text color instead of the intended accessible one. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Paul Tol Bright theme ignores intended accessible text color.
   - ⚠️ Accessibility contrast checks misrepresent Paul Tol Bright theme.
   ```
   </details>
   
   ```suggestion
               "colorText": "#000000",
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start Superset with this PR so that `superset/config.py` is loaded and
   `BUILT_IN_ACCESSIBILITY_THEMES` is defined (around lines 964–1042), 
including the
   `"ACCESSIBILITY_PAUL_TOL_BRIGHT"` entry where `"colorTextBase": "#000000"` 
is set at line
   1029.
   
   2. From the Superset UI, open the theme selector/theme admin page (as 
described in the PR
   summary: "UI-based theme administration for admins" using 
`BUILT_IN_ACCESSIBILITY_THEMES`
   from `superset/config.py`) and choose the "Accessibility Paul Tol Bright" 
theme as the
   active/system theme.
   
   3. Load any dashboard or page that uses standard body text (rendered via the 
Ant Design
   theme tokens originating from 
`THEME_DEFAULT`/`BUILT_IN_ACCESSIBILITY_THEMES` in
   `superset/config.py`) and observe that the primary text color remains 
whatever the default
   Ant Design `colorText` is, not the intended black (`#000000`).
   
   4. Compare behavior with the "Accessibility IBM Carbon" and "Accessibility 
Okabe-Ito"
   themes in `superset/config.py` (lines 968–1017), which correctly specify 
`"colorText":
   ...`; note that only `"ACCESSIBILITY_PAUL_TOL_BRIGHT"` uses 
`"colorTextBase"` so its text
   color override is ignored, demonstrating that the key name is inconsistent 
and the
   accessible text color is not applied.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/config.py
   **Line:** 1029:1029
   **Comment:**
        *Logic Error: In the Paul Tol Bright accessibility theme the primary 
text color is set under a `colorTextBase` key, but the base theme and other 
themes use `colorText`, so this value is likely ignored and the theme will 
inherit the default text color instead of the intended accessible one.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=303b4fb03bfbf900e5323c831b5a95d58368d940726d765faf78cf1ee6b9150c&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=303b4fb03bfbf900e5323c831b5a95d58368d940726d765faf78cf1ee6b9150c&reaction=dislike'>👎</a>



##########
superset-frontend/src/theme/accessibility.ts:
##########
@@ -0,0 +1,542 @@
+/**
+ * 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.
+ */
+
+/**
+ * WCAG 2.1 Accessibility utilities for theme contrast analysis.
+ *
+ * This module provides functions to analyze theme configurations for
+ * accessibility compliance, specifically contrast ratios between
+ * text and background colors.
+ *
+ * @see https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
+ */
+
+// eslint-disable-next-line no-restricted-syntax
+import { theme as antdTheme } from 'antd';
+import type { ThemeConfig } from 'antd';
+
+/**
+ * WCAG contrast ratio requirements
+ */
+export const WCAG_REQUIREMENTS = {
+  AA_NORMAL_TEXT: 4.5,
+  AA_LARGE_TEXT: 3.0,
+  AAA_NORMAL_TEXT: 7.0,
+  AAA_LARGE_TEXT: 4.5,
+} as const;
+
+/**
+ * Contrast issue severity levels
+ */
+export type ContrastSeverity = 'error' | 'warning';
+
+/**
+ * Represents a single contrast issue found during analysis
+ */
+export interface ContrastIssue {
+  /** Token name of the foreground color (e.g., 'colorText') */
+  foreground: string;
+  /** Token name of the background color (e.g., 'colorBgBase') */
+  background: string;
+  /** Actual hex color value of the foreground */
+  foregroundColor: string;
+  /** Actual hex color value of the background */
+  backgroundColor: string;
+  /** Calculated contrast ratio */
+  ratio: number;
+  /** Required ratio for AA compliance */
+  required: number;
+  /** Severity: error (fails AA) or warning (fails AAA) */
+  severity: ContrastSeverity;
+  /** Human-readable description of the issue */
+  description: string;
+}
+
+/**
+ * WCAG compliance level
+ */
+export type WCAGLevel = 'AAA' | 'AA' | 'A' | 'Fail';
+
+/**
+ * Complete accessibility analysis result
+ */
+export interface AccessibilityAnalysis {
+  /** Overall score from 0-100 */
+  score: number;
+  /** WCAG compliance level achieved */
+  level: WCAGLevel;
+  /** List of contrast issues found */
+  issues: ContrastIssue[];
+  /** Number of checks that passed AA requirements */
+  passedChecks: number;
+  /** Total number of contrast checks performed */
+  totalChecks: number;
+}
+
+/**
+ * Contrast pairs to check in theme analysis.
+ * Each pair represents a foreground/background color combination
+ * that should meet WCAG contrast requirements.
+ */
+const CONTRAST_PAIRS: Array<{
+  foreground: string;
+  background: string;
+  description: string;
+  isLargeText?: boolean;
+}> = [
+  {
+    foreground: 'colorText',
+    background: 'colorBgBase',
+    description: 'Primary text on base background',
+  },
+  {
+    foreground: 'colorText',
+    background: 'colorBgContainer',
+    description: 'Primary text on container background',
+  },
+  {
+    foreground: 'colorTextSecondary',
+    background: 'colorBgBase',
+    description: 'Secondary text on base background',
+  },
+  {
+    foreground: 'colorTextSecondary',
+    background: 'colorBgContainer',
+    description: 'Secondary text on container background',
+  },
+  {
+    foreground: 'colorTextDescription',
+    background: 'colorBgBase',
+    description: 'Description text on base background',
+  },
+  {
+    foreground: 'colorPrimary',
+    background: 'colorBgBase',
+    description: 'Primary color (buttons/links) on base background',
+  },
+  {
+    foreground: 'colorPrimary',
+    background: 'colorBgContainer',
+    description: 'Primary color on container background',
+  },
+  {
+    foreground: 'colorError',
+    background: 'colorBgBase',
+    description: 'Error text on base background',
+  },
+  {
+    foreground: 'colorError',
+    background: 'colorBgContainer',
+    description: 'Error text on container background',
+  },
+  {
+    foreground: 'colorWarning',
+    background: 'colorBgBase',
+    description: 'Warning text on base background',
+  },
+  {
+    foreground: 'colorSuccess',
+    background: 'colorBgBase',
+    description: 'Success text on base background',
+  },
+  {
+    foreground: 'colorLink',
+    background: 'colorBgBase',
+    description: 'Link text on base background',
+  },
+  {
+    foreground: 'colorTextHeading',
+    background: 'colorBgBase',
+    description: 'Heading text on base background',
+    isLargeText: true,
+  },
+];
+
+/**
+ * Converts a hex color string to RGB values (0-255).
+ * Supports 3-char, 6-char, and 8-char (with alpha) hex formats.
+ */
+function hexToRgb(hex: string): [number, number, number] | null {
+  const cleanHex = hex.replace(/^#/, '');
+
+  let fullHex = cleanHex;
+
+  // Handle shorthand (#fff -> #ffffff)
+  if (cleanHex.length === 3) {
+    fullHex = cleanHex
+      .split('')
+      .map(c => c + c)
+      .join('');
+  }
+
+  // Handle 8-char hex (with alpha) - just take the first 6 chars
+  if (fullHex.length === 8) {
+    fullHex = fullHex.substring(0, 6);
+  }
+
+  if (fullHex.length !== 6) {
+    return null;
+  }
+
+  const r = parseInt(fullHex.substring(0, 2), 16);
+  const g = parseInt(fullHex.substring(2, 4), 16);
+  const b = parseInt(fullHex.substring(4, 6), 16);
+
+  if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
+    return null;
+  }
+
+  return [r, g, b];
+}
+
+/**
+ * Parses an rgba() color string to RGB values.
+ */
+function rgbaToRgb(rgba: string): [number, number, number] | null {
+  const match = rgba.match(
+    /rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*[\d.]+\s*)?\)/,
+  );
+  if (!match) return null;
+  return [
+    parseInt(match[1], 10),
+    parseInt(match[2], 10),
+    parseInt(match[3], 10),
+  ];
+}
+
+/**
+ * Converts any color format to a normalized hex string.
+ * Handles hex (3, 6, or 8 char), rgb(), and rgba() formats.
+ */
+function normalizeColor(color: string): string | null {
+  if (!color || typeof color !== 'string') return null;
+
+  const trimmed = color.trim();
+
+  // Handle hex colors
+  if (trimmed.startsWith('#')) {
+    const rgb = hexToRgb(trimmed);
+    if (!rgb) return null;
+    return `#${rgb.map(c => c.toString(16).padStart(2, '0')).join('')}`;
+  }
+
+  // Handle rgb/rgba colors
+  if (trimmed.startsWith('rgb')) {
+    const rgb = rgbaToRgb(trimmed);
+    if (!rgb) return null;
+    return `#${rgb.map(c => c.toString(16).padStart(2, '0')).join('')}`;
+  }
+
+  return null;
+}
+
+/**
+ * Converts algorithm string to Ant Design algorithm function(s).
+ */
+function getAlgorithm(
+  algorithmConfig: string | string[] | undefined,
+): ThemeConfig['algorithm'] {
+  const { darkAlgorithm, compactAlgorithm, defaultAlgorithm } = antdTheme;
+
+  if (!algorithmConfig) {
+    return defaultAlgorithm;
+  }
+
+  const algorithms = Array.isArray(algorithmConfig)
+    ? algorithmConfig
+    : [algorithmConfig];
+
+  const algorithmFns = algorithms
+    .map(alg => {
+      switch (alg) {
+        case 'dark':
+          return darkAlgorithm;
+        case 'compact':
+          return compactAlgorithm;
+        default:
+          return defaultAlgorithm;
+      }
+    })
+    .filter(Boolean);
+
+  return algorithmFns.length === 1 ? algorithmFns[0] : algorithmFns;
+}
+
+/**
+ * Flattens nested color tokens from custom theme structures.
+ * Handles formats like { neutrals: { colorText: '#000' }, brand: { 
colorPrimary: '#00f' } }
+ */
+function flattenColorTokens(
+  themeConfig: Record<string, unknown>,
+): Record<string, unknown> {
+  const flattened: Record<string, unknown> = {};
+
+  // First, add any root-level color tokens
+  for (const [key, value] of Object.entries(themeConfig)) {
+    if (key.startsWith('color') && typeof value === 'string') {
+      flattened[key] = value;
+    }
+  }
+
+  // Then, flatten nested objects that might contain color tokens
+  for (const [, value] of Object.entries(themeConfig)) {
+    if (value && typeof value === 'object' && !Array.isArray(value)) {
+      const nestedObj = value as Record<string, unknown>;
+      for (const [nestedKey, nestedValue] of Object.entries(nestedObj)) {
+        if (nestedKey.startsWith('color') && typeof nestedValue === 'string') {
+          // Don't overwrite if already exists (root takes precedence)
+          if (!(nestedKey in flattened)) {
+            flattened[nestedKey] = nestedValue;
+          }
+        }
+      }
+    }
+  }
+
+  return flattened;
+}
+
+/**
+ * Resolves a theme configuration to computed design tokens using Ant Design.
+ * This allows us to analyze themes that only define seed colors.
+ * Also handles custom nested structures by flattening color tokens first.
+ */
+function resolveThemeTokens(
+  themeConfig: Record<string, unknown>,
+): Record<string, unknown> {
+  // First, flatten any custom nested color structures
+  const flattenedColors = flattenColorTokens(themeConfig);
+
+  try {
+    // Build Ant Design ThemeConfig from the user's config
+    // Merge flattened colors with existing token object
+    const tokenConfig = {
+      ...(themeConfig.token as Record<string, unknown>),
+      ...flattenedColors,
+    };
+
+    const antdConfig: ThemeConfig = {
+      token: tokenConfig as ThemeConfig['token'],
+      algorithm: getAlgorithm(themeConfig.algorithm as string | string[]),
+    };
+
+    // Use Ant Design's getDesignToken to compute all tokens
+    const resolvedTokens = antdTheme.getDesignToken(antdConfig);
+
+    // Merge flattened colors back in case Ant Design didn't recognize them
+    return {
+      ...(resolvedTokens as unknown as Record<string, unknown>),
+      ...flattenedColors,
+    };
+  } catch {
+    // If resolution fails, return the flattened colors plus original token 
object
+    return {
+      ...(themeConfig.token as Record<string, unknown>),

Review Comment:
   **Suggestion:** In `resolveThemeTokens`, the object spread 
`...(themeConfig.token as Record<string, unknown>)` will throw a runtime 
TypeError if `themeConfig.token` is `undefined` or `null`, and the same unsafe 
spread is repeated in the catch block, so calling `analyzeThemeAccessibility` 
with a theme config that omits `token` will crash instead of falling back. Use 
a default empty object for `themeConfig.token` and reuse it in both the try and 
catch paths to avoid spreading `undefined`. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Theme contrast analysis crashes for themes without token object.
   - ⚠️ Accessibility analysis unusable for simpler custom theme configs.
   ```
   </details>
   
   ```suggestion
     // Safely handle cases where themeConfig.token is undefined or null
     const baseToken =
       (themeConfig.token as Record<string, unknown> | undefined) ?? {};
   
     try {
       // Build Ant Design ThemeConfig from the user's config
       // Merge flattened colors with existing token object
       const tokenConfig = {
         ...baseToken,
         ...flattenedColors,
       };
   
       const antdConfig: ThemeConfig = {
         token: tokenConfig as ThemeConfig['token'],
         algorithm: getAlgorithm(themeConfig.algorithm as string | string[]),
       };
   
       // Use Ant Design's getDesignToken to compute all tokens
       const resolvedTokens = antdTheme.getDesignToken(antdConfig);
   
       // Merge flattened colors back in case Ant Design didn't recognize them
       return {
         ...(resolvedTokens as unknown as Record<string, unknown>),
         ...flattenedColors,
       };
     } catch {
       // If resolution fails, return the flattened colors plus original token 
object
       return {
         ...baseToken,
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Import and call `analyzeThemeAccessibility` from
   `superset-frontend/src/theme/accessibility.ts:443` with a theme object that 
has root-level
   colors but no `token` property, e.g. `{ colorText: '#000000', colorBgBase: 
'#ffffff' }`.
   
   2. `analyzeThemeAccessibility` calls `resolveThemeTokens(themeConfig)` at
   `superset-frontend/src/theme/accessibility.ts:448`, passing the same object.
   
   3. Inside `resolveThemeTokens` at 
`superset-frontend/src/theme/accessibility.ts:320-333`,
   `flattenColorTokens(themeConfig)` succeeds because it only inspects 
top-level properties
   and does not require `themeConfig.token`.
   
   4. Still in `resolveThemeTokens`, construction of `tokenConfig` at
   `superset-frontend/src/theme/accessibility.ts:328-332` executes `{ 
...(themeConfig.token
   as Record<string, unknown>), ...flattenedColors }`; since 
`themeConfig.token` is
   `undefined`, the spread causes `TypeError: Cannot convert undefined or null 
to object`,
   the catch block then attempts another spread of `themeConfig.token` at
   `superset-frontend/src/theme/accessibility.ts:348-352`, rethrowing the same 
error and
   causing `analyzeThemeAccessibility` to crash instead of returning an 
analysis result.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/theme/accessibility.ts
   **Line:** 326:350
   **Comment:**
        *Possible Bug: In `resolveThemeTokens`, the object spread 
`...(themeConfig.token as Record<string, unknown>)` will throw a runtime 
TypeError if `themeConfig.token` is `undefined` or `null`, and the same unsafe 
spread is repeated in the catch block, so calling `analyzeThemeAccessibility` 
with a theme config that omits `token` will crash instead of falling back. Use 
a default empty object for `themeConfig.token` and reuse it in both the try and 
catch paths to avoid spreading `undefined`.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=0b7708cb8ec2efe4250ec554ec24fd600d513d63c04dc40eb711af0ea0a3a636&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=0b7708cb8ec2efe4250ec554ec24fd600d513d63c04dc40eb711af0ea0a3a636&reaction=dislike'>👎</a>



##########
superset/static/service-worker.js:
##########
@@ -1,27 +1,1471 @@
-/**
- * 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.
+/*
+ * ATTENTION: An "eval-source-map" devtool has been used.
+ * This devtool is neither made for production nor for readable output files.
+ * It uses "eval()" calls to create a separate source file with attached 
SourceMaps in the browser devtools.
+ * If you are trying to read the output file, select a different devtool 
(https://webpack.js.org/configuration/devtool/)
+ * or disable the default devtool with "devtool: false".
+ * If you are looking for production-ready output files, see mode: 
"production" (https://webpack.js.org/configuration/mode/).
  */
+/******/ (() => { // webpackBootstrap
+/******/       "use strict";
+/******/       var __webpack_modules__ = ({
 
-// Minimal service worker for PWA file handling support
-self.addEventListener('install', event => {
-  event.waitUntil(self.skipWaiting());
-});
+/***/ "./src/service-worker.ts"
+/*!*******************************!*\
+  !*** ./src/service-worker.ts ***!
+  \*******************************/
+() {
 
-self.addEventListener('activate', event => {
-  event.waitUntil(self.clients.claim());
-});
+eval("{/**\n * Licensed to the Apache Software Foundation (ASF) under one\n * 
or more contributor license agreements.  See the NOTICE file\n * distributed 
with this work for additional information\n * regarding copyright ownership.  
The ASF licenses this file\n * to you under the Apache License, Version 2.0 
(the\n * \"License\"); you may not use this file except in compliance\n * with 
the License.  You may obtain a copy of the License at\n *\n *   
http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by 
applicable law or agreed to in writing,\n * software distributed under the 
License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR 
CONDITIONS OF ANY\n * KIND, either express or implied.  See the License for 
the\n * specific language governing permissions and limitations\n * under the 
License.\n */ // Service Worker types (declared locally to avoid polluting 
global scope)\nself.addEventListener('install', (event)=>{\n    
event.waitUntil(self.skipWaiting())
 ;\n});\nself.addEventListener('activate', (event)=>{\n    
event.waitUntil(self.clients.claim());\n});\n\n//# sourceURL=[module]\n//# 
sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvc2VydmljZS13b3JrZXIudHMiLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBaUJBO0FBWUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUEiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zdXBlcnNldC8uL3NyYy9zZXJ2aWNlLXdvcmtlci50cz83ZjU4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZVxuICogb3IgbW9yZSBjb250cmlidXRvciBsaWNlbnNlIGFncmVlbWVudHMuICBTZWUgdGhlIE5PVElDRSBmaWxlXG4gKiBkaXN0cmlidXRlZCB3aXRoIHRoaXMgd29yayBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvblxuICogcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuICBUaGUgQVNGIGxpY2Vuc2VzIHRoaXMgZmlsZVxuICogdG8geW91IHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZVxuICogXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiB3aXRoIHRoZSBMaWNlbnNlLiAgWW91IG1h
 
eSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsXG4gKiBzb2Z0d2FyZSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhblxuICogXCJBUyBJU1wiIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcbiAqIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZVxuICogc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZCBsaW1pdGF0aW9uc1xuICogdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLy8gU2VydmljZSBXb3JrZXIgdHlwZXMgKGRlY2xhcmVkIGxvY2FsbHkgdG8gYXZvaWQgcG9sbHV0aW5nIGdsb2JhbCBzY29wZSlcbmRlY2xhcmUgY29uc3Qgc2VsZjoge1xuICBza2lwV2FpdGluZygpOiBQcm9taXNlPHZvaWQ+O1xuICBjbGllbnRzOiB7IGNsYWltKCk6IFByb21pc2U8dm9pZD4gfTtcbiAgYWRkRXZlbnRMaXN0ZW5lcihcbiAgICB0eXBlOiAnaW5zdGFsbCcgfCAnYWN0aXZhdGUnLFxuICAgIGxpc3RlbmVyOiAoZXZlbnQ6IHsgd2FpdFVudGlsKHByb21pc2U6IFByb21pc2U8dW5rbm93bj4pOiB2b2lkIH0pID0+IHZvaWQsXG4gICk6IHZva
 
WQ7XG59O1xuXG5zZWxmLmFkZEV2ZW50TGlzdGVuZXIoJ2luc3RhbGwnLCBldmVudCA9PiB7XG4gIGV2ZW50LndhaXRVbnRpbChzZWxmLnNraXBXYWl0aW5nKCkpO1xufSk7XG5cbnNlbGYuYWRkRXZlbnRMaXN0ZW5lcignYWN0aXZhdGUnLCBldmVudCA9PiB7XG4gIGV2ZW50LndhaXRVbnRpbChzZWxmLmNsaWVudHMuY2xhaW0oKSk7XG59KTtcblxuZXhwb3J0IHt9O1xuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//#
 sourceURL=webpack-internal:///./src/service-worker.ts\n\n}");
+
+/***/ }
+
+/******/       });
+/************************************************************************/
+/******/       // The module cache
+/******/       var __webpack_module_cache__ = {};
+/******/
+/******/       // The require function
+/******/       function __webpack_require__(moduleId) {
+/******/               // Check if module is in cache
+/******/               var cachedModule = __webpack_module_cache__[moduleId];
+/******/               if (cachedModule !== undefined) {
+/******/                       return cachedModule.exports;
+/******/               }
+/******/               // Check if module exists (development only)
+/******/               if (__webpack_modules__[moduleId] === undefined) {
+/******/                       var e = new Error("Cannot find module '" + 
moduleId + "'");
+/******/                       e.code = 'MODULE_NOT_FOUND';
+/******/                       throw e;
+/******/               }
+/******/               // Create a new module (and put it into the cache)
+/******/               var module = __webpack_module_cache__[moduleId] = {
+/******/                       id: moduleId,
+/******/                       loaded: false,
+/******/                       exports: {}
+/******/               };
+/******/
+/******/               // Execute the module function
+/******/               var execOptions = { id: moduleId, module: module, 
factory: __webpack_modules__[moduleId], require: __webpack_require__ };
+/******/               __webpack_require__.i.forEach(function(handler) { 
handler(execOptions); });
+/******/               module = execOptions.module;
+/******/               execOptions.factory.call(module.exports, module, 
module.exports, execOptions.require);
+/******/
+/******/               // Flag the module as loaded
+/******/               module.loaded = true;
+/******/
+/******/               // Return the exports of the module
+/******/               return module.exports;
+/******/       }
+/******/
+/******/       // expose the modules object (__webpack_modules__)
+/******/       __webpack_require__.m = __webpack_modules__;
+/******/
+/******/       // expose the module cache
+/******/       __webpack_require__.c = __webpack_module_cache__;
+/******/
+/******/       // expose the module execution interceptor
+/******/       __webpack_require__.i = [];
+/******/
+/************************************************************************/
+/******/       /* webpack/runtime/chunk loaded */
+/******/       (() => {
+/******/               var deferred = [];
+/******/               __webpack_require__.O = (result, chunkIds, fn, 
priority) => {
+/******/                       if(chunkIds) {
+/******/                               priority = priority || 0;
+/******/                               for(var i = deferred.length; i > 0 && 
deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/                               deferred[i] = [chunkIds, fn, priority];
+/******/                               return;
+/******/                       }
+/******/                       var notFulfilled = Infinity;
+/******/                       for (var i = 0; i < deferred.length; i++) {
+/******/                               var [chunkIds, fn, priority] = 
deferred[i];
+/******/                               var fulfilled = true;
+/******/                               for (var j = 0; j < chunkIds.length; 
j++) {
+/******/                                       if ((priority & 1 === 0 || 
notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => 
(__webpack_require__.O[key](chunkIds[j])))) {
+/******/                                               chunkIds.splice(j--, 1);
+/******/                                       } else {
+/******/                                               fulfilled = false;
+/******/                                               if(priority < 
notFulfilled) notFulfilled = priority;
+/******/                                       }
+/******/                               }
+/******/                               if(fulfilled) {
+/******/                                       deferred.splice(i--, 1)
+/******/                                       var r = fn();
+/******/                                       if (r !== undefined) result = r;
+/******/                               }
+/******/                       }
+/******/                       return result;
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/compat get default export */
+/******/       (() => {
+/******/               // getDefaultExport function for compatibility with 
non-harmony modules
+/******/               __webpack_require__.n = (module) => {
+/******/                       var getter = module && module.__esModule ?
+/******/                               () => (module['default']) :
+/******/                               () => (module);
+/******/                       __webpack_require__.d(getter, { a: getter });
+/******/                       return getter;
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/create fake namespace object */
+/******/       (() => {
+/******/               var getProto = Object.getPrototypeOf ? (obj) => 
(Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
+/******/               var leafPrototypes;
+/******/               // create a fake namespace object
+/******/               // mode & 1: value is a module id, require it
+/******/               // mode & 2: merge all properties of value into the ns
+/******/               // mode & 4: return value when already ns object
+/******/               // mode & 16: return value when it's Promise-like
+/******/               // mode & 8|1: behave like require
+/******/               __webpack_require__.t = function(value, mode) {
+/******/                       if(mode & 1) value = this(value);
+/******/                       if(mode & 8) return value;
+/******/                       if(typeof value === 'object' && value) {
+/******/                               if((mode & 4) && value.__esModule) 
return value;
+/******/                               if((mode & 16) && typeof value.then === 
'function') return value;
+/******/                       }
+/******/                       var ns = Object.create(null);
+/******/                       __webpack_require__.r(ns);
+/******/                       var def = {};
+/******/                       leafPrototypes = leafPrototypes || [null, 
getProto({}), getProto([]), getProto(getProto)];
+/******/                       for(var current = mode & 2 && value; (typeof 
current == 'object' || typeof current == 'function') && 
!~leafPrototypes.indexOf(current); current = getProto(current)) {
+/******/                               
Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => 
(value[key])));
+/******/                       }
+/******/                       def['default'] = () => (value);
+/******/                       __webpack_require__.d(ns, def);
+/******/                       return ns;
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/define property getters */
+/******/       (() => {
+/******/               // define getter functions for harmony exports
+/******/               __webpack_require__.d = (exports, definition) => {
+/******/                       for(var key in definition) {
+/******/                               if(__webpack_require__.o(definition, 
key) && !__webpack_require__.o(exports, key)) {
+/******/                                       Object.defineProperty(exports, 
key, { enumerable: true, get: definition[key] });
+/******/                               }
+/******/                       }
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/get javascript update chunk filename */
+/******/       (() => {
+/******/               // This function allow to reference all chunks
+/******/               __webpack_require__.hu = (chunkId) => {
+/******/                       // return url for filenames based on template
+/******/                       return "" + chunkId + "." + 
__webpack_require__.h() + ".hot-update.js";
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/get update manifest filename */
+/******/       (() => {
+/******/               __webpack_require__.hmrF = () => ("service-worker." + 
__webpack_require__.h() + ".hot-update.json");
+/******/       })();
+/******/
+/******/       /* webpack/runtime/getFullHash */
+/******/       (() => {
+/******/               __webpack_require__.h = () => ("f4461569ed3749bcd919")
+/******/       })();
+/******/
+/******/       /* webpack/runtime/harmony module decorator */
+/******/       (() => {
+/******/               __webpack_require__.hmd = (module) => {
+/******/                       module = Object.create(module);
+/******/                       if (!module.children) module.children = [];
+/******/                       Object.defineProperty(module, 'exports', {
+/******/                               enumerable: true,
+/******/                               set: () => {
+/******/                                       throw new Error('ES Modules may 
not assign module.exports or exports.*, Use ESM export syntax, instead: ' + 
module.id);
+/******/                               }
+/******/                       });
+/******/                       return module;
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/hasOwnProperty shorthand */
+/******/       (() => {
+/******/               __webpack_require__.o = (obj, prop) => 
(Object.prototype.hasOwnProperty.call(obj, prop))
+/******/       })();
+/******/
+/******/       /* webpack/runtime/load script */
+/******/       (() => {
+/******/               var inProgress = {};
+/******/               var dataWebpackPrefix = "superset:";
+/******/               // loadScript function to load a script via script tag
+/******/               __webpack_require__.l = (url, done, key, chunkId) => {
+/******/                       if(inProgress[url]) { 
inProgress[url].push(done); return; }
+/******/                       var script, needAttach;
+/******/                       if(key !== undefined) {
+/******/                               var scripts = 
document.getElementsByTagName("script");
+/******/                               for(var i = 0; i < scripts.length; i++) 
{
+/******/                                       var s = scripts[i];
+/******/                                       if(s.getAttribute("src") == url 
|| s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; 
break; }
+/******/                               }
+/******/                       }
+/******/                       if(!script) {
+/******/                               needAttach = true;
+/******/                               script = 
document.createElement('script');
+/******/
+/******/                               script.charset = 'utf-8';
+/******/                               if (__webpack_require__.nc) {
+/******/                                       script.setAttribute("nonce", 
__webpack_require__.nc);
+/******/                               }
+/******/                               script.setAttribute("data-webpack", 
dataWebpackPrefix + key);
+/******/
+/******/                               script.src = url;
+/******/                       }
+/******/                       inProgress[url] = [done];
+/******/                       var onScriptComplete = (prev, event) => {
+/******/                               // avoid mem leaks in IE.
+/******/                               script.onerror = script.onload = null;
+/******/                               clearTimeout(timeout);
+/******/                               var doneFns = inProgress[url];
+/******/                               delete inProgress[url];
+/******/                               script.parentNode && 
script.parentNode.removeChild(script);
+/******/                               doneFns && doneFns.forEach((fn) => 
(fn(event)));
+/******/                               if(prev) return prev(event);
+/******/                       }
+/******/                       var timeout = 
setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: 
script }), 120000);
+/******/                       script.onerror = onScriptComplete.bind(null, 
script.onerror);
+/******/                       script.onload = onScriptComplete.bind(null, 
script.onload);
+/******/                       needAttach && document.head.appendChild(script);
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/make namespace object */
+/******/       (() => {
+/******/               // define __esModule on exports
+/******/               __webpack_require__.r = (exports) => {
+/******/                       if(typeof Symbol !== 'undefined' && 
Symbol.toStringTag) {
+/******/                               Object.defineProperty(exports, 
Symbol.toStringTag, { value: 'Module' });
+/******/                       }
+/******/                       Object.defineProperty(exports, '__esModule', { 
value: true });
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/node module decorator */
+/******/       (() => {
+/******/               __webpack_require__.nmd = (module) => {
+/******/                       module.paths = [];
+/******/                       if (!module.children) module.children = [];
+/******/                       return module;
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/sharing */
+/******/       (() => {
+/******/               __webpack_require__.S = {};
+/******/               var initPromises = {};
+/******/               var initTokens = {};
+/******/               __webpack_require__.I = (name, initScope) => {
+/******/                       if(!initScope) initScope = [];
+/******/                       // handling circular init calls
+/******/                       var initToken = initTokens[name];
+/******/                       if(!initToken) initToken = initTokens[name] = 
{};
+/******/                       if(initScope.indexOf(initToken) >= 0) return;
+/******/                       initScope.push(initToken);
+/******/                       // only runs once
+/******/                       if(initPromises[name]) return 
initPromises[name];
+/******/                       // creates a new share scope if needed
+/******/                       
if(!__webpack_require__.o(__webpack_require__.S, name)) 
__webpack_require__.S[name] = {};
+/******/                       // runs all init snippets from all modules 
reachable
+/******/                       var scope = __webpack_require__.S[name];
+/******/                       var warn = (msg) => {
+/******/                               if (typeof console !== "undefined" && 
console.warn) console.warn(msg);
+/******/                       };
+/******/                       var uniqueName = "superset";
+/******/                       var register = (name, version, factory, eager) 
=> {
+/******/                               var versions = scope[name] = 
scope[name] || {};
+/******/                               var activeVersion = versions[version];
+/******/                               if(!activeVersion || 
(!activeVersion.loaded && (!eager != !activeVersion.eager ? eager : uniqueName 
> activeVersion.from))) versions[version] = { get: factory, from: uniqueName, 
eager: !!eager };
+/******/                       };
+/******/                       var initExternal = (id) => {
+/******/                               var handleError = (err) => 
(warn("Initialization of sharing external failed: " + err));
+/******/                               try {
+/******/                                       var module = 
__webpack_require__(id);
+/******/                                       if(!module) return;
+/******/                                       var initFn = (module) => 
(module && module.init && module.init(__webpack_require__.S[name], initScope))
+/******/                                       if(module.then) return 
promises.push(module.then(initFn, handleError));
+/******/                                       var initResult = initFn(module);
+/******/                                       if(initResult && 
initResult.then) return promises.push(initResult['catch'](handleError));
+/******/                               } catch(err) { handleError(err); }
+/******/                       }
+/******/                       var promises = [];
+/******/                       switch(name) {
+/******/                               case "default": {
+/******/                                       register("antd", "5.27.6", () 
=> (() => (__webpack_require__(/*! ./node_modules/antd/es/index.js */ 
"./node_modules/antd/es/index.js"))), 1);
+/******/                                       register("react-dom", "17.0.2", 
() => (() => (__webpack_require__(/*! ./node_modules/react-dom/index.js */ 
"./node_modules/react-dom/index.js"))), 1);
+/******/                                       register("react", "17.0.2", () 
=> (() => (__webpack_require__(/*! ./node_modules/react/index.js */ 
"./node_modules/react/index.js"))), 1);
+/******/                               }
+/******/                               break;
+/******/                       }
+/******/                       if(!promises.length) return initPromises[name] 
= 1;
+/******/                       return initPromises[name] = 
Promise.all(promises).then(() => (initPromises[name] = 1));
+/******/               };
+/******/       })();
+/******/
+/******/       /* webpack/runtime/hot module replacement */
+/******/       (() => {
+/******/               var currentModuleData = {};
+/******/               var installedModules = __webpack_require__.c;
+/******/
+/******/               // module and require creation
+/******/               var currentChildModule;
+/******/               var currentParents = [];
+/******/
+/******/               // status
+/******/               var registeredStatusHandlers = [];
+/******/               var currentStatus = "idle";
+/******/
+/******/               // while downloading
+/******/               var blockingPromises = 0;
+/******/               var blockingPromisesWaiting = [];
+/******/
+/******/               // The update info
+/******/               var currentUpdateApplyHandlers;
+/******/               var queuedInvalidatedModules;
+/******/
+/******/               __webpack_require__.hmrD = currentModuleData;
+/******/
+/******/               __webpack_require__.i.push(function (options) {
+/******/                       var module = options.module;
+/******/                       var require = createRequire(options.require, 
options.id);
+/******/                       module.hot = createModuleHotObject(options.id, 
module);
+/******/                       module.parents = currentParents;
+/******/                       module.children = [];
+/******/                       currentParents = [];
+/******/                       options.require = require;
+/******/               });
+/******/
+/******/               __webpack_require__.hmrC = {};
+/******/               __webpack_require__.hmrI = {};
+/******/
+/******/               function createRequire(require, moduleId) {
+/******/                       var me = installedModules[moduleId];
+/******/                       if (!me) return require;
+/******/                       var fn = function (request) {
+/******/                               if (me.hot.active) {
+/******/                                       if (installedModules[request]) {
+/******/                                               var parents = 
installedModules[request].parents;
+/******/                                               if 
(parents.indexOf(moduleId) === -1) {
+/******/                                                       
parents.push(moduleId);
+/******/                                               }
+/******/                                       } else {
+/******/                                               currentParents = 
[moduleId];
+/******/                                               currentChildModule = 
request;
+/******/                                       }
+/******/                                       if 
(me.children.indexOf(request) === -1) {
+/******/                                               
me.children.push(request);
+/******/                                       }
+/******/                               } else {
+/******/                                       console.warn(
+/******/                                               "[HMR] unexpected 
require(" +
+/******/                                                       request +
+/******/                                                       ") from 
disposed module " +
+/******/                                                       moduleId
+/******/                                       );
+/******/                                       currentParents = [];
+/******/                               }
+/******/                               return require(request);
+/******/                       };
+/******/                       var createPropertyDescriptor = function (name) {
+/******/                               return {
+/******/                                       configurable: true,
+/******/                                       enumerable: true,
+/******/                                       get: function () {
+/******/                                               return require[name];
+/******/                                       },
+/******/                                       set: function (value) {
+/******/                                               require[name] = value;
+/******/                                       }
+/******/                               };
+/******/                       };
+/******/                       for (var name in require) {
+/******/                               if 
(Object.prototype.hasOwnProperty.call(require, name) && name !== "e") {
+/******/                                       Object.defineProperty(fn, name, 
createPropertyDescriptor(name));
+/******/                               }
+/******/                       }
+/******/                       fn.e = function (chunkId, fetchPriority) {
+/******/                               return 
trackBlockingPromise(require.e(chunkId, fetchPriority));
+/******/                       };
+/******/                       return fn;
+/******/               }
+/******/
+/******/               function createModuleHotObject(moduleId, me) {
+/******/                       var _main = currentChildModule !== moduleId;
+/******/                       var hot = {
+/******/                               // private stuff
+/******/                               _acceptedDependencies: {},
+/******/                               _acceptedErrorHandlers: {},
+/******/                               _declinedDependencies: {},
+/******/                               _selfAccepted: false,
+/******/                               _selfDeclined: false,
+/******/                               _selfInvalidated: false,
+/******/                               _disposeHandlers: [],
+/******/                               _main: _main,
+/******/                               _requireSelf: function () {
+/******/                                       currentParents = 
me.parents.slice();
+/******/                                       currentChildModule = _main ? 
undefined : moduleId;
+/******/                                       __webpack_require__(moduleId);
+/******/                               },
+/******/
+/******/                               // Module API
+/******/                               active: true,
+/******/                               accept: function (dep, callback, 
errorHandler) {
+/******/                                       if (dep === undefined) 
hot._selfAccepted = true;
+/******/                                       else if (typeof dep === 
"function") hot._selfAccepted = dep;
+/******/                                       else if (typeof dep === 
"object" && dep !== null) {
+/******/                                               for (var i = 0; i < 
dep.length; i++) {
+/******/                                                       
hot._acceptedDependencies[dep[i]] = callback || function () {};
+/******/                                                       
hot._acceptedErrorHandlers[dep[i]] = errorHandler;
+/******/                                               }
+/******/                                       } else {
+/******/                                               
hot._acceptedDependencies[dep] = callback || function () {};
+/******/                                               
hot._acceptedErrorHandlers[dep] = errorHandler;
+/******/                                       }
+/******/                               },
+/******/                               decline: function (dep) {
+/******/                                       if (dep === undefined) 
hot._selfDeclined = true;
+/******/                                       else if (typeof dep === 
"object" && dep !== null)
+/******/                                               for (var i = 0; i < 
dep.length; i++)
+/******/                                                       
hot._declinedDependencies[dep[i]] = true;
+/******/                                       else 
hot._declinedDependencies[dep] = true;
+/******/                               },
+/******/                               dispose: function (callback) {
+/******/                                       
hot._disposeHandlers.push(callback);
+/******/                               },
+/******/                               addDisposeHandler: function (callback) {
+/******/                                       
hot._disposeHandlers.push(callback);
+/******/                               },
+/******/                               removeDisposeHandler: function 
(callback) {
+/******/                                       var idx = 
hot._disposeHandlers.indexOf(callback);
+/******/                                       if (idx >= 0) 
hot._disposeHandlers.splice(idx, 1);
+/******/                               },
+/******/                               invalidate: function () {
+/******/                                       this._selfInvalidated = true;
+/******/                                       switch (currentStatus) {
+/******/                                               case "idle":
+/******/                                                       
currentUpdateApplyHandlers = [];
+/******/                                                       
Object.keys(__webpack_require__.hmrI).forEach(function (key) {
+/******/                                                               
__webpack_require__.hmrI[key](
+/******/                                                                       
moduleId,
+/******/                                                                       
currentUpdateApplyHandlers
+/******/                                                               );
+/******/                                                       });
+/******/                                                       
setStatus("ready");
+/******/                                                       break;
+/******/                                               case "ready":
+/******/                                                       
Object.keys(__webpack_require__.hmrI).forEach(function (key) {
+/******/                                                               
__webpack_require__.hmrI[key](
+/******/                                                                       
moduleId,
+/******/                                                                       
currentUpdateApplyHandlers
+/******/                                                               );
+/******/                                                       });
+/******/                                                       break;
+/******/                                               case "prepare":
+/******/                                               case "check":
+/******/                                               case "dispose":
+/******/                                               case "apply":
+/******/                                                       
(queuedInvalidatedModules = queuedInvalidatedModules || []).push(
+/******/                                                               moduleId
+/******/                                                       );
+/******/                                                       break;
+/******/                                               default:
+/******/                                                       // ignore 
requests in error states
+/******/                                                       break;
+/******/                                       }
+/******/                               },
+/******/
+/******/                               // Management API
+/******/                               check: hotCheck,
+/******/                               apply: hotApply,
+/******/                               status: function (l) {
+/******/                                       if (!l) return currentStatus;
+/******/                                       
registeredStatusHandlers.push(l);
+/******/                               },
+/******/                               addStatusHandler: function (l) {
+/******/                                       
registeredStatusHandlers.push(l);
+/******/                               },
+/******/                               removeStatusHandler: function (l) {
+/******/                                       var idx = 
registeredStatusHandlers.indexOf(l);
+/******/                                       if (idx >= 0) 
registeredStatusHandlers.splice(idx, 1);
+/******/                               },
+/******/
+/******/                               // inherit from previous dispose call
+/******/                               data: currentModuleData[moduleId]
+/******/                       };
+/******/                       currentChildModule = undefined;
+/******/                       return hot;
+/******/               }
+/******/
+/******/               function setStatus(newStatus) {
+/******/                       currentStatus = newStatus;
+/******/                       var results = [];
+/******/
+/******/                       for (var i = 0; i < 
registeredStatusHandlers.length; i++)
+/******/                               results[i] = 
registeredStatusHandlers[i].call(null, newStatus);
+/******/
+/******/                       return Promise.all(results).then(function () 
{});
+/******/               }
+/******/
+/******/               function unblock() {
+/******/                       if (--blockingPromises === 0) {
+/******/                               setStatus("ready").then(function () {
+/******/                                       if (blockingPromises === 0) {
+/******/                                               var list = 
blockingPromisesWaiting;
+/******/                                               blockingPromisesWaiting 
= [];
+/******/                                               for (var i = 0; i < 
list.length; i++) {
+/******/                                                       list[i]();
+/******/                                               }
+/******/                                       }
+/******/                               });
+/******/                       }
+/******/               }
+/******/
+/******/               function trackBlockingPromise(promise) {
+/******/                       switch (currentStatus) {
+/******/                               case "ready":
+/******/                                       setStatus("prepare");
+/******/                               /* fallthrough */
+/******/                               case "prepare":
+/******/                                       blockingPromises++;
+/******/                                       promise.then(unblock, unblock);
+/******/                                       return promise;
+/******/                               default:
+/******/                                       return promise;
+/******/                       }
+/******/               }
+/******/
+/******/               function waitForBlockingPromises(fn) {
+/******/                       if (blockingPromises === 0) return fn();
+/******/                       return new Promise(function (resolve) {
+/******/                               blockingPromisesWaiting.push(function 
() {
+/******/                                       resolve(fn());
+/******/                               });
+/******/                       });
+/******/               }
+/******/
+/******/               function hotCheck(applyOnUpdate) {
+/******/                       if (currentStatus !== "idle") {
+/******/                               throw new Error("check() is only 
allowed in idle status");
+/******/                       }
+/******/                       return setStatus("check")
+/******/                               .then(__webpack_require__.hmrM)
+/******/                               .then(function (update) {
+/******/                                       if (!update) {
+/******/                                               return 
setStatus(applyInvalidatedModules() ? "ready" : "idle").then(
+/******/                                                       function () {
+/******/                                                               return 
null;
+/******/                                                       }
+/******/                                               );
+/******/                                       }
+/******/
+/******/                                       return 
setStatus("prepare").then(function () {
+/******/                                               var updatedModules = [];
+/******/                                               
currentUpdateApplyHandlers = [];
+/******/
+/******/                                               return Promise.all(
+/******/                                                       
Object.keys(__webpack_require__.hmrC).reduce(function (
+/******/                                                               
promises,
+/******/                                                               key
+/******/                                                       ) {
+/******/                                                               
__webpack_require__.hmrC[key](
+/******/                                                                       
update.c,
+/******/                                                                       
update.r,
+/******/                                                                       
update.m,
+/******/                                                                       
promises,
+/******/                                                                       
currentUpdateApplyHandlers,
+/******/                                                                       
updatedModules,
+/******/                                                                       
update.css
+/******/                                                               );
+/******/                                                               return 
promises;
+/******/                                                       }, [])
+/******/                                               ).then(function () {
+/******/                                                       return 
waitForBlockingPromises(function () {
+/******/                                                               if 
(applyOnUpdate) {
+/******/                                                                       
return internalApply(applyOnUpdate);
+/******/                                                               }
+/******/                                                               return 
setStatus("ready").then(function () {
+/******/                                                                       
return updatedModules;
+/******/                                                               });
+/******/                                                       });
+/******/                                               });
+/******/                                       });
+/******/                               });
+/******/               }
+/******/
+/******/               function hotApply(options) {
+/******/                       if (currentStatus !== "ready") {
+/******/                               return Promise.resolve().then(function 
() {
+/******/                                       throw new Error(
+/******/                                               "apply() is only 
allowed in ready status (state: " +
+/******/                                                       currentStatus +
+/******/                                                       ")"
+/******/                                       );
+/******/                               });
+/******/                       }
+/******/                       return internalApply(options);
+/******/               }
+/******/
+/******/               function internalApply(options) {
+/******/                       options = options || {};
+/******/
+/******/                       applyInvalidatedModules();
+/******/
+/******/                       var results = 
currentUpdateApplyHandlers.map(function (handler) {
+/******/                               return handler(options);
+/******/                       });
+/******/                       currentUpdateApplyHandlers = undefined;
+/******/
+/******/                       var errors = results
+/******/                               .map(function (r) {
+/******/                                       return r.error;
+/******/                               })
+/******/                               .filter(Boolean);
+/******/
+/******/                       if (errors.length > 0) {
+/******/                               return setStatus("abort").then(function 
() {
+/******/                                       throw errors[0];
+/******/                               });
+/******/                       }
+/******/
+/******/                       // Now in "dispose" phase
+/******/                       var disposePromise = setStatus("dispose");
+/******/
+/******/                       results.forEach(function (result) {
+/******/                               if (result.dispose) result.dispose();
+/******/                       });
+/******/
+/******/                       // Now in "apply" phase
+/******/                       var applyPromise = setStatus("apply");
+/******/
+/******/                       var error;
+/******/                       var reportError = function (err) {
+/******/                               if (!error) error = err;
+/******/                       };
+/******/
+/******/                       var outdatedModules = [];
+/******/
+/******/                       var onAccepted = function () {
+/******/                               return Promise.all([disposePromise, 
applyPromise]).then(function () {
+/******/                                       // handle errors in accept 
handlers and self accepted module load
+/******/                                       if (error) {
+/******/                                               return 
setStatus("fail").then(function () {
+/******/                                                       throw error;
+/******/                                               });
+/******/                                       }
+/******/
+/******/                                       if (queuedInvalidatedModules) {
+/******/                                               return 
internalApply(options).then(function (list) {
+/******/                                                       
outdatedModules.forEach(function (moduleId) {
+/******/                                                               if 
(list.indexOf(moduleId) < 0) list.push(moduleId);
+/******/                                                       });
+/******/                                                       return list;
+/******/                                               });
+/******/                                       }
+/******/
+/******/                                       return 
setStatus("idle").then(function () {
+/******/                                               return outdatedModules;
+/******/                                       });
+/******/                               });
+/******/                       };
+/******/
+/******/                       return Promise.all(
+/******/                               results
+/******/                                       .filter(function (result) {
+/******/                                               return result.apply;
+/******/                                       })
+/******/                                       .map(function (result) {
+/******/                                               return 
result.apply(reportError);
+/******/                                       })
+/******/                       )
+/******/                               .then(function (applyResults) {
+/******/                                       applyResults.forEach(function 
(modules) {
+/******/                                               if (modules) {
+/******/                                                       for (var i = 0; 
i < modules.length; i++) {
+/******/                                                               
outdatedModules.push(modules[i]);
+/******/                                                       }
+/******/                                               }
+/******/                                       });
+/******/                               })
+/******/                               .then(onAccepted);
+/******/               }
+/******/
+/******/               function applyInvalidatedModules() {
+/******/                       if (queuedInvalidatedModules) {
+/******/                               if (!currentUpdateApplyHandlers) 
currentUpdateApplyHandlers = [];
+/******/                               
Object.keys(__webpack_require__.hmrI).forEach(function (key) {
+/******/                                       
queuedInvalidatedModules.forEach(function (moduleId) {
+/******/                                               
__webpack_require__.hmrI[key](
+/******/                                                       moduleId,
+/******/                                                       
currentUpdateApplyHandlers
+/******/                                               );
+/******/                                       });
+/******/                               });
+/******/                               queuedInvalidatedModules = undefined;
+/******/                               return true;
+/******/                       }
+/******/               }
+/******/       })();
+/******/
+/******/       /* webpack/runtime/publicPath */
+/******/       (() => {
+/******/               __webpack_require__.p = "/static/assets/";
+/******/       })();
+/******/
+/******/       /* webpack/runtime/react refresh */
+/******/       (() => {
+/******/               const setup = (moduleId) => {
+/******/                       const refresh = {
+/******/                               moduleId: moduleId,
+/******/                               register: (type, id) => {
+/******/                                       const typeId = moduleId + ' ' + 
id;
+/******/                                       refresh.runtime.register(type, 
typeId);
+/******/                               },
+/******/                               signature: () => 
(refresh.runtime.createSignatureFunctionForTransform()),
+/******/                               runtime: {
+/******/                                       
createSignatureFunctionForTransform: () => ((type) => (type)),
+/******/                                       register: x => {}
+/******/                               },
+/******/                       };
+/******/                       return refresh;
+/******/               };
+/******/
+/******/               __webpack_require__.i.push((options) => {
+/******/                       const originalFactory = options.factory;
+/******/                       options.factory = function(moduleObject, 
moduleExports, webpackRequire) {
+/******/                               const hotRequire = (request) => 
(webpackRequire(request));
+/******/                               const createPropertyDescriptor = (name) 
=> {
+/******/                                       return {
+/******/                                               configurable: true,
+/******/                                               enumerable: true,
+/******/                                               get: () => 
(webpackRequire[name]),
+/******/                                               set: (value) => {
+/******/                                                       
webpackRequire[name] = value;
+/******/                                               },
+/******/                                       };
+/******/                               };
+/******/                               for (const name in webpackRequire) {
+/******/                                       if (name === "$Refresh$") 
continue;
+/******/                                       if 
(Object.prototype.hasOwnProperty.call(webpackRequire, name)) {
+/******/                                               
Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));
+/******/                                       }
+/******/                               }
+/******/                               hotRequire.$Refresh$ = 
setup(options.id);
+/******/                               originalFactory.call(this, 
moduleObject, moduleExports, hotRequire);
+/******/                       };
+/******/               });
+/******/       })();
+/******/
+/******/       /* webpack/runtime/consumes */
+/******/       (() => {
+/******/               var parseVersion = (str) => {
+/******/                       // see webpack/lib/util/semver.js for original 
code
+/******/                       var p=p=>{return 
p.split(".").map(p=>{return+p==p?+p:p})},n=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(str),r=n[1]?p(n[1]):[];return
 
n[2]&&(r.length++,r.push.apply(r,p(n[2]))),n[3]&&(r.push([]),r.push.apply(r,p(n[3]))),r;
+/******/               }
+/******/               var versionLt = (a, b) => {
+/******/                       // see webpack/lib/util/semver.js for original 
code
+/******/                       a=parseVersion(a),b=parseVersion(b);for(var 
r=0;;){if(r>=a.length)return r<b.length&&"u"!=(typeof b[r])[0];var 
e=a[r],n=(typeof e)[0];if(r>=b.length)return"u"==n;var t=b[r],f=(typeof 
t)[0];if(n!=f)return"o"==n&&"n"==f||("s"==f||"u"==n);if("o"!=n&&"u"!=n&&e!=t)return
 e<t;r++}
+/******/               }
+/******/               var rangeToString = (range) => {
+/******/                       // see webpack/lib/util/semver.js for original 
code
+/******/                       var 
r=range[0],n="";if(1===range.length)return"*";if(r+.5){n+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var
 
e=1,a=1;a<range.length;a++){e--,n+="u"==(typeof(t=range[a]))[0]?"-":(e>0?".":"")+(e=2,t)}return
 n}var g=[];for(a=1;a<range.length;a++){var 
t=range[a];g.push(0===t?"not("+o()+")":1===t?"("+o()+" || 
"+o()+")":2===t?g.pop()+" "+g.pop():rangeToString(t))}return o();function 
o(){return g.pop().replace(/^\((.+)\)$/,"$1")}
+/******/               }
+/******/               var satisfy = (range, version) => {
+/******/                       // see webpack/lib/util/semver.js for original 
code
+/******/                       if(0 in 
range){version=parseVersion(version);var e=range[0],r=e<0;r&&(e=-e-1);for(var 
n=0,i=1,a=!0;;i++,n++){var f,s,g=i<range.length?(typeof 
range[i])[0]:"";if(n>=version.length||"o"==(s=(typeof(f=version[n]))[0]))return!a||("u"==g?i>e&&!r:""==g!=r);if("u"==s){if(!a||"u"!=g)return!1}else
 
if(a)if(g==s)if(i<=e){if(f!=range[i])return!1}else{if(r?f>range[i]:f<range[i])return!1;f!=range[i]&&(a=!1)}else
 
if("s"!=g&&"n"!=g){if(r||i<=e)return!1;a=!1,i--}else{if(i<=e||s<g!=r)return!1;a=!1}else"s"!=g&&"n"!=g&&(a=!1,i--)}}var
 t=[],o=t.pop.bind(t);for(n=1;n<range.length;n++){var 
u=range[n];t.push(1==u?o()|o():2==u?o()&o():u?satisfy(u,version):!o())}return!!o();
+/******/               }
+/******/               var exists = (scope, key) => {
+/******/                       return scope && __webpack_require__.o(scope, 
key);
+/******/               }
+/******/               var get = (entry) => {
+/******/                       entry.loaded = 1;
+/******/                       return entry.get()
+/******/               };
+/******/               var eagerOnly = (versions) => {
+/******/                       return Object.keys(versions).reduce((filtered, 
version) => {
+/******/                                       if (versions[version].eager) {
+/******/                                               filtered[version] = 
versions[version];
+/******/                                       }
+/******/                                       return filtered;
+/******/                       }, {});
+/******/               };
+/******/               var findLatestVersion = (scope, key, eager) => {
+/******/                       var versions = eager ? eagerOnly(scope[key]) : 
scope[key];
+/******/                       var key = Object.keys(versions).reduce((a, b) 
=> {
+/******/                               return !a || versionLt(a, b) ? b : a;
+/******/                       }, 0);
+/******/                       return key && versions[key];
+/******/               };
+/******/               var findSatisfyingVersion = (scope, key, 
requiredVersion, eager) => {
+/******/                       var versions = eager ? eagerOnly(scope[key]) : 
scope[key];
+/******/                       var key = Object.keys(versions).reduce((a, b) 
=> {
+/******/                               if (!satisfy(requiredVersion, b)) 
return a;
+/******/                               return !a || versionLt(a, b) ? b : a;
+/******/                       }, 0);
+/******/                       return key && versions[key]
+/******/               };
+/******/               var findSingletonVersionKey = (scope, key, eager) => {
+/******/                       var versions = eager ? eagerOnly(scope[key]) : 
scope[key];
+/******/                       return Object.keys(versions).reduce((a, b) => {
+/******/                               return !a || (!versions[a].loaded && 
versionLt(a, b)) ? b : a;
+/******/                       }, 0);
+/******/               };
+/******/               var getInvalidSingletonVersionMessage = (scope, key, 
version, requiredVersion) => {
+/******/                       return "Unsatisfied version " + version + " 
from " + (version && scope[key][version].from) + " of shared singleton module " 
+ key + " (required " + rangeToString(requiredVersion) + ")"
+/******/               };
+/******/               var getInvalidVersionMessage = (scope, scopeName, key, 
requiredVersion, eager) => {
+/******/                       var versions = scope[key];
+/******/                       return "No satisfying version (" + 
rangeToString(requiredVersion) + ")" + (eager ? " for eager consumption" : "") 
+ " of shared module " + key + " found in shared scope " + scopeName + ".\n" +
+/******/                               "Available versions: " + 
Object.keys(versions).map((key) => {
+/******/                               return key + " from " + 
versions[key].from;
+/******/                       }).join(", ");
+/******/               };
+/******/               var fail = (msg) => {
+/******/                       throw new Error(msg);
+/******/               }
+/******/               var failAsNotExist = (scopeName, key) => {
+/******/                       return fail("Shared module " + key + " doesn't 
exist in shared scope " + scopeName);
+/******/               }
+/******/               var warn = /*#__PURE__*/ (msg) => {
+/******/                       if (typeof console !== "undefined" && 
console.warn) console.warn(msg);
+/******/               };
+/******/               var init = (fn) => (function(scopeName, key, eager, c, 
d) {
+/******/                       var promise = __webpack_require__.I(scopeName);
+/******/                       if (promise && promise.then && !eager) {
+/******/                               return promise.then(fn.bind(fn, 
scopeName, __webpack_require__.S[scopeName], key, false, c, d));
+/******/                       }
+/******/                       return fn(scopeName, 
__webpack_require__.S[scopeName], key, eager, c, d);
+/******/               });
+/******/
+/******/               var useFallback = (scopeName, key, fallback) => {
+/******/                       return fallback ? fallback() : 
failAsNotExist(scopeName, key);
+/******/               }
+/******/               var load = /*#__PURE__*/ init((scopeName, scope, key, 
eager, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       return get(findLatestVersion(scope, key, 
eager));
+/******/               });
+/******/               var loadVersion = /*#__PURE__*/ init((scopeName, scope, 
key, eager, requiredVersion, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       var satisfyingVersion = 
findSatisfyingVersion(scope, key, requiredVersion, eager);
+/******/                       if (satisfyingVersion) return 
get(satisfyingVersion);
+/******/                       warn(getInvalidVersionMessage(scope, scopeName, 
key, requiredVersion, eager))
+/******/                       return get(findLatestVersion(scope, key, 
eager));
+/******/               });
+/******/               var loadStrictVersion = /*#__PURE__*/ init((scopeName, 
scope, key, eager, requiredVersion, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       var satisfyingVersion = 
findSatisfyingVersion(scope, key, requiredVersion, eager);
+/******/                       if (satisfyingVersion) return 
get(satisfyingVersion);
+/******/                       if (fallback) return fallback();
+/******/                       fail(getInvalidVersionMessage(scope, scopeName, 
key, requiredVersion, eager));
+/******/               });
+/******/               var loadSingleton = /*#__PURE__*/ init((scopeName, 
scope, key, eager, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       var version = findSingletonVersionKey(scope, 
key, eager);
+/******/                       return get(scope[key][version]);
+/******/               });
+/******/               var loadSingletonVersion = /*#__PURE__*/ 
init((scopeName, scope, key, eager, requiredVersion, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       var version = findSingletonVersionKey(scope, 
key, eager);
+/******/                       if (!satisfy(requiredVersion, version)) {
+/******/                               
warn(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));
+/******/                       }
+/******/                       return get(scope[key][version]);
+/******/               });
+/******/               var loadStrictSingletonVersion = /*#__PURE__*/ 
init((scopeName, scope, key, eager, requiredVersion, fallback) => {
+/******/                       if (!exists(scope, key)) return 
useFallback(scopeName, key, fallback);
+/******/                       var version = findSingletonVersionKey(scope, 
key, eager);
+/******/                       if (!satisfy(requiredVersion, version)) {
+/******/                               
fail(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));
+/******/                       }
+/******/                       return get(scope[key][version]);
+/******/               });
+/******/               var installedModules = {};
+/******/               var moduleToHandlerMapping = {
+/******/                       
"webpack/sharing/consume/default/react-dom/react-dom": () => 
(loadSingletonVersion("default", "react-dom", true, [1,17,0,2], () => (() => 
(__webpack_require__(/*! react-dom */ "./node_modules/react-dom/index.js"))))),
+/******/                       "webpack/sharing/consume/default/react/react": 
() => (loadSingletonVersion("default", "react", true, [1,17,0,2], () => (() => 
(__webpack_require__(/*! react */ "./node_modules/react/index.js")))))
+/******/               };
+/******/               var initialConsumes = 
["webpack/sharing/consume/default/react-dom/react-dom","webpack/sharing/consume/default/react/react"];
+/******/               initialConsumes.forEach((id) => {
+/******/                       __webpack_require__.m[id] = (module) => {
+/******/                               // Handle case when module is used sync
+/******/                               installedModules[id] = 0;
+/******/                               delete __webpack_require__.c[id];
+/******/                               var factory = 
moduleToHandlerMapping[id]();
+/******/                               if(typeof factory !== "function") throw 
new Error("Shared module is not available for eager consumption: " + id);
+/******/                               module.exports = factory();
+/******/                       }
+/******/               });
+/******/               // no chunk loading of consumes
+/******/       })();
+/******/
+/******/       /* webpack/runtime/jsonp chunk loading */
+/******/       (() => {
+/******/               // no baseURI
+/******/
+/******/               // object to store loaded and loading chunks
+/******/               // undefined = chunk not loaded, null = chunk 
preloaded/prefetched
+/******/               // [resolve, reject, Promise] = chunk loading, 0 = 
chunk loaded
+/******/               var installedChunks = __webpack_require__.hmrS_jsonp = 
__webpack_require__.hmrS_jsonp || {
+/******/                       "service-worker": 0,
+/******/                       
"webpack_sharing_consume_default_react-dom_react-dom-webpack_sharing_consume_default_react_rea-153fef":
 0
+/******/               };
+/******/
+/******/               // no chunk on demand loading
+/******/
+/******/               // no prefetching
+/******/
+/******/               // no preloaded
+/******/
+/******/               var currentUpdatedModulesList;
+/******/               var waitingUpdateResolves = {};
+/******/               function loadUpdateChunk(chunkId, updatedModulesList) {
+/******/                       currentUpdatedModulesList = updatedModulesList;
+/******/                       return new Promise((resolve, reject) => {
+/******/                               waitingUpdateResolves[chunkId] = 
resolve;
+/******/                               // start update chunk loading
+/******/                               var url = __webpack_require__.p + 
__webpack_require__.hu(chunkId);
+/******/                               // create error before stack unwound to 
get useful stacktrace later
+/******/                               var error = new Error();
+/******/                               var loadingEnded = (event) => {
+/******/                                       
if(waitingUpdateResolves[chunkId]) {
+/******/                                               
waitingUpdateResolves[chunkId] = undefined
+/******/                                               var errorType = event 
&& (event.type === 'load' ? 'missing' : event.type);
+/******/                                               var realSrc = event && 
event.target && event.target.src;
+/******/                                               error.message = 
'Loading hot update chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + 
realSrc + ')';
+/******/                                               error.name = 
'ChunkLoadError';
+/******/                                               error.type = errorType;
+/******/                                               error.request = realSrc;
+/******/                                               reject(error);
+/******/                                       }
+/******/                               };
+/******/                               __webpack_require__.l(url, 
loadingEnded);
+/******/                       });
+/******/               }
+/******/
+/******/               globalThis["webpackHotUpdatesuperset"] = (chunkId, 
moreModules, runtime) => {
+/******/                       for(var moduleId in moreModules) {
+/******/                               if(__webpack_require__.o(moreModules, 
moduleId)) {
+/******/                                       currentUpdate[moduleId] = 
moreModules[moduleId];
+/******/                                       if(currentUpdatedModulesList) 
currentUpdatedModulesList.push(moduleId);
+/******/                               }
+/******/                       }
+/******/                       if(runtime) currentUpdateRuntime.push(runtime);
+/******/                       if(waitingUpdateResolves[chunkId]) {
+/******/                               waitingUpdateResolves[chunkId]();
+/******/                               waitingUpdateResolves[chunkId] = 
undefined;
+/******/                       }
+/******/               };
+/******/
+/******/               var currentUpdateChunks;
+/******/               var currentUpdate;
+/******/               var currentUpdateRemovedChunks;
+/******/               var currentUpdateRuntime;
+/******/               function applyHandler(options) {
+/******/                       if (__webpack_require__.f) delete 
__webpack_require__.f.jsonpHmr;
+/******/                       currentUpdateChunks = undefined;
+/******/                       function 
getAffectedModuleEffects(updateModuleId) {
+/******/                               var outdatedModules = [updateModuleId];
+/******/                               var outdatedDependencies = {};
+/******/
+/******/                               var queue = 
outdatedModules.map(function (id) {
+/******/                                       return {
+/******/                                               chain: [id],
+/******/                                               id: id
+/******/                                       };
+/******/                               });
+/******/                               while (queue.length > 0) {
+/******/                                       var queueItem = queue.pop();
+/******/                                       var moduleId = queueItem.id;
+/******/                                       var chain = queueItem.chain;
+/******/                                       var module = 
__webpack_require__.c[moduleId];
+/******/                                       if (
+/******/                                               !module ||
+/******/                                               
(module.hot._selfAccepted && !module.hot._selfInvalidated)
+/******/                                       )
+/******/                                               continue;
+/******/                                       if (module.hot._selfDeclined) {
+/******/                                               return {
+/******/                                                       type: 
"self-declined",
+/******/                                                       chain: chain,
+/******/                                                       moduleId: 
moduleId
+/******/                                               };
+/******/                                       }
+/******/                                       if (module.hot._main) {
+/******/                                               return {
+/******/                                                       type: 
"unaccepted",
+/******/                                                       chain: chain,
+/******/                                                       moduleId: 
moduleId
+/******/                                               };
+/******/                                       }
+/******/                                       for (var i = 0; i < 
module.parents.length; i++) {
+/******/                                               var parentId = 
module.parents[i];
+/******/                                               var parent = 
__webpack_require__.c[parentId];
+/******/                                               if (!parent) continue;
+/******/                                               if 
(parent.hot._declinedDependencies[moduleId]) {
+/******/                                                       return {
+/******/                                                               type: 
"declined",
+/******/                                                               chain: 
chain.concat([parentId]),
+/******/                                                               
moduleId: moduleId,
+/******/                                                               
parentId: parentId
+/******/                                                       };
+/******/                                               }
+/******/                                               if 
(outdatedModules.indexOf(parentId) !== -1) continue;
+/******/                                               if 
(parent.hot._acceptedDependencies[moduleId]) {
+/******/                                                       if 
(!outdatedDependencies[parentId])
+/******/                                                               
outdatedDependencies[parentId] = [];
+/******/                                                       
addAllToSet(outdatedDependencies[parentId], [moduleId]);
+/******/                                                       continue;
+/******/                                               }
+/******/                                               delete 
outdatedDependencies[parentId];
+/******/                                               
outdatedModules.push(parentId);
+/******/                                               queue.push({
+/******/                                                       chain: 
chain.concat([parentId]),
+/******/                                                       id: parentId
+/******/                                               });
+/******/                                       }
+/******/                               }
+/******/
+/******/                               return {
+/******/                                       type: "accepted",
+/******/                                       moduleId: updateModuleId,
+/******/                                       outdatedModules: 
outdatedModules,
+/******/                                       outdatedDependencies: 
outdatedDependencies
+/******/                               };
+/******/                       }
+/******/
+/******/                       function addAllToSet(a, b) {
+/******/                               for (var i = 0; i < b.length; i++) {
+/******/                                       var item = b[i];
+/******/                                       if (a.indexOf(item) === -1) 
a.push(item);
+/******/                               }
+/******/                       }
+/******/
+/******/                       // at begin all updates modules are outdated
+/******/                       // the "outdated" status can propagate to 
parents if they don't accept the children
+/******/                       var outdatedDependencies = {};
+/******/                       var outdatedModules = [];
+/******/                       var appliedUpdate = {};
+/******/
+/******/                       var warnUnexpectedRequire = function 
warnUnexpectedRequire(module) {
+/******/                               console.warn(
+/******/                                       "[HMR] unexpected require(" + 
module.id + ") to disposed module"
+/******/                               );
+/******/                       };
+/******/
+/******/                       for (var moduleId in currentUpdate) {
+/******/                               if 
(__webpack_require__.o(currentUpdate, moduleId)) {
+/******/                                       var newModuleFactory = 
currentUpdate[moduleId];
+/******/                                       var result = newModuleFactory
+/******/                                               ? 
getAffectedModuleEffects(moduleId)
+/******/                                               : {
+/******/                                                               type: 
"disposed",
+/******/                                                               
moduleId: moduleId
+/******/                                                       };
+/******/                                       /** @type {Error|false} */
+/******/                                       var abortError = false;
+/******/                                       var doApply = false;
+/******/                                       var doDispose = false;
+/******/                                       var chainInfo = "";
+/******/                                       if (result.chain) {
+/******/                                               chainInfo = "\nUpdate 
propagation: " + result.chain.join(" -> ");
+/******/                                       }
+/******/                                       switch (result.type) {
+/******/                                               case "self-declined":
+/******/                                                       if 
(options.onDeclined) options.onDeclined(result);
+/******/                                                       if 
(!options.ignoreDeclined)
+/******/                                                               
abortError = new Error(
+/******/                                                                       
"Aborted because of self decline: " +
+/******/                                                                       
        result.moduleId +
+/******/                                                                       
        chainInfo
+/******/                                                               );
+/******/                                                       break;
+/******/                                               case "declined":
+/******/                                                       if 
(options.onDeclined) options.onDeclined(result);
+/******/                                                       if 
(!options.ignoreDeclined)
+/******/                                                               
abortError = new Error(
+/******/                                                                       
"Aborted because of declined dependency: " +
+/******/                                                                       
        result.moduleId +
+/******/                                                                       
        " in " +
+/******/                                                                       
        result.parentId +
+/******/                                                                       
        chainInfo
+/******/                                                               );
+/******/                                                       break;
+/******/                                               case "unaccepted":
+/******/                                                       if 
(options.onUnaccepted) options.onUnaccepted(result);
+/******/                                                       if 
(!options.ignoreUnaccepted)
+/******/                                                               
abortError = new Error(
+/******/                                                                       
"Aborted because " + moduleId + " is not accepted" + chainInfo
+/******/                                                               );
+/******/                                                       break;
+/******/                                               case "accepted":
+/******/                                                       if 
(options.onAccepted) options.onAccepted(result);
+/******/                                                       doApply = true;
+/******/                                                       break;
+/******/                                               case "disposed":
+/******/                                                       if 
(options.onDisposed) options.onDisposed(result);
+/******/                                                       doDispose = 
true;
+/******/                                                       break;
+/******/                                               default:
+/******/                                                       throw new 
Error("Unexception type " + result.type);
+/******/                                       }
+/******/                                       if (abortError) {
+/******/                                               return {
+/******/                                                       error: 
abortError
+/******/                                               };
+/******/                                       }
+/******/                                       if (doApply) {
+/******/                                               appliedUpdate[moduleId] 
= newModuleFactory;
+/******/                                               
addAllToSet(outdatedModules, result.outdatedModules);
+/******/                                               for (moduleId in 
result.outdatedDependencies) {
+/******/                                                       if 
(__webpack_require__.o(result.outdatedDependencies, moduleId)) {
+/******/                                                               if 
(!outdatedDependencies[moduleId])
+/******/                                                                       
outdatedDependencies[moduleId] = [];
+/******/                                                               
addAllToSet(
+/******/                                                                       
outdatedDependencies[moduleId],
+/******/                                                                       
result.outdatedDependencies[moduleId]
+/******/                                                               );
+/******/                                                       }
+/******/                                               }
+/******/                                       }
+/******/                                       if (doDispose) {
+/******/                                               
addAllToSet(outdatedModules, [result.moduleId]);
+/******/                                               appliedUpdate[moduleId] 
= warnUnexpectedRequire;
+/******/                                       }
+/******/                               }
+/******/                       }
+/******/                       currentUpdate = undefined;
+/******/
+/******/                       // Store self accepted outdated modules to 
require them later by the module system
+/******/                       var outdatedSelfAcceptedModules = [];
+/******/                       for (var j = 0; j < outdatedModules.length; 
j++) {
+/******/                               var outdatedModuleId = 
outdatedModules[j];
+/******/                               var module = 
__webpack_require__.c[outdatedModuleId];
+/******/                               if (
+/******/                                       module &&
+/******/                                       (module.hot._selfAccepted || 
module.hot._main) &&
+/******/                                       // removed self-accepted 
modules should not be required
+/******/                                       appliedUpdate[outdatedModuleId] 
!== warnUnexpectedRequire &&
+/******/                                       // when called invalidate 
self-accepting is not possible
+/******/                                       !module.hot._selfInvalidated
+/******/                               ) {
+/******/                                       
outdatedSelfAcceptedModules.push({
+/******/                                               module: 
outdatedModuleId,
+/******/                                               require: 
module.hot._requireSelf,
+/******/                                               errorHandler: 
module.hot._selfAccepted
+/******/                                       });
+/******/                               }
+/******/                       }
+/******/
+/******/                       var moduleOutdatedDependencies;
+/******/
+/******/                       return {
+/******/                               dispose: function () {
+/******/                                       
currentUpdateRemovedChunks.forEach(function (chunkId) {
+/******/                                               delete 
installedChunks[chunkId];
+/******/                                       });
+/******/                                       currentUpdateRemovedChunks = 
undefined;
+/******/
+/******/                                       var idx;
+/******/                                       var queue = 
outdatedModules.slice();
+/******/                                       while (queue.length > 0) {
+/******/                                               var moduleId = 
queue.pop();
+/******/                                               var module = 
__webpack_require__.c[moduleId];
+/******/                                               if (!module) continue;
+/******/
+/******/                                               var data = {};
+/******/
+/******/                                               // Call dispose handlers
+/******/                                               var disposeHandlers = 
module.hot._disposeHandlers;
+/******/                                               for (j = 0; j < 
disposeHandlers.length; j++) {
+/******/                                                       
disposeHandlers[j].call(null, data);
+/******/                                               }
+/******/                                               
__webpack_require__.hmrD[moduleId] = data;
+/******/
+/******/                                               // disable module (this 
disables requires from this module)
+/******/                                               module.hot.active = 
false;
+/******/
+/******/                                               // remove module from 
cache
+/******/                                               delete 
__webpack_require__.c[moduleId];
+/******/
+/******/                                               // when disposing there 
is no need to call dispose handler
+/******/                                               delete 
outdatedDependencies[moduleId];
+/******/
+/******/                                               // remove "parents" 
references from all children
+/******/                                               for (j = 0; j < 
module.children.length; j++) {
+/******/                                                       var child = 
__webpack_require__.c[module.children[j]];
+/******/                                                       if (!child) 
continue;
+/******/                                                       idx = 
child.parents.indexOf(moduleId);
+/******/                                                       if (idx >= 0) {
+/******/                                                               
child.parents.splice(idx, 1);
+/******/                                                       }
+/******/                                               }
+/******/                                       }
+/******/
+/******/                                       // remove outdated dependency 
from module children
+/******/                                       var dependency;
+/******/                                       for (var outdatedModuleId in 
outdatedDependencies) {
+/******/                                               if 
(__webpack_require__.o(outdatedDependencies, outdatedModuleId)) {
+/******/                                                       module = 
__webpack_require__.c[outdatedModuleId];
+/******/                                                       if (module) {
+/******/                                                               
moduleOutdatedDependencies =
+/******/                                                                       
outdatedDependencies[outdatedModuleId];
+/******/                                                               for (j 
= 0; j < moduleOutdatedDependencies.length; j++) {
+/******/                                                                       
dependency = moduleOutdatedDependencies[j];
+/******/                                                                       
idx = module.children.indexOf(dependency);
+/******/                                                                       
if (idx >= 0) module.children.splice(idx, 1);
+/******/                                                               }
+/******/                                                       }
+/******/                                               }
+/******/                                       }
+/******/                               },
+/******/                               apply: function (reportError) {
+/******/                                       var acceptPromises = [];
+/******/                                       // insert new code
+/******/                                       for (var updateModuleId in 
appliedUpdate) {
+/******/                                               if 
(__webpack_require__.o(appliedUpdate, updateModuleId)) {
+/******/                                                       
__webpack_require__.m[updateModuleId] = appliedUpdate[updateModuleId];
+/******/                                               }
+/******/                                       }
+/******/
+/******/                                       // run new runtime modules
+/******/                                       for (var i = 0; i < 
currentUpdateRuntime.length; i++) {
+/******/                                               
currentUpdateRuntime[i](__webpack_require__);
+/******/                                       }
+/******/
+/******/                                       // call accept handlers
+/******/                                       for (var outdatedModuleId in 
outdatedDependencies) {
+/******/                                               if 
(__webpack_require__.o(outdatedDependencies, outdatedModuleId)) {
+/******/                                                       var module = 
__webpack_require__.c[outdatedModuleId];
+/******/                                                       if (module) {
+/******/                                                               
moduleOutdatedDependencies =
+/******/                                                                       
outdatedDependencies[outdatedModuleId];
+/******/                                                               var 
callbacks = [];
+/******/                                                               var 
errorHandlers = [];
+/******/                                                               var 
dependenciesForCallbacks = [];
+/******/                                                               for 
(var j = 0; j < moduleOutdatedDependencies.length; j++) {
+/******/                                                                       
var dependency = moduleOutdatedDependencies[j];
+/******/                                                                       
var acceptCallback =
+/******/                                                                       
        module.hot._acceptedDependencies[dependency];
+/******/                                                                       
var errorHandler =
+/******/                                                                       
        module.hot._acceptedErrorHandlers[dependency];
+/******/                                                                       
if (acceptCallback) {
+/******/                                                                       
        if (callbacks.indexOf(acceptCallback) !== -1) continue;
+/******/                                                                       
        callbacks.push(acceptCallback);
+/******/                                                                       
        errorHandlers.push(errorHandler);
+/******/                                                                       
        dependenciesForCallbacks.push(dependency);
+/******/                                                                       
}
+/******/                                                               }
+/******/                                                               for 
(var k = 0; k < callbacks.length; k++) {
+/******/                                                                       
var result;
+/******/                                                                       
try {
+/******/                                                                       
        result = callbacks[k].call(null, moduleOutdatedDependencies);
+/******/                                                                       
} catch (err) {
+/******/                                                                       
        if (typeof errorHandlers[k] === "function") {
+/******/                                                                       
                try {
+/******/                                                                       
                        errorHandlers[k](err, {
+/******/                                                                       
                                moduleId: outdatedModuleId,
+/******/                                                                       
                                dependencyId: dependenciesForCallbacks[k]
+/******/                                                                       
                        });
+/******/                                                                       
                } catch (err2) {
+/******/                                                                       
                        if (options.onErrored) {
+/******/                                                                       
                                options.onErrored({
+/******/                                                                       
                                        type: "accept-error-handler-errored",
+/******/                                                                       
                                        moduleId: outdatedModuleId,
+/******/                                                                       
                                        dependencyId: 
dependenciesForCallbacks[k],
+/******/                                                                       
                                        error: err2,
+/******/                                                                       
                                        originalError: err
+/******/                                                                       
                                });
+/******/                                                                       
                        }
+/******/                                                                       
                        if (!options.ignoreErrored) {
+/******/                                                                       
                                reportError(err2);
+/******/                                                                       
                                reportError(err);
+/******/                                                                       
                        }
+/******/                                                                       
                }
+/******/                                                                       
        } else {
+/******/                                                                       
                if (options.onErrored) {
+/******/                                                                       
                        options.onErrored({
+/******/                                                                       
                                type: "accept-errored",
+/******/                                                                       
                                moduleId: outdatedModuleId,
+/******/                                                                       
                                dependencyId: dependenciesForCallbacks[k],
+/******/                                                                       
                                error: err
+/******/                                                                       
                        });
+/******/                                                                       
                }
+/******/                                                                       
                if (!options.ignoreErrored) {
+/******/                                                                       
                        reportError(err);
+/******/                                                                       
                }
+/******/                                                                       
        }
+/******/                                                                       
}
+/******/                                                                       
if (result && typeof result.then === "function") {
+/******/                                                                       
        acceptPromises.push(result);
+/******/                                                                       
}
+/******/                                                               }
+/******/                                                       }
+/******/                                               }
+/******/                                       }
+/******/
+/******/                                       var onAccepted = function () {
+/******/                                               // Load self accepted 
modules
+/******/                                               for (var o = 0; o < 
outdatedSelfAcceptedModules.length; o++) {
+/******/                                                       var item = 
outdatedSelfAcceptedModules[o];
+/******/                                                       var moduleId = 
item.module;
+/******/                                                       try {
+/******/                                                               
item.require(moduleId);
+/******/                                                       } catch (err) {
+/******/                                                               if 
(typeof item.errorHandler === "function") {
+/******/                                                                       
try {
+/******/                                                                       
        item.errorHandler(err, {
+/******/                                                                       
                moduleId: moduleId,
+/******/                                                                       
                module: __webpack_require__.c[moduleId]
+/******/                                                                       
        });
+/******/                                                                       
} catch (err1) {
+/******/                                                                       
        if (options.onErrored) {
+/******/                                                                       
                options.onErrored({
+/******/                                                                       
                        type: "self-accept-error-handler-errored",
+/******/                                                                       
                        moduleId: moduleId,
+/******/                                                                       
                        error: err1,
+/******/                                                                       
                        originalError: err
+/******/                                                                       
                });
+/******/                                                                       
        }
+/******/                                                                       
        if (!options.ignoreErrored) {
+/******/                                                                       
                reportError(err1);
+/******/                                                                       
                reportError(err);
+/******/                                                                       
        }
+/******/                                                                       
}
+/******/                                                               } else {
+/******/                                                                       
if (options.onErrored) {
+/******/                                                                       
        options.onErrored({
+/******/                                                                       
                type: "self-accept-errored",
+/******/                                                                       
                moduleId: moduleId,
+/******/                                                                       
                error: err
+/******/                                                                       
        });
+/******/                                                                       
}
+/******/                                                                       
if (!options.ignoreErrored) {
+/******/                                                                       
        reportError(err);
+/******/                                                                       
}
+/******/                                                               }
+/******/                                                       }
+/******/                                               }
+/******/                                       };
+/******/
+/******/                                       return 
Promise.all(acceptPromises)
+/******/                                               .then(onAccepted)
+/******/                                               .then(function () {
+/******/                                                       return 
outdatedModules;
+/******/                                               });
+/******/                               }
+/******/                       };
+/******/               }
+/******/               __webpack_require__.hmrI.jsonp = function (moduleId, 
applyHandlers) {
+/******/                       if (!currentUpdate) {
+/******/                               currentUpdate = {};
+/******/                               currentUpdateRuntime = [];
+/******/                               currentUpdateRemovedChunks = [];
+/******/                               applyHandlers.push(applyHandler);
+/******/                       }
+/******/                       if (!__webpack_require__.o(currentUpdate, 
moduleId)) {
+/******/                               currentUpdate[moduleId] = 
__webpack_require__.m[moduleId];
+/******/                       }
+/******/               };
+/******/               __webpack_require__.hmrC.jsonp = function (
+/******/                       chunkIds,
+/******/                       removedChunks,
+/******/                       removedModules,
+/******/                       promises,
+/******/                       applyHandlers,
+/******/                       updatedModulesList
+/******/               ) {
+/******/                       applyHandlers.push(applyHandler);
+/******/                       currentUpdateChunks = {};
+/******/                       currentUpdateRemovedChunks = removedChunks;
+/******/                       currentUpdate = removedModules.reduce(function 
(obj, key) {
+/******/                               obj[key] = false;
+/******/                               return obj;
+/******/                       }, {});
+/******/                       currentUpdateRuntime = [];
+/******/                       chunkIds.forEach(function (chunkId) {
+/******/                               if (
+/******/                                       
__webpack_require__.o(installedChunks, chunkId) &&
+/******/                                       installedChunks[chunkId] !== 
undefined
+/******/                               ) {
+/******/                                       
promises.push(loadUpdateChunk(chunkId, updatedModulesList));
+/******/                                       currentUpdateChunks[chunkId] = 
true;
+/******/                               } else {
+/******/                                       currentUpdateChunks[chunkId] = 
false;
+/******/                               }
+/******/                       });
+/******/                       if (__webpack_require__.f) {
+/******/                               __webpack_require__.f.jsonpHmr = 
function (chunkId, promises) {
+/******/                                       if (
+/******/                                               currentUpdateChunks &&
+/******/                                               
__webpack_require__.o(currentUpdateChunks, chunkId) &&
+/******/                                               
!currentUpdateChunks[chunkId]
+/******/                                       ) {
+/******/                                               
promises.push(loadUpdateChunk(chunkId));
+/******/                                               
currentUpdateChunks[chunkId] = true;
+/******/                                       }
+/******/                               };
+/******/                       }
+/******/               };
+/******/
+/******/               __webpack_require__.hmrM = () => {
+/******/                       if (typeof fetch === "undefined") throw new 
Error("No browser support: need fetch API");
+/******/                       return fetch(__webpack_require__.p + 
__webpack_require__.hmrF()).then((response) => {
+/******/                               if(response.status === 404) return; // 
no update available
+/******/                               if(!response.ok) throw new 
Error("Failed to fetch update manifest " + response.statusText);
+/******/                               return response.json();
+/******/                       });
+/******/               };
+/******/
+/******/               __webpack_require__.O.j = (chunkId) => 
(installedChunks[chunkId] === 0);
+/******/
+/******/               // install a JSONP callback for chunk loading
+/******/               var webpackJsonpCallback = (parentChunkLoadingFunction, 
data) => {
+/******/                       var [chunkIds, moreModules, runtime] = data;
+/******/                       // add "moreModules" to the modules object,
+/******/                       // then flag all "chunkIds" as loaded and fire 
callback
+/******/                       var moduleId, chunkId, i = 0;
+/******/                       if(chunkIds.some((id) => (installedChunks[id] 
!== 0))) {
+/******/                               for(moduleId in moreModules) {
+/******/                                       
if(__webpack_require__.o(moreModules, moduleId)) {
+/******/                                               
__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/                                       }
+/******/                               }
+/******/                               if(runtime) var result = 
runtime(__webpack_require__);
+/******/                       }
+/******/                       if(parentChunkLoadingFunction) 
parentChunkLoadingFunction(data);
+/******/                       for(;i < chunkIds.length; i++) {
+/******/                               chunkId = chunkIds[i];
+/******/                               
if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) 
{
+/******/                                       installedChunks[chunkId][0]();
+/******/                               }
+/******/                               installedChunks[chunkId] = 0;
+/******/                       }
+/******/                       return __webpack_require__.O(result);
+/******/               }
+/******/
+/******/               var chunkLoadingGlobal = 
globalThis["webpackChunksuperset"] = globalThis["webpackChunksuperset"] || [];
+/******/               
chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/               chunkLoadingGlobal.push = 
webpackJsonpCallback.bind(null, 
chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/       })();
+/******/
+/************************************************************************/
+/******/
+/******/       // module cache are used so entry inlining is disabled
+/******/       // startup
+/******/       // Load entry module and return exports
+/******/       __webpack_require__.O(undefined, 
["vendors","vendors-node_modules_rc-component_color-picker_es_index_js-node_modules_rc-component_mutate-o-484854","webpack_sharing_consume_default_react-dom_react-dom-webpack_sharing_consume_default_react_rea-153fef"],
 () => 
(__webpack_require__("./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js")))
+/******/       __webpack_require__.O(undefined, 
["vendors","vendors-node_modules_rc-component_color-picker_es_index_js-node_modules_rc-component_mutate-o-484854","webpack_sharing_consume_default_react-dom_react-dom-webpack_sharing_consume_default_react_rea-153fef"],
 () => 
(__webpack_require__("./node_modules/webpack-dev-server/client/index.js?protocol=ws%3A&hostname=0.0.0.0&port=0&pathname=%2Fws&logging=error&overlay=%7B%22errors%22%3Atrue%2C%22warnings%22%3Afalse%2C%22runtimeErrors%22%3A%22error%2520%253D%253E%2520%21%252FResizeObserver%252F.test%28error.message%29%22%7D&reconnect=10&hot=true&live-reload=true")))
+/******/       __webpack_require__.O(undefined, 
["vendors","vendors-node_modules_rc-component_color-picker_es_index_js-node_modules_rc-component_mutate-o-484854","webpack_sharing_consume_default_react-dom_react-dom-webpack_sharing_consume_default_react_rea-153fef"],
 () => (__webpack_require__("./node_modules/webpack/hot/dev-server.js")))

Review Comment:
   **Suggestion:** The service worker bundle is initializing webpack-dev-server 
and React Refresh client modules that assume a window/document DOM environment; 
when this script is executed as a service worker (which runs in a worker 
context without document or window), these modules will throw 
ReferenceError/TypeError on startup and prevent the service worker from 
installing. Restrict the startup to only load the actual service worker entry 
module so no browser-only dev tooling executes in the worker context. [logic 
error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Service worker script fails to evaluate in worker context.
   - ⚠️ `./src/service-worker.ts` install/activate handlers never execute.
   - ⚠️ PWA-style file handling for Superset is effectively disabled.
   - ⚠️ Dev-only tooling bloats and destabilizes service-worker bundle.
   ```
   </details>
   
   ```suggestion
   /******/     var __webpack_exports__ = 
__webpack_require__("./src/service-worker.ts");
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Build/run the Superset frontend in development mode so that the generated 
service
   worker bundle at `superset/static/service-worker.js` (shown in the final 
file state) is
   served to the browser as the service worker script. The bundle's main logic 
is the module
   bootstrap plus the startup block at lines 1461–1468.
   
   2. In the browser, register the service worker using this script URL (e.g.
   `navigator.serviceWorker.register('/static/service-worker.js')`), which 
causes the browser
   to execute `superset/static/service-worker.js` in a 
`ServiceWorkerGlobalScope`. During
   evaluation, the webpack bootstrap at lines 29–59 sets up 
`__webpack_require__`, and the
   startup code at lines 1461–1468 immediately runs.
   
   3. The startup block first calls `__webpack_require__.O(..., () =>
   
__webpack_require__("./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js"))`,
   
`__webpack_require__("./node_modules/webpack-dev-server/client/index.js?...")`, 
and
   `__webpack_require__("./node_modules/webpack/hot/dev-server.js")` (lines 
1464–1466). These
   modules are dev-only browser clients that assume a `window`/`document` DOM 
environment,
   while the current global is `ServiceWorkerGlobalScope` with no `document`.
   
   4. When those dev modules execute, they or the shared webpack runtime use 
`document`-based
   APIs (e.g. `document.getElementsByTagName("script")` in the chunk loader at 
lines 205–221)
   and other DOM APIs that are not available in the worker context, causing a
   `ReferenceError`/`TypeError` during service worker script evaluation. The 
exception aborts
   evaluation, and the service worker never reaches the actual entry module
   `./src/service-worker.ts`, so the SW installation/activation handlers 
defined there (see
   lines 13–19 in the eval'd source) never take effect.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/static/service-worker.js
   **Line:** 1464:1465
   **Comment:**
        *Logic Error: The service worker bundle is initializing 
webpack-dev-server and React Refresh client modules that assume a 
window/document DOM environment; when this script is executed as a service 
worker (which runs in a worker context without document or window), these 
modules will throw ReferenceError/TypeError on startup and prevent the service 
worker from installing. Restrict the startup to only load the actual service 
worker entry module so no browser-only dev tooling executes in the worker 
context.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=2cb3b7bd4f9fe69f396c15b585b261e39576a80188fd01003b970b29da802c24&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=2cb3b7bd4f9fe69f396c15b585b261e39576a80188fd01003b970b29da802c24&reaction=dislike'>👎</a>



##########
superset-frontend/src/features/themes/ThemeModal.tsx:
##########
@@ -509,26 +523,51 @@ const ThemeModal: FunctionComponent<ThemeModalProps> = ({
                 annotations={toEditorAnnotations(jsonAnnotations)}
               />
             </StyledEditorWrapper>
-            {canDevelopThemes && (
-              <div className="apply-button-container">
+            {accessibilityAnalysis && (

Review Comment:
   **Suggestion:** The accessibility analysis panel continues to display the 
last successful contrast analysis even after the JSON becomes invalid or no 
longer contains color tokens, because the render condition only checks for the 
presence of a previous analysis. This can mislead users into thinking the 
current configuration has been analyzed successfully when the "Analyze 
Contrast" button is disabled. Guard the rendering of the results with the 
current JSON validity and color-token checks so stale results are hidden when 
they no longer apply. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Theme modal shows contrast score for outdated JSON configuration.
   - ⚠️ Disabled analyze button conflicts with still-visible old results.
   - ⚠️ Can mislead admins validating WCAG of new theme JSON.
   ```
   </details>
   
   ```suggestion
               {accessibilityAnalysis &&
                 isAccessibilityJsonValid &&
                 hasColorTokens && (
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open the Theme editor modal so that `ThemeModal` from
   `superset-frontend/src/features/themes/ThemeModal.tsx` is rendered and 
visible (the
   `Modal` returned at the bottom of the file).
   
   2. In the JSON editor inside the modal (`EditorHost` configured around lines 
160–190),
   paste a valid theme JSON that includes color tokens so that
   `useThemeAnalysis(currentTheme?.json_data)` (around lines 80–90) reports
   `isAccessibilityJsonValid === true` and `hasColors === true`.
   
   3. Click the "Analyze Contrast" button (`Button` with 
`icon={<Icons.EyeOutlined />}` and
   `onClick={runAccessibilityAnalysis}` inside the `.apply-button-container` at 
lines
   513–570). This sets `accessibilityAnalysis` in the `useThemeAnalysis` hook 
and renders
   `<AccessibilityScoreResults />` because the JSX condition 
`{accessibilityAnalysis && ( ...
   )}` (lines 526–531) evaluates to true.
   
   4. Edit the JSON in the same editor so that it becomes invalid (e.g., delete 
a closing
   brace) or remove the color tokens entirely. `useThemeAnalysis` updates
   `isAccessibilityJsonValid` to `false` or `hasColors` to `false`, which 
disables the
   "Analyze Contrast" button via `disabled={!isAccessibilityJsonValid || 
!hasColorTokens}`
   (lines 545–548), but the render guard for the results still only checks
   `accessibilityAnalysis`. Since the previous analysis object remains truthy,
   `<AccessibilityScoreResults />` continues to render, showing stale results 
for JSON that
   is now invalid or lacks colors.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/features/themes/ThemeModal.tsx
   **Line:** 526:526
   **Comment:**
        *Logic Error: The accessibility analysis panel continues to display the 
last successful contrast analysis even after the JSON becomes invalid or no 
longer contains color tokens, because the render condition only checks for the 
presence of a previous analysis. This can mislead users into thinking the 
current configuration has been analyzed successfully when the "Analyze 
Contrast" button is disabled. Guard the rendering of the results with the 
current JSON validity and color-token checks so stale results are hidden when 
they no longer apply.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=2460a122f63a25ec74b486f06100015bddf64cbe8d8897f2c7d8b73a001a2f52&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37805&comment_hash=2460a122f63a25ec74b486f06100015bddf64cbe8d8897f2c7d8b73a001a2f52&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to