@devtron-labs/devtron-fe-common-lib 1.20.7 → 1.21.0-beta-1

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.
Files changed (31) hide show
  1. package/dist/{@code-editor-Dmh5KrSw.js → @code-editor-Db3cFxL2.js} +7148 -6779
  2. package/dist/{@common-rjsf-BFxXGz3f.js → @common-rjsf-4dkL5TGO.js} +2 -2
  3. package/dist/{@framer-motion-DZveCoIL.js → @framer-motion-s0JmPZws.js} +1 -1
  4. package/dist/{@react-dates-CZ1bNWJM.js → @react-dates-C-SIZ4x1.js} +1 -1
  5. package/dist/{@react-select-DS68hCUM.js → @react-select-oQ7yDO_E.js} +1 -1
  6. package/dist/{@react-virtualized-sticky-tree-V-8klKy9.js → @react-virtualized-sticky-tree-jv4XRZlA.js} +1 -1
  7. package/dist/{@vendor-3ORIJA0h.js → @vendor-x0E6hada.js} +12024 -11866
  8. package/dist/Common/BreadCrumb/BreadcrumbStore.d.ts +1 -0
  9. package/dist/Common/Constants.d.ts +8 -0
  10. package/dist/Pages/ResourceBrowser/types.d.ts +2 -1
  11. package/dist/Shared/Components/DatePicker/DayPickerRangeController.d.ts +2 -0
  12. package/dist/Shared/Components/DatePicker/constants.d.ts +62 -0
  13. package/dist/Shared/Components/DatePicker/index.d.ts +1 -0
  14. package/dist/Shared/Components/DatePicker/types.d.ts +13 -0
  15. package/dist/Shared/Components/DatePicker/utils.d.ts +12 -0
  16. package/dist/Shared/Components/ExportToCsv/ExportToCsv.d.ts +3 -0
  17. package/dist/Shared/Components/ExportToCsv/ExportToCsvDialog.d.ts +3 -0
  18. package/dist/Shared/Components/ExportToCsv/index.d.ts +2 -0
  19. package/dist/Shared/Components/ExportToCsv/types.d.ts +64 -0
  20. package/dist/Shared/Components/Icon/Icon.d.ts +7 -0
  21. package/dist/Shared/Components/index.d.ts +1 -0
  22. package/dist/Shared/types.d.ts +12 -3
  23. package/dist/assets/ic-bg-cloud-vms.7241e97c.svg +4 -0
  24. package/dist/assets/ic-bg-healthy-vms.653e8abc.svg +4 -0
  25. package/dist/assets/ic-bg-running-vms.e469929a.svg +4 -0
  26. package/dist/assets/ic-bg-tenants.d0369094.svg +4 -0
  27. package/dist/assets/ic-binoculars.c6ad42f4.svg +3 -0
  28. package/dist/assets/ic-enter-fullscreen.ccb625cf.svg +3 -0
  29. package/dist/assets/ic-exit-fullscreen.75ef3789.svg +3 -0
  30. package/dist/index.js +778 -768
  31. package/package.json +3 -1
@@ -1,6 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { BreadcrumbTextProps } from './Types';
3
3
  export declare const BreadcrumbText: ({ heading, isActive, shouldTruncate }: BreadcrumbTextProps) => JSX.Element;
4
+ export declare const getBreadCrumbSeparator: (sep?: string) => JSX.Element;
4
5
  declare const Store: ({ children }: {
5
6
  children: any;
6
7
  }) => JSX.Element;
@@ -64,6 +64,13 @@ export declare const URLS: {
64
64
  readonly GLOBAL_CONFIG_TEMPLATES_DEVTRON_APP_DETAIL: "/global-config/templates/devtron-apps/detail/:appId";
65
65
  readonly LICENSE_AUTH: "/license-auth";
66
66
  readonly GLOBAL_CONFIG_EDIT_CLUSTER: "/global-config/cluster-env/edit/:clusterId";
67
+ readonly OBSERVABILITY: "/observability";
68
+ readonly OBSERVABILITY_OVERVIEW: "/observability/overview";
69
+ readonly OBSERVABILITY_TENANTS: "/observability/tenants";
70
+ readonly OBSERVABILITY_TENANT_DETAILS: "/observability/tenants/:tenantName";
71
+ readonly OBSERVABILITY_TENANT_OVERVIEW: "/observability/tenants/:tenantName/overview";
72
+ readonly OBSERVABILITY_TENANT_VMS: "/observability/tenants/:tenantName/vms";
73
+ readonly OBSERVABILITY_TENANT_VM_DETAILS: "/observability/tenants/:tenantName/vms/:vmName";
67
74
  };
