@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.
Files changed (267) hide show
  1. package/.storybook/TopTheme.js +82 -0
  2. package/.storybook/TopThemeManager.js +44 -0
  3. package/.storybook/main.ts +43 -0
  4. package/.storybook/manager.ts +28 -0
  5. package/.storybook/preview-head.html +16 -0
  6. package/.storybook/preview.ts +48 -0
  7. package/.storybook/vue/coreDecorator.ts +19 -0
  8. package/.storybook/vue/vModelDecorator.ts +27 -0
  9. package/.vscode/extensions.json +11 -0
  10. package/.vscode/keybindings.example.json +121 -0
  11. package/.vscode/settings.json +46 -0
  12. package/Dockerfile +3 -0
  13. package/NPM.md +25 -0
  14. package/PUBLISH.md +18 -0
  15. package/README.md +19 -52
  16. package/STORYBOOK.md +27 -0
  17. package/USE_IN_PROJECT.md +29 -0
  18. package/build/afterBuild.sh +12 -0
  19. package/build/cssModules.ts +39 -0
  20. package/build/plugin/amdFix.ts +46 -0
  21. package/build/rollup.config.ts +18 -0
  22. package/nbproject/project.properties +11 -0
  23. package/nbproject/project.xml +9 -0
  24. package/package.json +68 -19
  25. package/public/README.md +63 -0
  26. package/src/components/common/common.ts +1 -0
  27. package/src/components/common/icon/icon.ts +4 -0
  28. package/src/components/common/icon/icon.vue +15 -0
  29. package/src/components/component.ts +133 -0
  30. package/src/components/forms/button/button.stories.ts +112 -0
  31. package/src/components/forms/button/button.ts +51 -0
  32. package/src/components/forms/button/button.vue +75 -0
  33. package/src/components/forms/button/stories/README.md +35 -0
  34. package/src/components/forms/button/stories/overview.vue +33 -0
  35. package/src/components/forms/button/style/button.css +124 -0
  36. package/src/components/forms/button/style/style-outline.css +42 -0
  37. package/src/components/forms/button/style/style-soft.css +31 -0
  38. package/src/components/forms/button/style/style-transparent.css +35 -0
  39. package/src/components/forms/checkbox/checkbox.stories.ts +33 -0
  40. package/src/components/forms/checkbox/checkbox.ts +23 -0
  41. package/src/components/forms/checkbox/checkbox.vue +135 -0
  42. package/src/components/forms/checkbox/stories/overview.vue +171 -0
  43. package/src/components/forms/controlLabel/controlLabel.stories.ts +38 -0
  44. package/src/components/forms/controlLabel/controlLabel.ts +4 -0
  45. package/src/components/forms/controlLabel/controlLabel.vue +48 -0
  46. package/src/components/forms/forms.ts +10 -0
  47. package/src/components/forms/helpers.ts +10 -0
  48. package/src/components/forms/hint/hint.stories.ts +46 -0
  49. package/src/components/forms/hint/hint.ts +8 -0
  50. package/src/components/forms/hint/hint.vue +32 -0
  51. package/src/components/forms/input/input.stories.ts +31 -0
  52. package/src/components/forms/input/input.ts +34 -0
  53. package/src/components/forms/input/input.vue +170 -0
  54. package/src/components/forms/input/stories/overview.vue +61 -0
  55. package/src/components/forms/inputDate/datepicker.css +233 -0
  56. package/src/components/forms/inputDate/datepicker.ts +101 -0
  57. package/src/components/forms/inputDate/inputDate.stories.ts +41 -0
  58. package/src/components/forms/inputDate/inputDate.ts +4 -0
  59. package/src/components/forms/inputDate/inputDate.vue +127 -0
  60. package/src/components/forms/inputDate/stories/overview.vue +35 -0
  61. package/src/components/forms/radio/radio.stories.ts +34 -0
  62. package/src/components/forms/radio/radio.ts +15 -0
  63. package/src/components/forms/radio/radio.vue +107 -0
  64. package/src/components/forms/radio/stories/overview.vue +79 -0
  65. package/src/components/forms/select/select.stories.ts +34 -0
  66. package/src/components/forms/select/select.ts +36 -0
  67. package/src/components/forms/select/select.vue +253 -0
  68. package/src/components/forms/select/stories/exampleOptions.ts +71 -0
  69. package/src/components/forms/select/stories/overview.vue +60 -0
  70. package/src/components/forms/switcher/stories/overview.vue +139 -0
  71. package/src/components/forms/switcher/switcher.stories.ts +33 -0
  72. package/src/components/forms/switcher/switcher.ts +22 -0
  73. package/src/components/forms/switcher/switcher.vue +113 -0
  74. package/src/components/forms/textarea/stories/overview.vue +62 -0
  75. package/src/components/forms/textarea/textarea.stories.ts +33 -0
  76. package/src/components/forms/textarea/textarea.ts +38 -0
  77. package/src/components/forms/textarea/textarea.vue +119 -0
  78. package/src/components/formsExt/editArea/editArea.stories.ts +72 -0
  79. package/src/components/formsExt/editArea/editArea.ts +25 -0
  80. package/src/components/formsExt/editArea/editArea.vue +172 -0
  81. package/src/components/formsExt/editArea/stories/README.md +17 -0
  82. package/src/components/formsExt/editArea/stories/overview.vue +66 -0
  83. package/src/components/formsExt/editInput/editInput.stories.ts +36 -0
  84. package/src/components/formsExt/editInput/editInput.ts +20 -0
  85. package/src/components/formsExt/editInput/editInput.vue +57 -0
  86. package/src/components/formsExt/editInput/stories/overview.vue +54 -0
  87. package/src/components/formsExt/formsExt.ts +3 -0
  88. package/src/components/formsExt/radioGroup/radioGroup.stories.ts +51 -0
  89. package/src/components/formsExt/radioGroup/radioGroup.ts +28 -0
  90. package/src/components/formsExt/radioGroup/radioGroup.vue +143 -0
  91. package/src/components/formsExt/radioGroup/stories/overview.vue +78 -0
  92. package/src/components/formsExt/radioGroup/styles/top-scrollBar.css +52 -0
  93. package/src/components/helper.js +10 -0
  94. package/src/components/helpersStories.ts +151 -0
  95. package/src/components/popup/lib/popup.globalEvents.js +205 -0
  96. package/src/components/popup/lib/popup.js +702 -0
  97. package/src/components/popup/lib/worker.globalEvents.js +78 -0
  98. package/src/components/popup/lib/worker.js +232 -0
  99. package/src/components/popup/popup/listItem.vue +42 -0
  100. package/src/components/popup/popup/opener.vue +74 -0
  101. package/src/components/popup/popup/popup.stories.ts +68 -0
  102. package/src/components/popup/popup/popup.ts +93 -0
  103. package/src/components/popup/popup/popup.vue +95 -0
  104. package/src/components/popup/popup/stories/README.md +34 -0
  105. package/src/components/popup/popup/stories/listItems.vue +44 -0
  106. package/src/components/popup/popup/stories/listSubItems.vue +52 -0
  107. package/src/components/popup/popup/stories/overview.vue +208 -0
  108. package/src/components/popup/popup/style/popup.css +243 -0
  109. package/src/components/popup/popup/style/popup.m.css +71 -0
  110. package/src/components/popup/popup/style/popup.pc.css +28 -0
  111. package/src/components/popup/popup.ts +3 -0
  112. package/src/components/popup/worker.ts +1 -0
  113. package/src/components/tabs/tabs/content.vue +24 -0
  114. package/src/components/tabs/tabs/stories/README.md +10 -0
  115. package/src/components/tabs/tabs/tab.vue +52 -0
  116. package/src/components/tabs/tabs/tabs.stories.ts +171 -0
  117. package/src/components/tabs/tabs/tabs.ts +22 -0
  118. package/src/components/tabs/tabs/tabs.vue +64 -0
  119. package/src/components/tabs/tabs.ts +3 -0
  120. package/src/core/base/Colors.stories.ts +15 -0
  121. package/src/core/base/Layout.stories.ts +15 -0
  122. package/src/core/base/Properties.stories.ts +15 -0
  123. package/src/core/base/base.mdx +21 -0
  124. package/src/core/core/core.ts +144 -0
  125. package/src/core/core/events.ts +54 -0
  126. package/src/core/core/options.ts +15 -0
  127. package/src/core/core/state.ts +44 -0
  128. package/src/core/directives/tooltip.ts +55 -0
  129. package/src/core/theme/Colors.stories.ts +15 -0
  130. package/src/core/theme/Properties.stories.ts +15 -0
  131. package/src/core/theme/theme.mdx +15 -0
  132. package/src/core/utils/date.ts +164 -0
  133. package/src/core/utils/device.ts +48 -0
  134. package/src/core/utils/dom.ts +185 -0
  135. 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
  136. 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
  137. 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
  138. package/src/docs/CSS/FAQ.mdx +43 -0
  139. 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
  140. 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
  141. 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
  142. 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
  143. package/src/docs/CSS//320/241/321/202/320/270/320/273/320/270.md +53 -0
  144. package/src/docs/CSS//320/241/321/202/320/270/320/273/320/270.mdx +4 -0
  145. 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
  146. package/src/docs/ROADMAP.md +17 -0
  147. package/src/docs/Roadmap.mdx +4 -0
  148. 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
  149. 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
  150. 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
  151. 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
  152. 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
  153. 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
  154. package/src/globals.d.ts +1 -0
  155. package/{icomoon → src/resources/icomoon}/demo-files/demo.css +161 -161
  156. package/{icomoon → src/resources/icomoon}/demo-files/demo.js +30 -30
  157. package/{icomoon → src/resources/icomoon}/demo.html +2945 -2945
  158. package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.svg +232 -232
  159. package/{icomoon → src/resources/icomoon}/style.css +647 -647
  160. package/src/resources/styles/core/colors.css +204 -0
  161. package/src/resources/styles/core/components.css +70 -0
  162. package/src/resources/styles/core/core.ts +10 -0
  163. package/src/resources/styles/core/forms/clear.css +19 -0
  164. package/src/resources/styles/core/forms/controls.css +20 -0
  165. package/src/resources/styles/core/forms/focusable.css +26 -0
  166. package/src/resources/styles/core/forms/forms.css +100 -0
  167. package/src/resources/styles/core/icon.css +58 -0
  168. package/src/resources/styles/core/layout.css +40 -0
  169. package/src/resources/styles/core/modifiers/as.css +9 -0
  170. package/src/resources/styles/core/modifiers/ellipsis.css +18 -0
  171. package/src/resources/styles/core/modifiers/modifiers.css +81 -0
  172. package/src/resources/styles/core/modifiers/only.css +19 -0
  173. package/src/resources/styles/core/select.css +16 -0
  174. package/src/resources/styles/jquery-ui.min.css +6 -0
  175. package/src/resources/styles/storybook.css +11 -0
  176. package/src/resources/styles/themes/dark/theme.css +139 -0
  177. package/src/resources/styles/themes/dark.ts +1 -0
  178. package/src/resources/styles/themes/light/theme.css +139 -0
  179. package/src/resources/styles/themes/light.ts +1 -0
  180. package/src/storybook/components/color.vue +45 -0
  181. package/src/storybook/components/colors.vue +34 -0
  182. package/src/storybook/components/icomoon.ts +38 -0
  183. package/src/storybook/components/properties.vue +82 -0
  184. package/src/storybook/resources/accessibility.png +0 -0
  185. package/src/storybook/resources/accessibility.svg +5 -0
  186. package/src/storybook/resources/addon-library.png +0 -0
  187. package/src/storybook/resources/assets.png +0 -0
  188. package/src/storybook/resources/context.png +0 -0
  189. package/src/storybook/resources/discord.svg +15 -0
  190. package/src/storybook/resources/docs.png +0 -0
  191. package/src/storybook/resources/figma-plugin.png +0 -0
  192. package/src/storybook/resources/github.svg +3 -0
  193. package/src/storybook/resources/share.png +0 -0
  194. package/src/storybook/resources/styling.png +0 -0
  195. package/src/storybook/resources/testing.png +0 -0
  196. package/src/storybook/resources/theming.png +0 -0
  197. package/src/storybook/resources/tutorials.svg +12 -0
  198. package/src/storybook/resources/youtube.svg +4 -0
  199. 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
  200. package/tsconfig.json +62 -0
  201. package/vite.config.ts +91 -0
  202. package/.chunks/datepicker-0b648b9f.es.js +0 -275
  203. package/.chunks/datepicker-0b648b9f.es.js.map +0 -1
  204. package/.chunks/datepicker-0e9a0541.amd.js +0 -234
  205. package/.chunks/datepicker-0e9a0541.amd.js.map +0 -1
  206. package/.chunks/forms-02202302.amd.js +0 -3
  207. package/.chunks/forms-02202302.amd.js.map +0 -1
  208. package/.chunks/forms-eb00d0c1.es.js +0 -946
  209. package/.chunks/forms-eb00d0c1.es.js.map +0 -1
  210. package/.chunks/popup-6f73b4b2.es.js +0 -700
  211. package/.chunks/popup-6f73b4b2.es.js.map +0 -1
  212. package/.chunks/popup-e1f34511.amd.js +0 -341
  213. package/.chunks/popup-e1f34511.amd.js.map +0 -1
  214. package/common/common.amd.js +0 -2
  215. package/common/common.amd.js.map +0 -1
  216. package/common/common.js +0 -2
  217. package/common/common.js.map +0 -1
  218. package/core/core.amd.js +0 -2
  219. package/core/core.amd.js.map +0 -1
  220. package/core/core.js +0 -6
  221. package/core/core.js.map +0 -1
  222. package/core.css +0 -1
  223. package/dark.css +0 -1
  224. package/forms/forms.amd.js +0 -2
  225. package/forms/forms.amd.js.map +0 -1
  226. package/forms/forms.js +0 -15
  227. package/forms/forms.js.map +0 -1
  228. package/forms/helpers.amd.js +0 -2
  229. package/forms/helpers.amd.js.map +0 -1
  230. package/forms/helpers.js +0 -9
  231. package/forms/helpers.js.map +0 -1
  232. package/forms.css +0 -1
  233. package/formsExt/formsExt.amd.js +0 -3
  234. package/formsExt/formsExt.amd.js.map +0 -1
  235. package/formsExt/formsExt.js +0 -152
  236. package/formsExt/formsExt.js.map +0 -1
  237. package/formsExt.css +0 -1
  238. package/light.css +0 -1
  239. package/popup/popup.amd.js +0 -3
  240. package/popup/popup.amd.js.map +0 -1
  241. package/popup/popup.js +0 -144
  242. package/popup/popup.js.map +0 -1
  243. package/popup/worker.amd.js +0 -2
  244. package/popup/worker.amd.js.map +0 -1
  245. package/popup/worker.js +0 -154
  246. package/popup/worker.js.map +0 -1
  247. package/popup.css +0 -1
  248. package/tabs/tabs.amd.js +0 -3
  249. package/tabs/tabs.amd.js.map +0 -1
  250. package/tabs/tabs.js +0 -97
  251. package/tabs/tabs.js.map +0 -1
  252. package/tabs.css +0 -1
  253. package/utils/date.amd.js +0 -2
  254. package/utils/date.amd.js.map +0 -1
  255. package/utils/date.js +0 -6
  256. package/utils/date.js.map +0 -1
  257. package/utils/device.amd.js +0 -2
  258. package/utils/device.amd.js.map +0 -1
  259. package/utils/device.js +0 -6
  260. package/utils/device.js.map +0 -1
  261. package/utils/dom.amd.js +0 -2
  262. package/utils/dom.amd.js.map +0 -1
  263. package/utils/dom.js +0 -64
  264. package/utils/dom.js.map +0 -1
  265. /package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.ttf +0 -0
  266. /package/{icomoon → src/resources/icomoon}/fonts/Topvisor-2.woff +0 -0
  267. /package/{icomoon → src/resources/icomoon}/selection.json +0 -0
