@dbcdk/react-components 0.0.172 → 0.0.173

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.
@@ -39,14 +39,15 @@ function Grid({
39
39
  );
40
40
  }
41
41
  function GridItem({ children, base = 12, md, lg, className, style }) {
42
+ const toTrackSpan = (span) => span * 2;
42
43
  return /* @__PURE__ */ jsxRuntime.jsx(
43
44
  "div",
44
45
  {
45
46
  className: [styles__default.default.item, className].filter(Boolean).join(" "),
46
47
  style: {
47
- "--span-base": base,
48
- ...md != null ? { "--span-md": md } : {},
49
- ...lg != null ? { "--span-lg": lg } : {},
48
+ "--span-base": toTrackSpan(base),
49
+ ...md != null ? { "--span-md": toTrackSpan(md) } : {},
50
+ ...lg != null ? { "--span-lg": toTrackSpan(lg) } : {},
50
51
  ...style
51
52
  },
52
53
  children
@@ -17,11 +17,11 @@ export interface GridProps {
17
17
  export declare function Grid({ children, gap, equalHeight, maxWidth, className, style, }: GridProps): import("react/jsx-runtime").JSX.Element;
18
18
  export interface GridItemProps {
19
19
  children?: ReactNode;
20
- /** Default span: <768px */
20
+ /** Default span: <768px. Supports 0.5 increments, e.g. 4.5 */
21
21
  base?: number;
22
- /** Medium span: ≥768px */
22
+ /** Medium span: ≥768px. Supports 0.5 increments, e.g. 4.5 */
23
23
  md?: number;
24
- /** Large span: ≥1200px */
24
+ /** Large span: ≥1200px. Supports 0.5 increments, e.g. 4.5 */
25
25
  lg?: number;
26
26
  className?: string;
27
27
  style?: CSSProperties;
@@ -33,14 +33,15 @@ function Grid({
33
33
  );
34
34
  }
35
35
  function GridItem({ children, base = 12, md, lg, className, style }) {
36
+ const toTrackSpan = (span) => span * 2;
36
37
  return /* @__PURE__ */ jsx(
37
38
  "div",
38
39
  {
39
40
  className: [styles.item, className].filter(Boolean).join(" "),
40
41
  style: {
41
- "--span-base": base,
42
- ...md != null ? { "--span-md": md } : {},
43
- ...lg != null ? { "--span-lg": lg } : {},
42
+ "--span-base": toTrackSpan(base),
43
+ ...md != null ? { "--span-md": toTrackSpan(md) } : {},
44
+ ...lg != null ? { "--span-lg": toTrackSpan(lg) } : {},
44
45
  ...style
45
46
  },
46
47
  children
@@ -1,6 +1,6 @@
1
1
  .grid {
2
2
  display: grid;
3
- grid-template-columns: repeat(12, minmax(0, 1fr));
3
+ grid-template-columns: repeat(24, minmax(0, 1fr));
4
4
  align-items: start;
5
5
  max-width: var(--max-width-base);
6
6
  }
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
4
5
  var client = require('../../client');
5
6
  var styles = require('./MetricTile.module.css');
6
7
 
@@ -11,23 +12,91 @@ var styles__default = /*#__PURE__*/_interopDefault(styles);
11
12
  function toSize(v) {
12
13
  return typeof v === "number" ? `${v}px` : v;
13
14
  }
14
- function MetricTile({
15
+ function getSlotName(el) {
16
+ var _a;
17
+ const t = el.type;
18
+ return (_a = t.__METRIC_TILE_SLOT__) != null ? _a : null;
19
+ }
20
+ function splitSlots(children) {
21
+ const slots = {};
22
+ const rest = [];
23
+ react.Children.forEach(children, (child) => {
24
+ if (!react.isValidElement(child)) {
25
+ if (child != null) rest.push(child);
26
+ return;
27
+ }
28
+ const slot = getSlotName(child);
29
+ if (!slot) {
30
+ rest.push(child);
31
+ return;
32
+ }
33
+ slots[slot] = child;
34
+ });
35
+ return { slots, rest };
36
+ }
37
+ const MetricTileValue = ({
38
+ children
39
+ }) => {
40
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
41
+ };
42
+ MetricTileValue.__METRIC_TILE_SLOT__ = "Value";
43
+ MetricTileValue.displayName = "MetricTile.Value";
44
+ const MetricTileAdornment = ({ children }) => {
45
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
46
+ };
47
+ MetricTileAdornment.__METRIC_TILE_SLOT__ = "Adornment";
48
+ MetricTileAdornment.displayName = "MetricTile.Adornment";
49
+ const MetricTileBase = ({
15
50
  severity,
16
51
  label,
52
+ icon,
17
53
  value,
18
54
  tooltip,
19
55
  size = "md",
56
+ variant = "filled",
20
57
  minWidth,
21
- maxWidth
22
- }) {
58
+ maxWidth,
59
+ secondaryLabel,
60
+ secondaryValue,
61
+ children
62
+ }) => {
63
+ var _a, _b, _c;
23
64
  const style = minWidth != null || maxWidth != null ? {
24
65
  ...minWidth != null ? { minWidth: toSize(minWidth) } : {},
25
66
  ...maxWidth != null ? { maxWidth: toSize(maxWidth) } : {}
26
67
  } : void 0;
27
- return /* @__PURE__ */ jsxRuntime.jsx(client.Tooltip, { content: tooltip, placement: "bottom", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.tile, "data-severity": severity, "data-size": size, style, children: [
28
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label }),
29
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.value, children: value })
30
- ] }) });
31
- }
68
+ const { slots } = splitSlots(children);
69
+ const resolvedValue = (_b = (_a = slots.Value) == null ? void 0 : _a.props.children) != null ? _b : value;
70
+ const resolvedAdornment = (_c = slots.Adornment) == null ? void 0 : _c.props.children;
71
+ const showValueRow = resolvedValue != null || resolvedAdornment != null;
72
+ return /* @__PURE__ */ jsxRuntime.jsx(client.Tooltip, { content: tooltip, placement: "bottom", children: /* @__PURE__ */ jsxRuntime.jsxs(
73
+ "span",
74
+ {
75
+ className: styles__default.default.tile,
76
+ "data-severity": severity,
77
+ "data-size": size,
78
+ "data-variant": variant,
79
+ style,
80
+ children: [
81
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.labelRow, children: [
82
+ icon != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: icon }) : null,
83
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: label })
84
+ ] }),
85
+ showValueRow ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.valueRow, children: [
86
+ resolvedValue != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.value, children: resolvedValue }) : null,
87
+ resolvedAdornment != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.adornment, children: resolvedAdornment }) : null
88
+ ] }) : null,
89
+ secondaryLabel != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.secondary, children: [
90
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.secondaryLabel, children: secondaryLabel }),
91
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.secondaryValue, children: secondaryValue })
92
+ ] })
93
+ ]
94
+ }
95
+ ) });
96
+ };
97
+ const MetricTile = Object.assign(MetricTileBase, {
98
+ Value: MetricTileValue,
99
+ Adornment: MetricTileAdornment
100
+ });
32
101
 
