@db-ux/react-core-components 4.7.2 → 4.8.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,15 @@
1
1
  # @db-ux/react-core-components
2
2
 
3
+ ## 4.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Notification content now supports additional inline elements like `span` without styling collisions. And added the possibility to set the duration as a machine-readable value via the new `timestampDatetime` property - [see commit dae5149](https://github.com/db-ux-design-system/core-web/commit/dae514902f92a74cb95a3a3adab205d560174692)
8
+
9
+ ## 4.7.3
10
+
11
+ _version bump_
12
+
3
13
  ## 4.7.2
4
14
 
5
15
  ### Patch Changes
package/README.md CHANGED
@@ -30,7 +30,10 @@ Import the styles in scss or css. Based on your technology the file names could
30
30
 
31
31
  ```scss
32
32
  // index.scss
33
- @forward "@db-ux/core-components/build/styles/rollup";
33
+ @forward "@db-ux/core-foundations/build/styles/theme/rollup"; // Palette tokens
34
+ @forward "@db-ux/core-foundations/build/styles/bundle"; // Semantic tokens
35
+ @forward "@db-ux/core-foundations/build/styles/icons/rollup"; // Icon fonts
36
+ @forward "@db-ux/core-components/build/styles/rollup"; // Component styling
34
37
  ```
35
38
 
36
39
  </details>
@@ -38,8 +41,11 @@ Import the styles in scss or css. Based on your technology the file names could
38
41
  <summary><strong>CSS</strong></summary>
39
42
 
40
43
  ```tsx
41
- // main.tsx
42
- import "@db-ux/core-components/build/styles/rollup.css";
44
+ // main.tsx — order matters!
45
+ import "@db-ux/core-foundations/build/styles/theme/rollup.css"; // Palette tokens
46
+ import "@db-ux/core-foundations/build/styles/bundle.css"; // Semantic tokens
47
+ import "@db-ux/core-foundations/build/styles/icons/rollup.css"; // Icon fonts
48
+ import "@db-ux/core-components/build/styles/rollup.css"; // Component styling
43
49
  ```
44
50
 
45
51
  </details>
@@ -40,6 +40,17 @@ export type DBNotificationDefaultProps = {
40
40
  * The timestamp attribute can be set for overlay notifications
41
41
  */
42
42
  timestamp?: string;
43
+ /**
44
+ * Machine-readable value for the `datetime` attribute of the rendered `<time>` element.
45
+ *
46
+ * Accepts any valid HTML datetime string:
47
+ * - Absolute moment: ISO 8601 date/time, e.g. `"2024-06-01T12:30:00"`
48
+ * - Duration: ISO 8601 duration, e.g. `"PT5M"` (5 minutes), `"PT1H30M"` (1 h 30 min)
49
+ *
50
+ * When omitted the `datetime` attribute is not rendered and assistive technologies
51
+ * fall back to the visible `timestamp` text.
52
+ */
53
+ timestampDatetime?: string;
43
54
  /**
44
55
  * Enables or disables the visibility of the timestamp.
45
56
  */
@@ -22,9 +22,9 @@ function DBNotificationFn(props, component) {
22
22
  ariaLive: props.ariaLive,
23
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 }),
24
24
  React.createElement(React.Fragment, null, props.image),
25
- stringPropVisible(props.headline, props.showHeadline) ? (React.createElement("header", null, props.headline)) : null,
25
+ stringPropVisible(props.headline, props.showHeadline) ? (React.createElement("header", { "data-area": "head" }, props.headline)) : null,
26
26
  React.createElement("div", { "data-area": "content" }, props.text ? React.createElement(React.Fragment, null, props.text) : React.createElement(React.Fragment, null, props.children)),
27
- stringPropVisible(props.timestamp, props.showTimestamp) ? (React.createElement("span", null, props.timestamp)) : null,
27
+ stringPropVisible(props.timestamp, props.showTimestamp) ? (React.createElement("time", { "data-area": "timestamp", dateTime: props.timestampDatetime }, props.timestamp)) : null,
28
28
  React.createElement(React.Fragment, null, props.link),
