shared-ritm 1.3.38 → 1.3.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 (62) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/shared-ritm.es.js +7 -7
  3. package/dist/shared-ritm.umd.js +150 -150
  4. package/package.json +70 -64
  5. package/src/App.vue +2461 -2461
  6. package/src/api/services/ControlsService.ts +96 -96
  7. package/src/api/services/EquipmentService.ts +29 -29
  8. package/src/api/services/GanttService.ts +23 -23
  9. package/src/api/services/MetricsService.ts +123 -123
  10. package/src/api/services/RepairsService.ts +111 -111
  11. package/src/api/services/TasksService.ts +157 -157
  12. package/src/api/services/UserService.ts +123 -123
  13. package/src/api/services/VideoService.ts +118 -118
  14. package/src/api/types/Api_Metrics.ts +5 -5
  15. package/src/api/types/Api_Repairs.ts +186 -186
  16. package/src/api/types/Api_Tasks.ts +376 -376
  17. package/src/api/types/Api_Video.ts +244 -244
  18. package/src/common/app-button/Button.stories.ts +369 -0
  19. package/src/common/app-checkbox/Checkbox.stories.ts +60 -0
  20. package/src/common/app-date-picker/DatePicker.stories.ts +66 -0
  21. package/src/common/app-datepicker/Datepicker.stories.ts +145 -0
  22. package/src/common/app-dialogs/AppConfirmDialog.vue +109 -109
  23. package/src/common/app-dialogs/Confirm.stories.ts +93 -0
  24. package/src/common/app-dropdown/Dropdown.stories.ts +94 -0
  25. package/src/common/app-file/File.stories.ts +104 -0
  26. package/src/common/app-icon/AppIcon.vue +108 -108
  27. package/src/common/app-icon/Icon.stories.ts +91 -0
  28. package/src/common/app-input/Input.stories.ts +160 -0
  29. package/src/common/app-input-new/InputNew.stories.ts +240 -0
  30. package/src/common/app-input-search/InputSearch.stories.ts +149 -0
  31. package/src/common/app-layout/components/AppLayoutHeader.vue +289 -273
  32. package/src/common/app-loader/Loader.stories.ts +114 -0
  33. package/src/common/app-select/AppSelect.vue +159 -159
  34. package/src/common/app-select/Select.stories.ts +155 -0
  35. package/src/common/app-sidebar/AppSidebar.vue +174 -174
  36. package/src/common/app-table/AppTable.vue +313 -313
  37. package/src/common/app-table/components/ModalSelect.stories.ts +323 -0
  38. package/src/common/app-table/components/ModalSelect.vue +302 -302
  39. package/src/common/app-table/components/TableModal.vue +367 -367
  40. package/src/common/app-table/controllers/useColumnSelector.ts +45 -45
  41. package/src/common/app-table/controllers/useTableModel.ts +97 -102
  42. package/src/common/app-toggle/Toggle.stories.ts +69 -0
  43. package/src/common/app-wrapper/AppWrapper.vue +31 -28
  44. package/src/configs/storybook.ts +14 -0
  45. package/src/index.ts +131 -131
  46. package/src/shared/styles/general.css +140 -124
  47. package/src/styles/variables.sass +12 -12
  48. package/src/utils/helpers.ts +59 -59
  49. package/dist/types/api/services/PhotoService.d.ts +0 -40
  50. package/dist/types/stories/Button.stories.d.ts +0 -13
  51. package/dist/types/stories/Checkbox.stories.d.ts +0 -7
  52. package/dist/types/stories/Confirm.stories.d.ts +0 -8
  53. package/dist/types/stories/DatePicker.stories.d.ts +0 -8
  54. package/dist/types/stories/Dropdown.stories.d.ts +0 -8
  55. package/dist/types/stories/File.stories.d.ts +0 -8
  56. package/dist/types/stories/Icon.stories.d.ts +0 -7
  57. package/dist/types/stories/Input.stories.d.ts +0 -11
  58. package/dist/types/stories/InputNew.stories.d.ts +0 -12
  59. package/dist/types/stories/InputSearch.stories.d.ts +0 -10
  60. package/dist/types/stories/Loader.stories.d.ts +0 -8
  61. package/dist/types/stories/Select.stories.d.ts +0 -7
  62. package/dist/types/stories/Toggle.stories.d.ts +0 -8
