@xen-orchestra/web-core 0.4.0 → 0.6.0

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 (132) hide show
  1. package/lib/assets/css/_colors.pcss +56 -24
  2. package/lib/assets/css/_context.pcss +9 -9
  3. package/lib/assets/css/base.pcss +6 -6
  4. package/lib/assets/error.svg +375 -0
  5. package/lib/assets/no-selection.svg +70 -0
  6. package/lib/components/backup-item/VtsBackupItem.vue +47 -0
  7. package/lib/components/backup-state/{BackupState.vue → VtsBackupState.vue} +4 -4
  8. package/lib/components/{button/ButtonGroup.vue → button-group/VtsButtonGroup.vue} +7 -6
  9. package/lib/components/cell-object/{CellObject.vue → VtsCellObject.vue} +14 -14
  10. package/lib/components/cell-text/{CellText.vue → VtsCellText.vue} +11 -11
  11. package/lib/components/console/VtsActionsConsole.vue +67 -0
  12. package/lib/components/console/VtsClipboardConsole.vue +38 -0
  13. package/lib/components/console/VtsLayoutConsole.vue +40 -0
  14. package/lib/components/console/{RemoteConsole.vue → VtsRemoteConsole.vue} +14 -17
  15. package/lib/components/donut-chart-with-legend/{DonutChartWithLegend.vue → VtsDonutChartWithLegend.vue} +6 -6
  16. package/lib/components/dropdown/DropdownItem.vue +8 -14
  17. package/lib/components/dropdown/DropdownTitle.vue +3 -3
  18. package/lib/components/icon/VtsIcon.vue +38 -42
  19. package/lib/components/layout/{LayoutSidebar.vue → VtsLayoutSidebar.vue} +31 -30
  20. package/lib/components/legend-group/VtsLegendGroup.vue +44 -0
  21. package/lib/components/{legend/LegendList.vue → legend-list/VtsLegendList.vue} +2 -2
  22. package/lib/components/menu/MenuTrigger.vue +2 -2
  23. package/lib/components/stacked-bar-with-legend/{StackedBarWithLegend.vue → VtsStackedBarWithLegend.vue} +14 -14
  24. package/lib/components/state-hero/VtsComingSoonHero.vue +13 -0
  25. package/lib/components/state-hero/VtsLoadingHero.vue +15 -0
  26. package/lib/components/state-hero/VtsNoDataHero.vue +11 -0
  27. package/lib/components/state-hero/VtsObjectNotFoundHero.vue +13 -0
  28. package/lib/components/state-hero/VtsStateHero.vue +117 -0
  29. package/lib/components/tab/TabItem.vue +6 -6
  30. package/lib/components/table/ColumnTitle.vue +7 -7
  31. package/lib/components/table/{UiTable.vue → VtsTable.vue} +7 -3
  32. package/lib/components/task/{QuickTaskButton.vue → VtsQuickTaskButton.vue} +8 -7
  33. package/lib/components/task/{QuickTaskList.vue → VtsQuickTaskList.vue} +10 -11
  34. package/lib/components/task/{QuickTaskTabBar.vue → VtsQuickTaskTabBar.vue} +9 -13
  35. package/lib/components/{tooltip/TooltipList.vue → tooltip-list/VtsTooltipList.vue} +2 -3
  36. package/lib/components/tree/{TreeItem.vue → VtsTreeItem.vue} +3 -4
  37. package/lib/components/tree/VtsTreeItemError.vue +18 -0
  38. package/lib/components/tree/{TreeLine.vue → VtsTreeLine.vue} +9 -11
  39. package/lib/components/tree/{TreeList.vue → VtsTreeList.vue} +5 -2
  40. package/lib/components/tree/VtsTreeLoadingItem.vue +61 -0
  41. package/lib/components/ui/account-menu-button/UiAccountMenuButton.vue +64 -0
  42. package/lib/components/ui/actions-title/UiActionsTitle.vue +2 -2
  43. package/lib/components/ui/button/UiButton.vue +532 -0
  44. package/lib/components/ui/button-icon/UiButtonIcon.vue +248 -0
  45. package/lib/components/{UiCard.vue → ui/card/UiCard.vue} +8 -6
  46. package/lib/components/ui/card-numbers/UiCardNumbers.vue +103 -0
  47. package/lib/components/ui/card-subtitle/UiCardSubtitle.vue +24 -0
  48. package/lib/components/ui/card-title/UiCardTitle.vue +56 -0
  49. package/lib/components/ui/checkbox/UiCheckbox.vue +410 -0
  50. package/lib/components/ui/checkbox-group/UiCheckboxGroup.vue +57 -0
  51. package/lib/components/ui/chip/ChipIcon.vue +21 -0
  52. package/lib/components/ui/chip/ChipRemoveIcon.vue +13 -0
  53. package/lib/components/ui/chip/UiChip.vue +135 -0
  54. package/lib/components/{icon/ComplexIcon.vue → ui/complex-icon/UiComplexIcon.vue} +21 -27
  55. package/lib/components/ui/counter/UiCounter.vue +134 -0
  56. package/lib/components/{donut-chart/DonutChart.vue → ui/donut-chart/UiDonutChart.vue} +28 -30
  57. package/lib/components/{head-bar/HeadBar.vue → ui/head-bar/UiHeadBar.vue} +31 -31
  58. package/lib/components/{info/VtsInfo.vue → ui/info/UiInfo.vue} +13 -11
  59. package/lib/components/{input → ui/input}/UiInput.vue +9 -7
  60. package/lib/components/ui/input/UiTextarea.vue +120 -0
  61. package/lib/components/{input/VtsLabel.vue → ui/label/UiLabel.vue} +25 -25
  62. package/lib/components/ui/legend/UiLegend.vue +98 -0
  63. package/lib/components/{LegendTitle.vue → ui/legend-title/UiLegendTitle.vue} +4 -4
  64. package/lib/components/{UiSpinner.vue → ui/loader/UiLoader.vue} +3 -3
  65. package/lib/components/{icon/ObjectIcon.vue → ui/object-icon/UiObjectIcon.vue} +44 -36
  66. package/lib/components/ui/object-link/UiObjectLink.vue +83 -0
  67. package/lib/components/ui/panel/UiPanel.vue +57 -0
  68. package/lib/components/{query-search-bar/QuerySearchBar.vue → ui/query-search-bar/UiQuerySearchBar.vue} +16 -16
  69. package/lib/components/{task/QuickTaskItem.vue → ui/quick-task-item/UiQuickTaskItem.vue} +46 -34
  70. package/lib/components/{task/QuickTaskPanel.vue → ui/quick-task-panel/UiQuickTaskPanel.vue} +8 -7
  71. package/lib/components/ui/radio-button/UiRadioButton.vue +196 -0
  72. package/lib/components/ui/radio-button-group/UiRadioButtonGroup.vue +56 -0
  73. package/lib/components/{stacked-bar → ui/stacked-bar}/StackedBarSegment.vue +23 -26
  74. package/lib/components/{stacked-bar/StackedBar.vue → ui/stacked-bar/UiStackedBar.vue} +6 -6
  75. package/lib/components/ui/table-actions/UiTableActions.vue +46 -0
  76. package/lib/components/ui/tag/UiTag.vue +118 -0
  77. package/lib/components/ui/title/UiTitle.vue +2 -2
  78. package/lib/components/ui/toaster/UiToaster.vue +100 -0
  79. package/lib/components/ui/toggle/UiToggle.vue +117 -0
  80. package/lib/components/{tooltip/TooltipItem.vue → ui/tooltip/UiTooltip.vue} +15 -15
  81. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +64 -0
  82. package/lib/components/{tree/TreeItemLabel.vue → ui/tree-item-label/UiTreeItemLabel.vue} +60 -59
  83. package/lib/components/ui/user-link/UiUserLink.vue +76 -0
  84. package/lib/components/ui/user-logo/UiUserLogo.vue +50 -0
  85. package/lib/composables/route-query.composable.md +136 -0
  86. package/lib/composables/table.composable.md +159 -0
  87. package/lib/composables/tree/define-tree.ts +1 -1
  88. package/lib/composables/tree/tree-node-base.ts +6 -6
  89. package/lib/composables/tree.composable.md +536 -0
  90. package/lib/i18n.ts +4 -0
  91. package/lib/layouts/CoreLayout.vue +8 -6
  92. package/lib/locales/cs.json +76 -0
  93. package/lib/locales/de.json +5 -2
  94. package/lib/locales/en.json +14 -3
  95. package/lib/locales/fa.json +5 -2
  96. package/lib/locales/fr.json +14 -3
  97. package/lib/types/color.type.ts +0 -2
  98. package/lib/types/subscribable-store.type.ts +2 -2
  99. package/lib/utils/create-subscribable-store-context.util.ts +1 -1
  100. package/lib/utils/if-else.utils.md +23 -0
  101. package/lib/utils/if-else.utils.ts +2 -2
  102. package/lib/utils/to-variants.util.md +62 -0
  103. package/package.json +7 -7
  104. package/lib/components/CardNumbers.vue +0 -101
  105. package/lib/components/PowerStateIcon.vue +0 -46
  106. package/lib/components/UiTag.vue +0 -101
  107. package/lib/components/backup-item/BackupItem.vue +0 -40
  108. package/lib/components/button/ButtonIcon.vue +0 -220
  109. package/lib/components/button/UiButton.vue +0 -470
  110. package/lib/components/card/CardSubtitle.vue +0 -24
  111. package/lib/components/card/CardTitle.vue +0 -57
  112. package/lib/components/chip/ChipIcon.vue +0 -30
  113. package/lib/components/chip/ChipRemoveIcon.vue +0 -13
  114. package/lib/components/chip/UiChip.vue +0 -137
  115. package/lib/components/counter/VtsCounter.vue +0 -147
  116. package/lib/components/legend/LegendGroup.vue +0 -44
  117. package/lib/components/legend/LegendItem.vue +0 -86
  118. package/lib/components/object-link/ObjectLink.vue +0 -87
  119. package/lib/components/state-hero/ComingSoonHero.vue +0 -13
  120. package/lib/components/state-hero/LoadingHero.vue +0 -15
  121. package/lib/components/state-hero/NoDataHero.vue +0 -11
  122. package/lib/components/state-hero/ObjectNotFoundHero.vue +0 -13
  123. package/lib/components/state-hero/StateHero.vue +0 -74
  124. package/lib/components/tree/TreeItemError.vue +0 -13
  125. package/lib/components/tree/TreeLoadingItem.vue +0 -60
  126. package/lib/components/user/UserLink.vue +0 -72
  127. package/lib/components/user/UserLogo.vue +0 -57
  128. package/lib/types/backup.type.ts +0 -11
  129. package/lib/types/size.type.ts +0 -1
  130. package/lib/types/task.type.ts +0 -13
  131. /package/lib/components/backdrop/{Backdrop.vue → VtsBackdrop.vue} +0 -0
  132. /package/lib/components/divider/{Divider.vue → VtsDivider.vue} +0 -0