33
102
  exports.MetricTile = MetricTile;
@@ -1,15 +1,28 @@
1
- import type { ReactNode, JSX } from 'react';
1
+ import type { FC, JSX, PropsWithChildren, ReactNode } from 'react';
2
2
  import { Severity } from '../../constants/severity.types';
3
3
  type MetricTileSize = 'sm' | 'md' | 'lg';
4
+ type MetricTileVariant = 'filled' | 'outlined';
4
5
  type SizeValue = number | string;
5
- interface MetricTileProps {
6
+ interface MetricTileSlotProps {
7
+ children: ReactNode;
8
+ }
9
+ interface MetricTileProps extends PropsWithChildren {
6
10
  severity: Severity;
7
11
  label: string;
8
- value: string | number;
12
+ icon?: JSX.Element;
13
+ value?: string | number;
9
14
  tooltip?: ReactNode;
10
15
  size?: MetricTileSize;
16
+ variant?: MetricTileVariant;
11
17
  minWidth?: SizeValue;
12
18
  maxWidth?: SizeValue;
19
+ /** Smaller secondary label shown below the main value, e.g. a second time period. */
20
+ secondaryLabel?: string;
21
+ /** Smaller secondary value shown alongside secondaryLabel. Ignored if secondaryLabel is omitted. */
22
+ secondaryValue?: string | number;
13
23
  }
14
- export declare function MetricTile({ severity, label, value, tooltip, size, minWidth, maxWidth, }: MetricTileProps): JSX.Element;
24
+ export declare const MetricTile: FC<MetricTileProps> & {
25
+ Value: FC<MetricTileSlotProps>;
26
+ Adornment: FC<MetricTileSlotProps>;
27
+ };
15
28
  export {};
@@ -1,27 +1,96 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
+ import { Children, isValidElement } from 'react';
2
3
  import { Tooltip } from '../../client';
3
4
  import styles from './MetricTile.module.css';
4
5
 
5
6
  function toSize(v) {
6
7
  return typeof v === "number" ? `${v}px` : v;
7
8
  }
8
- function MetricTile({
9
+ function getSlotName(el) {
10
+ var _a;
11
+ const t = el.type;
12
+ return (_a = t.__METRIC_TILE_SLOT__) != null ? _a : null;
13
+ }
14
+ function splitSlots(children) {
15
+ const slots = {};
16
+ const rest = [];
17
+ Children.forEach(children, (child) => {
18
+ if (!isValidElement(child)) {
19
+ if (child != null) rest.push(child);
20
+ return;
21
+ }
22
+ const slot = getSlotName(child);
23
+ if (!slot) {
24
+ rest.push(child);
25
+ return;
26
+ }
27
+ slots[slot] = child;
28
+ });
29
+ return { slots, rest };
30
+ }
31
+ const MetricTileValue = ({
32
+ children
33
+ }) => {
34
+ return /* @__PURE__ */ jsx(Fragment, { children });
35
+ };
36
+ MetricTileValue.__METRIC_TILE_SLOT__ = "Value";
37
+ MetricTileValue.displayName = "MetricTile.Value";
38
+ const MetricTileAdornment = ({ children }) => {
39
+ return /* @__PURE__ */ jsx(Fragment, { children });
40
+ };
41
+ MetricTileAdornment.__METRIC_TILE_SLOT__ = "Adornment";
42
+ MetricTileAdornment.displayName = "MetricTile.Adornment";
43
+ const MetricTileBase = ({
9
44
  severity,
10
45
  label,
46
+ icon,
11
47
  value,
12
48
  tooltip,
13
49
  size = "md",
50
+ variant = "filled",
14
51
  minWidth,
15
- maxWidth
16
- }) {
52
+ maxWidth,
53
+ secondaryLabel,
54
+ secondaryValue,
55
+ children
56
+ }) => {
57
+ var _a, _b, _c;
17
58
  const style = minWidth != null || maxWidth != null ? {
18
59
  ...minWidth != null ? { minWidth: toSize(minWidth) } : {},
19
60
  ...maxWidth != null ? { maxWidth: toSize(maxWidth) } : {}
20
61
  } : void 0;
21
- return /* @__PURE__ */ jsx(Tooltip, { content: tooltip, placement: "bottom", children: /* @__PURE__ */ jsxs("span", { className: styles.tile, "data-severity": severity, "data-size": size, style, children: [
22
- /* @__PURE__ */ jsx("span", { className: styles.label, children: label }),
23
- /* @__PURE__ */ jsx("span", { className: styles.value, children: value })
24
- ] }) });
25
- }
62
+ const { slots } = splitSlots(children);
63
+ const resolvedValue = (_b = (_a = slots.Value) == null ? void 0 : _a.props.children) != null ? _b : value;
64
+ const resolvedAdornment = (_c = slots.Adornment) == null ? void 0 : _c.props.children;
65
+ const showValueRow = resolvedValue != null || resolvedAdornment != null;
66
+ return /* @__PURE__ */ jsx(Tooltip, { content: tooltip, placement: "bottom", children: /* @__PURE__ */ jsxs(
67
+ "span",
68
+ {
69
+ className: styles.tile,
70
+ "data-severity": severity,
71
+ "data-size": size,
72
+ "data-variant": variant,
73
+ style,
74
+ children: [
75
+ /* @__PURE__ */ jsxs("span", { className: styles.labelRow, children: [
76
+ icon != null ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: icon }) : null,
77
+ /* @__PURE__ */ jsx("span", { className: styles.label, children: label })
78
+ ] }),
79
+ showValueRow ? /* @__PURE__ */ jsxs("span", { className: styles.valueRow, children: [
80
+ resolvedValue != null ? /* @__PURE__ */ jsx("span", { className: styles.value, children: resolvedValue }) : null,
81
+ resolvedAdornment != null ? /* @__PURE__ */ jsx("span", { className: styles.adornment, children: resolvedAdornment }) : null
82
+ ] }) : null,
83
+ secondaryLabel != null && /* @__PURE__ */ jsxs("span", { className: styles.secondary, children: [
84
+ /* @__PURE__ */ jsx("span", { className: styles.secondaryLabel, children: secondaryLabel }),
85
+ /* @__PURE__ */ jsx("span", { className: styles.secondaryValue, children: secondaryValue })
86
+ ] })
87
+ ]
88
+ }
89
+ ) });
90
+ };
91
+ const MetricTile = Object.assign(MetricTileBase, {
92
+ Value: MetricTileValue,
93
+ Adornment: MetricTileAdornment
94
+ });
26
95
 
