Skip to content

Commit baeff29

Browse files
authored
Merge pull request #183 from eccenca/release/v23.8.0
Release v23.8.0 into main branch
2 parents f145957 + 9535876 commit baeff29

24 files changed

Lines changed: 484 additions & 118 deletions

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,38 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- `<ApplicationContainer />`:
12+
- `monitorDropzonesFor` property can be used to monitor application wide dropzones for dragged elements via data attributes attached to body element containing the data transfer type of drag over events.
13+
- `<ReactFlow />`
14+
- `dropzoneFor` property can be used to mark react flow canvas as matching area to drop dragged elements.
15+
- `<Accordion />`, `<AccordionItem />`
16+
- `whitespaceSize` property to define how much whitespace is used on top and bottom inside the header and content of an accordion item.
17+
- `separationSize` property defines how much space is used for the separation between an accordion item and the next one.
18+
- class name prefixes are now available by variables with more readable names:
19+
- BlueprintJS: `$prefix-blueprintjs` (current value is `bp5`)
20+
- Carbon Design System: `$prefix-carbon` (current value is `cds`)
21+
- eccenca GUI elements: `$prefix-eccgui` (current value is `eccgui`)
22+
23+
### Fixed
24+
25+
- `<ElapsedDateTimeDisplay />`
26+
- negative values are not shown (e.g. in case server and browser clocks are apart)
27+
28+
### Changed
29+
30+
- `<TextArea />`
31+
- improve visual alignment to `TextField` regarding whitespace and colors
32+
- basic styles for Uppy widget were improved and moved to its own component folder
33+
34+
### Deprecated
35+
36+
- `<Accordion />`
37+
- `size` property in favour of `whitespaceSize`
38+
- `<AccordionItem />`
39+
- `condensed` property in favour of `whitespaceSize="none"`
40+
941
## [23.7.0] - 2024-06-26
1042

