@eccenca/gui-elements 25.1.0-rc.1 → 25.1.0-rc.3

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 (94) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +1 -1
  3. package/dist/cjs/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  4. package/dist/cjs/common/index.js +1 -0
  5. package/dist/cjs/common/index.js.map +1 -1
  6. package/dist/cjs/common/utils/CssCustomProperties.js.map +1 -1
  7. package/dist/cjs/common/utils/colorHash.js +26 -12
  8. package/dist/cjs/common/utils/colorHash.js.map +1 -1
  9. package/dist/cjs/components/ColorField/ColorField.js +114 -0
  10. package/dist/cjs/components/ColorField/ColorField.js.map +1 -0
  11. package/dist/cjs/components/RadioButton/RadioButton.js +5 -2
  12. package/dist/cjs/components/RadioButton/RadioButton.js.map +1 -1
  13. package/dist/cjs/components/TextField/useTextValidation.js +17 -8
  14. package/dist/cjs/components/TextField/useTextValidation.js.map +1 -1
  15. package/dist/cjs/components/Tooltip/Tooltip.js +11 -7
  16. package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
  17. package/dist/cjs/components/index.js +1 -0
  18. package/dist/cjs/components/index.js.map +1 -1
  19. package/dist/cjs/extensions/codemirror/CodeMirror.js +40 -14
  20. package/dist/cjs/extensions/codemirror/CodeMirror.js.map +1 -1
  21. package/dist/cjs/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.js +23 -0
  22. package/dist/cjs/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.js.map +1 -0
  23. package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js +5 -2
  24. package/dist/cjs/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -1
  25. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js +1 -1
  26. package/dist/esm/cmem/react-flow/StickyNoteModal/StickyNoteModal.js.map +1 -1
  27. package/dist/esm/common/index.js +2 -1
  28. package/dist/esm/common/index.js.map +1 -1
  29. package/dist/esm/common/utils/CssCustomProperties.js.map +1 -1
  30. package/dist/esm/common/utils/colorHash.js +26 -13
  31. package/dist/esm/common/utils/colorHash.js.map +1 -1
  32. package/dist/esm/components/ColorField/ColorField.js +140 -0
  33. package/dist/esm/components/ColorField/ColorField.js.map +1 -0
  34. package/dist/esm/components/RadioButton/RadioButton.js +6 -2
  35. package/dist/esm/components/RadioButton/RadioButton.js.map +1 -1
  36. package/dist/esm/components/TextField/useTextValidation.js +39 -8
  37. package/dist/esm/components/TextField/useTextValidation.js.map +1 -1
  38. package/dist/esm/components/Tooltip/Tooltip.js +11 -7
  39. package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
  40. package/dist/esm/components/index.js +1 -0
  41. package/dist/esm/components/index.js.map +1 -1
  42. package/dist/esm/extensions/codemirror/CodeMirror.js +42 -16
  43. package/dist/esm/extensions/codemirror/CodeMirror.js.map +1 -1
  44. package/dist/esm/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.js +47 -0
  45. package/dist/esm/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.js.map +1 -0
  46. package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js +16 -2
  47. package/dist/esm/extensions/codemirror/toolbars/markdown.toolbar.js.map +1 -1
  48. package/dist/types/common/index.d.ts +2 -1
  49. package/dist/types/common/utils/CssCustomProperties.d.ts +2 -2
  50. package/dist/types/common/utils/colorHash.d.ts +5 -4
  51. package/dist/types/components/ColorField/ColorField.d.ts +30 -0
  52. package/dist/types/components/RadioButton/RadioButton.d.ts +8 -2
  53. package/dist/types/components/index.d.ts +1 -0
  54. package/dist/types/extensions/codemirror/CodeMirror.d.ts +12 -9
  55. package/dist/types/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.d.ts +24 -0
  56. package/dist/types/extensions/codemirror/toolbars/markdown.toolbar.d.ts +2 -0
  57. package/package.json +1 -1
  58. package/src/_shame.scss +1 -35
  59. package/src/cmem/react-flow/StickyNoteModal/StickyNoteModal.tsx +1 -1
  60. package/src/common/index.ts +2 -1
  61. package/src/common/scss/_accessibility-defaults.scss +101 -0
  62. package/src/common/utils/CssCustomProperties.ts +5 -3
  63. package/src/common/utils/colorHash.ts +38 -20
  64. package/src/components/Application/_header.scss +21 -9
  65. package/src/components/Application/_sidebar.scss +6 -0
  66. package/src/components/Application/_toolbar.scss +3 -3
  67. package/src/components/AutoSuggestion/AutoSuggestion.scss +3 -1
  68. package/src/components/Checkbox/checkbox.scss +9 -1
  69. package/src/components/ColorField/ColorField.stories.tsx +72 -0
  70. package/src/components/ColorField/ColorField.test.tsx +101 -0
  71. package/src/components/ColorField/ColorField.tsx +200 -0
  72. package/src/components/ColorField/_colorfield.scss +67 -0
  73. package/src/components/Dialog/dialog.scss +8 -0
  74. package/src/components/Link/link.scss +5 -6
  75. package/src/components/MultiSuggestField/_multisuggestfield.scss +18 -0
  76. package/src/components/RadioButton/RadioButton.tsx +15 -3
  77. package/src/components/RadioButton/radiobutton.scss +18 -1
  78. package/src/components/TextField/stories/TextField.stories.tsx +23 -0
  79. package/src/components/TextField/tests/useTextValidation.test.tsx +83 -0
  80. package/src/components/TextField/textfield.scss +20 -0
  81. package/src/components/TextField/useTextValidation.ts +17 -8
  82. package/src/components/Tooltip/Tooltip.test.tsx +40 -5
  83. package/src/components/Tooltip/Tooltip.tsx +14 -10
  84. package/src/components/index.scss +1 -0
  85. package/src/components/index.ts +1 -0
  86. package/src/configuration/stories/customproperties.stories.tsx +4 -0
  87. package/src/extensions/codemirror/CodeMirror.stories.tsx +9 -4
  88. package/src/extensions/codemirror/CodeMirror.tsx +71 -26
  89. package/src/extensions/codemirror/_codemirror.scss +18 -28
  90. package/src/extensions/codemirror/tests/CodeEditor.test.tsx +138 -0
  91. package/src/extensions/codemirror/tests/EditorAppearanceConfigMenu.test.tsx +131 -0
  92. package/src/extensions/codemirror/toolbars/EditorAppearanceConfigMenu.tsx +59 -0
  93. package/src/extensions/codemirror/toolbars/markdown.toolbar.tsx +17 -3
  94. package/src/index.scss +1 -0
