@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,22 @@
|
|
|
1
|
+
type ModelValue = boolean | string[] | Set<string>;
|
|
2
|
+
|
|
3
|
+
export interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Может быть одного из трех типов:
|
|
6
|
+
* - boolean
|
|
7
|
+
* - string[]
|
|
8
|
+
* - Set
|
|
9
|
+
*
|
|
10
|
+
* [подробнее](https://vuejs.org/guide/essentials/forms.html#checkbox)
|
|
11
|
+
*/
|
|
12
|
+
modelValue: ModelValue;
|
|
13
|
+
name?: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
isError?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface Emits {
|
|
21
|
+
(e: 'update:modelValue', value: ModelValue): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import type { Props, Emits } from './switcher';
|
|
4
|
+
import ControlLabel from '../controlLabel/controlLabel.vue';
|
|
5
|
+
|
|
6
|
+
const props = defineProps<Props>();
|
|
7
|
+
const emit = defineEmits<Emits>();
|
|
8
|
+
|
|
9
|
+
const localValue = computed({
|
|
10
|
+
get() {
|
|
11
|
+
return props.modelValue;
|
|
12
|
+
},
|
|
13
|
+
set(value) {
|
|
14
|
+
emit('update:modelValue', value);
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<label
|
|
21
|
+
:class="{
|
|
22
|
+
['top-forms-optionWrapper']: true,
|
|
23
|
+
['top-checkboxSwitcher']: true,
|
|
24
|
+
['top-disabled']: disabled,
|
|
25
|
+
['top-error']: isError && !disabled,
|
|
26
|
+
}"
|
|
27
|
+
>
|
|
28
|
+
<input
|
|
29
|
+
type="checkbox"
|
|
30
|
+
:class="{
|
|
31
|
+
['top-forms-focusable']: !disabled,
|
|
32
|
+
['top-forms-option']: true,
|
|
33
|
+
['top-checkboxSwitcher_input']: true,
|
|
34
|
+
['top-error']: isError && !disabled,
|
|
35
|
+
}"
|
|
36
|
+
v-model="localValue"
|
|
37
|
+
:name="name"
|
|
38
|
+
:value="value"
|
|
39
|
+
:disabled="disabled"
|
|
40
|
+
>
|
|
41
|
+
|
|
42
|
+
<ControlLabel
|
|
43
|
+
v-if="$slots.default"
|
|
44
|
+
:description="description"
|
|
45
|
+
:disabled="disabled"
|
|
46
|
+
>
|
|
47
|
+
<!-- @slot Слот с заголовком -->
|
|
48
|
+
<slot></slot>
|
|
49
|
+
</ControlLabel>
|
|
50
|
+
</label>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style module>
|
|
54
|
+
.top-checkboxSwitcher {
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
gap: 4px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.top-checkboxSwitcher_input {
|
|
61
|
+
border-radius: 9px;
|
|
62
|
+
border: none;
|
|
63
|
+
background: var(--color-theme-100);
|
|
64
|
+
width: 36px;
|
|
65
|
+
height: 18px;
|
|
66
|
+
position: relative;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.top-checkboxSwitcher_input:before {
|
|
70
|
+
content: '';
|
|
71
|
+
border-radius: 50%;
|
|
72
|
+
background: var(--color-white);
|
|
73
|
+
width: 12px;
|
|
74
|
+
height: 12px;
|
|
75
|
+
margin: 3px;
|
|
76
|
+
position: absolute;
|
|
77
|
+
top: 0;
|
|
78
|
+
left: 0;
|
|
79
|
+
|
|
80
|
+
transition: left 0.1s;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.top-checkboxSwitcher_input:hover {
|
|
84
|
+
background: var(--color-theme-150);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* checked */
|
|
88
|
+
.top-checkboxSwitcher_input:checked {
|
|
89
|
+
background: var(--top-forms-option-color);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.top-checkboxSwitcher_input:checked:hover {
|
|
93
|
+
background: var(--top-forms-option-color-hover);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.top-checkboxSwitcher_input:checked:before {
|
|
97
|
+
left: 50%;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* disabled */
|
|
101
|
+
.top-checkboxSwitcher_input:disabled {
|
|
102
|
+
background: var(--color-theme-400);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* isError */
|
|
106
|
+
.top-checkboxSwitcher_input.top-error {
|
|
107
|
+
background: var(--color-negative);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.top-checkboxSwitcher_input.top-error:hover {
|
|
111
|
+
background: var(--color-negative-2);
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { reactive } from 'vue';
|
|
3
|
+
import type { Props } from '../textarea';
|
|
4
|
+
import Textarea from '../textarea.vue';
|
|
5
|
+
|
|
6
|
+
defineProps<Props>();
|
|
7
|
+
|
|
8
|
+
const genVariantProps = () => {
|
|
9
|
+
return {
|
|
10
|
+
'Без настроек': {
|
|
11
|
+
modelValue: '',
|
|
12
|
+
},
|
|
13
|
+
'С placeholder': {
|
|
14
|
+
modelValue: '',
|
|
15
|
+
placeholder: `Напишите что-нибудь...
|
|
16
|
+
|
|
17
|
+
Поддерживается многострочный placeholder
|
|
18
|
+
`,
|
|
19
|
+
},
|
|
20
|
+
'С текстом': {
|
|
21
|
+
modelValue: 'Текст введен',
|
|
22
|
+
},
|
|
23
|
+
'Много строк текста': {
|
|
24
|
+
modelValue: `Ночь, улица, фонарь, аптека,
|
|
25
|
+
Бессмысленный и тусклый свет.
|
|
26
|
+
Живи еще хоть четверть века -
|
|
27
|
+
Все будет так. Исхода нет.
|
|
28
|
+
|
|
29
|
+
Умрешь - начнешь опять сначала
|
|
30
|
+
И повторится все, как встарь:
|
|
31
|
+
Ночь, ледяная рябь канала,
|
|
32
|
+
Аптека, улица, фонарь.`,
|
|
33
|
+
},
|
|
34
|
+
'Не активная': {
|
|
35
|
+
modelValue: 'Текст введен',
|
|
36
|
+
disabled: true,
|
|
37
|
+
},
|
|
38
|
+
'Только чтение': {
|
|
39
|
+
modelValue: 'Текст введен',
|
|
40
|
+
readonly: true,
|
|
41
|
+
},
|
|
42
|
+
} satisfies Record<string, Props>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const variantProps = reactive(genVariantProps());
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div class="overview" style="display: grid; grid-template-columns: auto 1fr; gap: 32px;">
|
|
50
|
+
<template v-for="(props, h2) in variantProps">
|
|
51
|
+
<div>
|
|
52
|
+
<h2>
|
|
53
|
+
{{ h2 }}
|
|
54
|
+
</h2>
|
|
55
|
+
<Textarea
|
|
56
|
+
:="{...$props, ...props}"
|
|
57
|
+
v-model="props.modelValue"
|
|
58
|
+
></Textarea>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
|
|
3
|
+
import { genArgsTypes, genOverviewStory } from '@/components/helpersStories';
|
|
4
|
+
import Component from './textarea.vue';
|
|
5
|
+
import * as ComponentsConst from './textarea';
|
|
6
|
+
import OverviewComponent from './stories/overview.vue';
|
|
7
|
+
|
|
8
|
+
const argTypes = genArgsTypes(Component, ComponentsConst);
|
|
9
|
+
|
|
10
|
+
const meta = {
|
|
11
|
+
component: Component,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
args: {
|
|
14
|
+
modelValue: '',
|
|
15
|
+
},
|
|
16
|
+
argTypes,
|
|
17
|
+
} satisfies Meta<typeof Component>;
|
|
18
|
+
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Playground = {} satisfies Story;
|
|
22
|
+
|
|
23
|
+
export const Overview: Story = genOverviewStory({
|
|
24
|
+
args: {
|
|
25
|
+
hint: '',
|
|
26
|
+
rows: 5,
|
|
27
|
+
minHeight: 120,
|
|
28
|
+
expandable: false,
|
|
29
|
+
isError: false,
|
|
30
|
+
},
|
|
31
|
+
}, OverviewComponent);
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Определение параметров
|
|
3
|
+
*/
|
|
4
|
+
export interface Props {
|
|
5
|
+
modelValue: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Высота поля в строках, не работает в режиме **expandable**
|
|
11
|
+
*/
|
|
12
|
+
rows?: number;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Минимальная высота в px для режима **expandable**
|
|
16
|
+
*/
|
|
17
|
+
minHeight?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Автоматически изменять высоту при вводе текста
|
|
21
|
+
*/
|
|
22
|
+
expandable?: boolean;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
readonly?: boolean;
|
|
25
|
+
isError?: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Добавить к полю элемент с подсказкой, которая будет появляться при наведении
|
|
29
|
+
*/
|
|
30
|
+
hint?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Определение событий
|
|
35
|
+
*/
|
|
36
|
+
export interface Emits {
|
|
37
|
+
(e: 'update:modelValue', value?: string): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import Hint from '@/components/forms/hint/hint.vue';
|
|
4
|
+
import type { Props, Emits } from './textarea';
|
|
5
|
+
|
|
6
|
+
defineOptions({
|
|
7
|
+
inheritAttrs: false,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
11
|
+
rows: 5,
|
|
12
|
+
minHeight: 120,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<Emits>();
|
|
16
|
+
|
|
17
|
+
const value = computed({
|
|
18
|
+
get () {
|
|
19
|
+
return props.modelValue;
|
|
20
|
+
},
|
|
21
|
+
set (value) {
|
|
22
|
+
emit('update:modelValue', value);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<label
|
|
29
|
+
:class="{
|
|
30
|
+
['top-textarea']: true,
|
|
31
|
+
['top-textarea-' + name]: name,
|
|
32
|
+
['top-disabled']: disabled,
|
|
33
|
+
}"
|
|
34
|
+
>
|
|
35
|
+
<textarea
|
|
36
|
+
type="text"
|
|
37
|
+
:class="{
|
|
38
|
+
['top-forms-focusable']: !disabled,
|
|
39
|
+
['top-textarea_textarea']: true,
|
|
40
|
+
['top-textarea_textarea-expandable']: expandable,
|
|
41
|
+
['top-error']: isError,
|
|
42
|
+
}"
|
|
43
|
+
autocomplete="off_always"
|
|
44
|
+
:name="name"
|
|
45
|
+
:placeholder="placeholder"
|
|
46
|
+
:disabled="disabled"
|
|
47
|
+
:readonly="readonly"
|
|
48
|
+
:rows="!expandable ? rows : undefined"
|
|
49
|
+
:="$attrs"
|
|
50
|
+
v-model="value"
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
<div
|
|
54
|
+
v-if="expandable"
|
|
55
|
+
class="top-textarea_pseudoContent"
|
|
56
|
+
>
|
|
57
|
+
{{ value + ' ' }}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<Hint
|
|
61
|
+
v-if="hint"
|
|
62
|
+
class="top-textarea_hint"
|
|
63
|
+
:hint="hint"
|
|
64
|
+
v-top-tooltip
|
|
65
|
+
/>
|
|
66
|
+
</label>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<style module>
|
|
70
|
+
.top-textarea {
|
|
71
|
+
width: 180px;
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
position: relative;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.top-textarea_textarea {
|
|
78
|
+
background: var(--top-forms-background-color);
|
|
79
|
+
width: 100%;
|
|
80
|
+
padding: var(--top-forms-padding);
|
|
81
|
+
resize: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.top-textarea_textarea:hover {
|
|
85
|
+
background: var(--top-forms-background-color-hover);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.top-textarea_textarea:focus {
|
|
89
|
+
outline-color: var(--color-theme-75);
|
|
90
|
+
outline-offset: 0px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.top-textarea_textarea.top-textarea_textarea-expandable {
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: 100%;
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
position: absolute;
|
|
98
|
+
top: 0;
|
|
99
|
+
left: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.top-textarea_pseudoContent {
|
|
103
|
+
box-sizing: border-box;
|
|
104
|
+
min-height: v-bind(minHeight + 'px');
|
|
105
|
+
padding: var(--top-forms-padding);
|
|
106
|
+
font-size: 14px;
|
|
107
|
+
white-space: pre-wrap;
|
|
108
|
+
overflow-wrap: anywhere;
|
|
109
|
+
pointer-events: none;
|
|
110
|
+
opacity: 0;
|
|
111
|
+
z-index: -1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.top-textarea_hint {
|
|
115
|
+
position: absolute;
|
|
116
|
+
top: 2px;
|
|
117
|
+
right: 2px;
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
|
|
3
|
+
import { genArgsTypes, genOverviewStory } from '@/components/helpersStories';
|
|
4
|
+
import Component from './editArea.vue';
|
|
5
|
+
import * as ComponentsConst from './editArea';
|
|
6
|
+
import ReadMe from './stories/README.md?raw';
|
|
7
|
+
import OverviewComponent from './stories/overview.vue';
|
|
8
|
+
|
|
9
|
+
const argTypes = genArgsTypes(Component, ComponentsConst);
|
|
10
|
+
|
|
11
|
+
const meta = {
|
|
12
|
+
component: Component,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
args: {
|
|
15
|
+
modelValue: '',
|
|
16
|
+
},
|
|
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 = {} satisfies Story;
|
|
30
|
+
|
|
31
|
+
export const Overview: Story = genOverviewStory({
|
|
32
|
+
args: {
|
|
33
|
+
hint: '',
|
|
34
|
+
rows: 1,
|
|
35
|
+
minHeight: 20,
|
|
36
|
+
expandable: true,
|
|
37
|
+
isError: false,
|
|
38
|
+
},
|
|
39
|
+
}, OverviewComponent);
|
|
40
|
+
|
|
41
|
+
export const Expandable = {
|
|
42
|
+
args: {
|
|
43
|
+
title: 'Расширяемый editArea',
|
|
44
|
+
modelValue: `Люблю грозу в начале мая,
|
|
45
|
+
Когда весенний, первый гром,
|
|
46
|
+
как бы резвяся и играя,
|
|
47
|
+
Грохочет в небе голубом.
|
|
48
|
+
|
|
49
|
+
Гремят раскаты молодые,
|
|
50
|
+
Вот дождик брызнул, пыль летит,
|
|
51
|
+
Повисли перлы дождевые,
|
|
52
|
+
И солнце нити золотит.
|
|
53
|
+
|
|
54
|
+
С горы бежит поток проворный,
|
|
55
|
+
В лесу не молкнет птичий гам,
|
|
56
|
+
И гам лесной и шум нагорный -
|
|
57
|
+
Все вторит весело громам.`,
|
|
58
|
+
expandable: true,
|
|
59
|
+
attachToKeyboard: false,
|
|
60
|
+
isError: false,
|
|
61
|
+
},
|
|
62
|
+
} satisfies Story;
|
|
63
|
+
|
|
64
|
+
export const MobileVersion = {
|
|
65
|
+
args: {
|
|
66
|
+
modelValue: 'Мобильная версия editArea',
|
|
67
|
+
attachToKeyboard: true,
|
|
68
|
+
isError: false,
|
|
69
|
+
},
|
|
70
|
+
} satisfies Story;
|
|
71
|
+
|
|
72
|
+
export default meta;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Props as TextareaProps } from '@/components/forms/textarea/textarea';
|
|
2
|
+
|
|
3
|
+
export interface Props extends TextareaProps {
|
|
4
|
+
/**
|
|
5
|
+
* Поддерживает modelValue и **все другие** props компонента Textarea
|
|
6
|
+
*
|
|
7
|
+
* См. докуменатцию **Textarea**
|
|
8
|
+
*/
|
|
9
|
+
modelValue: string;
|
|
10
|
+
|
|
11
|
+
title?: string;
|
|
12
|
+
cancelText?: string;
|
|
13
|
+
submitText?: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Прикрепить к клавиатуре, прикрепляет форму к нижней части экрана
|
|
17
|
+
*/
|
|
18
|
+
attachToKeyboard?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface Emits {
|
|
22
|
+
(e: 'update:modelValue', value: string): void;
|
|
23
|
+
|
|
24
|
+
(e: 'cancel'): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, toRef, watch, computed } from 'vue';
|
|
3
|
+
import Button from '@/components/forms/button/button.vue';
|
|
4
|
+
import type { Props, Emits } from './editArea';
|
|
5
|
+
import Textarea from '@/components/forms/textarea/textarea.vue';
|
|
6
|
+
|
|
7
|
+
// TODO: добавить переменную top-forms-fixed-height и использовать ее при добавлении отступов у страницы
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
10
|
+
cancelText: 'Отмена',
|
|
11
|
+
submitText: 'Отправить',
|
|
12
|
+
expandable: true,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<Emits>();
|
|
16
|
+
|
|
17
|
+
const state = ref('');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Локальное значение modelValue, будет проброшено вверх только в случае отправки формы
|
|
21
|
+
*/
|
|
22
|
+
const localValue = ref(props.modelValue);
|
|
23
|
+
|
|
24
|
+
watch(toRef(props, 'modelValue'), () => {
|
|
25
|
+
localValue.value = props.modelValue;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const isChanged = computed(() => localValue.value !== props.modelValue);
|
|
29
|
+
|
|
30
|
+
const submit = (value: string) => {
|
|
31
|
+
emit('update:modelValue', value);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const cancel = () => {
|
|
35
|
+
emit('cancel');
|
|
36
|
+
|
|
37
|
+
// сброс введенного значения
|
|
38
|
+
localValue.value = props.modelValue;
|
|
39
|
+
};
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<div
|
|
44
|
+
:class="{
|
|
45
|
+
'top-editArea': true,
|
|
46
|
+
'top-editArea-attachedToKeyboard': attachToKeyboard,
|
|
47
|
+
}"
|
|
48
|
+
>
|
|
49
|
+
<div
|
|
50
|
+
v-if="title"
|
|
51
|
+
class="top-editArea_title"
|
|
52
|
+
>
|
|
53
|
+
{{ title }}
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div
|
|
57
|
+
:class="{
|
|
58
|
+
'top-editArea_form': true,
|
|
59
|
+
'top-error': isError,
|
|
60
|
+
'top-focus': state == 'focus',
|
|
61
|
+
}"
|
|
62
|
+
>
|
|
63
|
+
<Textarea
|
|
64
|
+
v-model="localValue"
|
|
65
|
+
:name="name"
|
|
66
|
+
:placeholder="placeholder"
|
|
67
|
+
:rows="rows"
|
|
68
|
+
:minHeight="minHeight"
|
|
69
|
+
:expandable="expandable"
|
|
70
|
+
:disabled="disabled"
|
|
71
|
+
:readonly="readonly"
|
|
72
|
+
:isError="isError"
|
|
73
|
+
:hint="hint"
|
|
74
|
+
class="top-editArea_element"
|
|
75
|
+
@focus="state = 'focus'"
|
|
76
|
+
@blur="state = ''"
|
|
77
|
+
@keyup.esc="cancel"
|
|
78
|
+
@keyup.ctrl.enter="submit(localValue)"
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
<div class="top-editArea_footer">
|
|
82
|
+
<Button
|
|
83
|
+
v-if="isChanged && (!attachToKeyboard || modelValue)"
|
|
84
|
+
class="top-editArea_button"
|
|
85
|
+
color="theme"
|
|
86
|
+
:icon="attachToKeyboard ? '': ''"
|
|
87
|
+
@click="cancel"
|
|
88
|
+
>
|
|
89
|
+
{{ attachToKeyboard ? '' : cancelText }}
|
|
90
|
+
</Button>
|
|
91
|
+
|
|
92
|
+
<Button
|
|
93
|
+
class="top-editArea_button"
|
|
94
|
+
:icon="attachToKeyboard ? '': ''"
|
|
95
|
+
@click="submit(localValue)"
|
|
96
|
+
>
|
|
97
|
+
{{ attachToKeyboard ? '' : submitText }}
|
|
98
|
+
</Button>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</template>
|
|
103
|
+
|
|
104
|
+
<style module>
|
|
105
|
+
.top-editArea {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
gap: 6px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.top-editArea_title {
|
|
112
|
+
font-size: 12px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.top-editArea_form {
|
|
116
|
+
background: var(--top-forms-background-color);
|
|
117
|
+
outline-color: var(--color-theme-75);
|
|
118
|
+
outline-offset: 0;
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.top-editArea_form:hover {
|
|
124
|
+
background: var(--top-forms-background-color-hover);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* textarea в EditArea */
|
|
128
|
+
.top-textarea {
|
|
129
|
+
width: 100%;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.top-editArea_element.top-textarea_textarea {
|
|
133
|
+
border: none;
|
|
134
|
+
outline: none;
|
|
135
|
+
animation: none;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* footer */
|
|
139
|
+
.top-editArea_footer {
|
|
140
|
+
padding: var(--top-forms-padding);
|
|
141
|
+
display: flex;
|
|
142
|
+
justify-content: flex-end;
|
|
143
|
+
gap: var(--top-forms-padding);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* attachedToKeyboard */
|
|
147
|
+
.top-editArea-attachedToKeyboard {
|
|
148
|
+
background: var(--top-forms-background-color);
|
|
149
|
+
margin-bottom: env(keyboard-inset-height, 0);
|
|
150
|
+
position: fixed;
|
|
151
|
+
bottom: 0;
|
|
152
|
+
right: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
z-index: 2;
|
|
155
|
+
gap: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.top-editArea-attachedToKeyboard .top-editArea_form {
|
|
159
|
+
border-radius: 0;
|
|
160
|
+
border: none;
|
|
161
|
+
border-top: 1px solid var(--top-forms-border-color);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.top-editArea-attachedToKeyboard .top-editArea_title {
|
|
165
|
+
border-top: 1px solid var(--color-line-2-opacity);
|
|
166
|
+
padding: var(--top-forms-padding);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.top-editArea-attachedToKeyboard .top-editArea_footer > [data-top-icon] {
|
|
170
|
+
border-radius: 100%;
|
|
171
|
+
}
|
|
172
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Компонент для ввода текста с кнопками Отправки и Отмены
|
|
2
|
+
|
|
3
|
+
Поддерживает все props компонента **Textarea**.
|
|
4
|
+
|
|
5
|
+
Работает с **modelValue**, обновляя его только при нажатии на кнопку **Отправки** или при нажатии **ctrl + enter**.
|
|
6
|
+
|
|
7
|
+
Полученное **modelValue** будет сохранено во внутренней переменной **localValue**. Чтобы его изменить извене необходимо установить
|
|
8
|
+
новое значения **modelValue**.
|
|
9
|
+
|
|
10
|
+
При нажатии кнопки **Отрпавки**, будет вызываться изменение **modelValue**.
|
|
11
|
+
|
|
12
|
+
При нажатии кнопки **Отмены**, содержимое textarea будет приведено к начальному состоянию, т.е. будет установлено **modelValue**,
|
|
13
|
+
также будет сгенерировано пользовательское событие **cancel**.
|
|
14
|
+
|
|
15
|
+
В режиме **attachToKeyboard** форма прикрепляется к низу экрана, чтобы всегда находиться рядом с клавиатурой.
|
|
16
|
+
Если **modelValue** пустое, то кнопка **Отмены** отображаться не будет, т.е. кнопка **Отмены** будет видна
|
|
17
|
+
только в режиме редактирвоания уже существующего значения.
|