@scm-manager/ui-core 4.0.0-REACT18-20250701-125025 → 4.0.0-REACT19

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.
Files changed (56) hide show
  1. package/{src/base/buttons/a11y.test.ts → .storybook/i18n.ts} +27 -9
  2. package/.storybook/main.ts +54 -0
  3. package/.storybook/preview-head.html +6 -1
  4. package/.storybook/preview.tsx +125 -0
  5. package/.turbo/turbo-test.log +164 -0
  6. package/.turbo/turbo-typecheck.log +3 -2
  7. package/package.json +37 -42
  8. package/src/base/buttons/Button.stories.tsx +179 -70
  9. package/src/base/buttons/Button.tsx +9 -9
  10. package/src/base/forms/AddListEntryForm.tsx +8 -8
  11. package/src/base/forms/ConfigurationForm.tsx +14 -5
  12. package/src/base/forms/Form.stories.tsx +599 -289
  13. package/src/base/forms/Form.tsx +8 -8
  14. package/src/base/forms/FormPathContext.tsx +3 -3
  15. package/src/base/forms/ScmFormContext.tsx +7 -4
  16. package/src/base/forms/ScmFormListContext.tsx +2 -1
  17. package/src/base/forms/base/Field.tsx +1 -1
  18. package/src/base/forms/base/label/Label.tsx +1 -1
  19. package/src/base/forms/chip-input/ChipInputField.stories.tsx +109 -28
  20. package/src/base/forms/chip-input/ChipInputField.tsx +20 -8
  21. package/src/base/forms/chip-input/ControlledChipInputField.tsx +3 -1
  22. package/src/base/forms/combobox/Combobox.stories.tsx +216 -89
  23. package/src/base/forms/combobox/Combobox.tsx +4 -2
  24. package/src/base/forms/combobox/ComboboxField.tsx +2 -1
  25. package/src/base/forms/headless-chip-input/ChipInput.tsx +9 -9
  26. package/src/base/forms/helpers.ts +12 -9
  27. package/src/base/forms/input/ControlledSecretConfirmationField.tsx +4 -2
  28. package/src/base/forms/radio-button/RadioButton.stories.tsx +317 -124
  29. package/src/base/forms/radio-button/RadioButton.tsx +8 -4
  30. package/src/base/forms/radio-button/RadioButtonContext.tsx +2 -1
  31. package/src/base/forms/table/ControlledColumn.tsx +1 -1
  32. package/src/base/forms/table/ControlledTable.tsx +12 -4
  33. package/src/base/helpers/useDocumentTitle.test.ts +15 -7
  34. package/src/base/layout/card/Card.stories.tsx +171 -72
  35. package/src/base/layout/card/Card.tsx +4 -4
  36. package/src/base/layout/card/CardDetail.tsx +2 -3
  37. package/src/base/layout/card-list/CardList.stories.tsx +283 -169
  38. package/src/base/layout/collapsible/Collapsible.stories.tsx +54 -16
  39. package/src/base/layout/index.ts +2 -5
  40. package/src/base/layout/tabs/Tabs.stories.tsx +58 -16
  41. package/src/base/layout/templates/data-page/DataPage.stories.tsx +289 -156
  42. package/src/base/layout/templates/data-page/DataPageHeader.tsx +1 -1
  43. package/src/base/overlays/dialog/Dialog.stories.tsx +94 -34
  44. package/src/base/overlays/menu/Menu.stories.tsx +116 -48
  45. package/src/base/overlays/menu/Menu.tsx +1 -0
  46. package/src/base/overlays/popover/Popover.stories.tsx +50 -37
  47. package/src/base/shortcuts/iterator/keyboardIterator.test.tsx +16 -7
  48. package/src/base/shortcuts/iterator/keyboardIterator.tsx +13 -5
  49. package/src/base/status/StatusIcon.stories.tsx +76 -27
  50. package/src/base/status/index.ts +1 -1
  51. package/src/base/text/SplitAndReplace.stories.tsx +128 -50
  52. package/src/base/text/index.ts +1 -1
  53. package/.storybook/RemoveThemesPlugin.js +0 -49
  54. package/.storybook/main.js +0 -86
  55. package/.storybook/preview.js +0 -87
  56. package/src/base/buttons/image-snapshot.test.ts +0 -26
