From f7ee745ddb99790a5ba4bbf073cb3c9f7df00d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B0=D0=B5=D0=B2=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= Date: Fri, 22 Jul 2022 18:46:12 +0300 Subject: [PATCH 1/4] add @storybook/addon-knobs --- .storybook/main.js | 12 +- package-lock.json | 274 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 286 insertions(+), 1 deletion(-) diff --git a/.storybook/main.js b/.storybook/main.js index bb278cf9..e657c387 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,6 +1,16 @@ module.exports = { stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: ['@storybook/preset-scss', '@storybook/addon-essentials'], + addons: [ + {name: '@storybook/preset-scss'}, + {name: '@storybook/addon-knobs'}, + { + name: '@storybook/addon-essentials', + options: { + controls: false, + actions: false, + }, + }, + ], typescript: { check: true, checkOptions: {}, diff --git a/package-lock.json b/package-lock.json index 0d06e7ad..d3e52a37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2364,6 +2364,106 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true }, + "@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "dev": true, + "requires": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + }, + "@emotion/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz", + "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5", + "@emotion/cache": "^10.0.27", + "@emotion/css": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + } + }, + "@emotion/css": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz", + "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==", + "dev": true, + "requires": { + "@emotion/serialize": "^0.11.15", + "@emotion/utils": "0.11.3", + "babel-plugin-emotion": "^10.0.27" + } + }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "dev": true + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "dev": true + }, + "@emotion/serialize": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", + "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", + "dev": true, + "requires": { + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/unitless": "0.7.5", + "@emotion/utils": "0.11.3", + "csstype": "^2.5.7" + }, + "dependencies": { + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==", + "dev": true + } + } + }, + "@emotion/sheet": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", + "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==", + "dev": true + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", + "dev": true + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "dev": true + }, + "@emotion/utils": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", + "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==", + "dev": true + }, + "@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", + "dev": true + }, "@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -4297,6 +4397,33 @@ "ts-dedent": "^2.0.0" } }, + "@storybook/addon-knobs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-knobs/-/addon-knobs-6.4.0.tgz", + "integrity": "sha512-DiH1/5e2AFHoHrncl1qLu18ZHPHzRMMPvOLFz8AWvvmc+VCqTdIaE+tdxKr3e8rYylKllibgvDOzrLjfTNjF+Q==", + "dev": true, + "requires": { + "copy-to-clipboard": "^3.3.1", + "core-js": "^3.8.2", + "escape-html": "^1.0.3", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.20", + "prop-types": "^15.7.2", + "qs": "^6.10.0", + "react-colorful": "^5.1.2", + "react-lifecycles-compat": "^3.0.4", + "react-select": "^3.2.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, "@storybook/addon-measure": { "version": "6.5.9", "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.5.9.tgz", @@ -8693,6 +8820,82 @@ "object.assign": "^4.1.0" } }, + "babel-plugin-emotion": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", + "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/serialize": "^0.11.16", + "babel-plugin-macros": "^2.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^1.0.5", + "find-root": "^1.1.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, "babel-plugin-extract-import-names": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", @@ -8869,6 +9072,12 @@ } } }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", + "dev": true + }, "babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -11632,6 +11841,16 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -13133,6 +13352,12 @@ } } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -21632,6 +21857,12 @@ "prop-types": "^15.6.2" } }, + "react-colorful": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", + "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", + "dev": true + }, "react-copy-to-clipboard": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz", @@ -21726,6 +21957,15 @@ "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==", "dev": true }, + "react-input-autosize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz", + "integrity": "sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==", + "dev": true, + "requires": { + "prop-types": "^15.5.8" + } + }, "react-inspector": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", @@ -21743,6 +21983,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", + "dev": true + }, "react-popper": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", @@ -21759,6 +22005,22 @@ "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", "dev": true }, + "react-select": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-3.2.0.tgz", + "integrity": "sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/cache": "^10.0.9", + "@emotion/core": "^10.0.9", + "@emotion/css": "^10.0.9", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.0", + "react-input-autosize": "^3.0.0", + "react-transition-group": "^4.3.0" + } + }, "react-sortable-hoc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz", @@ -21783,6 +22045,18 @@ "refractor": "^3.6.0" } }, + "react-transition-group": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, "react-virtualized-auto-sizer": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.6.tgz", diff --git a/package.json b/package.json index b4d2bf62..99eb1f18 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "devDependencies": { "@storybook/addon-essentials": "^6.5.9", + "@storybook/addon-knobs": "^6.4.0", "@storybook/preset-scss": "^1.0.3", "@storybook/react": "^6.5.9", "@types/jest": "^28.1.3", From 04c18b13c95337c010ac9559afe288ecdcd91ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B0=D0=B5=D0=B2=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= Date: Fri, 22 Jul 2022 18:47:40 +0300 Subject: [PATCH 2/4] fix Yagr Line story --- src/plugins/yagr/__stories__/Yagr.stories.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/yagr/__stories__/Yagr.stories.tsx b/src/plugins/yagr/__stories__/Yagr.stories.tsx index 125535db..7a7a81a9 100644 --- a/src/plugins/yagr/__stories__/Yagr.stories.tsx +++ b/src/plugins/yagr/__stories__/Yagr.stories.tsx @@ -12,13 +12,12 @@ export default { component: ChartKit, } as Meta; -settings.set({plugins: [YagrPlugin]}); - const Template: Story = () => { const [shown, setShown] = React.useState(false); const chartkitRef = React.useRef(); if (!shown) { + settings.set({plugins: [YagrPlugin]}); return ; } From fd0b376e88d298073e32cd69c1bc7201183ee1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B0=D0=B5=D0=B2=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= Date: Fri, 22 Jul 2022 18:48:05 +0300 Subject: [PATCH 3/4] add indicator plugin --- src/constants/common.ts | 2 + src/constants/index.ts | 1 + src/i18n/keysets/en.json | 1 + src/i18n/keysets/ru.json | 1 + src/plugins/index.ts | 2 + .../__stories__/Indicator.stories.tsx | 63 ++++++++++++++++++ src/plugins/indicator/index.ts | 7 ++ .../indicator/renderer/IndicatorItem.tsx | 35 ++++++++++ .../indicator/renderer/IndicatorWidget.scss | 66 +++++++++++++++++++ .../indicator/renderer/IndicatorWidget.tsx | 52 +++++++++++++++ src/plugins/indicator/types.ts | 24 +++++++ src/types/index.ts | 3 + src/types/widget.ts | 5 ++ 13 files changed, 262 insertions(+) create mode 100644 src/constants/common.ts create mode 100644 src/constants/index.ts create mode 100644 src/plugins/indicator/__stories__/Indicator.stories.tsx create mode 100644 src/plugins/indicator/index.ts create mode 100644 src/plugins/indicator/renderer/IndicatorItem.tsx create mode 100644 src/plugins/indicator/renderer/IndicatorWidget.scss create mode 100644 src/plugins/indicator/renderer/IndicatorWidget.tsx create mode 100644 src/plugins/indicator/types.ts diff --git a/src/constants/common.ts b/src/constants/common.ts new file mode 100644 index 00000000..b19578da --- /dev/null +++ b/src/constants/common.ts @@ -0,0 +1,2 @@ +// This css class should be added for DOM element for correct calculation of scrollHeight +export const CHARTKIT_SCROLLABLE_NODE_CLASSNAME = 'chartkit-scrollable-node'; diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 00000000..fe0e0e5e --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1 @@ +export {CHARTKIT_SCROLLABLE_NODE_CLASSNAME} from './common'; diff --git a/src/i18n/keysets/en.json b/src/i18n/keysets/en.json index 1675a4c4..60a607f2 100644 --- a/src/i18n/keysets/en.json +++ b/src/i18n/keysets/en.json @@ -4,6 +4,7 @@ "tooltip-rest": "Rest" }, "error": { + "label_no-data": "No data", "label_unknown-plugin": "Unknown plugin type \"{{type}}\"", "label_unknown-error": "Unknown error" } diff --git a/src/i18n/keysets/ru.json b/src/i18n/keysets/ru.json index a3f0f8cd..2426b641 100644 --- a/src/i18n/keysets/ru.json +++ b/src/i18n/keysets/ru.json @@ -4,6 +4,7 @@ "tooltip-rest": "Остальные" }, "error": { + "label_no-data": "Нет данных", "label_unknown-plugin": "Неизвестный тип плагина \"{{type}}\"", "label_unknown-error": "Неизвестная ошибка" } diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 45a65f29..d4ba5198 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -1,2 +1,4 @@ export {YagrPlugin} from './yagr'; export type {YagrWidgetData, YagrWidgetProps} from './yagr/types'; +export {IndicatorPlugin} from './indicator'; +export type {IndicatorWidgetData, IndicatorWidgetProps} from './indicator/types'; diff --git a/src/plugins/indicator/__stories__/Indicator.stories.tsx b/src/plugins/indicator/__stories__/Indicator.stories.tsx new file mode 100644 index 00000000..8d0a578e --- /dev/null +++ b/src/plugins/indicator/__stories__/Indicator.stories.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import {Meta, Story} from '@storybook/react'; +import {withKnobs, boolean, color as colorKnob, radios, text} from '@storybook/addon-knobs'; +import {cloneDeep} from 'lodash'; +import {Button} from '@yandex-cloud/uikit'; +import {settings} from '../../../libs'; +import {ChartKit} from '../../../components/ChartKit'; +import type {ChartKitRef} from '../../../types'; +import {IndicatorPlugin} from '../'; +import type {IndicatorWidgetData, IndicatorWidgetDataItem} from '../types'; + +const data: IndicatorWidgetData = { + data: [ + { + content: { + current: { + value: 1539577973, + }, + }, + }, + ], +}; + +const Template: Story = () => { + const [shown, setShown] = React.useState(false); + const chartkitRef = React.useRef(); + const color = colorKnob('color', '#4da2f1'); + const size = radios( + 'size', + {s: 's', m: 'm', l: 'l', xl: 'xl'}, + 'm', + ); + const title = text('title', 'Value title'); + const nowrap = boolean('nowrap', false); + const resultData = cloneDeep(data); + + if (resultData.data) { + resultData.data[0].size = size; + resultData.data[0].color = color; + resultData.data[0].title = title; + resultData.data[0].nowrap = nowrap; + } + + if (!shown) { + settings.set({plugins: [IndicatorPlugin]}); + return ; + } + + return ( +
+ +
+ ); +}; + +export const Showcase = Template.bind({}); + +const meta: Meta = { + title: 'Plugins/Indicator', + decorators: [withKnobs], +}; + +export default meta; diff --git a/src/plugins/indicator/index.ts b/src/plugins/indicator/index.ts new file mode 100644 index 00000000..e826e9ff --- /dev/null +++ b/src/plugins/indicator/index.ts @@ -0,0 +1,7 @@ +import React from 'react'; +import {ChartKitPlugin} from '../../types'; + +export const IndicatorPlugin: ChartKitPlugin = { + type: 'indicator', + renderer: React.lazy(() => import('./renderer/IndicatorWidget')), +}; diff --git a/src/plugins/indicator/renderer/IndicatorItem.tsx b/src/plugins/indicator/renderer/IndicatorItem.tsx new file mode 100644 index 00000000..f5f296f6 --- /dev/null +++ b/src/plugins/indicator/renderer/IndicatorItem.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import block from 'bem-cn-lite'; +import type {IndicatorWidgetProps, IndicatorWidgetDataItem} from '../types'; + +const b = block('chartkit-indicator'); + +export const IndicatorItem = ( + props: IndicatorWidgetDataItem & { + defaultColor?: string; + formatNumber?: IndicatorWidgetProps['formatNumber']; + }, +) => { + const {formatNumber, content, color, defaultColor, size, title, nowrap} = props; + const mods = {size, nowrap}; + const style: React.CSSProperties = {color: color || defaultColor}; + + let value = content.current.value; + + if (formatNumber && typeof value === 'number') { + value = formatNumber(value, content.current); + } + + return ( +
+ {title && ( +
+ {title} +
+ )} +
+ {value} +
+
+ ); +}; diff --git a/src/plugins/indicator/renderer/IndicatorWidget.scss b/src/plugins/indicator/renderer/IndicatorWidget.scss new file mode 100644 index 00000000..e0df3635 --- /dev/null +++ b/src/plugins/indicator/renderer/IndicatorWidget.scss @@ -0,0 +1,66 @@ +.chartkit-indicator { + $class: &; + + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + + &__content { + width: 100%; + overflow: auto; + } + + &__item { + padding: 15px; + font-size: inherit; + box-sizing: border-box; + + &_nowrap { + #{$class}__item-title { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + } + + &_size_s #{$class}__item-title { + font-size: 13px; + } + + &_size_s #{$class}__item-value { + font-size: 24px; + } + + &_size_l #{$class}__item-title { + font-size: 20px; + } + + &_size_l #{$class}__item-value { + font-size: 64px; + } + + &_size_xl #{$class}__item-title { + font-size: 24px; + } + + &_size_xl #{$class}__item-value { + font-size: 80px; + } + } + + &__item-title { + font-weight: 500; + line-height: 1.2; + color: var(--yc-color-text-primary); + font-size: 16px; + padding-bottom: 0.125em; + } + + &__item-value { + font-weight: 500; + line-height: 1.2; + font-size: 48px; + white-space: nowrap; + } +} diff --git a/src/plugins/indicator/renderer/IndicatorWidget.tsx b/src/plugins/indicator/renderer/IndicatorWidget.tsx new file mode 100644 index 00000000..81ecd47a --- /dev/null +++ b/src/plugins/indicator/renderer/IndicatorWidget.tsx @@ -0,0 +1,52 @@ +import React from 'react'; +import block from 'bem-cn-lite'; +import {i18n} from '../../../i18n'; +import {CHARTKIT_ERROR_CODE, ChartKitError} from '../../../libs'; +import {CHARTKIT_SCROLLABLE_NODE_CLASSNAME} from '../../../constants'; +import type {ChartKitWidgetRef} from '../../../types'; +import type {IndicatorWidgetProps} from '../types'; +import {IndicatorItem} from './IndicatorItem'; + +import './IndicatorWidget.scss'; + +const b = block('chartkit-indicator'); + +const IndicatorWidget = React.forwardRef( + // _ref needs to avoid this warning: + // "forwardRef render functions accept exactly two parameters: props and ref" + (props, _ref) => { + const { + onLoad, + formatNumber, + data: {data, defaultColor}, + } = props; + + React.useEffect(() => { + onLoad?.(); + }, []); + + if (!data) { + throw new ChartKitError({ + code: CHARTKIT_ERROR_CODE.NO_DATA, + message: i18n('error', 'label_no-data'), + }); + } + + return ( +
+
+ {data.map((item, index) => ( + + ))} +
+
+ ); + }, +); + +export default IndicatorWidget; diff --git a/src/plugins/indicator/types.ts b/src/plugins/indicator/types.ts new file mode 100644 index 00000000..e58308d1 --- /dev/null +++ b/src/plugins/indicator/types.ts @@ -0,0 +1,24 @@ +import type {ChartKitFormatNumber} from '../../types'; + +export type IndicatorWidgetDataItem = { + content: { + current: { + value: string | number; + } & Record; + }; + color?: string; + size?: 's' | 'm' | 'l' | 'xl'; + title?: string; + nowrap?: boolean; +}; + +export type IndicatorWidgetData = { + data?: IndicatorWidgetDataItem[]; + defaultColor?: string; +}; + +export type IndicatorWidgetProps = { + data: IndicatorWidgetData; + onLoad?: () => void; + formatNumber?: ChartKitFormatNumber; +}; diff --git a/src/types/index.ts b/src/types/index.ts index 5bc6261e..2e854e7d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -19,12 +19,15 @@ export type ChartKitOnLoadData = { export type ChartKitOnError = (data: {error: any}) => void; +export type ChartKitFormatNumber = (value: number, options?: unknown) => string; + export type ChartKitProps = { type: T; data: ChartkitWidget[T]['data']; id?: string; onLoad?: (data?: ChartKitOnLoadData) => void; onError?: ChartKitOnError; + formatNumber?: ChartKitFormatNumber; } & {[key in keyof Omit]: ChartkitWidget[T][key]}; export type ChartKitPlugin = { diff --git a/src/types/widget.ts b/src/types/widget.ts index 8bc41e82..5b5dcbe9 100644 --- a/src/types/widget.ts +++ b/src/types/widget.ts @@ -1,9 +1,14 @@ import type Yagr from 'yagr'; import type {YagrWidgetData} from '../plugins/yagr/types'; +import type {IndicatorWidgetData} from '../plugins/indicator/types'; export interface ChartkitWidget { yagr: { data: YagrWidgetData; widget: Yagr; }; + indicator: { + data: IndicatorWidgetData; + widget: never; + }; } From be6bf0c9c5912896a6ea3fc05eca138501524c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B0=D0=B5=D0=B2=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= Date: Mon, 25 Jul 2022 14:38:22 +0300 Subject: [PATCH 4/4] marginy review fixes --- src/plugins/indicator/renderer/IndicatorWidget.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/indicator/renderer/IndicatorWidget.tsx b/src/plugins/indicator/renderer/IndicatorWidget.tsx index 81ecd47a..800b6f1a 100644 --- a/src/plugins/indicator/renderer/IndicatorWidget.tsx +++ b/src/plugins/indicator/renderer/IndicatorWidget.tsx @@ -12,7 +12,7 @@ import './IndicatorWidget.scss'; const b = block('chartkit-indicator'); const IndicatorWidget = React.forwardRef( - // _ref needs to avoid this warning: + // _ref needs to avoid this React warning: // "forwardRef render functions accept exactly two parameters: props and ref" (props, _ref) => { const {