@@ -0,0 +1,79 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+ import type { Props } from '../radio';
4
+ import Radio from '../radio.vue';
5
+
6
+ defineProps<Props>();
7
+
8
+ const modelValue1 = ref('Мужчина');
9
+ const modelValue2 = ref('Мужчина');
10
+ const modelValue3 = ref('Мужчина');
11
+ </script>
12
+
13
+ <template>
14
+ <div>
15
+ <h2>Радио кнопка:</h2>
16
+
17
+ <p><b>Ваш выбор:</b> {{ modelValue1 }}</p>
18
+
19
+ <Radio
20
+ :="$props"
21
+ v-model="modelValue1"
22
+ value="Мужчина"
23
+ >
24
+ Мужчина
25
+ </Radio>
26
+
27
+ <Radio
28
+ :="$props"
29
+ v-model="modelValue1"
30
+ value="Женщина"
31
+ >
32
+ Женщина
33
+ </Radio>
34
+
35
+ <h2>Радио кнопка disabled:</h2>
36
+
37
+ <p><b>Ваш выбор:</b> {{ modelValue2 }}</p>
38
+
39
+ <Radio
40
+ :="$props"
41
+ v-model="modelValue2"
42
+ value="Мужчина"
43
+ :disabled="true"
44
+ >
45
+ Мужчина
46
+ </Radio>
47
+
48
+ <Radio
49
+ :="$props"
50
+ v-model="modelValue2"
51
+ value="Женщина"
52
+ :disabled="true"
53
+ >
54
+ Женщина
55
+ </Radio>
56
+
57
+ <h2>Радио кнопка с описанием:</h2>
58
+
59
+ <p><b>Ваш выбор:</b> {{ modelValue3 }}</p>
60
+
61
+ <Radio
62
+ :="$props"
63
+ v-model="modelValue3"
64
+ value="Мужчина"
65
+ description="👨 Мужик!"
66
+ >
67
+ Мужчина
68
+ </Radio>
69
+
70
+ <Radio
71
+ :="$props"
72
+ v-model="modelValue3"
73
+ value="Женщина"
74
+ description="👩 Красавица! "
75
+ >
76
+ Женщина
77
+ </Radio>
78
+ </div>
79
+ </template>
@@ -0,0 +1,34 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+
3
+ import { genArgsTypes, genOverviewStory } from '@/components/helpersStories';
4
+ import Component from './select.vue';
5
+ import * as ComponentsConst from './select';
6
+ import { optionsMap } from './stories/exampleOptions';
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
+ argTypes,
15
+ args: {
16
+ modelValue: optionsMap.keys().next().value,
17
+ options: optionsMap,
18
+ },
19
+ } satisfies Meta<typeof Component>;
20
+
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const Playground = {} satisfies Story;
24
+
25
+ export const Overview: Story = genOverviewStory({
26
+ args: {
27
+ size: 's',
28
+ title: '',
29
+ addChanger: false,
30
+ isError: false,
31
+ },
32
+ }, OverviewComponent);
33
+
34
+ export default meta;
@@ -0,0 +1,36 @@
1
+ import type { Size } from '@/components/forms/helpers';
2
+ import { sizes } from '@/components/forms/helpers';
3
+
4
+ export interface Props {
5
+ modelValue: string;
6
+
7
+ /**
8
+ * Словарь или массив с объктами Option, по которому будут генерироваться элементы option
9
+ *
10
+ * Ключи словаря могут быть произвольными строковыми значениями
11
+ *
12
+ * Можно задать optiongroup, передав в option.children вложенный список options
13
+ */
14
+ options: Map<string, Option> | Option[];
15
+ name?: string;
16
+ disabled?: boolean;
17
+ icon?: string;
18
+ size?: Size;
19
+ addChanger?: boolean;
20
+ title?: string;
21
+ isError?: boolean;
22
+ }
23
+
24
+ export interface Emits {
25
+ (e: 'update:modelValue', value: Props['modelValue']): void;
26
+ }
27
+
28
+ export interface Option {
29
+ value: Props['modelValue'];
30
+ title: string;
31
+ icon?: string;
32
+ disabled?: boolean;
33
+ children?: Props['options'];
34
+ }
35
+
36
+ export { sizes };
@@ -0,0 +1,253 @@
1
+ <script setup lang="ts">
2
+ import { toRef, computed, watch } from 'vue';
3
+ import type { Props, Emits } from './select';
4
+
5
+ const props = withDefaults(defineProps<Props>(), {
6
+ size: 's',
7
+ });
8
+
9
+ const emit = defineEmits<Emits>();
10
+
11
+ const localValue = computed({
12
+ get() {
13
+ return props.modelValue;
14
+ },
15
+
16
+ set(value) {
17
+ emit('update:modelValue', value);
18
+ },
19
+ });
20
+
21
+ /**
22
+ * Иконка выбранного option
23
+ */
24
+ const optionIcon = computed(() => {
25
+ return optionByValue.value.get(localValue.value)?.icon;
26
+ });
27
+
28
+ /**
29
+ * Словарь с доступными options
30
+ */
31
+ const optionByValue = computed(() => {
32
+ const res = new Map();
33
+
34
+ props.options.forEach((option) => {
35
+ if (option.disabled) {
36
+ return;
37
+ }
38
+
39
+ if (option.children) {
40
+ option.children.forEach(subOption => {
41
+ if (subOption.disabled) {
42
+ return;
43
+ }
44
+
45
+ res.set(subOption.value, subOption);
46
+ });
47
+
48
+ return;
49
+ }
50
+
51
+ res.set(option.value, option);
52
+ });
53
+
54
+ return res;
55
+ });
56
+
57
+ /**
58
+ * Логика для обртаной своместимости:
59
+ * - null - заменить на первое доступное значение
60
+ * - undefined - заменить на первое доступное значение
61
+ */
62
+ watch([
63
+ toRef(props.modelValue),
64
+ optionByValue,
65
+ ], () => {
66
+ if ((localValue.value === null || localValue.value === undefined) && optionByValue.value.size) {
67
+ console.warn('Пожалуйста, не передавайте в компонент Select значения null и undefined');
68
+
69
+ localValue.value = optionByValue.value.keys().next().value;
70
+ }
71
+ }, { immediate: true });
72
+
73
+ /**
74
+ * Выбрать следующее доступное значение
75
+ */
76
+ const selectNextValue = () => {
77
+ const listEnabledValues = [...optionByValue.value.keys()];
78
+ const currentIndex = listEnabledValues.indexOf(localValue.value);
79
+ const nextIndex = (currentIndex + 1) % listEnabledValues.length;
80
+
81
+ localValue.value = listEnabledValues[nextIndex];
82
+ };
83
+ </script>
84
+
85
+ <template>
86
+ <label
87
+ :class="{
88
+ ['top-select']:true,
89
+ ['top-select-' + name]:name,
90
+ ['top-size_' + size]: true,
91
+ ['top-formsCaptionWrapper']: !!title,
92
+ ['top-select-error']: isError,
93
+ ['top-disabled']: disabled,
94
+ }"
95
+ :data-value="localValue"
96
+ :data-top-icon="icon"
97
+ :data-top-icon2="optionIcon"
98
+ >
99
+ <select
100
+ :class="{
101
+ ['top-forms-focusable']: !disabled,
102
+ ['top-select_select']: true,
103
+ ['top-select_arrow']: true,
104
+ ['top-error']: isError,
105
+ }"
106
+ :name="name"
107
+ :disabled="disabled"
108
+ v-model="localValue"
109
+ >
110
+ <template v-for="[_index, option] of options.entries()">
111
+ <optgroup
112
+ v-if="option.children"
113
+ :key="'group_' + option.value"
114
+ :label="option.title"
115
+ :disabled="option.disabled"
116
+ >
117
+ <option
118
+ v-for="[_index, subOption] of option.children.entries()"
119
+ :key="option.value"
120
+ :value="subOption.value"
121
+ :selected="subOption.value === localValue"
122
+ :disabled="subOption.disabled"
123
+ >
124
+ {{ subOption.title }}
125
+ </option>
126
+ </optgroup>
127
+
128
+ <option
129
+ v-else
130
+ :key="option.value"
131
+ :value="option.value"
132
+ :selected="option.value === localValue"
133
+ :disabled="option.disabled"
134
+ >
135
+ {{ option.title }}
136
+ </option>
137
+ </template>
138
+ </select>
139
+
140
+ <span
141
+ v-if="addChanger && optionByValue.size && !disabled"
142
+ class="top-changer"
143
+ @click="selectNextValue"
144
+ ></span>
145
+
146
+ <span
147
+ v-if="title"
148
+ class="top-formsCaption"
149
+ >
150
+ {{ title }}
151
+ </span>
152
+ </label>
153
+ </template>
154
+
155
+ <style module>
156
+ .top-select {
157
+ --top-icon-color: var(--color-text-3);
158
+ --top-icon2-color: var(--color-text-2);
159
+
160
+ align-items: center;
161
+ width: 180px;
162
+ max-width: 100%;
163
+ vertical-align: middle;
164
+ display: inline-flex;
165
+ }
166
+
167
+ .top-select-error {
168
+ --top-icon-color: var(--color-negative);
169
+ --top-icon2-color: var(--color-negative);
170
+ }
171
+
172
+ .top-select_select {
173
+ background-color: var(--top-forms-background-color);
174
+
175
+ /* для select вместо padding нужно использовать text-indent */
176
+ padding-left: var(--top-forms-padding);
177
+
178
+ /* если есть значки, добавить отступ на их ширину с учетом уже добавленного padding */
179
+ text-indent: calc(clamp(0px, calc(var(--top-icon-both-width) - var(--top-forms-padding)), calc(var(--top-icon-both-width) - var(--top-forms-padding))));
180
+
181
+ width: 100%;
182
+ height: var(--top-forms-base-height);
183
+ text-overflow: ellipsis;
184
+ white-space: nowrap;
185
+ flex-grow: 1;
186
+ overflow: hidden;
187
+ }
188
+
189
+ .top-select_select:focus {
190
+ outline-color: var(--color-theme-75);
191
+ outline-offset: 0;
192
+ }
193
+
194
+ .top-select_select:disabled {
195
+ background: var(--color-theme-50);
196
+ }
197
+
198
+ .top-select optgroup {
199
+ color: var(--color-text-1);
200
+ font-style: normal;
201
+ }
202
+
203
+ .top-select option {
204
+ background: var(--content-background-color);
205
+ color: var(--color-text-1);
206
+ }
207
+
208
+ /* хром не мерняет цвет для optgroup option, стили оставлены по умолчанию */
209
+ /*
210
+ .top-select optgroup:disabled,
211
+ .top-select optgroup option,
212
+ .top-select option:disabled {
213
+
214
+ }
215
+ */
216
+
217
+ /* https://bugzilla.mozilla.org/show_bug.cgi?id=1743066 */
218
+ @-moz-document url-prefix() {
219
+ .top-select_select {
220
+ text-indent: calc(clamp(0px, calc(var(--top-icon-both-width) - var(--top-forms-padding)), calc(var(--top-icon-both-width) - var(--top-forms-padding))) / 2);
221
+ }
222
+ }
223
+
224
+ @media only screen and (min-width: 900px) {
225
+ /* changer */
226
+ .top-changer {
227
+ cursor: pointer;
228
+ border-radius: 100%;
229
+ width: 0;
230
+ transform: translateX(-44px);
231
+ color: var(--color-text-secondary-2);
232
+ font-size: 16px;
233
+ line-height: 1;
234
+ display: none;
235
+ z-index: 2;
236
+ order: 4;
237
+ }
238
+
239
+ .top-changer:hover {
240
+ color: var(--color-primary);
241
+ }
242
+
243
+ .top-changer:after {
244
+ content: '';
245
+ background-color: var(--top-forms-background-color);
246
+ font-family: 'Topvisor-2';
247
+ }
248
+
249
+ *:hover > .top-changer {
250
+ display: block;
251
+ }
252
+ }
253
+ </style>
@@ -0,0 +1,71 @@
1
+ import type { Option } from '../select';
2
+
3
+ const optionsMap: Map<string, Option> = new Map();
4
+
5
+ optionsMap.set('folders', {
6
+ value: 'folders',
7
+ title: 'Папки',
8
+ icon: '',
9
+ });
10
+
11
+ optionsMap.set('even', {
12
+ value: 'even',
13
+ title: 'Четные',
14
+ });
15
+
16
+ optionsMap.set('odd', {
17
+ value: 'odd',
18
+ title: 'Нечетные (заблокировано)',
19
+ disabled: true,
20
+ });
21
+
22
+ const groupOptions: Map<string, Option> = new Map();
23
+
24
+ groupOptions.set('1', {
25
+ value: '1',
26
+ title: 'Один',
27
+ });
28
+
29
+ groupOptions.set('2', {
30
+ value: '2',
31
+ title: 'Два',
32
+ });
33
+
34
+ groupOptions.set('3', {
35
+ value: '3',
36
+ title: 'Три',
37
+ });
38
+
39
+ const groupOptions2: Map<string, Option> = new Map();
40
+
41
+ groupOptions2.set('3', {
42
+ value: '3',
43
+ title: 'Три',
44
+ });
45
+
46
+ groupOptions2.set('4', {
47
+ value: '4',
48
+ title: 'Четыре',
49
+ });
50
+
51
+ groupOptions2.set('5', {
52
+ value: '5',
53
+ title: 'Пять',
54
+ });
55
+
56
+ optionsMap.set('group_1', {
57
+ value: 'group_1',
58
+ title: 'Группа чисел 1',
59
+ children: groupOptions,
60
+ });
61
+
62
+ optionsMap.set('group_2', {
63
+ value: 'group_2',
64
+ title: 'Группа чисел 2',
65
+ disabled: true,
66
+ children: groupOptions2,
67
+ });
68
+
69
+ const optionsArray = Array.from(optionsMap.values());
70
+
71
+ export { optionsMap, optionsArray };
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+ import type { Props } from '../select';
4
+ import Select from '../select.vue';
5
+ import { Radio } from '@/components/forms/forms';
6
+ import { optionsMap, optionsArray } from './exampleOptions';
7
+
8
+ defineProps<Props>();
9
+
10
+ const options = ref(optionsMap);
11
+
12
+ const select1 = ref('');
13
+ const select2 = ref('folders');
14
+ const select3 = ref('folders');
15
+ const select4 = ref('folders');
16
+ </script>
17
+
18
+ <template>
19
+ <div>
20
+ <Radio v-model="options" :value="optionsMap">optionsMap</Radio>
21
+
22
+ <br>
23
+
24
+ <Radio v-model="options" :value="optionsArray">optionsArray</Radio>
25
+
26
+ <h2>Без значения</h2>
27
+
28
+ <Select
29
+ :="$props"
30
+ :options="options"
31
+ v-model="select1"
32
+ />
33
+
34
+ <h2>Со значением</h2>
35
+
36
+ <Select
37
+ :="$props"
38
+ :options="options"
39
+ v-model="select2"
40
+ />
41
+
42
+ <h2>Disabled</h2>
43
+
44
+ <Select
45
+ :="$props"
46
+ :options="options"
47
+ v-model="select3"
48
+ :disabled="true"
49
+ />
50
+
51
+ <h2>Со значком</h2>
52
+
53
+ <Select
54
+ :="$props"
55
+ :options="options"
56
+ v-model="select4"
57
+ icon=""
58
+ />
59
+ </div>
60
+ </template>
@@ -0,0 +1,139 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+ import type { Props } from '../switcher';
4
+ import Switcher from '../switcher.vue';
5
+
6
+ defineProps<Props>();
7
+
8
+ const switcher1 = ref(false);
9
+ const switcher2 = ref([]);
10
+ const switcher3 = ref(new Set<string>());
11
+ </script>
12
+
13
+ <template>
14
+ <div>
15
+ <h2>Переключатель:</h2>
16
+
17
+ <Switcher
18
+ :="$props"
19
+ :disabled="false"
20
+ >
21
+ Переключатель
22
+ </Switcher>
23
+
24
+ <Switcher
25
+ :="$props"
26
+ :modelValue="true"
27
+ :disabled="false"
28
+ >
29
+ Переключатель
30
+ </Switcher>
31
+
32
+ <h2>Переключатель disabled:</h2>
33
+
34
+ <Switcher
35
+ :="$props"
36
+ :disabled="true"
37
+ >
38
+ Переключатель
39
+ </Switcher>
40
+
41
+ <Switcher
42
+ :="$props"
43
+ :modelValue="true"
44
+ :disabled="true"
45
+ >
46
+ Переключатель
47
+ </Switcher>
48
+
49
+ <h2>Переключатель c описанием:</h2>
50
+
51
+ <Switcher
52
+ :="$props"
53
+ description="Этот переключатель выключен"
54
+ >
55
+ Переключатель
56
+ </Switcher>
57
+
58
+ <Switcher
59
+ :="$props"
60
+ :modelValue="true"
61
+ description="Этот переключатель включен"
62
+ >
63
+ Переключатель
64
+ </Switcher>
65
+
66
+ <h2>Поддерижваемые типы v-model</h2>
67
+
68
+ <h3>boolean</h3>
69
+
70
+ <p>
71
+ <b>Ваш выбор:</b> {{ switcher1 }}
72
+ </p>
73
+
74
+ <Switcher
75
+ :="$props"
76
+ v-model="switcher1"
77
+ />
78
+
79
+ <h3>string[]</h3>
80
+
81
+ <p>
82
+ <b>Ваш выбор:</b> {{ switcher2 }}
83
+ </p>
84
+
85
+ <Switcher
86
+ :="$props"
87
+ value="Яблоко"
88
+ v-model="switcher2"
89
+ >
90
+ Яблоко
91
+ </Switcher>
92
+
93
+ <Switcher
94
+ :="$props"
95
+ value="Груша"
96
+ v-model="switcher2"
97
+ >
98
+ Груша
99
+ </Switcher>
100
+
101
+ <Switcher
102
+ :="$props"
103
+ value="Банан"
104
+ v-model="switcher2"
105
+ >
106
+ Банан
107
+ </Switcher>
108
+
109
+ <h3>Set[]</h3>
110
+
111
+ <p>
112
+ <b>Ваш выбор:</b> {{ switcher3 }}
113
+ </p>
114
+
115
+ <Switcher
116
+ :="$props"
117
+ value="Яблоко"
118
+ v-model="switcher3"
119
+ >
120
+ Яблоко
121
+ </Switcher>
122
+
123
+ <Switcher
124
+ :="$props"
125
+ value="Груша"
126
+ v-model="switcher3"
127
+ >
128
+ Груша
129
+ </Switcher>
130
+
131
+ <Switcher
132
+ :="$props"
133
+ value="Банан"
134
+ v-model="switcher3"
135
+ >
136
+ Банан
137
+ </Switcher>
138
+ </div>
139
+ </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 './switcher.vue';
5
+ import * as ComponentsConst from './switcher';
6
+ import OverviewComponent from './stories/overview.vue';
7
+
8
+ const argTypes = genArgsTypes(Component, ComponentsConst, true);
9
+
10
+ const meta = {
11
+ component: Component,
12
+ tags: ['autodocs'],
13
+ argTypes,
14
+ args: {
15
+ modelValue: false,
16
+ },
17
+ } satisfies Meta<typeof Component>;
18
+
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ export const Playground = {
22
+ args: {
23
+ default: 'Переключатель',
24
+ },
25
+ } satisfies Story;
26
+
27
+ export const Overview: Story = genOverviewStory({
28
+ args: {
29
+ isError: false,
30
+ },
31
+ }, OverviewComponent);
32
+
33
+ export default meta;