@shipfox/react-ui 0.22.0 → 0.24.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/dist/components/dashboard/context/dashboard-context.d.ts +12 -8
- package/dist/components/dashboard/context/dashboard-context.js +42 -7
- package/dist/components/dashboard/context/index.d.ts +2 -2
- package/dist/components/dashboard/context/index.js +1 -1
- package/dist/components/dashboard/context/types.d.ts +9 -7
- package/dist/components/dashboard/index.d.ts +2 -4
- package/dist/components/dashboard/index.js +1 -2
- package/dist/components/dashboard/pages/analytics-page.js +2 -9
- package/dist/components/dashboard/pages/jobs-page.js +2 -4
- package/dist/components/dashboard/toolbar/filter-button.d.ts +6 -10
- package/dist/components/dashboard/toolbar/filter-button.js +109 -76
- package/dist/components/dashboard/toolbar/page-toolbar.d.ts +7 -19
- package/dist/components/dashboard/toolbar/page-toolbar.js +11 -99
- package/dist/components/dashboard/toolbar/toolbar-actions.js +3 -3
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/interval-selector/hooks/index.d.ts +4 -0
- package/dist/components/interval-selector/hooks/index.js +5 -0
- package/dist/components/interval-selector/hooks/use-interval-selector-input.d.ts +30 -0
- package/dist/components/interval-selector/hooks/use-interval-selector-input.js +125 -0
- package/dist/components/interval-selector/hooks/use-interval-selector-navigation.d.ts +21 -0
- package/dist/components/interval-selector/hooks/use-interval-selector-navigation.js +58 -0
- package/dist/components/interval-selector/hooks/use-interval-selector.d.ts +25 -0
- package/dist/components/interval-selector/hooks/use-interval-selector.js +75 -0
- package/dist/components/interval-selector/index.d.ts +3 -0
- package/dist/components/interval-selector/index.js +4 -0
- package/dist/components/interval-selector/interval-selector-calendar.d.ts +7 -0
- package/dist/components/interval-selector/interval-selector-calendar.js +47 -0
- package/dist/components/interval-selector/interval-selector-input.d.ts +8 -0
- package/dist/components/interval-selector/interval-selector-input.js +34 -0
- package/dist/components/interval-selector/interval-selector-suggestions.d.ts +11 -0
- package/dist/components/interval-selector/interval-selector-suggestions.js +107 -0
- package/dist/components/interval-selector/interval-selector.d.ts +12 -0
- package/dist/components/interval-selector/interval-selector.js +56 -0
- package/dist/components/interval-selector/interval-selector.stories.js +232 -0
- package/dist/components/interval-selector/types.d.ts +19 -0
- package/dist/components/interval-selector/types.js +3 -0
- package/dist/components/interval-selector/utils/constants.d.ts +24 -0
- package/dist/components/interval-selector/utils/constants.js +129 -0
- package/dist/components/interval-selector/utils/format.d.ts +16 -0
- package/dist/components/interval-selector/utils/format.js +23 -0
- package/dist/components/interval-selector/utils/index.d.ts +3 -0
- package/dist/components/interval-selector/utils/index.js +4 -0
- package/dist/components/modal/modal.d.ts +10 -3
- package/dist/components/modal/modal.js +30 -2
- package/dist/components/popover/popover.d.ts +3 -1
- package/dist/components/popover/popover.js +2 -1
- package/dist/styles.css +1 -1
- package/dist/utils/date.js +130 -22
- package/dist/utils/format/date.d.ts +1 -0
- package/dist/utils/format/date.js +11 -4
- package/package.json +3 -2
- package/dist/components/dashboard/filters/expression-filter-bar.d.ts +0 -42
- package/dist/components/dashboard/filters/expression-filter-bar.js +0 -80
- package/dist/components/dashboard/filters/index.d.ts +0 -6
- package/dist/components/dashboard/filters/index.js +0 -5
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* Dashboard Context Provider
|
|
3
3
|
*
|
|
4
4
|
* Provides centralized state management for dashboard components including
|
|
5
|
-
* search, filters, column visibility, time
|
|
5
|
+
* search, filters, column visibility, time interval, and sidebar navigation.
|
|
6
6
|
*/
|
|
7
|
+
import type { IntervalSelection } from '../../../components/interval-selector';
|
|
7
8
|
import { type ReactNode } from 'react';
|
|
8
|
-
import type { DashboardState, FilterOption, ResourceType,
|
|
9
|
+
import type { DashboardState, FilterOption, ResourceType, ResourceTypeOption, ViewColumn } from './types';
|
|
10
|
+
export declare const RESOURCE_TYPES: Array<ResourceType>;
|
|
11
|
+
export declare const RESOURCE_TYPE_LABELS: Record<ResourceType, string>;
|
|
12
|
+
export declare const RESOURCE_TYPE_OPTIONS: ResourceTypeOption[];
|
|
9
13
|
export interface DashboardProviderProps {
|
|
10
14
|
children: ReactNode;
|
|
11
15
|
/**
|
|
@@ -19,10 +23,10 @@ export interface DashboardProviderProps {
|
|
|
19
23
|
*/
|
|
20
24
|
initialFilters?: FilterOption[];
|
|
21
25
|
/**
|
|
22
|
-
* Initial time
|
|
23
|
-
* @default '
|
|
26
|
+
* Initial time interval selection
|
|
27
|
+
* @default { type: 'relative', duration: {days: 7} }
|
|
24
28
|
*/
|
|
25
|
-
|
|
29
|
+
initialSelection?: IntervalSelection;
|
|
26
30
|
/**
|
|
27
31
|
* Initial active sidebar item
|
|
28
32
|
* @default 'reliability'
|
|
@@ -30,7 +34,7 @@ export interface DashboardProviderProps {
|
|
|
30
34
|
initialActiveSidebarItem?: string;
|
|
31
35
|
/**
|
|
32
36
|
* Initial resource type
|
|
33
|
-
* @default 'ci
|
|
37
|
+
* @default 'ci.pipeline'
|
|
34
38
|
*/
|
|
35
39
|
initialResourceType?: ResourceType;
|
|
36
40
|
/**
|
|
@@ -46,12 +50,12 @@ export interface DashboardProviderProps {
|
|
|
46
50
|
*
|
|
47
51
|
* @example
|
|
48
52
|
* ```tsx
|
|
49
|
-
* <DashboardProvider
|
|
53
|
+
* <DashboardProvider initialInterval={intervalToNowFromDuration({days: 7})}>
|
|
50
54
|
* <AnalyticsContent />
|
|
51
55
|
* </DashboardProvider>
|
|
52
56
|
* ```
|
|
53
57
|
*/
|
|
54
|
-
export declare function DashboardProvider({ children, initialColumns, initialFilters,
|
|
58
|
+
export declare function DashboardProvider({ children, initialColumns, initialFilters, initialSelection, initialActiveSidebarItem, initialResourceType, columnMapping, }: DashboardProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
55
59
|
/**
|
|
56
60
|
* Hook to access dashboard context
|
|
57
61
|
*
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Dashboard Context Provider
|
|
3
3
|
*
|
|
4
4
|
* Provides centralized state management for dashboard components including
|
|
5
|
-
* search, filters, column visibility, time
|
|
5
|
+
* search, filters, column visibility, time interval, and sidebar navigation.
|
|
6
6
|
*/ import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
|
8
8
|
import { updateViewColumnsFromVisibility, viewColumnsToVisibilityState } from './utils.js';
|
|
@@ -85,6 +85,37 @@ const DashboardContext = /*#__PURE__*/ createContext(undefined);
|
|
|
85
85
|
checked: false
|
|
86
86
|
}
|
|
87
87
|
];
|
|
88
|
+
export const RESOURCE_TYPES = [
|
|
89
|
+
'ci.pipeline',
|
|
90
|
+
'ci.job',
|
|
91
|
+
'ci.step',
|
|
92
|
+
'test.run',
|
|
93
|
+
'test.suite',
|
|
94
|
+
'test.case'
|
|
95
|
+
];
|
|
96
|
+
export const RESOURCE_TYPE_LABELS = {
|
|
97
|
+
'ci.pipeline': 'CI Pipeline',
|
|
98
|
+
'ci.job': 'CI Job',
|
|
99
|
+
'ci.step': 'CI Step',
|
|
100
|
+
'test.run': 'Test Run',
|
|
101
|
+
'test.suite': 'Test Suite',
|
|
102
|
+
'test.case': 'Test Case'
|
|
103
|
+
};
|
|
104
|
+
export const RESOURCE_TYPE_OPTIONS = [
|
|
105
|
+
...RESOURCE_TYPES.map((type)=>({
|
|
106
|
+
id: type,
|
|
107
|
+
label: RESOURCE_TYPE_LABELS[type],
|
|
108
|
+
disabled: type.startsWith('test.')
|
|
109
|
+
}))
|
|
110
|
+
];
|
|
111
|
+
/**
|
|
112
|
+
* Default selection (relative: last 7 days)
|
|
113
|
+
*/ const DEFAULT_SELECTION = {
|
|
114
|
+
type: 'relative',
|
|
115
|
+
duration: {
|
|
116
|
+
days: 7
|
|
117
|
+
}
|
|
118
|
+
};
|
|
88
119
|
/**
|
|
89
120
|
* Dashboard Provider Component
|
|
90
121
|
*
|
|
@@ -92,19 +123,22 @@ const DashboardContext = /*#__PURE__*/ createContext(undefined);
|
|
|
92
123
|
*
|
|
93
124
|
* @example
|
|
94
125
|
* ```tsx
|
|
95
|
-
* <DashboardProvider
|
|
126
|
+
* <DashboardProvider initialInterval={intervalToNowFromDuration({days: 7})}>
|
|
96
127
|
* <AnalyticsContent />
|
|
97
128
|
* </DashboardProvider>
|
|
98
129
|
* ```
|
|
99
|
-
*/ export function DashboardProvider({ children, initialColumns = DEFAULT_COLUMNS, initialFilters = DEFAULT_FILTERS,
|
|
130
|
+
*/ export function DashboardProvider({ children, initialColumns = DEFAULT_COLUMNS, initialFilters = DEFAULT_FILTERS, initialSelection = DEFAULT_SELECTION, initialActiveSidebarItem = 'reliability', initialResourceType = 'ci.pipeline', columnMapping }) {
|
|
100
131
|
// State management
|
|
101
132
|
const [searchQuery, setSearchQuery] = useState('');
|
|
102
|
-
const [
|
|
133
|
+
const [selection, setSelection] = useState(initialSelection);
|
|
103
134
|
const [lastUpdated, setLastUpdated] = useState('13s ago');
|
|
104
135
|
const [columns, setColumns] = useState(initialColumns);
|
|
105
136
|
const [filters, setFilters] = useState(initialFilters);
|
|
106
137
|
const [activeSidebarItem, setActiveSidebarItem] = useState(initialActiveSidebarItem);
|
|
107
138
|
const [resourceType, setResourceType] = useState(initialResourceType);
|
|
139
|
+
const handleSelectionChange = useCallback((newSelection)=>{
|
|
140
|
+
setSelection(newSelection);
|
|
141
|
+
}, []);
|
|
108
142
|
// Compute column visibility state
|
|
109
143
|
const columnVisibility = useMemo(()=>viewColumnsToVisibilityState(columns, columnMapping), [
|
|
110
144
|
columns,
|
|
@@ -121,8 +155,8 @@ const DashboardContext = /*#__PURE__*/ createContext(undefined);
|
|
|
121
155
|
const value = useMemo(()=>({
|
|
122
156
|
searchQuery,
|
|
123
157
|
setSearchQuery,
|
|
124
|
-
|
|
125
|
-
|
|
158
|
+
selection,
|
|
159
|
+
setSelection: handleSelectionChange,
|
|
126
160
|
lastUpdated,
|
|
127
161
|
setLastUpdated,
|
|
128
162
|
columns,
|
|
@@ -137,7 +171,8 @@ const DashboardContext = /*#__PURE__*/ createContext(undefined);
|
|
|
137
171
|
setResourceType
|
|
138
172
|
}), [
|
|
139
173
|
searchQuery,
|
|
140
|
-
|
|
174
|
+
selection,
|
|
175
|
+
handleSelectionChange,
|
|
141
176
|
lastUpdated,
|
|
142
177
|
columns,
|
|
143
178
|
columnVisibility,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Dashboard Context exports
|
|
3
3
|
*/
|
|
4
4
|
export type { DashboardProviderProps } from './dashboard-context';
|
|
5
|
-
export { DashboardProvider, useDashboardContext } from './dashboard-context';
|
|
6
|
-
export type { DashboardState, FilterOption, ResourceType,
|
|
5
|
+
export { DashboardProvider, RESOURCE_TYPE_LABELS, RESOURCE_TYPE_OPTIONS, RESOURCE_TYPES, useDashboardContext, } from './dashboard-context';
|
|
6
|
+
export type { DashboardState, FilterOption, ResourceType, ResourceTypeOption, ViewColumn, } from './types';
|
|
7
7
|
export { DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, updateViewColumnsFromVisibility, viewColumnsToVisibilityState, } from './utils';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard Context exports
|
|
3
|
-
*/ export { DashboardProvider, useDashboardContext } from './dashboard-context.js';
|
|
3
|
+
*/ export { DashboardProvider, RESOURCE_TYPE_LABELS, RESOURCE_TYPE_OPTIONS, RESOURCE_TYPES, useDashboardContext } from './dashboard-context.js';
|
|
4
4
|
export { DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, updateViewColumnsFromVisibility, viewColumnsToVisibilityState } from './utils.js';
|
|
5
5
|
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Shared types for dashboard components
|
|
3
3
|
*/
|
|
4
4
|
import type { VisibilityState } from '@tanstack/react-table';
|
|
5
|
+
import type { IntervalSelection } from '../../../components/interval-selector';
|
|
5
6
|
/**
|
|
6
7
|
* View column configuration for table visibility control
|
|
7
8
|
*/
|
|
@@ -18,22 +19,23 @@ export interface FilterOption {
|
|
|
18
19
|
label: string;
|
|
19
20
|
checked: boolean;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
* Time period option
|
|
23
|
-
*/
|
|
24
|
-
export type TimePeriod = '1hour' | '1day' | '2days' | '7days' | '30days';
|
|
22
|
+
export type ResourceType = 'ci.pipeline' | 'ci.job' | 'ci.step' | 'test.run' | 'test.suite' | 'test.case';
|
|
25
23
|
/**
|
|
26
24
|
* Resource type option
|
|
27
25
|
*/
|
|
28
|
-
export
|
|
26
|
+
export interface ResourceTypeOption {
|
|
27
|
+
id: ResourceType;
|
|
28
|
+
label: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
}
|
|
29
31
|
/**
|
|
30
32
|
* Dashboard context state
|
|
31
33
|
*/
|
|
32
34
|
export interface DashboardState {
|
|
33
35
|
searchQuery: string;
|
|
34
36
|
setSearchQuery: (query: string) => void;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
selection: IntervalSelection;
|
|
38
|
+
setSelection: (selection: IntervalSelection) => void;
|
|
37
39
|
lastUpdated: string;
|
|
38
40
|
setLastUpdated: (timestamp: string) => void;
|
|
39
41
|
columns: ViewColumn[];
|
|
@@ -7,12 +7,10 @@ export type { MobileSidebarProps } from './components/mobile-sidebar';
|
|
|
7
7
|
export { MobileSidebar } from './components/mobile-sidebar';
|
|
8
8
|
export type { SidebarNavItem, SidebarProps } from './components/sidebar';
|
|
9
9
|
export { defaultSidebarItems, Sidebar } from './components/sidebar';
|
|
10
|
-
export type { DashboardProviderProps, DashboardState, FilterOption, ResourceType,
|
|
11
|
-
export { DashboardProvider, DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, updateViewColumnsFromVisibility, useDashboardContext, viewColumnsToVisibilityState, } from './context';
|
|
10
|
+
export type { DashboardProviderProps, DashboardState, FilterOption, ResourceType, ViewColumn, } from './context';
|
|
11
|
+
export { DashboardProvider, DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, RESOURCE_TYPE_OPTIONS, updateViewColumnsFromVisibility, useDashboardContext, viewColumnsToVisibilityState, } from './context';
|
|
12
12
|
export type { DashboardProps } from './dashboard';
|
|
13
13
|
export { Dashboard } from './dashboard';
|
|
14
|
-
export type { ExpressionFilterBarProps, ResourceTypeOption } from './filters';
|
|
15
|
-
export { ExpressionFilterBar } from './filters';
|
|
16
14
|
export { AnalyticsPage, JobsPage } from './pages';
|
|
17
15
|
export type { TableWrapperProps } from './table';
|
|
18
16
|
export { TableWrapper } from './table';
|
|
@@ -3,9 +3,8 @@ export { DashboardAlert } from './components/dashboard-alert.js';
|
|
|
3
3
|
export { KpiCard, KpiCardsGroup } from './components/kpi-card.js';
|
|
4
4
|
export { MobileSidebar } from './components/mobile-sidebar.js';
|
|
5
5
|
export { defaultSidebarItems, Sidebar } from './components/sidebar.js';
|
|
6
|
-
export { DashboardProvider, DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, updateViewColumnsFromVisibility, useDashboardContext, viewColumnsToVisibilityState } from './context/index.js';
|
|
6
|
+
export { DashboardProvider, DEFAULT_COLUMN_ID_TO_ACCESSOR_KEY, RESOURCE_TYPE_OPTIONS, updateViewColumnsFromVisibility, useDashboardContext, viewColumnsToVisibilityState } from './context/index.js';
|
|
7
7
|
export { Dashboard } from './dashboard.js';
|
|
8
|
-
export { ExpressionFilterBar } from './filters/index.js';
|
|
9
8
|
export { AnalyticsPage, JobsPage } from './pages/index.js';
|
|
10
9
|
export { TableWrapper } from './table/index.js';
|
|
11
10
|
export { FilterButton, PageToolbar, ToolbarActions, ToolbarSearch, ViewDropdown } from './toolbar/index.js';
|
|
@@ -15,7 +15,6 @@ import { KpiCardsGroup } from '../components/kpi-card.js';
|
|
|
15
15
|
import { MobileSidebar } from '../components/mobile-sidebar.js';
|
|
16
16
|
import { defaultSidebarItems, Sidebar } from '../components/sidebar.js';
|
|
17
17
|
import { useDashboardContext } from '../context/index.js';
|
|
18
|
-
import { ExpressionFilterBar } from '../filters/index.js';
|
|
19
18
|
import { TableWrapper } from '../table/index.js';
|
|
20
19
|
import { PageToolbar, ToolbarActions } from '../toolbar/index.js';
|
|
21
20
|
const performanceData = [
|
|
@@ -147,7 +146,7 @@ const kpiCards = [
|
|
|
147
146
|
}
|
|
148
147
|
];
|
|
149
148
|
export function AnalyticsPage() {
|
|
150
|
-
const { searchQuery, setSearchQuery,
|
|
149
|
+
const { searchQuery, setSearchQuery, columnVisibility, updateColumnVisibility, activeSidebarItem, setActiveSidebarItem } = useDashboardContext();
|
|
151
150
|
const isDesktop = useMediaQuery('(min-width: 1024px)');
|
|
152
151
|
const [performanceTimeRange, setPerformanceTimeRange] = useState('2h');
|
|
153
152
|
const pageTitle = useMemo(()=>{
|
|
@@ -164,9 +163,7 @@ export function AnalyticsPage() {
|
|
|
164
163
|
children: [
|
|
165
164
|
/*#__PURE__*/ _jsx(PageToolbar, {
|
|
166
165
|
title: pageTitle,
|
|
167
|
-
|
|
168
|
-
onTimePeriodChange: setTimePeriod,
|
|
169
|
-
lastUpdated: lastUpdated,
|
|
166
|
+
onRefresh: ()=>undefined,
|
|
170
167
|
children: !isDesktop && /*#__PURE__*/ _jsx(MobileSidebar, {
|
|
171
168
|
items: defaultSidebarItems,
|
|
172
169
|
activeItemId: activeSidebarItem,
|
|
@@ -196,10 +193,6 @@ export function AnalyticsPage() {
|
|
|
196
193
|
onClick: ()=>undefined
|
|
197
194
|
}
|
|
198
195
|
}),
|
|
199
|
-
/*#__PURE__*/ _jsx(ExpressionFilterBar, {
|
|
200
|
-
value: resourceType,
|
|
201
|
-
onValueChange: setResourceType
|
|
202
|
-
}),
|
|
203
196
|
/*#__PURE__*/ _jsx(ToolbarActions, {}),
|
|
204
197
|
/*#__PURE__*/ _jsx(KpiCardsGroup, {
|
|
205
198
|
cards: kpiCards
|
|
@@ -9,7 +9,7 @@ import { useDashboardContext } from '../context/index.js';
|
|
|
9
9
|
import { TableWrapper } from '../table/index.js';
|
|
10
10
|
import { PageToolbar } from '../toolbar/index.js';
|
|
11
11
|
export function JobsPage() {
|
|
12
|
-
const { searchQuery, setSearchQuery,
|
|
12
|
+
const { searchQuery, setSearchQuery, columnVisibility, updateColumnVisibility } = useDashboardContext();
|
|
13
13
|
const filteredData = useMemo(()=>jobsData.filter((job)=>job.name.toLowerCase().includes(searchQuery.toLowerCase())), [
|
|
14
14
|
searchQuery
|
|
15
15
|
]);
|
|
@@ -18,9 +18,7 @@ export function JobsPage() {
|
|
|
18
18
|
children: [
|
|
19
19
|
/*#__PURE__*/ _jsx(PageToolbar, {
|
|
20
20
|
title: "Jobs",
|
|
21
|
-
|
|
22
|
-
onTimePeriodChange: setTimePeriod,
|
|
23
|
-
lastUpdated: lastUpdated
|
|
21
|
+
onRefresh: ()=>undefined
|
|
24
22
|
}),
|
|
25
23
|
/*#__PURE__*/ _jsx("div", {
|
|
26
24
|
className: "flex-1 px-12 pb-12 pt-4 md:px-24 md:pb-24 overflow-auto",
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
import type { ResourceType } from '../context/types';
|
|
3
|
+
export interface FilterButtonProps extends HTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
value: ResourceType;
|
|
5
|
+
onValueChange: (value: ResourceType) => void;
|
|
5
6
|
}
|
|
6
|
-
export
|
|
7
|
-
filters?: FilterOption[];
|
|
8
|
-
onFiltersChange?: (filters: FilterOption[]) => void;
|
|
9
|
-
className?: string;
|
|
10
|
-
}
|
|
11
|
-
export declare function FilterButton({ filters: controlledFilters, onFiltersChange, className, }: FilterButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function FilterButton({ value, onValueChange, className, ...props }: FilterButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
12
8
|
//# sourceMappingURL=filter-button.d.ts.map
|
|
@@ -1,73 +1,66 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Button } from '../../../components/button/index.js';
|
|
3
|
-
import { DropdownMenu,
|
|
4
|
-
import { Icon } from '../../../components/icon/index.js';
|
|
3
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from '../../../components/dropdown-menu/index.js';
|
|
5
4
|
import { Kbd } from '../../../components/kbd/index.js';
|
|
6
5
|
import { useEffect, useState } from 'react';
|
|
7
6
|
import { cn } from '../../../utils/cn.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
id: 'success',
|
|
11
|
-
label: 'Success',
|
|
12
|
-
checked: false
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
id: 'failed',
|
|
16
|
-
label: 'Failed',
|
|
17
|
-
checked: false
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
id: 'neutral',
|
|
21
|
-
label: 'Neutral',
|
|
22
|
-
checked: false
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'flaked',
|
|
26
|
-
label: 'Flaked',
|
|
27
|
-
checked: false
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: 'running',
|
|
31
|
-
label: 'Running',
|
|
32
|
-
checked: false
|
|
33
|
-
}
|
|
34
|
-
];
|
|
35
|
-
export function FilterButton({ filters: controlledFilters, onFiltersChange, className }) {
|
|
36
|
-
const [internalFilters, setInternalFilters] = useState(defaultFilters);
|
|
7
|
+
import { RESOURCE_TYPE_LABELS, RESOURCE_TYPE_OPTIONS } from '../context/index.js';
|
|
8
|
+
export function FilterButton({ value, onValueChange, className, ...props }) {
|
|
37
9
|
const [open, setOpen] = useState(false);
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
const filterOptions = RESOURCE_TYPE_OPTIONS.filter((opt)=>!opt.disabled);
|
|
11
|
+
const normalizedValue = filterOptions.some((opt)=>opt.id === value) ? value : filterOptions[0]?.id ?? value;
|
|
12
|
+
const selectedLabel = RESOURCE_TYPE_LABELS[normalizedValue] ?? normalizedValue;
|
|
13
|
+
const selectedIndex = filterOptions.findIndex((opt)=>opt.id === normalizedValue);
|
|
14
|
+
const handleFilterChange = (filterId)=>{
|
|
15
|
+
onValueChange(filterId);
|
|
16
|
+
setOpen(false);
|
|
17
|
+
};
|
|
18
|
+
const indicator = (index)=>{
|
|
19
|
+
if (index === 0) {
|
|
20
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
21
|
+
className: "size-[8.3px] rotate-45 border border-tag-purple-icon"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
25
|
+
className: "size-10 rounded-full border border-tag-neutral-icon"
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const calculatePaddingLeft = (index)=>{
|
|
29
|
+
switch(index){
|
|
30
|
+
case 0:
|
|
31
|
+
return 10;
|
|
32
|
+
case 1:
|
|
33
|
+
return 28;
|
|
34
|
+
case 2:
|
|
35
|
+
return 48;
|
|
36
|
+
default:
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const calculateLeftPosition = (index)=>{
|
|
41
|
+
switch(index){
|
|
42
|
+
case 0:
|
|
43
|
+
return 0;
|
|
44
|
+
case 1:
|
|
45
|
+
return 16;
|
|
46
|
+
case 2:
|
|
47
|
+
return 34;
|
|
48
|
+
default:
|
|
49
|
+
return 0;
|
|
48
50
|
}
|
|
49
51
|
};
|
|
50
|
-
const activeCount = filters.filter((f)=>f.checked).length;
|
|
51
|
-
// Keyboard shortcut handler for "F" key
|
|
52
52
|
useEffect(()=>{
|
|
53
53
|
const handleKeyDown = (event)=>{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
|
61
|
-
return;
|
|
54
|
+
if (event.key === 'ArrowDown' && (event.metaKey || event.ctrlKey) && event.target instanceof HTMLElement && ![
|
|
55
|
+
'INPUT',
|
|
56
|
+
'TEXTAREA'
|
|
57
|
+
].includes(event.target.tagName) && !event.target.isContentEditable) {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
setOpen(true);
|
|
62
60
|
}
|
|
63
|
-
// Open the dropdown
|
|
64
|
-
event.preventDefault();
|
|
65
|
-
setOpen(true);
|
|
66
61
|
};
|
|
67
62
|
window.addEventListener('keydown', handleKeyDown);
|
|
68
|
-
return ()=>
|
|
69
|
-
window.removeEventListener('keydown', handleKeyDown);
|
|
70
|
-
};
|
|
63
|
+
return ()=>window.removeEventListener('keydown', handleKeyDown);
|
|
71
64
|
}, []);
|
|
72
65
|
return /*#__PURE__*/ _jsxs(DropdownMenu, {
|
|
73
66
|
open: open,
|
|
@@ -78,25 +71,35 @@ export function FilterButton({ filters: controlledFilters, onFiltersChange, clas
|
|
|
78
71
|
children: /*#__PURE__*/ _jsxs(Button, {
|
|
79
72
|
variant: "secondary",
|
|
80
73
|
size: "sm",
|
|
81
|
-
className: cn(className),
|
|
74
|
+
className: cn('px-10', className),
|
|
75
|
+
...props,
|
|
82
76
|
children: [
|
|
83
|
-
/*#__PURE__*/ _jsx(Icon, {
|
|
84
|
-
name: "filterLine",
|
|
85
|
-
className: "size-16 text-foreground-neutral-subtle block md:hidden"
|
|
86
|
-
}),
|
|
87
77
|
/*#__PURE__*/ _jsxs("span", {
|
|
88
78
|
className: "hidden md:inline-flex items-center gap-6",
|
|
89
79
|
children: [
|
|
90
|
-
|
|
80
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
81
|
+
className: "inline-flex items-center gap-8",
|
|
82
|
+
children: [
|
|
83
|
+
selectedIndex >= 0 && indicator(selectedIndex),
|
|
84
|
+
/*#__PURE__*/ _jsx("span", {
|
|
85
|
+
children: selectedLabel
|
|
86
|
+
})
|
|
87
|
+
]
|
|
88
|
+
}),
|
|
91
89
|
/*#__PURE__*/ _jsx(Kbd, {
|
|
92
90
|
className: "h-16 min-w-16 px-4 text-[10px]",
|
|
93
|
-
children: "
|
|
91
|
+
children: "⌘↓"
|
|
94
92
|
})
|
|
95
93
|
]
|
|
96
94
|
}),
|
|
97
|
-
|
|
98
|
-
className: "
|
|
99
|
-
children:
|
|
95
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
96
|
+
className: "flex md:hidden items-center gap-8",
|
|
97
|
+
children: [
|
|
98
|
+
selectedIndex >= 0 && indicator(selectedIndex),
|
|
99
|
+
/*#__PURE__*/ _jsx("span", {
|
|
100
|
+
children: selectedLabel
|
|
101
|
+
})
|
|
102
|
+
]
|
|
100
103
|
})
|
|
101
104
|
]
|
|
102
105
|
})
|
|
@@ -106,15 +109,45 @@ export function FilterButton({ filters: controlledFilters, onFiltersChange, clas
|
|
|
106
109
|
className: "w-200",
|
|
107
110
|
children: [
|
|
108
111
|
/*#__PURE__*/ _jsx(DropdownMenuLabel, {
|
|
109
|
-
|
|
112
|
+
className: "text-foreground-neutral-muted text-xs",
|
|
113
|
+
children: "CI Structure"
|
|
110
114
|
}),
|
|
111
|
-
/*#__PURE__*/ _jsx(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
/*#__PURE__*/ _jsx(DropdownMenuGroup, {
|
|
116
|
+
children: filterOptions.map((option, index)=>{
|
|
117
|
+
return /*#__PURE__*/ _jsxs(DropdownMenuItem, {
|
|
118
|
+
onClick: ()=>handleFilterChange(option.id),
|
|
119
|
+
style: {
|
|
120
|
+
paddingLeft: calculatePaddingLeft(index)
|
|
121
|
+
},
|
|
122
|
+
className: cn('relative hover:text-foreground-neutral-base', selectedIndex === index && 'text-foreground-neutral-base'),
|
|
123
|
+
children: [
|
|
124
|
+
index !== 0 && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
125
|
+
children: [
|
|
126
|
+
/*#__PURE__*/ _jsx("span", {
|
|
127
|
+
className: "absolute top-0 bottom-0 w-px bg-border-neutral-strong h-16",
|
|
128
|
+
style: {
|
|
129
|
+
left: calculateLeftPosition(index)
|
|
130
|
+
}
|
|
131
|
+
}),
|
|
132
|
+
/*#__PURE__*/ _jsx("span", {
|
|
133
|
+
className: "absolute top-16 bottom-0 w-6 bg-border-neutral-strong h-px",
|
|
134
|
+
style: {
|
|
135
|
+
left: calculateLeftPosition(index)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
]
|
|
139
|
+
}),
|
|
140
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
141
|
+
className: "inline-flex items-center gap-8 ml-2",
|
|
142
|
+
children: [
|
|
143
|
+
indicator(index),
|
|
144
|
+
option.label
|
|
145
|
+
]
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
}, option.id);
|
|
149
|
+
})
|
|
150
|
+
})
|
|
118
151
|
]
|
|
119
152
|
})
|
|
120
153
|
]
|
|
@@ -5,26 +5,11 @@
|
|
|
5
5
|
* time period selector, and playback controls.
|
|
6
6
|
*/
|
|
7
7
|
import type { ComponentProps, ReactNode } from 'react';
|
|
8
|
-
import type { TimePeriod } from '../context';
|
|
9
8
|
export interface PageToolbarProps extends Omit<ComponentProps<'div'>, 'title' | 'children'> {
|
|
10
9
|
/**
|
|
11
10
|
* The title to display in the toolbar header
|
|
12
11
|
*/
|
|
13
12
|
title: ReactNode;
|
|
14
|
-
/**
|
|
15
|
-
* Last updated timestamp text
|
|
16
|
-
* @default '13s ago'
|
|
17
|
-
*/
|
|
18
|
-
lastUpdated?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Current time period value
|
|
21
|
-
* @default '2days'
|
|
22
|
-
*/
|
|
23
|
-
timePeriod?: TimePeriod;
|
|
24
|
-
/**
|
|
25
|
-
* Callback when time period changes
|
|
26
|
-
*/
|
|
27
|
-
onTimePeriodChange?: (value: TimePeriod) => void;
|
|
28
13
|
/**
|
|
29
14
|
* Callback when refresh button is clicked
|
|
30
15
|
*/
|
|
@@ -54,22 +39,25 @@ export interface PageToolbarProps extends Omit<ComponentProps<'div'>, 'title' |
|
|
|
54
39
|
* Children to render (e.g., mobile menu button)
|
|
55
40
|
*/
|
|
56
41
|
children?: ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Custom container for the interval selector popover
|
|
44
|
+
*/
|
|
45
|
+
intervalSelectorContainer?: HTMLElement | null;
|
|
57
46
|
}
|
|
58
47
|
/**
|
|
59
48
|
* Generic Page Toolbar
|
|
60
49
|
*
|
|
61
50
|
* A flexible toolbar component that can be used across different dashboard pages.
|
|
62
|
-
* Supports title customization, time
|
|
51
|
+
* Supports title customization, time interval selection, refresh indicator, and playback controls.
|
|
52
|
+
* Uses DashboardContext for interval state management.
|
|
63
53
|
*
|
|
64
54
|
* @example
|
|
65
55
|
* ```tsx
|
|
66
56
|
* <PageToolbar
|
|
67
57
|
* title="Analytics"
|
|
68
|
-
* timePeriod="2days"
|
|
69
|
-
* onTimePeriodChange={setTimePeriod}
|
|
70
58
|
* onRefresh={handleRefresh}
|
|
71
59
|
* />
|
|
72
60
|
* ```
|
|
73
61
|
*/
|
|
74
|
-
export declare function PageToolbar({ title,
|
|
62
|
+
export declare function PageToolbar({ title, onRefresh, showPlaybackControls, onRewind, onPlay, onSpeed, actions, children, intervalSelectorContainer, className, ...props }: PageToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
75
63
|
//# sourceMappingURL=page-toolbar.d.ts.map
|