@parca/profile 0.16.113 → 0.16.115

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/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.16.115](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.114...@parca/profile@0.16.115) (2023-02-13)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.114](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.113...@parca/profile@0.16.114) (2023-02-13)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.113](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.112...@parca/profile@0.16.113) (2023-02-13)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { HighlightedSeries } from '../';
3
+ interface Props {
4
+ x: number;
5
+ y: number;
6
+ highlighted: HighlightedSeries;
7
+ onLabelClick: (labelName: string, labelValue: string) => void;
8
+ contextElement: Element | null;
9
+ sampleUnit: string;
10
+ }
11
+ declare const MetricsTooltip: ({ x, y, highlighted, onLabelClick, contextElement, sampleUnit, }: Props) => JSX.Element;
12
+ export default MetricsTooltip;
@@ -0,0 +1,107 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
23
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
+ // Copyright 2022 The Parca Authors
25
+ // Licensed under the Apache License, Version 2.0 (the "License");
26
+ // you may not use this file except in compliance with the License.
27
+ // You may obtain a copy of the License at
28
+ //
29
+ // http://www.apache.org/licenses/LICENSE-2.0
30
+ //
31
+ // Unless required by applicable law or agreed to in writing, software
32
+ // distributed under the License is distributed on an "AS IS" BASIS,
33
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+ // See the License for the specific language governing permissions and
35
+ // limitations under the License.
36
+ import { useEffect, useState } from 'react';
37
+ import { usePopper } from 'react-popper';
38
+ import { TextWithTooltip } from '@parca/components';
39
+ import { valueFormatter, formatDate } from '@parca/functions';
40
+ import { timeFormat } from '../../';
41
+ var virtualElement = {
42
+ getBoundingClientRect: function () {
43
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
44
+ return {
45
+ width: 0,
46
+ height: 0,
47
+ top: 0,
48
+ left: 0,
49
+ right: 0,
50
+ bottom: 0,
51
+ };
52
+ },
53
+ };
54
+ function generateGetBoundingClientRect(contextElement, x, y) {
55
+ if (x === void 0) { x = 0; }
56
+ if (y === void 0) { y = 0; }
57
+ var domRect = contextElement.getBoundingClientRect();
58
+ return function () {
59
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
60
+ return ({
61
+ width: 0,
62
+ height: 0,
63
+ top: domRect.y + y,
64
+ left: domRect.x + x,
65
+ right: domRect.x + x,
66
+ bottom: domRect.y + y,
67
+ });
68
+ };
69
+ }
70
+ var MetricsTooltip = function (_a) {
71
+ var x = _a.x, y = _a.y, highlighted = _a.highlighted, onLabelClick = _a.onLabelClick, contextElement = _a.contextElement, sampleUnit = _a.sampleUnit;
72
+ var _b = useState(null), popperElement = _b[0], setPopperElement = _b[1];
73
+ var _c = usePopper(virtualElement, popperElement, {
74
+ placement: 'auto-start',
75
+ strategy: 'absolute',
76
+ modifiers: [
77
+ {
78
+ name: 'preventOverflow',
79
+ options: {
80
+ tether: false,
81
+ altAxis: true,
82
+ },
83
+ },
84
+ {
85
+ name: 'offset',
86
+ options: {
87
+ offset: [30, 30],
88
+ },
89
+ },
90
+ ],
91
+ }), styles = _c.styles, attributes = _c.attributes, popperProps = __rest(_c, ["styles", "attributes"]);
92
+ var update = popperProps.update;
93
+ useEffect(function () {
94
+ if (contextElement != null) {
95
+ virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, x, y);
96
+ void (update === null || update === void 0 ? void 0 : update());
97
+ }
98
+ }, [x, y, contextElement, update]);
99
+ var nameLabel = highlighted === null || highlighted === void 0 ? void 0 : highlighted.labels.find(function (e) { return e.name === '__name__'; });
100
+ var highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
101
+ return (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { className: "z-10" }, { children: _jsx("div", __assign({ className: "flex max-w-md" }, { children: _jsx("div", __assign({ className: "m-auto" }, { children: _jsx("div", __assign({ className: "border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90", style: { borderWidth: 1 } }, { children: _jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "ml-2 mr-6" }, { children: [_jsx("span", __assign({ className: "font-semibold" }, { children: highlightedNameLabel.value })), _jsx("span", __assign({ className: "block text-gray-700 dark:text-gray-300 my-2" }, { children: _jsx("table", __assign({ className: "table-auto" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Value" })), _jsx("td", __assign({ className: "w-3/4" }, { children: valueFormatter(highlighted.value, sampleUnit, 1) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "At" })), _jsx("td", __assign({ className: "w-3/4" }, { children: formatDate(highlighted.timestamp, timeFormat) }))] })] }) })) })), _jsx("span", __assign({ className: "block text-gray-500 my-2" }, { children: highlighted.labels
102
+ .filter(function (label) { return label.name !== '__name__'; })
103
+ .map(function (label) {
104
+ return (_jsx("button", __assign({ type: "button", className: "inline-block rounded-lg text-gray-700 bg-gray-200 dark:bg-gray-700 dark:text-gray-400 px-2 py-1 text-xs font-bold mr-3", onClick: function () { return onLabelClick(label.name, label.value); } }, { children: _jsx(TextWithTooltip, { text: "".concat(label.name, "=\"").concat(label.value, "\""), maxTextLength: 37, id: "tooltip-".concat(label.name, "-").concat(label.value) }) }), label.name));
105
+ }) })), _jsx("span", __assign({ className: "block text-gray-500 text-xs" }, { children: "Hold shift and click label to add to query." }))] })) })) })) })) })) })));
106
+ };
107
+ export default MetricsTooltip;
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
- import { SingleProfileSelection } from '..';
3
- import { MetricsSeries as MetricsSeriesPb, Label } from '@parca/client';
4
2
  import { DateTimeRange } from '@parca/components';
