Compare commits

...

6 Commits

Author SHA1 Message Date
Claude Code
e6218b3efd refactor(extensions): use declare function pattern for colors bridge
Replace the registry-with-state implementation in @apache-superset/core/colors
with declare-only function signatures. The host app (ExtensionsStartup) now
provides the concrete implementations via window.superset.colors, matching
the same pattern used by the authentication module.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 12:18:19 -07:00
Claude Code
d8f2fb7e6e refactor(colors): move palette data back to @superset-ui/core, keep only API in @apache-superset/core
Per reviewer feedback: @apache-superset/core/colors should expose the interface for
accessing color schemes (types, ColorSchemeGroup enum, registry bridge functions) but
leave the implementation details — which palettes exist and their hex values — to the
host app.

- Delete categorical/ and sequential/ palette data dirs from @apache-superset/core/colors
- Restore all 13 categorical and 2 sequential @superset-ui/core scheme files to owning
  their own palette data (revert thin wrappers)
- Slim @apache-superset/core/colors/index.ts to: ColorSchemeGroup, ColorSchemeConfig,
  SequentialSchemeConfig types + registry bridge functions only
- Restore setupColors.ts to import CategoricalScheme arrays from @superset-ui/core
- Update colors.test.ts to cover only ColorSchemeGroup enum and registry bridge
- Restore @superset-ui/core/src/color/types.ts to define ColorSchemeGroup directly
- Remove now-unnecessary palette exclusions from check-custom-rules.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:31:54 -07:00
Claude Code
3bf629f12c refactor(colors): use @apache-superset/core/colors for sequential scheme IDs in CountryMap story
The Storybook control only needs scheme IDs; switch from importing the SequentialD3
CategoricalScheme instances out of @superset-ui/core to the lightweight config array
from @apache-superset/core/colors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:31:54 -07:00
Claude Code
e9dc58e757 refactor(colors): delegate @superset-ui/core palette data to @apache-superset/core/colors
- Thin-wrap all 13 categorical and 2 sequential scheme files in @superset-ui/core to
  delegate to the canonical configs in @apache-superset/core/colors
- Re-export ColorSchemeGroup from @superset-ui/core for backward compatibility
- Rewrite setupColors.ts to consume allCategoricalColorSchemeConfigs and
  allSequentialColorSchemeConfigs from @apache-superset/core/colors
- Expand colorSchemes.test.ts to cover all 13 categorical groups

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:31:53 -07:00
Claude Code
77aa873915 feat(colors): add palette data to @apache-superset/core/colors
Add ColorSchemeGroup enum and ColorSchemeConfig/SequentialSchemeConfig types,
all 13 categorical palette definitions, both sequential palette groups, a barrel
index, and a test suite to packages/superset-core. This makes @apache-superset/core
the single source of truth for Superset color palette data, usable by both the
host app and extensions.

Also excludes the new palette data dirs from the no-literal-colors custom lint rule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:31:53 -07:00
Amin Ghadersohi
70251482d2 feat(extensions): expose Superset categorical color schemes to extensions
Add a `colors` module to superset-core that lets extensions read
Superset's registered categorical color palettes without taking a
direct dependency on @superset-ui/core.

Pattern: ExtensionsStartup injects the live CategoricalSchemeRegistry
singleton into superset-core at startup via
`registerCategoricalSchemeRegistry()`. Extensions then call
`colors.getCategoricalSchemeNames()` / `colors.getSchemeColors(name)`
through the federated `@apache-superset/core` module — the same
singleton, so palettes registered by the host are visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 15:31:53 -07:00
8 changed files with 196 additions and 2 deletions

View File

