@lobehub/ui 5.58.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/Grid/style.mjs +8 -8
- package/es/Grid/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/base-ui/Input/style.mjs +8 -2
- package/es/base-ui/Input/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/ChartGrid/ChartGrid.d.mts +10 -0
- package/es/dashboard/ChartGrid/ChartGrid.mjs +18 -0
- package/es/dashboard/ChartGrid/ChartGrid.mjs.map +1 -0
- package/es/dashboard/ChartGrid/index.d.mts +3 -0
- package/es/dashboard/ChartGrid/style.mjs +32 -0
- package/es/dashboard/ChartGrid/style.mjs.map +1 -0
- package/es/dashboard/ChartGrid/type.d.mts +9 -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 +22 -6
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/style.mjs +21 -0
- package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/type.d.mts +11 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs +18 -17
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -1
- package/es/dashboard/FilterStrip/FilterStrip.d.mts +11 -0
- package/es/dashboard/FilterStrip/FilterStrip.mjs +55 -0
- package/es/dashboard/FilterStrip/FilterStrip.mjs.map +1 -0
- package/es/dashboard/FilterStrip/index.d.mts +3 -0
- package/es/dashboard/FilterStrip/style.mjs +94 -0
- package/es/dashboard/FilterStrip/style.mjs.map +1 -0
- package/es/dashboard/FilterStrip/type.d.mts +26 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.d.mts +10 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.mjs +18 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.mjs.map +1 -0
- package/es/dashboard/LabelWithKey/index.d.mts +3 -0
- package/es/dashboard/LabelWithKey/type.d.mts +12 -0
- package/es/dashboard/MetricStrip/MetricCell.mjs +81 -0
- package/es/dashboard/MetricStrip/MetricCell.mjs.map +1 -0
- package/es/dashboard/MetricStrip/MetricStrip.d.mts +13 -0
- package/es/dashboard/MetricStrip/MetricStrip.mjs +47 -0
- package/es/dashboard/MetricStrip/MetricStrip.mjs.map +1 -0
- package/es/dashboard/MetricStrip/index.d.mts +3 -0
- package/es/dashboard/MetricStrip/style.mjs +161 -0
- package/es/dashboard/MetricStrip/style.mjs.map +1 -0
- package/es/dashboard/MetricStrip/type.d.mts +37 -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/PageToolbar/PageToolbar.d.mts +10 -0
- package/es/dashboard/PageToolbar/PageToolbar.mjs +21 -0
- package/es/dashboard/PageToolbar/PageToolbar.mjs.map +1 -0
- package/es/dashboard/PageToolbar/index.d.mts +3 -0
- package/es/dashboard/PageToolbar/style.mjs +34 -0
- package/es/dashboard/PageToolbar/style.mjs.map +1 -0
- package/es/dashboard/PageToolbar/type.d.mts +12 -0
- package/es/dashboard/PanelSurface/PanelSurface.d.mts +10 -0
- package/es/dashboard/PanelSurface/PanelSurface.mjs +39 -0
- package/es/dashboard/PanelSurface/PanelSurface.mjs.map +1 -0
- package/es/dashboard/PanelSurface/index.d.mts +3 -0
- package/es/dashboard/PanelSurface/style.mjs +24 -0
- package/es/dashboard/PanelSurface/style.mjs.map +1 -0
- package/es/dashboard/PanelSurface/type.d.mts +18 -0
- package/es/dashboard/Section/Section.d.mts +10 -0
- package/es/dashboard/Section/Section.mjs +81 -0
- package/es/dashboard/Section/Section.mjs.map +1 -0
- package/es/dashboard/Section/index.d.mts +3 -0
- package/es/dashboard/Section/style.mjs +35 -0
- package/es/dashboard/Section/style.mjs.map +1 -0
- package/es/dashboard/Section/type.d.mts +24 -0
- 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.d.mts +4 -3
- package/es/dashboard/Surface/Surface.mjs +83 -7
- package/es/dashboard/Surface/Surface.mjs.map +1 -1
- package/es/dashboard/Surface/index.d.mts +3 -2
- package/es/dashboard/Surface/link.d.mts +19 -0
- package/es/dashboard/Surface/link.mjs +33 -0
- package/es/dashboard/Surface/link.mjs.map +1 -0
- package/es/dashboard/Surface/style.d.mts +45 -3
- package/es/dashboard/Surface/style.mjs +358 -8
- package/es/dashboard/Surface/style.mjs.map +1 -1
- package/es/dashboard/Surface/type.d.mts +30 -2
- package/es/dashboard/TableIconActions/TableIconActions.d.mts +17 -0
- package/es/dashboard/TableIconActions/TableIconActions.mjs +39 -0
- package/es/dashboard/TableIconActions/TableIconActions.mjs.map +1 -0
- package/es/dashboard/TableIconActions/index.d.mts +3 -0
- package/es/dashboard/TableIconActions/type.d.mts +18 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.d.mts +10 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.mjs +28 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.mjs.map +1 -0
- package/es/dashboard/TitleWithTips/index.d.mts +3 -0
- package/es/dashboard/TitleWithTips/type.d.mts +11 -0
- package/es/dashboard/index.d.mts +38 -4
- package/es/dashboard/index.mjs +17 -3
- package/package.json +1 -1
- package/es/dashboard/StatCard/style.mjs +0 -135
- package/es/dashboard/StatCard/style.mjs.map +0 -1
|
@@ -23,6 +23,11 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
|
|
|
23
23
|
${responsive.laptop} {
|
|
24
24
|
margin-block-start: 0;
|
|
25
25
|
}
|
|
26
|
+
`,
|
|
27
|
+
/** Close button in the drawer's brand row: right edge, vertically centred with the brand. */
|
|
28
|
+
brandClose: css`
|
|
29
|
+
flex: none;
|
|
30
|
+
margin-inline: auto -7px;
|
|
26
31
|
`,
|
|
27
32
|
brandAnchor: css`
|
|
28
33
|
display: flex;
|
|
@@ -87,6 +92,16 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
|
|
|
87
92
|
gap: 16px;
|
|
88
93
|
padding: 16px;
|
|
89
94
|
}
|
|
95
|
+
`,
|
|
96
|
+
/**
|
|
97
|
+
* The drawer body is the scroll container. Without its default padding the scrollbar sits on
|
|
98
|
+
* the panel edge; the brand row, nav and footer keep their own insets.
|
|
99
|
+
*/
|
|
100
|
+
drawerBody: css`
|
|
101
|
+
&& {
|
|
102
|
+
min-block-size: 100%;
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
90
105
|
`,
|
|
91
106
|
navSlot: css`
|
|
92
107
|
display: flex;
|
|
@@ -182,6 +197,12 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
|
|
|
182
197
|
align-items: center;
|
|
183
198
|
|
|
184
199
|
margin-inline-start: auto;
|
|
200
|
+
`,
|
|
201
|
+
/** Light only: the content area sits midway between the layout canvas and container white. */
|
|
202
|
+
workspaceLight: css`
|
|
203
|
+
&& {
|
|
204
|
+
background: color-mix(in srgb, ${cssVar.colorBgLayout} 50%, ${cssVar.colorBgContainer});
|
|
205
|
+
}
|
|
185
206
|
`,
|
|
186
207
|
workspace: css`
|
|
187
208
|
overflow: hidden;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nconst SIDEBAR_INLINE_SIZE = 248;\n// Twice the nav icon inset (8px nav padding + 10px item padding) plus the 18px icon, so the icons\n// land centered on the rail without moving sideways.\nconst SIDEBAR_RAIL_INLINE_SIZE = 54;\nconst WORKSPACE_INSET = 8;\n\n/**\n * `responsive.laptop`, not `responsive.tablet`. The aliases are named for\n * devices, and only `laptop` (max-width 991px) lines up with `useIsCompact`.\n */\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n brand: css`\n display: flex;\n flex: none;\n align-items: center;\n\n block-size: 56px;\n margin-block-start: ${WORKSPACE_INSET}px;\n padding-inline: 15px;\n\n color: ${cssVar.colorText};\n white-space: nowrap;\n\n ${responsive.laptop} {\n margin-block-start: 0;\n }\n `,\n brandAnchor: css`\n display: flex;\n align-items: center;\n\n inline-size: 100%;\n min-inline-size: 0;\n\n color: inherit;\n text-decoration: none;\n `,\n brandLockup: css`\n display: flex;\n gap: 10px;\n align-items: center;\n min-inline-size: 0;\n `,\n brandName: css`\n overflow: hidden;\n\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: ${cssVar.colorText};\n text-overflow: ellipsis;\n white-space: nowrap;\n\n transition: opacity 120ms ease 80ms;\n\n [data-collapsed='true'] & {\n text-overflow: clip;\n opacity: 0;\n transition-delay: 0s;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n main: css`\n overflow: auto;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 20px;\n\n min-inline-size: 0;\n min-block-size: 0;\n padding: 24px;\n\n /*\n * A page that owns a full-height split sets data-page-layout=\"flush\" and\n * takes over padding and scrolling, so its sidebar can sit on the card edge.\n */\n &:has([data-page-layout='flush']) {\n overflow: hidden;\n gap: 0;\n padding: 0;\n }\n\n ${responsive.mobile} {\n gap: 16px;\n padding: 16px;\n }\n `,\n navSlot: css`\n display: flex;\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n `,\n shell: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n\n block-size: 100%;\n min-block-size: 0;\n\n background: ${cssVar.colorBgLayout};\n `,\n sidebar: css`\n overflow: hidden;\n display: flex;\n flex: none;\n flex-direction: column;\n\n inline-size: ${SIDEBAR_INLINE_SIZE}px;\n block-size: 100%;\n min-block-size: 0;\n\n transition: inline-size 200ms ease;\n\n &[data-collapsed='true'] {\n inline-size: ${SIDEBAR_RAIL_INLINE_SIZE}px;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n\n ${responsive.laptop} {\n display: none;\n }\n `,\n sidebarBottom: css`\n flex: none;\n padding: 8px;\n `,\n skipLink: css`\n position: fixed;\n z-index: 2000;\n inset-block-start: -100px;\n inset-inline-start: 12px;\n\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n\n &:focus {\n inset-block-start: 12px;\n }\n `,\n topbar: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n\n block-size: 56px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n `,\n topbarDivider: css`\n flex: none;\n\n inline-size: 1px;\n block-size: 18px;\n margin-inline: 2px;\n\n background: ${cssVar.colorBorderSecondary};\n `,\n topbarMain: css`\n display: flex;\n flex: 1;\n align-items: center;\n min-inline-size: 0;\n `,\n tools: css`\n display: flex;\n flex: none;\n gap: 6px;\n align-items: center;\n\n margin-inline-start: auto;\n `,\n workspace: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-inline-size: 0;\n min-block-size: 0;\n margin-block: ${WORKSPACE_INSET}px;\n margin-inline: 0 ${WORKSPACE_INSET}px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n\n background: ${cssVar.colorBgContainer};\n box-shadow: ${cssVar.boxShadowTertiary};\n\n ${responsive.laptop} {\n margin: 0;\n border: none;\n border-radius: 0;\n box-shadow: none;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAG5B,MAAM,2BAA2B;AACjC,MAAM,kBAAkB;;;;;AAMxB,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;0BAMc,gBAAgB;;;aAG7B,OAAO,UAAU;;;MAGxB,WAAW,OAAO;;;;
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nconst SIDEBAR_INLINE_SIZE = 248;\n// Twice the nav icon inset (8px nav padding + 10px item padding) plus the 18px icon, so the icons\n// land centered on the rail without moving sideways.\nconst SIDEBAR_RAIL_INLINE_SIZE = 54;\nconst WORKSPACE_INSET = 8;\n\n/**\n * `responsive.laptop`, not `responsive.tablet`. The aliases are named for\n * devices, and only `laptop` (max-width 991px) lines up with `useIsCompact`.\n */\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n brand: css`\n display: flex;\n flex: none;\n align-items: center;\n\n block-size: 56px;\n margin-block-start: ${WORKSPACE_INSET}px;\n padding-inline: 15px;\n\n color: ${cssVar.colorText};\n white-space: nowrap;\n\n ${responsive.laptop} {\n margin-block-start: 0;\n }\n `,\n /** Close button in the drawer's brand row: right edge, vertically centred with the brand. */\n brandClose: css`\n flex: none;\n margin-inline: auto -7px;\n `,\n brandAnchor: css`\n display: flex;\n align-items: center;\n\n inline-size: 100%;\n min-inline-size: 0;\n\n color: inherit;\n text-decoration: none;\n `,\n brandLockup: css`\n display: flex;\n gap: 10px;\n align-items: center;\n min-inline-size: 0;\n `,\n brandName: css`\n overflow: hidden;\n\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: ${cssVar.colorText};\n text-overflow: ellipsis;\n white-space: nowrap;\n\n transition: opacity 120ms ease 80ms;\n\n [data-collapsed='true'] & {\n text-overflow: clip;\n opacity: 0;\n transition-delay: 0s;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n main: css`\n overflow: auto;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 20px;\n\n min-inline-size: 0;\n min-block-size: 0;\n padding: 24px;\n\n /*\n * A page that owns a full-height split sets data-page-layout=\"flush\" and\n * takes over padding and scrolling, so its sidebar can sit on the card edge.\n */\n &:has([data-page-layout='flush']) {\n overflow: hidden;\n gap: 0;\n padding: 0;\n }\n\n ${responsive.mobile} {\n gap: 16px;\n padding: 16px;\n }\n `,\n /**\n * The drawer body is the scroll container. Without its default padding the scrollbar sits on\n * the panel edge; the brand row, nav and footer keep their own insets.\n */\n drawerBody: css`\n && {\n min-block-size: 100%;\n padding: 0;\n }\n `,\n navSlot: css`\n display: flex;\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n `,\n shell: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n\n block-size: 100%;\n min-block-size: 0;\n\n background: ${cssVar.colorBgLayout};\n `,\n sidebar: css`\n overflow: hidden;\n display: flex;\n flex: none;\n flex-direction: column;\n\n inline-size: ${SIDEBAR_INLINE_SIZE}px;\n block-size: 100%;\n min-block-size: 0;\n\n transition: inline-size 200ms ease;\n\n &[data-collapsed='true'] {\n inline-size: ${SIDEBAR_RAIL_INLINE_SIZE}px;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n\n ${responsive.laptop} {\n display: none;\n }\n `,\n sidebarBottom: css`\n flex: none;\n padding: 8px;\n `,\n skipLink: css`\n position: fixed;\n z-index: 2000;\n inset-block-start: -100px;\n inset-inline-start: 12px;\n\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n\n &:focus {\n inset-block-start: 12px;\n }\n `,\n topbar: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n\n block-size: 56px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n `,\n topbarDivider: css`\n flex: none;\n\n inline-size: 1px;\n block-size: 18px;\n margin-inline: 2px;\n\n background: ${cssVar.colorBorderSecondary};\n `,\n topbarMain: css`\n display: flex;\n flex: 1;\n align-items: center;\n min-inline-size: 0;\n `,\n tools: css`\n display: flex;\n flex: none;\n gap: 6px;\n align-items: center;\n\n margin-inline-start: auto;\n `,\n /** Light only: the content area sits midway between the layout canvas and container white. */\n workspaceLight: css`\n && {\n background: color-mix(in srgb, ${cssVar.colorBgLayout} 50%, ${cssVar.colorBgContainer});\n }\n `,\n workspace: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-inline-size: 0;\n min-block-size: 0;\n margin-block: ${WORKSPACE_INSET}px;\n margin-inline: 0 ${WORKSPACE_INSET}px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n\n background: ${cssVar.colorBgContainer};\n box-shadow: ${cssVar.boxShadowTertiary};\n\n ${responsive.laptop} {\n margin: 0;\n border: none;\n border-radius: 0;\n box-shadow: none;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAG5B,MAAM,2BAA2B;AACjC,MAAM,kBAAkB;;;;;AAMxB,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;0BAMc,gBAAgB;;;aAG7B,OAAO,UAAU;;;MAGxB,WAAW,OAAO;;;;;CAKtB,YAAY,GAAG;;;;CAIf,aAAa,GAAG;;;;;;;;;;CAUhB,aAAa,GAAG;;;;;;CAMhB,WAAW,GAAG;;;;;;aAMH,OAAO,UAAU;;;;;;;;;;;;;;;;CAgB5B,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;MAqBL,WAAW,OAAO;;;;;;;;;CAStB,YAAY,GAAG;;;;;;CAMf,SAAS,GAAG;;;;;;CAMZ,OAAO,GAAG;;;;;;;;kBAQM,OAAO,cAAc;;CAErC,SAAS,GAAG;;;;;;mBAMK,oBAAoB;;;;;;;qBAOlB,yBAAyB;;;;;;;MAOxC,WAAW,OAAO;;;;CAItB,eAAe,GAAG;;;;CAIlB,UAAU,GAAG;;;;;;;;qBAQM,OAAO,aAAa;;aAE5B,OAAO,UAAU;;kBAEZ,OAAO,gBAAgB;;;;;;CAMvC,QAAQ,GAAG;;;;;;;;kCAQqB,OAAO,qBAAqB;;CAE5D,eAAe,GAAG;;;;;;;kBAOF,OAAO,qBAAqB;;CAE5C,YAAY,GAAG;;;;;;CAMf,OAAO,GAAG;;;;;;;;;CASV,gBAAgB,GAAG;;uCAEkB,OAAO,cAAc,QAAQ,OAAO,iBAAiB;;;CAG1F,WAAW,GAAG;;;;;;;;oBAQI,gBAAgB;uBACb,gBAAgB;wBACf,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;kBAEzB,OAAO,iBAAiB;kBACxB,OAAO,kBAAkB;;MAErC,WAAW,OAAO;;;;;;;AAOxB,EAAE"}
|
|
@@ -38,6 +38,8 @@ interface ConsoleShellProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'
|
|
|
38
38
|
/** Location shown in the top bar, usually a `Breadcrumb`. */
|
|
39
39
|
breadcrumb?: ReactNode;
|
|
40
40
|
children?: ReactNode;
|
|
41
|
+
/** Accessible name of the close button in the compact navigation drawer. */
|
|
42
|
+
closeNavigationLabel?: string;
|
|
41
43
|
/** Collapse the sidebar to an icon rail. Ignored while compact. */
|
|
42
44
|
collapsed?: boolean;
|
|
43
45
|
collapseLabel?: string;
|
|
@@ -50,6 +52,15 @@ interface ConsoleShellProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'
|
|
|
50
52
|
* @default true
|
|
51
53
|
*/
|
|
52
54
|
hotkey?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Swap navigation and footer for skeletons, and render `loadingContent` (default `PageLoading`)
|
|
57
|
+
* in place of children. Brand, tools and `storageKey` still come from the caller.
|
|
58
|
+
*/
|
|
59
|
+
loading?: boolean;
|
|
60
|
+
/** Body while `loading`. Defaults to `<PageLoading />`. */
|
|
61
|
+
loadingContent?: ReactNode;
|
|
62
|
+
/** Skeleton nav shape while `loading`. Pass the real groups to mirror their row counts. */
|
|
63
|
+
loadingNavigation?: ReactNode;
|
|
53
64
|
/** Grouped navigation. Collapsed state comes from the shell. */
|
|
54
65
|
navigation?: ReactNode;
|
|
55
66
|
onCollapsedChange?: (collapsed: boolean) => void;
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import Button from "../../base-ui/Button/Button.mjs";
|
|
3
3
|
import Drawer from "../../base-ui/Drawer/Drawer.mjs";
|
|
4
4
|
import DraggablePanel from "../../base-ui/DraggablePanel/DraggablePanel.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { useSurfaceCardClassName } from "../Surface/link.mjs";
|
|
6
6
|
import { useIsCompact, useLocalStorage } from "../hooks.mjs";
|
|
7
7
|
import { FilterSplitProvider } from "./context.mjs";
|
|
8
|
-
import { styles
|
|
8
|
+
import { styles } from "./style.mjs";
|
|
9
9
|
import { clampSidebarWidth, sidebarWidth } from "./width.mjs";
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -34,6 +34,7 @@ function usePageSidebar(wide, storageKey) {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
function FilterSidebar({ body, children, flush, head, header, label, storageKey, summary, wide }) {
|
|
37
|
+
const cardClassName = useSurfaceCardClassName();
|
|
37
38
|
const isCompact = useIsCompact();
|
|
38
39
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
39
40
|
const sidebar = usePageSidebar(wide, storageKey);
|
|
@@ -41,7 +42,7 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
41
42
|
if (isCompact) return /* @__PURE__ */ jsx(FilterSplitProvider, {
|
|
42
43
|
active: !flush,
|
|
43
44
|
children: /* @__PURE__ */ jsxs("div", {
|
|
44
|
-
className: styles
|
|
45
|
+
className: styles.layout,
|
|
45
46
|
children: [
|
|
46
47
|
header,
|
|
47
48
|
/* @__PURE__ */ jsx(Button, {
|
|
@@ -57,12 +58,12 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
57
58
|
width: 300,
|
|
58
59
|
onClose: close,
|
|
59
60
|
children: /* @__PURE__ */ jsxs("div", {
|
|
60
|
-
className: styles
|
|
61
|
+
className: styles.drawerPanel,
|
|
61
62
|
children: [head?.(close), body(close)]
|
|
62
63
|
})
|
|
63
64
|
}),
|
|
64
65
|
/* @__PURE__ */ jsx("div", {
|
|
65
|
-
className: styles
|
|
66
|
+
className: styles.content,
|
|
66
67
|
children
|
|
67
68
|
})
|
|
68
69
|
]
|
|
@@ -71,7 +72,7 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
71
72
|
return /* @__PURE__ */ jsx(FilterSplitProvider, {
|
|
72
73
|
active: !flush,
|
|
73
74
|
children: /* @__PURE__ */ jsxs("div", {
|
|
74
|
-
className: flush ? styles
|
|
75
|
+
className: flush ? styles.layout : `${styles.layout} ${cardClassName}`,
|
|
75
76
|
"data-flush": flush ? true : void 0,
|
|
76
77
|
"data-page-layout": flush ? "flush" : void 0,
|
|
77
78
|
"data-split-card": flush ? void 0 : true,
|
|
@@ -79,8 +80,8 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
79
80
|
expandable: true,
|
|
80
81
|
showHandleWhenCollapsed: true,
|
|
81
82
|
"aria-label": label,
|
|
82
|
-
className: styles
|
|
83
|
-
classNames: { content: styles
|
|
83
|
+
className: styles.sidebar,
|
|
84
|
+
classNames: { content: styles.panel },
|
|
84
85
|
collapseThreshold: sidebarWidth.collapse,
|
|
85
86
|
"data-flush": flush ? true : void 0,
|
|
86
87
|
defaultSize: { width: wide ? sidebarWidth.wide : sidebarWidth.narrow },
|
|
@@ -94,15 +95,15 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
94
95
|
onExpandChange: sidebar.onExpandChange,
|
|
95
96
|
onSizeChange: (_delta, size) => sidebar.onSizeChange(size),
|
|
96
97
|
children: [head ? /* @__PURE__ */ jsx("div", {
|
|
97
|
-
className: styles
|
|
98
|
+
className: styles.head,
|
|
98
99
|
children: head(close)
|
|
99
100
|
}) : null, /* @__PURE__ */ jsx("div", {
|
|
100
|
-
className: styles
|
|
101
|
+
className: styles.body,
|
|
101
102
|
"data-flush": flush ? true : void 0,
|
|
102
103
|
children: body(close)
|
|
103
104
|
})]
|
|
104
105
|
}), /* @__PURE__ */ jsxs("div", {
|
|
105
|
-
className: styles
|
|
106
|
+
className: styles.content,
|
|
106
107
|
"data-flush": flush ? true : void 0,
|
|
107
108
|
children: [header, children]
|
|
108
109
|
})]
|
|
@@ -112,12 +113,12 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
|
|
|
112
113
|
FilterSidebar.displayName = "FilterSidebar";
|
|
113
114
|
function FilterRow({ count, name }) {
|
|
114
115
|
return /* @__PURE__ */ jsxs("span", {
|
|
115
|
-
className: styles
|
|
116
|
+
className: styles.row,
|
|
116
117
|
children: [/* @__PURE__ */ jsx("span", {
|
|
117
|
-
className: styles
|
|
118
|
+
className: styles.name,
|
|
118
119
|
children: name
|
|
119
120
|
}), count !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
120
|
-
className: styles
|
|
121
|
+
className: styles.count,
|
|
121
122
|
children: count
|
|
122
123
|
}) : null]
|
|
123
124
|
});
|
|
@@ -127,18 +128,18 @@ function FilterOption({ count, icon, label, name, onClick, selected, title }) {
|
|
|
127
128
|
return /* @__PURE__ */ jsxs("button", {
|
|
128
129
|
"aria-label": label,
|
|
129
130
|
"aria-pressed": selected,
|
|
130
|
-
className: styles
|
|
131
|
+
className: styles.option,
|
|
131
132
|
title,
|
|
132
133
|
type: "button",
|
|
133
134
|
onClick,
|
|
134
135
|
children: [
|
|
135
136
|
icon,
|
|
136
137
|
/* @__PURE__ */ jsx("span", {
|
|
137
|
-
className: styles
|
|
138
|
+
className: styles.name,
|
|
138
139
|
children: name
|
|
139
140
|
}),
|
|
140
141
|
count !== void 0 ? /* @__PURE__ */ jsx("span", {
|
|
141
|
-
className: styles
|
|
142
|
+
className: styles.count,
|
|
142
143
|
children: count
|
|
143
144
|
}) : null
|
|
144
145
|
]
|
|
@@ -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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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FilterStripProps } from "./type.mjs";
|
|
2
|
+
//#region src/dashboard/FilterStrip/FilterStrip.d.ts
|
|
3
|
+
declare const formatInteger: (count: number) => string;
|
|
4
|
+
/** One surface of selectable counts. Peer filters share a seam instead of a row of equal cards. */
|
|
5
|
+
declare const FilterStrip: {
|
|
6
|
+
({ emptyText, formatCount, items, label, onChange, value }: FilterStripProps): import("react").JSX.Element;
|
|
7
|
+
displayName: string;
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { FilterStrip as default, formatInteger };
|
|
11
|
+
//# sourceMappingURL=FilterStrip.d.mts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import Skeleton from "../../base-ui/Skeleton/index.mjs";
|
|
3
|
+
import { styles } from "../Surface/style.mjs";
|
|
4
|
+
import Surface from "../Surface/Surface.mjs";
|
|
5
|
+
import { styles as styles$1 } from "./style.mjs";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { cx } from "antd-style";
|
|
8
|
+
//#region src/dashboard/FilterStrip/FilterStrip.tsx
|
|
9
|
+
const countClass = {
|
|
10
|
+
danger: styles$1.countDanger,
|
|
11
|
+
warning: styles$1.countWarning
|
|
12
|
+
};
|
|
13
|
+
const integerFormat = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
|
|
14
|
+
const formatInteger = (count) => integerFormat.format(count);
|
|
15
|
+
/** One surface of selectable counts. Peer filters share a seam instead of a row of equal cards. */
|
|
16
|
+
const FilterStrip = ({ emptyText = "--", formatCount = formatInteger, items, label, onChange, value }) => /* @__PURE__ */ jsx(Surface, {
|
|
17
|
+
className: styles.clip,
|
|
18
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
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
|
+
})
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
FilterStrip.displayName = "FilterStrip";
|
|
52
|
+
//#endregion
|
|
53
|
+
export { FilterStrip as default, formatInteger };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=FilterStrip.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createStaticStyles } from "antd-style";
|
|
2
|
+
//#region src/dashboard/FilterStrip/style.ts
|
|
3
|
+
const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
4
|
+
cell: css`
|
|
5
|
+
cursor: pointer;
|
|
6
|
+
|
|
7
|
+
position: relative;
|
|
8
|
+
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: 6px;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
|
|
14
|
+
min-inline-size: 0;
|
|
15
|
+
margin: 0;
|
|
16
|
+
padding-block: 14px 16px;
|
|
17
|
+
padding-inline: 16px;
|
|
18
|
+
border: 0;
|
|
19
|
+
|
|
20
|
+
font: inherit;
|
|
21
|
+
color: inherit;
|
|
22
|
+
text-align: start;
|
|
23
|
+
|
|
24
|
+
background: transparent;
|
|
25
|
+
box-shadow:
|
|
26
|
+
inset -1px 0 0 var(--filter-seam),
|
|
27
|
+
inset 0 -1px 0 var(--filter-seam);
|
|
28
|
+
|
|
29
|
+
&::after {
|
|
30
|
+
content: '';
|
|
31
|
+
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset-block-end: 1px;
|
|
34
|
+
inset-inline: 0;
|
|
35
|
+
|
|
36
|
+
block-size: 3px;
|
|
37
|
+
|
|
38
|
+
background: transparent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&:hover {
|
|
42
|
+
background: ${cssVar.colorFillQuaternary};
|
|
43
|
+
}
|
|
44
|
+
`,
|
|
45
|
+
cellActive: css`
|
|
46
|
+
background: ${cssVar.colorFillTertiary};
|
|
47
|
+
|
|
48
|
+
&::after {
|
|
49
|
+
background: ${cssVar.colorText};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&:hover {
|
|
53
|
+
background: ${cssVar.colorFillTertiary};
|
|
54
|
+
}
|
|
55
|
+
`,
|
|
56
|
+
count: css`
|
|
57
|
+
font-size: ${cssVar.fontSizeHeading4};
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
font-variant-numeric: tabular-nums;
|
|
60
|
+
line-height: 1.15;
|
|
61
|
+
color: ${cssVar.colorText};
|
|
62
|
+
`,
|
|
63
|
+
countDanger: css`
|
|
64
|
+
color: ${cssVar.colorError};
|
|
65
|
+
`,
|
|
66
|
+
countWarning: css`
|
|
67
|
+
color: ${cssVar.colorWarning};
|
|
68
|
+
`,
|
|
69
|
+
frame: css`
|
|
70
|
+
--filter-seam: ${cssVar.colorFillSecondary};
|
|
71
|
+
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
border-radius: inherit;
|
|
74
|
+
`,
|
|
75
|
+
grid: css`
|
|
76
|
+
display: grid;
|
|
77
|
+
grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
|
|
78
|
+
inline-size: calc(100% + 1px);
|
|
79
|
+
margin-block-end: -1px;
|
|
80
|
+
`,
|
|
81
|
+
label: css`
|
|
82
|
+
font-size: 13px;
|
|
83
|
+
font-weight: 500;
|
|
84
|
+
line-height: 1.4;
|
|
85
|
+
color: ${cssVar.colorTextSecondary};
|
|
86
|
+
`,
|
|
87
|
+
labelActive: css`
|
|
88
|
+
color: ${cssVar.colorText};
|
|
89
|
+
`
|
|
90
|
+
}));
|
|
91
|
+
//#endregion
|
|
92
|
+
export { styles };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=style.mjs.map
|
|
@@ -0,0 +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: ${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,26 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/dashboard/FilterStrip/type.d.ts
|
|
3
|
+
interface FilterStripItem {
|
|
4
|
+
count?: number;
|
|
5
|
+
/** Shown as the control's title. Definitions stay off the number so the row can be scanned. */
|
|
6
|
+
hint?: string;
|
|
7
|
+
key: string;
|
|
8
|
+
label: ReactNode;
|
|
9
|
+
loading?: boolean;
|
|
10
|
+
/** Colors the count only when it is greater than zero; a zero is not an incident. */
|
|
11
|
+
tone?: 'danger' | 'warning';
|
|
12
|
+
}
|
|
13
|
+
interface FilterStripProps {
|
|
14
|
+
/** Shown when an item has no count. Defaults to `--`. */
|
|
15
|
+
emptyText?: ReactNode;
|
|
16
|
+
/** Formats a count. Defaults to a grouped integer, e.g. `12,345`. */
|
|
17
|
+
formatCount?: (count: number) => ReactNode;
|
|
18
|
+
items: FilterStripItem[];
|
|
19
|
+
/** Accessible name for the radio group. */
|
|
20
|
+
label: string;
|
|
21
|
+
onChange: (key: string) => void;
|
|
22
|
+
value: string;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { FilterStripItem, FilterStripProps };
|
|
26
|
+
//# sourceMappingURL=type.d.mts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LabelWithKeyProps } from "./type.mjs";
|
|
2
|
+
//#region src/dashboard/LabelWithKey/LabelWithKey.d.ts
|
|
3
|
+
/** A human label followed by its machine key as a tag. */
|
|
4
|
+
declare const LabelWithKey: {
|
|
5
|
+
({ tag, title, ...rest }: LabelWithKeyProps): import("react").JSX.Element;
|
|
6
|
+
displayName: string;
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { LabelWithKey as default };
|
|
10
|
+
//# sourceMappingURL=LabelWithKey.d.mts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
|
|
3
|
+
import Tag from "../../base-ui/Tag/Tag.mjs";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/dashboard/LabelWithKey/LabelWithKey.tsx
|
|
6
|
+
/** A human label followed by its machine key as a tag. */
|
|
7
|
+
const LabelWithKey = ({ tag, title, ...rest }) => /* @__PURE__ */ jsxs(FlexBasic_default, {
|
|
8
|
+
horizontal: true,
|
|
9
|
+
align: "center",
|
|
10
|
+
gap: 8,
|
|
11
|
+
...rest,
|
|
12
|
+
children: [title, /* @__PURE__ */ jsx(Tag, { children: tag })]
|
|
13
|
+
});
|
|
14
|
+
LabelWithKey.displayName = "LabelWithKey";
|
|
15
|
+
//#endregion
|
|
16
|
+
export { LabelWithKey as default };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=LabelWithKey.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LabelWithKey.mjs","names":["Flexbox"],"sources":["../../../src/dashboard/LabelWithKey/LabelWithKey.tsx"],"sourcesContent":["'use client';\n\nimport Tag from '@/base-ui/Tag';\nimport { Flexbox } from '@/Flex';\n\nimport type { LabelWithKeyProps } from './type';\n\n/** A human label followed by its machine key as a tag. */\nconst LabelWithKey = ({ tag, title, ...rest }: LabelWithKeyProps) => (\n <Flexbox horizontal align={'center'} gap={8} {...rest}>\n {title}\n <Tag>{tag}</Tag>\n </Flexbox>\n);\n\nLabelWithKey.displayName = 'LabelWithKey';\n\nexport default LabelWithKey;\n"],"mappings":";;;;;;AAQA,MAAM,gBAAgB,EAAE,KAAK,OAAO,GAAG,WACrC,qBAACA,mBAAD;CAAS,YAAA;CAAW,OAAO;CAAU,KAAK;CAAG,GAAI;CAAjD,UAAA,CACG,OACD,oBAAC,KAAD,EAAA,UAAM,IAAS,CAAA,CACR;;AAGX,aAAa,cAAc"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FlexboxProps } from "../../Flex/type.mjs";
|
|
2
|
+
import "../../Flex/index.mjs";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
//#region src/dashboard/LabelWithKey/type.d.ts
|
|
5
|
+
interface LabelWithKeyProps extends Omit<FlexboxProps, 'title'> {
|
|
6
|
+
/** The machine key shown as a tag after the label, e.g. a config or permission id. */
|
|
7
|
+
tag: ReactNode;
|
|
8
|
+
title: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { LabelWithKeyProps };
|
|
12
|
+
//# sourceMappingURL=type.d.mts.map
|
|
@@ -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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { MetricStripProps } from "./type.mjs";
|
|
2
|
+
//#region src/dashboard/MetricStrip/MetricStrip.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Peer metrics. `joined` shares one card divided into cells; `split` gives each item its own card,
|
|
5
|
+
* identical to StatCard.
|
|
6
|
+
*/
|
|
7
|
+
declare const MetricStrip: {
|
|
8
|
+
({ items, loading, renderLink, variant }: MetricStripProps): import("react").JSX.Element;
|
|
9
|
+
displayName: string;
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { MetricStrip as default };
|
|
13
|
+
//# sourceMappingURL=MetricStrip.d.mts.map
|