@dbcdk/react-components 0.0.171 → 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.
- package/dist/components/grid/Grid.cjs +4 -3
- package/dist/components/grid/Grid.d.ts +3 -3
- package/dist/components/grid/Grid.js +4 -3
- package/dist/components/grid/Grid.module.css +1 -1
- package/dist/components/headline/Headline.module.css +0 -4
- package/dist/components/metric-tile/MetricTile.cjs +77 -8
- package/dist/components/metric-tile/MetricTile.d.ts +17 -4
- package/dist/components/metric-tile/MetricTile.js +78 -9
- package/dist/components/metric-tile/MetricTile.module.css +122 -19
- package/dist/components/theme-script/ThemeScript.cjs +22 -0
- package/dist/components/theme-script/ThemeScript.d.ts +25 -0
- package/dist/components/theme-script/ThemeScript.js +20 -0
- package/dist/hooks/useTheme.cjs +57 -31
- package/dist/hooks/useTheme.d.ts +2 -3
- package/dist/hooks/useTheme.js +58 -32
- package/dist/index.cjs +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/utils/theme.constants.cjs +11 -0
- package/dist/utils/theme.constants.d.ts +4 -0
- package/dist/utils/theme.constants.js +7 -0
- package/package.json +1 -1
|
@@ -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,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
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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 {
|
|
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
|
|
6
|
+
interface MetricTileSlotProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
interface MetricTileProps extends PropsWithChildren {
|
|
6
10
|
severity: Severity;
|
|
7
11
|
label: string;
|
|
8
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
57
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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:
|
|
68
|
-
|
|
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
|
-
|
|
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
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var theme_constants = require('../../utils/theme.constants');
|
|
5
|
+
|
|
6
|
+
function buildThemeInitScript(defaultTheme) {
|
|
7
|
+
return `(function(){try{
|
|
8
|
+
var KEY=${JSON.stringify(theme_constants.THEME_STORAGE_KEY)};
|
|
9
|
+
var VARIANTS=${JSON.stringify(theme_constants.THEME_VARIANTS)};
|
|
10
|
+
function isVariant(x){return !!x && VARIANTS.indexOf(x)!==-1}
|
|
11
|
+
function getCookie(name){var m=document.cookie.match(new RegExp('(?:^|; )'+name+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}
|
|
12
|
+
var resolved=${JSON.stringify(defaultTheme)};
|
|
13
|
+
var fromCookie=getCookie(KEY);
|
|
14
|
+
if(isVariant(fromCookie)){resolved=fromCookie}else{try{var fromStorage=localStorage.getItem(KEY);if(isVariant(fromStorage))resolved=fromStorage}catch(e){}}
|
|
15
|
+
document.documentElement.dataset.theme=resolved;
|
|
16
|
+
}catch(e){}})();`;
|
|
17
|
+
}
|
|
18
|
+
function ThemeScript({ defaultTheme = "system" }) {
|
|
19
|
+
return /* @__PURE__ */ jsxRuntime.jsx("script", { dangerouslySetInnerHTML: { __html: buildThemeInitScript(defaultTheme) } });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.ThemeScript = ThemeScript;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ThemeVariant } from '../../utils/theme.constants';
|
|
2
|
+
export interface ThemeScriptProps {
|
|
3
|
+
/** Theme applied when nothing is stored yet. Defaults to 'system'. */
|
|
4
|
+
defaultTheme?: ThemeVariant;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Renders a blocking inline <script> that reads the persisted theme (cookie,
|
|
8
|
+
* falling back to localStorage) and sets `data-theme` on <html> synchronously
|
|
9
|
+
* — before the page paints and before React hydrates.
|
|
10
|
+
*
|
|
11
|
+
* `useTheme()` alone cannot prevent a flash of the wrong theme on load: its
|
|
12
|
+
* resolution runs inside a `useEffect`, which by definition only fires after
|
|
13
|
+
* the first render has already been committed (and, server-side, there is no
|
|
14
|
+
* `document` to read a cookie from at all). Closing that gap requires code
|
|
15
|
+
* that runs outside React's render lifecycle — this component is that code.
|
|
16
|
+
*
|
|
17
|
+
* Place it as early as possible in <head>, e.g. in Next.js's `_document.js`:
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <Head>
|
|
21
|
+
* <ThemeScript />
|
|
22
|
+
* </Head>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function ThemeScript({ defaultTheme }: ThemeScriptProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { THEME_STORAGE_KEY, THEME_VARIANTS } from '../../utils/theme.constants';
|
|
3
|
+
|
|
4
|
+
function buildThemeInitScript(defaultTheme) {
|
|
5
|
+
return `(function(){try{
|
|
6
|
+
var KEY=${JSON.stringify(THEME_STORAGE_KEY)};
|
|
7
|
+
var VARIANTS=${JSON.stringify(THEME_VARIANTS)};
|
|
8
|
+
function isVariant(x){return !!x && VARIANTS.indexOf(x)!==-1}
|
|
9
|
+
function getCookie(name){var m=document.cookie.match(new RegExp('(?:^|; )'+name+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}
|
|
10
|
+
var resolved=${JSON.stringify(defaultTheme)};
|
|
11
|
+
var fromCookie=getCookie(KEY);
|
|
12
|
+
if(isVariant(fromCookie)){resolved=fromCookie}else{try{var fromStorage=localStorage.getItem(KEY);if(isVariant(fromStorage))resolved=fromStorage}catch(e){}}
|
|
13
|
+
document.documentElement.dataset.theme=resolved;
|
|
14
|
+
}catch(e){}})();`;
|
|
15
|
+
}
|
|
16
|
+
function ThemeScript({ defaultTheme = "system" }) {
|
|
17
|
+
return /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: buildThemeInitScript(defaultTheme) } });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { ThemeScript };
|
package/dist/hooks/useTheme.cjs
CHANGED
|
@@ -2,62 +2,88 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var react = require('react');
|
|
5
|
+
var theme_constants = require('../utils/theme.constants');
|
|
5
6
|
|
|
6
|
-
const THEME_VARIANTS = ["light", "dark", "system"];
|
|
7
|
-
const STORAGE_KEY = "dbc_theme";
|
|
8
|
-
function isThemeVariant(x) {
|
|
9
|
-
return !!x && THEME_VARIANTS.includes(x);
|
|
10
|
-
}
|
|
11
7
|
function getCookie(name) {
|
|
12
8
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
13
9
|
return match ? decodeURIComponent(match[1]) : null;
|
|
14
10
|
}
|
|
15
11
|
function persistTheme(id) {
|
|
16
12
|
try {
|
|
17
|
-
localStorage.setItem(
|
|
13
|
+
localStorage.setItem(theme_constants.THEME_STORAGE_KEY, id);
|
|
18
14
|
} catch {
|
|
19
15
|
console.error("Failed to access localStorage");
|
|
20
16
|
}
|
|
21
17
|
try {
|
|
22
|
-
document.cookie = `${
|
|
18
|
+
document.cookie = `${theme_constants.THEME_STORAGE_KEY}=${encodeURIComponent(
|
|
23
19
|
id
|
|
24
20
|
)}; Path=/; Max-Age=${60 * 60 * 24 * 365}`;
|
|
25
21
|
} catch {
|
|
26
22
|
console.error("Failed to set theme cookie");
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
function
|
|
25
|
+
function getDomTheme() {
|
|
30
26
|
return document.documentElement.dataset.theme;
|
|
31
27
|
}
|
|
32
28
|
function applyTheme(id) {
|
|
33
29
|
document.documentElement.dataset.theme = id;
|
|
34
30
|
}
|
|
31
|
+
let currentTheme = null;
|
|
32
|
+
let resolved = false;
|
|
33
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
34
|
+
function notify() {
|
|
35
|
+
listeners.forEach((listener) => listener());
|
|
36
|
+
}
|
|
37
|
+
function subscribe(listener) {
|
|
38
|
+
listeners.add(listener);
|
|
39
|
+
return () => {
|
|
40
|
+
listeners.delete(listener);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function getSnapshot() {
|
|
44
|
+
return currentTheme;
|
|
45
|
+
}
|
|
46
|
+
function getServerSnapshot() {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function resolveInitialTheme(initialTheme) {
|
|
50
|
+
const themeFromDataAttributes = getDomTheme();
|
|
51
|
+
let resolvedTheme = theme_constants.isThemeVariant(themeFromDataAttributes) ? themeFromDataAttributes : initialTheme;
|
|
52
|
+
const fromCookie = getCookie(theme_constants.THEME_STORAGE_KEY);
|
|
53
|
+
if (theme_constants.isThemeVariant(fromCookie)) {
|
|
54
|
+
resolvedTheme = fromCookie;
|
|
55
|
+
} else {
|
|
56
|
+
try {
|
|
57
|
+
const fromStorage = localStorage.getItem(theme_constants.THEME_STORAGE_KEY);
|
|
58
|
+
if (theme_constants.isThemeVariant(fromStorage)) resolvedTheme = fromStorage;
|
|
59
|
+
} catch {
|
|
60
|
+
console.error("Failed to access localStorage");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return resolvedTheme;
|
|
64
|
+
}
|
|
65
|
+
function ensureResolved(initialTheme) {
|
|
66
|
+
if (resolved) return;
|
|
67
|
+
resolved = true;
|
|
68
|
+
const value = resolveInitialTheme(initialTheme);
|
|
69
|
+
applyTheme(value);
|
|
70
|
+
persistTheme(value);
|
|
71
|
+
currentTheme = value;
|
|
72
|
+
notify();
|
|
73
|
+
}
|
|
74
|
+
function switchTheme(id) {
|
|
75
|
+
applyTheme(id);
|
|
76
|
+
persistTheme(id);
|
|
77
|
+
currentTheme = id;
|
|
78
|
+
resolved = true;
|
|
79
|
+
notify();
|
|
80
|
+
return id;
|
|
81
|
+
}
|
|
35
82
|
function useTheme(initialTheme = "system") {
|
|
36
|
-
const [theme, setTheme] = react.useState(null);
|
|
37
83
|
react.useEffect(() => {
|
|
38
|
-
|
|
39
|
-
let resolved = isThemeVariant(themeFromDataAttributes) ? themeFromDataAttributes : initialTheme;
|
|
40
|
-
const fromCookie = getCookie(STORAGE_KEY);
|
|
41
|
-
if (isThemeVariant(fromCookie)) {
|
|
42
|
-
resolved = fromCookie;
|
|
43
|
-
} else {
|
|
44
|
-
try {
|
|
45
|
-
const fromStorage = localStorage.getItem(STORAGE_KEY);
|
|
46
|
-
if (isThemeVariant(fromStorage)) resolved = fromStorage;
|
|
47
|
-
} catch {
|
|
48
|
-
console.error("Failed to access localStorage");
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
applyTheme(resolved);
|
|
52
|
-
setTheme(resolved);
|
|
53
|
-
persistTheme(resolved);
|
|
84
|
+
ensureResolved(initialTheme);
|
|
54
85
|
}, [initialTheme]);
|
|
55
|
-
const
|
|
56
|
-
applyTheme(id);
|
|
57
|
-
setTheme(id);
|
|
58
|
-
persistTheme(id);
|
|
59
|
-
return id;
|
|
60
|
-
}, []);
|
|
86
|
+
const theme = react.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
61
87
|
return { theme, switchTheme };
|
|
62
88
|
}
|
|
63
89
|
|
package/dist/hooks/useTheme.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
export type ThemeVariant
|
|
1
|
+
import type { ThemeVariant } from '../utils/theme.constants';
|
|
2
|
+
export type { ThemeVariant };
|
|
3
3
|
export declare function useTheme(initialTheme?: ThemeVariant): {
|
|
4
4
|
theme: ThemeVariant | null;
|
|
5
5
|
switchTheme: (id: ThemeVariant) => ThemeVariant;
|
|
6
6
|
};
|
|
7
|
-
export {};
|
package/dist/hooks/useTheme.js
CHANGED
|
@@ -1,61 +1,87 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useSyncExternalStore } from 'react';
|
|
3
|
+
import { isThemeVariant, THEME_STORAGE_KEY } from '../utils/theme.constants';
|
|
3
4
|
|
|
4
|
-
const THEME_VARIANTS = ["light", "dark", "system"];
|
|
5
|
-
const STORAGE_KEY = "dbc_theme";
|
|
6
|
-
function isThemeVariant(x) {
|
|
7
|
-
return !!x && THEME_VARIANTS.includes(x);
|
|
8
|
-
}
|
|
9
5
|
function getCookie(name) {
|
|
10
6
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
11
7
|
return match ? decodeURIComponent(match[1]) : null;
|
|
12
8
|
}
|
|
13
9
|
function persistTheme(id) {
|
|
14
10
|
try {
|
|
15
|
-
localStorage.setItem(
|
|
11
|
+
localStorage.setItem(THEME_STORAGE_KEY, id);
|
|
16
12
|
} catch {
|
|
17
13
|
console.error("Failed to access localStorage");
|
|
18
14
|
}
|
|
19
15
|
try {
|
|
20
|
-
document.cookie = `${
|
|
16
|
+
document.cookie = `${THEME_STORAGE_KEY}=${encodeURIComponent(
|
|
21
17
|
id
|
|
22
18
|
)}; Path=/; Max-Age=${60 * 60 * 24 * 365}`;
|
|
23
19
|
} catch {
|
|
24
20
|
console.error("Failed to set theme cookie");
|
|
25
21
|
}
|
|
26
22
|
}
|
|
27
|
-
function
|
|
23
|
+
function getDomTheme() {
|
|
28
24
|
return document.documentElement.dataset.theme;
|
|
29
25
|
}
|
|
30
26
|
function applyTheme(id) {
|
|
31
27
|
document.documentElement.dataset.theme = id;
|
|
32
28
|
}
|
|
29
|
+
let currentTheme = null;
|
|
30
|
+
let resolved = false;
|
|
31
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
32
|
+
function notify() {
|
|
33
|
+
listeners.forEach((listener) => listener());
|
|
34
|
+
}
|
|
35
|
+
function subscribe(listener) {
|
|
36
|
+
listeners.add(listener);
|
|
37
|
+
return () => {
|
|
38
|
+
listeners.delete(listener);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function getSnapshot() {
|
|
42
|
+
return currentTheme;
|
|
43
|
+
}
|
|
44
|
+
function getServerSnapshot() {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
function resolveInitialTheme(initialTheme) {
|
|
48
|
+
const themeFromDataAttributes = getDomTheme();
|
|
49
|
+
let resolvedTheme = isThemeVariant(themeFromDataAttributes) ? themeFromDataAttributes : initialTheme;
|
|
50
|
+
const fromCookie = getCookie(THEME_STORAGE_KEY);
|
|
51
|
+
if (isThemeVariant(fromCookie)) {
|
|
52
|
+
resolvedTheme = fromCookie;
|
|
53
|
+
} else {
|
|
54
|
+
try {
|
|
55
|
+
const fromStorage = localStorage.getItem(THEME_STORAGE_KEY);
|
|
56
|
+
if (isThemeVariant(fromStorage)) resolvedTheme = fromStorage;
|
|
57
|
+
} catch {
|
|
58
|
+
console.error("Failed to access localStorage");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return resolvedTheme;
|
|
62
|
+
}
|
|
63
|
+
function ensureResolved(initialTheme) {
|
|
64
|
+
if (resolved) return;
|
|
65
|
+
resolved = true;
|
|
66
|
+
const value = resolveInitialTheme(initialTheme);
|
|
67
|
+
applyTheme(value);
|
|
68
|
+
persistTheme(value);
|
|
69
|
+
currentTheme = value;
|
|
70
|
+
notify();
|
|
71
|
+
}
|
|
72
|
+
function switchTheme(id) {
|
|
73
|
+
applyTheme(id);
|
|
74
|
+
persistTheme(id);
|
|
75
|
+
currentTheme = id;
|
|
76
|
+
resolved = true;
|
|
77
|
+
notify();
|
|
78
|
+
return id;
|
|
79
|
+
}
|
|
33
80
|
function useTheme(initialTheme = "system") {
|
|
34
|
-
const [theme, setTheme] = useState(null);
|
|
35
81
|
useEffect(() => {
|
|
36
|
-
|
|
37
|
-
let resolved = isThemeVariant(themeFromDataAttributes) ? themeFromDataAttributes : initialTheme;
|
|
38
|
-
const fromCookie = getCookie(STORAGE_KEY);
|
|
39
|
-
if (isThemeVariant(fromCookie)) {
|
|
40
|
-
resolved = fromCookie;
|
|
41
|
-
} else {
|
|
42
|
-
try {
|
|
43
|
-
const fromStorage = localStorage.getItem(STORAGE_KEY);
|
|
44
|
-
if (isThemeVariant(fromStorage)) resolved = fromStorage;
|
|
45
|
-
} catch {
|
|
46
|
-
console.error("Failed to access localStorage");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
applyTheme(resolved);
|
|
50
|
-
setTheme(resolved);
|
|
51
|
-
persistTheme(resolved);
|
|
82
|
+
ensureResolved(initialTheme);
|
|
52
83
|
}, [initialTheme]);
|
|
53
|
-
const
|
|
54
|
-
applyTheme(id);
|
|
55
|
-
setTheme(id);
|
|
56
|
-
persistTheme(id);
|
|
57
|
-
return id;
|
|
58
|
-
}, []);
|
|
84
|
+
const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
59
85
|
return { theme, switchTheme };
|
|
60
86
|
}
|
|
61
87
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var ThemeScript = require('./components/theme-script/ThemeScript');
|
|
4
|
+
var theme_constants = require('./utils/theme.constants');
|
|
3
5
|
var Icon = require('./components/icon/Icon');
|
|
4
6
|
var UserDisplay = require('./components/user-display/UserDisplay');
|
|
5
7
|
var Headline = require('./components/headline/Headline');
|
|
@@ -44,6 +46,18 @@ var CheckboxGroup = require('./components/forms/checkbox-group/CheckboxGroup');
|
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
|
|
49
|
+
Object.keys(ThemeScript).forEach(function (k) {
|
|
50
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
get: function () { return ThemeScript[k]; }
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
Object.keys(theme_constants).forEach(function (k) {
|
|
56
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return theme_constants[k]; }
|
|
59
|
+
});
|
|
60
|
+
});
|
|
47
61
|
Object.keys(Icon).forEach(function (k) {
|
|
48
62
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
49
63
|
enumerable: true,
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const THEME_VARIANTS = ["light", "dark", "system"];
|
|
4
|
+
const THEME_STORAGE_KEY = "dbc_theme";
|
|
5
|
+
function isThemeVariant(x) {
|
|
6
|
+
return !!x && THEME_VARIANTS.includes(x);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
exports.THEME_STORAGE_KEY = THEME_STORAGE_KEY;
|
|
10
|
+
exports.THEME_VARIANTS = THEME_VARIANTS;
|
|
11
|
+
exports.isThemeVariant = isThemeVariant;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const THEME_VARIANTS: readonly ["light", "dark", "system"];
|
|
2
|
+
export type ThemeVariant = (typeof THEME_VARIANTS)[number];
|
|
3
|
+
export declare const THEME_STORAGE_KEY = "dbc_theme";
|
|
4
|
+
export declare function isThemeVariant(x: string | null | undefined): x is ThemeVariant;
|