27
96
  export { MetricTile };
@@ -1,4 +1,7 @@
1
1
  .tile {
2
+ --metric-tile-bg: var(--color-bg-surface);
3
+ --metric-tile-fg: var(--color-fg-default);
4
+ --metric-tile-outline: var(--color-border-default);
2
5
  display: inline-flex;
3
6
  flex-direction: column;
4
7
  align-items: center;
@@ -9,6 +12,9 @@
9
12
  overflow: hidden;
10
13
  box-sizing: border-box;
11
14
  border-radius: var(--border-radius-md);
15
+ border: var(--border-width-thin) solid transparent;
16
+ background-color: var(--metric-tile-bg);
17
+ color: var(--metric-tile-fg);
12
18
  font-family: var(--font-family);
13
19
  cursor: default;
14
20
  }
@@ -20,6 +26,10 @@
20
26
  border-radius: var(--border-radius-sm);
21
27
  }
22
28
 
29
+ .tile[data-size='md'] {
30
+ gap: 8px;
31
+ }
32
+
23
33
  .tile[data-size='lg'] {
24
34
  gap: var(--spacing-2xs);
25
35
  padding: var(--spacing-md) var(--spacing-lg);
@@ -28,55 +38,86 @@
28
38
  }
29
39
 
30
40
  .tile[data-severity='success'] {
31
- background-color: var(--color-status-success-bg-soft);
32
- color: var(--color-status-success-fg-soft);
41
+ --metric-tile-bg: var(--color-status-success-bg-soft);
42
+ --metric-tile-fg: var(--color-status-success-fg-soft);
43
+ --metric-tile-outline: var(--color-status-success-fg-soft);
33
44
  }
