@shipfox/react-ui 0.21.0 → 0.23.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/components/charts/bar-chart.d.ts +3 -2
- package/dist/components/dashboard/components/charts/bar-chart.js +13 -7
- package/dist/components/dashboard/components/charts/line-chart.d.ts +3 -2
- package/dist/components/dashboard/components/charts/line-chart.js +13 -7
- 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 +41 -11
- 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/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 +2 -1
- 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
|
@@ -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
|
|
@@ -7,26 +7,26 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
*/ import { Button } from '../../../components/button/index.js';
|
|
8
8
|
import { ButtonGroup, ButtonGroupSeparator } from '../../../components/button-group/index.js';
|
|
9
9
|
import { Icon } from '../../../components/icon/index.js';
|
|
10
|
-
import {
|
|
11
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../components/select/index.js';
|
|
10
|
+
import { IntervalSelector } from '../../../components/interval-selector/index.js';
|
|
12
11
|
import { Header, Text } from '../../../components/typography/index.js';
|
|
13
12
|
import { cn } from '../../../utils/cn.js';
|
|
13
|
+
import { useDashboardContext } from '../context/index.js';
|
|
14
14
|
/**
|
|
15
15
|
* Generic Page Toolbar
|
|
16
16
|
*
|
|
17
17
|
* A flexible toolbar component that can be used across different dashboard pages.
|
|
18
|
-
* Supports title customization, time
|
|
18
|
+
* Supports title customization, time interval selection, refresh indicator, and playback controls.
|
|
19
|
+
* Uses DashboardContext for interval state management.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```tsx
|
|
22
23
|
* <PageToolbar
|
|
23
24
|
* title="Analytics"
|
|
24
|
-
* timePeriod="2days"
|
|
25
|
-
* onTimePeriodChange={setTimePeriod}
|
|
26
25
|
* onRefresh={handleRefresh}
|
|
27
26
|
* />
|
|
28
27
|
* ```
|
|
29
|
-
*/ export function PageToolbar({ title,
|
|
28
|
+
*/ export function PageToolbar({ title, onRefresh, showPlaybackControls = true, onRewind, onPlay, onSpeed, actions, children, intervalSelectorContainer, className, ...props }) {
|
|
29
|
+
const { selection, setSelection, lastUpdated } = useDashboardContext();
|
|
30
30
|
return /*#__PURE__*/ _jsxs("div", {
|
|
31
31
|
className: cn('flex flex-wrap gap-12 items-center justify-between px-12 py-20 md:px-24 md:py-40', className),
|
|
32
32
|
...props,
|
|
@@ -66,99 +66,11 @@ import { cn } from '../../../utils/cn.js';
|
|
|
66
66
|
]
|
|
67
67
|
})
|
|
68
68
|
}),
|
|
69
|
-
/*#__PURE__*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
className: "w-full md:w-280",
|
|
75
|
-
children: /*#__PURE__*/ _jsx("div", {
|
|
76
|
-
className: "flex items-center gap-8 flex-1 min-w-0",
|
|
77
|
-
children: /*#__PURE__*/ _jsx(SelectValue, {
|
|
78
|
-
placeholder: "Select time range"
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
}),
|
|
82
|
-
/*#__PURE__*/ _jsxs(SelectContent, {
|
|
83
|
-
children: [
|
|
84
|
-
/*#__PURE__*/ _jsx(SelectItem, {
|
|
85
|
-
value: "1hour",
|
|
86
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
87
|
-
className: "flex items-center gap-8",
|
|
88
|
-
children: [
|
|
89
|
-
/*#__PURE__*/ _jsx(Kbd, {
|
|
90
|
-
className: "h-16",
|
|
91
|
-
children: "1h"
|
|
92
|
-
}),
|
|
93
|
-
/*#__PURE__*/ _jsx("span", {
|
|
94
|
-
children: "Past 1 Hour"
|
|
95
|
-
})
|
|
96
|
-
]
|
|
97
|
-
})
|
|
98
|
-
}),
|
|
99
|
-
/*#__PURE__*/ _jsx(SelectItem, {
|
|
100
|
-
value: "1day",
|
|
101
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
102
|
-
className: "flex items-center gap-8",
|
|
103
|
-
children: [
|
|
104
|
-
/*#__PURE__*/ _jsx(Kbd, {
|
|
105
|
-
className: "h-16",
|
|
106
|
-
children: "1d"
|
|
107
|
-
}),
|
|
108
|
-
/*#__PURE__*/ _jsx("span", {
|
|
109
|
-
children: "Past 1 Day"
|
|
110
|
-
})
|
|
111
|
-
]
|
|
112
|
-
})
|
|
113
|
-
}),
|
|
114
|
-
/*#__PURE__*/ _jsx(SelectItem, {
|
|
115
|
-
value: "2days",
|
|
116
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
117
|
-
className: "flex items-center gap-8",
|
|
118
|
-
children: [
|
|
119
|
-
/*#__PURE__*/ _jsx(Kbd, {
|
|
120
|
-
className: "h-16",
|
|
121
|
-
children: "2d"
|
|
122
|
-
}),
|
|
123
|
-
/*#__PURE__*/ _jsx("span", {
|
|
124
|
-
children: "Past 2 Days"
|
|
125
|
-
})
|
|
126
|
-
]
|
|
127
|
-
})
|
|
128
|
-
}),
|
|
129
|
-
/*#__PURE__*/ _jsx(SelectItem, {
|
|
130
|
-
value: "7days",
|
|
131
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
132
|
-
className: "flex items-center gap-8",
|
|
133
|
-
children: [
|
|
134
|
-
/*#__PURE__*/ _jsx(Kbd, {
|
|
135
|
-
className: "h-16",
|
|
136
|
-
children: "7d"
|
|
137
|
-
}),
|
|
138
|
-
/*#__PURE__*/ _jsx("span", {
|
|
139
|
-
children: "Past 7 Days"
|
|
140
|
-
})
|
|
141
|
-
]
|
|
142
|
-
})
|
|
143
|
-
}),
|
|
144
|
-
/*#__PURE__*/ _jsx(SelectItem, {
|
|
145
|
-
value: "30days",
|
|
146
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
147
|
-
className: "flex items-center gap-8",
|
|
148
|
-
children: [
|
|
149
|
-
/*#__PURE__*/ _jsx(Kbd, {
|
|
150
|
-
className: "h-16",
|
|
151
|
-
children: "30d"
|
|
152
|
-
}),
|
|
153
|
-
/*#__PURE__*/ _jsx("span", {
|
|
154
|
-
children: "Past 30 Days"
|
|
155
|
-
})
|
|
156
|
-
]
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
]
|
|
160
|
-
})
|
|
161
|
-
]
|
|
69
|
+
/*#__PURE__*/ _jsx(IntervalSelector, {
|
|
70
|
+
selection: selection,
|
|
71
|
+
onSelectionChange: setSelection,
|
|
72
|
+
container: intervalSelectorContainer,
|
|
73
|
+
className: "w-[75vw] md:w-350"
|
|
162
74
|
}),
|
|
163
75
|
showPlaybackControls && /*#__PURE__*/ _jsxs(ButtonGroup, {
|
|
164
76
|
"aria-label": "Playback controls",
|
|
@@ -26,14 +26,14 @@ import { ViewDropdown } from './view-dropdown.js';
|
|
|
26
26
|
* </ToolbarActions>
|
|
27
27
|
* ```
|
|
28
28
|
*/ export function ToolbarActions({ showFilter = true, showSearch = true, showView = true, searchPlaceholder = 'Try: job name, status, pipeline...', className, children, ...props }) {
|
|
29
|
-
const { setSearchQuery,
|
|
29
|
+
const { setSearchQuery, resourceType, setResourceType, columns, setColumns } = useDashboardContext();
|
|
30
30
|
return /*#__PURE__*/ _jsxs("div", {
|
|
31
31
|
className: cn('flex items-start md:items-center gap-8 md:gap-12', className),
|
|
32
32
|
...props,
|
|
33
33
|
children: [
|
|
34
34
|
showFilter && /*#__PURE__*/ _jsx(FilterButton, {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
value: resourceType,
|
|
36
|
+
onValueChange: setResourceType
|
|
37
37
|
}),
|
|
38
38
|
showSearch && /*#__PURE__*/ _jsx(ToolbarSearch, {
|
|
39
39
|
placeholder: searchPlaceholder,
|
package/dist/components/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export * from './form/index.js';
|
|
|
23
23
|
export * from './icon/index.js';
|
|
24
24
|
export * from './inline-tips/index.js';
|
|
25
25
|
export * from './input/index.js';
|
|
26
|
+
export * from './interval-selector/index.js';
|
|
26
27
|
export * from './item/index.js';
|
|
27
28
|
export * from './kbd/index.js';
|
|
28
29
|
export * from './label/index.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { IntervalSelection } from '../types';
|
|
2
|
+
export interface UseNewIntervalSelectorInputProps {
|
|
3
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
4
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
5
|
+
onFocus?: () => void;
|
|
6
|
+
onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
7
|
+
onSelect: (selection: IntervalSelection) => void;
|
|
8
|
+
selection: IntervalSelection;
|
|
9
|
+
isNavigating: boolean;
|
|
10
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
11
|
+
isFocused: boolean;
|
|
12
|
+
setIsFocused: (isFocused: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function useIntervalSelectorInput({ onChange: onChangeProp, onKeyDown: onKeyDownProp, onFocus: onFocusProp, onBlur: onBlurProp, onSelect, selection, isNavigating, inputRef, isFocused, setIsFocused, }: UseNewIntervalSelectorInputProps): {
|
|
15
|
+
value: string;
|
|
16
|
+
shouldShake: boolean;
|
|
17
|
+
isFocused: boolean;
|
|
18
|
+
isInvalid: boolean;
|
|
19
|
+
displayValue: string;
|
|
20
|
+
shortcutValue: string;
|
|
21
|
+
setValue: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
22
|
+
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
23
|
+
onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
24
|
+
onFocus: () => void;
|
|
25
|
+
onMouseDown: () => void;
|
|
26
|
+
onMouseUp: () => void;
|
|
27
|
+
onBlur: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
28
|
+
inputRef: import("react").RefObject<HTMLInputElement | null>;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=use-interval-selector-input.d.ts.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { parseTextDurationShortcut, parseTextInterval } from '../../../utils/date.js';
|
|
3
|
+
import { formatSelection, formatSelectionForInput, formatShortcut } from '../utils/format.js';
|
|
4
|
+
export function useIntervalSelectorInput({ onChange: onChangeProp, onKeyDown: onKeyDownProp, onFocus: onFocusProp, onBlur: onBlurProp, onSelect, selection, isNavigating, inputRef, isFocused, setIsFocused }) {
|
|
5
|
+
const [value, setValue] = useState('');
|
|
6
|
+
const [isInvalid, setIsInvalid] = useState(false);
|
|
7
|
+
const [shouldShake, setShouldShake] = useState(false);
|
|
8
|
+
const shakeTimeoutRef = useRef(null);
|
|
9
|
+
const isMouseDownOnInputRef = useRef(false);
|
|
10
|
+
const onChange = useCallback((e)=>{
|
|
11
|
+
const newValue = e.target.value;
|
|
12
|
+
setValue(newValue);
|
|
13
|
+
const shortcut = parseTextDurationShortcut(newValue);
|
|
14
|
+
const interval = parseTextInterval(newValue);
|
|
15
|
+
const isValid = shortcut || interval || newValue.trim() === '';
|
|
16
|
+
setIsInvalid(!isValid);
|
|
17
|
+
onChangeProp?.(e);
|
|
18
|
+
}, [
|
|
19
|
+
onChangeProp
|
|
20
|
+
]);
|
|
21
|
+
const triggerShakeAnimation = useCallback(()=>{
|
|
22
|
+
if (shakeTimeoutRef.current) clearTimeout(shakeTimeoutRef.current);
|
|
23
|
+
setIsInvalid(true);
|
|
24
|
+
setShouldShake(true);
|
|
25
|
+
shakeTimeoutRef.current = setTimeout(()=>{
|
|
26
|
+
setShouldShake(false);
|
|
27
|
+
shakeTimeoutRef.current = null;
|
|
28
|
+
}, 500);
|
|
29
|
+
}, []);
|
|
30
|
+
const handleConfirmInput = useCallback(()=>{
|
|
31
|
+
const shortcut = parseTextDurationShortcut(value);
|
|
32
|
+
if (shortcut) return onSelect({
|
|
33
|
+
type: 'relative',
|
|
34
|
+
duration: shortcut
|
|
35
|
+
});
|
|
36
|
+
const interval = parseTextInterval(value);
|
|
37
|
+
if (interval) return onSelect({
|
|
38
|
+
type: 'interval',
|
|
39
|
+
interval
|
|
40
|
+
});
|
|
41
|
+
triggerShakeAnimation();
|
|
42
|
+
}, [
|
|
43
|
+
value,
|
|
44
|
+
onSelect,
|
|
45
|
+
triggerShakeAnimation
|
|
46
|
+
]);
|
|
47
|
+
const onKeyDown = useCallback((e)=>{
|
|
48
|
+
if (!isNavigating && e.key === 'Enter') {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
handleConfirmInput();
|
|
51
|
+
}
|
|
52
|
+
onKeyDownProp?.(e);
|
|
53
|
+
}, [
|
|
54
|
+
isNavigating,
|
|
55
|
+
handleConfirmInput,
|
|
56
|
+
onKeyDownProp
|
|
57
|
+
]);
|
|
58
|
+
const onFocus = useCallback(()=>{
|
|
59
|
+
setIsFocused(true);
|
|
60
|
+
setValue(formatSelectionForInput(selection));
|
|
61
|
+
setIsInvalid(false);
|
|
62
|
+
requestAnimationFrame(()=>{
|
|
63
|
+
inputRef.current?.select();
|
|
64
|
+
});
|
|
65
|
+
onFocusProp?.();
|
|
66
|
+
}, [
|
|
67
|
+
selection,
|
|
68
|
+
onFocusProp,
|
|
69
|
+
inputRef,
|
|
70
|
+
setIsFocused
|
|
71
|
+
]);
|
|
72
|
+
const onMouseDown = useCallback(()=>{
|
|
73
|
+
isMouseDownOnInputRef.current = true;
|
|
74
|
+
}, []);
|
|
75
|
+
const onMouseUp = useCallback(()=>{
|
|
76
|
+
setTimeout(()=>{
|
|
77
|
+
isMouseDownOnInputRef.current = false;
|
|
78
|
+
});
|
|
79
|
+
}, []);
|
|
80
|
+
const onBlur = useCallback((e)=>{
|
|
81
|
+
const relatedTarget = e.relatedTarget;
|
|
82
|
+
if (relatedTarget?.closest('[role="dialog"]')) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (isMouseDownOnInputRef.current) {
|
|
86
|
+
requestAnimationFrame(()=>{
|
|
87
|
+
inputRef.current?.focus();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
setIsFocused(false);
|
|
91
|
+
onBlurProp?.(e);
|
|
92
|
+
}, [
|
|
93
|
+
onBlurProp,
|
|
94
|
+
inputRef,
|
|
95
|
+
setIsFocused
|
|
96
|
+
]);
|
|
97
|
+
const displayValue = formatSelection({
|
|
98
|
+
selection,
|
|
99
|
+
isFocused: isFocused,
|
|
100
|
+
inputValue: value
|
|
101
|
+
});
|
|
102
|
+
const shortcutValue = formatShortcut({
|
|
103
|
+
selection,
|
|
104
|
+
inputValue: value,
|
|
105
|
+
isFocused: isFocused
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
value,
|
|
109
|
+
shouldShake,
|
|
110
|
+
isFocused,
|
|
111
|
+
isInvalid,
|
|
112
|
+
displayValue,
|
|
113
|
+
shortcutValue,
|
|
114
|
+
setValue,
|
|
115
|
+
onChange,
|
|
116
|
+
onKeyDown,
|
|
117
|
+
onFocus,
|
|
118
|
+
onMouseDown,
|
|
119
|
+
onMouseUp,
|
|
120
|
+
onBlur,
|
|
121
|
+
inputRef
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=use-interval-selector-input.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IntervalSelection, IntervalSuggestion, RelativeSuggestion } from '../types';
|
|
2
|
+
interface UseIntervalSelectorNavigationProps {
|
|
3
|
+
relativeSuggestions: RelativeSuggestion[];
|
|
4
|
+
intervalSuggestions: IntervalSuggestion[];
|
|
5
|
+
highlightedIndex: number;
|
|
6
|
+
setHighlightedIndex: (index: number) => void;
|
|
7
|
+
popoverOpen: boolean;
|
|
8
|
+
calendarOpen: boolean;
|
|
9
|
+
onOpenCalendar: () => void;
|
|
10
|
+
onSelect: (selection: IntervalSelection) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useIntervalSelectorNavigation({ relativeSuggestions, intervalSuggestions, highlightedIndex, setHighlightedIndex, popoverOpen, calendarOpen, onOpenCalendar, onSelect, }: UseIntervalSelectorNavigationProps): {
|
|
13
|
+
allNavigableItems: (RelativeSuggestion | IntervalSuggestion | {
|
|
14
|
+
type: "calendar";
|
|
15
|
+
label: string;
|
|
16
|
+
})[];
|
|
17
|
+
onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
18
|
+
isNavigating: boolean;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=use-interval-selector-navigation.d.ts.map
|