@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,55 @@
|
|
|
1
|
+
import type { DirectiveBinding, ObjectDirective, VNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _window: any = window;
|
|
4
|
+
|
|
5
|
+
const $ = (el: VNode) => {
|
|
6
|
+
if (!_window?.jQuery?.ui?.tooltip) {
|
|
7
|
+
console.info('Для работы v-top-tooltip требуется глобальная загрузка jQuery UI Tooltip');
|
|
8
|
+
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return _window.jQuery(el);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const tvTooltipGenOptions = (binding: DirectiveBinding, vnode: VNode) => {
|
|
16
|
+
const options = binding.value ?? {};
|
|
17
|
+
|
|
18
|
+
options.content ??= vnode.props?.title;
|
|
19
|
+
options.content = String(options.content).replace(/\r\n|\r|\n/g, '<br>');
|
|
20
|
+
|
|
21
|
+
options.position ??= {
|
|
22
|
+
my: 'bottom-18px',
|
|
23
|
+
at: 'top center',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return options;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const tooltip = {
|
|
30
|
+
mounted(el: VNode, binding: DirectiveBinding, vnode: VNode) {
|
|
31
|
+
$(el)?.tooltip(tvTooltipGenOptions(binding, vnode));
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
updated(el: VNode, binding: DirectiveBinding, vnode: VNode, _prevVnode: VNode) {
|
|
35
|
+
/**
|
|
36
|
+
* В результате обновления может быть открыто несколько тултипов поэтому изменить опции, без перерисовки тултипа
|
|
37
|
+
*/
|
|
38
|
+
const options = tvTooltipGenOptions(binding, vnode);
|
|
39
|
+
const instance = $(el)?.tooltip('instance');
|
|
40
|
+
if (!instance) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
instance.options = {
|
|
45
|
+
...instance.options,
|
|
46
|
+
...options,
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
unmounted(el: VNode, binding: DirectiveBinding, vnode: VNode) {
|
|
51
|
+
$(el)?.tooltip('destroy');
|
|
52
|
+
},
|
|
53
|
+
} satisfies ObjectDirective;
|
|
54
|
+
|
|
55
|
+
export default tooltip;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Args, ArgTypes, Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
import { getCurrentCSS } from '@/../.storybook/TopTheme';
|
|
3
|
+
import Component from '@/storybook/components/colors.vue';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
component: Component,
|
|
7
|
+
} satisfies Meta<typeof Component>;
|
|
8
|
+
|
|
9
|
+
export const Colors = {
|
|
10
|
+
args: {
|
|
11
|
+
style: getCurrentCSS()
|
|
12
|
+
}
|
|
13
|
+
} satisfies StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
import { getCurrentCSS } from '@/../.storybook/TopTheme';
|
|
3
|
+
import Component from '@/storybook/components/properties.vue';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
component: Component,
|
|
7
|
+
} satisfies Meta<typeof Component>;
|
|
8
|
+
|
|
9
|
+
export const Properties = {
|
|
10
|
+
args: {
|
|
11
|
+
style: getCurrentCSS()
|
|
12
|
+
}
|
|
13
|
+
} satisfies StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Canvas } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
# Темы
|
|
4
|
+
|
|
5
|
+
Каждая тема представляет из себя набор переменных. Может включать в себя переменные для настройки любых стилей.
|
|
6
|
+
|
|
7
|
+
Все темы должны реализовывать одинаковый набор переменных.
|
|
8
|
+
|
|
9
|
+
Переменные темы после сборки доступны в файле темы в:
|
|
10
|
+
- после сборки:
|
|
11
|
+
- **light.css**
|
|
12
|
+
- **dark.css**
|
|
13
|
+
- до сборки:
|
|
14
|
+
- **src/resources/styles/themes/light/*.css**
|
|
15
|
+
- **src/resources/styles/themes/dark/*.css**
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import Core from '@/core/core/core';
|
|
2
|
+
|
|
3
|
+
class UtilsDate {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Получить объект Date из строки
|
|
7
|
+
* @param date - строка с датой
|
|
8
|
+
*/
|
|
9
|
+
static stringToDate(date: string) {
|
|
10
|
+
if (date.indexOf('T') === -1) {
|
|
11
|
+
if (date.length == 10) {
|
|
12
|
+
date += ' 00:00:00';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
date = date.replace(' ', 'T') + Core.state.gmt;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return new Date(date);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Перевод миллисекунд (UTC) в дату-строку (время локальное)
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Перевод миллисекунд (UTC) в дату-строку (время локальное)
|
|
25
|
+
* @param {?number} ms
|
|
26
|
+
* @param {?boolean} useFormat
|
|
27
|
+
*/
|
|
28
|
+
static ms2Date(ms: number, useFormat: boolean = true): string {
|
|
29
|
+
let date;
|
|
30
|
+
if (ms != undefined) {
|
|
31
|
+
date = new Date(ms);
|
|
32
|
+
} else {
|
|
33
|
+
date = new Date();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const d = date.getDate().toString().padStart(2, '0');
|
|
37
|
+
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
38
|
+
const Y = date.getFullYear();
|
|
39
|
+
const H = date.getHours().toString().padStart(2, '0');
|
|
40
|
+
const i = date.getMinutes().toString().padStart(2, '0');
|
|
41
|
+
const s = date.getSeconds().toString().padStart(2, '0');
|
|
42
|
+
|
|
43
|
+
date = Y + '-' + m + '-' + d + ' ' + H + ':' + i + ':' + s;
|
|
44
|
+
|
|
45
|
+
if (useFormat) {
|
|
46
|
+
date = this.dateFormat(date);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return date;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Перевод даты в формат пользователя
|
|
54
|
+
* @param {string} date
|
|
55
|
+
* @param {0|1|2|3} time - 0: только дата, 1: дата и часы, 2: дата и часы с минутами, 3: дата и часы с минутами и секундами
|
|
56
|
+
*/
|
|
57
|
+
static dateFormat(date: string, time: 0 | 1 | 2 | 3 = 2, emptyValue: string = Core.L.Not_date): string {
|
|
58
|
+
if (!date || date.substring(0, 10) === '0000-00-00') {
|
|
59
|
+
if (emptyValue && emptyValue !== '0000-00-00') {
|
|
60
|
+
return emptyValue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const dateFormat = Core.state.dateFormat.toLowerCase();
|
|
65
|
+
|
|
66
|
+
let dateForObj = date.substring(0, 10);
|
|
67
|
+
|
|
68
|
+
if (dateForObj.length === 7) {
|
|
69
|
+
dateForObj += '-01';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
dateForObj += ' 00:00';
|
|
73
|
+
|
|
74
|
+
// safari fix
|
|
75
|
+
dateForObj = dateForObj.replace(/-/g, '/');
|
|
76
|
+
|
|
77
|
+
const dateObject = new Date(dateForObj);
|
|
78
|
+
if (isNaN(Number(dateObject))) {
|
|
79
|
+
return emptyValue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let result = dateFormat.
|
|
83
|
+
replace('y', String(dateObject.getFullYear()).padStart(2, '0')).
|
|
84
|
+
replace('m', String(dateObject.getMonth() + 1).padStart(2, '0')).
|
|
85
|
+
replace('d', String(dateObject.getDate()).padStart(2, '0'));
|
|
86
|
+
|
|
87
|
+
if (date.length > 10) {
|
|
88
|
+
switch (time) {
|
|
89
|
+
// часы
|
|
90
|
+
case 1:
|
|
91
|
+
result += ' ' + date.substring(11, 13);
|
|
92
|
+
|
|
93
|
+
break;
|
|
94
|
+
|
|
95
|
+
// часы и минуты
|
|
96
|
+
case 2:
|
|
97
|
+
result += ' ' + date.substring(11, 16);
|
|
98
|
+
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
// часы, минуты и секунды
|
|
102
|
+
case 3:
|
|
103
|
+
result += ' ' + date.substring(11, 19);
|
|
104
|
+
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Перевод даты из формата пользователя в системный формат
|
|
114
|
+
* @param {string} date
|
|
115
|
+
*/
|
|
116
|
+
static dateUnformat(date: string, emptyValue: string = Core.L.Not_date): string {
|
|
117
|
+
if (!date) {
|
|
118
|
+
return emptyValue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (date.match(/\d\d\d\d-\d\d-\d\d/)) {
|
|
122
|
+
return date;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const dateFormat = Core.state.dateFormat.toLowerCase();
|
|
126
|
+
|
|
127
|
+
const dateChunks = date.split(/\W/);
|
|
128
|
+
const dateFormatChunks = dateFormat.split(/\W/);
|
|
129
|
+
|
|
130
|
+
let d = '';
|
|
131
|
+
let m = '';
|
|
132
|
+
let y = '';
|
|
133
|
+
|
|
134
|
+
dateFormatChunks.forEach((type, index) => {
|
|
135
|
+
switch (type) {
|
|
136
|
+
case 'd':
|
|
137
|
+
d = dateChunks[index];
|
|
138
|
+
|
|
139
|
+
break;
|
|
140
|
+
case 'm':
|
|
141
|
+
m = dateChunks[index];
|
|
142
|
+
|
|
143
|
+
break;
|
|
144
|
+
case 'y':
|
|
145
|
+
y = dateChunks[index];
|
|
146
|
+
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
let result = y + '-' + m + '-' + d;
|
|
152
|
+
|
|
153
|
+
if (!result.match(/\d\d\d\d-\d\d-\d\d/)) {
|
|
154
|
+
console.info('Неверный формат даты, будет возращена текущая дата, ' + result);
|
|
155
|
+
|
|
156
|
+
result = this.ms2Date((new Date()).getTime(), false).substring(0, 10);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export default UtilsDate;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
class Device {
|
|
2
|
+
|
|
3
|
+
static isRetina () {
|
|
4
|
+
return ('devicePixelRatio' in window && window.devicePixelRatio > 1);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// определить, является ли устройство мобильным
|
|
8
|
+
static isMobile (): boolean {
|
|
9
|
+
return !!navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|IEMobile|Opera Mini/i);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// определить, открыт ли сайт в приложении
|
|
13
|
+
static isApp () {
|
|
14
|
+
return (navigator.userAgent.indexOf('Topvisor_App') != -1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// определить, является ли OS пользователя macOS
|
|
18
|
+
static isMacOS () {
|
|
19
|
+
return navigator.userAgent.indexOf('Mac OS X') !== -1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// определить, является ли текущий браузер пользователя Safari
|
|
23
|
+
static isSafari () {
|
|
24
|
+
const isChrome = /Chrome|Android/.test(navigator.userAgent);
|
|
25
|
+
|
|
26
|
+
let isSafari = /Safari/.test(navigator.userAgent);
|
|
27
|
+
if (isChrome && isSafari) {
|
|
28
|
+
isSafari = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return isSafari;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Вернуть текст для обозначения клавиши Ctrl / Command в зависимости от OS
|
|
36
|
+
* @returns {'Ctrl'|'⌘'}
|
|
37
|
+
*/
|
|
38
|
+
static getCommandKeyLabel (): 'Ctrl' | '⌘' {
|
|
39
|
+
if (this.isMacOS()) {
|
|
40
|
+
return '⌘';
|
|
41
|
+
} else {
|
|
42
|
+
return 'Ctrl';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default Device;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Функции для работы с работы с Document Object Model (DOM)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Создать элемент
|
|
7
|
+
* @param {string} tagName
|
|
8
|
+
* @param {any} attrs - атрибуты
|
|
9
|
+
* @param {Element[]} elsChildrens
|
|
10
|
+
* @returns {Element} - созданный элемент
|
|
11
|
+
*/
|
|
12
|
+
function genEl (tagName: string, attrs: any, ...elsChildrens: Element[]): Element {
|
|
13
|
+
const el: any = document.createElement(tagName);
|
|
14
|
+
|
|
15
|
+
for (const name in attrs) {
|
|
16
|
+
if (name.indexOf('on') === 0) {
|
|
17
|
+
// events
|
|
18
|
+
el[name] = attrs[name];
|
|
19
|
+
} else {
|
|
20
|
+
el.setAttribute(name, attrs[name]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
elsChildrens.forEach((elChildren) => {
|
|
25
|
+
if (typeof (elChildren) === 'string') {
|
|
26
|
+
el.insertAdjacentHTML('beforeend', elChildren);
|
|
27
|
+
} else {
|
|
28
|
+
el.append(elChildren);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return el;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Проверить видимость элемента
|
|
37
|
+
* @param {?Element} el
|
|
38
|
+
* @returns boolean - вернет true, если элемент считается видимым
|
|
39
|
+
*/
|
|
40
|
+
function isVisible (el?: Element) {
|
|
41
|
+
if (!el) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const boundingClientRect = el.getBoundingClientRect();
|
|
46
|
+
return !!(boundingClientRect.width || boundingClientRect.height);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Получить координаты элемента относительно документа
|
|
51
|
+
* @param {Element} el
|
|
52
|
+
* @returns {{top: number, left: number}} - координаты элемента относительно документа
|
|
53
|
+
*/
|
|
54
|
+
function offset (el: Element): { top: number, left: number } {
|
|
55
|
+
const boundingClientRect = el.getBoundingClientRect();
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
top: boundingClientRect.top + window.scrollY,
|
|
59
|
+
left: boundingClientRect.left + window.scrollX,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Получить значение css свойства элемента
|
|
65
|
+
* @param {Element} el
|
|
66
|
+
* @param {string} property - имя свойства
|
|
67
|
+
* @return {string} - значение css стиля
|
|
68
|
+
*/
|
|
69
|
+
function css (el: Element, property: string): string {
|
|
70
|
+
return window.getComputedStyle(el).getPropertyValue(property);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Обернуть элемент и вернуть только что созданный элемент
|
|
75
|
+
* @param {Element} el - элемент, который требуется обернуть
|
|
76
|
+
* @param {string} tagName - имя тега элемента, в который треубется обернуть элемент
|
|
77
|
+
* @returns {Element}
|
|
78
|
+
*/
|
|
79
|
+
function wrap (el: Element, tagName: string): Element {
|
|
80
|
+
const elWrapper = document.createElement(tagName);
|
|
81
|
+
el.after(elWrapper);
|
|
82
|
+
|
|
83
|
+
elWrapper.append(el);
|
|
84
|
+
|
|
85
|
+
return elWrapper;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Найти и вернуть первый видимый элемент
|
|
90
|
+
* @param {?Document|Element} el - корневой элемент поиска
|
|
91
|
+
* @param selectors - см. параметр selectors в Document.querySelectorAll()
|
|
92
|
+
* @returns {Element|null}
|
|
93
|
+
*/
|
|
94
|
+
function querySelectorVisible (el: Element, selectors: string): Element | null {
|
|
95
|
+
return querySelectorAllArray(el, selectors).find(isVisible) || null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Найти и вернуть последний видимый элемент
|
|
100
|
+
* @param {?Document|Element} el - корневой элемент поиска
|
|
101
|
+
* @param selectors - см. параметр selectors в Document.querySelectorAll()
|
|
102
|
+
* @returns {Element|null}
|
|
103
|
+
*/
|
|
104
|
+
function querySelectorVisibleLast (el: Element, selectors: string): Element | null {
|
|
105
|
+
return querySelectorAllArray(el, selectors).findLast(isVisible) || null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Найти видимые элементы
|
|
110
|
+
* @param {?Document|Element} el - корневой элемент поиска
|
|
111
|
+
* @param selectors - см. параметр selectors в Document.querySelectorAll()
|
|
112
|
+
* @returns {Element[]} - обратите внимание, возвращается не NodeList[], а Element[]
|
|
113
|
+
*/
|
|
114
|
+
function querySelectorAllVisible (el: Element, selectors: string): Element[] {
|
|
115
|
+
return querySelectorAllArray(el, selectors).filter(isVisible);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Найти элементы и вернуть в виде массива
|
|
120
|
+
* @param {?Document|Element} el - корневой элемент поиска
|
|
121
|
+
* @param selectors - см. параметр selectors в Document.querySelectorAll()
|
|
122
|
+
* @returns {Element[]}
|
|
123
|
+
*/
|
|
124
|
+
function querySelectorAllArray (el: Element, selectors: string): Element[] {
|
|
125
|
+
if (!el) {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return [...el.querySelectorAll(selectors)];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Хранилище данных элемента
|
|
134
|
+
* @param {Element} el
|
|
135
|
+
* @param {string} contextName - контекст, обычно используется имя компонента
|
|
136
|
+
* @param {?object | null} contextData - установить объект с данными, предыдущие данные будут заменены, установите null для удаления данных
|
|
137
|
+
* @returns {?object} - вернет объект контекста или undefined, если данные контекста не найдены
|
|
138
|
+
*/
|
|
139
|
+
function storage (
|
|
140
|
+
el?: Element & { topData?: any },
|
|
141
|
+
contextName: string = 'common', contextData: object | null | undefined = undefined,
|
|
142
|
+
): object | undefined {
|
|
143
|
+
if (!el) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!el.topData) {
|
|
148
|
+
el.topData = {};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (contextData) {
|
|
152
|
+
el.topData[contextName] = contextData;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (contextData === null) {
|
|
156
|
+
delete el.topData[contextName];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return el.topData[contextName];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Очистить хранилище элемента
|
|
164
|
+
*/
|
|
165
|
+
function storageClear (el?: Element & { topData?: any }) {
|
|
166
|
+
if (!el) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
delete el.topData;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default {
|
|
174
|
+
genEl,
|
|
175
|
+
isVisible,
|
|
176
|
+
offset,
|
|
177
|
+
css,
|
|
178
|
+
wrap,
|
|
179
|
+
querySelectorVisible,
|
|
180
|
+
querySelectorVisibleLast,
|
|
181
|
+
querySelectorAllVisible,
|
|
182
|
+
querySelectorAllArray,
|
|
183
|
+
storage,
|
|
184
|
+
storageClear,
|
|
185
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue';
|
|
3
|
+
import * as icomoon from '@/storybook/components/icomoon';
|
|
4
|
+
|
|
5
|
+
const clipboardCopy = (string: string) => navigator.clipboard.writeText(string);
|
|
6
|
+
|
|
7
|
+
const searchString = ref('');
|
|
8
|
+
|
|
9
|
+
const icons = computed(() => icomoon.genIconByLetter(searchString.value));
|
|
10
|
+
|
|
11
|
+
// TODO: использовать компонент Input
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<div class="icomoon">
|
|
16
|
+
<p>Поиск проивзоидтся по символу, названию и тегам.</p>
|
|
17
|
+
|
|
18
|
+
<p>Кликните на иконку, чтобы скопировать ее символ.</p>
|
|
19
|
+
|
|
20
|
+
<input
|
|
21
|
+
placeholder="Поиск"
|
|
22
|
+
@input="(e: any) => searchString = e.target.value"
|
|
23
|
+
>
|
|
24
|
+
|
|
25
|
+
<br><br>
|
|
26
|
+
|
|
27
|
+
<div class="icomoon_list">
|
|
28
|
+
<div
|
|
29
|
+
v-for="(icon, letter) in icons"
|
|
30
|
+
class="icomoon_item"
|
|
31
|
+
>
|
|
32
|
+
<span
|
|
33
|
+
class="icomoon_icon"
|
|
34
|
+
:data-top-icon="letter"
|
|
35
|
+
@click="clipboardCopy(icon.letter)"
|
|
36
|
+
></span>
|
|
37
|
+
|
|
38
|
+
{{ icon.name }}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
.icomoon {}
|
|
46
|
+
|
|
47
|
+
.icomoon_list {
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
gap: 20px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.icomoon_item {
|
|
54
|
+
width: 20%;
|
|
55
|
+
display: flex;
|
|
56
|
+
gap: 4px;
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap: 8px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.icomoon_icon {
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
border-radius: 8px;
|
|
65
|
+
border: 1px solid var(--color-line-1-opacity);
|
|
66
|
+
width: 32px;
|
|
67
|
+
height: 32px;
|
|
68
|
+
box-shadow: var(--top-shadow-s);
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
}
|
|
72
|
+
</style>../../storybook/components/icomoon
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Story } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
# Набор иконок
|
|
4
|
+
|
|
5
|
+
Шрифт иконок настраивается через сервис [icomoon](https://icomoon.io/) и сохранятся в папку **public/icomoon**.
|
|
6
|
+
|
|
7
|
+
Текущий конфиг icomoon: <a href="/src/resources/icomoon/selection.json" target="_blank">selection.json</a>.
|
|
8
|
+
|
|
9
|
+
После предкомпиляции он будет доступен в корне проекта в папке: **icomoon**.
|
|
10
|
+
|
|
11
|
+
Имя шрифта: **Topvisor-2**.
|
|
12
|
+
|
|
13
|
+
Topvisor-ui определяет стили для реализации вывода иконок в верстке через атрибуты **data-top-icon** и **data-top-icon2**.
|
|
14
|
+
|
|
15
|
+
## Варианты использования
|
|
16
|
+
|
|
17
|
+
Использование через атрибут, обычный html:
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<div data-top-icon="" />
|
|
21
|
+
<div data-top-icon2="" />
|
|
22
|
+
<div data-top-icon="" data-top-icon2="" />
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Использование через компонент [Icon](/story/components-common-icon--icon):
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<icon :icon="" />
|
|
29
|
+
<icon :icon2="" />
|
|
30
|
+
<icon :icon="" :icon2="" />
|
|
31
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
|
|
3
|
+
import Component from './gallery.vue';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title:'',
|
|
7
|
+
component: Component,
|
|
8
|
+
} satisfies Meta<typeof Component>;
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj<typeof meta>;
|
|
11
|
+
|
|
12
|
+
export const Default = {} satisfies Story;
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# FAQ
|
|
2
|
+
|
|
3
|
+
**Почему используется camelCase?**
|
|
4
|
+
|
|
5
|
+
> Для возможности использования одинарных разделителей, код становится чище
|
|
6
|
+
|
|
7
|
+
> Чтобы имя блока сответствовало имени компонента
|
|
8
|
+
|
|
9
|
+
**Почему в css модулях не добавляется хеш?**
|
|
10
|
+
|
|
11
|
+
> В UI-kit принято использовать понятные и чистые имена классов
|
|
12
|
+
|
|
13
|
+
> Упрощается процесс поиска нужного компонента или его элемента
|
|
14
|
+
|
|
15
|
+
**Зачем нужно следовать правилам БЭМ, если есть правила сборки css модуля?**
|
|
16
|
+
|
|
17
|
+
> Чтобы было можно быстро разобраться, к какому компоненту приналежит тот или иной класс
|
|
18
|
+
|
|
19
|
+
> Чтобы код следовал единому стилю
|
|
20
|
+
|
|
21
|
+
**Зачем нужен css модуль, если есть БЭМ?**
|
|
22
|
+
|
|
23
|
+
> В правила преобразовавний классов можно вынести рутинные действия, например добавление префикса, характеризующего namespace / workspace
|
|
24
|
+
|
|
25
|
+
> IDE поддерижвает автозаполнения классов модулей и навигацию по ним
|
|
26
|
+
|
|
27
|
+
> Позволяет использовать дополнительные плагины для добавления полезного функционала
|
|
28
|
+
|
|
29
|
+
**SSR с отдельной сборкой решает проблему размера сборки, зачем нужные ленивые компоненты?**
|
|
30
|
+
|
|
31
|
+
> SPA приложение предполагает смену страниц без перезагрузки, поэтому отдельные сборки для каждой страницы будут приводить
|
|
32
|
+
к дублям стилей при переходе между страницами. Так как страниц много, то возникнет ситуация, при которой кеш таких стилей будет мало полезен.
|
|
33
|
+
|
|
34
|
+
> Такие сборки придется дополнительно настраивать и следить за выгрзкой дублей стилей между разными сборками разных страниц.
|
|
35
|
+
|
|
36
|
+
> Автосборки SSR действительно удобны, однако если решить этот вопрос на этапе преоктировки UI, то таких проблем в SSR удастся избежать.
|
|
37
|
+
|
|
38
|
+
**Как поменять какие компоненты и стили надо грузить при загрузке страницы, а какие в отложенном режиме?**
|
|
39
|
+
|
|
40
|
+
> Сразу надо грузить те кмопоненты, которые должны быть отрисованы в момент загрузки текстовой страницы, например /forms/ и /content/.
|
|
41
|
+
|
|
42
|
+
> Если потребуется мгновенная отрисовка компонента на какой-то странице, в самом вверху этой страницы можно указать прямую ссылку на css компонента.
|
|
43
|
+
> Данный вопрос выходит за рамки UI-kit. Читайте: [CLS](https://web.dev/i18n/en/cls/).
|