mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-04 12:15:02 +03:00
89e200ead4
Zod 4: use the `error` param instead of the deprecated `message`. lint:deprecated missed these because tsgolint's no-deprecated does not resolve object-literal properties on a `string | Params` union. Geodata: key geo entry rows by page position. antd deprecates rowKey's index argument, and kind:value repeats within a page because the reader drops domain attributes (22 pairs in geosite_IR.dat, 108 in geosite_RU). Nord/PIA: the "All cities/regions" option used a null value, which antd warns on. Map it through a sentinel at the Select boundary so form state stays null, with tests that fail when the sentinel is not mapped back. Tests: - Run the oxlint guard through node; .bin/oxlint is a sh shim Windows cannot spawn, and the swallowed error left both guard cases vacuous. - Start unit workers with --no-experimental-webstorage; msw's localStorage probe made Node 25+ warn once per forked worker. - Set IS_REACT_ACT_ENVIRONMENT, which RTL never sets with globals: false, and settle the async updates it exposed inside act(). The row-cells memo test now fails when memo is removed. - Disable antd's click wave in Storybook; it re-rendered inside the next story's act() and tripped "not configured to support act". - Assert InboundFormModal's validation log instead of leaking it, and give the rule-form test a well-formed clients/list response.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import { useLayoutEffect } from 'react';
|
|
import type { Decorator, Preview } from '@storybook/react-vite';
|
|
import { ConfigProvider } from 'antd';
|
|
import i18next from 'i18next';
|
|
import { initReactI18next } from 'react-i18next';
|
|
|
|
import { buildAntdThemeConfig } from '@/hooks/useTheme';
|
|
import enUS from '../../internal/web/translation/en-US.json';
|
|
|
|
if (!i18next.isInitialized) {
|
|
void i18next.use(initReactI18next).init({
|
|
lng: 'en-US',
|
|
fallbackLng: 'en-US',
|
|
resources: { 'en-US': { translation: enUS } },
|
|
interpolation: { escapeValue: false, prefix: '{', suffix: '}' },
|
|
returnNull: false,
|
|
});
|
|
}
|
|
|
|
export const withTheme: Decorator = (Story, context) => {
|
|
const dark = context.globals.theme === 'dark';
|
|
useLayoutEffect(() => {
|
|
document.body.classList.remove('dark', 'light');
|
|
document.body.classList.add(dark ? 'dark' : 'light');
|
|
document.documentElement.style.colorScheme = dark ? 'dark' : 'light';
|
|
document.documentElement.removeAttribute('data-theme');
|
|
}, [dark]);
|
|
return (
|
|
// The click wave outlives its story and re-renders from a ResizeObserver
|
|
// inside the next story's act(), tripping React's act-environment warning.
|
|
<ConfigProvider theme={buildAntdThemeConfig(dark, false)} wave={{ disabled: true }}>
|
|
<div style={{ padding: 24, minWidth: 320 }}>
|
|
<Story />
|
|
</div>
|
|
</ConfigProvider>
|
|
);
|
|
};
|
|
|
|
const preview: Preview = {
|
|
decorators: [withTheme],
|
|
globalTypes: {
|
|
theme: {
|
|
description: 'Ant Design theme',
|
|
defaultValue: 'light',
|
|
toolbar: {
|
|
title: 'Theme',
|
|
icon: 'circlehollow',
|
|
items: [
|
|
{ value: 'light', title: 'Light' },
|
|
{ value: 'dark', title: 'Dark' },
|
|
],
|
|
dynamicTitle: true,
|
|
},
|
|
},
|
|
},
|
|
parameters: {
|
|
controls: {
|
|
expanded: true,
|
|
sort: 'requiredFirst',
|
|
matchers: {
|
|
color: /(background|color)$/i,
|
|
date: /Date$/i,
|
|
},
|
|
},
|
|
a11y: {
|
|
test: 'error',
|
|
},
|
|
},
|
|
};
|
|
|
|
export default preview;
|