34
45
 
35
46
  .tile[data-severity='error'] {
36
- background-color: var(--color-status-error-bg-soft);
37
- color: var(--color-status-error-fg-soft);
47
+ --metric-tile-bg: var(--color-status-error-bg-soft);
48
+ --metric-tile-fg: var(--color-status-error-fg-soft);
49
+ --metric-tile-outline: var(--color-status-error-fg-soft);
38
50
  }
39
51
 
40
52
  .tile[data-severity='warning'] {
41
- background-color: var(--color-status-warning-bg-soft);
42
- color: var(--color-status-warning-fg-soft);
53
+ --metric-tile-bg: var(--color-status-warning-bg-soft);
54
+ --metric-tile-fg: var(--color-status-warning-fg-soft);
55
+ --metric-tile-outline: var(--color-status-warning-fg-soft);
43
56
  }
44
57
 
45
58
  .tile[data-severity='info'] {
46
- background-color: var(--color-status-info-bg-soft);
47
- color: var(--color-status-info-fg-soft);
59
+ --metric-tile-bg: var(--color-status-info-bg-soft);
60
+ --metric-tile-fg: var(--color-status-info-fg-soft);
61
+ --metric-tile-outline: var(--color-status-info-fg-soft);
48
62
  }
49
63
 
50
64
  .tile[data-severity='neutral'] {
51
- background-color: var(--color-bg-toolbar);
52
- color: var(--color-fg-default);
65
+ --metric-tile-bg: var(--color-bg-toolbar);
66
+ --metric-tile-fg: var(--color-fg-default);
67
+ --metric-tile-outline: var(--color-border-default);
53
68
  }
54
69
 
55
70
  .tile[data-severity='brand'] {
56
- background-color: var(--color-brand);
57
- color: var(--color-fg-on-brand);
71
+ --metric-tile-bg: var(--color-brand);
72
+ --metric-tile-fg: var(--color-fg-on-brand);
73
+ --metric-tile-outline: var(--color-brand);
58
74
  }
59
75
 