68
75
  export declare const ROUTES: {
69
76
  readonly APP: "app";
@@ -327,6 +334,7 @@ export declare const DATE_TIME_FORMATS: {
327
334
  DD_MMM_YYYY_HH_MM: string;
328
335
  DD_MMM_YYYY: string;
329
336
  'DD/MM/YYYY': string;
337
+ FULL_DATE_WITH_TIME: string;
330
338
  };
331
339
  export declare const SEMANTIC_VERSION_DOCUMENTATION_LINK = "https://semver.org/";
332
340
  export declare const VULNERABILITIES_SORT_PRIORITY: {
@@ -128,6 +128,7 @@ export declare enum ResourceBrowserActionMenuEnum {
128
128
  logs = "logs",
129
129
  terminal = "terminal",
130
130
  delete = "delete",
131
- vulnerability = "vulnerability"
131
+ vulnerability = "vulnerability",
132
+ restart = "restart"
132
133
  }
133
134
  export {};
@@ -0,0 +1,2 @@
1
+ import { DatePickerRangeControllerProps } from './types';
2
+ export declare const DatePickerRangeController: ({ handlePredefinedRange, handleApply, calendar, calendarInputs, handleDateInput, handleDatesChange, calendarValue, focusedInput, handleFocusChange, }: DatePickerRangeControllerProps) => JSX.Element;
@@ -1,3 +1,24 @@
1
+ import { default as moment } from 'moment';
2
+ export declare const selectedStyles: {
3
+ background: string;
4
+ color: string;
5
+ hover: {
6
+ background: string;
7
+ color: string;
8
+ };
9
+ };
10
+ export declare const selectedSpanStyles: {
11
+ background: string;
12
+ color: string;
13
+ hover: {
14
+ background: string;
15
+ color: string;
16
+ };
17
+ };
18
+ export declare const hoveredSpanStyles: {
19
+ background: string;
20
+ color: string;
21
+ };
1
22
  export declare const customDayStyles: {
2
23
  selectedStartStyles: {
3
24
  background: string;
@@ -132,3 +153,44 @@ export declare const DATE_PICKER_IDS: {
132
153
  MONTH: string;
133
154
  TIME: string;
134
155
  };
156
+ export declare const styles: {
157
+ PresetDateRangePicker_panel: {
158
+ padding: string;
159
+ width: string;
160
+ height: string;
161
+ };
162
+ PresetDateRangePicker_button: {
163
+ width: string;
164
+ background: string;
165
+ border: string;
166
+ color: string;
167
+ padding: string;
168
+ font: string;
169
+ fontWeight: number;
170
+ lineHeight: string;
171
+ overflow: string;
172
+ cursor: string;
173
+ ':active': {
174
+ outline: number;
175
+ };
176
+ };
177
+ DayPicker__horizontal: {
178
+ borderRadius: string;
179
+ };
180
+ PresetDateRangePicker_button__selected: {
181
+ color: string;
182
+ fontWeight: number;
183
+ background: string;
184
+ outline: string;
185
+ };
186
+ };
187
+ export declare const DayPickerCalendarInfoHorizontal: {
188
+ width: string;
189
+ boxShadow: string;
190
+ };
191
+ export declare const DayPickerRangeControllerPresets: {
192
+ text: string;
193
+ endDate: moment.Moment;
194
+ startDate: moment.Moment;
195
+ endStr: string;
196
+ }[];
@@ -1,5 +1,6 @@
1
1
  export * from './constants';
2
2
  export { default as DateTimePicker } from './DateTimePicker';
3
+ export { DatePickerRangeController } from './DayPickerRangeController';
3
4
  export * from './MonthlySelect';
4
5
  export { default as SingleDatePickerComponent } from './SingleDatePickerComponent';
5
6
  export * from './TimeSelect';
@@ -119,3 +119,16 @@ export interface DateTimePickerProps extends Pick<TimeSelectProps, 'date' | 'tim
119
119
  */
120
120
  onChange: (date: Date) => void;
121
121
  }
122
+ export type CalendarFocusInputType = 'startDate' | 'endDate';
123
+ export interface DatePickerRangeControllerProps {
124
+ calendar: any;
125
+ calendarInputs: any;
126
+ focusedInput: any;
127
+ handleFocusChange: any;
128
+ handleDatesChange: any;
129
+ handleCalendarInputs?: any;
130
+ calendarValue: string;
131
+ handlePredefinedRange: (start: Moment, end: Moment, endStr: string) => void;
132
+ handleDateInput: (key: 'startDate' | 'endDate', value: string) => void;
133
+ handleApply: (...args: any[]) => void;
134
+ }
@@ -32,3 +32,15 @@ export declare const updateDate: (currentDateObj: Date, newDate: Date) => Date;
32
32
  * @returns
33
33
  */
34
34
  export declare const getDefaultDateFromTimeToLive: (timeToLive: string, isTomorrow?: boolean) => Date;
35
+ /**
36
+ * Returns a string representing the range of dates
37
+ * given by the start and end dates. If the end date
38
+ * is 'now' and the start date includes 'now',
39
+ * it will return the corresponding range from the
40
+ * DayPickerRangeControllerPresets array.
41
+ * @param startDateStr - the start date string
42
+ * @param endDateStr - the end date string
43
+ * @returns - a string representing the range of dates
44
+ */
45
+ export declare const getCalendarValue: (startDateStr: string, endDateStr: string) => string;
46
+ export declare const getTimestampFromDateIfAvailable: (dateString: string) => string;
@@ -0,0 +1,3 @@
1
+ import { ExportToCsvProps } from './types';
2
+ declare const ExportToCsv: <HeaderItemType extends string>({ apiPromise, fileName, triggerElementConfig, disabled, modalConfig, headers, downloadRequestId, }: ExportToCsvProps<HeaderItemType>) => JSX.Element;
3
+ export default ExportToCsv;
@@ -0,0 +1,3 @@
1
+ import { ExportToCsvDialogProps } from './types';
2
+ declare const ExportToCsvDialog: ({ exportDataError, isLoading, initiateDownload, handleCancelRequest, }: ExportToCsvDialogProps) => JSX.Element;
3
+ export default ExportToCsvDialog;
@@ -0,0 +1,2 @@
1
+ export { default as ExportToCsv } from './ExportToCsv';
2
+ export * from './types';
@@ -0,0 +1,64 @@
1
+ import { ServerErrors } from '../../../Common/ServerError';
2
+ import { APIOptions } from '../../../Common/Types';
3
+ import { ButtonProps } from '../Button';
4
+ type TriggerElementConfigType = {
5
+ buttonProps: ButtonProps;
6
+ showOnlyIcon?: boolean;
7
+ customButton?: never;
8
+ isExternalTrigger?: false;
9
+ } | {
10
+ customButton: {
11
+ content: JSX.Element;
12
+ className: string;
13
+ };
14
+ buttonProps?: never;
15
+ showOnlyIcon?: false;
16
+ isExternalTrigger?: false;
17
+ } | {
18
+ isExternalTrigger: true;
19
+ showOnlyIcon?: false;
20
+ buttonProps?: never;
21
+ customButton?: never;
22
+ } | {
23
+ showOnlyIcon: true;
24
+ buttonProps?: never;
25
+ customButton?: never;
26
+ isExternalTrigger?: false;
27
+ };
28
+ export interface ExportToCsvProps<HeaderItemKeyType extends string> {
29
+ headers: {
30
+ label: string;
31
+ key: HeaderItemKeyType;
32
+ }[];
33
+ apiPromise: ({ signal, }: Pick<APIOptions, 'signal'>) => Promise<Record<HeaderItemKeyType, string | number | boolean>[]>;
34
+ fileName: string;
35
+ /**
36
+ * If nothing given will render a Button with "Export CSV" text
37
+ */
38
+ triggerElementConfig?: TriggerElementConfigType;
39
+ /**
40
+ * @default false
41
+ */
42
+ disabled?: boolean;
43
+ /**
44
+ * If not given would show default dialog
45
+ */
46
+ modalConfig?: {
47
+ hideDialog: false;
48
+ renderCustomModal?: (proceedWithDownload: (shouldProceed: boolean) => void) => JSX.Element;
49
+ } | {
50
+ hideDialog: true;
51
+ renderCustomModal?: never;
52
+ };
53
+ /**
54
+ * If given, would trigger export on when this changes and has some value
55
+ */
56
+ downloadRequestId?: string | number;
57
+ }
58
+ export interface ExportToCsvDialogProps {
59
+ isLoading: boolean;
60
+ exportDataError: ServerErrors;
61
+ initiateDownload: () => void;
62
+ handleCancelRequest: () => void;
63
+ }
64
+ export {};
@@ -17,9 +17,14 @@ export declare const iconMap: {
17
17
  'ic-aws-codecommit': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
18
18
  'ic-azure-aks': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
19
19
  'ic-azure': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
20
+ 'ic-bg-cloud-vms': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
20
21
  'ic-bg-cluster': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
21
22
  'ic-bg-environment': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
23
+ 'ic-bg-healthy-vms': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
24
+ 'ic-bg-running-vms': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
25
+ 'ic-bg-tenants': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
22
26
  'ic-bharatpe': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
27
+ 'ic-binoculars': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
23
28
  'ic-bitbucket': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
24
29
  'ic-book-open': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
25
30
  'ic-brain': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
@@ -77,12 +82,14 @@ export declare const iconMap: {
77
82
  'ic-ecr': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
78
83
  'ic-edit': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
79
84
  'ic-email': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
85
+ 'ic-enter-fullscreen': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
80
86
  'ic-enterprise-feat': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
81
87
  'ic-enterprise-tag': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
82
88
  'ic-env': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
83
89
  'ic-environment-isolated': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
84
90
  'ic-environment': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
85
91
  'ic-error': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
92
+ 'ic-exit-fullscreen': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
86
93
  'ic-expand-right-sm': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
87
94
  'ic-expand-sm': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
88
95
  'ic-failure': import('react').FunctionComponent<import('react').SVGProps<SVGSVGElement>>;
@@ -36,6 +36,7 @@ export * from './EditImageFormField';
36
36
  export * from './EnvironmentSelector';
37
37
  export * from './Error';
38
38
  export * from './ExcludedImageNode';
39
+ export * from './ExportToCsv';
39
40
  export * from './FeatureDescription';
40
41
  export * from './FileUpload';
41
42
  export * from './FilterChips';
@@ -1,8 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ParsedCountry } from 'react-international-phone';
3
3
  import { Dayjs } from 'dayjs';
4
- import { APIOptions, ApprovalConfigDataType, Strategy } from '../Common/Types';
5
- import { ReleaseMode } from '../Pages/index';
4
+ import { ActionTypes, APIOptions, ApprovalConfigDataType, Strategy } from '../Common/Types';
5
+ import { ReleaseMode, UserStatus } from '../Pages/index';
6
6
  import { CommonNodeAttr, DeploymentAppTypes, OptionType, PluginType, RefVariableType, SegmentedControlProps, ServerError, ServerErrors, SortingParams, TriggerBlockType, ValueConstraintType, VariableType, VulnerabilityType } from '../Common';
7
7
  import { SelectPickerOptionType, WorkflowRunnerStatusDTO } from './Components';
8
8
  import { BASE_CONFIGURATION_ENV_ID, DEPLOYMENT_STATUS, EnvironmentTypeEnum, PatchOperationType } from './constants';
@@ -653,7 +653,8 @@ export declare enum EntityTypes {
653
653
  DOCKER = "docker",
654
654
  GIT = "git",
655
655
  CLUSTER = "cluster",
656
- NOTIFICATION = "notification"
656
+ NOTIFICATION = "notification",
657
+ OBSERVABILITY = "observe"
657
658
  }
658
659
  export interface CustomRoles {
659
660
  id: number;
@@ -1113,4 +1114,12 @@ export interface PipelineDeploymentStrategy {
1113
1114
  strategies: Strategy[];
1114
1115
  error: ServerError;
1115
1116
  }
1117
+ export interface ObservabilityPermissionFilter {
1118
+ entityName: OptionType[];
1119
+ action: ActionTypes.VIEW | ActionTypes.ADMIN;
1120
+ tenant: OptionType;
1121
+ entityNameError?: boolean;
1122
+ status: UserStatus;
1123
+ timeToLive: string;
1124
+ }
1116
1125
  export {};
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <rect width="24" height="24" fill="#FFE5DE" rx="6"/>
3
+ <path stroke="#FF7E5B" stroke-linecap="round" stroke-linejoin="round" d="M5.877 14.146A3.499 3.499 0 0 1 9.37 8.442c.63-1.109 1.408-2.186 2.717-2.728A5 5 0 0 1 18 13.333m-2.586 2H8.587m6.827 0c.324 0 .586.249.586.556v2.222c0 .307-.262.555-.586.555H8.587c-.324 0-.587-.248-.587-.555v-2.222c0-.307.263-.556.587-.556m6.827 0c.324 0 .586-.249.586-.556v-2.222c0-.307-.262-.555-.586-.555H8.587c-.324 0-.587.248-.587.555v2.223c0 .306.263.555.587.555m5.51 1.688h-.778m.778-3.333h-.778" vector-effect="non-scaling-stroke"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <rect width="24" height="24" fill="#E9FBF4" rx="6"/>
3
+ <path stroke="#1DAD70" stroke-linecap="round" stroke-linejoin="round" d="M9 12a5 5 0 1 1 5 5H8.5a3.5 3.5 0 1 1 .87-6.891m6.63.558-2.667 2.666L12 12" vector-effect="non-scaling-stroke"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <rect width="24" height="24" fill="#E5F2FF" rx="6"/>
3
+ <path stroke="#06C" stroke-linecap="round" stroke-linejoin="round" d="M9 12a5 5 0 1 1 5 5H8.5a3.5 3.5 0 1 1 .87-6.891m6.63.157v1.091l-.706-.771a1.83 1.83 0 0 0-.594-.434 1.696 1.696 0 0 0-1.4 0 1.83 1.83 0 0 0-.594.434M12 13.734v-1.091l.706.771c.17.186.372.333.594.434a1.697 1.697 0 0 0 1.4 0c.222-.1.424-.248.594-.434" vector-effect="non-scaling-stroke"/>
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <rect width="24" height="24" fill="#E5F2FF" rx="6"/>
3
+ <path stroke="#06C" stroke-linecap="round" stroke-linejoin="round" d="M5.5 18h13m-.822 0V6.522a.538.538 0 0 0-.144-.37.478.478 0 0 0-.348-.152h-5.9a.478.478 0 0 0-.347.153.538.538 0 0 0-.144.369m3.092 2.087h1.966m-.983 4.174h1.966m-3.649 2.608h1.541M9.812 13.43c1.243 0 2.25-1.024 2.25-2.286 0-1.263-1.007-2.286-2.25-2.286-1.242 0-2.25 1.023-2.25 2.286 0 1.262 1.008 2.286 2.25 2.286Zm0 0c1.864 0 3.375 1.535 3.375 3.428V18m-3.375-4.571c-1.864 0-3.375 1.535-3.375 3.428V18" vector-effect="non-scaling-stroke"/>
4
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
2
+ <path d="M9.75 8.24978H14.25M21.5241 14.4673L17.4319 5.15603C17.0099 4.7341 16.4376 4.49707 15.8409 4.49707C15.2442 4.49707 14.672 4.7341 14.25 5.15603V15.7498M14.25 15.7498C14.25 17.8208 15.9289 19.4998 18 19.4998C20.0711 19.4998 21.75 17.8208 21.75 15.7498C21.75 13.6787 20.0711 11.9998 18 11.9998C15.9289 11.9998 14.25 13.6787 14.25 15.7498ZM9.75 15.7498V5.15603C9.32805 4.7341 8.75577 4.49707 8.15906 4.49707C7.56235 4.49707 6.99008 4.7341 6.56812 5.15603L2.47594 14.4673M9.75 15.7498C9.75 17.8208 8.07107 19.4998 6 19.4998C3.92893 19.4998 2.25 17.8208 2.25 15.7498C2.25 13.6787 3.92893 11.9998 6 11.9998C8.07107 11.9998 9.75 13.6787 9.75 15.7498Z" stroke="#3B444C" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <path stroke="#3B444C" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15 4.5h4.5m0 0V9m0-4.5-5.25 5.25M9 19.5H4.5m0 0V15m0 4.5 5.25-5.25" vector-effect="non-scaling-stroke"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
2
+ <path stroke="#3B444C" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M14.25 5.25v4.5m0 0h4.5m-4.5 0L19.5 4.5M5.25 14.25h4.5m0 0v4.5m0-4.5L4.5 19.5" vector-effect="non-scaling-stroke"/>
3
+ </svg>