@db-ux/react-core-components 4.3.2 → 4.4.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @db-ux/react-core-components
2
2
 
3
+ ## 4.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: add `role` property to DBNotification & automatically add role based on semantic if no `role` or `ariaLive` is provided to increase UX for screen-reader users - [see commit 177d71e](https://github.com/db-ux-design-system/core-web/commit/177d71e287a64a6491ba446e7812d0adbda1717e)
8
+
9
+ - feat(DBSelect): hide empty first option in `required` selects with placeholder after the first user selection, and add `showEmptyOption` prop to overwrite this - [see commit 4280bc4](https://github.com/db-ux-design-system/core-web/commit/4280bc47538d6983d6bb5575f012b6c6b25b40e8)
10
+
3
11
  ## 4.3.2
4
12
 
5
13
  ### Patch Changes
@@ -1,3 +1,3 @@
1
1
  import * as React from "react";
2
- declare const DBBadge: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "text" | keyof import("../..").GlobalProps | keyof import("./model").DBBadgeDefaultProps | "semantic" | "size" | "emphasis"> & import("./model").DBBadgeDefaultProps & import("../..").GlobalProps & import("../..").SemanticProps & import("../..").SizeProps & import("../..").EmphasisProps & import("../..").TextProps & React.RefAttributes<any>>;
2
+ declare const DBBadge: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "semantic" | "text" | keyof import("../..").GlobalProps | keyof import("./model").DBBadgeDefaultProps | "size" | "emphasis"> & import("./model").DBBadgeDefaultProps & import("../..").GlobalProps & import("../..").SemanticProps & import("../..").SizeProps & import("../..").EmphasisProps & import("../..").TextProps & React.RefAttributes<any>>;
3
3
  export default DBBadge;
@@ -1,3 +1,3 @@
1
1
  import * as React from "react";
2
- declare const DBInfotext: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "text" | keyof import("../..").GlobalProps | "semantic" | "size" | "icon" | "showIcon"> & import("../..").GlobalProps & import("../..").SemanticProps & import("../..").IconProps & import("../..").SizeProps & import("../..").ShowIconProps & import("../..").TextProps & React.RefAttributes<any>>;
2
+ declare const DBInfotext: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "semantic" | "text" | keyof import("../..").GlobalProps | "size" | "icon" | "showIcon"> & import("../..").GlobalProps & import("../..").SemanticProps & import("../..").IconProps & import("../..").SizeProps & import("../..").ShowIconProps & import("../..").TextProps & React.RefAttributes<any>>;
3
3
  export default DBInfotext;
@@ -1,3 +1,3 @@
1
1
  import * as React from "react";
2
- declare const DBLink: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<any>, "text" | keyof import("../..").GlobalProps | "showIcon" | keyof import("./model").DBLinkDefaultProps | keyof import("../..").ClickEventProps<HTMLAnchorElement> | keyof import("../..").LinkProps | "wrap"> & import("./model").DBLinkDefaultProps & import("../..").GlobalProps & import("../..").ClickEventProps<HTMLAnchorElement> & import("../..").LinkProps & import("../..").ShowIconProps & import("../..").TextProps & import("../..").WrapProps & React.RefAttributes<any>>;
2
+ declare const DBLink: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<any>, "role" | "text" | keyof import("../..").GlobalProps | "showIcon" | keyof import("./model").DBLinkDefaultProps | keyof import("../..").ClickEventProps<HTMLAnchorElement> | keyof import("../..").LinkProps | "wrap"> & import("./model").DBLinkDefaultProps & import("../..").GlobalProps & import("../..").ClickEventProps<HTMLAnchorElement> & import("../..").LinkProps & import("../..").RoleProps & import("../..").ShowIconProps & import("../..").TextProps & import("../..").WrapProps & React.RefAttributes<any>>;
3
3
  export default DBLink;
@@ -1,4 +1,4 @@
1
- import { ClickEventProps, ClickEventState, GlobalProps, GlobalState, LinkProps, ShowIconProps, TextProps, WrapProps } from '../../shared/model';
1
+ import { ClickEventProps, ClickEventState, GlobalProps, GlobalState, LinkProps, RoleProps, ShowIconProps, TextProps, WrapProps } from '../../shared/model';
2
2
  export declare const LinkVariantList: readonly ["adaptive", "brand", "inline"];
3
3
  export type LinkVariantType = (typeof LinkVariantList)[number];
4
4
  export declare const LinkSizeList: readonly ["medium", "small"];
@@ -19,6 +19,6 @@ export type DBLinkDefaultProps = {
19
19
  */
20
20
  variant?: LinkVariantType;
21
21
  };
22
- export type DBLinkProps = DBLinkDefaultProps & GlobalProps & ClickEventProps<HTMLAnchorElement> & LinkProps & ShowIconProps & TextProps & WrapProps;
22
+ export type DBLinkProps = DBLinkDefaultProps & GlobalProps & ClickEventProps<HTMLAnchorElement> & LinkProps & RoleProps & ShowIconProps & TextProps & WrapProps;
23
23
  export type DBLinkDefaultState = {};
24
24
  export type DBLinkState = DBLinkDefaultState & GlobalState & ClickEventState<HTMLAnchorElement>;
@@ -1,4 +1,4 @@
1
- import { ClickEvent, CloseEventProps, CloseEventState, GlobalProps, GlobalState, IconProps, InnerCloseButtonProps, PopoverProps, SemanticProps, ShowIconProps, TextProps } from '../../shared/model';
1
+ import { ClickEvent, CloseEventProps, CloseEventState, GlobalProps, GlobalState, IconProps, InnerCloseButtonProps, PopoverProps, RoleProps, SemanticProps, ShowIconProps, TextProps } from '../../shared/model';
2
2
  export declare const NotificationVariantList: readonly ["docked", "standalone", "overlay"];
3
3
  export type NotificationVariantType = (typeof NotificationVariantList)[number];
4
4
  export declare const NotificationLinkVariantList: readonly ["block", "inline"];
@@ -52,6 +52,6 @@ export type DBNotificationDefaultProps = {
52
52
  */
53
53
  variant?: NotificationVariantType;
54
54
  };
55
- export type DBNotificationProps = DBNotificationDefaultProps & GlobalProps & CloseEventProps<ClickEvent<HTMLButtonElement>> & IconProps & SemanticProps & InnerCloseButtonProps & PopoverProps & ShowIconProps & TextProps;
55
+ export type DBNotificationProps = DBNotificationDefaultProps & GlobalProps & RoleProps & CloseEventProps<ClickEvent<HTMLButtonElement>> & IconProps & SemanticProps & InnerCloseButtonProps & PopoverProps & ShowIconProps & TextProps;
56
56
  export type DBNotificationDefaultState = {};
57
57
  export type DBNotificationState = DBNotificationDefaultState & GlobalState & CloseEventState<ClickEvent<HTMLButtonElement>>;
@@ -1,4 +1,4 @@
1
1
  import * as React from "react";
2
2
  import { ClickEvent } from "../../shared/model";
3
- declare const DBNotification: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "text" | keyof import("../../shared/model").GlobalProps | "semantic" | "icon" | "showIcon" | keyof import("../../shared/model").PopoverProps | keyof import("../../shared/model").InnerCloseButtonProps | keyof import("./model").DBNotificationDefaultProps | keyof import("../../shared/model").CloseEventProps<ClickEvent<HTMLButtonElement>>> & import("./model").DBNotificationDefaultProps & import("../../shared/model").GlobalProps & import("../../shared/model").CloseEventProps<ClickEvent<HTMLButtonElement>> & import("../../shared/model").IconProps & import("../../shared/model").SemanticProps & import("../../shared/model").InnerCloseButtonProps & import("../../shared/model").PopoverProps & import("../../shared/model").ShowIconProps & import("../../shared/model").TextProps & React.RefAttributes<any>>;
3
+ declare const DBNotification: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "role" | "semantic" | "text" | keyof import("../../shared/model").GlobalProps | "icon" | "showIcon" | keyof import("../../shared/model").PopoverProps | keyof import("../../shared/model").InnerCloseButtonProps | keyof import("./model").DBNotificationDefaultProps | keyof import("../../shared/model").CloseEventProps<ClickEvent<HTMLButtonElement>>> & import("./model").DBNotificationDefaultProps & import("../../shared/model").GlobalProps & import("../../shared/model").RoleProps & import("../../shared/model").CloseEventProps<ClickEvent<HTMLButtonElement>> & import("../../shared/model").IconProps & import("../../shared/model").SemanticProps & import("../../shared/model").InnerCloseButtonProps & import("../../shared/model").PopoverProps & import("../../shared/model").ShowIconProps & import("../../shared/model").TextProps & React.RefAttributes<any>>;
4
4
  export default DBNotification;
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import { filterPassingProps, getRootProps } from "../../utils/react";
4
4
  import { useRef, forwardRef } from "react";
5
5
  import { DEFAULT_CLOSE_BUTTON } from "../../shared/constants";
6
- import { cls, getBoolean, getBooleanAsString, stringPropVisible, } from "../../utils";
6
+ import { cls, getBoolean, getBooleanAsString, getNotificationRole, stringPropVisible, } from "../../utils";
7
7
  import DBButton from "../button/button";
8
8
  function DBNotificationFn(props, component) {
9
9
  var _a;
@@ -16,7 +16,11 @@ function DBNotificationFn(props, component) {
16
16
  props.onClose(event);
17
17
  }
18
18
  }
19
- return (React.createElement("article", Object.assign({ ref: _ref }, filterPassingProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font", "onClose"]), { id: props.id }, getRootProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font"]), { className: cls("db-notification", props.className), "aria-live": props.ariaLive, "data-semantic": props.semantic, "data-variant": props.variant, "data-icon": getBoolean(props.showIcon) !== false ? props.icon : undefined, "data-show-icon": getBooleanAsString(props.showIcon), "data-link-variant": props.linkVariant }),
19
+ return (React.createElement("div", Object.assign({ ref: _ref }, filterPassingProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font", "onClose"]), { id: props.id }, getRootProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font"]), { className: cls("db-notification", props.className), role: getNotificationRole({
20
+ semantic: props.semantic,
21
+ role: props.role,
22
+ ariaLive: props.ariaLive,
23
+ }), "aria-live": props.ariaLive, "data-semantic": props.semantic, "data-variant": props.variant, "data-icon": getBoolean(props.showIcon) !== false ? props.icon : undefined, "data-show-icon": getBooleanAsString(props.showIcon), "data-link-variant": props.linkVariant }),
20
24
  React.createElement(React.Fragment, null, props.image),
21
25
  stringPropVisible(props.headline, props.showHeadline) ? (React.createElement("header", null, props.headline)) : null,
22
26
  React.createElement("p", null, props.text ? React.createElement(React.Fragment, null, props.text) : React.createElement(React.Fragment, null, props.children)),
@@ -9,6 +9,15 @@ export type DBSelectDefaultProps = {
9
9
  * If you don't/can't use children/slots you can pass in the options as an array.
10
10
  */
11
11
  options?: DBSelectOptionType[];
12
+ /**
13
+ * Controls whether the empty placeholder option is shown in the dropdown after the user's selection of another option.
14
+ * By default, it is shown for non-required selects and hidden for required selects.
15
+ * Set to `true` to always show or `false` to always hide the empty option.
16
+ *
17
+ * Note: The empty option is only rendered when `variant === 'floating'` or a `placeholder` is set.
18
+ * Setting `showEmptyOption` alone has no effect if neither of these conditions is met.
19
+ */
20
+ showEmptyOption?: boolean;
12
21
  };
13
22
  export type DBSelectOptionType = {
14
23
  /**
@@ -40,5 +49,6 @@ export type DBSelectProps = GlobalProps & ClickEventProps<HTMLSelectElement> & C
40
49
  export type DBSelectDefaultState = {
41
50
  _placeholderId: string;
42
51
  getOptionLabel: (option: DBSelectOptionType) => string;
52
+ shouldShowEmptyOption: () => boolean;
43
53
  };
44
54
  export type DBSelectState = DBSelectDefaultState & GlobalState & ClickEventState<HTMLSelectElement> & ChangeEventState<HTMLSelectElement> & FocusEventState<HTMLSelectElement> & InputEventState<HTMLSelectElement> & FormState & InitializedState & FromValidState;
@@ -87,6 +87,17 @@ function DBSelectFn(props, component) {
87
87
  var _a, _b;
88
88
  return (_a = option.label) !== null && _a !== void 0 ? _a : (_b = option.value) === null || _b === void 0 ? void 0 : _b.toString();
89
89
  }
90
+ function shouldShowEmptyOption() {
91
+ const hasPlaceholderOrFloating = props.variant === "floating" || !!props.placeholder;
92
+ if (!hasPlaceholderOrFloating) {
93
+ return false;
94
+ }
95
+ if (props.showEmptyOption !== undefined) {
96
+ return props.showEmptyOption;
97
+ }
98
+ // Default: show empty option for non-required selects
99
+ return !props.required;
100
+ }
90
101
  useEffect(() => {
91
102
  var _a;
92
103
  setInitialized(true);
@@ -156,7 +167,7 @@ function DBSelectFn(props, component) {
156
167
  return (React.createElement("div", Object.assign({}, getRootProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font"]), { className: cls("db-select", props.className), "data-variant": props.variant, "data-hide-label": getHideProp(props.showLabel), "data-hide-asterisk": getHideProp(props.showRequiredAsterisk), "data-icon": props.icon, "data-show-icon": getBooleanAsString(props.showIcon) }),
157
168
  React.createElement("label", { htmlFor: _id }, (_a = props.label) !== null && _a !== void 0 ? _a : DEFAULT_LABEL),
158
169
  React.createElement("select", Object.assign({ "aria-invalid": props.validation === "invalid", "data-custom-validity": props.validation, ref: _ref }, filterPassingProps(props, ["data-icon-variant", "data-icon-variant-before", "data-icon-variant-after", "data-icon-weight", "data-icon-weight-before", "data-icon-weight-after", "data-interactive", "data-force-mobile", "data-color", "data-container-color", "data-bg-color", "data-on-bg-color", "data-color-scheme", "data-font-size", "data-headline-size", "data-divider", "data-focus", "data-font"]), { required: getBoolean(props.required, "required"), disabled: getBoolean(props.disabled, "disabled"), id: _id, name: props.name, size: props.size, value: props.value, autoComplete: props.autocomplete, multiple: props.multiple, onInput: (event) => handleInput(event), onClick: (event) => handleClick(event), onChange: (event) => handleChange(event), onBlur: (event) => handleBlur(event), onFocus: (event) => handleFocus(event), "aria-describedby": (_b = props.ariaDescribedBy) !== null && _b !== void 0 ? _b : _descByIds }),
159
- props.variant === "floating" || props.placeholder ? (React.createElement("option", { className: "placeholder", value: "" })) : null,
170
+ props.variant === "floating" || !!props.placeholder ? (React.createElement("option", { className: "placeholder", value: "", "data-show-empty-option": getBooleanAsString(shouldShowEmptyOption()) })) : null,
160
171
  ((_c = props.options) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(React.Fragment, null, (_d = props.options) === null || _d === void 0 ? void 0 : _d.map((option) => {
161
172
  var _a;
162
173
  return option.options ? (React.createElement("optgroup", { label: getOptionLabel(option), key: getOptionKey(option, "select-optgroup-") }, (_a = option.options) === null || _a === void 0 ? void 0 : _a.map((optgroupOption) => (React.createElement("option", { value: optgroupOption.value, disabled: optgroupOption.disabled, key: getOptionKey(optgroupOption, "select-optgroup-option-") }, getOptionLabel(optgroupOption)))))) : (React.createElement("option", { value: option.value, disabled: option.disabled, key: getOptionKey(option, "select-option-") }, getOptionLabel(option)));
@@ -1,3 +1,3 @@
1
1
  import * as React from "react";
2
- declare const DBTag: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "content" | keyof import("../../shared/model").GlobalProps | "semantic" | "emphasis" | "icon" | "showIcon" | keyof import("./model").DBTagDefaultProps | "overflow" | keyof import("./model").DBTagEventsProps> & import("./model").DBTagDefaultProps & import("../../shared/model").GlobalProps & import("../../shared/model").IconProps & import("../../shared/model").SemanticProps & import("../../shared/model").OverflowProps & import("../../shared/model").EmphasisProps & import("../../shared/model").ShowIconProps & import("../../shared/model").ContentSlotProps & import("./model").DBTagEventsProps & React.RefAttributes<any>>;
2
+ declare const DBTag: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<any>, "content" | "semantic" | keyof import("../../shared/model").GlobalProps | "emphasis" | "icon" | "showIcon" | keyof import("./model").DBTagDefaultProps | "overflow" | keyof import("./model").DBTagEventsProps> & import("./model").DBTagDefaultProps & import("../../shared/model").GlobalProps & import("../../shared/model").IconProps & import("../../shared/model").SemanticProps & import("../../shared/model").OverflowProps & import("../../shared/model").EmphasisProps & import("../../shared/model").ShowIconProps & import("../../shared/model").ContentSlotProps & import("./model").DBTagEventsProps & React.RefAttributes<any>>;
3
3
  export default DBTag;
@@ -398,10 +398,6 @@ export type LinkProps = {
398
398
  * The relationship of the linked URL as space-separated link types.
399
399
  */
400
400
  rel?: string;
401
- /**
402
- * Sets aria role based on [`aria-role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles).
403
- */
404
- role?: string;
405
401
  /**
406
402
  * How much of the referrer to send when following the link.
407
403
  * @deprecated use `referrerPolicy` instead
@@ -412,6 +408,12 @@ export type LinkProps = {
412
408
  */
413
409
  referrerPolicy?: LinkReferrerPolicyType;
414
410
  };
411
+ export type RoleProps = {
412
+ /**
413
+ * Sets aria role based on [`aria-role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles).
414
+ */
415
+ role?: string;
416
+ };
415
417
  export type TextProps = {
416
418
  /**
417
419
  * Alternative for default slot/children.
@@ -58,3 +58,15 @@ export declare const getOptionKey: (option: {
58
58
  value?: string | number | string[] | undefined;
59
59
  }, prefix: string) => string;
60
60
  export declare const isKeyboardEvent: <T>(event?: ClickEvent<T> | GeneralKeyboardEvent<T>) => event is GeneralKeyboardEvent<T>;
61
+ /**
62
+ * Maps semantic values to appropriate ARIA roles for notifications
63
+ * @param semantic - The semantic type of the notification
64
+ * @param role - The aria role of the notification
65
+ * @param ariaLive - The aria-live of the notification
66
+ * @returns The appropriate ARIA role or undefined for default behavior
67
+ */
68
+ export declare const getNotificationRole: ({ semantic, role, ariaLive }: {
69
+ semantic?: string;
70
+ role?: string;
71
+ ariaLive?: string;
72
+ }) => string | undefined;
@@ -141,3 +141,28 @@ export const getOptionKey = (option, prefix) => {
141
141
  return `${prefix}${key}`;
142
142
  };
143
143
  export const isKeyboardEvent = (event) => event.key !== undefined;
144
+ /**
145
+ * Maps semantic values to appropriate ARIA roles for notifications
146
+ * @param semantic - The semantic type of the notification
147
+ * @param role - The aria role of the notification
148
+ * @param ariaLive - The aria-live of the notification
149
+ * @returns The appropriate ARIA role or undefined for default behavior
150
+ */
151
+ export const getNotificationRole = ({ semantic, role, ariaLive }) => {
152
+ if (role) {
153
+ return role;
154
+ }
155
+ if (ariaLive) {
156
+ return 'article';
157
+ }
158
+ switch (semantic) {
159
+ case 'critical':
160
+ case 'warning':
161
+ return 'alert';
162
+ case 'informational':
163
+ case 'successful':
164
+ return 'status';
165
+ default:
166
+ return 'article';
167
+ }
168
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@db-ux/react-core-components",
3
- "version": "4.3.2",
3
+ "version": "4.4.0",
4
4
  "description": "React components for @db-ux/core-components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "devDependencies": {
33
33
  "@playwright/experimental-ct-react": "1.57.0",
34
- "@types/react": "19.2.8",
34
+ "@types/react": "19.2.9",
35
35
  "react": "19.2.3",
36
36
  "react-dom": "19.2.3"
37
37
  },
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "sideEffects": false,
43
43
  "dependencies": {
44
- "@db-ux/core-components": "4.3.2",
45
- "@db-ux/core-foundations": "4.3.2"
44
+ "@db-ux/core-components": "4.4.0",
45
+ "@db-ux/core-foundations": "4.4.0"
46
46
  }
47
47
  }