From 67eaf80bf153c453c2e07cad8e89b820fdd229b1 Mon Sep 17 00:00:00 2001 From: Razvan Dinicut Date: Thu, 19 Sep 2019 15:03:19 +0200 Subject: [PATCH] add copy button to display field (#46) --- .babelrc | 11 - .storybook/src/3.components/display-field.tsx | 27 ++ babel.config.js | 8 + package-lock.json | 296 +++++++++++++----- package.json | 5 +- packages/display-field/package.json | 3 +- .../display-field/src/DisplayField.test.tsx | 20 +- packages/display-field/src/DisplayField.tsx | 80 +++-- packages/theme/src/theme.ts | 6 +- packages/utils/.babelrc | 35 +++ packages/utils/.gitignore | 21 ++ packages/utils/README.md | 9 + packages/utils/package.json | 63 ++++ packages/utils/rollup.config.js | 53 ++++ packages/utils/src/copy-to-clipboard.ts | 23 ++ packages/utils/src/index.ts | 7 + packages/utils/tsconfig.json | 39 +++ tests.config.js | 25 ++ 18 files changed, 620 insertions(+), 111 deletions(-) delete mode 100644 .babelrc create mode 100644 packages/utils/.babelrc create mode 100755 packages/utils/.gitignore create mode 100644 packages/utils/README.md create mode 100644 packages/utils/package.json create mode 100644 packages/utils/rollup.config.js create mode 100644 packages/utils/src/copy-to-clipboard.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/tsconfig.json diff --git a/.babelrc b/.babelrc deleted file mode 100644 index c216703..0000000 --- a/.babelrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - {"modules": false} - ], - "@babel/preset-react" - ], - - "plugins": ["babel-plugin-styled-components"] -} diff --git a/.storybook/src/3.components/display-field.tsx b/.storybook/src/3.components/display-field.tsx index 9344706..5a6ebfe 100644 --- a/.storybook/src/3.components/display-field.tsx +++ b/.storybook/src/3.components/display-field.tsx @@ -85,6 +85,33 @@ storiesOf("Components | Display Field", module) return ; }) + + .add("With Copy", () => { + const Comp = (props) => { + + return ( + + + + + + + + ); + } + + return ; + }) + .add("With Link and Label", () => { const Comp = (props) => { diff --git a/babel.config.js b/babel.config.js index 4434900..b2bb72e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -14,6 +14,14 @@ module.exports = { "@babel/preset-react" ], plugins: [ + [ + require.resolve('babel-plugin-module-resolver'), + { + alias: { + "@centrifuge/axis-utils": "./packages/utils/src" + } + } + ], [ "@babel/plugin-transform-modules-commonjs", { allowTopLevelThis: true } diff --git a/package-lock.json b/package-lock.json index fd25633..9155d68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1266,6 +1266,9 @@ "@centrifuge/axis-theme": { "version": "file:packages/theme" }, + "@centrifuge/axis-utils": { + "version": "file:packages/utils" + }, "@cnakazawa/watch": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", @@ -6572,9 +6575,9 @@ } }, "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.1.tgz", + "integrity": "sha512-1zSbbCuoIjafKZ3mblY5ikvAb0ODUbqBnFuUb7f6uLeQhhGJ0vEV4ntmtxKLT2WgXCO94E07BjunsIw1jOMPZw==", "dev": true }, "abbrev": { @@ -6600,9 +6603,9 @@ "dev": true }, "acorn-globals": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", - "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "requires": { "acorn": "^6.0.1", @@ -6610,9 +6613,9 @@ } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", "dev": true }, "address": { @@ -7076,9 +7079,9 @@ "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, "asynckit": { @@ -7559,6 +7562,19 @@ "babel-helper-is-void-0": "^0.4.3" } }, + "babel-plugin-module-resolver": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-3.2.0.tgz", + "integrity": "sha512-tjR0GvSndzPew/Iayf4uICWZqjBwnlMWjSx6brryfQ81F9rxBVqwDJtFCV8oOs0+vJeefK9TmdZtkIFdFe1UnA==", + "dev": true, + "requires": { + "find-babel-config": "^1.1.0", + "glob": "^7.1.2", + "pkg-up": "^2.0.0", + "reselect": "^3.0.1", + "resolve": "^1.4.0" + } + }, "babel-plugin-named-asset-import": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.3.tgz", @@ -9607,15 +9623,15 @@ } }, "cssom": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, "cssstyle": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", - "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, "requires": { "cssom": "0.3.x" @@ -9679,19 +9695,6 @@ "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", "whatwg-url": "^7.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } } }, "date-now": { @@ -10438,9 +10441,9 @@ "dev": true }, "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", "dev": true, "requires": { "esprima": "^3.1.3", @@ -10951,6 +10954,24 @@ "unpipe": "~1.0.0" } }, + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "dev": true, + "requires": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + } + } + }, "find-cache-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz", @@ -13108,6 +13129,12 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -13829,6 +13856,84 @@ "jest-mock": "^24.8.0", "jest-util": "^24.8.0", "jsdom": "^11.5.1" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } } }, "jest-environment-node": { @@ -14172,49 +14277,43 @@ "dev": true }, "jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-15.1.1.tgz", + "integrity": "sha512-cQZRBB33arrDAeCrAEWn1U3SvrvC8XysBua9Oqg1yWrsY/gYcusloJC3RZJXuY5eehSCmws8f2YeliCqGSkrtQ==", "dev": true, "requires": { "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", + "acorn": "^6.1.1", + "acorn-globals": "^4.3.2", "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", + "cssom": "^0.3.6", + "cssstyle": "^1.2.2", + "data-urls": "^1.1.0", "domexception": "^1.0.1", - "escodegen": "^1.9.1", + "escodegen": "^1.11.1", "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", - "parse5": "4.0.0", + "nwsapi": "^2.1.4", + "parse5": "5.1.0", "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", + "request": "^2.88.0", + "request-promise-native": "^1.0.7", + "saxes": "^3.1.9", "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", + "tough-cookie": "^3.0.1", "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^7.0.0", "xml-name-validator": "^3.0.0" }, "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true } } @@ -18095,6 +18194,18 @@ "request-promise-core": "1.1.2", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } } }, "require-directory": { @@ -18115,6 +18226,12 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz", + "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc=", + "dev": true + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -18452,6 +18569,15 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "dev": true, + "requires": { + "xmlchars": "^2.1.1" + } + }, "scheduler": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", @@ -19437,9 +19563,9 @@ "dev": true }, "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, "symbol.prototype.description": { @@ -19879,11 +20005,12 @@ "dev": true }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", "dev": true, "requires": { + "ip-regex": "^2.1.0", "psl": "^1.1.28", "punycode": "^2.1.1" } @@ -20374,6 +20501,17 @@ "browser-process-hrtime": "^0.1.2" } }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -20591,9 +20729,9 @@ "dev": true }, "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -20793,12 +20931,12 @@ } }, "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", + "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "^1.0.0" } }, "xml-name-validator": { @@ -20807,6 +20945,12 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index be57a39..b7c2edb 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "awesome-typescript-loader": "^5.2.1", "babel-jest": "^24.1.0", "babel-plugin-external-helpers": "^6.22.0", + "babel-plugin-module-resolver": "^3.2.0", "babel-plugin-styled-components": "^1.10.0", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-object-rest-spread": "^6.26.0", @@ -59,6 +60,7 @@ "glob-loader": "^0.3.0", "grommet": "^2.7.5", "jest": "^24.1.0", + "jsdom": "^15.1.1", "lerna": "^3.13.1", "react": "^16.8.3", "react-docgen-typescript-loader": "^3.1.0", @@ -127,6 +129,7 @@ "@centrifuge/axis-search-select": "file:packages/search-select", "@centrifuge/axis-multiple-select": "file:packages/multiple-select", "@centrifuge/axis-number-input": "file:packages/number-input", - "@centrifuge/axis-spinner": "file:packages/spinner" + "@centrifuge/axis-spinner": "file:packages/spinner", + "@centrifuge/axis-utils": "file:packages/utils" } } diff --git a/packages/display-field/package.json b/packages/display-field/package.json index bcb4322..93e0455 100644 --- a/packages/display-field/package.json +++ b/packages/display-field/package.json @@ -30,7 +30,8 @@ "grommet": "2.7.x", "react": ">= 16.6.1", "react-dom": ">= 16.6.1", - "styled-components": ">= 4.x" + "styled-components": ">= 4.x", + "@centrifuge/axis-utils": ">= 0.x" }, "devDependencies": { "@babel/core": "^7.2.2", diff --git a/packages/display-field/src/DisplayField.test.tsx b/packages/display-field/src/DisplayField.test.tsx index 5721f95..2d38401 100644 --- a/packages/display-field/src/DisplayField.test.tsx +++ b/packages/display-field/src/DisplayField.test.tsx @@ -3,7 +3,7 @@ import DisplayField from "./DisplayField"; import {mount} from 'enzyme'; import {Anchor, Paragraph} from "grommet"; -describe("Sample Component test", () => { +describe("Display field", () => { describe('Child rendering and interaction', () => { let wrapper; const value = 'some value we want to display' @@ -17,7 +17,7 @@ describe("Sample Component test", () => { }); it('should display the value in a paragraph',() => { - const p = wrapper.find(Paragraph); + const p = wrapper.find('p'); expect(p.length).toEqual(1); expect(p.text()).toEqual(value); }) @@ -54,5 +54,21 @@ describe("Sample Component test", () => { expect(anchor.prop('target')).toEqual('_blank'); expect(anchor.text()).toEqual(value); }) + + it('should display a copy icon and copy the value to clipboard', async () => { + wrapper.setProps({ + copy:true, + link: { + href:"http://example.com", + target:'_blank' + } + }) + const anchor = wrapper.find(Anchor); + expect(anchor.length).toEqual(2); + const copy = anchor.at(1); + copy.simulate('click'); + expect(await window.navigator.clipboard.readText()).toEqual(value); + + }) }); }); diff --git a/packages/display-field/src/DisplayField.tsx b/packages/display-field/src/DisplayField.tsx index a1af5db..ad512b3 100644 --- a/packages/display-field/src/DisplayField.tsx +++ b/packages/display-field/src/DisplayField.tsx @@ -1,7 +1,10 @@ import React from "react"; import styled, {ThemeProps as StyledThemeProps, withTheme} from "styled-components"; import {defaultProps, extendDefaultTheme} from "grommet/default-props"; -import {Anchor, AnchorProps, Box, BoxProps, Paragraph, Text, TextProps} from "grommet"; +import {Anchor, AnchorProps, Box, BoxProps, Text, TextProps} from "grommet"; +import {MarginType, PolymorphicType} from "grommet/utils"; +import {copyToClipboard} from "@centrifuge/axis-utils"; +import {Copy, Icon} from "grommet-icons"; // Define type for theme props interface ThemeProps { @@ -10,12 +13,19 @@ interface ThemeProps { labelText?: TextProps, anchor?: AnchorProps, extend?: (props) => string, + icons: { + copy: Icon, + margin?: MarginType, + size?: "small" | "medium" | "large" | "xlarge" | string; + } } } interface Props extends StyledThemeProps { value: string, + as?: PolymorphicType; link?: string | AnchorProps, + copy?: boolean, label?: string, } @@ -24,23 +34,28 @@ const DisplayFieldBox = styled(Box)` & { padding: 2px 0px; // Force height on display field when value is empty - p { + .display_field_text { overflow: hidden; + display: block; white-space: nowrap; text-overflow: ellipsis; } - - a, a: hover { - text-decoration: none; - } - - p:after { + .display_field_text:after { content: ''; display: inline-block; } - + a,a:hover { + text-decoration: none; + } + a.display_field_anchor { + width: 100%; + } + a.icon_anchor { + svg { + vertical-align: middle; + } + } } - ${props => props.theme.displayField && props.theme.displayField.extend} `; @@ -55,35 +70,58 @@ export const DisplayField: React.FunctionComponent = ( value, link, label, + as = 'p', + copy, theme } ) => { - const {displayField: {labelBox, labelText, anchor}} = theme; + const { + displayField: { + labelBox, + labelText, + anchor, + icons + } + } = theme; const WithLink = ({link, children}) => { - return link ? + return link ? {children} : children; } const WithLabel = ({label, children}) => { return label ? - {label} + {label} {children} : children } + const WithCopyIcon = ({children}) => { + return copy ? + {children} + copyToClipboard(value)} title={'Copy to clipboard'}> + + + : children + } + return ( - - - {value} - - + + + { + copyToClipboard(value) + }}> + {value} + + + + ); @@ -98,8 +136,12 @@ export const defaultThemeProps: ThemeProps = { color: 'light-4' }, }, - anchor:{ + anchor: { color: 'brand' + }, + icons: { + copy: Copy, + size: 'small', } } }; diff --git a/packages/theme/src/theme.ts b/packages/theme/src/theme.ts index a49c8d0..52104b1 100644 --- a/packages/theme/src/theme.ts +++ b/packages/theme/src/theme.ts @@ -2,7 +2,7 @@ import { css } from "styled-components"; import { generate } from "grommet/themes"; import {Button, Select} from "grommet"; import { deepMerge } from "grommet/utils/object"; -import { Close, FormClose,Menu, User } from "grommet-icons"; +import { Close, FormClose,Menu, User,Copy, Clone } from "grommet-icons"; /* REUSED VARIABLES @@ -353,6 +353,10 @@ export const axisThemeConfig = deepMerge(base, { // Supports all Anchor props. color: 'brand', }, + icons: { + copy: Clone, + size: '18px', + }, extend: undefined, }, diff --git a/packages/utils/.babelrc b/packages/utils/.babelrc new file mode 100644 index 0000000..4953873 --- /dev/null +++ b/packages/utils/.babelrc @@ -0,0 +1,35 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "modules": false + } + ], + "@babel/preset-react", + "@babel/preset-typescript", + + ], + "plugins": [ + "transform-class-properties", + "babel-plugin-styled-components" + ], + "env": { + "test": { + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "entry" + } + ], + "@babel/preset-typescript", + "@babel/preset-react", + ], + "plugins": [ + "transform-class-properties", + "babel-plugin-styled-components" + ] + } + } +} diff --git a/packages/utils/.gitignore b/packages/utils/.gitignore new file mode 100755 index 0000000..272339c --- /dev/null +++ b/packages/utils/.gitignore @@ -0,0 +1,21 @@ +# dependency cache +node_modules + +# build +static/bundle.js +storybook-static +build/ +dist/ + +# logs +npm-debug.log + +# editor config +.idea +*.iml + +# OS files +*.DS_Store + +# code coverage +coverage diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 0000000..2dec693 --- /dev/null +++ b/packages/utils/README.md @@ -0,0 +1,9 @@ +# `Sample Component` + +> TODO: description + +## Usage + +``` +// TODO: DEMONSTRATE API +``` diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..07bf847 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,63 @@ +{ + "name": "@centrifuge/axis-utils", + "version": "0.3.1", + "description": "Utils functions", + "author": "razvan ", + "homepage": "https://github.com/centrifuge/axis/tree/master/packages/axis-sample-component#readme", + "license": "ISC", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "source": "src/index.ts", + "files": [ + "dist", + "src" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/centrifuge/axis.git" + }, + "scripts": { + "build": "rollup -c", + "test": "jest --no-cache --coverage --verbose" + }, + "bugs": { + "url": "https://github.com/centrifuge/axis/issues" + }, + "peerDependencies": { + "grommet": "2.7.x", + "react": ">= 16.6.1", + "react-dom": ">= 16.6.1", + "styled-components": ">= 4.x" + }, + "devDependencies": { + "@babel/core": "^7.2.2", + "@babel/plugin-transform-typescript": "^7.5.2", + "@babel/preset-env": "^7.5.4", + "@babel/runtime": "^7.3.1", + "@types/react": "^16.8.23", + "@types/react-dom": "^16.8.4", + "@types/styled-components": "^4.1.18", + "babel-jest": "^24.1.0", + "babel-plugin-external-helpers": "^6.22.0", + "babel-plugin-styled-components": "^1.10.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-preset-react-app": "^7.0.2", + "enzyme": "^3.8.0", + "enzyme-adapter-react-16": "^1.9.1", + "jest": "^24.1.0", + "prop-types": "^15.7.2", + "rollup": "^1.1.2", + "rollup-plugin-babel": "^4.3.2", + "rollup-plugin-filesize": "^6.0.1", + "rollup-plugin-node-resolve": "^4.0.0", + "rollup-plugin-peer-deps-external": "^2.2.0", + "rollup-plugin-progress": "^1.0.0", + "rollup-plugin-url": "^2.2.0", + "typescript": "^3.5.2" + }, + "gitHead": "ef53db97aa8cc0b402b3544a731dc10c9ff12641" +} diff --git a/packages/utils/rollup.config.js b/packages/utils/rollup.config.js new file mode 100644 index 0000000..15d3932 --- /dev/null +++ b/packages/utils/rollup.config.js @@ -0,0 +1,53 @@ +import babel from "rollup-plugin-babel"; +import filesize from "rollup-plugin-filesize"; +import resolve from "rollup-plugin-node-resolve"; +import progress from "rollup-plugin-progress"; +import peerDepsExternal from "rollup-plugin-peer-deps-external"; +import url from "rollup-plugin-url"; +import { DEFAULT_EXTENSIONS } from '@babel/core'; + +const extensions = [ + ...DEFAULT_EXTENSIONS, + '.ts', + '.tsx' +] + +export default { + input: "src/index.ts", + output: [ + { + exports: "named", + file: "dist/index.cjs.js", + format: "cjs", + sourcemap: true + }, + { + exports: "named", + file: "dist/index.esm.js", + format: "es", + sourcemap: true + } + ], + plugins: [ + + peerDepsExternal(), + progress(), + resolve({ + extensions + }), + url({ + include: ["**/*.woff", "**/*.woff2"], + // setting infinite limit will ensure that the files + // are always bundled with the code, not copied to /dist + limit: Infinity + }), + babel({ + babelrc: true, + extensions + + }), + filesize() + ] +}; + + diff --git a/packages/utils/src/copy-to-clipboard.ts b/packages/utils/src/copy-to-clipboard.ts new file mode 100644 index 0000000..0a36c60 --- /dev/null +++ b/packages/utils/src/copy-to-clipboard.ts @@ -0,0 +1,23 @@ +export const copyToClipboard = (value: string): Promise => { + if (!document || !window) throw new Error('this only works in the Browser') + // if navigator and clipboard api exists + if (window.navigator && window.navigator.clipboard) { + return window.navigator.clipboard.writeText(value); + } + + return new Promise((resolve, reject) => { + try { + let textField = document.createElement('textarea') + textField.innerText = value + document.body.appendChild(textField) + textField.select() + document.execCommand('copy') + textField.remove() + resolve(value); + } catch (e) { + console.log(e) + reject(e); + } + }) +}; + diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 0000000..c8054a2 --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,7 @@ +import {copyToClipboard} from './copy-to-clipboard' + +export { + copyToClipboard +} + + diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 0000000..d21dd26 --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,39 @@ +{ + "compilerOptions": { + "module": "esnext", + "noImplicitAny": false, + "removeComments": true, + "noLib": false, + "allowSyntheticDefaultImports": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es6", + "sourceMap": true, + "outDir": "./dist", + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": true, + "jsx": "preserve", + "isolatedModules": false, + "strictPropertyInitialization": false, + "lib": [ + "dom", + "dom.iterable", + "esnext" + ] + }, + "exclude": [ + "node_modules", + "build", + "scripts", + "acceptance-tests", + "webpack", + "jest", + "src/setupTests.ts" + ] +} diff --git a/tests.config.js b/tests.config.js index 36db575..6d17900 100644 --- a/tests.config.js +++ b/tests.config.js @@ -1,6 +1,31 @@ import { configure } from "enzyme"; import Adapter from "enzyme-adapter-react-16"; configure({ adapter: new Adapter() }); +import '@babel/polyfill'; +let clipboard = '' // polyfill functions +const prevNav = navigator; + window.scrollTo = () => {} +Object.defineProperty(window, 'navigator', { + get: function() { + return { + ...prevNav, + clipboard: { + writeText:(data) => { + return new Promise((resolve)=>{ + clipboard = data; + resolve() + }) + }, + readText:() =>{ + return new Promise((resolve)=>{ + resolve(clipboard) + }) + } + } + }; + }, +}); +