mirror of
https://github.com/lensapp/lens.git
synced 2024-09-11 09:25:26 +03:00
fix: Don't crash when hovering hotbar menu index
- Remove all uses of React.ReactNode as it is unsafe, replace them with usages of SafeReactNode which doesn't contain the '{}' type Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
f13a145a27
commit
9d51ef2aa6
13
package-lock.json
generated
13
package-lock.json
generated
@ -36625,6 +36625,7 @@
|
||||
"devDependencies": {
|
||||
"@async-fn/jest": "^1.6.4",
|
||||
"@k8slens/typescript": "^6.5.0-alpha.2",
|
||||
"@ogre-tools/injectable-extension-for-auto-registration": "^15.9.0",
|
||||
"@ogre-tools/test-utils": "^15.8.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
@ -36635,6 +36636,17 @@
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"packages/infrastructure/webpack/node_modules/@ogre-tools/injectable-extension-for-auto-registration": {
|
||||
"version": "15.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@ogre-tools/injectable-extension-for-auto-registration/-/injectable-extension-for-auto-registration-15.9.0.tgz",
|
||||
"integrity": "sha512-5Ik43ZLAOhBODrhF/MbTkC3SItFMNxibufBoYFqCERfHSHyZE6pUa5yMbjrh+YFkntIrDH2IScW7BqZkraHvTA==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@ogre-tools/fp": "*",
|
||||
"@ogre-tools/injectable": "*",
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"packages/infrastructure/webpack/node_modules/sass-loader": {
|
||||
"version": "13.2.2",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.2.tgz",
|
||||
@ -36869,6 +36881,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@k8slens/kube-object": "^1.0.0-alpha.1",
|
||||
"@k8slens/utilities": "^1.0.0-alpha.3",
|
||||
"@ogre-tools/injectable": "^15.8.1",
|
||||
"react": "^17.0.2"
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import invokeShortcutInjectable, { InvokeShortcut } from "./invoke-shortcut.injectable";
|
||||
|
||||
export interface KeyboardShortcutListenerProps {
|
||||
children: React.ReactNode;
|
||||
children: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import React from "react";
|
||||
|
||||
export interface KeyboardShortcutScopeProps {
|
||||
id: string;
|
||||
children: React.ReactNode;
|
||||
children: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export const KeyboardShortcutScope = ({ id, children }: KeyboardShortcutScopeProps) => (
|
||||
|
@ -7,7 +7,7 @@ import EventEmitter from "events";
|
||||
import type TypedEmitter from "typed-emitter";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { once } from "lodash";
|
||||
import type { Disposer } from "@k8slens/utilities";
|
||||
import type { Disposer, SafeReactNode } from "@k8slens/utilities";
|
||||
import { iter } from "@k8slens/utilities";
|
||||
import type { CategoryColumnRegistration, TitleCellProps } from "../../renderer/components/catalog/custom-category-columns";
|
||||
|
||||
@ -201,7 +201,7 @@ export abstract class CatalogCategory extends (EventEmitter as new () => TypedEm
|
||||
* Defaults to no badge.
|
||||
* The badge is displayed next to the Category name in the Catalog Category menu
|
||||
*/
|
||||
public getBadge(): React.ReactNode {
|
||||
public getBadge(): SafeReactNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
import "./add-remove-buttons.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Button } from "@k8slens/button";
|
||||
import { Icon } from "../icon";
|
||||
@ -13,8 +14,8 @@ import { Icon } from "../icon";
|
||||
export interface AddRemoveButtonsProps extends React.HTMLAttributes<any> {
|
||||
onAdd?: () => void;
|
||||
onRemove?: () => void;
|
||||
addTooltip?: React.ReactNode;
|
||||
removeTooltip?: React.ReactNode;
|
||||
addTooltip?: SafeReactNode;
|
||||
removeTooltip?: SafeReactNode;
|
||||
}
|
||||
|
||||
export class AddRemoveButtons extends React.PureComponent<AddRemoveButtonsProps> {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import "./animate.scss";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { RequestAnimationFrame } from "./request-animation-frame.injectable";
|
||||
@ -21,7 +22,7 @@ export interface AnimateProps {
|
||||
onLeave?: () => void;
|
||||
enterDuration?: number;
|
||||
leaveDuration?: number;
|
||||
children?: React.ReactNode;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
|
@ -8,7 +8,7 @@ import styles from "./avatar.module.scss";
|
||||
import type { ImgHTMLAttributes, MouseEventHandler } from "react";
|
||||
import React from "react";
|
||||
import randomColor from "randomcolor";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { computeDefaultShortName } from "../../../common/catalog/helpers";
|
||||
|
||||
@ -21,7 +21,7 @@ export interface AvatarProps {
|
||||
variant?: "circle" | "rounded" | "square";
|
||||
imgProps?: ImgHTMLAttributes<HTMLImageElement>;
|
||||
disabled?: boolean;
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
className?: string;
|
||||
id?: string;
|
||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||
|
@ -8,16 +8,18 @@ import styles from "./badge.module.scss";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { action, observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { withTooltip } from "@k8slens/tooltip";
|
||||
|
||||
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
small?: boolean;
|
||||
flat?: boolean;
|
||||
label?: React.ReactNode;
|
||||
label?: SafeReactNode;
|
||||
expandable?: boolean;
|
||||
disabled?: boolean;
|
||||
scrollable?: boolean;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
// Common handler for all Badge instances
|
||||
|
@ -3,9 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import type React from "react";
|
||||
import type { LensRendererExtension } from "../../../../extensions/lens-renderer-extension";
|
||||
import rendererExtensionsInjectable from "../../../../extensions/renderer-extensions.injectable";
|
||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||
@ -20,8 +20,8 @@ describe("Custom Category Views", () => {
|
||||
});
|
||||
|
||||
it("should order items correctly over all extensions", () => {
|
||||
const component1 = (): React.ReactNode => null;
|
||||
const component2 = (): React.ReactNode => null;
|
||||
const component1 = (): SafeReactNode => null;
|
||||
const component2 = (): SafeReactNode => null;
|
||||
|
||||
di.override(rendererExtensionsInjectable, () => computed(() => [
|
||||
{
|
||||
@ -58,8 +58,8 @@ describe("Custom Category Views", () => {
|
||||
});
|
||||
|
||||
it("should put put priority < 50 items in before", () => {
|
||||
const component1 = (): React.ReactNode => null;
|
||||
const component2 = (): React.ReactNode => null;
|
||||
const component1 = (): SafeReactNode => null;
|
||||
const component2 = (): SafeReactNode => null;
|
||||
|
||||
di.override(rendererExtensionsInjectable, () => computed(() => [
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { orderBy } from "lodash";
|
||||
import type { CatalogCategory, CatalogEntity } from "../../../../common/catalog";
|
||||
@ -35,7 +36,7 @@ const getCategoryColumnsInjectable = getInjectable({
|
||||
const sortingCallbacks: CategoryColumns["sortingCallbacks"] = {};
|
||||
const searchFilters: CategoryColumns["searchFilters"] = [];
|
||||
const renderTableHeader: CategoryColumns["renderTableHeader"] = [];
|
||||
const tableRowRenderers: ((entity: CatalogEntity) => React.ReactNode)[] = [];
|
||||
const tableRowRenderers: ((entity: CatalogEntity) => SafeReactNode)[] = [];
|
||||
|
||||
for (const registration of allRegistrations) {
|
||||
if (registration.sortCallback) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import type { CatalogEntity } from "../../../common/catalog";
|
||||
import type { TableCellProps } from "../table";
|
||||
|
||||
@ -32,7 +32,7 @@ export interface CategoryColumnRegistration {
|
||||
/**
|
||||
* This function will be called to generate the cells (on demand) for the column
|
||||
*/
|
||||
renderCell: (entity: CatalogEntity) => React.ReactNode;
|
||||
renderCell: (entity: CatalogEntity) => SafeReactNode;
|
||||
|
||||
/**
|
||||
* This function will be used to generate the columns title cell.
|
||||
@ -79,7 +79,7 @@ export interface AdditionalCategoryColumnRegistration extends CategoryColumnRegi
|
||||
export interface RegisteredAdditionalCategoryColumn {
|
||||
id: string;
|
||||
priority: number;
|
||||
renderCell: (entity: CatalogEntity) => React.ReactNode;
|
||||
renderCell: (entity: CatalogEntity) => SafeReactNode;
|
||||
titleProps: TableCellProps;
|
||||
sortCallback?: (entity: CatalogEntity) => string | number | (string | number)[];
|
||||
searchFilter?: (entity: CatalogEntity) => string | string[];
|
||||
|
@ -2,7 +2,6 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { ReactNode } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { MenuItem } from "../menu";
|
||||
@ -12,6 +11,7 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { Hotbar } from "../../../features/hotbar/storage/common/hotbar";
|
||||
import activeHotbarInjectable from "../../../features/hotbar/storage/common/active.injectable";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
interface Dependencies {
|
||||
activeHotbar: IComputedValue<Hotbar | undefined>;
|
||||
@ -19,8 +19,8 @@ interface Dependencies {
|
||||
|
||||
interface HotbarToggleMenuItemProps {
|
||||
entity: CatalogEntity;
|
||||
addContent: ReactNode;
|
||||
removeContent: ReactNode;
|
||||
addContent: SafeReactNode;
|
||||
removeContent: SafeReactNode;
|
||||
}
|
||||
|
||||
function NonInjectedHotbarToggleMenuItem({
|
||||
|
@ -5,17 +5,17 @@
|
||||
|
||||
import "./checkbox.scss";
|
||||
import React from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
|
||||
export interface CheckboxProps {
|
||||
className?: string;
|
||||
label?: React.ReactNode;
|
||||
label?: SafeReactNode;
|
||||
inline?: boolean;
|
||||
disabled?: boolean;
|
||||
value?: boolean;
|
||||
onChange?(value: boolean, evt: React.ChangeEvent<HTMLInputElement>): void;
|
||||
children?: SingleOrMany<React.ReactChild | React.ReactFragment>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export function Checkbox({ label, inline, className, value, children, onChange = noop, disabled, ...inputProps }: CheckboxProps) {
|
||||
|
@ -22,6 +22,7 @@ import type { RequestClusterActivation } from "../../../features/cluster/activat
|
||||
import requestClusterActivationInjectable from "../../../features/cluster/activation/renderer/request-activation.injectable";
|
||||
import type { GetClusterById } from "../../../features/cluster/storage/common/get-by-id.injectable";
|
||||
import getClusterByIdInjectable from "../../../features/cluster/storage/common/get-by-id.injectable";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
interface Dependencies {
|
||||
clusterId: IComputedValue<string>;
|
||||
@ -93,7 +94,7 @@ class NonInjectedClusterView extends React.Component<Dependencies> {
|
||||
]);
|
||||
}
|
||||
|
||||
renderStatus(): React.ReactNode {
|
||||
renderStatus(): SafeReactNode {
|
||||
const { cluster, isReady } = this;
|
||||
|
||||
if (cluster && !isReady) {
|
||||
|
@ -14,9 +14,10 @@ import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-create
|
||||
import type { DiRender } from "../test-utils/renderFor";
|
||||
import { renderFor } from "../test-utils/renderFor";
|
||||
import { HorizontalPodAutoscalerDetails } from "./details";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
jest.mock("react-router-dom", () => ({
|
||||
Link: ({ children }: { children: React.ReactNode }) => children,
|
||||
Link: ({ children }: { children: SafeReactNode }) => children,
|
||||
}));
|
||||
|
||||
const hpaV2 = {
|
||||
|
@ -5,11 +5,11 @@
|
||||
|
||||
import "./confirm-dialog.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { observable, makeObservable, computed } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, noop, prevDefault } from "@k8slens/utilities";
|
||||
import type { ButtonProps } from "@k8slens/button";
|
||||
import { Button } from "@k8slens/button";
|
||||
@ -30,10 +30,10 @@ export interface ConfirmDialogParams extends ConfirmDialogBooleanParams {
|
||||
}
|
||||
|
||||
export interface ConfirmDialogBooleanParams {
|
||||
labelOk?: ReactNode;
|
||||
labelCancel?: ReactNode;
|
||||
message: ReactNode;
|
||||
icon?: ReactNode;
|
||||
labelOk?: SafeReactNode;
|
||||
labelCancel?: SafeReactNode;
|
||||
message: SafeReactNode;
|
||||
icon?: SafeReactNode;
|
||||
okButtonProps?: Partial<ButtonProps>;
|
||||
cancelButtonProps?: Partial<ButtonProps>;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import "./crd-resource-details.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, safeJSONPathValue } from "@k8slens/utilities";
|
||||
import { Badge } from "../badge";
|
||||
import { DrawerItem } from "../drawer";
|
||||
@ -22,7 +23,7 @@ export interface CustomResourceDetailsProps extends KubeObjectDetailsProps<KubeO
|
||||
crd?: CustomResourceDefinition;
|
||||
}
|
||||
|
||||
function convertSpecValue(value: unknown): React.ReactNode {
|
||||
function convertSpecValue(value: unknown): SafeReactNode {
|
||||
if (Array.isArray(value)) {
|
||||
return (
|
||||
<ul>
|
||||
|
@ -106,7 +106,11 @@ class NonInjectedCustomResources extends React.Component<Dependencies> {
|
||||
isNamespaced && (
|
||||
<NamespaceSelectBadge namespace={customResource.getNs() as string} />
|
||||
),
|
||||
...extraColumns.map((column) => safeJSONPathValue(customResource, column.jsonPath)),
|
||||
...(
|
||||
extraColumns
|
||||
.map((column) => safeJSONPathValue(customResource, column.jsonPath))
|
||||
.map(formatJSONValue)
|
||||
),
|
||||
<KubeObjectAge key="age" object={customResource} />,
|
||||
]}
|
||||
failedToLoadMessage={(
|
||||
|
@ -10,6 +10,7 @@ import { createPortal } from "react-dom";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { reaction } from "mobx";
|
||||
import { Animate } from "../animate";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop, stopPropagation } from "@k8slens/utilities";
|
||||
import type { ObservableHistory } from "mobx-observable-history";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@ -29,7 +30,7 @@ export interface DialogProps {
|
||||
pinned?: boolean;
|
||||
animated?: boolean;
|
||||
"data-testid"?: string;
|
||||
children?: React.ReactNode | React.ReactNode[];
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface DialogState {
|
||||
|
@ -7,6 +7,7 @@ import styles from "./dock-tab.module.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, prevDefault, isMiddleClick } from "@k8slens/utilities";
|
||||
import type { DockStore, DockTab as DockTabModel } from "./dock/store";
|
||||
import type { TabProps } from "../tabs";
|
||||
@ -21,7 +22,7 @@ import isMacInjectable from "../../../common/vars/is-mac.injectable";
|
||||
import autoBindReact from "auto-bind/react";
|
||||
|
||||
export interface DockTabProps extends TabProps<DockTabModel> {
|
||||
moreActions?: React.ReactNode;
|
||||
moreActions?: SafeReactNode;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
import "./info-panel.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React, { Component } from "react";
|
||||
import { computed, observable, reaction, makeObservable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Button } from "@k8slens/button";
|
||||
import { Icon } from "../icon";
|
||||
@ -29,9 +29,9 @@ export interface InfoPanelProps extends OptionalProps {
|
||||
export interface OptionalProps {
|
||||
className?: string;
|
||||
error?: string;
|
||||
controls?: ReactNode;
|
||||
submitLabel?: ReactNode;
|
||||
submittingMessage?: ReactNode;
|
||||
controls?: SafeReactNode;
|
||||
submitLabel?: SafeReactNode;
|
||||
submittingMessage?: SafeReactNode;
|
||||
disableSubmit?: boolean;
|
||||
showButtons?: boolean;
|
||||
showSubmitClose?: boolean;
|
||||
|
@ -5,10 +5,11 @@
|
||||
|
||||
import "./drawer-item.scss";
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface DrawerItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
name: React.ReactNode;
|
||||
name: SafeReactNode;
|
||||
title?: string;
|
||||
labelsOnly?: boolean;
|
||||
hidden?: boolean;
|
||||
|
@ -6,11 +6,12 @@
|
||||
import "./drawer-param-toggler.scss";
|
||||
import React from "react";
|
||||
import { Icon } from "../icon";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface DrawerParamTogglerProps {
|
||||
label: string | number;
|
||||
children: React.ReactNode | React.ReactNode[];
|
||||
children: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -5,16 +5,17 @@
|
||||
|
||||
import styles from "./drawer-title.module.css";
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface DrawerTitleProps {
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
children?: SafeReactNode;
|
||||
|
||||
/**
|
||||
* @deprecated Prefer passing the value as `children`
|
||||
*/
|
||||
title?: React.ReactNode;
|
||||
title?: SafeReactNode;
|
||||
|
||||
/**
|
||||
* Specifies how large this title is
|
||||
|
@ -8,7 +8,7 @@ import "./drawer.scss";
|
||||
import React from "react";
|
||||
import { clipboard } from "electron";
|
||||
import { createPortal } from "react-dom";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
import { Icon } from "../icon";
|
||||
import type { AnimateName } from "../animate";
|
||||
@ -24,7 +24,7 @@ export type DrawerPosition = "top" | "left" | "right" | "bottom";
|
||||
|
||||
export interface DrawerProps {
|
||||
open: boolean;
|
||||
title: React.ReactNode;
|
||||
title: SafeReactNode;
|
||||
|
||||
/**
|
||||
* The width or heigh (depending on `position`) of the Drawer.
|
||||
@ -38,8 +38,8 @@ export interface DrawerProps {
|
||||
position?: DrawerPosition;
|
||||
animation?: AnimateName;
|
||||
onClose?: () => void;
|
||||
toolbar?: React.ReactNode;
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
toolbar?: SafeReactNode;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
"data-testid"?: string;
|
||||
testIdForClose?: string;
|
||||
}
|
||||
|
@ -3,18 +3,21 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { toSafeReactChildrenArray } from "@k8slens/utilities";
|
||||
import type { HTMLAttributes } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Menu } from "../menu";
|
||||
|
||||
interface DropdownProps extends HTMLAttributes<HTMLDivElement> {
|
||||
contentForToggle: React.ReactNode;
|
||||
contentForToggle: SafeReactNode;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export function Dropdown(props: DropdownProps) {
|
||||
const { id, contentForToggle, children, ...rest } = props;
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
|
||||
const toggle = () => {
|
||||
setOpened(!opened);
|
||||
};
|
||||
@ -31,7 +34,7 @@ export function Dropdown(props: DropdownProps) {
|
||||
close={toggle}
|
||||
open={toggle}
|
||||
>
|
||||
{React.Children.toArray(children)}
|
||||
{toSafeReactChildrenArray(children)}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
|
@ -22,7 +22,7 @@ const everySecond = 1000;
|
||||
const everyMinute = 60 * 1000;
|
||||
|
||||
/**
|
||||
* This function computes a resonable update interval, matching `formatDuration`'s rules on when to display seconds
|
||||
* This function computes a reasonable update interval, matching `formatDuration`'s rules on when to display seconds
|
||||
*/
|
||||
function computeUpdateInterval(creationTimestampEpoch: number, compact: boolean): number {
|
||||
const seconds = Math.floor((Date.now() - creationTimestampEpoch) / 1000);
|
||||
|
@ -11,7 +11,7 @@ import React from "react";
|
||||
import { Icon } from "../icon";
|
||||
import type { InputProps, InputValidator } from "../input";
|
||||
import { Input } from "../input";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import autoBindReact from "auto-bind/react";
|
||||
|
||||
export interface EditableListProps<T> {
|
||||
@ -23,7 +23,7 @@ export interface EditableListProps<T> {
|
||||
|
||||
// An optional prop used to convert T to a displayable string
|
||||
// defaults to `String`
|
||||
renderItem?: (item: T, index: number) => React.ReactNode;
|
||||
renderItem?: (item: T, index: number) => SafeReactNode;
|
||||
inputTheme?: InputProps["theme"];
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import { Spinner } from "../spinner";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import _ from "lodash";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export interface FileUploadProps {
|
||||
uploadDir: string;
|
||||
@ -48,7 +49,7 @@ export enum OverTotalSizeLimitStyle {
|
||||
|
||||
export interface BaseProps {
|
||||
accept?: string;
|
||||
label: React.ReactNode;
|
||||
label: SafeReactNode;
|
||||
multiple?: boolean;
|
||||
|
||||
// limit is the optional maximum number of files to upload
|
||||
@ -220,7 +221,7 @@ class DefaultedFilePicker extends React.Component<FilePickerProps & typeof defau
|
||||
);
|
||||
}
|
||||
|
||||
getIconRight(): React.ReactNode {
|
||||
getIconRight(): SafeReactNode {
|
||||
switch (this.status) {
|
||||
case FileInputStatus.PROCESSING:
|
||||
return <Spinner />;
|
||||
|
@ -4,13 +4,12 @@
|
||||
*/
|
||||
import "./hotbar-menu.scss";
|
||||
|
||||
import type { HTMLAttributes, ReactNode } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface HotbarCellProps extends HTMLAttributes<HTMLDivElement> {
|
||||
children?: ReactNode;
|
||||
export interface HotbarCellProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
index: number;
|
||||
innerRef?: React.Ref<HTMLDivElement>;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import "./hotbar-menu.scss";
|
||||
import React, { useState } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { HotbarEntityIcon } from "./hotbar-entity-icon";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry";
|
||||
import type { CatalogEntity } from "../../api/catalog-entity";
|
||||
@ -147,7 +147,7 @@ const NonInjectedHotbarMenu = observer((props: Dependencies & HotbarMenuProps) =
|
||||
)}
|
||||
</Draggable>
|
||||
)}
|
||||
{provided.placeholder}
|
||||
{provided.placeholder as SafeReactNode}
|
||||
</HotbarCell>
|
||||
)}
|
||||
</Droppable>
|
||||
|
@ -88,7 +88,7 @@ const NonInjectedHotbarSelector = observer(({
|
||||
targetId="hotbarIndex"
|
||||
preferredPositions={[TooltipPosition.TOP, TooltipPosition.TOP_LEFT]}
|
||||
>
|
||||
{hotbar?.name}
|
||||
{hotbar?.name.get()}
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Icon
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
import "./icon.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React, { createRef } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import type { LocationDescriptor } from "history";
|
||||
@ -37,6 +36,7 @@ import Workloads from "./workloads.svg";
|
||||
import type { Logger } from "@k8slens/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import type { SingleOrMany, SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
const hrefValidation = /https?:\/\//;
|
||||
|
||||
@ -158,7 +158,9 @@ export interface BaseIconProps {
|
||||
"data-testid"?: string;
|
||||
}
|
||||
|
||||
export interface IconProps extends React.HTMLAttributes<any>, BaseIconProps {}
|
||||
export interface IconProps extends React.HTMLAttributes<any>, BaseIconProps {
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export function isSvg(content: string): boolean {
|
||||
// source code of the asset
|
||||
@ -204,7 +206,7 @@ const RawIcon = (props: IconProps & Dependencies) => {
|
||||
onKeyDown?.(event);
|
||||
};
|
||||
|
||||
let iconContent: ReactNode;
|
||||
let iconContent: SafeReactNode;
|
||||
const iconProps: Partial<IconProps> = {
|
||||
className: cssNames("Icon", className,
|
||||
{ svg, material, interactive: isInteractive, disabled, sticker, active, focusable },
|
||||
|
@ -7,7 +7,7 @@ import "./input.scss";
|
||||
|
||||
import type { DOMAttributes, InputHTMLAttributes, TextareaHTMLAttributes } from "react";
|
||||
import React from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { debouncePromise, isPromiseSettledFulfilled, cssNames } from "@k8slens/utilities";
|
||||
import { Icon } from "../icon";
|
||||
import type { TooltipProps } from "@k8slens/tooltip";
|
||||
@ -53,12 +53,12 @@ export interface IconDataFnArg {
|
||||
}
|
||||
|
||||
/**
|
||||
* One of the folloing:
|
||||
* One of the following:
|
||||
* - A material icon name
|
||||
* - A react node
|
||||
* - Or a function that produces a react node
|
||||
*/
|
||||
export type IconData = string | React.ReactNode | ((opt: IconDataFnArg) => React.ReactNode);
|
||||
export type IconData = string | SafeReactNode | ((opt: IconDataFnArg) => SafeReactNode);
|
||||
|
||||
export type InputProps = Omit<InputElementProps, "onChange" | "onSubmit"> & {
|
||||
theme?: "round-black" | "round";
|
||||
@ -74,7 +74,7 @@ export type InputProps = Omit<InputElementProps, "onChange" | "onSubmit"> & {
|
||||
showErrorsAsTooltip?: boolean | Omit<TooltipProps, "targetId">; // show validation errors as a tooltip :hover (instead of block below)
|
||||
iconLeft?: IconData;
|
||||
iconRight?: IconData;
|
||||
contentRight?: string | React.ReactNode; // Any component of string goes after iconRight
|
||||
contentRight?: string | SafeReactNode; // Any component of string goes after iconRight
|
||||
validators?: SingleOrMany<InputValidator>;
|
||||
blurOnEnter?: boolean;
|
||||
onChange?(value: string, evt: React.ChangeEvent<InputElement>): void;
|
||||
@ -86,7 +86,7 @@ interface State {
|
||||
dirty: boolean;
|
||||
valid: boolean;
|
||||
validating: boolean;
|
||||
errors: React.ReactNode[];
|
||||
errors: SafeReactNode[];
|
||||
submitted: boolean;
|
||||
}
|
||||
|
||||
@ -171,8 +171,8 @@ export class Input extends React.Component<InputProps, State> {
|
||||
async validate() {
|
||||
const value = this.getValue();
|
||||
let validationId = (this.validationId = ""); // reset every time for async validators
|
||||
const asyncValidators: Promise<React.ReactNode>[] = [];
|
||||
const errors: React.ReactNode[] = [];
|
||||
const asyncValidators: Promise<SafeReactNode>[] = [];
|
||||
const errors: SafeReactNode[] = [];
|
||||
|
||||
// run validators
|
||||
for (const validator of this.validators) {
|
||||
@ -192,6 +192,8 @@ export class Input extends React.Component<InputProps, State> {
|
||||
asyncValidators.push((async () => {
|
||||
try {
|
||||
await validator.validate(value, this.props);
|
||||
|
||||
return undefined;
|
||||
} catch (error) {
|
||||
return this.getValidatorError(value, validator) || (error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
@ -220,7 +222,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
this.input?.setCustomValidity(errors[0]?.toString() ?? "");
|
||||
}
|
||||
|
||||
setValidation(errors: React.ReactNode[]) {
|
||||
setValidation(errors: SafeReactNode[]) {
|
||||
this.setState({
|
||||
validating: false,
|
||||
valid: !errors.length,
|
||||
@ -432,7 +434,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
const componentId = id || showErrorsAsTooltip
|
||||
? `input_tooltip_id_${uuid.v4()}`
|
||||
: undefined;
|
||||
let tooltipError: React.ReactNode;
|
||||
let tooltipError: SafeReactNode;
|
||||
|
||||
if (showErrorsAsTooltip && showErrors) {
|
||||
const tooltipProps = typeof showErrorsAsTooltip === "object" ? showErrorsAsTooltip : {};
|
||||
|
@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
import type { InputProps } from "./input";
|
||||
import type React from "react";
|
||||
import fse from "fs-extra";
|
||||
import { TypedRegEx } from "typed-regex";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export type InputValidationResult<IsAsync extends boolean> =
|
||||
IsAsync extends true
|
||||
@ -16,7 +16,7 @@ export type InputValidationResult<IsAsync extends boolean> =
|
||||
|
||||
export type InputValidation<IsAsync extends boolean> = (value: string, props?: InputProps) => InputValidationResult<IsAsync>;
|
||||
|
||||
export type SyncValidationMessage = React.ReactNode | ((value: string, props?: InputProps) => React.ReactNode);
|
||||
export type SyncValidationMessage = SafeReactNode | ((value: string, props?: InputProps) => SafeReactNode);
|
||||
|
||||
/**
|
||||
* @deprecated This type is not as type safe as it is possible to specify an async input validator without specifying a `debounce` time.
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
import "./item-list-layout.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed, makeObservable } from "mobx";
|
||||
@ -13,7 +12,7 @@ import { Observer, observer } from "mobx-react";
|
||||
import type { ConfirmDialogParams } from "../confirm-dialog";
|
||||
import type { TableCellProps, TableProps, TableRowProps, TableSortCallbacks } from "../table";
|
||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, isDefined, isReactNode, noop, prevDefault, stopPropagation } from "@k8slens/utilities";
|
||||
import type { AddRemoveButtonsProps } from "../add-remove-buttons";
|
||||
import { AddRemoveButtons } from "../add-remove-buttons";
|
||||
@ -50,8 +49,8 @@ export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStor
|
||||
sortingCallbacks?: TableSortCallbacks<Item>;
|
||||
tableProps?: Partial<TableProps<Item>>; // low-level table configuration
|
||||
renderTableHeader?: (TableCellProps | undefined | null)[];
|
||||
renderTableContents: (item: Item) => (ReactNode | TableCellProps)[];
|
||||
renderItemMenu?: (item: Item, store: ItemListStore<Item, PreLoadStores>) => ReactNode;
|
||||
renderTableContents: (item: Item) => (SafeReactNode | TableCellProps)[];
|
||||
renderItemMenu?: (item: Item, store: ItemListStore<Item, PreLoadStores>) => SafeReactNode;
|
||||
customizeTableRowProps?: (item: Item) => Partial<TableRowProps<Item>>;
|
||||
addRemoveButtons?: Partial<AddRemoveButtonsProps>;
|
||||
virtual?: boolean;
|
||||
@ -71,7 +70,7 @@ export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStor
|
||||
*
|
||||
* @default "Failed to load items"
|
||||
*/
|
||||
failedToLoadMessage?: React.ReactNode;
|
||||
failedToLoadMessage?: SafeReactNode;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
|
@ -5,10 +5,9 @@
|
||||
|
||||
import "./item-list-layout.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, isDefined } from "@k8slens/utilities";
|
||||
import type { ItemObject } from "@k8slens/list-layout";
|
||||
import type { Filter } from "./page-filters/store";
|
||||
@ -27,8 +26,8 @@ export interface ItemListLayoutHeaderProps<I extends ItemObject, PreLoadStores e
|
||||
showHeader?: boolean;
|
||||
headerClassName?: IClassName;
|
||||
renderHeaderTitle?:
|
||||
| ReactNode
|
||||
| (() => ReactNode);
|
||||
| SafeReactNode
|
||||
| (() => SafeReactNode);
|
||||
customizeHeader?: HeaderCustomizer | HeaderCustomizer[];
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,12 @@
|
||||
|
||||
import "./item-list-layout.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed, makeObservable, untracked } from "mobx";
|
||||
import type { ConfirmDialogParams } from "../confirm-dialog";
|
||||
import type { TableCellProps, TableProps, TableRowProps, TableSortCallbacks } from "../table";
|
||||
import type { IClassName, SingleOrMany } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
import type { AddRemoveButtonsProps } from "../add-remove-buttons";
|
||||
import type { ItemObject } from "@k8slens/list-layout";
|
||||
@ -39,10 +38,10 @@ export type ItemsFilter<I extends ItemObject> = (items: I[]) => I[];
|
||||
export type ItemsFilters<I extends ItemObject> = Record<string, ItemsFilter<I>>;
|
||||
|
||||
export interface HeaderPlaceholders {
|
||||
title?: ReactNode;
|
||||
title?: SafeReactNode;
|
||||
searchProps?: SearchInputUrlProps;
|
||||
filters?: ReactNode;
|
||||
info?: ReactNode;
|
||||
filters?: SafeReactNode;
|
||||
info?: SafeReactNode;
|
||||
}
|
||||
|
||||
function normalizeText(value: Primitive) {
|
||||
@ -79,7 +78,7 @@ export type ItemListStore<I extends ItemObject, PreLoadStores extends boolean> =
|
||||
export type RenderHeaderTitle<
|
||||
Item extends ItemObject,
|
||||
PreLoadStores extends boolean,
|
||||
> = ReactNode | ((parent: NonInjectedItemListLayout<Item, PreLoadStores>) => ReactNode);
|
||||
> = SafeReactNode | ((parent: NonInjectedItemListLayout<Item, PreLoadStores>) => SafeReactNode);
|
||||
|
||||
export type HeaderCustomizer = (placeholders: HeaderPlaceholders) => HeaderPlaceholders;
|
||||
export type ItemListLayoutProps<Item extends ItemObject, PreLoadStores extends boolean = boolean> = {
|
||||
@ -108,8 +107,8 @@ export type ItemListLayoutProps<Item extends ItemObject, PreLoadStores extends b
|
||||
sortingCallbacks?: TableSortCallbacks<Item>;
|
||||
tableProps?: Partial<TableProps<Item>>; // low-level table configuration
|
||||
renderTableHeader?: (TableCellProps | undefined | null)[];
|
||||
renderTableContents: (item: Item) => (ReactNode | TableCellProps)[];
|
||||
renderItemMenu?: (item: Item, store: ItemListStore<Item, PreLoadStores>) => ReactNode;
|
||||
renderTableContents: (item: Item) => (SafeReactNode | TableCellProps)[];
|
||||
renderItemMenu?: (item: Item, store: ItemListStore<Item, PreLoadStores>) => SafeReactNode;
|
||||
customizeTableRowProps?: (item: Item) => Partial<TableRowProps<Item>>;
|
||||
addRemoveButtons?: Partial<AddRemoveButtonsProps>;
|
||||
virtual?: boolean;
|
||||
@ -121,7 +120,7 @@ export type ItemListLayoutProps<Item extends ItemObject, PreLoadStores extends b
|
||||
|
||||
// other
|
||||
customizeRemoveDialog?: (selectedItems: Item[]) => Partial<ConfirmDialogParams>;
|
||||
renderFooter?: (parent: NonInjectedItemListLayout<Item, PreLoadStores>) => React.ReactNode;
|
||||
renderFooter?: (parent: NonInjectedItemListLayout<Item, PreLoadStores>) => SafeReactNode;
|
||||
|
||||
spinnerTestId?: string;
|
||||
|
||||
@ -130,7 +129,7 @@ export type ItemListLayoutProps<Item extends ItemObject, PreLoadStores extends b
|
||||
*
|
||||
* @default "Failed to load items"
|
||||
*/
|
||||
failedToLoadMessage?: React.ReactNode;
|
||||
failedToLoadMessage?: SafeReactNode;
|
||||
|
||||
filterCallbacks?: ItemsFilters<Item>;
|
||||
"data-testid"?: string;
|
||||
|
@ -7,6 +7,7 @@ import styles from "./kubeconfig-dialog.module.scss";
|
||||
import React from "react";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Button } from "@k8slens/button";
|
||||
import type { DialogProps } from "../dialog";
|
||||
@ -22,7 +23,7 @@ import kubeconfigDialogStateInjectable from "./state.injectable";
|
||||
import { saveFileDialog } from "../../utils/saveFile";
|
||||
|
||||
export interface KubeconfigDialogData {
|
||||
title?: React.ReactNode;
|
||||
title?: SafeReactNode;
|
||||
config: string;
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type React from "react";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import showCheckedErrorNotificationInjectable from "../notifications/show-checked-error.injectable";
|
||||
import kubeconfigDialogStateInjectable from "./state.injectable";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export interface OpenKubeconfigDialogArgs {
|
||||
title?: React.ReactNode;
|
||||
title?: SafeReactNode;
|
||||
loader: () => Promise<string>;
|
||||
}
|
||||
|
||||
@ -29,8 +29,8 @@ const openKubeconfigDialogInjectable = getInjectable({
|
||||
|
||||
state.set({ title, config });
|
||||
} catch (error) {
|
||||
showCheckedErrorNotification(error, "Failed to retrive config for dialog");
|
||||
logger.warn("[KUBEOCONFIG-DIALOG]: failed to retrived config for dialog", error);
|
||||
showCheckedErrorNotification(error, "Failed to retrieve config for dialog");
|
||||
logger.warn("[KUBECONFIG-DIALOG]: failed to retrieve config for dialog", error);
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
@ -7,12 +7,13 @@ import type { IconProps } from "../icon";
|
||||
import type React from "react";
|
||||
import type { PageTarget } from "../../routes/page-registration";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export interface ClusterPageMenuRegistration {
|
||||
id?: string;
|
||||
parentId?: string;
|
||||
target?: PageTarget;
|
||||
title: React.ReactNode;
|
||||
title: SafeReactNode;
|
||||
components: ClusterPageMenuComponents;
|
||||
visible?: IComputedValue<boolean>;
|
||||
orderNumber?: number;
|
||||
|
@ -7,6 +7,7 @@ import styles from "./main-layout.module.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { ErrorBoundary } from "@k8slens/error-boundary";
|
||||
import { ResizeDirection, ResizeGrowthDirection, ResizeSide, ResizingAnchor } from "@k8slens/resizing-anchor";
|
||||
@ -16,10 +17,10 @@ import sidebarStorageInjectable, { defaultSidebarWidth } from "./sidebar-storage
|
||||
import type { StorageLayer } from "../../utils/storage-helper";
|
||||
|
||||
export interface MainLayoutProps {
|
||||
sidebar: React.ReactNode;
|
||||
sidebar: SafeReactNode;
|
||||
className?: string;
|
||||
footer?: React.ReactNode;
|
||||
children?: React.ReactNode | React.ReactNode[];
|
||||
footer?: SafeReactNode;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,7 @@ import "./setting-layout.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { CloseButton } from "./close-button";
|
||||
import { getLegacyGlobalDiForExtensionApi } from "@k8slens/legacy-global-di";
|
||||
@ -19,7 +19,7 @@ export interface SettingLayoutProps extends React.DOMAttributes<any> {
|
||||
contentClass?: IClassName;
|
||||
provideBackButtonNavigation?: boolean;
|
||||
contentGaps?: boolean;
|
||||
navigation?: React.ReactNode;
|
||||
navigation?: SafeReactNode;
|
||||
back?: (evt: React.MouseEvent | KeyboardEvent) => void;
|
||||
closeButtonProps?: { "data-testid"?: string };
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ import React from "react";
|
||||
import siblingTabsInjectable from "../../routes/sibling-tabs.injectable";
|
||||
import { TabLayout } from "./tab-layout-2";
|
||||
import type { HierarchicalSidebarItem } from "./sidebar-items.injectable";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
interface SiblingTabLayoutProps {
|
||||
children: React.ReactNode;
|
||||
children: SafeReactNode;
|
||||
scrollable?: boolean;
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,14 @@ import { computed } from "mobx";
|
||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { byOrderNumber } from "../../../common/utils/composable-responsibilities/orderable/orderable";
|
||||
import type { SetRequired } from "type-fest";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export interface SidebarItemRegistration {
|
||||
id: string;
|
||||
parentId: string | null;
|
||||
title: React.ReactNode;
|
||||
title: SafeReactNode;
|
||||
onClick: () => void;
|
||||
getIcon?: () => React.ReactNode;
|
||||
getIcon?: () => SafeReactNode;
|
||||
isActive?: IComputedValue<boolean>;
|
||||
isVisible?: IComputedValue<boolean>;
|
||||
orderNumber: number;
|
||||
|
@ -5,14 +5,14 @@
|
||||
|
||||
import "./sub-header.scss";
|
||||
import React from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface SubHeaderProps {
|
||||
className?: string;
|
||||
withLine?: boolean; // add bottom line
|
||||
compact?: boolean; // no extra padding around content
|
||||
children: SingleOrMany<React.ReactNode>;
|
||||
children: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export class SubHeader extends React.Component<SubHeaderProps> {
|
||||
|
@ -5,15 +5,15 @@
|
||||
|
||||
import "./sub-title.scss";
|
||||
import React from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface SubTitleProps {
|
||||
className?: string;
|
||||
title: React.ReactNode;
|
||||
title: SafeReactNode;
|
||||
compact?: boolean; // no bottom padding
|
||||
id?: string;
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export class SubTitle extends React.Component<SubTitleProps> {
|
||||
|
@ -7,6 +7,7 @@ import "./tab-layout.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Tab, Tabs } from "../tabs";
|
||||
import { ErrorBoundary } from "@k8slens/error-boundary";
|
||||
@ -14,7 +15,7 @@ import type { HierarchicalSidebarItem } from "./sidebar-items.injectable";
|
||||
|
||||
export interface TabLayoutProps {
|
||||
tabs?: HierarchicalSidebarItem[];
|
||||
children?: React.ReactNode;
|
||||
children?: SafeReactNode;
|
||||
scrollable?: boolean;
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,10 @@
|
||||
|
||||
import "./tab-layout.scss";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import { matchPath, Redirect, Route, Switch } from "react-router";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Tab, Tabs } from "../tabs";
|
||||
import { ErrorBoundary } from "@k8slens/error-boundary";
|
||||
@ -23,13 +22,13 @@ export interface TabLayoutProps {
|
||||
className?: IClassName;
|
||||
contentClass?: IClassName;
|
||||
tabs?: TabLayoutRoute[];
|
||||
children?: ReactNode;
|
||||
children?: SafeReactNode;
|
||||
scrollable?: boolean;
|
||||
}
|
||||
|
||||
export interface TabLayoutRoute {
|
||||
routePath: string;
|
||||
title: React.ReactNode;
|
||||
title: SafeReactNode;
|
||||
component: React.ComponentType<any>;
|
||||
url?: string; // page-url, if not provided `routePath` is used (doesn't work when path has some :placeholder(s))
|
||||
exact?: boolean; // route-path matching rule
|
||||
|
@ -6,16 +6,16 @@
|
||||
import "./wizard-layout.scss";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface WizardLayoutProps extends React.DOMAttributes<any> {
|
||||
className?: IClassName;
|
||||
header?: React.ReactNode;
|
||||
header?: SafeReactNode;
|
||||
headerClass?: IClassName;
|
||||
contentClass?: IClassName;
|
||||
infoPanelClass?: IClassName;
|
||||
infoPanel?: React.ReactNode;
|
||||
infoPanel?: SafeReactNode;
|
||||
centered?: boolean; // Centering content horizontally
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import "./line-progress.scss";
|
||||
import React from "react";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { withTooltip } from "@k8slens/tooltip";
|
||||
|
||||
@ -14,6 +15,7 @@ export interface LineProgressProps extends React.HTMLProps<HTMLDivElement> {
|
||||
max?: number;
|
||||
className?: any;
|
||||
precise?: number;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
function valuePercent({ value, min, max, precise }: Required<Pick<LineProgressProps, "value" | "min" | "max" | "precise">>) {
|
||||
|
@ -9,13 +9,14 @@ import { SearchInput } from "../input";
|
||||
|
||||
import type { UseTableOptions } from "react-table";
|
||||
import { ReactTable } from "../table/react-table";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export type SearchFilter<T> = (item: T) => string | number;
|
||||
|
||||
export interface ListProps<T> extends UseTableOptions<any> {
|
||||
items: T[];
|
||||
filters: SearchFilter<T>[];
|
||||
title?: React.ReactNode;
|
||||
title?: SafeReactNode;
|
||||
}
|
||||
|
||||
export function List<T>({ columns, data, title, items, filters }: ListProps<T>) {
|
||||
|
@ -8,6 +8,7 @@ import "./menu-actions.scss";
|
||||
import React, { isValidElement } from "react";
|
||||
import { observable, makeObservable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import type { IconProps } from "../icon";
|
||||
import { Icon } from "../icon";
|
||||
@ -25,11 +26,11 @@ export interface MenuActionsProps extends Partial<MenuProps> {
|
||||
className?: string;
|
||||
toolbar?: boolean; // display menu as toolbar with icons
|
||||
autoCloseOnSelect?: boolean;
|
||||
triggerIcon?: string | (IconProps & TooltipDecoratorProps) | React.ReactNode;
|
||||
triggerIcon?: string | (IconProps & TooltipDecoratorProps) | SafeReactNode;
|
||||
/**
|
||||
* @deprecated Provide your own remove `<MenuItem>` as part of the `children` passed to this component
|
||||
*/
|
||||
removeConfirmationMessage?: React.ReactNode | (() => React.ReactNode);
|
||||
removeConfirmationMessage?: SafeReactNode | (() => SafeReactNode);
|
||||
/**
|
||||
* @deprecated Provide your own update `<MenuItem>` as part of the `children` passed to this component
|
||||
*/
|
||||
|
@ -5,9 +5,10 @@
|
||||
|
||||
import "./menu.scss";
|
||||
|
||||
import type { ReactElement, ReactNode } from "react";
|
||||
import type { ReactElement } from "react";
|
||||
import React, { Fragment } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
import { Animate } from "../animate";
|
||||
import type { IconProps } from "../icon";
|
||||
@ -48,7 +49,7 @@ export interface MenuProps {
|
||||
closeOnClickOutside?: boolean; // use false value for sub-menus
|
||||
closeOnScroll?: boolean; // applicable when usePortal={true}
|
||||
position?: MenuPosition; // applicable when usePortal={false}
|
||||
children?: ReactNode;
|
||||
children?: SafeReactNode;
|
||||
animated?: boolean;
|
||||
toggleEvent?: "click" | "contextmenu";
|
||||
"data-testid"?: string;
|
||||
|
@ -12,9 +12,10 @@ import { renderFor } from "../test-utils/renderFor";
|
||||
import hierarchicalNamespacesInjectable from "./hierarchical-namespaces.injectable";
|
||||
import { NamespaceTreeView } from "./namespace-tree-view";
|
||||
import type { NamespaceTree } from "./store";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
jest.mock("react-router-dom", () => ({
|
||||
Link: ({ children }: { children: React.ReactNode }) => children,
|
||||
Link: ({ children }: { children: SafeReactNode }) => children,
|
||||
}));
|
||||
|
||||
function createNamespace(name: string, labels?: Record<string, string>, annotations?: Record<string, string>): Namespace {
|
||||
|
@ -6,12 +6,12 @@
|
||||
import "./no-items.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
|
||||
export interface NoItemsProps {
|
||||
className?: IClassName;
|
||||
children?: React.ReactNode;
|
||||
children?: SafeReactNode;
|
||||
}
|
||||
|
||||
export function NoItems(props: NoItemsProps) {
|
||||
|
@ -15,6 +15,7 @@ import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||
import type { Logger } from "@k8slens/logger";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
|
||||
export interface PodSecurityPolicyDetailsProps extends KubeObjectDetailsProps<PodSecurityPolicy> {
|
||||
}
|
||||
@ -33,7 +34,7 @@ interface Dependencies {
|
||||
|
||||
@observer
|
||||
class NonInjectedPodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps & Dependencies> {
|
||||
renderRuleGroup(title: React.ReactNode, group: RuleGroup | undefined) {
|
||||
renderRuleGroup(title: SafeReactNode, group: RuleGroup | undefined) {
|
||||
if (!group) return null;
|
||||
const { rule, ranges } = group;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
import "./radio.scss";
|
||||
import React, { useContext, useRef } from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames, noop } from "@k8slens/utilities";
|
||||
|
||||
export interface RadioGroupProps<T> {
|
||||
@ -50,7 +50,7 @@ export function RadioGroup<T>({
|
||||
|
||||
export interface RadioProps<T> {
|
||||
className?: string;
|
||||
label: React.ReactNode;
|
||||
label: SafeReactNode;
|
||||
value: T;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import type { RequestIdleCallback } from "./request-idle-callback.injectable";
|
||||
import type { CancelIdleCallback } from "./cancel-idle-callback.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@ -13,8 +13,8 @@ import requestIdleCallbackInjectable from "./request-idle-callback.injectable";
|
||||
import idleCallbackTimeoutInjectable from "./idle-callback-timeout.injectable";
|
||||
|
||||
export interface RenderDelayProps {
|
||||
placeholder?: React.ReactNode;
|
||||
children: SingleOrMany<React.ReactNode>;
|
||||
placeholder?: SafeReactNode;
|
||||
children: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
|
@ -14,6 +14,7 @@ import { observer } from "mobx-react";
|
||||
import ReactSelect, { components, createFilter } from "react-select";
|
||||
import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select";
|
||||
import type { LensTheme } from "../../themes/lens-theme";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import activeThemeInjectable from "../../themes/active.injectable";
|
||||
@ -23,7 +24,7 @@ const { Menu } = components;
|
||||
|
||||
export interface SelectOption<Value> {
|
||||
value: Value;
|
||||
label: React.ReactNode;
|
||||
label: SafeReactNode;
|
||||
isDisabled?: boolean;
|
||||
isSelected?: boolean;
|
||||
id?: string;
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
/**
|
||||
@ -34,10 +35,10 @@ export interface StatusBarRegistration {
|
||||
/**
|
||||
* @deprecated use {@link StatusBarRegistration.components} instead
|
||||
*/
|
||||
item?: React.ReactNode | (() => React.ReactNode);
|
||||
item?: SafeReactNode | (() => SafeReactNode);
|
||||
|
||||
/**
|
||||
* The newer API, allows for registering a component instead of a ReactNode
|
||||
* The newer API, allows for registering a component instead of a SafeReactNode
|
||||
*/
|
||||
components?: StatusBarComponents;
|
||||
|
||||
|
@ -6,10 +6,12 @@
|
||||
import "./status-brick.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { withTooltip } from "@k8slens/tooltip";
|
||||
|
||||
export interface StatusBrickProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export const StatusBrick = withTooltip(({ className, ...elemProps }: StatusBrickProps) => (
|
||||
|
@ -3,17 +3,18 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import React from "react";
|
||||
|
||||
interface FormControlLabelProps {
|
||||
control: React.ReactElement<any, any>;
|
||||
label: React.ReactNode;
|
||||
label: SafeReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use <Switch/> instead from "../switch.tsx".
|
||||
*/
|
||||
export function FormSwitch(props: FormControlLabelProps & { children?: React.ReactNode }) {
|
||||
export function FormSwitch(props: FormControlLabelProps & { children?: SafeReactNode }) {
|
||||
const ClonedElement = React.cloneElement(props.control, {
|
||||
children: <span>{props.label}</span>,
|
||||
});
|
||||
|
@ -3,12 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import React from "react";
|
||||
import { Switch } from "./switch";
|
||||
|
||||
export interface SwitcherProps {
|
||||
disabled?: boolean;
|
||||
children?: React.ReactNode;
|
||||
children?: SafeReactNode;
|
||||
checked?: boolean;
|
||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>, checked: boolean) => void;
|
||||
name?: string;
|
||||
|
@ -6,8 +6,8 @@
|
||||
import "./table-cell.scss";
|
||||
import type { TableSortBy, TableSortParams } from "./table";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Icon } from "../icon";
|
||||
import { Checkbox } from "../checkbox";
|
||||
@ -29,7 +29,7 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* The actual value of the cell
|
||||
*/
|
||||
title?: ReactNode;
|
||||
title?: SafeReactNode;
|
||||
|
||||
/**
|
||||
* content inside could be scrolled
|
||||
|
@ -7,6 +7,7 @@ import "./table.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, isDefined } from "@k8slens/utilities";
|
||||
import type { TableRowElem, TableRowProps } from "./table-row";
|
||||
import { TableRow } from "./table-row";
|
||||
@ -86,7 +87,7 @@ export interface TableProps<Item> extends React.DOMAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* This is shown when {@link TableProps.items} is empty
|
||||
*/
|
||||
noItems?: React.ReactNode;
|
||||
noItems?: SafeReactNode;
|
||||
/**
|
||||
* Allows to scroll list to selected item
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@
|
||||
import "./tabs.scss";
|
||||
import type { DOMAttributes } from "react";
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Icon } from "../icon";
|
||||
import autoBindReact from "auto-bind/react";
|
||||
@ -55,8 +56,8 @@ export interface TabProps<D> extends DOMAttributes<HTMLElement> {
|
||||
className?: string;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
icon?: React.ReactNode | string; // material-io name or custom icon
|
||||
label?: React.ReactNode;
|
||||
icon?: SafeReactNode | string; // material-io name or custom icon
|
||||
label?: SafeReactNode;
|
||||
value: D;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
import styles from "./tree-view.module.scss";
|
||||
import type { MouseEventHandler } from "react";
|
||||
import React, { useState } from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { Icon } from "../icon";
|
||||
|
||||
@ -15,7 +16,7 @@ export interface TreeViewClasses {
|
||||
|
||||
export interface TreeViewProps {
|
||||
classes?: TreeViewClasses;
|
||||
children: React.ReactNode;
|
||||
children: SafeReactNode;
|
||||
}
|
||||
|
||||
export function TreeView(props: TreeViewProps) {
|
||||
|
@ -9,6 +9,7 @@ import moment from "moment";
|
||||
import React from "react";
|
||||
|
||||
import type { Secret } from "@k8slens/kube-object";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { prevDefault } from "@k8slens/utilities";
|
||||
import { Icon } from "../../icon";
|
||||
|
||||
@ -22,7 +23,7 @@ interface State {
|
||||
|
||||
interface RenderRowArgs {
|
||||
name: string;
|
||||
value: React.ReactNode;
|
||||
value: SafeReactNode;
|
||||
}
|
||||
|
||||
export class ServiceAccountsSecret extends React.Component<ServiceAccountsSecretProps, State> {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import "./wizard.scss";
|
||||
import React from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames, prevDefault } from "@k8slens/utilities";
|
||||
import { Button } from "@k8slens/button";
|
||||
import { Stepper } from "../stepper";
|
||||
@ -24,7 +25,7 @@ export interface WizardProps<D> extends WizardCommonProps<D> {
|
||||
className?: string;
|
||||
step?: number;
|
||||
title?: string;
|
||||
header?: React.ReactNode;
|
||||
header?: SafeReactNode;
|
||||
onChange?: (step: number) => void;
|
||||
children?: React.ReactElement<WizardStepProps<D>>[] | React.ReactElement<WizardStepProps<D>>;
|
||||
}
|
||||
@ -107,28 +108,28 @@ export interface WizardStepProps<D> extends WizardCommonProps<D> {
|
||||
title?: string;
|
||||
className?: string | object;
|
||||
contentClass?: string | object;
|
||||
customButtons?: React.ReactNode; // render custom buttons block in footer
|
||||
moreButtons?: React.ReactNode; // add more buttons to section in the footer
|
||||
customButtons?: SafeReactNode; // render custom buttons block in footer
|
||||
moreButtons?: SafeReactNode; // add more buttons to section in the footer
|
||||
loading?: boolean; // indicator of loading content for the step
|
||||
waiting?: boolean; // indicator of waiting response before going to next step
|
||||
disabledNext?: boolean; // disable next button flag, e.g when filling step is not finished
|
||||
hideNextBtn?: boolean;
|
||||
hideBackBtn?: boolean;
|
||||
step?: number;
|
||||
prevLabel?: React.ReactNode; // custom label for prev button
|
||||
nextLabel?: React.ReactNode; // custom label for next button
|
||||
prevLabel?: SafeReactNode; // custom label for prev button
|
||||
nextLabel?: SafeReactNode; // custom label for next button
|
||||
next?: () => void | boolean | Promise<any>; // custom action for next button
|
||||
prev?: () => void; // custom action for prev button
|
||||
first?: () => void;
|
||||
last?: () => void;
|
||||
isFirst?: () => boolean;
|
||||
isLast?: () => boolean;
|
||||
beforeContent?: React.ReactNode;
|
||||
afterContent?: React.ReactNode;
|
||||
beforeContent?: SafeReactNode;
|
||||
afterContent?: SafeReactNode;
|
||||
noValidate?: boolean; // no validate form attribute
|
||||
skip?: boolean; // don't render the step
|
||||
scrollable?: boolean;
|
||||
children?: React.ReactNode | React.ReactNode[];
|
||||
children?: SafeReactNode | SafeReactNode[];
|
||||
testIdForNext?: string;
|
||||
testIdForPrev?: string;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
"devDependencies": {
|
||||
"@async-fn/jest": "^1.6.4",
|
||||
"@k8slens/typescript": "^6.5.0-alpha.2",
|
||||
"@ogre-tools/injectable-extension-for-auto-registration": "^15.9.0",
|
||||
"@ogre-tools/test-utils": "^15.8.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
|
@ -33,6 +33,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@k8slens/kube-object": "^1.0.0-alpha.1",
|
||||
"@k8slens/utilities": "^1.0.0-alpha.3",
|
||||
"@ogre-tools/injectable": "^15.8.1",
|
||||
"react": "^17.0.2"
|
||||
},
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import type { KubeObject } from "@k8slens/kube-object";
|
||||
import type { ReactNode } from "react";
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import type { TableSortCallback, SearchFilter, TableCellProps } from "./list-layout-column";
|
||||
|
||||
export interface BaseKubeObjectListLayoutColumn<K extends KubeObject> {
|
||||
@ -13,7 +13,7 @@ export interface BaseKubeObjectListLayoutColumn<K extends KubeObject> {
|
||||
sortingCallBack?: TableSortCallback<K>;
|
||||
searchFilter?: SearchFilter<K>;
|
||||
header: TableCellProps | undefined | null;
|
||||
content: (item: K) => ReactNode | TableCellProps;
|
||||
content: (item: K) => SafeReactNode | TableCellProps;
|
||||
}
|
||||
|
||||
export interface GeneralKubeObjectListLayoutColumn extends BaseKubeObjectListLayoutColumn<KubeObject> {
|
||||
|
@ -3,8 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
|
||||
export interface ItemObject {
|
||||
getId: () => string;
|
||||
@ -37,7 +36,7 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* The actual value of the cell
|
||||
*/
|
||||
title?: ReactNode;
|
||||
title?: SafeReactNode;
|
||||
|
||||
/**
|
||||
* content inside could be scrolled
|
||||
|
@ -1,8 +1,9 @@
|
||||
import type { SafeReactNode } from "@k8slens/utilities";
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type React from "react";
|
||||
|
||||
export type ReactApplicationHigherOrderComponent = React.ComponentType<{
|
||||
children: React.ReactNode;
|
||||
children: SafeReactNode;
|
||||
}>;
|
||||
|
||||
export const reactApplicationHigherOrderComponentInjectionToken =
|
||||
|
@ -6,11 +6,11 @@
|
||||
import "./button.scss";
|
||||
import type { ButtonHTMLAttributes } from "react";
|
||||
import React from "react";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { cssNames, SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { withTooltip } from "@k8slens/tooltip";
|
||||
|
||||
export interface ButtonProps extends ButtonHTMLAttributes<any> {
|
||||
label?: React.ReactNode;
|
||||
label?: SafeReactNode;
|
||||
waiting?: boolean;
|
||||
primary?: boolean;
|
||||
accent?: boolean;
|
||||
@ -23,6 +23,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<any> {
|
||||
round?: boolean;
|
||||
href?: string; // render as hyperlink
|
||||
target?: "_blank"; // in case of using @href
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export const Button = withTooltip((props: ButtonProps) => {
|
||||
|
@ -9,7 +9,7 @@ import type { ErrorInfo } from "react";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Button } from "@k8slens/button";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import type { ObservableHistory } from "mobx-observable-history";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import { observableHistoryInjectionToken } from "@k8slens/routing";
|
||||
@ -18,7 +18,7 @@ const issuesTrackerUrl = "https://github.com/lensapp/lens/issues";
|
||||
const forumsUrl = "https://forums.k8slens.dev";
|
||||
|
||||
export interface ErrorBoundaryProps {
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -8,7 +8,7 @@ import "./tooltip.scss";
|
||||
import React from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { observer } from "mobx-react";
|
||||
import type { IClassName } from "@k8slens/utilities";
|
||||
import type { IClassName, SafeReactNode } from "@k8slens/utilities";
|
||||
import { cssNames } from "@k8slens/utilities";
|
||||
import { observable, makeObservable, action, runInAction } from "mobx";
|
||||
import autoBindReact from "auto-bind/react";
|
||||
@ -35,7 +35,7 @@ export interface TooltipProps {
|
||||
className?: IClassName;
|
||||
formatters?: TooltipContentFormatters;
|
||||
style?: React.CSSProperties;
|
||||
children?: React.ReactNode;
|
||||
children?: SafeReactNode;
|
||||
"data-testid"?: string;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
import type { SafeReactNode, SingleOrMany } from "@k8slens/utilities";
|
||||
import { render, RenderResult } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React from "react";
|
||||
@ -12,7 +12,7 @@ import { withTooltip } from "./withTooltip";
|
||||
type MyComponentProps = {
|
||||
text: string;
|
||||
id?: string;
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
"data-testid"?: string;
|
||||
};
|
||||
|
||||
|
@ -3,23 +3,22 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import React, { useState } from "react";
|
||||
import type { TooltipProps } from "./tooltip";
|
||||
import { Tooltip } from "./tooltip";
|
||||
import { isReactNode } from "@k8slens/utilities";
|
||||
import { isReactNode, SafeReactNode } from "@k8slens/utilities";
|
||||
import uniqueId from "lodash/uniqueId";
|
||||
import type { SingleOrMany } from "@k8slens/utilities";
|
||||
|
||||
export interface TooltipDecoratorProps {
|
||||
tooltip?: ReactNode | Omit<TooltipProps, "targetId">;
|
||||
tooltip?: SafeReactNode | Omit<TooltipProps, "targetId">;
|
||||
/**
|
||||
* forces tooltip to detect the target's parent for mouse events. This is
|
||||
* useful for displaying tooltips even when the target is "disabled"
|
||||
*/
|
||||
tooltipOverrideDisabled?: boolean;
|
||||
id?: string;
|
||||
children?: SingleOrMany<React.ReactNode>;
|
||||
children?: SingleOrMany<SafeReactNode>;
|
||||
}
|
||||
|
||||
export function withTooltip<TargetProps>(
|
||||
|
@ -17,7 +17,6 @@ export * from "./src/disposer";
|
||||
export * from "./src/formatDuration";
|
||||
export * from "./src/hash-set";
|
||||
export * from "./src/interval";
|
||||
export * from "./src/is-node-falsy";
|
||||
export * from "./src/isMiddleClick";
|
||||
export * from "./src/isReactNode";
|
||||
export * from "./src/iter";
|
||||
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type React from "react";
|
||||
|
||||
/**
|
||||
* Returns `true` if `node` is a falsy value
|
||||
*/
|
||||
export function isNodeFalsy(node: React.ReactNode): boolean {
|
||||
return !isNodeRenderable(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if React would render this
|
||||
*/
|
||||
export function isNodeRenderable(node: React.ReactNode): boolean {
|
||||
return Boolean(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first react node provided that is would be rendered by react
|
||||
*/
|
||||
export function foldNodes(...nodes: React.ReactNode[]): React.ReactNode {
|
||||
return nodes.find(isNodeRenderable);
|
||||
}
|
@ -3,12 +3,17 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
// Type guard for checking valid react node to use in render
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import { isObject } from "./type-narrowing";
|
||||
import type { SingleOrMany } from "./types";
|
||||
|
||||
export function isReactNode(node: unknown): node is ReactNode {
|
||||
export type SafeReactNode = React.ReactElement | React.ReactText | boolean | null | undefined | Iterable<SafeReactNode>;
|
||||
|
||||
export function toSafeReactChildrenArray(children: SingleOrMany<SafeReactNode>) {
|
||||
return React.Children.toArray(children) as (Exclude<SafeReactNode, boolean | null | undefined>)[];
|
||||
}
|
||||
|
||||
export function isReactNode(node: unknown): node is SafeReactNode {
|
||||
return (isObject(node) && React.isValidElement(node))
|
||||
|| Array.isArray(node) && node.every(isReactNode)
|
||||
|| node == null
|
||||
|
@ -95,7 +95,7 @@ export function formatJSONValue(value: unknown): string {
|
||||
/**
|
||||
* This function is a safer version of `JSONPath.value(obj, path)` with untrusted jsonpath strings
|
||||
*
|
||||
* This function will also stringify the value retreived from the object
|
||||
* This function will also stringify the value retrieved from the object
|
||||
*/
|
||||
export function safeJSONPathValue(obj: object, path: string): unknown {
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user