@@ -1,273 +1,289 @@
1
- <template>
2
- <q-header :class="[$style.header, { [$style[`header-full`]]: fullWidth }]">
3
- <q-toolbar :class="$style.toolbar">
4
- <h1>{{ pageTitle }}</h1>
5
- <div :class="$style['action-buttons']">
6
- <div v-if="settingsMenuItems?.find(x => x.name === 'root-on' && x.isShow)" :class="$style['root-mode']">
7
- <h1>Включен Root-режим</h1>
8
- </div>
9
-
10
- <div :class="$style['person']" @click="clickProfile">
11
- <app-icon name="person-icon" />
12
- <div :class="$style['person__info']">
13
- <p style="font-weight: 700; font-size: 14px">{{ shortName }}</p>
14
- <p style="font-weight: 300; font-size: 12px">{{ positionName }}</p>
15
- </div>
16
- </div>
17
- <div :class="$style['action-wrapper']">
18
- <!-- <q-btn :class="$style['notification']" flat padding="sm" :ripple="false" @click="clickNotification">-->
19
- <!-- <app-icon color="white" size="28px" name="notifications-icon" />-->
20
- <!-- </q-btn>-->
21
- <q-separator color="white" vertical size="1px" />
22
- <q-btn
23
- ref="refMenuSettings"
24
- flat
25
- padding="sm"
26
- :ripple="false"
27
- :class="[$style['settings'], { [$style['settings__open']]: isSettingsOpened }]"
28
- @click="openSettingsMenu"
29
- >
30
- <app-icon size="28px" name="setting-icon" />
31
- <q-menu max-height="160px" :offset="[-18, 4]" :class="$style['settings-menu']">
32
- <q-list v-for="item in settingsMenuItems" :key="item.name" :class="$style['settings-menu__list']">
33
- <q-item
34
- v-show="item.isShow"
35
- v-close-popup
36
- :class="$style['settings-menu__item']"
37
- clickable
38
- @click="clickSettingsMenuItem(item)"
39
- >{{ item.label }}</q-item
40
- >
41
- </q-list>
42
- </q-menu>
43
- </q-btn>
44
- </div>
45
-
46
- <!-- <app-button icon="person" text-color="black" :label="shortName" rounded :class="$style['button-person']" />-->
47
- </div>
48
- </q-toolbar>
49
- </q-header>
50
- </template>
51
-
52
- <script lang="ts" setup>
53
- import { computed, defineProps, ref, withDefaults } from 'vue'
54
- import { onClickOutside } from '@vueuse/core'
55
- import AppIcon from '@/common/app-icon/AppIcon.vue'
56
-
57
- interface Props {
58
- userData: any
59
- fullWidth?: boolean
60
- pageTitle?: string
61
- settingsMenuItems?: { label: string; name: string; isShow: boolean }[]
62
- }
63
-
64
- const emits = defineEmits(['clickSettingsMenuItem', 'clickNotification', 'clickProfile'])
65
-
66
- const props = withDefaults(defineProps<Props>(), {
67
- pageTitle: '',
68
- })
69
-
70
- const refMenuSettings = ref(null)
71
- const isSettingsOpened = ref(false)
72
-
73
- // const settingsMenuItems = ref([
74
- // { label: 'Поиск инструментов', name: 'instrument-search', isShow: true },
75
- // { label: 'Мониторинг оборудования', name: 'equipment-monitoring', isShow: true },
76
- // { label: 'Root-режим выключен', name: 'root-off', isShow: true },
77
- // { label: 'Root-режим включен', name: 'root-on', isShow: false },
78
- // ])
79
-
80
- const shortName = computed(() => {
81
- if (!props.userData?.full_name) return ''
82
-
83
- const [lastName, name, patronymic] = props.userData.full_name.split(' ')
84
-
85
- const mainPart = `${lastName} ${name}`
86
-
87
- if (!patronymic) return mainPart
88
-
89
- return `${mainPart} ${patronymic[0]}.`
90
- })
91
-
92
- const positionName = computed(() => props.userData?.positions?.[0]?.display_name)
93
-
94
- const openSettingsMenu = () => {
95
- return (isSettingsOpened.value = !isSettingsOpened.value)
96
- }
97
-
98
- const clickProfile = () => emits('clickProfile')
99
- const clickSettingsMenuItem = (item: any) => emits('clickSettingsMenuItem', item.name)
100
- const clickNotification = () => emits('clickNotification')
101
-
102
- onClickOutside(refMenuSettings, () => (isSettingsOpened.value = false))
103
- </script>
104
-
105
- <style lang="scss" module>
106
- .header {
107
- height: 100px;
108
- background: transparent;
109
- margin: 0 auto;
110
- max-width: 1300px;
111
- }
112
- .header-full {
113
- max-width: 100%;
114
- padding-right: 30px;
115
- padding-left: 30px;
116
- }
117
- .toolbar {
118
- padding: 0;
119
- min-height: 100%;
120
- h1 {
121
- font-weight: 600;
122
- font-size: 28px;
123
- line-height: 100%;
124
- font-family: Montserrat, sans-serif;
125
- }
126
- }
127
-
128
- .header-search {
129
- width: 412px;
130
- font-size: 16px;
131
- }
132
-
133
- .action-buttons {
134
- flex: 1;
135
- position: relative;
136
- display: flex;
137
- align-items: center;
138
- column-gap: 16px;
139
- justify-content: end;
140
- }
141
-
142
- .button {
143
- padding: 12px;
144
- background: white;
145
- transition: all 0.3s ease, color 0.3s ease;
146
- }
147
-
148
- .button-person {
149
- padding: 10px 14px;
150
- background: white;
151
- }
152
-
153
- .root-mode {
154
- display: flex;
155
- align-items: center;
156
- background-color: red;
157
- padding: 14px;
158
- border-radius: 10px;
159
- box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2), 0 2px 2px rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12);
160
- cursor: pointer;
161
- user-select: none;
162
- h1 {
163
- font-size: 16px;
164
- font-weight: 600;
165
- font-family: 'Nunito Sans', sans-serif;
166
- }
167
- &:active {
168
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 4px 4px rgba(0, 0, 0, 0.2), 0 6px 2px -5px rgba(0, 0, 0, 0.2);
169
- }
170
- }
171
-
172
- .person {
173
- display: flex;
174
- align-items: center;
175
- gap: 6px;
176
- padding: 20px 12px;
177
- height: 44px;
178
- border-radius: 10px;
179
- cursor: pointer;
180
- background-color: white;
181
- box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2), 0 2px 2px rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12);
182
- transition: all 0.3s ease;
183
- &__info {
184
- display: flex;
185
- flex-direction: column;
186
- user-select: none;
187
- p {
188
- line-height: 1.2;
189
- margin: 0;
190
- padding: 0;
191
- font-family: 'Nunito Sans', sans-serif;
192
- color: rgb(63, 140, 255);
193
- }
194
- }
195
- &:hover {
196
- background-color: #e1e0e0;
197
- transform: scale(1.01);
198
- }
199
- &:active {
200
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 4px 4px rgba(0, 0, 0, 0.2), 0 6px 2px -5px rgba(0, 0, 0, 0.2);
201
- }
202
- }
203
-
204
- .notification {
205
- cursor: pointer;
206
- transition: transform 0.3s ease;
207
- &:hover {
208
- transform: scale(1.1);
209
- }
210
- :global(.q-focus-helper) {
211
- display: none;
212
- }
213
- }
214
-
215
- .settings {
216
- cursor: pointer;
217
- transition: transform 0.3s ease;
218
- &__open {
219
- transform: rotate(90deg);
220
- }
221
- :global(.q-focus-helper) {
222
- display: none;
223
- }
224
- }
225
-
226
- .settings-menu {
227
- min-width: 210px;
228
- border-radius: 8px;
229
- &__list {
230
- min-width: 210px;
231
- }
232
- &__item {
233
- align-items: center;
234
- font-family: 'Nunito Sans', sans-serif;
235
- color: rgb(63, 140, 255);
236
- }
237
- }
238
-
239
- .action-wrapper {
240
- height: 32px;
241
- justify-content: space-between;
242
- align-items: center;
243
- display: flex;
244
- gap: 12px;
245
- }
246
-
247
- @media (max-width: 1440px) {
248
- .header {
249
- height: 100px;
250
- background: transparent;
251
- margin: 0 auto;
252
- }
253
- .header-search {
254
- width: 343px;
255
- font-size: 16px;
256
- }
257
- .action-buttons {
258
- position: relative;
259
- display: flex;
260
- align-items: center;
261
- column-gap: 8px;
262
- }
263
- .button {
264
- padding: 10px;
265
- background: white;
266
- transition: all 0.3s ease, color 0.3s ease;
267
- }
268
- .button-person {
269
- padding: 8px 10px;
270
- background: white;
271
- }
272
- }
273
- </style>
1
+ <template>
2
+ <q-header :class="[$style.header, { [$style[`header-full`]]: fullWidth }]">
3
+ <q-toolbar :class="$style.toolbar">
4
+ <h1>{{ pageTitle }}</h1>
5
+ <div :class="$style['action-buttons']">
6
+ <div v-if="settingsMenuItems?.find(x => x.name === 'root-on' && x.isShow)" :class="$style['root-mode']">
7
+ <h1>Включен Root-режим</h1>
8
+ </div>
9
+
10
+ <div :class="$style['person']" @click="clickProfile">
11
+ <app-icon name="person-icon" />
12
+ <div :class="$style['person__info']">
13
+ <p style="font-weight: 700; font-size: 14px">{{ shortName }}</p>
14
+ <p style="font-weight: 300; font-size: 12px">{{ positionName }}</p>
15
+ </div>
16
+ </div>
17
+ <div :class="$style['action-wrapper']">
18
+ <!-- <q-btn :class="$style['notification']" flat padding="sm" :ripple="false" @click="clickNotification">-->
19
+ <!-- <app-icon color="white" size="28px" name="notifications-icon" />-->
20
+ <!-- </q-btn>-->
21
+ <q-separator color="white" vertical size="1px" />
22
+ <q-btn
23
+ ref="refMenuSettings"
24
+ flat
25
+ padding="sm"
26
+ :ripple="false"
27
+ :class="[$style['settings'], { [$style['settings__open']]: isSettingsOpened }]"
28
+ @click="openSettingsMenu"
29
+ >
30
+ <app-icon size="28px" name="setting-icon" />
31
+ <q-menu max-height="160px" :offset="[-18, 4]" :class="$style['settings-menu']">
32
+ <q-list v-for="item in settingsMenuItems" :key="item.name" :class="$style['settings-menu__list']">
33
+ <q-item
34
+ v-show="item.isShow"
35
+ v-close-popup
36
+ :class="$style['settings-menu__item']"
37
+ clickable
38
+ @click="clickSettingsMenuItem(item)"
39
+ >{{ item.label }}</q-item
40
+ >
41
+ </q-list>
42
+ </q-menu>
43
+ </q-btn>
44
+ </div>
45
+
46
+ <!-- <app-button icon="person" text-color="black" :label="shortName" rounded :class="$style['button-person']" />-->
47
+ </div>
48
+ </q-toolbar>
49
+ </q-header>
50
+ </template>
51
+
52
+ <script lang="ts" setup>
53
+ import { computed, defineProps, ref, withDefaults } from 'vue'
54
+ import { onClickOutside } from '@vueuse/core'
55
+ import AppIcon from '@/common/app-icon/AppIcon.vue'
56
+
57
+ interface Props {
58
+ userData: any
59
+ fullWidth?: boolean
60
+ pageTitle?: string
61
+ settingsMenuItems?: { label: string; name: string; isShow: boolean }[]
62
+ }
63
+
64
+ const emits = defineEmits(['clickSettingsMenuItem', 'clickNotification', 'clickProfile'])
65
+
66
+ const props = withDefaults(defineProps<Props>(), {
67
+ pageTitle: '',
68
+ })
69
+
70
+ const refMenuSettings = ref(null)
71
+ const isSettingsOpened = ref(false)
72
+
73
+ // const settingsMenuItems = ref([
74
+ // { label: 'Поиск инструментов', name: 'instrument-search', isShow: true },
75
+ // { label: 'Мониторинг оборудования', name: 'equipment-monitoring', isShow: true },
76
+ // { label: 'Root-режим выключен', name: 'root-off', isShow: true },
77
+ // { label: 'Root-режим включен', name: 'root-on', isShow: false },
78
+ // ])
79
+
80
+ const shortName = computed(() => {
81
+ if (!props.userData?.full_name) return ''
82
+
83
+ const [lastName, name, patronymic] = props.userData.full_name.split(' ')
84
+
85
+ const mainPart = `${lastName} ${name}`
86
+
87
+ if (!patronymic) return mainPart
88
+
89
+ return `${mainPart} ${patronymic[0]}.`
90
+ })
91
+
92
+ const positionName = computed(() => props.userData?.positions?.[0]?.display_name)
93
+
94
+ const openSettingsMenu = () => {
95
+ return (isSettingsOpened.value = !isSettingsOpened.value)
96
+ }
97
+
98
+ const clickProfile = () => emits('clickProfile')
99
+ const clickSettingsMenuItem = (item: any) => emits('clickSettingsMenuItem', item.name)
100
+ const clickNotification = () => emits('clickNotification')
101
+
102
+ onClickOutside(refMenuSettings, () => (isSettingsOpened.value = false))
103
+ </script>
104
+
105
+ <style lang="scss" module>
106
+ .header {
107
+ height: 100px;
108
+ background: transparent;
109
+ margin: 0 auto;
110
+ max-width: 1300px;
111
+ }
112
+ .header-full {
113
+ max-width: 100%;
114
+ padding-right: 30px;
115
+ padding-left: 30px;
116
+ }
117
+ .toolbar {
118
+ padding: 0;
119
+ min-height: 100%;
120
+ h1 {
121
+ font-weight: 600;
122
+ font-size: 28px;
123
+ line-height: 100%;
124
+ font-family: Montserrat, sans-serif;
125
+ }
126
+ }
127
+
128
+ .header-search {
129
+ width: 412px;
130
+ font-size: 16px;
131
+ }
132
+
133
+ .action-buttons {
134
+ flex: 1;
135
+ position: relative;
136
+ display: flex;
137
+ align-items: center;
138
+ column-gap: 16px;
139
+ justify-content: end;
140
+ }
141
+
142
+ .button {
143
+ padding: 12px;
144
+ background: white;
145
+ transition:
146
+ all 0.3s ease,
147
+ color 0.3s ease;
148
+ }
149
+
150
+ .button-person {
151
+ padding: 10px 14px;
152
+ background: white;
153
+ }
154
+
155
+ .root-mode {
156
+ display: flex;
157
+ align-items: center;
158
+ background-color: red;
159
+ padding: 14px;
160
+ border-radius: 10px;
161
+ box-shadow:
162
+ 0 1px 5px rgba(0, 0, 0, 0.2),
163
+ 0 2px 2px rgba(0, 0, 0, 0.14),
164
+ 0 3px 1px -2px rgba(0, 0, 0, 0.12);
165
+ cursor: pointer;
166
+ user-select: none;
167
+ h1 {
168
+ font-size: 16px;
169
+ font-weight: 600;
170
+ font-family: 'Nunito Sans', sans-serif;
171
+ }
172
+ &:active {
173
+ box-shadow:
174
+ 0 2px 8px rgba(0, 0, 0, 0.3),
175
+ 0 4px 4px rgba(0, 0, 0, 0.2),
176
+ 0 6px 2px -5px rgba(0, 0, 0, 0.2);
177
+ }
178
+ }
179
+
180
+ .person {
181
+ display: flex;
182
+ align-items: center;
183
+ gap: 6px;
184
+ padding: 20px 12px;
185
+ height: 44px;
186
+ border-radius: 10px;
187
+ cursor: pointer;
188
+ background-color: white;
189
+ box-shadow:
190
+ 0 1px 5px rgba(0, 0, 0, 0.2),
191
+ 0 2px 2px rgba(0, 0, 0, 0.14),
192
+ 0 3px 1px -2px rgba(0, 0, 0, 0.12);
193
+ transition: all 0.3s ease;
194
+ &__info {
195
+ display: flex;
196
+ flex-direction: column;
197
+ user-select: none;
198
+ p {
199
+ line-height: 1.2;
200
+ margin: 0;
201
+ padding: 0;
202
+ font-family: 'Nunito Sans', sans-serif;
203
+ color: rgb(63, 140, 255);
204
+ }
205
+ }
206
+ &:hover {
207
+ background-color: #e1e0e0;
208
+ transform: scale(1.01);
209
+ }
210
+ &:active {
211
+ box-shadow:
212
+ 0 2px 8px rgba(0, 0, 0, 0.3),
213
+ 0 4px 4px rgba(0, 0, 0, 0.2),
214
+ 0 6px 2px -5px rgba(0, 0, 0, 0.2);
215
+ }
216
+ }
217
+
218
+ .notification {
219
+ cursor: pointer;
220
+ transition: transform 0.3s ease;
221
+ &:hover {
222
+ transform: scale(1.1);
223
+ }
224
+ :global(.q-focus-helper) {
225
+ display: none;
226
+ }
227
+ }
228
+
229
+ .settings {
230
+ cursor: pointer;
231
+ transition: transform 0.3s ease;
232
+ &__open {
233
+ transform: rotate(90deg);
234
+ }
235
+ :global(.q-focus-helper) {
236
+ display: none;
237
+ }
238
+ }
239
+
240
+ .settings-menu {
241
+ min-width: 210px;
242
+ border-radius: 8px;
243
+ &__list {
244
+ min-width: 210px;
245
+ }
246
+ &__item {
247
+ align-items: center;
248
+ font-family: 'Nunito Sans', sans-serif;
249
+ color: rgb(63, 140, 255);
250
+ }
251
+ }
252
+
253
+ .action-wrapper {
254
+ height: 32px;
255
+ justify-content: space-between;
256
+ align-items: center;
257
+ display: flex;
258
+ gap: 12px;
259
+ }
260
+
261
+ @media (max-width: 1440px) {
262
+ .header {
263
+ height: 100px;
264
+ background: transparent;
265
+ margin: 0 auto;
266
+ }
267
+ .header-search {
268
+ width: 343px;
269
+ font-size: 16px;
270
+ }
271
+ .action-buttons {
272
+ position: relative;
273
+ display: flex;
274
+ align-items: center;
275
+ column-gap: 8px;
276
+ }
277
+ .button {
278
+ padding: 10px;
279
+ background: white;
280
+ transition:
281
+ all 0.3s ease,
282
+ color 0.3s ease;
283
+ }
284
+ .button-person {
285
+ padding: 8px 10px;
286
+ background: white;
287
+ }
288
+ }
289
+ </style>
@@ -0,0 +1,114 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import AppLoader from '@/common/app-loader/index.vue'
3
+
4
+ const meta: Meta<typeof AppLoader> = {
5
+ title: 'Components/AppLoader',
6
+ component: AppLoader,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ loading: {
10
+ control: 'boolean',
11
+ description: 'Показывать ли спиннер',
12
+ },
13
+ backdrop: {
14
+ control: 'boolean',
15
+ description: 'Показывать затемнение фона при загрузке',
16
+ table: { disable: true },
17
+ },
18
+ size: {
19
+ control: 'select',
20
+ options: ['xs', 'sm', 'md', 'lg', 'xl'],
21
+ description: 'Размер спиннера',
22
+ },
23
+ thickness: {
24
+ control: 'number',
25
+ description: 'Толщина линии спиннера (в px)',
26
+ },
27
+ },
28
+ args: {
29
+ loading: true,
30
+ backdrop: false,
31
+ size: 'md',
32
+ thickness: 2,
33
+ },
34
+ }
35
+
36
+ export default meta
37
+ type Story = StoryObj<typeof AppLoader>
38
+
39
+ export const GlobalLoader: Story = {
40
+ render: args => ({
41
+ components: { AppLoader },
42
+ setup() {
43
+ return { args }
44
+ },
45
+ template: `
46
+ <div style="position: relative; height: 300px;">
47
+ <app-loader v-bind="args" />
48
+
49
+ <h2>Контент страницы</h2>
50
+ </div>
51
+ `,
52
+ }),
53
+ args: {
54
+ loading: true,
55
+ backdrop: true,
56
+ size: 'lg',
57
+ },
58
+ }
59
+
60
+ export const Size: Story = {
61
+ render: () => ({
62
+ components: { AppLoader },
63
+ template: `
64
+ <div style="display: flex; flex-wrap: wrap; gap: 32px; padding: 24px; background: white;">
65
+ <div style="text-align: center; width: 100px; height: 100px; position: relative; border: 1px solid #eee; border-radius: 8px;">
66
+ <app-loader :loading="true" size="xs" />
67
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">xs</div>
68
+ </div>
69
+ <div style="text-align: center; width: 100px; height: 100px; position: relative; border: 1px solid #eee; border-radius: 8px;">
70
+ <app-loader :loading="true" size="sm" />
71
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">sm</div>
72
+ </div>
73
+ <div style="text-align: center; width: 100px; height: 100px; position: relative; border: 1px solid #eee; border-radius: 8px;">
74
+ <app-loader :loading="true" size="md" />
75
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">md</div>
76
+ </div>
77
+ <div style="text-align: center; width: 100px; height: 100px; position: relative; border: 1px solid #eee; border-radius: 8px;">
78
+ <app-loader :loading="true" size="lg" />
79
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">lg</div>
80
+ </div>
81
+ <div style="text-align: center; width: 100px; height: 100px; position: relative; border: 1px solid #eee; border-radius: 8px;">
82
+ <app-loader :loading="true" size="xl" />
83
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">xl</div>
84
+ </div>
85
+ </div>
86
+ `,
87
+ }),
88
+ }
89
+
90
+ export const Thickness: Story = {
91
+ render: () => ({
92
+ components: { AppLoader },
93
+ template: `
94
+ <div style="display: flex; flex-wrap: wrap; gap: 32px; padding: 24px; background: white;">
95
+ <div style="text-align: center; width: 120px; height: 120px; position: relative; border: 1px solid #eee; border-radius: 8px;">
96
+ <app-loader :loading="true" size="lg" :thickness="1" />
97
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">thickness=1</div>
98
+ </div>
99
+ <div style="text-align: center; width: 120px; height: 120px; position: relative; border: 1px solid #eee; border-radius: 8px;">
100
+ <app-loader :loading="true" size="lg" :thickness="2" />
101
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">thickness=2</div>
102
+ </div>
103
+ <div style="text-align: center; width: 120px; height: 120px; position: relative; border: 1px solid #eee; border-radius: 8px;">
104
+ <app-loader :loading="true" size="lg" :thickness="3" />
105
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">thickness=3</div>
106
+ </div>
107
+ <div style="text-align: center; width: 120px; height: 120px; position: relative; border: 1px solid #eee; border-radius: 8px;">
108
+ <app-loader :loading="true" size="lg" :thickness="5" />
109
+ <div style="margin-top: 8px; font-size: 12px; color: #666;">thickness=5</div>
110
+ </div>
111
+ </div>
112
+ `,
113
+ }),
114
+ }