29
29
  getBoolean(props.closeable, "closeable") ? (React.createElement(DBButton, { icon: "cross", variant: "ghost", size: "small", id: props.closeButtonId, noText: true, onClick: (event) => handleClose(event) }, (_c = props.closeButtonText) !== null && _c !== void 0 ? _c : DEFAULT_CLOSE_BUTTON)) : null));
30
30
  }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@db-ux/react-core-components",
3
- "version": "4.7.2",
3
+ "version": "4.8.0",
4
4
  "description": "React components for @db-ux/core-components",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/db-ux-design-system/core-web.git"
8
8
  },
9
9
  "license": "Apache-2.0",
10
+ "type": "module",
10
11
  "main": "./dist/index.js",
11
12
  "module": "./dist/index.js",
12
13
  "types": "./dist/index.d.ts",
@@ -15,6 +16,25 @@
15
16
  "agent",
16
17
  "CHANGELOG.md"
17
18
  ],
19
+ "devDependencies": {
20
+ "npm-run-all2": "8.0.4",
21
+ "@playwright/experimental-ct-react": "1.59.1",
22
+ "@types/react": "19.2.14",
23
+ "cpr": "3.0.1",
24
+ "playwright": "1.59.1",
25
+ "react": "19.2.5",
26
+ "react-dom": "19.2.5",
27
+ "typescript": "5.9.3"
28
+ },
29
+ "publishConfig": {
30
+ "registry": "https://registry.npmjs.org/",
31
+ "access": "public"
32
+ },
33
+ "sideEffects": false,
34
+ "dependencies": {
35
+ "@db-ux/core-components": "4.8.0",
36
+ "@db-ux/core-foundations": "4.8.0"
37
+ },
18
38
  "scripts": {
19
39
  "build": "npm-run-all tsc --parallel mv:*",
20
40
  "mv:dist": "cpr dist ../../build-outputs/react/dist --overwrite",
@@ -28,20 +48,5 @@
28
48
  "test:windows": "playwright test --config playwright.screen-reader.win.ts",
29
49
  "test:components:ui": "playwright test --config playwright.config.ts --ui",
30
50
  "tsc": "tsc --project . --sourceMap false"
31
- },
32
- "devDependencies": {
33
- "@playwright/experimental-ct-react": "1.59.1",
34
- "@types/react": "19.2.14",
35
- "react": "19.2.5",
36
- "react-dom": "19.2.5"
37
- },
38
- "publishConfig": {
39
- "registry": "https://registry.npmjs.org/",
40
- "access": "public"
41
- },
42
- "sideEffects": false,
43
- "dependencies": {
44
- "@db-ux/core-components": "4.7.2",
45
- "@db-ux/core-foundations": "4.7.2"
46
51
  }