@@ -0,0 +1,248 @@
1
+ <!-- WIP -->
2
+ <!-- TODO: Add complex icon -->
3
+ <template>
4
+ <button :class="classNames" :disabled class="ui-button-icon" type="button">
5
+ <VtsIcon :icon accent="current" />
6
+ <span v-if="dot" class="dot" />
7
+ </button>
8
+ </template>
9
+
10
+ <script lang="ts" setup>
11
+ import VtsIcon from '@core/components/icon/VtsIcon.vue'
12
+ import { toVariants } from '@core/utils/to-variants.util'
13
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
14
+ import { computed } from 'vue'
15
+
16
+ type ButtonIconAccent = 'info' | 'success' | 'warning' | 'danger'
17
+ type ButtonSize = 'small' | 'medium' | 'large'
18
+
19
+ const props = withDefaults(
20
+ defineProps<{
21
+ icon: IconDefinition
22
+ size: ButtonSize
23
+ accent: ButtonIconAccent
24
+ disabled?: boolean
25
+ selected?: boolean
26
+ dot?: boolean
27
+ targetScale?: number | { x: number; y: number }
28
+ }>(),
29
+ { targetScale: 1 }
30
+ )
31
+
32
+ const cssTargetScale = computed(() => {
33
+ if (typeof props.targetScale === 'number') {
34
+ return `scale(${props.targetScale})`
35
+ }
36
+
37
+ return `scale(${props.targetScale.x}, ${props.targetScale.y})`
38
+ })
39
+
40
+ const classNames = computed(() => {
41
+ return [
42
+ toVariants({
43
+ accent: props.accent,
44
+ size: props.size,
45
+ muted: props.disabled,
46
+ selected: props.selected,
47
+ }),
48
+ ]
49
+ })
50
+ </script>
51
+
52
+ <style lang="postcss" scoped>
53
+ .ui-button-icon {
54
+ display: inline-flex;
55
+ justify-content: center;
56
+ align-items: center;
57
+ border: none;
58
+ padding: 0;
59
+ border-radius: 0.2rem;
60
+ position: relative;
61
+ cursor: pointer;
62
+ outline: none;
63
+
64
+ &:disabled {
65
+ cursor: not-allowed;
66
+ }
67
+
68
+ .dot {
69
+ position: absolute;
70
+ display: block;
71
+ border-radius: 50%;
72
+ background-color: var(--color-danger-txt-base);
73
+ }
74
+
75
+ /* ACCENT VARIANTS */
76
+
77
+ &.accent--info {
78
+ & {
79
+ color: var(--color-info-txt-base);
80
+ background-color: transparent;
81
+ }
82
+
83
+ &:is(:hover, :focus-visible) {
84
+ color: var(--color-info-txt-hover);
85
+ background-color: var(--color-info-background-hover);
86
+ }
87
+
88
+ &:active {
89
+ color: var(--color-info-txt-active);
90
+ background-color: var(--color-info-background-active);
91
+ }
92
+
93
+ &.selected {
94
+ color: var(--color-info-txt-base);
95
+ background-color: var(--color-info-background-selected);
96
+ }
97
+
98
+ &.muted {
99
+ color: var(--color-neutral-txt-secondary);
100
+ background-color: transparent;
101
+ }
102
+ }
103
+
104
+ &.accent--success {
105
+ & {
106
+ color: var(--color-success-txt-base);
107
+ background-color: transparent;
108
+ }
109
+
110
+ &:is(:hover, :focus-visible) {
111
+ color: var(--color-success-txt-hover);
112
+ background-color: var(--color-success-background-hover);
113
+ }
114
+
115
+ &:active {
116
+ color: var(--color-success-txt-active);
117
+ background-color: var(--color-success-background-active);
118
+ }
119
+
120
+ &.selected {
121
+ color: var(--color-success-txt-base);
122
+ background-color: var(--color-success-background-selected);
123
+ }
124
+
125
+ &.muted {
126
+ color: var(--color-neutral-txt-secondary);
127
+ background-color: transparent;
128
+ }
129
+ }
130
+
131
+ &.accent--warning {
132
+ & {
133
+ color: var(--color-warning-txt-base);
134
+ background-color: transparent;
135
+ }
136
+
137
+ &:is(:hover, :focus-visible) {
138
+ color: var(--color-warning-txt-hover);
139
+ background-color: var(--color-warning-background-hover);
140
+ }
141
+
142
+ &:active {
143
+ color: var(--color-warning-txt-active);
144
+ background-color: var(--color-warning-background-active);
145
+ }
146
+
147
+ &.selected {
148
+ color: var(--color-warning-txt-base);
149
+ background-color: var(--color-warning-background-selected);
150
+ }
151
+
152
+ &.muted {
153
+ color: var(--color-neutral-txt-secondary);
154
+ background-color: transparent;
155
+ }
156
+ }
157
+
158
+ &.accent--danger {
159
+ & {
160
+ color: var(--color-danger-txt-base);
161
+ background-color: transparent;
162
+
163
+ .dot {
164
+ background-color: var(--color-warning-txt-base);
165
+ }
166
+ }
167
+
168
+ &:is(:hover, :focus-visible) {
169
+ color: var(--color-danger-txt-hover);
170
+ background-color: var(--color-danger-background-hover);
171
+ }
172
+
173
+ &:active {
174
+ color: var(--color-danger-txt-active);
175
+ background-color: var(--color-danger-background-active);
176
+ }
177
+
178
+ &.selected {
179
+ color: var(--color-danger-txt-base);
180
+ background-color: var(--color-danger-background-selected);
181
+ }
182
+
183
+ &.muted {
184
+ color: var(--color-neutral-txt-secondary);
185
+ background-color: transparent;
186
+ }
187
+ }
188
+
189
+ /* SIZE VARIANTS */
190
+
191
+ &.size--small {
192
+ & {
193
+ width: 1.6rem;
194
+ height: 1.6rem;
195
+ font-size: 1.2rem;
196
+ }
197
+
198
+ .dot {
199
+ width: 0.4rem;
200
+ height: 0.4rem;
201
+ top: 0.2rem;
202
+ right: 0.2rem;
203
+ }
204
+ }
205
+
206
+ &.size--medium {
207
+ & {
208
+ width: 2.4rem;
209
+ height: 2.4rem;
210
+ font-size: 1.6rem;
211
+ }
212
+
213
+ .dot {
214
+ width: 0.5rem;
215
+ height: 0.5rem;
216
+ top: 0.4rem;
217
+ right: 0.4rem;
218
+ }
219
+ }
220
+
221
+ &.size--large {
222
+ & {
223
+ width: 4rem;
224
+ height: 4rem;
225
+ font-size: 2.4rem;
226
+ }
227
+
228
+ .dot {
229
+ width: 0.8rem;
230
+ height: 0.8rem;
231
+ top: 0.8rem;
232
+ right: 0.8rem;
233
+ }
234
+ }
235
+
236
+ /*
237
+ * Increase the size of the clickable area,
238
+ * without changing the padding of the ButtonIcon component
239
+ */
240
+
241
+ &::after {
242
+ content: '';
243
+ position: absolute;
244
+ inset: 0;
245
+ transform: v-bind(cssTargetScale);
246
+ }
247
+ }
248
+ </style>
@@ -5,11 +5,13 @@
5
5
  </template>
