@lobehub/ui 5.59.0 → 5.60.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/es/ActionIcon/style.mjs +8 -2
- package/es/ActionIcon/style.mjs.map +1 -1
- package/es/awesome/Grainient/Grainient.d.mts +11 -0
- package/es/awesome/Grainient/Grainient.mjs +311 -0
- package/es/awesome/Grainient/Grainient.mjs.map +1 -0
- package/es/awesome/Grainient/index.d.mts +3 -0
- package/es/awesome/Grainient/style.mjs +25 -0
- package/es/awesome/Grainient/style.mjs.map +1 -0
- package/es/awesome/Grainient/type.d.mts +122 -0
- package/es/awesome/index.d.mts +4 -1
- package/es/awesome/index.mjs +2 -1
- package/es/base-ui/ActionIcon/style.mjs +8 -2
- package/es/base-ui/ActionIcon/style.mjs.map +1 -1
- package/es/dashboard/AuthLayout/Aside.d.mts +10 -0
- package/es/dashboard/AuthLayout/Aside.mjs +30 -0
- package/es/dashboard/AuthLayout/Aside.mjs.map +1 -0
- package/es/dashboard/AuthLayout/AuthLayout.d.mts +3 -1
- package/es/dashboard/AuthLayout/AuthLayout.mjs +93 -37
- package/es/dashboard/AuthLayout/AuthLayout.mjs.map +1 -1
- package/es/dashboard/AuthLayout/index.d.mts +3 -2
- package/es/dashboard/AuthLayout/style.mjs +120 -1
- package/es/dashboard/AuthLayout/style.mjs.map +1 -1
- package/es/dashboard/AuthLayout/type.d.mts +39 -3
- package/es/dashboard/AuthTools/AuthLocaleSwitch.d.mts +10 -0
- package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs +32 -0
- package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs.map +1 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.d.mts +10 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.mjs +59 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.mjs.map +1 -0
- package/es/dashboard/AuthTools/index.d.mts +4 -0
- package/es/dashboard/AuthTools/style.mjs +63 -0
- package/es/dashboard/AuthTools/style.mjs.map +1 -0
- package/es/dashboard/AuthTools/type.d.mts +30 -0
- package/es/dashboard/ConsoleNav/Skeleton.d.mts +15 -0
- package/es/dashboard/ConsoleNav/Skeleton.mjs +81 -0
- package/es/dashboard/ConsoleNav/Skeleton.mjs.map +1 -0
- package/es/dashboard/ConsoleNav/index.d.mts +3 -2
- package/es/dashboard/ConsoleNav/style.mjs +15 -0
- package/es/dashboard/ConsoleNav/style.mjs.map +1 -1
- package/es/dashboard/ConsoleNav/type.d.mts +14 -1
- package/es/dashboard/ConsoleShell/ConsoleShell.d.mts +1 -1
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs +11 -3
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/style.mjs +6 -0
- package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/type.d.mts +9 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs +18 -17
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -1
- package/es/dashboard/FilterStrip/FilterStrip.mjs +36 -32
- package/es/dashboard/FilterStrip/FilterStrip.mjs.map +1 -1
- package/es/dashboard/FilterStrip/style.mjs +2 -1
- package/es/dashboard/FilterStrip/style.mjs.map +1 -1
- package/es/dashboard/MetricStrip/MetricCell.mjs +81 -0
- package/es/dashboard/MetricStrip/MetricCell.mjs.map +1 -0
- package/es/dashboard/MetricStrip/MetricStrip.d.mts +5 -2
- package/es/dashboard/MetricStrip/MetricStrip.mjs +33 -62
- package/es/dashboard/MetricStrip/MetricStrip.mjs.map +1 -1
- package/es/dashboard/MetricStrip/style.mjs +49 -4
- package/es/dashboard/MetricStrip/style.mjs.map +1 -1
- package/es/dashboard/MetricStrip/type.d.mts +12 -0
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs +20 -18
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs.map +1 -1
- package/es/dashboard/PageSkeleton/style.mjs +1 -1
- package/es/dashboard/PageSkeleton/style.mjs.map +1 -1
- package/es/dashboard/PanelSurface/PanelSurface.mjs +4 -1
- package/es/dashboard/PanelSurface/PanelSurface.mjs.map +1 -1
- package/es/dashboard/StatCard/StatCard.d.mts +2 -1
- package/es/dashboard/StatCard/StatCard.mjs +24 -72
- package/es/dashboard/StatCard/StatCard.mjs.map +1 -1
- package/es/dashboard/StatCard/type.d.mts +16 -5
- package/es/dashboard/Surface/Surface.mjs +26 -10
- package/es/dashboard/Surface/Surface.mjs.map +1 -1
- package/es/dashboard/Surface/index.d.mts +2 -2
- package/es/dashboard/Surface/link.d.mts +6 -1
- package/es/dashboard/Surface/link.mjs +12 -1
- package/es/dashboard/Surface/link.mjs.map +1 -1
- package/es/dashboard/Surface/style.d.mts +22 -3
- package/es/dashboard/Surface/style.mjs +95 -26
- package/es/dashboard/Surface/style.mjs.map +1 -1
- package/es/dashboard/index.d.mts +10 -4
- package/es/dashboard/index.mjs +7 -3
- package/package.json +1 -1
- package/es/dashboard/StatCard/style.mjs +0 -135
- package/es/dashboard/StatCard/style.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterSidebar.mjs","names":[
|
|
1
|
+
{"version":3,"file":"FilterSidebar.mjs","names":[],"sources":["../../../src/dashboard/FilterSidebar/FilterSidebar.tsx"],"sourcesContent":["'use client';\n\nimport { Filter } from 'lucide-react';\nimport { useState } from 'react';\n\nimport Button from '@/base-ui/Button';\nimport { DraggablePanel } from '@/base-ui/DraggablePanel';\nimport { Drawer } from '@/base-ui/Drawer';\n\nimport { useIsCompact, useLocalStorage } from '../hooks';\nimport { useSurfaceCardClassName } from '../Surface/link';\nimport { FilterSplitProvider } from './context';\nimport { styles } from './style';\nimport type { FilterOptionProps, FilterRowProps, FilterSidebarProps } from './type';\nimport { clampSidebarWidth, sidebarWidth } from './width';\n\nfunction usePageSidebar(wide: boolean | undefined, storageKey: string | undefined) {\n const fallback = wide ? sidebarWidth.wide : sidebarWidth.narrow;\n const [prefs, setPrefs] = useLocalStorage<{ expand?: boolean; width?: number }>(storageKey, {\n expand: true,\n width: fallback,\n });\n return {\n expand: prefs.expand !== false,\n onExpandChange: (expand: boolean) => setPrefs((current) => ({ ...current, expand })),\n onSizeChange: (size: { width?: number | string }) => {\n const next = typeof size.width === 'number' ? size.width : fallback;\n setPrefs((current) => ({ ...current, width: clampSidebarWidth(next, fallback) }));\n },\n width: clampSidebarWidth(Number(prefs.width), fallback),\n };\n}\n\nfunction FilterSidebar({\n body,\n children,\n flush,\n head,\n header,\n label,\n storageKey,\n summary,\n wide,\n}: FilterSidebarProps) {\n const cardClassName = useSurfaceCardClassName();\n const isCompact = useIsCompact();\n const [drawerOpen, setDrawerOpen] = useState(false);\n const sidebar = usePageSidebar(wide, storageKey);\n const close = () => setDrawerOpen(false);\n\n if (isCompact) {\n return (\n <FilterSplitProvider active={!flush}>\n <div className={styles.layout}>\n {header}\n <Button block icon={Filter} onClick={() => setDrawerOpen(true)}>\n {summary}\n </Button>\n <Drawer open={drawerOpen} placement=\"left\" title={label} width={300} onClose={close}>\n <div className={styles.drawerPanel}>\n {head?.(close)}\n {body(close)}\n </div>\n </Drawer>\n <div className={styles.content}>{children}</div>\n </div>\n </FilterSplitProvider>\n );\n }\n\n return (\n <FilterSplitProvider active={!flush}>\n <div\n className={flush ? styles.layout : `${styles.layout} ${cardClassName}`}\n data-flush={flush ? true : undefined}\n data-page-layout={flush ? 'flush' : undefined}\n data-split-card={flush ? undefined : true}\n >\n <DraggablePanel\n expandable\n showHandleWhenCollapsed\n aria-label={label}\n className={styles.sidebar}\n classNames={{ content: styles.panel }}\n collapseThreshold={sidebarWidth.collapse}\n data-flush={flush ? true : undefined}\n defaultSize={{ width: wide ? sidebarWidth.wide : sidebarWidth.narrow }}\n expand={sidebar.expand}\n maxWidth={sidebarWidth.max}\n minWidth={sidebarWidth.min}\n mode=\"fixed\"\n placement=\"left\"\n showBorder={false}\n size={{ width: sidebar.width }}\n onExpandChange={sidebar.onExpandChange}\n onSizeChange={(_delta, size) => sidebar.onSizeChange(size)}\n >\n {head ? <div className={styles.head}>{head(close)}</div> : null}\n <div className={styles.body} data-flush={flush ? true : undefined}>\n {body(close)}\n </div>\n </DraggablePanel>\n <div className={styles.content} data-flush={flush ? true : undefined}>\n {header}\n {children}\n </div>\n </div>\n </FilterSplitProvider>\n );\n}\n\nFilterSidebar.displayName = 'FilterSidebar';\n\nfunction FilterRow({ count, name }: FilterRowProps) {\n return (\n <span className={styles.row}>\n <span className={styles.name}>{name}</span>\n {count !== undefined ? <span className={styles.count}>{count}</span> : null}\n </span>\n );\n}\n\nFilterRow.displayName = 'FilterRow';\n\nfunction FilterOption({ count, icon, label, name, onClick, selected, title }: FilterOptionProps) {\n return (\n <button\n aria-label={label}\n aria-pressed={selected}\n className={styles.option}\n title={title}\n type=\"button\"\n onClick={onClick}\n >\n {icon}\n <span className={styles.name}>{name}</span>\n {count !== undefined ? <span className={styles.count}>{count}</span> : null}\n </button>\n );\n}\n\nFilterOption.displayName = 'FilterOption';\n\nexport { FilterOption, FilterRow };\nexport default FilterSidebar;\n"],"mappings":"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"}
|
|
@@ -1,49 +1,53 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import Skeleton from "../../base-ui/Skeleton/index.mjs";
|
|
3
|
+
import { styles } from "../Surface/style.mjs";
|
|
3
4
|
import Surface from "../Surface/Surface.mjs";
|
|
4
|
-
import { styles } from "./style.mjs";
|
|
5
|
+
import { styles as styles$1 } from "./style.mjs";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { cx } from "antd-style";
|
|
7
8
|
//#region src/dashboard/FilterStrip/FilterStrip.tsx
|
|
8
9
|
const countClass = {
|
|
9
|
-
danger: styles.countDanger,
|
|
10
|
-
warning: styles.countWarning
|
|
10
|
+
danger: styles$1.countDanger,
|
|
11
|
+
warning: styles$1.countWarning
|
|
11
12
|
};
|
|
12
13
|
const integerFormat = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
|
|
13
14
|
const formatInteger = (count) => integerFormat.format(count);
|
|
14
15
|
/** One surface of selectable counts. Peer filters share a seam instead of a row of equal cards. */
|
|
15
|
-
const FilterStrip = ({ emptyText = "--", formatCount = formatInteger, items, label, onChange, value }) => /* @__PURE__ */ jsx(Surface, {
|
|
16
|
-
|
|
17
|
-
className: styles.frame,
|
|
18
|
-
role: "radiogroup",
|
|
16
|
+
const FilterStrip = ({ emptyText = "--", formatCount = formatInteger, items, label, onChange, value }) => /* @__PURE__ */ jsx(Surface, {
|
|
17
|
+
className: styles.clip,
|
|
19
18
|
children: /* @__PURE__ */ jsx("div", {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
19
|
+
"aria-label": label,
|
|
20
|
+
className: styles$1.frame,
|
|
21
|
+
role: "radiogroup",
|
|
22
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
23
|
+
className: styles$1.grid,
|
|
24
|
+
children: items.map((item) => {
|
|
25
|
+
const active = item.key === value;
|
|
26
|
+
const missing = item.count === void 0 || item.count === null;
|
|
27
|
+
const emphasize = item.tone && typeof item.count === "number" && item.count > 0;
|
|
28
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
29
|
+
"aria-checked": active,
|
|
30
|
+
className: cx(styles$1.cell, active && styles$1.cellActive),
|
|
31
|
+
role: "radio",
|
|
32
|
+
title: item.hint,
|
|
33
|
+
type: "button",
|
|
34
|
+
onClick: () => onChange(item.key),
|
|
35
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: cx(styles$1.label, active && styles$1.labelActive),
|
|
37
|
+
children: item.label
|
|
38
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
39
|
+
className: cx(styles$1.count, emphasize && countClass[item.tone]),
|
|
40
|
+
children: item.loading ? /* @__PURE__ */ jsx(Skeleton, {
|
|
41
|
+
height: 22,
|
|
42
|
+
radius: 6,
|
|
43
|
+
width: 48
|
|
44
|
+
}) : missing ? emptyText : formatCount(item.count)
|
|
45
|
+
})]
|
|
46
|
+
}, item.key);
|
|
47
|
+
})
|
|
44
48
|
})
|
|
45
49
|
})
|
|
46
|
-
})
|
|
50
|
+
});
|
|
47
51
|
FilterStrip.displayName = "FilterStrip";
|
|
48
52
|
//#endregion
|
|
49
53
|
export { FilterStrip as default, formatInteger };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterStrip.mjs","names":[],"sources":["../../../src/dashboard/FilterStrip/FilterStrip.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport Skeleton from '@/base-ui/Skeleton';\n\nimport Surface from '../Surface/Surface';\nimport { styles } from './style';\nimport type { FilterStripProps } from './type';\n\nconst countClass = {\n danger: styles.countDanger,\n warning: styles.countWarning,\n} as const;\n\nconst integerFormat = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 });\n\nexport const formatInteger = (count: number) => integerFormat.format(count);\n\n/** One surface of selectable counts. Peer filters share a seam instead of a row of equal cards. */\nconst FilterStrip = ({\n emptyText = '--',\n formatCount = formatInteger,\n items,\n label,\n onChange,\n value,\n}: FilterStripProps) => (\n <Surface>\n <div aria-label={label} className={styles.frame} role=\"radiogroup\">\n <div className={styles.grid}>\n {items.map((item) => {\n const active = item.key === value;\n const missing = item.count === undefined || item.count === null;\n const emphasize = item.tone && typeof item.count === 'number' && item.count > 0;\n\n return (\n <button\n aria-checked={active}\n className={cx(styles.cell, active && styles.cellActive)}\n key={item.key}\n role=\"radio\"\n title={item.hint}\n type=\"button\"\n onClick={() => onChange(item.key)}\n >\n <span className={cx(styles.label, active && styles.labelActive)}>{item.label}</span>\n <span className={cx(styles.count, emphasize && countClass[item.tone!])}>\n {item.loading ? (\n <Skeleton height={22} radius={6} width={48} />\n ) : missing ? (\n emptyText\n ) : (\n formatCount(item.count!)\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </Surface>\n);\n\nFilterStrip.displayName = 'FilterStrip';\n\nexport default FilterStrip;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"FilterStrip.mjs","names":["styles","surfaceStyles"],"sources":["../../../src/dashboard/FilterStrip/FilterStrip.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport Skeleton from '@/base-ui/Skeleton';\n\nimport { styles as surfaceStyles } from '../Surface/style';\nimport Surface from '../Surface/Surface';\nimport { styles } from './style';\nimport type { FilterStripProps } from './type';\n\nconst countClass = {\n danger: styles.countDanger,\n warning: styles.countWarning,\n} as const;\n\nconst integerFormat = new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 });\n\nexport const formatInteger = (count: number) => integerFormat.format(count);\n\n/** One surface of selectable counts. Peer filters share a seam instead of a row of equal cards. */\nconst FilterStrip = ({\n emptyText = '--',\n formatCount = formatInteger,\n items,\n label,\n onChange,\n value,\n}: FilterStripProps) => (\n <Surface className={surfaceStyles.clip}>\n <div aria-label={label} className={styles.frame} role=\"radiogroup\">\n <div className={styles.grid}>\n {items.map((item) => {\n const active = item.key === value;\n const missing = item.count === undefined || item.count === null;\n const emphasize = item.tone && typeof item.count === 'number' && item.count > 0;\n\n return (\n <button\n aria-checked={active}\n className={cx(styles.cell, active && styles.cellActive)}\n key={item.key}\n role=\"radio\"\n title={item.hint}\n type=\"button\"\n onClick={() => onChange(item.key)}\n >\n <span className={cx(styles.label, active && styles.labelActive)}>{item.label}</span>\n <span className={cx(styles.count, emphasize && countClass[item.tone!])}>\n {item.loading ? (\n <Skeleton height={22} radius={6} width={48} />\n ) : missing ? (\n emptyText\n ) : (\n formatCount(item.count!)\n )}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </Surface>\n);\n\nFilterStrip.displayName = 'FilterStrip';\n\nexport default FilterStrip;\n"],"mappings":";;;;;;;;AAWA,MAAM,aAAa;CACjB,QAAQA,SAAO;CACf,SAASA,SAAO;AAClB;AAEA,MAAM,gBAAgB,IAAI,KAAK,aAAa,SAAS,EAAE,uBAAuB,EAAE,CAAC;AAEjF,MAAa,iBAAiB,UAAkB,cAAc,OAAO,KAAK;;AAG1E,MAAM,eAAe,EACnB,YAAY,MACZ,cAAc,eACd,OACA,OACA,UACA,YAEA,oBAAC,SAAD;CAAS,WAAWC,OAAc;CAChC,UAAA,oBAAC,OAAD;EAAK,cAAY;EAAO,WAAWD,SAAO;EAAO,MAAK;EACpD,UAAA,oBAAC,OAAD;GAAK,WAAWA,SAAO;GACpB,UAAA,MAAM,KAAK,SAAS;IACnB,MAAM,SAAS,KAAK,QAAQ;IAC5B,MAAM,UAAU,KAAK,UAAU,KAAA,KAAa,KAAK,UAAU;IAC3D,MAAM,YAAY,KAAK,QAAQ,OAAO,KAAK,UAAU,YAAY,KAAK,QAAQ;IAE9E,OACE,qBAAC,UAAD;KACE,gBAAc;KACd,WAAW,GAAGA,SAAO,MAAM,UAAUA,SAAO,UAAU;KAEtD,MAAK;KACL,OAAO,KAAK;KACZ,MAAK;KACL,eAAe,SAAS,KAAK,GAAG;KAPlC,UAAA,CASE,oBAAC,QAAD;MAAM,WAAW,GAAGA,SAAO,OAAO,UAAUA,SAAO,WAAW;MAAI,UAAA,KAAK;KAAY,CAAA,GACnF,oBAAC,QAAD;MAAM,WAAW,GAAGA,SAAO,OAAO,aAAa,WAAW,KAAK,KAAM;MAClE,UAAA,KAAK,UACJ,oBAAC,UAAD;OAAU,QAAQ;OAAI,QAAQ;OAAG,OAAO;MAAK,CAAA,IAC3C,UACF,YAEA,YAAY,KAAK,KAAM;KAErB,CAAA,CACA;IAhBD,GAAA,KAAK,GAgBJ;GAEZ,CAAC;EACE,CAAA;CACF,CAAA;AACE,CAAA;AAGX,YAAY,cAAc"}
|
|
@@ -67,9 +67,10 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
67
67
|
color: ${cssVar.colorWarning};
|
|
68
68
|
`,
|
|
69
69
|
frame: css`
|
|
70
|
-
--filter-seam:
|
|
70
|
+
--filter-seam: ${cssVar.colorFillSecondary};
|
|
71
71
|
|
|
72
72
|
overflow: hidden;
|
|
73
|
+
border-radius: inherit;
|
|
73
74
|
`,
|
|
74
75
|
grid: css`
|
|
75
76
|
display: grid;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/FilterStrip/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n cell: css`\n cursor: pointer;\n\n position: relative;\n\n display: flex;\n flex-direction: column;\n gap: 6px;\n align-items: flex-start;\n\n min-inline-size: 0;\n margin: 0;\n padding-block: 14px 16px;\n padding-inline: 16px;\n border: 0;\n\n font: inherit;\n color: inherit;\n text-align: start;\n\n background: transparent;\n box-shadow:\n inset -1px 0 0 var(--filter-seam),\n inset 0 -1px 0 var(--filter-seam);\n\n &::after {\n content: '';\n\n position: absolute;\n inset-block-end: 1px;\n inset-inline: 0;\n\n block-size: 3px;\n\n background: transparent;\n }\n\n &:hover {\n background: ${cssVar.colorFillQuaternary};\n }\n `,\n cellActive: css`\n background: ${cssVar.colorFillTertiary};\n\n &::after {\n background: ${cssVar.colorText};\n }\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n count: css`\n font-size: ${cssVar.fontSizeHeading4};\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n line-height: 1.15;\n color: ${cssVar.colorText};\n `,\n countDanger: css`\n color: ${cssVar.colorError};\n `,\n countWarning: css`\n color: ${cssVar.colorWarning};\n `,\n frame: css`\n --filter-seam:
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/FilterStrip/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n cell: css`\n cursor: pointer;\n\n position: relative;\n\n display: flex;\n flex-direction: column;\n gap: 6px;\n align-items: flex-start;\n\n min-inline-size: 0;\n margin: 0;\n padding-block: 14px 16px;\n padding-inline: 16px;\n border: 0;\n\n font: inherit;\n color: inherit;\n text-align: start;\n\n background: transparent;\n box-shadow:\n inset -1px 0 0 var(--filter-seam),\n inset 0 -1px 0 var(--filter-seam);\n\n &::after {\n content: '';\n\n position: absolute;\n inset-block-end: 1px;\n inset-inline: 0;\n\n block-size: 3px;\n\n background: transparent;\n }\n\n &:hover {\n background: ${cssVar.colorFillQuaternary};\n }\n `,\n cellActive: css`\n background: ${cssVar.colorFillTertiary};\n\n &::after {\n background: ${cssVar.colorText};\n }\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n count: css`\n font-size: ${cssVar.fontSizeHeading4};\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n line-height: 1.15;\n color: ${cssVar.colorText};\n `,\n countDanger: css`\n color: ${cssVar.colorError};\n `,\n countWarning: css`\n color: ${cssVar.colorWarning};\n `,\n frame: css`\n --filter-seam: ${cssVar.colorFillSecondary};\n\n overflow: hidden;\n border-radius: inherit;\n `,\n grid: css`\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));\n inline-size: calc(100% + 1px);\n margin-block-end: -1px;\n `,\n label: css`\n font-size: 13px;\n font-weight: 500;\n line-height: 1.4;\n color: ${cssVar.colorTextSecondary};\n `,\n labelActive: css`\n color: ${cssVar.colorText};\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAsCS,OAAO,oBAAoB;;;CAG7C,YAAY,GAAG;kBACC,OAAO,kBAAkB;;;oBAGvB,OAAO,UAAU;;;;oBAIjB,OAAO,kBAAkB;;;CAG3C,OAAO,GAAG;iBACK,OAAO,iBAAiB;;;;aAI5B,OAAO,UAAU;;CAE5B,aAAa,GAAG;aACL,OAAO,WAAW;;CAE7B,cAAc,GAAG;aACN,OAAO,aAAa;;CAE/B,OAAO,GAAG;qBACS,OAAO,mBAAmB;;;;;CAK7C,MAAM,GAAG;;;;;;CAMT,OAAO,GAAG;;;;aAIC,OAAO,mBAAmB;;CAErC,aAAa,GAAG;aACL,OAAO,UAAU;;AAE9B,EAAE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Icon from "../../Icon/Icon.mjs";
|
|
3
|
+
import Skeleton from "../../base-ui/Skeleton/index.mjs";
|
|
4
|
+
import { useSurfaceLink } from "../Surface/link.mjs";
|
|
5
|
+
import { styles } from "./style.mjs";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { cx } from "antd-style";
|
|
8
|
+
//#region src/dashboard/MetricStrip/MetricCell.tsx
|
|
9
|
+
const deltaClass = {
|
|
10
|
+
down: styles.deltaDown,
|
|
11
|
+
flat: styles.deltaFlat,
|
|
12
|
+
up: styles.deltaUp
|
|
13
|
+
};
|
|
14
|
+
const MetricBody = ({ item, loading }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
15
|
+
/* @__PURE__ */ jsxs("div", {
|
|
16
|
+
className: styles.head,
|
|
17
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
18
|
+
className: styles.headCopy,
|
|
19
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: styles.label,
|
|
21
|
+
children: item.label
|
|
22
|
+
}), item.action]
|
|
23
|
+
}), item.mark ? /* @__PURE__ */ jsx("span", {
|
|
24
|
+
"aria-hidden": true,
|
|
25
|
+
className: styles.mark,
|
|
26
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
27
|
+
icon: item.mark,
|
|
28
|
+
size: 14
|
|
29
|
+
})
|
|
30
|
+
}) : null]
|
|
31
|
+
}),
|
|
32
|
+
loading ? /* @__PURE__ */ jsx(Skeleton, {
|
|
33
|
+
height: 28,
|
|
34
|
+
radius: 6,
|
|
35
|
+
width: 88
|
|
36
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: cx(styles.value, item.valueTone === "danger" && styles.valueDanger, item.valueTone === "warning" && styles.valueWarning),
|
|
38
|
+
children: item.value
|
|
39
|
+
}),
|
|
40
|
+
!loading && (item.delta || item.hint) ? /* @__PURE__ */ jsxs("div", {
|
|
41
|
+
className: styles.foot,
|
|
42
|
+
children: [item.delta ? /* @__PURE__ */ jsx("span", {
|
|
43
|
+
className: cx(styles.delta, deltaClass[item.direction ?? "flat"]),
|
|
44
|
+
children: item.delta
|
|
45
|
+
}) : null, item.hint ? /* @__PURE__ */ jsx("span", {
|
|
46
|
+
className: styles.hint,
|
|
47
|
+
children: item.hint
|
|
48
|
+
}) : null]
|
|
49
|
+
}) : null
|
|
50
|
+
] });
|
|
51
|
+
/** One metric: label row, figure, delta and hint. Shared by MetricStrip and StatCard. */
|
|
52
|
+
const MetricCell = ({ item, loading, renderLink, seam = false }) => {
|
|
53
|
+
const link = useSurfaceLink(renderLink);
|
|
54
|
+
const body = /* @__PURE__ */ jsx(MetricBody, {
|
|
55
|
+
item,
|
|
56
|
+
loading: item.loading ?? loading
|
|
57
|
+
});
|
|
58
|
+
const cell = cx(styles.cell, seam && styles.cellSeam);
|
|
59
|
+
if (item.href) return /* @__PURE__ */ jsx("div", {
|
|
60
|
+
className: styles.slot,
|
|
61
|
+
children: link({
|
|
62
|
+
children: body,
|
|
63
|
+
className: cx(cell, styles.link),
|
|
64
|
+
href: item.href
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
if (item.onClick) return /* @__PURE__ */ jsx("button", {
|
|
68
|
+
className: cx(cell, styles.press),
|
|
69
|
+
type: "button",
|
|
70
|
+
onClick: item.onClick,
|
|
71
|
+
children: body
|
|
72
|
+
});
|
|
73
|
+
return /* @__PURE__ */ jsx("div", {
|
|
74
|
+
className: cell,
|
|
75
|
+
children: body
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
export { MetricCell as default };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=MetricCell.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricCell.mjs","names":[],"sources":["../../../src/dashboard/MetricStrip/MetricCell.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport Skeleton from '@/base-ui/Skeleton';\nimport Icon from '@/Icon';\n\nimport { useSurfaceLink } from '../Surface/link';\nimport type { SurfaceRenderLink } from '../Surface/type';\nimport { styles } from './style';\nimport type { MetricItem } from './type';\n\nconst deltaClass = {\n down: styles.deltaDown,\n flat: styles.deltaFlat,\n up: styles.deltaUp,\n} as const;\n\nconst MetricBody = ({ item, loading }: { item: MetricItem; loading?: boolean }) => (\n <>\n <div className={styles.head}>\n <div className={styles.headCopy}>\n <div className={styles.label}>{item.label}</div>\n {item.action}\n </div>\n {item.mark ? (\n <span aria-hidden className={styles.mark}>\n <Icon icon={item.mark} size={14} />\n </span>\n ) : null}\n </div>\n {loading ? (\n <Skeleton height={28} radius={6} width={88} />\n ) : (\n <div\n className={cx(\n styles.value,\n item.valueTone === 'danger' && styles.valueDanger,\n item.valueTone === 'warning' && styles.valueWarning,\n )}\n >\n {item.value}\n </div>\n )}\n {!loading && (item.delta || item.hint) ? (\n <div className={styles.foot}>\n {item.delta ? (\n <span className={cx(styles.delta, deltaClass[item.direction ?? 'flat'])}>\n {item.delta}\n </span>\n ) : null}\n {item.hint ? <span className={styles.hint}>{item.hint}</span> : null}\n </div>\n ) : null}\n </>\n);\n\nexport interface MetricCellProps {\n item: MetricItem;\n loading?: boolean;\n renderLink?: SurfaceRenderLink;\n /** Draw the joined-strip divider on the trailing and bottom edges. */\n seam?: boolean;\n}\n\n/** One metric: label row, figure, delta and hint. Shared by MetricStrip and StatCard. */\nconst MetricCell = ({ item, loading, renderLink, seam = false }: MetricCellProps) => {\n const link = useSurfaceLink(renderLink);\n const body = <MetricBody item={item} loading={item.loading ?? loading} />;\n const cell = cx(styles.cell, seam && styles.cellSeam);\n\n if (item.href) {\n return (\n <div className={styles.slot}>\n {link({ children: body, className: cx(cell, styles.link), href: item.href })}\n </div>\n );\n }\n if (item.onClick) {\n return (\n <button className={cx(cell, styles.press)} type=\"button\" onClick={item.onClick}>\n {body}\n </button>\n );\n }\n return <div className={cell}>{body}</div>;\n};\n\nexport default MetricCell;\n"],"mappings":";;;;;;;;AAYA,MAAM,aAAa;CACjB,MAAM,OAAO;CACb,MAAM,OAAO;CACb,IAAI,OAAO;AACb;AAEA,MAAM,cAAc,EAAE,MAAM,cAC1B,qBAAA,UAAA,EAAA,UAAA;CACE,qBAAC,OAAD;EAAK,WAAW,OAAO;EAAvB,UAAA,CACE,qBAAC,OAAD;GAAK,WAAW,OAAO;GAAvB,UAAA,CACE,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAQ,UAAA,KAAK;GAAW,CAAA,GAC9C,KAAK,MACH;EACJ,CAAA,GAAA,KAAK,OACJ,oBAAC,QAAD;GAAM,eAAA;GAAY,WAAW,OAAO;GAClC,UAAA,oBAAC,MAAD;IAAM,MAAM,KAAK;IAAM,MAAM;GAAK,CAAA;EAC9B,CAAA,IACJ,IACD;;CACJ,UACC,oBAAC,UAAD;EAAU,QAAQ;EAAI,QAAQ;EAAG,OAAO;CAAK,CAAA,IAE7C,oBAAC,OAAD;EACE,WAAW,GACT,OAAO,OACP,KAAK,cAAc,YAAY,OAAO,aACtC,KAAK,cAAc,aAAa,OAAO,YACzC;EAEC,UAAA,KAAK;CACH,CAAA;CAEN,CAAC,YAAY,KAAK,SAAS,KAAK,QAC/B,qBAAC,OAAD;EAAK,WAAW,OAAO;EAAvB,UAAA,CACG,KAAK,QACJ,oBAAC,QAAD;GAAM,WAAW,GAAG,OAAO,OAAO,WAAW,KAAK,aAAa,OAAO;GACnE,UAAA,KAAK;EACF,CAAA,IACJ,MACH,KAAK,OAAO,oBAAC,QAAD;GAAM,WAAW,OAAO;GAAO,UAAA,KAAK;EAAW,CAAA,IAAI,IAC7D;CACH,CAAA,IAAA;AACJ,EAAA,CAAA;;AAYJ,MAAM,cAAc,EAAE,MAAM,SAAS,YAAY,OAAO,YAA6B;CACnF,MAAM,OAAO,eAAe,UAAU;CACtC,MAAM,OAAO,oBAAC,YAAD;EAAkB;EAAM,SAAS,KAAK,WAAW;CAAU,CAAA;CACxE,MAAM,OAAO,GAAG,OAAO,MAAM,QAAQ,OAAO,QAAQ;CAEpD,IAAI,KAAK,MACP,OACE,oBAAC,OAAD;EAAK,WAAW,OAAO;EACpB,UAAA,KAAK;GAAE,UAAU;GAAM,WAAW,GAAG,MAAM,OAAO,IAAI;GAAG,MAAM,KAAK;EAAK,CAAC;CACxE,CAAA;CAGT,IAAI,KAAK,SACP,OACE,oBAAC,UAAD;EAAQ,WAAW,GAAG,MAAM,OAAO,KAAK;EAAG,MAAK;EAAS,SAAS,KAAK;EACpE,UAAA;CACK,CAAA;CAGZ,OAAO,oBAAC,OAAD;EAAK,WAAW;EAAO,UAAA;CAAU,CAAA;AAC1C"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { MetricStripProps } from "./type.mjs";
|
|
2
2
|
//#region src/dashboard/MetricStrip/MetricStrip.d.ts
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Peer metrics. `joined` shares one card divided into cells; `split` gives each item its own card,
|
|
5
|
+
* identical to StatCard.
|
|
6
|
+
*/
|
|
4
7
|
declare const MetricStrip: {
|
|
5
|
-
({ items, loading, renderLink }: MetricStripProps): import("react").JSX.Element;
|
|
8
|
+
({ items, loading, renderLink, variant }: MetricStripProps): import("react").JSX.Element;
|
|
6
9
|
displayName: string;
|
|
7
10
|
};
|
|
8
11
|
//#endregion
|
|
@@ -1,73 +1,44 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import { styles } from "../Surface/style.mjs";
|
|
3
|
+
import { useSurfaceCardClassName } from "../Surface/link.mjs";
|
|
4
4
|
import Surface from "../Surface/Surface.mjs";
|
|
5
|
-
import { styles } from "./style.mjs";
|
|
6
|
-
import
|
|
5
|
+
import { styles as styles$1 } from "./style.mjs";
|
|
6
|
+
import MetricCell from "./MetricCell.mjs";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
8
|
import { cx } from "antd-style";
|
|
8
9
|
//#region src/dashboard/MetricStrip/MetricStrip.tsx
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
const
|
|
15
|
-
/* @__PURE__ */ jsx("div", {
|
|
16
|
-
className: styles.
|
|
17
|
-
children: item
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
className: styles.foot,
|
|
29
|
-
children: [item.delta ? /* @__PURE__ */ jsx("span", {
|
|
30
|
-
className: cx(styles.delta, deltaClass[item.direction ?? "flat"]),
|
|
31
|
-
children: item.delta
|
|
32
|
-
}) : null, item.hint ? /* @__PURE__ */ jsx("span", {
|
|
33
|
-
className: styles.hint,
|
|
34
|
-
children: item.hint
|
|
35
|
-
}) : null]
|
|
36
|
-
}) : null
|
|
37
|
-
] });
|
|
38
|
-
/** One card, divided into metrics. Peer numbers share a surface instead of a row of equal cards. */
|
|
39
|
-
const MetricStrip = ({ items, loading, renderLink }) => {
|
|
40
|
-
const link = useSurfaceLink(renderLink);
|
|
41
|
-
return /* @__PURE__ */ jsx(Surface, { children: /* @__PURE__ */ jsx("div", {
|
|
42
|
-
className: styles.frame,
|
|
10
|
+
/**
|
|
11
|
+
* Peer metrics. `joined` shares one card divided into cells; `split` gives each item its own card,
|
|
12
|
+
* identical to StatCard.
|
|
13
|
+
*/
|
|
14
|
+
const MetricStrip = ({ items, loading, renderLink, variant = "joined" }) => {
|
|
15
|
+
const cardClassName = useSurfaceCardClassName();
|
|
16
|
+
if (variant === "split") return /* @__PURE__ */ jsx("div", {
|
|
17
|
+
className: styles$1.split,
|
|
18
|
+
children: items.map((item, index) => /* @__PURE__ */ jsx("div", {
|
|
19
|
+
className: cx(styles$1.card, cardClassName, styles.clip),
|
|
20
|
+
children: /* @__PURE__ */ jsx(MetricCell, {
|
|
21
|
+
item,
|
|
22
|
+
loading,
|
|
23
|
+
renderLink
|
|
24
|
+
})
|
|
25
|
+
}, index))
|
|
26
|
+
});
|
|
27
|
+
return /* @__PURE__ */ jsx(Surface, {
|
|
28
|
+
className: styles.clip,
|
|
43
29
|
children: /* @__PURE__ */ jsx("div", {
|
|
44
|
-
className: styles.
|
|
45
|
-
children:
|
|
46
|
-
|
|
30
|
+
className: styles$1.frame,
|
|
31
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
32
|
+
className: styles$1.grid,
|
|
33
|
+
children: items.map((item, index) => /* @__PURE__ */ jsx(MetricCell, {
|
|
34
|
+
seam: true,
|
|
47
35
|
item,
|
|
48
|
-
loading
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
className: styles.slot,
|
|
52
|
-
children: link({
|
|
53
|
-
children: body,
|
|
54
|
-
className: cx(styles.cell, styles.link),
|
|
55
|
-
href: item.href
|
|
56
|
-
})
|
|
57
|
-
}, `${index}:${item.href}`);
|
|
58
|
-
if (item.onClick) return /* @__PURE__ */ jsx("button", {
|
|
59
|
-
className: cx(styles.cell, styles.press),
|
|
60
|
-
type: "button",
|
|
61
|
-
onClick: item.onClick,
|
|
62
|
-
children: body
|
|
63
|
-
}, index);
|
|
64
|
-
return /* @__PURE__ */ jsx("div", {
|
|
65
|
-
className: styles.cell,
|
|
66
|
-
children: body
|
|
67
|
-
}, index);
|
|
36
|
+
loading,
|
|
37
|
+
renderLink
|
|
38
|
+
}, index))
|
|
68
39
|
})
|
|
69
40
|
})
|
|
70
|
-
})
|
|
41
|
+
});
|
|
71
42
|
};
|
|
72
43
|
MetricStrip.displayName = "MetricStrip";
|
|
73
44
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetricStrip.mjs","names":[],"sources":["../../../src/dashboard/MetricStrip/MetricStrip.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport
|
|
1
|
+
{"version":3,"file":"MetricStrip.mjs","names":["styles","surfaceStyles"],"sources":["../../../src/dashboard/MetricStrip/MetricStrip.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport { useSurfaceCardClassName } from '../Surface/link';\nimport { styles as surfaceStyles } from '../Surface/style';\nimport Surface from '../Surface/Surface';\nimport MetricCell from './MetricCell';\nimport { styles } from './style';\nimport type { MetricStripProps } from './type';\n\n/**\n * Peer metrics. `joined` shares one card divided into cells; `split` gives each item its own card,\n * identical to StatCard.\n */\nconst MetricStrip = ({ items, loading, renderLink, variant = 'joined' }: MetricStripProps) => {\n const cardClassName = useSurfaceCardClassName();\n\n if (variant === 'split') {\n return (\n <div className={styles.split}>\n {items.map((item, index) => (\n <div className={cx(styles.card, cardClassName, surfaceStyles.clip)} key={index}>\n <MetricCell item={item} loading={loading} renderLink={renderLink} />\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <Surface className={surfaceStyles.clip}>\n <div className={styles.frame}>\n <div className={styles.grid}>\n {items.map((item, index) => (\n <MetricCell seam item={item} key={index} loading={loading} renderLink={renderLink} />\n ))}\n </div>\n </div>\n </Surface>\n );\n};\n\nMetricStrip.displayName = 'MetricStrip';\n\nexport default MetricStrip;\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAM,eAAe,EAAE,OAAO,SAAS,YAAY,UAAU,eAAiC;CAC5F,MAAM,gBAAgB,wBAAwB;CAE9C,IAAI,YAAY,SACd,OACE,oBAAC,OAAD;EAAK,WAAWA,SAAO;EACpB,UAAA,MAAM,KAAK,MAAM,UAChB,oBAAC,OAAD;GAAK,WAAW,GAAGA,SAAO,MAAM,eAAeC,OAAc,IAAI;GAC/D,UAAA,oBAAC,YAAD;IAAkB;IAAe;IAAqB;GAAa,CAAA;EAChE,GAFoE,KAEpE,CACN;CACE,CAAA;CAIT,OACE,oBAAC,SAAD;EAAS,WAAWA,OAAc;EAChC,UAAA,oBAAC,OAAD;GAAK,WAAWD,SAAO;GACrB,UAAA,oBAAC,OAAD;IAAK,WAAWA,SAAO;IACpB,UAAA,MAAM,KAAK,MAAM,UAChB,oBAAC,YAAD;KAAY,MAAA;KAAW;KAA2B;KAAqB;IAAa,GAAlD,KAAkD,CACrF;GACE,CAAA;EACF,CAAA;CACE,CAAA;AAEb;AAEA,YAAY,cAAc"}
|
|
@@ -10,10 +10,54 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
10
10
|
padding-block: 16px;
|
|
11
11
|
padding-inline: 20px;
|
|
12
12
|
|
|
13
|
-
background:
|
|
13
|
+
background: transparent;
|
|
14
|
+
`,
|
|
15
|
+
/** Joined strip only: the divider on the cell's trailing and bottom edges. */
|
|
16
|
+
cellSeam: css`
|
|
14
17
|
box-shadow:
|
|
15
18
|
inset -1px 0 0 var(--metric-seam),
|
|
16
19
|
inset 0 -1px 0 var(--metric-seam);
|
|
20
|
+
`,
|
|
21
|
+
/** Split strip and StatCard: one card per item. */
|
|
22
|
+
card: css`
|
|
23
|
+
display: grid;
|
|
24
|
+
min-inline-size: 0;
|
|
25
|
+
`,
|
|
26
|
+
head: css`
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 8px;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: space-between;
|
|
31
|
+
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
min-inline-size: 0;
|
|
34
|
+
block-size: 32px;
|
|
35
|
+
`,
|
|
36
|
+
headCopy: css`
|
|
37
|
+
display: flex;
|
|
38
|
+
gap: 6px;
|
|
39
|
+
align-items: center;
|
|
40
|
+
min-inline-size: 0;
|
|
41
|
+
`,
|
|
42
|
+
mark: css`
|
|
43
|
+
display: inline-flex;
|
|
44
|
+
flex: none;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
|
|
48
|
+
inline-size: 24px;
|
|
49
|
+
block-size: 24px;
|
|
50
|
+
border: 1px solid ${cssVar.colorFillSecondary};
|
|
51
|
+
border-radius: ${cssVar.borderRadiusSM};
|
|
52
|
+
|
|
53
|
+
color: ${cssVar.colorTextTertiary};
|
|
54
|
+
|
|
55
|
+
background: ${cssVar.colorFillTertiary};
|
|
56
|
+
`,
|
|
57
|
+
split: css`
|
|
58
|
+
display: grid;
|
|
59
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
60
|
+
gap: 12px;
|
|
17
61
|
`,
|
|
18
62
|
delta: css`
|
|
19
63
|
font-size: 13px;
|
|
@@ -41,10 +85,11 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
41
85
|
* track, which reads louder than the cells.
|
|
42
86
|
*/
|
|
43
87
|
frame: css`
|
|
44
|
-
--metric-seam:
|
|
88
|
+
--metric-seam: ${cssVar.colorFillSecondary};
|
|
45
89
|
|
|
46
90
|
overflow: hidden;
|
|
47
|
-
|
|
91
|
+
border-radius: inherit;
|
|
92
|
+
background: transparent;
|
|
48
93
|
`,
|
|
49
94
|
grid: css`
|
|
50
95
|
display: grid;
|
|
@@ -53,7 +98,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
53
98
|
inline-size: calc(100% + 1px);
|
|
54
99
|
margin-block-end: -1px;
|
|
55
100
|
|
|
56
|
-
background:
|
|
101
|
+
background: transparent;
|
|
57
102
|
`,
|
|
58
103
|
hint: css`
|
|
59
104
|
font-size: 13px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/MetricStrip/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n cell: css`\n display: flex;\n flex-direction: column;\n gap: 6px;\n\n min-inline-size: 0;\n padding-block: 16px;\n padding-inline: 20px;\n\n background:
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/MetricStrip/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n cell: css`\n display: flex;\n flex-direction: column;\n gap: 6px;\n\n min-inline-size: 0;\n padding-block: 16px;\n padding-inline: 20px;\n\n background: transparent;\n `,\n /** Joined strip only: the divider on the cell's trailing and bottom edges. */\n cellSeam: css`\n box-shadow:\n inset -1px 0 0 var(--metric-seam),\n inset 0 -1px 0 var(--metric-seam);\n `,\n /** Split strip and StatCard: one card per item. */\n card: css`\n display: grid;\n min-inline-size: 0;\n `,\n /* One fixed 32px row (a small Segmented or ActionIcon fits): an action or mark in the head must not push the value down, so cells with and\n without header controls line up across a split strip or a row of StatCards. */\n head: css`\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n box-sizing: border-box;\n min-inline-size: 0;\n block-size: 32px;\n `,\n headCopy: css`\n display: flex;\n gap: 6px;\n align-items: center;\n min-inline-size: 0;\n `,\n mark: css`\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n\n inline-size: 24px;\n block-size: 24px;\n border: 1px solid ${cssVar.colorFillSecondary};\n border-radius: ${cssVar.borderRadiusSM};\n\n color: ${cssVar.colorTextTertiary};\n\n background: ${cssVar.colorFillTertiary};\n `,\n split: css`\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n `,\n delta: css`\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n line-height: 1.4;\n `,\n deltaDown: css`\n color: ${cssVar.colorError};\n `,\n deltaFlat: css`\n color: ${cssVar.colorTextSecondary};\n `,\n deltaUp: css`\n color: ${cssVar.colorSuccess};\n `,\n foot: css`\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: baseline;\n `,\n /**\n * Clips the seam that would otherwise sit on the card's trailing and bottom\n * edges. A short last row used to show the seam color across the empty\n * track, which reads louder than the cells.\n */\n frame: css`\n --metric-seam: ${cssVar.colorFillSecondary};\n\n overflow: hidden;\n border-radius: inherit;\n background: transparent;\n `,\n grid: css`\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n\n inline-size: calc(100% + 1px);\n margin-block-end: -1px;\n\n background: transparent;\n `,\n hint: css`\n font-size: 13px;\n line-height: 1.4;\n color: ${cssVar.colorTextSecondary};\n `,\n label: css`\n font-size: 13px;\n font-weight: 500;\n line-height: 1.4;\n color: ${cssVar.colorTextSecondary};\n `,\n link: css`\n color: inherit;\n text-decoration: none;\n\n &:hover {\n background: ${cssVar.colorFillQuaternary};\n }\n `,\n press: css`\n cursor: pointer;\n\n border: none;\n\n font: inherit;\n color: inherit;\n text-align: start;\n\n &:hover {\n background: ${cssVar.colorFillQuaternary};\n }\n `,\n /** Grid cell around a rendered link, so the link fills it. */\n slot: css`\n display: grid;\n min-inline-size: 0;\n `,\n value: css`\n overflow: hidden;\n\n font-size: ${cssVar.fontSizeHeading3};\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n line-height: 1.15;\n color: ${cssVar.colorText};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n valueDanger: css`\n color: ${cssVar.colorError};\n `,\n valueWarning: css`\n color: ${cssVar.colorWarning};\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,MAAM,GAAG;;;;;;;;;;;;CAYT,UAAU,GAAG;;;;;;CAMb,MAAM,GAAG;;;;CAMT,MAAM,GAAG;;;;;;;;;;CAUT,UAAU,GAAG;;;;;;CAMb,MAAM,GAAG;;;;;;;;wBAQa,OAAO,mBAAmB;qBAC7B,OAAO,eAAe;;aAE9B,OAAO,kBAAkB;;kBAEpB,OAAO,kBAAkB;;CAEzC,OAAO,GAAG;;;;;CAKV,OAAO,GAAG;;;;;CAKV,WAAW,GAAG;aACH,OAAO,WAAW;;CAE7B,WAAW,GAAG;aACH,OAAO,mBAAmB;;CAErC,SAAS,GAAG;aACD,OAAO,aAAa;;CAE/B,MAAM,GAAG;;;;;;;;;;;CAWT,OAAO,GAAG;qBACS,OAAO,mBAAmB;;;;;;CAM7C,MAAM,GAAG;;;;;;;;;CAST,MAAM,GAAG;;;aAGE,OAAO,mBAAmB;;CAErC,OAAO,GAAG;;;;aAIC,OAAO,mBAAmB;;CAErC,MAAM,GAAG;;;;;oBAKS,OAAO,oBAAoB;;;CAG7C,OAAO,GAAG;;;;;;;;;;oBAUQ,OAAO,oBAAoB;;;;CAI7C,MAAM,GAAG;;;;CAIT,OAAO,GAAG;;;iBAGK,OAAO,iBAAiB;;;;aAI5B,OAAO,UAAU;;;;CAI5B,aAAa,GAAG;aACL,OAAO,WAAW;;CAE7B,cAAc,GAAG;aACN,OAAO,aAAa;;AAEjC,EAAE"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { IconProps } from "../../Icon/type.mjs";
|
|
2
|
+
import "../../Icon/index.mjs";
|
|
1
3
|
import { SurfaceRenderLink } from "../Surface/type.mjs";
|
|
2
4
|
import { ReactNode } from "react";
|
|
3
5
|
//#region src/dashboard/MetricStrip/type.d.ts
|
|
4
6
|
interface MetricItem {
|
|
7
|
+
/** Control on the label row, such as a menu. */
|
|
8
|
+
action?: ReactNode;
|
|
5
9
|
delta?: ReactNode;
|
|
6
10
|
direction?: 'up' | 'down' | 'flat';
|
|
7
11
|
hint?: ReactNode;
|
|
@@ -9,6 +13,8 @@ interface MetricItem {
|
|
|
9
13
|
label: ReactNode;
|
|
10
14
|
/** This cell only. Cells fed by different queries arrive at different times. */
|
|
11
15
|
loading?: boolean;
|
|
16
|
+
/** Corner glyph. Hidden from assistive tech so it does not repeat the label. */
|
|
17
|
+
mark?: IconProps['icon'];
|
|
12
18
|
onClick?: () => void;
|
|
13
19
|
value: ReactNode;
|
|
14
20
|
/** Color the figure when the number itself is the thing to act on. */
|
|
@@ -19,6 +25,12 @@ interface MetricStripProps {
|
|
|
19
25
|
/** First load only: values become placeholders, labels stay. */
|
|
20
26
|
loading?: boolean;
|
|
21
27
|
renderLink?: SurfaceRenderLink;
|
|
28
|
+
/**
|
|
29
|
+
* `joined`: one card divided into cells. `split`: every item is its own card (the StatCard look)
|
|
30
|
+
* on a responsive grid with a gap.
|
|
31
|
+
* @default 'joined'
|
|
32
|
+
*/
|
|
33
|
+
variant?: 'joined' | 'split';
|
|
22
34
|
}
|
|
23
35
|
//#endregion
|
|
24
36
|
export { MetricItem, MetricStripProps };
|