@vc-shell/framework 1.0.38 → 1.0.39

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 (142) hide show
  1. package/components/atoms/vc-badge/vc-badge.stories.ts +27 -0
  2. package/components/atoms/vc-badge/vc-badge.vue +63 -0
  3. package/components/atoms/vc-button/vc-button.stories.ts +34 -0
  4. package/components/atoms/vc-button/vc-button.vue +219 -0
  5. package/components/atoms/vc-card/vc-card.vue +137 -0
  6. package/components/atoms/vc-checkbox/vc-checkbox.stories.ts +25 -0
  7. package/components/atoms/vc-checkbox/vc-checkbox.vue +130 -0
  8. package/components/atoms/vc-col/vc-col.vue +22 -0
  9. package/components/atoms/vc-container/vc-container.stories.ts +31 -0
  10. package/components/atoms/vc-container/vc-container.vue +220 -0
  11. package/components/atoms/vc-hint/vc-hint.stories.ts +23 -0
  12. package/components/atoms/vc-hint/vc-hint.vue +11 -0
  13. package/components/atoms/vc-icon/vc-icon.stories.ts +32 -0
  14. package/components/atoms/vc-icon/vc-icon.vue +36 -0
  15. package/components/atoms/vc-image/vc-image.stories.ts +40 -0
  16. package/components/atoms/vc-image/vc-image.vue +122 -0
  17. package/components/atoms/vc-info-row/vc-info-row.vue +42 -0
  18. package/components/atoms/vc-label/vc-label.stories.ts +23 -0
  19. package/components/atoms/vc-label/vc-label.vue +49 -0
  20. package/components/atoms/vc-link/vc-link.stories.ts +30 -0
  21. package/components/atoms/vc-link/vc-link.vue +46 -0
  22. package/components/atoms/vc-loading/vc-loading.vue +30 -0
  23. package/components/atoms/vc-progress/vc-progress.stories.ts +25 -0
  24. package/components/atoms/vc-progress/vc-progress.vue +65 -0
  25. package/components/atoms/vc-row/vc-row.vue +13 -0
  26. package/components/atoms/vc-status/vc-status.stories.ts +26 -0
  27. package/components/atoms/vc-status/vc-status.vue +78 -0
  28. package/components/atoms/vc-status-icon/vc-status-icon.vue +21 -0
  29. package/components/atoms/vc-switch/vc-switch.stories.ts +27 -0
  30. package/components/atoms/vc-switch/vc-switch.vue +100 -0
  31. package/components/atoms/vc-widget/vc-widget.vue +85 -0
  32. package/components/index.ts +43 -0
  33. package/components/molecules/vc-breadcrumbs/_internal/vc-breadcrumbs-item/vc-breadcrumbs-item.vue +103 -0
  34. package/components/molecules/vc-breadcrumbs/vc-breadcrumbs.stories.ts +39 -0
  35. package/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +21 -0
  36. package/components/molecules/vc-editor/vc-editor.vue +117 -0
  37. package/components/molecules/vc-file-upload/vc-file-upload.vue +134 -0
  38. package/components/molecules/vc-form/vc-form.stories.ts +23 -0
  39. package/components/molecules/vc-form/vc-form.vue +5 -0
  40. package/components/molecules/vc-input/vc-input.stories.ts +26 -0
  41. package/components/molecules/vc-input/vc-input.vue +443 -0
  42. package/components/molecules/vc-multivalue/vc-multivalue.vue +447 -0
  43. package/components/molecules/vc-notification/vc-notification.vue +101 -0
  44. package/components/molecules/vc-pagination/vc-pagination.stories.ts +23 -0
  45. package/components/molecules/vc-pagination/vc-pagination.vue +169 -0
  46. package/components/molecules/vc-rating/vc-rating.stories.ts +23 -0
  47. package/components/molecules/vc-rating/vc-rating.vue +77 -0
  48. package/components/molecules/vc-select/vc-select.stories.ts +25 -0
  49. package/components/molecules/vc-select/vc-select.vue +402 -0
  50. package/components/molecules/vc-slider/vc-slider.vue +106 -0
  51. package/components/molecules/vc-textarea/vc-textarea.stories.ts +23 -0
  52. package/components/molecules/vc-textarea/vc-textarea.vue +155 -0
  53. package/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +146 -0
  54. package/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +148 -0
  55. package/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +157 -0
  56. package/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +110 -0
  57. package/components/organisms/vc-app/vc-app.stories.ts +75 -0
  58. package/components/organisms/vc-app/vc-app.vue +171 -0
  59. package/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +126 -0
  60. package/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue +223 -0
  61. package/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +67 -0
  62. package/components/organisms/vc-blade/vc-blade.stories.ts +46 -0
  63. package/components/organisms/vc-blade/vc-blade.vue +87 -0
  64. package/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +292 -0
  65. package/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue +123 -0
  66. package/components/organisms/vc-gallery/_internal/vc-gallery-preview/vc-gallery-preview.vue +93 -0
  67. package/components/organisms/vc-gallery/vc-gallery.vue +186 -0
  68. package/components/organisms/vc-login-form/vc-login-form.stories.ts +55 -0
  69. package/components/organisms/vc-login-form/vc-login-form.vue +48 -0
  70. package/components/organisms/vc-popup/vc-popup.stories.ts +23 -0
  71. package/components/organisms/vc-popup/vc-popup.vue +97 -0
  72. package/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +113 -0
  73. package/components/organisms/vc-table/_internal/vc-table-counter/vc-table-counter.vue +29 -0
  74. package/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue +152 -0
  75. package/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue +272 -0
  76. package/components/organisms/vc-table/vc-table.stories.ts +99 -0
  77. package/components/organisms/vc-table/vc-table.vue +638 -0
  78. package/core/api/index.ts +1 -0
  79. package/core/api/platform.ts +8332 -0
  80. package/core/composables/index.ts +8 -0
  81. package/core/composables/useAutosave/index.ts +57 -0
  82. package/core/composables/useFunctions/debounce.ts +18 -0
  83. package/core/composables/useFunctions/delay.ts +7 -0
  84. package/core/composables/useFunctions/index.ts +21 -0
  85. package/core/composables/useFunctions/once.ts +14 -0
  86. package/core/composables/useFunctions/sleep.ts +4 -0
  87. package/core/composables/useFunctions/throttle.ts +17 -0
  88. package/core/composables/useI18n/index.ts +28 -0
  89. package/core/composables/useLogger/index.ts +24 -0
  90. package/core/composables/useNotifications/index.ts +116 -0
  91. package/core/composables/usePermissions/index.ts +32 -0
  92. package/core/composables/useSettings/index.ts +36 -0
  93. package/core/composables/useUser/index.ts +266 -0
  94. package/core/directives/autofocus/index.ts +9 -0
  95. package/core/directives/click-outside/index.ts +21 -0
  96. package/core/directives/index.ts +4 -0
  97. package/core/directives/loading/index.ts +28 -0
  98. package/core/directives/permissions/index.ts +20 -0
  99. package/core/plugins/index.ts +1 -0
  100. package/core/plugins/validation/index.ts +2 -0
  101. package/core/plugins/validation/rules.ts +196 -0
  102. package/core/types/index.ts +92 -0
  103. package/core/utilities/camelToSnake.ts +7 -0
  104. package/core/utilities/index.ts +1 -0
  105. package/dist/core/composables/useNotifications/index.d.ts +1 -1
  106. package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
  107. package/dist/core/composables/useUser/index.d.ts +2 -2
  108. package/dist/core/composables/useUser/index.d.ts.map +1 -1
  109. package/dist/core/plugins/validation/index.d.ts.map +1 -1
  110. package/dist/core/types/index.d.ts +1 -1
  111. package/dist/core/types/index.d.ts.map +1 -1
  112. package/dist/framework.js +70 -97
  113. package/dist/framework.js.map +1 -1
  114. package/dist/shared/app-switcher/composables/useAppSwitcher/index.d.ts +1 -1
  115. package/dist/shared/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -1
  116. package/dist/shared/app-switcher/index.d.ts +2 -2
  117. package/dist/shared/app-switcher/index.d.ts.map +1 -1
  118. package/dist/shared/blade-navigation/composables/useBladeNavigation/index.d.ts +1 -1
  119. package/dist/shared/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
  120. package/dist/shared/blade-navigation/types/index.d.ts +1 -1
  121. package/dist/shared/blade-navigation/types/index.d.ts.map +1 -1
  122. package/dist/style.css +1 -1
  123. package/dist/tsconfig.tsbuildinfo +1 -0
  124. package/dist/vite.config.d.ts.map +1 -1
  125. package/package.json +11 -8
  126. package/shared/app-switcher/components/index.ts +1 -0
  127. package/shared/app-switcher/components/vc-app-switcher/vc-app-switcher.vue +90 -0
  128. package/shared/app-switcher/composables/index.ts +1 -0
  129. package/shared/app-switcher/composables/useAppSwitcher/index.ts +54 -0
  130. package/shared/app-switcher/index.ts +14 -0
  131. package/shared/assets/components/assets-details/assets-details.vue +138 -0
  132. package/shared/assets/components/index.ts +1 -0
  133. package/shared/assets/index.ts +19 -0
  134. package/shared/assets/locales/en.json +29 -0
  135. package/shared/assets/locales/index.ts +2 -0
  136. package/shared/blade-navigation/components/index.ts +1 -0
  137. package/shared/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +84 -0
  138. package/shared/blade-navigation/composables/index.ts +1 -0
  139. package/shared/blade-navigation/composables/useBladeNavigation/index.ts +216 -0
  140. package/shared/blade-navigation/index.ts +15 -0
  141. package/shared/blade-navigation/types/index.ts +52 -0
  142. package/shared/index.ts +16 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Badge component.