47
- }
52
+ }
@@ -1 +0,0 @@
1
- export {};
@@ -1,167 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { handleFrameworkEventAngular, handleFrameworkEventVue } from './form-components';
3
- const createNumberEvent = (value, badInput, inputType) => ({
4
- inputType,
5
- target: {
6
- type: 'number',
7
- value,
8
- validity: {
9
- badInput
10
- }
11
- }
12
- });
13
- const createTextEvent = (value) => ({
14
- target: {
15
- type: 'text',
16
- value,
17
- validity: {
18
- badInput: false
19
- }
20
- }
21
- });
22
- describe('handleFrameworkEventAngular', () => {
23
- it('calls propagateChange and writeValue for valid number value', () => {
24
- const component = {
25
- propagateChange: vi.fn(),
26
- writeValue: vi.fn()
27
- };
28
- const event = createNumberEvent('1.5', false);
29
- handleFrameworkEventAngular(component, event);
30
- expect(component.propagateChange).toHaveBeenCalledWith('1.5');
31
- expect(component.writeValue).toHaveBeenCalledWith('1.5');
32
- });
33
- it('skips propagateChange and writeValue when "." is typed (intermediate state)', () => {
34
- const component = {
35
- propagateChange: vi.fn(),
36
- writeValue: vi.fn()
37
- };
38
- const event = {
39
- type: 'input',
40
- data: '.',
41
- inputType: 'insertText',
42
- target: {
43
- type: 'number',
44
- value: '1.'
45
- }
46
- };
47
- handleFrameworkEventAngular(component, event, 'value', '1');
48
- expect(component.propagateChange).not.toHaveBeenCalled();
49
- expect(component.writeValue).not.toHaveBeenCalled();
50
- });
51
- it('skips propagateChange and writeValue when "," is typed (intermediate state)', () => {
52
- const component = {
53
- propagateChange: vi.fn(),
54
- writeValue: vi.fn()
55
- };
56
- const event = {
57
- type: 'input',
58
- data: ',',
59
- inputType: 'insertText',
60
- target: {
61
- type: 'number',
62
- value: ''
63
- }
64
- };
65
- handleFrameworkEventAngular(component, event, 'value', '1');
66
- expect(component.propagateChange).not.toHaveBeenCalled();
67
- expect(component.writeValue).not.toHaveBeenCalled();
68
- });
69
- it.each(['e', 'E', '+', '-'])('skips propagateChange and writeValue when "%s" is typed (intermediate state)', char => {
70
- const component = {
71
- propagateChange: vi.fn(),
72
- writeValue: vi.fn()
73
- };
74
- const event = {
75
- type: 'input',
76
- data: char,
77
- inputType: 'insertText',
78
- target: {
79
- type: 'number',
80
- value: ''
81
- }
82
- };
83
- handleFrameworkEventAngular(component, event, 'value', '1');
84
- expect(component.propagateChange).not.toHaveBeenCalled();
85
- expect(component.writeValue).not.toHaveBeenCalled();
86
- });
87
- it('skips propagateChange and writeValue when deleting content and lastValue has decimal', () => {
88
- const component = {
89
- propagateChange: vi.fn(),
90
- writeValue: vi.fn()
91
- };
92
- const event = {
93
- type: 'input',
94
- data: null,
95
- inputType: 'deleteContentBackward',
96
- target: {
97
- type: 'number',
98
- value: ''
99
- }
100
- };
101
- handleFrameworkEventAngular(component, event, 'value', '1.5');
102
- expect(component.propagateChange).not.toHaveBeenCalled();
103
- expect(component.writeValue).not.toHaveBeenCalled();
104
- });
105
- it('calls propagateChange and writeValue when number input is cleared via backspace (no decimal in lastValue)', () => {
106
- const component = {
107
- propagateChange: vi.fn(),
108
- writeValue: vi.fn()
109
- };
110
- const event = createNumberEvent('', false, 'deleteContentBackward');
111
- handleFrameworkEventAngular(component, event);
112
- expect(component.propagateChange).toHaveBeenCalledWith('');
113
- expect(component.writeValue).toHaveBeenCalledWith('');
114
- });
115
- it('skips propagateChange and writeValue for number change events', () => {
116
- const component = {
117
- propagateChange: vi.fn(),
118
- writeValue: vi.fn()
119
- };
120
- const event = {
121
- type: 'change',
122
- target: {
123
- type: 'number',
124
- value: '5'
125
- }
126
- };
127
- handleFrameworkEventAngular(component, event);
128
- expect(component.propagateChange).not.toHaveBeenCalled();
129
- expect(component.writeValue).not.toHaveBeenCalled();
130
- });
131
- it('calls propagateChange and writeValue for text input type', () => {
132
- const component = {
133
- propagateChange: vi.fn(),
134
- writeValue: vi.fn()
135
- };
136
- const event = createTextEvent('hello');
137
- handleFrameworkEventAngular(component, event);
138
- expect(component.propagateChange).toHaveBeenCalledWith('hello');
139
- expect(component.writeValue).toHaveBeenCalledWith('hello');
140
- });
141
- });
142
- describe('handleFrameworkEventVue', () => {
143
- it('emits update:value for valid number value', () => {
144
- const emit = vi.fn();
145
- const event = createNumberEvent('1.5', false);
146
- handleFrameworkEventVue(emit, event);
147
- expect(emit).toHaveBeenCalledWith('update:value', '1.5');
148
- });
149
- it('emits update:value with empty string when number input has badInput (intermediate state like "1.")', () => {
150
- const emit = vi.fn();
151
- const event = createNumberEvent('', true);
152
- handleFrameworkEventVue(emit, event);
153
- expect(emit).toHaveBeenCalledWith('update:value', '');
154
- });
155
- it('emits update:value when number input is cleared (empty, no badInput)', () => {
156
- const emit = vi.fn();
157
- const event = createNumberEvent('', false);
158
- handleFrameworkEventVue(emit, event);
159
- expect(emit).toHaveBeenCalledWith('update:value', '');
160
- });
161
- it('emits update:value for text input type', () => {
162
- const emit = vi.fn();
163
- const event = createTextEvent('hello');
164
- handleFrameworkEventVue(emit, event);
165
- expect(emit).toHaveBeenCalledWith('update:value', 'hello');
166
- });
167
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { getStep } from './index';
3
- describe('getStep', () => {
4
- it('returns undefined when step is undefined', () => {
5
- expect(getStep(undefined)).toBeUndefined();
6
- });
7
- it('returns undefined when step is null', () => {
8
- // eslint-disable-next-line unicorn/no-null
9
- expect(getStep(null)).toBeUndefined();
10
- });
11
- it('returns "any" when step is "any"', () => {
12
- expect(getStep('any')).toBe('any');
13
- });
14
- it('returns a number when step is a number', () => {
15
- expect(getStep(5)).toBe(5);
16
- expect(getStep(0.5)).toBe(0.5);
17
- });
18
- it('returns a number when step is a numeric string', () => {
19
- expect(getStep('5')).toBe(5);
20
- expect(getStep('0.5')).toBe(0.5);
21
- });
22
- it('returns NaN when step is a non-numeric string', () => {
23
- expect(getStep('foo')).toBeNaN();
24
- expect(getStep('invalid')).toBeNaN();
25
- });
26
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,28 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { getShowCodeHref } from '../shared/showcase/show-code-link';
3
- describe('getShowCodeHref', () => {
4
- it('returns localhost react storybook url on localhost', () => {
5
- expect(getShowCodeHref('http://localhost:3000/core-web/sub/components/action/button/overview', 'react')).toBe('http://localhost:6005/?path=/docs/components-dbbutton');
6
- });
7
- it('returns localhost angular storybook url on localhost', () => {
8
- expect(getShowCodeHref('http://localhost:3000/core-web/sub/components/action/button/overview', 'angular')).toBe('http://localhost:6006/?path=/docs/components-dbbutton');
9
- });
10
- it('returns localhost vue storybook url on localhost', () => {
11
- expect(getShowCodeHref('http://127.0.0.1:3000/core-web/sub/components/action/button/overview', 'vue')).toBe('http://127.0.0.1:6007/?path=/docs/components-dbbutton');
12
- });
13
- it('returns localhost html storybook url on localhost', () => {
14
- expect(getShowCodeHref('http://localhost:3000/core-web/sub/components/action/button/overview', 'html')).toBe('http://localhost:6001/?path=/docs/components-dbbutton');
15
- });
16
- it('returns localhost url for direct docs route', () => {
17
- expect(getShowCodeHref('http://localhost:3000/core-web/components/button/docs', 'react')).toBe('http://localhost:6005/?path=/docs/components-dbbutton');
18
- });
19
- it('returns production url for non-localhost', () => {
20
- expect(getShowCodeHref('https://db-ui.com/core-web/sub/components/action/button/overview', 'react')).toBe('https://db-ui.com/core-web/sub/react-storybook?path=/docs/components-dbbutton');
21
- });
22
- it('returns undefined if url has no components segment', () => {
23
- expect(getShowCodeHref('https://db-ui.com/core-web/sub/', 'react')).toBe(undefined);
24
- });
25
- it('returns undefined for components root route', () => {
26
- expect(getShowCodeHref('https://db-ui.com/core-web/components', 'react')).toBe(undefined);
27
- });
28
- });