From 01059d8cb185c3566b58541c2aec14c52d7b12be Mon Sep 17 00:00:00 2001 From: Gabriel Date: Wed, 12 Apr 2023 20:16:57 +0200 Subject: [PATCH] chore: extract tooltip into package - chore: add sanity check unit test - chore: added tailwind.config.js to fix build - chore: .swcrc added for tests to pass - chore(deps): sass is not a dependency - fix: manually import the tooltip css to fix tooltips not showing up - chore: Run lint:fix against code - chore: Fix use of mock in @k8slens/core Signed-off-by: Gabriel Signed-off-by: Sebastian Malton --- package-lock.json | 56 +++++++++++++++++++ packages/core/package.json | 3 +- .../src/extensions/renderer-api/components.ts | 2 +- .../src/{jest.setup.ts => jest.setup.tsx} | 21 ++++++- .../renderer/components/+events/events.tsx | 2 +- .../components/+extensions/install.tsx | 2 +- .../+namespaces/subnamespace-badge.tsx | 2 +- .../src/renderer/components/+nodes/route.tsx | 2 +- .../+cluster-role-bindings/dialog/view.tsx | 2 +- .../+workloads-overview/overview.tsx | 2 +- .../components/+workloads-pods/pods.tsx | 2 +- .../src/renderer/components/badge/badge.tsx | 2 +- .../src/renderer/components/button/button.tsx | 2 +- .../src/renderer/components/dock/dock-tab.tsx | 2 +- .../components/hotbar/hotbar-icon.tsx | 2 +- .../components/hotbar/hotbar-selector.tsx | 2 +- .../src/renderer/components/icon/icon.tsx | 2 +- .../src/renderer/components/input/input.tsx | 4 +- .../kube-object-list-layout.tsx | 2 +- .../components/layout/sidebar-cluster.tsx | 2 +- .../line-progress/line-progress.tsx | 2 +- .../renderer/components/menu/menu-actions.tsx | 2 +- .../components/status-brick/status-brick.tsx | 2 +- .../tooltip/__mocks__/withTooltip.tsx | 24 -------- ...protect-from-importing-non-dependencies.js | 3 +- packages/open-lens/src/renderer/index.ts | 1 + packages/ui-components/tooltip/.eslintrc.json | 6 ++ packages/ui-components/tooltip/.prettierrc | 1 + packages/ui-components/tooltip/.swcrc | 19 +++++++ packages/ui-components/tooltip/README.md | 20 +++++++ packages/ui-components/tooltip/index.ts | 2 + packages/ui-components/tooltip/jest.config.js | 1 + packages/ui-components/tooltip/package.json | 50 +++++++++++++++++ .../src}/__snapshots__/tooltip.test.tsx.snap | 0 .../tooltip/src}/index.ts | 0 .../tooltip/src}/tooltip.scss | 17 ++---- .../tooltip/src}/tooltip.test.tsx | 42 ++++++-------- .../tooltip/src}/tooltip.tsx | 15 +++-- .../tooltip/src}/withTooltip.tsx | 11 +--- .../ui-components/tooltip/tailwind.config.js | 30 ++++++++++ packages/ui-components/tooltip/tsconfig.json | 4 ++ .../ui-components/tooltip/webpack.config.js | 1 + 42 files changed, 268 insertions(+), 101 deletions(-) rename packages/core/src/{jest.setup.ts => jest.setup.tsx} (78%) delete mode 100644 packages/core/src/renderer/components/tooltip/__mocks__/withTooltip.tsx create mode 100644 packages/ui-components/tooltip/.eslintrc.json create mode 100644 packages/ui-components/tooltip/.prettierrc create mode 100644 packages/ui-components/tooltip/.swcrc create mode 100644 packages/ui-components/tooltip/README.md create mode 100644 packages/ui-components/tooltip/index.ts create mode 100644 packages/ui-components/tooltip/jest.config.js create mode 100644 packages/ui-components/tooltip/package.json rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/__snapshots__/tooltip.test.tsx.snap (100%) rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/index.ts (100%) rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/tooltip.scss (75%) rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/tooltip.test.tsx (66%) rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/tooltip.tsx (95%) rename packages/{core/src/renderer/components/tooltip => ui-components/tooltip/src}/withTooltip.tsx (91%) create mode 100644 packages/ui-components/tooltip/tailwind.config.js create mode 100644 packages/ui-components/tooltip/tsconfig.json create mode 100644 packages/ui-components/tooltip/webpack.config.js diff --git a/package-lock.json b/package-lock.json index ffb7dc57e5..6458f6172c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3962,6 +3962,10 @@ "resolved": "packages/utility-features/test-utils", "link": true }, + "node_modules/@k8slens/tooltip": { + "resolved": "packages/ui-components/tooltip", + "link": true + }, "node_modules/@k8slens/typescript": { "resolved": "packages/infrastructure/typescript", "link": true @@ -35063,6 +35067,7 @@ "@k8slens/run-many": "^1.0.0-alpha.1", "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", + "@k8slens/tooltip": "^1.0.0-alpha.0", "@k8slens/utilities": "^1.0.0-alpha.1", "@ogre-tools/fp": "^15.3.1", "@ogre-tools/injectable": "^15.3.1", @@ -36601,6 +36606,57 @@ "react-dom": "^17.0.2" } }, + "packages/ui-components/tooltip": { + "name": "@k8slens/tooltip", + "version": "1.0.0-alpha.0", + "license": "MIT", + "devDependencies": { + "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "6.5.0-alpha.1", + "@k8slens/react-testing-library-discovery": "^1.0.0-alpha.0" + }, + "peerDependencies": { + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/utilities": "^1.0.0-alpha.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "auto-bind": "^4.0.0", + "lodash": "^4.17.21", + "mobx": "^6.8.0", + "mobx-react": "^7.6.0", + "react": "^17.0.2", + "react-dom": "^17.0.2" + } + }, + "packages/ui-components/tooltip/node_modules/@k8slens/eslint-config": { + "version": "6.5.0-alpha.1", + "resolved": "https://registry.npmjs.org/@k8slens/eslint-config/-/eslint-config-6.5.0-alpha.1.tgz", + "integrity": "sha512-6DdfKe/iafX85GBK/UlKgz29FOIOp/UVS03bFGLyw7Vmm7pauB0FEHTAdbr3g1qG/Zcn6nxhOM3uqQyRY/uEyA==", + "dev": true, + "bin": { + "lens-lint": "bin/lint" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": ">= 5", + "@typescript-eslint/parser": ">= 5", + "eslint": ">= 7", + "eslint-config-airbnb-typescript": ">= 17", + "eslint-config-prettier": ">= 8", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-import": ">= 2", + "eslint-plugin-jest": ">= 27", + "eslint-plugin-jsx-a11y": ">= 6", + "eslint-plugin-no-unsanitized": ">= 4.0.2", + "eslint-plugin-prettier": ">= 4", + "eslint-plugin-react-hooks": ">= 4", + "eslint-plugin-security": ">= 1.6.0", + "eslint-plugin-simple-import-sort": ">= 7", + "eslint-plugin-unused-imports": ">= 2", + "eslint-plugin-xss": ">= 0.1.12", + "prettier": ">= 2" + } + }, "packages/utility-features/react-testing-library-discovery": { "name": "@k8slens/react-testing-library-discovery", "version": "1.0.0-alpha.3", diff --git a/packages/core/package.json b/packages/core/package.json index 2cfe0c5ae5..be95235ca4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -84,7 +84,7 @@ "/static/build" ], "setupFiles": [ - "/src/jest.setup.ts", + "/src/jest.setup.tsx", "jest-canvas-mock" ], "globalSetup": "/src/jest.timezone.ts", @@ -321,6 +321,7 @@ "@k8slens/run-many": "^1.0.0-alpha.1", "@k8slens/startable-stoppable": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1", + "@k8slens/tooltip": "^1.0.0-alpha.0", "@k8slens/utilities": "^1.0.0-alpha.1", "@ogre-tools/fp": "^15.3.1", "@ogre-tools/injectable": "^15.3.1", diff --git a/packages/core/src/extensions/renderer-api/components.ts b/packages/core/src/extensions/renderer-api/components.ts index 8d2bb6840a..e1773b6eff 100644 --- a/packages/core/src/extensions/renderer-api/components.ts +++ b/packages/core/src/extensions/renderer-api/components.ts @@ -64,7 +64,7 @@ export const ConfirmDialog = Object.assign(_ConfirmDialog, { }); export * from "../../renderer/components/icon"; -export * from "../../renderer/components/tooltip"; +export * from "@k8slens/tooltip"; export * from "../../renderer/components/tabs"; export * from "../../renderer/components/table"; export * from "../../renderer/components/badge"; diff --git a/packages/core/src/jest.setup.ts b/packages/core/src/jest.setup.tsx similarity index 78% rename from packages/core/src/jest.setup.ts rename to packages/core/src/jest.setup.tsx index 96a4b816d4..c511090251 100644 --- a/packages/core/src/jest.setup.ts +++ b/packages/core/src/jest.setup.tsx @@ -9,6 +9,8 @@ import { TextEncoder, TextDecoder as TextDecoderNode } from "util"; import glob from "glob"; import path from "path"; import { enableMapSet, setAutoFreeze } from "immer"; +import type * as K8slensTooltip from "@k8slens/tooltip"; +import React from "react"; declare global { interface InjectablePaths { @@ -53,8 +55,25 @@ global.ResizeObserver = class { }; jest.mock("./renderer/components/monaco-editor/monaco-editor"); -jest.mock("./renderer/components/tooltip/withTooltip"); +jest.mock("@k8slens/tooltip", () => ({ + ...jest.requireActual("@k8slens/tooltip"), + withTooltip: (Target => ({ tooltip, tooltipOverrideDisabled, ...props }: any) => { + if (tooltip) { + const testId = props["data-testid"]; + return ( + <> + +
+ {tooltip.children || tooltip} +
+ + ); + } + + return ; + }) as typeof K8slensTooltip.withTooltip, +})); jest.mock("monaco-editor"); const getInjectables = (environment: "renderer" | "main", filePathGlob: string) => [ diff --git a/packages/core/src/renderer/components/+events/events.tsx b/packages/core/src/renderer/components/+events/events.tsx index 657e10436d..ad73848b28 100644 --- a/packages/core/src/renderer/components/+events/events.tsx +++ b/packages/core/src/renderer/components/+events/events.tsx @@ -16,7 +16,7 @@ import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { KubeEvent, KubeEventApi, KubeEventData } from "../../../common/k8s-api/endpoints/events.api"; import type { TableSortCallbacks, TableSortParams } from "../table"; import type { HeaderCustomizer } from "../item-object-list"; -import { Tooltip } from "../tooltip"; +import { Tooltip } from "@k8slens/tooltip"; import { Link } from "react-router-dom"; import type { IClassName } from "@k8slens/utilities"; import { cssNames, stopPropagation } from "@k8slens/utilities"; diff --git a/packages/core/src/renderer/components/+extensions/install.tsx b/packages/core/src/renderer/components/+extensions/install.tsx index ffbdc3ea2b..8c15430c00 100644 --- a/packages/core/src/renderer/components/+extensions/install.tsx +++ b/packages/core/src/renderer/components/+extensions/install.tsx @@ -11,7 +11,7 @@ import { Icon } from "../icon"; import { observer } from "mobx-react"; import { Input, InputValidators } from "../input"; import { SubTitle } from "../layout/sub-title"; -import { TooltipPosition } from "../tooltip"; +import { TooltipPosition } from "@k8slens/tooltip"; import type { ExtensionInstallationStateStore } from "../../../extensions/extension-installation-state-store/extension-installation-state-store"; import extensionInstallationStateStoreInjectable from "../../../extensions/extension-installation-state-store/extension-installation-state-store.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; diff --git a/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx b/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx index 74e7c02031..40510e995c 100644 --- a/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx +++ b/packages/core/src/renderer/components/+namespaces/subnamespace-badge.tsx @@ -5,7 +5,7 @@ import styles from "./subnamespace-badge.module.scss"; import React from "react"; -import { Tooltip } from "../tooltip"; +import { Tooltip } from "@k8slens/tooltip"; import { cssNames } from "@k8slens/utilities"; interface SubnamespaceBadgeProps extends React.HTMLAttributes { diff --git a/packages/core/src/renderer/components/+nodes/route.tsx b/packages/core/src/renderer/components/+nodes/route.tsx index 99e5900c87..0b51857235 100644 --- a/packages/core/src/renderer/components/+nodes/route.tsx +++ b/packages/core/src/renderer/components/+nodes/route.tsx @@ -12,7 +12,7 @@ import { KubeObjectListLayout } from "../kube-object-list-layout"; import type { Node } from "../../../common/k8s-api/endpoints/node.api"; import { formatNodeTaint } from "../../../common/k8s-api/endpoints/node.api"; import { LineProgress } from "../line-progress"; -import { Tooltip, TooltipPosition } from "../tooltip"; +import { Tooltip, TooltipPosition } from "@k8slens/tooltip"; import kebabCase from "lodash/kebabCase"; import upperFirst from "lodash/upperFirst"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; diff --git a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/dialog/view.tsx b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/dialog/view.tsx index 8c870704bf..c4ea424a92 100644 --- a/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/dialog/view.tsx +++ b/packages/core/src/renderer/components/+user-management/+cluster-role-bindings/dialog/view.tsx @@ -20,7 +20,7 @@ import { onMultiSelectFor, Select } from "../../../select"; import { Wizard, WizardStep } from "../../../wizard"; import { ObservableHashSet, iter } from "@k8slens/utilities"; import { Input } from "../../../input"; -import { TooltipPosition } from "../../../tooltip"; +import { TooltipPosition } from "@k8slens/tooltip"; import type { Subject } from "../../../../../common/k8s-api/endpoints/types/subject"; import type { ClusterRoleBindingDialogState } from "./state.injectable"; import type { ClusterRoleStore } from "../../+cluster-roles/store"; diff --git a/packages/core/src/renderer/components/+workloads-overview/overview.tsx b/packages/core/src/renderer/components/+workloads-overview/overview.tsx index 8b60676da2..ea0162b02a 100644 --- a/packages/core/src/renderer/components/+workloads-overview/overview.tsx +++ b/packages/core/src/renderer/components/+workloads-overview/overview.tsx @@ -15,7 +15,7 @@ import type { IComputedValue } from "mobx"; import { makeObservable, observable, reaction } from "mobx"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; import { Icon } from "../icon"; -import { TooltipPosition } from "../tooltip"; +import { TooltipPosition } from "@k8slens/tooltip"; import { withInjectables } from "@ogre-tools/injectable-react"; import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable"; import type { SubscribeStores } from "../../kube-watch-api/kube-watch-api"; diff --git a/packages/core/src/renderer/components/+workloads-pods/pods.tsx b/packages/core/src/renderer/components/+workloads-pods/pods.tsx index 1132c00a0c..ad932a99a7 100644 --- a/packages/core/src/renderer/components/+workloads-pods/pods.tsx +++ b/packages/core/src/renderer/components/+workloads-pods/pods.tsx @@ -29,7 +29,7 @@ import nodeApiInjectable from "../../../common/k8s-api/endpoints/node.api.inject import eventStoreInjectable from "../+events/store.injectable"; import podStoreInjectable from "./store.injectable"; import { NamespaceSelectBadge } from "../+namespaces/namespace-select-badge"; -import { Tooltip } from "../tooltip"; +import { Tooltip } from "@k8slens/tooltip"; enum columnId { name = "name", diff --git a/packages/core/src/renderer/components/badge/badge.tsx b/packages/core/src/renderer/components/badge/badge.tsx index 5fe12ade09..2e217c2de7 100644 --- a/packages/core/src/renderer/components/badge/badge.tsx +++ b/packages/core/src/renderer/components/badge/badge.tsx @@ -9,7 +9,7 @@ import React, { useEffect, useRef, useState } from "react"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { cssNames } from "@k8slens/utilities"; -import { withTooltip } from "../tooltip"; +import { withTooltip } from "@k8slens/tooltip"; export interface BadgeProps extends React.HTMLAttributes { small?: boolean; diff --git a/packages/core/src/renderer/components/button/button.tsx b/packages/core/src/renderer/components/button/button.tsx index e72a874641..987e299a9c 100644 --- a/packages/core/src/renderer/components/button/button.tsx +++ b/packages/core/src/renderer/components/button/button.tsx @@ -7,7 +7,7 @@ import "./button.scss"; import type { ButtonHTMLAttributes } from "react"; import React from "react"; import { cssNames } from "@k8slens/utilities"; -import { withTooltip } from "../tooltip"; +import { withTooltip } from "@k8slens/tooltip"; export interface ButtonProps extends ButtonHTMLAttributes { label?: React.ReactNode; diff --git a/packages/core/src/renderer/components/dock/dock-tab.tsx b/packages/core/src/renderer/components/dock/dock-tab.tsx index c65ea76ac9..d33eb682dc 100644 --- a/packages/core/src/renderer/components/dock/dock-tab.tsx +++ b/packages/core/src/renderer/components/dock/dock-tab.tsx @@ -16,7 +16,7 @@ import { Menu, MenuItem } from "../menu"; import { observable } from "mobx"; import { withInjectables } from "@ogre-tools/injectable-react"; import dockStoreInjectable from "./dock/store.injectable"; -import { Tooltip, TooltipPosition } from "../tooltip"; +import { Tooltip, TooltipPosition } from "@k8slens/tooltip"; import isMacInjectable from "../../../common/vars/is-mac.injectable"; import autoBindReact from "auto-bind/react"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx b/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx index ee9d4fb04e..2f9ffdd0e6 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-icon.tsx @@ -14,7 +14,7 @@ import { observer } from "mobx-react"; import type { AvatarProps } from "../avatar"; import { Avatar } from "../avatar"; import { Icon } from "../icon"; -import { Tooltip } from "../tooltip"; +import { Tooltip } from "@k8slens/tooltip"; import type { NormalizeCatalogEntityContextMenu } from "../../catalog/normalize-menu-item.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import normalizeCatalogEntityContextMenuInjectable from "../../catalog/normalize-menu-item.injectable"; diff --git a/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx b/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx index d5b720352d..c0ef3c54c7 100644 --- a/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx +++ b/packages/core/src/renderer/components/hotbar/hotbar-selector.tsx @@ -8,7 +8,7 @@ import React, { useRef, useState } from "react"; import { Icon } from "../icon"; import { Badge } from "../badge"; import { HotbarSwitchCommand } from "./hotbar-switch-command"; -import { Tooltip, TooltipPosition } from "../tooltip"; +import { Tooltip, TooltipPosition } from "@k8slens/tooltip"; import { observer } from "mobx-react"; import { withInjectables } from "@ogre-tools/injectable-react"; import commandOverlayInjectable from "../command-palette/command-overlay.injectable"; diff --git a/packages/core/src/renderer/components/icon/icon.tsx b/packages/core/src/renderer/components/icon/icon.tsx index 6da23f247e..6dd47ac3d3 100644 --- a/packages/core/src/renderer/components/icon/icon.tsx +++ b/packages/core/src/renderer/components/icon/icon.tsx @@ -10,7 +10,7 @@ import React, { createRef } from "react"; import { NavLink } from "react-router-dom"; import type { LocationDescriptor } from "history"; import { cssNames } from "@k8slens/utilities"; -import { withTooltip } from "../tooltip"; +import { withTooltip } from "@k8slens/tooltip"; import isNumber from "lodash/isNumber"; import Configuration from "./configuration.svg"; import Crane from "./crane.svg"; diff --git a/packages/core/src/renderer/components/input/input.tsx b/packages/core/src/renderer/components/input/input.tsx index ef4e52f3ed..5b0f10da5f 100644 --- a/packages/core/src/renderer/components/input/input.tsx +++ b/packages/core/src/renderer/components/input/input.tsx @@ -10,8 +10,8 @@ import React from "react"; import type { SingleOrMany } from "@k8slens/utilities"; import { debouncePromise, isPromiseSettledFulfilled, cssNames } from "@k8slens/utilities"; import { Icon } from "../icon"; -import type { TooltipProps } from "../tooltip"; -import { Tooltip } from "../tooltip"; +import type { TooltipProps } from "@k8slens/tooltip"; +import { Tooltip } from "@k8slens/tooltip"; import * as Validators from "./input_validators"; import type { InputValidator, InputValidation, InputValidationResult, SyncValidationMessage } from "./input_validators"; import uniqueId from "lodash/uniqueId"; diff --git a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx index 8d12c8a57a..77d0e19df1 100644 --- a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx +++ b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx @@ -18,7 +18,7 @@ import { KubeObjectMenu } from "../kube-object-menu"; import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter"; import { ResourceKindMap, ResourceNames } from "../../utils/rbac"; import { Icon } from "../icon"; -import { TooltipPosition } from "../tooltip"; +import { TooltipPosition } from "@k8slens/tooltip"; import { withInjectables } from "@ogre-tools/injectable-react"; import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable"; import type { SubscribableStore, SubscribeStores } from "../../kube-watch-api/kube-watch-api"; diff --git a/packages/core/src/renderer/components/layout/sidebar-cluster.tsx b/packages/core/src/renderer/components/layout/sidebar-cluster.tsx index 7ae6ee9405..06adad4ea2 100644 --- a/packages/core/src/renderer/components/layout/sidebar-cluster.tsx +++ b/packages/core/src/renderer/components/layout/sidebar-cluster.tsx @@ -12,7 +12,7 @@ import { IpcRendererNavigationEvents } from "../../../common/ipc/navigation-even import { Avatar } from "../avatar"; import { Icon } from "../icon"; import { Menu, MenuItem } from "../menu"; -import { Tooltip } from "../tooltip"; +import { Tooltip } from "@k8slens/tooltip"; import { withInjectables } from "@ogre-tools/injectable-react"; import { observer } from "mobx-react"; import type { VisitEntityContextMenu } from "../../../common/catalog/visit-entity-context-menu.injectable"; diff --git a/packages/core/src/renderer/components/line-progress/line-progress.tsx b/packages/core/src/renderer/components/line-progress/line-progress.tsx index 22e2e6437a..7ce47c10ca 100644 --- a/packages/core/src/renderer/components/line-progress/line-progress.tsx +++ b/packages/core/src/renderer/components/line-progress/line-progress.tsx @@ -6,7 +6,7 @@ import "./line-progress.scss"; import React from "react"; import { cssNames } from "@k8slens/utilities"; -import { withTooltip } from "../tooltip"; +import { withTooltip } from "@k8slens/tooltip"; export interface LineProgressProps extends React.HTMLProps { value: number; diff --git a/packages/core/src/renderer/components/menu/menu-actions.tsx b/packages/core/src/renderer/components/menu/menu-actions.tsx index 2eebf36778..b482ec9ea6 100644 --- a/packages/core/src/renderer/components/menu/menu-actions.tsx +++ b/packages/core/src/renderer/components/menu/menu-actions.tsx @@ -14,7 +14,7 @@ import { Icon } from "../icon"; import type { MenuProps } from "./menu"; import { Menu, MenuItem } from "./menu"; import isString from "lodash/isString"; -import type { TooltipDecoratorProps } from "../tooltip"; +import type { TooltipDecoratorProps } from "@k8slens/tooltip"; import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable"; import { withInjectables } from "@ogre-tools/injectable-react"; import openConfirmDialogInjectable from "../confirm-dialog/open.injectable"; diff --git a/packages/core/src/renderer/components/status-brick/status-brick.tsx b/packages/core/src/renderer/components/status-brick/status-brick.tsx index 858cdd8580..94e4e4e0c0 100644 --- a/packages/core/src/renderer/components/status-brick/status-brick.tsx +++ b/packages/core/src/renderer/components/status-brick/status-brick.tsx @@ -7,7 +7,7 @@ import "./status-brick.scss"; import React from "react"; import { cssNames } from "@k8slens/utilities"; -import { withTooltip } from "../tooltip"; +import { withTooltip } from "@k8slens/tooltip"; export interface StatusBrickProps extends React.HTMLAttributes { } diff --git a/packages/core/src/renderer/components/tooltip/__mocks__/withTooltip.tsx b/packages/core/src/renderer/components/tooltip/__mocks__/withTooltip.tsx deleted file mode 100644 index cbaa591d91..0000000000 --- a/packages/core/src/renderer/components/tooltip/__mocks__/withTooltip.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import React from "react"; - -export const withTooltip = - (Target: any) => - ({ tooltip, tooltipOverrideDisabled, ...props }: any) => { - if (tooltip) { - const testId = props["data-testid"]; - - return ( - <> - -
- {tooltip.children || tooltip} -
- - ); - } - - return ; - }; diff --git a/packages/infrastructure/webpack/src/plugins/protect-from-importing-non-dependencies.js b/packages/infrastructure/webpack/src/plugins/protect-from-importing-non-dependencies.js index 2df5e61d2c..47331b9c76 100644 --- a/packages/infrastructure/webpack/src/plugins/protect-from-importing-non-dependencies.js +++ b/packages/infrastructure/webpack/src/plugins/protect-from-importing-non-dependencies.js @@ -12,6 +12,7 @@ class ProtectFromImportingNonDependencies { compiler.hooks.normalModuleFactory.tap("irrelevant", (normalModuleFactory) => { normalModuleFactory.hooks.resolve.tap("irrelevant", (toBeResolved) => { + const isSassDependency = toBeResolved.request.endsWith(".scss"); const isLocalDependency = toBeResolved.request.startsWith("."); const isDependencyOfDependency = toBeResolved.context.includes("node_modules"); @@ -19,7 +20,7 @@ class ProtectFromImportingNonDependencies { const dependencyName = getDependencyName(toBeResolved.request); const dependencyWeAreInterested = - !isLocalDependency && !isDependencyOfDependency && dependencyName; + !isSassDependency && !isLocalDependency && !isDependencyOfDependency && dependencyName; if (dependencyWeAreInterested) { nodeModulesToBeResolved.add(dependencyName); diff --git a/packages/open-lens/src/renderer/index.ts b/packages/open-lens/src/renderer/index.ts index 64c5810574..2446390d29 100644 --- a/packages/open-lens/src/renderer/index.ts +++ b/packages/open-lens/src/renderer/index.ts @@ -1,4 +1,5 @@ import "@k8slens/core/styles"; +import "@k8slens/tooltip/dist/index.css"; import { runInAction } from "mobx"; import { rendererExtensionApi as Renderer, diff --git a/packages/ui-components/tooltip/.eslintrc.json b/packages/ui-components/tooltip/.eslintrc.json new file mode 100644 index 0000000000..b15115cb69 --- /dev/null +++ b/packages/ui-components/tooltip/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "@k8slens/eslint-config/eslint", + "parserOptions": { + "project": "./tsconfig.json" + } +} diff --git a/packages/ui-components/tooltip/.prettierrc b/packages/ui-components/tooltip/.prettierrc new file mode 100644 index 0000000000..edd47b479e --- /dev/null +++ b/packages/ui-components/tooltip/.prettierrc @@ -0,0 +1 @@ +"@k8slens/eslint-config/prettier" diff --git a/packages/ui-components/tooltip/.swcrc b/packages/ui-components/tooltip/.swcrc new file mode 100644 index 0000000000..4dd5c11a89 --- /dev/null +++ b/packages/ui-components/tooltip/.swcrc @@ -0,0 +1,19 @@ +{ + "module": { + "type": "commonjs" + }, + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": true, + "decorators": true, + "dynamicImport": false + }, + "transform": { + "legacyDecorator": true, + "decoratorMetadata": true + }, + "target": "es2019" + } +} + diff --git a/packages/ui-components/tooltip/README.md b/packages/ui-components/tooltip/README.md new file mode 100644 index 0000000000..3dc391655e --- /dev/null +++ b/packages/ui-components/tooltip/README.md @@ -0,0 +1,20 @@ +# @k8slens/tooltip + +This package contains stuff related to creating Lens-applications. + +# Usage + +```bash +$ npm install @k8slens/tooltip +``` + +```typescript +import { Tooltip, TooltipPosition } from "@k8slens/tooltip"; +import { withTooltip } from "@k8slens/tooltip"; + +import type { TooltipProps } from "@k8slens/tooltip"; +import type { TooltipDecoratorProps } from "@k8slens/tooltip"; + +``` + +## Extendability diff --git a/packages/ui-components/tooltip/index.ts b/packages/ui-components/tooltip/index.ts new file mode 100644 index 0000000000..cad2ff6ec9 --- /dev/null +++ b/packages/ui-components/tooltip/index.ts @@ -0,0 +1,2 @@ +export * from "./src/tooltip"; +export * from "./src/withTooltip"; \ No newline at end of file diff --git a/packages/ui-components/tooltip/jest.config.js b/packages/ui-components/tooltip/jest.config.js new file mode 100644 index 0000000000..38d54ab7b6 --- /dev/null +++ b/packages/ui-components/tooltip/jest.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; diff --git a/packages/ui-components/tooltip/package.json b/packages/ui-components/tooltip/package.json new file mode 100644 index 0000000000..ebe465a1e2 --- /dev/null +++ b/packages/ui-components/tooltip/package.json @@ -0,0 +1,50 @@ +{ + "name": "@k8slens/tooltip", + "private": false, + "version": "1.0.0-alpha.0", + "description": "Highly extendable tooltip in the Lens.", + "type": "commonjs", + "files": [ + "dist" + ], + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lensapp/lens.git" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "test:unit": "jest --coverage --runInBand", + "lint": "lens-lint", + "lint:fix": "lens-lint --fix" + }, + "peerDependencies": { + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/utilities": "^1.0.0-alpha.1", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/fp": "^15.1.2", + "auto-bind": "^4.0.0", + "lodash": "^4.17.21", + "mobx": "^6.8.0", + "mobx-react": "^7.6.0", + "react": "^17.0.2", + "react-dom": "^17.0.2" + }, + "devDependencies": { + "@async-fn/jest": "^1.6.4", + "@k8slens/eslint-config": "6.5.0-alpha.1", + "@k8slens/react-testing-library-discovery": "^1.0.0-alpha.0" + } +} diff --git a/packages/core/src/renderer/components/tooltip/__snapshots__/tooltip.test.tsx.snap b/packages/ui-components/tooltip/src/__snapshots__/tooltip.test.tsx.snap similarity index 100% rename from packages/core/src/renderer/components/tooltip/__snapshots__/tooltip.test.tsx.snap rename to packages/ui-components/tooltip/src/__snapshots__/tooltip.test.tsx.snap diff --git a/packages/core/src/renderer/components/tooltip/index.ts b/packages/ui-components/tooltip/src/index.ts similarity index 100% rename from packages/core/src/renderer/components/tooltip/index.ts rename to packages/ui-components/tooltip/src/index.ts diff --git a/packages/core/src/renderer/components/tooltip/tooltip.scss b/packages/ui-components/tooltip/src/tooltip.scss similarity index 75% rename from packages/core/src/renderer/components/tooltip/tooltip.scss rename to packages/ui-components/tooltip/src/tooltip.scss index d90d91f52e..28db216a4e 100644 --- a/packages/core/src/renderer/components/tooltip/tooltip.scss +++ b/packages/ui-components/tooltip/src/tooltip.scss @@ -5,20 +5,14 @@ .Tooltip { - --bgc: var(--mainBackground); - --radius: #{$radius}; - --color: var(--textColorAccent); - --border: 1px solid var(--borderColor); - // use positioning relative to viewport (window) - // https://developer.mozilla.org/en-US/docs/Web/CSS/position position: fixed; margin: 0 !important; - background: var(--bgc); + background: var(--mainBackground); font-size: small; font-weight: normal; - border-radius: var(--radius); - color: var(--color); + border-radius: 3px; + color: var(--textColorAccent); white-space: normal; padding: .5em; text-align: center; @@ -55,7 +49,7 @@ } &.small { - font-size: $font-size-small; + font-size: 12px; } &.warning { @@ -68,7 +62,6 @@ grid-template-columns: max-content 1fr; grid-template-rows: repeat(2, 1fr); - // backward compatibility: skips element in DOM to consider only children in grid-flow > .flex { display: contents; } @@ -79,7 +72,7 @@ } .title { - grid-column: 1 / 3; // merge + grid-column: 1 / 3; color: var(--textColorAccent); text-align: center; font-weight: bold; diff --git a/packages/core/src/renderer/components/tooltip/tooltip.test.tsx b/packages/ui-components/tooltip/src/tooltip.test.tsx similarity index 66% rename from packages/core/src/renderer/components/tooltip/tooltip.test.tsx rename to packages/ui-components/tooltip/src/tooltip.test.tsx index 6c8331be8a..f57f1c2ff3 100644 --- a/packages/core/src/renderer/components/tooltip/tooltip.test.tsx +++ b/packages/ui-components/tooltip/src/tooltip.test.tsx @@ -15,7 +15,7 @@ describe("", () => { beforeEach(() => { requestAnimationFrameSpy = jest.spyOn(window, "requestAnimationFrame"); - requestAnimationFrameSpy.mockImplementation(cb => { + requestAnimationFrameSpy.mockImplementation((cb) => { cb(0); return 0; @@ -26,31 +26,28 @@ describe("", () => { requestAnimationFrameSpy.mockRestore(); }); - - it("does not render to DOM if not visibile", () => { - const result = render(( + it("does not render to DOM if not visible", () => { + const result = render( <> - I am a tooltip + + I am a tooltip +
Target Text
- - )); + , + ); expect(result.baseElement).toMatchSnapshot(); }); it("renders to DOM when hovering over target", () => { - const result = render(( + const result = render( <> - + I am a tooltip
Target Text
- - )); + , + ); const target = result.baseElement.querySelector("#my-target"); @@ -60,20 +57,15 @@ describe("", () => { expect(result.baseElement).toMatchSnapshot(); }); - it("renders to DOM when forced to by visibile prop", () => { - const result = render(( + it("renders to DOM when forced to by visible prop", () => { + const result = render( <> - + I am a tooltip
Target Text
- - )); + , + ); expect(result.baseElement).toMatchSnapshot(); }); diff --git a/packages/core/src/renderer/components/tooltip/tooltip.tsx b/packages/ui-components/tooltip/src/tooltip.tsx similarity index 95% rename from packages/core/src/renderer/components/tooltip/tooltip.tsx rename to packages/ui-components/tooltip/src/tooltip.tsx index 5c2f512f2f..be590f8ceb 100644 --- a/packages/core/src/renderer/components/tooltip/tooltip.tsx +++ b/packages/ui-components/tooltip/src/tooltip.tsx @@ -55,8 +55,11 @@ export class Tooltip extends React.Component { static defaultProps = defaultProps as object; @observable.ref elem: HTMLDivElement | null = null; + @observable activePosition?: TooltipPosition; + @observable isVisible = false; + @observable isContentVisible = false; // animation manager constructor(props: TooltipProps) { @@ -95,7 +98,7 @@ export class Tooltip extends React.Component { @action protected onEnterTarget() { this.isVisible = true; - requestAnimationFrame(action(() => this.isContentVisible = true)); + requestAnimationFrame(action(() => (this.isContentVisible = true))); } @action @@ -134,7 +137,8 @@ export class Tooltip extends React.Component { // find proper position for (const pos of positions) { const { left, top, right, bottom } = this.getPosition(pos, selfBounds, targetBounds); - const fitsToWindow = left >= 0 && top >= 0 && right <= viewportWidth && bottom <= viewportHeight; + const fitsToWindow = + left >= 0 && top >= 0 && right <= viewportWidth && bottom <= viewportHeight; if (fitsToWindow) { this.activePosition = pos; @@ -224,12 +228,7 @@ export class Tooltip extends React.Component { formatter: !!formatters, }); const tooltip = ( -
this.elem = elem} - role="tooltip" - > +
(this.elem = elem)} role="tooltip"> {children}
); diff --git a/packages/core/src/renderer/components/tooltip/withTooltip.tsx b/packages/ui-components/tooltip/src/withTooltip.tsx similarity index 91% rename from packages/core/src/renderer/components/tooltip/withTooltip.tsx rename to packages/ui-components/tooltip/src/withTooltip.tsx index 533fbecf44..59a2e87bfa 100644 --- a/packages/core/src/renderer/components/tooltip/withTooltip.tsx +++ b/packages/ui-components/tooltip/src/withTooltip.tsx @@ -33,10 +33,7 @@ export function withTooltip( // TODO: Remove side-effect to allow deterministic unit testing const [defaultTooltipId] = useState(uniqueId("tooltip_target_")); - let { - id: targetId, - children: targetChildren, - } = props; + let { id: targetId, children: targetChildren } = props; const { tooltip, tooltipOverrideDisabled, @@ -56,16 +53,14 @@ export function withTooltip( targetId = tooltipProps.targetId; targetChildren = ( <> -
- {targetChildren} -
+
{targetChildren}
); } return ( - + {targetChildren} ); diff --git a/packages/ui-components/tooltip/tailwind.config.js b/packages/ui-components/tooltip/tailwind.config.js new file mode 100644 index 0000000000..59cf6201b3 --- /dev/null +++ b/packages/ui-components/tooltip/tailwind.config.js @@ -0,0 +1,30 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +const path = require('path'); + +module.exports = { + content: [ + path.join(__dirname, "src/**/*.tsx") + ], + darkMode: "class", + theme: { + fontFamily: { + sans: ["Roboto", "Helvetica", "Arial", "sans-serif"], + }, + extend: { + colors: { + textAccent: "var(--textColorAccent)", + textPrimary: "var(--textColorPrimary)", + textTertiary: "var(--textColorTertiary)", + textDimmed: "var(--textColorDimmed)", + }, + }, + }, + variants: { + extend: {}, + }, + plugins: [], +}; diff --git a/packages/ui-components/tooltip/tsconfig.json b/packages/ui-components/tooltip/tsconfig.json new file mode 100644 index 0000000000..9e140d79da --- /dev/null +++ b/packages/ui-components/tooltip/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@k8slens/typescript/config/base.json", + "include": ["**/*.ts", "**/*.tsx"], +} diff --git a/packages/ui-components/tooltip/webpack.config.js b/packages/ui-components/tooltip/webpack.config.js new file mode 100644 index 0000000000..1cda407f5a --- /dev/null +++ b/packages/ui-components/tooltip/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForReact;