@exakt/ui 0.0.8 → 0.0.10
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/README.md +6 -9
- package/dist/module.json +1 -1
- package/dist/runtime/components/e/btn.vue +26 -19
- package/dist/runtime/components/e/container.vue +11 -1
- package/dist/runtime/components/e/dialog.vue +1 -2
- package/dist/runtime/components/e/dropdown.vue +108 -60
- package/dist/runtime/components/e/focus-sheet.vue +1 -1
- package/dist/runtime/components/e/icon.vue +13 -1
- package/dist/runtime/components/e/image-lazy-view.vue +14 -12
- package/dist/runtime/components/e/input/combo.vue +43 -0
- package/dist/runtime/components/e/input/radio.vue +1 -1
- package/dist/runtime/components/e/input/text.vue +66 -53
- package/dist/runtime/components/e/passwordEye.vue +9 -1
- package/dist/runtime/components/e/progress/gradient.vue +41 -42
- package/dist/runtime/components/e/progress/linear.vue +5 -1
- package/dist/runtime/css/main.scss +9 -0
- package/dist/runtime/plugin.mjs +0 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Get your module up and running quickly.
|
|
3
|
-
|
|
4
|
-
Find and replace all on all files (CMD+SHIFT+F):
|
|
5
|
-
- Name: exakt
|
|
6
|
-
- Package name: @exakt/ui
|
|
7
|
-
- Description: My new Nuxt module
|
|
8
|
-
-->
|
|
9
|
-
|
|
10
1
|
# exakt
|
|
11
2
|
|
|
12
3
|
[![npm version][npm-version-src]][npm-version-href]
|
|
@@ -55,6 +46,12 @@ That's it! You can now use exakt in your Nuxt app ✨
|
|
|
55
46
|
|
|
56
47
|
## Development
|
|
57
48
|
|
|
49
|
+
### Important note
|
|
50
|
+
|
|
51
|
+
Because mkdist (and subsequently nuxt-module-builder) don't yet support *not* compiling SASS files, you'll need to use ``yarn link`` to substitute mkdist with the force-scss-off branch of https://github.com/wd-4000/mkdist
|
|
52
|
+
|
|
53
|
+
### The usual
|
|
54
|
+
|
|
58
55
|
```bash
|
|
59
56
|
# Install dependencies
|
|
60
57
|
npm install
|
package/dist/module.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
|
-
class="e-btn
|
|
3
|
+
class="e-btn"
|
|
4
4
|
:style="{ width, justifyContent: justifyWrapper }"
|
|
5
5
|
:type="type"
|
|
6
6
|
:disabled="disabled || loading"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
block,
|
|
12
12
|
rounded: solid,
|
|
13
13
|
'e-disabled': disabled,
|
|
14
|
-
'my-2':solid,
|
|
14
|
+
'my-2': solid,
|
|
15
15
|
loading,
|
|
16
16
|
fab,
|
|
17
17
|
loadingGradient,
|
|
@@ -36,14 +36,13 @@
|
|
|
36
36
|
<e-loading-spinner />
|
|
37
37
|
</div>
|
|
38
38
|
<span class="actual-content flex-center">
|
|
39
|
-
|
|
40
39
|
<slot />
|
|
41
40
|
</span>
|
|
42
41
|
</div>
|
|
43
42
|
</button>
|
|
44
43
|
</template>
|
|
45
44
|
<script lang="ts" setup>
|
|
46
|
-
import { computed,
|
|
45
|
+
import { computed, useNuxtApp } from "#imports";
|
|
47
46
|
//import { IonSpinner } from "@ionic/vue";
|
|
48
47
|
const { $exakt } = useNuxtApp();
|
|
49
48
|
const props = withDefaults(
|
|
@@ -62,15 +61,16 @@ const props = withDefaults(
|
|
|
62
61
|
disabled?: boolean;
|
|
63
62
|
type?: "button" | "submit" | "reset";
|
|
64
63
|
}>(),
|
|
65
|
-
{
|
|
64
|
+
{
|
|
65
|
+
type: "button",
|
|
66
|
+
background: "primary",
|
|
67
|
+
solid: true,
|
|
68
|
+
width: undefined,
|
|
69
|
+
justify: undefined,
|
|
70
|
+
color: undefined,
|
|
71
|
+
}
|
|
66
72
|
);
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
74
|
const justifyWrapper = computed(() => {
|
|
75
75
|
if (props.justify === "space-between") {
|
|
76
76
|
return "stretch";
|
|
@@ -104,7 +104,9 @@ const backgroundColorRgb = computed(() => {
|
|
|
104
104
|
return parseColor(parsedBackgroundProp.value);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
const parsedBackgroundProp = computed(() =>
|
|
107
|
+
const parsedBackgroundProp = computed(() =>
|
|
108
|
+
$exakt.parseColor(props.background)
|
|
109
|
+
);
|
|
108
110
|
|
|
109
111
|
const textColor = computed(() => {
|
|
110
112
|
if (props.color) {
|
|
@@ -124,8 +126,8 @@ const textColor = computed(() => {
|
|
|
124
126
|
});
|
|
125
127
|
|
|
126
128
|
const hoverColor = computed(() => {
|
|
127
|
-
if (parsedBackgroundProp.value ===
|
|
128
|
-
return
|
|
129
|
+
if (parsedBackgroundProp.value === "transparent") {
|
|
130
|
+
return "rgba(98, 98, 98, 0.15)";
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
const rgb = backgroundColorRgb.value;
|
|
@@ -166,13 +168,19 @@ const hoverColor = computed(() => {
|
|
|
166
168
|
border: none;
|
|
167
169
|
text-decoration: none;
|
|
168
170
|
cursor: pointer;
|
|
169
|
-
position: relative;
|
|
170
171
|
flex-shrink: 1;
|
|
171
|
-
|
|
172
|
+
position: relative;
|
|
172
173
|
transition: background 0.4s, color 0.3s, opacity 0.4s;
|
|
173
174
|
|
|
174
175
|
font-family: var(--e-font-family);
|
|
176
|
+
box-sizing: border-box;
|
|
175
177
|
|
|
178
|
+
|
|
179
|
+
border: transparent solid 0.1rem;
|
|
180
|
+
&:focus-visible {
|
|
181
|
+
transition: border-width 0.2s;
|
|
182
|
+
border: var(--e-color-dark) solid 0.1rem;
|
|
183
|
+
}
|
|
176
184
|
&.loading {
|
|
177
185
|
pointer-events: none;
|
|
178
186
|
|
|
@@ -182,20 +190,19 @@ const hoverColor = computed(() => {
|
|
|
182
190
|
transition: background 0.8s, color 0.5s, opacity 0.4s;
|
|
183
191
|
|
|
184
192
|
.actual-content {
|
|
185
|
-
|
|
186
193
|
opacity: 0.8;
|
|
187
|
-
transition: opacity 0.5s
|
|
194
|
+
transition: opacity 0.5s;
|
|
188
195
|
}
|
|
189
196
|
}
|
|
190
197
|
|
|
191
198
|
.actual-content {
|
|
192
199
|
opacity: 0;
|
|
193
200
|
}
|
|
194
|
-
|
|
195
201
|
}
|
|
196
202
|
|
|
197
203
|
&:hover {
|
|
198
204
|
background: rgba(98, 98, 98, 0.15);
|
|
205
|
+
border: transparent solid 0.1rem;
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
&:active {
|
|
@@ -12,7 +12,17 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
</template>
|
|
14
14
|
<script setup lang="ts">
|
|
15
|
-
|
|
15
|
+
withDefaults(
|
|
16
|
+
defineProps<{
|
|
17
|
+
noBtnPadding?: boolean;
|
|
18
|
+
forceFullWidth?: boolean;
|
|
19
|
+
|
|
20
|
+
}>(),
|
|
21
|
+
{
|
|
22
|
+
noBtnPadding: false,
|
|
23
|
+
forceFullWidth:false
|
|
24
|
+
}
|
|
25
|
+
);
|
|
16
26
|
</script>
|
|
17
27
|
<style lang="scss" scoped>
|
|
18
28
|
.content {
|
|
@@ -28,11 +28,10 @@
|
|
|
28
28
|
</template>
|
|
29
29
|
|
|
30
30
|
<script setup lang="ts">
|
|
31
|
-
|
|
31
|
+
defineProps<{
|
|
32
32
|
modelValue: boolean;
|
|
33
33
|
}>();
|
|
34
34
|
const emit = defineEmits(["update:modelValue"]);
|
|
35
|
-
const state = reactive({ active: false });
|
|
36
35
|
</script>
|
|
37
36
|
<style scoped lang="scss">
|
|
38
37
|
.dialog-wrap {
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="flex-stretch">
|
|
2
|
+
<div class="flex-stretch t-dropdown">
|
|
3
3
|
<!-- class="flex-stretch fullwidth" -->
|
|
4
4
|
<div
|
|
5
5
|
ref="activator"
|
|
6
|
-
@click="
|
|
6
|
+
@click="onActivatorClick"
|
|
7
7
|
>
|
|
8
8
|
<slot />
|
|
9
9
|
</div>
|
|
10
|
-
<e-focus-sheet v-model="
|
|
10
|
+
<e-focus-sheet v-model="visibleComputed" />
|
|
11
11
|
<e-tr-scale>
|
|
12
12
|
<div
|
|
13
|
-
v-if="
|
|
13
|
+
v-if="visibleComputed"
|
|
14
|
+
ref="list"
|
|
14
15
|
class="list rounded"
|
|
15
16
|
>
|
|
16
17
|
<component
|
|
@@ -25,8 +26,12 @@
|
|
|
25
26
|
class="item fullwidth"
|
|
26
27
|
:color="item.color"
|
|
27
28
|
:solid="false"
|
|
28
|
-
:background="item.background || 'transparent'"
|
|
29
|
-
:class="{
|
|
29
|
+
:background="item.background || 'transparent'"
|
|
30
|
+
:class="{
|
|
31
|
+
'rounded-top': i === 0,
|
|
32
|
+
'rounded-bottom': i === items.length - 1,
|
|
33
|
+
active: currentItem === i,
|
|
34
|
+
}"
|
|
30
35
|
@click="select(i)"
|
|
31
36
|
>
|
|
32
37
|
<e-icon
|
|
@@ -43,12 +48,58 @@
|
|
|
43
48
|
</div>
|
|
44
49
|
</template>
|
|
45
50
|
<script setup lang="ts">
|
|
46
|
-
|
|
51
|
+
import { computed, ref, reactive, watch/*, nextTick*/ } from "#imports";
|
|
47
52
|
import _ from "lodash";
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
interface DropdownItem {
|
|
55
|
+
name: string;
|
|
56
|
+
icon?: string;
|
|
57
|
+
href?: string;
|
|
58
|
+
callback?: () => void;
|
|
59
|
+
color?: string;
|
|
60
|
+
background?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const props = withDefaults(
|
|
64
|
+
defineProps<{
|
|
65
|
+
modelValue?: number;
|
|
66
|
+
width: string | number | "100%";
|
|
67
|
+
center?: boolean;
|
|
68
|
+
items: DropdownItem[];
|
|
69
|
+
visible?: boolean | null;
|
|
70
|
+
paddingY?: string;
|
|
71
|
+
}>(),
|
|
72
|
+
{ center: false, visible: null, paddingY: "", modelValue: undefined }
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const activator = ref<HTMLDivElement>();
|
|
76
|
+
const list = ref<HTMLDivElement>();
|
|
50
77
|
|
|
51
|
-
|
|
78
|
+
const state = reactive({
|
|
79
|
+
visibleInternal: false,
|
|
80
|
+
x: 0,
|
|
81
|
+
y: 0,
|
|
82
|
+
width: 0,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Visibility computed variable. We use the state unless we have a variable from the parent.
|
|
86
|
+
const visibleComputed = computed<boolean>({
|
|
87
|
+
get: () => {
|
|
88
|
+
if (props.visible != null) {
|
|
89
|
+
return props.visible;
|
|
90
|
+
}
|
|
91
|
+
return state.visibleInternal;
|
|
92
|
+
},
|
|
93
|
+
set: (value) => {
|
|
94
|
+
if (props.visible != null) {
|
|
95
|
+
emit("update:visible", value);
|
|
96
|
+
} else {
|
|
97
|
+
state.visibleInternal = value;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
function computeWidth(input: string | number) {
|
|
52
103
|
const div = document.createElement("div");
|
|
53
104
|
document.body.appendChild(div);
|
|
54
105
|
div.style.width = String(input);
|
|
@@ -59,88 +110,75 @@ function parseWidth(input: string | number) {
|
|
|
59
110
|
return parseInt(c, 10);
|
|
60
111
|
}
|
|
61
112
|
|
|
62
|
-
const updatePosition = () => {
|
|
63
|
-
if (
|
|
113
|
+
const updatePosition = async () => {
|
|
114
|
+
if (
|
|
115
|
+
!visibleComputed.value ||
|
|
116
|
+
!activator.value ||
|
|
117
|
+
!activator.value.firstElementChild
|
|
118
|
+
) {
|
|
64
119
|
window.removeEventListener("resize", debouncedUpdatePosition);
|
|
65
120
|
return;
|
|
66
121
|
}
|
|
67
|
-
const
|
|
122
|
+
const activatorRect = activator.value.getBoundingClientRect();
|
|
68
123
|
|
|
69
|
-
|
|
124
|
+
if (props.width === "100%") {
|
|
125
|
+
state.width = activatorRect.width;
|
|
126
|
+
} else {
|
|
127
|
+
state.width = computeWidth(props.width);
|
|
128
|
+
}
|
|
70
129
|
|
|
71
|
-
state.y =
|
|
130
|
+
state.y = activatorRect.height;
|
|
131
|
+
state.x = 0;
|
|
72
132
|
|
|
73
|
-
|
|
133
|
+
/* await nextTick();
|
|
134
|
+
if (!list.value) return;
|
|
74
135
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
state.x = rect.left + rect.width / 2 + expectedDropdownRight - 47;
|
|
82
|
-
}
|
|
136
|
+
const listRect = list.value.getBoundingClientRect();
|
|
137
|
+
if (window.innerHeight < listRect.bottom) {
|
|
138
|
+
// The list is too low.
|
|
139
|
+
// We can just render the list on top of the button.
|
|
140
|
+
state.y = 0 - listRect.height;
|
|
141
|
+
} */
|
|
83
142
|
};
|
|
84
143
|
|
|
85
144
|
const debouncedUpdatePosition = _.debounce(updatePosition, 200);
|
|
86
145
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (state.active) {
|
|
146
|
+
watch(visibleComputed, (value) => {
|
|
147
|
+
if (value) {
|
|
91
148
|
updatePosition();
|
|
92
149
|
window.addEventListener("resize", debouncedUpdatePosition);
|
|
93
150
|
} else {
|
|
94
151
|
window.removeEventListener("resize", debouncedUpdatePosition);
|
|
95
152
|
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
interface DropdownItem {
|
|
99
|
-
name: string;
|
|
100
|
-
icon?: string;
|
|
101
|
-
href?: string;
|
|
102
|
-
callback?: () => void;
|
|
103
|
-
color?: string;
|
|
104
|
-
background?: string;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const props = defineProps<{
|
|
108
|
-
modelValue?: number;
|
|
109
|
-
width: string | number;
|
|
110
|
-
items: DropdownItem[];
|
|
111
|
-
}>();
|
|
112
|
-
|
|
113
|
-
const emit = defineEmits(["update:modelValue"]);
|
|
114
|
-
|
|
115
|
-
const activator = ref();
|
|
116
|
-
|
|
117
|
-
const state = reactive({
|
|
118
|
-
active: false,
|
|
119
|
-
x: 0,
|
|
120
|
-
y: 0,
|
|
121
153
|
});
|
|
122
154
|
|
|
155
|
+
const emit = defineEmits(["update:modelValue", "update:visible"]);
|
|
156
|
+
|
|
123
157
|
const currentItem = computed({
|
|
124
158
|
get: () => props.modelValue,
|
|
125
159
|
set: (value) => emit("update:modelValue", value),
|
|
126
160
|
});
|
|
127
161
|
|
|
128
|
-
|
|
129
|
-
|
|
130
162
|
const select = (i: number) => {
|
|
131
|
-
|
|
163
|
+
visibleComputed.value = false;
|
|
132
164
|
currentItem.value = i;
|
|
133
165
|
};
|
|
166
|
+
|
|
167
|
+
const onActivatorClick = () => {
|
|
168
|
+
visibleComputed.value = !visibleComputed.value;
|
|
169
|
+
};
|
|
134
170
|
</script>
|
|
135
171
|
<style scoped lang="scss">
|
|
172
|
+
.t-dropdown {
|
|
173
|
+
position: relative;
|
|
174
|
+
}
|
|
136
175
|
.list {
|
|
137
|
-
position:
|
|
176
|
+
position: absolute;
|
|
138
177
|
left: v-bind('state.x + "px"');
|
|
139
178
|
top: v-bind('state.y + "px"');
|
|
140
|
-
width: v-bind(width);
|
|
179
|
+
width: v-bind('state.width+"px"');
|
|
141
180
|
display: flex;
|
|
142
181
|
|
|
143
|
-
|
|
144
182
|
background-color: var(--e-color-elev-2);
|
|
145
183
|
color: var(--e-color-dark);
|
|
146
184
|
z-index: 4;
|
|
@@ -149,24 +187,34 @@ const select = (i: number) => {
|
|
|
149
187
|
flex-direction: column;
|
|
150
188
|
overflow: clip;
|
|
151
189
|
justify-items: stretch;
|
|
190
|
+
margin-top: v-bind("props.paddingY");
|
|
152
191
|
|
|
153
192
|
.item {
|
|
154
193
|
// color: var(--e-color-dark);
|
|
155
194
|
font-size: 1rem;
|
|
156
195
|
padding: 0.7rem;
|
|
157
196
|
text-transform: capitalize;
|
|
197
|
+
position: relative;
|
|
198
|
+
|
|
199
|
+
&:hover {
|
|
200
|
+
background-color: rgba(var(--e-color-dark-rgb), 0.2);
|
|
201
|
+
}
|
|
202
|
+
&:focus {
|
|
203
|
+
}
|
|
158
204
|
|
|
159
205
|
&.active {
|
|
160
206
|
background-color: rgba(var(--e-color-primary-rgb), 0.2);
|
|
161
207
|
|
|
208
|
+
&:hover {
|
|
209
|
+
background-color: rgba(var(--e-color-primary-rgb), 0.4);
|
|
210
|
+
}
|
|
162
211
|
}
|
|
163
212
|
}
|
|
164
213
|
}
|
|
165
214
|
|
|
166
|
-
|
|
167
|
-
|
|
168
215
|
@media screen and (max-width: $e-md-screen-breakpoint) {
|
|
169
216
|
.list {
|
|
217
|
+
position: fixed;
|
|
170
218
|
top: unset;
|
|
171
219
|
bottom: 0px;
|
|
172
220
|
left: 0px;
|
|
@@ -9,7 +9,19 @@
|
|
|
9
9
|
</svg>
|
|
10
10
|
</template>
|
|
11
11
|
<script setup lang="ts">
|
|
12
|
-
|
|
12
|
+
withDefaults(
|
|
13
|
+
defineProps<{
|
|
14
|
+
icon: string;
|
|
15
|
+
color?: string;
|
|
16
|
+
size?: number | string;
|
|
17
|
+
}>(),
|
|
18
|
+
{
|
|
19
|
+
icon: "",
|
|
20
|
+
color: "",
|
|
21
|
+
size: "21",
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
13
25
|
</script>
|
|
14
26
|
<style scoped>
|
|
15
27
|
svg {
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
class="rounded lv-blur fullsize border-rad-custom"
|
|
28
28
|
:class="{ hidden: state.loaded, rounded: !borderRadius }"
|
|
29
29
|
/>
|
|
30
|
-
<!-- @transitionend.passive="transitionend" -->
|
|
31
30
|
</div>
|
|
32
31
|
|
|
33
32
|
<div
|
|
@@ -52,8 +51,8 @@ import {
|
|
|
52
51
|
} from "vue";
|
|
53
52
|
|
|
54
53
|
const props = defineProps<{
|
|
55
|
-
width
|
|
56
|
-
height
|
|
54
|
+
width: number;
|
|
55
|
+
height: number;
|
|
57
56
|
aspectRatio?: number;
|
|
58
57
|
blur?: string;
|
|
59
58
|
src?: string;
|
|
@@ -66,7 +65,7 @@ const slots = useSlots();
|
|
|
66
65
|
const wrapper = ref();
|
|
67
66
|
const canvas = ref();
|
|
68
67
|
|
|
69
|
-
const state = reactive({
|
|
68
|
+
const state = reactive<{loaded: boolean|undefined, renderBlur:boolean, blurHeight:number, blurWidth:number, resizeListenerActive:boolean, intersected:boolean}>({
|
|
70
69
|
loaded: undefined,
|
|
71
70
|
renderBlur: true,
|
|
72
71
|
blurHeight: 32,
|
|
@@ -87,12 +86,15 @@ const slotContentPresent = computed(() => {
|
|
|
87
86
|
return Boolean(slots.default);
|
|
88
87
|
});
|
|
89
88
|
const backgroundImage = computed(() => {
|
|
89
|
+
if(!props.src) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
90
92
|
return "url(".concat(props.src, ")");
|
|
91
93
|
});
|
|
92
94
|
|
|
93
95
|
watch(
|
|
94
96
|
() => props.blur,
|
|
95
|
-
(newBlur: string) => {
|
|
97
|
+
(newBlur: string|undefined) => {
|
|
96
98
|
if (!state.loaded) {
|
|
97
99
|
initialize(newBlur);
|
|
98
100
|
}
|
|
@@ -135,24 +137,24 @@ const getAspectRatio = () => {
|
|
|
135
137
|
return undefined;
|
|
136
138
|
};
|
|
137
139
|
|
|
138
|
-
const dimensionFix = (value) => {
|
|
140
|
+
const dimensionFix = (value: string|number) => {
|
|
139
141
|
if (!value) {
|
|
140
142
|
return undefined;
|
|
141
143
|
}
|
|
142
144
|
|
|
145
|
+
if(typeof value === "number") {
|
|
146
|
+
value = value.toString();
|
|
147
|
+
}
|
|
148
|
+
|
|
143
149
|
if (/^\d+$/.test(value)) {
|
|
144
150
|
return value + "px";
|
|
145
151
|
}
|
|
146
152
|
return value;
|
|
147
153
|
};
|
|
148
154
|
|
|
149
|
-
const transitionend = () => {
|
|
150
|
-
if (state.loaded) {
|
|
151
|
-
state.renderBlur = false;
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
|
|
157
|
+
const onIntersect = (intersecting: boolean) => {
|
|
156
158
|
if (intersecting && !state.intersected) {
|
|
157
159
|
initialize();
|
|
158
160
|
state.intersected = true;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<e-dropdown
|
|
3
|
+
v-model="dropdownActive"
|
|
4
|
+
:items="items"
|
|
5
|
+
width="100%"
|
|
6
|
+
:center="false"
|
|
7
|
+
:visible="dropdownVisible"
|
|
8
|
+
padding-y="0.25rem"
|
|
9
|
+
@update:visible="dropdownVisible = $event"
|
|
10
|
+
>
|
|
11
|
+
<e-input-text
|
|
12
|
+
v-model="searchField"
|
|
13
|
+
label="Input"
|
|
14
|
+
solid
|
|
15
|
+
/>
|
|
16
|
+
</e-dropdown>
|
|
17
|
+
</template>
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { ref, watch } from "#imports";
|
|
20
|
+
const items = [{ name: "test" }, { name: "test2" }, { name: "test3" }];
|
|
21
|
+
const dropdownActive = ref<undefined | number>(undefined);
|
|
22
|
+
const dropdownVisible = ref<boolean>(false);
|
|
23
|
+
|
|
24
|
+
const searchField = ref("");
|
|
25
|
+
|
|
26
|
+
watch(searchField, (value) => {
|
|
27
|
+
if (value.length > 0) {
|
|
28
|
+
//dropdownActive.value = 0;
|
|
29
|
+
dropdownVisible.value = true;
|
|
30
|
+
} else {
|
|
31
|
+
dropdownActive.value = undefined;
|
|
32
|
+
dropdownVisible.value = false;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
watch(dropdownActive, (value) => {
|
|
37
|
+
if (value == undefined) {
|
|
38
|
+
searchField.value = "";
|
|
39
|
+
} else {
|
|
40
|
+
searchField.value = items[value].name;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="pos-wrap"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
<!-- <div class="pos-wrap">-->
|
|
3
|
+
<div
|
|
4
|
+
class="wrapper fullwidth"
|
|
5
|
+
:style="inputState.overtakeStyle"
|
|
6
|
+
:class="{ rounded: solid, solid }"
|
|
7
|
+
@click="focus"
|
|
8
|
+
>
|
|
9
|
+
<e-icon
|
|
10
|
+
v-if="icon"
|
|
11
|
+
:icon="icon"
|
|
12
|
+
size="21"
|
|
13
|
+
/>
|
|
14
|
+
<textarea
|
|
15
|
+
v-if="type === 'textarea'"
|
|
16
|
+
ref="input"
|
|
17
|
+
v-model="currentText"
|
|
18
|
+
class="input"
|
|
19
|
+
:placeholder="label"
|
|
20
|
+
autocomplete="off"
|
|
21
|
+
auto-grow
|
|
22
|
+
rows="5"
|
|
23
|
+
@focus="inputState.focused = true"
|
|
24
|
+
@blur="inputState.focused = false"
|
|
25
|
+
/>
|
|
26
|
+
<input
|
|
27
|
+
v-else
|
|
28
|
+
ref="input"
|
|
29
|
+
v-model="currentText"
|
|
30
|
+
:disabled="disabled"
|
|
31
|
+
:type="type"
|
|
32
|
+
:autocomplete="autocomplete"
|
|
33
|
+
:spellcheck="spellcheck"
|
|
34
|
+
class="input"
|
|
35
|
+
:required="required"
|
|
36
|
+
:placeholder="label"
|
|
37
|
+
@click.stop=""
|
|
38
|
+
@focus="inputState.focused = true"
|
|
39
|
+
@blur="inputState.focused = false"
|
|
40
|
+
@transitionend="transitionEnd"
|
|
8
41
|
>
|
|
9
|
-
|
|
10
|
-
v-if="icon"
|
|
11
|
-
:icon="icon"
|
|
12
|
-
size="21"
|
|
13
|
-
/>
|
|
14
|
-
<textarea
|
|
15
|
-
v-if="type === 'textarea'"
|
|
16
|
-
ref="input"
|
|
17
|
-
v-model="currentText"
|
|
18
|
-
class="input"
|
|
19
|
-
:placeholder="label"
|
|
20
|
-
autocomplete="off"
|
|
21
|
-
auto-grow
|
|
22
|
-
rows="5"
|
|
23
|
-
@focus="inputState.focused = true"
|
|
24
|
-
@blur="inputState.focused = false"
|
|
25
|
-
/>
|
|
26
|
-
<input
|
|
27
|
-
v-else
|
|
28
|
-
ref="input"
|
|
29
|
-
v-model="currentText"
|
|
30
|
-
:disabled="disabled"
|
|
31
|
-
:type="type"
|
|
32
|
-
:autocomplete="autocomplete"
|
|
33
|
-
:spellcheck="spellcheck"
|
|
34
|
-
class="input"
|
|
35
|
-
:required="required"
|
|
36
|
-
:placeholder="label"
|
|
37
|
-
@click.stop=""
|
|
38
|
-
@focus="inputState.focused = true"
|
|
39
|
-
@blur="inputState.focused = false"
|
|
40
|
-
@transitionend="transitionEnd"
|
|
41
|
-
>
|
|
42
|
-
<slot />
|
|
43
|
-
</div>
|
|
42
|
+
<slot />
|
|
44
43
|
</div>
|
|
44
|
+
<!-- </div>-->
|
|
45
45
|
</template>
|
|
46
46
|
<script setup lang="ts">
|
|
47
|
-
import { ref, watch } from "
|
|
48
|
-
const input = ref<HTMLInputElement>();
|
|
49
|
-
const emit = defineEmits(["update:modelValue"]);
|
|
47
|
+
import { ref, watch, reactive, computed } from "#imports";
|
|
50
48
|
|
|
51
49
|
const inputState = reactive({
|
|
52
50
|
overtakeStyle: "",
|
|
@@ -54,15 +52,21 @@ const inputState = reactive({
|
|
|
54
52
|
focused: false,
|
|
55
53
|
});
|
|
56
54
|
|
|
55
|
+
const input = ref<HTMLInputElement>();
|
|
56
|
+
const emit = defineEmits(["update:modelValue"]);
|
|
57
|
+
|
|
57
58
|
const focus = () => {
|
|
58
|
-
if(!input.value){
|
|
59
|
-
return
|
|
59
|
+
if (!input.value) {
|
|
60
|
+
return;
|
|
60
61
|
}
|
|
61
62
|
const length = input.value.value.length;
|
|
62
63
|
|
|
63
64
|
// Not all input types support setSelectionRange
|
|
64
|
-
if
|
|
65
|
-
|
|
65
|
+
if (
|
|
66
|
+
!inputState.focused &&
|
|
67
|
+
["text", "search", "URL", "tel", "password"].includes(props.type)
|
|
68
|
+
) {
|
|
69
|
+
input.value.setSelectionRange(length, length);
|
|
66
70
|
}
|
|
67
71
|
input.value.focus();
|
|
68
72
|
};
|
|
@@ -86,7 +90,15 @@ const props = withDefaults(
|
|
|
86
90
|
spellcheck?: boolean;
|
|
87
91
|
height?: string;
|
|
88
92
|
}>(),
|
|
89
|
-
{
|
|
93
|
+
{
|
|
94
|
+
icon: undefined,
|
|
95
|
+
label: "Search",
|
|
96
|
+
solid: false,
|
|
97
|
+
type: "text",
|
|
98
|
+
modelValue: "",
|
|
99
|
+
autocomplete: "off",
|
|
100
|
+
height: "unset",
|
|
101
|
+
}
|
|
90
102
|
);
|
|
91
103
|
|
|
92
104
|
watch(
|
|
@@ -99,11 +111,12 @@ watch(
|
|
|
99
111
|
);
|
|
100
112
|
|
|
101
113
|
const getInputStyle = (prop: string) => {
|
|
102
|
-
|
|
114
|
+
if(input.value === undefined) return;
|
|
115
|
+
const c = getComputedStyle(input.value).getPropertyValue(prop);
|
|
103
116
|
return c;
|
|
104
117
|
};
|
|
105
118
|
|
|
106
|
-
const transitionEnd = (
|
|
119
|
+
const transitionEnd = () => {
|
|
107
120
|
inputState.autofilled = !inputState.autofilled;
|
|
108
121
|
|
|
109
122
|
if (inputState.autofilled) {
|
|
@@ -133,11 +146,11 @@ const transitionEnd = (a) => {
|
|
|
133
146
|
width: 100%;
|
|
134
147
|
outline: none;
|
|
135
148
|
resize: none;
|
|
136
|
-
margin: var(--e-core-padding-x)/2;
|
|
149
|
+
margin: var(--e-core-padding-x) / 2;
|
|
137
150
|
font-size: 1rem;
|
|
138
151
|
color: var(--e-color-dark);
|
|
139
152
|
font-family: var(--e-font-family);
|
|
140
|
-
height:v-bind(height);
|
|
153
|
+
height: v-bind(height);
|
|
141
154
|
|
|
142
155
|
&:-webkit-autofill {
|
|
143
156
|
// Expose a hook for JavaScript when auto fill is shown.
|
|
@@ -9,5 +9,13 @@
|
|
|
9
9
|
<script setup lang="ts">
|
|
10
10
|
import { mdiEye, mdiEyeOff } from "@mdi/js";
|
|
11
11
|
const emit = defineEmits(["update:modelValue"]);
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
withDefaults(
|
|
14
|
+
defineProps<{
|
|
15
|
+
modelValue: boolean;
|
|
16
|
+
}>(),
|
|
17
|
+
{
|
|
18
|
+
modelValue: false,
|
|
19
|
+
}
|
|
20
|
+
);
|
|
13
21
|
</script>
|
|
@@ -2,54 +2,53 @@
|
|
|
2
2
|
<div />
|
|
3
3
|
</template>
|
|
4
4
|
<script setup lang="ts">
|
|
5
|
-
|
|
5
|
+
import { useNuxtApp, computed } from "#imports";
|
|
6
|
+
|
|
7
|
+
const { $exakt } = useNuxtApp();
|
|
6
8
|
const props = withDefaults(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
defineProps<{
|
|
10
|
+
color: string;
|
|
11
|
+
}>(),
|
|
12
|
+
{ color: "primary" }
|
|
11
13
|
);
|
|
12
|
-
const parsedColor = computed(() => $exakt.parseColor(props.color,
|
|
13
|
-
|
|
14
|
+
const parsedColor = computed(() => $exakt.parseColor(props.color, "rgb"));
|
|
14
15
|
</script>
|
|
15
16
|
<style scoped lang="scss">
|
|
16
17
|
div {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
animation: pos 3.5s linear infinite;
|
|
18
|
+
display: block;
|
|
19
|
+
width: 100%;
|
|
20
|
+
height: 100%;
|
|
21
|
+
--pc: v-bind(parsedColor);
|
|
22
|
+
background-image: linear-gradient(
|
|
23
|
+
90deg,
|
|
24
|
+
rgba(var(--pc), 0) 0%,
|
|
25
|
+
rgba(var(--pc), 0.5) 50%,
|
|
26
|
+
rgba(var(--pc), 0) 50.1%,
|
|
27
|
+
rgba(var(--pc), 0) 100%
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
background-size: 200% 100%;
|
|
31
|
+
|
|
32
|
+
animation: pos 3.5s linear infinite;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
@keyframes pos {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
0%,
|
|
37
|
+
10% {
|
|
38
|
+
background-position: 100% 0%;
|
|
39
|
+
opacity: 1;
|
|
40
|
+
}
|
|
41
|
+
40% {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
70% {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
100% {
|
|
50
|
+
background-position: -100% 0%;
|
|
51
|
+
opacity: 0;
|
|
52
|
+
}
|
|
54
53
|
}
|
|
55
|
-
</style>
|
|
54
|
+
</style>
|
|
@@ -10,6 +10,15 @@ $root-blue-rgb: red($root-blue), green($root-blue), blue($root-blue);
|
|
|
10
10
|
.rounded {
|
|
11
11
|
border-radius: var(--e-rounded-border-radius);
|
|
12
12
|
}
|
|
13
|
+
.rounded-top{
|
|
14
|
+
border-top-left-radius: var(--e-rounded-border-radius);
|
|
15
|
+
border-top-right-radius: var(--e-rounded-border-radius);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.rounded-bottom{
|
|
19
|
+
border-bottom-left-radius: var(--e-rounded-border-radius);
|
|
20
|
+
border-bottom-right-radius: var(--e-rounded-border-radius);
|
|
21
|
+
}
|
|
13
22
|
|
|
14
23
|
|
|
15
24
|
|
package/dist/runtime/plugin.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exakt/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "A UI library for Nuxt.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dev:build": "nuxi build playground",
|
|
23
23
|
"dev:prepare": "nuxt-module-build --stub && nuxi prepare playground",
|
|
24
24
|
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
25
|
-
"lint": "eslint .",
|
|
25
|
+
"lint": "eslint . --fix",
|
|
26
26
|
"test": "vitest run",
|
|
27
27
|
"test:watch": "vitest watch"
|
|
28
28
|
},
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"@nuxt/schema": "^3.2.3",
|
|
40
40
|
"@nuxt/test-utils": "^3.2.3",
|
|
41
41
|
"@types/lodash": "^4.14.191",
|
|
42
|
+
"@types/node": "^20.2.4",
|
|
42
43
|
"changelogen": "^0.5.1",
|
|
43
44
|
"eslint": "^8.35.0",
|
|
44
45
|
"nuxt": "^3.4.3",
|
|
@@ -62,5 +63,6 @@
|
|
|
62
63
|
"bugs": {
|
|
63
64
|
"url": "https://github.com/wd-4000/exakt/issues"
|
|
64
65
|
},
|
|
65
|
-
"homepage": "https://github.com/wd-4000/exakt#readme"
|
|
66
|
-
|
|
66
|
+
"homepage": "https://github.com/wd-4000/exakt#readme",
|
|
67
|
+
"packageManager": "yarn@3.5.1"
|
|
68
|
+
}
|