6
6
 
7
7
  <script lang="ts" setup>
8
- type Props = {
8
+ defineProps<{
9
9
  horizontal?: boolean
10
- }
10
+ }>()
11
11
 
12
- defineProps<Props>()
12
+ defineSlots<{
13
+ default(): any
14
+ }>()
13
15
  </script>
14
16
 
15
17
  <style lang="postcss" scoped>
@@ -21,9 +23,9 @@ defineProps<Props>()
21
23
  background-color: var(--color-neutral-background-primary);
22
24
  border: 0.1rem solid var(--color-neutral-border);
23
25
  border-radius: 0.8rem;
24
- }
25
26
 
26
- .horizontal {
27
- flex-direction: row;
27
+ &.horizontal {
28
+ flex-direction: row;
29
+ }
28
30
  }
29
31
  </style>
@@ -0,0 +1,103 @@
1
+ <!-- v1 -->
2
+ <template>
3
+ <div class="ui-card-numbers" :class="sizeClass">
4
+ <span class="label" :class="labelFontClass">{{ label }}</span>
5
+ <div class="values" :class="sizeClass">
6
+ <span v-if="percentValue" class="value typo c2-semi-bold">
7
+ {{ percentValue }}
8
+ </span>
9
+
10
+ <div class="value" :class="valueFontClass">
11
+ {{ value ?? '-' }}<span class="unit" :class="unitFontClass">{{ unit }}</span>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script setup lang="ts" generic="TSize extends 'small' | 'medium'">
18
+ import { toVariants } from '@core/utils/to-variants.util'
19
+ import { computed } from 'vue'
20
+ import { useI18n } from 'vue-i18n'
21
+
22
+ const props = defineProps<{
23
+ label: string
24
+ size: TSize
25
+ value?: number
26
+ unit?: string
27
+ max?: TSize extends 'small' ? number : never
28
+ }>()
29
+
30
+ const { n } = useI18n()
31
+
32
+ const sizeClass = computed(() => toVariants({ size: props.size }))
33
+
34
+ const labelFontClass = computed(() => (props.size === 'medium' ? 'typo c3-semi-bold' : 'typo c2-semi-bold'))
35
+
36
+ const valueFontClass = computed(() => (props.size === 'medium' ? 'typo h3-semi-bold' : 'typo c2-semi-bold'))
37
+
38
+ const unitFontClass = computed(() => (props.size === 'medium' ? 'typo p2-medium' : 'typo c2-semi-bold'))
39
+
40
+ const percentValue = computed(() => {
41
+ if (props.size !== 'small' || props.max === undefined || props.max === 0) {
42
+ return undefined
43
+ }
44
+
45
+ if (props.value === undefined) {
46
+ return n(0, 'percent').replace('0', '-')
47
+ }
48
+
49
+ return n(props.value / props.max, 'percent')
50
+ })
51
+ </script>
52
+
53
+ <style lang="postcss" scoped>
54
+ .ui-card-numbers {
55
+ display: flex;
56
+ width: fit-content;
57
+
58
+ .values {
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: 0.8rem;
62
+ }
63
+
64
+ .value {
65
+ color: var(--color-neutral-txt-primary);
66
+ display: flex;
67
+ gap: 0.2rem;
68
+ align-items: center;
69
+ }
70
+
71
+ .unit {
72
+ color: var(--color-neutral-txt-primary);
73
+ }
74
+
75
+ /* SIZE VARIANTS */
76
+
77
+ &.size--small {
78
+ gap: 0.8rem;
79
+ flex-direction: row;
80
+
81
+ .label {
82
+ color: var(--color-neutral-txt-primary);
83
+ }
84
+
85
+ .values {
86
+ align-items: flex-end;
87
+ }
88
+ }
89
+
90
+ &.size--medium {
91
+ gap: 0.4rem;
92
+ flex-direction: column;
93
+
94
+ .label {
95
+ color: var(--color-neutral-txt-secondary);
96
+ }
97
+
98
+ .values {
99
+ align-items: flex-start;
100
+ }
101
+ }
102
+ }
103
+ </style>
@@ -0,0 +1,24 @@
1
+ <!-- v1 -->
2
+ <template>
3
+ <div class="ui-card-subtitle">
4
+ <span class="typo h7-semi-bold"><slot /></span>
5
+ <span v-if="slots.info" class="typo p3-medium"><slot name="info" /></span>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ const slots = defineSlots<{
11
+ default(): any
12
+ info?(): any
13
+ }>()
14
+ </script>
15
+
16
+ <style lang="postcss" scoped>
17
+ .ui-card-subtitle {
18
+ color: var(--color-info-txt-base);
19
+ border-bottom: 0.1rem solid var(--color-info-txt-base);
20
+ display: flex;
21
+ justify-content: space-between;
22
+ gap: 0.8rem;
23
+ }
24
+ </style>
@@ -0,0 +1,56 @@
1
+ <!-- v1 -->
2
+ <template>
3
+ <div class="ui-card-title">
4
+ <div class="main-content">
5
+ <div class="title typo h6-medium">
6
+ <slot />
7
+ </div>
8
+ <div v-if="slots.info" class="info typo h7-semi-bold">
9
+ <slot name="info" />
10
+ </div>
11
+ </div>
12
+ <p v-if="slots.description" class="description typo p3-regular">
13
+ <slot name="description" />
14
+ </p>
15
+ </div>
16
+ </template>
17
+
18
+ <script lang="ts" setup>
19
+ const slots = defineSlots<{
20
+ default(): any
21
+ info?(): any
22
+ description?(): any
23
+ }>()
24
+ </script>
25
+
26
+ <style lang="postcss" scoped>
27
+ .ui-card-title {
28
+ display: flex;
29
+ flex-direction: column;
30
+
31
+ .main-content {
32
+ display: flex;
33
+ gap: 1.6rem;
34
+ align-items: center;
35
+ }
36
+
37
+ .title {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 1.6rem;
41
+ color: var(--color-neutral-txt-primary);
42
+ }
43
+
44
+ .info {
45
+ margin-left: auto;
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 0.8rem;
49
+ color: var(--color-info-txt-base);
50
+ }
51
+
52
+ .description {
53
+ color: var(--color-neutral-txt-secondary);
54
+ }
55
+ }
56
+ </style>