@xen-orchestra/web-core 0.0.1

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 (91) hide show
  1. package/lib/assets/css/_colors.pcss +125 -0
  2. package/lib/assets/css/_context.pcss +99 -0
  3. package/lib/assets/css/_fonts.pcss +6 -0
  4. package/lib/assets/css/_reset.pcss +42 -0
  5. package/lib/assets/css/_shadows.pcss +36 -0
  6. package/lib/assets/css/_typography.pcss +6 -0
  7. package/lib/assets/css/base.pcss +91 -0
  8. package/lib/assets/css/typography/_legacy.pcss +123 -0
  9. package/lib/assets/css/typography/_letter-spacing.pcss +27 -0
  10. package/lib/assets/css/typography/_line-height.pcss +19 -0
  11. package/lib/assets/css/typography/_size.pcss +95 -0
  12. package/lib/assets/css/typography/_style.pcss +34 -0
  13. package/lib/assets/css/typography/_weight.pcss +57 -0
  14. package/lib/assets/user.png +0 -0
  15. package/lib/components/PowerStateIcon.vue +46 -0
  16. package/lib/components/StatusPill.vue +32 -0
  17. package/lib/components/UiCounter.vue +89 -0
  18. package/lib/components/UiSpinner.vue +48 -0
  19. package/lib/components/UiTag.vue +97 -0
  20. package/lib/components/button/ButtonGroup.vue +33 -0
  21. package/lib/components/button/ButtonIcon.vue +199 -0
  22. package/lib/components/button/UiButton.vue +207 -0
  23. package/lib/components/chip/ChipIcon.vue +29 -0
  24. package/lib/components/chip/ChipRemoveIcon.vue +13 -0
  25. package/lib/components/chip/UiChip.vue +138 -0
  26. package/lib/components/dropdown/DropdownItem.vue +192 -0
  27. package/lib/components/dropdown/DropdownList.vue +31 -0
  28. package/lib/components/dropdown/DropdownTitle.vue +65 -0
  29. package/lib/components/icon/ComplexIcon.vue +51 -0
  30. package/lib/components/icon/ObjectIcon.vue +243 -0
  31. package/lib/components/icon/UiIcon.vue +47 -0
  32. package/lib/components/icon/VmIcon.vue +30 -0
  33. package/lib/components/layout/LayoutSidebar.vue +100 -0
  34. package/lib/components/menu/MenuItem.vue +82 -0
  35. package/lib/components/menu/MenuList.vue +104 -0
  36. package/lib/components/menu/MenuSeparator.vue +27 -0
  37. package/lib/components/menu/MenuTrigger.vue +52 -0
  38. package/lib/components/tab/TabItem.vue +100 -0
  39. package/lib/components/tab/TabList.vue +32 -0
  40. package/lib/components/tooltip/TooltipItem.vue +80 -0
  41. package/lib/components/tooltip/TooltipList.vue +15 -0
  42. package/lib/components/tree/TreeItem.vue +34 -0
  43. package/lib/components/tree/TreeItemError.vue +13 -0
  44. package/lib/components/tree/TreeItemLabel.vue +128 -0
  45. package/lib/components/tree/TreeLine.vue +51 -0
  46. package/lib/components/tree/TreeList.vue +14 -0
  47. package/lib/components/tree/TreeLoadingItem.vue +64 -0
  48. package/lib/components/user/UserLink.vue +72 -0
  49. package/lib/components/user/UserLogo.vue +57 -0
  50. package/lib/composables/context.composable.ts +34 -0
  51. package/lib/composables/tree/branch-definition.ts +17 -0
  52. package/lib/composables/tree/branch.ts +143 -0
  53. package/lib/composables/tree/build-nodes.ts +20 -0
  54. package/lib/composables/tree/define-branch.ts +23 -0
  55. package/lib/composables/tree/define-leaf.ts +16 -0
  56. package/lib/composables/tree/define-tree.ts +65 -0
  57. package/lib/composables/tree/leaf-definition.ts +8 -0
  58. package/lib/composables/tree/leaf.ts +34 -0
  59. package/lib/composables/tree/tree-node-base.ts +103 -0
  60. package/lib/composables/tree/tree-node-definition-base.ts +12 -0
  61. package/lib/composables/tree/types.ts +92 -0
  62. package/lib/composables/tree-filter.composable.ts +12 -0
  63. package/lib/composables/tree.composable.ts +85 -0
  64. package/lib/context.ts +10 -0
  65. package/lib/directives/tooltip.directive.md +117 -0
  66. package/lib/directives/tooltip.directive.ts +52 -0
  67. package/lib/i18n.ts +158 -0
  68. package/lib/layouts/CoreLayout.vue +182 -0
  69. package/lib/locales/de.json +6 -0
  70. package/lib/locales/en.json +15 -0
  71. package/lib/locales/fr.json +15 -0
  72. package/lib/stores/panel.store.ts +12 -0
  73. package/lib/stores/sidebar.store.ts +63 -0
  74. package/lib/stores/tooltip.store.ts +74 -0
  75. package/lib/stores/ui.store.ts +34 -0
  76. package/lib/types/button.type.ts +3 -0
  77. package/lib/types/color.type.ts +5 -0
  78. package/lib/types/object-icon.type.ts +43 -0
  79. package/lib/types/power-state.type.ts +1 -0
  80. package/lib/types/size.type.ts +3 -0
  81. package/lib/types/subscribable-store.type.ts +21 -0
  82. package/lib/types/utility.type.ts +1 -0
  83. package/lib/utils/create-subscribable-store-context.util.ts +66 -0
  84. package/lib/utils/has-ellipsis.util.ts +11 -0
  85. package/lib/utils/if-else.utils.ts +27 -0
  86. package/lib/utils/injection-keys.util.ts +17 -0
  87. package/lib/utils/sort-by-name-label.util.ts +6 -0
  88. package/lib/utils/to-array.utils.ts +9 -0
  89. package/lib/utils/unique-id.util.ts +8 -0
  90. package/package.json +45 -0
  91. package/tsconfig.json +12 -0
