@type32/yaml-editor-form 0.1.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/README.md +1092 -0
- package/dist/module.d.mts +8 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +25 -0
- package/dist/runtime/assets/css/main.css +1 -0
- package/dist/runtime/components/YamlCollapsible.d.vue.ts +47 -0
- package/dist/runtime/components/YamlCollapsible.vue +43 -0
- package/dist/runtime/components/YamlCollapsible.vue.d.ts +47 -0
- package/dist/runtime/components/YamlFieldInput.d.vue.ts +54 -0
- package/dist/runtime/components/YamlFieldInput.vue +158 -0
- package/dist/runtime/components/YamlFieldInput.vue.d.ts +54 -0
- package/dist/runtime/components/YamlFormEditor.d.vue.ts +66 -0
- package/dist/runtime/components/YamlFormEditor.vue +70 -0
- package/dist/runtime/components/YamlFormEditor.vue.d.ts +66 -0
- package/dist/runtime/components/YamlFormField.d.vue.ts +56 -0
- package/dist/runtime/components/YamlFormField.vue +492 -0
- package/dist/runtime/components/YamlFormField.vue.d.ts +56 -0
- package/dist/runtime/composables/useYamlFieldTypes.d.ts +13 -0
- package/dist/runtime/composables/useYamlFieldTypes.js +137 -0
- package/dist/runtime/composables/useYamlFormData.d.ts +24 -0
- package/dist/runtime/composables/useYamlFormData.js +122 -0
- package/dist/runtime/types/types.d.ts +30 -0
- package/dist/types.d.mts +3 -0
- package/package.json +76 -0
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addComponentsDir, addImportsDir } from '@nuxt/kit';
|
|
2
|
+
|
|
3
|
+
const module$1 = defineNuxtModule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "@type32/yaml-editor-form",
|
|
6
|
+
configKey: "yamlEditorForm"
|
|
7
|
+
},
|
|
8
|
+
// Default configuration options of the Nuxt module
|
|
9
|
+
defaults: {},
|
|
10
|
+
setup(_options, _nuxt) {
|
|
11
|
+
const resolver = createResolver(import.meta.url);
|
|
12
|
+
addComponentsDir({ path: resolver.resolve("runtime/components") });
|
|
13
|
+
addImportsDir(resolver.resolve("runtime/composables"));
|
|
14
|
+
_nuxt.options.build.transpile.push("js-yaml");
|
|
15
|
+
_nuxt.options.alias["@type32/yaml-editor-form"] = resolver.resolve(
|
|
16
|
+
"./runtime/types/types"
|
|
17
|
+
);
|
|
18
|
+
_nuxt.options.alias["@type32/yaml-editor-form"] = resolver.resolve(
|
|
19
|
+
"./runtime/assets/css"
|
|
20
|
+
);
|
|
21
|
+
_nuxt.options.css.unshift(resolver.resolve("./runtime/assets/css/main.css"));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export { module$1 as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";@import "tailwindcss/utilities" layer(utilities);@import "@nuxt/ui";.yaml-collapsible-content{@apply mt-1 ml-2 pl-3 border-l border-l-muted}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
declare var __VLS_13: {}, __VLS_15: {}, __VLS_18: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
badge?: (props: typeof __VLS_13) => any;
|
|
4
|
+
} & {
|
|
5
|
+
actions?: (props: typeof __VLS_15) => any;
|
|
6
|
+
} & {
|
|
7
|
+
default?: (props: typeof __VLS_18) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
10
|
+
label: {
|
|
11
|
+
type: StringConstructor;
|
|
12
|
+
required: true;
|
|
13
|
+
};
|
|
14
|
+
defaultOpen: {
|
|
15
|
+
type: BooleanConstructor;
|
|
16
|
+
default: boolean;
|
|
17
|
+
};
|
|
18
|
+
open: {
|
|
19
|
+
type: import("vue").PropType<boolean>;
|
|
20
|
+
};
|
|
21
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
22
|
+
"update:open": (value: boolean) => any;
|
|
23
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
24
|
+
label: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
required: true;
|
|
27
|
+
};
|
|
28
|
+
defaultOpen: {
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
};
|
|
32
|
+
open: {
|
|
33
|
+
type: import("vue").PropType<boolean>;
|
|
34
|
+
};
|
|
35
|
+
}>> & Readonly<{
|
|
36
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
37
|
+
}>, {
|
|
38
|
+
defaultOpen: boolean;
|
|
39
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
40
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
41
|
+
declare const _default: typeof __VLS_export;
|
|
42
|
+
export default _default;
|
|
43
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
44
|
+
new (): {
|
|
45
|
+
$slots: S;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
label: {
|
|
4
|
+
type: String,
|
|
5
|
+
required: true
|
|
6
|
+
},
|
|
7
|
+
defaultOpen: {
|
|
8
|
+
type: Boolean,
|
|
9
|
+
default: false
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const open = defineModel("open", { type: Boolean, default: void 0 });
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<UCollapsible
|
|
17
|
+
v-model:open="open"
|
|
18
|
+
:default-open="defaultOpen"
|
|
19
|
+
class="group/collapsible"
|
|
20
|
+
>
|
|
21
|
+
<div class="flex items-center justify-between gap-2 w-full">
|
|
22
|
+
<div class="flex items-center gap-2">
|
|
23
|
+
<div
|
|
24
|
+
class="flex items-center justify-center size-3.5 rounded bg-elevated transition-colors duration-200 group-hover/collapsible:bg-accented">
|
|
25
|
+
<UIcon
|
|
26
|
+
name="i-lucide-chevron-right"
|
|
27
|
+
class="size-2.5 text-muted transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
<span class="text-xs font-medium text-highlighted tracking-tight">{{ label }}</span>
|
|
31
|
+
<slot name="badge"/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<slot name="actions"/>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<template #content>
|
|
38
|
+
<div class="yaml-collapsible-content">
|
|
39
|
+
<slot/>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
</UCollapsible>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
declare var __VLS_13: {}, __VLS_15: {}, __VLS_18: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
badge?: (props: typeof __VLS_13) => any;
|
|
4
|
+
} & {
|
|
5
|
+
actions?: (props: typeof __VLS_15) => any;
|
|
6
|
+
} & {
|
|
7
|
+
default?: (props: typeof __VLS_18) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
10
|
+
label: {
|
|
11
|
+
type: StringConstructor;
|
|
12
|
+
required: true;
|
|
13
|
+
};
|
|
14
|
+
defaultOpen: {
|
|
15
|
+
type: BooleanConstructor;
|
|
16
|
+
default: boolean;
|
|
17
|
+
};
|
|
18
|
+
open: {
|
|
19
|
+
type: import("vue").PropType<boolean>;
|
|
20
|
+
};
|
|
21
|
+
}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
22
|
+
"update:open": (value: boolean) => any;
|
|
23
|
+
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
24
|
+
label: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
required: true;
|
|
27
|
+
};
|
|
28
|
+
defaultOpen: {
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
};
|
|
32
|
+
open: {
|
|
33
|
+
type: import("vue").PropType<boolean>;
|
|
34
|
+
};
|
|
35
|
+
}>> & Readonly<{
|
|
36
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
37
|
+
}>, {
|
|
38
|
+
defaultOpen: boolean;
|
|
39
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
40
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
41
|
+
declare const _default: typeof __VLS_export;
|
|
42
|
+
export default _default;
|
|
43
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
44
|
+
new (): {
|
|
45
|
+
$slots: S;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { YamlFieldType } from "../types/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* YAML Field Input - Renders input components for simple field types
|
|
4
|
+
*
|
|
5
|
+
* Handles rendering of all primitive/simple type inputs:
|
|
6
|
+
* - String (UInput)
|
|
7
|
+
* - Textarea (UTextarea)
|
|
8
|
+
* - Number (UInputNumber)
|
|
9
|
+
* - Boolean (USwitch)
|
|
10
|
+
* - Date (UInputDate)
|
|
11
|
+
* - DateTime (UInputDate with granularity)
|
|
12
|
+
* - Tags (UInputTags)
|
|
13
|
+
* - Null (UInput disabled)
|
|
14
|
+
*
|
|
15
|
+
* Custom field types can be rendered via slots.
|
|
16
|
+
*/
|
|
17
|
+
type YamlValue = string | number | boolean | null | Date | YamlValue[] | {
|
|
18
|
+
[key: string]: YamlValue;
|
|
19
|
+
};
|
|
20
|
+
type __VLS_Props = {
|
|
21
|
+
/** Type of the field (string, number, boolean, etc.) */
|
|
22
|
+
valueType: string;
|
|
23
|
+
/** Whether the field is read-only */
|
|
24
|
+
readonly?: boolean;
|
|
25
|
+
/** Optional field type definition for custom component detection */
|
|
26
|
+
fieldType?: YamlFieldType;
|
|
27
|
+
};
|
|
28
|
+
type __VLS_ModelProps = {
|
|
29
|
+
modelValue: YamlValue;
|
|
30
|
+
};
|
|
31
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
32
|
+
declare var __VLS_2: string, __VLS_3: {
|
|
33
|
+
modelValue: YamlValue;
|
|
34
|
+
readonly: boolean;
|
|
35
|
+
valueType: string;
|
|
36
|
+
};
|
|
37
|
+
type __VLS_Slots = {} & {
|
|
38
|
+
[K in NonNullable<typeof __VLS_2>]?: (props: typeof __VLS_3) => any;
|
|
39
|
+
};
|
|
40
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
41
|
+
"update:modelValue": (value: YamlValue) => any;
|
|
42
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
43
|
+
"onUpdate:modelValue"?: ((value: YamlValue) => any) | undefined;
|
|
44
|
+
}>, {
|
|
45
|
+
readonly: boolean;
|
|
46
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
47
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
48
|
+
declare const _default: typeof __VLS_export;
|
|
49
|
+
export default _default;
|
|
50
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
51
|
+
new (): {
|
|
52
|
+
$slots: S;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { CalendarDate, CalendarDateTime, parseDate, parseDateTime } from "@internationalized/date";
|
|
3
|
+
import { ref, watch, computed } from "vue";
|
|
4
|
+
const modelValue = defineModel({ type: [String, Number, Boolean, null, Date, Array, Object], ...{ required: true } });
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
valueType: { type: String, required: true },
|
|
7
|
+
readonly: { type: Boolean, required: false, default: false },
|
|
8
|
+
fieldType: { type: Object, required: false }
|
|
9
|
+
});
|
|
10
|
+
function isDateObject(val) {
|
|
11
|
+
return val instanceof Date && !isNaN(val.getTime());
|
|
12
|
+
}
|
|
13
|
+
function jsDateToCalendarDate(date) {
|
|
14
|
+
return new CalendarDate(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
15
|
+
}
|
|
16
|
+
function jsDateToCalendarDateTime(date) {
|
|
17
|
+
return new CalendarDateTime(
|
|
18
|
+
date.getFullYear(),
|
|
19
|
+
date.getMonth() + 1,
|
|
20
|
+
date.getDate(),
|
|
21
|
+
date.getHours(),
|
|
22
|
+
date.getMinutes(),
|
|
23
|
+
date.getSeconds()
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function stringToCalendarDate(str) {
|
|
27
|
+
try {
|
|
28
|
+
return parseDate(str);
|
|
29
|
+
} catch {
|
|
30
|
+
return jsDateToCalendarDate(/* @__PURE__ */ new Date());
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function stringToCalendarDateTime(str) {
|
|
34
|
+
try {
|
|
35
|
+
return parseDateTime(str);
|
|
36
|
+
} catch {
|
|
37
|
+
return jsDateToCalendarDateTime(/* @__PURE__ */ new Date());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const hasCustomComponent = computed(() => {
|
|
41
|
+
return props.fieldType?.component !== void 0;
|
|
42
|
+
});
|
|
43
|
+
const customSlotName = computed(() => {
|
|
44
|
+
return props.fieldType?.component ? `field-${props.fieldType.component}` : void 0;
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<!-- Custom Component via Slot -->
|
|
50
|
+
<slot
|
|
51
|
+
v-if="hasCustomComponent && customSlotName"
|
|
52
|
+
:name="customSlotName"
|
|
53
|
+
:model-value="modelValue"
|
|
54
|
+
:readonly="readonly"
|
|
55
|
+
:value-type="valueType"
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
<!-- Built-in Input Components -->
|
|
59
|
+
<template v-else>
|
|
60
|
+
<!-- String -->
|
|
61
|
+
<UInput
|
|
62
|
+
v-if="valueType === 'string'"
|
|
63
|
+
:model-value="String(modelValue)"
|
|
64
|
+
size="xs"
|
|
65
|
+
:disabled="readonly"
|
|
66
|
+
placeholder="Enter text..."
|
|
67
|
+
@update:model-value="(val) => modelValue = val"
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<!-- Textarea (Long Text) -->
|
|
71
|
+
<UTextarea
|
|
72
|
+
v-else-if="valueType === 'textarea'"
|
|
73
|
+
:model-value="String(modelValue)"
|
|
74
|
+
size="xs"
|
|
75
|
+
:disabled="readonly"
|
|
76
|
+
placeholder="Enter long text..."
|
|
77
|
+
:rows="4"
|
|
78
|
+
autoresize
|
|
79
|
+
@update:model-value="(val) => modelValue = val"
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
<!-- Number -->
|
|
83
|
+
<UInputNumber
|
|
84
|
+
v-else-if="valueType === 'number'"
|
|
85
|
+
:model-value="Number(modelValue)"
|
|
86
|
+
size="xs"
|
|
87
|
+
:disabled="readonly"
|
|
88
|
+
placeholder="0"
|
|
89
|
+
@update:model-value="(val) => modelValue = val ?? 0"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<!-- Boolean -->
|
|
93
|
+
<USwitch
|
|
94
|
+
v-else-if="valueType === 'boolean'"
|
|
95
|
+
:model-value="Boolean(modelValue)"
|
|
96
|
+
size="xs"
|
|
97
|
+
:disabled="readonly"
|
|
98
|
+
@update:model-value="(val) => modelValue = val"
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<!-- Date (Date only, no time) -->
|
|
102
|
+
<UInputDate
|
|
103
|
+
v-else-if="valueType === 'date'"
|
|
104
|
+
:model-value="typeof modelValue === 'string' ? stringToCalendarDate(modelValue) : jsDateToCalendarDate(/* @__PURE__ */ new Date())"
|
|
105
|
+
size="xs"
|
|
106
|
+
:disabled="readonly"
|
|
107
|
+
@update:model-value="(val) => {
|
|
108
|
+
if (val && 'year' in val) {
|
|
109
|
+
modelValue = `${val.year}-${String(val.month).padStart(2, '0')}-${String(val.day).padStart(2, '0')}`;
|
|
110
|
+
}
|
|
111
|
+
}"
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<!-- DateTime (Date + Time) - UInputDate handles both with granularity -->
|
|
115
|
+
<UInputDate
|
|
116
|
+
v-else-if="valueType === 'datetime'"
|
|
117
|
+
:model-value="typeof modelValue === 'string' ? stringToCalendarDateTime(modelValue) : jsDateToCalendarDateTime(/* @__PURE__ */ new Date())"
|
|
118
|
+
size="xs"
|
|
119
|
+
:disabled="readonly"
|
|
120
|
+
granularity="second"
|
|
121
|
+
@update:model-value="(val) => {
|
|
122
|
+
if (val && 'year' in val && 'month' in val && 'day' in val) {
|
|
123
|
+
const hour = 'hour' in val ? val.hour : 0;
|
|
124
|
+
const minute = 'minute' in val ? val.minute : 0;
|
|
125
|
+
const second = 'second' in val ? val.second : 0;
|
|
126
|
+
const newDateTime = new CalendarDateTime(val.year, val.month, val.day, hour, minute, second);
|
|
127
|
+
const isoString = `${newDateTime.year}-${String(newDateTime.month).padStart(2, '0')}-${String(newDateTime.day).padStart(2, '0')}T${String(newDateTime.hour).padStart(2, '0')}:${String(newDateTime.minute).padStart(2, '0')}:${String(newDateTime.second).padStart(2, '0')}`;
|
|
128
|
+
modelValue = isoString;
|
|
129
|
+
}
|
|
130
|
+
}"
|
|
131
|
+
/>
|
|
132
|
+
|
|
133
|
+
<!-- String Array (Tags) -->
|
|
134
|
+
<UInputTags
|
|
135
|
+
v-else-if="valueType === 'string-array'"
|
|
136
|
+
:model-value="Array.isArray(modelValue) ? modelValue : []"
|
|
137
|
+
size="xs"
|
|
138
|
+
:disabled="readonly"
|
|
139
|
+
placeholder="Add tags..."
|
|
140
|
+
@update:model-value="(val) => modelValue = val"
|
|
141
|
+
/>
|
|
142
|
+
|
|
143
|
+
<!-- Null -->
|
|
144
|
+
<div v-else-if="valueType === 'null'" class="text-xs text-muted italic">
|
|
145
|
+
null
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<!-- Fallback for unknown types -->
|
|
149
|
+
<UInput
|
|
150
|
+
v-else
|
|
151
|
+
:model-value="String(modelValue || '')"
|
|
152
|
+
size="xs"
|
|
153
|
+
:disabled="readonly"
|
|
154
|
+
placeholder="Enter value..."
|
|
155
|
+
@update:model-value="(val) => modelValue = val"
|
|
156
|
+
/>
|
|
157
|
+
</template>
|
|
158
|
+
</template>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { YamlFieldType } from "../types/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* YAML Field Input - Renders input components for simple field types
|
|
4
|
+
*
|
|
5
|
+
* Handles rendering of all primitive/simple type inputs:
|
|
6
|
+
* - String (UInput)
|
|
7
|
+
* - Textarea (UTextarea)
|
|
8
|
+
* - Number (UInputNumber)
|
|
9
|
+
* - Boolean (USwitch)
|
|
10
|
+
* - Date (UInputDate)
|
|
11
|
+
* - DateTime (UInputDate with granularity)
|
|
12
|
+
* - Tags (UInputTags)
|
|
13
|
+
* - Null (UInput disabled)
|
|
14
|
+
*
|
|
15
|
+
* Custom field types can be rendered via slots.
|
|
16
|
+
*/
|
|
17
|
+
type YamlValue = string | number | boolean | null | Date | YamlValue[] | {
|
|
18
|
+
[key: string]: YamlValue;
|
|
19
|
+
};
|
|
20
|
+
type __VLS_Props = {
|
|
21
|
+
/** Type of the field (string, number, boolean, etc.) */
|
|
22
|
+
valueType: string;
|
|
23
|
+
/** Whether the field is read-only */
|
|
24
|
+
readonly?: boolean;
|
|
25
|
+
/** Optional field type definition for custom component detection */
|
|
26
|
+
fieldType?: YamlFieldType;
|
|
27
|
+
};
|
|
28
|
+
type __VLS_ModelProps = {
|
|
29
|
+
modelValue: YamlValue;
|
|
30
|
+
};
|
|
31
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
32
|
+
declare var __VLS_2: string, __VLS_3: {
|
|
33
|
+
modelValue: YamlValue;
|
|
34
|
+
readonly: boolean;
|
|
35
|
+
valueType: string;
|
|
36
|
+
};
|
|
37
|
+
type __VLS_Slots = {} & {
|
|
38
|
+
[K in NonNullable<typeof __VLS_2>]?: (props: typeof __VLS_3) => any;
|
|
39
|
+
};
|
|
40
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
41
|
+
"update:modelValue": (value: YamlValue) => any;
|
|
42
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
43
|
+
"onUpdate:modelValue"?: ((value: YamlValue) => any) | undefined;
|
|
44
|
+
}>, {
|
|
45
|
+
readonly: boolean;
|
|
46
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
47
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
48
|
+
declare const _default: typeof __VLS_export;
|
|
49
|
+
export default _default;
|
|
50
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
51
|
+
new (): {
|
|
52
|
+
$slots: S;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { YamlFieldType, YamlFormData } from "../types/types.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
filePath?: string;
|
|
4
|
+
readonly?: boolean;
|
|
5
|
+
/** Custom field type definitions (merged with defaults) */
|
|
6
|
+
fieldTypes?: YamlFieldType[];
|
|
7
|
+
};
|
|
8
|
+
type __VLS_ModelProps = {
|
|
9
|
+
/**
|
|
10
|
+
* YAML Form Data Editor
|
|
11
|
+
*
|
|
12
|
+
* Schema-driven form editor for YAML/frontmatter data.
|
|
13
|
+
* Supports custom field types through the fieldTypes prop.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Primitive types (string, number, boolean, null)
|
|
17
|
+
* - Complex types (date, datetime, string-array)
|
|
18
|
+
* - Objects (nested structures)
|
|
19
|
+
* - Arrays (primitives and objects)
|
|
20
|
+
* - Recursive structures
|
|
21
|
+
* - Custom field types with custom components
|
|
22
|
+
*
|
|
23
|
+
* Can be used standalone or embedded in the rich text editor for frontmatter editing.
|
|
24
|
+
*/
|
|
25
|
+
modelValue: YamlFormData;
|
|
26
|
+
};
|
|
27
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
28
|
+
declare var __VLS_19: string, __VLS_20: any;
|
|
29
|
+
type __VLS_Slots = {} & {
|
|
30
|
+
[K in NonNullable<typeof __VLS_19>]?: (props: typeof __VLS_20) => any;
|
|
31
|
+
};
|
|
32
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
33
|
+
"update:modelValue": (value: {
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
date?: Date;
|
|
38
|
+
draft?: boolean;
|
|
39
|
+
tags?: string[];
|
|
40
|
+
categories?: string[];
|
|
41
|
+
image?: string;
|
|
42
|
+
slug?: string;
|
|
43
|
+
}) => any;
|
|
44
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
45
|
+
"onUpdate:modelValue"?: ((value: {
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
title?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
date?: Date;
|
|
50
|
+
draft?: boolean;
|
|
51
|
+
tags?: string[];
|
|
52
|
+
categories?: string[];
|
|
53
|
+
image?: string;
|
|
54
|
+
slug?: string;
|
|
55
|
+
}) => any) | undefined;
|
|
56
|
+
}>, {
|
|
57
|
+
readonly: boolean;
|
|
58
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
59
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
60
|
+
declare const _default: typeof __VLS_export;
|
|
61
|
+
export default _default;
|
|
62
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
63
|
+
new (): {
|
|
64
|
+
$slots: S;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useYamlFieldTypes } from "../composables/useYamlFieldTypes";
|
|
3
|
+
import { ref, watch, computed } from "vue";
|
|
4
|
+
const data = defineModel({ type: null, ...{ required: true } });
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
filePath: { type: String, required: false },
|
|
7
|
+
readonly: { type: Boolean, required: false, default: false },
|
|
8
|
+
fieldTypes: { type: Array, required: false }
|
|
9
|
+
});
|
|
10
|
+
const { getDefaultValue, getTypeMenuItems } = useYamlFieldTypes(props.fieldTypes);
|
|
11
|
+
const isDirty = ref(false);
|
|
12
|
+
watch(data, () => {
|
|
13
|
+
isDirty.value = true;
|
|
14
|
+
}, { deep: true });
|
|
15
|
+
function addField(fieldType = "string") {
|
|
16
|
+
if (!data.value) data.value = {};
|
|
17
|
+
const newKey = `field_${Object.keys(data.value).length + 1}`;
|
|
18
|
+
data.value[newKey] = getDefaultValue(fieldType);
|
|
19
|
+
}
|
|
20
|
+
function removeField(key) {
|
|
21
|
+
if (data.value) {
|
|
22
|
+
delete data.value[key];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const addFieldOptions = computed(() => {
|
|
26
|
+
return getTypeMenuItems((type) => addField(type));
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<ClientOnly>
|
|
32
|
+
<div class="space-y-4">
|
|
33
|
+
<div class="space-y-3">
|
|
34
|
+
<YamlFormField
|
|
35
|
+
v-for="(value, key) in data"
|
|
36
|
+
:key="String(key)"
|
|
37
|
+
v-model="data[key]"
|
|
38
|
+
:field-key="String(key)"
|
|
39
|
+
:readonly="readonly"
|
|
40
|
+
:field-types="fieldTypes"
|
|
41
|
+
@remove="removeField(String(key))"
|
|
42
|
+
@update:field-key="(newKey) => {
|
|
43
|
+
if (newKey !== key) {
|
|
44
|
+
data[newKey] = data[key];
|
|
45
|
+
delete data[key];
|
|
46
|
+
}
|
|
47
|
+
}"
|
|
48
|
+
>
|
|
49
|
+
<!-- Forward all slots to YamlFormField for custom field components -->
|
|
50
|
+
<template v-for="(_, name) in $slots" #[name]="slotProps">
|
|
51
|
+
<slot :name="name" v-bind="slotProps" />
|
|
52
|
+
</template>
|
|
53
|
+
</YamlFormField>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<UDropdownMenu
|
|
57
|
+
v-if="!readonly"
|
|
58
|
+
:items="[addFieldOptions]"
|
|
59
|
+
size="sm"
|
|
60
|
+
>
|
|
61
|
+
<UButton
|
|
62
|
+
icon="i-lucide-plus"
|
|
63
|
+
label="Add Field"
|
|
64
|
+
variant="ghost"
|
|
65
|
+
size="sm"
|
|
66
|
+
/>
|
|
67
|
+
</UDropdownMenu>
|
|
68
|
+
</div>
|
|
69
|
+
</ClientOnly>
|
|
70
|
+
</template>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { YamlFieldType, YamlFormData } from "../types/types.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
filePath?: string;
|
|
4
|
+
readonly?: boolean;
|
|
5
|
+
/** Custom field type definitions (merged with defaults) */
|
|
6
|
+
fieldTypes?: YamlFieldType[];
|
|
7
|
+
};
|
|
8
|
+
type __VLS_ModelProps = {
|
|
9
|
+
/**
|
|
10
|
+
* YAML Form Data Editor
|
|
11
|
+
*
|
|
12
|
+
* Schema-driven form editor for YAML/frontmatter data.
|
|
13
|
+
* Supports custom field types through the fieldTypes prop.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Primitive types (string, number, boolean, null)
|
|
17
|
+
* - Complex types (date, datetime, string-array)
|
|
18
|
+
* - Objects (nested structures)
|
|
19
|
+
* - Arrays (primitives and objects)
|
|
20
|
+
* - Recursive structures
|
|
21
|
+
* - Custom field types with custom components
|
|
22
|
+
*
|
|
23
|
+
* Can be used standalone or embedded in the rich text editor for frontmatter editing.
|
|
24
|
+
*/
|
|
25
|
+
modelValue: YamlFormData;
|
|
26
|
+
};
|
|
27
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
28
|
+
declare var __VLS_19: string, __VLS_20: any;
|
|
29
|
+
type __VLS_Slots = {} & {
|
|
30
|
+
[K in NonNullable<typeof __VLS_19>]?: (props: typeof __VLS_20) => any;
|
|
31
|
+
};
|
|
32
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
33
|
+
"update:modelValue": (value: {
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
date?: Date;
|
|
38
|
+
draft?: boolean;
|
|
39
|
+
tags?: string[];
|
|
40
|
+
categories?: string[];
|
|
41
|
+
image?: string;
|
|
42
|
+
slug?: string;
|
|
43
|
+
}) => any;
|
|
44
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
45
|
+
"onUpdate:modelValue"?: ((value: {
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
title?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
date?: Date;
|
|
50
|
+
draft?: boolean;
|
|
51
|
+
tags?: string[];
|
|
52
|
+
categories?: string[];
|
|
53
|
+
image?: string;
|
|
54
|
+
slug?: string;
|
|
55
|
+
}) => any) | undefined;
|
|
56
|
+
}>, {
|
|
57
|
+
readonly: boolean;
|
|
58
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
59
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
60
|
+
declare const _default: typeof __VLS_export;
|
|
61
|
+
export default _default;
|
|
62
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
63
|
+
new (): {
|
|
64
|
+
$slots: S;
|
|
65
|
+
};
|
|
66
|
+
};
|