diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..07994fc7
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,23 @@
+version: 2
+updates:
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+ open-pull-requests-limit: 1 # set 0 to temporarily disable automatic update requests
+ pull-request-branch-name:
+ separator: "/"
+ assignees:
+ - "haschek"
+ # Maintain dependencies for npm
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+ versioning-strategy: increase
+ open-pull-requests-limit: 3 # set 0 to temporarily disable automatic update requests
+ pull-request-branch-name:
+ separator: "/"
+ assignees:
+ - "haschek"
diff --git a/.github/workflows/deployment-storybook.yml b/.github/workflows/deployment-storybook.yml
index 79875a9b..8006fa1d 100644
--- a/.github/workflows/deployment-storybook.yml
+++ b/.github/workflows/deployment-storybook.yml
@@ -19,19 +19,20 @@ on:
jobs:
chromatic-deployment:
runs-on: ubuntu-latest
+ if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
with:
fetch-depth: 0
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
- name: Install dependencies
run: yarn install
- name: Create jest results
run: yarn test:generate-output
- name: Publish to Chromatic
- uses: chromaui/action@v1
+ uses: chromaui/action@v11
with:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
diff --git a/.github/workflows/release-branch.yml b/.github/workflows/release-branch.yml
index 5b56d2a1..ae698b0c 100644
--- a/.github/workflows/release-branch.yml
+++ b/.github/workflows/release-branch.yml
@@ -4,7 +4,6 @@ on:
workflow_dispatch:
branches:
- "develop"
- - "feature/prepareReleaseForDM-CMEM-4151" # TODO: only for testing, remove it later
inputs:
releasetype:
description: "Type of release"
@@ -20,10 +19,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
+ - uses: actions/checkout@main
+ - uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
- name: Update package.json with new release candidate version
id: create-version
run: |
diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml
index 2683dd54..9ef9028a 100644
--- a/.github/workflows/release-candidate.yml
+++ b/.github/workflows/release-candidate.yml
@@ -30,15 +30,15 @@ jobs:
echo "You started it on '${{ steps.branch-name.outputs.current_branch }}'."
exit 1
fi
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
- name: Initialize mandatory git config
# @see https://github.community/t/how-do-i-get-gh-username-based-on-actions-events/17882
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
- name: Get version
id: package-version
run: echo "version=$(node -p -e "require('./package.json').version")" >> $GITHUB_OUTPUT
diff --git a/.github/workflows/release-final.yml b/.github/workflows/release-final.yml
index dd133eee..d9c775f4 100644
--- a/.github/workflows/release-final.yml
+++ b/.github/workflows/release-final.yml
@@ -13,15 +13,15 @@ jobs:
sha: ${{ steps.tag-revision.outputs.sha }}
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
- name: Initialize mandatory git config
# @see https://github.community/t/how-do-i-get-gh-username-based-on-actions-events/17882
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
- name: Get version
id: package-version
run: echo "version=$(node -p -e "require('./package.json').version.split('-').shift()")" >> $GITHUB_OUTPUT
@@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
needs: create-release-version
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
with:
ref: develop
- name: Initialize mandatory git config
diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml
index b3b09ec1..a282b1c5 100644
--- a/.github/workflows/release-publish.yml
+++ b/.github/workflows/release-publish.yml
@@ -26,13 +26,13 @@ jobs:
echo ${{ inputs.ref }}
echo ${{ inputs.sha }}
echo ${{ inputs.sectionChangelog }}
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
with:
fetch-depth: 0
ref: ${{ inputs.ref }}
- - uses: actions/setup-node@v3
+ - uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
registry-url: "https://registry.npmjs.org"
- name: Set name vars
id: info-vars
@@ -56,7 +56,7 @@ jobs:
# @see https://github.com/chromaui/chromatic-cli/issues/551
if: inputs.sectionChangelog != 'Unreleased'
id: chromatic-upload
- uses: chromaui/action@v1
+ uses: chromaui/action@v11
with:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.chromaticToken }}
diff --git a/.github/workflows/test-code.yml b/.github/workflows/test-code.yml
index 27629721..8e9ec7db 100644
--- a/.github/workflows/test-code.yml
+++ b/.github/workflows/test-code.yml
@@ -15,11 +15,11 @@ jobs:
test-code:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
- name: Test using Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@main
with:
- node-version: "16"
+ node-version: "18"
- run: yarn install
- run: yarn compile
- run: yarn compile-scss
diff --git a/.github/workflows/test-project.yml b/.github/workflows/test-project.yml
index ac4fac5f..cc84bc19 100644
--- a/.github/workflows/test-project.yml
+++ b/.github/workflows/test-project.yml
@@ -5,6 +5,8 @@ on:
branches-ignore:
- "develop"
- "main"
+ - "next"
+ - "legacy"
pull_request:
jobs:
@@ -12,22 +14,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Test branch name
- # https://github.com/marketplace/actions/branch-name-rules
- uses: deepakputhraya/action-branch-name@master
+ # https://github.com/marketplace/actions/enforce-branch-name
+ uses: finleyfamily/action-enforce-branch-name@master
with:
regex: '([a-z])+\/([a-z]).([aA-zZ\.\-\d])+'
- allowed_prefixes: "feature,release,fix,bugfix,hotfix,change,temp"
- ignore: "main,develop"
- min_length: 10
- max_length: 100
+ allowed_prefixes: "feature,release,fix,bugfix,hotfix,change,temp,dependabot"
+ exclude: "main,develop,next,legacy"
test-documentation:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@main
- name: Test existence of important files
# https://github.com/marketplace/actions/file-existence
id: check_files
- uses: andstor/file-existence-action@v2
+ uses: andstor/file-existence-action@main
with:
files: "package.json, LICENSE, README.md, CHANGELOG.md"
- name: 'Test for "## [Unreleased]" section in changelog'
diff --git a/.storybook/main.js b/.storybook/main.js
index 6af6376b..bdb1a2a4 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -15,6 +15,7 @@ module.exports = {
},
},
},
+ "@storybook/addon-webpack5-compiler-babel",
],
framework: {
name: "@storybook/react-webpack5",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 82ba8392..fe9d895d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,118 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [Unreleased]
+This is a major release, and it might be not compatible with your current usage of our library. Please read about the necessary changes in the section about how to migrate.
+
+### Migration from v23 to v24
+
+- upgrade Typescript to v5
+- upgrade Node to at least v18, see **Changed** section for more info about it
+- remove deprecated components, properties and imports from your project, if the info cannot be found here then it was already mentioned in **Deprecated** sections of the past changelogs
+ - ``
+ - `full`: was deprecated and now removed because it always uses full width if it is the only column and does not have any othe size config
+ - ``
+ - `fullWidth`: was deprecated and now removed, use `flexWidth` as replacement
+ - `iconName`: was deprecated and now removed, use `icon` property
+ - `
`
+ - `size`: use only "small", "medium" or "large" as value
+ - ``
+ - `emphasized`: was deprecated and now removed, use `minimal=false` plus `emphasis="stronger"` instead
+ - `IconSized` type: use `CarbonIconType`
+ - `TimeUnits` type: use `ElapsedDateTimeDisplayUnits`
+ - `MarkdownParserProps` interface: use `MarkdownProps`
+ - `elapsedTimeSegmented` function: use `elapsedDateTimeDisplayUtils.elapsedTimeSegmented`
+ - `simplifiedElapsedTime` function: use `elapsedDateTimeDisplayUtils.simplifiedElapsedTime`
+
+### Added
+
+- ``:
+ - `noTogglerContentSuffix`: Allows to add non-string elements at the end of the content if the full description is shown, i.e. no toggler is necessary. This allows to add non-string elements to both the full-view content and the pure string content.
+- ``
+ - An optional custom search function property has been added, it defines how to filter elements.
+ - Added a prop `limitHeightOpened` to limit the height of the dropdown by automatically calculating the available height in vh.
+- `` and ``
+ - helper components to create flex layouts for positioning sub elements
+ - stop misusing `Toolbar*` components to do that (anti pattern)
+- `` and ``
+ - `singleColumn` property to display label and value below each other
+- ``
+ - `emphasis` property to control visual appearance of the label text
+- basic Storybook example for `` components
+- ``
+ - `setEditorView` option for compatibility to Codemirror v6
+ - `supportCodeFolding` optional property to fold code for the supported modes e.g: `xml`, `json`, etc.
+ - `shouldHighlightActiveLine` optional property to highlight active line where the cursor is currently in.
+ - `shouldHaveMinimalSetup` optional property that imports codemirror's base minimal configurations.
+ - `additionalExtensions` optional property for additional extensions to customize the editor further.
+- ``
+ - `htmlContentBlockProps` can now be used to configure the wrapper around the Markdown content
+- `$eccgui-selector-text-spot-highlight` SCSS config variable to specify selector that is used to create shortly highlighted spots
+ - it is highlighted when the selector is also active local anchor target or if it has the `.eccgui-typography--spothighlight` class attached to it
+
+### Fixed
+
+- toggling on/off the `` was corrected, they kept displayed after re-entering with the cursor
+- ``
+ - change text overflow for selectors to `clip` because Firefox rendered `ellipsis` a bit too early
+- ``:
+ - `useDropzoneMonitor` helper hook process was improved so that less events are processed and the dropzone monitoring is more stable
+
+### Changed
+
+- GUI elements library needs node 18 or an higher version because dependencies were upgraded
+ - you may run into problems if you try it with Node v16 or v17, or Webpack v4, mainly because of a Node bugfix regarding the OpenSSL provider
+ - if you cannot upgrade your dependencies then you could workaround that by patching the `crypto` package or using Node with `--openssl-legacy-provider` option
+ - see https://github.com/webpack/webpack/issues/14532 and https://stackoverflow.com/questions/69692842/ for more info and possible solutions
+- upgrade to `@carbon/react` package
+ - almost all Carbon related packages were replaced by using only `@carbon/react`
+ - some component interfaces partly lack documentation in our Storybook because their base interfaces from `@carbon/react` are currently not exported: `AccordionItemProps`, `ApplicationHeaderProps`, `ApplicationToolbarProps`, `ApplicationToolbarActionProps`, `ApplicationToolbarPanelProps`, `CarbonIconType`, `TableCellProps`, `TableExpandRowProps`, `TableProps`
+- upgrade to Typescript v5
+ - your package should be compatible to Typescript 5 patterns
+- upgrade to Storybook v8
+ - include a few patches for actions, see https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function
+- allow `next` and `legacy` as branch names
+- ``
+ - `setInstance` interface changed to `setEditorView` for semantic compatibility to Codemirror v6
+- ``
+ - link color and separation char were adjusted
+- ``
+ - align blocks for language specific code to default code blocks
+- switch icons for `item-clone` and `item-copy` to Carbon's `` and ``
+- Remove duplicated icon names `artefact-customtask*` and only keep `artefact-task*` names.
+- ``
+ - improve examples in storybook
+ - improve display for images that are to large for the available space (fully show them)
+- ``:
+ - Add parameter `reInitOnInitialValueChange`, to allow the field to re-initialize if the initial value changes.
+
+### Deprecated
+
+- `` and ``
+ - `description` and `iconTitle`: use `title` as replacement.
+- `TableRowHeightSize` type: use `TableProps["size"]` directly
+- `IRenderModifiers` interface: use `SuggestFieldItemRendererModifierProps`
+- `IElementWidth` type: use `SuggestFieldItemRendererModifierProps["styleWidth"]`
+- `MultiSelectSelectionProps` interface: use `MultiSuggestFieldSelectionProps`
+- `MultiSelectProps` interface: use `MultiSuggestFieldProps`
+- `nodeTypes` and `edgeTypes`
+ - will be removed without replacement, define it yourself or use ``
+ - `AutoSuggestionProps`: use `CodeAutocompleteFieldProps` instead
+ - we renamed `ISuggestionBase`, `ISuggestionWithReplacementInfo`, `IReplacementResult`, `IPartialAutoCompleteResult`, `IValidationResult` to `CodeAutocompleteFieldSuggestionBase`, `CodeAutocompleteFieldSuggestionWithReplacementInfo`, `CodeAutocompleteFieldReplacementResult`, `CodeAutocompleteFieldPartialAutoCompleteResult`, `CodeAutocompleteFieldValidationResult`
+- all legacy support components are going to be removed, you need to replace them by activily maintained components
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``
+ - ``: switch to ``, ``, ``
+- `MultiSuggestField.ofType` method:
+ - instead of `MyMultiSuggest = MultiSuggestField.ofType()` use directly ` {...props} />`
+ - `MultiSuggestField.ofType` also returns the original BlueprintJS `MultiSelect` element, not our version!
+
## [23.8.0] - 2024-08-19
### Added
@@ -53,7 +165,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Element wraps the content that need to be displayed sticky.
- `utils`
- `getScrollParent`: method to find the scroll parent of an element
-- ``
+- ``
- Support loading more results when scrolling to the end of the result list.
- ``
- `intent` property to set the state, formerly used `hasStatePrimary`, `hasStateSuccess`, `hasStateWarning` and `hasStateDanger` properties are now deprecated
@@ -188,7 +300,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- ``
- added extra line to show timer for execution period
- ``
- - replaces `` to get used for the `` component
+ - replaces `` to get used for the `` component
- new icons
- `data-string`, `data-url`, `data-date`, `data-time`, `data-datetime`, `data-number`
@@ -236,7 +348,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- `loose`: can be set to `true` to prevent the box with border on the label component
- ``
- `toggleIcon`: optional icon that should be displayed instead of the default ones.
-- `Utilities`
+- `utils`
- `getGlobalVar` and `setGlobalVar`: can be used to manage global variables indepentently from component states. They are stored to the `window` object under a `eccgui` "namespace". Can be used for example to manage globally increased counters. Do not use them if you need to store user session properties or confidential data!
- canonical icons for `artefact-chatlog`, `entity-human`, `entity-robot` and `operation-magic`
@@ -366,7 +478,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- ``
- `IWorkspaceHeaderProps` interface is now deprecated, use `WorkspaceHeaderProps` instead
- ``
- - It will be remove because beside the special arrow buttons it does not add any special. Could be done also with `` combined with correct `type`.
+ - It will be removed because beside the special arrow buttons it does not add any special. Could be done also with `` combined with correct `type`.
- ``
- `HighlighterFunctions` renamed to `highlighterUtils`
- `extractSearchWords` moved to `highlighterUtils.extractSearchWords`
@@ -381,7 +493,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- `ReactFlow` extensions
- `NodeProps`: renamed to `NodeDefaultProps`
- `minimapNodeClassName`: moved to `miniMapUtils.nodeClassName`
- - `minimapNodeColor`: moved to `miniMapUtils.nodeClassName`
+ - `minimapNodeColor`: moved to `miniMapUtils.nodeColor`
- `nodeUtils`: renamed to `nodeDefaultUtils`
- `IHandleProps`: renamed to `NodeContentHandleProps`
- `NodeDimensions`: use `NodeContentProps['nodeDimensions']`
diff --git a/README.md b/README.md
index a2e317a0..99b66e9e 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,24 @@ All [configuration variables](https://github.com/eccenca/gui-elements/blob/devel
## Development
+### Branch management
+
+We have 4 types of major branches representing the current state:
+
+- `main`: contains the latest official release, only `release/*` branches will be merged into this branch
+- `develop`: contains the latest state of development, `feature/*`, `bugfix/*` and `next` branches will be merged into `develop`
+- `next`: development tree for an upcoming new major version, it will be merged into `develop` at some point, `feature/*`, `bugfix/*` and `release/*` branches will be merged into it
+- `legacy`: development tree for the predecessor of the current major version, only `bugfix/*` and `hotfix/*` branches will be merged into it
+
+We allow a few more prefixes for valid branchnames:
+
+- `feature/*`: extend functionality, maintain dependencies
+- `fix/*`, `bugfix/*`, `hotfix/*`: fix functionality
+- `release/*`: branches to finalize releases, also used to publish release candidate packages
+- `change/*`, `temp/*`
+
+`next` and `legacy` only exist if necessary, otherwise we do not maintain those branches. Merges into `main`, `develop`, `next` and `legacy` are always managed by pull requests.
+
### Running tests
Run the Jest tests with `yarn test`, for test coverage information run `yarn test:coverage`.
@@ -91,9 +109,11 @@ If necessary you can use [yalc](https://github.com/wclr/yalc) to develop gui ele
1. Install yalc globally via npm or yarn
2. Checkout [@eccenca/gui-elements](https://github.com/eccenca/gui-elements)
-3. Inside gui elements folder: `yalc publish --push`
-4. Inside your applications folder: `yalc link @eccenca/gui-elements`
-5. After updates to the gui elements: `yarn build:all && yalc push`
+3. Inside gui elements folder: `yarn build:all && yalc publish --push`
+4. Inside your applications folder: `yalc add @eccenca/gui-elements`
+5. After updates to the gui elements rebuild and update the applications yalc folder: `yarn build:all && yalc publish --push` (you usually are not required to fire another `yalc add` in your applications folder)
+
+After you tested the GUI elements package locally you can Clean up your applications folder by `yalc remove --all && git checkout -- pakage.json yarn.lock`.
### Process for pull requests and publishing releases
diff --git a/declarations.d.ts b/declarations.d.ts
index a3be346c..69eafcae 100644
--- a/declarations.d.ts
+++ b/declarations.d.ts
@@ -1,3 +1,2 @@
-declare module "@carbon/icons-react";
declare module "carbon-components-react/es/index";
declare module "wicg-inert";
diff --git a/package.json b/package.json
index 1f47ae6c..e8a5fe44 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@eccenca/gui-elements",
"description": "GUI elements based on other libraries, usable in React application, written in Typescript.",
- "version": "23.8.0",
+ "version": "24.0.0-rc.6",
"license": "Apache-2.0",
"homepage": "https://github.com/eccenca/gui-elements",
"bugs": "https://github.com/eccenca/gui-elements/issues",
@@ -28,7 +28,7 @@
"registry": "https://registry.npmjs.org"
},
"engines": {
- "node": ">=16.x"
+ "node": ">=18"
},
"style": "src/index.scss",
"main": "dist/cjs/index.js",
@@ -66,110 +66,104 @@
},
"dependencies": {
"@blueprintjs/colors": "^5.1.1",
- "@blueprintjs/core": "^5.10.3",
- "@blueprintjs/select": "^5.1.5",
- "@carbon/icons": "^11.19.0",
- "@carbon/icons-react": "11.19.0",
- "@carbon/styles": "1.32.0",
+ "@blueprintjs/core": "^5.11.0",
+ "@blueprintjs/select": "^5.2.2",
+ "@carbon/icons": "^11.47.1",
+ "@carbon/react": "^1.64.1",
+ "@codemirror/lang-json": "^6.0.1",
+ "@codemirror/lang-markdown": "^6.3.1",
+ "@codemirror/lang-xml": "^6.1.0",
+ "@codemirror/legacy-modes": "^6.4.2",
"@mavrin/remark-typograf": "^2.2.0",
- "carbon-components-react": "^8.28.0",
- "codemirror": "^5.65.16",
- "codemirror-formatting": "^1.0.0",
+ "codemirror": "^6.0.1",
"color": "^4.2.3",
+ "compute-scroll-into-view": "^3.1.0",
"lodash": "^4.17.21",
- "re-resizable": "6.9.9",
+ "re-resizable": "^6.10.1",
"react": "^16.13.1",
- "react-codemirror2": "^7.3.0",
"react-dom": "^16.13.1",
"react-flow-renderer": "9.7.4",
"react-flow-renderer-lts": "npm:react-flow-renderer@^10.3.17",
"react-inlinesvg": "^3.0.3",
"react-markdown": "^8.0.7",
- "react-syntax-highlighter": "15.5.0",
+ "react-syntax-highlighter": "^15.6.1",
"rehype-raw": "^6.1.1",
"remark-definition-list": "^1.2.0",
"remark-gfm": "^3.0.1",
"remark-parse": "^10.0.2",
"reset-css": "^5.0.2",
- "unified": "^11.0.4",
- "wicg-inert": "^3.1.2"
+ "unified": "^11.0.5",
+ "wicg-inert": "^3.1.3",
+ "xml-formatter": "^3.6.3"
},
"devDependencies": {
- "@babel/core": "^7.23.9",
+ "@babel/core": "^7.26.0",
"@babel/plugin-proposal-class-properties": "^7.16.7",
"@babel/plugin-proposal-private-methods": "^7.16.11",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
- "@babel/preset-env": "^7.23.9",
- "@babel/preset-flow": "^7.23.3",
- "@babel/preset-react": "^7.23.3",
- "@babel/preset-typescript": "^7.23.3",
- "@storybook/addon-actions": "^7.6.17",
- "@storybook/addon-essentials": "^7.6.17",
- "@storybook/addon-jest": "^7.6.17",
- "@storybook/addon-links": "^7.6.17",
- "@storybook/cli": "^7.6.17",
+ "@babel/preset-env": "^7.26.0",
+ "@babel/preset-flow": "^7.25.9",
+ "@babel/preset-react": "^7.25.9",
+ "@babel/preset-typescript": "^7.26.0",
+ "@storybook/addon-actions": "^8.4.3",
+ "@storybook/addon-essentials": "^8.4.3",
+ "@storybook/addon-jest": "^8.4.3",
+ "@storybook/addon-links": "^8.4.3",
+ "@storybook/addon-webpack5-compiler-babel": "^3.0.3",
+ "@storybook/cli": "^8.4.3",
"@storybook/preset-scss": "^1.0.3",
- "@storybook/react": "^7.6.17",
- "@storybook/react-webpack5": "^7.6.17",
- "@testing-library/jest-dom": "^6.4.2",
+ "@storybook/react": "^8.4.3",
+ "@storybook/react-webpack5": "^8.4.3",
+ "@storybook/test": "^8.4.3",
+ "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^12.1.2",
- "@types/carbon-components-react": "^7.55.10",
"@types/codemirror": "^5.60.15",
"@types/color": "^3.0.6",
"@types/jest": "^29.5.12",
- "@types/lodash": "^4.14.202",
- "@types/react-syntax-highlighter": "15.5.11",
+ "@types/lodash": "^4.17.7",
+ "@types/react-syntax-highlighter": "^15.5.13",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"babel-jest": "^29.7.0",
- "chromatic": "^10.9.6",
- "eslint": "^8.56.0",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-simple-import-sort": "^10.0.0",
+ "chromatic": "^11.18.1",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react": "^7.35.0",
+ "eslint-plugin-react-hooks": "^4.6.2",
+ "eslint-plugin-simple-import-sort": "^12.1.1",
"husky": "4",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-pnp-resolver": "^1.2.3",
- "lint-staged": "^13.3.0",
+ "lint-staged": "^15.2.9",
"node-sass-package-importer": "^5.3.3",
"prettier": "^2.8.8",
"react-app-polyfill": "^3.0.0",
"react-lorem-ipsum": "^1.4.9",
"regenerator-runtime": "^0.13.9",
- "rimraf": "^5.0.5",
+ "rimraf": "^5.0.10",
"sass": "1.62.1",
"sass-loader": "10.3.1",
- "storybook": "^7.6.17",
+ "storybook": "^8.4.3",
"stylelint": "^15.11.0",
"stylelint-config-recess-order": "^4.6.0",
"stylelint-config-standard-scss": "^9.0.0",
"ts-node": "^10.9.2",
- "tsc-esm-fix": "^2.20.25",
- "typescript": "4.5.2",
+ "tsc-esm-fix": "^3.0.2",
+ "typescript": "5.5.3",
"url-loader": "^4.1.1",
"yargs": "^17.7.2"
},
"peerDependencies": {
- "@carbon/icons-react": ">=11.34.1",
- "@carbon/styles": "<1.33.0",
- "@types/carbon-components-react": ">=7",
+ "@blueprintjs/core": ">=5",
"react": ">=16",
"react-dom": ">=16"
},
"resolutions": {
- "**/@types/react": "^17.0.75",
- "**/@carbon/icons-react": "11.19.0",
- "**/jackspeak": "2.1.1",
- "node-sass-package-importer/**/postcss": "^8.4.31",
- "**/word-wrap": "^1.2.4",
- "**/webpack-dev-middleware": "^6.1.2",
- "**/braces": "^3.0.3",
- "**/ws": "^8.17.1",
- "**/ejs": "^3.1.10",
- "**/tar": "^6.2.1",
- "**/express": "^4.19.2"
+ "**/@types/react": "^17.0.80",
+ "node-sass-package-importer/**/postcss": "^8.4.41",
+ "**/cross-spawn": "^7.0.5 ",
+ "**/micromatch": "^4.0.8"
},
"husky": {
"hooks": {
diff --git a/src/cmem/ActivityControl/ActivityControlTypes.ts b/src/cmem/ActivityControl/ActivityControlTypes.ts
index 12746530..11437fbe 100644
--- a/src/cmem/ActivityControl/ActivityControlTypes.ts
+++ b/src/cmem/ActivityControl/ActivityControlTypes.ts
@@ -1,5 +1,4 @@
-// @deprecated use `SilkActivityStatusProps`
-export interface IActivityStatus {
+export interface SilkActivityStatusProps {
// Optional project ID
project?: string;
// Optional task ID
@@ -23,7 +22,7 @@ export interface IActivityStatus {
// If the activity has been cancelled
cancelled: boolean;
// The concrete status ID
- concreteStatus: ConcreteActivityStatus;
+ concreteStatus: SilkActivityStatusConcrete;
// If there was an error, this contains the exception message
exceptionMessage?: string | null;
// The runtime in ms
@@ -33,10 +32,8 @@ export interface IActivityStatus {
// The queue time spent waiting before workflow is executed as date time, e.g. "2021-09-07T09:34:53.153Z"
queueTime?: string;
}
-export type SilkActivityStatusProps = IActivityStatus;
-// @deprecated use `SilkActivityStatusConcrete`
-export type ConcreteActivityStatus =
+export type SilkActivityStatusConcrete =
| "Cancelled"
| "Failed"
| "Successful"
@@ -44,4 +41,3 @@ export type ConcreteActivityStatus =
| "Running"
| "Waiting"
| "Canceling";
-export type SilkActivityStatusConcrete = ConcreteActivityStatus;
diff --git a/src/cmem/ActivityControl/ActivityControlWidget.stories.tsx b/src/cmem/ActivityControl/ActivityControlWidget.stories.tsx
index 982973a9..21c1bd13 100644
--- a/src/cmem/ActivityControl/ActivityControlWidget.stories.tsx
+++ b/src/cmem/ActivityControl/ActivityControlWidget.stories.tsx
@@ -1,6 +1,6 @@
import React from "react";
import { loremIpsum } from "react-lorem-ipsum";
-import { ComponentMeta, ComponentStory } from "@storybook/react";
+import { Meta, StoryFn } from "@storybook/react";
import { helpersArgTypes } from "../../../.storybook/helpers";
import { ActivityControlWidget, Tag, TagList } from "../../../index";
@@ -9,31 +9,13 @@ export default {
title: "Cmem/ActivityControlWidget",
component: ActivityControlWidget,
argTypes: {
- border: {
- table: {
- defaultValue: { summary: false },
- type: { summary: "boolean" },
- },
- },
- small: {
- table: {
- defaultValue: { summary: false },
- type: { summary: "boolean" },
- },
- },
- canShrink: {
- table: {
- defaultValue: { summary: false },
- type: { summary: "boolean" },
- },
- },
progressSpinnerFinishedIcon: {
...helpersArgTypes.exampleIcon,
},
},
-} as ComponentMeta;
+} as Meta;
-const Template: ComponentStory = (args) => ;
+const Template: StoryFn = (args) => ;
export const FullExample = Template.bind({});
@@ -82,7 +64,7 @@ FullExample.args = {
...commonWidgetArgs,
};
-const TemplateWithTags: ComponentStory = (args) => ;
+const TemplateWithTags: StoryFn = (args) => ;
export const WidgetWithTags = TemplateWithTags.bind({});
diff --git a/src/cmem/ActivityControl/ActivityControlWidget.tsx b/src/cmem/ActivityControl/ActivityControlWidget.tsx
index 95aa7990..dfa754e4 100644
--- a/src/cmem/ActivityControl/ActivityControlWidget.tsx
+++ b/src/cmem/ActivityControl/ActivityControlWidget.tsx
@@ -83,9 +83,6 @@ export interface ActivityControlWidgetProps extends TestableComponent {
timerExecutionMsg?: JSX.Element | null;
}
-// @deprecated use `ActivityControlWidgetProps`
-export type IActivityControlProps = ActivityControlWidgetProps;
-
interface IActivityContextMenu extends TestableComponent {
// Tooltip for the context menu
tooltip?: string;
@@ -106,9 +103,6 @@ export interface ActivityControlWidgetAction extends TestableComponent {
hasStateWarning?: boolean;
}
-// @deprecated use `ActivityControlWidgetAction`
-export type IActivityAction = ActivityControlWidgetAction;
-
interface IActivityMenuAction extends ActivityControlWidgetAction {
// Optional link
href?: string;
diff --git a/src/cmem/ActivityControl/SilkActivityControl.tsx b/src/cmem/ActivityControl/SilkActivityControl.tsx
index e38421af..284d86a0 100644
--- a/src/cmem/ActivityControl/SilkActivityControl.tsx
+++ b/src/cmem/ActivityControl/SilkActivityControl.tsx
@@ -4,7 +4,7 @@ import { Intent } from "@blueprintjs/core/src/common/intent";
import { Icon, Spacing } from "../../";
import { IntentTypes } from "../../common/Intent";
import { TestableComponent } from "../../components/interfaces";
-import { ElapsedDateTimeDisplay, TimeUnits } from "../DateTimeDisplay/ElapsedDateTimeDisplay";
+import { ElapsedDateTimeDisplay, ElapsedDateTimeDisplayUnits } from "../DateTimeDisplay/ElapsedDateTimeDisplay";
import { SilkActivityStatusConcrete, SilkActivityStatusProps } from "./ActivityControlTypes";
import { ActivityControlWidget, ActivityControlWidgetProps } from "./ActivityControlWidget";
@@ -42,13 +42,13 @@ export interface SilkActivityControlProps extends TestableComponent {
action: string | (() => any);
};
// DI activity actions
- executeActivityAction: (action: ActivityAction) => void;
+ executeActivityAction: (action: SilkActivityControlAction) => void;
/** If specified, the activity control will offer a "Start prioritized" button while the activity is in the waiting state.
* When the button is clicked it should start the activity via the startPrioritized endpoint.
*/
executePrioritized?: () => void;
// Get the translation for a specific key
- translate: (key: ActivityControlTranslationKeys) => string;
+ translate: (key: SilkActivityControlTranslationKeys) => string;
// When defined the elapsed time since the last start is displayed next to the label
elapsedTimeOfLastStart?: {
// Prefix before the elapsed time
@@ -56,7 +56,7 @@ export interface SilkActivityControlProps extends TestableComponent {
// Suffix after the elapsed time
suffix?: string;
// The translation of the time units
- translate: (unit: TimeUnits) => string;
+ translate: (unit: ElapsedDateTimeDisplayUnits) => string;
};
// configure how the widget is displayed
layoutConfig?: SilkActivityControlLayoutProps;
@@ -65,7 +65,7 @@ export interface SilkActivityControlProps extends TestableComponent {
/**
* The translation of the time units
*/
- translateUnits?: (unit: TimeUnits) => string;
+ translateUnits?: (unit: ElapsedDateTimeDisplayUnits) => string;
}
export interface SilkActivityControlLayoutProps {
@@ -83,9 +83,6 @@ export interface SilkActivityControlLayoutProps {
labelWrapper?: JSX.Element;
}
-// @deprecated use `SilkActivityControlLayoutProps`
-export type IActivityControlLayoutProps = SilkActivityControlLayoutProps;
-
const defaultLayout: SilkActivityControlLayoutProps = {
small: false,
border: false,
@@ -131,9 +128,6 @@ export interface SilkActivityExecutionReportProps {
stackTrace?: IStacktrace;
}
-// @deprecated use `SilkActivityExecutionReportProps`
-export type IActivityExecutionReport = SilkActivityExecutionReportProps;
-
interface IStacktrace {
// The final error message of the stacktrace
errorMessage?: string;
@@ -143,17 +137,13 @@ interface IStacktrace {
cause?: IStacktrace;
}
-// @deprecated use `SilkActivityControlTranslationKeys`
-export type ActivityControlTranslationKeys =
+export type SilkActivityControlTranslationKeys =
| "startActivity"
| "stopActivity"
| "reloadActivity"
| "showErrorReport"
| "startPrioritized";
-export type SilkActivityControlTranslationKeys = ActivityControlTranslationKeys;
-// @deprecated use `SilkActivityControlAction`
-export type ActivityAction = "start" | "cancel" | "restart";
-export type SilkActivityControlAction = ActivityAction;
+export type SilkActivityControlAction = "start" | "cancel" | "restart";
/** Silk activity control. */
export function SilkActivityControl(props: SilkActivityControlProps) {
@@ -178,7 +168,7 @@ export function useSilkActivityControl({
layoutConfig = defaultLayout,
hideMessageOnStatus = () => false,
executePrioritized,
- translateUnits = (unit: TimeUnits) => unit.toString(),
+ translateUnits = (unit: ElapsedDateTimeDisplayUnits) => unit.toString(),
...props
}: SilkActivityControlProps) {
const [activityStatus, setActivityStatus] = useState(initialStatus);
diff --git a/src/cmem/ConfidenceValue/ConfidenceValue.stories.tsx b/src/cmem/ConfidenceValue/ConfidenceValue.stories.tsx
index c62b04fd..03ef43ba 100644
--- a/src/cmem/ConfidenceValue/ConfidenceValue.stories.tsx
+++ b/src/cmem/ConfidenceValue/ConfidenceValue.stories.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { ComponentMeta, ComponentStory } from "@storybook/react";
+import { Meta, StoryFn } from "@storybook/react";
import { ConfidenceValue } from "../../../index";
@@ -11,9 +11,9 @@ export default {
control: "color",
},
},
-} as ComponentMeta;
+} as Meta;
-const TemplateIcons: ComponentStory = (args) => ;
+const TemplateIcons: StoryFn = (args) => ;
export const Default = TemplateIcons.bind({});
Default.args = {
value: "0.5",
diff --git a/src/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.tsx b/src/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.tsx
index 8dbee651..f9c08126 100644
--- a/src/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.tsx
+++ b/src/cmem/ContentBlobToggler/StringPreviewContentBlobToggler.tsx
@@ -18,6 +18,10 @@ export interface StringPreviewContentBlobTogglerProps
renderPreviewAsMarkdown?: boolean;
/** White-listing of HTML elements that will be rendered when renderPreviewAsMarkdown is enabled. */
allowedHtmlElementsInPreview?: string[];
+ /** Allows to add non-string elements at the end of the content if the full description is shown, i.e. no toggler is necessary.
+ * This allows to add non-string elements to both the full-view content and the pure string content.
+ */
+ noTogglerContentSuffix?: JSX.Element;
}
/** Version of the content toggler for text only content. */
@@ -32,21 +36,31 @@ export function StringPreviewContentBlobToggler({
firstNonEmptyLineOnly,
renderPreviewAsMarkdown = false,
allowedHtmlElementsInPreview,
+ noTogglerContentSuffix,
}: StringPreviewContentBlobTogglerProps) {
const previewMaybeFirstLine = firstNonEmptyLineOnly ? firstNonEmptyLine(content) : content;
const previewString = previewMaxLength ? previewMaybeFirstLine.substr(0, previewMaxLength) : previewMaybeFirstLine;
const enableToggler = previewString !== content;
+ let previewContent = renderPreviewAsMarkdown ? (
+
+ {previewString}
+
+ ) : (
+ previewString
+ );
+ if (!enableToggler && noTogglerContentSuffix) {
+ previewContent = (
+ <>
+ {previewContent}
+ {noTogglerContentSuffix}
+ >
+ );
+ }
return (
{previewString}
- ) : (
- previewString
- )
- }
+ previewContent={previewContent}
toggleExtendText={toggleExtendText}
toggleReduceText={toggleReduceText}
fullviewContent={fullviewContent}
@@ -60,9 +74,8 @@ const newLineRegex = new RegExp("\r|\n"); // eslint-disable-line
/**
* Takes the first non-empty line from a preview string.
- * @deprecated use `stringPreviewContentBlobTogglerUtils.firstNonEmptyLine`
*/
-export function firstNonEmptyLine(preview: string) {
+function firstNonEmptyLine(preview: string) {
const previewString = preview.trim();
const result = newLineRegex.exec(previewString);
return result !== null ? previewString.substr(0, result.index) : previewString;
diff --git a/src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx b/src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx
index c9e7885b..28a13ab2 100644
--- a/src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx
+++ b/src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx
@@ -2,9 +2,15 @@ import React, { useEffect, useState } from "react";
import { TestableComponent } from "../../components/interfaces";
-// @deprecated use `ElapsedDateTimeDisplayUnits`
-export type TimeUnits = "second" | "seconds" | "minute" | "minutes" | "hour" | "hours" | "day" | "days";
-export type ElapsedDateTimeDisplayUnits = TimeUnits;
+export type ElapsedDateTimeDisplayUnits =
+ | "second"
+ | "seconds"
+ | "minute"
+ | "minutes"
+ | "hour"
+ | "hours"
+ | "day"
+ | "days";
export interface ElapsedDateTimeDisplayProps extends TestableComponent {
// The date time given as string (parseable by Date) or number (ms since 1970-01-01 00:00:00 UTC)
@@ -28,9 +34,8 @@ const dateTimeToElapsedTimeInMs = (dateTime: string | number) => {
/**
* Returns a segmentation of the elapsed time, i.e. an array with the nr of days, hours, minutes, seconds
- * @deprecated moved to `elapsedDateTimeDisplayUtils.elapsedTimeSegmented`
*/
-export const elapsedTimeSegmented = (elapsedTimeInMs: number): number[] => {
+const elapsedTimeSegmented = (elapsedTimeInMs: number): number[] => {
// In how many segments the time should be split, i.e. hours, minutes, seconds
const segmentSteps = [24, 60, 60];
// First convert to time in seconds
@@ -47,9 +52,8 @@ export const elapsedTimeSegmented = (elapsedTimeInMs: number): number[] => {
/**
* Returns the simplified elapsed time
- * @deprecated moved to `elapsedDateTimeDisplayUtils.simplifiedElapsedTime`
*/
-export const simplifiedElapsedTime = (
+const simplifiedElapsedTime = (
timeSegments: number[],
translateUnits: (unit: ElapsedDateTimeDisplayUnits) => string,
includeSeconds = false
diff --git a/src/cmem/DateTimeDisplay/tests/ElapsedDateTimeDisplay.test.tsx b/src/cmem/DateTimeDisplay/tests/ElapsedDateTimeDisplay.test.tsx
index 456d4b58..198d9631 100644
--- a/src/cmem/DateTimeDisplay/tests/ElapsedDateTimeDisplay.test.tsx
+++ b/src/cmem/DateTimeDisplay/tests/ElapsedDateTimeDisplay.test.tsx
@@ -1,12 +1,17 @@
-import { elapsedTimeSegmented, simplifiedElapsedTime, TimeUnits } from "../ElapsedDateTimeDisplay";
+import { ElapsedDateTimeDisplayUnits, elapsedDateTimeDisplayUtils } from "../../../../index";
describe("Elapsed time component", () => {
const checkMS = (timeInMs: number, expectedString: string) =>
- expect(elapsedTimeSegmented(timeInMs).join(":")).toBe(expectedString);
+ expect(elapsedDateTimeDisplayUtils.elapsedTimeSegmented(timeInMs).join(":")).toBe(expectedString);
const checkS = (timeInSeconds: number, expectedString: string) => checkMS(timeInSeconds * 1000, expectedString);
- const translate = (timeUnit: TimeUnits) => timeUnit;
+ const translate = (timeUnit: ElapsedDateTimeDisplayUnits) => timeUnit;
const checkHumanReadable = (timeInSeconds: number, expectedString: string) =>
- expect(simplifiedElapsedTime(elapsedTimeSegmented(timeInSeconds * 1000), translate)).toBe(expectedString);
+ expect(
+ elapsedDateTimeDisplayUtils.simplifiedElapsedTime(
+ elapsedDateTimeDisplayUtils.elapsedTimeSegmented(timeInSeconds * 1000),
+ translate
+ )
+ ).toBe(expectedString);
it("should segment the time", () => {
checkMS(2123, "0:0:0:2");
checkS(2, "0:0:0:2");
diff --git a/src/cmem/markdown/Markdown.stories.tsx b/src/cmem/markdown/Markdown.stories.tsx
index a46d43a1..d067e791 100644
--- a/src/cmem/markdown/Markdown.stories.tsx
+++ b/src/cmem/markdown/Markdown.stories.tsx
@@ -1,6 +1,6 @@
import React from "react";
import { Blockquote } from "@blueprintjs/core";
-import { ComponentMeta, ComponentStory } from "@storybook/react";
+import { Meta, StoryFn } from "@storybook/react";
import { Markdown } from "./../../../index";
@@ -8,9 +8,9 @@ export default {
title: "Cmem/Markdown",
component: Markdown,
argTypes: {},
-} as ComponentMeta;
+} as Meta;
-const Template: ComponentStory = (args) => ;
+const Template: StoryFn = (args) => ;
export const Default = Template.bind({});
@@ -52,6 +52,12 @@ another code block
{{templateVar}}
\`\`\`
+\`\`\`json
+{
+ "json": "varname"
+}
+\`\`\`
+
> This is a block quote.
>
> With 2 paragraphs.
diff --git a/src/cmem/markdown/Markdown.tsx b/src/cmem/markdown/Markdown.tsx
index 25edcc48..f1bf796f 100644
--- a/src/cmem/markdown/Markdown.tsx
+++ b/src/cmem/markdown/Markdown.tsx
@@ -2,14 +2,14 @@ import React from "react";
import ReactMarkdown from "react-markdown";
import { PluggableList } from "react-markdown/lib/react-markdown";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
-import { materialLight } from "react-syntax-highlighter/dist/esm/styles/prism";
// @ts-ignore: No declaration file for module (TODO: should be @ts-expect-error but GUI elements is used inside project with `noImplicitAny=false`)
import remarkTypograf from "@mavrin/remark-typograf";
import rehypeRaw from "rehype-raw";
import { remarkDefinitionList } from "remark-definition-list";
import remarkGfm from "remark-gfm";
-import { HtmlContentBlock, TestableComponent } from "../../index";
+import { CLASSPREFIX as eccgui } from "../../configuration/constants";
+import { HtmlContentBlock, HtmlContentBlockProps, TestableComponent } from "../../index";
export interface MarkdownProps extends TestableComponent {
children: string;
@@ -28,7 +28,8 @@ export interface MarkdownProps extends TestableComponent {
*/
allowedElements?: string[];
/**
- * Do not wrap it in a content block element.
+ * Do not wrap content in a `HtmlContentBlock` component.
+ * This option is ignored if `htmlContentBlockProps` or `data-test-id` is given.
*/
inheritBlock?: boolean;
/**
@@ -41,9 +42,11 @@ export interface MarkdownProps extends TestableComponent {
* Set to `false` to disable this feature.
*/
linkTargetName?: false | string;
+ /**
+ * Configure the `HtmlContentBlock` component that is automatically used as wrapper for the parsed Markdown content.
+ */
+ htmlContentBlockProps?: Omit;
}
-/* @deprecated use `MarkdownProps` */
-export type MarkdownParserProps = MarkdownProps;
const configDefault = {
/*
@@ -104,6 +107,7 @@ export const Markdown = ({
allowedElements,
reHypePlugins,
linkTargetName = "_mdref",
+ htmlContentBlockProps,
...otherProps
}: MarkdownProps) => {
const configHtml = allowHtml
@@ -136,15 +140,17 @@ export const Markdown = ({
: undefined,
components: {
code(props: any) {
- const { children, className, node, ...rest } = props;
+ const { children, className, node, inline, ...rest } = props;
const match = /language-(\w+)/.exec(className || "");
return match ? (
) : (
@@ -162,9 +168,15 @@ export const Markdown = ({
// @ts-ignore because against the lib spec it does not allow a function for linkTarget.
const markdownDisplay = ;
- return inheritBlock ? (
+ return inheritBlock && !(otherProps["data-test-id"] || htmlContentBlockProps) ? (
markdownDisplay
) : (
- {markdownDisplay}
+
+ {markdownDisplay}
+
);
};
diff --git a/src/cmem/markdown/highlightSearchWords.test.ts b/src/cmem/markdown/highlightSearchWords.test.ts
index 7bbb0c64..a954ed51 100644
--- a/src/cmem/markdown/highlightSearchWords.test.ts
+++ b/src/cmem/markdown/highlightSearchWords.test.ts
@@ -1,12 +1,12 @@
import { Element, Parent, Root, Text } from "hast";
import { VFile } from "vfile";
-import highlightSearchWordsPluginFactory from "./highlightSearchWords";
+import { markdownUtils } from "../../../index";
describe("Highlight search words reHype plugin", () => {
it("should highlight search words", () => {
const searchQuery = "abc xyz";
- const highlightSearchWordsPlugin = highlightSearchWordsPluginFactory(searchQuery);
+ const highlightSearchWordsPlugin = markdownUtils.highlightSearchWordsPluginFactory(searchQuery);
const highlightSearchWordTransformer = highlightSearchWordsPlugin();
const textNode = (text: string): Text => ({ type: "text", value: text });
const markNode = (text: string): Element => ({ type: "element", tagName: "mark", children: [textNode(text)] });
@@ -22,6 +22,7 @@ describe("Highlight search words reHype plugin", () => {
],
},
new VFile(),
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
() => {}
);
const rootChildren = (result as Root).children;
diff --git a/src/cmem/markdown/highlightSearchWords.ts b/src/cmem/markdown/highlightSearchWords.ts
index 2f04bb07..0109cb58 100644
--- a/src/cmem/markdown/highlightSearchWords.ts
+++ b/src/cmem/markdown/highlightSearchWords.ts
@@ -4,7 +4,10 @@ import { Node } from "unist";
import { highlighterUtils } from "../../components/Typography/Highlighter";
-const highlightSearchWordsPluginFactoryFn = (searchQuery: string | undefined) => {
+/**
+ * Creates a react-markdown reHype plugin that marks text based on a multi-word search query.
+ */
+const highlightSearchWordsPluginFactory = (searchQuery: string | undefined) => {
const searchStringParts = searchQuery ? highlighterUtils.extractSearchWords(searchQuery) : [];
const multiWordRegex = highlighterUtils.createMultiWordRegex(searchStringParts);
const createTextNode = (text: string): Text => ({ type: "text", value: text });
@@ -65,14 +68,6 @@ const highlightSearchWordsPluginFactoryFn = (searchQuery: string | undefined) =>
};
};
-/**
- * Creates a react-markdown reHype plugin that marks text based on a multi-word search query.
- * @deprecated moved to `markdownUtils.highlightSearchWordsPluginFactory`
- */
-const highlightSearchWordsPluginFactory = highlightSearchWordsPluginFactoryFn;
-
-export default highlightSearchWordsPluginFactory;
-
export const markdownUtils = {
- highlightSearchWordsPluginFactory: highlightSearchWordsPluginFactoryFn,
+ highlightSearchWordsPluginFactory,
};
diff --git a/src/cmem/markdown/markdown.scss b/src/cmem/markdown/markdown.scss
index 61a87db6..5b390d1e 100644
--- a/src/cmem/markdown/markdown.scss
+++ b/src/cmem/markdown/markdown.scss
@@ -47,13 +47,16 @@
.#{$eccgui}-typography__contentblock {
a[href=""] {
+ color: currentcolor;
+ pointer-events: none;
+ cursor: text;
+ }
+
+ a[href=""]:not(#{$eccgui-selector-text-spot-highlight}) {
font-size: $eccgui-size-typo-caption;
line-height: $eccgui-size-typo-caption-lineheight;
- color: currentcolor;
text-decoration: none;
vertical-align: super;
- pointer-events: none;
- cursor: text;
&::before {
content: "[";
diff --git a/src/cmem/markdown/markdown.utils.ts b/src/cmem/markdown/markdown.utils.ts
new file mode 100644
index 00000000..30fb9474
--- /dev/null
+++ b/src/cmem/markdown/markdown.utils.ts
@@ -0,0 +1,18 @@
+/** Extracts the values of all named anchors used in the Markdown string, i.e. of the form . */
+const extractNamedAnchors = (markdown: string): string[] => {
+ const regex = new RegExp('[^<]*', "g");
+ const namedAnchors: string[] = [];
+
+ let results = regex.exec(markdown);
+ while (results !== null) {
+ namedAnchors.push(results[1]);
+ results = regex.exec(markdown);
+ }
+ return namedAnchors;
+};
+
+const utils = {
+ extractNamedAnchors,
+};
+
+export default utils;
diff --git a/src/cmem/markdown/markdownutils.test.ts b/src/cmem/markdown/markdownutils.test.ts
new file mode 100644
index 00000000..382797c6
--- /dev/null
+++ b/src/cmem/markdown/markdownutils.test.ts
@@ -0,0 +1,17 @@
+import utils from "./markdown.utils";
+
+describe("Markdown utils", () => {
+ it("should extract named anchors from the Markdown", () => {
+ const namedAnchors = utils.extractNamedAnchors(
+ '# Header\n\nsome text\n\n## point 1\n\n## point 2'
+ );
+ expect(namedAnchors).toStrictEqual(["anchor1", "anchor2"]);
+ });
+
+ it("should not extract named anchors from the Markdown that are not following the expected format", () => {
+ const namedAnchors = utils.extractNamedAnchors(
+ '# link text \n\n## point 2'
+ );
+ expect(namedAnchors).toStrictEqual([]);
+ });
+});
diff --git a/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx b/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx
index 199f4daf..3311a6a6 100644
--- a/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx
+++ b/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx
@@ -105,7 +105,7 @@ export const StickyNoteModal: React.FC = React.memo(
,
]}
{...simpleDialogProps}
- data-test-id={(simpleDialogProps ?? {})["data-test-id"] ?? "sticky-note-modal"} // @deprecated we remove this automatically set testid with the next major release
+ data-test-id={(simpleDialogProps ?? {})["data-test-id"] ?? "sticky-note-modal"} // @deprecated (v25) we remove this automatically set testid
>
) => {
+export const StickyNoteNode = memo((node: NodeDefaultProps) => {
const { data, ...otherNodeProps } = node;
data.minimalShape = data.minimalShape ?? "none";
diff --git a/src/common/index.ts b/src/common/index.ts
index b3ec3876..ed25944e 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -14,6 +14,3 @@ export const utils = {
setGlobalVar,
getScrollParent,
};
-
-// @deprecated use `utils`
-export const Utilities = utils;
diff --git a/src/components/Accordion/Accordion.tsx b/src/components/Accordion/Accordion.tsx
index dfdfdf00..7536a293 100644
--- a/src/components/Accordion/Accordion.tsx
+++ b/src/components/Accordion/Accordion.tsx
@@ -1,11 +1,12 @@
-import React from "react";
-import { Accordion as CarbonAccordion, AccordionProps as CarbonAccordionProps } from "carbon-components-react";
+import React, { ReactNode } from "react";
+import { Accordion as CarbonAccordion, AccordionProps as CarbonAccordionProps } from "@carbon/react";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
import { AccordionItemProps } from "./AccordionItem";
-export interface AccordionProps extends Omit {
+export interface AccordionProps extends Omit {
+ children?: ReactNode;
/**
* Additional CSS classes.
*/
@@ -18,26 +19,14 @@ export interface AccordionProps extends Omit {
const headerWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.header;
@@ -58,7 +47,6 @@ export const Accordion = ({
(className ? ` ${className}` : "")
}
align={align}
- size={carbonAccordionSizeMapping[size]}
{...otherProps}
>
{children}
diff --git a/src/components/Accordion/AccordionItem.tsx b/src/components/Accordion/AccordionItem.tsx
index 5b9c0193..1c3b18a1 100644
--- a/src/components/Accordion/AccordionItem.tsx
+++ b/src/components/Accordion/AccordionItem.tsx
@@ -1,15 +1,16 @@
import React from "react";
-import {
- AccordionItem as CarbonAccordionItem,
- AccordionItemProps as CarbonAccordionItemProps,
-} from "carbon-components-react";
+import { AccordionItem as CarbonAccordionItem } from "@carbon/react";
+// import { AccordionItemProps as CarbonAccordionItemProps } from "@carbon/react/es/components/Accordion/AccordionItem"; // TODO: check later again, currently interface is not exported
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
type sizeOptions = "none" | "small" | "medium" | "large";
+// workaround to get type/interface
+type CarbonAccordionItemProps = React.ComponentProps;
export interface AccordionItemProps
- extends Omit {
+ extends Omit,
+ Omit, "title"> {
/**
* additional user class name
*/
@@ -31,11 +32,6 @@ export interface AccordionItemProps
* Defines how much space is used for the separation between the accordion item and the next one.
*/
separationSize?: sizeOptions;
- /**
- * minimize white space and paddings
- * @deprecated Use `whitespaceSize="none"` on `Accordion` or `AccordionItem` instead.
- */
- condensed?: boolean;
/**
* do not use borders as visible separations on accordion item
*/
@@ -54,7 +50,6 @@ export const AccordionItem = ({
elevated = false,
whitespaceSize = "medium",
separationSize = "none",
- condensed = false,
noBorder = false,
...otherProps
}: AccordionItemProps) => {
@@ -74,7 +69,6 @@ export const AccordionItem = ({
? ` ${eccgui}-accordion__item--contentspace-${contentWhitespaceSize}`
: "") +
(separationSize !== "none" ? ` ${eccgui}-accordion__item--separationspace-${separationSize}` : "") +
- (condensed ? ` ${eccgui}-accordion__item--condensed` : "") +
(noBorder ? ` ${eccgui}-accordion__item--noborder` : "")
}
title={label}
diff --git a/src/components/Accordion/accordion.scss b/src/components/Accordion/accordion.scss
index 578ae93d..7e399ffc 100644
--- a/src/components/Accordion/accordion.scss
+++ b/src/components/Accordion/accordion.scss
@@ -1,6 +1,6 @@
// lib import
@use "sass:color";
-@use "~@carbon/styles/scss/components/accordion/accordion";
+@use "~@carbon/react/scss/components/accordion/accordion";
@include accordion.accordion;
// own vars
@@ -22,12 +22,10 @@ $eccgui-size-accordion-separation: $eccgui-size-block-whitespace * 0.5 !default;
--#{$eccgui}-accordion-content-whitespace: #{$eccgui-size-accordion-content-basespace};
--#{$eccgui}-accordion-separation: 0;
}
-.#{$eccgui}-accordion__item--condensed,
.#{$eccgui}-accordion__container--global-headerspace-none,
.#{$eccgui}-accordion__item--headerspace-none {
--#{$eccgui}-accordion-header-height: 0;
}
-.#{$eccgui}-accordion__item--condensed,
.#{$eccgui}-accordion__container--global-contentspace-none,
.#{$eccgui}-accordion__item--contentspace-none {
--#{$eccgui}-accordion-content-whitespace: #{$eccgui-size-block-whitespace * 0.25};
@@ -77,11 +75,21 @@ $eccgui-size-accordion-separation: $eccgui-size-block-whitespace * 0.5 !default;
}
}
+.#{$prefix}--accordion__wrapper {
+ .#{$prefix}--accordion__item--active > & {
+ padding-block: 0;
+ }
+}
+
.#{$prefix}--accordion__heading {
align-items: center;
min-height: var(--#{$eccgui}-accordion-header-height, mini-units(5));
color: inherit;
+ .#{$prefix}--accordion--end & {
+ padding-right: 0;
+ }
+
.#{$prefix}--accordion__arrow {
margin: 0 $eccgui-size-block-whitespace * 0.5 0 0;
@@ -90,7 +98,6 @@ $eccgui-size-accordion-separation: $eccgui-size-block-whitespace * 0.5 !default;
}
}
- .#{$eccgui}-accordion__item--condensed &,
.#{$eccgui}-accordion__container--global-contentspace-none &,
.#{$eccgui}-accordion__item--contentspace-none & {
.#{$prefix}--accordion__arrow {
@@ -110,6 +117,7 @@ $eccgui-size-accordion-separation: $eccgui-size-block-whitespace * 0.5 !default;
.#{$prefix}--accordion__title {
min-width: 0; // flex layout fix
+ padding-left: 0;
margin: 0 0 0 $eccgui-size-block-whitespace;
font-size: inherit;
line-height: inherit;
@@ -144,14 +152,12 @@ $eccgui-size-accordion-separation: $eccgui-size-block-whitespace * 0.5 !default;
margin: 0;
}
- .#{$eccgui}-accordion__item--condensed &,
.#{$eccgui}-accordion__container--global-contentspace-none &,
.#{$eccgui}-accordion__item--contentspace-none & {
padding-right: 0;
padding-left: 0;
}
- .#{$eccgui}-accordion__item--condensed:not(.#{$eccgui}-accordion__item--fullwidth) &,
.#{$prefix}--accordion--start.#{$eccgui}-accordion__container--global-contentspace-none
:not(.#{$eccgui}-accordion__item--fullwidth)
&,
diff --git a/src/components/Application/ApplicationContent.tsx b/src/components/Application/ApplicationContent.tsx
index 26f5b693..7a7869ba 100644
--- a/src/components/Application/ApplicationContent.tsx
+++ b/src/components/Application/ApplicationContent.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { Content as CarbonContent } from "carbon-components-react";
+import { Content as CarbonContent } from "@carbon/react";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
diff --git a/src/components/Application/ApplicationHeader.tsx b/src/components/Application/ApplicationHeader.tsx
index 5e4ded7e..dd29e9a5 100644
--- a/src/components/Application/ApplicationHeader.tsx
+++ b/src/components/Application/ApplicationHeader.tsx
@@ -1,9 +1,12 @@
import React from "react";
-import { Header as CarbonHeader, HeaderProps as CarbonHeaderProps } from "carbon-components-react";
+import { Header as CarbonHeader } from "@carbon/react";
+// import { HeaderProps as CarbonHeaderProps } from "@carbon/react/es/components/UIShell/Header"; // TODO: check later again, currently interface is not exported
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
-export type ApplicationHeaderProps = CarbonHeaderProps;
+// workaround to get type/interface
+type CarbonHeaderProps = React.ComponentProps;
+export interface ApplicationHeaderProps extends CarbonHeaderProps, React.HTMLAttributes {}
export const ApplicationHeader = ({
children = "",
diff --git a/src/components/Application/ApplicationSidebarNavigation.tsx b/src/components/Application/ApplicationSidebarNavigation.tsx
index fd84ef99..c4c5e977 100644
--- a/src/components/Application/ApplicationSidebarNavigation.tsx
+++ b/src/components/Application/ApplicationSidebarNavigation.tsx
@@ -1,10 +1,10 @@
import React from "react";
-import { SideNav as CarbonSideNav, SideNavProps as CarbonSideNavProps } from "carbon-components-react";
+import { SideNav as CarbonSideNav, SideNavProps as CarbonSideNavProps } from "@carbon/react";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
export interface ApplicationSidebarNavigationProps
- extends Omit,
+ extends Omit,
React.HTMLAttributes {}
export const ApplicationSidebarNavigation = ({
diff --git a/src/components/Application/ApplicationSidebarToggler.tsx b/src/components/Application/ApplicationSidebarToggler.tsx
index f02af50b..d043c2e1 100644
--- a/src/components/Application/ApplicationSidebarToggler.tsx
+++ b/src/components/Application/ApplicationSidebarToggler.tsx
@@ -2,7 +2,7 @@ import React from "react";
import {
HeaderMenuButton as CarbonHeaderMenuButton,
HeaderMenuButtonProps as CarbonHeaderMenuButtonProps,
-} from "carbon-components-react";
+} from "@carbon/react";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
diff --git a/src/components/Application/ApplicationTitle.tsx b/src/components/Application/ApplicationTitle.tsx
index f0bb7aba..edec4d05 100644
--- a/src/components/Application/ApplicationTitle.tsx
+++ b/src/components/Application/ApplicationTitle.tsx
@@ -1,27 +1,12 @@
import React from "react";
-import { HeaderName as CarbonHeaderName, HeaderNameProps as CarbonHeaderNameProps } from "carbon-components-react";
+import { HeaderName as CarbonHeaderName, HeaderNameProps as CarbonHeaderNameProps } from "@carbon/react";
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
type SvgDepiction = HTMLElement & SVGElement;
type ImgDepiction = HTMLElement & HTMLImageElement;
-export interface ApplicationTitleProps extends CarbonHeaderNameProps {
- // from CarbonHeaderNameProps
- /**
- addional class name
- */
- className?: string;
- /**
- prefix the application name by extra string, e.g. company name
- */
- prefix?: string;
- /**
- home link
- */
- href?: string;
-
- // our extensions
+export type ApplicationTitleProps = CarbonHeaderNameProps<"a"> & {
/**
application logo, ,