5
- interface RawMetricsGraphProps {
3
+ import { MetricsSeries as MetricsSeriesPb, Label } from '@parca/client';
4
+ import { SingleProfileSelection } from '..';
5
+ interface Props {
6
6
  data: MetricsSeriesPb[];
7
7
  from: number;
8
8
  to: number;
@@ -13,7 +13,7 @@ interface RawMetricsGraphProps {
13
13
  sampleUnit: string;
14
14
  width?: number;
15
15
  }
16
- interface HighlightedSeries {
16
+ export interface HighlightedSeries {
17
17
  seriesIndex: number;
18
18
  labels: Label[];
19
19
  timestamp: number;
@@ -21,16 +21,7 @@ interface HighlightedSeries {
21
21
  x: number;
22
22
  y: number;
23
23
  }
24
- declare const MetricsGraph: ({ data, from, to, profile, onSampleClick, onLabelClick, setTimeRange, sampleUnit, }: RawMetricsGraphProps) => JSX.Element;
24
+ declare const MetricsGraph: ({ data, from, to, profile, onSampleClick, onLabelClick, setTimeRange, sampleUnit, }: Props) => JSX.Element;
25
25
  export default MetricsGraph;
26
26
  export declare const parseValue: (value: string) => number | null;
27
- interface MetricsTooltipProps {
28
- x: number;
29
- y: number;
30
- highlighted: HighlightedSeries;
31
- onLabelClick: (labelName: string, labelValue: string) => void;
32
- contextElement: Element | null;
33
- sampleUnit: string;
34
- }
35
- export declare const MetricsTooltip: ({ x, y, highlighted, onLabelClick, contextElement, sampleUnit, }: MetricsTooltipProps) => JSX.Element;
36
- export declare const RawMetricsGraph: ({ data, from, to, profile, onSampleClick, onLabelClick, setTimeRange, width, sampleUnit, }: RawMetricsGraphProps) => JSX.Element;
27
+ export declare const RawMetricsGraph: ({ data, from, to, profile, onSampleClick, onLabelClick, setTimeRange, width, sampleUnit, }: Props) => JSX.Element;
@@ -9,17 +9,6 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- var __rest = (this && this.__rest) || function (s, e) {
13
- var t = {};
14
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
- t[p] = s[p];
16
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
- t[p[i]] = s[p[i]];
20
- }
21
- return t;
22
- };
23
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
24
13
  // Copyright 2022 The Parca Authors
25
14
  // Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,19 +22,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
33
22
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
23
  // See the License for the specific language governing permissions and
35
24
  // limitations under the License.
36
- import { useEffect, useRef, useState } from 'react';
25
+ import { useRef, useState } from 'react';
37
26
  import * as d3 from 'd3';
38
27
  import { pointer } from 'd3-selection';
39
- import { formatForTimespan } from '@parca/functions/time';
40
- import { timeFormat } from '..';
41
- import { cutToMaxStringLength } from '@parca/functions/string';
42
28
  import throttle from 'lodash.throttle';
43
- import { usePopper } from 'react-popper';
44
- import { valueFormatter, formatDate, sanitizeHighlightedValues } from '@parca/functions';
45
29
  import { DateTimeRange, useKeyDown } from '@parca/components';
46
30
  import { useContainerDimensions } from '@parca/dynamicsize';
31
+ import { formatForTimespan } from '@parca/functions/time';
32
+ import { valueFormatter, formatDate, sanitizeHighlightedValues } from '@parca/functions';
47
33
  import MetricsSeries from '../MetricsSeries';
48
34
  import MetricsCircle from '../MetricsCircle';
35
+ import MetricsTooltip from './MetricsTooltip';
49
36
  var MetricsGraph = function (_a) {
50
37
  var data = _a.data, from = _a.from, to = _a.to, profile = _a.profile, onSampleClick = _a.onSampleClick, onLabelClick = _a.onLabelClick, setTimeRange = _a.setTimeRange, sampleUnit = _a.sampleUnit;
51
38
  var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
@@ -60,72 +47,6 @@ export var parseValue = function (value) {
60
47
  };
61
48
  var lineStroke = '1px';
62
49
  var lineStrokeHover = '2px';
63
- function generateGetBoundingClientRect(contextElement, x, y) {
64
- if (x === void 0) { x = 0; }
65
- if (y === void 0) { y = 0; }
66
- var domRect = contextElement.getBoundingClientRect();
67
- return function () {
68
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
69
- return ({
70
- width: 0,
71
- height: 0,
72
- top: domRect.y + y,
73
- left: domRect.x + x,
74
- right: domRect.x + x,
75
- bottom: domRect.y + y,
76
- });
77
- };
78
- }
79
- var virtualElement = {
80
- getBoundingClientRect: function () {
81
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
82
- return {
83
- width: 0,
84
- height: 0,
85
- top: 0,
86
- left: 0,
87
- right: 0,
88
- bottom: 0,
89
- };
90
- },
91
- };
92
- export var MetricsTooltip = function (_a) {
93
- var x = _a.x, y = _a.y, highlighted = _a.highlighted, onLabelClick = _a.onLabelClick, contextElement = _a.contextElement, sampleUnit = _a.sampleUnit;
94
- var _b = useState(null), popperElement = _b[0], setPopperElement = _b[1];
95
- var _c = usePopper(virtualElement, popperElement, {
96
- placement: 'auto-start',
97
- strategy: 'absolute',
98
- modifiers: [
99
- {
100
- name: 'preventOverflow',
101
- options: {
102
- tether: false,
103
- altAxis: true,
104
- },
105
- },
106
- {
107
- name: 'offset',
108
- options: {
109
- offset: [30, 30],
110
- },
111
- },
112
- ],
113
- }), styles = _c.styles, attributes = _c.attributes, popperProps = __rest(_c, ["styles", "attributes"]);
114
- var update = popperProps.update;
115
- useEffect(function () {
116
- if (contextElement != null) {
117
- virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, x, y);
118
- void (update === null || update === void 0 ? void 0 : update());
119
- }
120
- }, [x, y, contextElement, update]);
121
- var nameLabel = highlighted === null || highlighted === void 0 ? void 0 : highlighted.labels.find(function (e) { return e.name === '__name__'; });
122
- var highlightedNameLabel = nameLabel !== undefined ? nameLabel : { name: '', value: '' };
123
- return (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { className: "z-10" }, { children: _jsx("div", __assign({ className: "flex max-w-md" }, { children: _jsx("div", __assign({ className: "m-auto" }, { children: _jsx("div", __assign({ className: "border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90", style: { borderWidth: 1 } }, { children: _jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "ml-2 mr-6" }, { children: [_jsx("span", __assign({ className: "font-semibold" }, { children: highlightedNameLabel.value })), _jsx("span", __assign({ className: "block text-gray-700 dark:text-gray-300 my-2" }, { children: _jsx("table", __assign({ className: "table-auto" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Value" })), _jsx("td", __assign({ className: "w-3/4" }, { children: valueFormatter(highlighted.value, sampleUnit, 1) }))] }), _jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "At" })), _jsx("td", __assign({ className: "w-3/4" }, { children: formatDate(highlighted.timestamp, timeFormat) }))] })] }) })) })), _jsx("span", __assign({ className: "block text-gray-500 my-2" }, { children: highlighted.labels
124
- .filter(function (label) { return label.name !== '__name__'; })
125
- .map(function (label) {
126
- return (_jsx("button", __assign({ type: "button", className: "inline-block rounded-lg text-gray-700 bg-gray-200 dark:bg-gray-700 dark:text-gray-400 px-2 py-1 text-xs font-bold mr-3", onClick: function () { return onLabelClick(label.name, label.value); } }, { children: cutToMaxStringLength("".concat(label.name, "=\"").concat(label.value, "\""), 37) }), label.name));
127
- }) })), _jsx("span", __assign({ className: "block text-gray-500 text-xs" }, { children: "Hold shift and click label to add to query." }))] })) })) })) })) })) })));
128
- };
129
50
  export var RawMetricsGraph = function (_a) {
130
51
  var data = _a.data, from = _a.from, to = _a.to, profile = _a.profile, onSampleClick = _a.onSampleClick, onLabelClick = _a.onLabelClick, setTimeRange = _a.setTimeRange, width = _a.width, sampleUnit = _a.sampleUnit;
131
52
  var graph = useRef(null);
@@ -62,7 +62,7 @@ var swapQueryParameters = function (o) {
62
62
  var ProfileExplorerApp = function (_a) {
63
63
  var _b, _c;
64
64
  var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
65
- var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data, error = _d.error;
65
+ var _d = useProfileTypes(queryClient), profileTypesLoading = _d.loading, profileTypesData = _d.data;
66
66
  var _e = useParcaContext(), loader = _e.loader, noDataPrompt = _e.noDataPrompt;
67
67
  /* eslint-disable @typescript-eslint/naming-convention */
68
68
  var from_a = queryParams.from_a, to_a = queryParams.to_a, merge_a = queryParams.merge_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, time_a = queryParams.time_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, merge_b = queryParams.merge_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, time_b = queryParams.time_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-\[-45px\]{top:-45px}.top-\[-48px\]{top:-48px}.top-\[-69px\]{top:-69px}.top-\[-54px\]{top:-54px}.top-\[-70px\]{top:-70px}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mr-3{margin-right:.75rem}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-36{height:9rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-auto{width:auto}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-full{width:100%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
1
+ /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.relative{position:relative}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-\[-45px\]{top:-45px}.top-\[-48px\]{top:-48px}.top-\[-69px\]{top:-69px}.top-\[-54px\]{top:-54px}.top-\[-70px\]{top:-70px}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.mr-3{margin-right:.75rem}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-36{height:9rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-auto{width:auto}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-full{width:100%}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-4{width:1rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.113",
3
+ "version": "0.16.115",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.62",
7
- "@parca/components": "^0.16.95",
7
+ "@parca/components": "^0.16.96",
8
8
  "@parca/dynamicsize": "^0.16.52",
9
9
  "@parca/functions": "^0.16.60",
10
10
  "@parca/parser": "^0.16.53",
@@ -19,7 +19,7 @@
19
19
  "react-copy-to-clipboard": "^5.1.0",
20
20
  "react-cytoscapejs": "1.2.1",
21
21
  "react-flame-graph": "^1.4.0",
22
- "react-konva": "18.2.3",
22
+ "react-konva": "18.2.4",
23
23
  "react-query": "^3.39.2",
24
24
  "react-textarea-autosize": "^8.4.0"
25
25
  },
@@ -45,5 +45,5 @@
45
45
  "access": "public",
46
46
  "registry": "https://registry.npmjs.org/"
47
47
  },
48
- "gitHead": "425c828b992528c8588ad6992fcda1d9f160f170"
48
+ "gitHead": "2685ef240a6d970d3db3ab3e626d25e5068db415"
49
49
  }
@@ -0,0 +1,163 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+
14
+ import {useEffect, useState} from 'react';
15
+ import {usePopper} from 'react-popper';
16
+ import type {VirtualElement} from '@popperjs/core';
17
+
18
+ import {Label} from '@parca/client';
19
+ import {TextWithTooltip} from '@parca/components';
20
+ import {valueFormatter, formatDate} from '@parca/functions';
21
+
22
+ import {timeFormat} from '../../';
23
+ import {HighlightedSeries} from '../';
24
+
25
+ interface Props {
26
+ x: number;
27
+ y: number;
28
+ highlighted: HighlightedSeries;
29
+ onLabelClick: (labelName: string, labelValue: string) => void;
30
+ contextElement: Element | null;
31
+ sampleUnit: string;
32
+ }
33
+
34
+ const virtualElement: VirtualElement = {
35
+ getBoundingClientRect: () => {
36
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37
+ return {
38
+ width: 0,
39
+ height: 0,
40
+ top: 0,
41
+ left: 0,
42
+ right: 0,
43
+ bottom: 0,
44
+ } as DOMRect;
45
+ },
46
+ };
47
+
48
+ function generateGetBoundingClientRect(contextElement: Element, x = 0, y = 0): () => DOMRect {
49
+ const domRect = contextElement.getBoundingClientRect();
50
+ return () =>
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
+ ({
53
+ width: 0,
54
+ height: 0,
55
+ top: domRect.y + y,
56
+ left: domRect.x + x,
57
+ right: domRect.x + x,
58
+ bottom: domRect.y + y,
59
+ } as DOMRect);
60
+ }
61
+
62
+ const MetricsTooltip = ({
63
+ x,
64
+ y,
65
+ highlighted,
66
+ onLabelClick,
67
+ contextElement,
68
+ sampleUnit,
69
+ }: Props): JSX.Element => {
70
+ const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
71
+
72
+ const {styles, attributes, ...popperProps} = usePopper(virtualElement, popperElement, {
73
+ placement: 'auto-start',
74
+ strategy: 'absolute',
75
+ modifiers: [
76
+ {
77
+ name: 'preventOverflow',
78
+ options: {
79
+ tether: false,
80
+ altAxis: true,
81
+ },
82
+ },
83
+ {
84
+ name: 'offset',
85
+ options: {
86
+ offset: [30, 30],
87
+ },
88
+ },
89
+ ],
90
+ });
91
+
92
+ const update = popperProps.update;
93
+
94
+ useEffect(() => {
95
+ if (contextElement != null) {
96
+ virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, x, y);
97
+ void update?.();
98
+ }
99
+ }, [x, y, contextElement, update]);
100
+
101
+ const nameLabel: Label | undefined = highlighted?.labels.find(e => e.name === '__name__');
102
+ const highlightedNameLabel: Label = nameLabel !== undefined ? nameLabel : {name: '', value: ''};
103
+
104
+ return (
105
+ <div ref={setPopperElement} style={styles.popper} {...attributes.popper} className="z-10">
106
+ <div className="flex max-w-md">
107
+ <div className="m-auto">
108
+ <div
109
+ className="border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90"
110
+ style={{borderWidth: 1}}
111
+ >
112
+ <div className="flex flex-row">
113
+ <div className="ml-2 mr-6">
114
+ <span className="font-semibold">{highlightedNameLabel.value}</span>
115
+ <span className="block text-gray-700 dark:text-gray-300 my-2">
116
+ <table className="table-auto">
117
+ <tbody>
118
+ <tr>
119
+ <td className="w-1/4">Value</td>
120
+ <td className="w-3/4">
121
+ {valueFormatter(highlighted.value, sampleUnit, 1)}
122
+ </td>
123
+ </tr>
124
+ <tr>
125
+ <td className="w-1/4">At</td>
126
+ <td className="w-3/4">{formatDate(highlighted.timestamp, timeFormat)}</td>
127
+ </tr>
128
+ </tbody>
129
+ </table>
130
+ </span>
131
+ <span className="block text-gray-500 my-2">
132
+ {highlighted.labels
133
+ .filter((label: Label) => label.name !== '__name__')
134
+ .map(function (label: Label) {
135
+ return (
136
+ <button
137
+ key={label.name}
138
+ type="button"
139
+ className="inline-block rounded-lg text-gray-700 bg-gray-200 dark:bg-gray-700 dark:text-gray-400 px-2 py-1 text-xs font-bold mr-3"
140
+ onClick={() => onLabelClick(label.name, label.value)}
141
+ >
142
+ <TextWithTooltip
143
+ text={`${label.name}="${label.value}"`}
144
+ maxTextLength={37}
145
+ id={`tooltip-${label.name}-${label.value}`}
146
+ />
147
+ </button>
148
+ );
149
+ })}
150
+ </span>
151
+ <span className="block text-gray-500 text-xs">
152
+ Hold shift and click label to add to query.
153
+ </span>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ );
161
+ };
162
+
163
+ export default MetricsTooltip;
@@ -11,24 +11,23 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {useEffect, useRef, useState} from 'react';
14
+ import React, {useRef, useState} from 'react';
15
15
  import * as d3 from 'd3';
16
16
  import {pointer} from 'd3-selection';
17
- import {formatForTimespan} from '@parca/functions/time';
18
- import {SingleProfileSelection, timeFormat} from '..';
19
- import {cutToMaxStringLength} from '@parca/functions/string';
20
17
  import throttle from 'lodash.throttle';
21
- import {MetricsSeries as MetricsSeriesPb, MetricsSample, Label} from '@parca/client';
22
- import {usePopper} from 'react-popper';
23
- import type {VirtualElement} from '@popperjs/core';
24
- import {valueFormatter, formatDate, sanitizeHighlightedValues} from '@parca/functions';
18
+
25
19
  import {DateTimeRange, useKeyDown} from '@parca/components';
26
20
  import {useContainerDimensions} from '@parca/dynamicsize';
21
+ import {formatForTimespan} from '@parca/functions/time';
22
+ import {MetricsSeries as MetricsSeriesPb, MetricsSample, Label} from '@parca/client';
23
+ import {valueFormatter, formatDate, sanitizeHighlightedValues} from '@parca/functions';
27
24
 
28
25
  import MetricsSeries from '../MetricsSeries';
29
26
  import MetricsCircle from '../MetricsCircle';
27
+ import MetricsTooltip from './MetricsTooltip';
28
+ import {SingleProfileSelection} from '..';
30
29
 
31
- interface RawMetricsGraphProps {
30
+ interface Props {
32
31
  data: MetricsSeriesPb[];
33
32
  from: number;
34
33
  to: number;
@@ -40,7 +39,7 @@ interface RawMetricsGraphProps {
40
39
  width?: number;
41
40
  }
42
41
 
43
- interface HighlightedSeries {
42
+ export interface HighlightedSeries {
44
43
  seriesIndex: number;
45
44
  labels: Label[];
46
45
  timestamp: number;
@@ -63,7 +62,7 @@ const MetricsGraph = ({
63
62
  onLabelClick,
64
63
  setTimeRange,
65
64
  sampleUnit,
66
- }: RawMetricsGraphProps): JSX.Element => {
65
+ }: Props): JSX.Element => {
67
66
  const {ref, dimensions} = useContainerDimensions();
68
67
 
69
68
  return (
@@ -95,140 +94,6 @@ export const parseValue = (value: string): number | null => {
95
94
  const lineStroke = '1px';
96
95
  const lineStrokeHover = '2px';
97
96
 
98
- interface MetricsTooltipProps {
99
- x: number;
100
- y: number;
101
- highlighted: HighlightedSeries;
102
- onLabelClick: (labelName: string, labelValue: string) => void;
103
- contextElement: Element | null;
104
- sampleUnit: string;
105
- }
106
-
107
- function generateGetBoundingClientRect(contextElement: Element, x = 0, y = 0): () => DOMRect {
108
- const domRect = contextElement.getBoundingClientRect();
109
- return () =>
110
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
111
- ({
112
- width: 0,
113
- height: 0,
114
- top: domRect.y + y,
115
- left: domRect.x + x,
116
- right: domRect.x + x,
117
- bottom: domRect.y + y,
118
- } as DOMRect);
119
- }
120
-
121
- const virtualElement: VirtualElement = {
122
- getBoundingClientRect: () => {
123
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
124
- return {
125
- width: 0,
126
- height: 0,
127
- top: 0,
128
- left: 0,
129
- right: 0,
130
- bottom: 0,
131
- } as DOMRect;
132
- },
133
- };
134
-
135
- export const MetricsTooltip = ({
136
- x,
137
- y,
138
- highlighted,
139
- onLabelClick,
140
- contextElement,
141
- sampleUnit,
142
- }: MetricsTooltipProps): JSX.Element => {
143
- const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
144
-
145
- const {styles, attributes, ...popperProps} = usePopper(virtualElement, popperElement, {
146
- placement: 'auto-start',
147
- strategy: 'absolute',
148
- modifiers: [
149
- {
150
- name: 'preventOverflow',
151
- options: {
152
- tether: false,
153
- altAxis: true,
154
- },
155
- },
156
- {
157
- name: 'offset',
158
- options: {
159
- offset: [30, 30],
160
- },
161
- },
162
- ],
163
- });
164
-
165
- const update = popperProps.update;
166
-
167
- useEffect(() => {
168
- if (contextElement != null) {
169
- virtualElement.getBoundingClientRect = generateGetBoundingClientRect(contextElement, x, y);
170
- void update?.();
171
- }
172
- }, [x, y, contextElement, update]);
173
-
174
- const nameLabel: Label | undefined = highlighted?.labels.find(e => e.name === '__name__');
175
- const highlightedNameLabel: Label = nameLabel !== undefined ? nameLabel : {name: '', value: ''};
176
-
177
- return (
178
- <div ref={setPopperElement} style={styles.popper} {...attributes.popper} className="z-10">
179
- <div className="flex max-w-md">
180
- <div className="m-auto">
181
- <div
182
- className="border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg opacity-90"
183
- style={{borderWidth: 1}}
184
- >
185
- <div className="flex flex-row">
186
- <div className="ml-2 mr-6">
187
- <span className="font-semibold">{highlightedNameLabel.value}</span>
188
- <span className="block text-gray-700 dark:text-gray-300 my-2">
189
- <table className="table-auto">
190
- <tbody>
191
- <tr>
192
- <td className="w-1/4">Value</td>
193
- <td className="w-3/4">
194
- {valueFormatter(highlighted.value, sampleUnit, 1)}
195
- </td>
196
- </tr>
197
- <tr>
198
- <td className="w-1/4">At</td>
199
- <td className="w-3/4">{formatDate(highlighted.timestamp, timeFormat)}</td>
200
- </tr>
201
- </tbody>
202
- </table>
203
- </span>
204
- <span className="block text-gray-500 my-2">
205
- {highlighted.labels
206
- .filter((label: Label) => label.name !== '__name__')
207
- .map(function (label: Label) {
208
- return (
209
- <button
210
- key={label.name}
211
- type="button"
212
- className="inline-block rounded-lg text-gray-700 bg-gray-200 dark:bg-gray-700 dark:text-gray-400 px-2 py-1 text-xs font-bold mr-3"
213
- onClick={() => onLabelClick(label.name, label.value)}
214
- >
215
- {cutToMaxStringLength(`${label.name}="${label.value}"`, 37)}
216
- </button>
217
- );
218
- })}
219
- </span>
220
- <span className="block text-gray-500 text-xs">
221
- Hold shift and click label to add to query.
222
- </span>
223
- </div>
224
- </div>
225
- </div>
226
- </div>
227
- </div>
228
- </div>
229
- );
230
- };
231
-
232
97
  export const RawMetricsGraph = ({
233
98
  data,
234
99
  from,
@@ -239,7 +104,7 @@ export const RawMetricsGraph = ({
239
104
  setTimeRange,
240
105
  width,
241
106
  sampleUnit,
242
- }: RawMetricsGraphProps): JSX.Element => {
107
+ }: Props): JSX.Element => {
243
108
  const graph = useRef(null);
244
109
  const [dragging, setDragging] = useState(false);
245
110
  const [hovering, setHovering] = useState(false);
@@ -71,11 +71,7 @@ const ProfileExplorerApp = ({
71
71
  queryParams,
72
72
  navigateTo,
73
73
  }: ProfileExplorerProps): JSX.Element => {
74
- const {
75
- loading: profileTypesLoading,
76
- data: profileTypesData,
77
- error,
78
- } = useProfileTypes(queryClient);
74
+ const {loading: profileTypesLoading, data: profileTypesData} = useProfileTypes(queryClient);
79
75
 
80
76
  const {loader, noDataPrompt} = useParcaContext();
81
77