@@ -0,0 +1,207 @@
1
+ <!-- v1.0 -->
2
+ <template>
3
+ <button :class="className" :disabled="busy || isDisabled" class="ui-button" type="button">
4
+ <UiIcon :busy :icon="leftIcon" class="icon" fixed-width />
5
+ <slot />
6
+ <UiIcon :icon="rightIcon" class="icon" fixed-width />
7
+ </button>
8
+ </template>
9
+
10
+ <script lang="ts" setup>
11
+ import UiIcon from '@core/components/icon/UiIcon.vue'
12
+ import { useContext } from '@core/composables/context.composable'
13
+ import { DisabledContext } from '@core/context'
14
+ import type { ButtonLevel, ButtonSize } from '@core/types/button.type'
15
+ import type { Color } from '@core/types/color.type'
16
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
17
+ import { computed } from 'vue'
18
+
19
+ const props = withDefaults(
20
+ defineProps<{
21
+ level?: ButtonLevel
22
+ busy?: boolean
23
+ disabled?: boolean
24
+ leftIcon?: IconDefinition
25
+ rightIcon?: IconDefinition
26
+ color?: Color
27
+ size?: ButtonSize
28
+ }>(),
29
+ {
30
+ disabled: undefined,
31
+ color: 'info',
32
+ level: 'primary',
33
+ size: 'small',
34
+ }
35
+ )
36
+
37
+ const isDisabled = useContext(DisabledContext, () => props.disabled)
38
+
39
+ const fontClasses = {
40
+ 'extra-small': 'typo p3-medium',
41
+ small: 'typo h6-medium',
42
+ medium: 'typo h3-semi-bold',
43
+ }
44
+
45
+ const className = computed(() => {
46
+ return [
47
+ props.color,
48
+ props.level,
49
+ props.size,
50
+ fontClasses[props.size],
51
+ {
52
+ busy: props.busy,
53
+ disabled: isDisabled.value,
54
+ },
55
+ ]
56
+ })
57
+ </script>
58
+
59
+ <style lang="postcss" scoped>
60
+ /* COLOR VARIANTS */
61
+ .ui-button {
62
+ &.info {
63
+ --accent-color: var(--color-purple-base);
64
+
65
+ &:is(:hover, .hover, :focus-visible) {
66
+ --accent-color: var(--color-purple-d20);
67
+ }
68
+
69
+ &:is(:active, .pressed) {
70
+ --accent-color: var(--color-purple-d40);
71
+ }
72
+
73
+ &:is(:disabled, .disabled) {
74
+ --accent-color: var(--color-grey-400);
75
+ }
76
+ }
77
+
78
+ &.success {
79
+ --accent-color: var(--color-green-base);
80
+
81
+ &:is(:hover, .hover, :focus-visible) {
82
+ --accent-color: var(--color-green-d20);
83
+ }
84
+
85
+ &:is(:active, .pressed) {
86
+ --accent-color: var(--color-green-d40);
87
+ }
88
+
89
+ &:is(:disabled, .disabled) {
90
+ --accent-color: var(--color-green-l60);
91
+ }
92
+ }
93
+
94
+ &.warning {
95
+ --accent-color: var(--color-orange-base);
96
+
97
+ &:is(:hover, .hover, :focus-visible) {
98
+ --accent-color: var(--color-orange-d20);
99
+ }
100
+
101
+ &:is(:active, .pressed) {
102
+ --accent-color: var(--color-orange-d40);
103
+ }
104
+
105
+ &:is(:disabled, .disabled) {
106
+ --accent-color: var(--color-orange-l60);
107
+ }
108
+ }
109
+
110
+ &:is(.danger, .error) {
111
+ --accent-color: var(--color-red-base);
112
+
113
+ &:is(:hover, .hover, :focus-visible) {
114
+ --accent-color: var(--color-red-d20);
115
+ }
116
+
117
+ &:is(:active, .pressed) {
118
+ --accent-color: var(--color-red-d40);
119
+ }
120
+
121
+ &:is(:disabled, .disabled) {
122
+ --accent-color: var(--color-red-l60);
123
+ }
124
+ }
125
+ }
126
+
127
+ /* SIZE VARIANTS */
128
+ .ui-button {
129
+ &.extra-small {
130
+ --padding: 0.4rem 0.8rem;
131
+
132
+ &.tertiary {
133
+ --padding: 0;
134
+ }
135
+ }
136
+
137
+ &.small {
138
+ --padding: 0.8rem 1.6rem;
139
+
140
+ &.tertiary {
141
+ --padding: 0.2rem 0;
142
+ }
143
+ }
144
+
145
+ &.medium {
146
+ --padding: 1.6rem 2.4rem;
147
+
148
+ &.tertiary {
149
+ --padding: 0.4rem 0;
150
+ }
151
+ }
152
+ }
153
+
154
+ /* LEVELS VARIANTS */
155
+ .ui-button {
156
+ &.primary {
157
+ --color: var(--color-grey-600);
158
+ --background-color: var(--accent-color);
159
+ --border-color: var(--accent-color);
160
+ --border-style: solid;
161
+ --border-radius: 0.8rem;
162
+ }
163
+
164
+ &.secondary {
165
+ --color: var(--accent-color);
166
+ --background-color: var(--background-color-primary);
167
+ --border-color: var(--accent-color);
168
+ --border-style: solid;
169
+ --border-radius: 0.8rem;
170
+ }
171
+
172
+ &.tertiary {
173
+ --color: var(--accent-color);
174
+ --background-color: transparent;
175
+ --border-color: var(--accent-color);
176
+ --border-style: none none solid;
177
+ --border-radius: 0;
178
+ }
179
+ }
180
+
181
+ /* IMPLEMENTATION */
182
+ .ui-button {
183
+ display: inline-flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ cursor: pointer;
187
+ vertical-align: middle;
188
+ gap: 0.75em;
189
+ border-width: 0.1rem;
190
+ outline: none;
191
+ border-color: var(--border-color);
192
+ border-radius: var(--border-radius);
193
+ border-style: var(--border-style);
194
+ color: var(--color);
195
+ background-color: var(--background-color);
196
+ padding: var(--padding);
197
+
198
+ &.busy,
199
+ &.disabled {
200
+ cursor: not-allowed;
201
+ }
202
+ }
203
+
204
+ .icon {
205
+ font-size: 0.8em;
206
+ }
207
+ </style>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <UiIcon :class="{ disabled }" :color :icon class="chip-icon" fixed-width />
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import UiIcon from '@core/components/icon/UiIcon.vue'
7
+ import type { Color } from '@core/types/color.type'
8
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
9
+
10
+ defineProps<{
11
+ color: Color
12
+ icon?: IconDefinition
13
+ disabled?: boolean
14
+ }>()
15
+ </script>
16
+
17
+ <style lang="postcss" scoped>
18
+ .chip-icon {
19
+ color: var(--color-grey-200);
20
+
21
+ &.disabled {
22
+ color: var(--color-grey-600);
23
+
24
+ &.info {
25
+ color: var(--color-grey-400);
26
+ }
27
+ }
28
+ }
29
+ </style>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <ButtonIcon :color :icon="faXmark" class="chip-remove-icon" size="small" />
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import ButtonIcon from '@core/components/button/ButtonIcon.vue'
7
+ import type { Color } from '@core/types/color.type'
8
+ import { faXmark } from '@fortawesome/free-solid-svg-icons'
9
+
10
+ defineProps<{
11
+ color: Color
12
+ }>()
13
+ </script>
@@ -0,0 +1,138 @@
1
+ <!-- v1.1 -->
2
+ <template>
3
+ <span :class="[color, { disabled }]" class="ui-chip typo p3-regular" @click="emit('edit')">
4
+ <ChipIcon :color :disabled :icon />
5
+ <span class="content">
6
+ <slot />
7
+ </span>
8
+ <ChipRemoveIcon v-if="!disabled" :color @click.stop="emit('remove')" />
9
+ </span>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import ChipIcon from '@core/components/chip/ChipIcon.vue'
14
+ import ChipRemoveIcon from '@core/components/chip/ChipRemoveIcon.vue'
15
+ import type { Color } from '@core/types/color.type'
16
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
17
+
18
+ withDefaults(
19
+ defineProps<{
20
+ icon?: IconDefinition
21
+ color?: Color
22
+ disabled?: boolean
23
+ }>(),
24
+ { color: 'info' }
25
+ )
26
+
27
+ const emit = defineEmits<{
28
+ (event: 'edit'): void
29
+ (event: 'remove'): void
30
+ }>()
31
+ </script>
32
+
33
+ <style lang="postcss" scoped>
34
+ /* COLOR VARIANTS */
35
+ .ui-chip {
36
+ --color: var(--color-grey-100);
37
+
38
+ &.disabled {
39
+ --color: var(--color-grey-600);
40
+
41
+ &.info {
42
+ --color: var(--color-grey-300);
43
+ }
44
+ }
45
+ }
46
+
47
+ /* BACKGROUND COLOR VARIANTS */
48
+ .ui-chip {
49
+ &.info {
50
+ --background-color: var(--background-color-purple-10);
51
+
52
+ &:is(:hover, .hover, :focus-visible) {
53
+ --background-color: var(--background-color-purple-20);
54
+ }
55
+
56
+ &:is(:active, .pressed) {
57
+ --background-color: var(--background-color-purple-30);
58
+ }
59
+
60
+ &.disabled {
61
+ --background-color: var(--background-color-secondary);
62
+ }
63
+ }
64
+
65
+ &.success {
66
+ --background-color: var(--background-color-green-10);
67
+
68
+ &:is(:hover, .hover, :focus-visible) {
69
+ --background-color: var(--background-color-green-20);
70
+ }
71
+
72
+ &:is(:active, .pressed) {
73
+ --background-color: var(--background-color-green-30);
74
+ }
75
+
76
+ &.disabled {
77
+ --background-color: var(--color-green-l60);
78
+ }
79
+ }
80
+
81
+ &.warning {
82
+ --background-color: var(--background-color-orange-10);
83
+
84
+ &:is(:hover, .hover, :focus-visible) {
85
+ --background-color: var(--background-color-orange-20);
86
+ }
87
+
88
+ &:is(:active, .pressed) {
89
+ --background-color: var(--background-color-orange-30);
90
+ }
91
+
92
+ &.disabled {
93
+ --background-color: var(--color-orange-l60);
94
+ }
95
+ }
96
+
97
+ &:is(.danger, .error) {
98
+ --background-color: var(--background-color-red-10);
99
+
100
+ &:is(:hover, .hover, :focus-visible) {
101
+ --background-color: var(--background-color-red-20);
102
+ }
103
+
104
+ &:is(:active, .pressed) {
105
+ --background-color: var(--background-color-red-30);
106
+ }
107
+
108
+ &.disabled {
109
+ --background-color: var(--color-red-l60);
110
+ }
111
+ }
112
+ }
113
+
114
+ /* IMPLEMENTATION */
115
+ .ui-chip {
116
+ display: inline-flex;
117
+ align-items: center;
118
+ gap: 0.8rem;
119
+ padding: 0.4rem 0.8rem;
120
+ border-radius: 10rem;
121
+ color: var(--color);
122
+ background-color: var(--background-color);
123
+ cursor: pointer;
124
+ min-height: 2.4rem;
125
+ vertical-align: middle;
126
+ white-space: nowrap;
127
+
128
+ &.disabled {
129
+ pointer-events: none;
130
+ }
131
+
132
+ .content {
133
+ line-height: 1.6rem;
134
+ overflow: hidden;
135
+ text-overflow: ellipsis;
136
+ }
137
+ }
138
+ </style>
@@ -0,0 +1,192 @@
1
+ <template>
2
+ <div v-tooltip="{ selector: '.label' }" :class="[color, { disabled, selected }]" class="dropdown-item">
3
+ <UiIcon v-if="checkbox" :color="color ?? 'info'" :icon="selected ? faSquareCheck : faSquare" />
4
+ <slot name="icon">
5
+ <UiIcon :icon />
6
+ </slot>
7
+ <div class="label p2 medium">
8
+ <slot />
9
+ </div>
10
+ <div v-if="info" class="info-text p3 italic">{{ info }}</div>
11
+ <UiIcon v-if="arrow" :color="disabled ? undefined : 'info'" :icon="faAngleRight" class="right-icon" />
12
+ </div>
13
+ </template>
14
+
15
+ <script lang="ts" setup>
16
+ import UiIcon from '@core/components/icon/UiIcon.vue'
17
+ import { vTooltip } from '@core/directives/tooltip.directive'
18
+ import type { Color } from '@core/types/color.type'
19
+ import { IK_DROPDOWN_CHECKBOX } from '@core/utils/injection-keys.util'
20
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
21
+ import { faSquare } from '@fortawesome/free-regular-svg-icons'
22
+ import { faAngleRight, faSquareCheck } from '@fortawesome/free-solid-svg-icons'
23
+ import { computed, inject } from 'vue'
24
+
25
+ defineProps<{
26
+ arrow?: boolean
27
+ color?: Color
28
+ disabled?: boolean
29
+ icon?: IconDefinition
30
+ info?: string
31
+ selected?: boolean
32
+ }>()
33
+
34
+ const checkbox = inject(
35
+ IK_DROPDOWN_CHECKBOX,
36
+ computed(() => false)
37
+ )
38
+ </script>
39
+
40
+ <style lang="postcss" scoped>
41
+ /* COLOR VARIANTS */
42
+ .dropdown-item {
43
+ & {
44
+ --color: var(--color-grey-100);
45
+ --background-color: var(--background-color-primary);
46
+
47
+ &:is(.active, .selected) {
48
+ --color: var(--color-grey-100);
49
+ --background-color: var(--background-color-purple-10);
50
+ }
51
+
52
+ &:is(:hover, .hover, :focus-visible) {
53
+ --color: var(--color-grey-100);
54
+ --background-color: var(--background-color-purple-20);
55
+ }
56
+
57
+ &:is(:active, .pressed) {
58
+ --color: var(--color-grey-100);
59
+ --background-color: var(--background-color-purple-30);
60
+ }
61
+
62
+ &.disabled {
63
+ --color: var(--color-grey-400);
64
+ --background-color: var(--background-color-primary);
65
+ }
66
+ }
67
+
68
+ &.info {
69
+ --color: var(--color-purple-base);
70
+ --background-color: var(--background-color-primary);
71
+
72
+ &:is(.active, .selected) {
73
+ --color: var(--color-purple-base);
74
+ --background-color: var(--background-color-purple-10);
75
+ }
76
+
77
+ &:is(:hover, .hover, :focus-visible) {
78
+ --color: var(--color-purple-d20);
79
+ --background-color: var(--background-color-purple-20);
80
+ }
81
+
82
+ &:is(:active, .pressed) {
83
+ --color: var(--color-purple-d40);
84
+ --background-color: var(--background-color-purple-30);
85
+ }
86
+
87
+ &.disabled {
88
+ --color: var(--color-purple-l60);
89
+ --background-color: var(--background-color-primary);
90
+ }
91
+ }
92
+
93
+ &.success {
94
+ --color: var(--color-green-base);
95
+ --background-color: var(--background-color-primary);
96
+
97
+ &:is(.active, .selected) {
98
+ --color: var(--color-green-base);
99
+ --background-color: var(--background-color-green-10);
100
+ }
101
+
102
+ &:is(:hover, .hover, :focus-visible) {
103
+ --color: var(--color-green-d20);
104
+ --background-color: var(--background-color-green-20);
105
+ }
106
+
107
+ &:is(:active, .pressed) {
108
+ --color: var(--color-green-d40);
109
+ --background-color: var(--background-color-green-30);
110
+ }
111
+
112
+ &.disabled {
113
+ --color: var(--color-green-l60);
114
+ --background-color: var(--background-color-primary);
115
+ }
116
+ }
117
+
118
+ &.warning {
119
+ --color: var(--color-orange-base);
120
+ --background-color: var(--background-color-primary);
121
+
122
+ &:is(.active, .selected) {
123
+ --color: var(--color-orange-base);
124
+ --background-color: var(--background-color-orange-10);
125
+ }
126
+
127
+ &:is(:hover, .hover, :focus-visible) {
128
+ --color: var(--color-orange-d20);
129
+ --background-color: var(--background-color-orange-20);
130
+ }
131
+
132
+ &:is(:active, .pressed) {
133
+ --color: var(--color-orange-d40);
134
+ --background-color: var(--background-color-orange-30);
135
+ }
136
+
137
+ &.disabled {
138
+ --color: var(--color-orange-l60);
139
+ --background-color: var(--background-color-primary);
140
+ }
141
+ }
142
+
143
+ &:is(.error, .danger) {
144
+ --color: var(--color-red-base);
145
+ --background-color: var(--background-color-primary);
146
+
147
+ &:is(.active, .selected) {
148
+ --color: var(--color-red-base);
149
+ --background-color: var(--background-color-red-10);
150
+ }
151
+
152
+ &:is(:hover, .hover, :focus-visible) {
153
+ --color: var(--color-red-d20);
154
+ --background-color: var(--background-color-red-20);
155
+ }
156
+
157
+ &:is(:active, .pressed) {
158
+ --color: var(--color-red-d40);
159
+ --background-color: var(--background-color-red-30);
160
+ }
161
+
162
+ &.disabled {
163
+ --color: var(--color-red-l60);
164
+ --background-color: var(--background-color-primary);
165
+ }
166
+ }
167
+ }
168
+
169
+ /* IMPLEMENTATION */
170
+ .dropdown-item {
171
+ display: flex;
172
+ align-items: center;
173
+ padding: 0.8rem;
174
+ gap: 0.8rem;
175
+ height: 3.7rem;
176
+ color: var(--color);
177
+ background: var(--background-color);
178
+ border-radius: 0.4rem;
179
+ margin: 0 0.4rem;
180
+ }
181
+
182
+ .label {
183
+ margin-right: auto;
184
+ white-space: nowrap;
185
+ overflow: hidden;
186
+ text-overflow: ellipsis;
187
+ }
188
+
189
+ .info-text {
190
+ color: var(--color-grey-300);
191
+ }
192
+ </style>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <div class="dropdown-list">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import { IK_DROPDOWN_CHECKBOX } from '@core/utils/injection-keys.util'
9
+ import { computed, provide } from 'vue'
10
+
11
+ const props = defineProps<{
12
+ checkbox?: boolean
13
+ }>()
14
+
15
+ provide(
16
+ IK_DROPDOWN_CHECKBOX,
17
+ computed(() => props.checkbox)
18
+ )
19
+ </script>
20
+
21
+ <style lang="postcss" scoped>
22
+ .dropdown-list {
23
+ display: flex;
24
+ flex-direction: column;
25
+ padding: 0.4rem 0;
26
+ gap: 0.2rem;
27
+ border-radius: 0.4rem;
28
+ background: var(--background-color-primary);
29
+ box-shadow: var(--shadow-300);
30
+ }
31
+ </style>
@@ -0,0 +1,65 @@
1
+ <!--
2
+ "Select all" / "Deselect all" spans are temporary, until we have a tertiary button
3
+ TODO: Replace `span` with `UiButton` when new version (with tertiary) is available
4
+ -->
5
+ <template>
6
+ <div class="dropdown-title">
7
+ <UiIcon :icon />
8
+ <div class="label c3 semi-bold">
9
+ <slot />
10
+ </div>
11
+ <div v-if="onToggleSelectAll" class="buttons">
12
+ <span v-if="selected !== 'all'" @click="emit('toggleSelectAll', true)">Select all</span>
13
+ <span v-if="selected !== 'none'" @click="emit('toggleSelectAll', false)">Deselect all</span>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script lang="ts" setup>
19
+ import UiIcon from '@core/components/icon/UiIcon.vue'
20
+ import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
21
+
22
+ withDefaults(
23
+ defineProps<{
24
+ icon?: IconDefinition
25
+ selected?: 'all' | 'some' | 'none'
26
+ onToggleSelectAll?: (value: boolean) => void
27
+ }>(),
28
+ { selected: 'none' }
29
+ )
30
+
31
+ const emit = defineEmits<{
32
+ (event: 'toggleSelectAll', value: boolean): void
33
+ }>()
34
+ </script>
35
+
36
+ <style lang="postcss" scoped>
37
+ .dropdown-title {
38
+ display: flex;
39
+ align-items: center;
40
+ padding: 0.4rem 1.6rem;
41
+ gap: 0.8rem;
42
+ height: 2.6rem;
43
+ background: var(--background-color-secondary);
44
+ }
45
+
46
+ .buttons {
47
+ display: flex;
48
+ gap: 0.8rem;
49
+ margin-left: auto;
50
+
51
+ span {
52
+ cursor: pointer;
53
+ text-decoration: underline;
54
+ color: var(--color-purple-base);
55
+
56
+ &:hover {
57
+ color: var(--color-purple-l20);
58
+ }
59
+
60
+ &:active {
61
+ color: var(--color-purple-l40);
62
+ }
63
+ }
64
+ }
65
+ </style>