diff --git a/package-lock.json b/package-lock.json index a2d9d65..f598dde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,12 +24,14 @@ "@types/uuid": "^9.0.7", "@types/video.js": "^7.3.56", "ahooks": "^3.8.0", + "animate.css": "^4.1.1", "antd": "^5.17.4", "axios": "^1.5.1", "bootstrap": "^5.3.1", "howler": "^2.2.3", "i18next": "^23.11.5", "i18next-browser-languagedetector": "^8.0.0", + "immer": "^10.1.1", "pino": "^8.16.1", "rc-slider": "^10.5.0", "react": "^18.2.0", @@ -5089,6 +5091,11 @@ "ajv": "^6.9.1" } }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + }, "node_modules/ansi-escapes": { "version": "4.3.2", "license": "MIT", @@ -9374,8 +9381,9 @@ } }, "node_modules/immer": { - "version": "9.0.21", - "license": "MIT", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -15548,6 +15556,15 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/react-dev-utils/node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/react-dev-utils/node_modules/loader-utils": { "version": "3.2.1", "license": "MIT", diff --git a/package.json b/package.json index c549938..bfbc4e7 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,14 @@ "@types/uuid": "^9.0.7", "@types/video.js": "^7.3.56", "ahooks": "^3.8.0", + "animate.css": "^4.1.1", "antd": "^5.17.4", "axios": "^1.5.1", "bootstrap": "^5.3.1", "howler": "^2.2.3", "i18next": "^23.11.5", "i18next-browser-languagedetector": "^8.0.0", + "immer": "^10.1.1", "pino": "^8.16.1", "rc-slider": "^10.5.0", "react": "^18.2.0", diff --git a/public/opacity.png b/public/opacity.png new file mode 100644 index 0000000..0fda3b9 Binary files /dev/null and b/public/opacity.png differ diff --git a/src/components/ConfigurationPage/css/Widget.css b/src/components/ConfigurationPage/css/Widget.css index 3cb76f4..96256e3 100644 --- a/src/components/ConfigurationPage/css/Widget.css +++ b/src/components/ConfigurationPage/css/Widget.css @@ -7,20 +7,19 @@ box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.5); } -.widget-settings .ant-tabs-top > .ant-tabs-nav::before { +.ant-tabs-top > .ant-tabs-nav::before { border-bottom: 1px solid #674afd; } -.widget-settings .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab-active { +.ant-tabs-card.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab-active { background-color: #684aff; border: 1px solid #684aff; } -.widget-settings .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab { +.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab { border: 1px solid #684aff; } -.widget-settings .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab-active @@ -73,6 +72,7 @@ vertical-align: middle; font-weight: 600; font-size: 24px; + font-family: Play; margin-left: 10px; } @@ -221,3 +221,7 @@ box-shadow: rgba(0, 0, 0, 0.15) 0 3px 9px 0; transform: translateY(-2px); } + +.ant-modal-content { + min-width: 800px; +} diff --git a/src/components/ConfigurationPage/css/WidgetSettings.css b/src/components/ConfigurationPage/css/WidgetSettings.css index 4ee5110..05f1a89 100644 --- a/src/components/ConfigurationPage/css/WidgetSettings.css +++ b/src/components/ConfigurationPage/css/WidgetSettings.css @@ -3,15 +3,18 @@ :root { --oda-main-border: 1px solid #674afd; --oda-main-text-color: white; - --oda-secondary-text-color: rgba(220, 220, 220, 0.9); --oda-main-font-family: Play; + --oda-control-background-color: #684aff; + --oda-secondary-text-color: rgba(220, 220, 220, 0.9); + --oda-label-font: 1rem var(--oda-main-font-family); + --oda-label-color: #FFFFFFDA; --oda-label-background-color: #151a33; --oda-btn-background-color: #151a33; } .oda-btn-default { color: var(--oda-main-text-color); - background-color: #151a33; + background-color: var(--oda-btn-background-color); border: var(--oda-main-border); font-family: var(--oda-main-font-family); font-size: 14px; @@ -43,8 +46,9 @@ .widget-settings-item { display: flex; - position: relative; justify-content: space-between; + align-items: center; + position: relative; margin-top: 10px; min-height: 45px; flex-wrap: wrap; @@ -56,7 +60,6 @@ } .widget-settings-name { - position: absolute; color: white; display: block; transition: 0.2s; @@ -101,7 +104,7 @@ top: 1px; } -.widget-settings .ant-color-picker-trigger { +.ant-color-picker-trigger { background-color: #684aff; width: 100%; justify-content: flex-start; @@ -117,7 +120,7 @@ border-radius: 2px; } -.widget-settings .ant-tabs .ant-tabs-tab { +.ant-tabs .ant-tabs-tab { color: #7885bd; font-family: "Play"; font-weight: 900; @@ -142,22 +145,11 @@ border-radius: 3px; } -.widget-settings .ant-input-number { - background-color: #684aff; - width: 25%; - position: absolute; - right: 0; - padding-top: 3px; - padding-bottom: 3px; - box-shadow: inset 0 0 5px 1px rgba(0, 0, 0, 0.9); - border-radius: 3px; -} - -.widget-settings .ant-input-number .ant-input-number-handler { +.ant-input-number .ant-input-number-handler { display: none; } -.widget-settings .ant-input-number .ant-input-number-handler-wrap { +.ant-input-number .ant-input-number-handler-wrap { display: none; } @@ -199,7 +191,7 @@ .widget-settings-value { font-family: inherit; - width: 100%; + width: 25%; outline: 0; font-size: 1rem; font-family: "Martian Mono", monospace; @@ -286,17 +278,17 @@ textarea.widget-settings-value { margin-bottom: 10px; } -.payment-alerts-previews-item .ant-tabs { +.ant-tabs { margin-top: 5px; flex: 1 1 auto; margin-bottom: 10px; } -.payment-alerts-previews-item .ant-tabs .ant-tabs-nav { +.ant-tabs .ant-tabs-nav { padding-left: 5px; } -.payment-alerts-previews-item .ant-tabs .ant-tabs-content-holder { +.ant-tabs .ant-tabs-content-holder { padding-left: 10px; padding-right: 10px; } @@ -424,23 +416,33 @@ div.payment-alert-image-preview { width: 100%; } -.widget-settings .ant-collapse { +.ant-collapse { background-color: #151a33; font-family: Play; border: 1px solid #674afd; margin-bottom: 20px; } -.widget-settings .ant-collapse .ant-collapse-content { +.ant-collapse .ant-collapse-content { background-color: #2b3566; } -.widget-settings .ant-collapse > .ant-collapse-item > .ant-collapse-header { +/* .ant-collapse .ant-collapse-item { */ +/* background-color: var(--oda-label-background-color); */ +/* border-radius: 10px; */ +/* } */ + +.ant-collapse > .ant-collapse-item > .ant-collapse-header { font-family: Play; font-weight: 900; color: white; } +.ant-collapse > .ant-collapse-item > .ant-collapse-header:first { + border-bottom-right-radius:0; + border-bottom-left-radius:0; +} + .configuration-container .ant-table { border: var(--oda-main-border); } diff --git a/src/components/ConfigurationPage/settings/ColorPicker.module.css b/src/components/ConfigurationPage/settings/ColorPicker.module.css index a4851b5..6717503 100644 --- a/src/components/ConfigurationPage/settings/ColorPicker.module.css +++ b/src/components/ConfigurationPage/settings/ColorPicker.module.css @@ -1,5 +1,5 @@ .container { width: 25%; - position: absolute; - right: 0; + /* position: absolute; */ + /* right: 0; */ } diff --git a/src/components/ConfigurationPage/settings/ColorPicker.tsx b/src/components/ConfigurationPage/settings/ColorPicker.tsx index f947338..6ebb714 100644 --- a/src/components/ConfigurationPage/settings/ColorPicker.tsx +++ b/src/components/ConfigurationPage/settings/ColorPicker.tsx @@ -1,18 +1,17 @@ -import -{ ColorPicker as AntColorPicker } -from -"antd" -; +import { ColorPicker as AntColorPicker } from "antd"; import classes from "./ColorPicker.module.css"; export default function ColorPicker({ value, onChange }) { return ( <>
- { - onChange(newValue.toRgbString()); - }}/> + { + onChange(newValue.toRgbString()); + }} + />
); diff --git a/src/components/ConfigurationPage/settings/PaymentAlertsSettings.tsx b/src/components/ConfigurationPage/settings/PaymentAlertsSettings.tsx index d53abf8..6e6fe5f 100644 --- a/src/components/ConfigurationPage/settings/PaymentAlertsSettings.tsx +++ b/src/components/ConfigurationPage/settings/PaymentAlertsSettings.tsx @@ -385,10 +385,7 @@ export default function PaymentAlertSettings({ )} {!alert.image && !alert.video && (
- +
)} @@ -436,12 +433,10 @@ export default function PaymentAlertSettings({ /> )} {prop.type === "color" && ( -
- update(prop.name, value, index)} - /> -
+ update(prop.name, value, index)} + /> )} {prop.type === "text" && ( <> @@ -478,7 +473,9 @@ export default function PaymentAlertSettings({ {[ ...tabContent(alert, "trigger", index),
-
{t("widget-alert-amount")}
+
+ {t("widget-alert-amount")} +
; + } + + calcStyle() { + return { + color: this.value.color, + fontSize: this.value.size, + fontFamily: this.value.family, + fontWeight: this.value.weight ? "bold" : "normal", + textDecoration: this.value.underline ? "underline" : "none", + fontStyle: this.value.italic ? "italic" : "normal", + textShadow: `${this.value.shadowOffsetX}px ${this.value.shadowOffsetY}px ${this.value.shadowWidth}px ${this.value.shadowColor}`, + }; + } + + button: React.FC = () => { + const [showModal, setShowModal] = useState(); + const { t } = useTranslation(); + const { updateConfig } = useContext(WidgetsContext); + + function toggleModal() { + const classList = document.getElementById("root")?.classList; + if (classList?.contains("blured")) { + classList.remove("blured"); + } else { + classList?.add("blured"); + } + setShowModal((old) => !old); + } + + return ( + <> + {this.createFontImport()} +
+ + + +
+
+ Это текст для демонстрации +
+
+
+ + {new FontProperty( + this.widgetId, + "font-family", + "font", + this.value.family, + "button-font", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.family = value; + }), + ); + })} + {new NumberProperty( + this.widgetId, + "font-size", + "number", + this.value.size, + "button-font-size", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.size = value; + }), + ); + })} + {new ColorProperty( + this.widgetId, + "color", + "color", + this.value.color, + "button-text-color", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.color = value; + }), + ); + })} + {new BooleanProperty( + this.widgetId, + "bold", + "boolean", + this.value.weight, + "widget-font-bold", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.weight = value; + }), + ); + })} + {new BooleanProperty( + this.widgetId, + "italic", + "boolean", + this.value.italic, + "widget-font-italic", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.italic = value; + }), + ); + })} + {new BooleanProperty( + this.widgetId, + "bold", + "boolean", + this.value.underline, + "widget-font-underline", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.underline = value; + }), + ); + })} + + ), + }, + { + label: t("widget-font-shadowtablabel"), + key: "shadow", + children: ( + <> + {new NumberProperty( + this.widgetId, + "shadow-offset-x", + "number", + this.value.shadowOffsetX, + "button-shadow-offset-x", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.shadowOffsetX = value; + }), + ); + })} + {new NumberProperty( + this.widgetId, + "shadow-offset-y", + "number", + this.value.shadowOffsetY, + "button-shadow-offset-y", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.shadowOffsetY = value; + }), + ); + })} + {new NumberProperty( + this.widgetId, + "shadow-size", + "number", + this.value.shadowWidth, + "button-shadow-size", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.shadowWidth = value; + }), + ); + })} + {new ColorProperty( + this.widgetId, + "shadow-color", + "color", + this.value.shadowColor, + "button-shadow-color", + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.shadowColor = value; + }), + ); + })} + + ), + }, + { + label: t("widget-font-animationtablabel"), + key: "animation", + children: ( + <> + {new SingleChoiceProperty( + this.widgetId, + "font-animation", + "choice", + this.value.animation, + "widget-font-animation", + animations, + ).markup((p1, p2, value) => { + updateConfig( + this.widgetId, + this.name, + produce(this.value, (draft) => { + draft.animation = value; + }), + ); + })} + + ), + }, + ]} + /> + +
+ + ); + }; + + markup(): ReactNode { + return <>{this.button({})}; + } +} diff --git a/src/components/ConfigurationPage/widgetproperties/ColorProperty.module.css b/src/components/ConfigurationPage/widgetproperties/ColorProperty.module.css new file mode 100644 index 0000000..3d7f1c7 --- /dev/null +++ b/src/components/ConfigurationPage/widgetproperties/ColorProperty.module.css @@ -0,0 +1,4 @@ +.label { + font: var(--oda-label-font); + color: var(--oda-label-color); +} diff --git a/src/components/ConfigurationPage/widgetproperties/ColorProperty.tsx b/src/components/ConfigurationPage/widgetproperties/ColorProperty.tsx index 17c8e30..d013646 100644 --- a/src/components/ConfigurationPage/widgetproperties/ColorProperty.tsx +++ b/src/components/ConfigurationPage/widgetproperties/ColorProperty.tsx @@ -1,6 +1,7 @@ import { ReactNode } from "react"; import ColorPicker from "../settings/ColorPicker"; import { Trans } from "react-i18next"; +import classes from "./ColorProperty.module.css"; export class ColorProperty { widgetId: string | null; @@ -29,10 +30,7 @@ export class ColorProperty { markup(updateConfig: Function): ReactNode { return (
-