Skip to content

Commit

Permalink
Merge pull request #183 from eccenca/release/v23.8.0
Browse files Browse the repository at this point in the history
Release v23.8.0 into main branch
  • Loading branch information
haschek authored Aug 19, 2024
2 parents f145957 + 9535876 commit baeff29
Show file tree
Hide file tree
Showing 24 changed files with 484 additions and 118 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

## [Unreleased]

### Added

- `<ApplicationContainer />`:
- `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.
- `<ReactFlow />`
- `dropzoneFor` property can be used to mark react flow canvas as matching area to drop dragged elements.
- `<Accordion />`, `<AccordionItem />`
- `whitespaceSize` property to define how much whitespace is used on top and bottom inside the header and content of an accordion item.
- `separationSize` property defines how much space is used for the separation between an accordion item and the next one.
- class name prefixes are now available by variables with more readable names:
- BlueprintJS: `$prefix-blueprintjs` (current value is `bp5`)
- Carbon Design System: `$prefix-carbon` (current value is `cds`)
- eccenca GUI elements: `$prefix-eccgui` (current value is `eccgui`)

### Fixed

- `<ElapsedDateTimeDisplay />`
- negative values are not shown (e.g. in case server and browser clocks are apart)

### Changed

- `<TextArea />`
- improve visual alignment to `TextField` regarding whitespace and colors
- basic styles for Uppy widget were improved and moved to its own component folder

### Deprecated

- `<Accordion />`
- `size` property in favour of `whitespaceSize`
- `<AccordionItem />`
- `condensed` property in favour of `whitespaceSize="none"`

## [23.7.0] - 2024-06-26

### Added
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@eccenca/gui-elements",
"description": "GUI elements based on other libraries, usable in React application, written in Typescript.",
"version": "23.7.0",
"version": "23.8.0-rc.2",
"license": "Apache-2.0",
"homepage": "https://github.com/eccenca/gui-elements",
"bugs": "https://github.com/eccenca/gui-elements/issues",
Expand Down Expand Up @@ -166,7 +166,10 @@
"**/word-wrap": "^1.2.4",
"**/webpack-dev-middleware": "^6.1.2",
"**/braces": "^3.0.3",
"**/ws": "^8.17.1"
"**/ws": "^8.17.1",
"**/ejs": "^3.1.10",
"**/tar": "^6.2.1",
"**/express": "^4.19.2"
},
"husky": {
"hooks": {
Expand Down
27 changes: 0 additions & 27 deletions src/_shame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,6 @@
border: 0;
}

.uppy-DragDrop-container {
color: inherit;
background-color: $data-table-zebra-color;
// TODO: create own file upload elements

border-width: 1px;

//border-style: dotted;
border-radius: 3px;

.uppy-DragDrop-inner {
padding: 1rem;
line-height: inherit;
}

.uppy-DragDrop-arrow {
width: 2rem;
height: 2rem;
margin-bottom: 0.5rem;
}

.uppy-DragDrop-label {
margin-bottom: 0.5rem;
font-size: inherit;
}
}

/*
WORKAROUND: thinner scrollbars
*/
Expand Down
3 changes: 2 additions & 1 deletion src/cmem/DateTimeDisplay/ElapsedDateTimeDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export interface ElapsedDateTimeDisplayProps extends TestableComponent {

const dateTimeToElapsedTimeInMs = (dateTime: string | number) => {
const absoluteMs = typeof dateTime === "number" ? dateTime : new Date(dateTime).getTime();
return new Date().getTime() - absoluteMs;
const elapsed = new Date().getTime() - absoluteMs;
return elapsed < 0 ? 0 : elapsed;
};

/**
Expand Down
42 changes: 40 additions & 2 deletions src/cmem/react-flow/ReactFlow/ReactFlow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { default as ReactFlowOriginal, ReactFlowProps as ReactFlowOriginalProps } from "react-flow-renderer";

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

/**
* Types data transfers that can be dragged in and dropped on the canvas.
*/
dropzoneFor?: string[];

/** If defined the canvas scrolls on all drag operations (node, selection, edge connect)
* when the mouse pointer comes near the canvas borders or goes beyond them.
* The `id` property of the ReactFlow component must be set in order for this to work.
Expand All @@ -37,7 +43,37 @@ export interface ReactFlowProps extends ReactFlowOriginalProps {
* Corporate Memory tools.
*/
export const ReactFlow = React.forwardRef<HTMLDivElement, ReactFlowProps>(
({ configuration = "unspecified", scrollOnDrag, children, ...originalProps }, ref) => {
({ configuration = "unspecified", scrollOnDrag, dropzoneFor, children, className, ...originalProps }, outerRef) => {
const innerRef = React.useRef<HTMLDivElement>(null);
React.useImperativeHandle(outerRef, () => innerRef.current!, []);

React.useEffect(() => {
const reactflowContainer = innerRef?.current;

if (reactflowContainer && dropzoneFor) {
const addDragover = (event: DragEvent) => {
reactflowContainer.classList.add(`${eccgui}-graphviz__canvas--draghover`);
event.preventDefault();
};

const removeDragover = (event: DragEvent) => {
if (reactflowContainer === event.target) {
reactflowContainer.classList.remove(`${eccgui}-graphviz__canvas--draghover`);
}
};

reactflowContainer.addEventListener("dragover", addDragover);
reactflowContainer.addEventListener("dragleave", removeDragover);
reactflowContainer.addEventListener("drop", removeDragover);
return () => {
reactflowContainer.removeEventListener("dragover", addDragover);
reactflowContainer.removeEventListener("dragleave", removeDragover);
reactflowContainer.removeEventListener("drop", removeDragover);
};
}
return;
}, [innerRef, dropzoneFor]);

/** If the hot keys should be disabled. By default, they are always disabled. */
const { hotKeysDisabled } = React.useContext(ReactFlowHotkeyContext);

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

return (
<ReactFlowOriginal
ref={ref}
ref={innerRef}
className={`${eccgui}-graphviz__canvas` + className ? ` ${className}` : ""}
nodeTypes={configReactFlow[configuration].nodeTypes}
edgeTypes={configReactFlow[configuration].edgeTypes}
{...originalProps}
{...scrollOnDragFunctions}
data-dropzone-for={dropzoneFor ? dropzoneFor.join(" ") : undefined}
selectionKeyCode={hotKeysDisabled ? null : (selectionKeyCode as any)}
deleteKeyCode={hotKeysDisabled ? null : (deleteKeyCode as any)}
multiSelectionKeyCode={hotKeysDisabled ? null : (multiSelectionKeyCode as any)}
Expand Down
15 changes: 15 additions & 0 deletions src/cmem/react-flow/_canvas.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.eccgui-graphviz__canvas--draghover {
body[data-monitor-dropzone~="application/reactflow"] &[data-dropzone-for~="application/reactflow"],
body[data-monitor-dropzone~="Files"] &[data-dropzone-for~="Files"] {
background-color: rgba($eccgui-color-accent, $eccgui-opacity-ghostly);
box-shadow: 0 0 $eccgui-size-block-whitespace $eccgui-color-accent inset;

& > * {
opacity: $eccgui-opacity-narrow;
}

.react-flow__node {
pointer-events: none !important;
}
}
}
1 change: 1 addition & 0 deletions src/cmem/react-flow/_index.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import "./configuration/colors";
@import "canvas";
@import "edges";
@import "handles";
@import "minimap";
Expand Down
29 changes: 28 additions & 1 deletion src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ import { Accordion as CarbonAccordion, AccordionProps as CarbonAccordionProps }

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

import { AccordionItemProps } from "./AccordionItem";

export interface AccordionProps extends Omit<CarbonAccordionProps, "className" | "size"> {
/**
* Additional CSS classes.
*/
className?: string;
/**
* Defines how much whitespace is used on top and bottom inside the header and content of an accordion item.
*/
whitespaceSize?: AccordionItemProps["whitespaceSize"];
/**
* Defines how much space is used for the separation between an accordion item and the next one.
*/
separationSize?: AccordionItemProps["separationSize"];
/**
* How much space is used for the header of the each of the accordion items.
* @deprecated Use ẁhitespaceSize` on `Accordion` or `AccordionItem` instead.
*/
size?: "small" | "medium" | "large";
}
Expand All @@ -24,12 +35,28 @@ export const Accordion = ({
children,
className = "",
align = "start",
whitespaceSize = "medium",
separationSize = "none",
size = "medium",
...otherProps
}: AccordionProps) => {
const headerWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.header;
const contentWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.content;
return (
<CarbonAccordion
className={`${eccgui}-accordion__container ` + className}
className={
`${eccgui}-accordion__container` +
(headerWhitespaceSize !== "medium"
? ` ${eccgui}-accordion__container--global-headerspace-${headerWhitespaceSize}`
: "") +
(contentWhitespaceSize !== "medium"
? ` ${eccgui}-accordion__container--global-contentspace-${contentWhitespaceSize}`
: "") +
(separationSize !== "none"
? ` ${eccgui}-accordion__container--global-separationspace-${separationSize}`
: "") +
(className ? ` ${className}` : "")
}
align={align}
size={carbonAccordionSizeMapping[size]}
{...otherProps}
Expand Down
23 changes: 23 additions & 0 deletions src/components/Accordion/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {

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

type sizeOptions = "none" | "small" | "medium" | "large";

export interface AccordionItemProps
extends Omit<CarbonAccordionItemProps, "title" | "iconDescription" | "renderExpando"> {
/**
Expand All @@ -20,8 +22,18 @@ export interface AccordionItemProps
* use full available width for content
*/
fullWidth?: boolean;
/**
* Defines how much whitespace is used on top and bottom inside the header and content of an accordion item.
* Seeting on `AccordionItem` overwrites the global setting on `Accordion`.
*/
whitespaceSize?: sizeOptions | { header: sizeOptions; content: sizeOptions };
/**
* 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;
/**
Expand All @@ -40,17 +52,28 @@ export const AccordionItem = ({
className = "",
fullWidth = false,
elevated = false,
whitespaceSize = "medium",
separationSize = "none",
condensed = false,
noBorder = false,
...otherProps
}: AccordionItemProps) => {
const headerWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.header;
const contentWhitespaceSize = typeof whitespaceSize === "string" ? whitespaceSize : whitespaceSize.content;
return (
<CarbonAccordionItem
className={
`${eccgui}-accordion__item` +
(className ? " " + className : "") +
(fullWidth ? ` ${eccgui}-accordion__item--fullwidth` : "") +
(elevated ? ` ${eccgui}-accordion__item--elevated` : "") +
(headerWhitespaceSize !== "medium"
? ` ${eccgui}-accordion__item--headerspace-${headerWhitespaceSize}`
: "") +
(contentWhitespaceSize !== "medium"
? ` ${eccgui}-accordion__item--contentspace-${contentWhitespaceSize}`
: "") +
(separationSize !== "none" ? ` ${eccgui}-accordion__item--separationspace-${separationSize}` : "") +
(condensed ? ` ${eccgui}-accordion__item--condensed` : "") +
(noBorder ? ` ${eccgui}-accordion__item--noborder` : "")
}
Expand Down
16 changes: 12 additions & 4 deletions src/components/Accordion/Stories/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { Meta, StoryFn } from "@storybook/react";

import { Accordion, AccordionItem } from "../../../../index";
import { Default as AccordionStoryItem } from "../Stories/AccordionItem.stories";
Expand All @@ -13,14 +13,22 @@ export default {
control: "none",
description: "Elements to include into the Accordion component",
},
whitespaceSize: {
control: "select",
options: ["none", "small", "medium", "large"],
},
separationSize: {
control: "select",
options: ["none", "small", "medium", "large"],
},
},
} as ComponentMeta<typeof Accordion>;
} as Meta<typeof Accordion>;

const TemplateIcons: ComponentStory<typeof Accordion> = (args) => <Accordion {...args} />;
const TemplateIcons: StoryFn<typeof Accordion> = (args) => <Accordion {...args} />;
export const Default = TemplateIcons.bind({});
Default.args = {
children: [
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 1" />,
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 1" fullWidth />,
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 2 (elevated)" elevated />,
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 3 (initially opened)" open />,
<AccordionItem {...AccordionStoryItem.args} label="Accordion item 4 (disabled)" disabled />,
Expand Down
14 changes: 11 additions & 3 deletions src/components/Accordion/Stories/AccordionItem.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 { Accordion, AccordionItem, HtmlContentBlock } from "../../../../index";

Expand All @@ -12,10 +12,18 @@ export default {
control: "none",
description: "content of accordion item",
},
whitespaceSize: {
control: "select",
options: ["none", "small", "medium", "large"],
},
separationSize: {
control: "select",
options: ["none", "small", "medium", "large"],
},
},
} as ComponentMeta<typeof AccordionItem>;
} as Meta<typeof AccordionItem>;

const Template: ComponentStory<typeof AccordionItem> = (args) => (
const Template: StoryFn<typeof AccordionItem> = (args) => (
<Accordion>
<AccordionItem {...args} />
</Accordion>
Expand Down
Loading

0 comments on commit baeff29

Please sign in to comment.