@@ -14,62 +14,140 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ // import React from "react";
18
+ // import { ComponentMeta, ComponentStory } from "@storybook/react";
19
+ // import SplitAndReplace from "./SplitAndReplace";
20
+ //
21
+ // export default {
22
+ // title: "SplitAndReplace",
23
+ // component: SplitAndReplace,
24
+ // } as ComponentMeta<typeof SplitAndReplace>;
25
+ //
26
+ // const textOne = "'So this is it,` said Arthur, 'We are going to die.`";
27
+ // const textTwo = "'Yes,` said Ford, 'except... no! Wait a minute!`";
28
+ //
29
+ // export const ReplaceOnce: ComponentStory<typeof SplitAndReplace> = () => {
30
+ // const replacements = [
31
+ // {
32
+ // textToReplace: "'",
33
+ // replacement: <span>!</span>,
34
+ // replaceAll: false,
35
+ // },
36
+ // ];
37
+ // return (
38
+ // <div>
39
+ // <h3>Replace ' with ! once</h3>
40
+ // <label>Original text:</label>
41
+ // <p>{textOne}</p>
42
+ // <label>Text with replacements:</label>
43
+ // <p>
44
+ // <SplitAndReplace text={textOne} replacements={replacements} />
45
+ // </p>
46
+ // </div>
47
+ // );
48
+ // };
49
+ //
50
+ // export const ReplaceAll: ComponentStory<typeof SplitAndReplace> = () => {
51
+ // const replacements = [
52
+ // {
53
+ // textToReplace: "'",
54
+ // replacement: <span>!</span>,
55
+ // replaceAll: true,
56
+ // },
57
+ // {
58
+ // textToReplace: "`",
59
+ // replacement: <span>?</span>,
60
+ // replaceAll: true,
61
+ // },
62
+ // ];
63
+ // return (
64
+ // <div>
65
+ // <h3>Replace all ` with ? and ' with !</h3>
66
+ // <label>Original text:</label>
67
+ // <p>{textTwo}</p>
68
+ //
69
+ // <label> Text with replacements: </label>
70
+ // <p>
71
+ // <SplitAndReplace text={textTwo} replacements={replacements} />
72
+ // </p>
73
+ // </div>
74
+ // );
75
+ // };
76
+
17
77
  import React from "react";
18
- import { ComponentMeta, ComponentStory } from "@storybook/react";
78
+ import type { Meta, StoryObj } from "@storybook/react";
79
+
19
80
  import SplitAndReplace from "./SplitAndReplace";
20
81
 
21
- export default {
22
- title: "SplitAndReplace",
82
+ const textOne = "'So this is it,' said Arthur, 'We are going to die.'";
83
+ const textTwo = "'Yes,' said Ford, 'except... no! Wait a minute!'";
84
+
85
+ const meta: Meta<typeof SplitAndReplace> = {
86
+ title: "Utilities/SplitAndReplace",
23
87
  component: SplitAndReplace,
24
- } as ComponentMeta<typeof SplitAndReplace>;
88
+ decorators: [
89
+ (Story) => (
90
+ <div style={{ margin: "2rem" }}>
91
+ <Story />
92
+ </div>
93
+ ),
94
+ ],
95
+ tags: ["autodocs"],
96
+ };
25
97
 
26
- const textOne = "'So this is it,` said Arthur, 'We are going to die.`";
27
- const textTwo = "'Yes,` said Ford, 'except... no! Wait a minute!`";
98
+ export default meta;
28
99
 
