@sybilion/uilib 1.0.26 → 1.0.28
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/assets/mini-app-global.css +12 -12
- package/dist/esm/components/ui/Chart/Chart.styl.js +1 -1
- package/dist/esm/components/ui/Chart/components/BaseChartWrapper.js +117 -170
- package/dist/esm/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.js +101 -1
- package/dist/esm/components/ui/ChartAreaInteractive/ChartAreaInteractive.js +12 -4
- package/dist/esm/index.js +1 -0
- package/dist/esm/mini-app/MiniAppRoot.js +9 -5
- package/dist/esm/mini-app/miniAppThemeConfig.js +40 -0
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.d.ts +6 -1
- package/dist/esm/types/src/docs/contexts/theme-context.d.ts +1 -0
- package/dist/esm/types/src/mini-app/MiniAppRoot.d.ts +4 -1
- package/dist/esm/types/src/mini-app/index.d.ts +4 -2
- package/dist/esm/types/src/mini-app/miniAppThemeConfig.d.ts +3 -0
- package/docs/workspace-mini-apps.md +3 -1
- package/package.json +1 -1
- package/src/components/ui/Chart/Chart.styl +7 -4
- package/src/components/ui/Chart/components/BaseChartWrapper.tsx +156 -193
- package/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.ts +90 -40
- package/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.tsx +15 -3
- package/src/docs/contexts/theme-context.tsx +9 -1
- package/src/docs/pages/ChartAreaInteractivePage.tsx +27 -1
- package/src/docs/pages/MiniAppRootPage.tsx +6 -1
- package/src/mini-app/MiniAppRoot.tsx +19 -1
- package/src/mini-app/index.ts +4 -8
- package/src/mini-app/miniAppThemeConfig.ts +45 -0
|
@@ -67,22 +67,99 @@ const timeRangeToMonths = {
|
|
|
67
67
|
|
|
68
68
|
export type TimeRange = keyof typeof timeRangeToMonths;
|
|
69
69
|
|
|
70
|
+
function isPlottableNumber(value: unknown): value is number {
|
|
71
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Any row the chart can draw a number for (excludes date-only or empty rows) */
|
|
75
|
+
function hasPlottableChartSeriesValue(item: ChartDataPoint): boolean {
|
|
76
|
+
for (const [key, v] of Object.entries(item)) {
|
|
77
|
+
if (key === 'date') continue;
|
|
78
|
+
if (isPlottableNumber(v)) return true;
|
|
79
|
+
if (Array.isArray(v) && v.some(x => isPlottableNumber(x))) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Row counts toward the "end" of the window when anchoring the time range to a
|
|
88
|
+
* selected forecast (shared historical + that analysis line / quantiles).
|
|
89
|
+
*/
|
|
90
|
+
function rowContributesToAnchoredTimeRange(
|
|
91
|
+
item: ChartDataPoint,
|
|
92
|
+
analysisId: number,
|
|
93
|
+
): boolean {
|
|
94
|
+
if (isPlottableNumber(item.historical)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
const forecastKey = `forecast_${analysisId}`;
|
|
98
|
+
if (isPlottableNumber(item[forecastKey])) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
for (const key of Object.keys(item)) {
|
|
102
|
+
if (key.startsWith('q') && key.endsWith(`_${analysisId}`)) {
|
|
103
|
+
if (isPlottableNumber(item[key])) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function computeLatestPlottableDate(
|
|
112
|
+
data: ChartDataPoint[],
|
|
113
|
+
options?: { endDateAnchorAnalysisId?: number | null },
|
|
114
|
+
): Date | null {
|
|
115
|
+
const anchorId = options?.endDateAnchorAnalysisId;
|
|
116
|
+
|
|
117
|
+
const pick = (item: ChartDataPoint, useAnchor: boolean): Date | null => {
|
|
118
|
+
if (!item.date) return null;
|
|
119
|
+
if (useAnchor && anchorId != null) {
|
|
120
|
+
if (!rowContributesToAnchoredTimeRange(item, anchorId)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
} else if (!hasPlottableChartSeriesValue(item)) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
return new Date(item.date);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
let latest: Date | null = null;
|
|
130
|
+
for (const item of data) {
|
|
131
|
+
const d = pick(item, true);
|
|
132
|
+
if (d && (!latest || d > latest)) {
|
|
133
|
+
latest = d;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (latest == null && anchorId != null) {
|
|
138
|
+
for (const item of data) {
|
|
139
|
+
const d = pick(item, false);
|
|
140
|
+
if (d && (!latest || d > latest)) {
|
|
141
|
+
latest = d;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return latest;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type FilterDataForTimeRangeOptions = {
|
|
150
|
+
/** When set (e.g. selected forecast on Forecast tab), the window ends at the
|
|
151
|
+
* latest point that has shared historical or that analysis — not at another run. */
|
|
152
|
+
endDateAnchorAnalysisId?: number | null;
|
|
153
|
+
};
|
|
154
|
+
|
|
70
155
|
export const filterDataForTimeRange = (
|
|
71
156
|
data: ChartDataPoint[],
|
|
72
157
|
currentTimeRange: TimeRange,
|
|
73
|
-
|
|
158
|
+
options?: FilterDataForTimeRangeOptions,
|
|
74
159
|
) => {
|
|
75
160
|
if (currentTimeRange === 'All') return data;
|
|
76
161
|
|
|
77
|
-
|
|
78
|
-
const latestDate = data.reduce(
|
|
79
|
-
(latest, item) => {
|
|
80
|
-
if (!item.date) return latest;
|
|
81
|
-
const itemDate = new Date(item.date);
|
|
82
|
-
return !latest || itemDate > latest ? itemDate : latest;
|
|
83
|
-
},
|
|
84
|
-
null as Date | null,
|
|
85
|
-
);
|
|
162
|
+
const latestDate = computeLatestPlottableDate(data, options);
|
|
86
163
|
|
|
87
164
|
// Pre-compute start date based on latest date in data
|
|
88
165
|
let startDate: Date | null = null;
|
|
@@ -93,41 +170,14 @@ export const filterDataForTimeRange = (
|
|
|
93
170
|
startDate.setMonth(startDate.getMonth() - monthsToSubtract);
|
|
94
171
|
}
|
|
95
172
|
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
const hasManyAnalyses = availableAnalyses.length > 10;
|
|
99
|
-
const hasAnalyses = availableAnalyses.length > 0;
|
|
100
|
-
const forecastKeysSet = hasManyAnalyses
|
|
101
|
-
? new Set(availableAnalyses.map(id => `${forecastKeyPrefix}${id}`))
|
|
102
|
-
: null;
|
|
103
|
-
|
|
173
|
+
// Slice by date for every row. Rows with forecast_* keys must not bypass the
|
|
174
|
+
// window (e.g. spaghetti plots), or the X range stays stuck at full history.
|
|
104
175
|
const filteredData = data.filter(item => {
|
|
105
|
-
if (
|
|
106
|
-
// Optimize forecast data check for many analyses
|
|
107
|
-
let hasForecastData = false;
|
|
108
|
-
if (hasManyAnalyses && forecastKeysSet) {
|
|
109
|
-
// Check if any forecast key exists in the item
|
|
110
|
-
hasForecastData = Object.keys(item).some(key =>
|
|
111
|
-
forecastKeysSet.has(key),
|
|
112
|
-
);
|
|
113
|
-
} else {
|
|
114
|
-
// Original approach for small number of analyses
|
|
115
|
-
hasForecastData = availableAnalyses.some(
|
|
116
|
-
analysisId => item[`forecast_${analysisId}`] !== undefined,
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (hasForecastData) {
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// For historical data, apply time range filtering
|
|
176
|
+
if (!item.date) return false;
|
|
126
177
|
if (startDate) {
|
|
127
178
|
const date = new Date(item.date);
|
|
128
179
|
return date >= startDate;
|
|
129
180
|
}
|
|
130
|
-
|
|
131
181
|
return true;
|
|
132
182
|
});
|
|
133
183
|
return filteredData;
|
|
@@ -11,6 +11,7 @@ import { TimeRangeControls } from '#uilib/components/ui/TimeRangeControls/TimeRa
|
|
|
11
11
|
import { ensureChartForecastBridge } from '#uilib/utils/chartConnectionPoint';
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
+
filterDataForTimeRange,
|
|
14
15
|
longDateFormatter,
|
|
15
16
|
shortDateFormatter,
|
|
16
17
|
} from './ChartAreaInteractive.helpers';
|
|
@@ -94,14 +95,25 @@ export function ChartAreaInteractive({
|
|
|
94
95
|
}
|
|
95
96
|
}, [selectedAnalysisId, ensureAnalysisSeriesVisible]);
|
|
96
97
|
|
|
98
|
+
const timeFilteredChartData = useMemo(() => {
|
|
99
|
+
const raw = selectedAnalysisId ?? selectedForecast?.id ?? null;
|
|
100
|
+
const anchorId =
|
|
101
|
+
raw == null ? null : typeof raw === 'number' ? raw : Number(raw);
|
|
102
|
+
const opts =
|
|
103
|
+
anchorId != null && Number.isFinite(anchorId)
|
|
104
|
+
? { endDateAnchorAnalysisId: anchorId }
|
|
105
|
+
: undefined;
|
|
106
|
+
return filterDataForTimeRange(chartData, timeRange, opts);
|
|
107
|
+
}, [chartData, timeRange, selectedAnalysisId, selectedForecast?.id]);
|
|
108
|
+
|
|
97
109
|
const bridgedChartData = useMemo(
|
|
98
110
|
() =>
|
|
99
111
|
disableForecastHistoricalBridge
|
|
100
|
-
?
|
|
101
|
-
: ensureChartForecastBridge(
|
|
112
|
+
? timeFilteredChartData
|
|
113
|
+
: ensureChartForecastBridge(timeFilteredChartData, {
|
|
102
114
|
forecastSeriesIds: forecastData?.map(f => f.id),
|
|
103
115
|
}),
|
|
104
|
-
[
|
|
116
|
+
[timeFilteredChartData, disableForecastHistoricalBridge, forecastData],
|
|
105
117
|
);
|
|
106
118
|
|
|
107
119
|
// Extract quantileBands from restProps
|
|
@@ -8,9 +8,11 @@ export type ThemeMode = 'light' | 'dark';
|
|
|
8
8
|
|
|
9
9
|
const ThemeContext = createContext<{
|
|
10
10
|
theme: ThemeMode;
|
|
11
|
+
isDarkMode: boolean;
|
|
11
12
|
setTheme: (theme: ThemeMode) => void;
|
|
12
13
|
}>({
|
|
13
14
|
theme: 'light',
|
|
15
|
+
isDarkMode: false,
|
|
14
16
|
setTheme: () => {},
|
|
15
17
|
});
|
|
16
18
|
|
|
@@ -37,7 +39,13 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
|
37
39
|
}, [theme]);
|
|
38
40
|
|
|
39
41
|
return (
|
|
40
|
-
<ThemeContext.Provider
|
|
42
|
+
<ThemeContext.Provider
|
|
43
|
+
value={{
|
|
44
|
+
theme,
|
|
45
|
+
isDarkMode: theme === 'dark',
|
|
46
|
+
setTheme,
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
41
49
|
<ThemeRoot config={currThemeConfig} />
|
|
42
50
|
{children}
|
|
43
51
|
</ThemeContext.Provider>
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
import { ForecastItemData } from '#uilib/components/ui/ChartAreaInteractive/ChartLines';
|
|
10
10
|
import { PageContentSection } from '#uilib/components/ui/Page';
|
|
11
11
|
import { Tabs, TabsList, TabsTrigger } from '#uilib/components/ui/Tabs';
|
|
12
|
+
import { useTheme } from '#uilib/docs/contexts/theme-context';
|
|
12
13
|
import type { ForecastData } from '#uilib/types/forecast-data';
|
|
13
14
|
|
|
14
15
|
import { AppPageHeader } from '../components/AppPageHeader/AppPageHeader';
|
|
@@ -48,6 +49,30 @@ const DEMO_DISCRETE_THRESHOLDS = (() => {
|
|
|
48
49
|
})();
|
|
49
50
|
|
|
50
51
|
const INITIAL_CHART: ChartDataPoint[] = [
|
|
52
|
+
{ date: '2021-01-01', historical: 6 },
|
|
53
|
+
{ date: '2021-02-01', historical: 8 },
|
|
54
|
+
{ date: '2021-03-01', historical: 7 },
|
|
55
|
+
{ date: '2021-04-01', historical: 10 },
|
|
56
|
+
{ date: '2021-05-01', historical: 9 },
|
|
57
|
+
{ date: '2021-06-01', historical: 10 },
|
|
58
|
+
{ date: '2021-07-01', historical: 11 },
|
|
59
|
+
{ date: '2021-08-01', historical: 10 },
|
|
60
|
+
{ date: '2021-09-01', historical: 12 },
|
|
61
|
+
{ date: '2021-10-01', historical: 11 },
|
|
62
|
+
{ date: '2021-11-01', historical: 13 },
|
|
63
|
+
{ date: '2021-12-01', historical: 12 },
|
|
64
|
+
{ date: '2022-01-01', historical: 8 },
|
|
65
|
+
{ date: '2022-02-01', historical: 10 },
|
|
66
|
+
{ date: '2022-03-01', historical: 9 },
|
|
67
|
+
{ date: '2022-04-01', historical: 12 },
|
|
68
|
+
{ date: '2022-05-01', historical: 11 },
|
|
69
|
+
{ date: '2022-06-01', historical: 12 },
|
|
70
|
+
{ date: '2022-07-01', historical: 13 },
|
|
71
|
+
{ date: '2022-08-01', historical: 12 },
|
|
72
|
+
{ date: '2022-09-01', historical: 14 },
|
|
73
|
+
{ date: '2022-10-01', historical: 13 },
|
|
74
|
+
{ date: '2022-11-01', historical: 15 },
|
|
75
|
+
{ date: '2022-12-01', historical: 14 },
|
|
51
76
|
{ date: '2023-01-01', historical: 10 },
|
|
52
77
|
{ date: '2023-02-01', historical: 12 },
|
|
53
78
|
{ date: '2023-03-01', historical: 11 },
|
|
@@ -65,6 +90,7 @@ const DEMO_FORECAST_ITEMS: ForecastItemData[] = [
|
|
|
65
90
|
type DemoMode = 'none' | OverlayMode;
|
|
66
91
|
|
|
67
92
|
export default function ChartAreaInteractivePage() {
|
|
93
|
+
const { isDarkMode } = useTheme();
|
|
68
94
|
const [timeRange, setTimeRange] = useState<TimeRange>('1y');
|
|
69
95
|
const [pinMonth, setPinMonth] = useState<string | undefined>(undefined);
|
|
70
96
|
const [demoMode, setDemoMode] = useState<DemoMode>('none');
|
|
@@ -139,7 +165,7 @@ export default function ChartAreaInteractivePage() {
|
|
|
139
165
|
chartData={chartData}
|
|
140
166
|
forecastData={DEMO_FORECAST_ITEMS}
|
|
141
167
|
loading={false}
|
|
142
|
-
isDarkTheme={
|
|
168
|
+
isDarkTheme={isDarkMode}
|
|
143
169
|
toggleLegendSeries={toggleLegendSeries}
|
|
144
170
|
ensureAnalysisSeriesVisible={ensureAnalysisSeriesVisible}
|
|
145
171
|
hiddenSeries={hidden}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PageContentSection } from '#uilib/components/ui/Page';
|
|
2
|
+
import { getThemeConfig } from '#uilib/docs/lib/theme';
|
|
2
3
|
import { MiniAppRoot, useMiniAppShellTheme } from '#uilib/mini-app';
|
|
3
4
|
|
|
4
5
|
import { AppPageHeader } from '../components/AppPageHeader/AppPageHeader';
|
|
@@ -44,7 +45,11 @@ export default function MiniAppRootPage() {
|
|
|
44
45
|
}
|
|
45
46
|
`}</style>
|
|
46
47
|
<PageContentSection style={{ maxHeight: '500px' }}>
|
|
47
|
-
<MiniAppRoot
|
|
48
|
+
<MiniAppRoot
|
|
49
|
+
appId="uilib-docs"
|
|
50
|
+
className="mini-app-root-page"
|
|
51
|
+
getThemeConfig={isDarkMode => getThemeConfig(isDarkMode)}
|
|
52
|
+
>
|
|
48
53
|
<MiniAppThemeDemo />
|
|
49
54
|
</MiniAppRoot>
|
|
50
55
|
</PageContentSection>
|
|
@@ -10,7 +10,7 @@ import React, {
|
|
|
10
10
|
useState,
|
|
11
11
|
} from 'react';
|
|
12
12
|
|
|
13
|
-
import { Scroll } from '@homecode/ui';
|
|
13
|
+
import { Scroll, Theme } from '@homecode/ui';
|
|
14
14
|
|
|
15
15
|
import S from './MiniAppRoot.styl';
|
|
16
16
|
import {
|
|
@@ -20,6 +20,10 @@ import {
|
|
|
20
20
|
parseThemeSyncMessage,
|
|
21
21
|
resolveParentOriginFromReferrer,
|
|
22
22
|
} from './miniAppProtocol';
|
|
23
|
+
import {
|
|
24
|
+
type MiniAppThemeConfig,
|
|
25
|
+
getDefaultMiniAppThemeConfig,
|
|
26
|
+
} from './miniAppThemeConfig';
|
|
23
27
|
|
|
24
28
|
const defaultTheme: ThemeSyncPayload = {
|
|
25
29
|
mode: 'light',
|
|
@@ -76,6 +80,8 @@ export type MiniAppRootProps = {
|
|
|
76
80
|
/** Included in READY payload when set. */
|
|
77
81
|
appId?: string;
|
|
78
82
|
onThemeChange?: (theme: ThemeSyncPayload) => void;
|
|
83
|
+
/** Overrides `@homecode/ui` `<Theme config>` builder (defaults to generic mini-app palette). */
|
|
84
|
+
getThemeConfig?: (isDarkMode: boolean) => MiniAppThemeConfig;
|
|
79
85
|
};
|
|
80
86
|
|
|
81
87
|
export function MiniAppRoot({
|
|
@@ -83,6 +89,7 @@ export function MiniAppRoot({
|
|
|
83
89
|
className,
|
|
84
90
|
appId,
|
|
85
91
|
onThemeChange,
|
|
92
|
+
getThemeConfig,
|
|
86
93
|
}: MiniAppRootProps): React.ReactElement {
|
|
87
94
|
const [theme, setTheme] = useState<ThemeSyncPayload>(() =>
|
|
88
95
|
isEmbeddedMiniApp() ? defaultTheme : themeFromDocument(),
|
|
@@ -90,6 +97,16 @@ export function MiniAppRoot({
|
|
|
90
97
|
const onThemeChangeRef = useRef(onThemeChange);
|
|
91
98
|
onThemeChangeRef.current = onThemeChange;
|
|
92
99
|
|
|
100
|
+
const getThemeConfigRef = useRef(
|
|
101
|
+
getThemeConfig ?? getDefaultMiniAppThemeConfig,
|
|
102
|
+
);
|
|
103
|
+
getThemeConfigRef.current = getThemeConfig ?? getDefaultMiniAppThemeConfig;
|
|
104
|
+
|
|
105
|
+
const currThemeConfig = useMemo(
|
|
106
|
+
() => getThemeConfigRef.current(theme.isDarkMode),
|
|
107
|
+
[theme.isDarkMode],
|
|
108
|
+
);
|
|
109
|
+
|
|
93
110
|
const sendReady = useCallback(() => {
|
|
94
111
|
if (!window.parent || window.parent === window) return;
|
|
95
112
|
const payload = appId ? { appId } : {};
|
|
@@ -131,6 +148,7 @@ export function MiniAppRoot({
|
|
|
131
148
|
|
|
132
149
|
return (
|
|
133
150
|
<MiniAppShellContext.Provider value={ctx}>
|
|
151
|
+
<Theme config={currThemeConfig} />
|
|
134
152
|
<Scroll
|
|
135
153
|
y
|
|
136
154
|
fadeSize="l"
|
package/src/mini-app/index.ts
CHANGED
|
@@ -11,11 +11,7 @@ export type {
|
|
|
11
11
|
MiniAppMessageThemeSync,
|
|
12
12
|
ThemeSyncPayload,
|
|
13
13
|
} from './miniAppProtocol';
|
|
14
|
-
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from './MiniAppRoot';
|
|
18
|
-
export type {
|
|
19
|
-
MiniAppRootProps,
|
|
20
|
-
MiniAppShellContextValue,
|
|
21
|
-
} from './MiniAppRoot';
|
|
14
|
+
export { getDefaultMiniAppThemeConfig } from './miniAppThemeConfig';
|
|
15
|
+
export type { MiniAppThemeConfig } from './miniAppThemeConfig';
|
|
16
|
+
export { MiniAppRoot, useMiniAppShellTheme } from './MiniAppRoot';
|
|
17
|
+
export type { MiniAppRootProps, MiniAppShellContextValue } from './MiniAppRoot';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ThemeDefaults, ThemeHelpers } from '@homecode/ui';
|
|
2
|
+
|
|
3
|
+
const { colors, getColors, getConfig } = ThemeDefaults;
|
|
4
|
+
|
|
5
|
+
const defaultPalette = getColors();
|
|
6
|
+
|
|
7
|
+
const colorsConfig = {
|
|
8
|
+
light: {
|
|
9
|
+
...ThemeHelpers.colorsConfigToVars({
|
|
10
|
+
...getColors({
|
|
11
|
+
accent: colors.dark,
|
|
12
|
+
decent: colors.light,
|
|
13
|
+
}),
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
dark: {
|
|
17
|
+
...ThemeHelpers.colorsConfigToVars({
|
|
18
|
+
...getColors({
|
|
19
|
+
accent: colors.light,
|
|
20
|
+
decent: colors.dark,
|
|
21
|
+
}),
|
|
22
|
+
}),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Homecode `<Theme config={...}>` shape for workspace mini-apps (generic palette). */
|
|
27
|
+
export function getDefaultMiniAppThemeConfig(isDarkMode: boolean) {
|
|
28
|
+
return {
|
|
29
|
+
...getConfig(),
|
|
30
|
+
...colorsConfig[isDarkMode ? 'dark' : 'light'],
|
|
31
|
+
...ThemeHelpers.colorsConfigToVars({
|
|
32
|
+
active: {
|
|
33
|
+
color: '#00a9c7',
|
|
34
|
+
mods: {
|
|
35
|
+
// @ts-ignore — extend defaults so --active-color-alpha-* variants match Homecode
|
|
36
|
+
alpha: [0, 50, 100, 200, ...defaultPalette.active.mods.alpha],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type MiniAppThemeConfig = ReturnType<
|
|
44
|
+
typeof getDefaultMiniAppThemeConfig
|
|
45
|
+
>;
|