@appscode/design-system 2.17.25 → 2.17.26-alpha-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 (36) hide show
  1. package/main.scss +4 -1
  2. package/package.json +1 -1
  3. package/vue-components/styles/base/utilities/_global.scss +8 -0
  4. package/vue-components/styles/base/utilities/_typography.scss +5 -0
  5. package/vue-components/styles/components/_ac-duration.scss +50 -0
  6. package/vue-components/styles/components/_file-explore.scss +31 -0
  7. package/vue-components/styles/components/_time-picker.scss +140 -0
  8. package/vue-components/styles/components/cards/_all.scss +1 -1
  9. package/vue-components/styles/components/cards/_cards-group.scss +26 -0
  10. package/vue-components/styles/components/form-fields/_input-card.scss +3 -1
  11. package/vue-components/styles/components/form-fields/_input.scss +65 -2
  12. package/vue-components/v3/alert/AlertLinked.vue +32 -0
  13. package/vue-components/v3/cards/UsageTableCard.vue +56 -4
  14. package/vue-components/v3/cards/UsageTableCardTwo.vue +162 -0
  15. package/vue-components/v3/config-secret/ConfigSecret.vue +61 -0
  16. package/vue-components/v3/editor/Editor.vue +3 -4
  17. package/vue-components/v3/form-fields/AcSingleInput.vue +20 -0
  18. package/vue-components/v3/form-fields/CheckRadio.vue +3 -1
  19. package/vue-components/v3/icons/ArrowDownLongIcon.vue +8 -0
  20. package/vue-components/v3/icons/ArrowRightIcon.vue +14 -0
  21. package/vue-components/v3/icons/BillableInfo.vue +13 -0
  22. package/vue-components/v3/icons/InfoLightIcon.vue +15 -0
  23. package/vue-components/v3/icons/MachineCpuIcon.vue +8 -0
  24. package/vue-components/v3/icons/MachineMemoryIcon.vue +8 -0
  25. package/vue-components/v3/icons/StorageIcon-2.vue +14 -0
  26. package/vue-components/v3/navbar/Appdrawer.vue +1 -1
  27. package/vue-components/v3/node-selection/NodeSelection.vue +82 -0
  28. package/vue-components/v3/postgres/Postgres.vue +33 -0
  29. package/vue-components/v3/replica-set/MachineProfile.vue +119 -0
  30. package/vue-components/v3/replica-set/MultiMachineProfile.vue +100 -0
  31. package/vue-components/v3/replica-set/UpgradeSet.vue +40 -0
  32. package/vue-components/v3/scaling-rules/ScalingRules.vue +93 -0
  33. package/vue-components/v3/section/SectionContent.vue +1 -1
  34. package/vue-components/v3/threshold/UsageThreshold.vue +24 -0
  35. package/vue-components/v3/time/AcDuration.vue +167 -0
  36. package/vue-components/v3/time/AcDurationNew.vue +235 -0
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ import { defineAsyncComponent } from "vue";
3
+ import InfoLightIcon from "@/components/vue-components/v3/icons/InfoLightIcon.vue";
4
+ import CrossIcon from "@/components/vue-components/v3/icons/CrossIcon.vue";
5
+
6
+ const StorageIcon2 = defineAsyncComponent(() => import("@/components/vue-components/v3/icons/StorageIcon-2.vue"));
7
+ const ArrowDownLongIcon = defineAsyncComponent(
8
+ () => import("@/components/vue-components/v3/icons/ArrowDownLongIcon.vue"),
9
+ );
10
+
11
+ interface Props {
12
+ title?: string;
13
+ initialStorage?: string;
14
+ rules: {
15
+ percent?: string;
16
+ size?: string;
17
+ role?: string;
18
+ showAddButton?: boolean;
19
+ showSaveDeleteButtons?: boolean;
20
+ }[];
21
+ }
22
+
23
+ withDefaults(defineProps<Props>(), {
24
+ title: "",
25
+ initialStorage: "",
26
+ rules: () => [],
27
+ });
28
+
29
+ const emit = defineEmits(["add-role", "save", "delete"]);
30
+
31
+ function addRole() {
32
+ emit("add-role");
33
+ }
34
+
35
+ function saveRules() {
36
+ emit("save");
37
+ }
38
+
39
+ function deleteRule() {
40
+ emit("delete");
41
+ }
42
+ </script>
43
+
44
+ <template>
45
+ <h5>{{ title }}</h5>
46
+
47
+ <span class="mb-4 is-inline-flex text-code px-2">Initial Storage</span>
48
+ <div class="is-flex is-flex-direction-column is-relative">
49
+ <div class="icon-with-input is-inactive width-120">
50
+ <label class="icon" for="initial">
51
+ <StorageIcon2 class="width-18" />
52
+ </label>
53
+ <div class="is-flex is-align-items-center px-2">{{ initialStorage }}</div>
54
+ </div>
55
+
56
+ <div v-for="(rule, index) in rules" :key="index" class="is-relative mt-4">
57
+ <div class="is-inline-flex is-align-items-center" style="margin-left: 52px">
58
+ <ArrowDownLongIcon />
59
+ <div class="input-with-icon width-80" style="margin: 4px">
60
+ <input type="text" class="ac-input" :value="rule.percent" />
61
+ <label class="icon">
62
+ <InfoLightIcon class="width-18" />
63
+ </label>
64
+ </div>
65
+ <p v-if="rule.role" class="ml-2">{{ rule.role }}</p>
66
+ </div>
67
+
68
+ <div class="is-flex is-align-items-center gap-8">
69
+ <div class="icon-with-input width-120">
70
+ <label class="icon">
71
+ <StorageIcon2 class="width-18" />
72
+ </label>
73
+ <input type="text" class="ac-input" :value="rule.size" />
74
+ </div>
75
+
76
+ <div class="buttons" v-if="rule.showAddButton || rule.showSaveDeleteButtons">
77
+ <button v-if="rule.showAddButton" class="button ac-button is-primary is-outlined is-soft" @click="addRole">
78
+ Add New Role
79
+ </button>
80
+
81
+ <template v-if="rule.showSaveDeleteButtons">
82
+ <button class="button ac-button is-primary is-outlined is-soft" @click="saveRules">Save</button>
83
+ <button class="button ac-button is-danger is-outlined is-soft" @click="deleteRule">
84
+ <span class="icon">
85
+ <CrossIcon />
86
+ </span>
87
+ </button>
88
+ </template>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </template>
@@ -4,7 +4,7 @@ import ArrowIcon from "../icons/ArrowIcon.vue";
4
4
  import AcButton from "../button/Button.vue";