@@ -58,6 +58,10 @@
"types": "./lib/components/index.d.ts",
"default": "./lib/components/index.js"
},
"./colors": {
"types": "./lib/colors/index.d.ts",
"default": "./lib/colors/index.js"
},
"./utils": {
"types": "./lib/utils/index.d.ts",
"default": "./lib/utils/index.js"

View File

@@ -0,0 +1,28 @@
/**
* 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 { ColorSchemeGroup } from '@apache-superset/core/colors';
// ─── ColorSchemeGroup enum ────────────────────────────────────────────────────
test('ColorSchemeGroup has the expected string values', () => {
expect(ColorSchemeGroup.Custom).toBe('custom');
expect(ColorSchemeGroup.Featured).toBe('featured');
expect(ColorSchemeGroup.Other).toBe('other');
});

View File

@@ -0,0 +1,51 @@
/**
* 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.
*/
// Types & enums for color scheme configuration — usable by extensions and host alike
export type { ColorSchemeConfig, SequentialSchemeConfig } from './types';
export { ColorSchemeGroup } from './types';
/**
* Minimal interface for the categorical color scheme registry.
* Mirrors the public surface of @superset-ui/core's ColorSchemeRegistry.
*/
export interface CategoricalScheme {
id: string;
label?: string;
colors: string[];
}
export interface CategoricalSchemeRegistryLike {
keys(): string[];
get(name: string): CategoricalScheme | null | undefined;
}
/**
* Returns an alphabetically sorted list of all registered categorical color
* scheme names. The host app (ExtensionsStartup) provides the implementation
* via window.superset.colors.
*/
export declare function getCategoricalSchemeNames(): string[];
/**
* Returns the color array for a named scheme, or null if not found.
* The host app (ExtensionsStartup) provides the implementation
* via window.superset.colors.
*/
export declare function getSchemeColors(schemeName: string): string[] | null;

View File

@@ -0,0 +1,46 @@
/**
* 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.
*/
/**
* Grouping/tier for a color scheme — controls how it appears in the
* scheme picker UI (e.g. Featured palettes are shown first).
*
* Mirrors @superset-ui/core's ColorSchemeGroup; kept here so
* palette configs have no dependency on @superset-ui/core.
*/
export enum ColorSchemeGroup {
Custom = 'custom',
Featured = 'featured',
Other = 'other',
}
/** Plain configuration object for a categorical color scheme. */
export interface ColorSchemeConfig {
id: string;
label?: string;
colors: string[];
description?: string;
isDefault?: boolean;
group?: ColorSchemeGroup;
}
/** Extension of ColorSchemeConfig for sequential / diverging schemes. */
export interface SequentialSchemeConfig extends ColorSchemeConfig {
isDiverging?: boolean;
}

View File

@@ -29,3 +29,4 @@ export * as theme from './theme';
export * as translation from './translation';
export * as components from './components';
export * as utils from './utils';
export * as colors from './colors';

View File

@@ -24,6 +24,12 @@ import {
CategoricalD3,
CategoricalGoogle,
CategoricalLyft,
CategoricalModernSunset,
CategoricalColorsOfRainbow,
CategoricalBlueToGreen,
CategoricalRedToYellow,
CategoricalWavesOfBlue,
CategoricalPresetSuperset,
SequentialCommon,
SequentialD3,
CategoricalScheme,
@@ -41,22 +47,59 @@ describe('Color Schemes', () => {
CategoricalLyft,
CategoricalSuperset,
CategoricalPreset,
CategoricalModernSunset,
CategoricalColorsOfRainbow,
CategoricalBlueToGreen,
CategoricalRedToYellow,
CategoricalWavesOfBlue,
CategoricalPresetSuperset,
].forEach(group => {
expect(group).toBeInstanceOf(Array);
expect(group.length).toBeGreaterThan(0);
group.forEach(scheme =>
expect(scheme).toBeInstanceOf(CategoricalScheme),
);
});
});
test('each scheme has a non-empty id and at least one color', () => {
[
...CategoricalAirbnb,
...CategoricalD3,
...CategoricalEcharts,
...CategoricalGoogle,
...CategoricalLyft,
...CategoricalPreset,
...CategoricalSuperset,
...CategoricalPresetSuperset,
...CategoricalModernSunset,
...CategoricalColorsOfRainbow,
...CategoricalBlueToGreen,
...CategoricalRedToYellow,
...CategoricalWavesOfBlue,
].forEach(scheme => {
expect(scheme.id).toBeTruthy();
expect(scheme.colors.length).toBeGreaterThan(0);
});
});
});
describe('sequential', () => {
test('returns an array of SequentialScheme', () => {
[SequentialCommon, SequentialD3].forEach(group => {
expect(group).toBeInstanceOf(Array);
expect(group.length).toBeGreaterThan(0);
group.forEach(scheme =>
expect(scheme).toBeInstanceOf(SequentialScheme),
);
});
});
test('each scheme has a non-empty id and at least two colors', () => {
[...SequentialCommon, ...SequentialD3].forEach(scheme => {
expect(scheme.id).toBeTruthy();
expect(scheme.colors.length).toBeGreaterThanOrEqual(2);
});
});
});
});

View File

@@ -593,7 +593,7 @@ function main() {
/\.stories\./,
/\/demo\//,
/\/examples\//,
/\/color\/colorSchemes\//,
/\/color\/colorSchemes\//, // @superset-ui/core palette scheme definitions legitimately contain colors
/\/cypress\//,
/\/cypress-base\//,
/\/esm\//,

View File

@@ -19,7 +19,12 @@
import { useEffect, useState } from 'react';
// eslint-disable-next-line no-restricted-syntax
import * as supersetCore from '@apache-superset/core';
import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core';
import {
FeatureFlag,
isFeatureEnabled,
getCategoricalSchemeRegistry,
} from '@superset-ui/core';
import type { CategoricalSchemeRegistryLike } from '@apache-superset/core/colors';
import {
authentication,
core,
@@ -45,6 +50,11 @@ declare global {
menus: typeof menus;
sqlLab: typeof sqlLab;
views: typeof views;
colors: {
ColorSchemeGroup: typeof supersetCore.colors.ColorSchemeGroup;
getCategoricalSchemeNames(): string[];
getSchemeColors(schemeName: string): string[] | null;
};
};
}
}
@@ -68,6 +78,8 @@ const ExtensionsStartup: React.FC<{ children?: React.ReactNode }> = ({
}
// Provide the implementations for @apache-superset/core
const registry =
getCategoricalSchemeRegistry() as CategoricalSchemeRegistryLike | null;
window.superset = {
...supersetCore,
authentication,
@@ -78,6 +90,15 @@ const ExtensionsStartup: React.FC<{ children?: React.ReactNode }> = ({
menus,
sqlLab,
views,
colors: {
ColorSchemeGroup: supersetCore.colors.ColorSchemeGroup,
getCategoricalSchemeNames(): string[] {
return (registry?.keys() ?? []).sort();
},
getSchemeColors(schemeName: string): string[] | null {
return registry?.get(schemeName)?.colors ?? null;
},
},
};
const setup = async () => {