29
- export const ReplaceOnce: ComponentStory<typeof SplitAndReplace> = () => {
30
- const replacements = [
31
- {
32
- textToReplace: "'",
33
- replacement: <span>!</span>,
34
- replaceAll: false,
35
- },
36
- ];
37
- return (
38
- <div>
39
- <h3>Replace ' with ! once</h3>
40
- <label>Original text:</label>
41
- <p>{textOne}</p>
42
- <label>Text with replacements:</label>
43
- <p>
44
- <SplitAndReplace text={textOne} replacements={replacements} />
45
- </p>
46
- </div>
47
- );
48
- };
100
+ type Story = StoryObj<typeof meta>;
49
101
 
50
- export const ReplaceAll: ComponentStory<typeof SplitAndReplace> = () => {
51
- const replacements = [
52
- {
53
- textToReplace: "'",
54
- replacement: <span>!</span>,
55
- replaceAll: true,
56
- },
57
- {
58
- textToReplace: "`",
59
- replacement: <span>?</span>,
60
- replaceAll: true,
61
- },
62
- ];
63
- return (
64
- <div>
65
- <h3>Replace all ` with ? and ' with !</h3>
66
- <label>Original text:</label>
67
- <p>{textTwo}</p>
102
+ export const ReplaceOnce: Story = {
103
+ name: "Replace Once",
104
+ render: () => {
105
+ const replacements = [
106
+ {
107
+ textToReplace: "'",
108
+ replacement: <span style={{ color: "red", fontWeight: "bold" }}>!</span>,
109
+ replaceAll: false,
110
+ },
111
+ ];
112
+ return (
113
+ <div>
114
+ <h3>Replace first instance of ' with !</h3>
115
+ <label>Original text:</label>
116
+ <p>{textOne}</p>
117
+ <label>Text with replacement:</label>
118
+ <p>
119
+ <SplitAndReplace text={textOne} replacements={replacements} />
120
+ </p>
121
+ </div>
122
+ );
123
+ },
124
+ };
68
125
 
69
- <label> Text with replacements: </label>
70
- <p>
71
- <SplitAndReplace text={textTwo} replacements={replacements} />
72
- </p>
73
- </div>
74
- );
126
+ export const ReplaceAll: Story = {
127
+ name: "Replace All",
128
+ render: () => {
129
+ const replacements = [
130
+ {
131
+ textToReplace: "'",
132
+ replacement: <span style={{ color: "red", fontWeight: "bold" }}>!</span>,
133
+ replaceAll: true,
134
+ },
135
+ {
136
+ textToReplace: "`",
137
+ replacement: <span style={{ color: "blue", fontWeight: "bold" }}>?</span>,
138
+ replaceAll: true,
139
+ },
140
+ ];
141
+ return (
142
+ <div>
143
+ <h3>Replace all ` with ? and ' with !</h3>
144
+ <label>Original text:</label>
145
+ <p>{textTwo}</p>
146
+ <label>Text with replacements:</label>
147
+ <p>
148
+ <SplitAndReplace text={textTwo} replacements={replacements} />
149
+ </p>
150
+ </div>
151
+ );
152
+ },
75
153
  };
@@ -14,4 +14,4 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
- export { default as SplitAndReplace, Replacement } from "./SplitAndReplace";
17
+ export { default as SplitAndReplace, type Replacement } from "./SplitAndReplace";
@@ -1,49 +0,0 @@
1
- /*
2
- * Copyright (c) 2020 - present Cloudogu GmbH
3
- *
4
- * This program is free software: you can redistribute it and/or modify it under
5
- * the terms of the GNU Affero General Public License as published by the Free
6
- * Software Foundation, version 3.
7
- *
8
- * This program is distributed in the hope that it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
- * details.
12
- *
13
- * You should have received a copy of the GNU Affero General Public License
14
- * along with this program. If not, see https://www.gnu.org/licenses/.
15
- */
16
-
17
- const HtmlWebpackPlugin = require('html-webpack-plugin');
18
-
19
- class RemoveThemesPlugin {
20
- apply (compiler) {
21
- compiler.hooks.compilation.tap('RemoveThemesPlugin', (compilation) => {
22
-
23
- HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(
24
- 'RemoveThemesPlugin',
25
- (data, cb) => {
26
-
27
- // remove generated style-loader bundles from the page
28
- // there should be a better way, which does not generate the bundles at all
29
- // but for now it works
30
- if (data.assets.js) {
31
- data.assets.js = data.assets.js.filter(bundle => !bundle.startsWith("ui-theme-"))
32
- .filter(bundle => !bundle.startsWith("runtime~ui-theme-"))
33
- }
34
-
35
- // remove css links to avoid conflicts with the themes
36
- // so we remove all and add our own via preview-head.html
37
- if (data.assets.css) {
38
- data.assets.css = data.assets.css.filter(css => !css.startsWith("ui-theme-"))
39
- }
40
-
41
- // Tell webpack to move on
42
- cb(null, data)
43
- }
44
- )
45
- })
46
- }
47
- }
48
-
49
- module.exports = RemoveThemesPlugin
@@ -1,86 +0,0 @@
1
- /*
2
- * Copyright (c) 2020 - present Cloudogu GmbH
3
- *
4
- * This program is free software: you can redistribute it and/or modify it under
5
- * the terms of the GNU Affero General Public License as published by the Free
6
- * Software Foundation, version 3.
7
- *
8
- * This program is distributed in the hope that it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
- * details.
12
- *
13
- * You should have received a copy of the GNU Affero General Public License
14
- * along with this program. If not, see https://www.gnu.org/licenses/.
15
- */
16
-
17
- const path = require("path");
18
- const fs = require("fs");
19
- const MiniCssExtractPlugin = require("mini-css-extract-plugin");
20
- const RemoveThemesPlugin = require("./RemoveThemesPlugin");
21
- const ReactDOM = require("react-dom");
22
-
23
- const root = path.resolve("..");
24
-
25
- const themedir = path.join(root, "ui-styles", "src");
26
-
27
- ReactDOM.createPortal = (node) => node;
28
-
29
- const themes = fs
30
- .readdirSync(themedir)
31
- .map((filename) => path.parse(filename))
32
- .filter((p) => p.ext === ".scss")
33
- .reduce((entries, current) => ({ ...entries, [`ui-theme-${current.name}`]: path.join(themedir, current.base) }), {});
34
-
35
- module.exports = {
36
- typescript: { reactDocgen: false },
37
- core: {
38
- builder: "webpack5",
39
- },
40
- stories: ["../docs/**/*.stories.mdx", "../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
41
- addons: [
42
- "storybook-addon-i18next",
43
- "storybook-addon-themes",
44
- "@storybook/addon-links",
45
- "@storybook/addon-essentials",
46
- "@storybook/addon-interactions",
47
- "@storybook/addon-a11y",
48
- "storybook-addon-pseudo-states",
49
- ],
50
- framework: "@storybook/react",
51
- webpackFinal: async (config) => {
52
- // add our themes to webpack entry points
53
- config.entry = {
54
- main: config.entry,
55
- ...themes,
56
- };
57
-
58
- // create separate css files for our themes
59
- config.plugins.push(
60
- new MiniCssExtractPlugin({
61
- filename: "[name].css",
62
- ignoreOrder: false,
63
- })
64
- );
65
-
66
- config.module.rules.push({
67
- test: /\.scss$/,
68
- use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
69
- });
70
-
71
- // the html-webpack-plugin adds the generated css and js files to the iframe,
72
- // which overrides our manually loaded css files.
73
- // So we use a custom plugin which uses a hook of html-webpack-plugin
74
- // to filter our themes from the output.
75
- config.plugins.push(new RemoveThemesPlugin());
76
-
77
- // force node version of "decode-named-character-reference" instead of browser version which does not work in web worker
78
- config.resolve.alias["decode-named-character-reference"] = require.resolve("decode-named-character-reference");
79
-
80
- // force cjs instead of esm
81
- // https://github.com/tannerlinsley/react-query/issues/3513
82
- config.resolve.alias["react-query/devtools"] = require.resolve("react-query/devtools");
83
-
84
- return config;
85
- },
86
- };
@@ -1,87 +0,0 @@
1
- /*
2
- * Copyright (c) 2020 - present Cloudogu GmbH
3
- *
4
- * This program is free software: you can redistribute it and/or modify it under
5
- * the terms of the GNU Affero General Public License as published by the Free
6
- * Software Foundation, version 3.
7
- *
8
- * This program is distributed in the hope that it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
- * details.
12
- *
13
- * You should have received a copy of the GNU Affero General Public License
14
- * along with this program. If not, see https://www.gnu.org/licenses/.
15
- */
16
-
17
- import i18next from "i18next";
18
- import { initReactI18next } from "react-i18next";
19
- import { withI18next } from "storybook-addon-i18next";
20
- import React, { useEffect } from "react";
21
- import withApiProvider from "./withApiProvider";
22
- import { withThemes } from "storybook-addon-themes/react";
23
-
24
- let i18n = i18next;
25
-
26
- // only use fetch backend for storybook
27
- // and not for storyshots
28
- if (!process.env.JEST_WORKER_ID) {
29
- const Backend = require("i18next-fetch-backend");
30
- i18n = i18n.use(Backend);
31
- }
32
-
33
- i18n.use(initReactI18next).init({
34
- whitelist: ["en", "de", "es"],
35
- lng: "en",
36
- fallbackLng: "en",
37
- interpolation: {
38
- escapeValue: false,
39
- },
40
- react: {
41
- useSuspense: false,
42
- },
43
- backend: {
44
- loadPath: "/locales/{{lng}}/{{ns}}.json",
45
- init: {
46
- credentials: "same-origin",
47
- },
48
- },
49
- });
50
-
51
- export const decorators = [
52
- withI18next({
53
- i18n,
54
- languages: {
55
- en: "English",
56
- de: "Deutsch",
57
- es: "Spanisch",
58
- },
59
- }),
60
- withApiProvider,
61
- withThemes,
62
- ];
63
-
64
- const Decorator = ({ children, themeName }) => {
65
- useEffect(() => {
66
- const link = document.querySelector("#ui-theme");
67
- if (link && link["data-theme"] !== themeName) {
68
- link.href = `/ui-theme-${themeName}.css`;
69
- link["data-theme"] = themeName;
70
- }
71
- }, [themeName]);
72
- return <>{children}</>;
73
- };
74
-
75
- export const parameters = {
76
- actions: { argTypesRegex: "^on[A-Z].*" },
77
- themes: {
78
- Decorator,
79
- clearable: false,
80
- default: "light",
81
- list: [
82
- { name: "light", color: "#fff" },
83
- { name: "highcontrast", color: "#050514" },
84
- { name: "dark", color: "#121212" },
85
- ],
86
- },
87
- };
@@ -1,26 +0,0 @@
1
- /*
2
- * Copyright (c) 2020 - present Cloudogu GmbH
3
- *
4
- * This program is free software: you can redistribute it and/or modify it under
5
- * the terms of the GNU Affero General Public License as published by the Free
6
- * Software Foundation, version 3.
7
- *
8
- * This program is distributed in the hope that it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
- * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
- * details.
12
- *
13
- * You should have received a copy of the GNU Affero General Public License
14
- * along with this program. If not, see https://www.gnu.org/licenses/.
15
- */
16
-
17
- import path from "path";
18
- import initStoryshots from "@storybook/addon-storyshots";
19
- import { imageSnapshot } from "@storybook/addon-storyshots-puppeteer";
20
-
21
- initStoryshots({
22
- suite: "Image snapshots",
23
- test: imageSnapshot({
24
- storybookUrl: `file://${path.resolve(__dirname, "../storybook-static")}`,
25
- })
26
- });