60
76
  .tile[data-severity='accent'] {
61
- background-color: var(--color-accent-bg-soft);
62
- color: var(--color-accent-fg-soft);
77
+ --metric-tile-bg: var(--color-accent-bg-soft);
78
+ --metric-tile-fg: var(--color-accent-fg-soft);
79
+ --metric-tile-outline: var(--color-accent-fg-soft);
80
+ }
81
+
82
+ .tile[data-variant='outlined'] {
83
+ background-color: var(--color-bg-surface);
84
+ color: var(--color-fg-default);
85
+ border-color: var(--metric-tile-outline);
86
+ }
87
+
88
+ .labelRow {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ gap: var(--spacing-xxs);
92
+ max-width: 100%;
93
+ min-width: 0;
63
94
  }
64
95
 
65
96
  .label {
66
97
  font-size: var(--font-size-xs);
67
- font-weight: var(--font-weight-semibold, 600);
68
- text-transform: uppercase;
69
- letter-spacing: var(--letter-spacing-wide);
98
+ font-weight: 400;
99
+ color: var(--color-fg-subtle);
70
100
  line-height: 1;
71
- opacity: 0.85;
72
101
  max-width: 100%;
73
102
  overflow: hidden;
74
103
  white-space: nowrap;
75
104
  text-overflow: ellipsis;
76
105
  }
77
106
 
107
+ .icon {
108
+ display: inline-flex;
109
+ align-items: center;
110
+ flex: 0 0 auto;
111
+ }
112
+
113
+ .icon :global(svg) {
114
+ width: 0.9em;
115
+ height: 0.9em;
116
+ }
117
+
78
118
  .value {
79
119
  font-size: var(--font-size-md);
120
+ font-weight: 500;
80
121
  line-height: 1;
81
122
  font-variant-numeric: tabular-nums;
82
123
  max-width: 100%;
@@ -85,15 +126,51 @@
85
126
  text-overflow: ellipsis;
86
127
  }
87
128
 
129
+ .valueRow {
130
+ display: inline-flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ gap: var(--spacing-xxs);
134
+ max-width: 100%;
135
+ min-width: 0;
136
+ }
137
+
138
+ .adornment {
139
+ display: inline-flex;
140
+ align-items: center;
141
+ gap: var(--spacing-xxs);
142
+ flex: 0 0 auto;
143
+ font-size: var(--font-size-xs);
144
+ line-height: 1;
145
+ opacity: 0.9;
146
+ }
147
+
148
+ .adornment :global(svg) {
149
+ width: 0.9em;
150
+ height: 0.9em;
151
+ }
152
+
88
153
  .tile[data-size='sm'] .label {
89
154
  font-size: var(--font-size-xs);
90
- letter-spacing: normal;
155
+ }
156
+
157
+ .tile[data-size='sm'] .labelRow {
158
+ gap: 2px;
91
159
  }
92
160
 
93
161
  .tile[data-size='sm'] .value {
94
162
  font-size: var(--font-size-xs);
95
163
  }
96
164
 
165
+ .tile[data-size='sm'] .valueRow {
166
+ gap: 2px;
167
+ }
168
+
169
+ .tile[data-size='sm'] .adornment {
170
+ gap: 2px;
171
+ font-size: 10px;
172
+ }
173
+
97
174
  .tile[data-size='lg'] .label {
98
175
  font-size: var(--font-size-sm);
99
176
  }
@@ -101,3 +178,29 @@
101
178
  .tile[data-size='lg'] .value {
102
179
  font-size: var(--font-size-xl);
103
180
  }
181
+
182
+ .secondary {
183
+ display: flex;
184
+ align-items: baseline;
185
+ gap: var(--spacing-2xs, 4px);
186
+ font-size: var(--font-size-xs);
187
+ opacity: 0.75;
188
+ max-width: 100%;
189
+ overflow: hidden;
190
+ white-space: nowrap;
191
+ }
192
+
193
+ .secondaryLabel {
194
+ text-transform: none;
195
+ letter-spacing: normal;
196
+ }
197
+
198
+ .secondaryValue {
199
+ font-variant-numeric: tabular-nums;
200
+ overflow: hidden;
201
+ text-overflow: ellipsis;
202
+ }
203
+
204
+ .tile[data-size='sm'] .secondary {
205
+ font-size: 10px;
206
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.172",
3
+ "version": "0.0.173",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",