1143
### Added

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@eccenca/gui-elements",
33
"description": "GUI elements based on other libraries, usable in React application, written in Typescript.",
4-
"version": "23.7.0",
4+
"version": "23.8.0-rc.2",
55
"license": "Apache-2.0",
66
"homepage": "https://github.com/eccenca/gui-elements",
77
"bugs": "https://github.com/eccenca/gui-elements/issues",
@@ -166,7 +166,10 @@
166166
"**/word-wrap": "^1.2.4",
167167
"**/webpack-dev-middleware": "^6.1.2",
168168
"**/braces": "^3.0.3",
169-
"**/ws": "^8.17.1"
169+
"**/ws": "^8.17.1",
170+
"**/ejs": "^3.1.10",
171+
"**/tar": "^6.2.1",
172+
"**/express": "^4.19.2"
170173
},
171174
"husky": {
172175
"hooks": {

src/_shame.scss

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,6 @@
1919
border: 0;
2020
}
2121

22-
.uppy-DragDrop-container {
23-
color: inherit;
24-
background-color: $data-table-zebra-color;
25-
// TODO: create own file upload elements
26-
27-
border-width: 1px;
28-
29-
//border-style: dotted;
30-
border-radius: 3px;
31-
32-
.uppy-DragDrop-inner {
33-
padding: 1rem;
34-
line-height: inherit;
35-
}
36-
37-
.uppy-DragDrop-arrow {
38-
width: 2rem;
39-
height: 2rem;
40-
margin-bottom: 0.5rem;
41-
}
42-
43-
.uppy-DragDrop-label {
44-
margin-bottom: 0.5rem;
45-
font-size: inherit;
46-
}
47-
}
48-
4922
/*
5023
WORKAROUND: thinner scrollbars
5124
*/

src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export interface ElapsedDateTimeDisplayProps extends TestableComponent {
2222

2323
const dateTimeToElapsedTimeInMs = (dateTime: string | number) => {
2424
const absoluteMs = typeof dateTime === "number" ? dateTime : new Date(dateTime).getTime();
25-
return new Date().getTime() - absoluteMs;
25+
const elapsed = new Date().getTime() - absoluteMs;
26+
return elapsed < 0 ? 0 : elapsed;
2627
};
2728

2829
/**

src/cmem/react-flow/ReactFlow/ReactFlow.tsx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import { default as ReactFlowOriginal, ReactFlowProps as ReactFlowOriginalProps } from "react-flow-renderer";
33

4+
import { CLASSPREFIX as eccgui } from "../../../configuration/constants";
45
import { ReactFlowMarkers } from "../../../extensions/react-flow/markers/ReactFlowMarkers";
56
import { ReactFlowHotkeyContext } from "../extensions/ReactFlowHotkeyContext";
67
import { useReactFlowScrollOnDrag } from "../extensions/scrollOnDragHook";
@@ -16,6 +17,11 @@ export interface ReactFlowProps extends ReactFlowOriginalProps {
1617
*/
1718
configuration?: "unspecified" | "graph" | "workflow" | "linking";
1819

20+
/**
21+
* Types data transfers that can be dragged in and dropped on the canvas.
22+
*/
23+
dropzoneFor?: string[];
24+
1925
/** If defined the canvas scrolls on all drag operations (node, selection, edge connect)
2026
* when the mouse pointer comes near the canvas borders or goes beyond them.
2127
* The `id` property of the ReactFlow component must be set in order for this to work.
@@ -37,7 +43,37 @@ export interface ReactFlowProps extends ReactFlowOriginalProps {
3743
* Corporate Memory tools.
3844
*/
3945
export const ReactFlow = React.forwardRef<HTMLDivElement, ReactFlowProps>(
40-
({ configuration = "unspecified", scrollOnDrag, children, ...originalProps }, ref) => {
46+
({ configuration = "unspecified", scrollOnDrag, dropzoneFor, children, className, ...originalProps }, outerRef) => {
47+
const innerRef = React.useRef<HTMLDivElement>(null);
48+
React.useImperativeHandle(outerRef, () => innerRef.current!, []);
49+
50+
React.useEffect(() => {
51+
const reactflowContainer = innerRef?.current;
52+
53+
if (reactflowContainer && dropzoneFor) {
54+
const addDragover = (event: DragEvent) => {
55+
reactflowContainer.classList.add(`${eccgui}-graphviz__canvas--draghover`);
56+
event.preventDefault();
57+
};
58+
59+
const removeDragover = (event: DragEvent) => {
60+
if (reactflowContainer === event.target) {
61+
reactflowContainer.classList.remove(`${eccgui}-graphviz__canvas--draghover`);
62+
}
63+
};
64+
65+
reactflowContainer.addEventListener("dragover", addDragover);
66+
reactflowContainer.addEventListener("dragleave", removeDragover);
67+
reactflowContainer.addEventListener("drop", removeDragover);
68+
return () => {
69+
reactflowContainer.removeEventListener("dragover", addDragover);
70+
reactflowContainer.removeEventListener("dragleave", removeDragover);
71+
reactflowContainer.removeEventListener("drop", removeDragover);
72+
};
73+
}
74+
return;
75+
}, [innerRef, dropzoneFor]);
76+
4177
/** If the hot keys should be disabled. By default, they are always disabled. */
4278
const { hotKeysDisabled } = React.useContext(ReactFlowHotkeyContext);
4379

@@ -57,11 +93,13 @@ export const ReactFlow = React.forwardRef<HTMLDivElement, ReactFlowProps>(
5793

5894
return (
5995
<ReactFlowOriginal
60-
ref={ref}
96+
ref={innerRef}
97+
className={`${eccgui}-graphviz__canvas` + className ? ` ${className}` : ""}
6198
nodeTypes={configReactFlow[configuration].nodeTypes}
6299
edgeTypes={configReactFlow[configuration].edgeTypes}
63100
{...originalProps}
64101
{...scrollOnDragFunctions}
102+
data-dropzone-for={dropzoneFor ? dropzoneFor.join(" ") : undefined}
65103
selectionKeyCode={hotKeysDisabled ? null : (selectionKeyCode as any)}
66104
deleteKeyCode={hotKeysDisabled ? null : (deleteKeyCode as any)}
67105
multiSelectionKeyCode={hotKeysDisabled ? null : (multiSelectionKeyCode as any)}

src/cmem/react-flow/_canvas.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.eccgui-graphviz__canvas--draghover {
2+
body[data-monitor-dropzone~="application/reactflow"] &[data-dropzone-for~="application/reactflow"],
3+
body[data-monitor-dropzone~="Files"] &[data-dropzone-for~="Files"] {
4+
background-color: rgba($eccgui-color-accent, $eccgui-opacity-ghostly);
5+
box-shadow: 0 0 $eccgui-size-block-whitespace $eccgui-color-accent inset;
6+
7+
& > * {
8+
opacity: $eccgui-opacity-narrow;
9+
}
10+
11+
.react-flow__node {
12+
pointer-events: none !important;
13+
}
14+
}
15+
}

src/cmem/react-flow/_index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@import "./configuration/colors";
2+
@import "canvas";
23
@import "edges";
34
@import "handles";
45
@import "minimap";

src/components/Accordion/Accordion.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@ import { Accordion as CarbonAccordion, AccordionProps as CarbonAccordionProps }
33

44
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
55

6+
import { AccordionItemProps } from "./AccordionItem";
7+
68
export interface AccordionProps extends Omit<CarbonAccordionProps, "className" | "size"> {
79
/**
810
* Additional CSS classes.
911
*/
1012
className?: string;
13+
/**
14+
* Defines how much whitespace is used on top and bottom inside the header and content of an accordion item.
15+
*/
16+
whitespaceSize?: AccordionItemProps["whitespaceSize"];
17+
/**
18+
* Defines how much space is used for the separation between an accordion item and the next one.
19+
*/
20+
separationSize?: AccordionItemProps["separationSize"];
1121
/**
1222
* How much space is used for the header of the each of the accordion items.
23+
* @deprecated Use ẁhitespaceSize` on `Accordion` or `AccordionItem` instead.
1324
*/
1425
size?: "small" | "medium" | "large";
1526
}
@@ -24,12 +35,28 @@ export const Accordion = ({
2435
children,
2536
className = "",
2637
align = "start",
38+
whitespaceSize = "medium",
39+
separationSize = "none",
2740
size = "medium",
2841
...otherProps
2942
}: AccordionProps) => {
43+
const headerWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.header;
44+
const contentWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.content;
3045
return (
3146
<CarbonAccordion
32-
className={`${eccgui}-accordion__container ` + className}
47+
className={
48+
`${eccgui}-accordion__container` +
49+
(headerWhitespaceSize !== "medium"
50+
? ` ${eccgui}-accordion__container--global-headerspace-${headerWhitespaceSize}`
51+
: "") +
52+
(contentWhitespaceSize !== "medium"
53+
? ` ${eccgui}-accordion__container--global-contentspace-${contentWhitespaceSize}`
54+
: "") +
55+
(separationSize !== "none"
56+
? ` ${eccgui}-accordion__container--global-separationspace-${separationSize}`
57+
: "") +
58+
(className ? ` ${className}` : "")
59+
}
3360
align={align}
3461
size={carbonAccordionSizeMapping[size]}
3562
{...otherProps}

src/components/Accordion/AccordionItem.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66

77
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
88

9+
type sizeOptions = "none" | "small" | "medium" | "large";
10+
911
export interface AccordionItemProps
1012
extends Omit<CarbonAccordionItemProps, "title" | "iconDescription" | "renderExpando"> {
1113
/**
@@ -20,8 +22,18 @@ export interface AccordionItemProps
2022
* use full available width for content
2123
*/
2224
fullWidth?: boolean;
25+
/**
26+
* Defines how much whitespace is used on top and bottom inside the header and content of an accordion item.
27+
* Seeting on `AccordionItem` overwrites the global setting on `Accordion`.
28+
*/
29+
whitespaceSize?: sizeOptions | { header: sizeOptions; content: sizeOptions };
30+
/**
31+
* Defines how much space is used for the separation between the accordion item and the next one.
32+
*/
33+
separationSize?: sizeOptions;
2334
/**
2435
* minimize white space and paddings
36+
* @deprecated Use `whitespaceSize="none"` on `Accordion` or `AccordionItem` instead.
2537
*/
2638
condensed?: boolean;
2739
/**
@@ -40,17 +52,28 @@ export const AccordionItem = ({
4052
className = "",
4153
fullWidth = false,
4254
elevated = false,
55+
whitespaceSize = "medium",
56+
separationSize = "none",
4357
condensed = false,
4458
noBorder = false,
4559
...otherProps
4660
}: AccordionItemProps) => {
61+
const headerWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.header;
62+
const contentWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.content;
4763
return (
4864
<CarbonAccordionItem
4965
className={
5066
`${eccgui}-accordion__item` +
5167
(className ? " " + className : "") +
5268
(fullWidth ? ` ${eccgui}-accordion__item--fullwidth` : "") +
5369
(elevated ? ` ${eccgui}-accordion__item--elevated` : "") +
70+
(headerWhitespaceSize !== "medium"
71+
? ` ${eccgui}-accordion__item--headerspace-${headerWhitespaceSize}`
72+
: "") +
73+
(contentWhitespaceSize !== "medium"
74+
? ` ${eccgui}-accordion__item--contentspace-${contentWhitespaceSize}`
75+
: "") +
76+
(separationSize !== "none" ? ` ${eccgui}-accordion__item--separationspace-${separationSize}` : "") +
5477
(condensed ? ` ${eccgui}-accordion__item--condensed` : "") +
5578
(noBorder ? ` ${eccgui}-accordion__item--noborder` : "")
5679
}

src/components/Accordion/Stories/Accordion.stories.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from "react";
2-
import { ComponentMeta, ComponentStory } from "@storybook/react";
2+
import { Meta, StoryFn } from "@storybook/react";
33

44
import { Accordion, AccordionItem } from "../../../../index";
55
import { Default as AccordionStoryItem } from "../Stories/AccordionItem.stories";
@@ -13,14 +13,22 @@ export default {
1313
control: "none",
1414
description: "Elements to include into the Accordion component",
1515
},
16+
whitespaceSize: {
17+
control: "select",
18+
options: ["none", "small", "medium", "large"],
19+
},
20+
separationSize: {
21+
control: "select",
22+
options: ["none", "small", "medium", "large"],
23+
},
1624
},
17-
} as ComponentMeta<typeof Accordion>;
25+
} as Meta<typeof Accordion>;
1826

19-
const TemplateIcons: ComponentStory<typeof Accordion> = (args) => <Accordion {...args} />;
27+
const TemplateIcons: StoryFn<typeof Accordion> = (args) => <Accordion {...args} />;
2028
export const Default = TemplateIcons.bind({});
2129
Default.args = {
2230
children: [
23-
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 1" />,
31+
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 1" fullWidth />,
2432
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 2 (elevated)" elevated />,
2533
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 3 (initially opened)" open />,
2634
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 4 (disabled)" disabled />,

0 commit comments

Comments
 (0)