3
+ * @author Iurii A Taranov <me@flanker72.ru>
4
+ */
5
+ import { Story } from "@storybook/vue3";
6
+ import VcBadge from "./vc-badge.vue";
7
+
8
+ export default {
9
+ title: "atoms/vc-badge",
10
+ component: VcBadge,
11
+ };
12
+
13
+ const Template: Story = (args) => ({
14
+ components: { VcBadge },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: '<vc-badge v-bind="args">42</vc-badge>',
19
+ });
20
+
21
+ export const Badge = Template.bind({});
22
+ Badge.storyName = "vc-badge";
23
+ Badge.args = {
24
+ active: false,
25
+ disabled: false,
26
+ clickable: true,
27
+ };
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <div
3
+ class="inline-block rounded-[var(--badge-border-radius)] py-1 px-2 text-base font-normal bg-[color:var(--badge-background-color)] text-[color:var(--badge-text-color)] border border-solid border-[color:var(--badge-border-color)] transition duration-200"
4
+ :class="{
5
+ 'bg-[color:var(--badge-background-color-active)] text-[color:var(--badge-text-color-active)] border-[color:var(--badge-border-color-active)]':
6
+ active,
7
+ 'cursor-pointer hover:bg-[color:var(--badge-background-color-active)] hover:text-[color:var(--badge-text-color-hover)] hover:border-[color:var(--badge-border-color-hover)]':
8
+ clickable,
9
+ 'cursor-not-allowed bg-[color:var(--badge-background-color-disabled)] text-[color:var(--badge-text-color-disabled)] border-[color:var(--badge-border-color-disabled)] hover:bg-[color:var(--badge-background-color-disabled)] hover:text-[color:var(--badge-text-color-disabled)] hover:border-[color:var(--badge-border-color-disabled)]':
10
+ disabled,
11
+ }"
12
+ @click="onClick"
13
+ >
14
+ <slot></slot>
15
+ </div>
16
+ </template>
17
+
18
+ <script lang="ts" setup>
19
+ const props = defineProps({
20
+ active: {
21
+ type: Boolean,
22
+ default: false,
23
+ },
24
+
25
+ disabled: {
26
+ type: Boolean,
27
+ default: false,
28
+ },
29
+
30
+ clickable: {
31
+ type: Boolean,
32
+ default: true,
33
+ },
34
+ });
35
+ const emit = defineEmits(["click"]);
36
+
37
+ function onClick(): void {
38
+ if (props.clickable && !props.disabled) {
39
+ emit("click");
40
+ }
41
+ }
42
+ </script>
43
+
44
+ <style lang="scss">
45
+ :root {
46
+ --badge-background-color: #ffffff;
47
+ --badge-background-color-hover: #fafafa;
48
+ --badge-background-color-active: #fafafa;
49
+ --badge-background-color-disabled: #f2f2f2;
50
+
51
+ --badge-text-color: #455668;
52
+ --badge-text-color-hover: #3b4959;
53
+ --badge-text-color-active: #3b4959;
54
+ --badge-text-color-disabled: #8296ab;
55
+
56
+ --badge-border-radius: 35px;
57
+
58
+ --badge-border-color: #a1bfd4;
59
+ --badge-border-color-hover: #8fb3cc;
60
+ --badge-border-color-active: #8fb3cc;
61
+ --badge-border-color-disabled: #b2cbdc;
62
+ }
63
+ </style>
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Button component.
3
+ * @author Iurii A Taranov <me@flanker72.ru>
4
+ */
5
+ import { Story } from "@storybook/vue3";
6
+ import VcButton from "./vc-button.vue";
7
+
8
+ export default {
9
+ title: "atoms/vc-button",
10
+ component: VcButton,
11
+ argTypes: {
12
+ variant: {
13
+ options: ["primary", "secondary", "special"],
14
+ control: { type: "radio" },
15
+ },
16
+ },
17
+ };
18
+
19
+ const Template: Story = (args) => ({
20
+ components: { VcButton },
21
+ setup() {
22
+ return { args };
23
+ },
24
+ template: '<vc-button v-bind="args">I am a button</vc-button>',
25
+ });
26
+
27
+ export const Button = Template.bind({});
28
+ Button.storyName = "vc-button";
29
+ Button.args = {
30
+ icon: "fas fa-star",
31
+ variant: "primary",
32
+ disabled: false,
33
+ small: false,
34
+ };
@@ -0,0 +1,219 @@
1
+ <template>
2
+ <button
3
+ class="vc-button"
4
+ :class="[
5
+ `vc-button_${variant}`,
6
+ {
7
+ 'vc-button_small': small,
8
+ 'vc-button_outline': outline,
9
+ 'vc-button_selected': selected,
10
+ },
11
+ ]"
12
+ @click="onClick"
13
+ :disabled="disabled"
14
+ >
15
+ <VcIcon
16
+ v-if="icon"
17
+ class="vc-button__icon"
18
+ :icon="icon"
19
+ :size="small ? 'xs' : 's'"
20
+ ></VcIcon>
21
+ <span v-if="$slots['default']" class="vc-button__title">
22
+ <slot></slot>
23
+ </span>
24
+ </button>
25
+ </template>
26
+
27
+ <script lang="ts" setup>
28
+ import { VcIcon } from "@/components";
29
+
30
+ const props = defineProps({
31
+ icon: {
32
+ type: String,
33
+ default: undefined,
34
+ },
35
+
36
+ variant: {
37
+ type: String,
38
+ enum: ["primary", "secondary", "special", "danger", "widget", "onlytext"],
39
+ default: "primary",
40
+ },
41
+
42
+ disabled: {
43
+ type: Boolean,
44
+ default: false,
45
+ },
46
+
47
+ small: {
48
+ type: Boolean,
49
+ default: false,
50
+ },
51
+
52
+ outline: {
53
+ type: Boolean,
54
+ default: false,
55
+ },
56
+
57
+ selected: {
58
+ type: Boolean,
59
+ default: false,
60
+ },
61
+ });
62
+
63
+ const emit = defineEmits(["click"]);
64
+
65
+ function onClick(e: Event): void {
66
+ if (!props.disabled) {
67
+ e.preventDefault();
68
+ emit("click", e);
69
+ }
70
+ }
71
+ </script>
72
+
73
+ <style lang="scss">
74
+ :root {
75
+ --button-primary-background-color: #41afe6;
76
+ --button-primary-background-color-hover: #319ed4;
77
+ --button-primary-background-color-active: #319ed4;
78
+ --button-primary-background-color-disabled: #a9ddf6;
79
+
80
+ --button-primary-text-color: #ffffff;
81
+ --button-primary-text-color-hover: #ffffff;
82
+ --button-primary-text-color-active: #ffffff;
83
+ --button-primary-text-color-disabled: #ffffff;
84
+
85
+ --button-secondary-background-color: #ffffff;
86
+ --button-secondary-background-color-hover: #ffffff;
87
+ --button-secondary-background-color-active: #ffffff;
88
+ --button-secondary-background-color-disabled: #ffffff;
89
+
90
+ --button-secondary-border-color: #43b0e6;
91
+ --button-secondary-border-color-hover: #319ed4;
92
+ --button-secondary-border-color-active: #319ed4;
93
+ --button-secondary-border-color-disabled: #a9ddf6;
94
+
95
+ --button-secondary-text-color: #43b0e6;
96
+ --button-secondary-text-color-hover: #319ed4;
97
+ --button-secondary-text-color-active: #319ed4;
98
+ --button-secondary-text-color-disabled: #a9ddf6;
99
+
100
+ --button-special-background-color: #f89406;
101
+ --button-special-background-color-hover: #eb8b03;
102
+ --button-special-background-color-active: #eb8b03;
103
+ --button-special-background-color-disabled: #fed498;
104
+
105
+ --button-danger-background-color: #ff4a4a;
106
+ --button-danger-background-color-hover: #d73a3a;
107
+ --button-danger-background-color-active: #d73a3a;
108
+ --button-danger-background-color-disabled: #ff5e5e;
109
+
110
+ --button-special-text-color: #ffffff;
111
+ --button-special-text-color-hover: #ffffff;
112
+ --button-special-text-color-active: #ffffff;
113
+ --button-special-text-color-disabled: #ffffff;
114
+
115
+ --button-widget-background-color: #ffffff;
116
+ --button-widget-background-color-hover: #f2faff;
117
+ --button-widget-background-color-active: #eaf6ff;
118
+ --button-widget-background-color-disabled: #fafafa;
119
+
120
+ --button-widget-border-color: #eaedf3;
121
+ --button-widget-border-color-hover: #d3e2ec;
122
+ --button-widget-border-color-active: #deecf4;
123
+
124
+ --button-border-radius: 3px;
125
+ --button-padding: 14px;
126
+ --button-padding-small: 12px;
127
+ --button-height: 36px;
128
+ --button-height-small: 28px;
129
+ }
130
+
131
+ $variants: primary, secondary, special, danger, widget;
132
+
133
+ .vc-button {
134
+ @apply inline-flex items-center font-medium text-sm cursor-pointer box-border transition duration-200 rounded-[var(--button-border-radius)] px-[var(--button-padding)] h-[var(--button-height)];
135
+
136
+ &__icon + &__title {
137
+ @apply ml-2;
138
+ }
139
+
140
+ @each $variant in $variants {
141
+ &_#{$variant} {
142
+ @apply bg-[color:var(--button-#{$variant}-background-color)]
143
+ text-left
144
+ text-[color:var(--button-#{$variant}-text-color)]
145
+ border border-solid border-[color:var(--button-#{$variant}-background-color)]
146
+ hover:bg-[color:var(--button-#{$variant}-background-color-hover)]
147
+ hover:text-[color:var(--button-#{$variant}-text-color-hover)]
148
+ hover:border-[color:var(--button-#{$variant}-background-color-hover)]
149
+ focus:bg-[color:var(--button-#{$variant}-background-color-active)]
150
+ focus:text-[color:var(--button-#{$variant}-text-color-active)]
151
+ focus:bg-[color:var(--button-#{$variant}-background-color-active)]
152
+ disabled:cursor-not-allowed
153
+ disabled:bg-[color:var(--button-#{$variant}-background-color-disabled)]
154
+ disabled:text-[color:var(--button-#{$variant}-text-color-disabled)]
155
+ disabled:border-[color:var(--button-#{$variant}-background-color-disabled)];
156
+ }
157
+ }
158
+
159
+ &_widget {
160
+ @apply h-auto border-[color:var(--button-widget-border-color)]
161
+ shadow-[1px_4px_10px_rgba(197,206,214,0.24)]
162
+ rounded-[4px]
163
+ p-[15px]
164
+ border-[color:var(--button-widget-background-color)]
165
+ hover:bg-[color:var(--button-widget-background-color-hover)]
166
+ focus:bg-[color:var(--button-widget-background-color-active)]
167
+ focus:border-[color:var(--button-widget-border-color-active)]
168
+ disabled:cursor-not-allowed
169
+ disabled:bg-[color:var(--button-widget-background-color-disabled)]
170
+ disabled:border-[color:var(--button-widget-background-color-disabled)];
171
+
172
+ .vc-button__icon {
173
+ @apply text-[30px] text-[color:#a9bfd2];
174
+ }
175
+ }
176
+
177
+ &_small {
178
+ @apply h-[var(--button-height-small)]
179
+ px-[var(--button-padding-small)]
180
+ font-normal
181
+ text-xs;
182
+
183
+ .vc-button__icon + .vc-button__title {
184
+ @apply ml-1;
185
+ }
186
+ }
187
+
188
+ &_outline {
189
+ @apply bg-transparent
190
+ text-[color:var(--button-secondary-text-color)]
191
+ border-[color:var(--button-secondary-border-color)]
192
+ hover:text-[color:var(--button-secondary-text-color-hover)]
193
+ hover:border-[color:var(--button-secondary-border-color-hover)]
194
+ hover:bg-transparent
195
+ focus:text-[color:var(--button-secondary-text-color-hover)]
196
+ focus:border-[color:var(--button-secondary-border-color-active)]
197
+ focus:bg-transparent
198
+ disabled:cursor-not-allowed
199
+ disabled:text-[color:var(--button-secondary-text-color-disabled)]
200
+ disabled:border-[color:var(--button-secondary-border-color-disabled)]
201
+ disabled:bg-transparent;
202
+ }
203
+
204
+ &_onlytext {
205
+ @apply text-[color:var(--button-secondary-text-color)]
206
+ p-0 border-none bg-transparent h-auto
207
+ hover:bg-transparent
208
+ hover:text-[color:var(--button-secondary-text-color-hover)]
209
+ focus:bg-transparent
210
+ focus:text-[color:var(--button-secondary-text-color-hover)];
211
+ }
212
+
213
+ &_selected {
214
+ &.vc-button_widget {
215
+ @apply bg-[color:var(--button-widget-background-color-hover)];
216
+ }
217
+ }
218
+ }
219
+ </style>
@@ -0,0 +1,137 @@
1
+ <template>
2
+ <div
3
+ class="vc-card"
4
+ :class="[{ 'vc-card_collapsable': isCollapsable }, `vc-card_${variant}`]"
5
+ >
6
+ <div class="vc-card__header" v-if="header" @click="onHeaderClick">
7
+ <VcIcon v-if="icon" class="vc-card__icon" :icon="icon" size="xl"></VcIcon>
8
+ <div class="vc-card__title">{{ header }}</div>
9
+ <div v-if="$slots['actions']" class="vc-card__actions">
10
+ <slot name="actions"></slot>
11
+ </div>
12
+ <VcIcon
13
+ v-if="isCollapsable"
14
+ class="vc-card__collapse"
15
+ :icon="`fas fa-chevron-${isCollapsedInternal ? 'down' : 'up'}`"
16
+ size="s"
17
+ ></VcIcon>
18
+ </div>
19
+ <transition name="fade">
20
+ <div
21
+ :class="[{ 'vc-flex': fill }, 'vc-card__body']"
22
+ v-show="!isCollapsedInternal"
23
+ >
24
+ <slot></slot>
25
+ </div>
26
+ </transition>
27
+ </div>
28
+ </template>
29
+
30
+ <script lang="ts" setup>
31
+ import { ref } from "vue";
32
+ const props = defineProps({
33
+ header: {
34
+ type: String,
35
+ default: undefined,
36
+ },
37
+
38
+ icon: {
39
+ type: String,
40
+ default: undefined,
41
+ },
42
+
43
+ isCollapsable: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+
48
+ isCollapsed: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+
53
+ fill: {
54
+ type: Boolean,
55
+ default: false,
56
+ },
57
+
58
+ variant: {
59
+ type: String,
60
+ enum: ["default", "success", "danger"],
61
+ default: "default",
62
+ },
63
+ });
64
+ const emit = defineEmits(["header:click", "state:collapsed"]);
65
+ const isCollapsedInternal = ref(props.isCollapsed);
66
+
67
+ function onHeaderClick() {
68
+ if (props.isCollapsable) {
69
+ isCollapsedInternal.value = !isCollapsedInternal.value;
70
+ emit("state:collapsed", isCollapsedInternal.value);
71
+ }
72
+ emit("header:click");
73
+ }
74
+ </script>
75
+
76
+ <style lang="scss">
77
+ :root {
78
+ --card-background: #ffffff;
79
+ --card-border-radius: 6px;
80
+ --card-box-shadow: 1px 1px 7px rgba(126, 142, 157, 0.15);
81
+ --card-header-background: #f4f8fb;
82
+ --card-header-color: #83a3be;
83
+
84
+ --card-header-background-success: #e9f7df;
85
+ --card-header-background-danger: #ffe6e6;
86
+
87
+ --card-header-color-success: #99c17a;
88
+ --card-header-color-danger: #f34747;
89
+ }
90
+
91
+ $variants: success, danger;
92
+
93
+ .vc-card {
94
+ @apply bg-[color:var(--card-background)] border
95
+ border-[color:#eef0f2] border-solid box-border
96
+ shadow-[1px_1px_7px_rgba(126,142,157,0.15)]
97
+ rounded-[var(--card-border-radius)] overflow-hidden
98
+ flex-grow flex flex-col;
99
+
100
+ &__header {
101
+ @apply bg-[color:var(--card-header-background)] px-4 py-3 flex items-center content-between w-full box-border;
102
+ }
103
+
104
+ &_collapsable &__header {
105
+ @apply cursor-pointer;
106
+ }
107
+
108
+ &__title {
109
+ @apply uppercase flex-grow
110
+ text-[color:var(--card-header-color)]
111
+ text-base font-bold uppercase;
112
+ }
113
+
114
+ &__icon {
115
+ @apply text-[color:var(--card-header-color)] mr-3;
116
+ }
117
+
118
+ &__collapse {
119
+ @apply text-[color:var(--card-header-color)] ml-3;
120
+ }
121
+
122
+ &__body {
123
+ @apply flex-grow box-border;
124
+ }
125
+
126
+ @each $variant in $variants {
127
+ &_#{$variant} {
128
+ .vc-card__header {
129
+ @apply bg-[color:var(--card-header-background-#{$variant})];
130
+ }
131
+ .vc-card__title {
132
+ @apply text-[color:var(--card-header-color-#{$variant})];
133
+ }
134
+ }
135
+ }
136
+ }
137
+ </style>
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Checkbox component.
3
+ * @author Iurii A Taranov <me@flanker72.ru>
4
+ */
5
+ import { Story } from "@storybook/vue3";
6
+ import VcCheckbox from "./vc-checkbox.vue";
7
+
8
+ export default {
9
+ title: "atoms/vc-checkbox",
10
+ component: VcCheckbox,
11
+ };
12
+
13
+ const Template: Story = (args) => ({
14
+ components: { VcCheckbox },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: '<vc-checkbox v-bind="args"></vc-checkbox>',
19
+ });
20
+
21
+ export const Checkbox = Template.bind({});
22
+ Checkbox.storyName = "vc-checkbox";
23
+ Checkbox.args = {
24
+ checked: false,
25
+ };
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <div class="vc-checkbox" :class="{ 'vc-checkbox_disabled': disabled }">
3
+ <label class="vc-checkbox__label">
4
+ <input
5
+ type="checkbox"
6
+ class="vc-checkbox__input"
7
+ :checked="modelValue"
8
+ :disabled="disabled"
9
+ @change="onChange"
10
+ />
11
+ <span class="vc-checkbox__checkmark"></span>
12
+ <span v-if="$slots['default']" class="ml-2">
13
+ <slot></slot>
14
+ </span>
15
+ <span
16
+ v-if="required"
17
+ class="text-[color:var(--checkbox-required-color)] ml-1"
18
+ >*</span
19
+ >
20
+ </label>
21
+
22
+ <slot v-if="errorMessage" name="error">
23
+ <VcHint class="vc-checkbox__error mt-1">
24
+ {{ errorMessage }}
25
+ </VcHint>
26
+ </slot>
27
+ </div>
28
+ </template>
29
+
30
+ <script lang="ts" setup>
31
+ import { watch } from "vue";
32
+
33
+ const props = defineProps({
34
+ modelValue: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+
39
+ disabled: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
43
+
44
+ required: {
45
+ type: Boolean,
46
+ default: false,
47
+ },
48
+
49
+ name: {
50
+ type: String,
51
+ default: "Field",
52
+ },
53
+
54
+ errorMessage: {
55
+ type: String,
56
+ default: undefined
57
+ }
58
+ });
59
+ const emit = defineEmits(["update:modelValue"]);
60
+
61
+ watch(
62
+ () => props.modelValue,
63
+ (value) => {
64
+ emit("update:modelValue", value);
65
+ }
66
+ );
67
+
68
+ // Handle input event to propertly validate value and emit changes
69
+ function onChange(e: InputEvent) {
70
+ const newValue = (e.target as HTMLInputElement).checked;
71
+ emit("update:modelValue", newValue);
72
+ }
73
+ </script>
74
+
75
+ <style lang="scss">
76
+ :root {
77
+ --checkbox-size: 14px;
78
+ --checkbox-border-radius: 2px;
79
+ --checkbox-background-color: #ffffff;
80
+ --checkbox-image: url("data:image/svg+xml;utf8,<svg width='14' height='14' viewBox='0 0 14 14' fill='none' xmlns='http://www.w3.org/2000/svg'><rect x='0.8' y='0.8' width='12.4' height='12.4' rx='1.7' stroke='%23ABC0D3' stroke-width='1.6'/></svg>");
81
+ --checkbox-image-checked: url("data:image/svg+xml;utf8,<svg width='15' height='14' viewBox='0 0 15 14' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M11.91 2.49661C12.4736 1.9331 13.3872 1.9331 13.9507 2.49661C14.5142 3.06011 14.5142 3.97374 13.9507 4.53725L7.7195 10.7684C7.52877 10.9592 7.29793 11.0853 7.05413 11.147C6.56096 11.2966 6.00345 11.1765 5.61355 10.7866L3.27419 8.44723C2.71069 7.88372 2.71069 6.97009 3.27419 6.40659C3.8377 5.84308 4.75133 5.84308 5.31484 6.40658L6.65745 7.7492L11.91 2.49661Z' fill='%23ABC0D3'/><path fill-rule='evenodd' clip-rule='evenodd' d='M2.85185 0C1.27682 0 0 1.27682 0 2.85185V11.1481C0 12.7232 1.27682 14 2.85185 14H11.1481C12.7232 14 14 12.7232 14 11.1481V7.25926H12.4444V11.1481C12.4444 11.8641 11.8641 12.4444 11.1481 12.4444H2.85185C2.13593 12.4444 1.55556 11.8641 1.55556 11.1481V2.85185C1.55556 2.13593 2.13593 1.55556 2.85185 1.55556H11.1481C11.474 1.55556 11.7718 1.6758 11.9996 1.87434L13.3636 1.05592C12.8407 0.411698 12.0425 0 11.1481 0H2.85185Z' fill='%23ABC0D3'/></svg>");
82
+ --checkbox-color-error: #f14e4e;
83
+ --checkbox-required-color: #f14e4e;
84
+ }
85
+
86
+ .vc-checkbox {
87
+ &__label {
88
+ @apply inline-flex select-none cursor-pointer text-base items-center;
89
+ }
90
+
91
+ &__input {
92
+ @apply absolute opacity-0 z-[-1] m-0;
93
+ }
94
+
95
+ &__error {
96
+ --hint-color: var(--checkbox-color-error);
97
+ }
98
+
99
+ &__checkmark {
100
+ @apply h-[var(--checkbox-size)];
101
+
102
+ &:before {
103
+ @apply inline-block box-border
104
+ w-[var(--checkbox-size)]
105
+ h-[var(--checkbox-size)]
106
+ shrink-0
107
+ grow-0
108
+ rounded-[var(--checkbox-border-radius)]
109
+ bg-no-repeat
110
+ bg-left-top
111
+ bg-[length:auto_var(--checkbox-size)]
112
+ bg-[color:var(--checkbox-background-color)]
113
+ bg-[image:var(--checkbox-image)]
114
+ content-[""];
115
+ }
116
+ }
117
+
118
+ &__input:checked ~ &__checkmark:before {
119
+ @apply bg-[image:var(--checkbox-image-checked)];
120
+ }
121
+
122
+ &_disabled &__checkmark:before {
123
+ @apply bg-[#fafafa];
124
+ }
125
+
126
+ &_disabled &__label {
127
+ @apply cursor-auto;
128
+ }
129
+ }
130
+ </style>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <div class="vc-col flex flex-col min-w-0 basis-0" :style="{ flexGrow: size }">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ defineProps({
9
+ size: {
10
+ type: String,
11
+ default: "1",
12
+ },
13
+ });
14
+ </script>
15
+
16
+ <style lang="scss">
17
+ .vc-col {
18
+ .vc-app_mobile & {
19
+ @apply grow #{!important};
20
+ }
21
+ }
22
+ </style>
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Container component.
3
+ * @author Iurii A Taranov <me@flanker72.ru>
4
+ */
5
+ import { Story } from "@storybook/vue3";
6
+ import VcContainer from "./vc-container.vue";
7
+
8
+ export default {
9
+ title: "atoms/vc-container",
10
+ component: VcContainer,
11
+ };
12
+
13
+ const Template: Story = (args) => ({
14
+ components: { VcContainer },
15
+ setup() {
16
+ return { args };
17
+ },
18
+ template: `<div style="width: 400px; height: 300px"><vc-container v-bind="args">
19
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pellentesque tortor id lacus viverra, ut mollis libero auctor. Curabitur viverra, justo eu convallis pulvinar, dui nisi luctus quam, ut egestas tortor dolor quis nisi. Sed dignissim tellus ac enim dignissim dapibus. Duis vitae ipsum sit amet leo ornare fringilla sit amet a felis. Quisque finibus elementum dolor eu rhoncus. Donec dapibus non nisl blandit lobortis. Suspendisse pellentesque elit nunc, at auctor orci dignissim sed. Cras malesuada nibh id porttitor hendrerit.</p>
20
+ <p>Maecenas ut malesuada risus, a euismod ligula. Mauris fringilla arcu a vestibulum varius. Phasellus et quam facilisis, egestas magna ut, ultrices est. Maecenas accumsan sit amet metus sit amet laoreet. Sed at accumsan orci, id tincidunt nibh. Nam laoreet eu nisl a condimentum. Fusce ac blandit justo. Vestibulum sollicitudin eros euismod, cursus arcu ac, blandit eros. Phasellus tempor mi et iaculis pulvinar. Cras blandit, tortor sit amet fermentum aliquet, metus ipsum ultricies est, eu congue dui nunc nec ligula.</p>
21
+ <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque porttitor felis non turpis volutpat, ut consequat nulla vestibulum. Donec ipsum dui, convallis a faucibus eget, vehicula faucibus quam. Maecenas et velit odio. Suspendisse posuere faucibus est vel condimentum. Mauris et est placerat risus tincidunt rutrum. Sed venenatis nunc a mollis dignissim. Nam felis nisl, blandit in venenatis et, sollicitudin ut eros. Quisque ornare lacus metus, sed placerat lacus malesuada et. Sed venenatis, turpis in porta suscipit, libero ex tristique erat, nec pretium lectus justo malesuada dolor.</p>
22
+ <p>Vivamus non nisi quis elit pellentesque pharetra quis eget augue. Donec tincidunt nunc id placerat tincidunt. Mauris ultrices quam id risus sodales, at euismod mauris convallis. Morbi quis aliquam nibh. Cras vitae mi a risus dapibus lacinia sit amet eu erat. Morbi ligula ex, aliquet ac nunc a, tempus lacinia lacus. Integer pretium arcu augue, vitae egestas libero rutrum eu.</p>
23
+ <p>Suspendisse malesuada nisl tempor tellus ullamcorper, ut varius enim molestie. Suspendisse eleifend at libero id ultricies. Duis sagittis quis metus eget condimentum. Praesent iaculis viverra mauris et mattis. Pellentesque cursus, turpis sed venenatis volutpat, nibh tortor eleifend eros, non varius neque lectus ut dolor. Sed eget lectus et risus hendrerit molestie. Cras lorem enim, rutrum sed pellentesque in, tristique et diam. Donec aliquet dolor sit amet cursus facilisis. Donec a placerat nibh.</p>
24
+ </vc-container></div>`,
25
+ });
26
+
27
+ export const Container = Template.bind({});
28
+ Container.storyName = "vc-container";
29
+ Container.args = {
30
+ shadow: false,
31
+ };