@topvisor/ui 0.0.34 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/TopTheme.js +82 -0
- package/.storybook/TopThemeManager.js +44 -0
- package/.storybook/main.ts +43 -0
- package/.storybook/manager.ts +28 -0
- package/.storybook/preview-head.html +16 -0
- package/.storybook/preview.ts +48 -0
- package/.storybook/vue/coreDecorator.ts +19 -0
- package/.storybook/vue/vModelDecorator.ts +27 -0
- package/.vscode/extensions.json +11 -0
- package/.vscode/keybindings.example.json +121 -0
- package/.vscode/settings.json +46 -0
- package/Dockerfile +3 -0
- package/NPM.md +25 -0
- package/PUBLISH.md +18 -0
- package/README.md +19 -52
- package/STORYBOOK.md +27 -0
- package/USE_IN_PROJECT.md +29 -0
- package/build/afterBuild.sh +12 -0
- package/build/cssModules.ts +39 -0
- package/build/plugin/amdFix.ts +46 -0
- package/build/rollup.config.ts +18 -0
- package/nbproject/project.properties +11 -0
- package/nbproject/project.xml +9 -0
- package/package.json +68 -19
- package/public/README.md +63 -0
- package/src/components/common/common.ts +1 -0
- package/src/components/common/icon/icon.ts +4 -0
- package/src/components/common/icon/icon.vue +15 -0
- package/src/components/component.ts +133 -0
- package/src/components/forms/button/button.stories.ts +112 -0
- package/src/components/forms/button/button.ts +51 -0
- package/src/components/forms/button/button.vue +75 -0
- package/src/components/forms/button/stories/README.md +35 -0
- package/src/components/forms/button/stories/overview.vue +33 -0
- package/src/components/forms/button/style/button.css +124 -0
- package/src/components/forms/button/style/style-outline.css +42 -0
- package/src/components/forms/button/style/style-soft.css +31 -0
- package/src/components/forms/button/style/style-transparent.css +35 -0
- package/src/components/forms/checkbox/checkbox.stories.ts +33 -0
- package/src/components/forms/checkbox/checkbox.ts +23 -0
- package/src/components/forms/checkbox/checkbox.vue +135 -0
- package/src/components/forms/checkbox/stories/overview.vue +171 -0
- package/src/components/forms/controlLabel/controlLabel.stories.ts +38 -0
- package/src/components/forms/controlLabel/controlLabel.ts +4 -0
- package/src/components/forms/controlLabel/controlLabel.vue +48 -0
- package/src/components/forms/forms.ts +10 -0
- package/src/components/forms/helpers.ts +10 -0
- package/src/components/forms/hint/hint.stories.ts +46 -0
- package/src/components/forms/hint/hint.ts +8 -0
- package/src/components/forms/hint/hint.vue +32 -0
- package/src/components/forms/input/input.stories.ts +31 -0
- package/src/components/forms/input/input.ts +34 -0
- package/src/components/forms/input/input.vue +170 -0
- package/src/components/forms/input/stories/overview.vue +61 -0
- package/src/components/forms/inputDate/datepicker.css +233 -0
- package/src/components/forms/inputDate/datepicker.ts +101 -0
- package/src/components/forms/inputDate/inputDate.stories.ts +41 -0
- package/src/components/forms/inputDate/inputDate.ts +4 -0
- package/src/components/forms/inputDate/inputDate.vue +127 -0
- package/src/components/forms/inputDate/stories/overview.vue +35 -0
- package/src/components/forms/radio/radio.stories.ts +34 -0
- package/src/components/forms/radio/radio.ts +15 -0
- package/src/components/forms/radio/radio.vue +107 -0
- package/src/components/forms/radio/stories/overview.vue +79 -0
- package/src/components/forms/select/select.stories.ts +34 -0
- package/src/components/forms/select/select.ts +36 -0
- package/src/components/forms/select/select.vue +253 -0
- package/src/components/forms/select/stories/exampleOptions.ts +71 -0
- package/src/components/forms/select/stories/overview.vue +60 -0
- package/src/components/forms/switcher/stories/overview.vue +139 -0
- package/src/components/forms/switcher/switcher.stories.ts +33 -0
- package/src/components/forms/switcher/switcher.ts +22 -0
- package/src/components/forms/switcher/switcher.vue +113 -0
- package/src/components/forms/textarea/stories/overview.vue +62 -0
- package/src/components/forms/textarea/textarea.stories.ts +33 -0
- package/src/components/forms/textarea/textarea.ts +38 -0
- package/src/components/forms/textarea/textarea.vue +119 -0
- package/src/components/formsExt/editArea/editArea.stories.ts +72 -0
- package/src/components/formsExt/editArea/editArea.ts +25 -0
- package/src/components/formsExt/editArea/editArea.vue +172 -0
- package/src/components/formsExt/editArea/stories/README.md +17 -0
- package/src/components/formsExt/editArea/stories/overview.vue +66 -0
- package/src/components/formsExt/editInput/editInput.stories.ts +36 -0
- package/src/components/formsExt/editInput/editInput.ts +20 -0
- package/src/components/formsExt/editInput/editInput.vue +57 -0
- package/src/components/formsExt/editInput/stories/overview.vue +54 -0
- package/src/components/formsExt/formsExt.ts +3 -0
- package/src/components/formsExt/radioGroup/radioGroup.stories.ts +51 -0
- package/src/components/formsExt/radioGroup/radioGroup.ts +28 -0
- package/src/components/formsExt/radioGroup/radioGroup.vue +143 -0
- package/src/components/formsExt/radioGroup/stories/overview.vue +78 -0
- package/src/components/formsExt/radioGroup/styles/top-scrollBar.css +52 -0
- package/src/components/helper.js +10 -0
- package/src/components/helpersStories.ts +151 -0
- package/src/components/popup/lib/popup.globalEvents.js +205 -0
- package/src/components/popup/lib/popup.js +702 -0
- package/src/components/popup/lib/worker.globalEvents.js +78 -0
- package/src/components/popup/lib/worker.js +232 -0
- package/src/components/popup/popup/listItem.vue +42 -0
- package/src/components/popup/popup/opener.vue +74 -0
- package/src/components/popup/popup/popup.stories.ts +68 -0
- package/src/components/popup/popup/popup.ts +93 -0
- package/src/components/popup/popup/popup.vue +95 -0
- package/src/components/popup/popup/stories/README.md +34 -0
- package/src/components/popup/popup/stories/listItems.vue +44 -0
- package/src/components/popup/popup/stories/listSubItems.vue +52 -0
- package/src/components/popup/popup/stories/overview.vue +208 -0
- package/src/components/popup/popup/style/popup.css +243 -0
- package/src/components/popup/popup/style/popup.m.css +71 -0
- package/src/components/popup/popup/style/popup.pc.css +28 -0
- package/src/components/popup/popup.ts +3 -0
- package/src/components/popup/worker.ts +1 -0
- package/src/components/tabs/tabs/content.vue +24 -0
- package/src/components/tabs/tabs/stories/README.md +10 -0
- package/src/components/tabs/tabs/tab.vue +52 -0
- package/src/components/tabs/tabs/tabs.stories.ts +171 -0
- package/src/components/tabs/tabs/tabs.ts +22 -0
- package/src/components/tabs/tabs/tabs.vue +64 -0
- package/src/components/tabs/tabs.ts +3 -0
- package/src/core/base/Colors.stories.ts +15 -0
- package/src/core/base/Layout.stories.ts +15 -0
- package/src/core/base/Properties.stories.ts +15 -0
- package/src/core/base/base.mdx +21 -0
- package/src/core/core/core.ts +144 -0
- package/src/core/core/events.ts +54 -0
- package/src/core/core/options.ts +15 -0
- package/src/core/core/state.ts +44 -0
- package/src/core/directives/tooltip.ts +55 -0
- package/src/core/theme/Colors.stories.ts +15 -0
- package/src/core/theme/Properties.stories.ts +15 -0
- package/src/core/theme/theme.mdx +15 -0
- package/src/core/utils/date.ts +164 -0
- package/src/core/utils/device.ts +48 -0
- package/src/core/utils/dom.ts +185 -0
- package/src/core//320/235/320/260/320/261/320/276/321/200 /320/270/320/272/320/276/320/275/320/276/320/272/gallery.vue" +72 -0
- package/src/core//320/235/320/260/320/261/320/276/321/200 /320/270/320/272/320/276/320/275/320/276/320/272//320/235/320/260/320/261/320/276/321/200 /320/270/320/272/320/276/320/275/320/276/320/272.mdx" +31 -0
- package/src/core//320/235/320/260/320/261/320/276/321/200 /320/270/320/272/320/276/320/275/320/276/320/272//320/235/320/260/320/261/320/276/321/200 /320/270/320/272/320/276/320/275/320/276/320/272.stories.ts" +14 -0
- package/src/docs/CSS/FAQ.mdx +43 -0
- package/src/docs/CSS//320/236/320/261/321/211/320/270/320/265 /320/274/320/276/320/264/320/270/321/204/320/270/320/272/320/260/321/202/320/276/321/200/321/213.mdx" +156 -0
- package/src/docs/CSS//320/237/320/265/321/200/320/265/320/274/320/265/320/275/320/275/321/213/320/265.mdx +47 -0
- package/src/docs/CSS//320/237/321/200/320/265/320/264/320/277/321/200/320/276/321/206/320/265/321/201/321/201/320/276/321/200/321/213.mdx +15 -0
- package/src/docs/CSS//320/240/320/265/320/272/320/276/320/274/320/265/320/275/320/264/320/260/321/206/320/270/320/270 /320/221/320/255/320/234.mdx" +49 -0
- package/src/docs/CSS//320/241/321/202/320/270/320/273/320/270.md +53 -0
- package/src/docs/CSS//320/241/321/202/320/270/320/273/320/270.mdx +4 -0
- package/src/docs/CSS//320/247/321/202/320/276 /321/202/320/260/320/272/320/276/320/265 css /320/274/320/276/320/264/321/203/320/273/321/214.mdx" +53 -0
- package/src/docs/ROADMAP.md +17 -0
- package/src/docs/Roadmap.mdx +4 -0
- package/src/docs//320/222/320/262/320/265/320/264/320/265/320/275/320/270/320/265 /320/262 Storybook.mdx" +323 -0
- package/src/docs//320/232/320/276/320/274/320/277/320/276/320/275/320/265/320/275/321/202/321/213.mdx +20 -0
- package/src/docs//320/237/320/276/320/273/320/265/320/267/320/275/320/260/321/217 /320/270/320/275/321/204/320/276/321/200/320/274/320/260/321/206/320/270/321/217.mdx" +8 -0
- package/src/docs//320/241/321/202/320/260/320/275/320/264/320/260/321/200/321/202/321/213 /320/272/320/276/320/264/320/260/IDE.mdx" +42 -0
- package/src/docs//320/241/321/202/320/260/320/275/320/264/320/260/321/200/321/202/321/213 /320/272/320/276/320/264/320/260//320/233/320/270/320/275/321/202/320/265/321/200.mdx" +72 -0
- package/src/docs//320/241/321/202/320/260/320/275/320/264/320/260/321/200/321/202/321/213 /320/272/320/276/320/264/320/260//320/241/321/202/320/260/320/275/320/264/320/260/321/200/321/202/321/213 /320/272/320/276/320/264/320/260.mdx" +29 -0
- package/src/globals.d.ts +1 -0
- package/{icomoon → src/resources/icomoon}/demo-files/demo.css +161 -161
- package/{icomoon → src/resources/icomoon}/demo-files/demo.js +30 -30
- package/{icomoon → src/resources/icomoon}/demo.html +2945 -2945
- package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.svg +232 -232
- package/{icomoon → src/resources/icomoon}/style.css +647 -647
- package/src/resources/styles/core/colors.css +204 -0
- package/src/resources/styles/core/components.css +70 -0
- package/src/resources/styles/core/core.ts +10 -0
- package/src/resources/styles/core/forms/clear.css +19 -0
- package/src/resources/styles/core/forms/controls.css +20 -0
- package/src/resources/styles/core/forms/focusable.css +26 -0
- package/src/resources/styles/core/forms/forms.css +100 -0
- package/src/resources/styles/core/icon.css +58 -0
- package/src/resources/styles/core/layout.css +40 -0
- package/src/resources/styles/core/modifiers/as.css +9 -0
- package/src/resources/styles/core/modifiers/ellipsis.css +18 -0
- package/src/resources/styles/core/modifiers/modifiers.css +81 -0
- package/src/resources/styles/core/modifiers/only.css +19 -0
- package/src/resources/styles/core/select.css +16 -0
- package/src/resources/styles/jquery-ui.min.css +6 -0
- package/src/resources/styles/storybook.css +11 -0
- package/src/resources/styles/themes/dark/theme.css +139 -0
- package/src/resources/styles/themes/dark.ts +1 -0
- package/src/resources/styles/themes/light/theme.css +139 -0
- package/src/resources/styles/themes/light.ts +1 -0
- package/src/storybook/components/color.vue +45 -0
- package/src/storybook/components/colors.vue +34 -0
- package/src/storybook/components/icomoon.ts +38 -0
- package/src/storybook/components/properties.vue +82 -0
- package/src/storybook/resources/accessibility.png +0 -0
- package/src/storybook/resources/accessibility.svg +5 -0
- package/src/storybook/resources/addon-library.png +0 -0
- package/src/storybook/resources/assets.png +0 -0
- package/src/storybook/resources/context.png +0 -0
- package/src/storybook/resources/discord.svg +15 -0
- package/src/storybook/resources/docs.png +0 -0
- package/src/storybook/resources/figma-plugin.png +0 -0
- package/src/storybook/resources/github.svg +3 -0
- package/src/storybook/resources/share.png +0 -0
- package/src/storybook/resources/styling.png +0 -0
- package/src/storybook/resources/testing.png +0 -0
- package/src/storybook/resources/theming.png +0 -0
- package/src/storybook/resources/tutorials.svg +12 -0
- package/src/storybook/resources/youtube.svg +4 -0
- package/src//320/224/320/276/320/261/321/200/320/276 /320/277/320/276/320/266/320/260/320/273/320/276/320/262/320/260/321/202/321/214.mdx" +3 -0
- package/tsconfig.json +62 -0
- package/vite.config.ts +91 -0
- package/.chunks/datepicker-0b648b9f.es.js +0 -275
- package/.chunks/datepicker-0b648b9f.es.js.map +0 -1
- package/.chunks/datepicker-0e9a0541.amd.js +0 -234
- package/.chunks/datepicker-0e9a0541.amd.js.map +0 -1
- package/.chunks/forms-02202302.amd.js +0 -3
- package/.chunks/forms-02202302.amd.js.map +0 -1
- package/.chunks/forms-eb00d0c1.es.js +0 -946
- package/.chunks/forms-eb00d0c1.es.js.map +0 -1
- package/.chunks/popup-6f73b4b2.es.js +0 -700
- package/.chunks/popup-6f73b4b2.es.js.map +0 -1
- package/.chunks/popup-e1f34511.amd.js +0 -341
- package/.chunks/popup-e1f34511.amd.js.map +0 -1
- package/common/common.amd.js +0 -2
- package/common/common.amd.js.map +0 -1
- package/common/common.js +0 -2
- package/common/common.js.map +0 -1
- package/core/core.amd.js +0 -2
- package/core/core.amd.js.map +0 -1
- package/core/core.js +0 -6
- package/core/core.js.map +0 -1
- package/core.css +0 -1
- package/dark.css +0 -1
- package/forms/forms.amd.js +0 -2
- package/forms/forms.amd.js.map +0 -1
- package/forms/forms.js +0 -15
- package/forms/forms.js.map +0 -1
- package/forms/helpers.amd.js +0 -2
- package/forms/helpers.amd.js.map +0 -1
- package/forms/helpers.js +0 -9
- package/forms/helpers.js.map +0 -1
- package/forms.css +0 -1
- package/formsExt/formsExt.amd.js +0 -3
- package/formsExt/formsExt.amd.js.map +0 -1
- package/formsExt/formsExt.js +0 -152
- package/formsExt/formsExt.js.map +0 -1
- package/formsExt.css +0 -1
- package/light.css +0 -1
- package/popup/popup.amd.js +0 -3
- package/popup/popup.amd.js.map +0 -1
- package/popup/popup.js +0 -144
- package/popup/popup.js.map +0 -1
- package/popup/worker.amd.js +0 -2
- package/popup/worker.amd.js.map +0 -1
- package/popup/worker.js +0 -154
- package/popup/worker.js.map +0 -1
- package/popup.css +0 -1
- package/tabs/tabs.amd.js +0 -3
- package/tabs/tabs.amd.js.map +0 -1
- package/tabs/tabs.js +0 -97
- package/tabs/tabs.js.map +0 -1
- package/tabs.css +0 -1
- package/utils/date.amd.js +0 -2
- package/utils/date.amd.js.map +0 -1
- package/utils/date.js +0 -6
- package/utils/date.js.map +0 -1
- package/utils/device.amd.js +0 -2
- package/utils/device.amd.js.map +0 -1
- package/utils/device.js +0 -6
- package/utils/device.js.map +0 -1
- package/utils/dom.amd.js +0 -2
- package/utils/dom.amd.js.map +0 -1
- package/utils/dom.js +0 -64
- package/utils/dom.js.map +0 -1
- /package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.ttf +0 -0
- /package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.woff +0 -0
- /package/{icomoon → src/resources/icomoon}/selection.json +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Core from '@/core/core/core';
|
|
2
|
+
import Events from '@/core/core/events';
|
|
3
|
+
import Worker from '@/components/popup/lib/worker';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Глобальные события, для реализации Popup
|
|
7
|
+
*/
|
|
8
|
+
class WorkerEvents {
|
|
9
|
+
static init () {
|
|
10
|
+
// автоматическое открытие при наведении мыши, событие глобальное, так как инициализация popup отложена
|
|
11
|
+
document.addEventListener('mouseover', (e) => {
|
|
12
|
+
if (!e.target.dataset?.topPopupOpenByHover) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
e.target.click();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// при скролле страницы убирать закрыть Popup
|
|
20
|
+
document.addEventListener('scroll', () => {
|
|
21
|
+
if (Core.isMobile) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Worker.getAll().forEach(elPopup => Worker.close(elPopup));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
Events.addOnReize(e => {
|
|
29
|
+
// закрыть popup при повороте экрана телефона
|
|
30
|
+
// если была отображена ПК версия, она будет закрыта
|
|
31
|
+
if (Core.state.isMobile && e.topEvent.widthDiff) {
|
|
32
|
+
Worker.getAll().forEach(elPopup => Worker.close(elPopup));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
document.addEventListener('click', this.onclick);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Глобальный обработчик кликов
|
|
41
|
+
* обрабатывает клики на открытие Popup
|
|
42
|
+
* @param {Event} e
|
|
43
|
+
*/
|
|
44
|
+
static async onclick (e) {
|
|
45
|
+
let elOpener;
|
|
46
|
+
|
|
47
|
+
switch (true) {
|
|
48
|
+
case !!e.target.dataset?.topPopup:
|
|
49
|
+
elOpener = e.target;
|
|
50
|
+
|
|
51
|
+
break;
|
|
52
|
+
|
|
53
|
+
case !!e.target.parentElement?.dataset.topPopup:
|
|
54
|
+
elOpener = e.target.parentElement;
|
|
55
|
+
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!elOpener) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (elOpener.dataset.topPopupDisabled) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// меню уже открыто
|
|
68
|
+
if (elOpener.dataset.topPopupOpened) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
|
|
74
|
+
await Worker.openByOpener(elOpener);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default WorkerEvents;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import Core from '@/core/core/core';
|
|
2
|
+
import DOM from '@/core/utils/dom';
|
|
3
|
+
import GlobalEvents from '@/components/popup/lib/worker.globalEvents';
|
|
4
|
+
|
|
5
|
+
let decoratorBeforeOpen;
|
|
6
|
+
let decoratorAfterOpen;
|
|
7
|
+
let decoratorIsIgnoreOuterClick;
|
|
8
|
+
let i18n = {
|
|
9
|
+
Close: 'Close',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
class Worker {
|
|
13
|
+
|
|
14
|
+
// глобальное выключение закрытия меню, используется при различных оверлеях
|
|
15
|
+
static noClose = false;
|
|
16
|
+
|
|
17
|
+
static vueConnectors = new Map();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Вызывается при инициализаци приложения
|
|
21
|
+
* устанавливает глобальные статические декортаоры для компонента Popup
|
|
22
|
+
* @param {{
|
|
23
|
+
* decoratorBeforeOpen: (object) => void
|
|
24
|
+
* decoratorAfterOpen: (object) => void,
|
|
25
|
+
* decoratorIsIgnoreOuterClick: (e) => void,
|
|
26
|
+
* i18n: {Close: string}
|
|
27
|
+
* }} options
|
|
28
|
+
*/
|
|
29
|
+
static onInitApp (options) {
|
|
30
|
+
decoratorBeforeOpen = options?.decoratorBeforeOpen;
|
|
31
|
+
decoratorAfterOpen = options?.decoratorAfterOpen;
|
|
32
|
+
decoratorIsIgnoreOuterClick = options?.decoratorIsIgnoreOuterClick;
|
|
33
|
+
i18n = options?.i18n;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// вернуть объект компонента popup, привязанный к элементу
|
|
37
|
+
static getPopup (elPopup) {
|
|
38
|
+
return DOM.storage(elPopup, 'Popup');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static getAll () {
|
|
42
|
+
return DOM.querySelectorAllArray(document, '.top-popup-wrapper');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static getAllVisible () {
|
|
46
|
+
return DOM.querySelectorAllVisible(document, '.top-popup-wrapper');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Открть Popup от указанного elOpener
|
|
51
|
+
* @param {Element} elOpener - элемент, который должен вызвать открытие Popup
|
|
52
|
+
*/
|
|
53
|
+
static async openByOpener (elOpener) {
|
|
54
|
+
const options = {};
|
|
55
|
+
|
|
56
|
+
options.popup = elOpener.dataset.topPopup;
|
|
57
|
+
|
|
58
|
+
if (elOpener.dataset.topPopupP) {
|
|
59
|
+
options.p = parseInt(elOpener.dataset.topPopupP);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (elOpener.dataset.topPopupNotch) {
|
|
63
|
+
options.notch = elOpener.dataset.topPopupNotch;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (elOpener.dataset.topPopupClass) {
|
|
67
|
+
options.class = elOpener.dataset.topPopupClass;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (elOpener.dataset.topPopupPosBy) {
|
|
71
|
+
options.posBy = elOpener.dataset.topPopupPosBy;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (elOpener.dataset.topPopupFront) {
|
|
75
|
+
options.frontSelector = elOpener.dataset.topPopupFront;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (elOpener.dataset.topPopupInvertX) {
|
|
79
|
+
options.invertX = elOpener.dataset.topPopupInvertX;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (elOpener.dataset.topPopupOpenByHover) {
|
|
83
|
+
options.openByHover = elOpener.dataset.topPopupOpenByHover;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (elOpener.dataset.topPopupUseOriginal) {
|
|
87
|
+
options.useOriginal = elOpener.dataset.topPopupUseOriginal;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return await Worker.open(elOpener, options);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Создать и открыть Popup
|
|
95
|
+
* @param {Element} elOpener - элемент, вызвавший открытие Popup
|
|
96
|
+
* @param {object} options - опции Popup
|
|
97
|
+
*/
|
|
98
|
+
static async open (elOpener, options) {
|
|
99
|
+
elOpener.dataset.topPopupOpened = 'opened';
|
|
100
|
+
|
|
101
|
+
const { default: Popup } = await import('./popup');
|
|
102
|
+
|
|
103
|
+
if (typeof (jQuery) === 'function') {
|
|
104
|
+
const $elOpener = jQuery(elOpener);
|
|
105
|
+
|
|
106
|
+
// deprecated, используется aftershow.top-menu-popup
|
|
107
|
+
if ($elOpener.data('aftershow')) {
|
|
108
|
+
let afterShow = $elOpener.data('aftershow');
|
|
109
|
+
if (typeof (afterShow) == 'string') {
|
|
110
|
+
afterShow = eval(afterShow.replace(/\W/g, ''));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
$elOpener.one('aftershow.top-menu-popup', afterShow);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// deprecated, используется afterclose.top-menu-popup
|
|
117
|
+
if ($elOpener.data('afterclose')) {
|
|
118
|
+
let afterclose = $elOpener.data('afterclose');
|
|
119
|
+
if (typeof (afterclose) == 'string') {
|
|
120
|
+
afterclose = eval(afterclose.replace(/\W/g, ''));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
$elOpener.one('afterclose.top-menu-popup', afterclose);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
options.isFullScreen = Core.state.isMobile;
|
|
128
|
+
options.i18n = i18n;
|
|
129
|
+
|
|
130
|
+
return await new Popup(elOpener, options);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static close (elPopup) {
|
|
134
|
+
const popup = Worker.getPopup(elPopup);
|
|
135
|
+
if (popup) {
|
|
136
|
+
popup.close();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static recalcPosition (elPopup) {
|
|
141
|
+
const popup = Worker.getPopup(elPopup);
|
|
142
|
+
if (popup) {
|
|
143
|
+
popup.recalcPosition();
|
|
144
|
+
|
|
145
|
+
// контроль за состоянием тени скролла
|
|
146
|
+
// вызывать после имзенения высоты скролла popup.elPopupBody
|
|
147
|
+
HelperCommon.genHasScroll($(popup.elPopupBody));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// скролл к активному элементу списка
|
|
152
|
+
static scrollToActive (elPopup) {
|
|
153
|
+
const elItemActive = DOM.querySelectorVisible(elPopup, 'ul.top-popup_content > li > .top-active');
|
|
154
|
+
if (!elItemActive) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const elUl = elPopup.querySelector('ul.top-popup_content');
|
|
159
|
+
const elsLi = DOM.querySelectorAllVisible(elPopup, 'ul.top-popup_content > li');
|
|
160
|
+
|
|
161
|
+
elPopup.classList.add('top-popup-wrapper-no_animate');
|
|
162
|
+
setTimeout(() => elPopup.classList.remove('top-popup-wrapper-no_animate'), 100);
|
|
163
|
+
|
|
164
|
+
let top = 100;
|
|
165
|
+
for (const elLi of elsLi) {
|
|
166
|
+
if (elLi.querySelector(':scope > .top-active')) {
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
top += elLi.offsetHeight;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const heightWrapper = elUl.offsetHeight;
|
|
174
|
+
if (top > heightWrapper) {
|
|
175
|
+
elUl.scrollTop = top - heightWrapper;
|
|
176
|
+
} else {
|
|
177
|
+
elUl.scrollTop = 0;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static decoratorBeforeOpen (popup) {
|
|
182
|
+
if (decoratorBeforeOpen) {
|
|
183
|
+
decoratorBeforeOpen(popup);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
static decoratorAfterOpen (popup) {
|
|
188
|
+
if (decoratorAfterOpen) {
|
|
189
|
+
decoratorAfterOpen(popup);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Определитель того, что клик вне Popup нужно игнорировать
|
|
195
|
+
* @returns {boolean} - игнорировать клик, то есть не закрывать Popup
|
|
196
|
+
*/
|
|
197
|
+
static decoratorIsIgnoreOuterClick (e) {
|
|
198
|
+
if (decoratorIsIgnoreOuterClick) {
|
|
199
|
+
return decoratorIsIgnoreOuterClick(e);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Зарегистрировать Vue компонент
|
|
207
|
+
*
|
|
208
|
+
* Каждый экземляр Popup регистрируется в словаре vueConnectors для последующего доступа из js
|
|
209
|
+
* @param {string} id
|
|
210
|
+
* @param {any} vueConnector
|
|
211
|
+
*/
|
|
212
|
+
static regVueComponent (id, vueConnector) {
|
|
213
|
+
if (Worker.vueConnectors.get(id)) {
|
|
214
|
+
throw 'Vue component Popup use duplicated id: ' + id;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Worker.vueConnectors.set(id, vueConnector);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Снять с регистрации Vue компонент
|
|
222
|
+
* @param {string} id
|
|
223
|
+
*/
|
|
224
|
+
static unregVueComponent (id) {
|
|
225
|
+
Worker.vueConnectors.delete(id);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
GlobalEvents.init(Worker, Core);
|
|
231
|
+
|
|
232
|
+
export default Worker;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ListItemProps } from './popup';
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
inheritAttrs: false,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<ListItemProps>(), {
|
|
9
|
+
type: 'simple',
|
|
10
|
+
closeByClick: true,
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<li :class="{
|
|
16
|
+
'top-popup_listDelimiter': type === 'delimiter',
|
|
17
|
+
'top-popup_listTitle': type === 'title'
|
|
18
|
+
}">
|
|
19
|
+
<!--Выбираемый элемент -->
|
|
20
|
+
<component
|
|
21
|
+
v-if="props.type === 'simple' || props.type === 'link'"
|
|
22
|
+
:is="props.type === 'link' ? 'a' : 'i'"
|
|
23
|
+
:class="{
|
|
24
|
+
'top-popup_item': true,
|
|
25
|
+
'top-popup_item-a': props.type === 'simple', // имитация оформления ссылки
|
|
26
|
+
'a': true, // deprecated
|
|
27
|
+
'top-popup-noCloser': !closeByClick
|
|
28
|
+
}"
|
|
29
|
+
:=$attrs
|
|
30
|
+
>
|
|
31
|
+
<slot></slot>
|
|
32
|
+
</component>
|
|
33
|
+
|
|
34
|
+
<!--Заголовок или элемент формы -->
|
|
35
|
+
<template
|
|
36
|
+
v-if="props.type === 'title' || props.type === 'control'"
|
|
37
|
+
class="top-popup_listTitle"
|
|
38
|
+
>
|
|
39
|
+
<slot></slot>
|
|
40
|
+
</template>
|
|
41
|
+
</li>
|
|
42
|
+
</template>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onUpdated, ref } from 'vue';
|
|
3
|
+
import type { OpenerProps } from './popup';
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<OpenerProps>(), {
|
|
6
|
+
pos: '3',
|
|
7
|
+
notch: true,
|
|
8
|
+
posBy: 'fixed',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const id = props.id || Math.random() + '';
|
|
12
|
+
|
|
13
|
+
let elOpener: Element;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Необычная функция для проброски props внтурь элемента слота
|
|
17
|
+
*
|
|
18
|
+
* @param el - вспомогательрный элемент для доступа к элементам слота
|
|
19
|
+
*/
|
|
20
|
+
function render (el: any) {
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
elOpener = el.nextElementSibling;
|
|
23
|
+
|
|
24
|
+
if (elOpener) {
|
|
25
|
+
renderOpener(elOpener);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onUpdated(() => {
|
|
31
|
+
if (elOpener) {
|
|
32
|
+
renderOpener(elOpener);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function renderOpener (elOpener: any) {
|
|
37
|
+
elOpener.dataset.topPopup = 'vue-' + id;
|
|
38
|
+
elOpener.dataset.topPopupId = id;
|
|
39
|
+
elOpener.dataset.topPopupP = props.pos;
|
|
40
|
+
elOpener.dataset.topPopupPosBy = props.posBy;
|
|
41
|
+
elOpener.dataset.topPopupNotch = props.notch ? 'true' : '';
|
|
42
|
+
elOpener.dataset.topPopupOpenByHover = props.openByHover ? 'true' : '';
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template>
|
|
47
|
+
<template :ref="render"></template>
|
|
48
|
+
|
|
49
|
+
<!-- @slot элемент для открытия Popup -->
|
|
50
|
+
<slot></slot>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style>
|
|
54
|
+
h3[data-top-popup],
|
|
55
|
+
div[data-top-popup],
|
|
56
|
+
i[data-top-popup]:not(.btn):not(.g_btn),
|
|
57
|
+
b[data-top-popup]:not(.btn):not(.g_btn) {
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
user-select: none;
|
|
60
|
+
font-style: normal;
|
|
61
|
+
text-decoration: none;
|
|
62
|
+
display: inline-flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[data-top-popup][data-top-popup-disabled] {
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
cursor: auto !important;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
i[contenteditable] {
|
|
72
|
+
cursor: text !important;
|
|
73
|
+
}
|
|
74
|
+
</style>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
|
|
3
|
+
import { genArgsTypes, genOverviewStory } from '@/components/helpersStories';
|
|
4
|
+
import OverviewComponent from './stories/overview.vue';
|
|
5
|
+
|
|
6
|
+
import Component from './popup.vue';
|
|
7
|
+
import * as ComponentsConst from './popup';
|
|
8
|
+
import ReadMe from './stories/README.md?raw';
|
|
9
|
+
|
|
10
|
+
import Button from '@/components/forms/button/button.vue';
|
|
11
|
+
|
|
12
|
+
const argTypes = genArgsTypes(Component, ComponentsConst);
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
component: Component,
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
argTypes,
|
|
18
|
+
parameters: {
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component: ReadMe,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
} satisfies Meta<typeof Component>;
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
export const Playground = {
|
|
30
|
+
render: (args) => ({
|
|
31
|
+
components: {
|
|
32
|
+
Popup: Component,
|
|
33
|
+
Button,
|
|
34
|
+
},
|
|
35
|
+
setup () {
|
|
36
|
+
return { args };
|
|
37
|
+
},
|
|
38
|
+
template: `
|
|
39
|
+
<Popup :="args">
|
|
40
|
+
<template #opener>
|
|
41
|
+
<Button>
|
|
42
|
+
Просто текст
|
|
43
|
+
</Button>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<template #header>
|
|
47
|
+
Текст в слоте #header
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<template #content>
|
|
51
|
+
Текст в слоте #content
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<template #footer>
|
|
55
|
+
<Button>
|
|
56
|
+
Закрыть
|
|
57
|
+
</Button>
|
|
58
|
+
</template>
|
|
59
|
+
</Popup>
|
|
60
|
+
`,
|
|
61
|
+
}),
|
|
62
|
+
} satisfies Story;
|
|
63
|
+
|
|
64
|
+
export const Overview: Story = genOverviewStory({
|
|
65
|
+
args: {},
|
|
66
|
+
}, OverviewComponent);
|
|
67
|
+
|
|
68
|
+
export default meta;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export interface Props extends OpenerProps {
|
|
2
|
+
/**
|
|
3
|
+
* Уникальный id компонента, используется только в setup, т.е. изменение id будет проигнорировано
|
|
4
|
+
*
|
|
5
|
+
* Генерируется автоматически при создании кнопки Popup
|
|
6
|
+
*
|
|
7
|
+
* Можно задать вручную, если необходимо создать Popup без кнопки для последюущего использования,
|
|
8
|
+
* особенно важно при создании большого числа кнопок, например в списках и таблицах
|
|
9
|
+
*/
|
|
10
|
+
id?: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Класс, который нужно добавить к Popup, устанавилвается в момент открытия
|
|
14
|
+
*/
|
|
15
|
+
class?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Emits {
|
|
19
|
+
/**
|
|
20
|
+
* Будет вызвано при открытии Popup
|
|
21
|
+
*/
|
|
22
|
+
(e: 'open'): void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Будет вызвано после закрытия Popup
|
|
26
|
+
*/
|
|
27
|
+
(e: 'close'): void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface OpenerProps {
|
|
31
|
+
/**
|
|
32
|
+
* id компонента Popup, который необходимо открыть
|
|
33
|
+
*/
|
|
34
|
+
id?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Положение Popup по часовой стрелке
|
|
38
|
+
*/
|
|
39
|
+
pos?: Pos;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Добавить клювик
|
|
43
|
+
*/
|
|
44
|
+
notch?: boolean;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Открывать / закрывать при наведении / отведении мыши
|
|
48
|
+
*/
|
|
49
|
+
openByHover?: boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Способ привязки позиционирования меню
|
|
53
|
+
*
|
|
54
|
+
* left/right - левый/правый край родителя
|
|
55
|
+
*
|
|
56
|
+
* fixed - по окну
|
|
57
|
+
*/
|
|
58
|
+
posBy?: PosBy;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ListItemProps {
|
|
62
|
+
/**
|
|
63
|
+
* Тип элемента списка
|
|
64
|
+
* * simple - обычный кликабельный (выбираемый) элемент
|
|
65
|
+
* * link - ссылка
|
|
66
|
+
* * control - элемент формы, например чекбокс
|
|
67
|
+
* * delimiter - разделитель
|
|
68
|
+
*/
|
|
69
|
+
type?: 'simple' | 'link' | 'control' | 'title' | 'delimiter';
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Следует ли закрывать меню по клику на элемент типа simple и link
|
|
73
|
+
*/
|
|
74
|
+
closeByClick?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const pos = {
|
|
78
|
+
over: '0',
|
|
79
|
+
top: '1',
|
|
80
|
+
right: '2',
|
|
81
|
+
bottom: '3',
|
|
82
|
+
left: '4',
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
export type Pos = typeof pos[keyof typeof pos];
|
|
86
|
+
|
|
87
|
+
export const posBy = {
|
|
88
|
+
fixed: 'fixed',
|
|
89
|
+
left: 'left',
|
|
90
|
+
right: 'right',
|
|
91
|
+
} as const;
|
|
92
|
+
|
|
93
|
+
export type PosBy = typeof posBy[keyof typeof posBy];
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, toRef, onUnmounted } from 'vue';
|
|
3
|
+
import type { Props, Emits } from './popup';
|
|
4
|
+
import Opener from './opener.vue';
|
|
5
|
+
import Worker from '@/components/popup/lib/worker';
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
8
|
+
id: '',
|
|
9
|
+
pos: '3',
|
|
10
|
+
notch: true,
|
|
11
|
+
posBy: 'fixed',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<Emits>();
|
|
15
|
+
|
|
16
|
+
const id = props.id || Math.random() + '';
|
|
17
|
+
const elPopupRef = ref(null);
|
|
18
|
+
|
|
19
|
+
// см. lib/popup
|
|
20
|
+
const onOpen = async (popup: any) => {
|
|
21
|
+
popup.elPopupInner.innerText = '';
|
|
22
|
+
|
|
23
|
+
elPopupRef.value = popup.elPopupInner;
|
|
24
|
+
|
|
25
|
+
vueConnector.opened = true;
|
|
26
|
+
vueConnector.popup = popup;
|
|
27
|
+
|
|
28
|
+
emit('open');
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// см. lib/popup
|
|
32
|
+
const onClose = (popup: any) => {
|
|
33
|
+
elPopupRef.value = null;
|
|
34
|
+
|
|
35
|
+
vueConnector.opened = false;
|
|
36
|
+
vueConnector.popup = null;
|
|
37
|
+
|
|
38
|
+
emit('close');
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const vueConnector = {
|
|
42
|
+
onOpen,
|
|
43
|
+
onClose,
|
|
44
|
+
classRef: toRef(props, 'class'),
|
|
45
|
+
opened: false,
|
|
46
|
+
popup: null,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Worker.regVueComponent(id, vueConnector);
|
|
50
|
+
|
|
51
|
+
onUnmounted(() => {
|
|
52
|
+
Worker.unregVueComponent(id);
|
|
53
|
+
});
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<Opener
|
|
58
|
+
v-if="$slots.opener"
|
|
59
|
+
:id="id"
|
|
60
|
+
:pos="pos"
|
|
61
|
+
:posBy="posBy"
|
|
62
|
+
:notch="notch"
|
|
63
|
+
:openByHover="openByHover"
|
|
64
|
+
>
|
|
65
|
+
<!-- @slot элемент для открытия Popup -->
|
|
66
|
+
<slot name="opener"></slot>
|
|
67
|
+
</Opener>
|
|
68
|
+
|
|
69
|
+
<!-- Это шаблон для компонента Popup, сам Popup генерируется в js и может находиться где угодно -->
|
|
70
|
+
<!-- elPopupRef будет установлен только после открытия и будет сброшен сразу после закрытия Popup -->
|
|
71
|
+
<teleport
|
|
72
|
+
v-if="elPopupRef"
|
|
73
|
+
:to="elPopupRef"
|
|
74
|
+
>
|
|
75
|
+
<div v-if="$slots.header" class="top-popup_header">
|
|
76
|
+
<!-- @slot Шапка -->
|
|
77
|
+
<slot name="header"></slot>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div v-if="$slots.content" class="top-popup_content">
|
|
81
|
+
<!-- @slot Контент в свободной форме -->
|
|
82
|
+
<slot name="content"></slot>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<ul v-if="$slots.contentList" class="top-popup_content">
|
|
86
|
+
<!-- @slot Контент в виде списка, для вставки элементов списка испоьзуйте компонент popup/listItem -->
|
|
87
|
+
<slot name="contentList"></slot>
|
|
88
|
+
</ul>
|
|
89
|
+
|
|
90
|
+
<div v-if="$slots.footer" class="top-popup_footer">
|
|
91
|
+
<!-- @slot Футер -->
|
|
92
|
+
<slot name="footer"></slot>
|
|
93
|
+
</div>
|
|
94
|
+
</teleport>
|
|
95
|
+
</template>
|