mktcms 0.2.16 → 0.3.2
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/dist/module.json +1 -1
- package/dist/module.mjs +2 -1
- package/dist/runtime/app/components/content/editor/{selectFile/index.vue.d.ts → frontmatter/filePicker/modal.d.vue.ts} +3 -2
- package/dist/runtime/app/components/content/editor/frontmatter/filePicker/modal.vue +122 -0
- package/dist/runtime/app/components/content/editor/{selectFile/index.d.vue.ts → frontmatter/filePicker/modal.vue.d.ts} +3 -2
- package/dist/runtime/app/components/content/editor/{selectFile/breadcrumb.d.vue.ts → frontmatter/filePicker/node.d.vue.ts} +5 -2
- package/dist/runtime/app/components/content/editor/frontmatter/filePicker/node.vue +145 -0
- package/dist/runtime/app/components/content/editor/{selectFile/breadcrumb.vue.d.ts → frontmatter/filePicker/node.vue.d.ts} +5 -2
- package/dist/runtime/app/components/content/editor/frontmatter/form.d.vue.ts +1 -2
- package/dist/runtime/app/components/content/editor/frontmatter/form.vue +175 -193
- package/dist/runtime/app/components/content/editor/frontmatter/form.vue.d.ts +1 -2
- package/dist/runtime/app/components/content/editor/frontmatter/input.d.vue.ts +4 -0
- package/dist/runtime/app/components/content/editor/frontmatter/input.vue +41 -30
- package/dist/runtime/app/components/content/editor/frontmatter/input.vue.d.ts +4 -0
- package/dist/runtime/app/components/content/editor/frontmatter/modal.d.vue.ts +1 -0
- package/dist/runtime/app/components/content/editor/frontmatter/modal.vue +17 -87
- package/dist/runtime/app/components/content/editor/frontmatter/modal.vue.d.ts +1 -0
- package/dist/runtime/app/components/content/editor/markdown.vue +3 -1
- package/dist/runtime/app/styles/admin.css +1 -1
- package/dist/runtime/app/styles/admin.min.css +1 -1
- package/dist/runtime/server/api/admin/list.js +13 -5
- package/dist/runtime/server/api/admin/md.d.ts +1 -0
- package/dist/runtime/server/api/admin/md.js +15 -2
- package/package.json +2 -1
- package/dist/runtime/app/components/content/editor/selectFile/breadcrumb.vue +0 -51
- package/dist/runtime/app/components/content/editor/selectFile/index.vue +0 -89
|
@@ -1,86 +1,155 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import { computed, watch } from "vue";
|
|
3
3
|
import FrontmatterInput from "./input.vue";
|
|
4
4
|
defineOptions({
|
|
5
5
|
name: "FrontmatterForm"
|
|
6
6
|
});
|
|
7
7
|
const props = defineProps({
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
depth: { type: Number, required: false, default: 0 },
|
|
9
|
+
schema: { type: [Object, null], required: true }
|
|
10
10
|
});
|
|
11
11
|
const frontmatter = defineModel("frontmatter", { type: null, ...{
|
|
12
12
|
required: true
|
|
13
13
|
} });
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return typeof value === "boolean";
|
|
14
|
+
function isRecord(value) {
|
|
15
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17
16
|
}
|
|
18
|
-
function
|
|
19
|
-
return
|
|
17
|
+
function isBooleanSchema(schema) {
|
|
18
|
+
return isRecord(schema) && schema.type === "boolean";
|
|
20
19
|
}
|
|
21
20
|
function isObject(value) {
|
|
22
|
-
return
|
|
21
|
+
return isRecord(value);
|
|
22
|
+
}
|
|
23
|
+
function isArraySchema(schema) {
|
|
24
|
+
return isRecord(schema) && schema.type === "array";
|
|
25
|
+
}
|
|
26
|
+
function isObjectSchema(schema) {
|
|
27
|
+
return isRecord(schema) && schema.type === "object";
|
|
23
28
|
}
|
|
24
|
-
function
|
|
25
|
-
return
|
|
29
|
+
function isPrimitiveSchema(schema) {
|
|
30
|
+
return isRecord(schema) && ["string", "number", "date", "datetime"].includes(schema.type ?? "");
|
|
26
31
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
32
|
+
function isSchemaMap(schema) {
|
|
33
|
+
return isRecord(schema) && !("type" in schema);
|
|
29
34
|
}
|
|
30
|
-
function
|
|
31
|
-
|
|
35
|
+
function schemaEntries(schema) {
|
|
36
|
+
return Object.entries(schema);
|
|
37
|
+
}
|
|
38
|
+
function createDefaultFromSchema(schema) {
|
|
39
|
+
if (!schema || !schema.type) {
|
|
40
|
+
return "";
|
|
41
|
+
}
|
|
42
|
+
if (schema.type === "array") {
|
|
32
43
|
return [];
|
|
33
44
|
}
|
|
34
|
-
if (
|
|
45
|
+
if (schema.type === "object") {
|
|
35
46
|
const next = {};
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
const properties = schema.properties ?? {};
|
|
48
|
+
for (const key of Object.keys(properties)) {
|
|
49
|
+
next[key] = createDefaultFromSchema(properties[key]);
|
|
38
50
|
}
|
|
39
51
|
return next;
|
|
40
52
|
}
|
|
41
|
-
if (
|
|
53
|
+
if (schema.type === "boolean") {
|
|
42
54
|
return false;
|
|
43
55
|
}
|
|
44
|
-
if (
|
|
56
|
+
if (schema.type === "number") {
|
|
45
57
|
return 0;
|
|
46
58
|
}
|
|
47
59
|
return "";
|
|
48
60
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
function ensureInitializedFromSchema() {
|
|
62
|
+
const schema = props.schema;
|
|
63
|
+
if (!schema) {
|
|
52
64
|
return;
|
|
53
65
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
if (isSchemaMap(schema)) {
|
|
67
|
+
if (!isObject(frontmatter.value)) {
|
|
68
|
+
frontmatter.value = {};
|
|
69
|
+
}
|
|
70
|
+
for (const [key, fieldSchema] of schemaEntries(schema)) {
|
|
71
|
+
if (frontmatter.value[key] === void 0) {
|
|
72
|
+
frontmatter.value[key] = createDefaultFromSchema(fieldSchema);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
59
75
|
return;
|
|
60
76
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
if (isObjectSchema(schema)) {
|
|
78
|
+
if (!isObject(frontmatter.value)) {
|
|
79
|
+
frontmatter.value = {};
|
|
80
|
+
}
|
|
81
|
+
const properties = schema.properties ?? {};
|
|
82
|
+
for (const [key, fieldSchema] of schemaEntries(properties)) {
|
|
83
|
+
if (frontmatter.value[key] === void 0) {
|
|
84
|
+
frontmatter.value[key] = createDefaultFromSchema(fieldSchema);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
65
87
|
return;
|
|
66
88
|
}
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
if (isArraySchema(schema) && !Array.isArray(frontmatter.value)) {
|
|
90
|
+
frontmatter.value = [];
|
|
91
|
+
}
|
|
69
92
|
}
|
|
70
|
-
|
|
71
|
-
|
|
93
|
+
watch(
|
|
94
|
+
() => props.schema,
|
|
95
|
+
() => {
|
|
96
|
+
ensureInitializedFromSchema();
|
|
97
|
+
},
|
|
98
|
+
{ immediate: true, deep: true }
|
|
99
|
+
);
|
|
100
|
+
const objectSchemaEntries = computed(() => {
|
|
101
|
+
if (!props.schema) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
if (isSchemaMap(props.schema)) {
|
|
105
|
+
return schemaEntries(props.schema);
|
|
106
|
+
}
|
|
107
|
+
if (isObjectSchema(props.schema)) {
|
|
108
|
+
return schemaEntries(props.schema.properties ?? {});
|
|
109
|
+
}
|
|
110
|
+
return [];
|
|
111
|
+
});
|
|
112
|
+
const arrayItemSchema = computed(() => {
|
|
113
|
+
if (!props.schema || !isArraySchema(props.schema)) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return props.schema.items ?? null;
|
|
117
|
+
});
|
|
118
|
+
function addArrayItem(arrayRef, itemSchema) {
|
|
119
|
+
arrayRef.push(createDefaultFromSchema(itemSchema));
|
|
72
120
|
}
|
|
73
|
-
function
|
|
74
|
-
return
|
|
121
|
+
function getFieldLabel(key, fieldSchema) {
|
|
122
|
+
return fieldSchema.label || key;
|
|
75
123
|
}
|
|
76
|
-
function
|
|
77
|
-
if (
|
|
78
|
-
|
|
124
|
+
function getInputTypeFromSchema(schema) {
|
|
125
|
+
if (!schema || !schema.type) {
|
|
126
|
+
return "text";
|
|
127
|
+
}
|
|
128
|
+
if (schema.type === "number") {
|
|
129
|
+
return "number";
|
|
79
130
|
}
|
|
80
|
-
|
|
131
|
+
if (schema.type === "date") {
|
|
132
|
+
return "date";
|
|
133
|
+
}
|
|
134
|
+
if (schema.type === "datetime") {
|
|
135
|
+
return "datetime-local";
|
|
136
|
+
}
|
|
137
|
+
return "text";
|
|
81
138
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
139
|
+
function getUiHintFromSchema(schema) {
|
|
140
|
+
if (!schema || schema.type !== "string") {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
if (schema["x-ui"] === "image" || schema["x-ui"] === "pdf" || schema["x-ui"] === "file") {
|
|
144
|
+
return schema["x-ui"];
|
|
145
|
+
}
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
function removeArrayItem(arrayRef, index) {
|
|
149
|
+
if (arrayRef.length <= 1) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
arrayRef.splice(index, 1);
|
|
84
153
|
}
|
|
85
154
|
</script>
|
|
86
155
|
|
|
@@ -96,86 +165,24 @@ function toggleOpen(key) {
|
|
|
96
165
|
'bg-gray-100/90': props.depth >= 5
|
|
97
166
|
}"
|
|
98
167
|
>
|
|
99
|
-
<
|
|
100
|
-
v-if="props.label"
|
|
101
|
-
class="font-bold text-[15px]"
|
|
102
|
-
>
|
|
103
|
-
{{ props.label }}
|
|
104
|
-
</p>
|
|
105
|
-
|
|
106
|
-
<template v-if="Array.isArray(frontmatter)">
|
|
168
|
+
<template v-if="props.schema && isArraySchema(props.schema) && Array.isArray(frontmatter)">
|
|
107
169
|
<div
|
|
108
170
|
v-for="(item, index) in frontmatter"
|
|
109
171
|
:key="index"
|
|
110
|
-
class="flex flex-col gap-
|
|
172
|
+
class="flex flex-col gap-2"
|
|
111
173
|
>
|
|
112
|
-
<div class="flex items-center justify-
|
|
174
|
+
<div class="flex items-center justify-end gap-2">
|
|
113
175
|
<button
|
|
114
|
-
v-if="!isBoolean(item)"
|
|
115
176
|
type="button"
|
|
116
|
-
class="
|
|
117
|
-
:
|
|
118
|
-
@click="
|
|
177
|
+
class="button secondary small"
|
|
178
|
+
:disabled="frontmatter.length <= 1"
|
|
179
|
+
@click="removeArrayItem(frontmatter, index)"
|
|
119
180
|
>
|
|
120
|
-
|
|
121
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
122
|
-
fill="none"
|
|
123
|
-
viewBox="0 0 24 24"
|
|
124
|
-
stroke-width="1.5"
|
|
125
|
-
stroke="currentColor"
|
|
126
|
-
class="size-4 transition-transform duration-300"
|
|
127
|
-
:class="{ 'rotate-180': isOpen(arrayItemStateKey(index)) }"
|
|
128
|
-
>
|
|
129
|
-
<path
|
|
130
|
-
stroke-linecap="round"
|
|
131
|
-
stroke-linejoin="round"
|
|
132
|
-
d="m19.5 8.25-7.5 7.5-7.5-7.5"
|
|
133
|
-
/>
|
|
134
|
-
</svg>
|
|
135
|
-
<span class="font-bold text-sm">{{ arrayItemLabel(index) }}</span>
|
|
181
|
+
Entfernen
|
|
136
182
|
</button>
|
|
137
|
-
|
|
138
|
-
<div
|
|
139
|
-
v-else
|
|
140
|
-
class="flex-1 min-w-0 px-2 py-1"
|
|
141
|
-
>
|
|
142
|
-
<span class="font-bold text-sm">{{ arrayItemLabel(index) }}</span>
|
|
143
|
-
</div>
|
|
144
|
-
|
|
145
|
-
<div class="flex items-center gap-1">
|
|
146
|
-
<button
|
|
147
|
-
type="button"
|
|
148
|
-
class="button secondary small"
|
|
149
|
-
:disabled="index === 0"
|
|
150
|
-
@click="moveArrayItem(frontmatter, index, index - 1)"
|
|
151
|
-
>
|
|
152
|
-
↑
|
|
153
|
-
</button>
|
|
154
|
-
|
|
155
|
-
<button
|
|
156
|
-
type="button"
|
|
157
|
-
class="button secondary small"
|
|
158
|
-
:disabled="index === frontmatter.length - 1"
|
|
159
|
-
@click="moveArrayItem(frontmatter, index, index + 1)"
|
|
160
|
-
>
|
|
161
|
-
↓
|
|
162
|
-
</button>
|
|
163
|
-
|
|
164
|
-
<button
|
|
165
|
-
type="button"
|
|
166
|
-
class="button secondary small"
|
|
167
|
-
:disabled="frontmatter.length <= 1"
|
|
168
|
-
@click="removeArrayItem(frontmatter, index)"
|
|
169
|
-
>
|
|
170
|
-
Entfernen
|
|
171
|
-
</button>
|
|
172
|
-
</div>
|
|
173
183
|
</div>
|
|
174
184
|
|
|
175
|
-
<div
|
|
176
|
-
v-if="isBoolean(item)"
|
|
177
|
-
class="px-3 pb-3"
|
|
178
|
-
>
|
|
185
|
+
<div v-if="isBooleanSchema(arrayItemSchema)">
|
|
179
186
|
<label class="inline-flex items-center">
|
|
180
187
|
<input
|
|
181
188
|
v-model="frontmatter[index]"
|
|
@@ -185,110 +192,85 @@ function toggleOpen(key) {
|
|
|
185
192
|
</label>
|
|
186
193
|
</div>
|
|
187
194
|
|
|
188
|
-
<
|
|
189
|
-
v-else
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
v-if="typeof item === 'string' || isNumber(item)"
|
|
196
|
-
v-model:value="frontmatter[index]"
|
|
197
|
-
label=""
|
|
198
|
-
/>
|
|
195
|
+
<FrontmatterInput
|
|
196
|
+
v-else-if="isPrimitiveSchema(arrayItemSchema)"
|
|
197
|
+
v-model:value="frontmatter[index]"
|
|
198
|
+
label=""
|
|
199
|
+
:input-type="getInputTypeFromSchema(arrayItemSchema)"
|
|
200
|
+
:ui-hint="getUiHintFromSchema(arrayItemSchema)"
|
|
201
|
+
/>
|
|
199
202
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
<FrontmatterForm
|
|
204
|
+
v-else-if="isObjectSchema(arrayItemSchema) || isArraySchema(arrayItemSchema)"
|
|
205
|
+
v-model:frontmatter="frontmatter[index]"
|
|
206
|
+
:schema="arrayItemSchema"
|
|
207
|
+
:depth="props.depth + 1"
|
|
208
|
+
/>
|
|
206
209
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
</div>
|
|
213
|
-
</div>
|
|
210
|
+
<FrontmatterInput
|
|
211
|
+
v-else
|
|
212
|
+
v-model:value="frontmatter[index]"
|
|
213
|
+
label=""
|
|
214
|
+
/>
|
|
214
215
|
</div>
|
|
215
216
|
|
|
216
217
|
<button
|
|
217
218
|
type="button"
|
|
218
219
|
class="button secondary small self-start"
|
|
219
|
-
@click="addArrayItem(frontmatter)"
|
|
220
|
+
@click="addArrayItem(frontmatter, arrayItemSchema)"
|
|
220
221
|
>
|
|
221
222
|
Element hinzufügen
|
|
222
223
|
</button>
|
|
223
224
|
</template>
|
|
224
225
|
|
|
225
|
-
<template v-else>
|
|
226
|
+
<template v-else-if="objectSchemaEntries.length > 0 && isObject(frontmatter)">
|
|
226
227
|
<div
|
|
227
|
-
v-for="
|
|
228
|
-
:key="
|
|
229
|
-
class="flex flex-col gap-
|
|
228
|
+
v-for="entry in objectSchemaEntries"
|
|
229
|
+
:key="entry[0]"
|
|
230
|
+
class="flex flex-col gap-1"
|
|
230
231
|
>
|
|
231
232
|
<label
|
|
232
|
-
v-if="
|
|
233
|
-
class="w-full inline-flex items-center
|
|
233
|
+
v-if="isBooleanSchema(entry[1])"
|
|
234
|
+
class="w-full inline-flex items-center font-bold text-sm"
|
|
234
235
|
>
|
|
235
236
|
<input
|
|
236
|
-
v-model="frontmatter[
|
|
237
|
+
v-model="frontmatter[entry[0]]"
|
|
237
238
|
type="checkbox"
|
|
238
239
|
class="mr-2"
|
|
239
240
|
>
|
|
240
|
-
<span>{{
|
|
241
|
+
<span>{{ getFieldLabel(entry[0], entry[1]) }}</span>
|
|
241
242
|
</label>
|
|
242
243
|
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
:aria-expanded="isOpen(objectItemStateKey(key))"
|
|
248
|
-
@click="toggleOpen(objectItemStateKey(key))"
|
|
249
|
-
>
|
|
250
|
-
<svg
|
|
251
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
252
|
-
fill="none"
|
|
253
|
-
viewBox="0 0 24 24"
|
|
254
|
-
stroke-width="1.5"
|
|
255
|
-
stroke="currentColor"
|
|
256
|
-
class="size-4 transition-transform duration-300"
|
|
257
|
-
:class="{ 'rotate-180': isOpen(objectItemStateKey(key)) }"
|
|
258
|
-
>
|
|
259
|
-
<path
|
|
260
|
-
stroke-linecap="round"
|
|
261
|
-
stroke-linejoin="round"
|
|
262
|
-
d="m19.5 8.25-7.5 7.5-7.5-7.5"
|
|
263
|
-
/>
|
|
264
|
-
</svg>
|
|
265
|
-
<span class="font-bold text-sm">{{ key }}</span>
|
|
266
|
-
</button>
|
|
244
|
+
<template v-else>
|
|
245
|
+
<p class="font-bold text-sm">
|
|
246
|
+
{{ getFieldLabel(entry[0], entry[1]) }}
|
|
247
|
+
</p>
|
|
267
248
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
<FrontmatterInput
|
|
275
|
-
v-if="typeof frontmatter[key] === 'string' || isNumber(frontmatter[key])"
|
|
276
|
-
v-model:value="frontmatter[key]"
|
|
277
|
-
/>
|
|
249
|
+
<FrontmatterInput
|
|
250
|
+
v-if="isPrimitiveSchema(entry[1])"
|
|
251
|
+
v-model:value="frontmatter[entry[0]]"
|
|
252
|
+
:input-type="getInputTypeFromSchema(entry[1])"
|
|
253
|
+
:ui-hint="getUiHintFromSchema(entry[1])"
|
|
254
|
+
/>
|
|
278
255
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
256
|
+
<FrontmatterForm
|
|
257
|
+
v-else-if="isObjectSchema(entry[1]) || isArraySchema(entry[1])"
|
|
258
|
+
v-model:frontmatter="frontmatter[entry[0]]"
|
|
259
|
+
:schema="entry[1]"
|
|
260
|
+
:depth="props.depth + 1"
|
|
261
|
+
/>
|
|
285
262
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
263
|
+
<FrontmatterInput
|
|
264
|
+
v-else
|
|
265
|
+
v-model:value="frontmatter[entry[0]]"
|
|
266
|
+
/>
|
|
267
|
+
</template>
|
|
268
|
+
</div>
|
|
269
|
+
</template>
|
|
270
|
+
|
|
271
|
+
<template v-else>
|
|
272
|
+
<div class="text-sm text-gray-600">
|
|
273
|
+
Keine Felder in der Frontmatter-Konfiguration vorhanden.
|
|
292
274
|
</div>
|
|
293
275
|
</template>
|
|
294
276
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
|
-
label?: string;
|
|
3
2
|
depth?: number;
|
|
3
|
+
schema: Record<string, any> | null;
|
|
4
4
|
};
|
|
5
5
|
type __VLS_ModelProps = {
|
|
6
6
|
'frontmatter': any;
|
|
@@ -11,7 +11,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
11
11
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
12
|
"onUpdate:frontmatter"?: ((value: any) => any) | undefined;
|
|
13
13
|
}>, {
|
|
14
|
-
label: string;
|
|
15
14
|
depth: number;
|
|
16
15
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
16
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
label?: string;
|
|
3
|
+
inputType?: 'text' | 'number' | 'date' | 'datetime-local';
|
|
4
|
+
uiHint?: 'image' | 'pdf' | 'file';
|
|
3
5
|
};
|
|
4
6
|
type __VLS_ModelProps = {
|
|
5
7
|
'value': string | number;
|
|
@@ -11,6 +13,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
11
13
|
"onUpdate:value"?: ((value: string | number) => any) | undefined;
|
|
12
14
|
}>, {
|
|
13
15
|
label: string;
|
|
16
|
+
uiHint: "image" | "pdf" | "file";
|
|
17
|
+
inputType: "text" | "number" | "date" | "datetime-local";
|
|
14
18
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
19
|
declare const _default: typeof __VLS_export;
|
|
16
20
|
export default _default;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed, ref } from "vue";
|
|
3
|
-
import
|
|
3
|
+
import FilePickerModal from "./filePicker/modal.vue";
|
|
4
4
|
const props = defineProps({
|
|
5
|
-
label: { type: String, required: false, default: "" }
|
|
5
|
+
label: { type: String, required: false, default: "" },
|
|
6
|
+
inputType: { type: String, required: false, default: "text" },
|
|
7
|
+
uiHint: { type: String, required: false, default: void 0 }
|
|
6
8
|
});
|
|
7
9
|
const value = defineModel("value", { type: [String, Number], ...{
|
|
8
10
|
required: true
|
|
9
11
|
} });
|
|
10
|
-
const
|
|
12
|
+
const isPickerOpen = ref(false);
|
|
13
|
+
const resolvedInputType = computed(() => {
|
|
14
|
+
if (props.inputType !== "text") {
|
|
15
|
+
return props.inputType;
|
|
16
|
+
}
|
|
17
|
+
return typeof value.value === "number" ? "number" : "text";
|
|
18
|
+
});
|
|
19
|
+
const isNumberInput = computed(() => resolvedInputType.value === "number");
|
|
11
20
|
const inputValue = computed({
|
|
12
21
|
get() {
|
|
13
22
|
return `${value.value ?? ""}`;
|
|
@@ -21,7 +30,21 @@ const inputValue = computed({
|
|
|
21
30
|
value.value = newValue;
|
|
22
31
|
}
|
|
23
32
|
});
|
|
24
|
-
const
|
|
33
|
+
const pickerButtonLabel = computed(() => {
|
|
34
|
+
if (props.uiHint === "image") {
|
|
35
|
+
return "Bild ausw\xE4hlen";
|
|
36
|
+
}
|
|
37
|
+
if (props.uiHint === "pdf") {
|
|
38
|
+
return "PDF ausw\xE4hlen";
|
|
39
|
+
}
|
|
40
|
+
if (props.uiHint === "file") {
|
|
41
|
+
return "Datei ausw\xE4hlen";
|
|
42
|
+
}
|
|
43
|
+
return "";
|
|
44
|
+
});
|
|
45
|
+
function onPickerSelect(path) {
|
|
46
|
+
value.value = path;
|
|
47
|
+
}
|
|
25
48
|
</script>
|
|
26
49
|
|
|
27
50
|
<template>
|
|
@@ -32,41 +55,29 @@ const showFileSelect = ref(false);
|
|
|
32
55
|
>
|
|
33
56
|
{{ props.label }}
|
|
34
57
|
</label>
|
|
35
|
-
<div class="
|
|
58
|
+
<div class="flex items-center gap-2">
|
|
36
59
|
<input
|
|
37
60
|
v-model="inputValue"
|
|
38
|
-
:type="
|
|
61
|
+
:type="resolvedInputType"
|
|
39
62
|
class="w-full"
|
|
40
63
|
>
|
|
64
|
+
|
|
41
65
|
<button
|
|
42
|
-
v-if="
|
|
66
|
+
v-if="props.uiHint"
|
|
43
67
|
type="button"
|
|
44
|
-
class="
|
|
45
|
-
@click="
|
|
68
|
+
class="button secondary small whitespace-nowrap"
|
|
69
|
+
@click="isPickerOpen = true"
|
|
46
70
|
>
|
|
47
|
-
|
|
48
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
49
|
-
fill="none"
|
|
50
|
-
viewBox="0 0 24 24"
|
|
51
|
-
stroke-width="1.5"
|
|
52
|
-
stroke="currentColor"
|
|
53
|
-
class="size-5"
|
|
54
|
-
>
|
|
55
|
-
<path
|
|
56
|
-
stroke-linecap="round"
|
|
57
|
-
stroke-linejoin="round"
|
|
58
|
-
d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"
|
|
59
|
-
/>
|
|
60
|
-
</svg>
|
|
71
|
+
{{ pickerButtonLabel }}
|
|
61
72
|
</button>
|
|
62
73
|
</div>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
|
|
75
|
+
<FilePickerModal
|
|
76
|
+
v-if="props.uiHint"
|
|
77
|
+
:is-open="isPickerOpen"
|
|
78
|
+
:ui-hint="props.uiHint"
|
|
79
|
+
@close="isPickerOpen = false"
|
|
80
|
+
@select="onPickerSelect"
|
|
70
81
|
/>
|
|
71
82
|
</div>
|
|
72
83
|
</template>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
label?: string;
|
|
3
|
+
inputType?: 'text' | 'number' | 'date' | 'datetime-local';
|
|
4
|
+
uiHint?: 'image' | 'pdf' | 'file';
|
|
3
5
|
};
|
|
4
6
|
type __VLS_ModelProps = {
|
|
5
7
|
'value': string | number;
|
|
@@ -11,6 +13,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
11
13
|
"onUpdate:value"?: ((value: string | number) => any) | undefined;
|
|
12
14
|
}>, {
|
|
13
15
|
label: string;
|
|
16
|
+
uiHint: "image" | "pdf" | "file";
|
|
17
|
+
inputType: "text" | "number" | "date" | "datetime-local";
|
|
14
18
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
19
|
declare const _default: typeof __VLS_export;
|
|
16
20
|
export default _default;
|