@cloud-ru/ds-theme 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +201 -0
- package/README.md +365 -0
- package/dist/cjs/components/ChildThemeProvider/ChildThemeProvider.d.ts +24 -0
- package/dist/cjs/components/ChildThemeProvider/ChildThemeProvider.js +25 -0
- package/dist/cjs/components/ChildThemeProvider/index.d.ts +1 -0
- package/dist/cjs/components/ChildThemeProvider/index.js +17 -0
- package/dist/cjs/components/RootThemeProvider/RootThemeProvider.d.ts +49 -0
- package/dist/cjs/components/RootThemeProvider/RootThemeProvider.js +30 -0
- package/dist/cjs/components/RootThemeProvider/index.d.ts +1 -0
- package/dist/cjs/components/RootThemeProvider/index.js +17 -0
- package/dist/cjs/components/ThemeProvider/ThemeProvider.d.ts +28 -0
- package/dist/cjs/components/ThemeProvider/ThemeProvider.js +16 -0
- package/dist/cjs/components/ThemeProvider/index.d.ts +1 -0
- package/dist/cjs/components/ThemeProvider/index.js +17 -0
- package/dist/cjs/components/ThemeScope/ThemeScope.d.ts +32 -0
- package/dist/cjs/components/ThemeScope/ThemeScope.js +65 -0
- package/dist/cjs/components/ThemeScope/index.d.ts +1 -0
- package/dist/cjs/components/ThemeScope/index.js +17 -0
- package/dist/cjs/components/index.d.ts +3 -0
- package/dist/cjs/components/index.js +19 -0
- package/dist/cjs/constants/appearance.d.ts +22 -0
- package/dist/cjs/constants/appearance.js +27 -0
- package/dist/cjs/constants/colorScheme.d.ts +17 -0
- package/dist/cjs/constants/colorScheme.js +23 -0
- package/dist/cjs/constants/index.d.ts +2 -0
- package/dist/cjs/constants/index.js +18 -0
- package/dist/cjs/context/appearanceContext.d.ts +20 -0
- package/dist/cjs/context/appearanceContext.js +22 -0
- package/dist/cjs/context/index.d.ts +4 -0
- package/dist/cjs/context/index.js +7 -0
- package/dist/cjs/context/themeContext.d.ts +12 -0
- package/dist/cjs/context/themeContext.js +15 -0
- package/dist/cjs/hooks/index.d.ts +4 -0
- package/dist/cjs/hooks/index.js +20 -0
- package/dist/cjs/hooks/useApplyCustomTheme.d.ts +27 -0
- package/dist/cjs/hooks/useApplyCustomTheme.js +39 -0
- package/dist/cjs/hooks/useColorScheme.d.ts +37 -0
- package/dist/cjs/hooks/useColorScheme.js +80 -0
- package/dist/cjs/hooks/useIsomorphicLayoutEffect.d.ts +7 -0
- package/dist/cjs/hooks/useIsomorphicLayoutEffect.js +16 -0
- package/dist/cjs/hooks/useThemeClassnames.d.ts +11 -0
- package/dist/cjs/hooks/useThemeClassnames.js +18 -0
- package/dist/cjs/hooks/useThemeConfig.d.ts +24 -0
- package/dist/cjs/hooks/useThemeConfig.js +15 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.js +23 -0
- package/dist/cjs/keys.d.ts +4 -0
- package/dist/cjs/keys.js +19 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/ssr.d.ts +15 -0
- package/dist/cjs/ssr.js +38 -0
- package/dist/cjs/store/globalStore.d.ts +29 -0
- package/dist/cjs/store/globalStore.js +72 -0
- package/dist/cjs/store/index.d.ts +1 -0
- package/dist/cjs/store/index.js +17 -0
- package/dist/cjs/types/appearance.d.ts +23 -0
- package/dist/cjs/types/appearance.js +3 -0
- package/dist/cjs/types/colorScheme.d.ts +5 -0
- package/dist/cjs/types/colorScheme.js +2 -0
- package/dist/cjs/types/index.d.ts +2 -0
- package/dist/cjs/types/index.js +18 -0
- package/dist/cjs/utils/colorSchemeFromHeaders.d.ts +22 -0
- package/dist/cjs/utils/colorSchemeFromHeaders.js +44 -0
- package/dist/cjs/utils/colorSchemeStorage.d.ts +35 -0
- package/dist/cjs/utils/colorSchemeStorage.js +85 -0
- package/dist/cjs/utils/customTheme/buildBrandPaletteCss.d.ts +11 -0
- package/dist/cjs/utils/customTheme/buildBrandPaletteCss.js +35 -0
- package/dist/cjs/utils/customTheme/buildBrandPaletteVars.d.ts +11 -0
- package/dist/cjs/utils/customTheme/buildBrandPaletteVars.js +42 -0
- package/dist/cjs/utils/customTheme/color/apca.d.ts +4 -0
- package/dist/cjs/utils/customTheme/color/apca.js +62 -0
- package/dist/cjs/utils/customTheme/color/colorSpace.d.ts +5 -0
- package/dist/cjs/utils/customTheme/color/colorSpace.js +72 -0
- package/dist/cjs/utils/customTheme/color/conversions.d.ts +17 -0
- package/dist/cjs/utils/customTheme/color/conversions.js +101 -0
- package/dist/cjs/utils/customTheme/color/hex.d.ts +10 -0
- package/dist/cjs/utils/customTheme/color/hex.js +34 -0
- package/dist/cjs/utils/customTheme/color/index.d.ts +4 -0
- package/dist/cjs/utils/customTheme/color/index.js +20 -0
- package/dist/cjs/utils/customTheme/color/oklch.d.ts +3 -0
- package/dist/cjs/utils/customTheme/color/oklch.js +21 -0
- package/dist/cjs/utils/customTheme/color/types.d.ts +40 -0
- package/dist/cjs/utils/customTheme/color/types.js +2 -0
- package/dist/cjs/utils/customTheme/constants.d.ts +31 -0
- package/dist/cjs/utils/customTheme/constants.js +49 -0
- package/dist/cjs/utils/customTheme/generateBrandPalette.d.ts +10 -0
- package/dist/cjs/utils/customTheme/generateBrandPalette.js +25 -0
- package/dist/cjs/utils/customTheme/index.d.ts +4 -0
- package/dist/cjs/utils/customTheme/index.js +20 -0
- package/dist/cjs/utils/getThemeClassnames.d.ts +17 -0
- package/dist/cjs/utils/getThemeClassnames.js +38 -0
- package/dist/cjs/utils/index.d.ts +7 -0
- package/dist/cjs/utils/index.js +23 -0
- package/dist/cjs/utils/mergeAppearance.d.ts +7 -0
- package/dist/cjs/utils/mergeAppearance.js +17 -0
- package/dist/cjs/utils/resolveColorScheme.d.ts +7 -0
- package/dist/cjs/utils/resolveColorScheme.js +15 -0
- package/dist/cjs/utils/themeBootstrap.d.ts +12 -0
- package/dist/cjs/utils/themeBootstrap.js +19 -0
- package/dist/esm/components/ChildThemeProvider/ChildThemeProvider.d.ts +24 -0
- package/dist/esm/components/ChildThemeProvider/ChildThemeProvider.js +22 -0
- package/dist/esm/components/ChildThemeProvider/index.d.ts +1 -0
- package/dist/esm/components/ChildThemeProvider/index.js +1 -0
- package/dist/esm/components/RootThemeProvider/RootThemeProvider.d.ts +49 -0
- package/dist/esm/components/RootThemeProvider/RootThemeProvider.js +27 -0
- package/dist/esm/components/RootThemeProvider/index.d.ts +1 -0
- package/dist/esm/components/RootThemeProvider/index.js +1 -0
- package/dist/esm/components/ThemeProvider/ThemeProvider.d.ts +28 -0
- package/dist/esm/components/ThemeProvider/ThemeProvider.js +13 -0
- package/dist/esm/components/ThemeProvider/index.d.ts +1 -0
- package/dist/esm/components/ThemeProvider/index.js +1 -0
- package/dist/esm/components/ThemeScope/ThemeScope.d.ts +32 -0
- package/dist/esm/components/ThemeScope/ThemeScope.js +59 -0
- package/dist/esm/components/ThemeScope/index.d.ts +1 -0
- package/dist/esm/components/ThemeScope/index.js +1 -0
- package/dist/esm/components/index.d.ts +3 -0
- package/dist/esm/components/index.js +3 -0
- package/dist/esm/constants/appearance.d.ts +22 -0
- package/dist/esm/constants/appearance.js +24 -0
- package/dist/esm/constants/colorScheme.d.ts +17 -0
- package/dist/esm/constants/colorScheme.js +20 -0
- package/dist/esm/constants/index.d.ts +2 -0
- package/dist/esm/constants/index.js +2 -0
- package/dist/esm/context/appearanceContext.d.ts +20 -0
- package/dist/esm/context/appearanceContext.js +18 -0
- package/dist/esm/context/index.d.ts +4 -0
- package/dist/esm/context/index.js +2 -0
- package/dist/esm/context/themeContext.d.ts +12 -0
- package/dist/esm/context/themeContext.js +11 -0
- package/dist/esm/hooks/index.d.ts +4 -0
- package/dist/esm/hooks/index.js +4 -0
- package/dist/esm/hooks/useApplyCustomTheme.d.ts +27 -0
- package/dist/esm/hooks/useApplyCustomTheme.js +36 -0
- package/dist/esm/hooks/useColorScheme.d.ts +37 -0
- package/dist/esm/hooks/useColorScheme.js +76 -0
- package/dist/esm/hooks/useIsomorphicLayoutEffect.d.ts +7 -0
- package/dist/esm/hooks/useIsomorphicLayoutEffect.js +13 -0
- package/dist/esm/hooks/useThemeClassnames.d.ts +11 -0
- package/dist/esm/hooks/useThemeClassnames.js +15 -0
- package/dist/esm/hooks/useThemeConfig.d.ts +24 -0
- package/dist/esm/hooks/useThemeConfig.js +12 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/keys.d.ts +4 -0
- package/dist/esm/keys.js +16 -0
- package/dist/esm/ssr.d.ts +15 -0
- package/dist/esm/ssr.js +15 -0
- package/dist/esm/store/globalStore.d.ts +29 -0
- package/dist/esm/store/globalStore.js +69 -0
- package/dist/esm/store/index.d.ts +1 -0
- package/dist/esm/store/index.js +1 -0
- package/dist/esm/types/appearance.d.ts +23 -0
- package/dist/esm/types/appearance.js +2 -0
- package/dist/esm/types/colorScheme.d.ts +5 -0
- package/dist/esm/types/colorScheme.js +1 -0
- package/dist/esm/types/index.d.ts +2 -0
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/utils/colorSchemeFromHeaders.d.ts +22 -0
- package/dist/esm/utils/colorSchemeFromHeaders.js +40 -0
- package/dist/esm/utils/colorSchemeStorage.d.ts +35 -0
- package/dist/esm/utils/colorSchemeStorage.js +81 -0
- package/dist/esm/utils/customTheme/buildBrandPaletteCss.d.ts +11 -0
- package/dist/esm/utils/customTheme/buildBrandPaletteCss.js +32 -0
- package/dist/esm/utils/customTheme/buildBrandPaletteVars.d.ts +11 -0
- package/dist/esm/utils/customTheme/buildBrandPaletteVars.js +39 -0
- package/dist/esm/utils/customTheme/color/apca.d.ts +4 -0
- package/dist/esm/utils/customTheme/color/apca.js +59 -0
- package/dist/esm/utils/customTheme/color/colorSpace.d.ts +5 -0
- package/dist/esm/utils/customTheme/color/colorSpace.js +68 -0
- package/dist/esm/utils/customTheme/color/conversions.d.ts +17 -0
- package/dist/esm/utils/customTheme/color/conversions.js +91 -0
- package/dist/esm/utils/customTheme/color/hex.d.ts +10 -0
- package/dist/esm/utils/customTheme/color/hex.js +29 -0
- package/dist/esm/utils/customTheme/color/index.d.ts +4 -0
- package/dist/esm/utils/customTheme/color/index.js +4 -0
- package/dist/esm/utils/customTheme/color/oklch.d.ts +3 -0
- package/dist/esm/utils/customTheme/color/oklch.js +18 -0
- package/dist/esm/utils/customTheme/color/types.d.ts +40 -0
- package/dist/esm/utils/customTheme/color/types.js +1 -0
- package/dist/esm/utils/customTheme/constants.d.ts +31 -0
- package/dist/esm/utils/customTheme/constants.js +46 -0
- package/dist/esm/utils/customTheme/generateBrandPalette.d.ts +10 -0
- package/dist/esm/utils/customTheme/generateBrandPalette.js +22 -0
- package/dist/esm/utils/customTheme/index.d.ts +4 -0
- package/dist/esm/utils/customTheme/index.js +4 -0
- package/dist/esm/utils/getThemeClassnames.d.ts +17 -0
- package/dist/esm/utils/getThemeClassnames.js +34 -0
- package/dist/esm/utils/index.d.ts +7 -0
- package/dist/esm/utils/index.js +7 -0
- package/dist/esm/utils/mergeAppearance.d.ts +7 -0
- package/dist/esm/utils/mergeAppearance.js +14 -0
- package/dist/esm/utils/resolveColorScheme.d.ts +7 -0
- package/dist/esm/utils/resolveColorScheme.js +12 -0
- package/dist/esm/utils/themeBootstrap.d.ts +12 -0
- package/dist/esm/utils/themeBootstrap.js +16 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +45 -0
- package/src/components/ChildThemeProvider/ChildThemeProvider.tsx +54 -0
- package/src/components/ChildThemeProvider/index.ts +1 -0
- package/src/components/RootThemeProvider/RootThemeProvider.tsx +87 -0
- package/src/components/RootThemeProvider/index.ts +1 -0
- package/src/components/ThemeProvider/ThemeProvider.tsx +41 -0
- package/src/components/ThemeProvider/index.ts +1 -0
- package/src/components/ThemeScope/ThemeScope.tsx +106 -0
- package/src/components/ThemeScope/index.ts +1 -0
- package/src/components/index.ts +3 -0
- package/src/constants/appearance.ts +27 -0
- package/src/constants/colorScheme.ts +23 -0
- package/src/constants/index.ts +2 -0
- package/src/context/appearanceContext.tsx +39 -0
- package/src/context/index.ts +4 -0
- package/src/context/themeContext.ts +18 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useApplyCustomTheme.ts +56 -0
- package/src/hooks/useColorScheme.ts +131 -0
- package/src/hooks/useIsomorphicLayoutEffect.ts +17 -0
- package/src/hooks/useThemeClassnames.ts +18 -0
- package/src/hooks/useThemeConfig.tsx +44 -0
- package/src/index.ts +7 -0
- package/src/keys.ts +18 -0
- package/src/ssr.ts +25 -0
- package/src/store/globalStore.ts +93 -0
- package/src/store/index.ts +1 -0
- package/src/types/appearance.ts +29 -0
- package/src/types/colorScheme.ts +7 -0
- package/src/types/index.ts +2 -0
- package/src/utils/colorSchemeFromHeaders.ts +57 -0
- package/src/utils/colorSchemeStorage.ts +117 -0
- package/src/utils/customTheme/buildBrandPaletteCss.ts +37 -0
- package/src/utils/customTheme/buildBrandPaletteVars.ts +56 -0
- package/src/utils/customTheme/color/apca.ts +74 -0
- package/src/utils/customTheme/color/colorSpace.ts +82 -0
- package/src/utils/customTheme/color/conversions.ts +113 -0
- package/src/utils/customTheme/color/hex.ts +39 -0
- package/src/utils/customTheme/color/index.ts +4 -0
- package/src/utils/customTheme/color/oklch.ts +22 -0
- package/src/utils/customTheme/color/types.ts +32 -0
- package/src/utils/customTheme/constants.ts +57 -0
- package/src/utils/customTheme/generateBrandPalette.ts +30 -0
- package/src/utils/customTheme/index.ts +4 -0
- package/src/utils/getThemeClassnames.ts +40 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/mergeAppearance.ts +16 -0
- package/src/utils/resolveColorScheme.ts +15 -0
- package/src/utils/themeBootstrap.ts +18 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Тон акцента (`--sn-brand-color-primary-55`) — им становится сам seed-цвет. */
|
|
2
|
+
export declare const PRIMARY_ACCENT_TONE = "55";
|
|
3
|
+
/** Near-white тон для текста на акценте (совпадает с дефолтом `onAccentLight` бренда `brandA`). */
|
|
4
|
+
export declare const NEAR_WHITE_TONE = "99";
|
|
5
|
+
/** Near-dark тон для текста на акценте (совпадает с дефолтом `onAccentDark` бренда `brandA`). */
|
|
6
|
+
export declare const NEAR_DARK_TONE = "5";
|
|
7
|
+
/** Все числовые тоны палитры `--sn-brand-color-primary-<tone>`. */
|
|
8
|
+
export declare const BRAND_PRIMARY_TONES: readonly ["5", "10", "15", "25", "45", "55", "60", "65", "80", "90", "95", "99"];
|
|
9
|
+
export type BrandPrimaryTone = (typeof BRAND_PRIMARY_TONES)[number];
|
|
10
|
+
/** Опорные hex тонов бренда `brandA` — источник `L`/`C` для генерации по любому seed-цвету. */
|
|
11
|
+
export declare const BASE_BRAND_PALETTE: Record<BrandPrimaryTone, string>;
|
|
12
|
+
/** Префикс CSS-переменных бренд-палитры. */
|
|
13
|
+
export declare const BRAND_PRIMARY_VAR_PREFIX = "--sn-brand-color-primary-";
|
|
14
|
+
/** Alpha-суффикс для `--sn-brand-color-primary-transparent` (совпадает с дефолтом `#389f7424` бренда `brandA`). */
|
|
15
|
+
export declare const TRANSPARENT_ALPHA_SUFFIX = "24";
|
|
16
|
+
/**
|
|
17
|
+
* Тинты акцента для activated-состояний (`--sn-brand-color-state-activated-*-background`) — это
|
|
18
|
+
* акцентный тон с alpha. Суффиксы совпадают с дефолтами brandA (`#389f7426/59/73`). Без них
|
|
19
|
+
* activated-заливки (выбранная строка таблицы, active-состояния) не следуют за кастомным бренд-цветом.
|
|
20
|
+
*/
|
|
21
|
+
export declare const ACTIVATED_ALPHA_SUFFIX: {
|
|
22
|
+
readonly default: "26";
|
|
23
|
+
readonly hovered: "59";
|
|
24
|
+
readonly pressed: "73";
|
|
25
|
+
};
|
|
26
|
+
/** Имена CSS-переменных activated-заливок. */
|
|
27
|
+
export declare const BRAND_ACTIVATED_VAR: {
|
|
28
|
+
readonly default: "--sn-brand-color-state-activated-default-background";
|
|
29
|
+
readonly hovered: "--sn-brand-color-state-activated-hovered-background";
|
|
30
|
+
readonly pressed: "--sn-brand-color-state-activated-pressed-background";
|
|
31
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Опорная палитра и тон-константы для генерации кастомного бренд-цвета. Тоновый набор и дефолтные
|
|
3
|
+
// hex совпадают с `--sn-brand-color-primary-<tone>` бренда `brandA` из `@cloud-ru/figma-variables`:
|
|
4
|
+
// генератор держит `L`/`C` этих тонов и поворачивает hue к seed-цвету потребителя.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BRAND_ACTIVATED_VAR = exports.ACTIVATED_ALPHA_SUFFIX = exports.TRANSPARENT_ALPHA_SUFFIX = exports.BRAND_PRIMARY_VAR_PREFIX = exports.BASE_BRAND_PALETTE = exports.BRAND_PRIMARY_TONES = exports.NEAR_DARK_TONE = exports.NEAR_WHITE_TONE = exports.PRIMARY_ACCENT_TONE = void 0;
|
|
7
|
+
/** Тон акцента (`--sn-brand-color-primary-55`) — им становится сам seed-цвет. */
|
|
8
|
+
exports.PRIMARY_ACCENT_TONE = '55';
|
|
9
|
+
/** Near-white тон для текста на акценте (совпадает с дефолтом `onAccentLight` бренда `brandA`). */
|
|
10
|
+
exports.NEAR_WHITE_TONE = '99';
|
|
11
|
+
/** Near-dark тон для текста на акценте (совпадает с дефолтом `onAccentDark` бренда `brandA`). */
|
|
12
|
+
exports.NEAR_DARK_TONE = '5';
|
|
13
|
+
/** Все числовые тоны палитры `--sn-brand-color-primary-<tone>`. */
|
|
14
|
+
exports.BRAND_PRIMARY_TONES = ['5', '10', '15', '25', '45', '55', '60', '65', '80', '90', '95', '99'];
|
|
15
|
+
/** Опорные hex тонов бренда `brandA` — источник `L`/`C` для генерации по любому seed-цвету. */
|
|
16
|
+
exports.BASE_BRAND_PALETTE = {
|
|
17
|
+
'5': '#21372f',
|
|
18
|
+
'10': '#243e35',
|
|
19
|
+
'15': '#2b483c',
|
|
20
|
+
'25': '#2c5e49',
|
|
21
|
+
'45': '#22775b',
|
|
22
|
+
'55': '#389f74',
|
|
23
|
+
'60': '#5ebb91',
|
|
24
|
+
'65': '#85ceaa',
|
|
25
|
+
'80': '#caeadb',
|
|
26
|
+
'90': '#edf7f1',
|
|
27
|
+
'95': '#f5fdf8',
|
|
28
|
+
'99': '#fbfffc',
|
|
29
|
+
};
|
|
30
|
+
/** Префикс CSS-переменных бренд-палитры. */
|
|
31
|
+
exports.BRAND_PRIMARY_VAR_PREFIX = '--sn-brand-color-primary-';
|
|
32
|
+
/** Alpha-суффикс для `--sn-brand-color-primary-transparent` (совпадает с дефолтом `#389f7424` бренда `brandA`). */
|
|
33
|
+
exports.TRANSPARENT_ALPHA_SUFFIX = '24';
|
|
34
|
+
/**
|
|
35
|
+
* Тинты акцента для activated-состояний (`--sn-brand-color-state-activated-*-background`) — это
|
|
36
|
+
* акцентный тон с alpha. Суффиксы совпадают с дефолтами brandA (`#389f7426/59/73`). Без них
|
|
37
|
+
* activated-заливки (выбранная строка таблицы, active-состояния) не следуют за кастомным бренд-цветом.
|
|
38
|
+
*/
|
|
39
|
+
exports.ACTIVATED_ALPHA_SUFFIX = {
|
|
40
|
+
default: '26',
|
|
41
|
+
hovered: '59',
|
|
42
|
+
pressed: '73',
|
|
43
|
+
};
|
|
44
|
+
/** Имена CSS-переменных activated-заливок. */
|
|
45
|
+
exports.BRAND_ACTIVATED_VAR = {
|
|
46
|
+
default: '--sn-brand-color-state-activated-default-background',
|
|
47
|
+
hovered: '--sn-brand-color-state-activated-hovered-background',
|
|
48
|
+
pressed: '--sn-brand-color-state-activated-pressed-background',
|
|
49
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BrandPrimaryTone } from './constants';
|
|
2
|
+
/** Сгенерированная бренд-палитра: тон → hex. */
|
|
3
|
+
export type BrandPalette = Record<BrandPrimaryTone, string>;
|
|
4
|
+
/**
|
|
5
|
+
* Строит бренд-палитру из одного seed-цвета: берёт `L`/`C` каждого опорного тона `BASE_BRAND_PALETTE`
|
|
6
|
+
* и поворачивает hue к hue seed-цвета (OKLCH). Тон акцента (`55`) становится самим seed-цветом.
|
|
7
|
+
* Так один цвет потребителя перекрашивает всю шкалу `--sn-brand-color-primary-<tone>`, сохраняя
|
|
8
|
+
* светлоту/насыщенность DS-палитры. Невалидный hex → `null`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateBrandPalette(seedColor: string): BrandPalette | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateBrandPalette = generateBrandPalette;
|
|
4
|
+
const color_1 = require("./color");
|
|
5
|
+
const constants_1 = require("./constants");
|
|
6
|
+
/**
|
|
7
|
+
* Строит бренд-палитру из одного seed-цвета: берёт `L`/`C` каждого опорного тона `BASE_BRAND_PALETTE`
|
|
8
|
+
* и поворачивает hue к hue seed-цвета (OKLCH). Тон акцента (`55`) становится самим seed-цветом.
|
|
9
|
+
* Так один цвет потребителя перекрашивает всю шкалу `--sn-brand-color-primary-<tone>`, сохраняя
|
|
10
|
+
* светлоту/насыщенность DS-палитры. Невалидный hex → `null`.
|
|
11
|
+
*/
|
|
12
|
+
function generateBrandPalette(seedColor) {
|
|
13
|
+
const seed = (0, color_1.hex2color)(seedColor);
|
|
14
|
+
if (!seed) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const { h: hue } = seed;
|
|
18
|
+
const palette = {};
|
|
19
|
+
for (const tone of constants_1.BRAND_PRIMARY_TONES) {
|
|
20
|
+
const baseHex = tone === constants_1.PRIMARY_ACCENT_TONE ? seedColor : constants_1.BASE_BRAND_PALETTE[tone];
|
|
21
|
+
const base = (0, color_1.hex2color)(baseHex);
|
|
22
|
+
palette[tone] = base ? (0, color_1.lch2color)([base.l, base.c, hue]).hex : baseHex;
|
|
23
|
+
}
|
|
24
|
+
return palette;
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./constants"), exports);
|
|
18
|
+
__exportStar(require("./generateBrandPalette"), exports);
|
|
19
|
+
__exportStar(require("./buildBrandPaletteVars"), exports);
|
|
20
|
+
__exportStar(require("./buildBrandPaletteCss"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ThemeAppearance } from '../types/appearance';
|
|
2
|
+
/**
|
|
3
|
+
* Чистая функция: собирает **полный** набор `sn-*` классов из осей оформления списком токенов.
|
|
4
|
+
* Полный набор обязателен на каждой DOM-границе — токены `@cloud-ru/figma-variables` не
|
|
5
|
+
* переопределяются по одной оси через CSS-каскад (см. providers-standard.md). Базовые слои
|
|
6
|
+
* (`sn-base-styles`, `sn-figmaStyles`, `sn-components`) и материал (`sn-yes`/`sn-no`)
|
|
7
|
+
* — всегда; `density`/`colorScheme`/`brand`/`brandRole` — если заданы.
|
|
8
|
+
*
|
|
9
|
+
* Списочная форма — источник истины для `getThemeClassnames` (строка через `join`) и для
|
|
10
|
+
* `element.classList.add(...)`, которому нужны отдельные токены без промежуточного `split`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getThemeClassnameList(appearance?: ThemeAppearance): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Строковая форма набора `sn-*` (через `join`). Используется на SSR (строка класса на `<html>`) и
|
|
15
|
+
* как основа хука `useThemeClassnames`. Для `classList`-операций бери `getThemeClassnameList`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getThemeClassnames(appearance?: ThemeAppearance): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getThemeClassnameList = getThemeClassnameList;
|
|
4
|
+
exports.getThemeClassnames = getThemeClassnames;
|
|
5
|
+
/**
|
|
6
|
+
* Чистая функция: собирает **полный** набор `sn-*` классов из осей оформления списком токенов.
|
|
7
|
+
* Полный набор обязателен на каждой DOM-границе — токены `@cloud-ru/figma-variables` не
|
|
8
|
+
* переопределяются по одной оси через CSS-каскад (см. providers-standard.md). Базовые слои
|
|
9
|
+
* (`sn-base-styles`, `sn-figmaStyles`, `sn-components`) и материал (`sn-yes`/`sn-no`)
|
|
10
|
+
* — всегда; `density`/`colorScheme`/`brand`/`brandRole` — если заданы.
|
|
11
|
+
*
|
|
12
|
+
* Списочная форма — источник истины для `getThemeClassnames` (строка через `join`) и для
|
|
13
|
+
* `element.classList.add(...)`, которому нужны отдельные токены без промежуточного `split`.
|
|
14
|
+
*/
|
|
15
|
+
function getThemeClassnameList(appearance = {}) {
|
|
16
|
+
const { density, colorScheme, brand, brandRole, acrylic } = appearance;
|
|
17
|
+
const classes = ['sn-base-styles', 'sn-figmaStyles', 'sn-components', acrylic ? 'sn-yes' : 'sn-no'];
|
|
18
|
+
if (density) {
|
|
19
|
+
classes.push(`sn-${density}`);
|
|
20
|
+
}
|
|
21
|
+
if (colorScheme) {
|
|
22
|
+
classes.push(`sn-${colorScheme}`);
|
|
23
|
+
}
|
|
24
|
+
if (brand) {
|
|
25
|
+
classes.push(`sn-${brand}`);
|
|
26
|
+
}
|
|
27
|
+
if (brandRole) {
|
|
28
|
+
classes.push(`sn-${brandRole}`);
|
|
29
|
+
}
|
|
30
|
+
return classes;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Строковая форма набора `sn-*` (через `join`). Используется на SSR (строка класса на `<html>`) и
|
|
34
|
+
* как основа хука `useThemeClassnames`. Для `classList`-операций бери `getThemeClassnameList`.
|
|
35
|
+
*/
|
|
36
|
+
function getThemeClassnames(appearance = {}) {
|
|
37
|
+
return getThemeClassnameList(appearance).join(' ');
|
|
38
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./mergeAppearance"), exports);
|
|
18
|
+
__exportStar(require("./getThemeClassnames"), exports);
|
|
19
|
+
__exportStar(require("./resolveColorScheme"), exports);
|
|
20
|
+
__exportStar(require("./colorSchemeStorage"), exports);
|
|
21
|
+
__exportStar(require("./colorSchemeFromHeaders"), exports);
|
|
22
|
+
__exportStar(require("./themeBootstrap"), exports);
|
|
23
|
+
__exportStar(require("./customTheme"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ThemeAppearance } from '../types/appearance';
|
|
2
|
+
/**
|
|
3
|
+
* Сливает оформление родителя с переопределениями: незаданные (`undefined`) оси `overrides` НЕ
|
|
4
|
+
* затирают унаследованные (`??` сохраняет, в т.ч. `acrylic: false`). Используется `ChildThemeProvider`
|
|
5
|
+
* для Figma-цепочки модификаторов.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mergeAppearance(parent: ThemeAppearance, overrides: Partial<ThemeAppearance>): ThemeAppearance;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeAppearance = mergeAppearance;
|
|
4
|
+
/**
|
|
5
|
+
* Сливает оформление родителя с переопределениями: незаданные (`undefined`) оси `overrides` НЕ
|
|
6
|
+
* затирают унаследованные (`??` сохраняет, в т.ч. `acrylic: false`). Используется `ChildThemeProvider`
|
|
7
|
+
* для Figma-цепочки модификаторов.
|
|
8
|
+
*/
|
|
9
|
+
function mergeAppearance(parent, overrides) {
|
|
10
|
+
return {
|
|
11
|
+
colorScheme: overrides.colorScheme ?? parent.colorScheme,
|
|
12
|
+
brand: overrides.brand ?? parent.brand,
|
|
13
|
+
brandRole: overrides.brandRole ?? parent.brandRole,
|
|
14
|
+
density: overrides.density ?? parent.density,
|
|
15
|
+
acrylic: overrides.acrylic ?? parent.acrylic,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ColorScheme, ThemeOverride } from '../types/colorScheme';
|
|
2
|
+
/**
|
|
3
|
+
* Резолв итоговой схемы: явный override (`light`/`dark`) побеждает; `system`/отсутствие — по
|
|
4
|
+
* системному `prefers-color-scheme` (`systemPrefersDark`). Поэтому «всегда светлая» остаётся
|
|
5
|
+
* светлой даже на тёмном устройстве.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveColorScheme(override: ThemeOverride | undefined, systemPrefersDark: boolean): ColorScheme;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveColorScheme = resolveColorScheme;
|
|
4
|
+
const colorScheme_1 = require("../constants/colorScheme");
|
|
5
|
+
/**
|
|
6
|
+
* Резолв итоговой схемы: явный override (`light`/`dark`) побеждает; `system`/отсутствие — по
|
|
7
|
+
* системному `prefers-color-scheme` (`systemPrefersDark`). Поэтому «всегда светлая» остаётся
|
|
8
|
+
* светлой даже на тёмном устройстве.
|
|
9
|
+
*/
|
|
10
|
+
function resolveColorScheme(override, systemPrefersDark) {
|
|
11
|
+
if (override === colorScheme_1.THEME_OVERRIDE.Light || override === colorScheme_1.THEME_OVERRIDE.Dark) {
|
|
12
|
+
return override;
|
|
13
|
+
}
|
|
14
|
+
return systemPrefersDark ? colorScheme_1.COLOR_SCHEME.Dark : colorScheme_1.COLOR_SCHEME.Light;
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Возвращает строку синхронного inline-скрипта для `<head>` (до `<body>`): читает override из
|
|
3
|
+
* cookie + `prefers-color-scheme` и ставит `sn-light`/`sn-dark` на корень ДО первой отрисовки —
|
|
4
|
+
* устраняет «моргание» темы при перезагрузке. Вставляется через `<script dangerouslySetInnerHTML>`
|
|
5
|
+
* (Next) или статическим `<script>` в `<head>` (single-spa). Читает ту же cookie, что и SSR.
|
|
6
|
+
*
|
|
7
|
+
* `target` — CSS-селектор корня; по умолчанию `<html>` (`document.documentElement`).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getThemeBootstrapScript(options?: {
|
|
10
|
+
storageKey?: string;
|
|
11
|
+
target?: string;
|
|
12
|
+
}): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getThemeBootstrapScript = getThemeBootstrapScript;
|
|
4
|
+
const colorScheme_1 = require("../constants/colorScheme");
|
|
5
|
+
/**
|
|
6
|
+
* Возвращает строку синхронного inline-скрипта для `<head>` (до `<body>`): читает override из
|
|
7
|
+
* cookie + `prefers-color-scheme` и ставит `sn-light`/`sn-dark` на корень ДО первой отрисовки —
|
|
8
|
+
* устраняет «моргание» темы при перезагрузке. Вставляется через `<script dangerouslySetInnerHTML>`
|
|
9
|
+
* (Next) или статическим `<script>` в `<head>` (single-spa). Читает ту же cookie, что и SSR.
|
|
10
|
+
*
|
|
11
|
+
* `target` — CSS-селектор корня; по умолчанию `<html>` (`document.documentElement`).
|
|
12
|
+
*/
|
|
13
|
+
function getThemeBootstrapScript(options) {
|
|
14
|
+
const storageKey = JSON.stringify(options?.storageKey ?? colorScheme_1.THEME_OVERRIDE_STORAGE_KEY);
|
|
15
|
+
const target = options?.target
|
|
16
|
+
? `document.querySelector(${JSON.stringify(options.target)})`
|
|
17
|
+
: 'document.documentElement';
|
|
18
|
+
return `(function(){try{var k=${storageKey},m=document.cookie.match(new RegExp('(?:^|; )'+k+'=([^;]*)')),o=m?decodeURIComponent(m[1]):null,d=(o==='dark')||((o==='system'||!o)&&matchMedia('(prefers-color-scheme: dark)').matches),el=${target};if(el){el.classList.toggle('sn-dark',d);el.classList.toggle('sn-light',!d);}}catch(e){}})();`;
|
|
19
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
import { ThemeAppearance } from '../../types/appearance.js';
|
|
3
|
+
export type ChildThemeProviderProps = {
|
|
4
|
+
/** Оси, переопределяемые в поддереве. Остальные наследуются от ближайшего родителя (слияние). */
|
|
5
|
+
value: Partial<ThemeAppearance>;
|
|
6
|
+
/**
|
|
7
|
+
* Внешний элемент для полного слитого набора `sn-*`. Если не задан — провайдер оборачивает
|
|
8
|
+
* children в `<div>` с этим набором.
|
|
9
|
+
*/
|
|
10
|
+
rootRef?: RefObject<HTMLElement | null>;
|
|
11
|
+
/** Дополнительный класс на wrapper-`<div>` (паддинги/фон). Только в wrapper-режиме (без `rootRef`). */
|
|
12
|
+
className?: string;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Вложенный провайдер оформления (Figma-цепочка модификаторов): читает ближайшее оформление, сливает
|
|
17
|
+
* свои `value`-переопределения и реэмитит полный слитый набор `sn-*` на границе. Потребители ниже
|
|
18
|
+
* читают уже слитое значение. Read-only — глобальное значение менять нельзя (это умеет только
|
|
19
|
+
* `RootThemeProvider`/`getGlobalThemeStore`).
|
|
20
|
+
*/
|
|
21
|
+
export declare function ChildThemeProvider({ value, rootRef, className, children }: ChildThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare namespace ChildThemeProvider {
|
|
23
|
+
var displayName: string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { staticStore } from '@cloud-ru/ds-context-kit';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { ThemeAppearanceStoreProvider, useThemeAppearance, } from '../../context/appearanceContext.js';
|
|
5
|
+
import { mergeAppearance } from '../../utils/mergeAppearance.js';
|
|
6
|
+
import { ThemeScope } from '../ThemeScope/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Вложенный провайдер оформления (Figma-цепочка модификаторов): читает ближайшее оформление, сливает
|
|
9
|
+
* свои `value`-переопределения и реэмитит полный слитый набор `sn-*` на границе. Потребители ниже
|
|
10
|
+
* читают уже слитое значение. Read-only — глобальное значение менять нельзя (это умеет только
|
|
11
|
+
* `RootThemeProvider`/`getGlobalThemeStore`).
|
|
12
|
+
*/
|
|
13
|
+
export function ChildThemeProvider({ value, rootRef, className, children }) {
|
|
14
|
+
const { appearance: parent } = useThemeAppearance();
|
|
15
|
+
const { colorScheme, brand, brandRole, density, acrylic } = value;
|
|
16
|
+
const childStore = useMemo(() => staticStore({
|
|
17
|
+
appearance: mergeAppearance(parent, { colorScheme, brand, brandRole, density, acrylic }),
|
|
18
|
+
setAppearance: undefined,
|
|
19
|
+
}), [parent, colorScheme, brand, brandRole, density, acrylic]);
|
|
20
|
+
return (_jsx(ThemeAppearanceStoreProvider, { store: childStore, children: _jsx(ThemeScope, { rootRef: rootRef, className: className, children: children }) }));
|
|
21
|
+
}
|
|
22
|
+
ChildThemeProvider.displayName = 'ChildThemeProvider';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ChildThemeProvider.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ChildThemeProvider.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
import { ThemeAppearanceStore } from '../../context/appearanceContext.js';
|
|
3
|
+
import { ThemeAppearance } from '../../types/appearance.js';
|
|
4
|
+
export type RootThemeProviderProps = {
|
|
5
|
+
/**
|
|
6
|
+
* Оформление приложения. Используется в static-режиме (один React-корень: SSR — одно значение на
|
|
7
|
+
* запрос, либо CSR с собственным state, напр. `colorScheme` из `useColorScheme`). Для multi-root
|
|
8
|
+
* (single-spa) — см. `store`.
|
|
9
|
+
*/
|
|
10
|
+
value?: ThemeAppearance;
|
|
11
|
+
/**
|
|
12
|
+
* Внешний реактивный стор оформления (`getGlobalThemeStore().store`). Если задан — приоритетнее
|
|
13
|
+
* `value`; подписанные провайдеры обновляются при смене темы без перерендера провайдера. Так один
|
|
14
|
+
* глобальный стор охватывает все микрофронты. Сеттер для shell — `getGlobalThemeStore().setAppearance`.
|
|
15
|
+
*/
|
|
16
|
+
store?: ThemeAppearanceStore;
|
|
17
|
+
/**
|
|
18
|
+
* Внешний элемент для полного набора `sn-*` (обычно `<html>`/`<body>`). Если не задан — провайдер
|
|
19
|
+
* оборачивает children в `<div>` с этим набором.
|
|
20
|
+
*/
|
|
21
|
+
rootRef?: RefObject<HTMLElement | null>;
|
|
22
|
+
/** Дополнительный класс на wrapper-`<div>` (паддинги/фон). Только в wrapper-режиме (без `rootRef`). */
|
|
23
|
+
className?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Кастомный бренд-цвет потребителя (hex `#rrggbb`) для white-label. Генерирует бренд-палитру из
|
|
26
|
+
* seed-цвета и инжектит scoped `<style>` на бренд-классы этого поддерева. Правило на бренд-классе
|
|
27
|
+
* (а не inline на одном элементе) переживает переэмиты `sn-*` вложенными компонентами (Table и т.п.),
|
|
28
|
+
* поэтому кастомный цвет доходит до всей вложенности. Невалидный hex игнорируется. Глобальная
|
|
29
|
+
* (app-root) альтернатива для порталов — хук `useApplyCustomTheme`.
|
|
30
|
+
*/
|
|
31
|
+
brandColor?: string;
|
|
32
|
+
/** CSP-`nonce` для инжектируемого `<style>` кастомного бренд-цвета. */
|
|
33
|
+
nonce?: string;
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Корневой провайдер оформления. Ставится один раз в корне приложения: задаёт контекст осей
|
|
38
|
+
* (`colorScheme`/`brand`/`brandRole`/`density`/`acrylic`) и эмитит полный набор `sn-*` на корень
|
|
39
|
+
* (`rootRef`) либо на собственный wrapper. Объект контекста — глобальный синглтон (`Symbol.for`),
|
|
40
|
+
* поэтому провайдер работает даже при нескольких версиях пакета в разных микрофронтах, а потребитель
|
|
41
|
+
* читает ближайший провайдер. Локальные переопределения осей в поддереве — через `ChildThemeProvider`.
|
|
42
|
+
*
|
|
43
|
+
* Этот провайдер НЕ управляет состоянием цветовой схемы (override/system/cross-tab) — это `useColorScheme`;
|
|
44
|
+
* результат передаётся в `value.colorScheme`. Не путать со старым `ThemeProvider` (themeMap/changeTheme).
|
|
45
|
+
*/
|
|
46
|
+
export declare function RootThemeProvider({ value, store, rootRef, className, brandColor, nonce, children, }: RootThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
export declare namespace RootThemeProvider {
|
|
48
|
+
var displayName: string;
|
|
49
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { staticStore } from '@cloud-ru/ds-context-kit';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { ThemeAppearanceStoreProvider, } from '../../context/appearanceContext.js';
|
|
5
|
+
import { ThemeScope } from '../ThemeScope/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Корневой провайдер оформления. Ставится один раз в корне приложения: задаёт контекст осей
|
|
8
|
+
* (`colorScheme`/`brand`/`brandRole`/`density`/`acrylic`) и эмитит полный набор `sn-*` на корень
|
|
9
|
+
* (`rootRef`) либо на собственный wrapper. Объект контекста — глобальный синглтон (`Symbol.for`),
|
|
10
|
+
* поэтому провайдер работает даже при нескольких версиях пакета в разных микрофронтах, а потребитель
|
|
11
|
+
* читает ближайший провайдер. Локальные переопределения осей в поддереве — через `ChildThemeProvider`.
|
|
12
|
+
*
|
|
13
|
+
* Этот провайдер НЕ управляет состоянием цветовой схемы (override/system/cross-tab) — это `useColorScheme`;
|
|
14
|
+
* результат передаётся в `value.colorScheme`. Не путать со старым `ThemeProvider` (themeMap/changeTheme).
|
|
15
|
+
*/
|
|
16
|
+
export function RootThemeProvider({ value, store, rootRef, className, brandColor, nonce, children, }) {
|
|
17
|
+
const { colorScheme, brand, brandRole, density, acrylic } = value ?? {};
|
|
18
|
+
// Мемо по значениям осей (не по идентичности объекта `value`): иначе литерал `value={{…}}` у
|
|
19
|
+
// потребителя пересоздавал бы стор на каждом рендере. Сеттер в static-режиме не нужен — значением
|
|
20
|
+
// владеет сам потребитель через проп `value`.
|
|
21
|
+
const staticThemeStore = useMemo(() => staticStore({
|
|
22
|
+
appearance: { colorScheme, brand, brandRole, density, acrylic },
|
|
23
|
+
setAppearance: undefined,
|
|
24
|
+
}), [colorScheme, brand, brandRole, density, acrylic]);
|
|
25
|
+
return (_jsx(ThemeAppearanceStoreProvider, { store: store ?? staticThemeStore, children: _jsx(ThemeScope, { rootRef: rootRef, className: className, brandColor: brandColor, nonce: nonce, children: children }) }));
|
|
26
|
+
}
|
|
27
|
+
RootThemeProvider.displayName = 'RootThemeProvider';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './RootThemeProvider.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './RootThemeProvider.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
type UseThemePropsWithDefaultTheme = {
|
|
3
|
+
/**
|
|
4
|
+
* Объект с указанием соответсвия темы и css-класса
|
|
5
|
+
*/
|
|
6
|
+
themeMap: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Значение темы по умолчанию
|
|
9
|
+
*/
|
|
10
|
+
defaultTheme: string;
|
|
11
|
+
};
|
|
12
|
+
type UseThemeProps = {
|
|
13
|
+
/**
|
|
14
|
+
* Объект с указанием соответсвия темы и css-класса
|
|
15
|
+
*/
|
|
16
|
+
themeMap: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
export type ThemeProviderProps = {
|
|
19
|
+
/**
|
|
20
|
+
* Дети, которые будут обёрнуты в провайдер
|
|
21
|
+
*/
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
} & (UseThemePropsWithDefaultTheme | UseThemeProps);
|
|
24
|
+
/**
|
|
25
|
+
* Провайдер, предназначенный для работы с темами
|
|
26
|
+
*/
|
|
27
|
+
export declare function ThemeProvider({ children, ...props }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { ThemeValueProvider } from '../../context/themeContext.js';
|
|
4
|
+
import { useThemeConfig } from '../../hooks/useThemeConfig.js';
|
|
5
|
+
/**
|
|
6
|
+
* Провайдер, предназначенный для работы с темами
|
|
7
|
+
*/
|
|
8
|
+
export function ThemeProvider({ children, ...props }) {
|
|
9
|
+
const { theme, themeClassName, changeTheme } = useThemeConfig(props);
|
|
10
|
+
// Мемоизируем объект значения (createSharedContext оборачивает его в staticStore по ссылке).
|
|
11
|
+
const value = useMemo(() => ({ theme, themeClassName, changeTheme }), [theme, themeClassName, changeTheme]);
|
|
12
|
+
return _jsx(ThemeValueProvider, { value: value, children: children });
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ThemeProvider.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ThemeProvider.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
export type ThemeScopeProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Внешний элемент, на который ставится полный набор `sn-*` (обычно `<html>`/`<body>` для корня).
|
|
5
|
+
* Если не задан — `ThemeScope` рендерит собственный wrapper `<div>` с этим набором.
|
|
6
|
+
*/
|
|
7
|
+
rootRef?: RefObject<HTMLElement | null>;
|
|
8
|
+
/**
|
|
9
|
+
* Дополнительный класс на wrapper-`<div>` (паддинги/фон вокруг темы). Действует только в wrapper-режиме;
|
|
10
|
+
* при `rootRef` игнорируется (внешним элементом владеет потребитель).
|
|
11
|
+
*/
|
|
12
|
+
className?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Кастомный бренд-цвет (hex). Инжектит scoped `<style>`, переопределяющий бренд-палитру на бренд-классах
|
|
15
|
+
* поддерева. В отличие от inline-переменных, правило на бренд-классе переживает переэмиты `sn-*` внутри
|
|
16
|
+
* (Table/Stepper и т.п.), поэтому кастомный цвет доходит до вложенных компонентов.
|
|
17
|
+
*/
|
|
18
|
+
brandColor?: string;
|
|
19
|
+
/** CSP-`nonce` для инжектируемого `<style>`. */
|
|
20
|
+
nonce?: string;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Внутренний помощник Root/Child-провайдеров: читает ближайшее оформление (= собственный стор
|
|
25
|
+
* провайдера, под которым отрендерен) и эмитит полный набор `sn-*`. Реактивен — при смене темы
|
|
26
|
+
* пересобирает и переустанавливает классы.
|
|
27
|
+
*
|
|
28
|
+
* - `rootRef` задан → классы добавляются на внешний элемент через эффект (без лишнего DOM-узла);
|
|
29
|
+
* при смене набора старые классы снимаются, новые ставятся.
|
|
30
|
+
* - `rootRef` не задан → классы навешиваются на wrapper `<div>` (+ `className` потребителя).
|
|
31
|
+
*/
|
|
32
|
+
export declare function ThemeScope({ rootRef, className, brandColor, nonce, children }: ThemeScopeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { useId, useMemo } from 'react';
|
|
4
|
+
import { useThemeAppearance } from '../../context/appearanceContext.js';
|
|
5
|
+
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect.js';
|
|
6
|
+
import { buildBrandPaletteCss } from '../../utils/customTheme/index.js';
|
|
7
|
+
import { getThemeClassnameList } from '../../utils/getThemeClassnames.js';
|
|
8
|
+
// Атрибут-маркер поддерева для scope кастомной палитры. Правило нацеливается на бренд-классы внутри
|
|
9
|
+
// этого маркера (см. `buildBrandPaletteCss`), поэтому переживает переэмиты `sn-*` вложенными обёртками.
|
|
10
|
+
const BRAND_SCOPE_ATTR = 'data-ds-brand-scope';
|
|
11
|
+
/**
|
|
12
|
+
* Внутренний помощник Root/Child-провайдеров: читает ближайшее оформление (= собственный стор
|
|
13
|
+
* провайдера, под которым отрендерен) и эмитит полный набор `sn-*`. Реактивен — при смене темы
|
|
14
|
+
* пересобирает и переустанавливает классы.
|
|
15
|
+
*
|
|
16
|
+
* - `rootRef` задан → классы добавляются на внешний элемент через эффект (без лишнего DOM-узла);
|
|
17
|
+
* при смене набора старые классы снимаются, новые ставятся.
|
|
18
|
+
* - `rootRef` не задан → классы навешиваются на wrapper `<div>` (+ `className` потребителя).
|
|
19
|
+
*/
|
|
20
|
+
export function ThemeScope({ rootRef, className, brandColor, nonce, children }) {
|
|
21
|
+
const { appearance } = useThemeAppearance();
|
|
22
|
+
// Список токенов — источник истины: `classList.add(...)` принимает их напрямую (без `split`),
|
|
23
|
+
// а wrapper-режим джойнит через `cn`. Мемо по `appearance` держит ссылку стабильной между
|
|
24
|
+
// рендерами, поэтому эффект переустанавливает классы только при реальной смене темы.
|
|
25
|
+
const themeClasses = useMemo(() => getThemeClassnameList(appearance), [appearance]);
|
|
26
|
+
const scopeId = useId();
|
|
27
|
+
const brandCss = useMemo(() => (brandColor ? buildBrandPaletteCss(brandColor, `[${BRAND_SCOPE_ATTR}="${scopeId}"]`) : null), [brandColor, scopeId]);
|
|
28
|
+
// Layout-эффект (не `useEffect`): классы/scope-маркер ставим на внешний элемент синхронно до пейнта,
|
|
29
|
+
// иначе первый кадр рендерится без набора `sn-*` (и без scoped бренд-правила) — видно моргание темы.
|
|
30
|
+
useIsomorphicLayoutEffect(() => {
|
|
31
|
+
const element = rootRef?.current;
|
|
32
|
+
if (!element) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
element.classList.add(...themeClasses);
|
|
36
|
+
return () => {
|
|
37
|
+
element.classList.remove(...themeClasses);
|
|
38
|
+
};
|
|
39
|
+
}, [rootRef, themeClasses]);
|
|
40
|
+
// В rootRef-режиме scope-маркер ставим на внешний элемент, чтобы scoped-правило достало его поддерево
|
|
41
|
+
// (в wrapper-режиме маркер — атрибут `div`а ниже).
|
|
42
|
+
useIsomorphicLayoutEffect(() => {
|
|
43
|
+
const element = rootRef?.current;
|
|
44
|
+
if (!element || !brandCss) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
element.setAttribute(BRAND_SCOPE_ATTR, scopeId);
|
|
48
|
+
return () => {
|
|
49
|
+
element.removeAttribute(BRAND_SCOPE_ATTR);
|
|
50
|
+
};
|
|
51
|
+
}, [rootRef, brandCss, scopeId]);
|
|
52
|
+
// `<style>` рендерится в дерево (React управляет монтированием/размонтированием, без ручной инъекции).
|
|
53
|
+
// В body он не имеет визуального бокса — только применяет правило по scoped-селектору.
|
|
54
|
+
const styleTag = brandCss ? _jsx("style", { nonce: nonce, children: brandCss }) : null;
|
|
55
|
+
if (rootRef) {
|
|
56
|
+
return (_jsxs(_Fragment, { children: [styleTag, children] }));
|
|
57
|
+
}
|
|
58
|
+
return (_jsxs("div", { className: cn(themeClasses, className), "data-ds-brand-scope": brandCss ? scopeId : undefined, children: [styleTag, children] }));
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ThemeScope.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ThemeScope.js';
|