@appscode/design-system 2.4.2 → 2.4.3
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.
package/package.json
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
z-index: 9;
|
|
4
4
|
|
|
5
|
+
&.is-disabled {
|
|
6
|
+
pointer-events: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
input[type="text"] {
|
|
6
10
|
padding-right: 32px;
|
|
7
11
|
}
|
|
@@ -11,7 +15,7 @@
|
|
|
11
15
|
padding: 8px 15px;
|
|
12
16
|
border-radius: 4px;
|
|
13
17
|
line-height: 1;
|
|
14
|
-
cursor: pointer;
|
|
18
|
+
// cursor: pointer;
|
|
15
19
|
display: flex;
|
|
16
20
|
align-items: center;
|
|
17
21
|
height: 36px;
|
|
@@ -80,7 +84,7 @@
|
|
|
80
84
|
width: 100%;
|
|
81
85
|
max-height: 500px;
|
|
82
86
|
overflow-y: auto;
|
|
83
|
-
transition: 0.2s ease-in-out;
|
|
87
|
+
// transition: 0.2s ease-in-out;
|
|
84
88
|
opacity: 0;
|
|
85
89
|
visibility: hidden;
|
|
86
90
|
|
|
@@ -101,7 +105,7 @@
|
|
|
101
105
|
li {
|
|
102
106
|
display: flex;
|
|
103
107
|
|
|
104
|
-
&:hover:not(.is-active) {
|
|
108
|
+
&:hover:not(.is-active, .is-disabled) {
|
|
105
109
|
background-color: $primary-light-gray;
|
|
106
110
|
color: $color-heading;
|
|
107
111
|
|
|
@@ -129,7 +133,7 @@
|
|
|
129
133
|
cursor: pointer;
|
|
130
134
|
}
|
|
131
135
|
|
|
132
|
-
&:hover:not(.group li, .is-active) {
|
|
136
|
+
&:hover:not(.group li, .is-active, .is-disabled) {
|
|
133
137
|
background-color: $primary-light-gray;
|
|
134
138
|
color: $color-heading;
|
|
135
139
|
|
|
@@ -155,6 +159,9 @@
|
|
|
155
159
|
&.is-disabled {
|
|
156
160
|
opacity: 0.6;
|
|
157
161
|
cursor: not-allowed;
|
|
162
|
+
label {
|
|
163
|
+
cursor: not-allowed;
|
|
164
|
+
}
|
|
158
165
|
}
|
|
159
166
|
}
|
|
160
167
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
withDefaults(defineProps<{ direction?: "up" | "down" }>(), {
|
|
3
|
+
direction: "up",
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
1
7
|
<template>
|
|
2
8
|
<svg
|
|
3
9
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -8,6 +14,7 @@
|
|
|
8
14
|
stroke-width="1.5"
|
|
9
15
|
stroke="currentColor"
|
|
10
16
|
class="size-6"
|
|
17
|
+
:style="direction === 'up' ? 'transform: rotate(0deg)' : 'transform: rotate(-180deg)'"
|
|
11
18
|
>
|
|
12
19
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
13
20
|
</svg>
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
withDefaults(defineProps<{ direction?: "up" | "down" }>(), {
|
|
3
|
+
direction: "up",
|
|
4
|
+
});
|
|
5
|
+
</script>
|
|
6
|
+
|
|
1
7
|
<template>
|
|
2
8
|
<svg
|
|
3
9
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -8,6 +14,7 @@
|
|
|
8
14
|
stroke-width="1.5"
|
|
9
15
|
stroke="currentColor"
|
|
10
16
|
class="size-6"
|
|
17
|
+
:style="direction === 'up' ? 'transform: rotate(0deg)' : 'transform: rotate(-180deg)'"
|
|
11
18
|
>
|
|
12
19
|
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
|
13
20
|
</svg>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, defineAsyncComponent, ref, watch } from "vue";
|
|
3
|
+
import { onClickOutside, useFocus } from "@vueuse/core";
|
|
4
|
+
|
|
5
|
+
import AcButton from "../button/Button.vue";
|
|
6
|
+
import AcButtons from "../button/Buttons.vue";
|
|
7
|
+
|
|
8
|
+
const ArrowDownIcon = defineAsyncComponent(() => import("../icons/ArrowDownIcon.vue"));
|
|
9
|
+
const RefreshIcon = defineAsyncComponent(() => import("../icons/RefreshIcon.vue"));
|
|
10
|
+
const CloseIcon = defineAsyncComponent(() => import("../icons/CloseIcon.vue"));
|
|
11
|
+
|
|
12
|
+
type Option = { text: string; value: string };
|
|
13
|
+
interface prop {
|
|
14
|
+
custom?: boolean;
|
|
15
|
+
options?: Array<Option>;
|
|
16
|
+
isLoading?: boolean;
|
|
17
|
+
optionType?: "simple" | "custom";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = withDefaults(defineProps<prop>(), {
|
|
21
|
+
custom: false,
|
|
22
|
+
options: () => [],
|
|
23
|
+
isLoading: false,
|
|
24
|
+
optionType: "simple",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
defineEmits(["onRefreshClick"]);
|
|
28
|
+
|
|
29
|
+
const selectedValue = ref<Option>();
|
|
30
|
+
const labelHoisted = ref(false);
|
|
31
|
+
const searchText = ref("");
|
|
32
|
+
const isOpen = ref(false);
|
|
33
|
+
|
|
34
|
+
// handle outside box
|
|
35
|
+
const selectBox = ref(null);
|
|
36
|
+
onClickOutside(selectBox, () => (isOpen.value = false));
|
|
37
|
+
|
|
38
|
+
// handle input click
|
|
39
|
+
const searchInput = ref(null);
|
|
40
|
+
const { focused } = useFocus(searchInput, { initialValue: true });
|
|
41
|
+
|
|
42
|
+
// filter options based on search text
|
|
43
|
+
const filteredOptions = computed(() => {
|
|
44
|
+
if (searchText.value) {
|
|
45
|
+
return props.options.filter((op) => op.text.includes(searchText.value));
|
|
46
|
+
} else return props.options || [];
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// handle selection
|
|
50
|
+
const onLabelClick = (op: Option) => {
|
|
51
|
+
selectedValue.value = op;
|
|
52
|
+
isOpen.value = false;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// handle label click
|
|
56
|
+
const selectClick = () => {
|
|
57
|
+
isOpen.value = true;
|
|
58
|
+
focused.value = true;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// handle clear btn
|
|
62
|
+
const handleClear = () => {
|
|
63
|
+
selectedValue.value = undefined;
|
|
64
|
+
searchText.value = "";
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// handle depend on selected data
|
|
68
|
+
watch(selectedValue, (n) => {
|
|
69
|
+
if (n) labelHoisted.value = true;
|
|
70
|
+
else labelHoisted.value = false;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
watch(isOpen, (n) => {
|
|
74
|
+
if (n) searchText.value = "";
|
|
75
|
+
else {
|
|
76
|
+
if (!selectedValue.value?.value) labelHoisted.value = false;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<template>
|
|
82
|
+
<div
|
|
83
|
+
ref="selectBox"
|
|
84
|
+
class="ac-single-input is-small is-selectbox"
|
|
85
|
+
:class="{ 'is-open': isOpen, 'is-disabled': isLoading }"
|
|
86
|
+
:style="[isOpen ? { 'z-index': 2 } : '']"
|
|
87
|
+
>
|
|
88
|
+
<label for="custom-select" class="ac-label" :class="{ 'show-label': labelHoisted || isOpen }" @click="selectClick">
|
|
89
|
+
Select Option
|
|
90
|
+
</label>
|
|
91
|
+
|
|
92
|
+
<input
|
|
93
|
+
v-if="isOpen"
|
|
94
|
+
v-model="searchText"
|
|
95
|
+
type="text"
|
|
96
|
+
ref="searchInput"
|
|
97
|
+
placeholder="Select One"
|
|
98
|
+
@click="selectClick"
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<p v-else class="custom-select-placeholder" @click="selectClick">
|
|
102
|
+
<span class="is-ellipsis-1">{{ selectedValue?.text }}</span>
|
|
103
|
+
</p>
|
|
104
|
+
|
|
105
|
+
<ac-buttons>
|
|
106
|
+
<button class="button ac-button is-white" @click="handleClear">
|
|
107
|
+
<ArrowDownIcon />
|
|
108
|
+
</button>
|
|
109
|
+
|
|
110
|
+
<ac-button modifier-classes="is-white" @click="$emit('onRefreshClick')">
|
|
111
|
+
<RefreshIcon :class="{ 'is-spin': isLoading }" />
|
|
112
|
+
</ac-button>
|
|
113
|
+
|
|
114
|
+
<ac-button modifier-classes="is-white" @click="isOpen = !isOpen">
|
|
115
|
+
<CloseIcon :direction="isOpen ? 'down' : 'up'" />
|
|
116
|
+
</ac-button>
|
|
117
|
+
</ac-buttons>
|
|
118
|
+
|
|
119
|
+
<div v-if="optionType === 'custom'" class="custom-select options">
|
|
120
|
+
<slot />
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<ul v-else class="options">
|
|
124
|
+
<template v-for="op in filteredOptions" :key="op.value">
|
|
125
|
+
<li @click="onLabelClick(op)" :class="{ 'is-active': selectedValue?.value === op.value }">
|
|
126
|
+
<label for="opt-one">{{ op.text }}</label>
|
|
127
|
+
</li>
|
|
128
|
+
</template>
|
|
129
|
+
<li v-if="filteredOptions.length <= 0" class="is-disabled">
|
|
130
|
+
<label>No element found. Consider changing the search text</label>
|
|
131
|
+
</li>
|
|
132
|
+
</ul>
|
|
133
|
+
</div>
|
|
134
|
+
</template>
|