@@ -4,7 +4,15 @@ import { EditorView, Rect } from "@codemirror/view";
4
4
  import { IntentTypes } from "../../common/Intent";
5
5
  import { TestableComponent } from "../../components/interfaces";
6
6
  import { SupportedCodeEditorModes } from "./hooks/useCodemirrorModeExtension.hooks";
7
- export interface CodeEditorProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "translate" | "onChange" | "onKeyDown" | "onMouseDown" | "onScroll">, TestableComponent {
7
+ interface EditorAppearance {
8
+ /**
9
+ * If enabled the code editor won't show numbers before each line.
10
+ */
11
+ preventLineNumbers?: boolean;
12
+ /** Long lines are wrapped and displayed on multiple lines */
13
+ wrapLines?: boolean;
14
+ }
15
+ export interface CodeEditorProps extends EditorAppearance, Omit<React.HTMLAttributes<HTMLDivElement>, "translate" | "onChange" | "onKeyDown" | "onMouseDown" | "onScroll">, TestableComponent {
8
16
  setEditorView?: (editor: EditorView | undefined) => void;
9
17
  /**
10
18
  * `name` attribute of connected textarea element.
@@ -55,18 +63,12 @@ export interface CodeEditorProps extends Omit<React.HTMLAttributes<HTMLDivElemen
55
63
  * Default value used first when the editor is instanciated.
56
64
  */
57
65
  defaultValue?: string;
58
- /**
59
- * If enabled the code editor won't show numbers before each line.
60
- */
61
- preventLineNumbers?: boolean;
62
66
  /** Set read-only mode. Default: false */
63
67
  readOnly?: boolean;
64
68
  /** Optional height of the component */
65
69
  height?: number | string;
66
- /** Long lines are wrapped and displayed on multiple lines */
67
- wrapLines?: boolean;
68
70
  /**
69
- * Add properties to the `div` used as warpper element.
71
+ * Add properties to the `div` used as wrapper element.
70
72
  * @deprecated (v26) You can now use all properties directly on `CodeEditor`.
71
73
  */
72
74
  outerDivAttributes?: Omit<React.HTMLAttributes<HTMLDivElement>, "id" | "data-test-id" | "data-testid" | "translate" | "onChange" | "onKeyDown" | "onMouseDown" | "onScroll">;
@@ -137,6 +139,7 @@ export interface CodeEditorProps extends Omit<React.HTMLAttributes<HTMLDivElemen
137
139
  * Includes a code editor, currently we use CodeMirror library as base.
138
140
  */
139
141
  export declare const CodeEditor: {
140
- ({ className, onChange, onSelection, onMouseDown, onFocusChange, onKeyDown, onCursorChange, name, id, mode, preventLineNumbers, defaultValue, readOnly, shouldHaveMinimalSetup, wrapLines, onScroll, setEditorView, supportCodeFolding, shouldHighlightActiveLine, outerDivAttributes, tabIntentSize, tabIntentStyle, placeholder, additionalExtensions, tabForceSpaceForModes, enableTab, height, useLinting, autoFocus, disabled, intent, useToolbar, translate, ...otherCodeEditorProps }: CodeEditorProps): React.JSX.Element;
142
+ ({ className, onChange, onSelection, onMouseDown, onFocusChange, onKeyDown, onCursorChange, name, id, mode, preventLineNumbers, wrapLines, defaultValue, readOnly, shouldHaveMinimalSetup, onScroll, setEditorView, supportCodeFolding, shouldHighlightActiveLine, outerDivAttributes, tabIntentSize, tabIntentStyle, placeholder, additionalExtensions, tabForceSpaceForModes, enableTab, height, useLinting, autoFocus, disabled, intent, useToolbar, translate, ...otherCodeEditorProps }: CodeEditorProps): React.JSX.Element;
141
143
  supportedModes: ("html" | "markdown" | "python" | "sparql" | "turtle" | "xml" | "yaml" | "jinja2" | "json" | "ntriples" | "mathematica" | "sql" | "javascript")[];
142
144
  };
145
+ export {};
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { ContextMenuProps } from "../../../components";
3
+ export interface EditorAppearanceConfigMenuProps {
4
+ /** Object containing a `true`/`false` value for each property */
5
+ config: {
6
+ [s: string]: boolean;
7
+ };
8
+ /** Object containing `true` for each property that cannot be changed by user */
9
+ configLocked?: {
10
+ [s: string]: boolean | undefined;
11
+ };
12
+ /** Handler that returns a translation for each config property key */
13
+ configPropertyTranslate?: (key: string) => string | false;
14
+ /** Handler to update config after user changes */
15
+ setConfig: React.Dispatch<React.SetStateAction<{
16
+ [s: string]: boolean;
17
+ }>>;
18
+ /** Additional properties used for the included `ContextMenu` */
19
+ contextMenuProps?: ContextMenuProps;
20
+ }
21
+ /**
22
+ * Returns a simple context menu that provides switches to control the editor appearance.
23
+ */
24
+ export declare function EditorAppearanceConfigMenu({ config, configLocked, configPropertyTranslate, setConfig, contextMenuProps, }: EditorAppearanceConfigMenuProps): React.JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { EditorView } from "codemirror";
3
+ import { EditorAppearanceConfigMenu } from "./EditorAppearanceConfigMenu";
3
4
  interface MarkdownToolbarProps {
4
5
  view?: EditorView;
5
6
  togglePreviewStatus: () => void;
@@ -7,6 +8,7 @@ interface MarkdownToolbarProps {
7
8
  translate: (key: string) => string | false;
8
9
  disabled?: boolean;
9
10
  readonly?: boolean;
11
+ configMenu?: React.ReactElement<typeof EditorAppearanceConfigMenu>;
10
12
  }
11
13
  export declare const MarkdownToolbar: React.FC<MarkdownToolbarProps>;
12
14
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eccenca/gui-elements",
3
3
  "description": "GUI elements based on other libraries, usable in React application, written in Typescript.",
4
- "version": "25.1.0-rc.1",
4
+ "version": "25.1.0-rc.3",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/eccenca/gui-elements",
7
7
  "bugs": "https://github.com/eccenca/gui-elements/issues",
package/src/_shame.scss CHANGED
@@ -1,31 +1,13 @@
1
1
  // Add stuff to test fast and dirty.
2
2
  // This file should not contain any styles.
3
3
 
4
- .#{$prefix}--assistive-text,
5
- .#{$prefix}--visually-hidden {
6
- /*
7
- TODO: move to better place, originally from ~@carbon/styles/scss/css--helpers
8
- but we cannot use it directly because of other included rules there.
9
- */
10
- position: absolute;
11
- width: 1px;
12
- height: 1px;
13
- padding: 0;
14
- margin: -1px;
15
- overflow: hidden;
16
- clip: rect(0, 0, 0, 0);
17
- white-space: nowrap;
18
- visibility: inherit;
19
- border: 0;
20
- }
21
-
22
4
  /*
23
5
  WORKAROUND: thinner scrollbars
24
6
  */
25
7
 
26
8
  * {
27
- scrollbar-width: thin;
28
9
  scrollbar-color: #bbb transparent;
10
+ scrollbar-width: thin;
29
11
 
30
12
  &::-webkit-scrollbar {
31
13
  width: 0.25rem;
@@ -38,19 +20,3 @@
38
20
  border-radius: 0.125rem;
39
21
  }
40
22
  }
41
-
42
- /*
43
- CHANGE: default focus behaviour
44
- */
45
-
46
- :focus,
47
- input:focus-visible,
48
- textarea:focus-visible {
49
- outline: none;
50
- outline-offset: 0;
51
- }
52
-
53
- :focus-visible {
54
- outline: eccgui-color-rgba($eccgui-color-accent, $eccgui-opacity-muted) solid 2px;
55
- outline-offset: 1px;
56
- }
@@ -130,7 +130,7 @@ export const StickyNoteModal: React.FC<StickyNoteModalProps> = React.memo(
130
130
  name={translate("noteLabel")}
131
131
  id={"sticky-note-input"}
132
132
  mode="markdown"
133
- preventLineNumbers
133
+ useToolbar
134
134
  onChange={(value) => {
135
135
  refNote.current = value;
136
136
  }}
@@ -3,7 +3,7 @@ import { decode } from "he";
3
3
  import { invisibleZeroWidthCharacters } from "./utils/characters";
4
4
  import { colorCalculateDistance } from "./utils/colorCalculateDistance";
5
5
  import decideContrastColorValue from "./utils/colorDecideContrastvalue";
6
- import { getEnabledColorsFromPalette, textToColorHash } from "./utils/colorHash";
6
+ import { getEnabledColorPropertiesFromPalette, getEnabledColorsFromPalette, textToColorHash } from "./utils/colorHash";
7
7
  import getColorConfiguration from "./utils/getColorConfiguration";
8
8
  import { getScrollParent } from "./utils/getScrollParent";
9
9
  import { getGlobalVar, setGlobalVar } from "./utils/globalVars";
@@ -22,6 +22,7 @@ export const utils = {
22
22
  setGlobalVar,
23
23
  getScrollParent,
24
24
  getEnabledColorsFromPalette,
25
+ getEnabledColorPropertiesFromPalette,
25
26
  textToColorHash,
26
27
  reduceToText,
27
28
  decodeHtmlEntities: decode,
@@ -0,0 +1,101 @@
1
+ .#{$prefix}--assistive-text,
2
+ .#{$prefix}--visually-hidden {
3
+ /*
4
+ originally from ~@carbon/styles/scss/css--helpers
5
+ but we cannot use it directly because of other included rules there.
6
+ */
7
+ position: absolute;
8
+ visibility: inherit;
9
+ width: 1px;
10
+ height: 1px;
11
+ padding: 0;
12
+ margin: -1px;
13
+ overflow: hidden;
14
+ white-space: nowrap;
15
+ border: 0;
16
+ clip-path: rect(0, 0, 0, 0);
17
+ }
18
+
19
+ /*
20
+ default focus indicator
21
+ */
22
+
23
+ :root {
24
+ --#{$eccgui}-a11y-outline-color: #{eccgui-color-var("layout", "magenta", "900")};
25
+ --#{$eccgui}-a11y-outline-style: solid;
26
+ --#{$eccgui}-a11y-outline-width: #{0.25 * $eccgui-size-block-whitespace};
27
+
28
+ // shift outline min 2px inside element to have a minimum 2px outline even with hidden overflow
29
+ --#{$eccgui}-a11y-outline-offset: min(calc(var(--#{$eccgui}-a11y-outline-width) * -0.5), -2px);
30
+ }
31
+
32
+ @keyframes outline-bounce {
33
+ 0% {
34
+ outline-width: calc(var(--#{$eccgui}-a11y-outline-width) * 0.5);
35
+ outline-color: var(--#{$eccgui}-a11y-outline-color);
36
+ outline-offset: var(--#{$eccgui}-a11y-outline-offset);
37
+ }
38
+
39
+ 33.3% {
40
+ outline-color: var(--#{$eccgui}-a11y-outline-color);
41
+ outline-offset: calc(var(--#{$eccgui}-a11y-outline-width));
42
+ }
43
+
44
+ 66.6% {
45
+ outline-color: currentcolor;
46
+ outline-offset: calc(var(--#{$eccgui}-a11y-outline-width) * -2);
47
+ }
48
+
49
+ 100% {
50
+ outline-width: var(--#{$eccgui}-a11y-outline-width);
51
+ outline-color: var(--#{$eccgui}-a11y-outline-color);
52
+ outline-offset: var(--#{$eccgui}-a11y-outline-offset);
53
+ }
54
+ }
55
+
56
+ @mixin focus-by-keyboard-static {
57
+ // strong visual focus indication for keyboard devices
58
+
59
+ outline: var(--#{$eccgui}-a11y-outline-color) var(--#{$eccgui}-a11y-outline-style)
60
+ var(--#{$eccgui}-a11y-outline-width);
61
+ outline-offset: var(--#{$eccgui}-a11y-outline-offset);
62
+ }
63
+
64
+ @mixin focus-by-keyboard-animation {
65
+ @media (prefers-reduced-motion: no-preference) {
66
+ animation: outline-bounce 0.5s;
67
+ }
68
+ }
69
+
70
+ .#{$eccgui}-a11y-focus-by-keyboard-animated {
71
+ @include focus-by-keyboard-static;
72
+ @include focus-by-keyboard-animation;
73
+ }
74
+
75
+ .#{$eccgui}-a11y-focus-by-keyboard-static {
76
+ @include focus-by-keyboard-static;
77
+
78
+ animation: none;
79
+ }
80
+
81
+ @mixin focus-by-pointer {
82
+ // limited visual focus indication for pointer devices
83
+
84
+ outline: transparent none 0;
85
+ outline-offset: 0;
86
+ }
87
+
88
+ .#{$eccgui}-a11y-focus-by-pointer {
89
+ @include focus-by-pointer;
90
+ }
91
+
92
+ *[tabindex]:not([tabindex^="-"]):focus-visible,
93
+ :focus-visible {
94
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
95
+ }
96
+
97
+ input:focus:not(:focus-visible),
98
+ textarea:focus:not(:focus-visible),
99
+ :focus:not(:focus-visible) {
100
+ @extend .#{$eccgui}-a11y-focus-by-pointer;
101
+ }
@@ -28,7 +28,7 @@ export default class CssCustomProperties {
28
28
 
29
29
  // Methods
30
30
 
31
- customProperties = (props: getCustomPropertiesProps = {}): string[][] | Record<string, string> => {
31
+ customProperties = (props: getCustomPropertiesProps = {}): [string, string][] | Record<string, string> => {
32
32
  // FIXME:
33
33
  // in case of performance issues results should get saved at least into intern variables
34
34
  // other cache strategies could be also tested
@@ -104,7 +104,9 @@ export default class CssCustomProperties {
104
104
  });
105
105
  };
106
106
 
107
- static listCustomProperties = (props: getCustomPropertiesProps = {}): string[][] | Record<string, string> => {
107
+ static listCustomProperties = (
108
+ props: getCustomPropertiesProps = {}
109
+ ): [string, string][] | Record<string, string> => {
108
110
  const { removeDashPrefix = true, returnObject = true, filterName = () => true, ...filterProps } = props;
109
111
 
110
112
  const customProperties = CssCustomProperties.listLocalCssStyleRuleProperties({
@@ -123,6 +125,6 @@ export default class CssCustomProperties {
123
125
 
124
126
  return returnObject
125
127
  ? (Object.fromEntries(customProperties) as Record<string, string>)
126
- : (customProperties as string[][]);
128
+ : (customProperties as [string, string][]);
127
129
  };
128
130
  }
@@ -6,10 +6,10 @@ import { colorCalculateDistance } from "./colorCalculateDistance";
6
6
  import CssCustomProperties from "./CssCustomProperties";
7
7
 
8
8
  type ColorOrFalse = Color | false;
9
- type ColorWeight = 100 | 300 | 500 | 700 | 900;
10
- type PaletteGroup = "identity" | "semantic" | "layout" | "extra";
9
+ export type ColorWeight = 100 | 300 | 500 | 700 | 900;
10
+ export type PaletteGroup = "identity" | "semantic" | "layout" | "extra";
11
11
 
12
- interface getEnabledColorsProps {
12
+ export interface getEnabledColorsProps {
13
13
  /** Specify the palette groups used to define the set of colors. */
14
14
  includePaletteGroup?: PaletteGroup[];
15
15
  /** Use only some weights of a color tint. */
@@ -21,20 +21,43 @@ interface getEnabledColorsProps {
21
21
  }
22
22
 
23
23
  const getEnabledColorsFromPaletteCache = new Map<string, Color[]>();
24
+ const getEnabledColorPropertiesFromPaletteCache = new Map<string, [string, string][]>();
24
25
 
25
- export function getEnabledColorsFromPalette({
26
+ export function getEnabledColorsFromPalette(props: getEnabledColorsProps): Color[] {
27
+ const configId = JSON.stringify({
28
+ includePaletteGroup: props.includePaletteGroup,
29
+ includeColorWeight: props.includeColorWeight,
30
+ });
31
+
32
+ if (getEnabledColorsFromPaletteCache.has(configId)) {
33
+ return getEnabledColorsFromPaletteCache.get(configId)!;
34
+ }
35
+
36
+ const colorPropertiesFromPalette = Object.values(getEnabledColorPropertiesFromPalette(props));
37
+
38
+ getEnabledColorsFromPaletteCache.set(
39
+ configId,
40
+ colorPropertiesFromPalette.map((color) => {
41
+ return Color(color[1]);
42
+ })
43
+ );
44
+
45
+ return getEnabledColorsFromPaletteCache.get(configId)!;
46
+ }
47
+
48
+ export function getEnabledColorPropertiesFromPalette({
26
49
  includePaletteGroup = ["layout"],
27
50
  includeColorWeight = [100, 300, 500, 700, 900],
28
- // TODO (planned for later): includeMixedColors = false,
51
+ // (planned for later): includeMixedColors = false,
29
52
  minimalColorDistance = COLORMINDISTANCE,
30
- }: getEnabledColorsProps): Color[] {
53
+ }: getEnabledColorsProps): [string, string][] {
31
54
  const configId = JSON.stringify({
32
55
  includePaletteGroup,
33
56
  includeColorWeight,
34
57
  });
35
58
 
36
- if (getEnabledColorsFromPaletteCache.has(configId)) {
37
- return getEnabledColorsFromPaletteCache.get(configId)!;
59
+ if (getEnabledColorPropertiesFromPaletteCache.has(configId)) {
60
+ return getEnabledColorPropertiesFromPaletteCache.get(configId)!;
38
61
  }
39
62
 
40
63
  const colorsFromPalette = new CssCustomProperties({
@@ -50,18 +73,18 @@ export function getEnabledColorsFromPalette({
50
73
  const weight = parseInt(tint[2], 10) as ColorWeight;
51
74
  return includePaletteGroup.includes(group) && includeColorWeight.includes(weight);
52
75
  },
53
- removeDashPrefix: false,
76
+ removeDashPrefix: true,
54
77
  returnObject: true,
55
78
  }).customProperties();
56
79
 
57
- const colorsFromPaletteValues = Object.values(colorsFromPalette) as string[];
80
+ const colorsFromPaletteValues = Object.entries(colorsFromPalette) as [string, string][];
58
81
 
59
82
  const colorsFromPaletteWithEnoughDistance =
60
83
  minimalColorDistance > 0
61
- ? colorsFromPaletteValues.reduce((enoughDistance: string[], color: string) => {
84
+ ? colorsFromPaletteValues.reduce((enoughDistance: [string, string][], color: [string, string]) => {
62
85
  if (enoughDistance.includes(color)) {
63
86
  return enoughDistance.filter((checkColor) => {
64
- const distance = colorCalculateDistance({ color1: color, color2: checkColor });
87
+ const distance = colorCalculateDistance({ color1: color[1], color2: checkColor[1] });
65
88
  return checkColor === color || (distance && minimalColorDistance <= distance);
66
89
  });
67
90
  } else {
@@ -70,14 +93,9 @@ export function getEnabledColorsFromPalette({
70
93
  }, colorsFromPaletteValues)
71
94
  : colorsFromPaletteValues;
72
95
 
73
- getEnabledColorsFromPaletteCache.set(
74
- configId,
75
- colorsFromPaletteWithEnoughDistance.map((color: string) => {
76
- return Color(color);
77
- })
78
- );
96
+ getEnabledColorPropertiesFromPaletteCache.set(configId, colorsFromPaletteWithEnoughDistance);
79
97
 
80
- return getEnabledColorsFromPaletteCache.get(configId)!;
98
+ return getEnabledColorPropertiesFromPaletteCache.get(configId)!;
81
99
  }
82
100
 
83
101
  function getColorcode(text: string): ColorOrFalse {
@@ -148,7 +166,7 @@ export function textToColorHash({
148
166
  }
149
167
 
150
168
  function stringToIntegerHash(inputString: string): number {
151
- /* this function is idempotend, meaning it retrieves the same result for the same input
169
+ /* this function is idempotent, meaning it retrieves the same result for the same input
152
170
  no matter how many times it's called */
153
171
  // Convert the string to a hash code
154
172
  let hashCode = 0;
@@ -190,15 +190,27 @@ a.#{$prefix}--header__menu-item:active {
190
190
  }
191
191
 
192
192
  // $shell-header-focus
193
- .#{$prefix}--header__action:focus,
194
- .#{$prefix}--header__action.#{$prefix}--btn--icon-only:focus,
195
- .#{$prefix}--header__action.#{$prefix}--btn--primary:focus,
196
- a.#{$prefix}--header__name:focus,
197
- a.#{$prefix}--header__menu-item:focus {
198
- outline: 1px dotted $shell-header-focus;
199
- outline-offset: -1px;
200
- border: none;
201
- box-shadow: none;
193
+ .#{$prefix}--header__action,
194
+ .#{$prefix}--header__action.#{$prefix}--btn--icon-only,
195
+ .#{$prefix}--header__action.#{$prefix}--btn--primary,
196
+ a.#{$prefix}--header__name,
197
+ a.#{$prefix}--header__menu-item {
198
+ &:focus {
199
+ @extend .#{$eccgui}-a11y-focus-by-pointer;
200
+
201
+ border: none;
202
+ box-shadow: none;
203
+ }
204
+
205
+ &,
206
+ .#{$prefix}--popover--open & {
207
+ &:focus-visible {
208
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
209
+
210
+ border: none;
211
+ box-shadow: none;
212
+ }
213
+ }
202
214
  }
203
215
  .#{$prefix}--header__menu-title[aria-expanded="true"] {
204
216
  color: $shell-header-focus;
@@ -28,3 +28,9 @@ $ui-02: $eccgui-color-workspace-background !default;
28
28
  padding: $eccgui-size-block-whitespace calc(0.5 * (#{mini-units(8)} - 30px));
29
29
  transition: none;
30
30
  }
31
+
32
+ .#{$eccgui}-application__menu__toggler.cds--header__action {
33
+ &:focus-visible {
34
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
35
+ }
36
+ }
@@ -51,18 +51,18 @@ $shell-panel-focus: $shell-header-focus !default;
51
51
  .#{$eccgui}-application__toolbar__panel-backdrop--onleave,
52
52
  .#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
53
53
  position: fixed;
54
- inset: mini-units(8) 0 0 0;
54
+ inset: mini-units(8) 0 0;
55
55
  }
56
56
 
57
57
  .#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
58
58
  top: 0;
59
59
  }
60
60
 
61
- // add rules for own class identiiers
61
+ // add rules for own class identifiers
62
62
 
63
63
  .#{$eccgui}-application__toolbar {
64
- flex-basis: auto;
65
64
  flex-grow: 0;
65
+ flex-basis: auto;
66
66
 
67
67
  .#{$prefix}--popover--bottom-right .#{$prefix}--popover-content {
68
68
  // for some reason the original calculation still moves out the tooltip
@@ -39,7 +39,9 @@
39
39
  }
40
40
 
41
41
  &:has(.cm-editor.cm-focused) {
42
- box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
42
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};
43
+
44
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-static;
43
45
  }
44
46
 
45
47
  .cm-editor {
@@ -47,7 +47,7 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
47
47
  }
48
48
 
49
49
  input:focus ~ .#{$ns}-control-indicator {
50
- outline-offset: 0;
50
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-static;
51
51
  }
52
52
 
53
53
  input:disabled ~ .#{$ns}-control-indicator,
@@ -72,6 +72,14 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
72
72
  background-image: url("~@carbon/icons/svg/32/checkbox--indeterminate.svg");
73
73
  }
74
74
  }
75
+
76
+ &.#{$ns}-switch {
77
+ --#{$eccgui}-a11y-outline-offset: 1px;
78
+
79
+ input:focus ~ .#{$ns}-control-indicator {
80
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-static;
81
+ }
82
+ }
75
83
  }
76
84
 
77
85
  .#{$ns}-control-indicator + *,
@@ -0,0 +1,72 @@
1
+ import React from "react";
2
+ import { Meta, StoryFn } from "@storybook/react";
3
+
4
+ import { getEnabledColorsProps } from "../../common/utils/colorHash";
5
+ import textFieldTest from "../TextField/stories/TextField.stories";
6
+
7
+ import { ColorField, ColorFieldProps } from "./ColorField";
8
+
9
+ export default {
10
+ title: "Forms/ColorField",
11
+ component: ColorField,
12
+ argTypes: {
13
+ ...textFieldTest.argTypes,
14
+ },
15
+ } as Meta<typeof ColorField>;
16
+
17
+ const Template: StoryFn<typeof ColorField> = (args) => <ColorField {...args}></ColorField>;
18
+
19
+ export const Default = Template.bind({});
20
+ Default.args = {
21
+ onChange: (e) => {
22
+ alert(e.target.value);
23
+ },
24
+ };
25
+
26
+ export const NoPalettePresets = Template.bind({});
27
+ NoPalettePresets.args = {
28
+ ...Default.args,
29
+ allowCustomColor: true,
30
+ colorPresets: [],
31
+ };
32
+
33
+ type TemplateColorHashProps = { stringForColorHashValue: string } & Pick<
34
+ ColorFieldProps,
35
+ "onChange" | "allowCustomColor"
36
+ > &
37
+ Pick<getEnabledColorsProps, "includeColorWeight" | "includePaletteGroup">;
38
+
39
+ const TemplateColorHash: StoryFn<TemplateColorHashProps> = (args: TemplateColorHashProps) => (
40
+ <ColorField
41
+ allowCustomColor={args.allowCustomColor}
42
+ colorPresets={ColorField.listColorPalettePresets({
43
+ includeColorWeight: args.includeColorWeight,
44
+ includePaletteGroup: args.includePaletteGroup,
45
+ })}
46
+ value={ColorField.calculateColorHashValue(args.stringForColorHashValue, {
47
+ allowCustomColor: args.allowCustomColor,
48
+ includeColorWeight: args.includeColorWeight,
49
+ includePaletteGroup: args.includePaletteGroup,
50
+ })}
51
+ />
52
+ );
53
+
54
+ /**
55
+ * Component provides a helper function to calculate a color hash from a text,
56
+ * that can be used as `value` or `defaultValue`.
57
+ *
58
+ * ```
59
+ * <ColorField value={ColorField.calculateColorHashValue("MyText")} />
60
+ * ```
61
+ *
62
+ * You can add `options` to set the config for the color palette filters.
63
+ * The same default values like on `ColorField` are used for them.
64
+ */
65
+ export const ColorHashValue = TemplateColorHash.bind({});
66
+ ColorHashValue.args = {
67
+ ...Default.args,
68
+ allowCustomColor: true,
69
+ includeColorWeight: [300, 500, 700],
70
+ includePaletteGroup: ["layout", "extra"],
71
+ stringForColorHashValue: "My text that will used to create a color hash as initial value.",
72
+ };