diff --git a/.stylelintrc.json b/.stylelintrc.json index d106f90a6..4c74be1d3 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,33 +1,16 @@ { - "extends": "stylelint-config-standard", + "extends": "stylelint-config-standard-scss", "rules": { - "declaration-block-no-redundant-longhand-properties": null, - "shorthand-property-no-redundant-values": null, + "scss/at-function-pattern": null, + "scss/dollar-variable-pattern": null, "selector-class-pattern": null, + "scss/at-mixin-pattern": null, + "comment-empty-line-before": null, + "scss/double-slash-comment-empty-line-before": null, "custom-property-pattern": null, "selector-id-pattern": null, - "keyframes-name-pattern": null, - "property-no-vendor-prefix": null, - "value-no-vendor-prefix": null, "number-max-precision": null, - "color-function-notation": null, - "alpha-value-notation": null, - "selector-attribute-quotes": null, - "function-url-quotes": null, - "font-family-name-quotes": null, "no-descending-specificity": null, - "selector-not-notation": null, - "at-rule-no-unknown": [ - true, - { - "ignoreAtRules": ["define-mixin", "mixin", "include"] - } - ], - "selector-pseudo-class-no-unknown": [ - true, - { - "ignorePseudoClasses": ["global"] - } - ] + "keyframes-name-pattern": null } } diff --git a/package-lock.json b/package-lock.json index 3d7b3fd65..d0b079279 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,12 @@ "version": "2.5.0-alpha.1", "license": "BSD-3-Clause", "dependencies": { + "@radix-ui/react-alert-dialog": "^1.0.5", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", "@xmldom/xmldom": "^0.8.10", "classnames": "^2.5.1", "commonmark": "^0.31.0", @@ -38,6 +44,7 @@ "r2-utils-js": "^1.0.38", "ramda": "^0.29.1", "react": "^18.2.0", + "react-aria-components": "^1.1.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-focus-lock": "^2.11.2", @@ -131,11 +138,6 @@ "mini-css-extract-plugin": "^2.8.1", "ncp": "^2.0.0", "node-loader": "^2.0.0", - "postcss": "^8.4.38", - "postcss-import": "^16.1.0", - "postcss-loader": "^8.1.1", - "postcss-mixins": "^10.0.0", - "postcss-nesting": "^12.1.1", "prettier": "^3.2.5", "react-svg-loader": "^3.0.3", "remote-redux-devtools": "^0.5.16", @@ -145,6 +147,7 @@ "style-loader": "^4.0.0", "stylelint": "^16.3.1", "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard-scss": "^13.1.0", "svg-sprite-loader": "^6.0.11", "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.1.2", @@ -852,28 +855,6 @@ "@csstools/css-tokenizer": "^2.2.4" } }, - "node_modules/@csstools/selector-resolve-nested": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-1.1.0.tgz", - "integrity": "sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.13" - } - }, "node_modules/@csstools/selector-specificity": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", @@ -1827,6 +1808,84 @@ "@flatten-js/core": "^1.4.2" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "dependencies": { + "@floating-ui/utils": "^0.2.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "dependencies": { + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", + "dependencies": { + "@floating-ui/dom": "^1.6.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.2.tgz", + "integrity": "sha512-+QoPW4csYALsQIl8GbN14igZzDbuwzcpWrku9nyMXlaqAlwRBgl5V+p0vWMGFqHOw37czNXaP/lEk4wbLgcmtA==", + "dependencies": { + "@formatjs/intl-localematcher": "0.5.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz", + "integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.6.tgz", + "integrity": "sha512-etVau26po9+eewJKYoiBKP6743I1br0/Ie00Pb/S/PtmYfmjTcOn2YCh2yNkSZI12h6Rg+BOgQYborXk46BvkA==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/icu-skeleton-parser": "1.8.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.0.tgz", + "integrity": "sha512-QWLAYvM0n8hv7Nq5BEs4LKIjevpVpbGLAJgOaYzg9wABEoX1j0JO1q2/jVkO6CVlq0dbsxZCngS5aXbysYueqA==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz", + "integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -1888,6 +1947,39 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@internationalized/date": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.2.tgz", + "integrity": "sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/message": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.2.tgz", + "integrity": "sha512-MHAWsZWz8jf6jFPZqpTudcCM361YMtPIRu9CXkYmKjJ/0R3pQRScV5C0zS+Qi50O5UAm8ecKhkXx6mWDDcF6/g==", + "dependencies": { + "@swc/helpers": "^0.5.0", + "intl-messageformat": "^10.1.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.5.1.tgz", + "integrity": "sha512-N0fPU/nz15SwR9IbfJ5xaS9Ss/O5h1sVXMZf43vc9mxEG48ovglvvzBjF53aHlq20uoR6c+88CrIXipU/LSzwg==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.1.tgz", + "integrity": "sha512-vWQOvRIauvFMzOO+h7QrdsJmtN1AXAFVcaLWP9AseRN2o7iHceZ6bIXhBD4teZl8i91A3gxKnWBlGgjCwU6MFQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3939,114 +4031,2230 @@ "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", "dev": true }, - "node_modules/@redux-devtools/extension": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", - "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", - "dev": true, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", "dependencies": { - "@babel/runtime": "^7.23.2", - "immutable": "^4.3.4" + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz", + "integrity": "sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" }, "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@redux-saga/core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.3.0.tgz", - "integrity": "sha512-L+i+qIGuyWn7CIg7k1MteHGfttKPmxwZR5E7OsGikCL2LzYA0RERlaUY00Y3P3ZV2EYgrsYlBrGs6cJP5OKKqA==", + "node_modules/@radix-ui/react-arrow": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", + "integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==", "dependencies": { - "@babel/runtime": "^7.6.3", - "@redux-saga/deferred": "^1.2.1", - "@redux-saga/delay-p": "^1.2.1", - "@redux-saga/is": "^1.1.3", - "@redux-saga/symbols": "^1.1.3", - "@redux-saga/types": "^1.2.1", - "typescript-tuple": "^2.2.1" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/redux-saga" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@redux-saga/deferred": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.2.1.tgz", - "integrity": "sha512-cmin3IuuzMdfQjA0lG4B+jX+9HdTgHZZ+6u3jRAOwGUxy77GSlTi4Qp2d6PM1PUoTmQUR5aijlA39scWWPF31g==" - }, - "node_modules/@redux-saga/delay-p": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.2.1.tgz", - "integrity": "sha512-MdiDxZdvb1m+Y0s4/hgdcAXntpUytr9g0hpcOO1XFVyyzkrDu3SKPgBFOtHn7lhu7n24ZKIAT1qtKyQjHqRd+w==", + "node_modules/@radix-ui/react-collection": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", + "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", "dependencies": { - "@redux-saga/symbols": "^1.1.3" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@redux-saga/is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.3.tgz", - "integrity": "sha512-naXrkETG1jLRfVfhOx/ZdLj0EyAzHYbgJWkXbB3qFliPcHKiWbv/ULQryOAEKyjrhiclmr6AMdgsXFyx7/yE6Q==", + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dependencies": { - "@redux-saga/symbols": "^1.1.3", - "@redux-saga/types": "^1.2.1" + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@redux-saga/symbols": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.3.tgz", - "integrity": "sha512-hCx6ZvU4QAEUojETnX8EVg4ubNLBFl1Lps4j2tX7o45x/2qg37m3c6v+kSp8xjDJY+2tJw4QB3j8o8dsl1FDXg==" + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/@redux-saga/types": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz", - "integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA==" + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } }, - "node_modules/@remix-run/router": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", - "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", - "engines": { - "node": ">=14.0.0" + "node_modules/@radix-ui/react-direction": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", + "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dev": true, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" }, - "engines": { - "node": ">=14.0.0" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" }, "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, "peerDependenciesMeta": { - "rollup": { + "@types/react": { "optional": true } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.14.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.2.tgz", - "integrity": "sha512-ahxSgCkAEk+P/AVO0vYr7DxOD3CwAQrT0Go9BJyGQ9Ef0QxVOfjDZMiF4Y2s3mLyPrjonchIMH/tbWHucJMykQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.14.2", + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.7.tgz", + "integrity": "sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", + "integrity": "sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1", + "@radix-ui/react-use-rect": "1.0.1", + "@radix-ui/react-use-size": "1.0.1", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.3.tgz", + "integrity": "sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", + "integrity": "sha512-egZfYY/+wRNCflXNHx+dePvnz9FbmssDTJBtgRfDY7e8SE5oIo3Py2eCB1ckAbh1Q7cQ/6yJZThJ++sgbxibog==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz", + "integrity": "sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz", + "integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/rect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz", + "integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz", + "integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz", + "integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@react-aria/breadcrumbs": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.11.tgz", + "integrity": "sha512-bQz4g2tKvcWxeqPGj9O0RQf++Ka8f2o/pJMJB+QQ27DVQWhxpQpND//oFku2aFYkxHB/fyD9qVoiqpQR25bidw==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/link": "^3.6.5", + "@react-aria/utils": "^3.23.2", + "@react-types/breadcrumbs": "^3.7.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/button": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.9.3.tgz", + "integrity": "sha512-ZXo2VGTxfbaTEnfeIlm5ym4vYpGAy8sGrad8Scv+EyDAJWLMKokqctfaN6YSWbqUApC3FN63IvMqASflbmnYig==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/calendar": { + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.5.6.tgz", + "integrity": "sha512-PA0Ur5WcODMn7t2gCUvq61YktkB+WlSZjzDr5kcY3sdl53ZjiyqCa2hYgrb6R0J859LVJXAp+5Qaproz8g1oLA==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-stately/calendar": "^3.4.4", + "@react-types/button": "^3.9.2", + "@react-types/calendar": "^3.4.4", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/checkbox": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.14.1.tgz", + "integrity": "sha512-b4rtrg5SpRSa9jBOqzJMmprJ+jDi3KyVvUh+DsvISe5Ti7gVAhMBgnca1D0xBp22w2jhk/o4gyu1bYxGLum0GA==", + "dependencies": { + "@react-aria/form": "^3.0.3", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/toggle": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-stately/checkbox": "^3.6.3", + "@react-stately/form": "^3.0.1", + "@react-stately/toggle": "^3.7.2", + "@react-types/checkbox": "^3.7.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/combobox": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.8.4.tgz", + "integrity": "sha512-HyTWIo2B/0xq0Of+sDEZCfJyf4BvCvDYIWG4UhjqL1kHIHIGQyyr+SldbVUjXVYnk8pP1eGB3ttiREujjjALPQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/listbox": "^3.11.5", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/menu": "^3.13.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/combobox": "^3.8.2", + "@react-stately/form": "^3.0.1", + "@react-types/button": "^3.9.2", + "@react-types/combobox": "^3.10.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/datepicker": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.9.3.tgz", + "integrity": "sha512-1AjCAizd88ACKjVNhFazX4HZZFwWi2rsSlGCTm66Nx6wm5N/Cpbm466dpYEFyQUsKSOG4CC65G1zfYoMPe48MQ==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/number": "^3.5.1", + "@internationalized/string": "^3.2.1", + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/spinbutton": "^3.6.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/datepicker": "^3.9.2", + "@react-stately/form": "^3.0.1", + "@react-types/button": "^3.9.2", + "@react-types/calendar": "^3.4.4", + "@react-types/datepicker": "^3.7.2", + "@react-types/dialog": "^3.5.8", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/dialog": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.12.tgz", + "integrity": "sha512-7UJR/h/Y364u6Ltpw0bT51B48FybTuIBacGpEJN5IxZlpxvQt0KQcBDiOWfAa/GQogw4B5hH6agaOO0nJcP49Q==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/dialog": "^3.5.8", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/dnd": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.5.3.tgz", + "integrity": "sha512-0gi6sRnr97fSQnGy+CMt+99/+vVqr+qv2T9Ts8X9TAzxHNokz5QfSL88QSlTU36EnAVLxPY18iZQWCExSjKpEQ==", + "dependencies": { + "@internationalized/string": "^3.2.1", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/dnd": "^3.2.8", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.16.2.tgz", + "integrity": "sha512-Rqo9ummmgotESfypzFjI3uh58yMpL+E+lJBbQuXkBM0u0cU2YYzu0uOrFrq3zcHk997udZvq1pGK/R+2xk9B7g==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/form": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.3.tgz", + "integrity": "sha512-5Q2BHE4TTPDzGY2npCzpRRYshwWUb3SMUA/Cbz7QfEtBk+NYuVaq3KjvqLqgUUdyKtqLZ9Far0kIAexloOC4jw==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/grid": { + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.8.8.tgz", + "integrity": "sha512-7Bzbya4tO0oIgqexwRb8D6ZdC0GASYq9f/pnkrqocgvG9e1SCld4zOioKbYQDvAK/NnbCgXmmdqFAcLM/iazaA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/grid": "^3.8.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/checkbox": "^3.7.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/gridlist": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.7.5.tgz", + "integrity": "sha512-RmHEJ++vngHYEWbUCtLLmGh7H3vNd2Y9S0q/9SgHFPbqPZycT5mxDZ2arqpOXeHRVRvPBaW9ZlMxI2bPOePrYw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/grid": "^3.8.8", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/list": "^3.10.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/i18n": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.10.2.tgz", + "integrity": "sha512-Z1ormoIvMOI4mEdcFLYsoJy9w/EzBdBmgfLP+S/Ah+1xwQOXpgwZxiKOhYHpWa0lf6hkKJL34N9MHJvCJ5Crvw==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/message": "^3.1.2", + "@internationalized/number": "^3.5.1", + "@internationalized/string": "^3.2.1", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.1.tgz", + "integrity": "sha512-AlHf5SOzsShkHfV8GLLk3v9lEmYqYHURKcXWue0JdYbmquMRkUsf/+Tjl1+zHVAQ8lKqRnPYbTmc4AcZbqxltw==", + "dependencies": { + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/label": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.6.tgz", + "integrity": "sha512-ap9iFS+6RUOqeW/F2JoNpERqMn1PvVIo3tTMrJ1TY1tIwyJOxdCBRgx9yjnPBnr+Ywguep+fkPNNi/m74+tXVQ==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/link": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.6.5.tgz", + "integrity": "sha512-kg8CxKqkciQFzODvLAfxEs8gbqNXFZCW/ISOE2LHYKbh9pA144LVo71qO3SPeYVVzIjmZeW4vEMdZwqkNozecw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/link": "^3.5.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/listbox": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.11.5.tgz", + "integrity": "sha512-y3a3zQYjT+JKgugCMMKS7K9sRoCoP1Z6Fiiyfd77OHXWzh9RlnvWGsseljynmbxLzSuPwFtCYkU1Jz4QwsPUIg==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/list": "^3.10.3", + "@react-types/listbox": "^3.4.7", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/live-announcer": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.3.2.tgz", + "integrity": "sha512-aOyPcsfyY9tLCBhuUaYCruwcd1IrYLc47Ou+J7wMzjeN9v4lsaEfiN12WFl8pDqOwfy6/7It2wmlm5hOuZY8wQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-aria/menu": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.13.1.tgz", + "integrity": "sha512-jF80YIcvD16Fgwm5pj7ViUE3Dj7z5iewQixLaFVdvpgfyE58SD/ZVU9/JkK5g/03DYM0sjpUKZGkdFxxw8eKnw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/menu": "^3.6.1", + "@react-stately/tree": "^3.7.6", + "@react-types/button": "^3.9.2", + "@react-types/menu": "^3.9.7", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/meter": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.11.tgz", + "integrity": "sha512-P1G3Jdh0f/uieUDqvc3Ee4wzqBJa7H077BVSC3KPRqEp6YY7JimZGWjOwbFlO2PXhryXm/dI8EzUmh+4ZXjq/g==", + "dependencies": { + "@react-aria/progress": "^3.4.11", + "@react-types/meter": "^3.3.7", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/numberfield": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.1.tgz", + "integrity": "sha512-JQ1Z+Ho5H+jeav7jt9A4vBsIQR/Dd2CFbObrULjGkqSrnWjARFZBv3gZwmfGCtplEPeAv9buYKHAqebPtJNUww==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/spinbutton": "^3.6.3", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-stately/numberfield": "^3.9.1", + "@react-types/button": "^3.9.2", + "@react-types/numberfield": "^3.8.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/overlays": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.21.1.tgz", + "integrity": "sha512-djEBDF+TbIIOHWWNpdm19+z8xtY8U+T+wKVQg/UZ6oWnclSqSWeGl70vu73Cg4HVBJ4hKf1SRx4Z/RN6VvH4Yw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/overlays": "^3.6.5", + "@react-types/button": "^3.9.2", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/progress": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.11.tgz", + "integrity": "sha512-RePHbS15/KYFiApYLdwazwvWKsB9q0Kn5DGCSb0hqCC+k2Eui8iVVOsegswiP+xqkk/TiUCIkBEw22W3Az4kTg==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-types/progress": "^3.5.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/radio": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.10.2.tgz", + "integrity": "sha512-CTUTR+qt3BLjmyQvKHZuVm+1kyvT72ZptOty++sowKXgJApTLdjq8so1IpaLAr8JIfzqD5I4tovsYwIQOX8log==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/radio": "^3.10.2", + "@react-types/radio": "^3.7.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/searchfield": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.7.3.tgz", + "integrity": "sha512-mnYI969R7tU3yMRIGmY1+peq7tmEW0W3MB/J2ImK36Obz/91tTtspHHEeFtPlQDLIyvVPB0Ucam4LIxCKPJm/Q==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/searchfield": "^3.5.1", + "@react-types/button": "^3.9.2", + "@react-types/searchfield": "^3.5.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/select": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.14.3.tgz", + "integrity": "sha512-9KCxI41FI+jTxEfUzRsMdJsZvjkCuuhL4UHig8MZXtXs0nsi7Ir3ezUDQ9m5MSG+ooBYM/CA9DyLDvo5Ioef+g==", + "dependencies": { + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/listbox": "^3.11.5", + "@react-aria/menu": "^3.13.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/select": "^3.6.2", + "@react-types/button": "^3.9.2", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/selection": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.17.5.tgz", + "integrity": "sha512-gO5jBUkc7WdkiFMlWt3x9pTSuj3Yeegsxfo44qU5NPlKrnGtPRZDWrlACNgkDHu645RNNPhlyoX0C+G8mUg1xA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/selection": "^3.14.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/separator": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.3.11.tgz", + "integrity": "sha512-UTla+3P2pELpP73WSfbwZgP1y1wODFBQbEOHnUxxO8ocyaUyQLJdvc07bBLLpPoyutlggRG0v9ACo0Rui7AjOg==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/slider": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.6.tgz", + "integrity": "sha512-ZeZhyHzhk9gxGuThPKgX2K3RKsxPxsFig1iYoJvqP8485NtHYQIPht2YcpEKA9siLxGF0DR9VCfouVhSoW0AEA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/slider": "^3.5.2", + "@react-types/shared": "^3.22.1", + "@react-types/slider": "^3.7.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/spinbutton": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.3.tgz", + "integrity": "sha512-IlfhRu/pc9zOt2C5zSEB7NmmzddvWisGx2iGzw8BwIKMD+cN3uy+Qwp+sG6Z/JzFEBN0F6Mxm3l5lhbiqjpICQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.2.tgz", + "integrity": "sha512-0gKkgDYdnq1w+ey8KzG9l+H5Z821qh9vVjztk55rUg71vTk/Eaebeir+WtzcLLwTjw3m/asIjx8Y59y1lJZhBw==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/switch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.2.tgz", + "integrity": "sha512-X5m/omyhXK+V/vhJFsHuRs2zmt9Asa/RuzlldbXnWohLdeuHMPgQnV8C9hg3f+sRi3sh9UUZ64H61pCtRoZNwg==", + "dependencies": { + "@react-aria/toggle": "^3.10.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/switch": "^3.5.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/table": { + "version": "3.13.5", + "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.13.5.tgz", + "integrity": "sha512-P2nHEDk2CCoEbMFKNCyBC9qvmv7F/IXARDt/7z/J4mKFgU2iNSK+/zw6yrb38q33Zlk8hDaqSYNxHlMrh+/1MQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/grid": "^3.8.8", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/collections": "^3.10.5", + "@react-stately/flags": "^3.0.1", + "@react-stately/table": "^3.11.6", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/checkbox": "^3.7.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tabs": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.8.5.tgz", + "integrity": "sha512-Jvt33/W+66n5oCxVwHAYarJ3Fit61vULiPcG7uTez0Mf11cq/C72wOrj+ZuNz6PTLTi2veBNQ7MauY72SnOjRg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/tabs": "^3.6.4", + "@react-types/shared": "^3.22.1", + "@react-types/tabs": "^3.3.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tag": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.3.3.tgz", + "integrity": "sha512-tlJD9qj1XcsPIZD7DVJ6tWv8t7Z87/8qkbRDx7ugNqeHso9z0WqH9ZkSt17OFUWE2IQIk3V8D3iBSOtmhXcZGQ==", + "dependencies": { + "@react-aria/gridlist": "^3.7.5", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/list": "^3.10.3", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/textfield": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.3.tgz", + "integrity": "sha512-wPSjj/mTABspYQdahg+l5YMtEQ3m5iPCTtb5g6nR1U1rzJkvS4i5Pug6PUXeLeMz2H3ToflPWGlNOqBioAFaOQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@react-types/textfield": "^3.9.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/toggle": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.2.tgz", + "integrity": "sha512-DgitscHWgI6IFgnvp2HcMpLGX/cAn+XX9kF5RJQbRQ9NqUgruU5cEEGSOLMrEJ6zXDa2xmOiQ+kINcyNhA+JLg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/checkbox": "^3.7.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/toolbar": { + "version": "3.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.3.tgz", + "integrity": "sha512-tPIEPRsZI/6Mb0tAW/GBTt3wBk7dfJg/eUnTloY8NHialvDa+cMUQyUVzPyLWGpErhYeBeutBmw1e2seMjmu+A==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/tooltip": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.7.2.tgz", + "integrity": "sha512-6jXOSGPao3gPgUQWLbH2r/jxGMqIaIKrJgfwu9TQrh+UkwwiTYW20EpEDCYY2nRFlcoi7EYAiPDSEbHCwXS7Lg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/tooltip": "^3.4.7", + "@react-types/shared": "^3.22.1", + "@react-types/tooltip": "^3.4.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.23.2.tgz", + "integrity": "sha512-yznR9jJ0GG+YJvTMZxijQwVp+ahP66DY0apZf7X+dllyN+ByEDW+yaL1ewYPIpugxVzH5P8jhnBXsIyHKN411g==", + "dependencies": { + "@react-aria/ssr": "^3.9.2", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/visually-hidden": { + "version": "3.8.10", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.10.tgz", + "integrity": "sha512-np8c4wxdbE7ZrMv/bnjwEfpX0/nkWy9sELEb0sK8n4+HJ+WycoXXrVxBUb9tXgL/GCx5ReeDQChjQWwajm/z3A==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/calendar": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.4.4.tgz", + "integrity": "sha512-f9ZOd096gGGD+3LmU1gkmfqytGyQtrgi+Qjn+70GbM2Jy65pwOR4I9YrobbmeAFov5Tff13mQEa0yqWvbcDLZQ==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-stately/utils": "^3.9.1", + "@react-types/calendar": "^3.4.4", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/checkbox": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.3.tgz", + "integrity": "sha512-hWp0GXVbMI4sS2NbBjWgOnHNrRqSV4jeftP8zc5JsIYRmrWBUZitxluB34QuVPzrBO29bGsF0GTArSiQZt6BWw==", + "dependencies": { + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/checkbox": "^3.7.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/collections": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.5.tgz", + "integrity": "sha512-k8Q29Nnvb7iAia1QvTanZsrWP2aqVNBy/1SlE6kLL6vDqtKZC+Esd1SDLHRmIcYIp5aTdfwIGd0NuiRQA7a81Q==", + "dependencies": { + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/combobox": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.2.tgz", + "integrity": "sha512-f+IHuFW848VoMbvTfSakn2WIh2urDxO355LrKxnisXPCkpQHpq3lvT2mJtKJwkPxjAy7xPjpV8ejgga2R6p53Q==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/form": "^3.0.1", + "@react-stately/list": "^3.10.3", + "@react-stately/overlays": "^3.6.5", + "@react-stately/select": "^3.6.2", + "@react-stately/utils": "^3.9.1", + "@react-types/combobox": "^3.10.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/data": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.11.2.tgz", + "integrity": "sha512-yhK2upk2WbJeiLBRWHrh/4G2CvmmozCzoivLaRAPYu53m1J3MyzVGCLJgnZMbMZvAbNcYWZK6IzO6VqZ2y1fOw==", + "dependencies": { + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/datepicker": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.2.tgz", + "integrity": "sha512-Z6FrK6Af7R5BizqHhJFCj3Hn32mg5iLSDdEgFQAuO043guOXUKFUAnbxfbQUjL6PGE6QwWMfQD7PPGebHn9Ifw==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/string": "^3.2.1", + "@react-stately/form": "^3.0.1", + "@react-stately/overlays": "^3.6.5", + "@react-stately/utils": "^3.9.1", + "@react-types/datepicker": "^3.7.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/dnd": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.2.8.tgz", + "integrity": "sha512-oSo+2Bzum3Q1/d+3FuaDmpVHqqBB004tycuQDDFtad3N1BKm+fNfmslRK1ioLkPLK4sm1130V+BZBY3JXLe80A==", + "dependencies": { + "@react-stately/selection": "^3.14.3", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.1.tgz", + "integrity": "sha512-h5PcDMj54aipQNO18ig/IMI1kzPwcvSwVq5M6Ib6XE1WIkOH0dIuW2eADdAOhcGi3KXJtXVdD29zh0Eox1TKgQ==", + "dependencies": { + "@swc/helpers": "^0.4.14" + } + }, + "node_modules/@react-stately/flags/node_modules/@swc/helpers": { + "version": "0.4.36", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.36.tgz", + "integrity": "sha512-5lxnyLEYFskErRPenYItLRSge5DjrJngYKdVjRSrWfza9G6KkgHEXi0vUZiyUeMU5JfXH1YnvXZzSp8ul88o2Q==", + "dependencies": { + "legacy-swc-helpers": "npm:@swc/helpers@=0.4.14", + "tslib": "^2.4.0" + } + }, + "node_modules/@react-stately/form": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.0.1.tgz", + "integrity": "sha512-T1Ul2Ou0uE/S4ECLcGKa0OfXjffdjEHfUFZAk7OZl0Mqq/F7dl5WpoLWJ4d4IyvZzGO6anFNenP+vODWbrF3NA==", + "dependencies": { + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/grid": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.8.5.tgz", + "integrity": "sha512-KCzi0x0p1ZKK+OptonvJqMbn6Vlgo6GfOIlgcDd0dNYDP8TJ+3QFJAFre5mCr7Fubx7LcAOio4Rij0l/R8fkXQ==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/list": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.10.3.tgz", + "integrity": "sha512-Ul8el0tQy2Ucl3qMQ0fiqdJ874W1ZNjURVSgSxN+pGwVLNBVRjd6Fl7YwZFCXER2YOlzkwg+Zqozf/ZlS0EdXA==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/menu": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.6.1.tgz", + "integrity": "sha512-3v0vkTm/kInuuG8jG7jbxXDBnMQcoDZKWvYsBQq7+POt0LmijbLdbdZPBoz9TkZ3eo/OoP194LLHOaFTQyHhlw==", + "dependencies": { + "@react-stately/overlays": "^3.6.5", + "@react-types/menu": "^3.9.7", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/numberfield": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.1.tgz", + "integrity": "sha512-btBIcBEfSVCUm6NwJrMrMygoIu/fQGazzD0RhF7PNsfvkFiWn+TSOyQqSXcsUJVOnBfoS/dVWj6r57KA7zl3FA==", + "dependencies": { + "@internationalized/number": "^3.5.1", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/numberfield": "^3.8.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/overlays": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.5.tgz", + "integrity": "sha512-U4rCFj6TPJPXLUvYXAcvh+yP/CO2W+7f0IuqP7ZZGE+Osk9qFkT+zRK5/6ayhBDFpmueNfjIEAzT9gYPQwNHFw==", + "dependencies": { + "@react-stately/utils": "^3.9.1", + "@react-types/overlays": "^3.8.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/radio": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.2.tgz", + "integrity": "sha512-JW5ZWiNMKcZvMTsuPeWJQLHXD5rlqy7Qk6fwUx/ZgeibvMBW/NnW19mm2+IMinzmbtERXvR6nsiA837qI+4dew==", + "dependencies": { + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/radio": "^3.7.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/searchfield": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.1.tgz", + "integrity": "sha512-9A8Wghx1avRHhMpNH1Nj+jFfiF1bhsff2GEC5PZgWYzhCykw3G5bywn3JAuUS4kh7Vpqhbu4KpHAhmWPSv4B/Q==", + "dependencies": { + "@react-stately/utils": "^3.9.1", + "@react-types/searchfield": "^3.5.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/select": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.2.tgz", + "integrity": "sha512-duOxdHKol93h6Ew6fap6Amz+zngoERKZLSKVm/8I8uaBgkoBhEeTFv7mlpHTgINxymMw3mMrvy6GL/gfKFwkqg==", + "dependencies": { + "@react-stately/form": "^3.0.1", + "@react-stately/list": "^3.10.3", + "@react-stately/overlays": "^3.6.5", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/selection": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.14.3.tgz", + "integrity": "sha512-d/t0rIWieqQ7wjLoMoWnuHEUSMoVXxkPBFuSlJF3F16289FiQ+b8aeKFDzFTYN7fFD8rkZTnpuE4Tcxg3TmA+w==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/slider": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.2.tgz", + "integrity": "sha512-ntH3NLRG+AwVC7q4Dx9DcmMkMh9vmHjHNXAgaoqNjhvwfSIae7sQ69CkVe6XeJjIBy6LlH81Kgapz+ABe5a1ZA==", + "dependencies": { + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@react-types/slider": "^3.7.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/table": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.11.6.tgz", + "integrity": "sha512-34YsfOILXusj3p6QNcKEaDWVORhM6WEhwPSLCZlkwAJvkxuRQFdih5rQKoIDc0uV5aZsB6bYBqiFhnjY0VERhw==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/flags": "^3.0.1", + "@react-stately/grid": "^3.8.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tabs": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.4.tgz", + "integrity": "sha512-WZJgMBqzLgN88RN8AxhY4aH1+I+4w1qQA0Lh3LRSDegaytd+NHixCWaP3IPjePgCB5N1UsPe96Xglw75zjHmDg==", + "dependencies": { + "@react-stately/list": "^3.10.3", + "@react-types/shared": "^3.22.1", + "@react-types/tabs": "^3.3.5", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/toggle": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.2.tgz", + "integrity": "sha512-SHCF2btcoK57c4lyhucRbyPBAFpp0Pdp0vcPdn3hUgqbu6e5gE0CwG/mgFmZRAQoc7PRc7XifL0uNw8diJJI0Q==", + "dependencies": { + "@react-stately/utils": "^3.9.1", + "@react-types/checkbox": "^3.7.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tooltip": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.7.tgz", + "integrity": "sha512-ACtRgBQ8rphBtsUaaxvEAM0HHN9PvMuyvL0vUHd7jvBDCVZJ6it1BKu9SBKjekBkoBOw9nemtkplh9R2CA6V8Q==", + "dependencies": { + "@react-stately/overlays": "^3.6.5", + "@react-types/tooltip": "^3.4.7", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/tree": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.7.6.tgz", + "integrity": "sha512-y8KvEoZX6+YvqjNCVGS3zA/BKw4D3XrUtUKIDme3gu5Mn6z97u+hUXKdXVCniZR7yvV3fHAIXwE5V2K8Oit4aw==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.9.1.tgz", + "integrity": "sha512-yzw75GE0iUWiyps02BOAPTrybcsMIxEJlzXqtvllAb01O9uX5n0i3X+u2eCpj2UoDF4zS08Ps0jPgWxg8xEYtA==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/virtualizer": { + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.6.8.tgz", + "integrity": "sha512-Pf06ihTwExRJltGhi72tmLIo0pcjkL55nu7ifMafAAdxZK4ONxRLSuUjjpvYf/0Rs92xRZy2t/XmHREnfirdkQ==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/breadcrumbs": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.3.tgz", + "integrity": "sha512-eFto/+6J+JR58vThNcALZRA1OlqlG3GzQ/bq3q8IrrkOZcrfbEJJCWit/+53Ia98siJKuF4OJHnotxIVIz5I3w==", + "dependencies": { + "@react-types/link": "^3.5.3", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/button": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.2.tgz", + "integrity": "sha512-EnPTkGHZRtiwAoJy5q9lDjoG30bEzA/qnvKG29VVXKYAGeqY2IlFs1ypmU+z1X/CpJgPcG3I5cakM7yTVm3pSg==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/calendar": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.4.tgz", + "integrity": "sha512-hV1Thmb/AES5OmfPvvmyjSkmsEULjiDfA7Yyy70L/YKuSNKb7Su+Bf2VnZuDW3ec+GxO4JJNlpJ0AkbphWBvcg==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/checkbox": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.7.1.tgz", + "integrity": "sha512-kuGqjQFex0As/3gfWyk+e9njCcad/ZdnYLLiNvhlk15730xfa0MmnOdpqo9jfuFSXBjOcpxoofvEhvrRMtEdUA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/combobox": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.10.1.tgz", + "integrity": "sha512-XMno1rgVRNta49vf5nV7VJpVSVAV20tt79t618gG1qRKH5Kt2Cy8lz2fQ5vHG6UTv/6jUOvU8g5Pc93sLaTmoA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/datepicker": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.2.tgz", + "integrity": "sha512-zThqFAdhQL1dqyVDsDSSTdfCjoD6634eyg/B0ZJfQxcLUR/5pch3v/gxBhbyCVDGMNHRWUWIJvY9DVOepuoSug==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-types/calendar": "^3.4.4", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/dialog": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.8.tgz", + "integrity": "sha512-RX8JsMvty8ADHRqVEkppoynXLtN4IzUh8d5z88UEBbcvWKlHfd6bOBQjQcBH3AUue5wjfpPIt6brw2VzgBY/3Q==", + "dependencies": { + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/form": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.2.tgz", + "integrity": "sha512-6/isEJY4PsYoHdMaGQtqQyquXGTwB1FqCBOPKQjI/vBGWG3fL7FGfWm4Z62eTbCH4Xyv3FZuNywlT8UjPMQyKA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/grid": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.4.tgz", + "integrity": "sha512-sDVoyQcH7MoGdx5nBi5ZOU/mVFBt9YTxhvr0PZ97dMdEHZtJC1w9SuezwWS34f50yb8YAXQRTICbZYcK4bAlDA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/link": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.3.tgz", + "integrity": "sha512-yVafjW3IejyVnK3oMBNjFABCGG6J27EUG8rvkaGaI1uB6srGUEhpJ97XLv11aj1QkXHBy3VGXqxEV3S7wn4HTw==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/listbox": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.4.7.tgz", + "integrity": "sha512-68y5H9CVSPFiwO6MOFxTbry9JQMK/Lb1M9i3M8TDyq1AbJxBPpgAvJ9RaqIMCucsnqCzpY/zA3D/X417zByL1w==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/menu": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.7.tgz", + "integrity": "sha512-K6KhloJVoGsqwkdeez72fkNI9dfrmLI/sNrB4XuOKo2crDQ/eyZYWyJmzz8giz/tHME9w774k487rVoefoFh5w==", + "dependencies": { + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/meter": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.3.7.tgz", + "integrity": "sha512-p+YJ0+Lpn5MLmlbFZbDH1P0ILv1+AuMcUbxLcXMIVMGn7o0FO7eVZnFuq76D+qTDm9all+TRLJix7bctOrP+5Q==", + "dependencies": { + "@react-types/progress": "^3.5.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/numberfield": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.1.tgz", + "integrity": "sha512-GaCjLQgXUGCt40SLjKk3/COMWFlN2vV/3Xs3VSLAEdFZpk99b+Ik1oR21+7ZP5/iMHuQDc1MJRWdFfIjxCvVDQ==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/overlays": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.5.tgz", + "integrity": "sha512-4D7EEBQigD/m8hE68Ys8eloyyZFHHduqykSIgINJ0edmo0jygRbWlTwuhWFR9USgSP4dK54duN0Mvq0m4HEVEw==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/progress": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.2.tgz", + "integrity": "sha512-aQql22kusEudsHwDEzq6y/Mh29AM+ftRDKdS5E5g4MkCY5J4FMbOYco1T5So83NIvvG9+eKcxPoJUMjQQACAyA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/radio": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.7.1.tgz", + "integrity": "sha512-Zut3rN1odIUBLZdijeyou+UqsLeRE76d9A+npykYGu29ndqmo3w4sLn8QeQcdj1IR71ZnG0pW2Y2BazhK5XrrQ==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/searchfield": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.5.3.tgz", + "integrity": "sha512-gBfsT1WpY8UIb74yyYmnjiHpVasph2mdmGj9i8cGF2HUYwx5p+Fr85mtCGDph0uirvRoM5ExMp4snD+ueNAVCg==", + "dependencies": { + "@react-types/shared": "^3.22.1", + "@react-types/textfield": "^3.9.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/select": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.2.tgz", + "integrity": "sha512-fGFrunednY3Pq/BBwVOf87Fsuyo/SlevL0wFIE9OOl2V5NXVaTY7/7RYA8hIOHPzmvsMbndy419BEudiNGhv4A==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.22.1.tgz", + "integrity": "sha512-PCpa+Vo6BKnRMuOEzy5zAZ3/H5tnQg1e80khMhK2xys0j6ZqzkgQC+fHMNZ7VDFNLqqNMj/o0eVeSBDh2POjkw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/slider": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.1.tgz", + "integrity": "sha512-FKO3YZYdrBs00XbBW5acP+0L1cCdevl/uRJiXbnLpGysO5PrSFIRS7Wlv4M7ztf6gT7b1Ao4FNC9crbxBr6BzA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/switch": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.1.tgz", + "integrity": "sha512-2LFEKMGeufqyYmeN/5dtkDkCPG6x9O4eu6aaBaJmPGon7C/l3yiFEgRue6oCUYc1HixR7Qlp0sPxk0tQeWzrSg==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/table": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.9.3.tgz", + "integrity": "sha512-Hs/pMbxJdga2zBol4H5pV1FVIiRjCuSTXst6idJjkctanTexR4xkyrtBwl+rdLNoGwQ2pGii49vgklc5bFK7zA==", + "dependencies": { + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/tabs": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.5.tgz", + "integrity": "sha512-6NTSZBOWekCtApdZrhu5tHhE/8q52oVohQN+J5T7shAXd6ZAtu8PABVR/nH4BWucc8FL0OUajRqunqzQMU13gA==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/textfield": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.1.tgz", + "integrity": "sha512-JBHY9M2CkL6xFaGSfWmUJVu3tEK09FaeB1dU3IEh6P41xxbFnPakYHSSAdnwMXBtXPoSHIVsUBickW/pjgfe5g==", + "dependencies": { + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/tooltip": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.7.tgz", + "integrity": "sha512-rV4HZRQxLRNhe24yATOxnFQtGRUmsR7mqxMupXCmd1vrw8h+rdKlQv1zW2q8nALAKNmnRXZJHxYQ1SFzb98fgg==", + "dependencies": { + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@redux-devtools/extension": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", + "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "immutable": "^4.3.4" + }, + "peerDependencies": { + "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/@redux-saga/core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.3.0.tgz", + "integrity": "sha512-L+i+qIGuyWn7CIg7k1MteHGfttKPmxwZR5E7OsGikCL2LzYA0RERlaUY00Y3P3ZV2EYgrsYlBrGs6cJP5OKKqA==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@redux-saga/deferred": "^1.2.1", + "@redux-saga/delay-p": "^1.2.1", + "@redux-saga/is": "^1.1.3", + "@redux-saga/symbols": "^1.1.3", + "@redux-saga/types": "^1.2.1", + "typescript-tuple": "^2.2.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/redux-saga" + } + }, + "node_modules/@redux-saga/deferred": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.2.1.tgz", + "integrity": "sha512-cmin3IuuzMdfQjA0lG4B+jX+9HdTgHZZ+6u3jRAOwGUxy77GSlTi4Qp2d6PM1PUoTmQUR5aijlA39scWWPF31g==" + }, + "node_modules/@redux-saga/delay-p": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.2.1.tgz", + "integrity": "sha512-MdiDxZdvb1m+Y0s4/hgdcAXntpUytr9g0hpcOO1XFVyyzkrDu3SKPgBFOtHn7lhu7n24ZKIAT1qtKyQjHqRd+w==", + "dependencies": { + "@redux-saga/symbols": "^1.1.3" + } + }, + "node_modules/@redux-saga/is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.3.tgz", + "integrity": "sha512-naXrkETG1jLRfVfhOx/ZdLj0EyAzHYbgJWkXbB3qFliPcHKiWbv/ULQryOAEKyjrhiclmr6AMdgsXFyx7/yE6Q==", + "dependencies": { + "@redux-saga/symbols": "^1.1.3", + "@redux-saga/types": "^1.2.1" + } + }, + "node_modules/@redux-saga/symbols": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.3.tgz", + "integrity": "sha512-hCx6ZvU4QAEUojETnX8EVg4ubNLBFl1Lps4j2tX7o45x/2qg37m3c6v+kSp8xjDJY+2tJw4QB3j8o8dsl1FDXg==" + }, + "node_modules/@redux-saga/types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@redux-saga/types/-/types-1.2.1.tgz", + "integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA==" + }, + "node_modules/@remix-run/router": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.2.tgz", + "integrity": "sha512-ahxSgCkAEk+P/AVO0vYr7DxOD3CwAQrT0Go9BJyGQ9Ef0QxVOfjDZMiF4Y2s3mLyPrjonchIMH/tbWHucJMykQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.14.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.2.tgz", "integrity": "sha512-lAarIdxZWbFSHFSDao9+I/F5jDaKyCqAPMq5HqnfpBw8dKDiCaaqM0lq5h1pQTLeIqueeay4PieGR5jGZMWprw==", "cpu": [ @@ -4275,6 +6483,14 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.9.tgz", + "integrity": "sha512-XI76sLwMJoLjJTOK5RblBZkouOJG3X3hjxLCzLnyN1ifAiKQc6Hck3uvnU4Z/dV/Dyk36Ffj8FLvDLV2oWvKTw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -4743,7 +6959,7 @@ "version": "18.2.25", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz", "integrity": "sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/react": "*" } @@ -6245,6 +8461,17 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -7576,15 +9803,6 @@ "node": ">=6" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001609", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz", @@ -7878,6 +10096,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -7993,6 +10216,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -12477,6 +14708,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -13846,6 +16085,25 @@ "node": ">= 0.10" } }, + "node_modules/intl-messageformat": { + "version": "10.5.11", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.11.tgz", + "integrity": "sha512-eYq5fkFBVxc7GIFDzpFQkDOZgNayNTQn4Oufe8jw6YY6OHVw70/4pA3FyCsQ0Gb2DnvEJEMmN2tOaXUGByM+kg==", + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.2", + "@formatjs/fast-memoize": "2.2.0", + "@formatjs/icu-messageformat-parser": "2.7.6", + "tslib": "^2.4.0" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/inversify": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", @@ -16442,15 +18700,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -16933,6 +19182,15 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/legacy-swc-helpers": { + "name": "@swc/helpers", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -19246,15 +21504,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -19428,230 +21677,82 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", - "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.2.0", - "mlly": "^1.2.0", - "pathe": "^1.1.0" - } - }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", - "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-loader": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", - "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", - "dev": true, - "dependencies": { - "cosmiconfig": "^9.0.0", - "jiti": "^1.20.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/postcss-loader/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", "dev": true, "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" } }, - "node_modules/postcss-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=10" + "node": ">=10.4.0" } }, - "node_modules/postcss-loader/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/postcss-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/postcss-mixins": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-10.0.0.tgz", - "integrity": "sha512-CHw+Q8Y7Jz67lqyXbVezvWUsXPVEdPEVLKFb0u8hSRKWzdHMIGwwkZDf17tgAmFOYyoM529WyctZ1sNuVjZ9DQ==", + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "fast-glob": "^3.3.2", - "postcss-js": "^4.0.1", - "postcss-simple-vars": "^7.0.1", - "sugarss": "^4.0.1" + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" }, "engines": { - "node": "^18.0 || >= 20.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" + "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, "node_modules/postcss-modules": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz", @@ -19730,33 +21831,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-nesting": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.1.tgz", - "integrity": "sha512-qc74KvIAQNa5ujZKG1UV286dhaDW6basbUy2i9AzNU/T8C9hpvGu9NZzm1SfePe2yP7sPYgpA8d4sPVopn2Hhw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/selector-resolve-nested": "^1.1.0", - "@csstools/selector-specificity": "^3.0.3", - "postcss-selector-parser": "^6.0.13" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/postcss-prefix-selector": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.0.tgz", @@ -19798,6 +21872,32 @@ "postcss": "^8.4.31" } }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.16", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", @@ -19811,22 +21911,6 @@ "node": ">=4" } }, - "node_modules/postcss-simple-vars": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", - "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", - "dev": true, - "engines": { - "node": ">=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.1" - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -20548,6 +22632,84 @@ "node": ">=0.10.0" } }, + "node_modules/react-aria": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.32.1.tgz", + "integrity": "sha512-7KCJg4K5vlRqiXdGjgCT05Du8RhGBYC+2ok4GOh/Znmg8aMwOk7t0YwxaT5i1z30+fmDcJS/pk/ipUPUg28CXg==", + "dependencies": { + "@internationalized/string": "^3.2.1", + "@react-aria/breadcrumbs": "^3.5.11", + "@react-aria/button": "^3.9.3", + "@react-aria/calendar": "^3.5.6", + "@react-aria/checkbox": "^3.14.1", + "@react-aria/combobox": "^3.8.4", + "@react-aria/datepicker": "^3.9.3", + "@react-aria/dialog": "^3.5.12", + "@react-aria/dnd": "^3.5.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/gridlist": "^3.7.5", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/link": "^3.6.5", + "@react-aria/listbox": "^3.11.5", + "@react-aria/menu": "^3.13.1", + "@react-aria/meter": "^3.4.11", + "@react-aria/numberfield": "^3.11.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/progress": "^3.4.11", + "@react-aria/radio": "^3.10.2", + "@react-aria/searchfield": "^3.7.3", + "@react-aria/select": "^3.14.3", + "@react-aria/selection": "^3.17.5", + "@react-aria/separator": "^3.3.11", + "@react-aria/slider": "^3.7.6", + "@react-aria/ssr": "^3.9.2", + "@react-aria/switch": "^3.6.2", + "@react-aria/table": "^3.13.5", + "@react-aria/tabs": "^3.8.5", + "@react-aria/tag": "^3.3.3", + "@react-aria/textfield": "^3.14.3", + "@react-aria/tooltip": "^3.7.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/react-aria-components": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-aria-components/-/react-aria-components-1.1.1.tgz", + "integrity": "sha512-XdgqSbrlh9V1vJEvTwrnr+YGndQWYcVEAbN+Rx104o9g88cAAabclgetU2OUJ9Gbht6+gwnvnA0ksgXzVZog2Q==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/string": "^3.2.1", + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/menu": "^3.13.1", + "@react-aria/toolbar": "3.0.0-beta.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/menu": "^3.6.1", + "@react-stately/table": "^3.11.6", + "@react-stately/utils": "^3.9.1", + "@react-types/form": "^3.7.2", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", + "@swc/helpers": "^0.5.0", + "client-only": "^0.0.1", + "react-aria": "^3.32.1", + "react-stately": "^3.30.1", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/react-clientside-effect": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", @@ -20646,6 +22808,51 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "6.22.3", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", @@ -20676,6 +22883,61 @@ "react-dom": ">=16.8" } }, + "node_modules/react-stately": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.30.1.tgz", + "integrity": "sha512-IEhKHMT7wijtczA5vtw/kdq9CZuOIF+ReoSimydTFiABRQxWO9ESAl/fToXOUM9qmCdhdqjGJgMAhqTnmheh8g==", + "dependencies": { + "@react-stately/calendar": "^3.4.4", + "@react-stately/checkbox": "^3.6.3", + "@react-stately/collections": "^3.10.5", + "@react-stately/combobox": "^3.8.2", + "@react-stately/data": "^3.11.2", + "@react-stately/datepicker": "^3.9.2", + "@react-stately/dnd": "^3.2.8", + "@react-stately/form": "^3.0.1", + "@react-stately/list": "^3.10.3", + "@react-stately/menu": "^3.6.1", + "@react-stately/numberfield": "^3.9.1", + "@react-stately/overlays": "^3.6.5", + "@react-stately/radio": "^3.10.2", + "@react-stately/searchfield": "^3.5.1", + "@react-stately/select": "^3.6.2", + "@react-stately/selection": "^3.14.3", + "@react-stately/slider": "^3.5.2", + "@react-stately/table": "^3.11.6", + "@react-stately/tabs": "^3.6.4", + "@react-stately/toggle": "^3.7.2", + "@react-stately/tooltip": "^3.4.7", + "@react-stately/tree": "^3.7.6", + "@react-types/shared": "^3.22.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-svg-core": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/react-svg-core/-/react-svg-core-3.0.3.tgz", @@ -20757,15 +23019,6 @@ "read-binary-file-arch": "cli.js" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, "node_modules/read-config-file": { "version": "6.3.2", "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", @@ -23171,6 +25424,29 @@ "stylelint": "^16.0.0" } }, + "node_modules/stylelint-config-recommended-scss": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.0.0.tgz", + "integrity": "sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==", + "dev": true, + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.0", + "stylelint-scss": "^6.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.0.2" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, "node_modules/stylelint-config-standard": { "version": "36.0.0", "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz", @@ -23186,6 +25462,53 @@ "stylelint": "^16.1.0" } }, + "node_modules/stylelint-config-standard-scss": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-13.1.0.tgz", + "integrity": "sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==", + "dev": true, + "dependencies": { + "stylelint-config-recommended-scss": "^14.0.0", + "stylelint-config-standard": "^36.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.3.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-scss": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.2.1.tgz", + "integrity": "sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==", + "dev": true, + "dependencies": { + "known-css-properties": "^0.29.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.15", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.2" + } + }, + "node_modules/stylelint-scss/node_modules/known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, "node_modules/stylelint/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -23292,22 +25615,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/sugarss": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", - "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", - "dev": true, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", diff --git a/package.json b/package.json index 57bd1134d..cbfde0762 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "start:quick": "cross-env DEBUG=r2:*,readium-desktop:*,-readium-desktop:main#streamerNoHttp,-readium-desktop:main:saga:persist,-r2:navigator#electron/common/readium-css-inject electron .", "lint:ts": "ESLINT_USE_FLAT_CONFIG=false eslint \"src/**/*.{ts,tsx}\"", "lint:ts:fix": "ESLINT_USE_FLAT_CONFIG=false eslint --fix \"src/**/*.{ts,tsx}\"", - "lint:css": "stylelint \"src/renderer/assets/styles/**/*.css\"", - "lint:css:fix": "stylelint --fix \"src/renderer/assets/styles/**/*.css\"", + "lint:css": "stylelint \"src/renderer/assets/styles/**/*.scss\"", + "lint:css:fix": "stylelint --fix \"src/renderer/assets/styles/**/*.scss\"", "lint": "npm run lint:ts && npm run lint:css", "lint:fix": "npm run lint:ts:fix && npm run lint:css:fix", "start:dev:renderer:library-reader-pdf": "npm run start:dev:renderer:pdf && concurrently --kill-others \"npm run start:dev:renderer:library\" \"npm run start:dev:renderer:reader\"", @@ -249,6 +249,12 @@ } }, "dependencies": { + "@radix-ui/react-alert-dialog": "^1.0.5", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", "@xmldom/xmldom": "^0.8.10", "classnames": "^2.5.1", "commonmark": "^0.31.0", @@ -278,6 +284,7 @@ "r2-utils-js": "^1.0.38", "ramda": "^0.29.1", "react": "^18.2.0", + "react-aria-components": "^1.1.1", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-focus-lock": "^2.11.2", @@ -371,11 +378,6 @@ "mini-css-extract-plugin": "^2.8.1", "ncp": "^2.0.0", "node-loader": "^2.0.0", - "postcss": "^8.4.38", - "postcss-import": "^16.1.0", - "postcss-loader": "^8.1.1", - "postcss-mixins": "^10.0.0", - "postcss-nesting": "^12.1.1", "prettier": "^3.2.5", "react-svg-loader": "^3.0.3", "remote-redux-devtools": "^0.5.16", @@ -385,6 +387,7 @@ "style-loader": "^4.0.0", "stylelint": "^16.3.1", "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard-scss": "^13.1.0", "svg-sprite-loader": "^6.0.11", "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.1.2", diff --git a/postcss.config.js b/postcss.config.js index fac909602..f538ef37f 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,55 +1,55 @@ -const path = require("path"); +// const path = require("path"); -module.exports = { - plugins: [ - require("postcss-import")({ - filter: (p) => { - const ok = p && p.indexOf("mixin") >= 0; - console.log("POSTCSS IMPORT? =====> ", p, ok); - return ok; +// module.exports = { +// plugins: [ +// require("postcss-import")({ +// filter: (p) => { +// const ok = p && p.indexOf("mixin") >= 0; +// console.log("POSTCSS IMPORT? =====> ", p, ok); +// return ok; - // console.log("POSTCSS IMPORT (skip) =====> ", p); - // return false; - }, - }), - require("postcss-mixins")({ - // mixinsFiles: path.join(__dirname, "src/renderer/assets/styles", "**/*(mixin|mixins).css"), - }), - require("postcss-nesting")({ - // mixinsFiles: path.join(__dirname, "src/renderer/assets/styles", "**/*(mixin|mixins).css"), - }), - // require("postcss-preset-env")({ - // stage: 2, - // browsers: "last 2 Chrome versions", - // // autoprefixer: false, - // features: { - // "nesting-rules": true, - // }, - // // importFrom: [ - // // "src/renderer/assets/styles/partials/variables.css", - // // "src/renderer/assets/styles/variable.css", - // // ], - // }), - // require("postcss-cssnext")({ - // // CSS compatible with the last 4 chrome versions - // browsers: ["last 4 Chrome versions"], - // // features: { - // // customProperties: { - // // variables: { - // // "main-color": "#4d4d4d", - // // "secondary-color": "white", - // // "disabled-color": "#767676", - // // "color-primary": "#4d4d4d", - // // "color-secondary": "#fff", - // // "color-tertiary": "#67a3e0", - // // "color-disabled": "#b7b7b7", - // // "color-light-grey": "#f1f1f1", - // // "color-medium-grey": "#e5e5e5", - // // "color-accent": "rgb(0, 188, 212)", - // // "color-accent-contrast": "#fff", - // // }, - // // }, - // // }, - // }), - ], -}; +// // console.log("POSTCSS IMPORT (skip) =====> ", p); +// // return false; +// }, +// }), +// require("postcss-mixins")({ +// // mixinsFiles: path.join(__dirname, "src/renderer/assets/styles", "**/*(mixin|mixins).css"), +// }), +// require("postcss-nesting")({ +// // mixinsFiles: path.join(__dirname, "src/renderer/assets/styles", "**/*(mixin|mixins).css"), +// }), +// // require("postcss-preset-env")({ +// // stage: 2, +// // browsers: "last 2 Chrome versions", +// // // autoprefixer: false, +// // features: { +// // "nesting-rules": true, +// // }, +// // // importFrom: [ +// // // "src/renderer/assets/styles/partials/variables.css", +// // // "src/renderer/assets/styles/variable.css", +// // // ], +// // }), +// // require("postcss-cssnext")({ +// // // CSS compatible with the last 4 chrome versions +// // browsers: ["last 4 Chrome versions"], +// // // features: { +// // // customProperties: { +// // // variables: { +// // // "main-color": "#4d4d4d", +// // // "secondary-color": "white", +// // // "disabled-color": "#767676", +// // // "color-primary": "#4d4d4d", +// // // "color-secondary": "#fff", +// // // "color-tertiary": "#67a3e0", +// // // "color-disabled": "#b7b7b7", +// // // "color-light-grey": "#f1f1f1", +// // // "color-medium-grey": "#e5e5e5", +// // // "color-accent": "rgb(0, 188, 212)", +// // // "color-accent-contrast": "#fff", +// // // }, +// // // }, +// // // }, +// // }), +// ], +// }; diff --git a/src/common/constant.ts b/src/common/constant.ts index 7fde915e1..765c33174 100644 --- a/src/common/constant.ts +++ b/src/common/constant.ts @@ -6,3 +6,6 @@ // ==LICENSE-END== export const ABOUT_BOOK_TITLE_PREFIX = "EDRLAB.ThoriumReader-"; + +export const WINDOW_MIN_WIDTH = 700; +export const WINDOW_MIN_HEIGHT = 600; diff --git a/src/common/keyboard.ts b/src/common/keyboard.ts index 788fb00ed..3477a84ab 100644 --- a/src/common/keyboard.ts +++ b/src/common/keyboard.ts @@ -304,33 +304,40 @@ const _defaults_ = Object.freeze({ shift: false, key: "Digit9", }), - AnnotationsTest1: Object.freeze({ - alt: true, - control: true, - shift: true, - // meta: true, - key: "Digit5", - }), - AnnotationsTest2: Object.freeze({ - alt: true, - control: true, - shift: true, - // meta: true, - key: "Digit6", - }), - AnnotationsTest3: Object.freeze({ - alt: true, - control: true, - shift: true, - // meta: true, - key: "Digit7", - }), - AnnotationsTest4: Object.freeze({ + // AnnotationsTest1: Object.freeze({ + // alt: true, + // control: true, + // shift: true, + // // meta: true, + // key: "Digit5", + // }), + // AnnotationsTest2: Object.freeze({ + // alt: true, + // control: true, + // shift: true, + // // meta: true, + // key: "Digit6", + // }), + // AnnotationsTest3: Object.freeze({ + // alt: true, + // control: true, + // shift: true, + // // meta: true, + // key: "Digit7", + // }), + // AnnotationsTest4: Object.freeze({ + // alt: true, + // control: true, + // shift: true, + // // meta: true, + // key: "Digit8", + // }), + + AnnotationDrawMarginOrPlainAnnotationToggleSwitch: Object.freeze({ alt: true, control: true, - shift: true, - // meta: true, - key: "Digit8", + shift: false, + key: "KeyM", }), }); export const _defaults = sortObject(_defaults_); diff --git a/src/common/models/dialog.ts b/src/common/models/dialog.ts index 0f8d40416..13dbd380b 100644 --- a/src/common/models/dialog.ts +++ b/src/common/models/dialog.ts @@ -57,9 +57,6 @@ export interface DialogType { feed: IOpdsFeedView; }; [DialogTypeName.ApiappAddForm]: {}; - [DialogTypeName.DeletePublicationConfirm]: { - publicationView: PublicationView; - }; [DialogTypeName.DeleteOpdsFeedConfirm]: { feed: IOpdsFeedView; }; diff --git a/src/common/models/reader.ts b/src/common/models/reader.ts index e228f05fc..4cf0edf0d 100644 --- a/src/common/models/reader.ts +++ b/src/common/models/reader.ts @@ -8,6 +8,7 @@ import { PublicationView } from "readium-desktop/common/views/publication"; import { Publication as R2Publication } from "@r2-shared-js/models/publication"; +import { IAnnotationReaderConfigState } from "../redux/states/renderer/annotation"; export enum ReaderMode { Attached = "attached", @@ -49,7 +50,10 @@ export interface ReaderConfigStrings extends ReaderConfigStringsAdjustables { } export interface ReaderConfigBooleans { + + // not used ? dark: boolean; + invert: boolean; night: boolean; paged: boolean; @@ -66,7 +70,7 @@ export interface ReaderConfigBooleans { ttsEnableOverlayMode: boolean; } -export interface ReaderConfig extends ReaderConfigStrings, ReaderConfigBooleans { +export interface ReaderConfig extends ReaderConfigStrings, ReaderConfigBooleans, IAnnotationReaderConfigState { } // export interface BookmarkCollection { diff --git a/src/common/redux/actions/index.ts b/src/common/redux/actions/index.ts index 0f3510915..1befdfb92 100644 --- a/src/common/redux/actions/index.ts +++ b/src/common/redux/actions/index.ts @@ -20,6 +20,7 @@ import * as readerActions from "./reader/"; import * as toastActions from "./toast/"; import * as sessionActions from "./session/"; import * as catalogActions from "./catalog"; +import * as themeActions from "./theme"; export { historyActions, @@ -37,4 +38,5 @@ export { loadActions, sessionActions, catalogActions, + themeActions, }; diff --git a/src/renderer/reader/redux/actions/bookmarks/index.ts b/src/common/redux/actions/reader/annotations/index.ts similarity index 100% rename from src/renderer/reader/redux/actions/bookmarks/index.ts rename to src/common/redux/actions/reader/annotations/index.ts diff --git a/src/common/redux/actions/reader/annotations/pop.ts b/src/common/redux/actions/reader/annotations/pop.ts new file mode 100644 index 000000000..31fedc551 --- /dev/null +++ b/src/common/redux/actions/reader/annotations/pop.ts @@ -0,0 +1,27 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { Action } from "readium-desktop/common/models/redux"; +import { IAnnotationState } from "readium-desktop/common/redux/states/renderer/annotation"; + +export const ID = "READER_ANNOTATIONS_POP"; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +// interface IPayload extends Pick { +interface IPayload extends IAnnotationState { +} + +export function build(param: IAnnotationState): + Action { + + return { + type: ID, + payload: {...param}, + }; +} +build.toString = () => ID; // Redux StringableActionCreator +export type TAction = ReturnType; diff --git a/src/common/redux/actions/reader/annotations/push.ts b/src/common/redux/actions/reader/annotations/push.ts new file mode 100644 index 000000000..a8e5fb685 --- /dev/null +++ b/src/common/redux/actions/reader/annotations/push.ts @@ -0,0 +1,29 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { Action } from "readium-desktop/common/models/redux"; +import { IAnnotationState } from "readium-desktop/common/redux/states/renderer/annotation"; +import { v4 as uuidv4 } from "uuid"; + +export const ID = "READER_ANNOTATIONS_PUSH"; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface IPayload extends IAnnotationState { +} + +export function build(param: Omit & Partial>): + Action { + + param.uuid = param.uuid || uuidv4(); + + return { + type: ID, + payload: {...param} as IAnnotationState, + }; +} +build.toString = () => ID; // Redux StringableActionCreator +export type TAction = ReturnType; diff --git a/src/common/redux/actions/reader/annotations/update.ts b/src/common/redux/actions/reader/annotations/update.ts new file mode 100644 index 000000000..78347256a --- /dev/null +++ b/src/common/redux/actions/reader/annotations/update.ts @@ -0,0 +1,26 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { Action } from "readium-desktop/common/models/redux"; +import { IAnnotationState } from "readium-desktop/common/redux/states/renderer/annotation"; + +export const ID = "READER_ANNOTATIONS_UPDATE"; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +// interface IPayload extends Pick { +interface IPayload extends IAnnotationState { +} +export function build(param: IAnnotationState): + Action { + + return { + type: ID, + payload: param, + }; +} +build.toString = () => ID; // Redux StringableActionCreator +export type TAction = ReturnType; diff --git a/src/common/redux/actions/reader/bookmarks/index.ts b/src/common/redux/actions/reader/bookmarks/index.ts new file mode 100644 index 000000000..b162bd31e --- /dev/null +++ b/src/common/redux/actions/reader/bookmarks/index.ts @@ -0,0 +1,16 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import * as pop from "./pop"; +import * as push from "./push"; +import * as update from "./update"; + +export { + push, + pop, + update, +}; diff --git a/src/renderer/reader/redux/actions/bookmarks/pop.ts b/src/common/redux/actions/reader/bookmarks/pop.ts similarity index 100% rename from src/renderer/reader/redux/actions/bookmarks/pop.ts rename to src/common/redux/actions/reader/bookmarks/pop.ts diff --git a/src/renderer/reader/redux/actions/bookmarks/push.ts b/src/common/redux/actions/reader/bookmarks/push.ts similarity index 100% rename from src/renderer/reader/redux/actions/bookmarks/push.ts rename to src/common/redux/actions/reader/bookmarks/push.ts diff --git a/src/renderer/reader/redux/actions/bookmarks/update.ts b/src/common/redux/actions/reader/bookmarks/update.ts similarity index 100% rename from src/renderer/reader/redux/actions/bookmarks/update.ts rename to src/common/redux/actions/reader/bookmarks/update.ts diff --git a/src/common/redux/actions/reader/index.ts b/src/common/redux/actions/reader/index.ts index aa7c430b5..c2f9e69dc 100644 --- a/src/common/redux/actions/reader/index.ts +++ b/src/common/redux/actions/reader/index.ts @@ -19,6 +19,8 @@ import * as openError from "./openError"; import * as openRequest from "./openRequest"; import * as setReduxState from "./setReduxState"; import * as disableRTLFlip from "./rtlFlip"; +import * as bookmark from "./bookmarks"; +import * as annotation from "./annotations"; export { openRequest, @@ -35,4 +37,6 @@ export { fullScreenRequest, clipboardCopy, disableRTLFlip, + bookmark, + annotation, }; diff --git a/src/common/redux/actions/theme/index.ts b/src/common/redux/actions/theme/index.ts new file mode 100644 index 000000000..d3e0edd81 --- /dev/null +++ b/src/common/redux/actions/theme/index.ts @@ -0,0 +1,12 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import * as setTheme from "./setTheme"; + +export { + setTheme, +}; diff --git a/src/common/redux/actions/theme/setTheme.ts b/src/common/redux/actions/theme/setTheme.ts new file mode 100644 index 000000000..238fb6e00 --- /dev/null +++ b/src/common/redux/actions/theme/setTheme.ts @@ -0,0 +1,27 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { Action } from "readium-desktop/common/models/redux"; +import { TTheme } from "../../states/theme"; + +export const ID = "SET_APP_THEME"; + +export interface Payload { + name: TTheme; +} + +export function build(theme: TTheme): Action { + + return { + type: ID, + payload: { + name: theme, + }, + }; +} +build.toString = () => ID; // Redux StringableActionCreator +export type TAction = ReturnType; diff --git a/src/common/redux/reducers/theme.ts b/src/common/redux/reducers/theme.ts new file mode 100644 index 000000000..f248a057d --- /dev/null +++ b/src/common/redux/reducers/theme.ts @@ -0,0 +1,25 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { type Reducer } from "redux"; + +import { themeActions } from "../actions"; +import { ITheme } from "../states/theme"; + +function themeReducer_( + state: ITheme = {name: "system"}, + action: themeActions.setTheme.TAction, +): ITheme { + switch (action.type) { + case themeActions.setTheme.ID: + return {name: action.payload.name}; + default: + return state; + } +} + +export const themeReducer = themeReducer_ as Reducer>; diff --git a/src/common/redux/reducers/winModeReducer.ts b/src/common/redux/reducers/winModeReducer.ts index 2ec3ccfeb..13039b8c4 100644 --- a/src/common/redux/reducers/winModeReducer.ts +++ b/src/common/redux/reducers/winModeReducer.ts @@ -10,7 +10,7 @@ import { type Reducer } from "redux"; import { ReaderMode } from "readium-desktop/common/models/reader"; import { readerActions } from "readium-desktop/common/redux/actions"; -const initialState: ReaderMode = ReaderMode.Attached; +const initialState: ReaderMode = ReaderMode.Detached; function winModeReducer_( state: ReaderMode = initialState, diff --git a/src/common/redux/states/commonRootState.ts b/src/common/redux/states/commonRootState.ts index eeb50f800..573aceb9f 100644 --- a/src/common/redux/states/commonRootState.ts +++ b/src/common/redux/states/commonRootState.ts @@ -9,6 +9,7 @@ import { ISessionState } from "readium-desktop/common/redux/states/session"; import { IRTLFlipState } from "readium-desktop/common/redux/states/renderer/rtlFlip"; import { IKeyboardState } from "readium-desktop/common/redux/states/keyboard"; import { ReaderConfig } from "readium-desktop/common/models/reader"; +import { ITheme } from "./theme"; export interface ICommonRootState { session: ISessionState @@ -17,4 +18,5 @@ export interface ICommonRootState { defaultConfig: ReaderConfig, disableRTLFlip: IRTLFlipState, }; + theme: ITheme; } diff --git a/src/common/redux/states/reader.ts b/src/common/redux/states/reader.ts index 550b4fd6c..b544e2761 100644 --- a/src/common/redux/states/reader.ts +++ b/src/common/redux/states/reader.ts @@ -7,15 +7,32 @@ import { ReaderConfig } from "readium-desktop/common/models/reader"; import { FONT_ID_DEFAULT } from "readium-desktop/utils/fontList"; +import { IAnnotationReaderConfigState, IColor } from "./renderer/annotation"; + +export const DEFAULT_COLOR_ANNOTATION: IColor = {red: 235, green: 150, blue: 148}; + +export const readerConfigInitialStateDefaultPublisher = { + font: FONT_ID_DEFAULT, + fontSize: "100%", + pageMargins: "0.5", + wordSpacing: "0", + letterSpacing: "0", + paraSpacing: "0", + lineHeight: "0", +}; + +export const readerConfigInitialStateAnnotation: IAnnotationReaderConfigState = { + annotation_defaultColor: DEFAULT_COLOR_ANNOTATION, + annotation_defaultDrawType: "solid_background", + annotation_popoverNotOpenOnNoteTaking: false, + annotation_defaultDrawView: "annotation", +}; export const readerConfigInitialState: ReaderConfig = { align: "auto", colCount: "auto", dark: false, - font: FONT_ID_DEFAULT, - fontSize: "100%", invert: false, - lineHeight: "0", night: false, paged: true, // https://github.com/edrlab/thorium-reader/issues/1222 readiumcss: true, @@ -24,13 +41,11 @@ export const readerConfigInitialState: ReaderConfig = { reduceMotion: false, noFootnotes: false, noRuby: false, - pageMargins: "0.5", - wordSpacing: "0", - letterSpacing: "0", - paraSpacing: "0", darken: undefined, mediaOverlaysEnableSkippability: true, ttsEnableSentenceDetection: true, mediaOverlaysEnableCaptionsMode: false, ttsEnableOverlayMode: false, + ...readerConfigInitialStateDefaultPublisher, + ...readerConfigInitialStateAnnotation, }; diff --git a/src/common/redux/states/renderer/annotation.ts b/src/common/redux/states/renderer/annotation.ts new file mode 100644 index 000000000..7f378bea5 --- /dev/null +++ b/src/common/redux/states/renderer/annotation.ts @@ -0,0 +1,41 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import { LocatorExtended } from "r2-navigator-js/dist/es8-es2017/src/electron/renderer"; +import { TPQueueState } from "readium-desktop/utils/redux-reducers/pqueue.reducer"; + +export interface IColor { + red: number; + green: number; + blue: number; +} + +export type TDrawType = "solid_background" | "underline" | "strikethrough" | "outline"; + +export interface IAnnotationState { + uuid: string; + locatorExtended: LocatorExtended; + comment: string; + color: IColor; + drawType: TDrawType; +} + +export type TAnnotationState = TPQueueState; + +export interface IAnnotationModeState { + enable: boolean, + cleanText: string, +} + +export type TDrawView = "annotation" | "margin"; + +export interface IAnnotationReaderConfigState { + annotation_popoverNotOpenOnNoteTaking: boolean, + annotation_defaultColor: IColor, + annotation_defaultDrawType: TDrawType + annotation_defaultDrawView: TDrawView +} diff --git a/src/common/redux/states/renderer/highlight.ts b/src/common/redux/states/renderer/highlight.ts index bd53e2ba1..53fc42d99 100644 --- a/src/common/redux/states/renderer/highlight.ts +++ b/src/common/redux/states/renderer/highlight.ts @@ -13,12 +13,12 @@ export interface IHighlightBaseState { export interface IHighlightHandlerState extends IHighlightBaseState { href: string; - type: "search" | "annotation"; + // type: "search" | "annotation"; def: IHighlightDefinition; } export interface IHighlightMounterState extends IHighlightBaseState { href: string; - type: IHighlightHandlerState["type"]; + // type: IHighlightHandlerState["type"]; ref: IHighlight; } diff --git a/src/common/redux/states/renderer/picker.ts b/src/common/redux/states/renderer/picker.ts index 00bddd8bb..00b1880e9 100644 --- a/src/common/redux/states/renderer/picker.ts +++ b/src/common/redux/states/renderer/picker.ts @@ -7,5 +7,5 @@ export interface IPickerState { open: boolean; - type: "search" | "annotation"; + type: "search"; } diff --git a/src/common/redux/states/renderer/readerRootState.ts b/src/common/redux/states/renderer/readerRootState.ts index 8c0473565..fda120dff 100644 --- a/src/common/redux/states/renderer/readerRootState.ts +++ b/src/common/redux/states/renderer/readerRootState.ts @@ -18,12 +18,14 @@ import { LocatorExtended } from "@r2-navigator-js/electron/renderer"; import { TBookmarkState } from "../bookmark"; import { IRTLFlipState } from "./rtlFlip"; +import { IAnnotationModeState, TAnnotationState } from "./annotation"; export interface IReaderRootState extends IRendererCommonRootState { reader: IReaderStateReader; picker: IPickerState; search: ISearchState; mode: ReaderMode; + annotation: IAnnotationModeState; } export interface IReaderStateReader { @@ -31,6 +33,7 @@ export interface IReaderStateReader { info: ReaderInfo; locator: LocatorExtended; bookmark: TBookmarkState; + annotation: TAnnotationState; highlight: { handler: TMapState; mounter: TMapState; diff --git a/src/common/redux/states/theme.ts b/src/common/redux/states/theme.ts new file mode 100644 index 000000000..55d8ccf18 --- /dev/null +++ b/src/common/redux/states/theme.ts @@ -0,0 +1,13 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +export type TTheme = "system" | "dark" | "light"; + +export interface ITheme { + name: TTheme, +} +export const themesList: Array = ["system", "dark", "light"]; diff --git a/src/common/views/catalog.ts b/src/common/views/catalog.ts index 667de904c..0300b355b 100644 --- a/src/common/views/catalog.ts +++ b/src/common/views/catalog.ts @@ -8,7 +8,7 @@ import { PublicationView } from "./publication"; export interface CatalogEntryView { - title: string; + id: "continueReading" | "lastAdditions" | "continueReadingAudioBooks" | "continueReadingDivina" | "continueReadingPdf"; tag?: string; totalCount?: number; publicationViews?: PublicationView[]; diff --git a/src/main/redux/middleware/persistence.ts b/src/main/redux/middleware/persistence.ts index 55f1df5da..b6ee5ce76 100644 --- a/src/main/redux/middleware/persistence.ts +++ b/src/main/redux/middleware/persistence.ts @@ -26,6 +26,7 @@ export const reduxPersistMiddleware: Middleware const nextState = store.getState(); const persistPrevState: PersistRootState = { + theme: prevState.theme, win: prevState.win, reader: prevState.reader, i18n: prevState.i18n, @@ -39,6 +40,7 @@ export const reduxPersistMiddleware: Middleware }; const persistNextState: PersistRootState = { + theme: nextState.theme, win: nextState.win, reader: nextState.reader, i18n: nextState.i18n, diff --git a/src/main/redux/middleware/sync.ts b/src/main/redux/middleware/sync.ts index 0e5900253..49da7ebfa 100644 --- a/src/main/redux/middleware/sync.ts +++ b/src/main/redux/middleware/sync.ts @@ -10,7 +10,7 @@ import { syncIpc } from "readium-desktop/common/ipc"; import { ActionWithSender, SenderType } from "readium-desktop/common/models/sync"; import { apiActions, authActions, catalogActions, dialogActions, downloadActions, historyActions, i18nActions, keyboardActions, lcpActions, - readerActions, sessionActions, toastActions, + readerActions, sessionActions, themeActions, toastActions, } from "readium-desktop/common/redux/actions"; import { ActionSerializer } from "readium-desktop/common/services/serializer"; import { getLibraryWindowFromDi, getReaderWindowFromDi } from "readium-desktop/main/di"; @@ -64,6 +64,15 @@ const SYNCHRONIZABLE_ACTIONS: string[] = [ readerActions.disableRTLFlip.ID, readerActions.configSetDefault.ID, // readerConfig + themeActions.setTheme.ID, + + readerActions.bookmark.pop.ID, + readerActions.bookmark.push.ID, + readerActions.bookmark.update.ID, + + readerActions.annotation.pop.ID, + readerActions.annotation.push.ID, + readerActions.annotation.update.ID, ]; export const reduxSyncMiddleware: Middleware diff --git a/src/main/redux/reducers/index.ts b/src/main/redux/reducers/index.ts index 007f38a1c..05fa8e9a6 100644 --- a/src/main/redux/reducers/index.ts +++ b/src/main/redux/reducers/index.ts @@ -25,9 +25,11 @@ import { readerRTLFlipReducer } from "../../../common/redux/reducers/reader/rtlF import { publicationDbReducers } from "./publication/db"; import { opdsDbReducers } from "./opds/db"; import { _APP_VERSION } from "readium-desktop/preprocessor-directives"; +import { themeReducer } from "readium-desktop/common/redux/reducers/theme"; import { ActionWithSender } from "readium-desktop/common/models/sync"; export const rootReducer = combineReducers({ // RootState + theme: themeReducer, session: sessionReducer, streamer: streamerReducer, i18n: i18nReducer, diff --git a/src/main/redux/sagas/auth.ts b/src/main/redux/sagas/auth.ts index 694a40850..4917d64a1 100644 --- a/src/main/redux/sagas/auth.ts +++ b/src/main/redux/sagas/auth.ts @@ -483,6 +483,8 @@ function getHtmlAuthenticationUrl(auth: IOPDSAuthDocParsed) { auth.labels?.password, auth.title, auth.logo?.url, + auth.register?.url, + auth.help, auth.nonce, auth.qop, auth.algorithm, @@ -518,6 +520,10 @@ interface IOPDSAuthDocParsed { logo?: IOpdsLinkView | undefined; + register?: IOpdsLinkView | undefined; + + help?: string[] | undefined; + // digest authentication // see IWWWAuthenticateDataParsed nonce?: string, @@ -583,7 +589,7 @@ function opdsAuthDocConverter(doc: OPDSAuthenticationDoc, baseUrl: string): IOPD const logo = tryCatchSync(() => { const ln = Array.isArray(doc.Links) ? doc.Links.find((v) => { - debug(v); + // debug(v); return (v.Rel || []).includes("logo"); }) : undefined; @@ -595,6 +601,37 @@ function opdsAuthDocConverter(doc: OPDSAuthenticationDoc, baseUrl: string): IOPD }, filename_); + const register = tryCatchSync(() => { + const ln = Array.isArray(doc.Links) + ? doc.Links.find((v) => { + // debug(v); + return (v.Rel || []).includes("register"); + }) + : undefined; + if (ln) { + const linkView = viewConvert.convertLinkToView(ln, baseUrl); + return linkView; + } + return undefined; + + }, filename_); + + const helpLinkView = tryCatchSync(() => { + const ln = Array.isArray(doc.Links) + ? doc.Links.filter((v) => { + // debug(v); + return (v.Rel || []).includes("help"); + }) + : []; + if (ln) { + const linksView = ln.map((lnItem) => viewConvert.convertLinkToView(lnItem, baseUrl)); + return linksView; + } + return undefined; + + }, filename_); + const helpStringArray = helpLinkView.map((item) => item.url); + return { title: doc.Title || "", id: doc.Id || "", @@ -602,6 +639,8 @@ function opdsAuthDocConverter(doc: OPDSAuthenticationDoc, baseUrl: string): IOPD links, labels, logo, + register, + help: helpStringArray, nonce: typeof authentication.AdditionalJSON?.nonce === "string" ? authentication.AdditionalJSON.nonce : undefined, algorithm: typeof authentication.AdditionalJSON?.algorithm === "string" ? authentication.AdditionalJSON.algorithm : undefined, qop: typeof authentication.AdditionalJSON?.qop === "string" ? authentication.AdditionalJSON.qop : undefined, @@ -753,13 +792,29 @@ function parseRequestFromCustomProtocol(req: Electron.ProtocolRequest) return undefined; } +const AvatarIcon = ` + +`; + +const PasswordIcon = ` + +`; + +const AddIcon = " image/svg+xml "; + +const LoginIcon = ` + +`; + // tslint:disable-next-line: max-line-length const htmlLoginTemplate = ( urlToSubmit = "", - loginLabel = "login", - passLabel = "password", + loginLabel = diMainGet("translator").translate("catalog.opds.auth.username"), + passLabel = diMainGet("translator").translate("catalog.opds.auth.password"), title: string | undefined, logoUrl?: string, + registerUrl?: string, + help?: string[], nonce?: string, qop?: string, algorithm?: string, @@ -770,216 +825,394 @@ const htmlLoginTemplate = ( } return ` - - - - - - - - - ${title} - - - - - - - - - -`; + input[type=submit]:hover + label svg { + fill: #1053C8; + } + + input[type=button]:hover { + background: white; + } + + .lt-ie9 input[type=text], .lt-ie9 input[type=password] { + line-height: 34px; + } + + + + + + + + `; }; diff --git a/src/main/redux/sagas/catalog.ts b/src/main/redux/sagas/catalog.ts index e74e87d45..e13e36d10 100644 --- a/src/main/redux/sagas/catalog.ts +++ b/src/main/redux/sagas/catalog.ts @@ -17,11 +17,11 @@ import { PublicationDocument } from "readium-desktop/main/db/document/publicatio import { ToastType } from "readium-desktop/common/models/toast"; import { publicationApi } from "./api"; import { diMainGet } from "readium-desktop/main/di"; -import { isAudiobookFn, isDivinaFn, isPdfFn } from "readium-desktop/common/isManifestType"; +// import { isPdfFn } from "readium-desktop/common/isManifestType"; -import { PublicationView } from "readium-desktop/common/views/publication"; -import { TaJsonDeserialize } from "@r2-lcp-js/serializable"; -import { Publication as R2Publication } from "@r2-shared-js/models/publication"; +// import { PublicationView } from "readium-desktop/common/views/publication"; +// import { TaJsonDeserialize } from "@r2-lcp-js/serializable"; +// import { Publication as R2Publication } from "@r2-shared-js/models/publication"; import { CatalogEntryView } from "readium-desktop/common/views/catalog"; import { aboutFiltered } from "readium-desktop/main/tools/filter"; import { publicationActions } from "../actions"; @@ -32,28 +32,28 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ const filename_ = "readium-desktop:main:redux:sagas:catalog"; const debug = debug_(filename_); -const NB_PUB = 5; +const NB_PUB = 10; // TODO: this memo-ization is very expensive (memory and CPU-wise) ... // and TaJsonDeserialize() is called in several other places in the library lifecycle // (including below via convertDocumentToView()) // so it would make sense to hoist the cache higher in the application architecture -const viewToR2Pub = (view: PublicationView) => { - // Legacy Base64 data blobs - // const r2PublicationStr = Buffer.from(view.r2PublicationBase64, "base64").toString("utf-8"); - // const r2PublicationJson = JSON.parse(r2PublicationStr); - const r2Publication = TaJsonDeserialize(view.r2PublicationJson, R2Publication); - - return r2Publication; -}; -const _pdfMemo: {[str: string]: boolean} = {}; -const isPdfMemo = (view: PublicationView): boolean => { - if (typeof _pdfMemo[view.identifier] === "undefined") { - const r2Publication = viewToR2Pub(view); - _pdfMemo[view.identifier] = isPdfFn(r2Publication); - } - return _pdfMemo[view.identifier]; -}; +// const viewToR2Pub = (view: PublicationView) => { +// // Legacy Base64 data blobs +// // const r2PublicationStr = Buffer.from(view.r2PublicationBase64, "base64").toString("utf-8"); +// // const r2PublicationJson = JSON.parse(r2PublicationStr); +// const r2Publication = TaJsonDeserialize(view.r2PublicationJson, R2Publication); + +// return r2Publication; +// }; +// const _pdfMemo: {[str: string]: boolean} = {}; +// const isPdfMemo = (view: PublicationView): boolean => { +// if (typeof _pdfMemo[view.identifier] === "undefined") { +// const r2Publication = viewToR2Pub(view); +// _pdfMemo[view.identifier] = isPdfFn(r2Publication); +// } +// return _pdfMemo[view.identifier]; +// }; const getLastAddedPublicationDocument = async (publicationRepository: PublicationRepository) => { @@ -129,37 +129,37 @@ function* getPublicationView() { } } - const audio = { - readed: lastReadedPublicationsView.filter(isAudiobookFn), - added: lastAddedPublicationsView.filter(isAudiobookFn), - }; + // const audio = { + // readed: lastReadedPublicationsView.filter(isAudiobookFn), + // added: lastAddedPublicationsView.filter(isAudiobookFn), + // }; - const divina = { - readed: lastReadedPublicationsView.filter(isDivinaFn), - added: lastAddedPublicationsView.filter(isDivinaFn), - }; + // const divina = { + // readed: lastReadedPublicationsView.filter(isDivinaFn), + // added: lastAddedPublicationsView.filter(isDivinaFn), + // }; - const pdf = { - readed: lastReadedPublicationsView.filter( - (view: PublicationView) => { - return isPdfMemo(view); - }), - added: lastAddedPublicationsView.filter( - (view: PublicationView) => { - return isPdfMemo(view); - }), - }; + // const pdf = { + // readed: lastReadedPublicationsView.filter( + // (view: PublicationView) => { + // return isPdfMemo(view); + // }), + // added: lastAddedPublicationsView.filter( + // (view: PublicationView) => { + // return isPdfMemo(view); + // }), + // }; - const epub = { - readed: lastReadedPublicationsView.filter( - (view: PublicationView) => { - return !isAudiobookFn(view) && !isDivinaFn(view) && !isPdfMemo(view); - }), - added: lastAddedPublicationsView.filter( - (view: PublicationView) => { - return !isAudiobookFn(view) && !isDivinaFn(view) && !isPdfMemo(view); - }), - }; + // const epub = { + // readed: lastReadedPublicationsView.filter( + // (view: PublicationView) => { + // return !isAudiobookFn(view) && !isDivinaFn(view) && !isPdfMemo(view); + // }), + // added: lastAddedPublicationsView.filter( + // (view: PublicationView) => { + // return !isAudiobookFn(view) && !isDivinaFn(view) && !isPdfMemo(view); + // }), + // }; const all = { readed: lastReadedPublicationsView, @@ -167,10 +167,10 @@ function* getPublicationView() { }; return { - audio, - epub, - divina, - pdf, + // audio, + // epub, + // divina, + // pdf, all, }; } @@ -180,63 +180,68 @@ function* getPublicationView() { export function* getCatalog(): SagaGenerator { debug("getCatalog"); - const translator = diMainGet("translator"); - const __ = translator.translate.bind(translator); - const { - audio: { - readed: audiobookReaded, - }, - divina: { - readed: divinaReaded, - }, - epub: { - readed: epubReaded, - }, - pdf: { - readed: pdfReaded, - }, + // audio: { + // readed: audiobookReaded, + // }, + // divina: { + // readed: divinaReaded, + // }, + // epub: { + // readed: epubReaded, + // }, + // pdf: { + // readed: pdfReaded, + // }, all: { added: allAdded, + readed: allReaded, }, } = yield* callTyped(getPublicationView); const _allAdded = aboutFiltered(allAdded); - const _epubReaded = aboutFiltered(epubReaded); + const _allReaded = aboutFiltered(allReaded); + // const _epubReaded = aboutFiltered(epubReaded); const allAdded_ = _allAdded.slice(0, NB_PUB); - const epubReaded_ = _epubReaded.slice(0, NB_PUB); - const audiobookReaded_ = audiobookReaded.slice(0, NB_PUB); - const divinaReaded_ = divinaReaded.slice(0, NB_PUB); - const pdfReaded_ = pdfReaded.slice(0, NB_PUB); + const allReaded_ = _allReaded.slice(0, NB_PUB); + // const epubReaded_ = _epubReaded.slice(0, NB_PUB); + // const audiobookReaded_ = audiobookReaded.slice(0, NB_PUB); + // const divinaReaded_ = divinaReaded.slice(0, NB_PUB); + // const pdfReaded_ = pdfReaded.slice(0, NB_PUB); // Dynamic entries const entries: CatalogEntryView[] = [ { - title: __("catalog.entry.lastAdditions"), - totalCount: allAdded_.length, - publicationViews: allAdded_, - }, - { - title: __("catalog.entry.continueReading"), - totalCount: epubReaded_.length, - publicationViews: epubReaded_, + id: "continueReading", + totalCount: allReaded.length, + publicationViews: allReaded_, }, { - title: __("catalog.entry.continueReadingAudioBooks"), - totalCount: audiobookReaded_.length, - publicationViews: audiobookReaded_, - }, - { - title: __("catalog.entry.continueReadingDivina"), - totalCount: divinaReaded_.length, - publicationViews: divinaReaded_, - }, - { - title: __("catalog.entry.continueReadingPdf"), - totalCount: pdfReaded_.length, - publicationViews: pdfReaded_, + id: "lastAdditions", + totalCount: allAdded_.length, + publicationViews: allAdded_, }, + // { + // id: "continueReading", + // totalCount: epubReaded_.length, + // publicationViews: epubReaded_, + // }, + // { + // id: "continueReadingAudioBooks", + // totalCount: audiobookReaded_.length, + // publicationViews: audiobookReaded_, + // }, + // { + // id: "continueReadingDivina", + // totalCount: divinaReaded_.length, + // publicationViews: divinaReaded_, + // }, + // { + // id: "continueReadingPdf", + // totalCount: pdfReaded_.length, + // publicationViews: pdfReaded_, + // }, ]; const publicationRepository = diMainGet("publication-repository"); const allTags = yield* callTyped(() => publicationRepository.getAllTags()); diff --git a/src/main/redux/sagas/persist.ts b/src/main/redux/sagas/persist.ts index 6969888bb..06a52adce 100644 --- a/src/main/redux/sagas/persist.ts +++ b/src/main/redux/sagas/persist.ts @@ -32,6 +32,7 @@ const persistStateToFs = async (nextState: RootState) => { debug("start of persist reduxState in disk"); const value: PersistRootState = { + theme: nextState.theme, win: nextState.win, publication: nextState.publication, reader: nextState.reader, diff --git a/src/main/redux/sagas/win/browserWindow/createLibraryWindow.ts b/src/main/redux/sagas/win/browserWindow/createLibraryWindow.ts index 887e5ac74..2c6323ce8 100644 --- a/src/main/redux/sagas/win/browserWindow/createLibraryWindow.ts +++ b/src/main/redux/sagas/win/browserWindow/createLibraryWindow.ts @@ -22,6 +22,7 @@ import { put } from "redux-saga/effects"; import { call as callTyped, select as selectTyped } from "typed-redux-saga/macro"; import { contextMenuSetup } from "@r2-navigator-js/electron/main/browser-window-tracker"; +import { WINDOW_MIN_HEIGHT, WINDOW_MIN_WIDTH } from "readium-desktop/common/constant"; // Logger const debug = debug_("readium-desktop:createLibraryWindow"); @@ -45,8 +46,8 @@ export function* createLibraryWindow(_action: winActions.library.openRequest.TAc libWindow = new BrowserWindow({ ...windowBound, - minWidth: 800, - minHeight: 600, + minWidth: WINDOW_MIN_WIDTH, + minHeight: WINDOW_MIN_HEIGHT, webPreferences: { // enableRemoteModule: false, allowRunningInsecureContent: false, diff --git a/src/main/redux/sagas/win/browserWindow/createReaderWindow.ts b/src/main/redux/sagas/win/browserWindow/createReaderWindow.ts index 08edc57c4..06ae984f4 100644 --- a/src/main/redux/sagas/win/browserWindow/createReaderWindow.ts +++ b/src/main/redux/sagas/win/browserWindow/createReaderWindow.ts @@ -21,6 +21,7 @@ import { } from "@r2-navigator-js/electron/main/browser-window-tracker"; import { getPublication } from "../../api/publication/getPublication"; +import { WINDOW_MIN_HEIGHT, WINDOW_MIN_WIDTH } from "readium-desktop/common/constant"; // Logger const debug = debug_("readium-desktop:createReaderWindow"); @@ -34,8 +35,8 @@ export function* createReaderWindow(action: winActions.reader.openRequest.TActio const readerWindow = new BrowserWindow({ ...winBound, - minWidth: 600, - minHeight: 400, + minWidth: WINDOW_MIN_WIDTH, + minHeight: WINDOW_MIN_HEIGHT, webPreferences: { // enableRemoteModule: false, allowRunningInsecureContent: false, diff --git a/src/main/redux/sagas/win/library.ts b/src/main/redux/sagas/win/library.ts index 359bc0b20..4033d8631 100644 --- a/src/main/redux/sagas/win/library.ts +++ b/src/main/redux/sagas/win/library.ts @@ -96,6 +96,7 @@ function* winOpen(action: winActions.library.openSucess.TAction) { const state = yield* selectTyped((_state: RootState) => _state); const payload: Partial = { + theme: state.theme, win: { identifier, }, diff --git a/src/main/redux/sagas/win/reader.ts b/src/main/redux/sagas/win/reader.ts index 78bb25b8c..882e7605b 100644 --- a/src/main/redux/sagas/win/reader.ts +++ b/src/main/redux/sagas/win/reader.ts @@ -9,7 +9,6 @@ import * as debug_ from "debug"; import { readerIpc } from "readium-desktop/common/ipc"; import { ReaderMode } from "readium-desktop/common/models/reader"; import { normalizeRectangle } from "readium-desktop/common/rectangle/window"; -import { readerActions } from "readium-desktop/common/redux/actions"; import { takeSpawnEvery } from "readium-desktop/common/redux/sagas/takeSpawnEvery"; import { getLibraryWindowFromDi, getReaderWindowFromDi } from "readium-desktop/main/di"; import { error } from "readium-desktop/main/tools/error"; @@ -38,6 +37,7 @@ function* winOpen(action: winActions.reader.openSucess.TAction) { const reader = yield* selectTyped((_state: RootState) => _state.win.session.reader[identifier]); const keyboard = yield* selectTyped((_state: RootState) => _state.keyboard); const mode = yield* selectTyped((state: RootState) => state.mode); + const theme = yield* selectTyped((state: RootState) => state.theme); webContents.send(readerIpc.CHANNEL, { type: readerIpc.EventType.request, @@ -51,6 +51,7 @@ function* winOpen(action: winActions.reader.openSucess.TAction) { reader: reader?.reduxState, keyboard, mode, + theme, }, } as readerIpc.EventPayload); } @@ -92,7 +93,9 @@ function* winClose(action: winActions.reader.closed.TAction) { const mode = yield* selectTyped((state: RootState) => state.mode); if (mode === ReaderMode.Detached) { - yield put(readerActions.attachModeRequest.build()); + + // disabled for the new UI refactoring by choice of the designer + // yield put(readerActions.attachModeRequest.build()); } else { const readerWin = yield* callTyped(() => getReaderWindowFromDi(identifier)); diff --git a/src/main/redux/states/index.ts b/src/main/redux/states/index.ts index e706c5fdd..88f28371c 100644 --- a/src/main/redux/states/index.ts +++ b/src/main/redux/states/index.ts @@ -49,4 +49,4 @@ export interface RootState extends ICommonRootState { } -export type PersistRootState = Pick; +export type PersistRootState = Pick; diff --git a/src/main/redux/store/memory.ts b/src/main/redux/store/memory.ts index cee69d85c..8f9655415 100644 --- a/src/main/redux/store/memory.ts +++ b/src/main/redux/store/memory.ts @@ -22,6 +22,8 @@ import createSagaMiddleware, { SagaMiddleware } from "redux-saga"; import { applyPatch } from "rfc6902"; import { reduxPersistMiddleware } from "../middleware/persistence"; +import { readerConfigInitialState } from "readium-desktop/common/redux/states/reader"; +import { defaultDisableRTLFLip } from "readium-desktop/common/redux/states/renderer/rtlFlip"; // import { composeWithDevTools } from "remote-redux-devtools"; const REDUX_REMOTE_DEVTOOLS_PORT = 7770; @@ -203,9 +205,21 @@ export async function initStore() debug("REDUX STATE VALUE :: ", typeof reduxState, reduxState ? Object.keys(reduxState) : "nil"); // debug(reduxState); + const forceDisableReaderDefaultConfigAndSessionForTheNewUI: Partial = { + reader: { + defaultConfig: readerConfigInitialState, + disableRTLFlip: reduxState?.reader?.disableRTLFlip || { disabled: defaultDisableRTLFLip }, + }, + session: { + state: true, + }, + }; const preloadedState = reduxState ? { ...reduxState, - } : {}; + ...forceDisableReaderDefaultConfigAndSessionForTheNewUI, + } : { + ...forceDisableReaderDefaultConfigAndSessionForTheNewUI, + }; const sagaMiddleware = createSagaMiddleware(); @@ -224,7 +238,7 @@ export async function initStore() const store = createStore( rootReducer, - preloadedState, + preloadedState as {}, middleware, ); diff --git a/src/renderer/assets/fonts/NunitoSans_10pt-Regular.ttf b/src/renderer/assets/fonts/NunitoSans_10pt-Regular.ttf new file mode 100644 index 000000000..50cb31274 Binary files /dev/null and b/src/renderer/assets/fonts/NunitoSans_10pt-Regular.ttf differ diff --git a/src/renderer/assets/fonts/NunitoSans_10pt-SemiBold.ttf b/src/renderer/assets/fonts/NunitoSans_10pt-SemiBold.ttf new file mode 100644 index 000000000..78334352e Binary files /dev/null and b/src/renderer/assets/fonts/NunitoSans_10pt-SemiBold.ttf differ diff --git a/src/renderer/assets/icons/.unused-icons/Scrollable-icon.svg b/src/renderer/assets/icons/.unused-icons/Scrollable-icon.svg new file mode 100644 index 000000000..f4761a01d --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/Scrollable-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/renderer/assets/icons/add.svg b/src/renderer/assets/icons/.unused-icons/add.svg similarity index 100% rename from src/renderer/assets/icons/add.svg rename to src/renderer/assets/icons/.unused-icons/add.svg diff --git a/src/renderer/assets/icons/.unused-icons/alt-icon.svg b/src/renderer/assets/icons/.unused-icons/alt-icon.svg new file mode 100644 index 000000000..27a7cfdbf --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/alt-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/arrow-clockwise.svg b/src/renderer/assets/icons/.unused-icons/arrow-clockwise.svg similarity index 100% rename from src/renderer/assets/icons/arrow-clockwise.svg rename to src/renderer/assets/icons/.unused-icons/arrow-clockwise.svg diff --git a/src/renderer/assets/icons/arrow-left.svg b/src/renderer/assets/icons/.unused-icons/arrow-left.svg similarity index 100% rename from src/renderer/assets/icons/arrow-left.svg rename to src/renderer/assets/icons/.unused-icons/arrow-left.svg diff --git a/src/renderer/assets/icons/arrow.svg b/src/renderer/assets/icons/.unused-icons/arrow.svg similarity index 100% rename from src/renderer/assets/icons/arrow.svg rename to src/renderer/assets/icons/.unused-icons/arrow.svg diff --git a/src/renderer/assets/icons/auto.svg b/src/renderer/assets/icons/.unused-icons/auto.svg similarity index 100% rename from src/renderer/assets/icons/auto.svg rename to src/renderer/assets/icons/.unused-icons/auto.svg diff --git a/src/renderer/assets/icons/baseline-arrow_back-24px-grey.svg b/src/renderer/assets/icons/.unused-icons/baseline-arrow_back-24px-grey.svg similarity index 100% rename from src/renderer/assets/icons/baseline-arrow_back-24px-grey.svg rename to src/renderer/assets/icons/.unused-icons/baseline-arrow_back-24px-grey.svg diff --git a/src/renderer/assets/icons/baseline-arrow_back-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-arrow_back-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-arrow_back-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-arrow_back-24px.svg diff --git a/src/renderer/assets/icons/baseline-close-24px-blue.svg b/src/renderer/assets/icons/.unused-icons/baseline-close-24px-blue.svg similarity index 100% rename from src/renderer/assets/icons/baseline-close-24px-blue.svg rename to src/renderer/assets/icons/.unused-icons/baseline-close-24px-blue.svg diff --git a/src/renderer/assets/icons/baseline-drag_handle-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-drag_handle-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-drag_handle-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-drag_handle-24px.svg diff --git a/src/renderer/assets/icons/baseline-edit-24px-grey.svg b/src/renderer/assets/icons/.unused-icons/baseline-edit-24px-grey.svg similarity index 100% rename from src/renderer/assets/icons/baseline-edit-24px-grey.svg rename to src/renderer/assets/icons/.unused-icons/baseline-edit-24px-grey.svg diff --git a/src/renderer/assets/icons/baseline-edit-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-edit-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-edit-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-edit-24px.svg diff --git a/src/renderer/assets/icons/baseline-list-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-list-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-list-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-list-24px.svg diff --git a/src/renderer/assets/icons/baseline-more_vert-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-more_vert-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-more_vert-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-more_vert-24px.svg diff --git a/src/renderer/assets/icons/baseline-pause-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-pause-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-pause-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-pause-24px.svg diff --git a/src/renderer/assets/icons/baseline-play_arrow-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-play_arrow-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-play_arrow-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-play_arrow-24px.svg diff --git a/src/renderer/assets/icons/baseline-remove-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-remove-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-remove-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-remove-24px.svg diff --git a/src/renderer/assets/icons/baseline-search-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-search-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-search-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-search-24px.svg diff --git a/src/renderer/assets/icons/baseline-skip_next-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-skip_next-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-skip_next-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-skip_next-24px.svg diff --git a/src/renderer/assets/icons/baseline-skip_previous-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-skip_previous-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-skip_previous-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-skip_previous-24px.svg diff --git a/src/renderer/assets/icons/baseline-stop-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-stop-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-stop-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-stop-24px.svg diff --git a/src/renderer/assets/icons/baseline-view_list-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-view_list-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-view_list-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-view_list-24px.svg diff --git a/src/renderer/assets/icons/baseline-view_module-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-view_module-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-view_module-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-view_module-24px.svg diff --git a/src/renderer/assets/icons/baseline-volume_up-24px.svg b/src/renderer/assets/icons/.unused-icons/baseline-volume_up-24px.svg similarity index 100% rename from src/renderer/assets/icons/baseline-volume_up-24px.svg rename to src/renderer/assets/icons/.unused-icons/baseline-volume_up-24px.svg diff --git a/src/renderer/assets/icons/chevron-bar-left.svg b/src/renderer/assets/icons/.unused-icons/chevron-bar-left.svg similarity index 100% rename from src/renderer/assets/icons/chevron-bar-left.svg rename to src/renderer/assets/icons/.unused-icons/chevron-bar-left.svg diff --git a/src/renderer/assets/icons/chevron-bar-right.svg b/src/renderer/assets/icons/.unused-icons/chevron-bar-right.svg similarity index 100% rename from src/renderer/assets/icons/chevron-bar-right.svg rename to src/renderer/assets/icons/.unused-icons/chevron-bar-right.svg diff --git a/src/renderer/assets/icons/.unused-icons/clockwise-icon.svg b/src/renderer/assets/icons/.unused-icons/clockwise-icon.svg new file mode 100644 index 000000000..b07687664 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/clockwise-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/colonne.svg b/src/renderer/assets/icons/.unused-icons/colonne.svg similarity index 100% rename from src/renderer/assets/icons/colonne.svg rename to src/renderer/assets/icons/.unused-icons/colonne.svg diff --git a/src/renderer/assets/icons/colonne2.svg b/src/renderer/assets/icons/.unused-icons/colonne2.svg similarity index 100% rename from src/renderer/assets/icons/colonne2.svg rename to src/renderer/assets/icons/.unused-icons/colonne2.svg diff --git a/src/renderer/assets/icons/content-table.svg b/src/renderer/assets/icons/.unused-icons/content-table.svg similarity index 100% rename from src/renderer/assets/icons/content-table.svg rename to src/renderer/assets/icons/.unused-icons/content-table.svg diff --git a/src/renderer/assets/icons/continue.svg b/src/renderer/assets/icons/.unused-icons/continue.svg similarity index 100% rename from src/renderer/assets/icons/continue.svg rename to src/renderer/assets/icons/.unused-icons/continue.svg diff --git a/src/renderer/assets/icons/defile.svg b/src/renderer/assets/icons/.unused-icons/defile.svg similarity index 100% rename from src/renderer/assets/icons/defile.svg rename to src/renderer/assets/icons/.unused-icons/defile.svg diff --git a/src/renderer/assets/icons/edit.svg b/src/renderer/assets/icons/.unused-icons/edit.svg similarity index 100% rename from src/renderer/assets/icons/edit.svg rename to src/renderer/assets/icons/.unused-icons/edit.svg diff --git a/src/renderer/assets/icons/eye.svg b/src/renderer/assets/icons/.unused-icons/eye.svg similarity index 100% rename from src/renderer/assets/icons/eye.svg rename to src/renderer/assets/icons/.unused-icons/eye.svg diff --git a/src/renderer/assets/icons/font-size.svg b/src/renderer/assets/icons/.unused-icons/font-size.svg similarity index 100% rename from src/renderer/assets/icons/font-size.svg rename to src/renderer/assets/icons/.unused-icons/font-size.svg diff --git a/src/renderer/assets/icons/gauche.svg b/src/renderer/assets/icons/.unused-icons/gauche.svg similarity index 100% rename from src/renderer/assets/icons/gauche.svg rename to src/renderer/assets/icons/.unused-icons/gauche.svg diff --git a/src/renderer/assets/icons/.unused-icons/gear.svg b/src/renderer/assets/icons/.unused-icons/gear.svg new file mode 100644 index 000000000..9950bff19 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/gear.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/gift.svg b/src/renderer/assets/icons/.unused-icons/gift.svg similarity index 100% rename from src/renderer/assets/icons/gift.svg rename to src/renderer/assets/icons/.unused-icons/gift.svg diff --git a/src/renderer/assets/icons/grid.svg b/src/renderer/assets/icons/.unused-icons/grid.svg similarity index 100% rename from src/renderer/assets/icons/grid.svg rename to src/renderer/assets/icons/.unused-icons/grid.svg diff --git a/src/renderer/assets/icons/home.svg b/src/renderer/assets/icons/.unused-icons/home.svg similarity index 96% rename from src/renderer/assets/icons/home.svg rename to src/renderer/assets/icons/.unused-icons/home.svg index ff750bb6a..1314c2b8e 100644 --- a/src/renderer/assets/icons/home.svg +++ b/src/renderer/assets/icons/.unused-icons/home.svg @@ -1,52 +1,52 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/house-fill.svg b/src/renderer/assets/icons/.unused-icons/house-fill.svg similarity index 100% rename from src/renderer/assets/icons/house-fill.svg rename to src/renderer/assets/icons/.unused-icons/house-fill.svg diff --git a/src/renderer/assets/icons/info.svg b/src/renderer/assets/icons/.unused-icons/info.svg similarity index 75% rename from src/renderer/assets/icons/info.svg rename to src/renderer/assets/icons/.unused-icons/info.svg index 5c09d08bd..c0cdf5ede 100644 --- a/src/renderer/assets/icons/info.svg +++ b/src/renderer/assets/icons/.unused-icons/info.svg @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/src/renderer/assets/icons/justifie.svg b/src/renderer/assets/icons/.unused-icons/justifie.svg similarity index 100% rename from src/renderer/assets/icons/justifie.svg rename to src/renderer/assets/icons/.unused-icons/justifie.svg diff --git a/src/renderer/assets/icons/landmark.svg b/src/renderer/assets/icons/.unused-icons/landmark.svg similarity index 100% rename from src/renderer/assets/icons/landmark.svg rename to src/renderer/assets/icons/.unused-icons/landmark.svg diff --git a/src/renderer/assets/icons/list.svg b/src/renderer/assets/icons/.unused-icons/list.svg similarity index 100% rename from src/renderer/assets/icons/list.svg rename to src/renderer/assets/icons/.unused-icons/list.svg diff --git a/src/renderer/assets/icons/.unused-icons/minus.svg b/src/renderer/assets/icons/.unused-icons/minus.svg new file mode 100644 index 000000000..088f5b4c1 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/minus.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/.unused-icons/minusBorder-icon.svg b/src/renderer/assets/icons/.unused-icons/minusBorder-icon.svg new file mode 100644 index 000000000..085c6d1bb --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/minusBorder-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/night.svg b/src/renderer/assets/icons/.unused-icons/night.svg similarity index 100% rename from src/renderer/assets/icons/night.svg rename to src/renderer/assets/icons/.unused-icons/night.svg diff --git a/src/renderer/assets/icons/opds.svg b/src/renderer/assets/icons/.unused-icons/opds.svg similarity index 100% rename from src/renderer/assets/icons/opds.svg rename to src/renderer/assets/icons/.unused-icons/opds.svg diff --git a/src/renderer/assets/icons/outline-bookmark-24px-grey.svg b/src/renderer/assets/icons/.unused-icons/outline-bookmark-24px-grey.svg similarity index 100% rename from src/renderer/assets/icons/outline-bookmark-24px-grey.svg rename to src/renderer/assets/icons/.unused-icons/outline-bookmark-24px-grey.svg diff --git a/src/renderer/assets/icons/outline-bookmark-24px.svg b/src/renderer/assets/icons/.unused-icons/outline-bookmark-24px.svg similarity index 100% rename from src/renderer/assets/icons/outline-bookmark-24px.svg rename to src/renderer/assets/icons/.unused-icons/outline-bookmark-24px.svg diff --git a/src/renderer/assets/icons/.unused-icons/outline-bookmark_border-24px.svg b/src/renderer/assets/icons/.unused-icons/outline-bookmark_border-24px.svg new file mode 100644 index 000000000..e62806903 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/outline-bookmark_border-24px.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/outline-restore-24px.svg b/src/renderer/assets/icons/.unused-icons/outline-restore-24px.svg similarity index 100% rename from src/renderer/assets/icons/outline-restore-24px.svg rename to src/renderer/assets/icons/.unused-icons/outline-restore-24px.svg diff --git a/src/renderer/assets/icons/page.svg b/src/renderer/assets/icons/.unused-icons/page.svg similarity index 100% rename from src/renderer/assets/icons/page.svg rename to src/renderer/assets/icons/.unused-icons/page.svg diff --git a/src/renderer/assets/icons/.unused-icons/paginated-icon.svg b/src/renderer/assets/icons/.unused-icons/paginated-icon.svg new file mode 100644 index 000000000..dc5cb55a0 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/paginated-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/renderer/assets/icons/pagine.svg b/src/renderer/assets/icons/.unused-icons/pagine.svg similarity index 100% rename from src/renderer/assets/icons/pagine.svg rename to src/renderer/assets/icons/.unused-icons/pagine.svg diff --git a/src/renderer/assets/icons/paragraph-center.svg b/src/renderer/assets/icons/.unused-icons/paragraph-center.svg similarity index 100% rename from src/renderer/assets/icons/paragraph-center.svg rename to src/renderer/assets/icons/.unused-icons/paragraph-center.svg diff --git a/src/renderer/assets/icons/paragraph-left.svg b/src/renderer/assets/icons/.unused-icons/paragraph-left.svg similarity index 100% rename from src/renderer/assets/icons/paragraph-left.svg rename to src/renderer/assets/icons/.unused-icons/paragraph-left.svg diff --git a/src/renderer/assets/icons/paragraph-right.svg b/src/renderer/assets/icons/.unused-icons/paragraph-right.svg similarity index 100% rename from src/renderer/assets/icons/paragraph-right.svg rename to src/renderer/assets/icons/.unused-icons/paragraph-right.svg diff --git a/src/renderer/assets/icons/person-circle.svg b/src/renderer/assets/icons/.unused-icons/person-circle.svg similarity index 100% rename from src/renderer/assets/icons/person-circle.svg rename to src/renderer/assets/icons/.unused-icons/person-circle.svg diff --git a/src/renderer/assets/icons/person.svg b/src/renderer/assets/icons/.unused-icons/person.svg similarity index 100% rename from src/renderer/assets/icons/person.svg rename to src/renderer/assets/icons/.unused-icons/person.svg diff --git a/src/renderer/assets/icons/plus.svg b/src/renderer/assets/icons/.unused-icons/plus.svg similarity index 95% rename from src/renderer/assets/icons/plus.svg rename to src/renderer/assets/icons/.unused-icons/plus.svg index 8c5dab3f3..46ac6816f 100644 --- a/src/renderer/assets/icons/plus.svg +++ b/src/renderer/assets/icons/.unused-icons/plus.svg @@ -1,42 +1,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/.unused-icons/plusBorder-icon.svg b/src/renderer/assets/icons/.unused-icons/plusBorder-icon.svg new file mode 100644 index 000000000..c4b4f3f2e --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/plusBorder-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/question.svg b/src/renderer/assets/icons/.unused-icons/question.svg similarity index 100% rename from src/renderer/assets/icons/question.svg rename to src/renderer/assets/icons/.unused-icons/question.svg diff --git a/src/renderer/assets/icons/.unused-icons/reading-icon.svg b/src/renderer/assets/icons/.unused-icons/reading-icon.svg new file mode 100644 index 000000000..14680b39c --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/reading-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/refresh.svg b/src/renderer/assets/icons/.unused-icons/refresh.svg similarity index 96% rename from src/renderer/assets/icons/refresh.svg rename to src/renderer/assets/icons/.unused-icons/refresh.svg index 56638115d..b826f9fef 100644 --- a/src/renderer/assets/icons/refresh.svg +++ b/src/renderer/assets/icons/.unused-icons/refresh.svg @@ -1,46 +1,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/settings.svg b/src/renderer/assets/icons/.unused-icons/settings.svg similarity index 100% rename from src/renderer/assets/icons/settings.svg rename to src/renderer/assets/icons/.unused-icons/settings.svg diff --git a/src/renderer/assets/icons/sharp-crop_free-24px.svg b/src/renderer/assets/icons/.unused-icons/sharp-crop_free-24px.svg similarity index 96% rename from src/renderer/assets/icons/sharp-crop_free-24px.svg rename to src/renderer/assets/icons/.unused-icons/sharp-crop_free-24px.svg index f37f84f02..9afed59a7 100644 --- a/src/renderer/assets/icons/sharp-crop_free-24px.svg +++ b/src/renderer/assets/icons/.unused-icons/sharp-crop_free-24px.svg @@ -4,7 +4,6 @@ viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> diff --git a/src/renderer/assets/icons/sharp-uncrop_free-24px.svg b/src/renderer/assets/icons/.unused-icons/sharp-uncrop_free-24px.svg similarity index 88% rename from src/renderer/assets/icons/sharp-uncrop_free-24px.svg rename to src/renderer/assets/icons/.unused-icons/sharp-uncrop_free-24px.svg index 290390fb9..0a81a7150 100644 --- a/src/renderer/assets/icons/sharp-uncrop_free-24px.svg +++ b/src/renderer/assets/icons/.unused-icons/sharp-uncrop_free-24px.svg @@ -1,10 +1,7 @@ - + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> diff --git a/src/renderer/assets/icons/.unused-icons/shift-icon.svg b/src/renderer/assets/icons/.unused-icons/shift-icon.svg new file mode 100644 index 000000000..a4f4d90b7 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/shift-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/view-card.svg b/src/renderer/assets/icons/.unused-icons/view-card.svg similarity index 100% rename from src/renderer/assets/icons/view-card.svg rename to src/renderer/assets/icons/.unused-icons/view-card.svg diff --git a/src/renderer/assets/icons/view-list.svg b/src/renderer/assets/icons/.unused-icons/view-list.svg similarity index 100% rename from src/renderer/assets/icons/view-list.svg rename to src/renderer/assets/icons/.unused-icons/view-list.svg diff --git a/src/renderer/assets/icons/.unused-icons/volup-icon.svg b/src/renderer/assets/icons/.unused-icons/volup-icon.svg new file mode 100644 index 000000000..5913b9d87 --- /dev/null +++ b/src/renderer/assets/icons/.unused-icons/volup-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/2cols-icon.svg b/src/renderer/assets/icons/2cols-icon.svg new file mode 100644 index 000000000..106b255b7 --- /dev/null +++ b/src/renderer/assets/icons/2cols-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/BookmarkRemove-icon.svg b/src/renderer/assets/icons/BookmarkRemove-icon.svg new file mode 100644 index 000000000..17b254e1c --- /dev/null +++ b/src/renderer/assets/icons/BookmarkRemove-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/renderer/assets/icons/Minus-Bold.svg b/src/renderer/assets/icons/Minus-Bold.svg new file mode 100644 index 000000000..f5665c2b5 --- /dev/null +++ b/src/renderer/assets/icons/Minus-Bold.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/Plus-bold.svg b/src/renderer/assets/icons/Plus-bold.svg new file mode 100644 index 000000000..f09ba8121 --- /dev/null +++ b/src/renderer/assets/icons/Plus-bold.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/SaveAs-icon.svg b/src/renderer/assets/icons/SaveAs-icon.svg new file mode 100644 index 000000000..d2cf9a83b --- /dev/null +++ b/src/renderer/assets/icons/SaveAs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/renderer/assets/icons/TextOutline-icon.svg b/src/renderer/assets/icons/TextOutline-icon.svg new file mode 100644 index 000000000..6a7c1ea28 --- /dev/null +++ b/src/renderer/assets/icons/TextOutline-icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/renderer/assets/icons/TextStrikethrough-icon.svg b/src/renderer/assets/icons/TextStrikethrough-icon.svg new file mode 100644 index 000000000..2ea854dd0 --- /dev/null +++ b/src/renderer/assets/icons/TextStrikethrough-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/add-alone.svg b/src/renderer/assets/icons/add-alone.svg index 2d2c530ad..65a81fcb4 100644 --- a/src/renderer/assets/icons/add-alone.svg +++ b/src/renderer/assets/icons/add-alone.svg @@ -1,4 +1,3 @@ - + + diff --git a/src/renderer/assets/icons/align-auto-icon.svg b/src/renderer/assets/icons/align-auto-icon.svg new file mode 100644 index 000000000..184f54b11 --- /dev/null +++ b/src/renderer/assets/icons/align-auto-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/align-justify-icon.svg b/src/renderer/assets/icons/align-justify-icon.svg new file mode 100644 index 000000000..82da7a984 --- /dev/null +++ b/src/renderer/assets/icons/align-justify-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/align-right-icon.svg b/src/renderer/assets/icons/align-right-icon.svg new file mode 100644 index 000000000..e31d175ad --- /dev/null +++ b/src/renderer/assets/icons/align-right-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/alignleft-icon.svg b/src/renderer/assets/icons/alignleft-icon.svg new file mode 100644 index 000000000..c28885570 --- /dev/null +++ b/src/renderer/assets/icons/alignleft-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/annotation-icon.svg b/src/renderer/assets/icons/annotation-icon.svg new file mode 100644 index 000000000..25cb9bc02 --- /dev/null +++ b/src/renderer/assets/icons/annotation-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/annotations-icon.svg b/src/renderer/assets/icons/annotations-icon.svg new file mode 100644 index 000000000..151689075 --- /dev/null +++ b/src/renderer/assets/icons/annotations-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/arrow-right.svg b/src/renderer/assets/icons/arrow-right.svg index fda98a3a0..25bc476cc 100644 --- a/src/renderer/assets/icons/arrow-right.svg +++ b/src/renderer/assets/icons/arrow-right.svg @@ -1,4 +1,5 @@ - +arrow-right + diff --git a/src/renderer/assets/icons/arrowFirst-icon.svg b/src/renderer/assets/icons/arrowFirst-icon.svg new file mode 100644 index 000000000..f42eb3a8f --- /dev/null +++ b/src/renderer/assets/icons/arrowFirst-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/arrowLast-icon.svg b/src/renderer/assets/icons/arrowLast-icon.svg new file mode 100644 index 000000000..6ccbd0b04 --- /dev/null +++ b/src/renderer/assets/icons/arrowLast-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/audio-next-icon.svg b/src/renderer/assets/icons/audio-next-icon.svg new file mode 100644 index 000000000..88f27bb7e --- /dev/null +++ b/src/renderer/assets/icons/audio-next-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/audio-pause-icon.svg b/src/renderer/assets/icons/audio-pause-icon.svg new file mode 100644 index 000000000..8ea265c5b --- /dev/null +++ b/src/renderer/assets/icons/audio-pause-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/audio-play-icon.svg b/src/renderer/assets/icons/audio-play-icon.svg new file mode 100644 index 000000000..8f971a625 --- /dev/null +++ b/src/renderer/assets/icons/audio-play-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/audio-previous-icon.svg b/src/renderer/assets/icons/audio-previous-icon.svg new file mode 100644 index 000000000..763096970 --- /dev/null +++ b/src/renderer/assets/icons/audio-previous-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/audio-stop-icon.svg b/src/renderer/assets/icons/audio-stop-icon.svg new file mode 100644 index 000000000..7d77c85f7 --- /dev/null +++ b/src/renderer/assets/icons/audio-stop-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/available-icon.svg b/src/renderer/assets/icons/available-icon.svg new file mode 100644 index 000000000..c15b875e8 --- /dev/null +++ b/src/renderer/assets/icons/available-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/avatar.svg b/src/renderer/assets/icons/avatar.svg index 19af83ee3..237390304 100644 --- a/src/renderer/assets/icons/avatar.svg +++ b/src/renderer/assets/icons/avatar.svg @@ -1,53 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/backward-icon.svg b/src/renderer/assets/icons/backward-icon.svg new file mode 100644 index 000000000..a3f390c21 --- /dev/null +++ b/src/renderer/assets/icons/backward-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/bin-icon.svg b/src/renderer/assets/icons/bin-icon.svg new file mode 100644 index 000000000..4f7e9a745 --- /dev/null +++ b/src/renderer/assets/icons/bin-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/renderer/assets/icons/bookOpen-icon.svg b/src/renderer/assets/icons/bookOpen-icon.svg new file mode 100644 index 000000000..dd4c09762 --- /dev/null +++ b/src/renderer/assets/icons/bookOpen-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/bookmarkMultiple-icon.svg b/src/renderer/assets/icons/bookmarkMultiple-icon.svg new file mode 100644 index 000000000..53b0ba539 --- /dev/null +++ b/src/renderer/assets/icons/bookmarkMultiple-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/bookmarkSingle-icon.svg b/src/renderer/assets/icons/bookmarkSingle-icon.svg new file mode 100644 index 000000000..e62806903 --- /dev/null +++ b/src/renderer/assets/icons/bookmarkSingle-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/borrow-icon.svg b/src/renderer/assets/icons/borrow-icon.svg new file mode 100644 index 000000000..4458f3da3 --- /dev/null +++ b/src/renderer/assets/icons/borrow-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/breadcrumbsNav-icon.svg b/src/renderer/assets/icons/breadcrumbsNav-icon.svg new file mode 100644 index 000000000..6bd546171 --- /dev/null +++ b/src/renderer/assets/icons/breadcrumbsNav-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/calendar-icon.svg b/src/renderer/assets/icons/calendar-icon.svg new file mode 100644 index 000000000..c9976839b --- /dev/null +++ b/src/renderer/assets/icons/calendar-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/calendar2-icon.svg b/src/renderer/assets/icons/calendar2-icon.svg new file mode 100644 index 000000000..f5f974767 --- /dev/null +++ b/src/renderer/assets/icons/calendar2-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/calendarExpired-icon.svg b/src/renderer/assets/icons/calendarExpired-icon.svg new file mode 100644 index 000000000..98c18b95e --- /dev/null +++ b/src/renderer/assets/icons/calendarExpired-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/cart-icon.svg b/src/renderer/assets/icons/cart-icon.svg new file mode 100644 index 000000000..4f0ced210 --- /dev/null +++ b/src/renderer/assets/icons/cart-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/catalogs-icon.svg b/src/renderer/assets/icons/catalogs-icon.svg new file mode 100644 index 000000000..9b3d8cdf5 --- /dev/null +++ b/src/renderer/assets/icons/catalogs-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/chevron-down.svg b/src/renderer/assets/icons/chevron-down.svg index 1f0b8bc70..38e033c8c 100644 --- a/src/renderer/assets/icons/chevron-down.svg +++ b/src/renderer/assets/icons/chevron-down.svg @@ -1,3 +1,4 @@ - - + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/chevron-up.svg b/src/renderer/assets/icons/chevron-up.svg new file mode 100644 index 000000000..3e06aada7 --- /dev/null +++ b/src/renderer/assets/icons/chevron-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/clock-reverse-icon.svg b/src/renderer/assets/icons/clock-reverse-icon.svg new file mode 100644 index 000000000..8b25098e9 --- /dev/null +++ b/src/renderer/assets/icons/clock-reverse-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/close-icon.svg b/src/renderer/assets/icons/close-icon.svg new file mode 100644 index 000000000..5e0a29d78 --- /dev/null +++ b/src/renderer/assets/icons/close-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/cog-icon.svg b/src/renderer/assets/icons/cog-icon.svg new file mode 100644 index 000000000..7d6469bd0 --- /dev/null +++ b/src/renderer/assets/icons/cog-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/renderer/assets/icons/comment-icon.svg b/src/renderer/assets/icons/comment-icon.svg new file mode 100644 index 000000000..d1b46fc37 --- /dev/null +++ b/src/renderer/assets/icons/comment-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/defaultPage-icon.svg b/src/renderer/assets/icons/defaultPage-icon.svg new file mode 100644 index 000000000..8b341ac58 --- /dev/null +++ b/src/renderer/assets/icons/defaultPage-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/deleteFilter-icon.svg b/src/renderer/assets/icons/deleteFilter-icon.svg new file mode 100644 index 000000000..cd39fde09 --- /dev/null +++ b/src/renderer/assets/icons/deleteFilter-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/dockleft-icon.svg b/src/renderer/assets/icons/dockleft-icon.svg new file mode 100644 index 000000000..3102cc7b0 --- /dev/null +++ b/src/renderer/assets/icons/dockleft-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/dockmodal-icon.svg b/src/renderer/assets/icons/dockmodal-icon.svg new file mode 100644 index 000000000..9b21c18ab --- /dev/null +++ b/src/renderer/assets/icons/dockmodal-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/dockright-icon.svg b/src/renderer/assets/icons/dockright-icon.svg new file mode 100644 index 000000000..e8ee5d9b5 --- /dev/null +++ b/src/renderer/assets/icons/dockright-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/doubleCheck-icon.svg b/src/renderer/assets/icons/doubleCheck-icon.svg new file mode 100644 index 000000000..4cf6a97b0 --- /dev/null +++ b/src/renderer/assets/icons/doubleCheck-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/duplicate-icon.svg b/src/renderer/assets/icons/duplicate-icon.svg new file mode 100644 index 000000000..5b09bf873 --- /dev/null +++ b/src/renderer/assets/icons/duplicate-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/emptylibrary-background-icon.svg b/src/renderer/assets/icons/emptylibrary-background-icon.svg new file mode 100644 index 000000000..72284527e --- /dev/null +++ b/src/renderer/assets/icons/emptylibrary-background-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/emptylibrary-icon.svg b/src/renderer/assets/icons/emptylibrary-icon.svg new file mode 100644 index 000000000..a678f49cf --- /dev/null +++ b/src/renderer/assets/icons/emptylibrary-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/renderer/assets/icons/filter-icon.svg b/src/renderer/assets/icons/filter-icon.svg new file mode 100644 index 000000000..56270b117 --- /dev/null +++ b/src/renderer/assets/icons/filter-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/floppydisk-icon.svg b/src/renderer/assets/icons/floppydisk-icon.svg new file mode 100644 index 000000000..6c0d49198 --- /dev/null +++ b/src/renderer/assets/icons/floppydisk-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/followLink-icon.svg b/src/renderer/assets/icons/followLink-icon.svg new file mode 100644 index 000000000..c3cbccefb --- /dev/null +++ b/src/renderer/assets/icons/followLink-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/forbidden-icon.svg b/src/renderer/assets/icons/forbidden-icon.svg new file mode 100644 index 000000000..c21fc81d5 --- /dev/null +++ b/src/renderer/assets/icons/forbidden-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/forward-icon.svg b/src/renderer/assets/icons/forward-icon.svg new file mode 100644 index 000000000..d8effc727 --- /dev/null +++ b/src/renderer/assets/icons/forward-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/fullscreen-corners-icon.svg b/src/renderer/assets/icons/fullscreen-corners-icon.svg new file mode 100644 index 000000000..85aa87554 --- /dev/null +++ b/src/renderer/assets/icons/fullscreen-corners-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/fullscreen-icon.svg b/src/renderer/assets/icons/fullscreen-icon.svg new file mode 100644 index 000000000..9f0940b35 --- /dev/null +++ b/src/renderer/assets/icons/fullscreen-icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/fullscreenExit-icon.svg b/src/renderer/assets/icons/fullscreenExit-icon.svg new file mode 100644 index 000000000..657075908 --- /dev/null +++ b/src/renderer/assets/icons/fullscreenExit-icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/gear-icon.svg b/src/renderer/assets/icons/gear-icon.svg new file mode 100644 index 000000000..c7ec85de5 --- /dev/null +++ b/src/renderer/assets/icons/gear-icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/globe-icon.svg b/src/renderer/assets/icons/globe-icon.svg new file mode 100644 index 000000000..c609ad4ab --- /dev/null +++ b/src/renderer/assets/icons/globe-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/grid-icon.svg b/src/renderer/assets/icons/grid-icon.svg new file mode 100644 index 000000000..065ef1a05 --- /dev/null +++ b/src/renderer/assets/icons/grid-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/headphone-icon.svg b/src/renderer/assets/icons/headphone-icon.svg new file mode 100644 index 000000000..3d73ae3b6 --- /dev/null +++ b/src/renderer/assets/icons/headphone-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/highlight-icon.svg b/src/renderer/assets/icons/highlight-icon.svg new file mode 100644 index 000000000..c6e21475e --- /dev/null +++ b/src/renderer/assets/icons/highlight-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/home-icon.svg b/src/renderer/assets/icons/home-icon.svg new file mode 100644 index 000000000..034b07a13 --- /dev/null +++ b/src/renderer/assets/icons/home-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/info-icon.svg b/src/renderer/assets/icons/info-icon.svg new file mode 100644 index 000000000..b91e81f4b --- /dev/null +++ b/src/renderer/assets/icons/info-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/key-icon.svg b/src/renderer/assets/icons/key-icon.svg new file mode 100644 index 000000000..94b007c2c --- /dev/null +++ b/src/renderer/assets/icons/key-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/keyreturn-icon.svg b/src/renderer/assets/icons/keyreturn-icon.svg new file mode 100644 index 000000000..12242c02e --- /dev/null +++ b/src/renderer/assets/icons/keyreturn-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/landmark-icon.svg b/src/renderer/assets/icons/landmark-icon.svg new file mode 100644 index 000000000..a4dbaf553 --- /dev/null +++ b/src/renderer/assets/icons/landmark-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/language.svg b/src/renderer/assets/icons/language.svg new file mode 100644 index 000000000..6ad733f71 --- /dev/null +++ b/src/renderer/assets/icons/language.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/layout-icon.svg b/src/renderer/assets/icons/layout-icon.svg new file mode 100644 index 000000000..7d84fd857 --- /dev/null +++ b/src/renderer/assets/icons/layout-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/library-icon.svg b/src/renderer/assets/icons/library-icon.svg new file mode 100644 index 000000000..d4660fd2b --- /dev/null +++ b/src/renderer/assets/icons/library-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/lightbulb-icon.svg b/src/renderer/assets/icons/lightbulb-icon.svg new file mode 100644 index 000000000..cf8713134 --- /dev/null +++ b/src/renderer/assets/icons/lightbulb-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/link-icon.svg b/src/renderer/assets/icons/link-icon.svg new file mode 100644 index 000000000..adfb867b4 --- /dev/null +++ b/src/renderer/assets/icons/link-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/list-icon.svg b/src/renderer/assets/icons/list-icon.svg new file mode 100644 index 000000000..825979aab --- /dev/null +++ b/src/renderer/assets/icons/list-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/loader.svg b/src/renderer/assets/icons/loader.svg index 4a225e5e6..f699ab211 100644 --- a/src/renderer/assets/icons/loader.svg +++ b/src/renderer/assets/icons/loader.svg @@ -1,7 +1,7 @@ - + - + \ No newline at end of file + \ No newline at end of file diff --git a/src/renderer/assets/icons/magnifying_glass.svg b/src/renderer/assets/icons/magnifying_glass.svg index 09bf2cae1..a845f370c 100644 --- a/src/renderer/assets/icons/magnifying_glass.svg +++ b/src/renderer/assets/icons/magnifying_glass.svg @@ -1,43 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/renderer/assets/icons/menu.svg b/src/renderer/assets/icons/menu.svg index e8b551e94..8811cf696 100644 --- a/src/renderer/assets/icons/menu.svg +++ b/src/renderer/assets/icons/menu.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/renderer/assets/icons/ongoingBook-icon.svg b/src/renderer/assets/icons/ongoingBook-icon.svg new file mode 100644 index 000000000..54fe53be9 --- /dev/null +++ b/src/renderer/assets/icons/ongoingBook-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/open_book.svg b/src/renderer/assets/icons/open_book.svg index 6fe9b0f75..ab5d47ac7 100644 --- a/src/renderer/assets/icons/open_book.svg +++ b/src/renderer/assets/icons/open_book.svg @@ -1,16 +1,3 @@ - - - - - - - + + diff --git a/src/renderer/assets/icons/outline-bookmark_border-24px.svg b/src/renderer/assets/icons/outline-bookmark_border-24px.svg deleted file mode 100644 index 006829f8b..000000000 --- a/src/renderer/assets/icons/outline-bookmark_border-24px.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/renderer/assets/icons/page-icon.svg b/src/renderer/assets/icons/page-icon.svg new file mode 100644 index 000000000..ca740e12c --- /dev/null +++ b/src/renderer/assets/icons/page-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/paintbrush-icon.svg b/src/renderer/assets/icons/paintbrush-icon.svg new file mode 100644 index 000000000..03c893fb4 --- /dev/null +++ b/src/renderer/assets/icons/paintbrush-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/palette-icon.svg b/src/renderer/assets/icons/palette-icon.svg new file mode 100644 index 000000000..fcbec1b7c --- /dev/null +++ b/src/renderer/assets/icons/palette-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/password-icon.svg b/src/renderer/assets/icons/password-icon.svg new file mode 100644 index 000000000..f304a2643 --- /dev/null +++ b/src/renderer/assets/icons/password-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/pen-icon.svg b/src/renderer/assets/icons/pen-icon.svg new file mode 100644 index 000000000..e1771addb --- /dev/null +++ b/src/renderer/assets/icons/pen-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/readBook-icon.svg b/src/renderer/assets/icons/readBook-icon.svg new file mode 100644 index 000000000..34b615573 --- /dev/null +++ b/src/renderer/assets/icons/readBook-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/refresh-icon.svg b/src/renderer/assets/icons/refresh-icon.svg new file mode 100644 index 000000000..1fc926033 --- /dev/null +++ b/src/renderer/assets/icons/refresh-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/scroll-icon.svg b/src/renderer/assets/icons/scroll-icon.svg new file mode 100644 index 000000000..b97fc39d1 --- /dev/null +++ b/src/renderer/assets/icons/scroll-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/search-icon.svg b/src/renderer/assets/icons/search-icon.svg new file mode 100644 index 000000000..b0434ff3c --- /dev/null +++ b/src/renderer/assets/icons/search-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/shelf-icon.svg b/src/renderer/assets/icons/shelf-icon.svg new file mode 100644 index 000000000..7c974810e --- /dev/null +++ b/src/renderer/assets/icons/shelf-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/speaker-icon.svg b/src/renderer/assets/icons/speaker-icon.svg new file mode 100644 index 000000000..b3d7e506a --- /dev/null +++ b/src/renderer/assets/icons/speaker-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/stop-icon.svg b/src/renderer/assets/icons/stop-icon.svg new file mode 100644 index 000000000..1eee53bb6 --- /dev/null +++ b/src/renderer/assets/icons/stop-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/swatches-icon.svg b/src/renderer/assets/icons/swatches-icon.svg new file mode 100644 index 000000000..e73d8a3c8 --- /dev/null +++ b/src/renderer/assets/icons/swatches-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/table-icon.svg b/src/renderer/assets/icons/table-icon.svg new file mode 100644 index 000000000..13afbf82e --- /dev/null +++ b/src/renderer/assets/icons/table-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/tag-icon.svg b/src/renderer/assets/icons/tag-icon.svg new file mode 100644 index 000000000..97299ec60 --- /dev/null +++ b/src/renderer/assets/icons/tag-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/target-icon.svg b/src/renderer/assets/icons/target-icon.svg new file mode 100644 index 000000000..88e58ff42 --- /dev/null +++ b/src/renderer/assets/icons/target-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/textarea-icon.svg b/src/renderer/assets/icons/textarea-icon.svg new file mode 100644 index 000000000..38655358e --- /dev/null +++ b/src/renderer/assets/icons/textarea-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/toc-icon.svg b/src/renderer/assets/icons/toc-icon.svg new file mode 100644 index 000000000..be80c0d30 --- /dev/null +++ b/src/renderer/assets/icons/toc-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/trash-icon.svg b/src/renderer/assets/icons/trash-icon.svg new file mode 100644 index 000000000..f70e81d52 --- /dev/null +++ b/src/renderer/assets/icons/trash-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/underline-icon.svg b/src/renderer/assets/icons/underline-icon.svg new file mode 100644 index 000000000..5049cb962 --- /dev/null +++ b/src/renderer/assets/icons/underline-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/validated-icon.svg b/src/renderer/assets/icons/validated-icon.svg new file mode 100644 index 000000000..1ba79d9be --- /dev/null +++ b/src/renderer/assets/icons/validated-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/volume-icon.svg b/src/renderer/assets/icons/volume-icon.svg new file mode 100644 index 000000000..4dc04ba99 --- /dev/null +++ b/src/renderer/assets/icons/volume-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/styles/app.css.d.ts b/src/renderer/assets/styles/app.css.d.ts deleted file mode 100644 index 0dc603fa3..000000000 --- a/src/renderer/assets/styles/app.css.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare const styles: { - readonly "___DEBUG___APP_CSS": string; - readonly "downloadsPanel": string; - readonly "percent": string; - readonly "title": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/app.css b/src/renderer/assets/styles/app.scss similarity index 56% rename from src/renderer/assets/styles/app.css rename to src/renderer/assets/styles/app.scss index 6829c6e70..9bf396935 100644 --- a/src/renderer/assets/styles/app.css +++ b/src/renderer/assets/styles/app.scss @@ -1,32 +1,31 @@ /* -=-=-= app.css +=-=-= app.scss */ .downloadsPanel { display: block; position: absolute; - left: 10px; - right: 10px; + left: 20px; + right: 20px; + border-radius: 5px; bottom: 0; height: auto; overflow: hidden; overflow-y: auto; - background: white; - border: 2px solid black; + background: var(--color-light-grey); + border: 2px solid var(--color-light-blue); margin: 0; padding: 10px; z-index: 110; - & li { - /* backgroundxx: red; */ + li { display: inline-block; width: 100%; list-style-type: none; margin: 0; padding: 0; - & span.percent { - /* backgroundxx: blue; */ + span.percent { display: inline-block; width: 40px; margin: 0; @@ -34,7 +33,7 @@ padding: 3px; } - & progress { + progress { background-color: green; border-radius: 0; height: 20px; @@ -46,22 +45,35 @@ padding: 0; } - & progress::-webkit-progress-bar { + progress::-webkit-progress-bar { background-color: silver; border-radius: 0; } - & progress::-webkit-progress-value { - background-color: black; + progress::-webkit-progress-value { + background-color: var(--color-blue); border-radius: 0; } - & span.title { - /* backgroundxx: green; */ + span.title { display: inline-block; width: auto; margin: 0; padding: 3px; + color: var(--color-primary); + + svg { + width: 12px; + height: 12px; + fill: var(--color-primary); + color: var(--color-primary); + transition: 200ms; + + &:hover { + fill: var(--color-error-dark); + color: var(--color-error-dark); + } + } } } } diff --git a/src/renderer/assets/styles/app.scss.d.ts b/src/renderer/assets/styles/app.scss.d.ts new file mode 100644 index 000000000..4dac14814 --- /dev/null +++ b/src/renderer/assets/styles/app.scss.d.ts @@ -0,0 +1,4 @@ +export declare const ___DEBUG___APP_CSS: string; +export declare const downloadsPanel: string; +export declare const percent: string; +export declare const title: string; diff --git a/src/renderer/assets/styles/bookDetailsDialog.css b/src/renderer/assets/styles/bookDetailsDialog.css deleted file mode 100644 index 8322a0410..000000000 --- a/src/renderer/assets/styles/bookDetailsDialog.css +++ /dev/null @@ -1,325 +0,0 @@ -/* -=-=-= bookDetailsDialog.css -*/ - -.c_dialog { - position: fixed; - z-index: 100; - top: 0; - left: 0; - right: 0; - bottom: 0; - display: flex; - padding: 0; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - background-color: rgba(0, 0, 0, 0.5); - transition: 0.2s; - min-width: 700px; -} - -.c_dialog_background { - position: fixed; - z-index: 102; - top: 0; - left: 0; - right: 0; - bottom: 0; - - /* filter: blur(2px); */ -} - -.c_dialog__box { - z-index: 102; - display: flex; - width: 90%; - max-width: 92rem; - margin: 100px auto 20px 5rem; - padding: 60px; - background-color: white; - overflow-y: auto; - overflow-x: hidden; - align-content: flex-start; - color: #3b3b3b; - position: relative; -} - -.c_dialog__box button { - position: absolute; - top: 15px; - right: 15px; - height: 50px; - display: block; - width: 50px; - cursor: pointer; - fill: #3b3b3b; -} - -.c_dialog__box button svg { - width: 80%; -} - -.dialog_left { - width: 33%; - height: fit-content; - min-width: 9rem; - - & img { - width: 100%; - box-shadow: 0 0 20px 0 #cfcfcf; - } - - & .liens { - list-style: none; - padding: 0; - - & li { - font-size: 1.08rem; - margin-top: 1rem 0; - text-align: center; - - & svg { - display: inline-block; - vertical-align: top; - width: 20px; - height: 20px; - margin-right: 3px; - } - - & button { - font-weight: 600; - } - } - } - - & button, - & a { - text-decoration: none; - color: inherit; - cursor: pointer; - font-size: 1.08rem; - font-weight: 600; - width: 100%; - height: unset; - opacity: 1; - - &.lire { - display: block; - text-align: center; - padding: 8px 10px; - font-size: 1.1rem; - margin-top: 24px; - border: 2px solid #c1c1c1; - margin-bottom: 32px; - font-weight: bold; - border-radius: 2px; - box-shadow: 0 6px 5px -5px #cfcfcf; - } - } - - & button[disabled] { - cursor: not-allowed; - } -} - -.dialog_right { - height: fit-content; - overflow-wrap: break-word; - width: 77%; - padding: 0 30px 0 54px; -} - -.dialog_right .author { - font-size: 1.3rem; - margin-bottom: 30px; -} - -.dialog_right h2 { - margin-bottom: 0; - font-weight: 600; - font-size: 1.4rem; -} - -.c_dialog[aria-hidden="true"] { - visibility: hidden; - opacity: 0; -} - -.dialog_right p { - margin-top: 0; - margin-bottom: 3px; - font-weight: 300; - font-size: 1.1rem; -} - -.dialog_right span { - font-weight: 600; - font-size: 1.1rem; -} - -.dialog_right .description { - font-size: 0.95rem; -} - -.dialog_right .tags { - font-size: 1rem; -} - -.dialog_right .tags ul { - display: inline-block; - padding-left: 0; - margin-top: 0; -} - -.dialog_right .tags .tag_list { - display: flex; - - & > div { - display: inline-block; - margin-left: 15px; - flex: 1; - } - - & > span { - align-self: flex-start; - margin-top: 8px; - font-weight: 600; - } - - & button { - width: 20px; - height: 20px; - margin-left: 1rem; - padding: 0; - border: none; - background-color: transparent; - - &.addTagButton { - font-size: 1rem; - font-weight: bold; - color: rgb(59, 59, 59); - height: auto; - width: auto; - padding: 0.5rem; - border: 1px solid rgb(59, 59, 59); - border-radius: 5px; - } - } -} - -.dialog_right .tags li { - display: inline-flex; - align-items: center; - background-color: #e7f1fb; - padding: 2px 6px; - font-size: 1.1rem; - border-radius: 3px; - border: 1px solid #67a3e0; - color: #67a3e0; - margin: 0.3rem 0; -} - -.dialog_right .tags li:not(:first-child) { - margin-left: 10px; -} - -.dialog_right .tags li svg { - display: inline-block; - width: 20px; - height: 20px; - vertical-align: top; -} - -.dialog_right h3 { - font-weight: 600; - margin-top: 30px; -} - -.dialog_right #flux_search { - margin-bottom: 0; - margin-left: 0; - height: auto; - width: fit-content; /* width: 100%; */ - display: flex; -} - -.tag_inputs { - position: relative; - max-width: 300px; - flex: 1; - border-radius: 0; - border: none; - height: 35px; - background-color: transparent; - color: var(--color-primary); - font-size: 0.9rem; - border-bottom: 1px solid #c1c1c1; -} - -.tag_inputs::placeholder { - font-size: 0.9rem; - font-weight: 300; - color: #c1c1c1; -} - -.image_wrapper { - width: 100%; - position: relative; - - & > div { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: flex; - align-items: center; - - & img { - max-height: 100%; - max-width: 100%; - margin: auto; - display: block; - } - } -} - -.image_wrapper::before { - content: ""; - display: block; - padding-top: 140%; -} - -.descriptionWrapper { - max-height: 10rem; - overflow: hidden; - position: relative; - - &.hideEnd { - &::after { - content: ""; - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 1)); - height: 2rem; - } - } - - &.seeMore { - max-height: unset; - - &::after { - content: none; - } - } -} - -.allowUserSelect { - user-select: text; -} - -.___DEBUG___BOOK_DETAILS_DIALOG_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/bookDetailsDialog.css.d.ts b/src/renderer/assets/styles/bookDetailsDialog.css.d.ts deleted file mode 100644 index 95b88d3ce..000000000 --- a/src/renderer/assets/styles/bookDetailsDialog.css.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -declare const styles: { - readonly "___DEBUG___BOOK_DETAILS_DIALOG_CSS": string; - readonly "addTagButton": string; - readonly "allowUserSelect": string; - readonly "author": string; - readonly "c_dialog": string; - readonly "c_dialog__box": string; - readonly "c_dialog_background": string; - readonly "description": string; - readonly "descriptionWrapper": string; - readonly "dialog_left": string; - readonly "dialog_right": string; - readonly "flux_search": string; - readonly "hideEnd": string; - readonly "image_wrapper": string; - readonly "liens": string; - readonly "lire": string; - readonly "seeMore": string; - readonly "tag_inputs": string; - readonly "tag_list": string; - readonly "tags": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/bookDetailsDialog.scss b/src/renderer/assets/styles/bookDetailsDialog.scss new file mode 100644 index 000000000..26a9a949a --- /dev/null +++ b/src/renderer/assets/styles/bookDetailsDialog.scss @@ -0,0 +1,340 @@ +/* +=-=-= bookDetailsDialog.scss +*/ + +.c_dialog { + position: fixed; + z-index: 100; + inset: 0; + display: flex; + padding: 0; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + background-color: rgb(0 0 0 / 50%); + transition: 0.2s; + min-width: 700px; + + &_background { + position: fixed; + z-index: 102; + inset: 0; + } + + &__box { + z-index: 102; + display: flex; + width: 90%; + max-width: 92rem; + margin: 100px auto 20px 5rem; + padding: 60px; + background-color: white; + overflow: hidden auto; + align-content: flex-start; + color: #3b3b3b; + position: relative; + } + + &__box button { + position: absolute; + top: 15px; + right: 15px; + height: 50px; + display: block; + width: 50px; + cursor: pointer; + fill: #3b3b3b; + + svg { + width: 80%; + } + } +} + +.dialog_left { + width: 33%; + height: fit-content; + min-width: 9rem; + + & img { + width: 100%; + box-shadow: 0 0 20px 0 #cfcfcf; + } + + & .liens { + list-style: none; + padding: 0; + + & li { + font-size: 1.08rem; + margin-top: 1rem 0; + text-align: center; + + & svg { + display: inline-block; + vertical-align: top; + width: 20px; + height: 20px; + margin-right: 3px; + } + + & button { + font-weight: 600; + } + } + } + + & button, + & a { + text-decoration: none; + color: inherit; + cursor: pointer; + font-size: 1.08rem; + font-weight: 600; + width: 100%; + height: unset; + opacity: 1; + + &.lire { + display: block; + text-align: center; + padding: 8px 10px; + font-size: 1.1rem; + margin-top: 24px; + border: 2px solid #c1c1c1; + margin-bottom: 32px; + font-weight: bold; + border-radius: 2px; + box-shadow: 0 6px 5px -5px #cfcfcf; + } + } + + & button[disabled] { + cursor: not-allowed; + } +} + +.dialog_right { + height: fit-content; + overflow-wrap: break-word; + width: 77%; + padding: 0 30px 0 54px; + + h3 { + font-weight: 600; + margin-top: 30px; + } + + #flux_search { + margin-bottom: 0; + margin-left: 0; + height: auto; + width: fit-content; /* width: 100%; */ + display: flex; + } + + .author { + font-size: 1.3rem; + margin-bottom: 30px; + } + + h2 { + margin-bottom: 0; + font-weight: 600; + font-size: 1.4rem; + } + + p { + margin-top: 0; + margin-bottom: 3px; + font-weight: 300; + font-size: 1.1rem; + } + + span { + font-weight: 600; + font-size: 1.1rem; + } + + .description { + font-size: 0.95rem; + } + + .tags { + font-size: 1rem; + + ul { + display: inline-block; + padding-left: 0; + margin-top: 0; + } + + .tag_list { + display: flex; + + & > div { + display: inline-block; + margin-left: 15px; + flex: 1; + } + + & > span { + align-self: flex-start; + margin-top: 8px; + font-weight: 600; + } + + & button { + width: 20px; + height: 20px; + margin-left: 1rem; + padding: 0; + border: none; + background-color: transparent; + + &.addTagButton { + font-size: 1rem; + font-weight: bold; + color: rgb(59 59 59); + height: auto; + width: auto; + padding: 0.5rem; + border: 1px solid rgb(59 59 59); + border-radius: 5px; + } + } + } + + li { + display: inline-flex; + align-items: center; + background-color: #e7f1fb; + padding: 2px 6px; + font-size: 1.1rem; + border-radius: 3px; + border: 1px solid #67a3e0; + color: #67a3e0; + margin: 0.3rem 0; + + &:not(:first-child) { + margin-left: 10px; + } + + svg { + display: inline-block; + width: 20px; + height: 20px; + vertical-align: top; + } + } + } +} + + +.c_dialog[aria-hidden="true"] { + visibility: hidden; + opacity: 0; +} + +.tag_inputs { + position: relative; + max-width: 300px; + flex: 1; + border-radius: 0; + border: none; + height: 35px; + background-color: transparent; + color: var(--color-primary); + font-size: 0.9rem; + border-bottom: 1px solid #c1c1c1; + + &::placeholder { + font-size: 0.9rem; + font-weight: 300; + color: #c1c1c1; + } +} + +.image_wrapper { + width: 100%; + position: relative; + + & > div { + position: absolute; + inset: 0; + display: flex; + align-items: center; + + & img { + max-height: 100%; + max-width: 100%; + margin: auto; + display: block; + } + } + + &::before { + content: ""; + display: block; + padding-top: 140%; + } +} + +.descriptionWrapper { + max-height: 10rem; + overflow: hidden; + position: relative; + + &.hideEnd { + &::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: linear-gradient(rgb(255 255 255 / 0%), var(--color-secondary)); + height: 2rem; + } + } + + &.seeMore { + max-height: unset; + + &::after { + content: none; + } + } +} + +.allowUserSelect { + user-select: text; +} + +.___DEBUG___BOOK_DETAILS_DIALOG_CSS { + display: none; +} + + +.opds_book{ + &_infos { + margin-left: 25%; + display: flex; + align-items: center; + justify-content: start; + gap: 5px; + } + + &_state { + display: flex; + align-items: center; + justify-content: center; + gap: 2px; + } + + &_available { + color: green; + } + + &_unavailable { + color: var(--color-error-dark); + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/bookDetailsDialog.scss.d.ts b/src/renderer/assets/styles/bookDetailsDialog.scss.d.ts new file mode 100644 index 000000000..fd5b96754 --- /dev/null +++ b/src/renderer/assets/styles/bookDetailsDialog.scss.d.ts @@ -0,0 +1,24 @@ +export declare const ___DEBUG___BOOK_DETAILS_DIALOG_CSS: string; +export declare const addTagButton: string; +export declare const allowUserSelect: string; +export declare const author: string; +export declare const c_dialog: string; +export declare const c_dialog__box: string; +export declare const c_dialog_background: string; +export declare const description: string; +export declare const descriptionWrapper: string; +export declare const dialog_left: string; +export declare const dialog_right: string; +export declare const flux_search: string; +export declare const hideEnd: string; +export declare const image_wrapper: string; +export declare const liens: string; +export declare const lire: string; +export declare const opds_book_available: string; +export declare const opds_book_infos: string; +export declare const opds_book_state: string; +export declare const opds_book_unavailable: string; +export declare const seeMore: string; +export declare const tag_inputs: string; +export declare const tag_list: string; +export declare const tags: string; diff --git a/src/renderer/assets/styles/components/aboutFooter.scss b/src/renderer/assets/styles/components/aboutFooter.scss new file mode 100644 index 000000000..7cd88d305 --- /dev/null +++ b/src/renderer/assets/styles/components/aboutFooter.scss @@ -0,0 +1,44 @@ +/* +=-=-= aboutFooter.scss +*/ + +// .footer_wrapper{ +// display: flex; +// justify-content: end; +// align-items: center; +// gap: 10px; +// border-top: 1px solid var(--color-extralight-grey); +// margin: 0; + +// a { +// font-style: italic; +// text-decoration: underline; +// cursor: pointer; +// } +// } + +.footer_wrapper { + position: fixed; + bottom: -10px; + right: 40px; + border-top: 1px solid var(--color-extralight-grey); + margin: 0; + margin-bottom: 10px; + display: flex; + align-items: center; + justify-content: end; + gap: 10px; + height: 30px; + width: calc(100% - 247px); + background-color: var(--color-secondary); + + @media screen and (width <= 800px) { + width: calc(100% - 112px); + } + + a { + font-style: italic; + text-decoration: underline; + cursor: pointer; + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/aboutFooter.scss.d.ts b/src/renderer/assets/styles/components/aboutFooter.scss.d.ts new file mode 100644 index 000000000..4aa56bf8c --- /dev/null +++ b/src/renderer/assets/styles/components/aboutFooter.scss.d.ts @@ -0,0 +1 @@ +export declare const footer_wrapper: string; diff --git a/src/renderer/assets/styles/components/alert.modals.scss b/src/renderer/assets/styles/components/alert.modals.scss new file mode 100644 index 000000000..0a3cfd01e --- /dev/null +++ b/src/renderer/assets/styles/components/alert.modals.scss @@ -0,0 +1,100 @@ + +/* +=-=-= alert.modals.scss +*/ + +.AlertDialogOverlay { + background-color: rgb(0 0 0 / 50%); + position: fixed; + inset: 0; + animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1); + z-index: 110; +} + +.AlertDialogContent { + background-color: var(--color-secondary); + border-radius: 6px; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90vw; + max-width: 500px; + max-height: 85vh; + padding: 25px; + animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1); + z-index: 110; +} + +.AlertDialogContent:focus { + outline: none; +} + +.AlertDialogTitle { + margin: 0; + color: var(--color-primary); +} + +.AlertDialogDescription { + margin-bottom: 20px; + color: var(--color-primary); + line-height: 1.5; + + ul { + padding-left: 20px; + list-style-type: "- "; + } +} + +.AlertDialogButtonContainer { + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.AlertDialogButton { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 4px; + padding: 0 10px; + font-size: 15px; + line-height: 1; + font-weight: 500; + height: 35px; +} + +.AlertDialogButton.yes { + color: var(--color-secondary); + background-color: var(--color-blue); + transition: 200ms; + + svg { + margin-right: 5px; + width: 10px; + height: 10px; + fill: var(--color-secondary); + } +} + +.AlertDialogButton.abort { + color: var(--color-blue); + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + transition: 200ms; + + &:hover { + background-color: white; + } +} + +.AlertDialogButton.delete { + color: var(--color-blue); + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + transition: 200ms; + + &:hover { + background-color: white; + } +} diff --git a/src/renderer/assets/styles/components/alert.modals.scss.d.ts b/src/renderer/assets/styles/components/alert.modals.scss.d.ts new file mode 100644 index 000000000..67795f65e --- /dev/null +++ b/src/renderer/assets/styles/components/alert.modals.scss.d.ts @@ -0,0 +1,10 @@ +export declare const abort: string; +export declare const AlertDialogButton: string; +export declare const AlertDialogButtonContainer: string; +export declare const AlertDialogContent: string; +export declare const AlertDialogDescription: string; +export declare const AlertDialogOverlay: string; +export declare const AlertDialogTitle: string; +export declare const contentShow: string; +export declare const overlayShow: string; +export declare const yes: string; diff --git a/src/renderer/assets/styles/components/allPublicationsPage.scss b/src/renderer/assets/styles/components/allPublicationsPage.scss new file mode 100644 index 000000000..4ed36a284 --- /dev/null +++ b/src/renderer/assets/styles/components/allPublicationsPage.scss @@ -0,0 +1,415 @@ +/* +=-=-= allPublicationsPage.scss +*/ + +.allBooks { + &_header { + font-size: 18px; + max-width: 300px; + text-overflow: ellipsis; + overflow: hidden; + + + &_navigation { + background-color: var(--color-extralight-grey); + border-radius: 6px; + height: 96px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 20px; + margin: 10px 0; + width: inherit; + + // @media screen and (width <= 1024px) { + // height: 125px; + // } + + &_inputs { + display: flex; + align-items: center; + gap: 10px; + + @media screen and (width <= 1024px) { + gap: 30px; + flex-direction: column; + align-items: start; + } + } + + .form_group { + width: 260px!important; + height: 30px!important; + + &:has(input:focus) { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } + + * { + margin-left: 0.4em; + } + + label { + background-color: var(--color-extralight-grey); + top: -18px; + } + + i { + position: relative; + width: 25px; + height: 25px; + margin: auto; + + svg { + width: 20px; + height: 20px; + } + } + + #globalSearchInput { + width: 100%; + padding: 0.2em; + height: 30px; + + &::placeholder { + color: #aaa8a8; + } + } + + > div { + display: inline-block; + overflow: visible; + white-space: nowrap; + } + + > button { + padding: 0.6em; + } + } + } + + &_pagination { + &_title { + font-size: 14px; + margin: 0 0 5px 40px; + position: absolute; + top: -18px; + left: 12px; + } + + &_container { + display: flex; + align-items: center; + gap: 10px; + + button[disabled] { + color: gray; + } + + svg { + width: 20px; + } + } + + &_arrow { + margin: 0; + padding: 0; + width: 20px; + color: var(--color-blue); + + a { + color: var(--color-blue); + } + } + + &_select { + cursor: pointer; + min-width: 7em; + text-align: center; + padding: 0.2em; + margin: 0; + margin-left: 0; + margin-right: 0; + border: 1px solid gray; + border-radius: 4px; + height: 30px; + background-color: var(--color-secondary); + color: var(--color-primary); + } + + &_opds_currentPage { + min-width: 7em; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid gray; + border-radius: 4px; + height: 30px; + } + } + } +} + +.opds_publication_wrapper { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; +} + +.showColFilters { + &_wrapper { + display: flex; + align-items: center; + + .showColFilters_input { + border: 1px solid var(--color-blue); + border-radius: 4px; + margin: 0; + padding: 0.2em; + background-color: var(--color-secondary); } + } + + > button { + border: 1px solid gray; + border-radius: 4px; + margin: 0; + margin-left: 0.4em; + width: 24px; + height: 24px; + padding: 0.2em; + } +} + +.cell { + a { + cursor: pointer; + } + + &_coverImg { + padding: 0; + margin: 0; + text-align: center; + min-height: 100px; + // border: 1px solid #e2e2e2; + display: flex; + cursor: pointer; + + img { + object-fit: contain; + width: 100%; + height: 100%; + min-height: 100px; + cursor: pointer; + } + } + + &_bookTitle { + font-weight: bold; + padding: 0.4em 0; + cursor: pointer; + } + + &_link { + display: flex; + align-items: center; + text-align: left; + padding: 2px 6px; + cursor: pointer; + text-decoration: underline; + text-decoration-skip: ink; + margin-right: 6px; + margin-bottom: 6px; + } + + &_wrapper { + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: start; + padding-top: 0.2em; + overflow: hidden auto; + height: 100px; + margin-right: 2px; + + &:has(.button_nav_primary), &:has(.dropdown_trigger) { + justify-content: center; + } + + &::-webkit-scrollbar { + width: 12px; + + &-thumb { + background-color: var(--scrollbar-thumb); + border-radius: 6px; + border-left: 2px solid transparent; + background-clip: padding-box; + cursor: pointer; + + &:hover { + border: 0; + } + } + + &-track { + background-color: var(--color-secondary); + } + } + + &:hover { + &::-webkit-scrollbar-thumb { + background-color: var(--color-blue); + } + } + } + + &_multi_langs { + list-style-type: none; + padding: 5px; + display: flex; + flex-flow: column nowrap; + align-items: start; + justify-content: start!important; + gap: 5px; + max-height: 90px; + + li { + margin: 0; + padding: 0; + } + } + + &_description { + position: relative; + + p { + margin-top: 0; + max-height: 65px; + overflow: hidden; + text-overflow: ellipsis; + } + + button { + position: absolute; + right: 0; + bottom: -20px; + color: var(--color-blue); + width: 15px; + height: 15px; + } + } +} + +.allBook_table { + &_wrapper { + overflow: auto; + inset: 280px 20px 30px 26px; + padding: 0; + margin-top: 0; + margin-bottom: 0.4em; + position: absolute; + background-color: var(--color-secondary); + + &::-webkit-scrollbar { + width: 10px; + height: 10px; + background-color: var(--color-secondary); + + &-thumb { + background-color: var(--scrollbar-thumb); + border-radius: 6px; + border-left: 2px solid transparent; + background-clip: padding-box; + cursor: pointer; + + &:hover { + border-left: 0; + } + } + + &-track { + background-color: var(--color-secondary); + } + } + } + + &_head { + border-bottom: 2px solid var(--color-light-blue); + padding: 0.7em; + margin: 0; + background-color: var(--color-light-blue); + white-space: nowrap; + + button { + color: var(--color-blue); + height: auto; + padding: 0.2em; + margin: 0; + font-weight: bold; + } + } + + &_body { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-gap: 15px; + grid-row-gap: 30px; + margin-bottom: 20px; + background-color: var(--color-secondary); + + tr td { + border-bottom: none; + margin: 0; + padding: 0; + } + } + + border-radius: 8px; + padding: 4px; + margin: 0; + border-spacing: 0; + width: 100%; + position: relative; +} + +.filter_container { + .react_aria_ComboBox { + position: relative; + padding: 0; + margin: 0; + + .react_aria_Label { + position: absolute; + top: -20px; + } + + .react_aria_Input { + width: inherit; + } + + .my_combobox_container { + width: fit-content; + min-width: 150px; + background-color: var(--color-secondary); + padding: 2px 0; + + button span { + width: fit-content; + min-width: 100px; + padding: 0 10px; + text-align: left; + } + + .react_aria_Button { + margin-left: unset; + margin-right: 5px; + height: 24px; + width: 24px; + display: flex; + align-items: center; + justify-content: center; + } + } + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/allPublicationsPage.scss.d.ts b/src/renderer/assets/styles/components/allPublicationsPage.scss.d.ts new file mode 100644 index 000000000..0f980329c --- /dev/null +++ b/src/renderer/assets/styles/components/allPublicationsPage.scss.d.ts @@ -0,0 +1,33 @@ +export declare const allBook_table: string; +export declare const allBook_table_body: string; +export declare const allBook_table_head: string; +export declare const allBook_table_wrapper: string; +export declare const allBooks_header: string; +export declare const allBooks_header_navigation: string; +export declare const allBooks_header_navigation_inputs: string; +export declare const allBooks_header_pagination_arrow: string; +export declare const allBooks_header_pagination_container: string; +export declare const allBooks_header_pagination_opds_currentPage: string; +export declare const allBooks_header_pagination_select: string; +export declare const allBooks_header_pagination_title: string; +export declare const button_nav_primary: string; +export declare const cell: string; +export declare const cell_bookTitle: string; +export declare const cell_coverImg: string; +export declare const cell_description: string; +export declare const cell_link: string; +export declare const cell_multi_langs: string; +export declare const cell_wrapper: string; +export declare const dropdown_trigger: string; +export declare const filter_container: string; +export declare const form_group: string; +export declare const globalSearchInput: string; +export declare const my_combobox_container: string; +export declare const opds_publication_wrapper: string; +export declare const react_aria_Button: string; +export declare const react_aria_ComboBox: string; +export declare const react_aria_Input: string; +export declare const react_aria_Label: string; +export declare const showColFilters: string; +export declare const showColFilters_input: string; +export declare const showColFilters_wrapper: string; diff --git a/src/renderer/assets/styles/components/annotations.scss b/src/renderer/assets/styles/components/annotations.scss new file mode 100644 index 000000000..3958fc407 --- /dev/null +++ b/src/renderer/assets/styles/components/annotations.scss @@ -0,0 +1,408 @@ +@import "src/renderer/assets/styles/focus"; + +.annotations_tab { + display: flex; + flex-direction: column; + gap: 5px; +} + +.annotations_options { + summary { + display: flex; + align-items: center; + justify-content: start; + color: var(--color-blue); + font-size: 14px; + + span svg { + fill: var(--color-blue); + width: 20px; + height: 20px; + margin: 0 0.75em; + padding-top: 5px; + padding-bottom: 0; + } + + svg { + fill: var(--color-blue); + width: 14px; + height: 14px; + margin-right: 0.5em; + } + } + + &[open] > summary span svg { + transform: rotate(180deg); + padding-bottom: 5px; + padding-top: 0; + } + + .annotations_checkbox { + display: flex; + align-items: start; + padding: 5px; + height: fit-content; + margin-left: 15px; + + label { + margin: 0; + height: fit-content!important; + } +} +} + +.annotation_form { + background-color: var(--color-light-grey); + max-width: 400px; + border-radius: 6px; + border: 1px solid var(--color-medium-grey); + display: flex; + flex-direction: column; + padding: 5px 10px; + color: var(--color-primary); + + // gap: 10px; + + h4 { + margin: 5px 0; + } + + label { + margin: 5px; + } + + &_textarea{ + width: 380px; + min-width: 380px; + height: 100px; + min-height: 100px; + max-width: 380px; + border: 1px solid rgb(118 118 118); + border-radius: 3px; + font-family: Nunito, sans-serif; + + + &_container { + display: flex; + flex-direction: column; + } + + &_buttons { + margin: 5px 0; + display: flex; + gap: 5px; + + button { + min-width: unset; + width: fit-content; + height: 25px; + + &.button_primary_blue { + color: var(--color-secondary); + + &:hover { + color: var(--color-blue); + } + } + + svg { + fill: var(--color-secondary); + color: var(--color-secondary); + } + + &:hover svg { + fill: var(--color-blue); + color: var(--color-blue); + } + } + } + } + } + + .annotation_actions { + display: flex; + align-items: center; + gap: 30px; + margin: 10px 0; + + &_container { + display: flex; + flex-direction: column; + justify-content: start; + } + + >div { + display: inherit; + + >div { + display: flex; + // gap: 5px; + align-items: center; + } + + p { + margin: 0; + } + + svg { + width: 20px; + height: 20px; + } + } + + &_buttons { + button:disabled { + border-radius: 5px; + background-color: var(--color-medium-grey); + + svg { + fill: var(--color-primary); + color: var(--color-primary); + } + } + + svg { + fill: var(--color-blue); + color: var(--color-blue); + } + } + } + + .annotation_edit_form { + display: flex; + flex-direction: column; + + p { + background-color: var(--color-light-grey); + width: 95%!important; + border-radius: 5px; + margin-bottom: 10px!important; + } + + &_textarea{ + min-width: 95%; + max-width: 95%; + min-height: 30px; + border: 1px solid var(--color-primary); + border-radius: 3px; + font-family: Nunito, sans-serif; + overflow: hidden; + + &_container { + display: flex; + flex-direction: column; + } + + &_buttons { + margin: 5px 0; + display: flex; + gap: 5px; + } + } + } + + .colorPicker { + display: flex; + background-color: var(--color-secondary); + padding: 2px; + gap: 1px; + border: 1px solid var(--color-primary); + border-radius: 6px; + + &:has(input:focus) { + @include R2_MIXIN_FOCUS_OUTLINE; + } + + div { + input { + position: absolute; + z-index: -1; + } + + label { + z-index: 20; + width: 25px; + height: 25px; + margin: 0; + border: 1px solid white; + display: flex; + align-items: center; + justify-content: center; + border-radius: 5px; + cursor: pointer; + } + } + } + + .stylePicker { + display: flex; + padding: 2px; + gap: 10px; + border-radius: 5px; + + &:has(input:focus) { + @include R2_MIXIN_FOCUS_OUTLINE; + } + + div { + input { + position: absolute; + z-index: -1; + } + + label { + z-index: 20; + width: 27px; + height: 27px; + margin: 0; + background-color: inherit; + cursor: pointer; + border-radius: 3px; + display: flex; + align-items: center; + justify-content: center; + + svg { + color: var(--color-blue); + } + } + } + } + + .drawType_active { + background-color: var(--color-blue)!important; + + svg { + color: var(--color-secondary)!important; + fill: var(--color-secondary)!important; + } + } + + .annotations_line { + width: calc(100% - 10px); + position: relative; + text-align: left; + font-size: 1rem; + border-left: 2px solid var(--color-blue); + padding-left: 10px; + margin: 10px 0; + + p { + text-align: left; + + // overflow: hidden; + // text-overflow: ellipsis; + width: 100%; + + // display: -webkit-box; + // -webkit-box-orient: vertical; + // -webkit-line-clamp: 3; + padding: 5px; + margin: 0; + } + + // @media (prefers-color-scheme: dark) { + // background-color: #2D2D2D; + // } + + .annnotation_container:has(.annotation_name:focus) { + outline: 2px solid var(--color-blue); + border-radius: 5px; + } + + .annotation_name { + background-color: var(--color-light-grey); + border-bottom: 8px solid var(--color-light-grey); + height: unset; + font-family: Nunito, sans-serif; + + p { + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 4; + margin: 0; + padding: 8px; + padding-bottom: 0; + } + + // &:focus { + // outline: 2px solid var(--color-blue); + // } + } + + .update_form input { + width: 100%; + border-radius: 6px; + } + + & > button { + border: none; + background-color: transparent; + cursor: pointer; + padding: 0; + + & svg { + width: 24px; + } + } + + & img { + width: 30px; + height: 30px; + display: inline-block; + vertical-align: top; + } + + // & .chapter_marker { + // vertical-align: top; + // position: relative; + // display: inline-block; + // flex: 1; + // font-size: 0.9rem; + // margin-right: 0.5rem; + // } + + & span { + display: inline-block; + vertical-align: top; + margin-top: 5px; + } + + .annotation_edit { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 5px; + + >div { + display: inherit; + align-items: center; + gap: 5px; + + button { + padding: 5px; + } + + >div { + display: flex; + gap: 5px; + align-items: center; + } + + svg { + width: 18px; + height: 18px; + } + } + } + } + +.docked_annotation_line { + border-left: 2px solid var(--color-blue); + padding: 0 10px; + margin-top: 5px; +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/annotations.scss.d.ts b/src/renderer/assets/styles/components/annotations.scss.d.ts new file mode 100644 index 000000000..ab0dfc8f3 --- /dev/null +++ b/src/renderer/assets/styles/components/annotations.scss.d.ts @@ -0,0 +1,31 @@ +export declare const ___DEBUG___FOCUS_CSS: string; +export declare const ___DEBUG___FOCUS_MIXIN_CSS: string; +export declare const annnotation_container: string; +export declare const annotation_actions: string; +export declare const annotation_actions_buttons: string; +export declare const annotation_actions_container: string; +export declare const annotation_edit: string; +export declare const annotation_edit_form: string; +export declare const annotation_edit_form_textarea: string; +export declare const annotation_edit_form_textarea_buttons: string; +export declare const annotation_edit_form_textarea_container: string; +export declare const annotation_form: string; +export declare const annotation_form_textarea: string; +export declare const annotation_form_textarea_buttons: string; +export declare const annotation_form_textarea_container: string; +export declare const annotation_name: string; +export declare const annotations_checkbox: string; +export declare const annotations_line: string; +export declare const annotations_options: string; +export declare const annotations_tab: string; +export declare const body_element: string; +export declare const button_primary_blue: string; +export declare const colorPicker: string; +export declare const docked_annotation_line: string; +export declare const drawType_active: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; +export declare const R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE: string; +export declare const R2_CSS_CLASS__KEYBOARD_INTERACT: string; +export declare const readium2ElectronAnimation_TARGET: string; +export declare const stylePicker: string; +export declare const update_form: string; diff --git a/src/renderer/assets/styles/components/blocks.css b/src/renderer/assets/styles/components/blocks.css deleted file mode 100644 index 7569af54b..000000000 --- a/src/renderer/assets/styles/components/blocks.css +++ /dev/null @@ -1,173 +0,0 @@ -/* -=-=-= components/blocks.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/blocks.css -*/ - -/* - - 1. .block_line - .block_line_edit - - 2. .block_full - .block_full_wrapper - .block_full_close - -*/ - -/* 1. .block_line ... */ - -.block_line { - padding: 0.5em; - border-radius: 8px; - border-width: 1px; - border-style: solid; - border-color: var(--color-disabled); - - &.description_see_more { - position: relative; - font-size: 1rem; - - & p { - margin: 0; - } - } -} - -.block_line_edit { - padding: 0.5em; - border-radius: 8px; - border-width: 1px; - border-style: dashed; - border-color: var(--color-primary); -} - -.block_line, -.block_line_edit { - margin-top: 20px; -} - -.block_line_inactive { - opacity: 0.5; -} - -/* 1. .block_full ... */ - -.block_full { - padding: 0.5em; - border-radius: 10px; - border-width: 1px; - border-style: solid; - background: linear-gradient(160.03deg, #6fa4fc 0%, #4083fd 100%); - border-color: transparent; - display: flex; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - text-decoration: none; - font-size: 20px; - box-shadow: 0 2px 15px rgba(0, 0, 0, 0); - transition: all 0.3s; - line-break: anywhere; - - & p, - & a, - & button { - color: #fff; - } -} - -.block_full_wrapper { - list-style: none; - width: 191px; - height: 191px; - padding-right: 20px; - padding-bottom: 20px; - position: relative; - transition: all 0.3s; - flex: none; - margin-right: 15px; - margin-bottom: 15px; - - &:hover { - transform: scale(1.05); - - & .block_full { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2); - } - } -} - -.block_full_close { - position: absolute; - top: 10px; - right: 10px; - z-index: 2; - color: #fff; - fill: #fff; - font-size: 20px; - font-weight: 800; - border-radius: 5px; - background: rgba(255, 255, 255, 0); - transition: all 0.2s; - cursor: pointer; - margin-right: 0 !important; - - &:hover { - background: rgba(255, 255, 255, 0.2); - } -} - -.block_full_update { - position: absolute; - top: 10px; - left: 10px; - z-index: 2; - color: #fff; - fill: #fff; - border-radius: 5px; - background: rgba(255, 255, 255, 0); - transition: all 0.2s; - cursor: pointer; - - & svg { - transform: scale(0.8); - } - - &:hover { - background: rgba(255, 255, 255, 0.2); - } -} - -.block_dashed { - border-radius: 1em; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - border: 1px #5c5c5c dashed; - min-height: 17rem; - max-width: 43rem; - margin: 2rem auto; - box-sizing: border-box; - color: #5c5c5c; - - & p { - font-size: 1.1rem; - } - - & p:last-child { - font-size: 1rem; - } -} - -.___DEBUG___COMPONENTS_BLOCKS_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/blocks.css.d.ts b/src/renderer/assets/styles/components/blocks.css.d.ts deleted file mode 100644 index 641c04ccd..000000000 --- a/src/renderer/assets/styles/components/blocks.css.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_BLOCKS_CSS": string; - readonly "block_dashed": string; - readonly "block_full": string; - readonly "block_full_close": string; - readonly "block_full_update": string; - readonly "block_full_wrapper": string; - readonly "block_line": string; - readonly "block_line_edit": string; - readonly "block_line_inactive": string; - readonly "description_see_more": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/blocks.scss b/src/renderer/assets/styles/components/blocks.scss new file mode 100644 index 000000000..1015c4a89 --- /dev/null +++ b/src/renderer/assets/styles/components/blocks.scss @@ -0,0 +1,64 @@ +/* +=-=-= blocks.scss +*/ + +.block_line { + padding: 0.5em; + border-radius: 8px; + border-width: 1px; + border-style: solid; + border-color: var(--color-disabled); + + &.description_see_more { + position: relative; + font-size: 1rem; + + & p { + margin: 0; + } + } +} + +.block_line_edit { + padding: 0.5em; + border-radius: 8px; + border-width: 1px; + border-style: dashed; + border-color: var(--color-primary); +} + +.block_line, +.block_line_edit { + margin-top: 20px; +} + +.block_line_inactive { + opacity: 0.5; +} + + +.block_dashed { + border-radius: 1em; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + border: 1px var(--color-disabled) dashed; + min-height: 17rem; + max-width: 43rem; + margin: 2rem auto; + box-sizing: border-box; + color: var(--color-disabled); + + & p { + font-size: 1.1rem; + } + + & p:last-child { + font-size: 1rem; + } +} + +.___DEBUG___COMPONENTS_BLOCKS_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/components/blocks.scss.d.ts b/src/renderer/assets/styles/components/blocks.scss.d.ts new file mode 100644 index 000000000..e767fe81e --- /dev/null +++ b/src/renderer/assets/styles/components/blocks.scss.d.ts @@ -0,0 +1,6 @@ +export declare const ___DEBUG___COMPONENTS_BLOCKS_CSS: string; +export declare const block_dashed: string; +export declare const block_line: string; +export declare const block_line_edit: string; +export declare const block_line_inactive: string; +export declare const description_see_more: string; diff --git a/src/renderer/assets/styles/components/breadcrumb.css b/src/renderer/assets/styles/components/breadcrumb.css deleted file mode 100644 index 9900ed465..000000000 --- a/src/renderer/assets/styles/components/breadcrumb.css +++ /dev/null @@ -1,62 +0,0 @@ -/* -=-=-= components/breadcrumb.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/breadcrumb.css -*/ - -.breadcrumb { - padding: 10px 60px; - font-size: 16px; - display: flex; - align-items: center; - - /* color: rgb(59, 59, 59); */ - color: var(--color-accent); - position: fixed; - top: 123px; - width: calc(100% - 120px); - border-bottom: 1px solid var(--color-light-grey); - - & .button_transparency_icon { - position: relative; - height: 38px; - width: 42px; - margin-right: 10px; - - & svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - height: 24px; - width: 24px; - } - } - - & .button_transparency { - font-weight: 500; - text-decoration: none; - font-size: inherit; - white-space: nowrap; - - &::after { - content: "/"; - margin-left: 10px; - margin-right: -5px; - } - - & + .button_transparency { - margin-left: -10px; - } - } -} - -.___DEBUG___COMPONENTS_BREADCRUMB_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/breadcrumb.css.d.ts b/src/renderer/assets/styles/components/breadcrumb.css.d.ts deleted file mode 100644 index ff1ec629f..000000000 --- a/src/renderer/assets/styles/components/breadcrumb.css.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_BREADCRUMB_CSS": string; - readonly "breadcrumb": string; - readonly "button_transparency": string; - readonly "button_transparency_icon": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/breadcrumb.scss b/src/renderer/assets/styles/components/breadcrumb.scss new file mode 100644 index 000000000..287df795a --- /dev/null +++ b/src/renderer/assets/styles/components/breadcrumb.scss @@ -0,0 +1,90 @@ +/* +=-=-= breadcrumbs.scss +*/ + +.breadcrumb { + font-size: 16px; + display: flex; + align-items: center; + font-weight: bold; + color: var(--color-blue); + width: calc(100% - 120px); + + a { + display: flex; + max-width: 150px; + + & p { + font-size: 14px; + max-width: 110px; + overflow: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + } + + } + + & strong { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + margin: 0 10px; + } + + & .breadcrumb_icon { + position: relative; + height: 38px; + width: 42px; + + & svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + height: 24px; + width: 24px; + } + } + + & .button_transparency { + font-weight: 500; + text-decoration: underline; + font-size: inherit; + white-space: nowrap; + height: 32px; + padding: 0 5px; + margin: 0 10px; + border: 1px solid transparent; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + + svg { + width: 20px; + } + + &:hover { + background-color: var(--color-secondary); + border-color: var(--color-blue); + } + + p { + margin: auto; + } + + & + .button_transparency { + margin-left: -10px; + } + } + + svg { + height: 20px; + color: var(--color-blue); + } +} + +.___DEBUG___COMPONENTS_BREADCRUMB_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/components/breadcrumb.scss.d.ts b/src/renderer/assets/styles/components/breadcrumb.scss.d.ts new file mode 100644 index 000000000..2d319bced --- /dev/null +++ b/src/renderer/assets/styles/components/breadcrumb.scss.d.ts @@ -0,0 +1,4 @@ +export declare const ___DEBUG___COMPONENTS_BREADCRUMB_CSS: string; +export declare const breadcrumb: string; +export declare const breadcrumb_icon: string; +export declare const button_transparency: string; diff --git a/src/renderer/assets/styles/components/buttons.css b/src/renderer/assets/styles/components/buttons.css deleted file mode 100644 index f40963040..000000000 --- a/src/renderer/assets/styles/components/buttons.css +++ /dev/null @@ -1,427 +0,0 @@ -/* -=-=-= components/buttons.css => '../partials/mixins.css' -*/ -@import url('../partials/mixins.css'); - -/* -=-=-= components/buttons.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/buttons.css -*/ - -/* - - 1. button - - 2. .button_primary - .button_primary_small - - 3. .button_secondary - - 4. (x) .button_tertiary - - 5. .button_transparency - .button_transparency_icon - .button_link - - 6. .button_keyboard - -*/ - -/* button */ - -button, -.button_primary, -.button_primary_small { - &:not(:last-child) { - margin-right: 10px; - } -} - -button { - padding: 0; - background: none; - border: 0; - height: 30px; - fill: var(--color-primary); - cursor: pointer; - - &:hover { - opacity: 1; - } -} - -.button_outline_accessibility button { - width: auto; - height: 40px; - border-radius: 5px; -} - -/* - - 2. .button_primary - .button_primary_small - .button_primary_icon - -*/ - -.button_primary_form_default { - border-width: 2px !important; - font-weight: bold !important; -} - -.button_primary { - @mixin button_primary; - - font: 1rem Arial, sans-serif; - padding: 10px 15px; - - & svg { - vertical-align: -2px; - width: auto; - height: 14px; - margin-right: 8px; - transition: all 0.2s; - fill: var(--color-primary); - } - - &.icon_end { - & svg { - margin-right: 0; - margin-left: 8px; - } - } - - &.disabled, - &[disabled] { - opacity: 0.5; - cursor: default; - pointer-events: none; - - &:hover { - background: transparent; - } - } -} - -.button_primary_small, -.heading button { - @mixin button_primary; - - font: 14px Arial, sans-serif; - padding: 8px 15px; - - & svg { - height: 14px; - width: 14px; - vertical-align: -2px; - margin-left: 5px; - fill: var(--color-primary); - - } - - &.button_icon { - height: 16px; - padding: 8px 20px; - background: var(--color-secondary); - overflow: visible; - - & input { - overflow: hidden; - z-index: -1; - position: absolute; - top: -2px; - left: -2px; - width: calc(100% + 2px); - height: calc(100% + 2px); - appearance: none; - color: transparent; - background: transparent; - border-radius: 7px; - border: 1px solid transparent; - } - - & svg { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 18px; - height: 18px; - margin: 0; - vertical-align: 0; - } - } -} - -.button_primary_icon { - @mixin button_primary; - - padding: 10px 15px; - width: 18px; - height: 18px; -} - -/* 4. .button_secondary */ - -.button_secondary { - font: 1rem Arial, sans-serif; - padding: 10px 15px; - position: relative; - display: inline; - background-color: var(--color-accent); - border: none; - border-radius: 5px; - text-align: center; - color: var(--color-accent-contrast); - fill: var(--color-accent-contrast); - text-decoration: none; - overflow: hidden; - cursor: pointer; - width: auto; - height: auto; - transition: all 0.2s; - - & svg { - vertical-align: -2px; - fill: var(--color-accent-contrast); - width: auto; - height: 14px; - margin-right: 8px; - transition: all 0.2s; - } - - &[disabled], - &.disabled { - color: #fff; - background-color: var(--color-disabled); - } -} - -/* - - 5. .button_transparncy - .button_transparency_icon - .button_primary_icon - -*/ - -.button_transparency, -.button_transparency_icon { - display: inline-block; - color: var(--color-primary); - transition: all 0.2s; - border-radius: 5px; - background: rgba(0, 0, 0, 0); - font-size: 1rem; - font-family: "Arial", sans-serif; - font-weight: 600; - cursor: pointer; - - & svg { - fill: var(--color-primary); - } - - &:hover { - background: rgba(0, 0, 0, 0.1); - } -} - -.button_transparency { - padding: 10px 15px; - width: auto; - height: auto; - - & svg { - width: 18px; - margin-right: 8px; - vertical-align: -3px; - color: var(--color-disabled); - } -} - -.button_transparency_icon, -.button_transparency_icon_inactive { - height: 34px; - width: 34px; - transition-duration: 0ms; - - & svg { - height: 34px; - width: 34px; - transition: all 0.2s 0.05s; - } - - &.button_refresh:hover svg { - transform: scale(0.8) rotate(90deg); - } - - &.button_small svg { - transform: scale(0.8); - } - - &:hover { - background: rgba(0, 0, 0, 0.1); - } -} - -.button_transparency_icon_inactive { - fill: #767676; -} - -.button_link { - color: var(--color-tertiary); - text-decoration: underline; - text-underline-offset: 1px; - cursor: pointer; - display: inline-block; -} - -/* - - 6. .button_keyboard - -*/ - -.button_keyboard { - width: auto; - height: auto; - font-size: 80%; - display: inline-block; - padding: 0.3em; - margin-right: 1em; - border: 2px solid rgb(171, 171, 171); - border-bottom: 2px solid rgb(41, 41, 41); - border-right: 2px solid rgb(41, 41, 41); - border-radius: 3px; - background-color: #d0d0d0; -} - -.skip_link { - position: absolute; - left: -2000px; - - &:focus { - left: unset; - left: 0; - width: fit-content; - top: 0; - opacity: 1; - height: unset; - z-index: 150; - font-size: 1rem; - padding: 1rem; - color: white; - background-color: #0366d6; - } -} - -.button_see_more { - font-size: 1rem; - height: auto; - position: absolute; - bottom: 0; - left: 0; - right: 0; - width: 100%; - margin: 0; - padding: 5px 0; - border-top: 1px solid var(--color-disabled); - border-radius: 0 0 5px 5px; - color: #000; - -webkit-font-smoothing: subpixel-antialiased; - box-shadow: 0 -2px 4px 0 rgb(0 0 0 / 10%); - transition: all 0.2s; - - &:hover { - background: rgba(0, 0, 0, 0.1); - } -} - -.buttons_list { - list-style-type: none; - padding: 0; - display: flex; - flex-flow: wrap; - margin: 0; - justify-content: left; - - & li { - width: 50%; - } - - & .button_transparency { - margin: 2px 0; - text-decoration: none; - width: calc(100% - 30px); - display: flex; - justify-content: space-between; - - & span:last-child:not(:only-child) { - font-weight: 500; - opacity: 0.8; - font-size: 90%; - } - } -} - -.col_filter { - & .block_line { - border: none; - border-radius: 0; - padding: 0; - } - - & .buttons_list { - display: block; - - & li { - width: auto; - } - } -} - -@media (width >= 1200px) { - .buttons_list li { - width: 33%; - } - - .col_filter .buttons_list li { - width: auto; - } -} - -@media (width >= 1500px) { - .buttons_list li { - width: 25%; - } - - .col_filter .buttons_list li { - width: auto; - } -} - -.col_book_img { - & .button_primary, - & .button_transparency { - width: 100%; - } - - & .button_primary { - margin: 8px 0; - } - - & .button_transparency { - margin: 2px 0; - } -} - -.___DEBUG___COMPONENTS_BUTTONS_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/buttons.css.d.ts b/src/renderer/assets/styles/components/buttons.css.d.ts deleted file mode 100644 index 398924e60..000000000 --- a/src/renderer/assets/styles/components/buttons.css.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_BUTTONS_CSS": string; - readonly "block_line": string; - readonly "button_icon": string; - readonly "button_keyboard": string; - readonly "button_link": string; - readonly "button_outline_accessibility": string; - readonly "button_primary": string; - readonly "button_primary_form_default": string; - readonly "button_primary_icon": string; - readonly "button_primary_small": string; - readonly "button_refresh": string; - readonly "button_secondary": string; - readonly "button_see_more": string; - readonly "button_small": string; - readonly "button_transparency": string; - readonly "button_transparency_icon": string; - readonly "button_transparency_icon_inactive": string; - readonly "buttons_list": string; - readonly "col_book_img": string; - readonly "col_filter": string; - readonly "disabled": string; - readonly "heading": string; - readonly "icon_end": string; - readonly "skip_link": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/buttons.scss b/src/renderer/assets/styles/components/buttons.scss new file mode 100644 index 000000000..4fb73e520 --- /dev/null +++ b/src/renderer/assets/styles/components/buttons.scss @@ -0,0 +1,515 @@ +/* +=-=-= buttons.scss +*/ + +@import "src/renderer/assets/styles/partials/mixin"; + +button { + padding: 0; + background: none; + border: 0; + height: 30px; + color: var(--color-primary); + fill: var(--color-primary); + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + + &:hover { + opacity: 1; + background: transparent; + } + + &[type="submit"] svg { + width: 13px; + } + + &.disabled, + &[disabled] { + opacity: 0.5; + cursor: default; + pointer-events: none; + } +} + +.button_outline_accessibility button { + width: auto; + height: 40px; + border-radius: 5px; +} + +.button_primary_form_default { + border-width: 2px !important; + font-weight: bold !important; +} + +.button_primary_blue { + border: 1px solid var(--color-blue); + height: 30px; + border-radius: 4px; + padding: 5px; + min-width: 100px; + background-color: var(--color-blue); + color: white; + transition: 200ms linear; + display: inline-flex; + align-items: center; + justify-content: center; + + svg { + width: 14px; + fill: white; + } + + &:hover { + color: var(--color-blue); + background-color: var(--color-light-blue) + } +} + +.button_primary { + @include button_primary; + + padding: 10px 15px; + + &_small { + font: 14px Arial, sans-serif; + padding: 8px 15px; + + & svg { + height: 14px; + width: 14px; + vertical-align: -2px; + margin-left: 5px; + fill: var(--color-primary); + } + + &.button_icon { + height: 16px; + padding: 8px 20px; + background: var(--color-secondary); + overflow: visible; + + & input { + overflow: hidden; + z-index: -1; + position: absolute; + top: -2px; + left: -2px; + width: calc(100% + 2px); + height: calc(100% + 2px); + appearance: none; + color: transparent; + background: transparent; + border-radius: 7px; + border: 1px solid transparent; + } + + & svg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 18px; + height: 18px; + margin: 0; + vertical-align: 0; + } + } + } + + & svg { + vertical-align: -2px; + width: auto; + height: 14px; + transition: all 0.2s; + fill: var(--color-primary); + } + + &.icon_end { + & svg { + margin-right: 0; + margin-left: 8px; + } + } +} +/* 4. .button_secondary */ + +.button_secondary_blue { + border: 1px solid var(--color-blue); + height: 30px; + border-radius: 4px; + padding: 5px; + min-width: 100px; + background-color: var(--color-light-blue); + color: var(--color-blue); + display: flex; + align-items: center; + justify-content: center; + + &:hover { + color: var(--color-blue); + background-color: var(--color-secondary) + } + + svg { + width: 12px; + height: 12px; + fill: var(--color-blue); + } +} + +.button_secondary { + padding: 10px 15px; + position: relative; + display: inline; + background-color: var(--color-accent); + border: none; + border-radius: 5px; + text-align: center; + color: var(--color-accent-contrast); + fill: var(--color-accent-contrast); + text-decoration: none; + overflow: hidden; + cursor: pointer; + width: auto; + height: auto; + transition: all 0.2s; + + & svg { + vertical-align: -2px; + fill: var(--color-accent-contrast); + width: auto; + height: 14px; + transition: all 0.2s; + } + + &[disabled], + &.disabled { + color: #fff; + background-color: var(--color-disabled); + } +} + +.button_transparency, +.button_transparency_icon { + display: inline-block; + color: var(--color-primary); + transition: all 0.2s; + border-radius: 5px; + background: rgb(0 0 0 / 0%); + font-size: 1rem; + font-family: Arial, sans-serif; + font-weight: 600; + cursor: pointer; + + & svg { + fill: var(--color-primary); + } + + &:hover { + background: rgb(0 0 0 / 10%); + } +} + +.button_transparency { + padding: 10px 15px; + width: auto; + height: auto; + + & svg { + width: 18px; + vertical-align: -3px; + color: var(--color-disabled); + } +} + +.button_transparency_icon, +.button_transparency_icon_inactive { + height: 30px; + width: 30px; + transition-duration: 0ms; + fill: var(--color-blue); + + & svg { + height: 20px; + width: 20px; + fill: var(--color-blue); + color: var(--color-blue); + transition: all 0.2s 0.05s; + } + + &.button_refresh:hover svg { + transform: scale(0.8) rotate(90deg); + } + + &.button_small svg { + transform: scale(0.8); + } + + &:hover { + background: rgb(0 0 0 / 10%); + } + + &:disabled { + background-color: var(--color-medium-grey); + } +} + +.button_transparency_icon_inactive { + fill: #767676; +} + +.button_link { + color: var(--color-tertiary); + text-decoration: underline; + text-underline-offset: 1px; + cursor: pointer; + display: inline-block; +} + +.button_nav_primary { + border: 1px solid var(--color-blue); + height: 20px; + border-radius: 4px; + padding: 5px; + background-color: var(--color-light-blue); + color: var(--color-blue); + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + width: fit-content; + cursor: pointer; + gap: 5px; + box-sizing: content-box; + position: relative; + + &:focus-within { + @include R2_MIXIN_FOCUS_OUTLINE; + } + + svg { + width: 15px; + height: 15px; + fill: var(--color-blue); + } + + input { + position: absolute; + right: 0; + top: 0; + width: 100%; + height: 100%; + z-index: -10; + } +} + +.button_nav_secondary { + border: 1px solid transparent; + height: 20px; + border-radius: 4px; + padding: 5px; + background-color: transparent; + color: var(--color-primary); + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + width: fit-content; + cursor: pointer; + gap: 5px; + + svg { + width: 15px; + height: 15px; + fill: var(--color-primary); + } + + input { + display: none; + } +} + +.button_nav_tertiary { + border: 1px solid; + border-color: transparent; + height: 15px; + border-radius: 4px; + padding: 5px; + background-color: transparent; + color: var(--color-blue); + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + width: fit-content; + cursor: pointer; + gap: 5px; + box-sizing: content-box; + position: relative; + transition: 200ms; + + &:hover { + border-color: var(--color-blue); + } + + &:focus-within { + @include R2_MIXIN_FOCUS_OUTLINE; + } + + a { + height: inherit; + + &:hover svg { + transform: rotate(90deg); + } + } + + svg { + width: 15px; + height: 15px; + fill: var(--color-blue); + color: var(--color-blue); + transform: rotate(0); + transition: 200ms; + } + + input { + position: absolute; + right: 0; + top: 0; + width: 100%; + height: 100%; + z-index: -10; + } +} + +.button_catalog_infos { + color: var(--color-blue); + border-radius: 4px; + padding: 5px; + background-color: var(--color-light-blue); + margin: 30px 0; + width: fit-content; + + &[open] { + width: 100%; + } + + summary { + font-size: 14px; + } + + .catalog_infos_text { + padding-left: 5px; + } + + svg { + width: 20px; + fill: var(--color-blue); + } +} + +.skip_link { + position: absolute; + left: -2000px; + + &:focus { + left: unset; + left: 0; + width: fit-content; + top: 0; + opacity: 1; + height: unset; + z-index: 150; + font-size: 1rem; + padding: 1rem; + color: white; + background-color: #0366d6; + } +} + +.buttons_list { + list-style-type: none; + padding: 0; + display: flex; + flex-flow: wrap; + margin: 0; + justify-content: left; + + & li { + width: 50%; + } + + & .button_transparency { + margin: 2px 0; + text-decoration: none; + width: calc(100% - 30px); + display: flex; + justify-content: space-between; + + & span:last-child:not(:only-child) { + font-weight: 500; + opacity: 0.8; + font-size: 90%; + } + } +} + +.col_filter { + & .block_line { + border: none; + border-radius: 0; + padding: 0; + } + + & .buttons_list { + display: block; + + & li { + width: auto; + } + } +} + +@media (width >= 1200px) { + .buttons_list li { + width: 33%; + } + + .col_filter .buttons_list li { + width: auto; + } +} + +@media (width >= 1500px) { + .buttons_list li { + width: 25%; + } + + .col_filter .buttons_list li { + width: auto; + } +} + +.col_book_img { + & .button_primary, + & .button_transparency { + width: 100%; + } + + & .button_primary { + margin: 8px 0; + } + + & .button_transparency { + margin: 2px 0; + } +} + +.___DEBUG___COMPONENTS_BUTTONS_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/components/buttons.scss.d.ts b/src/renderer/assets/styles/components/buttons.scss.d.ts new file mode 100644 index 000000000..e12810a2a --- /dev/null +++ b/src/renderer/assets/styles/components/buttons.scss.d.ts @@ -0,0 +1,28 @@ +export declare const ___DEBUG___COMPONENTS_BUTTONS_CSS: string; +export declare const ___DEBUG___PARTIALS_MIXINS_CSS: string; +export declare const block_line: string; +export declare const button_catalog_infos: string; +export declare const button_icon: string; +export declare const button_link: string; +export declare const button_nav_primary: string; +export declare const button_nav_secondary: string; +export declare const button_nav_tertiary: string; +export declare const button_outline_accessibility: string; +export declare const button_primary: string; +export declare const button_primary_blue: string; +export declare const button_primary_form_default: string; +export declare const button_primary_small: string; +export declare const button_refresh: string; +export declare const button_secondary: string; +export declare const button_secondary_blue: string; +export declare const button_small: string; +export declare const button_transparency: string; +export declare const button_transparency_icon: string; +export declare const button_transparency_icon_inactive: string; +export declare const buttons_list: string; +export declare const catalog_infos_text: string; +export declare const col_book_img: string; +export declare const col_filter: string; +export declare const disabled: string; +export declare const icon_end: string; +export declare const skip_link: string; diff --git a/src/renderer/assets/styles/components/catalogs.scss b/src/renderer/assets/styles/components/catalogs.scss new file mode 100644 index 000000000..c3bb896bf --- /dev/null +++ b/src/renderer/assets/styles/components/catalogs.scss @@ -0,0 +1,289 @@ +/* +=-=-= catalogs.scss +*/ + +.catalog_wrapper { + display: flex; + flex-wrap: wrap; + justify-content: start; + align-items: center; + gap: 50px; + width: 100%; + padding: 0; + + @media screen and (width <= 800px) { + gap: 40px; + } + + .catalog_container { + width: 260px; + height: 175px; + list-style-type: none; + position: relative; + transition: 200ms ease-in-out; + } + + .catalog_content { + border-radius: 6px; + border-width: 2px; + border-style: solid; + border-color: var(--color-medium-grey); + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + text-decoration: none; + box-shadow: 0 2px 15px rgb(0 0 0 / 0%); + transition: all 0.3s; + padding: 0; + background-color: var(--color-secondary); + + &::after { + content: ""; + width: inherit; + height: inherit; + position: absolute; + top: -8px; + right: -10px; + border-radius: 6px; + border-right: 1px solid var(--color-medium-grey); + border-top: 1px solid var(--color-medium-grey); + } + + svg { + width: 101%; + position: absolute; + top: 1px; + left: 1px; + padding: 0; + } + + .catalog_title { + position: absolute; + top: 25px; + left: 30px; + display: block; + + svg { + width: 30px; + height: 30px; + margin-bottom: 30px; + color: var(--color-blue); + background-color: var(--color-secondary); + padding: 11px; + border-radius: 50%; + position: absolute; + top: 0; + left: -10px; + } + + p { + position: relative; + padding-right: 10px; + top: 35px; + left: -10px; + color: var(--color-primary); + overflow-wrap: anywhere; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 4; + line-clamp: 4; + -webkit-box-orient: vertical; + } + } + } + + .button_edit, .button_delete { + position: absolute; + bottom: 10px; + color: var(--color-blue); + transition: 200ms ease-in-out; + border: 1px solid transparent; + border-radius: 4px; + height: 18px; + width: 18px; + padding: 5px; + box-sizing: content-box; + + &:hover { + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + } + } + + .button_edit { + right: 45px; + } + + .button_delete { + right: 15px; + height: 16px; + width: 16px; + } +} + +.entryList{ + &_ul { + list-style-type: none; + padding: 10px 0 0; + display: flex; + flex-flow: wrap; + margin: 0; + justify-content: left; + gap: 20px; + } + + &_item { + border-radius: 6px; + border-width: 2px; + border-style: solid; + border-color: var(--color-medium-grey); + display: flex; + align-items: center; + justify-content: center; + width: 250px; + height: 70px; + text-decoration: none; + box-shadow: 0 2px 15px rgb(0 0 0 / 0%); + transition: all 0.3s; + position: relative; + + &::after { + content: ""; + z-index: -1; + width: inherit; + height: 100%; + position: absolute; + top: -8px; + right: -10px; + border-radius: 6px; + border-right: 1px solid var(--color-medium-grey); + border-top: 1px solid var(--color-medium-grey); + } + + a { + width: 100%; + height: calc(100% - 15px); + align-self: center; + text-decoration: none; + font-size: 14px; + font-weight: 400; + display: flex; + align-items: center; + justify-content: center; + } + } +} + +.col_filter .entryList_ul { + gap: unset; + + .entryList_item { + height: 35px; + border-color: transparent; + + a { + justify-content: unset; + + &:hover { + background-color: unset; + } + } + + &::after { + border: none; + } + + &:hover { + background-color: var(--color-light-blue)!important; + } + } +} + +.catalog_infos_text { + margin-bottom: 30px; + font-size: 14px; + max-width: 750px; + + a { + color: var(--color-blue); + display: flex; + align-items: center; + gap: 5px; + + svg { + width: 14px; + } + } +} + +.catalog_breadcrumbSearch_Wrapper { + display: flex; + align-items: center; + background-color: var(--color-extralight-grey); + padding: 15px; + min-height: 40px; + margin-bottom: 40px; + + label { + background-color: var(--color-extralight-grey)!important; + top: -18px!important; + } + + @media screen and (width <= 1024px) { + flex-direction: column; + align-items: end; + + .breadcrumb { + width: 100%; + padding-bottom: 20px; + } + + form[role="search"] { + width: 290px!important; + } + } +} + +.numberOfItems { + + // position: absolute; + top: 5px; + right: 5px; + font-size: 12px; + font-weight: 400; + margin-left: 5px; +} + +.noPublication { + + // width: 100%; + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + font-size: 16px; + padding: 5px; + border-radius: 6px; + display: flex; + align-items: center; + gap: 5px; + + svg { + width: 16px; + color: var(--color-blue); + } +} + +.opds_browserResults { + overflow: auto; + inset: 280px 20px 30px 30px; + padding: 0; + margin-top: 0; + margin-bottom: 0.4em; + position: absolute; + padding-right: 25px; + + .loader { + margin: 20%; + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/catalogs.scss.d.ts b/src/renderer/assets/styles/components/catalogs.scss.d.ts new file mode 100644 index 000000000..0c877ba24 --- /dev/null +++ b/src/renderer/assets/styles/components/catalogs.scss.d.ts @@ -0,0 +1,16 @@ +export declare const breadcrumb: string; +export declare const button_delete: string; +export declare const button_edit: string; +export declare const catalog_breadcrumbSearch_Wrapper: string; +export declare const catalog_container: string; +export declare const catalog_content: string; +export declare const catalog_infos_text: string; +export declare const catalog_title: string; +export declare const catalog_wrapper: string; +export declare const col_filter: string; +export declare const entryList_item: string; +export declare const entryList_ul: string; +export declare const loader: string; +export declare const noPublication: string; +export declare const numberOfItems: string; +export declare const opds_browserResults: string; diff --git a/src/renderer/assets/styles/components/columns.css.d.ts b/src/renderer/assets/styles/components/columns.css.d.ts deleted file mode 100644 index 88654ad98..000000000 --- a/src/renderer/assets/styles/components/columns.css.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_COLUMNS_CSS": string; - readonly "col": string; - readonly "col_1": string; - readonly "col_10": string; - readonly "col_11": string; - readonly "col_12": string; - readonly "col_2": string; - readonly "col_3": string; - readonly "col_4": string; - readonly "col_5": string; - readonly "col_6": string; - readonly "col_7": string; - readonly "col_8": string; - readonly "col_9": string; - readonly "col_book_img": string; - readonly "col_filter": string; - readonly "row": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/columns.css b/src/renderer/assets/styles/components/columns.scss similarity index 76% rename from src/renderer/assets/styles/components/columns.css rename to src/renderer/assets/styles/components/columns.scss index b6eb0929e..51e911a4c 100644 --- a/src/renderer/assets/styles/components/columns.css +++ b/src/renderer/assets/styles/components/columns.scss @@ -1,18 +1,8 @@ /* -=-=-= components/columns.css +=-=-= columns.scss */ -/* - - 1. .row - - 2. .col_x - -*/ - -/* 1. .row */ .row { - margin-left: -15px; margin-right: -15px; display: flex; flex-direction: row; @@ -58,77 +48,71 @@ -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; + + .card_wrapper { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-gap: 10px; + } } .col_1 { - -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col_2 { - -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col_3, .col_filter { - -ms-flex: 0 0 25%; flex: 0 0 25%; - max-width: 25%; + max-width: 300px; } .col_4 { - -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col_5 { - -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col_6 { - -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col_7 { - -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col_8 { - -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col_9 { - -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col_10 { - -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col_11 { - -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col_12 { - -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } diff --git a/src/renderer/assets/styles/components/columns.scss.d.ts b/src/renderer/assets/styles/components/columns.scss.d.ts new file mode 100644 index 000000000..e6724dda2 --- /dev/null +++ b/src/renderer/assets/styles/components/columns.scss.d.ts @@ -0,0 +1,18 @@ +export declare const ___DEBUG___COMPONENTS_COLUMNS_CSS: string; +export declare const card_wrapper: string; +export declare const col: string; +export declare const col_1: string; +export declare const col_10: string; +export declare const col_11: string; +export declare const col_12: string; +export declare const col_2: string; +export declare const col_3: string; +export declare const col_4: string; +export declare const col_5: string; +export declare const col_6: string; +export declare const col_7: string; +export declare const col_8: string; +export declare const col_9: string; +export declare const col_book_img: string; +export declare const col_filter: string; +export declare const row: string; diff --git a/src/renderer/assets/styles/components/combobox.scss b/src/renderer/assets/styles/components/combobox.scss new file mode 100644 index 000000000..1d024d29f --- /dev/null +++ b/src/renderer/assets/styles/components/combobox.scss @@ -0,0 +1,138 @@ +/* +=-=-= combobox.scss +*/ + +.react_aria_ComboBox { + color: var(--text-color); + padding-bottom: 15px; + margin: 10px 0; + width: 100%; + display: flex; + flex-direction: column; + gap: 5px; + + .my_combobox_container { + border: 1px solid var(--color-primary); + border-radius: 6px; + display: flex; + align-items: center; + width: 320px; + padding-right: 10px; + position: relative; + + > svg { + width: 20px; + height: 20px; + position: absolute; + left: 5px; + fill: var(--color-primary); + } + + &:has(.react_aria_Input[data-focused]) { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } + } + + .react_aria_Label { + font-weight: 600; + margin: 0; + } + + .react_aria_Input { + margin: 2px; + font-size: 14px; + background: transparent!important; + color: var(--field-text-color); + height: 24px; + padding: 0 5px 0 40px; + vertical-align: middle; + border: none; + width: 320px; + } + + .react_aria_Button { + + // display: inline-block; + background: var(--color-secondary); + color: var(--highlight-foreground); + forced-color-adjust: none; + border-radius: 4px; + border: none; + margin-left: -1.714rem; + width: 1.429rem; + height: 1.429rem; + padding: 0; + font-size: 0.857rem; + cursor: pointer; + position: relative; + + &[data-pressed] { + box-shadow: none; + background: var(--color-secondary); + } + + svg { + width: 20px; + } + } +} + +.react_aria_Popover[data-trigger="ComboBox"], .react_aria_Popover[data-trigger="Select"] { + width: var(--trigger-width); + background-color: var(--color-secondary); + pointer-events: auto; + border: 1px solid var(--color-primary); + border-radius: 6px; + height: fit-content; + max-height: 350px!important; + overflow: auto; + + .react_aria_ListBox { + display: block; + max-height: inherit; + min-height: unset; + border: none; + + .react_aria_Header { + padding-left: 1.571rem; + } + } +} + +.my_item { + margin: 2px; + padding: 4px 8px 4px 22px; + border-radius: 6px; + outline: none; + cursor: pointer; + color: var(--color-primary); + position: relative; + transition: 100ms; + + &.selected { + font-weight: 600; + background: none; + + &::before { + content: '✓'; + content: '✓' / ''; + alt: ' '; + position: absolute; + top: 4px; + left: 4px; + } + } + + &.focused { + background: var(--color-blue); + color: white; + } + } + + @media (forced-colors: active) { + .my_item.focused { + background: Highlight; + color: HighlightText; + } + } \ No newline at end of file diff --git a/src/renderer/assets/styles/components/combobox.scss.d.ts b/src/renderer/assets/styles/components/combobox.scss.d.ts new file mode 100644 index 000000000..9c4e1623b --- /dev/null +++ b/src/renderer/assets/styles/components/combobox.scss.d.ts @@ -0,0 +1,11 @@ +export declare const focused: string; +export declare const my_combobox_container: string; +export declare const my_item: string; +export declare const react_aria_Button: string; +export declare const react_aria_ComboBox: string; +export declare const react_aria_Header: string; +export declare const react_aria_Input: string; +export declare const react_aria_Label: string; +export declare const react_aria_ListBox: string; +export declare const react_aria_Popover: string; +export declare const selected: string; diff --git a/src/renderer/assets/styles/components/dropdown.css b/src/renderer/assets/styles/components/dropdown.css deleted file mode 100644 index 5031a83a5..000000000 --- a/src/renderer/assets/styles/components/dropdown.css +++ /dev/null @@ -1,150 +0,0 @@ -/* -=-=-= components/dropdown.css => '../partials/mixins.css' -*/ -@import url('../partials/mixins.css'); - -/* -=-=-= components/dropdown.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/dropdown.css -*/ - -.dropdown_menu { - height: fit-content; - width: 180px; - display: flex; - flex-direction: column; - background-color: white; - font-size: 0.9rem; - box-shadow: 0 0 10px 0 var(--color-medium-grey); - border-width: 1px; - border-color: var(--color-primary); - border-style: solid; - border-radius: 5px; - margin-top: 20px; - position: relative; - - &::after { - content: " "; - position: absolute; - top: -10px; - left: 16px; - width: 0; - height: 0; - border-style: solid; - border-width: 0 7.5px 10px 7.5px; - border-color: transparent transparent var(--color-primary) transparent; - } - - &.dropdown_right::after { - left: auto; - right: 34px; - } - - &.dropdown_publication::after { - left: auto; - right: 25px; - } - - & > * { - text-decoration: none; - color: black; - padding: 0.7rem; - text-align: center; - cursor: pointer; - height: 2.5rem; - width: 100%; - box-sizing: border-box; - font-size: 0.9rem; - opacity: 1; - margin: 0; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - display: inline-block; - - &:first-child { - border-radius: 6px 6px 0 0; - } - - &:last-child { - border-radius: 0 0 6px 6px; - } - - &:not(:last-child) { - border-bottom: 1px solid var(--color-medium-grey); - } - - &:hover { - background-color: var(--color-medium-grey); - } - } -} - -.menu { - height: fit-content; - width: 180px; - display: flex; - flex-direction: column; - background-color: white; - font-size: 0.9rem; - box-shadow: 0 0 10px 0 #cfcfcf; - overflow: hidden; - - & button, - & a, - & span label { - text-decoration: none; - color: var(--color-primary); - padding: 0.7rem; - text-align: center; - cursor: pointer; - height: 2.5rem; - box-sizing: border-box; - width: 100%; - font-size: 0.9rem; - opacity: 1; - margin: 0; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - display: inline-block; - - &:hover { - background-color: #cecece; - } - - &:not(:last-child) { - border-bottom: 1px solid #e5e3e3; - } - } - - & button[disabled] { - cursor: not-allowed; - } - - & span { - cursor: pointer; - - & input { - height: 0; - width: 0; - position: absolute; - left: -2000px; - } - - & input:focus + label { - @mixin R2_MIXIN_FOCUS_OUTLINE; - } - } -} - -.___DEBUG___COMPONENTS_DROPDOWN_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/dropdown.css.d.ts b/src/renderer/assets/styles/components/dropdown.css.d.ts deleted file mode 100644 index d4c2ba043..000000000 --- a/src/renderer/assets/styles/components/dropdown.css.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_DROPDOWN_CSS": string; - readonly "dropdown_menu": string; - readonly "dropdown_publication": string; - readonly "dropdown_right": string; - readonly "menu": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/dropdown.scss b/src/renderer/assets/styles/components/dropdown.scss new file mode 100644 index 000000000..4b4a82190 --- /dev/null +++ b/src/renderer/assets/styles/components/dropdown.scss @@ -0,0 +1,189 @@ +/* +=-=-= dropdown.scss +*/ + +.dropdown{ + &_description { + width: 400px; + height: fit-content; + box-shadow: 0 3px 10px 5px var(--color-extralight-grey); + border-width: 1px; + border-color: var(--color-blue); + border-style: solid; + border-radius: 10px; + position: relative; + background-color: var(--color-secondary); + margin: 0; + padding: 10px; + text-align: justify; + line-height: 1.5em; + color: var(--color-primary); + } + + &_trigger { + width: 30px!important; + height: 30px!important; + padding: 5px; + border: 1px solid transparent; + border-radius: 5px; + transition: 200ms; + + &:hover, &:focus { + border-color: var(--color-blue); + background-color: var(--color-light-blue); + } + } + + &_menu { + height: fit-content; + width: 180px; + display: flex; + flex-direction: column; + font-size: 0.9rem; + box-shadow: 0 0 10px 0 var(--color-medium-grey); + border-width: 1px; + border-color: var(--color-blue); + border-style: solid; + border-radius: 5px; + position: relative; + background-color: var(--color-light-blue); + + &.dropdown_right::after { + left: auto; + right: 34px; + } + + &.dropdown_publication::after { + left: auto; + right: 25px; + } + + & > * { + text-decoration: none; + color: var(--color-blue);; + padding: 0.7rem; + text-align: center; + cursor: pointer; + height: 2.5rem; + width: 100%; + box-sizing: border-box; + font-size: 0.9rem; + opacity: 1; + margin: 0; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + display: inline-block; + + &:first-child { + border-radius: 6px 6px 0 0; + } + + &:last-child { + border-radius: 0 0 6px 6px; + } + + &:not(:last-child) { + border-bottom: 1px solid var(--color-medium-grey); + } + + &:hover { + background-color: var(--color-extralight-grey); + } + } + + button { + display: flex; + align-items: center; + justify-content: start; + gap: 10px; + + p { + font-size: inherit; + } + + svg { + width: 15px; + height: 15px; + } + } + } +} + +.popover_open { + border-color: var(--color-blue); + background-color: var(--color-light-blue); +} + +.PopoverArrow { + fill: var(--color-blue); + width: 20px; + height: 12px; +} + +.PopoverContent { + z-index: 10000; +} + +.menu { + height: fit-content; + width: 180px; + display: flex; + flex-direction: column; + background-color: white; + font-size: 0.9rem; + box-shadow: 0 0 10px 0 #cfcfcf; + overflow: hidden; + + & button, + & a, + & span label { + text-decoration: none; + color: var(--color-primary); + padding: 0.7rem; + text-align: center; + cursor: pointer; + height: 2.5rem; + box-sizing: border-box; + width: 100%; + font-size: 0.9rem; + opacity: 1; + margin: 0; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + display: inline-block; + + &:hover { + background-color: #cecece; + } + + &:not(:last-child) { + border-bottom: 1px solid #e5e3e3; + } + } + + & button[disabled] { + cursor: not-allowed; + } + + & span { + cursor: pointer; + + & input { + height: 0; + width: 0; + position: absolute; + left: -2000px; + } + + & input:focus + label { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } + } +} + +.___DEBUG___COMPONENTS_DROPDOWN_CSS { + display: none; +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/dropdown.scss.d.ts b/src/renderer/assets/styles/components/dropdown.scss.d.ts new file mode 100644 index 000000000..a4618eb7c --- /dev/null +++ b/src/renderer/assets/styles/components/dropdown.scss.d.ts @@ -0,0 +1,10 @@ +export declare const ___DEBUG___COMPONENTS_DROPDOWN_CSS: string; +export declare const dropdown_description: string; +export declare const dropdown_menu: string; +export declare const dropdown_publication: string; +export declare const dropdown_right: string; +export declare const dropdown_trigger: string; +export declare const menu: string; +export declare const popover_open: string; +export declare const PopoverArrow: string; +export declare const PopoverContent: string; diff --git a/src/renderer/assets/styles/components/grids.css.d.ts b/src/renderer/assets/styles/components/grids.css.d.ts deleted file mode 100644 index 6f60ef18e..000000000 --- a/src/renderer/assets/styles/components/grids.css.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_GRIDS_CSS": string; - readonly "grid_uniform_item": string; - readonly "grid_uniform_wrapper": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/grids.css b/src/renderer/assets/styles/components/grids.scss similarity index 95% rename from src/renderer/assets/styles/components/grids.css rename to src/renderer/assets/styles/components/grids.scss index 8e7182da2..02a7284f1 100644 --- a/src/renderer/assets/styles/components/grids.css +++ b/src/renderer/assets/styles/components/grids.scss @@ -1,5 +1,5 @@ /* -=-=-= components/grids.css +=-=-= grids.scss */ .grid_uniform_wrapper { diff --git a/src/renderer/assets/styles/components/grids.scss.d.ts b/src/renderer/assets/styles/components/grids.scss.d.ts new file mode 100644 index 000000000..13d541749 --- /dev/null +++ b/src/renderer/assets/styles/components/grids.scss.d.ts @@ -0,0 +1,3 @@ +export declare const ___DEBUG___COMPONENTS_GRIDS_CSS: string; +export declare const grid_uniform_item: string; +export declare const grid_uniform_wrapper: string; diff --git a/src/renderer/assets/styles/components/images.css b/src/renderer/assets/styles/components/images.css deleted file mode 100644 index 011ead5fb..000000000 --- a/src/renderer/assets/styles/components/images.css +++ /dev/null @@ -1,19 +0,0 @@ -/* -=-=-= components/images.css -*/ - -.cover_img { - height: 100%; - width: 100%; - max-width: 100%; - max-height: 100%; - object-fit: contain; - box-sizing: border-box; - border: 1px solid #e2e2e2; - border-radius: 6px; - background-color: #f1f1f1; -} - -.___DEBUG___COMPONENTS_IMAGES_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/images.css.d.ts b/src/renderer/assets/styles/components/images.css.d.ts deleted file mode 100644 index 3470a5612..000000000 --- a/src/renderer/assets/styles/components/images.css.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_IMAGES_CSS": string; - readonly "cover_img": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/inputs.css b/src/renderer/assets/styles/components/inputs.css deleted file mode 100644 index 06bd46faa..000000000 --- a/src/renderer/assets/styles/components/inputs.css +++ /dev/null @@ -1,235 +0,0 @@ -/* -=-=-= components/inputs.css => '../partials/mixins.css' -*/ -@import url('../partials/mixins.css'); - -/* -=-=-= components/inputs.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/inputs.css -*/ - -/* - - 1. input[type="text"] - input[type="number"] - input[type="phone"] - input[type="email"] - input[type="password"] - input[type="date"] - input[type="time"] - input[type="week"] - input[type="color"] - input[type="url"] - input[type="search"] - - 2. input[type="checkbox"] - - 3. input[type="radio"] (list) - - 4. select & option - - 5. form_group - - 6. dropzone - -*/ - -/* 1. input[type="text"] ... */ - -input[type="text"], -input[type="number"], -input[type="phone"], -input[type="email"], -input[type="password"], -input[type="date"], -input[type="time"], -input[type="week"], -input[type="color"], -input[type="url"], -input[type="search"] { - display: inline-block; - position: relative; - width: auto; - height: 35px; - background-color: transparent; - border-top: none; - border-right: none; - border-left: none; - border-bottom: 1px solid var(--color-medium-grey); - border-radius: 0; - - /* outline: inherit; */ - color: var(--color-primary); - font-size: 0.9rem; - - &::placeholder { - color: var(--color-medium-grey); - } - - &.outline { - border: 1px solid var(--color-medium-grey); - } - - &:focus { - @mixin R2_MIXIN_FOCUS_OUTLINE; - } -} - -form[role="search"] { - position: relative; - width: auto; - display: inline-block; - - & input[type="search"] { - width: 225px; - } - - & button { - position: absolute; - top: 0; - right: 0; - height: 38px; - width: 36px; - background-color: transparent; - margin: 0; - } -} - -/* 2. input[type="checkbox"] */ - -.checkbox_keyboard { - position: absolute; - left: -2000px; - - & + label { - width: auto; - height: auto; - font-size: 80%; - display: inline; - padding: 0.3em; - margin-right: 1em; - border-radius: 3px; - cursor: pointer; - background-color: #ffd4d4; - border: 2px solid rgb(171, 171, 171); - border-bottom: 2px solid rgb(41, 41, 41); - border-right: 2px solid rgb(41, 41, 41); - - /* border: 2px solid rgb(41, 41, 41); - border-bottom: 2px solid rgb(171, 171, 171); - border-right: 2px solid rgb(171, 171, 171); */ - } - - &:checked + label { - background-color: #d4ffc6; - - /* border: 2px solid rgb(171, 171, 171); - border-bottom: 2px solid rgb(41, 41, 41); - border-right: 2px solid rgb(41, 41, 41); */ - } - - &:focus + label { - @mixin R2_MIXIN_FOCUS_OUTLINE; - } -} - -/* 3. input[type="radio"] (list) */ - -.radio_list { - list-style-type: none; - margin-bottom: 20px; - - & label { - display: inline-flex; - margin-bottom: 3px; - padding: 5px 10px 5px 2rem; - font-size: 16px; - height: 1.2rem; - width: 20rem; - color: black; - background: var(--color-medium-grey); - cursor: pointer; - - & svg { - height: 1rem; - width: 1rem; - margin-left: -1.3rem; - margin-right: 0.3rem; - } - - &:hover { - background: var(--color-light-grey); - } - } - - & input { - position: absolute; - -webkit-appearance: none; - opacity: 0; - width: 1px; - height: 1px; - - &:focus + label { - @mixin R2_MIXIN_FOCUS_OUTLINE; - } - - &:checked + label { - background: var(--color-light-grey); - } - } -} - -/* 4. select & option */ - -select { - appearance: none; -} - -/* 5. form_group */ - -.form_group { - display: flex; - justify-content: left; - align-items: center; - width: 100%; - - & label { - margin-right: 10px; - flex: none; - } - - & button { - margin-left: 10px; - flex: none; - } - - & input { - flex: 1; - } - - &:not(:last-child):not(:only-child) { - margin-bottom: 2rem; - } -} - -/* 6. dropzone */ - -.dropzone { - position: absolute; - overflow: hidden; - top: 0; - bottom: 0; - left: 0; - right: 0; -} - -.___DEBUG___COMPONENTS_INPUTS_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/inputs.css.d.ts b/src/renderer/assets/styles/components/inputs.css.d.ts deleted file mode 100644 index 9ab89d269..000000000 --- a/src/renderer/assets/styles/components/inputs.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_INPUTS_CSS": string; - readonly "checkbox_keyboard": string; - readonly "dropzone": string; - readonly "form_group": string; - readonly "outline": string; - readonly "radio_list": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/inputs.scss b/src/renderer/assets/styles/components/inputs.scss new file mode 100644 index 000000000..f2fd21272 --- /dev/null +++ b/src/renderer/assets/styles/components/inputs.scss @@ -0,0 +1,183 @@ +/* +=-=-= inouts.scss +*/ + +@import 'src/renderer/assets/styles/partials/mixin'; + + +input[type="text"], +input[type="number"], +input[type="phone"], +input[type="email"], +input[type="password"], +input[type="date"], +input[type="time"], +input[type="week"], +input[type="color"], +input[type="url"], +input[type="search"] { + display: inline-block; + position: relative; + width: auto; + height: 35px; + background-color: transparent; + border-top: none; + border-right: none; + border-left: none; + border-bottom: 1px solid var(--color-medium-grey); + border-radius: 0; + color: var(--color-primary); + font-size: 0.9rem; + + // @media (prefers-color-scheme: dark) { + // background-color: #2D2D2D; + + // &::placeholder { + // color: white; + // } + // } + + &::placeholder { + color: var(--color-medium-grey); + } + + &.outline { + border: 1px solid var(--color-medium-grey); + } +} + +input[type="text"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="number"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="phone"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="email"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="password"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="date"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="time"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="week"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="color"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="url"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE), +input[type="search"]:not(.R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE) { + &:focus { + @include R2_MIXIN_FOCUS_OUTLINE; + } +} + +form[role="search"] { + background-color: var(--color-secondary); + color: var(--color-primary); + width: 370px !important; + height: 30px !important; + + &:has(input:focus) { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } +} + +select { + appearance: none; +} + + +.form_group { + width: 150px; + height: 25px; + padding:2px; + border:1px solid var(--color-primary); + margin: 0; + border-radius: 6px; + position: relative; + display: flex; + align-items: center; + background-color: var(--color-secondary); + + // @media (prefers-color-scheme: dark) { + // background-color: #2D2D2D; + // } + + &:has(input:focus), &:has(button:focus) { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } + + & >label{ + position:absolute; + top:-10px; + left:10px; + background-color: var(--color-secondary); + padding: 0 5px; + z-index: 1; + } + + & >input{ + border:none; + width: calc(100% - 35px); + height: 25px; + margin-left: 30px; + background-color: var(--color-secondary); + } + + & i { + width: 15px; + padding: 5px; + position: absolute; + } + +} + +.form_group_catalog { + width: 100%; + height: 30px; + margin-top: 30px; + + &:has(input:focus) { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + } + + svg { + height: 14px; + position: absolute; + left: 20px; + transform: translate(-50%, -50%); + top: 50%; + } +} + +.form_group_wrapper { + display: flex; + flex-wrap: nowrap; + align-items: end; + gap: 10px; + + & button { + min-width: 100px; + height: 35px; + } +} + +/* 6. dropzone */ + +.dropzone { + position: absolute; + overflow: hidden; + inset: 0; +} + +.___DEBUG___COMPONENTS_INPUTS_CSS { + display: none; +} + + +.passphrase_error { + color: var(--color-error-dark); + display: flex; + align-items: center; + gap: 5px; + margin: 0; + + svg { + fill: var(--color-error-dark); + height: 12px; + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/inputs.scss.d.ts b/src/renderer/assets/styles/components/inputs.scss.d.ts new file mode 100644 index 000000000..7b8c2ad77 --- /dev/null +++ b/src/renderer/assets/styles/components/inputs.scss.d.ts @@ -0,0 +1,9 @@ +export declare const ___DEBUG___COMPONENTS_INPUTS_CSS: string; +export declare const ___DEBUG___PARTIALS_MIXINS_CSS: string; +export declare const dropzone: string; +export declare const form_group: string; +export declare const form_group_catalog: string; +export declare const form_group_wrapper: string; +export declare const outline: string; +export declare const passphrase_error: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; diff --git a/src/renderer/assets/styles/components/keyboardsShortcuts.scss b/src/renderer/assets/styles/components/keyboardsShortcuts.scss new file mode 100644 index 000000000..0a73cf843 --- /dev/null +++ b/src/renderer/assets/styles/components/keyboardsShortcuts.scss @@ -0,0 +1,140 @@ +/* +=-=-= keyboardsShortcuts.scss +*/ + +.keyshortElement { + &_container { + display: flex; + flex-direction: column; + margin: 10px 0; + border-bottom: 1px solid var(--color-light-grey); + } + + &_title { + font-size: 16px; + margin: 5px; + font-weight: bold; + } + + &_shortcut { + display: flex; + place-items: center center; + color: var(--color-blue); + background-color: var(--color-light-blue); + padding: 3px; + gap: 5px; + width: fit-content; + font-size: 16px; + + &_container { + margin-bottom: 10px; + + svg { + color: var(--color-blue)!important; + width: 15px; + height: 15px; + padding-bottom: 5px; + padding-left: 5px; + transition: 200ms; + + &:hover { + scale: 1.2; + } + } + + &_edit { + border-left: 2px solid var(--color-blue); + width: 100%; + color: var(--color--primary); + background-color: var(--color-light-blue); + padding: 5px; + + .keyshortElement_shortcut { + color: var(--color--primary); + background-color: transparent; + } + + > * { + margin-left: 5px; + } + + &_input { + position: absolute; + left: -2000px; + + &:checked + label { + border: 1px solid var(--color-blue); + background-color: var(--color-secondary); + color: var(--color-blue); + + svg { + fill: var(--color-blue); + } + } + + &:focus + label { + outline: 2px solid var(--color--blue); + } + } + + label { + border: 1px solid transparent; + border-radius: 6px; + color: var(--color--primary); + padding: 3px; + background-color: var(--color-light-grey); + + &:hover { + cursor: pointer; + } + + svg { + width: 30px; + height: 30px; + } + + &:focus { + outline-color: var(--color--blue)!important; + } + } + + .form_group { + width: 100px; + height: 30px; + margin-bottom: 0!important; + color: var(--color--primary); + } + + .outline { + background-color: var(--color-secondary); + width: 50px; + } + } + } + } + + &_description { + font-size: 14px; + } +} + +.action_buttons_container { + display: flex; + gap: 10px; +} + +.advanced_trigger { + min-width: 20px!important; + height: 20px; + width: fit-content!important; + border: 1px solid; + border-color: transparent; + background-color: transparent; + transition: 200ms linear; + padding: 3px; + + &:hover{ + background-color: var(--color-light-blue); + border-color: var(--color-blue); + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/keyboardsShortcuts.scss.d.ts b/src/renderer/assets/styles/components/keyboardsShortcuts.scss.d.ts new file mode 100644 index 000000000..edd88d9ba --- /dev/null +++ b/src/renderer/assets/styles/components/keyboardsShortcuts.scss.d.ts @@ -0,0 +1,11 @@ +export declare const action_buttons_container: string; +export declare const advanced_trigger: string; +export declare const form_group: string; +export declare const keyshortElement_container: string; +export declare const keyshortElement_description: string; +export declare const keyshortElement_shortcut: string; +export declare const keyshortElement_shortcut_container: string; +export declare const keyshortElement_shortcut_container_edit: string; +export declare const keyshortElement_shortcut_container_edit_input: string; +export declare const keyshortElement_title: string; +export declare const outline: string; diff --git a/src/renderer/assets/styles/components/modals.css.d.ts b/src/renderer/assets/styles/components/modals.css.d.ts deleted file mode 100644 index 84f29abd7..000000000 --- a/src/renderer/assets/styles/components/modals.css.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_MODALS_CSS": string; - readonly "add_dialog": string; - readonly "c_dialog__box": string; - readonly "close_button": string; - readonly "field": string; - readonly "modal_dialog": string; - readonly "modal_dialog_body": string; - readonly "modal_dialog_body_centered": string; - readonly "modal_dialog_footer": string; - readonly "modal_dialog_full": string; - readonly "modal_dialog_header": string; - readonly "modal_dialog_overlay": string; - readonly "modal_dialog_overlay_hidden": string; - readonly "opds_form_dialog": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/modals.css b/src/renderer/assets/styles/components/modals.scss similarity index 55% rename from src/renderer/assets/styles/components/modals.css rename to src/renderer/assets/styles/components/modals.scss index cbf229372..0012882d1 100644 --- a/src/renderer/assets/styles/components/modals.css +++ b/src/renderer/assets/styles/components/modals.scss @@ -1,115 +1,138 @@ /* -=-=-= components/modals.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/modals.css +=-=-= modals.scss */ .modal_dialog_overlay { position: fixed; z-index: 102; - top: 0; - left: 0; - right: 0; - bottom: 0; + inset: 0; display: flex; padding: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; - background-color: rgba(0, 0, 0, 0.5); + background-color: rgb(0 0 0 / 50%); transition: 0.2s; min-width: 700px; align-items: center; justify-content: center; -} -.modal_dialog_overlay_hidden { - position: fixed; - z-index: 101; - top: 0; - left: 0; - right: 0; - bottom: 0; + &_hidden { + position: fixed; + z-index: 101; + inset: 0; + } } .modal_dialog { - margin: 30px; - min-height: 400px; - min-width: 700px; + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + width: 776px; + min-height: 401px; + height: fit-content; max-width: calc(100vw - 60px); max-height: calc(100vh - 60px); border-radius: 10px; z-index: 102; display: flex; flex-direction: column; - background-color: var(--color-secondary); - overflow-y: auto; - overflow-x: hidden; + overflow: hidden auto; align-content: flex-start; - color: var(--color-primary);; - position: relative; + position: fixed; box-sizing: border-box; &.modal_dialog_full { - width: calc(100vw - 60px); - height: calc(100vh - 60px); + position: relative; + box-sizing: border-box; + + &_full { + width: calc(100vw - 60px); + height: calc(100vh - 100px); + } } -} + + background-color: var(--color-secondary); + color: var(--color-primary); -/* -.modal_dialog_form_wrapper { - display: flex; - flex: 1; - flex-direction: column; - height: 100%; + &_reader { + .display_options_item { + color: var(--color-primary); + } + + .settings_container { + background-color: var(--color-secondary); + } + + color: var(--color-primary); + + .react_aria_ComboBox { + .react_aria_Button { + background-color: var(--color-secondary); + } + + .react_aria_Input { + background-color: var(--reader-secondaryColor); + color: var(--color-primary); + } + } + } } -*/ .modal_dialog_body { flex: 1; - padding: 20px 30px; - overflow-x: hidden; - overflow-y: auto; + padding: 0 20px 0 30px; + overflow: hidden auto; + display: flex; + flex-direction: column; + justify-content: space-between; - &.modal_dialog_body_centered { + &_centered { display: flex; align-items: center; justify-content: center; } } +.modal_dialog_body_cover > img { + display: flex; + align-items: center; + justify-content: center; + min-height: 570px; + max-height: calc(100vh - 200px); +} + .modal_dialog_header, .modal_dialog_footer { display: flex; flex: none; - padding: 0 20px; + margin: 0 20px 10px; align-items: center; - height: 70px; + height: 50px; } .modal_dialog_header { justify-content: space-between; border-bottom: 1px solid var(--color-medium-grey); - & h2 { + & h1 { font-weight: bold; margin: 10px 0; - font-size: 22px; margin-left: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-size: 20px; } } .modal_dialog_footer { justify-content: end; border-top: 1px solid var(--color-medium-grey); + position: sticky; + bottom: 0; + right: 0; + background-color: var(--color-secondary); + gap: 10px; & [type="submit"] { min-width: 100px; @@ -147,7 +170,6 @@ } & input { - font-size: 1rem; padding-bottom: 4px; padding-left: 0.3rem; border: none; @@ -168,6 +190,21 @@ } } -.___DEBUG___COMPONENTS_MODALS_CSS { - display: none; +.lcp_hint { + color: var(--color-blue); + background-color: var(--color-light-blue); + padding: 5px; + display: flex; + align-items: center; + gap: 5px; + width: fit-content; + + svg { + height: 14px; + } } + +.urlHint { + font-size: 14px; + color: var(--color-blue); +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/modals.scss.d.ts b/src/renderer/assets/styles/components/modals.scss.d.ts new file mode 100644 index 000000000..9835dc092 --- /dev/null +++ b/src/renderer/assets/styles/components/modals.scss.d.ts @@ -0,0 +1,23 @@ +export declare const add_dialog: string; +export declare const c_dialog__box: string; +export declare const close_button: string; +export declare const display_options_item: string; +export declare const field: string; +export declare const lcp_hint: string; +export declare const modal_dialog: string; +export declare const modal_dialog_body: string; +export declare const modal_dialog_body_centered: string; +export declare const modal_dialog_body_cover: string; +export declare const modal_dialog_footer: string; +export declare const modal_dialog_full: string; +export declare const modal_dialog_full_full: string; +export declare const modal_dialog_header: string; +export declare const modal_dialog_overlay: string; +export declare const modal_dialog_overlay_hidden: string; +export declare const modal_dialog_reader: string; +export declare const opds_form_dialog: string; +export declare const react_aria_Button: string; +export declare const react_aria_ComboBox: string; +export declare const react_aria_Input: string; +export declare const settings_container: string; +export declare const urlHint: string; diff --git a/src/renderer/assets/styles/components/popoverDialog.scss b/src/renderer/assets/styles/components/popoverDialog.scss new file mode 100644 index 000000000..33e361572 --- /dev/null +++ b/src/renderer/assets/styles/components/popoverDialog.scss @@ -0,0 +1,582 @@ +/* +=-=-= popoverDialog.scss +*/ + +.modal_dialog_reader { + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + width: 776px; + min-height: 401px; + height: 597px; + max-width: calc(100vw - 60px); + max-height: calc(100vh - 60px); + border-radius: 10px; + z-index: 100; + display: flex; + flex-direction: column; + + // overflow: hidden auto; + align-content: flex-start; + color: var(--color-primary); + position: fixed; + box-sizing: border-box; + box-shadow: 0 2px 10px 5px var(--color-medium-grey); + + > .settings_container { + padding: 0 20px 0 30px; + overflow: hidden auto; + } + + &.modal_dialog_full { + position: relative; + box-sizing: border-box; + + &_full { + width: calc(100vw - 60px); + height: calc(100vh - 100px); + } + } + + @media screen and (height <= 700px) { + height: 450px; +} +} + +.popover_dialog_reader { + width: 350px; + height: calc(100dvh - 94px); + display: flex; + margin-top: 50px; + flex-direction: column; + box-sizing: border-box; + z-index: 100; + background-color: var(--color-secondary); + position: absolute; + overflow: hidden; + + .settings_container { + height: calc(100dvh - 235px); + padding: 0; + overflow: hidden auto; + + .settings_tab_container_reading_spacing { + grid-template-columns: repeat(1, 1fr); + } + } + + .settings_tab .settings_reading_text .section { + width: 90%; + } + + .display_options_item { + background-color: transparent; + color: var(--color-primary); + } + + .react_aria_ComboBox { + // margin: 0; + // padding: 0; + padding-bottom: 15px; + + .my_combobox_container { + width: fit-content; + min-width: 110px; + height: 28px; + background-color: var(--color-light-blue); + color: var(--color-blue); + border-color: var(--color-blue) !important; + display: flex; + align-items: center; + + > button { + color: var(--color-blue); + + > span { + text-overflow: ellipsis; + overflow: hidden; + max-width: 120px; + white-space: nowrap; + } + + svg { + fill: var(--color-blue); + } + } + + input, > button { + width: fit-content; + height: 25px; + background-color: inherit; + font-size: 14px; + margin-left: 10px; + padding: 0 !important; + padding-left: 30px!important; + } + + button { + background-color: inherit; + + svg { + margin-left: unset; + background-color: unset; + } + } + } + } + + .bookmarks_line .bookmark_textArea { + min-width: unset; + width: 270px; + } +} + +.docked_header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px; + + .my_combobox_container button { + min-width: 110px; + } + + &_controls { + width: 135px; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + flex-wrap: nowrap; + + .button_transparency_icon { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + + svg { + width: 16px; + height: 16px; + } + } + } +} + +.toc_container { + padding: 0; + height: auto; + list-style-type: none; + font-size: 12px; + font-weight: 400; + + >li > div[aria-level="1"] { + font-weight: 600; + font-size: 14px; + } +} + +.chapters_content { + padding: 0; + height: auto; + list-style: none; + + & > li > div > a > span, & .line span { + line-height: 1.5em; + } + + .line, .subheading:not(.inert) { + color: var(--color-primary); + border-left: 2px solid transparent; + transition: 200ms; + width: fit-content; + text-align: left; + display: block; + padding: 5px 40px 5px 5px; + margin: 5px 0; + + &.active:not(.inert) { + &:hover { + background-color: var(--color-light-blue); + } + } + } + + & .chapters_content { + padding: 0 0 0 10px; + } + + & .subheading:not(.inert) { + &:hover { + background-color: var(--color-light-blue) !important; + } + } + + .line { + &:not(.inert) { + cursor: pointer; + } + + &:last-child { + border-bottom: 0; + } + } +} + +.search_container { + display: flex; + flex-direction: column; + + .correspondances { + padding: 0; + margin: 0; + padding-bottom: 0.4em; + margin-bottom: 0.4em; + } + + .subheading { + font-weight: 600; + font-size: 14px; + } + + li[aria-level="1"] { + color: var(--color-primary); + border-left: 2px solid var(--color-blue); + transition: 200ms; + width: 90%; + text-align: left; + display: block; + padding: 5px 40px 5px 5px; + margin: 5px 0; + background-color: var(--color-light-grey); + } +} + +.navigation_container { + display: flex; + align-items: end; + justify-content: end; + gap: 10px; + margin-bottom: 10px; + + .pages { + display: flex; + flex-direction: column; + align-items: start; + justify-content: center; + + .react_aria_ComboBox { + margin: 0; + padding: 0; + } + } + + button { + transition: 100ms; + } + + button svg { + width: 20px; + fill: var(--color-blue); + color: var(--color-blue); + } + + button:disabled { + visibility: hidden; + } + + .my_combobox_container { + width: fit-content!important; + padding-right: 0!important; + + button { + width: fit-content; + padding: 0 10px; + + svg { + margin-left: unset; + } + } + } + + // span { + // padding: 5px; + // border: 1px solid black; + // border-radius: 6px; + // margin: 0 5px; + // } +} + +.bookmarks_line { + width: calc(100% - 10px); + position: relative; + text-align: left; + padding: 20px 0; + font-size: 1rem; + + .bookmark_textArea { + margin: 10px 0; + width: 430px; + min-width: 430px; + // height: 100px; + // min-height: 100px; + max-width: 430px; + // max-height: 100px; + border: 1px solid rgb(118 118 118); + border-radius: 3px; + font-family: Nunito, sans-serif; + + &:focus { + border: 2px solid var(--color-blue); + } + } + + .bookmark_name { + text-align: left; + } + + .update_form input { + width: 100%; + border-radius: 6px; + } + + .bookmark_infos { + width: 100%; + display: flex; + background-color: var(--color-light-grey); + border-left: 2px solid var(--color-blue); + height: fit-content; + padding: 0 10px; + + // @media (prefers-color-scheme: dark) { + // background-color: #2D2D2D; + // } + + .button_secondary_blue, .button_primary_blue { + min-width: unset; + width: fit-content; + height: 25px; + } + + .bookmark_actions { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 10px; + + > div { + display: inherit; + align-items: center; + gap: 5px; + + p { + margin: 0; + } + + svg { + width: 16px; + height: 16px; + padding: 5px; + } + } + + &_buttons svg { + fill: var(--color-blue); + color: var(--color-blue); + } + + button { + height: unset; + + &:focus { + border: 1px solid var(--color-blue); + border-radius: 5px; + background-color: var(--color-light-blue); + } + } + } + } + + & > button { + border: none; + background-color: transparent; + cursor: pointer; + padding: 0; + + & svg { + width: 24px; + } + } + + & img { + width: 30px; + height: 30px; + display: inline-block; + vertical-align: top; + } + + & .chapter_marker { + vertical-align: top; + position: relative; + display: inline-block; + flex: 1; + font-size: 0.9rem; + margin-right: 0.5rem; + } + + & span { + display: inline-block; + vertical-align: top; + margin-top: 5px; + font-family: Nunito, sans-serif; + } +} + +.bookmarks_line:last-child { + border-bottom: 0; +} + +.chapter_marker .gauge { + width: 100%; + margin-top: 2px; + height: 4px; + background-color: #ececec; + + & .fill { + height: 100%; + position: relative; + width: 63%; + background-color: #3b3b3b; + } +} + +.goToPage { + text-align: center; + + .currentPage { + display: flex; + align-items: center; + gap: 5px; + margin: 20px 0 30px; + + svg { + width: 20px; + } + } + + form { + display: flex; + align-items: start; + gap: 20px; + + .form_group { + height: 30px; + width: 375px; + + .react_aria_Label { + position: absolute; + left: 10px; + // top: -20px; + background-color: var(--color-secondary); + text-overflow: ellipsis; + overflow: hidden; + max-width: 250px; + white-space: nowrap; + } + + & input { + margin: 0; + } + + label { + margin: 0; + top: -12px; + position: absolute; + } + + & *:disabled { + cursor: not-allowed; + } + } + + select { + width: 375px; + height: 36px; + padding: 2px; + border-radius: 6px; + border: 1px solid black; + appearance: auto; + box-sizing: border-box; + margin: 0; + margin-right: 5px; + } + + button { + background-color: var(--color-blue); + color: white; + width: fit-content; + border-radius: 6px; + display: flex; + flex-wrap: nowrap; + padding: 3px 5px; + text-wrap: nowrap; + box-sizing: content-box; + + svg { + width: 15px; + fill: white!important; + color: white!important; + } + } + } + + & .title { + color: var(--reader-fontColor); + font-size: 1.1rem; + } + + & .goToErrorMessage { + color: var(--color-error-dark); + } +} + +.gotopage_combobox { + .react_aria_ComboBox .my_combobox_container { + border: none; + width: 100%; + height: 100%; + padding: 0; + background-color: inherit; + color: inherit; + position: absolute; + bottom: 0; + left: 0; + + &:has(.react_aria_Input[data-focused]) { + outline: none!important; + } + + input { + width: calc(100% - 45px); + outline: none!important; + } + + .react_aria_Button svg { + width: 15px; + color: var(--color-primary)!important; + } + } +} + + +.react_aria_ListBox { + width: inherit; + background-color: var(--color-secondary); + color: var(--color-primary); +} + +.react_aria_ComboBox [role="group"]:focus-within { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/popoverDialog.scss.d.ts b/src/renderer/assets/styles/components/popoverDialog.scss.d.ts new file mode 100644 index 000000000..a389dfd7e --- /dev/null +++ b/src/renderer/assets/styles/components/popoverDialog.scss.d.ts @@ -0,0 +1,47 @@ +export declare const active: string; +export declare const bookmark_actions: string; +export declare const bookmark_actions_buttons: string; +export declare const bookmark_infos: string; +export declare const bookmark_name: string; +export declare const bookmark_textArea: string; +export declare const bookmarks_line: string; +export declare const button_primary_blue: string; +export declare const button_secondary_blue: string; +export declare const button_transparency_icon: string; +export declare const chapter_marker: string; +export declare const chapters_content: string; +export declare const correspondances: string; +export declare const currentPage: string; +export declare const display_options_item: string; +export declare const docked_header: string; +export declare const docked_header_controls: string; +export declare const fill: string; +export declare const form_group: string; +export declare const gauge: string; +export declare const goToErrorMessage: string; +export declare const goToPage: string; +export declare const gotopage_combobox: string; +export declare const inert: string; +export declare const line: string; +export declare const modal_dialog_full: string; +export declare const modal_dialog_full_full: string; +export declare const modal_dialog_reader: string; +export declare const my_combobox_container: string; +export declare const navigation_container: string; +export declare const pages: string; +export declare const popover_dialog_reader: string; +export declare const react_aria_Button: string; +export declare const react_aria_ComboBox: string; +export declare const react_aria_Input: string; +export declare const react_aria_Label: string; +export declare const react_aria_ListBox: string; +export declare const search_container: string; +export declare const section: string; +export declare const settings_container: string; +export declare const settings_reading_text: string; +export declare const settings_tab: string; +export declare const settings_tab_container_reading_spacing: string; +export declare const subheading: string; +export declare const title: string; +export declare const toc_container: string; +export declare const update_form: string; diff --git a/src/renderer/assets/styles/components/publications.css.d.ts b/src/renderer/assets/styles/components/publications.css.d.ts deleted file mode 100644 index bf85244de..000000000 --- a/src/renderer/assets/styles/components/publications.css.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_PUBLICATIONS_CSS": string; - readonly "author": string; - readonly "block_book": string; - readonly "block_book_list": string; - readonly "book_author": string; - readonly "book_title": string; - readonly "box": string; - readonly "cover": string; - readonly "cover_img": string; - readonly "icon_seemore": string; - readonly "image_wrapper": string; - readonly "infos_sup": string; - readonly "legend": string; - readonly "menu": string; - readonly "no_img": string; - readonly "no_img_wrapper": string; - readonly "publication_description": string; - readonly "publication_image_wrapper": string; - readonly "publication_infos": string; - readonly "publication_infos_wrapper": string; - readonly "publication_list_infos": string; - readonly "publication_list_title_authors": string; - readonly "publication_list_wrapper": string; - readonly "publication_title": string; - readonly "publication_wrapper": string; - readonly "title": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/publications.css b/src/renderer/assets/styles/components/publications.scss similarity index 55% rename from src/renderer/assets/styles/components/publications.css rename to src/renderer/assets/styles/components/publications.scss index 0c1d91269..0ccd701e5 100644 --- a/src/renderer/assets/styles/components/publications.css +++ b/src/renderer/assets/styles/components/publications.scss @@ -1,110 +1,133 @@ /* -=-=-= components/publications.css +=-=-= publications.scss */ -/* - - 1. card - - 2. list - -*/ - -/* 1. card */ - .publication_wrapper { - width: 175px; + width: 200px; + height: 400px; display: flex; flex-direction: column; align-items: flex-start; + justify-content: space-between; } -.publication_image_wrapper { - width: 100%; +.publication_main_container { + transition: 200ms linear; + border: 1px solid transparent; + width: calc(100% - 14px); + display: flex; + flex-direction: column; + gap: 10px; + cursor: pointer; + padding: 6px; + border-radius: 2px; + perspective: 1000px; + overflow: hidden; position: relative; - display: block; - padding-top: 150%; + + &:hover { + img, .no_img_wrapper { + transform: rotateX(10deg); + } + + .gradient { + height: 90%; + opacity: 0.8; + } + } + + &:has(.hasEnded) { + perspective: unset; + cursor: not-allowed; + + &:hover { + img, .no_img_wrapper { + transform: unset; + } + } + } & img { - position: absolute; - top: 2px; - bottom: 2px; - left: 2px; - right: 2px; + transform-origin: 100% 0; + transition: transform 0.3s ease-in-out; display: flex; align-items: flex-end; justify-content: center; - cursor: pointer; - height: calc(100% - 4px); - width: calc(100% - 4px); - max-width: calc(100% - 4px); - max-height: calc(100% - 4px); + height: 285px; object-fit: contain; box-sizing: border-box; - border: 1px solid #e2e2e2; + // border: 1px solid #e2e2e2; border-radius: 6px; - background-color: #f1f1f1; + background-color: var(--color-light-grey); } -} - -.no_img_wrapper { - height: calc(100% - 4px); - width: calc(100% - 4px); - text-align: center; - box-sizing: border-box; - padding: 5%; - border: 1px solid silver; - border-radius: 6px; - position: absolute; - top: 2px; - left: 2px; - & .no_img { - border: 1px black solid; - width: 100%; - height: 100%; - line-height: inital; + .gradient { + position: absolute; + content: ""; + top: -50px; + left: 0; + z-index: 1; + transform: rotate(30deg); + transform-origin: top right; + width: 200%; + height: 65%; + opacity: 0.3; + background: linear-gradient( + 0turn, + transparent 0%, + rgb(200 200 200 / 40%) 5%, + rgb(255 255 255 / 20%) 15%, + rgb(255 255 255 / 10%) 100% + ); + transition: height 0.3s ease-in-out, opacity 0.3s ease-in-out; + } + + + + .no_img_wrapper { + height: 285px; + text-align: center; + box-sizing: border-box; + padding: 5%; + border: 1px solid silver; + border-radius: 6px; display: flex; - flex-direction: column; - justify-content: center; align-items: center; - - & p { - word-break: break-all; - display: -webkit-inline-box; - -webkit-line-clamp: 3; - - /* autoprefixer: ignore next */ - -webkit-box-orient: vertical; - overflow: hidden; - text-align: center; - margin: 10px 5%; - color: var(--color-primary); - ; - - &:not(:first-child) { - font-size: 90%; + justify-content: center; + transform-origin: 100% 0; + transition: transform 0.3s ease-in-out; + + & .no_img { + border: 1px black solid; + width: 100%; + height: 100%; + line-height: inital; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + & p { + word-break: break-all; + display: -webkit-inline-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-align: center; + margin: 10px 5%; + color: var(--color-primary); + + &:not(:first-child) { + font-size: 90%; + } } } - } } -.publication_infos_wrapper { - width: 100%; - margin-top: 10px; - display: flex; - flex-direction: row; - align-items: flex-start; - justify-content: space-between; - font-size: 15px; - - & button { - width: 30px; - } - - & .publication_infos { - flex: 1; + & .publication_title_wrapper { overflow: hidden; + min-height: 30px; + margin-left: 4px; & p { margin: 0; @@ -117,9 +140,11 @@ white-space: nowrap; overflow: hidden; line-height: 1.2em; + font-size: 14px; + margin-bottom: 5px; } - & .publication_description { + & .publication_authors { font-weight: 300; overflow-wrap: break-word; line-height: 1.2em; @@ -130,11 +155,82 @@ line-clamp: 2; } } + + &:hover, &:focus { + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + } +} + +.expired { + &:hover, &:focus { + border: 1px solid red; + background-color: var(--color-error); + } +} + +.publication_infos_wrapper { + width: calc(100% - 12px); + // margin-top: 10px; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: end; + font-size: 15px; + gap: 10px; + padding: 0 6px; + + & button { + width: 20px; + } + + & .publication_infos { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + width: 100%; + height: 50px; + + & span { + height: 20px; + padding: 0 2px; + width: fit-content; + min-width: 30px; + font-size: 10px; + } + + & svg { + fill: var(--color-blue); + color: var(--color-blue); + border-radius: 4px; + transition: 200ms linear; + } + } +} + +.lcpIndicator { + width: fit-content; + display: flex; + justify-content: center; + gap: 5px; + font-size: 12px; + + svg { + width: 13px; + height: 13px; + color: var(--color-primary)!important; + } +} + +.lcp_over svg { + color: var(--color-error-dark)!important; } /* 2. list */ -.publication_list_wrapper { +.publication_list { + &_wrapper { display: flex; margin-left: 0; height: 40px; @@ -143,11 +239,11 @@ align-items: center; &:nth-child(odd) { - background-color: #f3f3f3; + background-color: var(--color-light-grey); } } -.publication_list_infos { +&_infos { flex: 1; position: relative; display: flex; @@ -169,58 +265,25 @@ & .publication_list_title_authors { margin-right: 20px; - width: calc(60% - 20px); + width: 50%; + max-width: 300px; } & div:last-child { - width: 40%; display: flex; justify-content: space-between; align-items: center; - } -} - -.block_book_list { - display: block; - width: calc(100% + 120px); - margin-left: -60px; - height: 40px; - padding: 10px 50px 10px 50px; - min-width: 600px; - font-size: 0.8rem; -} - -.block_book_list button { - float: left; -} - -.block_book_list:nth-child(odd) { - background-color: #f3f3f3; -} + width: 50%; -.block_book_list .icon_seemore { - position: relative; - display: inline-block; - width: 20px; - height: 30px; - margin: -5px 10px 0 10px; - top: 2px !important; -} - -.block_book_list p.book_title { - display: inline-block; - font-weight: 600; + & p { + width: 100px; + margin: 0 5px; + } + } } - -.block_book_list p.book_author { - display: inline-block; } -.block_book_list p.infos_sup { - display: inline-block; - width: 15%; - color: grey; -} +.block_book .block_book { width: 175px; @@ -231,10 +294,7 @@ & > a { position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; + inset: 0; display: flex; align-items: flex-end; justify-content: center; @@ -267,7 +327,51 @@ margin-right: -8px; & svg { - fill: rgb(107, 107, 107); + fill: rgb(107 107 107); + } + } + + &_list { + display: block; + width: calc(100% + 120px); + margin-left: -60px; + height: 40px; + padding: 10px 50px; + min-width: 600px; + font-size: 0.8rem; + + button { + float: left; + } + + &:nth-child(odd) { + background-color: #f3f3f3; + } + + .icon_seemore { + position: relative; + display: inline-block; + width: 20px; + height: 30px; + margin: -5px 10px 0; + top: 2px !important; + } + + p.book{ + &_title { + display: inline-block; + font-weight: 600; + } + + &_author { + display: inline-block; + } + } + + p.infos_sup { + display: inline-block; + width: 15%; + color: grey; } } } @@ -291,12 +395,6 @@ line-height: 1.2em; max-height: 2.4em; overflow: hidden; - - /* - multiline ellipsis! - white-space: nowrap; - text-overflow: ellipsis; - */ padding-right: 1em; } @@ -328,12 +426,6 @@ line-height: 1.2em; max-height: 2.4em; overflow: hidden; - - /* - multiline ellipsis! - white-space: nowrap; - text-overflow: ellipsis; - */ padding-right: 1em; } @@ -461,9 +553,35 @@ max-height: 100%; object-fit: contain; box-sizing: border-box; - border: 1px solid #e2e2e2; + // border: 1px solid #e2e2e2; border-radius: 6px; - background-color: #f1f1f1; + background-color: var(--color-light-grey); +} + +.corner { + // transform:rotate(40deg); + position: absolute; + // top: -15px; + // right: -15px; + // background-color: var(--color-blue); + display : inline-block; + height : 0; + width : 0; + border-top : 50px solid var(--color-secondary); + border-left : 50px solid transparent; + opacity: 0.8; + right: 5px; + top: 5px; + + svg { + width: 15px; + height: 15px; + color: var(--color-blue); + position: absolute; + transform: translate(-50%, -50%); + top: -32px; + right: 0; + } } .___DEBUG___COMPONENTS_PUBLICATIONS_CSS { diff --git a/src/renderer/assets/styles/components/publications.scss.d.ts b/src/renderer/assets/styles/components/publications.scss.d.ts new file mode 100644 index 000000000..635fb1f09 --- /dev/null +++ b/src/renderer/assets/styles/components/publications.scss.d.ts @@ -0,0 +1,33 @@ +export declare const ___DEBUG___COMPONENTS_PUBLICATIONS_CSS: string; +export declare const author: string; +export declare const block_book: string; +export declare const block_book_list: string; +export declare const book_author: string; +export declare const book_title: string; +export declare const box: string; +export declare const corner: string; +export declare const cover: string; +export declare const cover_img: string; +export declare const expired: string; +export declare const gradient: string; +export declare const hasEnded: string; +export declare const icon_seemore: string; +export declare const image_wrapper: string; +export declare const infos_sup: string; +export declare const lcp_over: string; +export declare const lcpIndicator: string; +export declare const legend: string; +export declare const menu: string; +export declare const no_img: string; +export declare const no_img_wrapper: string; +export declare const publication_authors: string; +export declare const publication_infos: string; +export declare const publication_infos_wrapper: string; +export declare const publication_list_infos: string; +export declare const publication_list_title_authors: string; +export declare const publication_list_wrapper: string; +export declare const publication_main_container: string; +export declare const publication_title: string; +export declare const publication_title_wrapper: string; +export declare const publication_wrapper: string; +export declare const title: string; diff --git a/src/renderer/assets/styles/components/readerFooter.scss b/src/renderer/assets/styles/components/readerFooter.scss new file mode 100644 index 000000000..81d12a5f6 --- /dev/null +++ b/src/renderer/assets/styles/components/readerFooter.scss @@ -0,0 +1,301 @@ +/* +=-=-= readerFooter.scss +*/ + +.RTL_FLIP { + transform: scale(-1, 1); +} + +.navigation_arrow { + &_left { + left: 10px; + } + + &_right { + right: 10px; + } + + &_docked_left { + left: 360px; + } + + &_docked_right { + right: 360px; + } +} + +.arrows button { + width: 50px; + height: 50px; + position: absolute; + top: calc(50dvh - 100px); + z-index: 10; + + svg { + fill: var(--color-blue); + + // @media (prefers-color-scheme: dark) { + // fill: #FEFEFE; + // color: #FEFEFE; + // } + } +} + +#track_reading { + position: relative; + width: 100%; + height: 10px; + background-color: var(--color-light-grey); + border: 1px solid var(--color-medium-grey); + border-radius: 6px; + overflow: hidden; +} + +#track_reading + span { + font-style: italic; + font-size: 0.8rem; + padding-bottom: 10px; + cursor: pointer; + margin: 0; +} + + +.reader_footer { + position: fixed; + bottom: 0; + right: 0; + left: 0; + background-color: var(--reader-mainColor); + + .HIDE_CURSOR_CLASS_foot { + visibility: hidden !important; + } + + .history { + // float: left; + // margin-top: 1.5rem; + // margin-left: 1rem; + + position: absolute; + bottom: 7px; + left: 10px; + + & button { + display: inline; + border: 0; + cursor: pointer; + padding: 5px; + border-radius: 6px; + background-color: transparent; + width: 30px; + height: 30px; + margin: 0 10px; + + svg { + color: var(--color-blue); + + // @media (prefers-color-scheme: dark) { + // fill: #FEFEFE; + // color: #FEFEFE; + // } + } + + &.disabled { + cursor: not-allowed; + background-color: var(--color-medium-grey); + + svg { + color: var(--color-dark-grey); + fill: var(--color-dark-grey); + } + } + } + + & svg { + fill: var(--reader-fontColor); + opacity: 1; + transform: scale(0.8); + } + } + + & .arrows { + float: right; + margin-top: 1rem; + margin-right: 2rem; + + & button { + display: inline; + border: 0; + cursor: pointer; + padding: 0; + background-color: transparent; + width: 40px; + height: 40px; + } + } + + & .track_reading_wrapper { + padding: 1rem 5rem 1rem 8rem; + bottom: 0; + + // margin-top: 1rem; + color: var(--color-primary); + background-color: var(--color-secondary); + } + + & .track_reading_wrapper_noArrows { + padding-top: 1rem; + padding-right: 5rem; + padding-bottom: 1rem; + } +} + +.reader_footer_fullscreen { + background-color: transparent; + pointer-events: none; + + & .arrows { + background-color: var(--reader-mainColor); + pointer-events: all; + margin-bottom: 15px; + margin-right: 20px; + } + + & .history { + background-color: transparent; + pointer-events: all; + margin-bottom: 15px; + margin-left: 20px; + } +} + +#chapters_markers { + display: flex; + position: absolute; + width: 100%; + height: 16px; + margin-top: -3px; + top: 0; + cursor: pointer; + + span { + border-left: 1px solid transparent; + transition: 200ms; + } + + &:hover { + span:has(span) { + border-left: 1px solid var(--color-extralight-grey); + + span { + border-left: 1px solid var(--color-extralight-grey); + } + } + + span { + border-left: 1px solid var(--color-blue); + } + } + + .progressChunkSpineItem { + transition: 200ms; + background-color: transparent; + + span { + opacity: 1; + transition: 200ms; + } + + &:hover { + outline: var(--color-blue) solid 1px; + z-index: 10; + outline-offset: 0; + background-color: white; + + span { + opacity: 0.5; + } + } + } + + &.more_information > span { + &.currentSpineItem { + border-radius: 6px; + outline: var(--color-blue) solid 1px; + outline-offset: 0; + background-color: white; + + span { + display: none; + } + } + } + + & > span { + flex-grow: 1; + margin: 2px 0; + height: 12px; + + & > span { + display: block; + background-color: var(--color-blue); + width: 100%; + height: 100%; + } + + &:last-child { + border-right: none; + } + } +} + +.tooltip_content { + span { + fill: var(--color-light-grey); + } +} + +#arrow_box { +width: fit-content; +height: auto; +padding: 10px 5px 5px; +background: var(--color-light-grey); +border: 1px solid var(--color-medium-grey); +font-size: 16px; +color: var(--color-primary); +text-align: left; +box-shadow: 0 3px 2px 0 var(--color-medium-grey); + + +& span { + display: block; + margin: 0 5px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: bold; + + & em { + font-size: 80%; + font-weight: normal; + } +} + +& p { + margin: 5px 0; + font-size: 0.8rem; + padding: 0 5px; +} +} + +.finishedIcon { + position: absolute; + right: 30px; + bottom: 10px; + width: 25px; + + svg { + fill: #1BAF01; + color: #1BAF01; + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/readerFooter.scss.d.ts b/src/renderer/assets/styles/components/readerFooter.scss.d.ts new file mode 100644 index 000000000..28c0f24e0 --- /dev/null +++ b/src/renderer/assets/styles/components/readerFooter.scss.d.ts @@ -0,0 +1,21 @@ +export declare const arrow_box: string; +export declare const arrows: string; +export declare const chapters_markers: string; +export declare const currentSpineItem: string; +export declare const disabled: string; +export declare const finishedIcon: string; +export declare const HIDE_CURSOR_CLASS_foot: string; +export declare const history: string; +export declare const more_information: string; +export declare const navigation_arrow_docked_left: string; +export declare const navigation_arrow_docked_right: string; +export declare const navigation_arrow_left: string; +export declare const navigation_arrow_right: string; +export declare const progressChunkSpineItem: string; +export declare const reader_footer: string; +export declare const reader_footer_fullscreen: string; +export declare const RTL_FLIP: string; +export declare const tooltip_content: string; +export declare const track_reading: string; +export declare const track_reading_wrapper: string; +export declare const track_reading_wrapper_noArrows: string; diff --git a/src/renderer/assets/styles/components/readerHeader.scss b/src/renderer/assets/styles/components/readerHeader.scss new file mode 100644 index 000000000..9c02f917f --- /dev/null +++ b/src/renderer/assets/styles/components/readerHeader.scss @@ -0,0 +1,312 @@ +/* +=-=-= readerHeader.scss +*/ + +.toolbar_navigation { + height: 50px; + width: 100%; + padding: 0; + background-color: var(--color-extralight-grey); + border-bottom: 2px solid var(--color-medium-grey); + box-sizing: border-box; + + &.ttsAudioActivated .tts_toolbar::before { + content: ""; + position: absolute; + left: calc(50% - 105px); + top: 42px; + height: 1px; + width: 210px; /* or 100px */ + border-bottom: 2px solid var(--color-blue); + } + + > ul { + display: flex; + align-items: center; + justify-content: space-between; + height: inherit; + margin: 0; + list-style-type: none; + padding: 0 20px; + + .tts_toolbar { + justify-content: center; + position: relative; + } + + .menu_option { + justify-content: end; + gap: 10px; + } + + .pdf_options { + max-width: 100px; + } + + li { + height: 40px; + width: 40px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 5px; + + &:has(input:disabled) { + .menu_button { + background-color: transparent; + cursor:auto; + + &:not(:has(.active_svg)):hover, + &:not(:has(.active_svg)):focus { + border-color: transparent; + background-color: transparent; + } + + svg { + fill: var(--color-medium-grey); + color: var(--color-medium-grey); + } + } + } + + .my_combobox_container { + width: unset; + } + + .menu_button { + height: 42px; + width: 42px; + cursor: pointer; + padding: 5px; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid transparent; + transition: .2s; + border-radius: 5px; + + &:not(:has(.active_svg)):hover, + &:not(:has(.active_svg)):focus { + border-color: var(--color-blue); + background-color: var(--color-light-blue); + } + + svg { + height: 20px; + width: 30px; + fill: var(--color-blue); + color: var(--color-blue); + + // @media (prefers-color-scheme: dark) { + // fill: #FEFEFE; + // color: #FEFEFE; + // } + } + } + + input { + position: relative; + opacity: 0; + } + + label { + position: absolute; + display: block; + align-items: center; + + + svg { + width: inherit; + height: inherit; + fill: var(--color-blue); + } + } + } + + > ul { + display: flex; + padding: 0; + flex: 1; + } + } +} + +.active_svg { + fill: white!important; + color: white!important; + + // @media (prefers-color-scheme: dark) { + // fill: black!important; + // color: black!important; + // } +} + +.picker_container { + display: flex; + align-items: center; + padding: 0; + width: 100vw; + height: 48px; + background-color: var(--color-extralight-grey); + margin-right: 5px; + z-index: 100; + top: 65px; + right: 10px; + left: unset; + border: 1px solid var(--color-medium-grey); + + button[title="Close"] { + width: 15px; + height: 15px; + padding: 4px; + margin: 0; + + svg { + height: 15px; + } + } + + .form_group { + width: 200px!important; + height: 24px!important; + + label { + top: -18px; + background-color: var(--color-extralight-grey); + } + + button { + svg { + fill: var(--color-blue); + } + } + } +} + +.button { + &_close { + width: 20px; + height: 20px; + } + + &_arrow { + fill: var(--color-extralight-grey); + width: 15px; + height: 10px; + } +} + +.Tts_popover_container { + display: flex; + align-items: center; + height: 75px; + background-color: var(--color-extralight-grey); + box-shadow: 0 6px 10px 0 var(--color-medium-grey); + border-radius: 6px; + list-style-type: none; + margin: 0; + padding: 0; + border: 1px solid var(--color-medium-grey); + + li { + display: flex; + flex-direction: column; + justify-content: center; + align-items: start; + border-right: 1px solid var(--color-medium-grey); + height: 50px; + padding: 0 20px; + + .react_aria_Input { + background-color: var(--color-secondary)!important; + color: var(--color-primary)!important; + } + + select { + width: fit-content; + height: 30px; + border-radius: 6px; + padding: 0 10px; + background-color: var(--color-secondary); + color: var(--color-primary); + } + } +} + +.popover_arrow { + border-top: 2px solid var(--color-extralight-grey); + fill: var(--color-extralight-grey); + width: 15px; + height: 10px; +} + +.bookmarkButton:focus + label { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; + +} + +#bookmarkLabel .bookmarkRemove{ + display: none; + height: 24px; +} + +#bookmarkLabel .bookmarkIcon{ + display: block; +} + +#bookmarkLabel:hover .bookmarkRemove{ + display: none; +} + +#bookmarkLabel:hover .bookmarkIcon{ + display: block; +} + +#bookmarkLabel:hover .active_svg.bookmarkRemove { + display: block; +} + +#bookmarkLabel:hover .bookmarkIcon.active_svg { + display: none; +} + +.annotationsIcon svg { + width: 22px!important; + height: 25px!important; +} + +.searchHeader_container { + display: flex; + align-items: center; + + // padding: 20px 0; + width: 400px; + margin-right: 10%; + + .searchActions { + display: flex; + align-items: center; + + &::before { + content: ""; + position: absolute; + margin-right: 10%; + top: 48px; + height: 1px; + width: 200px; + border-bottom: 2px solid var(--color-blue); + } + } + + form::before { + content: ""; + position: absolute; + margin-right: 10%; + top: 37px; + height: 1px; + width: 100%; + border-bottom: 2px solid var(--color-blue); + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/readerHeader.scss.d.ts b/src/renderer/assets/styles/components/readerHeader.scss.d.ts new file mode 100644 index 000000000..07405eb12 --- /dev/null +++ b/src/renderer/assets/styles/components/readerHeader.scss.d.ts @@ -0,0 +1,22 @@ +export declare const active_svg: string; +export declare const annotationsIcon: string; +export declare const bookmarkButton: string; +export declare const bookmarkIcon: string; +export declare const bookmarkLabel: string; +export declare const bookmarkRemove: string; +export declare const button_arrow: string; +export declare const button_close: string; +export declare const form_group: string; +export declare const menu_button: string; +export declare const menu_option: string; +export declare const my_combobox_container: string; +export declare const pdf_options: string; +export declare const picker_container: string; +export declare const popover_arrow: string; +export declare const react_aria_Input: string; +export declare const searchActions: string; +export declare const searchHeader_container: string; +export declare const toolbar_navigation: string; +export declare const Tts_popover_container: string; +export declare const tts_toolbar: string; +export declare const ttsAudioActivated: string; diff --git a/src/renderer/assets/styles/components/settings.scss b/src/renderer/assets/styles/components/settings.scss new file mode 100644 index 000000000..22c1e2937 --- /dev/null +++ b/src/renderer/assets/styles/components/settings.scss @@ -0,0 +1,816 @@ +/* +=-=-= settings.scss +*/ + +$settings_bg: var(--color-light-blue); +$setting_color: var(--color-blue); + +.settings_container { + display: flex; + height: 597px; + + input[type='range'], input[type="checkbox"] { + accent-color: $setting_color; + } + + @media screen and (height <= 700px) { + height: 450px; + } + + .section { + padding-bottom: 15px ; + border-bottom: 3px solid var(--color-light-grey); + margin: 10px 0 20px; + width: 100%; + display: flex; + flex-direction: column; + gap: 5px; + + input[type="range"] { + width: 150px; + + &.range_inactive { + accent-color: grey; + + &::-webkit-slider-thumb { + width: 2em; + padding: 0.25em; + border: 1px solid var(--color-disabled); + border-radius: 50%; + box-shadow: 0 0 .5em #FFF inset; + background: linear-gradient(#888, #FFF) content-box, + linear-gradient(-90deg, #888, #DDD) border-box; + } + } + } + + .btn_primary { + width: fit-content; + padding: 0 5px; + height: 35px; + border: 1px solid $setting_color; + border-radius: 5px; + background-color: $settings_bg; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + color: $setting_color; + + p { + font-size: 14px; + } + + svg { + width: 20px; + height: 16px; + fill: $setting_color; + } + } + } + + h4 { + margin: 0; + font-weight: 600; + } +} + +.settings_tabslist { + display: flex; + flex-direction: column; + width: 100%; + flex: 1; + border-right: 1px solid var(--color-medium-grey); + padding-top: 50px; + background-color: var(--color-extralight-grey); + gap: 10px; + + button { + height: 30px; + transition: 200ms; + // width: 80%; + display: flex; + align-items: center; + justify-content: left; + margin: 0 10%; + gap: 10px; + padding: 5px; + border: 1px solid transparent; + border-radius: 6px; + font-weight: normal; + + h3 { + font-size: 14px; + text-overflow: ellipsis; + overflow: hidden; + max-width: 120px; + white-space: nowrap; + } + + &:hover { + background-color: var(--color-medium-grey); + } + + &[data-state="active"]{ + color: $setting_color; + background-color: $settings_bg; + border: 1px solid $setting_color; + + svg { + fill: $setting_color; + } + } + + &:focus { + position: relative; + } + + svg { + width: 15px; + transition: 200ms linear; + } + } + + .allowCustom { + margin: 10px 10%; + gap: 5px; + } + + button[data-value="tab-text"], button[data-value="tab-spacing"] { + margin-left: 20%; + } +} + +.allowCustom { + display: flex; + accent-color: var(--color-blue); + margin: 10px; +} + +.tablist_reading { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex: 1; + border-bottom: 1px solid var(--color-medium-grey); + margin-bottom: 20px; + + button { + transition: 200ms; + height: 100%; + width: 100px; + gap: 10px; + margin: 0 !important; + border-bottom: 1px solid transparent; + font-weight: normal; + flex-direction: column; + + &:hover { + background-color: var(--color-medium-grey); + } + + &[data-state="active"]{ + color: $setting_color; + background-color: $settings_bg; + border-bottom: 2px solid $setting_color; + + svg { + width: 30px; + height: 30px; + } + } + + &:focus { + position: relative; + } + + svg { + width: 25px; + height: 25px; + transition: 200ms linear; + } + + p { + margin: 5px; + } + } +} + +.settings_content { + flex: 2; + overflow: hidden scroll; + margin-top: 50px; + + &::-webkit-scrollbar-thumb { + border-radius: 5px; + } + + &::-webkit-scrollbar { + width: 10px; + background: var(--color-secondary); + } + + &:hover::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb); + } + + .button_transparency_icon { + position: relative; + + svg { + position: absolute; + transform: translate(-50%,-50%); + left: 50%; + top: 50%; + fill: $setting_color; + } + } +} + +.close_button_div { + position: absolute; + top: 10px; + right: 20px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + background-color: var(--color-secondary); + padding: 10px; + width: 60%; + z-index: 10; + + div { + display: flex; + align-items: center; + gap: 5px; + } + + .settings_tab_title { + margin: 0; + + h2 { + margin: 0; + } + } +} + +.reset_button { + width: 20px; + height: 20px; + padding: 5px; + border-radius: 5px; + transition: 200ms; + box-sizing: content-box; + border: 1px solid transparent; + + &:active, &:hover { + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue)!important; + } + + svg { + color: var(--color-blue); + } +} + +.settings_tab { + margin: 30px 25px 0!important; + + &_container { + margin: 35px; + + &_reading { + margin: 0 25px; + + .size_range { + display: flex; + align-items: center; + height: 30px; + gap: 10px; + + input { + cursor: pointer; + } + + button { + width: 20px; + height: 20px; + padding: auto; + } + + p { + padding: 5px; + width: 50px; + text-align: center; + background-color: $settings_bg; + border-radius: 5px; + } + } + + &_spacing { + display: grid; + grid-template-columns: repeat(2, 1fr); + + .section { + width: 90%!important; + + .size_range { + display: flex; + align-items: center; + gap: 5px; + height: 30px; + + .range_inactive { + accent-color: grey; + + &::-webkit-slider-thumb { + width: 2em; + padding: 0.25em; + border: 1px solid var(--color-disabled); + border-radius: 50%; + box-shadow: 0 0 .5em #FFF inset; + background: linear-gradient(#888, #FFF) content-box, + linear-gradient(-90deg, #888, #DDD) border-box; + } + } + + input[type="range"] { + width: 150px; + height: 5px; + } + } + + label { + font-weight: 600; + } + + p { + font-size: 14px; + } + + h4 { + margin: 0; + max-width: 120px; + } + } + + .session_text { + display: flex; + align-items: start; + justify-content: flex-start; + gap: 10px; + font-size: 14px; + background-color: var(--color-light-grey); + color: var(--color-primary); + padding: 5px 10px; + border-radius: 5px; + margin: 10px 0; + + p { + margin: 5px 0; + } + + svg { + margin-top: 5px; + width: 25px; + height: 25px; + color: $setting_color; + } + } + } + } + } + + &_title { + display: flex; + align-items: start; + justify-content: flex-start; + margin: 0 25px 20px; + font-size: 16px; + gap: 10px; + + h2 { + margin-top: 0; + } + + button[data-state="open"] .advanced_trigger { + background-color: var(--color-light-blue); + border-color: var(--color-blue); + } + } + + .session_text { + display: flex; + align-items: start; + justify-content: flex-start; + gap: 10px; + width: 320px; + font-size: 14px; + background-color: var(--color-light-grey); + color: var(--color-primary); + padding: 5px 10px; + border-radius: 5px; + margin: 10px 0; + + p { + margin: 5px 0; + } + + svg { + margin-top: 5px; + width: 16px; + height: 16px; + color: $setting_color; + } + } +} + +.select { + &_trigger { + display: flex; + align-items: center; + justify-content: space-between; + gap: 30px; + padding: 0 25px 0 10px; + border: 1px solid var(--color-primary); + border-radius: 4px; + height: 35px; + width: 300px; + + > div { + display: flex; + align-items: center; + gap: 10px; + } + } + + &_icon { + width: 24px; + height: 24px; + } + + &_item { + line-height: 2; + border-radius: 3px; + display: flex; + align-items: center; + height: 25; + padding: 0 35px 0 25px; + position: relative; + border-bottom: 1px solid var(--color-medium-grey); + color: var(--color-primary); + font-size: 14px; + + &:hover { + cursor: pointer; + background-color: $settings_bg; + color: $setting_color; + } + } + + &_content { + overflow: hidden; + background-color: var(--color-secondary)!important; + opacity: 1; + border-radius: 4px; + z-index:10001; + border: 1px solid var(--color-medium-grey); + width: 300px; + max-height: 300px; + font-size: 14px; + } +} + +div[data-radix-popper-content-wrapper] { + position: fixed!important; +} + +.scale_button { + scale: 1.3; + color: var(--color-blue); + border-radius: 4px; + width: 15px; + height: 15px; + text-align: center; + border: 1px solid transparent; + position: relative; + padding: 3px; + box-sizing: content-box; + transition: 200ms; + + span { + position: absolute; + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + } + + &:active, &:hover { + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue)!important; + } +} + +.spacing_heading { + display: flex; + align-items: center; + gap: 10px; + justify-content: space-between; + + p { + width: fit-content; + padding: 2px 4px; + border-radius: 4px; + text-align: center; + background-color: var(--color-light-grey); + } +} + + +.settings_reading { + &_text { + input[type="range"] { + width: 200px; + height: 5px; + } + + .label_fontSize, .label_fontFamily { + margin: 10px 0 20px; + } + + select.form_group { + height: 30px !important; + width: 300px; + } + + .size_range { + display: flex; + align-items: center; + gap: 10px; + + p { + padding: 0; + text-align: center; + background-color: transparent; + } + } + } +} + + +.display_options { + display: flex; + font-size: 14px; + height: 80px; + list-style-type: none; + + svg { + width: 30px; + height: 30px; + } + + &_item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 95px; + padding-top: 5px; + border: 1px solid transparent; + border-radius: 6px; + transition: 200ms linear; + min-height: 70px; + background-color: var(--color-extralight-grey); + + &:hover:not([disabled]) { + border: 1px solid $setting_color; + background-color: $settings_bg; + cursor: pointer; + } + + } + + div[role="radiogroup"] { + button { + transition: 200ms linear; + + &[data-state="checked"] { + border: 1px solid $setting_color; + background-color: $settings_bg; + color: $setting_color; + + svg { + fill: $setting_color; + } + } + } + } +} + +.settings_font{ + &_container { + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + + &:hover { + border: none transparent; + box-shadow: none; + } + + > svg { + position: absolute; + left: 10px; + width: 24px; + height: 24px; + } + } + + &_selection { + padding: 0 0 0 35px; + border: 1px solid var(--color-primary); + border-radius: 4px; + width: 300px; + height: 35px; + + &__control { + display: flex; + align-items: center; + width: 100%; + height: 30px; + border: none; + margin-right: 0; + background-color: var(--color-secondary)!important; + + &:hover { + box-shadow: none; + } + } + + &__value-container { + padding: 0; + color: var(--color-primary)!important; + height: 25px; + } + + &__input { + width: 220px!important; + padding-left: 5px!important; + height: 23px!important; + } + + &__menu { + left: 0; + background-color: var(--color-secondary)!important; + color: var(--color-primary)!important; + z-index: 2000000; + + > div { + border: 1px solid black; + + > div:hover { + cursor: pointer; + + } + + } + } + } +} + +.maths_options { + display: flex; + flex-direction: column; + align-items: start; + justify-content: start; + gap: 5px; +} + +.toggleCustom { + position: absolute; + bottom: 30px; + left: 20px; + width: 190px; + display: flex; + align-items: start; + border: 0 solid var(--color-blue); + border-radius: 5px; + + p { + font-size: 14px; + } + + label .label { + display: inline-block; + width: 9em; + user-select: none; + } + + label input[role="switch"] { + opacity: 0; + } + + label input[role="switch"] ~ .state { + display: inline-block; + user-select: none; + } + + label input[role="switch"] ~ .state > .container { + position: relative; + top: 2px; + display: inline-block; + border: 1px solid transparent; + width: 30px; + height: 18px; + border-radius: 11px; + background-color: #61646B; + cursor: pointer; + } + + label input[role="switch"] ~ .state > .container > .position { + position: relative; + top: 1px; + left: 2px; + display: inline-block; + border: 2px solid white; + border-radius: 9px; + width: 12px; + height: 12px; + background: white; + } + + label input[role="switch"]:not(:checked) ~ .state span.on { + display: none; + } + + label input[role="switch"]:checked ~ .state > span.off { + display: none; + } + + label input[role="switch"]:checked ~ .state > .container { + background-color: #0B8454; + + > .position { + left: 12px; + border-color: white; + background: white; + opacity: 1; + } + } + + &.focus { + border-width: 2px; + outline: none; + background-color: #def; + } + + &.focus span.container, + &:hover span.container { + background-color: white; + } +} + + +.settings_theme_container { + border-radius: 6px; + border-width: 2px; + border-style: solid; + border-color: var(--color-medium-grey); + width: 85px; + height: 45px!important; + min-height: 45px!important; + text-decoration: none; + box-shadow: 0 2px 15px rgb(0 0 0 / 0%); + transition: all 0.3s; + padding: 0; + background-color: var(--color-secondary); + margin: 0!important; + display: flex!important; + align-items: center; + justify-content: center; + cursor: pointer; + position: relative; + + &::after { + content: ""; + width: inherit; + height: inherit; + position: absolute; + top: -6px; + right: -8px; + border-radius: 6px; + border-right: 1px solid var(--color-medium-grey); + border-top: 1px solid var(--color-medium-grey); + } + + svg { + width: 12px; + height: 12px; + position: absolute; + top: 2px; + right: 5px; + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/settings.scss.d.ts b/src/renderer/assets/styles/components/settings.scss.d.ts new file mode 100644 index 000000000..3d117de77 --- /dev/null +++ b/src/renderer/assets/styles/components/settings.scss.d.ts @@ -0,0 +1,46 @@ +export declare const advanced_trigger: string; +export declare const allowCustom: string; +export declare const btn_primary: string; +export declare const button_transparency_icon: string; +export declare const close_button_div: string; +export declare const container: string; +export declare const display_options: string; +export declare const display_options_item: string; +export declare const focus: string; +export declare const form_group: string; +export declare const label: string; +export declare const label_fontFamily: string; +export declare const label_fontSize: string; +export declare const maths_options: string; +export declare const off: string; +export declare const on: string; +export declare const position: string; +export declare const range_inactive: string; +export declare const reset_button: string; +export declare const scale_button: string; +export declare const section: string; +export declare const select_content: string; +export declare const select_icon: string; +export declare const select_item: string; +export declare const select_trigger: string; +export declare const session_text: string; +export declare const settings_container: string; +export declare const settings_content: string; +export declare const settings_font_container: string; +export declare const settings_font_selection: string; +export declare const settings_font_selection__control: string; +export declare const settings_font_selection__input: string; +export declare const settings_font_selection__menu: string; +export declare const settings_reading_text: string; +export declare const settings_tab: string; +export declare const settings_tab_container: string; +export declare const settings_tab_container_reading: string; +export declare const settings_tab_container_reading_spacing: string; +export declare const settings_tab_title: string; +export declare const settings_tabslist: string; +export declare const settings_theme_container: string; +export declare const size_range: string; +export declare const spacing_heading: string; +export declare const state: string; +export declare const tablist_reading: string; +export declare const toggleCustom: string; diff --git a/src/renderer/assets/styles/components/slider.css b/src/renderer/assets/styles/components/slider.css deleted file mode 100644 index 3c04deceb..000000000 --- a/src/renderer/assets/styles/components/slider.css +++ /dev/null @@ -1,47 +0,0 @@ -/* -=-=-= components/slider.css -*/ - -.slider { - display: block; - width: 100%; - position: relative; -} - -.slider_wrapper { - position: relative; - overflow-x: hidden; - overflow-y: hidden; - height: 340px; -} - -.slider_items { - display: inline-flex; - position: absolute; - top: 0; - left: 0; - - & > *:not(:first-child) { - margin-left: 15px; - } -} - -.slider_button_prev, -.slider_button_next { - position: absolute; - top: 40%; -} - -.slider_button_prev { - left: -50px; - transform: translateY(-50%) rotateY(180deg); -} - -.slider_button_next { - right: -50px; - transform: translateY(-50%); -} - -.___DEBUG___COMPONENTS_SLIDER_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/slider.css.d.ts b/src/renderer/assets/styles/components/slider.css.d.ts deleted file mode 100644 index 32f9a2526..000000000 --- a/src/renderer/assets/styles/components/slider.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_SLIDER_CSS": string; - readonly "slider": string; - readonly "slider_button_next": string; - readonly "slider_button_prev": string; - readonly "slider_items": string; - readonly "slider_wrapper": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/slider.scss b/src/renderer/assets/styles/components/slider.scss new file mode 100644 index 000000000..8b2fb271d --- /dev/null +++ b/src/renderer/assets/styles/components/slider.scss @@ -0,0 +1,98 @@ +/* +=-=-= slider.scss +*/ + +.slider { + display: block; + position: relative; + + &_wrapper { + position: relative; + overflow: hidden hidden; + height: 400px; + } + + &_items { + display: inline-flex; + position: absolute; + top: 0; + left: 0; + + & > *:not(:first-child) { + margin-left: 15px; + } + } + + > button { + display: flex; + } + + button:disabled { + svg { + fill: var(--color-disabled); + } + } +} + +.slider_button { + &_prev { + right: 40px; + transform: translateY(-50%) rotateY(180deg); + + svg { + margin: auto; + } + } + + &_next { + right: 0; + transform: translateY(-50%); + + svg { + margin: auto; + } + } + + &_prev, + &_next { + position: absolute; + top: -30px; + } +} + + +.continue_reading { + border: 1px solid var(--color-medium-grey); + background-color: var(--color-extralight-grey); + border-radius: 6px; + margin: 20px; + padding: 20px; + + .slider_wrapper { + min-height: 380px; + height: fit-content; + padding-bottom: 10px; + } + + .publication_wrapper { + width: 170px; + height: 360px; + + img, .no_img_wrapper { + height: 225px; + } + } + + .cover_img { + background-color: var(--color-secondary); + } +} + +.home_section { + border: 1px solid transparent; + margin: 20px; +} + +.___DEBUG___COMPONENTS_SLIDER_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/components/slider.scss.d.ts b/src/renderer/assets/styles/components/slider.scss.d.ts new file mode 100644 index 000000000..9c99121ce --- /dev/null +++ b/src/renderer/assets/styles/components/slider.scss.d.ts @@ -0,0 +1,11 @@ +export declare const ___DEBUG___COMPONENTS_SLIDER_CSS: string; +export declare const continue_reading: string; +export declare const cover_img: string; +export declare const home_section: string; +export declare const no_img_wrapper: string; +export declare const publication_wrapper: string; +export declare const slider: string; +export declare const slider_button_next: string; +export declare const slider_button_prev: string; +export declare const slider_items: string; +export declare const slider_wrapper: string; diff --git a/src/renderer/assets/styles/components/tags.css b/src/renderer/assets/styles/components/tags.css deleted file mode 100644 index bf1f7aca6..000000000 --- a/src/renderer/assets/styles/components/tags.css +++ /dev/null @@ -1,73 +0,0 @@ -/* -=-=-= components/tags.css => '../partials/variables.css' -*/ - -/* -@import url('../partials/variables.css'); -*/ - -/* -=-=-= components/tags.css -*/ - -.tags_wrapper { - display: flex; - flex-direction: row; - align-items: flex-start; - justify-content: flex-start; - flex-wrap: wrap; -} - -.tag { - display: flex; - align-items: center; - background-color: #e7f1fb; - padding: 2px 6px; - font-size: 1.1rem; - border-radius: 5px; - border: 1px solid var(--color-tertiary); - color: var(--color-tertiary); - cursor: pointer; - text-decoration: none; - transition: all 0.2s; - margin-right: 10px; - margin-bottom: 10px; - - &:hover { - background-color: #d0e2f5; - } - - &.no_hover:hover { - background-color: #e7f1fb; - cursor: default; - } - - & button { - width: 21px; - height: 21px; - margin: 0 0 0 5px; - } -} - -.tag_inputs { - position: relative; - max-width: 300px; - flex: 1; - border-radius: 0; - border: none; - height: 35px; - background-color: transparent; - color: var(--color-primary); - font-size: 0.9rem; - border-bottom: 1px solid #c1c1c1; - - &::placeholder { - font-size: 0.9rem; - font-weight: 300; - color: #c1c1c1; - } -} - -.___DEBUG___COMPONENTS_TAGS_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/components/tags.css.d.ts b/src/renderer/assets/styles/components/tags.css.d.ts deleted file mode 100644 index 5669f3136..000000000 --- a/src/renderer/assets/styles/components/tags.css.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_TAGS_CSS": string; - readonly "no_hover": string; - readonly "tag": string; - readonly "tag_inputs": string; - readonly "tags_wrapper": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/tags.scss b/src/renderer/assets/styles/components/tags.scss new file mode 100644 index 000000000..12916846f --- /dev/null +++ b/src/renderer/assets/styles/components/tags.scss @@ -0,0 +1,188 @@ +/* +=-=-= tags.scss +*/ + +.tags_wrapper { + display: flex; + flex-flow: row wrap; + align-items: flex-start; + justify-content: flex-start; +} + +.tag { + display: flex; + align-items: center; + background-color: var(--color-light-blue); + padding: 2px 6px; + border-radius: 5px; + border: 1px solid var(--color-blue); + color: var(--color-blue)!important; + cursor: pointer; + text-decoration: none; + transition: all 0.2s; + margin-right: 10px; + margin-bottom: 5px; + + + a { + display: flex; + align-items: center; + text-decoration: none!important; + color: var(--color-blue)!important; + + &:visited { + color: var(--color-blue); + } + } + + &:has(button[data-state="open"]) { + background-color: var(--color-light-grey); + border: 1px solid var(--color-primary); + color: var(--color-primary); + + a { + color: black!important; + } + + &:hover { + background-color: var(--color-light-grey); + } + + svg { + color: var(--color-primary); + } + } + + & svg { + fill: var(--color-blue); + color: var(--color-blue); + } + + &:hover { + background-color: var(--color-secondary); + } + + &.no_hover:hover { + background-color: var(--color-secondary); + cursor: default; + } + + & button { + width: 11px; + height: 11px; + margin: 0 0 0 5px; + + &:hover svg { + color: var(--color-primary); + } + } + + &_inputs { + position: relative; + max-width: 300px; + flex: 1; + border-radius: 0; + border: none; + height: 35px; + background-color: transparent; + color: var(--color-primary); + border-bottom: 1px solid #c1c1c1; + + &::placeholder { + font-weight: 300; + color: #c1c1c1; + } + } +} + +.___DEBUG___COMPONENTS_TAGS_CSS { + display: none; +} + +.Popover_delete_tag { + z-index: 1000; + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + border-radius: 6px; + transition: 200ms; + + &:hover { + background-color: #e7f1fb; + } + + button { + padding: 5px; + color: var(--color-blue); + height: unset; + + svg { + width: 10px; + } + } +} + + +.allPub_tagsTrigger { + width: fit-content; + height: fit-content; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + border-radius: 6px; + padding: 5px; + + svg { + width: 24px; + color: var(--color-blue); + fill: var(--color-blue); + } +} + +.Popover_filter_container { + background-color: var(--color-secondary); + border-radius: 6px; + border: 1px solid var(--color-medium-grey); + box-shadow: 0 3px 10px 5px var(--color-medium-grey); + padding: 20px 0 0; + overflow: scroll; + max-height: 50dvh; + width: fit-content; + + > div { + display: flex; + flex-flow: column wrap; + justify-content: center; + gap: 5px 10px 0; + width: 100%; + padding: 10px 0 0; + + .tag_item { + font-size: 14px; + border-bottom: 1px solid var(--color-medium-grey); + width: 100%; + padding: 5px 10px 5px 5px; + margin: 0; + + &:hover { + cursor: pointer; + background-color: var(--color-light-blue); + } + } + } + + .resetFilter { + margin: auto; + + svg { + width: 20px; + color: var(--color-blue); + fill: var(--color-blue); + } + + &:hover svg { + color: var(--color-error-dark); + fill: var(--color-error-dark); + } + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/components/tags.scss.d.ts b/src/renderer/assets/styles/components/tags.scss.d.ts new file mode 100644 index 000000000..8ff7ea355 --- /dev/null +++ b/src/renderer/assets/styles/components/tags.scss.d.ts @@ -0,0 +1,10 @@ +export declare const ___DEBUG___COMPONENTS_TAGS_CSS: string; +export declare const allPub_tagsTrigger: string; +export declare const no_hover: string; +export declare const Popover_delete_tag: string; +export declare const Popover_filter_container: string; +export declare const resetFilter: string; +export declare const tag: string; +export declare const tag_inputs: string; +export declare const tag_item: string; +export declare const tags_wrapper: string; diff --git a/src/renderer/assets/styles/components/toasts.css.d.ts b/src/renderer/assets/styles/components/toasts.css.d.ts deleted file mode 100644 index f922bf242..000000000 --- a/src/renderer/assets/styles/components/toasts.css.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare const styles: { - readonly "___DEBUG___COMPONENTS_TOASTS_CSS": string; - readonly "closeButton": string; - readonly "error": string; - readonly "icon": string; - readonly "leave": string; - readonly "start": string; - readonly "success": string; - readonly "toRemove": string; - readonly "toast": string; - readonly "toasts_wrapper": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/components/toasts.css b/src/renderer/assets/styles/components/toasts.scss similarity index 52% rename from src/renderer/assets/styles/components/toasts.css rename to src/renderer/assets/styles/components/toasts.scss index 179b50343..01e504bf1 100644 --- a/src/renderer/assets/styles/components/toasts.css +++ b/src/renderer/assets/styles/components/toasts.scss @@ -1,11 +1,11 @@ /* -=-=-= components/toasts.css +=-=-= toasts.scss */ .toasts_wrapper { position: fixed; - bottom: 1rem; - left: 0; + bottom: 2rem; + left: 1rem; z-index: 10000; } @@ -14,55 +14,76 @@ margin-bottom: 1rem; position: relative; padding: 1rem; - border: 1px grey solid; - border-left: none; - border-top-right-radius: 0.5em; - border-bottom-right-radius: 0.5em; - width: 20rem; - height: 4.125rem; + border: 1px #0B8454 solid; + border-radius: 6px; + width: 15rem; + height: fit-content; background: white; display: flex; align-items: center; animation-name: start; animation-duration: 0.5s; + opacity: 0.9; + transition: 300ms ease-in-out; &:focus-within { border-width: 4px; } &.error { - background: #fedbd8; + background: var(--color-error); + border-color: var(--color-primary); + + .closeButton svg { + fill: var(--color-primary); + } } &.success { - background: #f0fed8; + background: var(--color-success); + + // @media (prefers-color-scheme: dark){ + // background-color: #111d19; + // } } - & p { + p { margin: 0; flex: 1; padding-right: 1em; overflow: hidden; user-select: text; + text-overflow: ellipsis; + width: 100%; + height: 100%; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 4; + color: var(--color-primary); } - & .icon { + .toast_open { + -webkit-line-clamp: unset; + } + + .icon { height: 3rem; margin-right: 1rem; } - & .closeButton { + .closeButton { position: absolute; right: 0; top: 0; - height: 1.3rem; - width: 1.3rem; - padding: 0; - margin: 3px; - - & svg { - height: 100%; - width: 100%; + height: 25px; + width: 25px; + padding: 5px; + box-sizing: content-box; + + svg { + height: 20px; + width: 20px; + fill: #0B8454; } } } diff --git a/src/renderer/assets/styles/components/toasts.scss.d.ts b/src/renderer/assets/styles/components/toasts.scss.d.ts new file mode 100644 index 000000000..f38f1dacd --- /dev/null +++ b/src/renderer/assets/styles/components/toasts.scss.d.ts @@ -0,0 +1,11 @@ +export declare const ___DEBUG___COMPONENTS_TOASTS_CSS: string; +export declare const closeButton: string; +export declare const error: string; +export declare const icon: string; +export declare const leave: string; +export declare const start: string; +export declare const success: string; +export declare const toast: string; +export declare const toast_open: string; +export declare const toasts_wrapper: string; +export declare const toRemove: string; diff --git a/src/renderer/assets/styles/focus-mixin.css b/src/renderer/assets/styles/focus-mixin.css deleted file mode 100644 index 6f964c0b0..000000000 --- a/src/renderer/assets/styles/focus-mixin.css +++ /dev/null @@ -1,14 +0,0 @@ -/* -=-=-= focus-mixin.css -*/ - -@define-mixin R2_MIXIN_FOCUS_OUTLINE { - outline-color: blue !important; - outline-style: solid !important; - outline-width: 2px !important; - outline-offset: -2px; -} - -.___DEBUG___FOCUS_MIXIN_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/focus-mixin.css.d.ts b/src/renderer/assets/styles/focus-mixin.css.d.ts deleted file mode 100644 index f91e7ed92..000000000 --- a/src/renderer/assets/styles/focus-mixin.css.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare const styles: { - readonly "___DEBUG___FOCUS_MIXIN_CSS": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/focus.css.d.ts b/src/renderer/assets/styles/focus.css.d.ts deleted file mode 100644 index af1452f05..000000000 --- a/src/renderer/assets/styles/focus.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare const styles: { - readonly "R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE": string; - readonly "R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE": string; - readonly "R2_CSS_CLASS__KEYBOARD_INTERACT": string; - readonly "___DEBUG___FOCUS_CSS": string; - readonly "body_element": string; - readonly "readium2ElectronAnimation_TARGET": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/focus.css b/src/renderer/assets/styles/focus.scss similarity index 77% rename from src/renderer/assets/styles/focus.css rename to src/renderer/assets/styles/focus.scss index 05cad3c7f..eb5e83d41 100644 --- a/src/renderer/assets/styles/focus.css +++ b/src/renderer/assets/styles/focus.scss @@ -1,11 +1,11 @@ -/* -=-=-= focus.css => './focus-mixin.css' -*/ -@import url('./focus-mixin.css'); +@mixin R2_MIXIN_FOCUS_OUTLINE { + outline: var(--color-blue) solid 2px !important; + outline-offset: -2px; +} -/* -=-=-= focus.css -*/ +.___DEBUG___FOCUS_MIXIN_CSS { + display: none; +} :root *:focus { outline: none; @@ -20,7 +20,7 @@ /* :global */ :root.R2_CSS_CLASS__KEYBOARD_INTERACT *:focus { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } /* :global */ @@ -36,9 +36,7 @@ } :root *:target { - outline-color: green !important; - outline-style: solid !important; - outline-width: 2px !important; + outline: green solid 2px !important; outline-offset: 0; animation-name: readium2ElectronAnimation_TARGET; animation-duration: 3s; diff --git a/src/renderer/assets/styles/focus.scss.d.ts b/src/renderer/assets/styles/focus.scss.d.ts new file mode 100644 index 000000000..e677dcc87 --- /dev/null +++ b/src/renderer/assets/styles/focus.scss.d.ts @@ -0,0 +1,7 @@ +export declare const ___DEBUG___FOCUS_CSS: string; +export declare const ___DEBUG___FOCUS_MIXIN_CSS: string; +export declare const body_element: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; +export declare const R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE: string; +export declare const R2_CSS_CLASS__KEYBOARD_INTERACT: string; +export declare const readium2ElectronAnimation_TARGET: string; diff --git a/src/renderer/assets/styles/global.css b/src/renderer/assets/styles/global.css deleted file mode 100644 index 522573d09..000000000 --- a/src/renderer/assets/styles/global.css +++ /dev/null @@ -1,333 +0,0 @@ -/* -=-=-= global.css => './partials/mixins.css' -*/ -@import url('./partials/mixins.css'); - -/* -=-=-= global.css => './partials/focus.css' -*/ -@import url('./partials/focus.css'); - -/* -=-=-= global.css => './components/blocks.css' -*/ - -/* -@import__ './components/blocks.css'; -*/ - -/* -=-=-= global.css => './components/buttons.css' -*/ - -/* -@import__ './components/buttons.css'; -*/ - -/* -=-=-= global.css => './components/breadcrumb.css' -*/ - -/* -@import__ './components/breadcrumb.css'; -*/ - -/* -=-=-= global.css => './components/columns.css' -*/ - -/* -@import__ './components/columns.css'; -*/ - -/* -=-=-= global.css => './components/dropdown.css' -*/ - -/* -@import__ './components/dropdown.css'; -*/ - -/* -=-=-= global.css => './components/grids.css' -*/ - -/* -@import__ './components/grids.css'; -*/ - -/* -=-=-= global.css => './components/images.css' -*/ - -/* -@import__ './components/images.css'; -*/ - -/* -=-=-= global.css => './components/inputs.css' -*/ - -/* -@import__ './components/inputs.css'; -*/ - -/* -=-=-= global.css => './components/modals.css' -*/ - -/* -@import__ './components/modals.css'; -*/ - -/* -=-=-= global.css => './components/publications.css' -*/ - -/* -@import__ './components/publications.css'; -*/ - -/* -=-=-= global.css => './components/slider.css' -*/ - -/* -@import__ './components/slider.css'; -*/ - -/* -=-=-= global.css => './components/tags.css' -*/ - -/* -@import__ './components/tags.css'; -*/ - -/* -=-=-= global.css => './components/toasts.css' -*/ - -/* -@import__ './components/toasts.css'; -*/ - -/* -=-=-= global.css -*/ - -/* ============ GLOBAL ELEMENTS =============== */ - -:root { - user-select: none; - color: var(--color-primary); -} - -*, -*::after, -*::before { - -webkit-user-drag: none; - -webkit-app-region: no-drag; -} - -body { - margin: 0; - padding: 0; - width: 100%; - font: 1.1rem "Open Sans", sans-serif; - background: var(--color-secondary); -} - -section { - margin-bottom: 40px; -} - -.main { - width: calc(100% - 120px); - padding: 30px 60px; - overflow-y: auto; - position: absolute; - bottom: 0; - left: 0; - right: 0; - top: 57px; -} - -nav + nav + .main { - top: 123px; -} - -nav + nav + .breadcrumb + .main { - top: 181px; -} - -table > * { - background-color: var(--color-light-grey); - color: black !important; -} - -table tr td { - border-bottom: 1px solid black; -} - -/* ============== FAST CLASS ================= */ - -.anchor_link { - position: absolute; - display: block; - width: 1px; - height: 1px; - top: 0; - left: 0; - opacity: 0.6; - background: transparent; - overflow: hidden; - color: transparent; - padding: 0; - margin: 0; -} - -.rotate180 { - transform: rotate(180deg); -} - -.fw_bold { - font-weight: 700; -} - -.text_right { - text-align: right; -} - -.p_0 { - padding: 0; -} - -.m_0 { - margin: 0; -} - -.mr_10 { - margin-right: 10px; -} - -.mt_10 { - margin-top: 10px; -} - -.mt_30 { - margin-top: 30px; -} - -.mb_20 { - margin-bottom: 20px; -} - -.mb_30 { - margin-bottom: 30px; -} - -.my_10 { - margin-top: 10px; - margin-bottom: 10px; -} - -.w_50 { - width: 50%; -} - -.color_red { - color: red; -} - -.d_none { - display: none; -} - -.d_flex, -.justify_content_between, -.align_items_center, -.flex_wrap { - display: flex; -} - -.justify_content_between { - justify-content: space-between; -} - -.align_items_center { - align-items: center; -} - -.flex_wrap { - flex-wrap: wrap; -} - -.flex_none { - flex: none; -} - -.flex_1 { - flex: 1; -} - -.text_center { - text-align: center; -} - -.visibility_visible { - visibility: visible; -} - -.visibility_hidden { - visibility: hidden; -} - -/* ============== NAVIGATION ================= */ - -.heading { - display: flex; - justify-content: space-between; - align-items: center; - padding-bottom: 5px; - margin-bottom: 15px; - border-bottom: 3px solid var(--color-light-grey); - - & h2 { - position: relative; - font-weight: 700; - margin: 0; - font-size: 1.5rem; - } - - & h3 { - position: relative; - font-weight: 700; - margin: 0; - font-size: 1.27rem; - } -} - -.heading_link a { - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 3px solid var(--color-light-grey); - position: relative; - font-weight: 700; - margin: 0 0 20px 0; - font-size: 1.5rem; - border-radius: 5px 5px 0 0; - padding: 10px 0 5px 0; - text-decoration: none; -} - -/* List: ul / ol / li */ - -li.no_list_style { - list-style: none; -} - -.___DEBUG___GLOBAL_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/global.css.d.ts b/src/renderer/assets/styles/global.css.d.ts deleted file mode 100644 index 5ae65bb37..000000000 --- a/src/renderer/assets/styles/global.css.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -declare const styles: { - readonly "___DEBUG___GLOBAL_CSS": string; - readonly "align_items_center": string; - readonly "anchor_link": string; - readonly "breadcrumb": string; - readonly "color_red": string; - readonly "d_flex": string; - readonly "d_none": string; - readonly "flex_1": string; - readonly "flex_none": string; - readonly "flex_wrap": string; - readonly "fw_bold": string; - readonly "heading": string; - readonly "heading_link": string; - readonly "justify_content_between": string; - readonly "m_0": string; - readonly "main": string; - readonly "mb_20": string; - readonly "mb_30": string; - readonly "mr_10": string; - readonly "mt_10": string; - readonly "mt_30": string; - readonly "my_10": string; - readonly "no_list_style": string; - readonly "p_0": string; - readonly "rotate180": string; - readonly "text_center": string; - readonly "text_right": string; - readonly "visibility_hidden": string; - readonly "visibility_visible": string; - readonly "w_50": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/global.scss b/src/renderer/assets/styles/global.scss index b81448062..792348633 100644 --- a/src/renderer/assets/styles/global.scss +++ b/src/renderer/assets/styles/global.scss @@ -1,5 +1,434 @@ +/*** be careful this file is imported in library and reader windows ***/ + +/* +=-=-= global.scss +*/ + +@import 'src/renderer/assets/styles/partials/mixin'; +@import 'src/renderer/assets/styles/partials/focus'; + +/* ============ GLOBAL ELEMENTS =============== */ + .__LOAD_FILE_SELECTOR_NOT_USED_JUST_TO_TRIGGER_WEBPACK_SCSS_FILE__ { display: none; } -/*** be careful this file is imported in library and reader windows ***/ +:root { + user-select: none; + color: var(--color-primary); +} + +*, +*::after, +*::before { + -webkit-user-drag: none; + -webkit-app-region: no-drag; +} + +body { + margin: 0; + padding: 0; + width: 100%; + font: 12px Nunito, sans-serif; + background: var(--color-secondary); + + &[data-theme="dark"] { + .modal_dialog { + box-shadow: 0 0 5px 2px black; + } + } + + @media (prefers-color-scheme: dark) { + .modal_dialog { + box-shadow: 0 0 5px 2px black; + } + } +} + +input { + font-family: Nunito, sans-serif; +} + +p, input, select { + font-size: 12px; +} + +h1 { + font-size: 24px; +} + +h2 { + font-size: 20px; +} + +h3 { + font-size: 16px; +} + +h4, button, label { + font-size: 14px; +} + +section { + margin-bottom: 20px; +} + +.main { + width: calc(100% - 120px); + padding: 10px 30px; + overflow-y: scroll; + flex: 6; + height: 100vh; + box-sizing: border-box; + position: relative; + color: var(--color-primary); + + &:has(.footer_wrapper) { + padding-bottom: 40px; + } + + &::-webkit-scrollbar { + width: 12px; + transition: 200ms; + + &-thumb { + background-color: var(--scrollbar-thumb); + border-radius: 6px; + border-left: 2px solid transparent; + background-clip: padding-box; + cursor: pointer; + + &:hover { + border: 0; + } + + } + + &-track { + background-color: var(--color-secondary); + } + } +} + +nav + nav + .main { + top: 123px; +} + +nav + nav + .breadcrumb + .main { + top: 181px; +} + +/* ============== FAST CLASS ================= */ + +.anchor_link { + position: absolute; + display: block; + width: 1px; + height: 1px; + top: 0; + left: 0; + opacity: 0.6; + background: transparent; + overflow: hidden; + color: transparent; + padding: 0; + margin: 0; +} + +.rotate180 { + transform: rotate(180deg); +} + +.fw_bold { + font-weight: 700; +} + +.text_right { + text-align: right; +} + +.p_0 { + padding: 0; +} + +.m_0 { + margin: 0; +} + +.mr_10 { + margin-right: 10px; +} + +.mt_10 { + margin-top: 10px; +} + +.mt_30 { + margin-top: 30px; +} + +.mb_20 { + margin-bottom: 20px; +} + +.mb_30 { + margin-bottom: 30px; +} + +.my_10 { + margin-top: 10px; + margin-bottom: 10px; +} + +.w_50 { + width: 50%; +} + +.color_red { + color: var(--color-error-dark); +} + +.d_none { + display: none; +} + +.d_flex, +.justify_content_between, +.align_items_center, +.flex_wrap { + display: flex; +} + +.justify_content_between { + justify-content: space-between; +} + +.align_items_center { + align-items: center; +} + +.flex_wrap { + flex-wrap: wrap; +} + +.flex_none { + flex: none; +} + +.flex_1 { + flex: 1; +} + +.text_center { + text-align: center; +} + +.visibility_visible { + visibility: visible; +} + +.visibility_hidden { + visibility: hidden; +} + +/* ============== NAVIGATION ================= */ + +.heading { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 5px; + margin-bottom: 15px; + border-bottom: 3px solid var(--color-light-grey); + max-width: 250px; + + & h2 { + position: relative; + font-weight: 700; + margin: 0; + font-size: 1.5rem; + } + + & h3 { + position: relative; + font-weight: 700; + margin: 0; + font-size: 1.27rem; + } + + & button { + width: fit-content; + + & svg { + width: 15px; + } + } +} + +.heading_link:only-child { + font-style: italic; + + span { + color: var(--color-medium-grey); + } + + a { + cursor: not-allowed; + background-color: unset; + } +} + +.heading_link a { + display: flex; + // justify-content: space-between; + align-items: center; + border-bottom: 3px solid var(--color-light-grey); + position: relative; + font-weight: 700; + margin: 0 0 10px; + font-size: 20px; + border-radius: 5px 5px 0 0; + padding: 10px 0 5px; + text-decoration: none; +} + +.new_version { + background-color: var(--color-light-blue); + color: var(--color-primary); + font-size: 14px; + position: fixed; + bottom: 50px; + right: 55px; + width: calc(100% - 320px); + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 20px; + border: 1px solid var(--color-blue); + border-radius: 5px; + margin: 0; + + > div { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 5px; + } + + @media screen and (width <= 800px) { + width: calc(100% - 112px); + } + + svg { + fill: var(--color-blue); + color: var(--color-blue); + width: 16px; + } + + a { + padding: 0; + margin: 0; + font-size: 12px; + color: var(--color-primary); + + &:visited { + color: var(--color-primary); + } + } +} + +.noPublications{ + &_container { + position: absolute; + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + width: 500px; + height: 500px; + + @media screen and (width <= 1000px) { + width: 400px; + height: 400px; + } + + svg { + position: absolute; + top: 0; + } + + .emptyLibraryIcon { + top: 20px; + left: -20px; + } + } + + &_text { + transform: translateX(-50%); + position: absolute; + top: 320px; + left: 50%; + width: 100%; + text-align: center; + + @media screen and (width <= 1000px) { + top: 250px; + + details { + margin-bottom: 50px; + } + } + + .acceptedExtension { + display: flex; + flex-wrap: wrap; + max-width: 500px; + align-items: center; + justify-content: center; + + span { + display: flex; + align-items: center; + margin: 0 5px; + height: 30px; + } + } + + p { + font-size: 16px; + } + + strong { + font-size: 30px; + } + + details { + .summary_content { + border: 1px solid var(--color-blue); + border-radius: 10px; + background-color: var(--color-secondary); + padding: 20px; + } + + summary { + color: var(--color-blue); + margin-bottom: 40px; + } + + p { + font-size: 14px; + width: fit-content; + } + } + } +} + +/* List: ul / ol / li */ + +li.no_list_style { + list-style: none; +} + +.___DEBUG___GLOBAL_CSS { + display: none; +} + diff --git a/src/renderer/assets/styles/global.scss.d.ts b/src/renderer/assets/styles/global.scss.d.ts index 7bd8fa498..da326895d 100644 --- a/src/renderer/assets/styles/global.scss.d.ts +++ b/src/renderer/assets/styles/global.scss.d.ts @@ -1 +1,46 @@ +export declare const ___DEBUG___GLOBAL_CSS: string; +export declare const ___DEBUG___PARTIALS_FOCUS_CSS: string; +export declare const ___DEBUG___PARTIALS_MIXINS_CSS: string; export declare const __LOAD_FILE_SELECTOR_NOT_USED_JUST_TO_TRIGGER_WEBPACK_SCSS_FILE__: string; +export declare const acceptedExtension: string; +export declare const align_items_center: string; +export declare const anchor_link: string; +export declare const body_element: string; +export declare const breadcrumb: string; +export declare const color_red: string; +export declare const d_flex: string; +export declare const d_none: string; +export declare const emptyLibraryIcon: string; +export declare const flex_1: string; +export declare const flex_none: string; +export declare const flex_wrap: string; +export declare const footer_wrapper: string; +export declare const fw_bold: string; +export declare const heading: string; +export declare const heading_link: string; +export declare const justify_content_between: string; +export declare const m_0: string; +export declare const main: string; +export declare const mb_20: string; +export declare const mb_30: string; +export declare const modal_dialog: string; +export declare const mr_10: string; +export declare const mt_10: string; +export declare const mt_30: string; +export declare const my_10: string; +export declare const new_version: string; +export declare const no_list_style: string; +export declare const noPublications_container: string; +export declare const noPublications_text: string; +export declare const p_0: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; +export declare const R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE: string; +export declare const R2_CSS_CLASS__KEYBOARD_INTERACT: string; +export declare const readium2ElectronAnimation_TARGET: string; +export declare const rotate180: string; +export declare const summary_content: string; +export declare const text_center: string; +export declare const text_right: string; +export declare const visibility_hidden: string; +export declare const visibility_visible: string; +export declare const w_50: string; diff --git a/src/renderer/assets/styles/header.css b/src/renderer/assets/styles/header.css deleted file mode 100644 index 5cf63c162..000000000 --- a/src/renderer/assets/styles/header.css +++ /dev/null @@ -1,150 +0,0 @@ -/* -=-=-= header.css => './partials/mixins.css' -*/ -@import url('./partials/mixins.css'); - -/* -=-=-= header.css => './partials/variables.css' -*/ - -/* -@import url('./partials/variables.css'); -*/ - -/* -=-=-= header.css -*/ - -.main_navigation_library { - position: fixed; - - @mixin main_navigation_library; - - & ul { - padding-left: 60px; - padding-right: 60px; - margin: 0; - - & a { - text-decoration: none; - color: inherit; - padding: 1.125rem 0.3125rem; - } - - & li { - display: inline-block; - padding-bottom: 18px; - padding-top: 18px; - font-weight: 600; - color: var(--color-disabled); - cursor: pointer; - margin-right: 60px; - - &.active { - color: var(--color-primary); - border-bottom: 3px solid var(--color-primary); - padding-bottom: 15px; - } - } - } -} - -.preferences { - position: relative; - float: right; -} - -/* ============ SECONDARY NAVIGATION =============== */ - -.nav_secondary { - display: flex; - flex-direction: row; - align-items: center; - border-bottom: 1px solid var(--color-light-grey); - background-color: var(--color-secondary); - position: fixed; - left: 0; - width: calc(100% - 120px); - height: 3.5rem; - padding: 5px 60px; - z-index: 101; - top: 57px; - min-width: 600px; - padding-left: 60px; - padding-right: 60px; - - & form { - display: inline-block; - border-bottom: 1px solid #c1c1c1; - margin-left: 40px; - height: auto; - } - - & input[type=search] { - position: relative; - width: 225px; - border-radius: 0; - border: none; - height: 35px; - background-color: transparent; - color: var(--color-primary); - font-size: 0.9rem; - } - - & input[type=search]::placeholder { - font-size: 0.9rem; - font-weight: 300; - color: #c1c1c1; - } - - & form button { - position: relative; - top: 10px; - height: 38px; - width: 36px; - background-color: transparent; - } - - & form[role="search"] { - margin: 0 30px; - flex: 1; - - & input { - width: 100% !important; - } - } -} - -.nav_secondary svg { - display: inline-block; - position: relative; - width: 35px; - height: 35px; -} - -.nav_secondary svg:nth-child(2) { - margin-left: 20px; -} - -.skip_link { - position: absolute; - left: -2000px; - - &:focus { - left: unset; - left: 0; - width: fit-content; - top: 0; - opacity: 1; - height: unset; - z-index: 150; - font-size: 1rem; - padding: 1rem; - color: white; - background-color: #0366d6; - } -} - -.___DEBUG___HEADER_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/header.css.d.ts b/src/renderer/assets/styles/header.css.d.ts deleted file mode 100644 index 3d9e64f57..000000000 --- a/src/renderer/assets/styles/header.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare const styles: { - readonly "___DEBUG___HEADER_CSS": string; - readonly "active": string; - readonly "main_navigation_library": string; - readonly "nav_secondary": string; - readonly "preferences": string; - readonly "skip_link": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/header.scss b/src/renderer/assets/styles/header.scss new file mode 100644 index 000000000..d9227631d --- /dev/null +++ b/src/renderer/assets/styles/header.scss @@ -0,0 +1,199 @@ +/* +=-=-= header.scss +*/ + +.main_navigation_library { + top: 0; + padding-top: 0; + padding-bottom: 0; + height: 100vh; + background-color: var(--color-extralight-grey); + max-width: 204px; + border-right: 2px solid var(--color-light-grey); + flex: 1; + transition: 200ms linear; + + @media screen and (width <= 800px) { + width: fit-content; + flex: unset; + + ul { + padding: 10px!important; + width: 50px; + } + + h3 { + display: none; + } + + ul a, ul button { + min-width: unset!important; + } + + svg { + padding: 5px; + } + } + + & ul { + margin: 0; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 30px 20px; + height: calc(100% - 60px); + + & button { + font-family: Nunito, sans-serif; + text-align: start; + height: auto; + } + + & a, & button { + text-decoration: none; + color: var(--color-primary); + min-width: 150px; + justify-content: start; + align-items: center; + gap: 10px; + display: flex; + padding: 5px; + + &[aria-pressed="true"] { + color: inherit; + } + + h3 { + margin: 0; + } + } + + & li { + padding-bottom: 10px; + padding-top: 10px; + font-weight: 600; + color: var(--color-disabled); + cursor: pointer; + border: 1px solid transparent; + height: 30px; + border-radius: 4px; + background-color: transparent; + display: flex; + align-items: center; + justify-content: start; + + @media screen and (width <= 800px) { + justify-content: center; + } + + svg { + width: 15px; + height: 15px; + fill: var(--color-blue); + color: var(--color-blue); + } + + &.active { + color: var(--color-blue); + } + } + } +} + +.preferences { + position: relative; + float: right; +} + +/* ============ SECONDARY NAVIGATION =============== */ + +.nav_secondary { + display: flex; + flex-direction: row; + align-items: end; + justify-content: space-between; + border-bottom: 1px solid var(--color-light-grey); + background-color: var(--color-secondary); + z-index: 101; + gap: 10px; + padding-bottom: 30px; + + h3 { + margin: 5px 0; + } + + & form { + display: inline-block; + border-bottom: 1px solid #c1c1c1; + margin-left: 40px; + height: auto; + } + + & input[type="search"] { + position: relative; + width: 225px; + border-radius: 0; + border: none; + height: 35px; + background-color: transparent; + color: var(--color-primary); + font-size: 0.9rem; + } + + & input[type="search"]::placeholder { + font-size: 0.9rem; + font-weight: 300; + color: #c1c1c1; + } + + & form button { + position: relative; + top: 10px; + height: 38px; + width: 36px; + background-color: transparent; + } + + & form[role="search"] { + margin: 0 30px; + flex: 1; + + & input { + width: 100% !important; + } + } +} + +.nav_secondary svg { + display: inline-block; + position: relative; + width: 35px; + height: 35px; +} + +.nav_secondary svg:nth-child(2) { + margin-left: 20px; +} + +.skip_link { + position: absolute; + left: -2000px; + + &:focus { + left: unset; + left: 0; + width: fit-content; + top: 0; + opacity: 1; + height: unset; + z-index: 150; + font-size: 1rem; + padding: 1rem; + color: white; + background-color: #0366d6; + } +} + +.___DEBUG___HEADER_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/header.scss.d.ts b/src/renderer/assets/styles/header.scss.d.ts new file mode 100644 index 000000000..4395c9c2e --- /dev/null +++ b/src/renderer/assets/styles/header.scss.d.ts @@ -0,0 +1,6 @@ +export declare const ___DEBUG___HEADER_CSS: string; +export declare const active: string; +export declare const main_navigation_library: string; +export declare const nav_secondary: string; +export declare const preferences: string; +export declare const skip_link: string; diff --git a/src/renderer/assets/styles/loader.css b/src/renderer/assets/styles/loader.css deleted file mode 100644 index 378998e78..000000000 --- a/src/renderer/assets/styles/loader.css +++ /dev/null @@ -1,31 +0,0 @@ -/* -=-=-= loader.css -*/ - -.loader { - text-align: center; - - & svg { - width: 5rem; - } -} - -.loader_small { - position: absolute; - top: 10px; - right: 10px; - z-index: 999; - - & svg { - width: 2rem; - } -} - -.loader_search_picker { - width: 24px; - align-self: center; -} - -.___DEBUG___LOADER_CSS { - display: none; -} diff --git a/src/renderer/assets/styles/loader.css.d.ts b/src/renderer/assets/styles/loader.css.d.ts deleted file mode 100644 index 341ce908d..000000000 --- a/src/renderer/assets/styles/loader.css.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare const styles: { - readonly "___DEBUG___LOADER_CSS": string; - readonly "loader": string; - readonly "loader_search_picker": string; - readonly "loader_small": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/loader.scss b/src/renderer/assets/styles/loader.scss new file mode 100644 index 000000000..bf4313a03 --- /dev/null +++ b/src/renderer/assets/styles/loader.scss @@ -0,0 +1,33 @@ +/* +=-=-= loader.scss +*/ + +.loader { + text-align: center; + + svg { + width: 5rem; + } + + &_small { + position: absolute; + top: 5px; + right: 10px; + z-index: 999; + + & svg { + width: 2rem; + } + } + + &_search_picker { + width: 15px; + position: absolute; + left: 5px; + top: 6px; + } +} + +.___DEBUG___LOADER_CSS { + display: none; +} diff --git a/src/renderer/assets/styles/loader.scss.d.ts b/src/renderer/assets/styles/loader.scss.d.ts new file mode 100644 index 000000000..1ade6f990 --- /dev/null +++ b/src/renderer/assets/styles/loader.scss.d.ts @@ -0,0 +1,4 @@ +export declare const ___DEBUG___LOADER_CSS: string; +export declare const loader: string; +export declare const loader_search_picker: string; +export declare const loader_small: string; diff --git a/src/renderer/assets/styles/partials/_screenSizes.scss b/src/renderer/assets/styles/partials/_screenSizes.scss deleted file mode 100644 index 28de49743..000000000 --- a/src/renderer/assets/styles/partials/_screenSizes.scss +++ /dev/null @@ -1,3 +0,0 @@ -$laptop : 992px; -$large : 1200px; -$tablet : 768px; diff --git a/src/renderer/assets/styles/partials/focus.css.d.ts b/src/renderer/assets/styles/partials/focus.css.d.ts deleted file mode 100644 index 7cb8f22dd..000000000 --- a/src/renderer/assets/styles/partials/focus.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare const styles: { - readonly "R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE": string; - readonly "R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE": string; - readonly "R2_CSS_CLASS__KEYBOARD_INTERACT": string; - readonly "___DEBUG___PARTIALS_FOCUS_CSS": string; - readonly "body_element": string; - readonly "readium2ElectronAnimation_TARGET": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/partials/focus.css b/src/renderer/assets/styles/partials/focus.scss similarity index 76% rename from src/renderer/assets/styles/partials/focus.css rename to src/renderer/assets/styles/partials/focus.scss index d95773d4f..59ca7fea0 100644 --- a/src/renderer/assets/styles/partials/focus.css +++ b/src/renderer/assets/styles/partials/focus.scss @@ -1,20 +1,11 @@ -/* -=-=-= partials/focus.css => './mixins.css' -*/ -@import url('./mixins.css'); - -/* -=-=-= partials/focus.css -*/ +@import "src/renderer/assets/styles/partials/mixin"; :root *:focus { outline: none; } :root *:target { - outline-color: green !important; - outline-style: solid !important; - outline-width: 2px !important; + outline: green solid 2px !important; outline-offset: 0; animation-name: readium2ElectronAnimation_TARGET; animation-duration: 3s; @@ -32,7 +23,7 @@ /* :global */ :root.R2_CSS_CLASS__KEYBOARD_INTERACT *:focus { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } /* :global */ diff --git a/src/renderer/assets/styles/partials/focus.scss.d.ts b/src/renderer/assets/styles/partials/focus.scss.d.ts new file mode 100644 index 000000000..6755ab180 --- /dev/null +++ b/src/renderer/assets/styles/partials/focus.scss.d.ts @@ -0,0 +1,7 @@ +export declare const ___DEBUG___PARTIALS_FOCUS_CSS: string; +export declare const ___DEBUG___PARTIALS_MIXINS_CSS: string; +export declare const body_element: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; +export declare const R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE: string; +export declare const R2_CSS_CLASS__KEYBOARD_INTERACT: string; +export declare const readium2ElectronAnimation_TARGET: string; diff --git a/src/renderer/assets/styles/partials/mixins.css b/src/renderer/assets/styles/partials/mixin.scss similarity index 56% rename from src/renderer/assets/styles/partials/mixins.css rename to src/renderer/assets/styles/partials/mixin.scss index fd8f2c448..027118b01 100644 --- a/src/renderer/assets/styles/partials/mixins.css +++ b/src/renderer/assets/styles/partials/mixin.scss @@ -1,16 +1,4 @@ -/* -=-=-= mixins.css => './variables.css' -*/ - -/* -@import url('./variables.css'); -*/ - -/* -=-=-= partials/mixins.css -*/ - -@define-mixin main_navigation_library { +@mixin main_navigation_library { z-index: 102; width: 100%; top: 0; @@ -18,11 +6,11 @@ padding-bottom: 0; height: auto; background-color: var(--color-secondary); - box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.19); + box-shadow: 0 0 15px 0 rgb(0 0 0 / 19%); min-width: 600px; } -@define-mixin button_primary { +@mixin button_primary { position: relative; display: inline; border: 1px solid var(--color-primary); @@ -37,15 +25,13 @@ transition: all 0.2s; flex: none; - &:hover { - background: rgba(0, 0, 0, 0.05); + :hover { + background: rgb(0 0 0 / 5%); } } -@define-mixin R2_MIXIN_FOCUS_OUTLINE { - outline-color: blue !important; - outline-style: solid !important; - outline-width: 2px !important; +@mixin R2_MIXIN_FOCUS_OUTLINE { + outline: var(--color-blue) solid 2px !important; outline-offset: -2px; } diff --git a/src/renderer/assets/styles/partials/mixin.scss.d.ts b/src/renderer/assets/styles/partials/mixin.scss.d.ts new file mode 100644 index 000000000..b534f829b --- /dev/null +++ b/src/renderer/assets/styles/partials/mixin.scss.d.ts @@ -0,0 +1 @@ +export declare const ___DEBUG___PARTIALS_MIXINS_CSS: string; diff --git a/src/renderer/assets/styles/partials/mixins.css.d.ts b/src/renderer/assets/styles/partials/mixins.css.d.ts deleted file mode 100644 index acc1dbe60..000000000 --- a/src/renderer/assets/styles/partials/mixins.css.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare const styles: { - readonly "___DEBUG___PARTIALS_MIXINS_CSS": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/partials/variables.css b/src/renderer/assets/styles/partials/variables.css deleted file mode 100644 index 9de392aff..000000000 --- a/src/renderer/assets/styles/partials/variables.css +++ /dev/null @@ -1,37 +0,0 @@ -/* -=-=-= partials/variables.css -*/ - -@media (prefers-color-scheme: light) { - :root { - /* Colors */ - --color-primary: #4d4d4d; - --color-secondary: #fff; - --color-tertiary: #67a3e0; - --color-disabled: #b7b7b7; - --color-light-grey: #f1f1f1; - --color-medium-grey: #e5e5e5; - --color-accent: rgb(0, 188, 212); - --color-accent-contrast: #fff; - --reader-fontColor: #000; - } -} - -@media (prefers-color-scheme: dark) { - :root { - /* Colors */ - --color-primary: #fff; - --color-secondary: #4d4d4d; - --color-tertiary: #67a3e0; - --color-disabled: #b7b7b7; - --color-light-grey: #f1f1f1; - --color-medium-grey: #e5e5e5; - --color-accent: rgb(0, 188, 212); - --color-accent-contrast: #fff; - --reader-fontColor: #fff; - } -} - -.___DEBUG___PARTIALS_VARIABLES_CSS { - display: none; -} \ No newline at end of file diff --git a/src/renderer/assets/styles/partials/variables.css.d.ts b/src/renderer/assets/styles/partials/variables.css.d.ts deleted file mode 100644 index b851dba59..000000000 --- a/src/renderer/assets/styles/partials/variables.css.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare const styles: { - readonly "___DEBUG___PARTIALS_VARIABLES_CSS": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/partials/variables.css.map b/src/renderer/assets/styles/partials/variables.css.map deleted file mode 100644 index 900632bde..000000000 --- a/src/renderer/assets/styles/partials/variables.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sourceRoot":"","sources":["variables.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAGA;EACE;AACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;AAIJ;EACE;AACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;AAIJ;EACE","file":"variables.css"} \ No newline at end of file diff --git a/src/renderer/assets/styles/partials/variables.scss b/src/renderer/assets/styles/partials/variables.scss index 8126d4b5f..9ad33ac79 100644 --- a/src/renderer/assets/styles/partials/variables.scss +++ b/src/renderer/assets/styles/partials/variables.scss @@ -1,59 +1,56 @@ -/* -=-=-= partials/variables.css -=-=-= globally imported by sass-loader with : { additionalData: `@import "./src/renderer/assets/styles/partials/variables.scss";` } -*/ - @use "sass:map"; $color-palette: ( light: ( --color-primary: #4d4d4d, --color-secondary: #fff, - --color-tertiary: #67a3e0, - --color-disabled: #040303, + --color-blue: #1053C8, + --color-light-blue: #ECF2FD, + --color-extralight-grey: #f5f5f5, --color-light-grey: #f1f1f1, --color-medium-grey: #e5e5e5, - --color-accent: rgb(0, 188, 212), + --color-accent: #00BCD4, --color-accent-contrast: #fff, --reader-fontColor: #000, - --color-button-primary: rgba(16, 83, 200, 1), - --color-button-secondary: rgba(16, 83, 200, 0.05), - --color-bg-tab: rgba(246, 246, 246, 0.84), - --setting-btn-primary: #3a00e5, - --setting-btn-secondary: #f7f5ff, + --scrollbar-thumb: #98989d, + --color-disabled: #61646B, + --color-error: #fedbd8, + --color-error-dark: red, + --color-success: #ECFEF7, ), dark: ( - --color-primary: #4d4d4d, - --color-secondary: #fff, + --color-primary: #e7eaf8, + --color-secondary: #121212, + --color-blue: #99A9E3, + --color-light-blue: #2D2D2D, + --color-extralight-grey: #27272a, + --color-light-grey: #48484b, + --color-medium-grey: #7c7d86, + --color-accent: #00BCD4, + --color-accent-contrast: #fff, + --reader-fontColor: #000, + --scrollbar-thumb: #98989d, + --color-disabled: #a7a9b3, + --color-error: #4f1d1d, + --color-error-dark: #F590A9, + --color-success: #121d19, + + /* + --color-primary: #fff, + --color-secondary: #4d4d4d, --color-tertiary: #67a3e0, - --color-disabled: #040303, + --color-disabled: #b7b7b7, --color-light-grey: #f1f1f1, --color-medium-grey: #e5e5e5, --color-accent: rgb(0, 188, 212), --color-accent-contrast: #fff, - --reader-fontColor: #000, - --color-button-primary: rgba(16, 83, 200, 1), - --color-button-secondary: rgba(16, 83, 200, 0.05), - --color-bg-tab: rgba(246, 246, 246, 0.84), - --setting-btn-primary: #3a00e5, - --setting-btn-secondary: #f7f5ff, - - // disable in develop branch, TODO improve darkmode color - // --color-primary: #fff, - // --color-secondary: #4d4d4d, - // --color-tertiary: #67a3e0, - // --color-disabled: #b7b7b7, - // --color-light-grey: #f1f1f1, - // --color-medium-grey: #e5e5e5, - // --color-accent: rgb(0, 188, 212), - // --color-accent-contrast: #fff, - // --reader-fontColor: #fff, - // --color-button-primary: rgba(16, 83, 200, 1), - // --color-button-secondary: rgba(16, 83, 200, 0.05), - // --color-bg-tab: rgba(16, 18, 22, 0.6), - // --setting-btn-primary: #fff, - // --setting-btn-secondary: var(--color-secondary), - + --reader-fontColor: #fff, + --color-blue: rgba(16, 83, 200, 1), + --color-light-blue: rgba(236, 242, 253, 1), + --color-bg-tab: rgba(16, 18, 22, 0.6), + --setting-btn-primary: #fff, + --setting-btn-secondary: var(--color-secondary), + */ ), ); diff --git a/src/renderer/assets/styles/publicationInfos.scss b/src/renderer/assets/styles/publicationInfos.scss new file mode 100644 index 000000000..bca1b98b6 --- /dev/null +++ b/src/renderer/assets/styles/publicationInfos.scss @@ -0,0 +1,310 @@ +/* +=-=-= publicationInfo.scss +*/ + +.publicationInfo_container { + display: flex; + margin-left: -15px; + margin-right: -15px; + flex-direction: row; + align-items: flex-start; + + button { + font-weight: 400; + transition: 200ms linear; + } + + svg { + width: 14px; + height: 14px; + } + + .corner svg { + width: 20px; + height: 20px; + top: -35px; + right: -5px; + } + + section { + margin-bottom: 20px; + + .form_group svg { + position: absolute; + left: 10px; + width: 16px; + top: 8px; + } + } + + .button_primary { + border: 1px solid var(--color-blue); + height: 25px; + border-radius: 4px; + padding: 4px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--color-blue); + color: white; + + svg { + fill: var(--color-secondary); + } + } + + .button_secondary, .button_transparency { + border: 1px solid var(--color-blue); + height: 25px; + border-radius: 4px; + padding: 2px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--color-light-blue); + color: var(--color-blue); + + svg { + fill: var(--color--button-primary); + } + + &:hover { + background-color: var(--color-secondary); + color: var(--color-blue); + } + } +} + +.publicationInfo_leftSide { + flex: 1; + max-width: 35%; + text-align: center; + + &_coverWrapper { + width: 100%; + min-height: 350px; + position: relative; + display: flex; + align-items: center; + background-color: var(--color-light-grey); + border: 1px solid var(--color-medium-grey); + border-radius: 6px; + + .no_img_wrapper { + height: 350px; + width: 100%; + text-align: center; + box-sizing: border-box; + padding: 5%; + border: 1px solid silver; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + + & .no_img { + border: 1px black solid; + width: 100%; + height: 100%; + line-height: inital; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + & p { + word-break: break-all; + display: -webkit-inline-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-align: center; + margin: 10px 5%; + color: var(--color-primary); + + &:not(:first-child) { + font-size: 90%; + } + } + } + } + } + + &_buttonsWrapper { + width: 100%; + display: flex; + flex-flow: column wrap; + justify-content: center; + align-items: center; + margin: 20px 0; + + > div { + width: 100%; + } + + button { + flex: 1 0 25%; + margin: 5px 0; + } + } +} + +.publicationInfo { + &_rightSide { + padding: 0 20px; + flex: 2; + + .book_title { + font-size: 24px; + } + + h2 { + font-style: italic; + font-weight: 700; + } + + .authors { + font-size: 18px; + } + } + + &_heading h4 { + position: relative; + font-weight: 600; + margin: 5px 0 10px; + } + + &_description_bloc { + position: relative; + + &_seeMore { + color: var(--color-blue); + text-decoration: underline; + display: flex; + width: 100px; + align-items: center; + justify-content: center; + + svg { + width: 20px; + margin: auto; + } + } + } + + &_moreInfo_content, &_lcpInfo_content { + div { + margin-bottom: 5px; + + strong { + font-weight: 600; + } + } + } +} + +.tag_list { + display: flex; + align-items: baseline; + gap: 10px; + + h4 { + min-width: fit-content; + margin-top: 0; + } +} + +.publicationInfo_tagContainer { + form { + display: flex; + align-items: center; + gap: 10px; + margin-top: 10px; + + button { + width: fit-content; + min-width: 50px; + + svg { + fill: white; + } + } + } +} + +.publicationInfo_progressionContainer { + display: flex; + flex-direction: column; + gap: 10px; + + p { + display: flex; + align-items: center; + gap: 10px; + margin: 0; + } + + details { + summary { + color: var(--color-blue); + background-color: var(--color-light-blue); + display: flex; + align-items: center; + gap: 10px; + + :hover { + cursor: pointer; + } + + svg { + width: 12px; + height: 12px; + margin-left: 2px; + } + + &:first-of-type { + list-style-type: none; + } + } + + ul { + list-style-type: none; + + li a { + color: var(--color-blue); + } + } + } +} + +.accessibility_infos { + line-height: 1.5; + + &_left { + margin-block-start: 0; + flex: 1; + padding-left: 20px; + list-style-type: "- "; + } + + &_right { + flex: 1; + + ul { + list-style-type: none; + margin-block-start: 0; + padding-left: 0; + } + + details { + color: var(--color-primary); + + summary { + color: var(--color-blue); + cursor: pointer; + } + } + } +} \ No newline at end of file diff --git a/src/renderer/assets/styles/publicationInfos.scss.d.ts b/src/renderer/assets/styles/publicationInfos.scss.d.ts new file mode 100644 index 000000000..306ca5543 --- /dev/null +++ b/src/renderer/assets/styles/publicationInfos.scss.d.ts @@ -0,0 +1,25 @@ +export declare const accessibility_infos: string; +export declare const accessibility_infos_left: string; +export declare const accessibility_infos_right: string; +export declare const authors: string; +export declare const book_title: string; +export declare const button_primary: string; +export declare const button_secondary: string; +export declare const button_transparency: string; +export declare const corner: string; +export declare const form_group: string; +export declare const no_img: string; +export declare const no_img_wrapper: string; +export declare const publicationInfo_container: string; +export declare const publicationInfo_description_bloc: string; +export declare const publicationInfo_description_bloc_seeMore: string; +export declare const publicationInfo_heading: string; +export declare const publicationInfo_lcpInfo_content: string; +export declare const publicationInfo_leftSide: string; +export declare const publicationInfo_leftSide_buttonsWrapper: string; +export declare const publicationInfo_leftSide_coverWrapper: string; +export declare const publicationInfo_moreInfo_content: string; +export declare const publicationInfo_progressionContainer: string; +export declare const publicationInfo_rightSide: string; +export declare const publicationInfo_tagContainer: string; +export declare const tag_list: string; diff --git a/src/renderer/assets/styles/publicationView.css.d.ts b/src/renderer/assets/styles/publicationView.css.d.ts deleted file mode 100644 index bf29e4699..000000000 --- a/src/renderer/assets/styles/publicationView.css.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare const styles: { - readonly "___DEBUG___PUBLICATION_VIEW_CSS": string; - readonly "card_substitute": string; - readonly "card_wrapper": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/publicationView.css b/src/renderer/assets/styles/publicationView.scss similarity index 83% rename from src/renderer/assets/styles/publicationView.css rename to src/renderer/assets/styles/publicationView.scss index fdd70f192..a17325f32 100644 --- a/src/renderer/assets/styles/publicationView.css +++ b/src/renderer/assets/styles/publicationView.scss @@ -1,5 +1,5 @@ /* -=-=-= publicationView.css +=-=-= publicationView.scss */ .card_wrapper { @@ -7,13 +7,13 @@ flex-wrap: wrap; justify-content: space-between; - & .card_substitute { + .card_substitute { width: 175px; height: 0; margin-bottom: 0; } - & > * { + > * { &:not(:last-child) { margin-right: 10px; } diff --git a/src/renderer/assets/styles/publicationView.scss.d.ts b/src/renderer/assets/styles/publicationView.scss.d.ts new file mode 100644 index 000000000..72d64a85b --- /dev/null +++ b/src/renderer/assets/styles/publicationView.scss.d.ts @@ -0,0 +1,3 @@ +export declare const ___DEBUG___PUBLICATION_VIEW_CSS: string; +export declare const card_substitute: string; +export declare const card_wrapper: string; diff --git a/src/renderer/assets/styles/reader-app.css.d.ts b/src/renderer/assets/styles/reader-app.css.d.ts deleted file mode 100644 index 091dd4b44..000000000 --- a/src/renderer/assets/styles/reader-app.css.d.ts +++ /dev/null @@ -1,107 +0,0 @@ -declare const styles: { - readonly "HIDE_CURSOR_CLASS": string; - readonly "HIDE_CURSOR_CLASS_foot": string; - readonly "HIDE_CURSOR_CLASS_head": string; - readonly "RTL_FLIP": string; - readonly "___DEBUG___READER_APP_CSS": string; - readonly "active": string; - readonly "after": string; - readonly "anchor_link": string; - readonly "arrow_box": string; - readonly "arrows": string; - readonly "blue": string; - readonly "bookmarkButton": string; - readonly "bookmark_infos": string; - readonly "bookmark_name": string; - readonly "bookmarks_line": string; - readonly "button_audio": string; - readonly "center_in_tab": string; - readonly "chapter_marker": string; - readonly "chapter_settings_list": string; - readonly "chapters_content": string; - readonly "chapters_description": string; - readonly "chapters_markers": string; - readonly "chapters_settings": string; - readonly "colorChange": string; - readonly "config_save": string; - readonly "content_root": string; - readonly "content_root_fullscreen": string; - readonly "content_root_skip_bottom_spacing": string; - readonly "content_table": string; - readonly "content_table_open": string; - readonly "currentPage": string; - readonly "currentSpineItem": string; - readonly "disable": string; - readonly "disabled": string; - readonly "divina_grid_container": string; - readonly "divina_grid_item": string; - readonly "fill": string; - readonly "focus_element": string; - readonly "gauge": string; - readonly "goToErrorMessage": string; - readonly "goToPage": string; - readonly "go_to_page": string; - readonly "hasTtsAudio": string; - readonly "history": string; - readonly "inert": string; - readonly "landmarks_tabs": string; - readonly "landmarks_tabs_button": string; - readonly "left_button": string; - readonly "line": string; - readonly "line_tab_content": string; - readonly "magnifyingGlassButton": string; - readonly "main_navigation": string; - readonly "main_navigation_fullscreen": string; - readonly "mathml_section": string; - readonly "menu_background": string; - readonly "menu_button": string; - readonly "menu_option": string; - readonly "menu_section_svg": string; - readonly "more_information": string; - readonly "nightMode": string; - readonly "noAudio": string; - readonly "notUsed": string; - readonly "option_auto": string; - readonly "option_colonne": string; - readonly "option_colonne1": string; - readonly "option_colonne2": string; - readonly "option_justif": string; - readonly "option_start": string; - readonly "out_of_screen": string; - readonly "page_option": string; - readonly "publication_viewport": string; - readonly "publication_viewport_container": string; - readonly "read_settings": string; - readonly "read_settings_list": string; - readonly "reader": string; - readonly "reader_footer": string; - readonly "reader_footer_fullscreen": string; - readonly "reader_settings_value": string; - readonly "right": string; - readonly "root": string; - readonly "rtlDir": string; - readonly "scroll_option": string; - readonly "sepiaMode": string; - readonly "settings_action": string; - readonly "settings_content": string; - readonly "settings_icones": string; - readonly "showInFullScreen": string; - readonly "side_button": string; - readonly "side_button_svg": string; - readonly "skip_link": string; - readonly "slidein": string; - readonly "slider_marker": string; - readonly "subheading": string; - readonly "tab_content": string; - readonly "themes_list": string; - readonly "title": string; - readonly "track_reading": string; - readonly "track_reading_wrapper": string; - readonly "track_reading_wrapper_noArrows": string; - readonly "ttsAudioActivated": string; - readonly "ttsSelectRate": string; - readonly "ttsSelectVoice": string; - readonly "tts_toolbar": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/reader-app.css b/src/renderer/assets/styles/reader-app.scss similarity index 60% rename from src/renderer/assets/styles/reader-app.css rename to src/renderer/assets/styles/reader-app.scss index f23bc948b..ee489c51b 100644 --- a/src/renderer/assets/styles/reader-app.css +++ b/src/renderer/assets/styles/reader-app.scss @@ -1,20 +1,7 @@ -/* -=-=-= reader-app.css => './focus-mixin.css' -*/ -@import url('./focus-mixin.css'); - -/* -=-=-= reader-app.css => './focus.css' -*/ -@import url('./focus.css'); - -/* -=-=-= reader-app.css => './variable.css' -*/ -@import url('./variable.css'); +@import "src/renderer/assets/styles/focus"; /* -=-=-= reader-app.css +=-=-= reader-app.scss */ /* :global */ @@ -25,7 +12,7 @@ :root.HIDE_CURSOR_CLASS, :root.HIDE_CURSOR_CLASS * { - cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), none !important; + cursor: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="), none !important; } .anchor_link { @@ -46,7 +33,7 @@ :root { user-select: none; - --sideButtonColor: rgb(130, 130, 130, 0.5); + --sideButtonColor: rgb(130 130 130 / 50%); --reader-mainColor: white; --reader-secondaryColor: white; --reader-fontColor: #000; @@ -87,7 +74,6 @@ body { margin: 0; padding: 0; width: 100%; - font: 1.1rem "Open Sans", sans-serif; overflow: hidden; } @@ -95,21 +81,22 @@ button { background: none; border: 0; cursor: pointer; - color: var(--reader-fontColor) !important; - fill: var(--reader-fontColor) !important; + fill: var(--reader-fontColor); height: auto; &:hover { opacity: 1; } + + &:disabled svg { + fill: var(--color-disabled)!important; + color: var(--color-disabled)!important; + } } .root { position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; + inset: 0; display: flex; flex-direction: column; overflow: hidden; @@ -117,33 +104,33 @@ button { color: var(--reader-fontColor); fill: var(--reader-fontColor); - & input[type=range] { + & input[type="range"] { position: relative; - -webkit-appearance: none; + appearance: none; width: 50%; height: 18px; background-color: transparent; cursor: pointer; - } - & input[type=range]::-webkit-slider-runnable-track { - width: 100%; - height: 2px; - background: #c0c0c0; - } - - & input[type=range]::-webkit-slider-thumb { - height: 15px; - width: 15px; - border-radius: 10px; - background: #6b6b6b; - cursor: pointer; - -webkit-appearance: none; - margin-top: -6px; - } + &::-webkit-slider-runnable-track { + width: 100%; + height: 2px; + background: #c0c0c0; + } + + &::-webkit-slider-thumb { + height: 15px; + width: 15px; + border-radius: 10px; + background: var(--scrollbar-thumb); + cursor: pointer; + appearance: none; + margin-top: -6px; + } - & input[type=range]:focus::-webkit-slider-runnable-track { - background: #c0c0c0; + &:focus::-webkit-slider-runnable-track { + background: #c0c0c0; + } } & .slider_marker { @@ -157,17 +144,17 @@ button { height: 100%; display: flex; align-items: stretch; - margin-top: 1rem; - margin-bottom: 5rem; -} + margin-top: 0.5rem; -.content_root_fullscreen { - margin-top: -10px; - margin-bottom: 60px; -} + // margin-bottom: 5rem; + + &_fullscreen { + margin-bottom: 60px; + } -.content_root_skip_bottom_spacing { - margin-top: 0; + &_skip_bottom_spacing { + margin-top: 0; + } } /* ========== READER ========== */ @@ -176,29 +163,60 @@ button { overflow: hidden; display: block; position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; + inset: 100px 50px; margin: 0; padding: 0; box-sizing: border-box; background: white; + + + &_container { + position: relative; + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + } } -.publication_viewport_container { - position: relative; - flex: 1; +.docked { + &_left { + left: 400px!important; + + &_pdf { + left: 350px!important; + } + } + + &_right { + right: 400px!important; + + &_pdf { + right: 350px!important; + } + + &_scrollable { + right: 350px!important; + } + } +} + +.isOnSearch { + top: 100px!important; } +.isOnSearchPdf { + top: 48px!important; +} + + .side_button { z-index: 3; display: inline-block; width: 50px; - background-color: rgb(0, 0, 0, 0); + background-color: rgb(0 0 0 / 0%); border: none; - - /* outline: none; */ fill: var(--sideButtonColor); &:hover { @@ -206,14 +224,10 @@ button { fill: var(--secondary-color); } - /* &:focus { - outline: 1pt dashed #999; - } */ -} - -.side_button_svg { - width: 45px; - margin: auto; + &_svg { + width: 45px; + margin: auto; + } } .left_button { @@ -222,8 +236,7 @@ button { .reader { display: flex; - overflow-y: auto; - overflow-x: hidden; + overflow: hidden auto; flex-grow: 2; } @@ -238,9 +251,6 @@ button { } & div { - display: flex; - text-align: center; - & label { flex-grow: 1; height: 1.5rem; @@ -249,7 +259,7 @@ button { } .settings_action { - background-color: rgb(0, 0, 0, 0); + background-color: rgb(0 0 0 / 0%); border: 0; font-size: 1rem; height: 2.5rem; @@ -273,29 +283,29 @@ button { border-right: 1px var(--main-color) solid; background-color: #e0e0e0; overflow: auto; -} - -.content_table_open { - animation-duration: 500ms; - animation-name: slidein; - animation-iteration-count: 1; - animation-fill-mode: forwards; -} - -.content_table ul { - list-style-type: none; - padding: 1rem; - margin: 0; - - & li { - padding-top: 0.5rem; - & a { - text-decoration: none; - color: var(--reader-fontColor); + &_open { + animation-duration: 500ms; + animation-name: slidein; + animation-iteration-count: 1; + animation-fill-mode: forwards; + } - &:hover { - text-decoration: underline; + ul { + list-style-type: none; + padding: 1rem; + margin: 0; + + & li { + padding-top: 0.5rem; + + & a { + text-decoration: none; + color: var(--reader-fontColor); + + &:hover { + text-decoration: underline; + } } } } @@ -303,20 +313,20 @@ button { .landmarks_tabs { background-color: black; -} - -.landmarks_tabs_button { - padding: 8px 16px; - width: auto; - border: none; - display: inline-block; - background-color: transparent; - color: white; - cursor: pointer; - &:hover { - color: var(--reader-fontColor); - background-color: rgba(255, 255, 255, 0.6); + &_button { + padding: 8px 16px; + width: auto; + border: none; + display: inline-block; + background-color: transparent; + color: white; + cursor: pointer; + + &:hover { + color: var(--reader-fontColor); + background-color: rgb(255 255 255 / 60%); + } } } @@ -344,7 +354,7 @@ button { padding-bottom: 0; height: auto; background-color: var(--reader-secondaryColor); - box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.19); + box-shadow: 0 0 15px 0 rgb(0 0 0 / 19%); min-width: 600px; &:not(.hasTtsAudio) { @@ -419,7 +429,7 @@ button { text-align: center !important; font-size: 0.9em !important; width: 4em; - -webkit-appearance: none; + appearance: none; border: 1px solid #aaa; border-radius: 0.4em; box-sizing: border-box; @@ -479,11 +489,11 @@ button { left: -2000px; &:checked + label.menu_button { - background-color: rgb(193, 193, 193); + background-color: rgb(193 193 193); } &:focus + label.menu_button { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } } @@ -492,11 +502,11 @@ button { left: -2000px; &:checked + label.menu_button { - background-color: rgb(193, 193, 193); + background-color: rgb(193 193 193); } &:focus + label.menu_button { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } } } @@ -517,10 +527,7 @@ button { .menu_background { position: absolute; - top: 60px; - bottom: 0; - left: 0; - right: 0; + inset: 60px 0 0; background-color: black; opacity: 0.55; z-index: 10; @@ -571,11 +578,6 @@ button { color: var(--reader-fontColor); &:disabled { - /* - color: grey; - opacity: 0.5; - cursor: auto; - */ color: var(--disabled-color) !important; cursor: not-allowed; @@ -595,49 +597,6 @@ button { } } -.main_navigation_fullscreen { - & > ul:not(.showInFullScreen) > ul:not(.showInFullScreen) > li:not(.showInFullScreen), - & > ul:not(.showInFullScreen) > li:not(.showInFullScreen) { - display: none; - } - - & > ul > ul.tts_toolbar { - margin-left: 0; - } - - &:not(.hasTtsAudio) { - background-color: transparent; - box-shadow: none; - - & > ul { - display: block; - - & > ul.tts_toolbar { - display: none; - } - } - } - - &.hasTtsAudio:not(.ttsAudioActivated) { - background-color: transparent; - box-shadow: none; - } - - /* & > { - display: block; - } - & > ul, & ul.menu_option { - margin-right: 20px; - & > li { - & > .menu_button { - border-right: 1px solid #c1c1c1; - border-bottom: 1px solid #c1c1c1; - background-color: var(--reader-secondaryColor); - } - } - } */ -} - .tab_content { position: relative; background-color: var(--reader-menuPartColor); @@ -669,54 +628,21 @@ button { font-size: 1rem; margin-top: 10px; margin-bottom: 30px; -} -.go_to_page input[type=number] { - background-color: transparent; - border: none; - border-bottom: 1px solid #c1c1c1; - border-radius: 0; - width: 50px; - padding: 10px; - font-size: 1rem; - text-align: center; -} - -.go_to_page input[type=number]::placeholder { - overflow: visible; - color: #c1c1c1; -} - -.chapters_content { - padding: 0; - height: auto; - list-style: none; - - & > li > div > a > span { - /* color: red !important; */ - line-height: 1.5em; - } - - & .chapters_content { - border-left: 1px solid var(--reader-separatorColor); - padding: 0 0 0 20px; - } - - & .subheading:not(.inert) { - &:hover { - background-color: var(--reader-menuPartTitleHoverColor) !important; - } - } + input[type="number"] { + background-color: transparent; + border: none; + border-bottom: 1px solid #c1c1c1; + border-radius: 0; + width: 50px; + padding: 10px; + font-size: 1rem; + text-align: center; - & .line.active:not(.inert) { - &:hover { - /* color: #808080 !important; */ - background-color: var(--reader-separatorColor); + &::placeholder { + overflow: visible; + color: #c1c1c1; } - - /* &:focus { - outline: -webkit-focus-ring-color auto 5px; - } */ } } @@ -782,89 +708,10 @@ button { } } -.chapters_content .line { - text-align: left; - font-size: 0.9rem; - display: block; - font-weight: bold; - color: #c1c1c1; - padding: 0.625rem 0.3125rem; - border-bottom: 1px solid #e5e5e5; -} - -.chapters_content .line:not(.inert) { - cursor: pointer; -} - -.chapters_content .line:last-child { - border-bottom: 0; -} - p.chapters_description { font-weight: 500; } -.bookmarks_line:last-child { - border-bottom: 0; -} - -.bookmarks_line { - width: calc(100% - 40px); - margin-left: 20px; - position: relative; - text-align: left; - padding: 20px 0 20px 0; - font-size: 1rem; - border-bottom: 1px solid #e5e5e5; - - & > button { - border: none; - background-color: transparent; - cursor: pointer; - padding: 0; - - & svg { - width: 24px; - } - } - - & img { - width: 30px; - height: 30px; - display: inline-block; - vertical-align: top; - } - - & .chapter_marker { - vertical-align: top; - position: relative; - display: inline-block; - flex: 1; - font-size: 0.9rem; - margin-right: 0.5rem; - } - - & span { - display: inline-block; - vertical-align: top; - margin-top: 5px; - } -} - -.chapter_marker .gauge { - width: 100%; - margin-top: 2px; - height: 4px; - background-color: #ececec; - - & .fill { - height: 100%; - position: relative; - width: 63%; - background-color: #3b3b3b; - } -} - /* ============= SETTINGS MENU =================== */ #themes_list { @@ -877,7 +724,7 @@ p.chapters_description { & label { display: inline-flex; - margin: 0 3px 3px 3px; + margin: 0 3px 3px; padding: 5px 10px 5px 2rem; font-size: 1.25em; height: 1.2rem; @@ -897,7 +744,7 @@ p.chapters_description { left: -2000px; &:focus + label { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } &:disabled + label { @@ -976,10 +823,10 @@ p.chapters_description { & label { cursor: pointer; - padding: 10px 10px 10px; + padding: 10px; &:focus + input { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } } @@ -1010,43 +857,17 @@ p.chapters_description { left: -20000px; &:focus + label { - @mixin R2_MIXIN_FOCUS_OUTLINE; + @include R2_MIXIN_FOCUS_OUTLINE; } } & label { display: inline-flex; - margin: 0 5px 0 5px; + margin: 0 5px; } } -#option_colonne, -#option_colonne1, -#option_colonne2 { - display: inline-block; - text-align: center; - margin: 0 10px 20px 10px; - line-height: 2rem; - vertical-align: baseline; - height: 70px; - width: 63px; -} - -#option_auto, -#option_justif, -#option_start, -#scroll_option, -#page_option { - display: inline-block; - text-align: center; - margin: 0 10px 20px 10px; - line-height: 2rem; - vertical-align: baseline; - height: 15px; - width: 20px; -} - -input[type=number] { +input[type="number"] { padding: 10px; margin-top: 10px; background-color: white; @@ -1057,7 +878,7 @@ input[type=number] { text-align: center; } -input[type=radio] + label { +input[type="radio"] + label { display: inline-block; } @@ -1107,212 +928,6 @@ input[type=radio] + label { /* ========= FOOTER ========= */ -.reader_footer { - &.HIDE_CURSOR_CLASS_foot { - visibility: hidden !important; - } - - position: fixed; - bottom: 0; - right: 0; - left: 0; - background-color: var(--reader-mainColor); - - & .history { - float: left; - margin-top: 1rem; - margin-left: 2rem; - - & button { - border: 0; - cursor: pointer; - padding: 0; - background-color: transparent; - width: 40px; - height: 40px; - - &.disabled { - cursor: not-allowed; - opacity: 0.5; - } - } - - & svg { - /* fill: #c1c1c1; */ - - /* fill: #555555; */ - fill: var(--reader-fontColor); - opacity: 0.5; - transform: scale(0.8); - } - } - - & .arrows { - float: right; - margin-top: 1rem; - margin-right: 2rem; - - & button { - border: 0; - cursor: pointer; - padding: 0; - background-color: transparent; - width: 40px; - height: 40px; - } - - & svg { - /* fill: #c1c1c1; */ - - /* fill: #555555; */ - fill: var(--reader-fontColor); - opacity: 0.5; - } - } - - & .track_reading_wrapper { - padding: 1rem 8rem 1rem 8rem; - bottom: 0; - margin-top: 1rem; - color: var(--reader-fontColor); - } - - & .track_reading_wrapper_noArrows { - /* padding: 1rem 5rem 1rem 5rem; */ - padding-top: 1rem; - padding-right: 5rem; - padding-bottom: 1rem; - - /* padding-left: 5rem; */ - } -} - -.reader_footer_fullscreen { - background-color: transparent; - pointer-events: none; - - & .arrows { - background-color: var(--reader-mainColor); - pointer-events: all; - margin-bottom: 15px; - margin-right: 20px; - } - - & .history { - background-color: var(--reader-mainColor); - pointer-events: all; - margin-bottom: 15px; - margin-left: 20px; - } -} - -#track_reading { - position: relative; - width: 100%; - height: 10px; - background-color: #c1c1c1; -} - -#track_reading + span { - font-style: italic; - font-size: 0.8rem; - padding-bottom: 10px; - cursor: pointer; -} - -/* -#current { - position: relative; -} -*/ - -#chapters_markers { - display: flex; - position: absolute; - width: 100%; - height: 16px; - margin-top: -3px; - top: 0; - - &.more_information > span { - border-right: 1px solid #929292; - - &.currentSpineItem { - outline-color: grey; - outline-offset: 0; - outline-style: solid; - outline-width: 1px; - } - } - - & > span { - flex-grow: 1; - padding: 3px 0; - - & > span { - display: block; - background-color: grey; - width: 100%; - height: 100%; - } - - &:last-child { - border-right: none; - } - } -} - -#arrow_box { - position: absolute; - width: 450px; - height: auto; - padding: 10px 0 5px 0; - margin: -76px 0 0 0; - left: 50%; - background: white; - font-size: 16px; - color: var(--color-primary); - text-align: center; - box-shadow: 0 0 46px 0 rgba(0, 0, 0, 0.12); - transform: translateX(-50%) translateY(0%); - - & .after { - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - border: solid rgba(0, 0, 0, 0); - top: 59px; - border-color: rgba(0, 0, 0, 0); - border-width: 9px; - border-top-color: white; - left: 50%; - margin-left: -9px; - } - - & span { - display: block; - margin: 0 20px 5px 20px; - border-bottom: 1px solid #c1c1c1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-weight: bold; - - & em { - font-size: 80%; - font-weight: normal; - } - } - - & p { - margin: 10px 0 0 0; - font-size: 0.8rem; - padding: 0 20px 0 20px; - } -} - .skip_link { position: absolute; left: -2000px; @@ -1332,54 +947,6 @@ input[type=radio] + label { } } -.currentPage { - font-size: 80%; - font-weight: normal; - margin-bottom: 1em; -} - -.goToPage { - text-align: center; - - & .title { - color: var(--reader-fontColor); - font-size: 1.1rem; - } - - & .goToErrorMessage { - color: red; - } - - & form { - display: flex; - align-items: center; - justify-content: center; - - & button { - border: 1px solid black; - border-radius: 5px; - background: none; - margin: 1rem; - margin-left: 8px; - padding: 0.5rem; - color: var(--reader-fontColor); - } - - & select { - margin: 0; - margin-right: 5px; - } - - & input { - margin: 0; - } - - & *:disabled { - cursor: not-allowed; - } - } -} - .mathml_section { display: flex; padding: 10px; @@ -1422,3 +989,68 @@ input[type=radio] + label { .___DEBUG___READER_APP_CSS { display: none; } + +.button_exitZen { + width: 25px; + height: 25px; + position: absolute; + right: 25px; + top: 12px; + z-index: 10; + + svg { + color: var(--color-blue); + width: 25px; + } +} + +.select_fxl { + width: 80px!important; + + .react_aria_ComboBox { + padding-bottom: 0!important; + margin: 0!important; + gap: 0!important; + } + + .my_combobox_container { + border: none!important; + padding-right: 0!important; + } + + #buttonFXLZoom { + border: 1px solid transparent; + background-color: transparent; + color: var(--color-blue); + padding: 5px; + border-radius: 6px; + text-align: center; + height: 30px; + width: 80px; + font-size: 16px; + cursor: pointer; + transition: 200ms; + + svg { + margin-left: 0!important; + background: none!important; + } + + .my_combobox_container { + padding-right: 0; + } + + &:hover, &:focus { + border: 1px solid var(--color-blue); + background-color: var(--color-light-blue); + color: var(--color-blue); + } + } +} + +.bookmarkList_button { + height: fit-content; + display: block; + text-align: left; + width: 100%; +} diff --git a/src/renderer/assets/styles/reader-app.scss.d.ts b/src/renderer/assets/styles/reader-app.scss.d.ts new file mode 100644 index 000000000..1ff67ac99 --- /dev/null +++ b/src/renderer/assets/styles/reader-app.scss.d.ts @@ -0,0 +1,90 @@ +export declare const ___DEBUG___FOCUS_CSS: string; +export declare const ___DEBUG___FOCUS_MIXIN_CSS: string; +export declare const ___DEBUG___READER_APP_CSS: string; +export declare const active: string; +export declare const anchor_link: string; +export declare const blue: string; +export declare const body_element: string; +export declare const bookmark_infos: string; +export declare const bookmark_name: string; +export declare const bookmarkButton: string; +export declare const bookmarkList_button: string; +export declare const bookmarks_line: string; +export declare const button_audio: string; +export declare const button_exitZen: string; +export declare const buttonFXLZoom: string; +export declare const center_in_tab: string; +export declare const chapter_settings_list: string; +export declare const chapters_description: string; +export declare const chapters_settings: string; +export declare const colorChange: string; +export declare const config_save: string; +export declare const content_root: string; +export declare const content_root_fullscreen: string; +export declare const content_root_skip_bottom_spacing: string; +export declare const content_table: string; +export declare const content_table_open: string; +export declare const disable: string; +export declare const divina_grid_container: string; +export declare const divina_grid_item: string; +export declare const docked_left: string; +export declare const docked_left_pdf: string; +export declare const docked_right: string; +export declare const docked_right_pdf: string; +export declare const docked_right_scrollable: string; +export declare const focus_element: string; +export declare const go_to_page: string; +export declare const hasTtsAudio: string; +export declare const HIDE_CURSOR_CLASS: string; +export declare const HIDE_CURSOR_CLASS_head: string; +export declare const inert: string; +export declare const isOnSearch: string; +export declare const isOnSearchPdf: string; +export declare const landmarks_tabs: string; +export declare const landmarks_tabs_button: string; +export declare const left_button: string; +export declare const line: string; +export declare const line_tab_content: string; +export declare const magnifyingGlassButton: string; +export declare const main_navigation: string; +export declare const mathml_section: string; +export declare const menu_background: string; +export declare const menu_button: string; +export declare const menu_option: string; +export declare const menu_section_svg: string; +export declare const my_combobox_container: string; +export declare const nightMode: string; +export declare const noAudio: string; +export declare const notUsed: string; +export declare const out_of_screen: string; +export declare const publication_viewport: string; +export declare const publication_viewport_container: string; +export declare const R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE: string; +export declare const R2_CSS_CLASS__FORCE_NO_TARGET_OUTLINE: string; +export declare const R2_CSS_CLASS__KEYBOARD_INTERACT: string; +export declare const react_aria_ComboBox: string; +export declare const read_settings: string; +export declare const read_settings_list: string; +export declare const reader: string; +export declare const reader_settings_value: string; +export declare const readium2ElectronAnimation_TARGET: string; +export declare const right: string; +export declare const root: string; +export declare const RTL_FLIP: string; +export declare const rtlDir: string; +export declare const select_fxl: string; +export declare const sepiaMode: string; +export declare const settings_action: string; +export declare const settings_content: string; +export declare const settings_icones: string; +export declare const side_button: string; +export declare const side_button_svg: string; +export declare const skip_link: string; +export declare const slidein: string; +export declare const slider_marker: string; +export declare const subheading: string; +export declare const tab_content: string; +export declare const themes_list: string; +export declare const tts_toolbar: string; +export declare const ttsSelectRate: string; +export declare const ttsSelectVoice: string; diff --git a/src/renderer/assets/styles/variable.css.d.ts b/src/renderer/assets/styles/variable.css.d.ts deleted file mode 100644 index 52cb7bf80..000000000 --- a/src/renderer/assets/styles/variable.css.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare const styles: { - readonly "___DEBUG___VARIABLE_CSS": string; -}; -export = styles; - diff --git a/src/renderer/assets/styles/variable.css b/src/renderer/assets/styles/variable.scss similarity index 87% rename from src/renderer/assets/styles/variable.css rename to src/renderer/assets/styles/variable.scss index 48fe1380b..59d2c9600 100644 --- a/src/renderer/assets/styles/variable.css +++ b/src/renderer/assets/styles/variable.scss @@ -1,5 +1,5 @@ /* -=-=-= variable.css +=-=-= variable.scss */ :root { diff --git a/src/renderer/assets/styles/variable.scss.d.ts b/src/renderer/assets/styles/variable.scss.d.ts new file mode 100644 index 000000000..bc4c6c8c9 --- /dev/null +++ b/src/renderer/assets/styles/variable.scss.d.ts @@ -0,0 +1 @@ +export declare const ___DEBUG___VARIABLE_CSS: string; diff --git a/src/renderer/common/components/ComboBox.tsx b/src/renderer/common/components/ComboBox.tsx new file mode 100644 index 000000000..142bb63cc --- /dev/null +++ b/src/renderer/common/components/ComboBox.tsx @@ -0,0 +1,86 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import * as React from "react"; +import { Button, ComboBox as ComboBoxReactAria, Input, Label, ListBox, ListBoxItem, Popover, ComboBoxProps, ValidationResult, Group } from "react-aria-components"; +import { FieldError, Text } from "react-aria-components"; +import SVG, { ISVGProps } from "./SVG"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as StylesCombobox from "readium-desktop/renderer/assets/styles/components/combobox.scss"; +import classNames from "classnames"; + +export interface MyComboBoxProps + extends Omit, "children"> { + label?: string; + description?: string | null; + errorMessage?: string | ((validation: ValidationResult) => string); + children: React.ReactNode | ((item: T) => React.ReactNode); + svg?: ISVGProps; + refInputEl?: React.Ref; +} + +// function forwardRef( +// render: React.ForwardRefRenderFunction>, +// ): React.ForwardRefExoticComponent> & React.RefAttributes> { +// return React.forwardRef(render); +// } + +// export const ComboBox = forwardRef( +// ({ children, label, svg, description, errorMessage, ...props }, forwardedRef) => ( +// +// +//
+// {svg ? : <>} +// +// +//
+// {description ? {description} : <>} +// {errorMessage} +// +// +// {children} +// +// +// +// ) +// ); + +export function ComboBox( + { label, description, errorMessage, children, svg, refInputEl, ...props }: MyComboBoxProps, +) { + return ( + + + + {svg ? : <>} + + + + {description ? {description} : <>} + {errorMessage} + + + {children} + + + + ); +} + +export function ComboBoxItem(props: T) { + return ( + + classNames(StylesCombobox.my_item, isFocused ? StylesCombobox.focused : "", isSelected ? StylesCombobox.selected : "")} + /> + ); +} diff --git a/src/renderer/common/components/Cover.tsx b/src/renderer/common/components/Cover.tsx index 1fc81beea..8b2d17408 100644 --- a/src/renderer/common/components/Cover.tsx +++ b/src/renderer/common/components/Cover.tsx @@ -10,8 +10,7 @@ import { encodeURIComponent_RFC3986 } from "@r2-utils-js/_utils/http/UrlUtils"; import * as React from "react"; import { RandomCustomCovers } from "readium-desktop/common/models/custom-cover"; import { TPublication } from "readium-desktop/common/type/publication.type"; -import * as stylesImages from "readium-desktop/renderer/assets/styles/components/images.css"; -import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.css"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; import { formatContributorToString, } from "readium-desktop/renderer/common/logics/formatContributor"; @@ -19,6 +18,9 @@ import { import { TranslatorProps, withTranslator } from "./hoc/translator"; import { PublicationView } from "readium-desktop/common/views/publication"; import { convertMultiLangStringToString, langStringIsRTL } from "readium-desktop/renderer/common/language-string"; +import { useTranslator } from "../hooks/useTranslator"; +// import * as ValidateIcon from "readium-desktop/renderer/assets/icons/validated-icon.svg"; +// import SVG from "./SVG"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -26,6 +28,9 @@ interface IBaseProps extends TranslatorProps { coverType?: "cover" | "thumbnail" | undefined; onClick?: () => void; onKeyPress?: (e: React.KeyboardEvent) => void; + forwardedRef?: React.ForwardedRef; + imgRadixProp?: any; + hasEnded?: boolean; } // IProps may typically extend: @@ -70,22 +75,59 @@ class Cover extends React.Component { this.imageOnError = this.imageOnError.bind(this); } - public render() { + public componentDidUpdate(prevProps: Readonly): void { + if (prevProps.publicationViewMaybeOpds?.cover !== this.props.publicationViewMaybeOpds?.cover) { + + const { cover } = this.props.publicationViewMaybeOpds; + + if (cover) { + const coverUrl = cover.coverUrl || cover.coverLinks[0]?.url; + const thumbnailUrl = cover.coverUrl || cover.thumbnailLinks[0]?.url; + + if (this.props.coverType === "cover") { + this.setState({ imgUrl: coverUrl || thumbnailUrl }); + } else { + this.setState({ imgUrl: thumbnailUrl || coverUrl }); + } + } else { + this.setState({ imgUrl: undefined }); + } + } + } + + public render() { const { publicationViewMaybeOpds, translator } = this.props; + // let tagString = ""; + // for (const tag of publicationViewMaybeOpds.tags) { + // if (typeof tag === "string") { + // tagString = tag; + // } else { + // tagString = tag.name; + // } + // }; + if (this.state.imgUrl) { return ( + <> {this.props.onKeyPress + {/* {tagString === "/finished/" ? +
+ : <>} */} +
+ ); } @@ -111,6 +153,10 @@ class Cover extends React.Component {

{authors}

+ {/* {!this.props.publicationViewMaybeOpds.lastReadTimeStamp ? +
+ : <>} */} +
); @@ -126,4 +172,22 @@ class Cover extends React.Component { } } -export default withTranslator(Cover); +const CoverWithTranslator = withTranslator(Cover); +export default CoverWithTranslator; + +export const CoverWithForwardedRef = React.forwardRef(({publicationViewMaybeOpds, coverType, ...props}, forwardedRef) => { + const [__] = useTranslator(); + + return ( + + ); +}); + +CoverWithForwardedRef.displayName = "CoverWithForwardedRef"; diff --git a/src/renderer/common/components/Loader.tsx b/src/renderer/common/components/Loader.tsx index f1137ae49..e42f8f92e 100644 --- a/src/renderer/common/components/Loader.tsx +++ b/src/renderer/common/components/Loader.tsx @@ -7,7 +7,7 @@ import * as React from "react"; import * as LoaderIcon from "readium-desktop/renderer/assets/icons/loader.svg"; -import * as stylesLoader from "readium-desktop/renderer/assets/styles/loader.css"; +import * as stylesLoader from "readium-desktop/renderer/assets/styles/loader.scss"; import SVG from "./SVG"; diff --git a/src/renderer/common/components/Select.tsx b/src/renderer/common/components/Select.tsx new file mode 100644 index 000000000..eec3913f1 --- /dev/null +++ b/src/renderer/common/components/Select.tsx @@ -0,0 +1,59 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import * as React from "react"; +import { Button, Select as SelectReactAria, Label, ListBox, ListBoxItem, Popover, SelectProps, ValidationResult, Group, SelectValue } from "react-aria-components"; +import { FieldError, Text } from "react-aria-components"; +import SVG, { ISVGProps } from "./SVG"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as StylesCombobox from "readium-desktop/renderer/assets/styles/components/combobox.scss"; +import classNames from "classnames"; + +export interface MySelectProps + extends Omit, "children"> { + label?: string; + description?: string; + errorMessage?: string | ((validation: ValidationResult) => string); + items?: Iterable; + children: React.ReactNode | ((item: T) => React.ReactNode); + svg?: ISVGProps; + refButEl?: React.Ref; +} + +export function Select( + { label, description, errorMessage, children, svg, refButEl, items, ...props }: MySelectProps, +) { + return ( + + + + {svg ? : <>} + + + {description && {description}} + {errorMessage} + + + {children} + + + + ); +} + +export function SelectItem(props: T) { + return ( + + classNames(StylesCombobox.my_item, isFocused ? StylesCombobox.focused : "", isSelected ? StylesCombobox.selected : "")} + /> + ); +} diff --git a/src/renderer/common/components/dialog/Dialog.tsx b/src/renderer/common/components/dialog/Dialog.tsx index 02745cc8c..77e99cbee 100644 --- a/src/renderer/common/components/dialog/Dialog.tsx +++ b/src/renderer/common/components/dialog/Dialog.tsx @@ -9,9 +9,9 @@ import classNames from "classnames"; import * as React from "react"; import * as ReactDOM from "react-dom"; import FocusLock from "react-focus-lock"; -import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; import SVG from "readium-desktop/renderer/common/components/SVG"; import { TranslatorProps, withTranslator } from "../hoc/translator"; diff --git a/src/renderer/common/components/dialog/publicationInfos/FormatContributorWithLink.tsx b/src/renderer/common/components/dialog/publicationInfos/FormatContributorWithLink.tsx index 746103075..f9dc2ca0a 100644 --- a/src/renderer/common/components/dialog/publicationInfos/FormatContributorWithLink.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/FormatContributorWithLink.tsx @@ -5,21 +5,24 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== +import classNames from "classnames"; import * as React from "react"; import { Translator } from "readium-desktop/common/services/translator"; import { IOpdsContributorView } from "readium-desktop/common/views/opds"; -import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/publicationInfos.scss"; interface IProps { contributors: string[] | IOpdsContributorView[] | undefined; translator: Translator; onClickLinkCb?: (newContributor: IOpdsContributorView) => () => void; + className?: string; } export const FormatContributorWithLink: React.FC = (props) => { - const { contributors, translator, onClickLinkCb } = props; + const { contributors, translator, onClickLinkCb, className } = props; const retElement: JSX.Element[] = []; @@ -37,20 +40,20 @@ export const FormatContributorWithLink: React.FC = (props) => { // FIXME : add pointer hover on 'a' links retElement.push( {translator.translateContentField(newContributor.name)} , ); } else if (typeof newContributor === "object") { retElement.push( - + {translator.translateContentField(newContributor.name)} , ); } else { retElement.push( - + {translator.translateContentField(newContributor)} , ); diff --git a/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx b/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx index dd8550c27..48b876d55 100644 --- a/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx @@ -6,12 +6,13 @@ // ==LICENSE-END== import classNames from "classnames"; -import * as debug_ from "debug"; import * as moment from "moment"; import * as React from "react"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylePublication from "readium-desktop/renderer/assets/styles/publicationInfos.scss"; + import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -30,9 +31,6 @@ interface IBaseProps extends TranslatorProps { interface IProps extends IBaseProps { } -// Logger -const debug = debug_("readium-desktop:renderer:publication-info:lcp-info"); - class LcpInfo extends React.Component { constructor(props: IProps) { @@ -57,28 +55,42 @@ class LcpInfo extends React.Component { const lcpRightsCopy = (lcp?.rights?.copy) ? lcp.rights.copy : 0; const lcpRightsCopies = publicationLcp.lcpRightsCopies ?? 0; + const now = moment(); + const lcpRightsStartDate = (lcp?.rights?.start) ? lcp.rights.start : undefined; - let lcpRightsStartDateStr: string | undefined; + let lcpRightsStartDateStr = ""; + let remainingDays= ""; + let futureDays= ""; + if (lcpRightsStartDate) { - try { - lcpRightsStartDateStr = moment(lcpRightsStartDate).format("LLL"); - } catch (err) { - debug(err); - lcpRightsStartDateStr = lcpRightsStartDate; + const momentStart = moment(lcpRightsStartDate); + lcpRightsStartDateStr = momentStart.format("LLL"); + const timeStartDif = momentStart.diff(now, "days"); + if (timeStartDif > 1) { + futureDays = `${timeStartDif} ${__("publication.days")}`; + } else if (timeStartDif === 1) { + futureDays = `${timeStartDif} ${__("publication.day")}`; } } const lcpRightsEndDate = (lcp?.rights?.end) ? lcp.rights.end : undefined; - let lcpRightsEndDateStr: string | undefined; + let lcpRightsEndDateStr = ""; if (lcpRightsEndDate) { - try { - lcpRightsEndDateStr = moment(lcpRightsEndDate).format("LLL"); - } catch (err) { - debug(err); - lcpRightsEndDateStr = lcpRightsEndDate; + const momentEnd = moment(lcpRightsEndDate); + lcpRightsEndDateStr = momentEnd.format("LLL"); + const timeEndDif = momentEnd.diff(now, "days"); + if (timeEndDif > 1) { + remainingDays = `${timeEndDif} ${__("publication.days")}`; + } else if (timeEndDif === 1) { + remainingDays = `${timeEndDif} ${__("publication.day")}`; + } else { + remainingDays = `${__("publication.expired")}`; } + } + + // TODO: fix r2-lcp-js to handle encrypted fields // (need lcp.node with userkey decrypt, not contentkey): // if (lcp && lcp.r2LCPBase64) { @@ -102,8 +114,8 @@ class LcpInfo extends React.Component { return ( <> -
-

LCP

+
+

{__("publication.licenceLCP")}

{(lsdStatus && @@ -112,16 +124,16 @@ class LcpInfo extends React.Component { { (lsdStatus === StatusEnum.Expired ? __("publication.expiredLcp") - : + : ((lsdStatus === StatusEnum.Cancelled) ? __("publication.cancelledLcp") - : + : ((lsdStatus === StatusEnum.Revoked) ? __("publication.revokedLcp") - : + : (lsdStatus === StatusEnum.Returned ? __("publication.returnedLcp") - : + : `LCP LSD: ${lsdStatus}` ) ) @@ -132,26 +144,38 @@ class LcpInfo extends React.Component {

} - - {lcpRightsStartDateStr && <> - {__("publication.lcpStart")}: {lcpRightsStartDateStr} + { + futureDays ? + <> + {__("publication.lcpStart")}: + {futureDays} ({lcpRightsStartDateStr}) +
+ + : <> + } + {lcpRightsEndDateStr ? + <> + {__("publication.timeLeft")}: + {remainingDays} ({lcpRightsEndDateStr})
- } + + : <> + } - {lcpRightsEndDateStr && <> - {__("publication.lcpEnd")}: {lcpRightsEndDateStr} + {/*{lcpRightsEndDateStr && <> + {__("publication.lcpEnd")}: {lcpRightsEndDateStr}

- } + } */} {lcpRightsCopy ? <> {__("publication.lcpRightsCopy")}: - {lcpRightsCopies} / {lcpRightsCopy}
+ {lcpRightsCopies} / {lcpRightsCopy}
: undefined} {lcpRightsPrint ? <> {__("publication.lcpRightsPrint")}: - 0 / {lcpRightsPrint}
+ 0 / {lcpRightsPrint}
: undefined}
diff --git a/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx b/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx index 5a801f41e..69990f0aa 100644 --- a/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx @@ -11,10 +11,11 @@ import DOMPurify from "dompurify"; import * as React from "react"; import { I18nTyped, Translator } from "readium-desktop/common/services/translator"; import { TPublication } from "readium-desktop/common/type/publication.type"; -import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.css"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.scss"; +import * as stylePublication from "readium-desktop/renderer/assets/styles/publicationInfos.scss"; +import SVG from "../../SVG"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; // Logger const debug = debug_("readium-desktop:renderer:publicationInfoDescription"); @@ -68,15 +69,14 @@ export default class PublicationInfoDescription extends React.Component; return ( <> -
-

{__("catalog.description")}

+
+

{__("catalog.description")}

-
+
{ this.state.needSeeMore && - diff --git a/src/renderer/common/components/dialog/publicationInfos/tag/tagButton.tsx b/src/renderer/common/components/dialog/publicationInfos/tag/tagButton.tsx index b75ce22f2..8c7a3a56b 100644 --- a/src/renderer/common/components/dialog/publicationInfos/tag/tagButton.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/tag/tagButton.tsx @@ -6,24 +6,97 @@ // ==LICENSE-END== import * as React from "react"; -import { I18nTyped } from "readium-desktop/common/services/translator"; import { IOpdsTagView } from "readium-desktop/common/views/opds"; -import * as CrossIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px-blue.svg"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as EditIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.scss"; +import * as Popover from "@radix-ui/react-popover"; +import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.scss"; +import { Link } from "react-router-dom"; +import { encodeURIComponent_RFC3986 } from "r2-utils-js/dist/es8-es2017/src/_utils/http/UrlUtils"; +// import { DisplayType } from "readium-desktop/renderer/library/routing"; +import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; -export interface IProps { +interface IBaseProps { tag: string | IOpdsTagView; index?: number; - __?: I18nTyped; pubId?: string; onClickDeleteCb?: (index: number) => () => void | undefined; onClickLinkCb?: (tag: IOpdsTagView) => () => void | undefined; } +export interface IProps extends IBaseProps, ReturnType { +} + export const TagButton: React.FC> = (props) => { + const { tag, index, pubId, onClickDeleteCb, onClickLinkCb, location } = props; + let button = <>; - const { tag, index, __, pubId, onClickDeleteCb, onClickLinkCb } = props; + const [__] = useTranslator(); + let tagString = ""; + if (typeof tag === "string") { + tagString = tag; + } else { + tagString = tag.name; + } + + if (pubId && onClickDeleteCb) { + button = ( + <> + + {tag as string} + + + + + + + + + + + + + + ); + } else if (typeof tag === "object" && tag?.link?.length && onClickLinkCb) { + button = (<> + this.props.link(tag.link[0], this.props.location, tag.name) + onClickLinkCb(tag)}> + {tagString} + + + ); + } else { + button = (<>{tagString}); + } + return button; +}; + +export const TagReaderButton: React.FC> = (props) => { + const { tag, /* index, __, pubId, onClickDeleteCb, */ onClickLinkCb } = props; let button = <>; let tagString = ""; @@ -32,42 +105,38 @@ export const TagButton: React.FC> = (props) => { } else { tagString = tag.name; } - +/* if (pubId && onClickDeleteCb && __) { button = ( <> {tagString} - ); - } else if (typeof tag === "object" && tag?.link?.length && onClickLinkCb) { + } else */if (typeof tag === "object" && tag?.link?.length && onClickLinkCb) { button = ( <> - this.props.link(tag.link[0], this.props.location, tag.name) - onClickLinkCb(tag) - } + this.props.link(tag.link[0], this.props.location, tag.name) + onClickLinkCb(tag)} > {tagString} ); } else { - button = ( - <> - {tagString} - - ); + button = (<>{tagString}); } - return button; }; + +const mapStateToProps = (state: ILibraryRootState) => ({ + location: state.router.location, +}); + diff --git a/src/renderer/common/components/dialog/publicationInfos/tag/tagList.tsx b/src/renderer/common/components/dialog/publicationInfos/tag/tagList.tsx index e7586d25c..c59050ab4 100644 --- a/src/renderer/common/components/dialog/publicationInfos/tag/tagList.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/tag/tagList.tsx @@ -8,7 +8,7 @@ import classNames from "classnames"; import * as React from "react"; import { IOpdsTagView } from "readium-desktop/common/views/opds"; -import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.css"; +import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.scss"; interface IProps { tagArray: string[] | IOpdsTagView[]; @@ -30,7 +30,7 @@ export const TagList: React.FC = (props) => { stylesTags.tag, // pointer hover style for IOpdsTagView links typeof tag === "string" || !tag.link?.length ? stylesTags.no_hover : undefined, - )}> + )}> { children(tag, index) } diff --git a/src/renderer/common/components/hoc/translator.tsx b/src/renderer/common/components/hoc/translator.tsx index fe5e3bbab..2924352d4 100644 --- a/src/renderer/common/components/hoc/translator.tsx +++ b/src/renderer/common/components/hoc/translator.tsx @@ -19,6 +19,29 @@ type TComponentConstructor

= React.ComponentClass

| React.FunctionComponen export function withTranslator(WrappedComponent: TComponentConstructor>) { const WrapperComponent = class extends React.Component, undefined> { public static displayName: string; + unsubscribe_: () => void | undefined; + + // from useTranslator.ts + // const [, forceUpdate] = React.useReducer(x => x + 1, 0); + // React.useEffect(() => { + // const handleLocaleChange = () => { + // forceUpdate(); + // }; + // return translator.subscribe(handleLocaleChange); + // }, [translator.subscribe]); + + constructor(props: React.PropsWithChildren) { + super(props); + + this.unsubscribe_ = undefined; + } + + componentWillUnmount(): void { + if (this.unsubscribe_) { + this.unsubscribe_(); + this.unsubscribe_ = undefined; + } + } public render() { @@ -37,6 +60,10 @@ export function withTranslator(WrappedComponent: TComponentConstructor { this.forceUpdate(); }); + } + const newProps = { ...this.props, __: translator.translate, diff --git a/src/renderer/common/components/menu/Menu.tsx b/src/renderer/common/components/menu/Menu.tsx index d8b584b1b..648203ed4 100644 --- a/src/renderer/common/components/menu/Menu.tsx +++ b/src/renderer/common/components/menu/Menu.tsx @@ -6,166 +6,40 @@ // ==LICENSE-END== import * as React from "react"; -import * as ReactDOM from "react-dom"; -import { v4 as uuidv4 } from "uuid"; -import MenuButton from "./MenuButton"; -import MenuContent from "./MenuContent"; -import { connect } from "react-redux"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; +import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.scss"; +import * as Popover from "@radix-ui/react-popover"; +import classNames from "classnames"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps { button: React.ReactElement; - content: React.ReactElement; - dir: string; // Direction of menu: right or left - focusMenuButton?: (ref: React.RefObject, currentMenuId: string) => void; } -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} - -interface IState { - contentStyle: React.CSSProperties; - menuOpen: boolean; -} - -class Menu extends React.Component { - - private backFocusMenuButtonRef: React.RefObject; - private contentRef: HTMLDivElement; - private menuId: string; - - constructor(props: IProps) { - super(props); - - this.backFocusMenuButtonRef = React.createRef(); - - this.state = { - contentStyle: {}, - menuOpen: false, - }; - this.menuId = "menu-" + uuidv4(); - this.doBackFocusMenuButton = this.doBackFocusMenuButton.bind(this); - this.setBackFocusMenuButton = this.setBackFocusMenuButton.bind(this); - this.toggleOpenMenu = this.toggleOpenMenu.bind(this); - } - - public componentDidUpdate(oldProps: IProps, oldState: IState) { - if (this.state.menuOpen && !oldState.menuOpen) { - this.refreshStyle(); - } - if (oldProps.infoDialogIsOpen === true && - oldProps.infoDialogIsOpen !== this.props.infoDialogIsOpen) { - this.doBackFocusMenuButton(); - } - } - - public render(): React.ReactElement<{}> { - const { button, dir, content } = this.props; - const contentStyle = this.state.contentStyle; - return ( - <> - - {button} - - { this.state.menuOpen ? - { this.contentRef = ref; }} - doBackFocusMenuButton={this.doBackFocusMenuButton} - > - setTimeout(this.toggleOpenMenu, 1)}> - {content} - - - : <> - } - - ); - } - - private toggleOpenMenu() { - this.setState({ menuOpen: !this.state.menuOpen }); - } - - private offset(el: HTMLElement) { - const rect = el.getBoundingClientRect(); - const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; - const scrollTop = window.pageYOffset || document.documentElement.scrollTop; - const right = window.innerWidth - (rect.right + 19) - scrollLeft; - return { - top: rect.top + scrollTop, - left: rect.left + scrollLeft, - right, - }; - } - - private refreshStyle() { - if (!this.backFocusMenuButtonRef?.current || !this.contentRef) { - return; - } - const contentStyle: React.CSSProperties = { - position: "absolute", - }; - - // calculate vertical position of the menu - const button = this.backFocusMenuButtonRef.current; - const buttonRect = button.getBoundingClientRect(); - const bottomPos = window.innerHeight - buttonRect.bottom; - const contentElement = ReactDOM.findDOMNode(this.contentRef) as HTMLElement; - const contentHeight = contentElement.getBoundingClientRect().height; - - if (bottomPos < contentHeight) { - contentStyle.top = Math.round(this.offset(button).top - contentHeight) + "px"; - } else { - contentStyle.top = Math.round(this.offset(button).top + buttonRect.height) + "px"; - } - - if (this.props.dir === "right") { - contentStyle.right = Math.round(this.offset(button).right) + "px"; - } else { - contentStyle.left = Math.round(this.offset(button).left) + "px"; - } - - this.setState({ contentStyle }); - } - - private setBackFocusMenuButton(currentRef: React.RefObject, currentMenuId: string) { - if (currentRef?.current && this.menuId === currentMenuId) { - this.backFocusMenuButtonRef = currentRef; - } - } - - private doBackFocusMenuButton() { - if (this.backFocusMenuButtonRef?.current) { - this.backFocusMenuButtonRef.current.focus(); - } - } -} - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => { - return { - infoDialogIsOpen: state.dialog.open - && (state.dialog.type === DialogTypeName.PublicationInfoOpds - || state.dialog.type === DialogTypeName.PublicationInfoLib - || state.dialog.type === DialogTypeName.DeletePublicationConfirm), - }; +const Menu = (props: React.PropsWithChildren) => { + + const [triggerOpen, setTriggerOpen] = React.useState(false); + + const collisionValue = location.hash === "#/home" ? 10 : 280; + const collision: Partial> = {top : collisionValue}; + + return ( + setTriggerOpen(!triggerOpen)}> + + + + + +

+ {props.children} +
+ + + + + ); }; -export default connect(mapStateToProps)(Menu); +export default (Menu); diff --git a/src/renderer/common/components/menu/MenuButton.tsx b/src/renderer/common/components/menu/MenuButton.tsx deleted file mode 100644 index cfe95f7c1..000000000 --- a/src/renderer/common/components/menu/MenuButton.tsx +++ /dev/null @@ -1,62 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps { - menuId: string; - open: boolean; - toggle: () => void; - setBackFocusMenuButton?: (ref: React.RefObject, menuID: string) => void; -} - -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps { -} - -export default class MenuButton extends React.Component, undefined> { - private backFocusMenuButtonRef: React.RefObject; - - constructor(props: IProps) { - super(props); - this.backFocusMenuButtonRef = React.createRef(); - - this.setBackFocusMenuButton = this.setBackFocusMenuButton.bind(this); - } - - public componentDidMount() { - this.setBackFocusMenuButton(); - } - public componentDidUpdate(_oldProps: IProps) { - this.setBackFocusMenuButton(); - } - - public render(): React.ReactElement<{}> { - const { toggle, open, menuId, children } = this.props; - return ( - - ); - } - - public setBackFocusMenuButton() { - if (this.backFocusMenuButtonRef?.current && this.props.open) { - this.props.setBackFocusMenuButton(this.backFocusMenuButtonRef, this.props.menuId); - } - } -} diff --git a/src/renderer/common/components/menu/MenuContent.tsx b/src/renderer/common/components/menu/MenuContent.tsx deleted file mode 100644 index 2ec82f066..000000000 --- a/src/renderer/common/components/menu/MenuContent.tsx +++ /dev/null @@ -1,83 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; -import * as ReactDOM from "react-dom"; - -import AccessibleMenu from "./AccessibleMenu"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps { - id: string; - open: boolean; - dir: string; - menuStyle: React.CSSProperties; // {[key: string]: string}; - toggle: () => void; - doBackFocusMenuButton?: () => void; - setContentRef?: (ref: HTMLDivElement) => void; -} - -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps { -} - -export default class MenuContent extends React.Component, undefined> { - private appElement: HTMLElement; - private appOverlayElement: HTMLElement; - private rootElement: HTMLElement; - - constructor(props: IProps) { - super(props); - - this.appElement = document.getElementById("app"); - this.appOverlayElement = document.getElementById("app-overlay"); - this.rootElement = document.createElement("div"); - } - - public componentDidMount() { - this.appElement.setAttribute("aria-hidden", "true"); - this.appOverlayElement.appendChild(this.rootElement); - } - - public componentWillUnmount() { - this.appElement.setAttribute("aria-hidden", "false"); - this.appOverlayElement.removeChild(this.rootElement); - } - - public render() { - const { open, toggle, setContentRef } = this.props; - return ReactDOM.createPortal( - ( - - - - ), - this.rootElement, - ); - } -} diff --git a/src/renderer/common/components/toast/Toast.tsx b/src/renderer/common/components/toast/Toast.tsx index 99201b144..eb3e95de1 100644 --- a/src/renderer/common/components/toast/Toast.tsx +++ b/src/renderer/common/components/toast/Toast.tsx @@ -11,8 +11,9 @@ import * as React from "react"; import { ToastType } from "readium-desktop/common/models/toast"; import { _APP_NAME } from "readium-desktop/preprocessor-directives"; import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as stylesToasts from "readium-desktop/renderer/assets/styles/components/toasts.css"; +import * as stylesToasts from "readium-desktop/renderer/assets/styles/components/toasts.scss"; import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as ChevronDownIcon from "readium-desktop/renderer/assets/icons/chevron-down.svg"; import { TranslatorProps, withTranslator } from "../hoc/translator"; @@ -40,6 +41,7 @@ interface IProps extends IBaseProps { interface IState { willLeave: boolean; toRemove: boolean; + opened: boolean; } export class Toast extends React.Component { @@ -55,6 +57,7 @@ export class Toast extends React.Component { this.state = { willLeave: false, toRemove: false, + opened: false, }; this.handleTransitionEnd = this.handleTransitionEnd.bind(this); @@ -133,9 +136,16 @@ export class Toast extends React.Component { }} onClick={() => { this.cancelTimer(true); + this.setState({ opened : !this.state.opened }); }} onMouseOut={() => { this.triggerTimer(true); + + }} + onBlur={() => { + this.ignoreTimer = false; + this.setState({ opened : false }); + this.triggerTimer(true); }} className={classNames( stylesToasts.toast, @@ -152,6 +162,7 @@ export class Toast extends React.Component { aria-relevant="all" role="alert" tabIndex={0} + className={ this.state.opened ? stylesToasts.toast_open : ""} onFocus={() => { this.cancelTimer(true); }} @@ -181,11 +192,17 @@ export class Toast extends React.Component { onFocus={() => { this.cancelTimer(true); }} - onClick={() => this.handleClose()} + onClick={(e) => { + e.stopPropagation(); + this.handleClose(); + }} className={stylesToasts.closeButton} title={this.props.__("accessibility.closeDialog")} > - + {this.state.opened ? + + : + }
); @@ -193,6 +210,7 @@ export class Toast extends React.Component { private handleClose() { this.setState({ willLeave: true }); + this.setState({ opened : false }); } private handleTransitionEnd() { diff --git a/src/renderer/common/components/toast/ToastManager.tsx b/src/renderer/common/components/toast/ToastManager.tsx index 52966e99c..8715a05f7 100644 --- a/src/renderer/common/components/toast/ToastManager.tsx +++ b/src/renderer/common/components/toast/ToastManager.tsx @@ -10,7 +10,7 @@ import { connect } from "react-redux"; import { ToastType } from "readium-desktop/common/models/toast"; import { IRendererCommonRootState } from "readium-desktop/common/redux/states/rendererCommonRootState"; import { ToastState } from "readium-desktop/common/redux/states/toast"; -import * as stylesToasts from "readium-desktop/renderer/assets/styles/components/toasts.css"; +import * as stylesToasts from "readium-desktop/renderer/assets/styles/components/toasts.scss"; import { v4 as uuidv4 } from "uuid"; import { TranslatorProps, withTranslator } from "../hoc/translator"; diff --git a/src/renderer/library/components/App.tsx b/src/renderer/library/components/App.tsx index 22121156f..5e8f6f92a 100644 --- a/src/renderer/library/components/App.tsx +++ b/src/renderer/library/components/App.tsx @@ -15,7 +15,7 @@ import { Provider } from "react-redux"; import { acceptedExtension, acceptedExtensionObject } from "readium-desktop/common/extension"; import { DialogTypeName } from "readium-desktop/common/models/dialog"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; +import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.scss"; import ToastManager from "readium-desktop/renderer/common/components/toast/ToastManager"; import { ensureKeyboardListenerIsInstalled } from "readium-desktop/renderer/common/keyboard"; import { TranslatorContext } from "readium-desktop/renderer/common/translator.context"; @@ -29,8 +29,8 @@ import { toastActions } from "readium-desktop/common/redux/actions"; import { ToastType } from "readium-desktop/common/models/toast"; import { acceptedExtensionArray } from "readium-desktop/common/extension"; -import Nunito from "readium-desktop/renderer/assets/fonts/nunito.ttf"; -import NunitoBold from "readium-desktop/renderer/assets/fonts/nunitoBold.ttf"; +import Nunito from "readium-desktop/renderer/assets/fonts/NunitoSans_10pt-Regular.ttf"; +import NunitoBold from "readium-desktop/renderer/assets/fonts/NunitoSans_10pt-SemiBold.ttf"; import * as globalScssStyle from "readium-desktop/renderer/assets/styles/global.scss"; globalScssStyle.__LOAD_FILE_SELECTOR_NOT_USED_JUST_TO_TRIGGER_WEBPACK_SCSS_FILE__; @@ -86,6 +86,9 @@ export default class App extends React.Component<{}, undefined> { public async componentDidMount() { ensureKeyboardListenerIsInstalled(); + + const store = diLibraryGet("store"); // diRendererSymbolTable.store + document.body.setAttribute("data-theme", store.getState().theme.name); } public render(): React.ReactElement<{}> { diff --git a/src/renderer/library/components/DownloadsPanel.tsx b/src/renderer/library/components/DownloadsPanel.tsx index 49ae3c2d7..1e897deb1 100644 --- a/src/renderer/library/components/DownloadsPanel.tsx +++ b/src/renderer/library/components/DownloadsPanel.tsx @@ -8,12 +8,14 @@ import * as React from "react"; import { connect } from "react-redux"; import { downloadActions } from "readium-desktop/common/redux/actions"; -import * as stylesApp from "readium-desktop/renderer/assets/styles/app.css"; +import * as stylesApp from "readium-desktop/renderer/assets/styles/app.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { TDispatch } from "readium-desktop/typings/redux"; +import * as CloseIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -50,7 +52,7 @@ class DownloadsPanel extends React.Component { progress = 0; } return
  • - abortDownload(id)}>X + abortDownload(id)}> {progress}% {progress} {dl.downloadUrl} diff --git a/src/renderer/library/components/LoaderMainLoad.tsx b/src/renderer/library/components/LoaderMainLoad.tsx index e0955e4e2..cc69e6ce4 100644 --- a/src/renderer/library/components/LoaderMainLoad.tsx +++ b/src/renderer/library/components/LoaderMainLoad.tsx @@ -8,7 +8,7 @@ import * as React from "react"; import { connect } from "react-redux"; import * as LoaderIcon from "readium-desktop/renderer/assets/icons/loader.svg"; -import * as stylesLoader from "readium-desktop/renderer/assets/styles/loader.css"; +import * as stylesLoader from "readium-desktop/renderer/assets/styles/loader.scss"; import SVG from "readium-desktop/renderer/common/components/SVG"; import { ILibraryRootState } from "../../../common/redux/states/renderer/libraryRootState"; diff --git a/src/renderer/library/components/SecondaryHeader.tsx b/src/renderer/library/components/SecondaryHeader.tsx index 734c69fc9..c62173779 100644 --- a/src/renderer/library/components/SecondaryHeader.tsx +++ b/src/renderer/library/components/SecondaryHeader.tsx @@ -6,7 +6,7 @@ // ==LICENSE-END== import * as React from "react"; -import * as stylesHeader from "readium-desktop/renderer/assets/styles/header.css"; +import * as stylesHeader from "readium-desktop/renderer/assets/styles/header.scss"; import { TranslatorProps, withTranslator } from "../../common/components/hoc/translator"; diff --git a/src/renderer/library/components/catalog/AboutThoriumButton.tsx b/src/renderer/library/components/catalog/AboutThoriumButton.tsx index a9939ca7f..9d770da9d 100644 --- a/src/renderer/library/components/catalog/AboutThoriumButton.tsx +++ b/src/renderer/library/components/catalog/AboutThoriumButton.tsx @@ -13,8 +13,7 @@ import { ABOUT_BOOK_TITLE_PREFIX } from "readium-desktop/common/constant"; import { readerActions } from "readium-desktop/common/redux/actions"; import { PublicationView } from "readium-desktop/common/views/publication"; import { _APP_NAME, _APP_VERSION, _PACKAGING } from "readium-desktop/preprocessor-directives"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesFooter from "readium-desktop/renderer/assets/styles/components/aboutFooter.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -53,17 +52,14 @@ class AboutThoriumButton extends React.Component { public render() { const { __ } = this.props; return ( -
    -
    -

    {__("catalog.about.title", { appName: capitalizedAppName })}

    - -
    -

    {`v${_APP_VERSION}`}

    +
    + { + if (e.key === "Enter") { + this.about(); + } + }} + tabIndex={0}>{__("catalog.about.title", { appName: capitalizedAppName })} +

    - {`v${_APP_VERSION}`}

    ); } diff --git a/src/renderer/library/components/catalog/Catalog.tsx b/src/renderer/library/components/catalog/Catalog.tsx index 33841b13e..7532057e8 100644 --- a/src/renderer/library/components/catalog/Catalog.tsx +++ b/src/renderer/library/components/catalog/Catalog.tsx @@ -15,12 +15,15 @@ import { } from "readium-desktop/renderer/common/redux/api/api"; import LibraryLayout from "readium-desktop/renderer/library/components/layout/LibraryLayout"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DisplayType, IRouterLocationState } from "readium-desktop/renderer/library/routing"; import { Dispatch } from "redux"; import CatalogGridView from "./GridView"; -import Header from "./Header"; -import CatalogListView from "./ListView"; +import PublicationAddButton from "./PublicationAddButton"; +import { + ensureKeyboardListenerIsInstalled, registerKeyboardListener, unregisterKeyboardListener, +} from "readium-desktop/renderer/common/keyboard"; +import { IRouterLocationState, dispatchHistoryPush } from "../../routing"; +import { keyboardShortcutsMatch } from "readium-desktop/common/keyboard"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -36,45 +39,80 @@ interface IProps extends IBaseProps, class Catalog extends React.Component { + constructor(props: IProps) { + super(props); + + this.onKeyboardFocusSearch = this.onKeyboardFocusSearch.bind(this); + } + + componentDidMount(): void { + ensureKeyboardListenerIsInstalled(); + this.registerAllKeyboardListeners(); + } + + componentWillUnmount(): void { + this.unregisterAllKeyboardListeners(); + } + + componentDidUpdate(oldProps: Readonly): void { + if (!keyboardShortcutsMatch(oldProps.keyboardShortcuts, this.props.keyboardShortcuts)) { + this.unregisterAllKeyboardListeners(); + this.registerAllKeyboardListeners(); + } + } + public render(): React.ReactElement<{}> { const { __, catalog, tags } = this.props; - const displayType = (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) || DisplayType.Grid; - - const secondaryHeader =
    ; + const secondaryHeader = ; return ( { catalog?.entries - && ( - displayType === DisplayType.Grid - ? - : - ) } ); } + + private registerAllKeyboardListeners() { + registerKeyboardListener( + true, // listen for key up (not key down) + this.props.keyboardShortcuts.FocusSearch, + this.onKeyboardFocusSearch); + } + + private unregisterAllKeyboardListeners() { + unregisterKeyboardListener(this.onKeyboardFocusSearch); + } + + private onKeyboardFocusSearch = () => { + this.props.historyPush({ + ...this.props.location, + search: "?focus=search", + pathname: "/library", + + }, this.props.location.state as IRouterLocationState); + }; } const mapStateToProps = (state: ILibraryRootState) => ({ location: state.router.location, catalog: state.publication.catalog, tags: state.publication.tag, + keyboardShortcuts: state.keyboard.shortcuts, }); const mapDispatchToProps = (dispatch: Dispatch) => ({ api: apiDispatch(dispatch), apiClean: apiClean(dispatch), + historyPush: dispatchHistoryPush(dispatch), }); export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(Catalog)); diff --git a/src/renderer/library/components/catalog/GridTagButton.tsx b/src/renderer/library/components/catalog/GridTagButton.tsx index 9c01d321d..64854d719 100644 --- a/src/renderer/library/components/catalog/GridTagButton.tsx +++ b/src/renderer/library/components/catalog/GridTagButton.tsx @@ -9,9 +9,9 @@ import { encodeURIComponent_RFC3986 } from "r2-utils-js/dist/es8-es2017/src/_uti import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; -import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.css"; +import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.scss"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DisplayType, IRouterLocationState } from "../../routing"; +import { DisplayType } from "../../routing"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps { @@ -37,9 +37,11 @@ class GridTagButton extends React.Component { {this.props.name} diff --git a/src/renderer/library/components/catalog/GridView.tsx b/src/renderer/library/components/catalog/GridView.tsx index f79432482..6ea0100cd 100644 --- a/src/renderer/library/components/catalog/GridView.tsx +++ b/src/renderer/library/components/catalog/GridView.tsx @@ -7,11 +7,9 @@ import * as React from "react"; import { connect } from "react-redux"; -import { Link } from "react-router-dom"; import { CatalogEntryView } from "readium-desktop/common/views/catalog"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesSlider from "readium-desktop/renderer/assets/styles/components/slider.css"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylesSlider from "readium-desktop/renderer/assets/styles/components/slider.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -21,9 +19,16 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ import AboutThoriumButton from "./AboutThoriumButton"; import NoPublicationInfo from "./NoPublicationInfo"; -import SortMenu from "./SortMenu"; -import TagLayout from "./TagLayout"; -import { DisplayType, IRouterLocationState } from "../../routing"; +// import SortMenu from "./SortMenu"; +// import TagLayout from "./TagLayout"; +import classNames from "classnames"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/info-icon.svg"; +import * as CloseIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import { _APP_NAME, _APP_VERSION } from "readium-desktop/preprocessor-directives"; + +const capitalizedAppName = _APP_NAME.charAt(0).toUpperCase() + _APP_NAME.substring(1); // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -42,6 +47,7 @@ interface IProps extends IBaseProps, ReturnType { interface IState { tabTags: string[]; status: SortStatus; + versionInfo: boolean; } enum SortStatus { @@ -49,6 +55,48 @@ enum SortStatus { Alpha, } +const EntrySection = ({entry, entryIndex}: {entry: CatalogEntryView, entryIndex: number}) => { + const [__] = useTranslator(); + let title = ""; + + switch (entry.id) { + case "lastAdditions": + title = __("catalog.entry.lastAdditions"); + break; + case "continueReading": + title = __("catalog.entry.continueReading"); + break; + case "continueReadingAudioBooks": + title = __("catalog.entry.continueReadingAudioBooks"); + break; + case "continueReadingDivina": + title = __("catalog.entry.continueReadingDivina"); + break; + case "continueReadingPdf": + title = __("catalog.entry.continueReadingPdf"); + break; + } + + return ( +
    +

    {title}

    + { + + , + )} + /> + } + +
    + ); +}; + class CatalogGridView extends React.Component { constructor(props: IProps) { @@ -57,6 +105,7 @@ class CatalogGridView extends React.Component { this.state = { tabTags: this.props.tags ? this.props.tags.slice() : [], status: SortStatus.Count, + versionInfo: false, }; this.sortByAlpha = this.sortByAlpha.bind(this); this.sortbyCount = this.sortbyCount.bind(this); @@ -87,37 +136,7 @@ class CatalogGridView extends React.Component { this.props.catalogEntries.map((entry, entryIndex: number) => entry.totalCount > 0 ? ( -
    - { - -
    -

    {entry.title}

    - - {this.props.__("header.allBooks")} - -
    - } - { - - , - )} - /> - } - -
    + ) :
    { ) } { - this.state.tabTags.length > 0 - ? } - /> - : <> + this.state.versionInfo ? +
    + + +
    + : <> } { this.state.tabTags.length === 0 && catalogEntriesIsEmpty diff --git a/src/renderer/library/components/catalog/Header.tsx b/src/renderer/library/components/catalog/Header.tsx index 33f180506..a214ce336 100644 --- a/src/renderer/library/components/catalog/Header.tsx +++ b/src/renderer/library/components/catalog/Header.tsx @@ -6,13 +6,15 @@ // ==LICENSE-END== // import * as SearchIcon from "readium-desktop/renderer/assets/icons/baseline-search-24px-grey.svg"; -import * as magnifyingGlass from "readium-desktop/renderer/assets/icons/magnifying_glass.svg"; +// import * as magnifyingGlass from "readium-desktop/renderer/assets/icons/magnifying_glass.svg"; import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; -import * as GridIcon from "readium-desktop/renderer/assets/icons/grid.svg"; -import * as ListIcon from "readium-desktop/renderer/assets/icons/list.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as GridIcon from "readium-desktop/renderer/assets/icons/grid-icon.svg"; +// import * as ListIcon from "readium-desktop/renderer/assets/icons/list-icon.svg"; +import * as TableIcon from "readium-desktop/renderer/assets/icons/table-icon.svg"; +import * as CheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -23,7 +25,7 @@ import { DisplayType, IRouterLocationState } from "readium-desktop/renderer/libr import PublicationAddButton from "./PublicationAddButton"; -import SearchForm from "./SearchForm"; +// import SearchForm from "./SearchForm"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -49,61 +51,76 @@ class Header extends React.Component { return ( - - - - - - - { +
    +

    {__("header.viewMode")}

    +
    + + {(displayType === DisplayType.Grid) ? + : + + } +

    {__("header.gridTitle")}

    + + + {(displayType === DisplayType.List) ? + : + + } +

    {__("header.listTitle")}

    + +
    +
    +
    + + {/* { window.location.hash.indexOf("search") === -1 ? -
    - - - { - <> - {this.props.__("header.searchPlaceholder")} - - - } - - -
    + <> + + + { + <> + +

    {this.props.__("header.searchPlaceholder")}

    + + } + + : <> - } + } */} +
    ); } diff --git a/src/renderer/library/components/catalog/ListView.tsx b/src/renderer/library/components/catalog/ListView.tsx index a07382d0c..e9ca352a5 100644 --- a/src/renderer/library/components/catalog/ListView.tsx +++ b/src/renderer/library/components/catalog/ListView.tsx @@ -9,9 +9,9 @@ import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; import { CatalogEntryView } from "readium-desktop/common/views/catalog"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -55,16 +55,16 @@ class CatalogListView extends React.Component {
    {
    -

    { entry.title }

    +

    { entry.id }

    {this.props.__("header.allBooks")} diff --git a/src/renderer/library/components/catalog/NoPublicationInfo.tsx b/src/renderer/library/components/catalog/NoPublicationInfo.tsx index dcdafd71c..829331840 100644 --- a/src/renderer/library/components/catalog/NoPublicationInfo.tsx +++ b/src/renderer/library/components/catalog/NoPublicationInfo.tsx @@ -7,9 +7,13 @@ import * as React from "react"; import { acceptedExtensionArray } from "readium-desktop/common/extension"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; +// import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; import { TranslatorProps, withTranslator } from "../../../common/components/hoc/translator"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as EmptyLibraryIcon from "readium-desktop/renderer/assets/icons/emptylibrary-icon.svg"; +import * as EmptyLibraryBgIcon from "readium-desktop/renderer/assets/icons/emptylibrary-background-icon.svg"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -32,7 +36,7 @@ class NoPublicationInfo extends React.Component { const { __ } = this.props; return ( <> -
    + {/*

    {__("catalog.noPublicationHelpL1")}

    {__("catalog.noPublicationHelpL2")}

    {__("catalog.noPublicationHelpL3")}

    @@ -49,6 +53,34 @@ class NoPublicationInfo extends React.Component { ) }

    +
    */} +
    + + +
    +

    {__("catalog.noPublicationHelpL1")}

    +

    {__("catalog.noPublicationHelpL2")}

    + {/*

    {__("catalog.noPublicationHelpL3")}

    */} +
    + + {__("catalog.noPublicationHelpL4")} + +
    + {__("catalog.noPublicationHelpL3")} +
    + { + acceptedExtensionArray.map( + (ext, i) => +

    { + ext + }

    + {i < acceptedExtensionArray.length - 1 ? " | " : ""} +
    , + )} +
    +
    +
    +
    ); diff --git a/src/renderer/library/components/catalog/PublicationAddButton.tsx b/src/renderer/library/components/catalog/PublicationAddButton.tsx index 9e508660b..1771048f6 100644 --- a/src/renderer/library/components/catalog/PublicationAddButton.tsx +++ b/src/renderer/library/components/catalog/PublicationAddButton.tsx @@ -5,12 +5,11 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { acceptedExtensionArray, acceptedExtensionObject } from "readium-desktop/common/extension"; import * as PlusIcon from "readium-desktop/renderer/assets/icons/baseline-add-24px.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import SVG from "readium-desktop/renderer/common/components/SVG"; import { apiDispatch } from "readium-desktop/renderer/common/redux/api/api"; import { TChangeEventOnInput } from "readium-desktop/typings/react"; @@ -44,9 +43,10 @@ export class PublicationAddButton extends React.Component { // htmlFor="epubInput" return (
  • ; +}; - return ( - -
    -
    - { - if (e.key === "Enter") { - this.search(undefined); - // e.preventDefault(); - e.stopPropagation(); - } - }} - /> - -
    -
    - { - listItems.length - ?
      - {listItems} -
    - : - this.state.query ? __("apiapp.noLibraryFound", { name: this.state.query }) : <> - } -
    -
    -
    - ); - } +const ApiappAddForm = () => { + const [__] = useTranslator(); + const searchInputRef = React.useRef(); + const [infoOpen, setInfoOpen] = React.useState(false); + + const ItemListWithStyle = () => +
    + { + searchResultView?.length ?
      + {searchResultView.map((v) => )} +
    + : searchInputRef?.current?.value ? __("apiapp.noLibraryFound", { name: searchInputRef?.current.value }) : <> + } +
    ; - private addDoubleClick = (e: React.UIEvent) => { - e.preventDefault(); - this.add(); - this.props.closeDialog(); - }; + const [resultApiAppSearchAction, apiAppSearchAction] = useApi(undefined, "apiapp/search"); + const searchResultView = resultApiAppSearchAction?.data?.result || []; - private add = () => { - if (!this.state.selectSearchResult?.name || !this.state.selectSearchResult?.id || !this.state.selectSearchResult?.url) { - return; - } - const title = this.state.selectSearchResult.name; - const url = `apiapp://${this.state.selectSearchResult.id}:apiapp:${this.state.selectSearchResult.url}`; - apiAction("opds/addFeed", { title, url }).catch((err) => { - console.error("Error to fetch api opds/addFeed", err); - }); + const openInfo = (e: any) => { + e.preventDefault(); + setInfoOpen(!infoOpen); }; - private search: React.MouseEventHandler = (e) => { - e?.preventDefault(); // undefined on enter keydown input search - - const value = this.inputRef?.current?.value; - this.setState({ query: "" }); + return ( +
    +
    +
    + + { + if (e.key === "Enter") { + e.stopPropagation(); + e.preventDefault(); + const v = searchInputRef.current?.value; + if (!v) return ; + apiAppSearchAction(v); + // e.preventDefault(); + // e.stopPropagation(); + } + }} + /> +
    + +
    + +
    + + { infoOpen ? +
    +

    + {__("apiapp.informations")} +

    + + {__("apiapp.documentation")} + + +
    + : <>} +
    +
    + ); +}; - if (value && typeof value === "string") { - apiAction("apiapp/search", value) - .then((searchResultView) => { - this.setState({ searchResultView }); - this.setState({ query: value }); - }) - .catch((error) => console.error("Error to fetch api apiapp/search", error)); +export const ApiappAddFormDialog = () => { + const [__] = useTranslator(); + const [, apiAddFeedAction] = useApi(undefined, "opds/addFeed"); + const [selectSearchResult, setSelectSearchResult] = React.useState(undefined); + const addFeedAction = React.useCallback(() => { + if (!selectSearchResult?.name || !selectSearchResult?.id || !selectSearchResult?.url) { + return; } - }; -} - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - closeDialog: () => { - dispatch( - dialogActions.closeRequest.build(), - ); - }, - }; + const title = selectSearchResult.name; + const url = `apiapp://${selectSearchResult.id}:apiapp:${selectSearchResult.url}`; + apiAddFeedAction({title, url}); + }, [selectSearchResult, apiAddFeedAction]); + + const submitButtonRef = React.useRef(); + const contextValue = {selectSearchResult, setSelectSearchResult, submitAction: () => submitButtonRef.current.click()}; + + return + + + + +
    + +
    + + {__("opds.addFormApiapp.title")} + +
    + + + +
    +
    +
    + +
    + +
    +
    + + + + + + +
    +
    +
    +
    +
    +
    ; }; -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.ApiappAddForm, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(ApiappAddForm)); +export default ApiappAddFormDialog; diff --git a/src/renderer/library/components/dialog/DeleteOpdsFeedConfirm.tsx b/src/renderer/library/components/dialog/DeleteOpdsFeedConfirm.tsx index 6ebedfbd3..10b81f9dd 100644 --- a/src/renderer/library/components/dialog/DeleteOpdsFeedConfirm.tsx +++ b/src/renderer/library/components/dialog/DeleteOpdsFeedConfirm.tsx @@ -6,64 +6,53 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} - -class DeleteOpdsFeedConfirm extends React.Component { - - constructor(props: IProps) { - super(props); - } - - public render(): React.ReactElement<{}> { - if (!this.props.open || !this.props.feed) { - return (<>); - } - - const { __ } = this.props; - return ( - -

    - {this.props.feed.title} -

    -
    - ); - } - - private remove = () => { - apiAction("opds/deleteFeed", this.props.feed.identifier).catch((error) => { - console.error("Error to fetch opds/deleteFeed", error); - }); - }; -} - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.DeleteOpdsFeedConfirm, - feed: (state.dialog.data as DialogType[DialogTypeName.DeleteOpdsFeedConfirm]).feed, -}); - -export default connect(mapStateToProps)(withTranslator(DeleteOpdsFeedConfirm)); +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import { IOpdsFeedView } from "readium-desktop/common/views/opds"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import { useApi } from "readium-desktop/renderer/common/hooks/useApi"; +import { useDispatch } from "react-redux"; +import { dialogActions } from "readium-desktop/common/redux/actions"; +import * as stylesAlertModals from "readium-desktop/renderer/assets/styles/components/alert.modals.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; + +const DeleteOpdsFeedConfirm = (props: { feed: IOpdsFeedView, trigger: React.ReactNode } & AlertDialog.AlertDialogProps) => { + const [__] = useTranslator(); + const [_, remove] = useApi(undefined, "opds/deleteFeed"); + const dispatch = useDispatch(); + const removeAction = React.useCallback(() => { + dispatch(dialogActions.closeRequest.build()); + remove(props.feed.identifier); + }, [remove, props.feed.identifier]); + + return ( + + + {props.trigger} + + +
    + + {__("dialog.deleteFeed")} + + {props.feed.title} + +
    + + + + + + +
    +
    +
    +
    + ); + +}; + +export default DeleteOpdsFeedConfirm; diff --git a/src/renderer/library/components/dialog/DeletePublicationConfirm.tsx b/src/renderer/library/components/dialog/DeletePublicationConfirm.tsx index f73a222d1..ada14b7d4 100644 --- a/src/renderer/library/components/dialog/DeletePublicationConfirm.tsx +++ b/src/renderer/library/components/dialog/DeletePublicationConfirm.tsx @@ -6,65 +6,58 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} - -class DeletePublicationConfirm extends React.Component { - - constructor(props: IProps) { - super(props); - - } - - public render(): React.ReactElement<{}> { - if (!this.props.open || !this.props.publicationView) { - return <>; - } - - const { __ } = this.props; - return ( - -

    - {this.props.publicationView.documentTitle} -

    -
    - ); - } - - private remove = () => { - apiAction("publication/delete", this.props.publicationView.identifier).catch((error) => { - console.error("Error to fetch publication/delete", error); - }); - }; -} - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.DeletePublicationConfirm, - publicationView: (state.dialog.data as DialogType[DialogTypeName.DeletePublicationConfirm]).publicationView, -}); - -export default connect(mapStateToProps)(withTranslator(DeletePublicationConfirm)); +import { PublicationView } from "readium-desktop/common/views/publication"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import { useApi } from "readium-desktop/renderer/common/hooks/useApi"; +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import * as stylesAlertModals from "readium-desktop/renderer/assets/styles/components/alert.modals.scss"; +import { useDispatch } from "readium-desktop/renderer/common/hooks/useDispatch"; +import { dialogActions } from "readium-desktop/common/redux/actions"; +import SVG from "../../../common/components/SVG"; +import * as Trash from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; + + +const DeletePublicationConfirm = (props: { publicationView: PublicationView, trigger: React.ReactNode } & AlertDialog.AlertDialogProps) => { + const [__] = useTranslator(); + const [_, remove] = useApi(undefined, "publication/delete"); + const dispatch = useDispatch(); + const removeAction = React.useCallback(() => { + dispatch(dialogActions.closeRequest.build()); + remove(props.publicationView.identifier); + }, [remove, props.publicationView.identifier]); + + return ( + + + {props.trigger} + + + + {/** Overlay Component doesn't work */} + {/* */} +
    + + {__("dialog.deletePublication")} + + {props.publicationView.documentTitle} + +
    + + + + + + +
    +
    +
    +
    + ); + +}; + +export default DeletePublicationConfirm; diff --git a/src/renderer/library/components/dialog/DialogManager.tsx b/src/renderer/library/components/dialog/DialogManager.tsx index 670023217..7d53bac15 100644 --- a/src/renderer/library/components/dialog/DialogManager.tsx +++ b/src/renderer/library/components/dialog/DialogManager.tsx @@ -7,18 +7,10 @@ import * as React from "react"; import { connect } from "react-redux"; -import PublicationInfo from "readium-desktop/renderer/library/components/dialog/publicationInfos/PublicationInfo"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import ApiappAddForm from "./ApiappAddForm"; -import DeleteOpdsFeedConfirm from "./DeleteOpdsFeedConfirm"; -import DeletePublicationConfirm from "./DeletePublicationConfirm"; import FileImport from "./FileImport"; import LcpAuthentication from "./LcpAuthentication"; -import OpdsFeedAddForm from "./OpdsFeedAddForm"; -import OpdsFeedUpdateForm from "./OpdsFeedUpdateForm"; -import RenewLsdConfirm from "./RenewLsdConfirm"; -import ReturnLsdConfirm from "./ReturnLsdConfirm"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps { @@ -46,16 +38,8 @@ class DialogManager extends React.Component { return ( <> - - - - - - - - ); diff --git a/src/renderer/library/components/dialog/FileImport.tsx b/src/renderer/library/components/dialog/FileImport.tsx index 58c849dfc..bd39f6712 100644 --- a/src/renderer/library/components/dialog/FileImport.tsx +++ b/src/renderer/library/components/dialog/FileImport.tsx @@ -9,13 +9,18 @@ import * as React from "react"; import { connect } from "react-redux"; import { acceptedExtensionArray } from "readium-desktop/common/extension"; import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; +import * as stylesAlertModals from "readium-desktop/renderer/assets/styles/components/alert.modals.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import classNames from "classnames"; +import { TDispatch } from "readium-desktop/typings/redux"; +import { dialogActions } from "readium-desktop/common/redux/actions"; +import * as AddIcon from "readium-desktop/renderer/assets/icons/add-alone.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -25,7 +30,7 @@ interface IBaseProps extends TranslatorProps { // ReturnType // ReturnType // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { +interface IProps extends IBaseProps, ReturnType, ReturnType { } class FileImport extends React.Component { @@ -40,40 +45,58 @@ class FileImport extends React.Component { } const { files } = this.props; - return ( - - { - (!files || files.length === 0) ? - ( -
    - { - this.props.__("dialog.importError", { - acceptedExtension: acceptedExtensionArray.join(" "), - }) - } -
    - ) : ( -
    -
    -

    {this.props.__("dialog.import")}

    -
      - {files.map((file, i) =>
    • {file.name}
    • )} -
    -
    -
    -
    -
    - ) - } -
    - ); + + return !b ? this.props.closeDialog() : undefined}> + +
    + + + {(files?.length > 0) ? + this.props.__("dialog.import") + : + this.props.__("catalog.addBookToLib") + } + + + { + // useless ?? + (!files || files.length === 0) ? + ( + //
    + <> + { + this.props.__("dialog.importError", { + acceptedExtension: acceptedExtensionArray.join(" "), + }) + } + + //
    + ) : ( + //
    +
    +
      + {files.map((file, i) =>
    • {file.name}
    • )} +
    +
    + //
    + //
    + //
    + ) + } +
    +
    + + + + + + +
    +
    +
    +
    ; } private importFiles = () => { @@ -93,4 +116,16 @@ const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ files: (state.dialog.data as DialogType[DialogTypeName.FileImport]).files, }); -export default connect(mapStateToProps)(withTranslator(FileImport)); +const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { + return { + closeDialog: () => { + dispatch( + dialogActions.closeRequest.build(), + ); + }, + }; +}; + + + +export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(FileImport)); diff --git a/src/renderer/library/components/dialog/LcpAuthentication.tsx b/src/renderer/library/components/dialog/LcpAuthentication.tsx index 05d4bab70..958c8b085 100644 --- a/src/renderer/library/components/dialog/LcpAuthentication.tsx +++ b/src/renderer/library/components/dialog/LcpAuthentication.tsx @@ -6,11 +6,22 @@ // ==LICENSE-END== import * as React from "react"; +import * as Dialog from "@radix-ui/react-dialog"; import { connect } from "react-redux"; import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; +// import * as InfoIcon from "readium-desktop/renderer/assets/icons/outline-info-24px.svg"; +// import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +// import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; +import * as FollowLinkIcon from "readium-desktop/renderer/assets/icons/followLink-icon.svg"; +import * as CrossIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import * as PassIcon from "readium-desktop/renderer/assets/icons/password-icon.svg"; +import * as LightBulbIcon from "readium-desktop/renderer/assets/icons/lightbulb-icon.svg"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -18,6 +29,8 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ import { TChangeEventOnInput } from "readium-desktop/typings/react"; import { TDispatch } from "readium-desktop/typings/redux"; import { lcpActions } from "readium-desktop/common/redux/actions"; +import classNames from "classnames"; +import { dialogActions } from "readium-desktop/common/redux/actions"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -32,6 +45,7 @@ interface IProps extends IBaseProps, ReturnType, ReturnT interface IState { password: string | undefined; + // infoOpen: boolean; } export class LCPAuthentication extends React.Component { @@ -44,6 +58,7 @@ export class LCPAuthentication extends React.Component { this.state = { password: undefined, + // infoOpen : false, }; } @@ -58,48 +73,91 @@ export class LCPAuthentication extends React.Component { return <>; } + // const openInfo = (e: any) => { + // e.preventDefault(); + // this.setState({infoOpen : !this.state.infoOpen}); + // }; + const { __ } = this.props; - return ( - -
    -

    {__("library.lcp.sentence")}

    - { - typeof this.props.message === "string" ? -

    - {this.props.message} -

    - : <> - } -

    - {__("library.lcp.hint", { hint: this.props.hint })} -

    -
    - - + return { if (open === false) { this.props.closeDialog(); } }}> + +
    + +
    + + {__("library.lcp.sentence")} + +
    + + + +
    - { - this.props.urlHint?.href - ? - - {this.props.urlHint.title || __("library.lcp.urlHint")} - - : <> - } -
    -
    - ); +
    +

    + + + {__("library.lcp.hint", { hint: this.props.hint })} + +

    +
    + + + +
    + { + typeof this.props.message === "string" ? +

    + + {this.props.message}. +

    + : <> + } + { + this.props.urlHint?.href + ? + + {this.props.urlHint.title || __("library.lcp.urlHint")} + + : <> + } +
    + + {/* */} + {__("library.lcp.whatIsLcp?")} + {/* */} + +
    +

    + {__("library.lcp.whatIsLcpInfoDetails")} +

    + + {__("library.lcp.whatIsLcpInfoDetailsLink")} + + +
    +
    +
    + + + + + + +
    +
    + + + ; } private onPasswordChange = (e: TChangeEventOnInput) => { @@ -125,6 +183,11 @@ const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { unlockPublication: (id: string, pass: string) => { dispatch(lcpActions.unlockPublicationWithPassphrase.build(id, pass)); }, + closeDialog: () => { + dispatch( + dialogActions.closeRequest.build(), + ); + }, }; }; diff --git a/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx b/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx index f86670d74..6f71ec98e 100644 --- a/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx +++ b/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx @@ -6,117 +6,128 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; -import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; +import * as Dialog from "@radix-ui/react-dialog"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as AddIcon from "readium-desktop/renderer/assets/icons/add-alone.svg"; +import { useApi } from "readium-desktop/renderer/common/hooks/useApi"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.scss"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; +import classNames from "classnames"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/outline-info-24px.svg"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; +import * as FollowLinkIcon from "readium-desktop/renderer/assets/icons/followLink-icon.svg"; +import * as penIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; +import * as linkIcon from "readium-desktop/renderer/assets/icons/link-icon.svg"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; +import * as GlobeIcon from "readium-desktop/renderer/assets/icons/globe-icon.svg"; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} +export const ApiappAddFormDialog = () => { + const [__] = useTranslator(); + const [, apiAddFeedAction] = useApi(undefined, "opds/addFeed"); -interface IState { - name: string | undefined; - url: string | undefined; -} - -class OpdsFeedAddForm extends React.Component { - private focusRef: React.RefObject; - - constructor(props: IProps) { - super(props); - - this.focusRef = React.createRef(); - - this.state = { - name: undefined, - url: undefined, - }; - - } - - public componentDidMount() { - if (this.focusRef?.current) { - this.focusRef.current.focus(); - } - } - - public render(): React.ReactElement<{}> { - if (!this.props.open) { - return (<>); - } - - const { __ } = this.props; - const { name, url } = this.state; - return ( - -
    -
    - - this.setState({ - name: e.target.value, - })} - type="text" - aria-label={__("opds.addForm.name")} - placeholder={__("opds.addForm.namePlaceholder")} - defaultValue={name} - ref={this.focusRef} - /> -
    -
    - - this.setState({ - url: e.target.value, - })} - type="text" - aria-label={__("opds.addForm.url")} - placeholder={__("opds.addForm.urlPlaceholder")} - defaultValue={url} - /> -
    -
    -
    - ); - } - - public add = () => { - const title = this.state.name; - const url = this.state.url; + const [title, setTitle] = React.useState(""); + const [url, setUrl] = React.useState(""); + const [infoOpen, setInfoOpen] = React.useState(false); + const addAction = () => { if (!title || !url) { return; } - apiAction("opds/addFeed", { title, url }).catch((err) => { - console.error("Error to fetch api opds/addFeed", err); - }); + apiAddFeedAction({ title, url }); }; -} -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.OpdsFeedAddForm, -}); + return + + + + +
    + +
    + + {__("opds.addMenu")} + +
    + + + +
    +
    +
    +
    +
    + + + setTitle(e?.target?.value)} + type="text" + aria-label={__("opds.addForm.name")} + className="R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE" + // placeholder={__("opds.addForm.namePlaceholder")} + required + /> +
    +
    + + {/* */} + + setUrl(e?.target?.value)} + type="text" + aria-label={__("opds.addForm.url")} + className="R2_CSS_CLASS__FORCE_NO_FOCUS_OUTLINE" + // placeholder={__("opds.addForm.urlPlaceholder")} + required + /> +
    +
    + + {infoOpen ? +
    +

    + {__("opds.informations")} +

    + + {__("opds.documentation")} + + +
    + : <>} +
    +
    +
    + + + + + + +
    +
    +
    +
    +
    ; +}; -export default connect(mapStateToProps)(withTranslator(OpdsFeedAddForm)); +export default ApiappAddFormDialog; diff --git a/src/renderer/library/components/dialog/OpdsFeedUpdateForm.tsx b/src/renderer/library/components/dialog/OpdsFeedUpdateForm.tsx index 6de0959c9..a1aaa4696 100644 --- a/src/renderer/library/components/dialog/OpdsFeedUpdateForm.tsx +++ b/src/renderer/library/components/dialog/OpdsFeedUpdateForm.tsx @@ -6,17 +6,18 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; -import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; +import * as Dialog from "@radix-ui/react-dialog"; +import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.scss"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; +import { IOpdsFeedView } from "readium-desktop/common/views/opds"; +import classNames from "classnames"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -26,83 +27,96 @@ interface IBaseProps extends TranslatorProps { // ReturnType // ReturnType // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { +interface IProps extends IBaseProps { + feed: IOpdsFeedView; + trigger: React.ReactNode; } interface IState { - name: string | undefined; + title: string | undefined; url: string | undefined; } class OpdsFeedUpdateForm extends React.Component { - private focusRef: React.RefObject; - constructor(props: IProps) { super(props); - - this.focusRef = React.createRef(); - this.state = { - name: props.feed?.title, + title: props.feed?.title, url: props.feed?.url, }; } - - public componentDidMount() { - if (this.focusRef?.current) { - this.focusRef.current.focus(); - } - } - public render(): React.ReactElement<{}> { - if (!this.props.open) { - return (<>); - } const { __ } = this.props; - const { name, url } = this.state; - return ( - -
    -
    - - this.setState({ - name: e.target.value, - // url: this.state.url || this.props.feed.url, - })} - type="text" - aria-label={__("opds.updateForm.name")} - defaultValue={this.props.feed.title} - ref={this.focusRef} - /> + const { title, url } = this.state; + return + + {this.props.trigger} + + +
    + +
    + + {__("opds.updateForm.title")} + +
    + + + +
    -
    - - this.setState({ - // name: this.state.name || this.props.feed.title, - url: e.target.value, - })} - type="text" - aria-label={__("opds.updateForm.url")} - defaultValue={this.props.feed.url} - /> -
    -
    -
    - ); +
    +
    +
    + + this.setState({ + title: e.target.value, + // url: this.state.url || this.props.feed.url, + })} + type="text" + aria-label={__("opds.updateForm.name")} + required + /> +
    +
    + + this.setState({ + // name: this.state.name || this.props.feed.title, + url: e.target.value, + })} + type="text" + aria-label={__("opds.updateForm.url")} + required + /> +
    +
    +
    + + + + + + +
    +
    + + + ; } private update = () => { - const title = this.state.name; + const title = this.state.title; const url = this.state.url; if (!title || !url) { return; @@ -118,9 +132,4 @@ class OpdsFeedUpdateForm extends React.Component { } -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.OpdsFeedUpdateForm, - feed: (state.dialog.data as DialogType[DialogTypeName.DeleteOpdsFeedConfirm]).feed, -}); - -export default connect(mapStateToProps)(withTranslator(OpdsFeedUpdateForm)); +export default withTranslator(OpdsFeedUpdateForm); diff --git a/src/renderer/library/components/dialog/RenewLsdConfirm.tsx b/src/renderer/library/components/dialog/RenewLsdConfirm.tsx deleted file mode 100644 index 3f03197bb..000000000 --- a/src/renderer/library/components/dialog/RenewLsdConfirm.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; -import { connect } from "react-redux"; -import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import { lcpActions } from "readium-desktop/common/redux/actions"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TDispatch } from "readium-desktop/typings/redux"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType, ReturnType { -} - -class RenewLsdConfirm extends React.Component { - - constructor(props: IProps) { - super(props); - } - - public render(): React.ReactElement<{}> { - if (!this.props.open || !this.props.publicationView) { - return <>; - } - - const { __ } = this.props; - return ( - this.props.renewLsdConfirm(this.props.publicationView.identifier)} - submitButtonDisabled={false} - shouldOkRefEnabled={true} - submitButtonTitle={this.props.__("dialog.yes")} - size={"small"} - > -
    -

    {__("dialog.renew")}

    -

    {this.props.publicationView.documentTitle}

    -
    -
    - ); - } -} - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - ...{ - open: state.dialog.type === DialogTypeName.LsdRenewConfirm, - }, ...state.dialog.data as DialogType[DialogTypeName.LsdRenewConfirm], -}); - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - renewLsdConfirm: (publicationId: string) => { - dispatch(lcpActions.renewPublicationLicense.build(publicationId)); - }, - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(RenewLsdConfirm)); diff --git a/src/renderer/library/components/dialog/ReturnLsdConfirm.tsx b/src/renderer/library/components/dialog/ReturnLsdConfirm.tsx deleted file mode 100644 index 9d803a42b..000000000 --- a/src/renderer/library/components/dialog/ReturnLsdConfirm.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; -import { connect } from "react-redux"; -import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; -import { lcpActions } from "readium-desktop/common/redux/actions"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TDispatch } from "readium-desktop/typings/redux"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType, ReturnType { -} - -class LsdReturnConfirm extends React.Component { - - constructor(props: IProps) { - super(props); - } - - public render(): React.ReactElement<{}> { - if (!this.props.open || !this.props.publicationView) { - return <>; - } - - const { __ } = this.props; - return ( - this.props.returnPublication(this.props.publicationView.identifier)} - submitButtonDisabled={false} - submitButtonTitle={this.props.__("dialog.yes")} - shouldOkRefEnabled={true} - size={"small"} - > -
    -

    {__("dialog.return")}

    -

    {this.props.publicationView.documentTitle}

    -
    -
    - ); - } -} - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - ...{ - open: state.dialog.type === DialogTypeName.LsdReturnConfirm, - }, ...state.dialog.data as DialogType[DialogTypeName.LsdReturnConfirm], -}); - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - returnPublication: (publicationId: string) => { - dispatch(lcpActions.returnPublication.build(publicationId)); - }, - }; -}; - -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(LsdReturnConfirm)); diff --git a/src/renderer/library/components/dialog/publicationInfos/PublicationInfo.tsx b/src/renderer/library/components/dialog/publicationInfos/PublicationInfo.tsx index 11003d2a9..f8b3a48a5 100644 --- a/src/renderer/library/components/dialog/publicationInfos/PublicationInfo.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/PublicationInfo.tsx @@ -5,9 +5,8 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import * as debug_ from "debug"; +import * as Dialog from "@radix-ui/react-dialog"; import * as React from "react"; -import { connect } from "react-redux"; import { DialogType, DialogTypeName } from "readium-desktop/common/models/dialog"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; @@ -15,128 +14,220 @@ import { PublicationView } from "readium-desktop/common/views/publication"; import { PublicationInfoContent, } from "readium-desktop/renderer/common/components/dialog/publicationInfos/publicationInfoContent"; -import PublicationInfoManager from "readium-desktop/renderer/common/components/dialog/publicationInfos/publicationInfoManager"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; import { dispatchOpdsLink } from "readium-desktop/renderer/library/opds/handleLink"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TDispatch } from "readium-desktop/typings/redux"; import CatalogControls from "./catalogControls"; import CatalogLcpControls from "./catalogLcpControls"; import OpdsControls from "./opdsControls/OpdsControls"; import TagManager from "./TagManager"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; + +import * as QuitIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import { useSelector } from "readium-desktop/renderer/common/hooks/useSelector"; +import { useDispatch } from "readium-desktop/renderer/common/hooks/useDispatch"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; +import { TPublication } from "readium-desktop/common/type/publication.type"; +import Loader from "readium-desktop/renderer/common/components/Loader"; +import { useLocation } from "react-router"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType, ReturnType { +interface IProps { } -// Logger -const debug = debug_("readium-desktop:renderer:library:publication-info"); - -class PublicationInfo extends React.Component { +const PublicationInfoLibContext = React.createContext(undefined); +export const PublicationInfoLibWithRadix: React.FC}>> = (props) => { + const defaultOpen = false; - public render() { - const { publication, toggleCoverZoom, closeDialog, coverZoom, open } = this.props; - - if (!open) { - return <>; + const dispatch = useDispatch(); + const [open, setOpen] = React.useState(defaultOpen); + const openFromState = useSelector((state: ILibraryRootState) => state.dialog.open); + React.useMemo(() => { + if (!openFromState) { + setOpen(false); } + }, [openFromState]); + const data = useSelector((state: ILibraryRootState) => + state.dialog.type === DialogTypeName.PublicationInfoLib + ? state.dialog.data as DialogType[DialogTypeName.PublicationInfoLib] + : undefined); + return ( + { + if (open) { + dispatch(dialogActions.openRequest.build(DialogTypeName.PublicationInfoLib, { + publicationIdentifier: props.publicationView.identifier, + })); + setOpen(true); + } else { + dispatch(dialogActions.closeRequest.build()); + setOpen(false); + } + }} + > + + {props.children} + + + ); +}; +export const PublicationInfoLibWithRadixTrigger = Dialog.Trigger; +PublicationInfoLibWithRadixTrigger.displayName = Dialog.Trigger.displayName; +export const PublicationInfoLibWithRadixContent = React.forwardRef( + ({ ...props }, forwardRef) => { + const [__] = useTranslator(); + const dispatch = useDispatch(); return ( - - () => - this.props.link( - _link.link[0], this.props.location, _link.name) + + {/* */} +
    + +
    + {/* {__("catalog.bookInfo")} */} +

    {__("catalog.bookInfo")}

    + + + +
    +
    + + { + (data) => + dispatch(dialogActions.closeRequest.build())} + /> + } + +
    +
    +
    + ); + }, +); +PublicationInfoLibWithRadixContent.displayName = "PublicationInfoLibWithRadixContent"; + +const PublicationInfoOpdsContext = React.createContext(undefined); +export const PublicationInfoOpdsWithRadix: React.FC> = (props) => { + const defaultOpen = false; + + const dispatch = useDispatch(); + const [open, setOpen] = React.useState(defaultOpen); + const openFromState = useSelector((state: ILibraryRootState) => state.dialog.open); + React.useMemo(() => { + if (!openFromState) { + setOpen(false); + } + }, [openFromState]); + return ( + { + if (open) { + dispatch(dialogActions.openRequest.build(DialogTypeName.PublicationInfoOpds, { + publication: props.opdsPublicationView, + })); + setOpen(true); + } else { + dispatch(dialogActions.closeRequest.build()); + setOpen(false); } - focusWhereAmI={false} - pdfPlayerNumberOfPages={undefined} - divinaNumberOfPages={undefined} - divinaContinousEqualTrue={undefined} - readerReadingLocation={undefined} - closeDialogCb={closeDialog} - > -
    -
    + }} + > + + {props.children} + + + ); +}; +export const PublicationInfoOpdsWithRadixTrigger = Dialog.Trigger; +PublicationInfoOpdsWithRadixTrigger.displayName = Dialog.Trigger.displayName; +export const PublicationInfoOpdsWithRadixContent = React.forwardRef( + ({ ...props }, forwardRef) => { + const [__] = useTranslator(); + const dispatch = useDispatch(); + return ( + + {/* */} +
    + +
    + {/* {__("catalog.bookInfo")} */} +

    {__("catalog.bookInfo")}

    + + + +
    +
    + + { + (opdsPublicationView) => + dispatch(dialogActions.closeRequest.build())} isOpds={true} + /> + } + +
    +
    +
    ); - } - - private controlsComponent = () => { - const { publicationInfoLib, publicationInfoOpds, publication } = this.props; + }, +); +PublicationInfoOpdsWithRadixContent.displayName = "PublicationInfoOpdsWithRadixContent"; - let controlsComponent = (<>); +const PublicationInfoWithRadixContent = (props: {publicationViewMaybeOpds: TPublication | undefined, closeDialog: () => void, isOpds?: boolean}) => { + const [, translator] = useTranslator(); // FIXME in reader.tsx + const dispatch = useDispatch(); + const link = dispatchOpdsLink(dispatch); + const location = useLocation(); - if (publicationInfoOpds) { - controlsComponent = (); - } - if (publicationInfoLib) { - if (publication?.lcp) { - controlsComponent = (); - } else { - controlsComponent = (); - } - } + if (!props.publicationViewMaybeOpds?.documentTitle) { + return ; + } - return controlsComponent; - }; + let controlsComponent = () => (<>); -} + if (props.isOpds) { + controlsComponent = () => (); + } else { + if (props.publicationViewMaybeOpds?.lcp) { + controlsComponent = () => (); + } else { + controlsComponent = () => (); + } + } -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - // Warning : mapDispatchToProps isn't rendered when the state is updateds - // but only when the component is mounted - debug("mapDispatchToProps rendered"); - return { - closeDialog: () => { - dispatch( - dialogActions.closeRequest.build(), - ); - }, - toggleCoverZoom: (state: boolean) => { - dispatch(dialogActions.updateRequest.build( - { - coverZoom: !state, - }, - )); - }, - link: (...data: Parameters>) => - dispatchOpdsLink(dispatch)(...data), - }; + return ( + setCoverZoom(!coverZoom)} + ControlComponent={controlsComponent} + TagManagerComponent={TagManager} + // coverZoom={coverZoom} + translator={translator} + onClikLinkCb={ + (_link) => () => link( + _link.link[0], location, _link.name) + } + focusWhereAmI={false} + pdfPlayerNumberOfPages={undefined} + divinaNumberOfPages={undefined} + divinaContinousEqualTrue={undefined} + readerReadingLocation={undefined} + closeDialogCb={props.closeDialog} + > + + ); }; - -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - ...{ - open: state.dialog.type === DialogTypeName.PublicationInfoOpds - || state.dialog.type === DialogTypeName.PublicationInfoLib, - publicationInfoOpds: state.dialog.type === DialogTypeName.PublicationInfoOpds, - publicationInfoLib: state.dialog.type === DialogTypeName.PublicationInfoLib, - }, - ...(state.dialog.data as DialogType[DialogTypeName.PublicationInfoOpds]), - location: state.router.location, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(PublicationInfo)); diff --git a/src/renderer/library/components/dialog/publicationInfos/TagManager.tsx b/src/renderer/library/components/dialog/publicationInfos/TagManager.tsx index 40a261475..4fb2ecbed 100644 --- a/src/renderer/library/components/dialog/publicationInfos/TagManager.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/TagManager.tsx @@ -26,6 +26,10 @@ import { apiDispatch } from "readium-desktop/renderer/common/redux/api/api"; import { dispatchOpdsLink } from "readium-desktop/renderer/library/opds/handleLink"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { TDispatch } from "readium-desktop/typings/redux"; +import * as stylePublication from "readium-desktop/renderer/assets/styles/publicationInfos.scss"; +import classNames from "classnames"; +// import GridTagButton from "../../catalog/GridTagButton"; + // Logger const debug = debug_("readium-desktop:renderer:reader:dialog:pubInfo:tagManager"); @@ -66,31 +70,35 @@ class TagManager extends React.Component { deleteTag(this.props.tagArray, setTagsCb)(index); return ( -
    - - { - (tag, index) => - () => this.props.link( - _tag.link[0], this.props.location, _tag.name) - } - > - - } - +
    +
    +

    {__("catalog.tags")} {this.props.tagArray?.length > 0 ? ":" : ""}

    + + { + (tag, index) => + () => this.props.link( + _tag.link[0], this.props.location, _tag.name) + } + location={this.props.location} + > + + // + } + +
    -
    + ); } } diff --git a/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx b/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx index 52b1270d8..fe4162aa3 100644 --- a/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx @@ -7,13 +7,13 @@ import * as React from "react"; import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; import { readerActions } from "readium-desktop/common/redux/actions"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as DeleteIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as ExportIcon from "readium-desktop/renderer/assets/icons/download.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as SaveAsIcon from "readium-desktop/renderer/assets/icons/SaveAs-icon.svg"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as ReadBook from "readium-desktop/renderer/assets/icons/readBook-icon.svg"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -21,10 +21,14 @@ import SVG from "readium-desktop/renderer/common/components/SVG"; import { TMouseEventOnButton } from "readium-desktop/typings/react"; import { TDispatch } from "readium-desktop/typings/redux"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; +import DeletePublicationConfirm from "../DeletePublicationConfirm"; +import * as DoubleCheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { publicationView: PublicationView; + isReading?: boolean; } // IProps may typically extend: // RouteComponentProps @@ -40,7 +44,6 @@ export class CatalogControls extends React.Component { super(props); this.handleRead = this.handleRead.bind(this); - this.deletePublication = this.deletePublication.bind(this); this.exportPublication = this.exportPublication.bind(this); } @@ -54,25 +57,35 @@ export class CatalogControls extends React.Component { return ( <> - + : <> + } + + + {__("catalog.deleteBook")} + + + )} + publicationView={this.props.publicationView} + /> - ); } - private deletePublication(e: TMouseEventOnButton) { - e.preventDefault(); - this.props.openDeleteDialog(); - } private exportPublication(e: TMouseEventOnButton) { e.preventDefault(); @@ -84,7 +97,6 @@ export class CatalogControls extends React.Component { private handleRead(e: TMouseEventOnButton) { e.preventDefault(); - this.props.openReader(); } } @@ -95,13 +107,6 @@ const mapDispatchToProps = (dispatch: TDispatch, props: IBaseProps) => { dispatch(dialogActions.closeRequest.build()); dispatch(readerActions.openRequest.build(props.publicationView.identifier)); }, - openDeleteDialog: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.DeletePublicationConfirm, - { - publicationView: props.publicationView, - }, - )); - }, }; }; diff --git a/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx b/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx index a034a0885..2e595f8f4 100644 --- a/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx @@ -6,16 +6,12 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import { readerActions } from "readium-desktop/common/redux/actions"; +import { connect, useDispatch } from "react-redux"; +import { lcpActions, readerActions } from "readium-desktop/common/redux/actions"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as ArrowIcon from "readium-desktop/renderer/assets/icons/arrow-right.svg"; -import * as DeleteIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as ExportIcon from "readium-desktop/renderer/assets/icons/download.svg"; import * as LoopIcon from "readium-desktop/renderer/assets/icons/loop.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -25,10 +21,21 @@ import { TDispatch } from "readium-desktop/typings/redux"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; import { StatusEnum } from "@r2-lcp-js/parser/epub/lsd"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import * as stylesAlertModals from "readium-desktop/renderer/assets/styles/components/alert.modals.scss"; +import DeletePublicationConfirm from "../DeletePublicationConfirm"; +import * as SaveAsIcon from "readium-desktop/renderer/assets/icons/SaveAs-icon.svg"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as ReadBook from "readium-desktop/renderer/assets/icons/readBook-icon.svg"; +import * as ArrowIcon from "readium-desktop/renderer/assets/icons/arrow-right.svg"; +import * as DoubleCheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { publicationView: PublicationView; + isReading?: boolean; } // IProps may typically extend: // RouteComponentProps @@ -44,11 +51,7 @@ class CatalogLcpControls extends React.Component { super(props); this.handleRead = this.handleRead.bind(this); - this.deletePublication = this.deletePublication.bind(this); this.exportPublication = this.exportPublication.bind(this); - - this.returnPublicationDialog = this.returnPublicationDialog.bind(this); - this.renewPublicationDialog = this.renewPublicationDialog.bind(this); } public render(): React.ReactElement<{}> { @@ -78,65 +81,65 @@ class CatalogLcpControls extends React.Component { return ( <> {(!lsdStatus || - (lsdStatus === StatusEnum.Active || lsdStatus === StatusEnum.Ready)) ? - + : <> + } + {this.props.isReading ? + : <> } { // lsdStatus === StatusEnum.Expired && - lsdRenewLink && - + lsdRenewLink ? + + + {__("publication.renewButton")} + + )} /> : <> } { - lsdReturnLink && - + lsdReturnLink ? + + + {__("publication.returnButton")} + + )} /> : <> } - - - + + )} + publicationView={this.props.publicationView} + /> + + ); } - private renewPublicationDialog(e: TMouseEventOnButton) { - e.preventDefault(); - this.props.openRenewDialog(); - } - private returnPublicationDialog(e: TMouseEventOnButton) { - e.preventDefault(); - this.props.openReturnDialog(); - } - - private deletePublication(e: TMouseEventOnButton) { - e.preventDefault(); - this.props.openDeleteDialog(); - } private exportPublication(e: TMouseEventOnButton) { e.preventDefault(); @@ -159,28 +162,81 @@ const mapDispatchToProps = (dispatch: TDispatch, props: IBaseProps) => { dispatch(dialogActions.closeRequest.build()); dispatch(readerActions.openRequest.build(props.publicationView.identifier)); }, - openDeleteDialog: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.DeletePublicationConfirm, - { - publicationView: props.publicationView, - }, - )); - }, - openRenewDialog: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.LsdRenewConfirm, - { - publicationView: props.publicationView, - }, - )); - }, - openReturnDialog: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.LsdReturnConfirm, - { - publicationView: props.publicationView, - }, - )); - }, }; }; export default connect(undefined, mapDispatchToProps)(withTranslator(CatalogLcpControls)); + +const RenewLsdConfirm = (props: { publicationView: PublicationView, trigger: React.ReactNode } & AlertDialog.AlertDialogProps) => { + const [__] = useTranslator(); + const dispatch = useDispatch(); + + const renew = () => { + dispatch(lcpActions.renewPublicationLicense.build(props.publicationView.identifier)); + }; + + return ( + + + {props.trigger} + + +
    + + {__("dialog.renew")} + {/* replace with

    */} + {props.publicationView.documentTitle} +
    +
    + + + + + + +
    +
    +
    +
    + ); + +}; + +const ReturnLsdConfirm = (props: { publicationView: PublicationView, trigger: React.ReactNode } & AlertDialog.AlertDialogProps) => { + const [__] = useTranslator(); + const dispatch = useDispatch(); + + const renew = () => { + dispatch(lcpActions.returnPublication.build(props.publicationView.identifier)); + }; + + return ( + + + {props.trigger} + + +
    + + {__("dialog.return")} + + {props.publicationView.documentTitle} + +
    + + + + + + +
    +
    +
    +
    + ); + +}; diff --git a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx index e89beb272..b916ab3fc 100644 --- a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx @@ -10,10 +10,11 @@ import * as React from "react"; import { connect } from "react-redux"; import { dialogActions, importActions } from "readium-desktop/common/redux/actions/"; import { IOpdsLinkView, IOpdsPublicationView } from "readium-desktop/common/views/opds"; -import * as CartFillIcon from "readium-desktop/renderer/assets/icons/cart-fill.svg"; +import * as CartFillIcon from "readium-desktop/renderer/assets/icons/cart-icon.svg"; +import * as BorrowIcon from "readium-desktop/renderer/assets/icons/borrow-icon.svg"; import * as ImportIcon from "readium-desktop/renderer/assets/icons/import.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -57,22 +58,22 @@ export class OpdsControls extends React.Component { __, } = this.props; - const boxStyle = {border: "1px solid silver", borderRadius: "8px", padding: "0.4em", paddingTop: "0.2em", marginBottom: "0.5em", marginTop: "0.4em"}; + const boxStyle = { height: "50px", padding: "0.4em", paddingTop: "0.2em", marginBottom: "0.5em", marginTop: "0.4em", fontSize: "14px" }; const m = findMimeTypeWithExtension(ADOBE_ADEPT_XML); const orderLinks = (links: IOpdsLinkView[]) => { return Array.from(links).sort((a, b) => { if (a.properties?.indirectAcquisitionTypes?.top === m && b.properties?.indirectAcquisitionTypes?.top === m) { - return 0; + return 0; } if (a.properties?.indirectAcquisitionTypes?.top === m && b.properties?.indirectAcquisitionTypes?.top !== m) { - return 1; + return 1; } if (a.properties?.indirectAcquisitionTypes?.top !== m && b.properties?.indirectAcquisitionTypes?.top === m) { - return -1; + return -1; } return 0; }); @@ -81,9 +82,8 @@ export class OpdsControls extends React.Component { const adjustDisplayType = (str: string | undefined) => str?.replace("lcpl", "LCP").replace("lcpdf", "PDF").replace("pdf", "PDF").replace("epub", "EPUB"); const typeStr = (ln: IOpdsLinkView) => { return ln.properties?.indirectAcquisitionTypes?.top ? - ` (${adjustDisplayType(findExtWithMimeType(ln.properties.indirectAcquisitionTypes.top)) || ln.properties.indirectAcquisitionTypes.top}${ - ln.properties?.indirectAcquisitionTypes?.child ? ` ${adjustDisplayType(findExtWithMimeType(ln.properties.indirectAcquisitionTypes.child)) || ln.properties.indirectAcquisitionTypes.child}` : ""})` : - (ln.type ? ` (${adjustDisplayType(findExtWithMimeType(ln.type)) || adjustDisplayType(findExtWithMimeType(ln.type.replace("+json", "+zip")))})` : ""); + ` (${adjustDisplayType(findExtWithMimeType(ln.properties.indirectAcquisitionTypes.top)) || ln.properties.indirectAcquisitionTypes.top}${ln.properties?.indirectAcquisitionTypes?.child ? ` ${adjustDisplayType(findExtWithMimeType(ln.properties.indirectAcquisitionTypes.child)) || ln.properties.indirectAcquisitionTypes.child}` : ""})` : + (ln.type ? ` (${adjustDisplayType(findExtWithMimeType(ln.type)) || adjustDisplayType(findExtWithMimeType(ln.type.replace("+json", "+zip")))})` : ""); }; const openAccessLinksButton = () => @@ -96,7 +96,7 @@ export class OpdsControls extends React.Component { ln, opdsPublicationView, )} - className={stylesButtons.button_primary} + className={feedLinksList.length > 0 ? stylesButtons.button_secondary : stylesButtons.button_primary} disabled={openAccessButtonIsDisabled()} > {`${__("catalog.addBookToLib")}${typeStr(ln)}`} @@ -118,10 +118,10 @@ export class OpdsControls extends React.Component { ln, opdsPublicationView, )} - className={stylesButtons.button_primary} + className={stylesButtons.button_secondary} disabled={sampleButtonIsDisabled()} > - + {`${__("opds.menu.addExtract")}${typeStr(ln)}`} { } > - + {__("opds.menu.goBuyBook")} -
    , ) @@ -164,13 +163,14 @@ export class OpdsControls extends React.Component { (ln, idx) =>
    @@ -184,7 +184,7 @@ export class OpdsControls extends React.Component { (ln, idx) =>
    -
    )) @@ -286,14 +284,14 @@ const mapStateToProps = (state: ILibraryRootState, props: IBaseProps) => { location: state.router.location, openAccessButtonIsDisabled: () => { return !!state.download.find( - ([{downloadUrl}]) => props.opdsPublicationView.openAccessLinks.find( + ([{ downloadUrl }]) => props.opdsPublicationView.openAccessLinks.find( (ln) => ln.url === downloadUrl, ), ); }, sampleButtonIsDisabled: () => { return !!state.download.find( - ([{downloadUrl}]) => props.opdsPublicationView.sampleOrPreviewLinks.find( + ([{ downloadUrl }]) => props.opdsPublicationView.sampleOrPreviewLinks.find( (ln) => ln.url === downloadUrl, ), ); diff --git a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsLinkProperties.tsx b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsLinkProperties.tsx index ec3cbc4d4..787df1624 100644 --- a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsLinkProperties.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsLinkProperties.tsx @@ -8,13 +8,16 @@ import * as moment from "moment"; import * as React from "react"; import { IOPDSPropertiesView } from "readium-desktop/common/views/opds"; -import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.css"; +import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import { OPDSAvailabilityEnum } from "@r2-opds-js/opds/opds2/opds2-availability"; import { findMimeTypeWithExtension, ADOBE_ADEPT_XML } from "readium-desktop/utils/mimeTypes"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as AvailableIcon from "readium-desktop/renderer/assets/icons/available-icon.svg"; +import * as UnvavailableIcon from "readium-desktop/renderer/assets/icons/stop-icon.svg"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -42,76 +45,104 @@ class OpdsLinkProperties extends React.Component { return (<>); } - const metadataLineComponent = (text: string, property: string | number) => - property && - <> + const MetadataLineComponent: React.FC = ({text, children}) => +
    {`${text}: `} - - {property} - + + {children} +
    - ; +
    ; + + const stateInfo = ( + () => { + if (properties.availabilityState) { + + switch (properties.availabilityState) { + case OPDSAvailabilityEnum.Available: + return ( +
    + +

    {__("catalog.opds.info.availableState.available")}

    +
    + ); + case OPDSAvailabilityEnum.Unavailable: + return ( +
    + +

    {__("catalog.opds.info.availableState.unavailable")}

    +
    + ); + case OPDSAvailabilityEnum.Ready: + return <>{__("catalog.opds.info.availableState.ready")}; + case OPDSAvailabilityEnum.Reserved: + return <>{__("catalog.opds.info.availableState.reserved")}; + default: + return <>{__("catalog.opds.info.availableState.unknown")}; + } + } + return undefined; + } + )(); return ( <> { properties.indirectAcquisitionTypes?.top === findMimeTypeWithExtension(ADOBE_ADEPT_XML) ? - <>(Adobe Adept)

    : <> + <>(Adobe Adept)

    : <> } - { - metadataLineComponent(__("catalog.opds.info.numberOfItems"), properties.numberOfItems) + {properties.numberOfItems ? + + <>{properties.numberOfItems} + : <> } { - properties.priceValue && properties.priceCurrency && - metadataLineComponent( - __("catalog.opds.info.priveValue"), - `${properties.priceValue} ${properties.priceCurrency}`) + (properties.priceValue && properties.priceCurrency) ? + + <>{`${properties.priceValue} ${properties.priceCurrency}`} + : <> } { - metadataLineComponent(__("catalog.opds.info.copyTotal"), properties.copyTotal) + properties.copyTotal ? + + <>{properties.copyTotal} + : <> } { - metadataLineComponent(__("catalog.opds.info.copyAvalaible"), properties.copyAvailable) + properties.copyAvailable ? + + <>{properties.copyAvailable} + : <> } { - metadataLineComponent(__("catalog.opds.info.holdTotal"), properties.holdTotal) + properties.holdTotal ? + + <>{properties.holdTotal} + : <> } { - metadataLineComponent(__("catalog.opds.info.holdPosition"), properties.holdPosition) + properties.holdPosition ? + + <>{properties.holdPosition} + : <> } { - metadataLineComponent(__("catalog.opds.info.state"), ( - () => { - if (properties.availabilityState) { - - switch (properties.availabilityState) { - case OPDSAvailabilityEnum.Available: - return __("catalog.opds.info.availableState.available"); - case OPDSAvailabilityEnum.Unavailable: - return __("catalog.opds.info.availableState.unavailable"); - case OPDSAvailabilityEnum.Ready: - return __("catalog.opds.info.availableState.ready"); - case OPDSAvailabilityEnum.Reserved: - return __("catalog.opds.info.availableState.reserved"); - default: - return __("catalog.opds.info.availableState.unknown"); - } - } - return undefined; - } - )()) + stateInfo ? + + {stateInfo} + : <> } { - properties.availabilitySince && - metadataLineComponent( - __("catalog.opds.info.availableSince"), - moment(properties.availabilitySince).format("LLL")) + properties.availabilitySince ? + + <>{moment(properties.availabilitySince).format("LLL")} + : <> } { - properties.availabilityUntil && - metadataLineComponent( - __("catalog.opds.info.availableUntil"), - moment(properties.availabilityUntil).format("LLL")) + properties.availabilityUntil ? + + <>{moment(properties.availabilityUntil).format("LLL")} + : <> } ); diff --git a/src/renderer/library/components/layout/BreadCrumb.tsx b/src/renderer/library/components/layout/BreadCrumb.tsx index a2addc503..791cecde4 100644 --- a/src/renderer/library/components/layout/BreadCrumb.tsx +++ b/src/renderer/library/components/layout/BreadCrumb.tsx @@ -9,9 +9,10 @@ import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; -import * as ArrowIcon from "readium-desktop/renderer/assets/icons/arrow-left.svg"; -import * as stylesBreadcrumb from "readium-desktop/renderer/assets/styles/components/breadcrumb.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as BreacrmbsNavIcon from "readium-desktop/renderer/assets/icons/breadcrumbsNav-icon.svg"; +import * as ChevronRight from "readium-desktop/renderer/assets/icons/chevron-right.svg"; +import * as stylesBreadcrumb from "readium-desktop/renderer/assets/styles/components/breadcrumb.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -40,47 +41,98 @@ class BreadCrumb extends React.Component { } public render(): React.ReactElement<{}> { - const { breadcrumb, __ } = this.props; + const { breadcrumb } = this.props; return (
    - { - breadcrumb.length >= 2 - && - - - } { breadcrumb - && breadcrumb.map( - (item, index) => - item.path && index !== breadcrumb.length - 1 ? + ? + breadcrumb.length > 5 ? + <> + + +

    {breadcrumb[0].name}

    + + + +

    ...

    + + + +

    {breadcrumb[breadcrumb.length - 2].name}

    + + + + {breadcrumb[breadcrumb.length - 1].name} + + + : + breadcrumb.length >= 2 && breadcrumb.length <= 5 ? + <> - {item.name} + +

    {breadcrumb[0].name}

    - : - - {item.name} - , - ) - } + + {breadcrumb.slice(1).map( + (item, index) => + item.path && index !== breadcrumb.length - 2 ? + + +

    {item.name}

    + + +
    + : + + {item.name} + , + )} + + : <> : <> + }
    ); } diff --git a/src/renderer/library/components/layout/LibraryHeader.tsx b/src/renderer/library/components/layout/LibraryHeader.tsx index 94bac4c62..7c3e01dee 100644 --- a/src/renderer/library/components/layout/LibraryHeader.tsx +++ b/src/renderer/library/components/layout/LibraryHeader.tsx @@ -9,40 +9,60 @@ import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; -import * as stylesHeader from "readium-desktop/renderer/assets/styles/header.css"; +import * as stylesHeader from "readium-desktop/renderer/assets/styles/header.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; + import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import SkipLink from "readium-desktop/renderer/common/components/SkipLink"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { DisplayType, IRouterLocationState } from "../../routing"; +import * as HomeIcon from "readium-desktop/renderer/assets/icons/home-icon.svg"; +import * as CatalogsIcon from "readium-desktop/renderer/assets/icons/catalogs-icon.svg"; +import * as ShelfIcon from "readium-desktop/renderer/assets/icons/shelf-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import { Settings } from "../settings/Settings"; interface NavigationHeader { route: string; label: string; matchRoutes: string[]; + searchEnable?: boolean; styles: string[]; + svg: any; } const headerNav: NavigationHeader[] = [ + { + route: "/home", + label: "homeTitle", + matchRoutes: ["/", "/home"], + styles: [], + svg: HomeIcon, + }, { route: "/library", - label: "books", - matchRoutes: ["/", "/library"], + label: "allBooks", + matchRoutes: ["/library"], + searchEnable: false, styles: [], + svg: ShelfIcon, }, { route: "/opds", label: "catalogs", matchRoutes: ["/opds"], styles: [], + svg: CatalogsIcon, }, - { - route: "/settings", - label: "settings", - matchRoutes: ["/settings"], - styles: [], - }, + // { + // route: "/settings", + // label: "settings", + // matchRoutes: ["/settings"], + // styles: [], + // svg: GearIcon, + // }, ]; // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -73,12 +93,17 @@ class Header extends React.Component { /> ); @@ -114,9 +139,10 @@ class Header extends React.Component { const nextLocation = this.props.history.reduce( (pv, cv) => - cv?.pathname?.startsWith(item.route) + cv?.pathname.startsWith(item.route) ? { ...this.props.location, + search: item.searchEnable ? this.props.location?.search : "", pathname: cv.pathname, } : pv, @@ -131,15 +157,18 @@ class Header extends React.Component { - { + className={active ? stylesButtons.button_nav_primary : ""} + title={ translate("header." + item.label) } + > + +

    { + translate("header." + item.label) + }

    ); diff --git a/src/renderer/library/components/layout/LibraryLayout.tsx b/src/renderer/library/components/layout/LibraryLayout.tsx index 151bd0077..f0ce8e444 100644 --- a/src/renderer/library/components/layout/LibraryLayout.tsx +++ b/src/renderer/library/components/layout/LibraryLayout.tsx @@ -11,7 +11,9 @@ import { connect } from "react-redux"; import { keyboardShortcutsMatch } from "readium-desktop/common/keyboard"; import { _APP_NAME } from "readium-desktop/preprocessor-directives"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; +import * as stylesAllBooks from "readium-desktop/renderer/assets/styles/components/allPublicationsPage.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -22,6 +24,15 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ import LibraryHeader from "./LibraryHeader"; +import * as RefreshIcon from "readium-desktop/renderer/assets/icons/refresh-icon.svg"; +import * as HomeIcon from "readium-desktop/renderer/assets/icons/home-icon.svg"; +import * as AvatarIcon from "readium-desktop/renderer/assets/icons/person-fill.svg"; +import { buildOpdsBrowserRoute } from "readium-desktop/renderer/library/opds/route"; +import { DisplayType, IOpdsBrowse, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; +import { Link, matchPath } from "react-router-dom"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; + const capitalizedAppName = _APP_NAME.charAt(0).toUpperCase() + _APP_NAME.substring(1); // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -29,7 +40,9 @@ interface IBaseProps extends TranslatorProps { secondaryHeader?: React.ReactElement; breadCrumb?: React.ReactElement; title?: string; + page?: string; mainClassName?: string; + search?: React.ReactElement; // since React 16.10.0 (was not needed in 16.9.0) children?: React.ReactNode; // JSX.Element[] | JSX.Element @@ -81,12 +94,12 @@ class LibraryLayout extends React.Component { } public render() { - const { title } = this.props; + const { page } = this.props; const { __ } = this.props; let helmetTitle = capitalizedAppName; - if (title) { - helmetTitle += " - " + title; + if (page) { + helmetTitle += " - " + page; } window.document.title = helmetTitle; @@ -103,27 +116,55 @@ class LibraryLayout extends React.Component { > {__("accessibility.toolbar")} - - { this.props.secondaryHeader } - { this.props.breadCrumb } -
    - + +
    - {__("accessibility.mainContent")} - - { this.props.children } -
    + {this.props.secondaryHeader} + {(page === __("opds.breadcrumbRoot")) ? +
    +

    {this.props.title}

    + {this.props.breadCrumb ? +
    + { + this.home() + } + { + this.bookshelf() + } + { + this.refresh() + } +
    + : <> + } +
    + + : <> + } + {this.props.breadCrumb ? +
    + { this.props.breadCrumb } + { this.props.search } +
    + : <>} + + {__("accessibility.mainContent")} + + { this.props.children } +
    +
    ); } @@ -155,11 +196,152 @@ class LibraryLayout extends React.Component { this.refToolbar.current.focus(); } }; + + private bookshelf = () => { + const { bookshelf } = this.props.headerLinks; + + let bookshelfComponent = <>; + if (bookshelf) { + + const { __ } = this.props; + + const param = matchPath( + routes["/opds/browse"].path, + this.props.location.pathname, + ).params; + + const lvl = parseInt(param.level, 10); + + const route = buildOpdsBrowserRoute( + param.opdsId, + __("opds.shelf"), + bookshelf, + lvl === 1 ? 3 : (lvl + 1), + ); + + bookshelfComponent = ( + + + + ); + } + + return bookshelfComponent; + }; + + private home = () => { + const { start } = this.props.headerLinks; + + let homeComponent = <>; + if (start) { + + const { __ } = this.props; + + const param = matchPath( + routes["/opds/browse"].path, + this.props.location.pathname, + ).params; + + const home = this.props.breadcrumb[1]; + + const route = buildOpdsBrowserRoute( + param.opdsId, + home.name || "", + start, + 1, + ); + + homeComponent = ( + + + + ); + } + + return homeComponent; + }; + + private refresh = () => { + const { self } = this.props.headerLinks; + const { __ } = this.props; + + let refreshComponet = <>; + if (self) { + + const param = matchPath( + routes["/opds/browse"].path, + this.props.location.pathname, + ).params; + + const lvl = parseInt(param.level, 10); + + const i = (lvl > 1) ? (lvl - 1) : lvl; + const name = this.props.breadcrumb[i]?.name; + + const route = buildOpdsBrowserRoute( + param.opdsId, + name, + self, + lvl, + ); + + refreshComponet = ( + + ); + } else { + refreshComponet = ( + + ); + } + + return refreshComponet; + }; } const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ // dialogOpen: state.dialog.open, // unused ? keyboardShortcuts: state.keyboard.shortcuts, + location: state.router.location, + headerLinks: state.opds.browser.header, + breadcrumb: state.opds.browser.breadcrumb, }); export default connect(mapStateToProps)(withTranslator(LibraryLayout)); diff --git a/src/renderer/library/components/opds/Browser.tsx b/src/renderer/library/components/opds/Browser.tsx index 20a62e703..6e0d3fc39 100644 --- a/src/renderer/library/components/opds/Browser.tsx +++ b/src/renderer/library/components/opds/Browser.tsx @@ -16,6 +16,10 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ import BreadCrumb from "../layout/BreadCrumb"; import BrowserResult from "./BrowserResult"; import Header from "./Header"; +import SearchForm from "./SearchForm"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as ForbiddenIcon from "readium-desktop/renderer/assets/icons/forbidden-icon.svg"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -37,15 +41,25 @@ class Browser extends React.Component { public render(): React.ReactElement { const secondaryHeader =
    ; const breadCrumb = ; + const search = ; + const catalogTitle = this.props.breadrumb[1]?.name; + return ( - {this.props.breadrumb.length && + {this.props.breadrumb.length ? + : +

    + + {this.props.__("opds.empty")} +

    }
    ); diff --git a/src/renderer/library/components/opds/BrowserResult.tsx b/src/renderer/library/components/opds/BrowserResult.tsx index 2b838297e..bb19b5838 100644 --- a/src/renderer/library/components/opds/BrowserResult.tsx +++ b/src/renderer/library/components/opds/BrowserResult.tsx @@ -7,8 +7,9 @@ import * as React from "react"; import { connect } from "react-redux"; -import * as stylesColumns from "readium-desktop/renderer/assets/styles/components/columns.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesColumns from "readium-desktop/renderer/assets/styles/components/columns.scss"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -127,52 +128,55 @@ export class BrowserResult extends React.Component { } else if (opds.groups || opds.publications || opds.navigation) { - content = ( <> { - opds.navigation && + opds.navigation ? + : <> } { - opds.publications && + opds.publications ? + : <> } { opds.groups?.map((group, i) =>
    - + { group.publications?.length > 1 ?
    + : <>} { - group.navigation && + group.navigation ? + : <> } { - group.publications && - ( - (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) || DisplayType.Grid - ) === DisplayType.Grid ? - - , - )} - /> : - + group.publications?.length > 1 ? + (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) === DisplayType.Grid ? + + , + )} + /> + : + + : <> }
    , ) @@ -198,7 +202,7 @@ export class BrowserResult extends React.Component { } } - return
    + return
    {content}
    ; } diff --git a/src/renderer/library/components/opds/Entry.tsx b/src/renderer/library/components/opds/Entry.tsx index 0f2aeb158..8791d789e 100644 --- a/src/renderer/library/components/opds/Entry.tsx +++ b/src/renderer/library/components/opds/Entry.tsx @@ -9,10 +9,11 @@ import * as React from "react"; import { connect } from "react-redux"; import { Link, matchPath } from "react-router-dom"; import { IOpdsNavigationLinkView } from "readium-desktop/common/views/opds"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { buildOpdsBrowserRoute } from "readium-desktop/renderer/library/opds/route"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { DisplayType, IOpdsBrowse, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps { @@ -51,49 +52,34 @@ class Entry extends React.Component { ); return ( - <> -
    - - - {entry.title} - { - (entry.subtitle && entry.subtitle !== entry.title) ? - ( -
    {entry.subtitle.substr(0, 40) + (entry.subtitle.length > 40 ? "..." : "")} -
    ) : - (<>) - } -
    - { - (entry.numberOfItems) ? - ( - - {entry.numberOfItems} - - ) : - (<>) - } - -
    - {/* - , - ) + + + {entry.title} + { + (entry.subtitle && entry.subtitle !== entry.title) ? + ( +
    {entry.subtitle.substr(0, 40) + (entry.subtitle.length > 40 ? "..." : "")} +
    ) : + (<>) } - className={styles.flux_slider} - /> */} - +
    + { + (entry.numberOfItems) ? + ( + + ({entry.numberOfItems}) + + ) : + (<>) + } + ); } } diff --git a/src/renderer/library/components/opds/EntryList.tsx b/src/renderer/library/components/opds/EntryList.tsx index 38338e963..07e91d1bb 100644 --- a/src/renderer/library/components/opds/EntryList.tsx +++ b/src/renderer/library/components/opds/EntryList.tsx @@ -8,8 +8,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { IOpdsNavigationLinkView } from "readium-desktop/common/views/opds"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import Entry from "./Entry"; @@ -33,10 +32,10 @@ class EntryList extends React.Component { public render(): React.ReactElement<{}> { return ( -
    -
      +
      +
        {this.props.entries.map((entry, index) => -
      • +
      • , )} diff --git a/src/renderer/library/components/opds/EntryPublicationList.tsx b/src/renderer/library/components/opds/EntryPublicationList.tsx index d5f7fec24..c2d486b04 100644 --- a/src/renderer/library/components/opds/EntryPublicationList.tsx +++ b/src/renderer/library/components/opds/EntryPublicationList.tsx @@ -8,16 +8,21 @@ import * as React from "react"; import { connect } from "react-redux"; import { IOpdsPublicationView, IOpdsResultView } from "readium-desktop/common/views/opds"; -import Loader from "readium-desktop/renderer/common/components/Loader"; import { GridView } from "readium-desktop/renderer/library/components/utils/GridView"; import { ListView } from "readium-desktop/renderer/library/components/utils/ListView"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { DisplayType, IRouterLocationState } from "readium-desktop/renderer/library/routing"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as ForbiddenIcon from "readium-desktop/renderer/assets/icons/forbidden-icon.svg"; +import { + TranslatorProps, withTranslator, +} from "readium-desktop/renderer/common/components/hoc/translator"; import PageNavigation from "./PageNavigation"; -interface IBaseProps { - opdsPublicationView: IOpdsPublicationView[] | undefined; +interface IBaseProps extends TranslatorProps { + opdsPublicationView?: IOpdsPublicationView[] | undefined; links: IOpdsResultView["links"]; pageInfo?: IOpdsResultView["metadata"]; } @@ -41,7 +46,7 @@ class EntryPublicationList extends React.Component { return ( <> - {this.props.opdsPublicationView + {this.props.opdsPublicationView?.length > 0 ? <> {displayType === DisplayType.Grid ? { pageInfo={this.props.pageInfo} /> - : } + : +

        + + {this.props.__("opds.empty")} +

        } ); } @@ -68,4 +77,4 @@ const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ location: state.router.location, }); -export default connect(mapStateToProps)(EntryPublicationList); +export default connect(mapStateToProps)(withTranslator(EntryPublicationList)); diff --git a/src/renderer/library/components/opds/FeedList.tsx b/src/renderer/library/components/opds/FeedList.tsx index a152e3a6f..d2c54c8d7 100644 --- a/src/renderer/library/components/opds/FeedList.tsx +++ b/src/renderer/library/components/opds/FeedList.tsx @@ -5,18 +5,16 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; import { DialogTypeName } from "readium-desktop/common/models/dialog"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { IOpdsFeedView } from "readium-desktop/common/views/opds"; -import * as DeleteIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as EditIcon from "readium-desktop/renderer/assets/icons/edit.svg"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as DeleteIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as EditIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; +import * as GlobeIcon from "readium-desktop/renderer/assets/icons/globe-icon.svg"; +import * as stylesCatalogs from "readium-desktop/renderer/assets/styles/components/catalogs.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -25,10 +23,11 @@ import { apiAction } from "readium-desktop/renderer/library/apiAction"; import { apiSubscribe } from "readium-desktop/renderer/library/apiSubscribe"; import { buildOpdsBrowserRoute } from "readium-desktop/renderer/library/opds/route"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TMouseEventOnButton } from "readium-desktop/typings/react"; import { TDispatch } from "readium-desktop/typings/redux"; import { Unsubscribe } from "redux"; import { DisplayType, IRouterLocationState } from "../../routing"; +import DeleteOpdsFeedConfirm from "../dialog/DeleteOpdsFeedConfirm"; +import OpdsFeedUpdateForm from "../dialog/OpdsFeedUpdateForm"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -76,10 +75,11 @@ class FeedList extends React.Component { const { __ } = this.props; return (
        -
          +

          {__("header.myCatalogs")}

          +
            {this.state.feedsResult.map((item, index) => { return ( -
          • +
          • { item.url, ), }} - state = {{displayType: (this.props.location.state && (this.props.location.state as IRouterLocationState).displayType) ? (this.props.location.state as IRouterLocationState).displayType : DisplayType.Grid}} - className={stylesBlocks.block_full} + state={{ displayType: (this.props.location.state && (this.props.location.state as IRouterLocationState).displayType) ? (this.props.location.state as IRouterLocationState).displayType : DisplayType.Grid }} + className={stylesCatalogs.catalog_content} > -

            {item.title}

            +
            +
            + +

            {item.title}

            +
            - - + + + + )} + feed={item} + /> + this.deleteFeed(e, item)} + className={stylesCatalogs.button_delete} + title={__("catalog.delete")} + > + + + )} feed={item} />
          • ); })} @@ -119,15 +128,10 @@ class FeedList extends React.Component { ); } - private deleteFeed(event: TMouseEventOnButton, feed: IOpdsFeedView) { - event.preventDefault(); - this.props.openDeleteDialog(feed); - } - - private updateFeed(event: TMouseEventOnButton, feed: IOpdsFeedView) { - event.preventDefault(); - this.props.openUpdateDialog(feed); - } + // private deleteFeed(event: TMouseEventOnButton, feed: IOpdsFeedView) { + // event.preventDefault(); + // this.props.openDeleteDialog(feed); + // } private async loadFeeds() { try { @@ -141,13 +145,13 @@ class FeedList extends React.Component { const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { return { - openDeleteDialog: (feed: IOpdsFeedView) => { - dispatch(dialogActions.openRequest.build(DialogTypeName.DeleteOpdsFeedConfirm, - { - feed, - }, - )); - }, + // openDeleteDialog: (feed: IOpdsFeedView) => { + // dispatch(dialogActions.openRequest.build(DialogTypeName.DeleteOpdsFeedConfirm, + // { + // feed, + // }, + // )); + // }, openUpdateDialog: (feed: IOpdsFeedView) => { dispatch(dialogActions.openRequest.build(DialogTypeName.OpdsFeedUpdateForm, { diff --git a/src/renderer/library/components/opds/Header.tsx b/src/renderer/library/components/opds/Header.tsx index 42e09b1a7..bf7666496 100644 --- a/src/renderer/library/components/opds/Header.tsx +++ b/src/renderer/library/components/opds/Header.tsx @@ -5,26 +5,25 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import classNames from "classnames"; + import * as React from "react"; import { connect } from "react-redux"; -import { Link, matchPath } from "react-router-dom"; -import * as RefreshIcon from "readium-desktop/renderer/assets/icons/arrow-clockwise.svg"; -import * as GridIcon from "readium-desktop/renderer/assets/icons/grid.svg"; -import * as HomeIcon from "readium-desktop/renderer/assets/icons/house-fill.svg"; -import * as ListIcon from "readium-desktop/renderer/assets/icons/list.svg"; -import * as AvatarIcon from "readium-desktop/renderer/assets/icons/person-fill.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import { Link } from "react-router-dom"; + +import * as GridIcon from "readium-desktop/renderer/assets/icons/grid-icon.svg"; +import * as ListIcon from "readium-desktop/renderer/assets/icons/list-icon.svg"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import SVG from "readium-desktop/renderer/common/components/SVG"; import SecondaryHeader from "readium-desktop/renderer/library/components/SecondaryHeader"; -import { buildOpdsBrowserRoute } from "readium-desktop/renderer/library/opds/route"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DisplayType, IOpdsBrowse, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; +import { DisplayType, IRouterLocationState } from "readium-desktop/renderer/library/routing"; +import * as CheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; +import ApiappAddFormDialog from "readium-desktop/renderer/library/components/dialog/ApiappAddForm"; +import OpdsFeedAddForm from "../dialog/OpdsFeedAddForm"; -import SearchForm from "./SearchForm"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -52,176 +51,54 @@ class Header extends React.Component { // FIXME : css in code return ( - - - - - - - - { - this.home() - } - { - this.refresh() - } - { - this.bookshelf() - } +
            +

            {__("header.viewMode")}

            +
            + + {(displayType === DisplayType.Grid) ? + : + + } +

            {__("header.gridTitle")}

            + + + {(displayType === DisplayType.List) ? + : + + } +

            {__("header.listTitle")}

            + +
            +
            +
            + + +
            ); } - - private bookshelf = () => { - const { bookshelf } = this.props.headerLinks; - - let bookshelfComponent = <>; - if (bookshelf) { - - const { __ } = this.props; - - const param = matchPath( - routes["/opds/browse"].path, - this.props.location.pathname, - ).params; - - const lvl = parseInt(param.level, 10); - - const route = buildOpdsBrowserRoute( - param.opdsId, - __("opds.shelf"), - bookshelf, - lvl === 1 ? 3 : (lvl + 1), - ); - - bookshelfComponent = ( - - - - ); - } - - return bookshelfComponent; - }; - - private home = () => { - const { start } = this.props.headerLinks; - - let homeComponent = <>; - if (start) { - - const { __ } = this.props; - - const param = matchPath( - routes["/opds/browse"].path, - this.props.location.pathname, - ).params; - - const home = this.props.breadcrumb[1]; - - const route = buildOpdsBrowserRoute( - param.opdsId, - home.name || "", - start, - 1, - ); - - homeComponent = ( - - - - ); - } - - return homeComponent; - }; - - private refresh = () => { - const { self } = this.props.headerLinks; - const { __ } = this.props; - - let refreshComponet = <>; - if (self) { - - const param = matchPath( - routes["/opds/browse"].path, - this.props.location.pathname, - ).params; - - const lvl = parseInt(param.level, 10); - - const i = (lvl > 1) ? (lvl - 1) : lvl; - const name = this.props.breadcrumb[i]?.name; - - const route = buildOpdsBrowserRoute( - param.opdsId, - name, - self, - lvl, - ); - - refreshComponet = ( - - - - ); - } else { - refreshComponet = ( - - - - ); - } - - return refreshComponet; - }; } const mapStateToProps = (state: ILibraryRootState) => ({ diff --git a/src/renderer/library/components/opds/MessageOpdBrowserResult.tsx b/src/renderer/library/components/opds/MessageOpdBrowserResult.tsx index ba5810ac2..1a4b02d83 100644 --- a/src/renderer/library/components/opds/MessageOpdBrowserResult.tsx +++ b/src/renderer/library/components/opds/MessageOpdBrowserResult.tsx @@ -6,7 +6,7 @@ // ==LICENSE-END== import * as React from "react"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps { @@ -32,7 +32,7 @@ export default class MessageOpdBrowserResult extends React.Component

            {title}

            - {message &&

            {message}

            } + {message ?

            {message}

            :

            🙈

            }
    ); } diff --git a/src/renderer/library/components/opds/Opds.tsx b/src/renderer/library/components/opds/Opds.tsx index 50ae61d58..1cf4a2c14 100644 --- a/src/renderer/library/components/opds/Opds.tsx +++ b/src/renderer/library/components/opds/Opds.tsx @@ -35,9 +35,9 @@ class Opds extends React.Component { const { __ } = this.props; return ( } > - ); diff --git a/src/renderer/library/components/opds/OpdsAddForm.tsx b/src/renderer/library/components/opds/OpdsAddForm.tsx index 6925d8e61..6674002b1 100644 --- a/src/renderer/library/components/opds/OpdsAddForm.tsx +++ b/src/renderer/library/components/opds/OpdsAddForm.tsx @@ -6,66 +6,19 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; -import * as AddIcon from "readium-desktop/renderer/assets/icons/add-alone.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import SVG from "readium-desktop/renderer/common/components/SVG"; -import { TDispatch } from "readium-desktop/typings/redux"; +import ApiappAddFormDialog from "readium-desktop/renderer/library/components/dialog/ApiappAddForm"; +import OpdsFeedAddForm from "../dialog/OpdsFeedAddForm"; +import * as stylesHeader from "readium-desktop/renderer/assets/styles/header.scss"; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} +const OpdsAddForm: React.FC = () => { + return ( +
    + + +
    + ); -export class OpdsAddForm extends React.Component { - - constructor(props: IProps) { - super(props); - } - - public render(): React.ReactElement<{}> { - const { __ } = this.props; - return ( -
    - - -
    - ); - } -} - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - openOpdsFeedAddForm: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.OpdsFeedAddForm, {})); - }, - openApiappAddForm: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.ApiappAddForm, {})); - }, - }; }; -export default connect(undefined, mapDispatchToProps)(withTranslator(OpdsAddForm)); +export default OpdsAddForm; diff --git a/src/renderer/library/components/opds/PageNavigation.tsx b/src/renderer/library/components/opds/PageNavigation.tsx index b6e5c2c8a..5d82bd0d2 100644 --- a/src/renderer/library/components/opds/PageNavigation.tsx +++ b/src/renderer/library/components/opds/PageNavigation.tsx @@ -5,18 +5,13 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom"; import { keyboardShortcutsMatch } from "readium-desktop/common/keyboard"; import { IOpdsResultView } from "readium-desktop/common/views/opds"; -import * as ArrowRightIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_forward_ios-24px.svg"; -import * as ArrowLeftIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_left_ios-24px.svg"; -import * as ArrowFirstIcon from "readium-desktop/renderer/assets/icons/chevron-bar-left.svg"; -import * as ArrowLastIcon from "readium-desktop/renderer/assets/icons/chevron-bar-right.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as ArrowFirstIcon from "readium-desktop/renderer/assets/icons/arrowFirst-icon.svg"; +import * as ArrowLastIcon from "readium-desktop/renderer/assets/icons/arrowLast-icon.svg"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -26,9 +21,12 @@ import { } from "readium-desktop/renderer/common/keyboard"; import { buildOpdsBrowserRouteWithLink } from "readium-desktop/renderer/library/opds/route"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { dispatchHistoryPush, DisplayType, IRouterLocationState } from "readium-desktop/renderer/library/routing"; +import { dispatchHistoryPush, IRouterLocationState } from "readium-desktop/renderer/library/routing"; import { TDispatch } from "readium-desktop/typings/redux"; +import * as stylesPublication from "readium-desktop/renderer/assets/styles/components/allPublicationsPage.scss"; +import * as ChevronRight from "readium-desktop/renderer/assets/icons/chevron-right.svg"; + interface IBaseProps extends TranslatorProps { pageLinks?: IOpdsResultView["links"]; pageInfo?: IOpdsResultView["metadata"]; @@ -71,111 +69,103 @@ class PageNavigation extends React.Component { const buildRoute = buildOpdsBrowserRouteWithLink(this.props.location.pathname); + + return ( -
    -
    - { - pageLinks?.first[0]?.url ? +
    + {/* */} + {/*

    {__("catalog.numberOfPages")}

    */} +
    +
    - { - pageInfo?.currentPage - && pageInfo.numberOfItems - && pageInfo.itemsPerPage - && + : + } + + + + + {/* */} + + {pageInfo.currentPage} / {Math.ceil(pageInfo.numberOfItems / pageInfo.itemsPerPage)} - } -
    - { - pageLinks?.next[0]?.url ? + + +
    ); diff --git a/src/renderer/library/components/opds/SearchForm.tsx b/src/renderer/library/components/opds/SearchForm.tsx index f3c2ad5b1..c01956f9d 100644 --- a/src/renderer/library/components/opds/SearchForm.tsx +++ b/src/renderer/library/components/opds/SearchForm.tsx @@ -10,7 +10,7 @@ import * as React from "react"; import { connect } from "react-redux"; import { matchPath } from "react-router-dom"; import { keyboardShortcutsMatch } from "readium-desktop/common/keyboard"; -import * as SearchIcon from "readium-desktop/renderer/assets/icons/baseline-search-24px-grey.svg"; +import * as SearchIcon from "readium-desktop/renderer/assets/icons/search-icon.svg"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -24,6 +24,7 @@ import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/ import { dispatchHistoryPush, IOpdsBrowse, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; import { TFormEvent } from "readium-desktop/typings/react"; import { TDispatch } from "readium-desktop/typings/redux"; +import * as stylesInput from "readium-desktop/renderer/assets/styles/components/inputs.scss"; import { encodeURIComponent_RFC3986 } from "@r2-utils-js/_utils/http/UrlUtils"; @@ -75,23 +76,30 @@ class SearchForm extends React.Component { return (
    + + - + */}
    ); } @@ -128,12 +136,12 @@ class SearchForm extends React.Component { debug("SubmitSearch 2", searchWords, url); const level = this.props.search.level - || parseInt( - matchPath( - routes["/opds/browse"].path, - this.props.location.pathname, - ).params.level, - 10); + || parseInt( + matchPath( + routes["/opds/browse"].path, + this.props.location.pathname, + ).params.level, + 10); this.props.historyPush({ ...this.props.location, diff --git a/src/renderer/library/components/publication/PublicationCard.tsx b/src/renderer/library/components/publication/PublicationCard.tsx index cf8dc9b4d..95226ec37 100644 --- a/src/renderer/library/components/publication/PublicationCard.tsx +++ b/src/renderer/library/components/publication/PublicationCard.tsx @@ -5,7 +5,6 @@ // that can be found in the LICENSE file exposed on Github (readium) in the project repository. // ==LICENSE-END== -import classNames from "classnames"; import * as React from "react"; import { connect } from "react-redux"; import { DialogTypeName } from "readium-desktop/common/models/dialog"; @@ -14,8 +13,9 @@ import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; import { PublicationView } from "readium-desktop/common/views/publication"; import * as MenuIcon from "readium-desktop/renderer/assets/icons/menu.svg"; -import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.css"; -import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.css"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; + import Cover from "readium-desktop/renderer/common/components/Cover"; import { TranslatorProps, withTranslator, @@ -31,11 +31,20 @@ import CatalogMenu from "./menu/CatalogMenu"; import OpdsMenu from "./menu/OpdsMenu"; import { convertMultiLangStringToString, langStringIsRTL } from "readium-desktop/renderer/common/language-string"; +import { PublicationInfoOpdsWithRadix, PublicationInfoOpdsWithRadixContent, PublicationInfoOpdsWithRadixTrigger } from "../dialog/publicationInfos/PublicationInfo"; +import * as CalendarIcon from "readium-desktop/renderer/assets/icons/calendar2-icon.svg"; +// import * as CalendarExpiredIcon from "readium-desktop/renderer/assets/icons/calendarExpired-icon.svg"; +import * as DoubleCheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; +import * as KeyIcon from "readium-desktop/renderer/assets/icons/key-icon.svg"; +import classNames from "classnames"; +import * as moment from "moment"; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { publicationViewMaybeOpds: PublicationView | IOpdsPublicationView; isOpds?: boolean; + isReading?: boolean; } // IProps may typically extend: // RouteComponentProps @@ -63,40 +72,132 @@ class PublicationCard extends React.Component { const pubTitleIsRTL = langStringIsRTL(pubTitleLang); const pubTitleStr = pubTitleLangStr && pubTitleLangStr[1] ? pubTitleLangStr[1] : ""; + const publicationView = publicationViewMaybeOpds as PublicationView; + + let pubFormat = "EPUB"; + if (publicationView.isAudio) { + pubFormat = "Audio"; + } else if (publicationView.isDivina) { + pubFormat = "Divina"; + } else if (publicationView.isPDF) { + pubFormat = "PDF"; + } else if (publicationView.isDaisy) { + pubFormat = "DAISY"; + } else if (publicationView.isFixedLayoutPublication) { + pubFormat = "EPUB (FXL)"; + } + + const lcpRightsEndDate = (publicationView.lcp?.rights?.end) ? publicationView.lcp.rights.end : undefined; + let remainingDays= ""; + const now = moment(); + let hasEnded = false; + const isLcp = publicationView.lcp?.rights ? true : false; + + if (lcpRightsEndDate) { + const momentEnd = moment(lcpRightsEndDate); + const timeEndDif = momentEnd.diff(now, "days"); + if (timeEndDif > 1) { + remainingDays = `${timeEndDif} ${__("publication.days")}`; + } else if (timeEndDif === 1) { + remainingDays = `${timeEndDif} ${__("publication.day")}`; + } else { + remainingDays = `${__("publication.expired")}`; + hasEnded = true; + } + } + + let tagString = ""; + if (publicationViewMaybeOpds.tags) { + for (const tag of publicationViewMaybeOpds.tags) { + if (typeof tag === "string") { + tagString = tag; + } else { + tagString = tag.name; + } + }; + } + // aria-haspopup="dialog" // aria-controls="dialog" return (
    - this.handleBookClick(e)} - onKeyPress={ - (e) => - (e.key === "Enter") && this.handleBookClick(e) - } - title={`${publicationViewMaybeOpds.documentTitle} - ${authors}`} - className={stylesPublications.publication_image_wrapper} - tabIndex={0} - > - - -
    - this.handleBookClick(e)} - className={stylesPublications.publication_infos} + { + isOpds ? + + + + +
    +

    + {pubTitleStr} +

    +

    + {this.truncateAuthors(authors)} +

    +
    +
    + + + + : + this.handleLocalBookshelfBookClick(e)} + onKeyPress={ + (e) => + (e.key === "Enter") && this.handleLocalBookshelfBookClick(e) + } + title={`${publicationViewMaybeOpds.documentTitle} - ${authors}`} + className={classNames(stylesPublications.publication_main_container, hasEnded ? stylesPublications.expired : "")} + tabIndex={0} > -

    - {pubTitleStr} -

    -

    - {this.truncateAuthors(authors)} -

    -
    - - )} - content={( -
    + +
    +

    + {pubTitleStr} +

    +

    + {this.truncateAuthors(authors)} +

    +
    + + } +
    +
    + {isOpds ? <> + :
    + {tagString === "/finished/" ? +
    {__("publication.read")}
    + : <>} + { + remainingDays ? +
    + + {remainingDays} +
    + : (isLcp && !remainingDays) ? +
    + + {__("publication.licensed")} +
    + : <> + } +
    } +
    + {isOpds ? <> + : {pubFormat}} + + )} + > {isOpds ? { } -
    - )} - dir="right" - /> +
    +
    +
    ); } - private handleBookClick(e: React.SyntheticEvent) { + private handleLocalBookshelfBookClick(e: React.SyntheticEvent) { e.preventDefault(); const { publicationViewMaybeOpds } = this.props; - - if (this.props.isOpds) { - this.props.openInfosDialog(publicationViewMaybeOpds as IOpdsPublicationView); - } else { - this.props.openReader(publicationViewMaybeOpds as PublicationView); - } + this.props.openReader(publicationViewMaybeOpds as PublicationView); } /* function Truncate very long titles at 60 characters */ diff --git a/src/renderer/library/components/publication/PublicationListElement.tsx b/src/renderer/library/components/publication/PublicationListElement.tsx index bc6f7ccbf..3e75aefe7 100644 --- a/src/renderer/library/components/publication/PublicationListElement.tsx +++ b/src/renderer/library/components/publication/PublicationListElement.tsx @@ -15,9 +15,8 @@ import { TPublication } from "readium-desktop/common/type/publication.type"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; import { PublicationView } from "readium-desktop/common/views/publication"; import * as MenuIcon from "readium-desktop/renderer/assets/icons/menu.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.css"; -import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -28,7 +27,6 @@ import { formatContributorToString, } from "readium-desktop/renderer/common/logics/formatContributor"; import { TDispatch } from "readium-desktop/typings/redux"; -import { v4 as uuidv4 } from "uuid"; import { convertMultiLangStringToString, langStringIsRTL } from "readium-desktop/renderer/common/language-string"; // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -46,7 +44,6 @@ interface IProps extends IBaseProps, ReturnType, Retu } export class PublicationListElement extends React.Component { - private menuId: string; private buttonRef: React.RefObject; constructor(props: IProps) { @@ -56,8 +53,6 @@ export class PublicationListElement extends React.Component { // this.deletePublication = this.deletePublication.bind(this); this.focusButton = this.focusButton.bind(this); - - this.menuId = "menu-" + uuidv4(); } public render(): React.ReactElement<{}> { @@ -110,16 +105,9 @@ export class PublicationListElement extends React.Component { svg={MenuIcon} />) } - content={( -
    - {this.props.menuContent} -
    - )} - dir="left" - /> + > + {this.props.menuContent} + {/* - - = (props) => { + const [__] = useTranslator(); + + return ( + <> + + + + + - - ); - } - - private deletePublication() { - this.props.openDeleteDialog(); - } - - private displayPublicationInfo() { - this.props.displayPublicationInfo(); - } -} - -const mapDispatchToProps = (dispatch: TDispatch, props: IBaseProps) => { - return { - displayPublicationInfo: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.PublicationInfoLib, - { - publicationIdentifier: props.publicationView.identifier, - }, - )); - }, - openDeleteDialog: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.DeletePublicationConfirm, - { - publicationView: props.publicationView, - }, - )); - }, - }; + + {props.publicationView.lastReadTimeStamp ? + + : <> + } + + +

    {__("catalog.delete")}

    + + )} + publicationView={props.publicationView} + /> + + + ); }; -export default connect(undefined, mapDispatchToProps)(withTranslator(CatalogMenu)); +export default (CatalogMenu); diff --git a/src/renderer/library/components/publication/menu/OpdsMenu.tsx b/src/renderer/library/components/publication/menu/OpdsMenu.tsx index d32d7f4f9..3830c1d88 100644 --- a/src/renderer/library/components/publication/menu/OpdsMenu.tsx +++ b/src/renderer/library/components/publication/menu/OpdsMenu.tsx @@ -6,74 +6,33 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import { dialogActions } from "readium-desktop/common/redux/actions/"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TMouseEventOnButton } from "readium-desktop/typings/react"; -import { TDispatch } from "readium-desktop/typings/redux"; +import { PublicationInfoOpdsWithRadix, PublicationInfoOpdsWithRadixContent, PublicationInfoOpdsWithRadixTrigger } from "../../dialog/publicationInfos/PublicationInfo"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/info-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; + +const OpdsMenu: React.FC<{opdsPublicationView: IOpdsPublicationView}> = (props) => { + const [__] = useTranslator(); + + return ( + <> + + + + + + + + + ); -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { - opdsPublicationView: IOpdsPublicationView; -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType, ReturnType { -} - -export class OpdsMenu extends React.Component { - - constructor(props: IProps) { - super(props); - - } - - public render(): React.ReactElement<{}> { - - const { - __, - } = this.props; - - return ( - <> - - - ); - } - - private displayPublicationInfo = (e: TMouseEventOnButton) => { - e.preventDefault(); - this.props.displayPublicationInfo(); - }; -} - -const mapDispatchToProps = (dispatch: TDispatch, props: IBaseProps) => { - return { - displayPublicationInfo: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.PublicationInfoOpds, - { - publication: props.opdsPublicationView, - }, - )); - }, - }; -}; - -const mapStateToProps = (_state: ILibraryRootState, _props: IBaseProps) => { - return { - }; }; -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(OpdsMenu)); +export default (OpdsMenu); diff --git a/src/renderer/library/components/publication/menu/PublicationExportButton.tsx b/src/renderer/library/components/publication/menu/PublicationExportButton.tsx index b79982f21..03824ade5 100644 --- a/src/renderer/library/components/publication/menu/PublicationExportButton.tsx +++ b/src/renderer/library/components/publication/menu/PublicationExportButton.tsx @@ -11,6 +11,8 @@ import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; +import * as SaveIcon from "readium-desktop/renderer/assets/icons/SaveAs-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -35,10 +37,10 @@ class PublicationExportButton extends React.Component { const { __ } = this.props; return ( ); } diff --git a/src/renderer/library/components/searchResult/AllPublicationPage.tsx b/src/renderer/library/components/searchResult/AllPublicationPage.tsx index ff4028595..b926d7888 100644 --- a/src/renderer/library/components/searchResult/AllPublicationPage.tsx +++ b/src/renderer/library/components/searchResult/AllPublicationPage.tsx @@ -7,19 +7,19 @@ import "regenerator-runtime/runtime"; // for react-table (useAsyncDebounce()) see: https://github.com/TanStack/react-table/issues/2071#issuecomment-679999096 -// import { classThemeExample, classStyleExample } from "./AllPublicationPage.css"; -// import classNames from "classnames"; - import { convertMultiLangStringToString, langStringIsRTL } from "readium-desktop/renderer/common/language-string"; import { IStringMap } from "@r2-shared-js/models/metadata-multilang"; import { Location } from "history"; import SVG from "readium-desktop/renderer/common/components/SVG"; -// import * as SearchIcon from "readium-desktop/renderer/assets/icons/baseline-search-24px-grey.svg"; -import * as magnifyingGlass from "readium-desktop/renderer/assets/icons/magnifying_glass.svg"; -import * as ArrowRightIcon from "readium-desktop/renderer/assets/icons/baseline-play_arrow-24px.svg"; // baseline-arrow_forward_ios-24px -- arrow -// import * as ArrowLeftIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_left_ios-24px.svg"; -import * as ArrowLastIcon from "readium-desktop/renderer/assets/icons/baseline-skip_next-24px.svg"; -import * as ArrowFirstIcon from "readium-desktop/renderer/assets/icons/baseline-skip_previous-24px.svg"; +import * as stylesPublication from "readium-desktop/renderer/assets/styles/components/allPublicationsPage.scss"; +import * as stylesInput from "readium-desktop/renderer/assets/styles/components/inputs.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as ArrowLastIcon from "readium-desktop/renderer/assets/icons/arrowLast-icon.svg"; +import * as SearchIcon from "readium-desktop/renderer/assets/icons/search-icon.svg"; +import * as ArrowFirstIcon from "readium-desktop/renderer/assets/icons/arrowFirst-icon.svg"; +import * as ChevronRight from "readium-desktop/renderer/assets/icons/chevron-right.svg"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as TagIcon from "readium-desktop/renderer/assets/icons/tag-icon.svg"; import { matchSorter } from "match-sorter"; import { readerActions } from "readium-desktop/common/redux/actions"; import { DialogTypeName } from "readium-desktop/common/models/dialog"; @@ -54,7 +54,7 @@ import { } from "react-table"; import { Column, useTable, useFilters, useSortBy, usePagination, useGlobalFilter, useAsyncDebounce } from "react-table"; import { formatTime } from "readium-desktop/common/utils/time"; -import DOMPurify from "dompurify"; +import * as DOMPurify from "dompurify"; import * as moment from "moment"; import { AvailableLanguages, I18nTyped, Translator } from "readium-desktop/common/services/translator"; import * as React from "react"; @@ -65,7 +65,6 @@ import { } from "readium-desktop/renderer/common/components/hoc/translator"; import { apiAction } from "readium-desktop/renderer/library/apiAction"; import { apiSubscribe } from "readium-desktop/renderer/library/apiSubscribe"; -import BreadCrumb from "readium-desktop/renderer/library/components/layout/BreadCrumb"; import LibraryLayout from "readium-desktop/renderer/library/components/layout/LibraryLayout"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; import { Unsubscribe } from "redux"; @@ -78,6 +77,30 @@ import { ensureKeyboardListenerIsInstalled, registerKeyboardListener, unregisterKeyboardListener, } from "readium-desktop/renderer/common/keyboard"; import { ipcRenderer } from "electron"; +import PublicationCard from "../publication/PublicationCard"; +import classNames from "classnames"; +import * as Popover from "@radix-ui/react-popover"; +import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.scss"; +// import { PublicationInfoLibWithRadix, PublicationInfoLibWithRadixContent, PublicationInfoLibWithRadixTrigger } from "../dialog/publicationInfos/PublicationInfo"; +import { useSearchParams } from "react-router-dom"; +// import * as FilterIcon from "readium-desktop/renderer/assets/icons/filter-icon.svg"; +// import * as DeleteFilter from "readium-desktop/renderer/assets/icons/deleteFilter-icon.svg"; +// import * as stylesTags from "readium-desktop/renderer/assets/styles/components/tags.scss"; +import { MySelectProps, Select } from "readium-desktop/renderer/common/components/Select"; +import { ComboBox, ComboBoxItem } from "readium-desktop/renderer/common/components/ComboBox"; +import * as CalendarIcon from "readium-desktop/renderer/assets/icons/calendar2-icon.svg"; +// import * as CalendarExpiredIcon from "readium-desktop/renderer/assets/icons/calendarExpired-icon.svg"; +// import * as DoubleCheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; +import * as KeyIcon from "readium-desktop/renderer/assets/icons/key-icon.svg"; +import AboutThoriumButton from "../catalog/AboutThoriumButton"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; +import Menu from "readium-desktop/renderer/common/components/menu/Menu"; +import CatalogMenu from "../publication/menu/CatalogMenu"; +import * as MenuIcon from "readium-desktop/renderer/assets/icons/menu.svg"; +import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; + + +// import GridTagButton from "../catalog/GridTagButton"; // import { // formatContributorToString, @@ -102,6 +125,7 @@ interface IProps extends IBaseProps, ReturnType, ReturnT interface IState { publicationViews: PublicationView[] | undefined; accessibilitySupportEnabled: boolean; + tags: string[]; } export class AllPublicationPage extends React.Component { @@ -117,6 +141,7 @@ export class AllPublicationPage extends React.Component { this.state = { publicationViews: undefined, accessibilitySupportEnabled: false, + tags: this.props.tags ? this.props.tags.slice() : [], }; } @@ -142,13 +167,20 @@ export class AllPublicationPage extends React.Component { ], () => { apiAction("publication/findAll") .then((publicationViews) => { - this.setState({publicationViews}); + this.setState({ publicationViews }); setTimeout(() => { - this.onKeyboardFocusSearch(); + // this.onKeyboardFocusSearch(); }, 400); }) .catch((error) => console.error("Error to fetch api publication/findAll", error)); }); + + if (this.props.location.search.indexOf("focus=search") > -1) { + console.log("focus=search"); + setTimeout(() => { + this.onKeyboardFocusSearch(); + }, 400); + } } public componentWillUnmount() { @@ -179,16 +211,15 @@ export class AllPublicationPage extends React.Component { const displayType = (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) || DisplayType.Grid; const { __ } = this.props; - const title = __("catalog.allBooks"); const secondaryHeader =
    ; - const breadCrumb = ; + // const breadCrumb = ; return ( { this.state.publicationViews ? @@ -202,12 +233,14 @@ export class AllPublicationPage extends React.Component { displayPublicationInfo={this.props.displayPublicationInfo} openReader={this.props.openReader} focusInputRef={this.focusInputRef} + tags={this.props.tags} /> // (displayType === DisplayType.Grid ? // : // ) - : <> + : <> } + ); } @@ -288,6 +321,7 @@ export class AllPublicationPage extends React.Component { const mapStateToProps = (state: ILibraryRootState) => ({ location: state.router.location, keyboardShortcuts: state.keyboard.shortcuts, + tags: state.publication.tag, }); const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { @@ -305,17 +339,16 @@ const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { }; }; -const commonCellStyles = (props: ITableCellProps_Column & ITableCellProps_GenericCell): React.CSSProperties => { +const commonCellStyles = (props: ITableCellProps_Column & ITableCellProps_GenericCell): React.CSSProperties => { return { // minHeight: props.displayType === DisplayType.Grid ? "150px" : "80px", - maxHeight: props.displayType === DisplayType.Grid ? "150px" : "80px", + maxHeight: props.displayType === DisplayType.Grid ? "150px" : "100px", // minWidth: props.displayType === DisplayType.Grid ? "150px" : "100px", // maxWidth: props.displayType === DisplayType.Grid ? "150px" : "50px", padding: "0.4em", - overflowY: "auto", - textAlign: "center", + textAlign: "left", userSelect: "text", }; }; @@ -347,7 +380,7 @@ const CellGlobalFilter: React.FC = (props) => { const onInputChange = useAsyncDebounce((v) => { // if (v) {} - props.setShowColumnFilters(false); + props.setShowColumnFilters(true); props.setGlobalFilter(v); }, 500); @@ -356,38 +389,23 @@ const CellGlobalFilter: React.FC = (props) => { // className={classNames(classStyleExample)} return ( -
    - +
    -
    - {props.globalFilteredRows.length !== props.preGlobalFilteredRows.length ? ` (${props.globalFilteredRows.length} / ${props.preGlobalFilteredRows.length})` : ` (${props.preGlobalFilteredRows.length})`} -
    + {/* value={value || ""} */} = (props) => { }} onKeyUp={(e) => { if (props.accessibilitySupportEnabled && e.key === "Enter") { - props.setShowColumnFilters(false); + props.setShowColumnFilters(true); props.setGlobalFilter( // value (props.focusInputRef?.current?.value || "").trim() || undefined); } }} placeholder={`${props.__("header.searchTitle")}`} - style={{ - border: "1px solid gray", - borderRadius: "4px", - margin: "0", - marginLeft: "0.4em", - width: "10em", - padding: "0.2em", - }} - /> + /> {props.accessibilitySupportEnabled ? : <> - } -
    - : <>; + } + }, []); + + const onInputChange = useAsyncDebounce((v) => { + props.column.setFilter(v); + }, 500); + + return props.showColumnFilters ? +
    + { + /* + value={ // props.column.filterValue + value || ""} + */ + } + { + // setValue(e.target.value); + // forceReRender(NaN); + if (!props.accessibilitySupportEnabled) { + onInputChange((e.target.value || "").trim() || undefined); + if (props.column.id === "colTags") { + props.setSelectedTag(e.target.value.trim()); + } + } + }} + onKeyUp={(e) => { + if (props.accessibilitySupportEnabled && e.key === "Enter") { + // (e.target as EventTarget & HTMLInputElement).value + // value + props.column.setFilter( // props.column.filterValue + (inputRef?.current?.value || "").trim() || undefined); + if (props.column.id === "colTags") { + props.setSelectedTag(inputRef?.current?.value.trim()); + console.log(inputRef.current.value); + } + } + }} + aria-label={`${props.__("header.searchPlaceholder")} (${props.column.Header})`} + placeholder={`${props.__("header.searchPlaceholder")} (${props.column.Header})`} + className={stylesPublication.showColFilters_input} + style={{ + width: props.accessibilitySupportEnabled ? "calc(100% - 30px)" : "100%", + }} + /> + { + props.accessibilitySupportEnabled ? : <> + } +
    + : <>; }; interface ITableCellProps_GenericCell extends ITableCellProps_Common { setShowColumnFilters: (show: boolean, columnId: string, filterValue: string) => void; + + selectedTag: string, + setSelectedTag: React.Dispatch>, } interface IColumnValue_Cover extends IColumnValue_BaseString { @@ -571,58 +594,23 @@ interface ITableCellProps_Value_Cover { value: IColumnValue_Cover; } const CellCoverImage: React.FC = (props) => { - return (
    - { - e.preventDefault(); - - props.displayPublicationInfo(props.value.publicationViewIdentifier); - // props.openReader(props.value.publicationViewIdentifier); - }} - onKeyPress={ - (e) => { - if (e.key === "Enter") { - e.preventDefault(); - - props.displayPublicationInfo(props.value.publicationViewIdentifier); - // props.openReader(props.value.publicationViewIdentifier); - } - } - } - title={`${props.value.title} (${props.__("catalog.bookInfo")})`} - > - {""} - + return (); }; @@ -632,51 +620,27 @@ const CellFormat: React.FC { if (e.key === "Enter") { - e.preventDefault(); - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} + onKeyPress={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + } + }} onClick={(e) => { e.preventDefault(); // props.column.setFilter(t); props.setShowColumnFilters(true, props.column.id, t); }} - style={{ - display: "flex", - alignItems: "center", - textAlign: "center", - padding: "2px 6px", - fontSize: "1rem", - // backgroundColor: "#e7f1fb", - // borderRadius: "5px", - // border: "1px solid var(--color-tertiary)", - // color: "var(--color-tertiary)", - cursor: "pointer", - // textDecoration: "none", - textDecoration: "underline", - textDecorationColor: "var(--color-tertiary)", - textDecorationSkip: "ink", - marginRight: "6px", - marginBottom: "6px", - }}>{t}; - }; - - const flexStyle: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "center", - flexWrap: "wrap", - paddingTop: "0.2em", + className={stylesButtons.button_nav_primary} style={{ padding: "2px" }}>{t}; }; - return (
    + return (
    { - link(props.value) + link(props.value) } -
    ); +
    ); }; interface IColumnValue_Langs extends IColumnValue_BaseString { @@ -691,79 +655,44 @@ const CellLangs: React.FC { if (e.key === "Enter") { - e.preventDefault(); - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} + onKeyPress={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + } + }} onClick={(e) => { e.preventDefault(); // props.column.setFilter(t); props.setShowColumnFilters(true, props.column.id, t); }} - style={{ - display: "flex", - alignItems: "center", - textAlign: "center", - padding: "2px 6px", - fontSize: "1rem", - // backgroundColor: "#e7f1fb", - // borderRadius: "5px", - // border: "1px solid var(--color-tertiary)", - // color: "var(--color-tertiary)", - cursor: "pointer", - // textDecoration: "none", - textDecoration: "underline", - textDecorationColor: "var(--color-tertiary)", - textDecorationSkip: "ink", - marginRight: "6px", - marginBottom: "6px", - }}>{t}; + className={stylesPublication.cell_link}>{t}; }; // props.value.label === props.value.tags.join(", ") - const flexStyle: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "center", - flexWrap: "wrap", - paddingTop: "0.2em", - }; - return props.value.langs?.length ? - ( - props.value.langs.length === 1 ? ( -
    - { - link(props.value.langs[0]) - } -
    - ) : ( -
      - { - props.value.langs.map((t, i) => { - return
    • {link(t)}
    • ; - }) - } -
    - )) - : <>; + ( + props.value.langs.length === 1 ? ( +
    + { + link(props.value.langs[0]) + } +
    + ) : ( +
      + { + props.value.langs.map((t, i) => { + return
    • {link(t)}
    • ; + }) + } +
    + )) + : <>; }; interface IColumnValue_Publishers extends IColumnValue_BaseString { @@ -778,79 +707,44 @@ const CellPublishers: React.FC { if (e.key === "Enter") { - e.preventDefault(); - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} + onKeyPress={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + } + }} onClick={(e) => { e.preventDefault(); // props.column.setFilter(t); props.setShowColumnFilters(true, props.column.id, t); }} - style={{ - display: "flex", - alignItems: "center", - textAlign: "center", - padding: "2px 6px", - fontSize: "1rem", - // backgroundColor: "#e7f1fb", - // borderRadius: "5px", - // border: "1px solid var(--color-tertiary)", - // color: "var(--color-tertiary)", - cursor: "pointer", - // textDecoration: "none", - textDecoration: "underline", - textDecorationColor: "var(--color-tertiary)", - textDecorationSkip: "ink", - marginRight: "6px", - marginBottom: "6px", - }}>{t}; + className={stylesPublication.cell_link}>{t}; }; // props.value.label === props.value.tags.join(", ") - const flexStyle: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "center", - flexWrap: "wrap", - paddingTop: "0.2em", - }; - return props.value.publishers?.length ? - ( - props.value.publishers.length === 1 ? ( -
    - { - link(props.value.publishers[0]) - } -
    - ) : ( -
      - { - props.value.publishers.map((t, i) => { - return
    • {link(t)}
    • ; - }) - } -
    - )) - : <>; + ( + props.value.publishers.length === 1 ? ( +
    + { + link(props.value.publishers[0]) + } +
    + ) : ( +
      + { + props.value.publishers.map((t, i) => { + return
    • {link(t)}
    • ; + }) + } +
    + )) + : <>; }; interface IColumnValue_Authors extends IColumnValue_BaseString { @@ -865,89 +759,54 @@ const CellAuthors: React.FC { if (e.key === "Enter") { - e.preventDefault(); - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} + onKeyPress={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + } + }} onClick={(e) => { e.preventDefault(); // props.column.setFilter(t); props.setShowColumnFilters(true, props.column.id, t); }} - style={{ - display: "flex", - alignItems: "center", - textAlign: "center", - padding: "2px 6px", - fontSize: "1rem", - // backgroundColor: "#e7f1fb", - // borderRadius: "5px", - // border: "1px solid var(--color-tertiary)", - // color: "var(--color-tertiary)", - cursor: "pointer", - // textDecoration: "none", - textDecoration: "underline", - textDecorationColor: "var(--color-tertiary)", - textDecorationSkip: "ink", - marginRight: "6px", - marginBottom: "6px", - }}>{t}; + className={stylesPublication.cell_link}>{t}; }; // props.value.label === props.value.tags.join(", ") - const flexStyle: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "center", - flexWrap: "wrap", - paddingTop: "0.2em", - }; - return props.value.authors?.length ? - ( -
    - { - props.value.authors.length === 1 ? ( -
    - { - link(props.value.authors[0]) - } -
    - ) : ( -
      - { - props.value.authors.map((t, i) => { - return
    • {link(t)}
    • ; - }) - } -
    - ) - } -
    - ) - : <>; + ( +
    + { + props.value.authors.length === 1 ? ( +
    + { + link(props.value.authors[0]) + } +
    + ) : ( +
      + { + props.value.authors.map((t, i) => { + return
    • {link(t)}
    • ; + }) + } +
    + ) + } +
    + ) + : <>; }; interface IColumnValue_Tags extends IColumnValue_BaseString { @@ -965,93 +824,85 @@ const CellTags: React.FC { if (e.key === "Enter") { - e.preventDefault(); - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} + onKeyPress={(e) => { + if (e.key === "Enter") { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + props.setSelectedTag(t); + } + }} onClick={(e) => { e.preventDefault(); // props.column.setFilter(t); props.setShowColumnFilters(true, props.column.id, t); + props.setSelectedTag(t); }} - style={{ - display: "flex", - alignItems: "center", - textAlign: "center", - backgroundColor: "#e7f1fb", - padding: "2px 6px", - fontSize: "1rem", - borderRadius: "5px", - border: "1px solid var(--color-tertiary)", - color: "var(--color-tertiary)", - cursor: "pointer", - textDecoration: "none", - marginRight: "6px", - marginBottom: "6px", - }}>{t}; + className={stylesButtons.button_nav_primary} style={{ padding: "2px" }}> +

    {t}

    + ; }; // props.value.label === props.value.tags.join(", ") - const flexStyle: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "center", - flexWrap: "wrap", - paddingTop: "0.2em", - }; - return props.value.tags?.length ? - ( - props.value.tags.length === 1 ? ( -
    - { - link(props.value.tags[0]) - } -
    - ) : ( -
      - { - props.value.tags.map((t, i) => { - return
    • {link(t)}
    • ; - }) - } -
    - )) - : <>; + ( + props.value.tags.length === 1 ? ( +
    + { + link(props.value.tags[0]) + } +
    + ) : ( +
      + { + props.value.tags.map((t, i) => { + return
    • {link(t)}
    • ; + }) + } +
    + )) + : <>; }; const CellDescription: React.FC = (props) => { - return (
    ); + // textAlign: props.displayType === DisplayType.Grid ? "justify" : "start", + textAlign: "start", + }}> +

    + {props.value ? + + + + + + +

    + +
    +
    +
    + : ""} +
    ); }; // interface IColumnValue_A11y_StringArrayArray extends IColumnValue_BaseString { @@ -1240,47 +1091,32 @@ interface ITableCellProps_Value_Date { } const CellDate: React.FC = (props) => { return ( - props.value.label ? -
    - { if (e.key === "Enter") { - e.preventDefault(); - const t = props.value.label.substring(0, props.column.id === "colLastReadTimestamp" ? 7 : 4); // YYYY or YYYY-MM - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); - }}} - - onClick={(e) => { - e.preventDefault(); - const t = props.value.label.substring(0, props.column.id === "colLastReadTimestamp" ? 7 : 4); // YYYY or YYYY-MM - // props.column.setFilter(t); - props.setShowColumnFilters(true, props.column.id, t); + props.value.label ? + - : <> + > + { + if (e.key === "Enter") { + e.preventDefault(); + const t = props.value.label.substring(0, props.column.id === "colLastReadTimestamp" ? 7 : 4); // YYYY or YYYY-MM + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + } + }} + + onClick={(e) => { + e.preventDefault(); + const t = props.value.label.substring(0, props.column.id === "colLastReadTimestamp" ? 7 : 4); // YYYY or YYYY-MM + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + }} + className={stylesPublication.cell_link}>{props.value.date} +
    + : <> ); }; @@ -1292,6 +1128,15 @@ interface IColumnValue_Title extends IColumnValue_BaseString { interface ITableCellProps_Value_Title { value: IColumnValue_Title; } + +interface ITableCellProps_Value_Remaining { + value: IColumnValue_Remain; +} + +interface ITableCellProps_Value_Actions { + value: IColumnValue_Actions; +} + const CellTitle: React.FC = (props) => { // props.value.label @@ -1302,38 +1147,80 @@ const CellTitle: React.FC { - e.preventDefault(); - - props.displayPublicationInfo(props.value.publicationViewIdentifier); - // props.openReader(props.value.publicationViewIdentifier); - }} - onKeyPress={ - (e) => { + dir={pubTitleIsRTL ? "rtl" : undefined} + > + props.openReader(props.value.publicationViewIdentifier)} + > + {pubTitleStr} + +
    ); +}; + +const CellRemainingDays: React.FC = (props) => { + + const link = (t: string) => { + return { if (e.key === "Enter") { e.preventDefault(); - - props.displayPublicationInfo(props.value.publicationViewIdentifier); - // props.openReader(props.value.publicationViewIdentifier); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); } - } - } - title={`${pubTitleStr} (${props.__("catalog.bookInfo")})`} - > - {pubTitleStr} - + }} + + onClick={(e) => { + e.preventDefault(); + // props.column.setFilter(t); + props.setShowColumnFilters(true, props.column.id, t); + }}>{t}; + }; + + return (
    + { + props.value.label ? +
    + + {link(props.value.label)} +
    + : props.value.isLcp ? +
    + + {props.__("publication.licensed")} +
    + : <>}
    ); }; +const CellActions: React.FC = (props) => { + const label = props.value.label; + const publication = props.value.publication; + + return ( +
    + + )} + > + + +
    + + ); +}; + const TableCell: React.FC = (props) => { return (
    convertMultiLangStringToString() // col_a11y_accessMode: IColumnValue_A11y_StringArray; // string[] @@ -1405,13 +1306,18 @@ interface ITableCellProps_TableView { focusInputRef: React.RefObject; location: Location; accessibilitySupportEnabled: boolean; + tags: string[]; } + export const TableView: React.FC = (props) => { - const [showColumnFilters, setShowColumnFilters] = React.useState(false); + const [showColumnFilters, setShowColumnFilters] = React.useState(true); + const [selectedTag, setSelectedTag] = React.useState(""); const scrollToViewRef = React.useRef(null); + const { __ } = props; + const renderProps_Filter: ITableCellProps_Filter = { __: props.__, @@ -1420,6 +1326,9 @@ export const TableView: React.FC { - return props.publicationViews.map((publicationView) => { + return props.publicationViews.slice().reverse().map((publicationView) => { // translator.translateContentField(author) // const authors = publicationView.authors ? formatContributorToString(publicationView.authors, props.translator) : ""; @@ -1484,6 +1396,25 @@ export const TableView: React.FC 1) { + remainingDays = `${timeEndDif} ${__("publication.days")}`; + } else if (timeEndDif === 1) { + remainingDays = `${timeEndDif} ${__("publication.day")}`; + } else { + remainingDays = `${__("publication.expired")}`; + hasEnded = true; + } + } + const langsArray = publicationView.languages ? publicationView.languages.map((lang) => { // See FormatPublicationLanguage @@ -1547,6 +1478,11 @@ export const TableView: React.FC { const arr: (Column & - UseTableColumnOptions & - UseSortByColumnOptions & - UseGlobalFiltersColumnOptions & + UseTableColumnOptions & + UseSortByColumnOptions & + UseGlobalFiltersColumnOptions & UseFiltersColumnOptions)[] = [ - { - Header: props.__("publication.cover.img"), - accessor: "colCover", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellCoverImage, - // filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("publication.title"), - accessor: "colTitle", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellTitle, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("publication.author"), - accessor: "colAuthors", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellAuthors, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("catalog.lang"), - accessor: "colLanguages", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellLangs, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("catalog.tags"), - accessor: "colTags", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellTags, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("catalog.format"), - accessor: "colFormat", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellFormat, - sortType: sortFunction, - }, - { - Header: props.__("catalog.lastRead"), - accessor: "colLastReadTimestamp", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellDate, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("catalog.publisher"), - accessor: "colPublishers", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellPublishers, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: props.__("catalog.released"), - accessor: "colPublishedDate", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellDate, - filter: "text", // because IColumnValue_BaseString instead of plain string - sortType: sortFunction, - }, - { - Header: "DRM", - accessor: "colLCP", - sortType: sortFunction, - }, - { - Header: props.__("publication.duration.title"), - accessor: "colDuration", - sortType: sortFunction, - }, - { - Header: props.__("catalog.description"), - accessor: "colDescription", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellDescription, - sortType: sortFunction, - }, + { + Header: props.__("publication.cover.img"), + accessor: "colCover", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellCoverImage, + // filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("publication.title"), + accessor: "colTitle", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellTitle, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("publication.author"), + accessor: "colAuthors", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellAuthors, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("publication.remainingTime"), + accessor: "colRemainingDays", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellRemainingDays, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("catalog.lang"), + accessor: "colLanguages", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellLangs, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("catalog.tags"), + accessor: "colTags", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellTags, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("catalog.format"), + accessor: "colFormat", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellFormat, + sortType: sortFunction, + }, + { + Header: props.__("catalog.lastRead"), + accessor: "colLastReadTimestamp", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellDate, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("catalog.publisher"), + accessor: "colPublishers", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellPublishers, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: props.__("catalog.released"), + accessor: "colPublishedDate", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellDate, + filter: "text", // because IColumnValue_BaseString instead of plain string + sortType: sortFunction, + }, + { + Header: "DRM", + accessor: "colLCP", + sortType: sortFunction, + }, + { + Header: props.__("publication.duration.title"), + accessor: "colDuration", + sortType: sortFunction, + }, + { + Header: props.__("catalog.description"), + accessor: "colDescription", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellDescription, + sortType: sortFunction, + }, - { - Header: props.__("catalog.about.button"), - accessor: "col_a11y_accessibilitySummary", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - Cell: CellDescription, - sortType: sortFunction, - }, - // { - // Header: "accessMode", - // accessor: "col_a11y_accessMode", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "accessModeSufficient", - // accessor: "col_a11y_accessModeSufficient", - // Cell: CellStringArrayArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "accessibilityFeature", - // accessor: "col_a11y_accessibilityFeature", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "accessibilityHazard", - // accessor: "col_a11y_accessibilityHazard", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "certifiedBy", - // accessor: "col_a11y_certifiedBy", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "certifierCredential", - // accessor: "col_a11y_certifierCredential", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "certifierReport", - // accessor: "col_a11y_certifierReport", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - // { - // Header: "conformsTo", - // accessor: "col_a11y_conformsTo", - // Cell: CellStringArray, - // filter: "text", // because IColumnValue_BaseString instead of plain string - // sortType: sortFunction, - // }, - - // { - // Header: props.__("publication.progression.title"), - // accessor: "colProgression", - // sortType: sortFunction, - // }, - // { - // Header: "Identifier", - // accessor: "colIdentifier", - // sortType: sortFunction, - // }, - // { - // Header: "Type", - // accessor: "colPublicationType", - // sortType: sortFunction, - // }, - ]; + { + Header: props.__("publication.accessibility.name"), + accessor: "col_a11y_accessibilitySummary", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellDescription, + sortType: sortFunction, + }, + { + Header: props.__("publication.actions"), + accessor: "colActions", + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + Cell: CellActions, + disableFilters: true, + disableSortBy: true, + }, + // { + // Header: "accessMode", + // accessor: "col_a11y_accessMode", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "accessModeSufficient", + // accessor: "col_a11y_accessModeSufficient", + // Cell: CellStringArrayArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "accessibilityFeature", + // accessor: "col_a11y_accessibilityFeature", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "accessibilityHazard", + // accessor: "col_a11y_accessibilityHazard", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "certifiedBy", + // accessor: "col_a11y_certifiedBy", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "certifierCredential", + // accessor: "col_a11y_certifierCredential", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "certifierReport", + // accessor: "col_a11y_certifierReport", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + // { + // Header: "conformsTo", + // accessor: "col_a11y_conformsTo", + // Cell: CellStringArray, + // filter: "text", // because IColumnValue_BaseString instead of plain string + // sortType: sortFunction, + // }, + + // { + // Header: props.__("publication.progression.title"), + // accessor: "colProgression", + // sortType: sortFunction, + // }, + // { + // Header: "Identifier", + // accessor: "colIdentifier", + // sortType: sortFunction, + // }, + // { + // Header: "Type", + // accessor: "colPublicationType", + // sortType: sortFunction, + // }, + ]; return arr; }, [props.displayType]); @@ -1848,29 +1807,30 @@ export const TableView: React.FC ({ - globalFilter: (rows: Row[], columnIds: string[], filterValue: string) => { - const set = new Set>(); - columnIds.forEach((columnId) => { - const subRes = filterTypes.text(rows, columnId, filterValue); - subRes.forEach((r) => { - set.add(r); - }); + globalFilter: (rows: Row[], columnIds: string[], filterValue: string) => { + const set = new Set>(); + columnIds.forEach((columnId) => { + const subRes = filterTypes.text(rows, columnId, filterValue); + subRes.forEach((r) => { + set.add(r); }); - const res = Array.from(set); - // console.log(`filterTypes.globalFilter ======= ${rows.length} ${JSON.stringify(columnIds)} ${typeof filterValue} ${res.length}`); - return res; - }, - text: (rows: Row[], columnId: string, filterValue: string) => { - // const res = rows.filter((row) => { - // let rowValue = row.values[columnId]; - // if (typeof rowValue !== "string") { - // rowValue = (rowValue as IColumnValue).label; - // } - // return rowValue - // ? String(rowValue).toLowerCase().startsWith(String(filterValue).toLowerCase()) - // : true; // keep (filter in, not out) - // }); - const res = matchSorter>(rows, filterValue, { keys: [(row) => { + }); + const res = Array.from(set); + // console.log(`filterTypes.globalFilter ======= ${rows.length} ${JSON.stringify(columnIds)} ${typeof filterValue} ${res.length}`); + return res; + }, + text: (rows: Row[], columnId: string, filterValue: string) => { + // const res = rows.filter((row) => { + // let rowValue = row.values[columnId]; + // if (typeof rowValue !== "string") { + // rowValue = (rowValue as IColumnValue).label; + // } + // return rowValue + // ? String(rowValue).toLowerCase().startsWith(String(filterValue).toLowerCase()) + // : true; // keep (filter in, not out) + // }); + const res = matchSorter>(rows, filterValue, { + keys: [(row) => { let rowValue = row.values[columnId]; if (typeof rowValue !== "string") { rowValue = (rowValue as IColumnValue_BaseString).label; @@ -1878,12 +1838,13 @@ export const TableView: React.FC & TableState = { - pageSize: 20, // props.displayType === DisplayType.List ? 20 : 10; + pageSize: 50, // props.displayType === DisplayType.List ? 20 : 10; pageIndex: 0, hiddenColumns: props.displayType === DisplayType.Grid ? ["colLanguages", "colPublishers", "colPublishedDate", "colLCP", "colDuration", "colDescription", "col_a11y_accessibilitySummary"] : [], }; @@ -1959,360 +1920,367 @@ export const TableView: React.FC // ))} // + + const SelectRef = React.forwardRef>((props, forwardedRef) => + ); + SelectRef.displayName = "ComboBox"; + + const tagsOptions = props.tags.map((v, i) => ({ id: i, value: i, name: v })); + + return ( <> -
    -
    - { - // ${props.__("catalog.opds.info.numberOfItems")} - // `(${tableRows.length})` - } - { - const currentShow = showColumnFilters; - setShowColumnFilters(show); - setTimeout(() => { - if (currentShow && !show) { - for (const col of tableInstance.allColumns) { - tableInstance.setFilter(col.id, ""); - } - } - }, 200); - }} - /> -
    - -
    -
    - - - - - -
    -
    - -
    - {" "} - - {tableInstance.headerGroups.map((headerGroup, index) => - ({ - headerGroup.headers.map((col, i) => { - - const column = col as unknown as ( - ColumnWithLooseAccessor & // { Header: string } & - UseTableColumnProps & - UseSortByColumnProps & - UseFiltersColumnProps - ); - - const columnIsSortable = column.id !== "colCover"; - - const W = column.id === "colCover" ? - (props.displayType === DisplayType.Grid ? "100px" : "40px") : - column.id === "colLCP" ? - "60px" : - column.id === "colPublishedDate" ? - "120px" : - column.id === "colProgression" ? - "100px" : - column.id === "colDuration" ? - "100px" : - column.id === "col_a11y_accessibilitySummary" ? - "180px" : - "160px"; - - return (); - }, - )}), - )} - { - // - // - // - } - - - {tableInstance.page.map((row, index) => { - tableInstance.prepareRow(row); + +
    + +
    + + + + + +
    +
    + + +
    + {" "} +
    - { - columnIsSortable ? - <> - { - column.canFilter ? - (
    { column.render("Filter", { - ...renderProps_Filter, - // columnFilter: column.filterValue, - }) }
    ) - : <> - } - - : - // - // { - // // props.displayType === DisplayType.List ? "" : column.render("Header") - // // column.render("Header") - // } - // - <> { - const show = showColumnFilters; - setShowColumnFilters(!showColumnFilters); +
    +

    {__("catalog.allBooks")}

    +
    +
    + { + const currentShow = showColumnFilters; + setShowColumnFilters(show); setTimeout(() => { - if (!show) { - tableInstance.setGlobalFilter(""); - } - if (show) { + if (currentShow && !show) { for (const col of tableInstance.allColumns) { tableInstance.setFilter(col.id, ""); } } }, 200); }} - style={{position: "absolute", left: "-999px"}} - /> + /> + { + (props.tags.length > 0) && (props.displayType === DisplayType.Grid) + ? + //
    + // { + // setSelectedTag(i as number); + // // tableInstance.setGlobalFilter(tagsOptions.find((tag) => tag.id === i).name); + // tableInstance.setFilter("colTags",tagsOptions.find((tag) => tag.id === i).name); + // }} + // label={__("reader.navigation.page")} + // className={stylesPublication.form_group} + // > + // {item => {item.name}} + // + //
    + +
    + tag.name?.toLowerCase().includes(selectedTag?.toLowerCase()))?.id || undefined} + onSelectionChange={(i) => { + setSelectedTag(tagsOptions.find((tag) => tag.id === i)?.name); + tableInstance.setFilter("colTags", tagsOptions.find((tag) => tag.id === i)?.name); + // console.log(tableInstance.columns.find((element) => element.Header === "Tags")) + }} + svg={TagIcon} + allowsCustomValue + > + {item => {item.name}} + +
    + + // + // + // + // + // + // + // + //
    + // {props.tags.map((tag, i: number) => { + // return ( + // tableInstance.setGlobalFilter(tag)} + // className={stylesTags.tag_item} + // > + // {tag} + // + // ); + // })} + //
    + // + //
    + //
    + //
    + : <> } -
    - // - //
    + {props.displayType === DisplayType.Grid ? "" + : + {tableInstance.headerGroups.map((headerGroup, index) => + ({ + headerGroup.headers.map((col, i) => { + + const column = col as unknown as ( + ColumnWithLooseAccessor & // { Header: string } & + UseTableColumnProps & + UseSortByColumnProps & + UseFiltersColumnProps + ); + + const columnIsSortable = column.id !== "colCover"; + + const W = column.id === "colCover" ? + "60px" : + column.id === "colPublishedDate" ? + "100px" : + column.id === "colProgression" ? + "100px" : + column.id === "colDuration" ? + "100px" : + column.id === "col_a11y_accessibilitySummary" ? + "160px" : + column.id === "colAuthors" ? + "160px" : + column.id === "colRemainingDays" ? + "150px" : + column.id === "colActions" ? + "60px" : + "100px"; + + return (); + }, + )}), + )} + { + // + // + // + } - return ({row.cells.map((cell, i) => - { - return ({ - cell.render("Cell", renderProps_Cell) - }); - }, - )} - - ); - })} -
    + { + !column.canSort ? + + : + columnIsSortable ? + <> + { + column.canFilter ? + (
    {column.render("Filter", { + ...renderProps_Filter, + // columnFilter: column.filterValue, + })}
    ) + : <> + } + + : + // + // { + // // props.displayType === DisplayType.List ? "" : column.render("Header") + // // column.render("Header") + // } + // + <> { + + const show = showColumnFilters; + setShowColumnFilters(!showColumnFilters); + + setTimeout(() => { + if (!show) { + tableInstance.setGlobalFilter(""); + } + if (show) { + for (const col of tableInstance.allColumns) { + tableInstance.setFilter(col.id, ""); + } + } + }, 200); + }} + style={{ position: "absolute", left: "-999px" }} + /> + } +
    + // + //
    } +
    -
    + > + {tableInstance.page.map((row, index) => { + const id = parseInt(row.id, 10); + + tableInstance.prepareRow(row); + return ( + props.displayType === DisplayType.Grid ? + + + + : + + {row.cells.map((cell, i) => { + return ({ + cell.render("Cell", renderProps_Cell) + }); + }, + )} + + ); + })} + + {/* */} +
    ); }; diff --git a/src/renderer/library/components/searchResult/TagSearchResult.tsx b/src/renderer/library/components/searchResult/TagSearchResult.tsx deleted file mode 100644 index 658ddedc5..000000000 --- a/src/renderer/library/components/searchResult/TagSearchResult.tsx +++ /dev/null @@ -1,111 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; -import { connect } from "react-redux"; -import { matchPath } from "react-router-dom"; -import { PublicationView } from "readium-desktop/common/views/publication"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { apiSubscribe } from "readium-desktop/renderer/library/apiSubscribe"; -import BreadCrumb from "readium-desktop/renderer/library/components/layout/BreadCrumb"; -import LibraryLayout from "readium-desktop/renderer/library/components/layout/LibraryLayout"; -import { GridView } from "readium-desktop/renderer/library/components/utils/GridView"; -import { ListView } from "readium-desktop/renderer/library/components/utils/ListView"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DisplayType, ILibrarySearchText, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; -import { Unsubscribe } from "redux"; - -import Header from "../catalog/Header"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} - -interface IState { - publicationViews: PublicationView[] | undefined; -} - -export class TagSearchResult extends React.Component { - private unsubscribe: Unsubscribe; - - constructor(props: IProps) { - super(props); - this.state = { - publicationViews: undefined, - }; - } - - public componentDidMount() { - this.unsubscribe = apiSubscribe([ - "publication/delete", - "publication/importFromFs", - "publication/updateTags", - // "catalog/addEntry", - ], () => { - const value = matchPath( - routes["/library/search/tag"].path, - this.props.location.pathname, - ).params.value; - - apiAction("publication/findByTag", value) - .then((publicationViews) => this.setState({ publicationViews })) - .catch((error) => console.error("Error to fetch api publication/findByTag", error)); - }); - } - - public componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); - } - } - - public render(): React.ReactElement<{}> { - const displayType = (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) || DisplayType.Grid; - - const { __ } = this.props; - - const title = matchPath( - routes["/library/search/tag"].path, - this.props.location.pathname, - ).params.value; - - const secondaryHeader =
    ; - const breadCrumb = ; - - return ( - -
    - {this.state.publicationViews ? - (displayType === DisplayType.Grid ? - : - ) - : <>} -
    -
    - ); - } -} - -const mapStateToProps = (state: ILibraryRootState) => ({ - location: state.router.location, -}); - -export default connect(mapStateToProps)(withTranslator(TagSearchResult)); diff --git a/src/renderer/library/components/searchResult/TextSearchResult.tsx b/src/renderer/library/components/searchResult/TextSearchResult.tsx deleted file mode 100644 index 70a3d28d0..000000000 --- a/src/renderer/library/components/searchResult/TextSearchResult.tsx +++ /dev/null @@ -1,134 +0,0 @@ -// ==LICENSE-BEGIN== -// Copyright 2017 European Digital Reading Lab. All rights reserved. -// Licensed to the Readium Foundation under one or more contributor license agreements. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file exposed on Github (readium) in the project repository. -// ==LICENSE-END== - -import * as React from "react"; -import { connect } from "react-redux"; -import { matchPath } from "react-router-dom"; -import { PublicationView } from "readium-desktop/common/views/publication"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { apiSubscribe } from "readium-desktop/renderer/library/apiSubscribe"; -import BreadCrumb from "readium-desktop/renderer/library/components/layout/BreadCrumb"; -import LibraryLayout from "readium-desktop/renderer/library/components/layout/LibraryLayout"; -import { GridView } from "readium-desktop/renderer/library/components/utils/GridView"; -import { ListView } from "readium-desktop/renderer/library/components/utils/ListView"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { DisplayType, ILibrarySearchText, IRouterLocationState, routes } from "readium-desktop/renderer/library/routing"; -import { Unsubscribe } from "redux"; - -import Header from "../catalog/Header"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} - -interface IState { - publicationViews: PublicationView[] | undefined; -} - -export class TextSearchResult extends React.Component { - private unsubscribe: Unsubscribe; - - constructor(props: IProps) { - super(props); - - this.state = { - publicationViews: undefined, - }; - } - - public componentDidMount() { - this.unsubscribe = apiSubscribe([ - "publication/importFromFs", - "publication/delete", - // "catalog/addEntry", - "publication/updateTags", - ], this.searchPublications); - } - - public componentDidUpdate(prevProps: IProps) { - - const text = matchPath( - routes["/library/search/text"].path, - this.props.location.pathname, - ).params.value; - - const prevText = matchPath( - routes["/library/search/text"].path, - prevProps.location.pathname, - ).params.value; - - if (text !== prevText) { - // Refresh searched pubs - this.searchPublications(); - } - } - - public componentWillUnmount() { - if (this.unsubscribe) { - this.unsubscribe(); - } - } - - public render(): React.ReactElement<{}> { - const displayType = (this.props.location?.state && (this.props.location.state as IRouterLocationState).displayType) || DisplayType.Grid; - - const { __ } = this.props; - - const title = matchPath( - routes["/library/search/text"].path, - this.props.location.pathname, - ).params.value; - - const secondaryHeader =
    ; - const breadCrumb = ; - - return ( - -
    - {this.state.publicationViews ? - (displayType === DisplayType.Grid ? - : - ) - : <>} -
    -
    - ); - } - - private searchPublications = (text?: string) => { - if (!text) { - - text = matchPath( - routes["/library/search/text"].path, - this.props.location.pathname, - ).params.value; - } - apiAction("publication/search", text) - .then((publicationViews) => this.setState({ publicationViews })) - .catch((error) => console.error("Error to fetch api publication/search", error)); - }; -} - -const mapStateToProps = (state: ILibraryRootState) => ({ - location: state.router.location, -}); - -export default connect(mapStateToProps)(withTranslator(TextSearchResult)); diff --git a/src/renderer/library/components/settings/AuthSettings.tsx b/src/renderer/library/components/settings/AuthSettings.tsx index de2478521..b4ff915ed 100644 --- a/src/renderer/library/components/settings/AuthSettings.tsx +++ b/src/renderer/library/components/settings/AuthSettings.tsx @@ -8,8 +8,8 @@ import * as React from "react"; import { connect } from "react-redux"; import { authActions } from "readium-desktop/common/redux/actions"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; diff --git a/src/renderer/library/components/settings/KeyboardSettings.tsx b/src/renderer/library/components/settings/KeyboardSettings.tsx index be2c4aaaa..70b310e7c 100644 --- a/src/renderer/library/components/settings/KeyboardSettings.tsx +++ b/src/renderer/library/components/settings/KeyboardSettings.tsx @@ -7,6 +7,7 @@ import classNames from "classnames"; import * as React from "react"; +import * as Popover from "@radix-ui/react-popover"; import FocusLock from "react-focus-lock"; import { connect } from "react-redux"; import { @@ -15,17 +16,19 @@ import { } from "readium-desktop/common/keyboard"; import { ToastType } from "readium-desktop/common/models/toast"; import { keyboardActions, toastActions } from "readium-desktop/common/redux/actions/"; -import * as ChevronDownIcon from "readium-desktop/renderer/assets/icons/chevron-down.svg"; import * as MenuIcon from "readium-desktop/renderer/assets/icons/menu.svg"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/info-icon.svg"; +import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.scss"; +import * as stylesSettings from "readium-desktop/renderer/assets/styles/components/settings.scss"; +import * as stylesKeys from "readium-desktop/renderer/assets/styles/components/keyboardsShortcuts.scss"; +import * as stylesDropDown from "readium-desktop/renderer/assets/styles/components/dropdown.scss"; + import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; -import Menu from "readium-desktop/renderer/common/components/menu/Menu"; import { ensureKeyboardListenerIsInstalled, KEY_CODES, TKeyboardDocument, } from "readium-desktop/renderer/common/keyboard"; @@ -36,6 +39,11 @@ import { ObjectKeys } from "readium-desktop/utils/object-keys-values"; import { sortObject } from "@r2-utils-js/_utils/JsonUtils"; import SVG from "../../../common/components/SVG"; +import * as EditIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; +import * as SaveIcon from "readium-desktop/renderer/assets/icons/floppydisk-icon.svg"; +import { useTranslator } from "../../../common/hooks/useTranslator"; +import { useDispatch } from "../../../common/hooks/useDispatch"; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { @@ -54,6 +62,52 @@ interface IState { editKeyboardShortcutData: TKeyboardShortcut | undefined; } +export const AdvancedTrigger = () => { + const [ __ ]= useTranslator(); + const dispatch = useDispatch(); + + const onClickKeyboardShortcutsShow = () => { + dispatch(keyboardActions.showShortcuts.build(true)); + }; + + const onClickKeyboardShortcutsReload = (defaults: boolean) => { + dispatch(keyboardActions.reloadShortcuts.build(defaults)); + }; + + return ( + + + + + + +
    + + + +
    + +
    +
    +
    + ); +}; + + class KeyboardSettings extends React.Component { private selectRef: React.RefObject; @@ -90,57 +144,23 @@ class KeyboardSettings extends React.Component { public render(): React.ReactElement<{}> { const { __ } = this.props; + return ( <>
    -
    -

    {__("settings.keyboard.keyboardShortcuts")}

    -
    - - { - ( - this.state.displayKeyboardShortcuts && !this.state.editKeyboardShortcutId - ) && ( - ) - } - content={( -
    - - - -
    - )} - dir="left" - /> + {/* {!this.state.editKeyboardShortcutId && ( + ) - } + } */} +
    + +

    {__("settings.keyboard.disclaimer")}

    +
    - {this.state.displayKeyboardShortcuts && (
    ) => { if (e.key === "Escape") { @@ -159,61 +179,79 @@ class KeyboardSettings extends React.Component { const def = this.props.keyboardShortcuts[id]; const hit = this.state.editKeyboardShortcutId === id; const frag = <> - - { - hit && - - } - - {id} -
    { - hit ? - this.editifyKeyboardShortcut(id, this.state.editKeyboardShortcutData) - : - this.prettifyKeyboardShortcut(def) - }
    +

    {id}

    +
    +
    + {this.prettifyKeyboardShortcut(def)} + +
    + { + hit && + <> + {this.editifyKeyboardShortcut(id, this.state.editKeyboardShortcutData)} +
    + + +
    + + } +
    + {/*

    Suspendisse varius risus magna, vitae cursus quam fringilla a.

    */} ; return
  • { (hit ? { })}
  • - )}
    ); @@ -311,6 +348,7 @@ class KeyboardSettings extends React.Component { // this.props.toast( // `${this.props.translator.translate("settings.keyboard.keyboardShortcuts")} ${kstring}`); } + private onClickKeyboardShortcutEditCancel(id: TKeyboardShortcutId) { if (!this.state.editKeyboardShortcutId || @@ -329,29 +367,19 @@ class KeyboardSettings extends React.Component { editKeyboardShortcutData: undefined, }); } - private onClickKeyboardShortcutsShowHide() { - this.setState({ - displayKeyboardShortcuts: !this.state.displayKeyboardShortcuts, - - editKeyboardShortcutId: undefined, - editKeyboardShortcutData: undefined, - }); - } - private onClickKeyboardShortcutsShow() { - this.props.showKeyboardShortcuts(); - } - private onClickKeyboardShortcutsReload(defaults: boolean) { - this.props.reloadKeyboardShortcuts(defaults); - } + // private onClickKeyboardShortcutsShow() { + // this.props.showKeyboardShortcuts(); + // } + // private onClickKeyboardShortcutsReload(defaults: boolean) { + // this.props.reloadKeyboardShortcuts(defaults); + // } private prettifyKeyboardShortcut(def: TKeyboardShortcut) { - const alt = def.alt ? ALT : null; - const shift = def.shift ? SHIFT : null; - const control = def.control ? CTRL : null; - const meta = def.meta ? META : null; - const key = {def.key}; - return <>{shift}{control}{alt}{meta}{(def.shift || def.control || def.alt || def.meta) ? - (+) : - null}{key}; + const alt = def.alt ? ALT + : null; + const shift = def.shift ? SHIFT + : null; + const control = def.control ? CTRL + : null; + const meta = def.meta ? META + : null; + const key = {def.key}; + return <>{shift}{control}{alt}{meta}{key}; } private stringifyKeyboardShortcut(def: TKeyboardShortcut) { return `${def.shift ? "SHIFT " : ""}${def.control ? "CTRL " : ""}${def.alt ? "ALT " : ""}${def.meta ? "META " : ""}${(def.shift || def.control || def.alt || def.meta) ? "+ " : ""}${def.key}`; @@ -362,7 +390,7 @@ class KeyboardSettings extends React.Component { id={`idcheckbox_${id}_ALT`} type="checkbox" checked={def.alt ? true : false} - className={stylesInputs.checkbox_keyboard} + className={stylesKeys.keyshortElement_shortcut_container_edit_input} onChange={() => { const editKeyboardShortcutData = JSON.parse(JSON.stringify(this.state.editKeyboardShortcutData)) as TKeyboardShortcut; @@ -384,7 +412,7 @@ class KeyboardSettings extends React.Component { id={`idcheckbox_${id}_SHIFT`} type="checkbox" checked={def.shift ? true : false} - className={stylesInputs.checkbox_keyboard} + className={stylesKeys.keyshortElement_shortcut_container_edit_input} onChange={() => { const editKeyboardShortcutData = JSON.parse(JSON.stringify(this.state.editKeyboardShortcutData)) as TKeyboardShortcut; @@ -406,7 +434,7 @@ class KeyboardSettings extends React.Component { id={`idcheckbox_${id}_CTRL`} type="checkbox" checked={def.control ? true : false} - className={stylesInputs.checkbox_keyboard} + className={stylesKeys.keyshortElement_shortcut_container_edit_input} onChange={() => { const editKeyboardShortcutData = JSON.parse(JSON.stringify(this.state.editKeyboardShortcutData)) as TKeyboardShortcut; @@ -428,7 +456,7 @@ class KeyboardSettings extends React.Component { id={`idcheckbox_${id}_META`} type="checkbox" checked={def.meta ? true : false} - className={stylesInputs.checkbox_keyboard} + className={stylesKeys.keyshortElement_shortcut_container_edit_input} onChange={() => { const editKeyboardShortcutData = JSON.parse(JSON.stringify(this.state.editKeyboardShortcutData)) as TKeyboardShortcut; @@ -451,6 +479,7 @@ class KeyboardSettings extends React.Component { } const keySelect = + <> + + ; const kstring = this.stringifyKeyboardShortcut(def); const keySink = { } }} >; - return <>{shift}{control}{alt}{meta}{keySelect}{keySink}; + return
    {shift}{control}{alt}{meta}{keySelect}{keySink}
    ; } } diff --git a/src/renderer/library/components/settings/LanguageSettings.tsx b/src/renderer/library/components/settings/LanguageSettings.tsx index 450a97669..e70a17bf4 100644 --- a/src/renderer/library/components/settings/LanguageSettings.tsx +++ b/src/renderer/library/components/settings/LanguageSettings.tsx @@ -10,8 +10,7 @@ import { connect } from "react-redux"; import { i18nActions } from "readium-desktop/common/redux/actions/"; import { AvailableLanguages } from "readium-desktop/common/services/translator"; import * as DoneIcon from "readium-desktop/renderer/assets/icons/done.svg"; -import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -42,7 +41,7 @@ class LanguageSettings extends React.Component {

    {__("settings.language.languageChoice")}

    -
    + { ObjectKeys(AvailableLanguages).map((lang, i) =>
    {

    {__("settings.session.title")}

    - +
    -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps { -} - -class Settings extends React.Component { - - public render(): React.ReactElement<{}> { - const { __ } = this.props; - return ( - <> - -
    - -
    - - - -
    +import * as Dialog from "@radix-ui/react-dialog"; +import * as Tabs from "@radix-ui/react-tabs"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/close-icon.svg"; +import * as CogIcon from "readium-desktop/renderer/assets/icons/cog-icon.svg"; +import * as PaletteIcon from "readium-desktop/renderer/assets/icons/palette-icon.svg"; +import * as KeyReturnIcon from "readium-desktop/renderer/assets/icons/keyreturn-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.scss"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesSettings from "readium-desktop/renderer/assets/styles/components/settings.scss"; +import classNames from "classnames"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import { useSelector } from "readium-desktop/renderer/common/hooks/useSelector"; +import { IRendererCommonRootState } from "readium-desktop/common/redux/states/rendererCommonRootState"; +import { AvailableLanguages } from "readium-desktop/common/services/translator"; +// import * as LanguageIcon from "readium-desktop/renderer/assets/icons/language.svg"; +// import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import { ComboBox, ComboBoxItem } from "readium-desktop/renderer/common/components/ComboBox"; +import { useDispatch } from "readium-desktop/renderer/common/hooks/useDispatch"; +import { authActions, i18nActions, themeActions } from "readium-desktop/common/redux/actions"; +import * as BinIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import { ICommonRootState } from "readium-desktop/common/redux/states/commonRootState"; +import { TTheme } from "readium-desktop/common/redux/states/theme"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/info-icon.svg"; +import * as LanguageIcon from "readium-desktop/renderer/assets/icons/language.svg"; +import * as BrushIcon from "readium-desktop/renderer/assets/icons/paintbrush-icon.svg"; +import KeyboardSettings, { AdvancedTrigger } from "readium-desktop/renderer/library/components/settings/KeyboardSettings"; +import * as GearIcon from "readium-desktop/renderer/assets/icons/gear-icon.svg"; + +interface ISettingsProps {}; + +const TabTitle = (props: React.PropsWithChildren<{title: string}>) => { + return ( +
    +

    {props.title}

    + {props.children} +
    + ); +}; + +const LanguageSettings: React.FC<{}> = () => { + const [__] = useTranslator(); + const locale = useSelector((state: IRendererCommonRootState) => state.i18n.locale); + const currentLanguageISO = locale as keyof typeof AvailableLanguages; + const currentLanguageString = AvailableLanguages[currentLanguageISO]; + const dispatch = useDispatch(); + const [options] = React.useState(() => Object.entries(AvailableLanguages).sort().map(([k,v], i) => ({id: i, name: v, iso: k}))); + const setLang = (localeSelected: React.Key) => { + + if (typeof localeSelected !== "number") return; + const obj = options.find(({id}) => id === localeSelected); + dispatch(i18nActions.setLocale.build(obj.iso)); + }; + const selectedKey = options.find(({name}) => name === currentLanguageString); + return ( + + {item => {item.name}} + + ); +}; + +export const Auth = () => { + const [__] = useTranslator(); + const dispatch = useDispatch(); + + return ( + + ); +}; + +const ConnectionSettings: React.FC<{}> = () => { + const [__] = useTranslator(); + return ( +
    +

    {__("catalog.opds.auth.login")}

    + +
    + ); +}; + + +const Themes = () => { + const [__] = useTranslator(); + const dispatch = useDispatch(); + const theme = useSelector((s: ICommonRootState) => s.theme); + const options: Array<{id: number, value: TTheme, name: string}> = [ + {id: 1, value: "dark", name: __("settings.theme.dark")}, + {id: 2, value: "light", name: __("settings.theme.light")}, + {id: 3, value: "system", name: __("settings.theme.auto")}, + ]; + + const setTheme = (themeSelected: React.Key) => { + + if (typeof themeSelected !== "number") return; + const { value: themeChosen } = options.find(({ id }) => id === themeSelected) || {}; + document.body.setAttribute("data-theme", themeChosen); + dispatch(themeActions.setTheme.build(themeChosen)); + }; + const selectedKey = options.find(({ value }) => value === theme.name); + + return ( +
    + + {item => {item.name}} + + {theme.name === "system" ? ( +
    + +

    {__("settings.theme.description")}

    +
    + ) : ( + <> + )} +
    + ); +}; + +const TabHeader = (props: React.PropsWithChildren<{title: string}>) => { + return ( +
    + + {props.children} + + + + +
    + ); +}; + + +export const Settings: React.FC = () => { + const [__] = useTranslator(); + + return + + + + +
    + + + + + +

    {__("settings.tabs.general")}

    +
    + + +

    {__("settings.tabs.appearance")}

    +
    + + +

    {__("settings.tabs.keyboardShortcuts")}

    +
    +
    +
    + + +
    + + +
    +
    + + +
    + +
    +
    + + + + +
    + +
    +
    - - - ); - } -} +
    -export default withTranslator(Settings); + {/*
    + + + +
    */} +
    +
    +
    ; +}; diff --git a/src/renderer/library/components/utils/GridView.tsx b/src/renderer/library/components/utils/GridView.tsx index 17c5ffe80..e91d5bff3 100644 --- a/src/renderer/library/components/utils/GridView.tsx +++ b/src/renderer/library/components/utils/GridView.tsx @@ -8,7 +8,7 @@ import * as React from "react"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as stylesPublicationView from "readium-desktop/renderer/assets/styles/publicationView.css"; +import * as stylesPublicationView from "readium-desktop/renderer/assets/styles/publicationView.scss"; import PublicationCard from "readium-desktop/renderer/library/components/publication/PublicationCard"; type NormalOrOpdsPublicationView = PublicationView | IOpdsPublicationView; diff --git a/src/renderer/library/components/utils/ListView.tsx b/src/renderer/library/components/utils/ListView.tsx index 16deadc11..7e0c22282 100644 --- a/src/renderer/library/components/utils/ListView.tsx +++ b/src/renderer/library/components/utils/ListView.tsx @@ -8,8 +8,8 @@ import * as React from "react"; import { IOpdsPublicationView } from "readium-desktop/common/views/opds"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; -import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.css"; +import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scss"; +import * as stylesPublications from "readium-desktop/renderer/assets/styles/components/publications.scss"; import CatalogMenu from "readium-desktop/renderer/library/components/publication/menu/CatalogMenu"; import OpdsMenu from "readium-desktop/renderer/library/components/publication/menu/OpdsMenu"; import PublicationListElement from "readium-desktop/renderer/library/components/publication/PublicationListElement"; diff --git a/src/renderer/library/components/utils/Slider.tsx b/src/renderer/library/components/utils/Slider.tsx index 8a38a5a49..b5d04cbb1 100644 --- a/src/renderer/library/components/utils/Slider.tsx +++ b/src/renderer/library/components/utils/Slider.tsx @@ -8,8 +8,8 @@ import classNames from "classnames"; import * as React from "react"; import * as ArrowRightIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_forward_ios-24px.svg"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesSlider from "readium-desktop/renderer/assets/styles/components/slider.css"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesSlider from "readium-desktop/renderer/assets/styles/components/slider.scss"; import SVG from "readium-desktop/renderer/common/components/SVG"; import { TranslatorProps, withTranslator } from "../../../common/components/hoc/translator"; @@ -104,35 +104,55 @@ class Slider extends React.Component { return (
    - {this.state.position < 0 ? - : <> - } -
    + + +
    {this.handleScroll(e)}} */>
    {list}
    - {this.state.position > max ? - : <> - }
    ); } + // private handleScroll(e: React.UIEvent): void { + // if (!this.wrapperRef?.current || !this.contentRef?.current) { + // return; + // } + // const max = - this.wrapperRef.current.scrollWidth + this.wrapperRef.current.offsetWidth; + // let step = - e.currentTarget.scrollLeft; + + // if (this.state.position === max) { + // step = - step; + // } + + // let position = Math.round((this.state.position + step) / 10) * 10; + + // if (position > 0) { + // position = 0; + // } else if (position < max) { + // position = max; + // } + + // this.setState({ position, refreshVisible: true }); + // console.log(position, step); + // } + private handleMove(moveRight: number) { if (!this.wrapperRef?.current || !this.contentRef?.current) { return; @@ -148,7 +168,6 @@ class Slider extends React.Component { } else if (position < max) { position = max; } - this.setState({position, refreshVisible: true}); } diff --git a/src/renderer/library/index_library.ts b/src/renderer/library/index_library.ts index 53ab59daf..7dd484192 100644 --- a/src/renderer/library/index_library.ts +++ b/src/renderer/library/index_library.ts @@ -68,7 +68,9 @@ ipcRenderer.on(winIpc.CHANNEL, (_0: any, data: winIpc.EventPayload) => { switch (data.type) { case winIpc.EventType.IdResponse: // Initialize window + const preloadedState: Partial = { + theme: data.payload.theme, publication: data.payload.publication, }; createStoreFromDi(preloadedState) diff --git a/src/renderer/library/redux/middleware/sync.ts b/src/renderer/library/redux/middleware/sync.ts index 050cbb87f..c95f25f62 100644 --- a/src/renderer/library/redux/middleware/sync.ts +++ b/src/renderer/library/redux/middleware/sync.ts @@ -6,7 +6,7 @@ // ==LICENSE-END== import { - apiActions, authActions, catalogActions, downloadActions, i18nActions, keyboardActions, lcpActions, readerActions, sessionActions, + apiActions, authActions, catalogActions, downloadActions, i18nActions, keyboardActions, lcpActions, readerActions, sessionActions, themeActions, } from "readium-desktop/common/redux/actions"; import { syncFactory } from "readium-desktop/renderer/common/redux/middleware/syncFactory"; @@ -43,6 +43,12 @@ const SYNCHRONIZABLE_ACTIONS: string[] = [ readerActions.disableRTLFlip.ID, readerActions.configSetDefault.ID, // readerConfig + + themeActions.setTheme.ID, + + readerActions.bookmark.pop.ID, + readerActions.bookmark.push.ID, + readerActions.bookmark.update.ID, ]; export const reduxSyncMiddleware = syncFactory(SYNCHRONIZABLE_ACTIONS); diff --git a/src/renderer/library/redux/reducers/index.ts b/src/renderer/library/redux/reducers/index.ts index e23a63b3f..363e0ac7e 100644 --- a/src/renderer/library/redux/reducers/index.ts +++ b/src/renderer/library/redux/reducers/index.ts @@ -27,11 +27,14 @@ import { sessionReducer } from "readium-desktop/common/redux/reducers/session"; import { catalogViewReducer } from "./catalog"; import { tagReducer } from "./tag"; import { readerDefaultConfigReducer } from "readium-desktop/common/redux/reducers/reader/defaultConfig"; +import { themeReducer } from "readium-desktop/common/redux/reducers/theme"; + // import { ReaderConfig } from "readium-desktop/common/models/reader"; import { readerRTLFlipReducer } from "readium-desktop/common/redux/reducers/reader/rtlFlip"; export const rootReducer = (routerReducer: Reducer) => { // : Reducer> return combineReducers({ // ILibraryRootState + theme: themeReducer, reader: combineReducers({ defaultConfig: readerDefaultConfigReducer, disableRTLFlip: readerRTLFlipReducer, diff --git a/src/renderer/library/routing.ts b/src/renderer/library/routing.ts index a7756e5ec..fbef59b09 100644 --- a/src/renderer/library/routing.ts +++ b/src/renderer/library/routing.ts @@ -13,9 +13,8 @@ import Catalog from "./components/catalog/Catalog"; import Browser from "./components/opds/Browser"; import Opds from "./components/opds/Opds"; import AllPublicationPage from "./components/searchResult/AllPublicationPage"; -import TagSearchResult from "./components/searchResult/TagSearchResult"; -import TextSearchResult from "./components/searchResult/TextSearchResult"; -import Settings from "./components/settings/Settings"; +// import TagSearchResult from "./components/searchResult/TagSearchResult"; +// import TextSearchResult from "./components/searchResult/TextSearchResult"; interface Route { path: string; @@ -59,30 +58,35 @@ const _routes = { // exact: false, // component: LanguageSettings, // } as Route, - "/settings": { - path: "/settings", - // exact: false, - component: Settings, - } as Route, - "/library/search/text": { - // ILibrarySearchText - path: "/library/search/text/:value", - // exact: true, - component: TextSearchResult, - } as Route, - "/library/search/tag": { - // ILibrarySearchTag - path: "/library/search/tag/:value", - // exact: true, - component: TagSearchResult, - } as Route, - "/library/search/all": { - path: "/library/search/all", + // "/settings": { + // path: "/settings", + // // exact: false, + // component: Settings, + // } as Route, + // "/library/search/text": { + // // ILibrarySearchText + // path: "/library/search/text/:value", + // // exact: true, + // component: TextSearchResult, + // } as Route, + // "/library/search/tag": { + // // ILibrarySearchTag + // path: "/library/search/tag/:value", + // // exact: true, + // component: TagSearchResult, + // } as Route, + // "/library/focus": { + // path: "/library/focus/:focusElement/:value?", + // // exact: true, + // component: AllPublicationPage, + // } as Route, + "/library": { + path: "/library", // exact: true, component: AllPublicationPage, } as Route, - "/library": { - path: "/library", + "/home": { + path: "/home", // exact: true, component: Catalog, } as Route, diff --git a/src/renderer/reader/components/AnnotationEdit.tsx b/src/renderer/reader/components/AnnotationEdit.tsx new file mode 100644 index 000000000..8acc5d301 --- /dev/null +++ b/src/renderer/reader/components/AnnotationEdit.tsx @@ -0,0 +1,239 @@ +// ==LICENSE-BEGIN== +// Copyright 2017 European Digital Reading Lab. All rights reserved. +// Licensed to the Readium Foundation under one or more contributor license agreements. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file exposed on Github (readium) in the project repository. +// ==LICENSE-END== + +import * as React from "react"; +import { IAnnotationState, IColor, TDrawType } from "readium-desktop/common/redux/states/renderer/annotation"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import { useSelector } from "readium-desktop/renderer/common/hooks/useSelector"; +import { IReaderRootState } from "readium-desktop/common/redux/states/renderer/readerRootState"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.scss"; +import * as stylesAnnotations from "readium-desktop/renderer/assets/styles/components/annotations.scss"; + +import * as Popover from "@radix-ui/react-popover"; +// import * as PenIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as CheckIcon from "readium-desktop/renderer/assets/icons/doubleCheck-icon.svg"; +import * as SaveIcon from "readium-desktop/renderer/assets/icons/floppydisk-icon.svg"; +import * as HighLightIcon from "readium-desktop/renderer/assets/icons/highlight-icon.svg"; +import * as UnderLineIcon from "readium-desktop/renderer/assets/icons/underline-icon.svg"; +import * as TextStrikeThroughtIcon from "readium-desktop/renderer/assets/icons/TextStrikethrough-icon.svg"; +import * as TextOutlineIcon from "readium-desktop/renderer/assets/icons/TextOutline-icon.svg"; +import { useDispatch } from "readium-desktop/renderer/common/hooks/useDispatch"; +import { readerLocalActionSetConfig } from "../redux/actions"; +import classNames from "classnames"; + +interface IPros { + save: (color: IColor, comment: string, drawType: TDrawType) => void; + cancel: () => void; + uuid?: string; + dockedMode: boolean; + btext?: string; +} + +// const annotationsColors = [ +// "#B80000", +// "#DB3E00", +// "#FCCB00", +// "#008B02", +// "#006B76", +// "#1273DE", +// "#004DCF", +// "#5300EB"]; + +const annotationsColorsLight = [ + "#EB9694", + "#FAD0C3", + "#FEF3BD", + "#C1EAC5", + "#BEDADC", + "#C4DEF6", + "#BED3F3", + "#D4C4FB", +]; + +const drawType: TDrawType[] = [ + "solid_background", + "underline", + "strikethrough", + "outline", +]; + +export const AnnotationEdit: React.FC = (props) => { + + const { save, cancel, uuid, dockedMode} = props; + + const displayFromReaderMenu = !!uuid; + const [__] = useTranslator(); + const { annotation_defaultColor, annotation_defaultDrawType } = useSelector((state: IReaderRootState) => state.reader.defaultConfig); + + const { cleanText } = useSelector((state: IReaderRootState) => state.annotation); + + let annotationState: Pick & { locatorExtended: { selectionInfo: { cleanText: string } } } + = { color: annotation_defaultColor, comment: "", drawType: annotation_defaultDrawType, locatorExtended: { selectionInfo: { cleanText } } }; + if (uuid) { + [, annotationState] = useSelector((state: IReaderRootState) => state.reader.annotation.find(([, annotationState]) => annotationState.uuid === uuid)); + } + + const colorStr = `#${annotationState.color.red.toString(16).padStart(2, "0")}${annotationState.color.green.toString(16).padStart(2, "0")}${annotationState.color.blue.toString(16).padStart(2, "0")}`.toUpperCase(); + + const [colorSelected, setColor] = React.useState(colorStr); + + const dispatch = useDispatch(); + const readerConfig = useSelector((state: IReaderRootState) => state.reader.config); + + const rgbresultmatch = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(colorSelected); + const colorObj = rgbresultmatch ? { + red: parseInt(rgbresultmatch[1], 16), + green: parseInt(rgbresultmatch[2], 16), + blue: parseInt(rgbresultmatch[3], 16), + } : annotationState.color; + + const previousColorSelected = React.useRef(colorObj); + + + const textAreaRef = React.useRef(); + + const [drawTypeSelected, setDrawType] = React.useState(annotationState.drawType); + const previousDrawTypeSelected = React.useRef(drawTypeSelected); + + const drawIcon = [ + HighLightIcon, + UnderLineIcon, + TextStrikeThroughtIcon, + TextOutlineIcon, + ]; + +// switch (drawType) { +// case "solid_background": +// drawIcon = HighLightIcon; +// break; +// case "underline": +// drawIcon = UnderLineIcon; +// break; +// case "strikethrough": +// drawIcon = TextStrikeThroughtIcon; +// break; +// case "outline": +// drawIcon = TextOutlineIcon; +// break; +// } + + const saveConfig = () => { + + let flag = false; + if (previousColorSelected.current.red !== colorObj.red || previousColorSelected.current.blue !== colorObj.blue || previousColorSelected.current.green !== colorObj.green) { + flag = true; + } + if (previousDrawTypeSelected.current !== drawTypeSelected) { + flag = true; + } + + if (flag) { + const newReaderConfig = { ...readerConfig }; + newReaderConfig.annotation_defaultColor = { ...colorObj }; + newReaderConfig.annotation_defaultDrawType = drawTypeSelected; + dispatch(readerLocalActionSetConfig.build(newReaderConfig)); + } + + previousColorSelected.current = { ...colorObj }; + previousDrawTypeSelected.current = drawTypeSelected; + }; + + React.useEffect(() => { + if (textAreaRef.current) { + textAreaRef.current.style.height = "auto"; + textAreaRef.current.style.height = textAreaRef.current.scrollHeight + 3 + "px"; + textAreaRef.current.focus(); + } + }, []); + + const component = + {displayFromReaderMenu ? <> : +

    {__("reader.annotations.addNote")}

    + } +
    +

    {annotationState.locatorExtended.selectionInfo.cleanText}

    + + +
    +
    + {/*
    */} +
    +

    {__("reader.annotations.Color")}

    +
    + {annotationsColorsLight.map((color) => ( +
    + setColor(color)} + checked={colorSelected === color} + /> + +
    + ), + )} +
    +
    +
    +

    {__("reader.annotations.highlight")}

    +
    + {drawType.map((type, i) => ( +
    + setDrawType(type)} + checked={drawTypeSelected === type} + /> + +
    + ), + )} +
    +
    +
    + + {/* */} +
    + {displayFromReaderMenu + ? + : {__("dialog.cancel")} + } + {displayFromReaderMenu + ? + : + { e.preventDefault(); save(colorObj, textAreaRef?.current?.value || "", drawTypeSelected); saveConfig(); }} + > + + {__("reader.annotations.saveNote")} + + } +
    + {/*
    */} + ; + + return component; +}; diff --git a/src/renderer/reader/components/App.tsx b/src/renderer/reader/components/App.tsx index b954c2f88..c0bc202a8 100644 --- a/src/renderer/reader/components/App.tsx +++ b/src/renderer/reader/components/App.tsx @@ -15,10 +15,10 @@ import { } from "readium-desktop/preprocessor-directives"; import ToastManager from "readium-desktop/renderer/common/components/toast/ToastManager"; import { TranslatorContext } from "readium-desktop/renderer/common/translator.context"; -import DialogManager from "readium-desktop/renderer/reader/components/dialog/DialogManager"; import { diReaderGet } from "readium-desktop/renderer/reader/di"; -import Nunito from "readium-desktop/renderer/assets/fonts/nunito.ttf"; -import NunitoBold from "readium-desktop/renderer/assets/fonts/nunitoBold.ttf"; + +import Nunito from "readium-desktop/renderer/assets/fonts/NunitoSans_10pt-Regular.ttf"; +import NunitoBold from "readium-desktop/renderer/assets/fonts/NunitoSans_10pt-SemiBold.ttf"; import * as globalScssStyle from "readium-desktop/renderer/assets/styles/global.scss"; globalScssStyle.__LOAD_FILE_SELECTOR_NOT_USED_JUST_TO_TRIGGER_WEBPACK_SCSS_FILE__; @@ -134,7 +134,6 @@ url("${rcssPath}/fonts/iAWriterDuospace-Regular.ttf") format("truetype"); - diff --git a/src/renderer/reader/components/Reader.tsx b/src/renderer/reader/components/Reader.tsx index 310bc6537..081ae9785 100644 --- a/src/renderer/reader/components/Reader.tsx +++ b/src/renderer/reader/components/Reader.tsx @@ -17,7 +17,7 @@ import { isDivinaFn, isPdfFn } from "readium-desktop/common/isManifestType"; import { DEBUG_KEYBOARD, keyboardShortcutsMatch } from "readium-desktop/common/keyboard"; import { DialogTypeName } from "readium-desktop/common/models/dialog"; import { - ReaderConfig, ReaderConfigBooleans, ReaderConfigStrings, ReaderConfigStringsAdjustables, + ReaderConfig, ReaderConfigStringsAdjustables, } from "readium-desktop/common/models/reader"; import { ToastType } from "readium-desktop/common/models/toast"; import { dialogActions, readerActions, toastActions } from "readium-desktop/common/redux/actions"; @@ -34,7 +34,9 @@ import * as DoubleArrowDownIcon from "readium-desktop/renderer/assets/icons/doub import * as DoubleArrowLeftIcon from "readium-desktop/renderer/assets/icons/double_arrow_left_black_24dp.svg"; import * as DoubleArrowRightIcon from "readium-desktop/renderer/assets/icons/double_arrow_right_black_24dp.svg"; import * as DoubleArrowUpIcon from "readium-desktop/renderer/assets/icons/double_arrow_up_black_24dp.svg"; -import * as stylesReader from "readium-desktop/renderer/assets/styles/reader-app.css"; +import * as exitZenModeIcon from "readium-desktop/renderer/assets/icons/fullscreenExit-icon.svg"; +import * as stylesReader from "readium-desktop/renderer/assets/styles/reader-app.scss"; +import * as stylesReaderFooter from "readium-desktop/renderer/assets/styles/components/readerFooter.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -47,7 +49,7 @@ import { import ReaderFooter from "readium-desktop/renderer/reader/components/ReaderFooter"; import ReaderHeader from "readium-desktop/renderer/reader/components/ReaderHeader"; import { - TChangeEventOnInput, TChangeEventOnSelect, TKeyboardEventOnAnchor, TMouseEventOnAnchor, + TChangeEventOnInput, TKeyboardEventOnAnchor, TMouseEventOnAnchor, TMouseEventOnSpan, } from "readium-desktop/typings/react"; import { TDispatch } from "readium-desktop/typings/redux"; @@ -71,7 +73,7 @@ import { readiumCssUpdate, setEpubReadingSystemInfo, setKeyDownEventHandler, setKeyUpEventHandler, setReadingLocationSaver, ttsClickEnable, ttsListen, ttsNext, ttsOverlayEnable, ttsPause, ttsPlay, ttsPlaybackRate, ttsPrevious, ttsResume, ttsSkippabilityEnable, ttsSentenceDetectionEnable, TTSStateEnum, - ttsStop, ttsVoice, + ttsStop, ttsVoice, highlightsClickListen, } from "@r2-navigator-js/electron/renderer/index"; import { reloadContent } from "@r2-navigator-js/electron/renderer/location"; import { Locator as R2Locator } from "@r2-navigator-js/electron/common/locator"; @@ -79,25 +81,23 @@ import { Locator as R2Locator } from "@r2-navigator-js/electron/common/locator"; import { TToc } from "../pdf/common/pdfReader.type"; import { pdfMount } from "../pdf/driver"; import { - readerLocalActionBookmarks, readerLocalActionDivina, readerLocalActionSetConfig, + readerLocalActionDivina, readerLocalActionSetConfig, readerLocalActionSetLocator, } from "../redux/actions"; import { TdivinaReadingMode, defaultReadingMode } from "readium-desktop/common/redux/states/renderer/divina"; import optionsValues, { - AdjustableSettingsNumber, IReaderMenuProps, IReaderOptionsProps, isDivinaReadingMode, + AdjustableSettingsNumber, IPopoverDialogProps, IReaderMenuProps, IReaderSettingsProps, isDivinaReadingMode, } from "./options-values"; -import PickerManager from "./picker/PickerManager"; import { URL_PARAM_CLIPBOARD_INTERCEPT, URL_PARAM_CSS, URL_PARAM_DEBUG_VISUALS, URL_PARAM_EPUBREADINGSYSTEM, URL_PARAM_GOTO, URL_PARAM_GOTO_DOM_RANGE, URL_PARAM_IS_IFRAME, URL_PARAM_PREVIOUS, URL_PARAM_REFRESH, URL_PARAM_SECOND_WEBVIEW, URL_PARAM_SESSION_INFO, URL_PARAM_WEBVIEW_SLOT } from "@r2-navigator-js/electron/renderer/common/url-params"; -import { createOrGetPdfEventBus } from "readium-desktop/renderer/reader/pdf/driver"; - -import { - highlightsCreate, -} from "@r2-navigator-js/electron/renderer"; +import * as ArrowRightIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_forward_ios-24px.svg"; +import * as ArrowLeftIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_left_ios-24px.svg"; +import { isAudiobookFn } from "readium-desktop/common/isManifestType"; -import { IS_DEV, _CONTINUOUS_INTEGRATION_DEPLOY } from "readium-desktop/preprocessor-directives"; +import { createOrGetPdfEventBus } from "readium-desktop/renderer/reader/pdf/driver"; -const ENABLE_HIGHLIGHTS_TEST_FEATURE = IS_DEV || _CONTINUOUS_INTEGRATION_DEPLOY; +import { winActions } from "readium-desktop/renderer/common/redux/actions"; +import { diReaderGet } from "../di"; // main process code! // thoriumhttps @@ -154,13 +154,13 @@ const handleLinkUrl_UpdateHistoryState = (url: string, isFromOnPopState = false) // console.log(">> HISTORY POP STATE DO URL (1)", url_); if (window.history.state?.data === url_) { - window.history.replaceState({data: url_, index: windowHistory._length - 1}, ""); + window.history.replaceState({ data: url_, index: windowHistory._length - 1 }, ""); } else { windowHistory._length++; - window.history.pushState({data: url_, index: windowHistory._length - 1}, ""); + window.history.pushState({ data: url_, index: windowHistory._length - 1 }, ""); } if (windowHistory._readerInstance) { - windowHistory._readerInstance.setState({historyCanGoForward: false, historyCanGoBack: windowHistory._length > 1}); + windowHistory._readerInstance.setState({ historyCanGoForward: false, historyCanGoBack: windowHistory._length > 1 }); } } }; @@ -201,7 +201,9 @@ interface IState { landmarksOpen: boolean; landmarkTabOpen: number; menuOpen: boolean; + focusMenuOpen: number; fullscreen: boolean; + zenMode: boolean; ttsState: TTSStateEnum; ttsPlaybackRate: string; @@ -221,12 +223,15 @@ interface IState { pdfPlayerToc: TToc | undefined; pdfPlayerNumberOfPages: number | undefined; - openedSectionSettings: number | undefined; - openedSectionMenu: number | undefined; + // openedSectionSettings: number | undefined; + openedSectionMenu: string; + annotationUUID: string; historyCanGoBack: boolean; historyCanGoForward: boolean; + dockingMode: "full" | "left" | "right"; + // bookmarkMessage: string | undefined; } @@ -267,6 +272,10 @@ class Reader extends React.Component { this.onKeyboardInfoWhereAmISpeak = this.onKeyboardInfoWhereAmISpeak.bind(this); this.onKeyboardFocusSettings = this.onKeyboardFocusSettings.bind(this); this.onKeyboardFocusNav = this.onKeyboardFocusNav.bind(this); + this.annotationDrawMarginOrPlainAnnotationToggleSwitch = this.annotationDrawMarginOrPlainAnnotationToggleSwitch.bind(this); + this.navLeftOrRight_.bind(this); + this.onKeyboardNavigationToBegin.bind(this); + this.onKeyboardNavigationToEnd.bind(this); this.onPopState = this.onPopState.bind(this); @@ -287,6 +296,7 @@ class Reader extends React.Component { menuOpen: false, fullscreen: false, + zenMode: false, ttsState: TTSStateEnum.STOPPED, ttsPlaybackRate: "1", @@ -304,21 +314,26 @@ class Reader extends React.Component { pdfPlayerToc: undefined, pdfPlayerNumberOfPages: undefined, - openedSectionSettings: undefined, - openedSectionMenu: undefined, + // openedSectionSettings: undefined, + openedSectionMenu: "tab-toc", + annotationUUID: "", divinaArrowEnabled: true, divinaContinousEqualTrue: false, historyCanGoBack: false, historyCanGoForward: false, + + dockingMode: "full", + + focusMenuOpen: 0, }; ttsListen((ttss: TTSStateEnum) => { - this.setState({ttsState: ttss}); + this.setState({ ttsState: ttss }); }); mediaOverlaysListen((mos: MediaOverlaysStateEnum) => { - this.setState({mediaOverlaysState: mos}); + this.setState({ mediaOverlaysState: mos }); }); this.handleTTSPlay = this.handleTTSPlay.bind(this); @@ -352,7 +367,7 @@ class Reader extends React.Component { this.handleToggleBookmark = this.handleToggleBookmark.bind(this); this.goToLocator = this.goToLocator.bind(this); this.handleLinkClick = this.handleLinkClick.bind(this); - this.displayPublicationInfo = this.displayPublicationInfo.bind(this); + this.handlePublicationInfo = this.handlePublicationInfo.bind(this); this.handleDivinaSound = this.handleDivinaSound.bind(this); @@ -362,6 +377,9 @@ class Reader extends React.Component { public async componentDidMount() { windowHistory._readerInstance = this; + const store = diReaderGet("store"); // diRendererSymbolTable.store + document.body.setAttribute("data-theme", store.getState().theme.name); + const handleMouseKeyboard = (isKey: boolean) => { if (_mouseMoveTimeout) { @@ -374,9 +392,9 @@ class Reader extends React.Component { if (nav) { nav.classList.remove(stylesReader.HIDE_CURSOR_CLASS_head); } - const foot = window.document.querySelector(`.${stylesReader.reader_footer}`); + const foot = window.document.querySelector(`.${stylesReaderFooter.reader_footer}`); if (foot) { - foot.classList.remove(stylesReader.HIDE_CURSOR_CLASS_foot); + foot.classList.remove(stylesReaderFooter.HIDE_CURSOR_CLASS_foot); } // if (!window.document.fullscreenElement && !window.document.fullscreen) { @@ -394,9 +412,9 @@ class Reader extends React.Component { if (nav) { nav.classList.add(stylesReader.HIDE_CURSOR_CLASS_head); } - const foot = window.document.querySelector(`.${stylesReader.reader_footer}`); + const foot = window.document.querySelector(`.${stylesReaderFooter.reader_footer}`); if (foot) { - foot.classList.add(stylesReader.HIDE_CURSOR_CLASS_foot); + foot.classList.add(stylesReaderFooter.HIDE_CURSOR_CLASS_foot); } }, 1000); }; @@ -525,11 +543,71 @@ class Reader extends React.Component { // sets state visibleBookmarkList await this.updateVisibleBookmarks(); + + + highlightsClickListen((href, highlight, event) => { + + if (highlight.group !== "annotation") { + if (typeof (window as any).__hightlightClickChannelEmitFn === "function") { + (window as any).__hightlightClickChannelEmitFn([href, highlight, event]); + } + return ; + } + + console.log("HIGHLIGHT Click from Reader.tsx"); + console.log(`href: ${href} | highlight: ${JSON.stringify(highlight, null, 4)} | event : ${JSON.stringify(event)}`); + + const store = diReaderGet("store"); + const mounterStateMap = store.getState()?.reader.highlight.mounter; + if (!mounterStateMap?.length) { + console.log(`highlightsClickListen MOUNTER STATE EMPTY -- mounterStateMap: [${JSON.stringify(mounterStateMap, null, 4)}]`); + return; + } + + const mounterStateItem = mounterStateMap.find(([_uuid, mounterState]) => mounterState.ref.id === highlight.id && mounterState.href === href); + + if (!mounterStateItem) { + console.log(`highlightsClickListen CANNOT FIND MOUNTER -- href: [${href}] ref.id: [${highlight.id}] mounterStateMap: [${JSON.stringify(mounterStateMap, null, 4)}]`); + return; + } + + const [mounterStateItemUuid] = mounterStateItem; // mounterStateItem[0] + + const handlerStateMap = store.getState()?.reader.highlight.handler; + if (!handlerStateMap?.length) { + console.log(`highlightsClickListen HANDLER STATE EMPTY -- handlerStateMap: [${JSON.stringify(handlerStateMap, null, 4)}]`); + return; + } + + const handlerStateItem = handlerStateMap.find(([uuid, _handlerState]) => uuid === mounterStateItemUuid); + + if (!handlerStateItem) { + console.log(`dispatchClick CANNOT FIND HANDLER -- uuid: [${mounterStateItemUuid}] handlerStateMap: [${JSON.stringify(handlerStateMap, null, 4)}]`); + return; + } + + const [uuid, handlerState] = handlerStateItem; + + console.log(`dispatchClick CLICK ACTION ... -- uuid: [${uuid}] handlerState: [${JSON.stringify(handlerState, null, 4)}]`); + + this.handleMenuButtonClick(true, "tab-annotation", true, uuid); + + if (href && handlerState.def.selectionInfo?.rangeInfo) { + this.handleLinkLocator({ + href, + locations: { + cssSelector: handlerState.def.selectionInfo.rangeInfo.startContainerElementCssSelector, + }, + }); + } + }); + + this.props.dispatchReaderTSXMountedAndPublicationIntoViewportLoaded(); } public async componentDidUpdate(oldProps: IProps, oldState: IState) { // if (oldProps.readerMode !== this.props.readerMode) { - // console.log("READER MODE = ", this.props.readerMode === ReaderMode.Detached ? "detached" : "attached"); + // console.log("READER MODE = ", this.props.readerMode === ReaderMode.Detached ? "detached" : "attached"); // } if (oldProps.bookmarks !== this.props.bookmarks || oldState.currentLocation !== this.state.currentLocation) { @@ -588,6 +666,7 @@ class Reader extends React.Component { const readerMenuProps: IReaderMenuProps = { open: this.state.menuOpen, + focus: this.state.focusMenuOpen, r2Publication: this.props.r2Publication, handleLinkClick: this.handleLinkClick, goToLocator: this.goToLocator, @@ -596,14 +675,17 @@ class Reader extends React.Component { pdfToc: this.state.pdfPlayerToc, isPdf: this.props.isPdf, openedSection: this.state.openedSectionMenu, + annotationUUID: this.state.annotationUUID, + resetAnnotationUUID: () => { this.setState({ annotationUUID: "" }); }, pdfNumberOfPages: this.state.pdfPlayerNumberOfPages, + setOpenedSection: (v: string) => this.setState({ openedSectionMenu: v }), }; - const readerOptionsProps: IReaderOptionsProps = { + const ReaderSettingsProps: IReaderSettingsProps = { open: this.state.settingsOpen, indexes: this.props.indexes, readerConfig: this.props.readerConfig, - handleSettingChange: this.handleSettingChange.bind(this), + // handleSettingChange: this.handleSettingChange.bind(this), handleIndexChange: this.handleIndexChange.bind(this), setSettings: this.setSettings, toggleMenu: this.handleSettingsClick, @@ -618,7 +700,17 @@ class Reader extends React.Component { isDivina: this.props.isDivina, isPdf: this.props.isPdf, - openedSection: this.state.openedSectionSettings, + isFXL: this.props.publicationView.isFixedLayoutPublication, + // openedSection: this.state.openedSectionSettings, + zenMode: this.state.zenMode, + setZenMode : () => this.setState({ zenMode : !this.state.zenMode}), + searchEnable: this.props.searchEnable, + }; + + const readerPopoverDialogContext: IPopoverDialogProps = { + dockingMode: this.state.dockingMode, + dockedMode: this.state.dockingMode !== "full", + setDockingMode: (m) => { this.setState({"dockingMode": m }); }, }; // {this.state.bookmarkMessage ?
    { // > // {this.state.bookmarkMessage} //
    : <>} + + + const isAudioBook = isAudiobookFn(this.props.r2Publication); + const arrowDisabledNotEpub = isAudioBook || this.props.isPdf || this.props.isDivina; + const isFXL = this.isFixedLayout(); + const isPaginated = this.props.readerConfig.paged; + + // console.log(arrowDisabledNotEpub, isFXL, isPaginated); + // epub non fxl (page) : false false true : true + // epub non fxl (scroll) : false false false : false + // epub fxl : false true true : true + // epub fxl (scroll) : false true false : true + // pdf : true false true : false + // audiobook : true false true : false + // divina : true false true : false + + const arrowEnabled = !arrowDisabledNotEpub && (isFXL || isPaginated); + return (
    { label={this.props.__("accessibility.skipLink")} />
    - { toggleBookmark={() => this.handleToggleBookmark(false)} isOnBookmark={this.state.visibleBookmarkList.length > 0} isOnSearch={this.props.searchEnable} - readerOptionsProps={readerOptionsProps} + ReaderSettingsProps={ReaderSettingsProps} readerMenuProps={readerMenuProps} - displayPublicationInfo={this.displayPublicationInfo} + handlePublicationInfo={this.handlePublicationInfo} // tslint:disable-next-line: max-line-length currentLocation={this.props.isDivina || this.props.isPdf ? this.props.locator : this.state.currentLocation} isDivina={this.props.isDivina} @@ -698,21 +809,28 @@ class Reader extends React.Component { divinaSoundPlay={this.handleDivinaSound} r2Publication={this.props.r2Publication} + readerPopoverDialogContext={readerPopoverDialogContext} + showSearchResults={this.showSearchResults} disableRTLFlip={this.props.disableRTLFlip} isRTLFlip={this.isRTLFlip} /> -
    this.setState({ zenMode : false})} className={stylesReader.button_exitZen}> + + + } + +
    -
    + className={stylesReader.publication_viewport_container} + > { aria-label={this.props.__("accessibility.mainContent")} tabIndex={-1}>{this.props.__("accessibility.mainContent")} + {arrowEnabled && !this.state.zenMode ? +
    + +
    + : + <>} +
    + style={{ inset: isAudioBook || !this.props.readerConfig.paged || this.props.isPdf || this.props.isDivina ? "0" : "100px 50px" }}>
    - { this.props.isDivina && this.state.divinaArrowEnabled ? @@ -769,11 +922,33 @@ class Reader extends React.Component {
    : <> } - + {arrowEnabled && !this.state.zenMode ? +
    + +
    + : + <>}
    + { !this.state.zenMode ? { disableRTLFlip={this.props.disableRTLFlip} isRTLFlip={this.isRTLFlip} /> + : <> + }
    ); } @@ -951,25 +1128,10 @@ class Reader extends React.Component { this.props.keyboardShortcuts.AudioStop, this.onKeyboardAudioStop); - // TODO HIGHLIGHTS-ANNOTATIONS: just for testing! - if (ENABLE_HIGHLIGHTS_TEST_FEATURE) { - registerKeyboardListener( - true, // listen for key up (not key down) - this.props.keyboardShortcuts.AnnotationsTest1, - this.onKeyboardAnnotationsTest1); - registerKeyboardListener( - true, // listen for key up (not key down) - this.props.keyboardShortcuts.AnnotationsTest2, - this.onKeyboardAnnotationsTest2); - registerKeyboardListener( - true, // listen for key up (not key down) - this.props.keyboardShortcuts.AnnotationsTest3, - this.onKeyboardAnnotationsTest3); - registerKeyboardListener( - true, // listen for key up (not key down) - this.props.keyboardShortcuts.AnnotationsTest4, - this.onKeyboardAnnotationsTest4); - } + registerKeyboardListener( + true, // listen for key up (not key down) + this.props.keyboardShortcuts.AnnotationDrawMarginOrPlainAnnotationToggleSwitch, + this.annotationDrawMarginOrPlainAnnotationToggleSwitch); } private unregisterAllKeyboardListeners() { @@ -997,14 +1159,7 @@ class Reader extends React.Component { unregisterKeyboardListener(this.onKeyboardAudioPreviousAlt); unregisterKeyboardListener(this.onKeyboardAudioNextAlt); unregisterKeyboardListener(this.onKeyboardAudioStop); - - // TODO HIGHLIGHTS-ANNOTATIONS: just for testing! - if (ENABLE_HIGHLIGHTS_TEST_FEATURE) { - unregisterKeyboardListener(this.onKeyboardAnnotationsTest1); - unregisterKeyboardListener(this.onKeyboardAnnotationsTest2); - unregisterKeyboardListener(this.onKeyboardAnnotationsTest3); - unregisterKeyboardListener(this.onKeyboardAnnotationsTest4); - } + unregisterKeyboardListener(this.annotationDrawMarginOrPlainAnnotationToggleSwitch); } private handleLinkLocator = (locator: R2Locator, isFromOnPopState = false) => { @@ -1016,14 +1171,14 @@ class Reader extends React.Component { if (!isFromOnPopState) { // console.log("#+$%".repeat(5) + " goToLocator history pushState()", JSON.stringify(locator), JSON.stringify(document.location), JSON.stringify(window.location), JSON.stringify(window.history.state), window.history.length, windowHistory._length); if (window.history.state && r.equals(locator, window.history.state.data)) { - window.history.replaceState({data: locator, index: windowHistory._length - 1}, ""); + window.history.replaceState({ data: locator, index: windowHistory._length - 1 }, ""); } else { windowHistory._length++; - window.history.pushState({data: locator, index: windowHistory._length - 1}, ""); + window.history.pushState({ data: locator, index: windowHistory._length - 1 }, ""); } // windowHistory._readerInstance === this - this.setState({historyCanGoForward: false, historyCanGoBack: windowHistory._length > 1}); + this.setState({ historyCanGoForward: false, historyCanGoBack: windowHistory._length > 1 }); } r2HandleLinkLocator(locator); }; @@ -1033,84 +1188,19 @@ class Reader extends React.Component { r2HandleLinkUrl(url); }; - // TODO HIGHLIGHTS-ANNOTATIONS: just for testing! - private onKeyboardAnnotationsTest = (type: number) => { - - if (!ENABLE_HIGHLIGHTS_TEST_FEATURE) { - return; - } - if (this.props.isDivina || this.props.isPdf) { - return; - } - - // navigator loc has updated selectionInfo (may have been invalidated / cleared since last notified here ... so takes precedence over local state) - const loc = getCurrentReadingLocation() || this.state.currentLocation; - - if (!loc?.locator?.href || !loc?.selectionInfo) { // loc?.selectionIsNew + private annotationDrawMarginOrPlainAnnotationToggleSwitch = () => { + if (!this.state.shortcutEnable) { + if (DEBUG_KEYBOARD) { + console.log("!shortcutEnable (AnnotationDrawMarginOrPlainAnnotationToggleSwitch)"); + } return; } - // TODO: define a preset of colours that work well in both light (aka. neutral) and dark (aka.night) modes. - // CSS mix-blend-mode is multiply for light, hard-light for dark. - const colors = [{ - red: 210, - green: 137, - blue: 156, - }, - { - red: 6, - green: 202, - blue: 56, - }, - { - red: 57, - green: 153, - blue: 208, - }, - { - red: 213, - green: 180, - blue: 120, - }, - { - red: 61, - green: 181, - blue: 172, - }]; - const color = false ? colors[Math.floor(Math.random() * colors.length)] : { - red: Math.floor(Math.random() * 256), - green: Math.floor(Math.random() * 256), - blue: Math.floor(Math.random() * 256), - }; - console.log("DEV HIGHLIGHT CREATE: " + type, JSON.stringify(color, null, 4)); - - highlightsCreate(loc.locator.href, [ - { - selectionInfo: loc.selectionInfo, - // range: Range, - - color, - - // 0 is full background (default), 1 is underline, 2 is strikethrough, 3 is outline - drawType: type, + const newReaderConfig = {...this.props.readerConfig}; + newReaderConfig.annotation_defaultDrawView = newReaderConfig.annotation_defaultDrawView === "annotation" ? "margin" : "annotation"; - expand: 3, - - group: "annotations", - }, - ]); - }; - private onKeyboardAnnotationsTest1 = () => { - this.onKeyboardAnnotationsTest(0); - }; - private onKeyboardAnnotationsTest2 = () => { - this.onKeyboardAnnotationsTest(1); - }; - private onKeyboardAnnotationsTest3 = () => { - this.onKeyboardAnnotationsTest(2); - }; - private onKeyboardAnnotationsTest4 = () => { - this.onKeyboardAnnotationsTest(3); + console.log(`AnnotationDrawMarginOrPlainAnnotationToggleSwitch : highlight=${newReaderConfig.annotation_defaultDrawView}`); + this.props.setConfig(newReaderConfig, this.props.session); }; private onKeyboardAudioStop = () => { @@ -1244,7 +1334,7 @@ class Reader extends React.Component { } return; } - this.displayPublicationInfo(true); + this.handlePublicationInfo(undefined, true); }; private onKeyboardInfoWhereAmISpeak = () => { @@ -1266,154 +1356,154 @@ class Reader extends React.Component { } try { - const isAudio = locatorExt.audioPlaybackInfo - && locatorExt.audioPlaybackInfo.globalDuration - && typeof locatorExt.locator.locations.position === "number"; + const isAudio = locatorExt.audioPlaybackInfo + && locatorExt.audioPlaybackInfo.globalDuration + && typeof locatorExt.locator.locations.position === "number"; - const isDivina = this.props.r2Publication && isDivinaFn(this.props.r2Publication); - const isPdf = this.props.r2Publication && isPdfFn(this.props.r2Publication); + const isDivina = this.props.r2Publication && isDivinaFn(this.props.r2Publication); + const isPdf = this.props.r2Publication && isPdfFn(this.props.r2Publication); const isFixedLayoutPublication = this.props.r2Publication && this.props.r2Publication.Metadata?.Rendition?.Layout === "fixed"; - let txtProgression: string | undefined; - let txtPagination: string | undefined; - let txtHeadings: string | undefined; - - if (isAudio) { - const percent = Math.round(locatorExt.locator.locations.position * 100); - txtProgression = `${percent}% [${formatTime(Math.round(locatorExt.audioPlaybackInfo.globalTime))} / ${formatTime(Math.round(locatorExt.audioPlaybackInfo.globalDuration))}]`; - } else if (isDivina) { - let totalPages = (this.state.divinaNumberOfPages && !this.state.divinaContinousEqualTrue) ? this.state.divinaNumberOfPages : (this.props.r2Publication?.Spine?.length ? this.props.r2Publication.Spine.length : undefined); - if (typeof totalPages === "string") { - try { - totalPages = parseInt(totalPages, 10); - } catch (_e) { - totalPages = 0; + let txtProgression: string | undefined; + let txtPagination: string | undefined; + let txtHeadings: string | undefined; + + if (isAudio) { + const percent = Math.round(locatorExt.locator.locations.position * 100); + txtProgression = `${percent}% [${formatTime(Math.round(locatorExt.audioPlaybackInfo.globalTime))} / ${formatTime(Math.round(locatorExt.audioPlaybackInfo.globalDuration))}]`; + } else if (isDivina) { + let totalPages = (this.state.divinaNumberOfPages && !this.state.divinaContinousEqualTrue) ? this.state.divinaNumberOfPages : (this.props.r2Publication?.Spine?.length ? this.props.r2Publication.Spine.length : undefined); + if (typeof totalPages === "string") { + try { + totalPages = parseInt(totalPages, 10); + } catch (_e) { + totalPages = 0; + } } - } - let pageNum = !this.state.divinaContinousEqualTrue ? - (locatorExt.locator.locations.position || 0) : - (Math.floor(locatorExt.locator.locations.progression * this.props.r2Publication.Spine.length) - 1); - if (typeof pageNum === "string") { - try { - pageNum = parseInt(pageNum, 10) + 1; - } catch (_e) { - pageNum = 0; + let pageNum = !this.state.divinaContinousEqualTrue ? + (locatorExt.locator.locations.position || 0) : + (Math.floor(locatorExt.locator.locations.progression * this.props.r2Publication.Spine.length) - 1); + if (typeof pageNum === "string") { + try { + pageNum = parseInt(pageNum, 10) + 1; + } catch (_e) { + pageNum = 0; + } + } else if (typeof pageNum === "number") { + pageNum = pageNum + 1; } - } else if (typeof pageNum === "number") { - pageNum = pageNum + 1; - } - if (totalPages && typeof pageNum === "number") { - txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); + if (totalPages && typeof pageNum === "number") { + txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); - txtProgression = `${Math.round(100 * (locatorExt.locator.locations.progression || 0))}%`; + txtProgression = `${Math.round(100 * (locatorExt.locator.locations.progression || 0))}%`; - } else { - if (typeof pageNum === "number") { - txtPagination = this.props.__("reader.navigation.currentPage", { current: `${pageNum}` }); - } + } else { + if (typeof pageNum === "number") { + txtPagination = this.props.__("reader.navigation.currentPage", { current: `${pageNum}` }); + } - if (typeof locatorExt.locator.locations.progression === "number") { - const percent = Math.round(locatorExt.locator.locations.progression * 100); - txtProgression = `${percent}%`; + if (typeof locatorExt.locator.locations.progression === "number") { + const percent = Math.round(locatorExt.locator.locations.progression * 100); + txtProgression = `${percent}%`; + } } - } - } else if (isPdf) { - let totalPages = this.state.pdfPlayerNumberOfPages ? - this.state.pdfPlayerNumberOfPages : - (this.props.r2Publication?.Metadata?.NumberOfPages ? this.props.r2Publication.Metadata.NumberOfPages : undefined); + } else if (isPdf) { + let totalPages = this.state.pdfPlayerNumberOfPages ? + this.state.pdfPlayerNumberOfPages : + (this.props.r2Publication?.Metadata?.NumberOfPages ? this.props.r2Publication.Metadata.NumberOfPages : undefined); - if (typeof totalPages === "string") { - try { - totalPages = parseInt(totalPages, 10); - } catch (_e) { - totalPages = 0; + if (typeof totalPages === "string") { + try { + totalPages = parseInt(totalPages, 10); + } catch (_e) { + totalPages = 0; + } } - } - let pageNum = (locatorExt.locator?.href as unknown) as number; - if (typeof pageNum === "string") { - try { - pageNum = parseInt(pageNum, 10); - } catch (_e) { - pageNum = 0; + let pageNum = (locatorExt.locator?.href as unknown) as number; + if (typeof pageNum === "string") { + try { + pageNum = parseInt(pageNum, 10); + } catch (_e) { + pageNum = 0; + } } - } - if (totalPages) { - txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); - txtProgression = `${Math.round(100 * (pageNum / totalPages))}%`; - } else { - txtPagination = this.props.__("reader.navigation.currentPage", { current: `${pageNum}` }); - } + if (totalPages) { + txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); + txtProgression = `${Math.round(100 * (pageNum / totalPages))}%`; + } else { + txtPagination = this.props.__("reader.navigation.currentPage", { current: `${pageNum}` }); + } - } else if (this.props.r2Publication?.Spine && locatorExt.locator?.href) { + } else if (this.props.r2Publication?.Spine && locatorExt.locator?.href) { - const spineIndex = this.props.r2Publication.Spine.findIndex((l) => { - return l.Href === locatorExt.locator.href; - }); - if (spineIndex >= 0) { - if (isFixedLayoutPublication) { - const pageNum = spineIndex + 1; - const totalPages = this.props.r2Publication.Spine.length; + const spineIndex = this.props.r2Publication.Spine.findIndex((l) => { + return l.Href === locatorExt.locator.href; + }); + if (spineIndex >= 0) { + if (isFixedLayoutPublication) { + const pageNum = spineIndex + 1; + const totalPages = this.props.r2Publication.Spine.length; - txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); - txtProgression = `${Math.round(100 * (pageNum / totalPages))}%`; + txtPagination = this.props.__("reader.navigation.currentPageTotal", { current: `${pageNum}`, total: `${totalPages}` }); + txtProgression = `${Math.round(100 * (pageNum / totalPages))}%`; - } else { + } else { - if (locatorExt.epubPage) { - let epubPage = locatorExt.epubPage; - if (epubPage.trim().length === 0 && locatorExt.epubPageID && this.props.r2Publication.PageList) { - const p = this.props.r2Publication.PageList.find((page) => { - return page.Title && page.Href && page.Href.endsWith(`#${locatorExt.epubPageID}`); - }); - if (p) { - epubPage = p.Title; + if (locatorExt.epubPage) { + let epubPage = locatorExt.epubPage; + if (epubPage.trim().length === 0 && locatorExt.epubPageID && this.props.r2Publication.PageList) { + const p = this.props.r2Publication.PageList.find((page) => { + return page.Title && page.Href && page.Href.endsWith(`#${locatorExt.epubPageID}`); + }); + if (p) { + epubPage = p.Title; + } } + txtPagination = this.props.__("reader.navigation.currentPage", { current: epubPage }); } - txtPagination = this.props.__("reader.navigation.currentPage", { current: epubPage }); - } - const percent = Math.round(locatorExt.locator.locations.progression * 100); - txtProgression = `${spineIndex + 1}/${this.props.r2Publication.Spine.length}${locatorExt.locator.title ? ` (${locatorExt.locator.title})` : ""} [${percent}%]`; + const percent = Math.round(locatorExt.locator.locations.progression * 100); + txtProgression = `${spineIndex + 1}/${this.props.r2Publication.Spine.length}${locatorExt.locator.title ? ` (${locatorExt.locator.title})` : ""} [${percent}%]`; - if (locatorExt.headings) { + if (locatorExt.headings) { - let rank = 999; - const hs = locatorExt.headings.filter((h, _i) => { - if (h.level < rank) { + let rank = 999; + const hs = locatorExt.headings.filter((h, _i) => { + if (h.level < rank) { - rank = h.level; - return true; - } - return false; - }).reverse(); - const summary = hs.reduce((arr, h, i) => { - return arr.concat( - i === 0 ? " " : " / ", - `H${h.level} `, - h.txt ? `${h.txt}` : `${h.id ? `[${h.id}]` : "_"}`, + rank = h.level; + return true; + } + return false; + }).reverse(); + const summary = hs.reduce((arr, h, i) => { + return arr.concat( + i === 0 ? " " : " / ", + `H${h.level} `, + h.txt ? `${h.txt}` : `${h.id ? `[${h.id}]` : "_"}`, ); - }, []); + }, []); - // const details = locatorExt.headings.slice().reverse().reduce((arr, h, i) => { - // return arr.concat(i === 0 ? " " : " / ", `H${h.level} ${h.txt ? `${h.txt}` : `${h.id ? `[${h.id}]` : "_"}`}`); - // }, []); + // const details = locatorExt.headings.slice().reverse().reduce((arr, h, i) => { + // return arr.concat(i === 0 ? " " : " / ", `H${h.level} ${h.txt ? `${h.txt}` : `${h.id ? `[${h.id}]` : "_"}`}`); + // }, []); - // txtHeadings = `${summary.join("")} ${details.join("")}`; + // txtHeadings = `${summary.join("")} ${details.join("")}`; - txtHeadings = summary.join(""); + txtHeadings = summary.join(""); + } } } } - } - this.props.toasty(`${txtPagination ? `${txtPagination} -- ` : ""}${txtProgression ? `${this.props.__("publication.progression.title")} = ${txtProgression}` : ""}${txtHeadings ? ` -- ${txtHeadings}` : ""}`); + this.props.toasty(`${txtPagination ? `${txtPagination} -- ` : ""}${txtProgression ? `${this.props.__("publication.progression.title")} = ${txtProgression}` : ""}${txtHeadings ? ` -- ${txtHeadings}` : ""}`); } catch (_err) { this.props.toasty("ERROR"); @@ -1427,7 +1517,7 @@ class Reader extends React.Component { } return; } - this.displayPublicationInfo(); + this.handlePublicationInfo(); }; private onKeyboardFocusNav = () => { @@ -1620,21 +1710,24 @@ class Reader extends React.Component { console.log(">> HISTORY POP STATE SKIP URL (2)", popState.state.data); } } - this.setState({historyCanGoForward: windowHistory._length > 1 && popState.state.index < windowHistory._length - 1, historyCanGoBack: windowHistory._length > 1 && popState.state.index > 0}); + this.setState({ historyCanGoForward: windowHistory._length > 1 && popState.state.index < windowHistory._length - 1, historyCanGoBack: windowHistory._length > 1 && popState.state.index > 0 }); } else { - this.setState({historyCanGoForward: false, historyCanGoBack: false}); + this.setState({ historyCanGoForward: false, historyCanGoBack: false }); } }; - private displayPublicationInfo(focusWhereAmI?: boolean) { - if (this.props.publicationView) { - // TODO: subscribe to Redux action type == CloseRequest - // in order to reset shortcutEnable to true? Problem: must be specific to this reader window. - // So instead we subscribe to DOM event "Thorium:DialogClose", but this is a short-term hack! + private handlePublicationInfo(open?: boolean, focusWhereAmI?: boolean) { + + if (open === false) { + this.setState({ + shortcutEnable: true, + }); + this.props.closePublicationInfo(); + } + else if (this.props.publicationView) { this.setState({ shortcutEnable: false, }); - const readerReadingLocation = this.state.currentLocation ? this.state.currentLocation : undefined; this.props.displayPublicationInfo(this.props.publicationView.identifier, this.state.pdfPlayerNumberOfPages, this.state.divinaNumberOfPages, this.state.divinaContinousEqualTrue, readerReadingLocation, this.handleLinkUrl.bind(this), focusWhereAmI); } @@ -1920,8 +2013,8 @@ class Reader extends React.Component { eventEmitter.on("readingmodechange", (data: any) => { // console.log("READING MODE BEFORE DROP FIRST TEST"); // if (!readingmodeDropFirst) { - // readingmodeDropFirst = true; - // return; + // readingmodeDropFirst = true; + // return; // } console.log("DIVINA: 'readingmodechange'", data); @@ -1988,7 +2081,7 @@ class Reader extends React.Component { } console.log("DIVINA: 'pagechange'", data); - this.setState({divinaArrowEnabled: false}); + this.setState({ divinaArrowEnabled: false }); const isInPageChangeData = (data: any): data is { percent: number, locator: R2Locator } => { return typeof data === "object" && @@ -2067,7 +2160,7 @@ class Reader extends React.Component { windowHistory._length = 1; // console.log("#+$%".repeat(5) + " installNavigatorDOM => window history replaceState() ...", JSON.stringify(locator), JSON.stringify(window.history.state), window.history.length, windowHistory._length, JSON.stringify(document.location), JSON.stringify(window.location)); // does not trigger onPopState! - window.history.replaceState(locator ? {data: locator, index: windowHistory._length - 1} : null, ""); + window.history.replaceState(locator ? { data: locator, index: windowHistory._length - 1 } : null, ""); } } @@ -2080,7 +2173,7 @@ class Reader extends React.Component { } // WARNING: "goto page" zero-based index in SectionData[] of ReaderMenu.tsx - this.handleMenuButtonClick(4); + this.handleMenuButtonClick(true, "tab-gotopage", true); } private onKeyboardShowTOC() { @@ -2092,20 +2185,27 @@ class Reader extends React.Component { } // WARNING: "table of contents" zero-based index in SectionData[] of ReaderMenu.tsx - this.handleMenuButtonClick(0); + this.handleMenuButtonClick(true, "tab-toc", true); } private showSearchResults() { // WARNING: "search" zero-based index in SectionData[] of ReaderMenu.tsx - this.handleMenuButtonClick(3); + this.handleMenuButtonClick(true, "tab-search", true); } - private handleMenuButtonClick(openedSectionMenu?: number | undefined) { + private handleMenuButtonClick(open?: boolean, openedSectionMenu?: string, focused?: boolean, annotationUUID?: string) { + console.log("handleMenuButtonClick", "menuOpen=", this.state.menuOpen ? "closeMenu" : "openMenu", open !== undefined ? `openFromParam=${open ? "openMenu" : "closeMenu"}` : ""); + + const openToggle = !this.state.menuOpen; + const menuOpen = open !== undefined ? open : openToggle; + this.setState({ - menuOpen: !this.state.menuOpen, - shortcutEnable: this.state.menuOpen, + menuOpen: menuOpen, + shortcutEnable: true,//!menuOpen, settingsOpen: false, - openedSectionMenu, + openedSectionMenu: openedSectionMenu ? openedSectionMenu : this.state.openedSectionMenu, + focusMenuOpen: focused ? (this.state.focusMenuOpen + 1) : this.state.focusMenuOpen, + annotationUUID: annotationUUID ? annotationUUID : "", }); } @@ -2140,7 +2240,7 @@ class Reader extends React.Component { // console.log("#+$%".repeat(5) + " handleReadingLocationChange (INIT history state) => window history replaceState() ...", JSON.stringify(loc.locator), JSON.stringify(window.history.state), window.history.length, windowHistory._length, JSON.stringify(document.location), JSON.stringify(window.location)); windowHistory._length = 1; // does not trigger onPopState! - window.history.replaceState({data: loc.locator, index: windowHistory._length - 1}, ""); + window.history.replaceState({ data: loc.locator, index: windowHistory._length - 1 }, ""); } // No need to explicitly refresh the bookmarks status here, @@ -2152,7 +2252,7 @@ class Reader extends React.Component { // check if a bookmark is on the screen private async updateVisibleBookmarks(): Promise { if (!this.props.bookmarks) { - this.setState({ visibleBookmarkList: []}); + this.setState({ visibleBookmarkList: [] }); return undefined; } @@ -2170,7 +2270,7 @@ class Reader extends React.Component { } } else if (this.props.r2Publication) { // isLocatorVisible() API only once navigator ready let isVisible = false; - try{ + try { isVisible = await isLocatorVisible(bookmark.locator); } catch (_e) { // rejection because webview not fully loaded yet @@ -2355,7 +2455,7 @@ class Reader extends React.Component { const l = visibleBookmarkList.length; // reader.navigation.bookmarkTitle - const msg = `${this.props.__("catalog.delete")} - ${this.props.__("reader.marks.bookmarks")} [${this.props.bookmarks?.length ? this.props.bookmarks.length - l : 0}]`; + const msg = `${this.props.__("catalog.delete")} - ${this.props.__("reader.marks.bookmarks")} [${this.props.bookmarks?.length ? this.props.bookmarks.length + 1 - l : 0}]`; // this.setState({bookmarkMessage: msg}); this.props.toasty(msg); @@ -2380,9 +2480,9 @@ class Reader extends React.Component { return identical; }) && (this.state.currentLocation.audioPlaybackInfo || - !visibleBookmarkList?.length || - fromKeyboard || // SCREEN READER CTRL+B on discrete text position (container element) - locator.text?.highlight + !visibleBookmarkList?.length || + fromKeyboard || // SCREEN READER CTRL+B on discrete text position (container element) + locator.text?.highlight ); if (addCurrentLocationToBookmarks) { @@ -2445,12 +2545,17 @@ class Reader extends React.Component { } } - private handleSettingsClick(openedSectionSettings?: number | undefined) { + private handleSettingsClick(open?: boolean) { + console.log("HandleSettingsClick", "settingsOpen=", this.state.settingsOpen ? "closeSettings" : "openSettings", open !== undefined ? `openFromParam=${open ? "openSettings" : "closeSettings"}`: ""); + + const openToggle = !this.state.settingsOpen; + const settingsOpen = open !== undefined ? open : openToggle; + this.setState({ - settingsOpen: !this.state.settingsOpen, - shortcutEnable: this.state.settingsOpen, + settingsOpen, + shortcutEnable: true,//!settingsOpen, menuOpen: false, - openedSectionSettings, + // openedSectionSettings, }); } @@ -2554,34 +2659,34 @@ class Reader extends React.Component { } } - private handleSettingChange( - event: TChangeEventOnInput | TChangeEventOnSelect | undefined, - name: keyof ReaderConfig, - givenValue?: string | boolean) { + // private handleSettingChange( + // event: TChangeEventOnInput | TChangeEventOnSelect | undefined, + // name: keyof ReaderConfig, + // givenValue?: string | boolean) { - let value = givenValue; - if (value === null || value === undefined) { - if (event?.target?.value) { - value = event.target.value.toString(); - } else { - return; - } - } + // let value = givenValue; + // if (value === null || value === undefined) { + // if (event?.target?.value) { + // value = event.target.value.toString(); + // } else { + // return; + // } + // } - const readerConfig = r.clone(this.props.readerConfig); + // const readerConfig = r.clone(this.props.readerConfig); - const typedName = - name as (typeof value extends string ? keyof ReaderConfigStrings : keyof ReaderConfigBooleans); - const typedValue = - value as (typeof value extends string ? string : boolean); - readerConfig[typedName] = typedValue; + // const typedName = + // name as (typeof value extends string ? keyof ReaderConfigStrings : keyof ReaderConfigBooleans); + // const typedValue = + // value as (typeof value extends string ? string : boolean); + // readerConfig[typedName] = typedValue; - if (readerConfig.paged) { - readerConfig.enableMathJax = false; - } + // if (readerConfig.paged) { + // readerConfig.enableMathJax = false; + // } - this.handleSettingsSave(readerConfig); - } + // this.handleSettingsSave(readerConfig); + // } private handleIndexChange(event: TChangeEventOnInput, name: keyof ReaderConfigStringsAdjustables) { @@ -2690,7 +2795,7 @@ const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { dispatch(toastActions.openRequest.build(ToastType.Success, msg)); }, toggleFullscreen: (fullscreenOn: boolean) => { - dispatch(readerActions.fullScreenRequest.build(fullscreenOn)); + dispatch(readerActions.fullScreenRequest.build(fullscreenOn)); }, closeReader: () => { dispatch(readerActions.closeRequest.build()); @@ -2712,6 +2817,9 @@ const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { }, )); }, + closePublicationInfo: () => { + dispatch(dialogActions.closeRequest.build()); + }, setLocator: (locator: LocatorExtended) => { dispatch(readerLocalActionSetLocator.build(locator)); }, @@ -2723,20 +2831,25 @@ const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { } }, addBookmark: (bookmark: IBookmarkStateWithoutUUID) => { - dispatch(readerLocalActionBookmarks.push.build(bookmark)); + dispatch(readerActions.bookmark.push.build(bookmark)); }, deleteBookmark: (bookmark: IBookmarkState) => { - dispatch(readerLocalActionBookmarks.pop.build(bookmark)); + dispatch(readerActions.bookmark.pop.build(bookmark)); }, setDisableRTLFlip: (disable: boolean) => { dispatch(readerActions.disableRTLFlip.build(disable)); }, setReadingMode: (readingMode: TdivinaReadingMode) => { - dispatch(readerLocalActionDivina.setReadingMode.build({readingMode})); + + console.log("Persist the reading mode", readingMode); + dispatch(readerLocalActionDivina.setReadingMode.build({ readingMode })); }, clipboardCopy: (publicationIdentifier: string, clipboardData: IEventPayload_R2_EVENT_CLIPBOARD_COPY) => { dispatch(readerActions.clipboardCopy.build(publicationIdentifier, clipboardData)); }, + dispatchReaderTSXMountedAndPublicationIntoViewportLoaded: () => { + dispatch(winActions.initSuccess.build()); + }, }; }; diff --git a/src/renderer/reader/components/ReaderFooter.tsx b/src/renderer/reader/components/ReaderFooter.tsx index 949b7ab36..ddd078c2c 100644 --- a/src/renderer/reader/components/ReaderFooter.tsx +++ b/src/renderer/reader/components/ReaderFooter.tsx @@ -9,16 +9,14 @@ // import * as ForwardIcon from "readium-desktop/renderer/assets/icons/baseline-skip_next-24px.svg"; // import * as BackIcon from "readium-desktop/renderer/assets/icons/double_arrow_left_black_24dp.svg"; // import * as ForwardIcon from "readium-desktop/renderer/assets/icons/double_arrow_right_black_24dp.svg"; -import * as BackIcon from "readium-desktop/renderer/assets/icons/arrow-left.svg"; -import * as ForwardIcon from "readium-desktop/renderer/assets/icons/arrow-right.svg"; +import * as BackIcon from "readium-desktop/renderer/assets/icons/backward-icon.svg"; +import * as ForwardIcon from "readium-desktop/renderer/assets/icons/forward-icon.svg"; import classNames from "classnames"; import * as React from "react"; import { isAudiobookFn } from "readium-desktop/common/isManifestType"; import { formatTime } from "readium-desktop/common/utils/time"; -import * as ArrowRightIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_forward_ios-24px.svg"; -import * as ArrowLeftIcon from "readium-desktop/renderer/assets/icons/baseline-arrow_left_ios-24px.svg"; -import * as stylesReader from "readium-desktop/renderer/assets/styles/reader-app.css"; +import * as stylesReaderFooter from "readium-desktop/renderer/assets/styles/components/readerFooter.scss"; import { TranslatorProps, withTranslator, } from "readium-desktop/renderer/common/components/hoc/translator"; @@ -31,6 +29,11 @@ import { LocatorExtended } from "@r2-navigator-js/electron/renderer/index"; import { Locator as R2Locator } from "@r2-navigator-js/electron/common/locator"; import { Publication as R2Publication } from "@r2-shared-js/models/publication"; import { Link } from "@r2-shared-js/models/publication-link"; +import * as Tooltip from "@radix-ui/react-tooltip"; +// import * as ValidatedIcon from "readium-desktop/renderer/assets/icons/validated-icon.svg"; +import { TDispatch } from "readium-desktop/typings/redux"; +// import { readerActions } from "readium-desktop/common/redux/actions"; +import { connect } from "react-redux"; function throttle(callback: (...args: any) => void, limit: number) { let waiting = false; @@ -47,7 +50,7 @@ function throttle(callback: (...args: any) => void, limit: number) { } // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { +interface IBaseProps extends TranslatorProps, ReturnType { navLeftOrRight: (left: boolean) => void; gotoBegin: () => void; gotoEnd: () => void; @@ -111,6 +114,19 @@ export class ReaderFooter extends React.Component { let spineTitle = currentLocation.locator?.title || currentLocation.locator.href; + // const isEnding = (isDivina + // ? parseInt(spineTitle) + // : isPdf ? + // parseInt(currentLocation.locator?.href, 10).toString() + // : + // ((r2Publication.Spine.findIndex((spineLink) => spineLink.Href === currentLocation.locator?.href)) + 1).toString() + // ) == + // (isPdf ? (r2Publication.Metadata?.NumberOfPages ? r2Publication.Metadata.NumberOfPages : 0) : + // (isDivina + // ? (this.props.divinaContinousEqualTrue ? r2Publication.Spine.length : this.props.divinaNumberOfPages) + // : r2Publication.Spine.length) + // ); + if (isDivina) { try { spineTitle = this.props.divinaContinousEqualTrue @@ -126,8 +142,8 @@ export class ReaderFooter extends React.Component { const isRTL = this.props.isRTLFlip(); return ( -
    { if (ev.deltaY < 0 || ev.deltaX < 0) { this.navLeftOrRightThrottled(true); @@ -137,9 +153,9 @@ export class ReaderFooter extends React.Component { }}> { // !this.props.fullscreen && -
    +
    } - {!isAudioBook && -
    + {/* {!isAudioBook && +
    - } + } */} {!this.props.fullscreen && -