5
5
  import HeaderItem from "../header/HeaderItem.vue";
6
6
  import HeaderItems from "../header/HeaderItems.vue";
7
- import ArrowUturnLeft from "../icons/ArrowUturnLeft.vue";
7
+ import HeroiconsArrowUturnLeft20Solid from "~icons/heroicons/arrow-uturn-left-20-solid.svg";
8
8
 
9
9
  interface Props {
10
10
  title?: string;
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ interface Props {
3
+ title?: string;
4
+ subtitle?: string;
5
+ minRange?: number;
6
+ maxRange?: number;
7
+ }
8
+
9
+ withDefaults(defineProps<Props>(), {
10
+ title: "",
11
+ subtitle: "",
12
+ });
13
+
14
+ const threshold = defineModel<number>();
15
+ </script>
16
+
17
+ <template>
18
+ <h5>{{ title }}</h5>
19
+ <p>{{ subtitle }}</p>
20
+ <div class="ac-range">
21
+ <input v-model="threshold" type="range" :min="minRange" :max="maxRange" value="50" />
22
+ <span class="pl-8">{{ threshold }}</span>
23
+ </div>
24
+ </template>
@@ -0,0 +1,167 @@
1
+ <script setup lang="ts">
2
+ import { defineAsyncComponent, ref } from "vue";
3
+
4
+ interface Props {
5
+ modifierClasses?: string;
6
+ label?: string;
7
+ required?: boolean;
8
+ }
9
+
10
+ withDefaults(defineProps<Props>(), {
11
+ modifierClasses: "",
12
+ label: "Default",
13
+ required: false,
14
+ });
15
+
16
+ const showDuration = ref(false);
17
+ const selectedDay = ref(0);
18
+ const selectedHour = ref(0);
19
+ const selectedMinute = ref(0);
20
+
21
+ const AcSingleInput = defineAsyncComponent(
22
+ () => import("@/components/vue-components/v3/form-fields/AcSingleInput.vue"),
23
+ );
24
+
25
+ const vClickOutside = {
26
+ mounted(el: any, binding: any) {
27
+ el.__clickOutsideHandler__ = (event: any) => {
28
+ if (!(el === event.target || el.contains(event.target))) {
29
+ binding.value(event);
30
+ }
31
+ };
32
+ document.addEventListener("click", el.__clickOutsideHandler__);
33
+ },
34
+ unmounted(el: any) {
35
+ document.removeEventListener("click", el.__clickOutsideHandler__);
36
+ },
37
+ };
38
+
39
+ function handleScroll(type: "day" | "hour" | "minute") {
40
+ const container = document.querySelector(`.${type}-scroll`);
41
+ if (!container) return;
42
+
43
+ const scrollTop = container.scrollTop;
44
+ const itemHeight = container.querySelector("li")?.clientHeight || 0;
45
+ const containerHeight = container.clientHeight;
46
+
47
+ // Correctly calculate the middle index
48
+ const middleIndex = Math.round((scrollTop + containerHeight / 2 - itemHeight / 2) / itemHeight);
49
+
50
+ if (type === "day") {
51
+ selectedDay.value = middleIndex;
52
+ } else if (type === "hour") {
53
+ selectedHour.value = middleIndex;
54
+ } else if (type === "minute") {
55
+ selectedMinute.value = middleIndex + 1;
56
+ }
57
+ }
58
+
59
+ function getSelectedValue(type: "day" | "hour" | "minute") {
60
+ if (type === "day") return selectedDay.value;
61
+ if (type === "hour") return selectedHour.value;
62
+ return selectedMinute.value;
63
+ }
64
+
65
+ function setSelectedValue(type: "day" | "hour" | "minute", value: number) {
66
+ if (type === "day") {
67
+ selectedDay.value = value;
68
+ } else if (type === "hour") {
69
+ selectedHour.value = value;
70
+ } else if (type === "minute") {
71
+ selectedMinute.value = value;
72
+ }
73
+ }
74
+ </script>
75
+ <template>
76
+ <div class="ac-duration-wrapper" :class="modifierClasses" v-click-outside="() => (showDuration = false)">
77
+ <ac-single-input class="width-220" @click="showDuration = !showDuration">
78
+ <label for="Value" :class="{ 'ac-label': true, 'is-required': required }">
79
+ {{ selectedDay }}d {{ selectedHour }}h {{ selectedMinute }}m
80
+ </label>
81
+ <input class="ac-input" />
82
+ </ac-single-input>
83
+
84
+ <div class="ac-duration" v-if="showDuration">
85
+ <div class="duration-header has-text-center">
86
+ <h6>Duration</h6>
87
+ </div>
88
+ <div class="duration-body">
89
+ <div class="is-flex">
90
+ <!-- Days -->
91
+ <div class="duration">
92
+ <span>DAY</span>
93
+ <ul class="day-scroll scroll-list" @scroll="handleScroll('day')">
94
+ <li
95
+ v-for="i in Array.from({ length: 30 }, (_, i) => i)"
96
+ :key="'d' + i"
97
+ :class="{ active: getSelectedValue('day') === i }"
98
+ @click="setSelectedValue('day', i)"
99
+ >
100
+ {{ i }}
101
+ </li>
102
+ </ul>
103
+ </div>
104
+
105
+ <!-- Hours -->
106
+ <div class="duration">
107
+ <span>HOUR</span>
108
+ <ul class="hour-scroll scroll-list" @scroll="handleScroll('hour')">
109
+ <li
110
+ v-for="i in Array.from({ length: 24 }, (_, i) => i)"
111
+ :key="'h' + i"
112
+ :class="{ active: getSelectedValue('hour') === i }"
113
+ @click="setSelectedValue('hour', i)"
114
+ >
115
+ {{ i }}
116
+ </li>
117
+ </ul>
118
+ </div>
119
+
120
+ <!-- Minutes -->
121
+ <div class="duration">
122
+ <span>MIN</span>
123
+ <ul class="minute-scroll scroll-list" @scroll="handleScroll('minute')">
124
+ <li
125
+ v-for="i in Array.from({ length: 60 }, (_, i) => i)"
126
+ :key="'m' + i"
127
+ :class="{ active: getSelectedValue('minute') === i }"
128
+ @click="setSelectedValue('minute', i)"
129
+ >
130
+ {{ i }}
131
+ </li>
132
+ </ul>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ <div class="duration-footer">
138
+ <div class="buttons">
139
+ <button class="button ac-button is-small is-outlined" @click="showDuration = false">Cancel</button>
140
+ <button class="button ac-button is-small is-outlined">Ok</button>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ </template>
146
+ <style scoped>
147
+ .scroll-list {
148
+ height: 150px;
149
+ overflow-y: scroll;
150
+ scroll-snap-type: y mandatory;
151
+ padding: 0;
152
+ margin: 0;
153
+ }
154
+ .scroll-list li {
155
+ color: #888;
156
+ }
157
+ .scroll-list li.active {
158
+ color: #007bff;
159
+ font-weight: 600;
160
+ }
161
+
162
+ .duration > span {
163
+ display: block;
164
+ text-align: center;
165
+ margin-bottom: 5px;
166
+ }
167
+ </style>
@@ -0,0 +1,235 @@
1
+ <script setup>
2
+ import { onMounted, onBeforeUnmount } from "vue";
3
+
4
+ function useDraggable(selector) {
5
+ let isDragging = false;
6
+ let startY = 0;
7
+ let scrollTop = 0;
8
+
9
+ const onMouseMove = (e) => {
10
+ if (!isDragging) return;
11
+ const y = e.pageY;
12
+ const walk = y - startY;
13
+ el.scrollTop = scrollTop - walk;
14
+ };
15
+
16
+ const onTouchMove = (e) => {
17
+ if (!isDragging) return;
18
+ const y = e.touches[0].pageY;
19
+ const walk = y - startY;
20
+ el.scrollTop = scrollTop - walk;
21
+ };
22
+
23
+ const stopDrag = () => (isDragging = false);
24
+
25
+ let el;
26
+
27
+ onMounted(() => {
28
+ el = document.querySelector(selector);
29
+ if (!el) return;
30
+
31
+ const startDragMouse = (e) => {
32
+ isDragging = true;
33
+ startY = e.pageY;
34
+ scrollTop = el.scrollTop;
35
+ };
36
+
37
+ const startDragTouch = (e) => {
38
+ isDragging = true;
39
+ startY = e.touches[0].pageY;
40
+ scrollTop = el.scrollTop;
41
+ };
42
+
43
+ el.addEventListener("mousedown", startDragMouse);
44
+ el.addEventListener("touchstart", startDragTouch);
45
+ window.addEventListener("mousemove", onMouseMove);
46
+ window.addEventListener("mouseup", stopDrag);
47
+ window.addEventListener("touchmove", onTouchMove, { passive: false });
48
+ window.addEventListener("touchend", stopDrag);
49
+ });
50
+
51
+ onBeforeUnmount(() => {
52
+ window.removeEventListener("mousemove", onMouseMove);
53
+ window.removeEventListener("mouseup", stopDrag);
54
+ window.removeEventListener("touchmove", onTouchMove);
55
+ window.removeEventListener("touchend", stopDrag);
56
+ });
57
+ }
58
+
59
+ useDraggable(".picker-day");
60
+ useDraggable(".picker-hour");
61
+ useDraggable(".picker-minute");
62
+ </script>
63
+
64
+ <template>
65
+ <div class="picker-wrapper">
66
+ <div class="duration-header"><h6>Duration ( 1day 06h 9min )</h6></div>
67
+ <div class="d-title">
68
+ <span>DAY</span>
69
+ <span>HOUR</span>
70
+ <span>MINUTE</span>
71
+ </div>
72
+ <div class="picker">
73
+ <div class="picker-window"></div>
74
+ <!-- <div class="triangle"></div> -->
75
+
76
+ <ul class="picker-day">
77
+ <li v-for="i in 30" :key="i">{{ i }}</li>
78
+ </ul>
79
+ <ul class="picker-hour">
80
+ <li v-for="i in 24" :key="i">{{ i }}</li>
81
+ </ul>
82
+ <ul class="picker-minute">
83
+ <li v-for="i in 60" :key="i">{{ i }}</li>
84
+ </ul>
85
+ </div>
86
+ <div class="duration-footer is-flex is-justify-content-flex-end pr-8 pb-8">
87
+ <div class="buttons">
88
+ <button class="button ac-button is-small is-outlined" @click="showDuration = false">Cancel</button>
89
+ <button class="button ac-button is-small is-outlined">Ok</button>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </template>
94
+ <style lang="scss" scoped>
95
+ /* ========== Variables ========== */
96
+ $cool-gray: #eff1f1;
97
+ $secondary-light-gray: #f7f9fa;
98
+ $scroll-highlight: darken($cool-gray, 10);
99
+
100
+ /* ========== Mixins ========== */
101
+ @mixin hide-scrollbars {
102
+ -ms-overflow-style: none; // IE 10+
103
+ scrollbar-width: none; // Firefox
104
+ &::-webkit-scrollbar {
105
+ display: none;
106
+ }
107
+ }
108
+
109
+ /* ========== Container ========== */
110
+ .picker-wrapper {
111
+ background: white;
112
+ box-shadow: 0 0.5vw 2vw -5px rgba(0, 0, 0, 0.2);
113
+ display: inline-flex;
114
+ flex-direction: column;
115
+ border-radius: 8px;
116
+ }
117
+
118
+ /* ========== Header ========== */
119
+ .duration-header {
120
+ background-color: $secondary-light-gray;
121
+ text-align: center;
122
+ height: 36px;
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+
127
+ h6 {
128
+ font-size: 13px;
129
+ margin: 0;
130
+ font-weight: 600;
131
+ }
132
+ }
133
+
134
+ /* ========== Title Labels ========== */
135
+ .d-title {
136
+ display: inline-grid;
137
+ grid-template-columns: repeat(3, fit-content(100px));
138
+ justify-content: end;
139
+ gap: 0.5em;
140
+ font-weight: bold;
141
+ font-size: 11px;
142
+ padding: 8px 1rem 0;
143
+
144
+ span {
145
+ width: 40px;
146
+ text-align: center;
147
+ margin-right: 1em;
148
+ }
149
+ }
150
+
151
+ /* ========== Picker Section ========== */
152
+ .picker {
153
+ position: relative;
154
+ display: inline-grid;
155
+ grid-template-columns: repeat(3, fit-content(80px));
156
+ justify-content: end;
157
+ padding: 0 1rem;
158
+ font-size: 13px;
159
+ font-weight: 500;
160
+ font-feature-settings: "tnum";
161
+
162
+ &::before,
163
+ &::after {
164
+ content: "";
165
+ position: absolute;
166
+ width: 100%;
167
+ pointer-events: none;
168
+ z-index: 1;
169
+ }
170
+
171
+ &::before {
172
+ top: 0;
173
+ height: 50%;
174
+ background: linear-gradient(white, rgba(255, 255, 255, 0));
175
+ }
176
+
177
+ &::after {
178
+ bottom: 0;
179
+ height: 50%;
180
+ background: linear-gradient(rgba(255, 255, 255, 0), white);
181
+ }
182
+
183
+ ul {
184
+ @include hide-scrollbars();
185
+ max-height: 190px;
186
+ overflow-y: scroll;
187
+ padding: 1.5em 0;
188
+ margin-right: 1em;
189
+ scroll-snap-type: y mandatory;
190
+ scroll-behavior: smooth;
191
+
192
+ li {
193
+ scroll-snap-align: center;
194
+ height: 2.35em;
195
+ width: 40px;
196
+ text-align: center;
197
+ user-select: none;
198
+ cursor: pointer;
199
+ line-height: 2.35em;
200
+ border-radius: 4px;
201
+
202
+ &:hover {
203
+ background: #f0f0f0;
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ /* ========== Highlight Window ========== */
210
+ .picker-window {
211
+ position: absolute;
212
+ top: 50%;
213
+ left: 0;
214
+ width: 100%;
215
+ height: 2.4em;
216
+ transform: translateY(-52%);
217
+ border-top: 1px solid $scroll-highlight;
218
+ border-bottom: 1px solid $scroll-highlight;
219
+ pointer-events: none;
220
+ z-index: 2;
221
+ }
222
+
223
+ /* ========== Footer Buttons ========== */
224
+ .duration-footer {
225
+ padding: 0 1rem 1rem;
226
+ display: flex;
227
+ justify-content: flex-end;
228
+ gap: 0.5rem;
229
+
230
+ .buttons {
231
+ display: flex;
232
+ gap: 0.5rem;
233
+ }
234
+ }
235
+ </style>