rimelight-components 2.0.97 → 2.0.99
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.d.mts +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/page/PageEditor.d.vue.ts +2 -2
- package/dist/runtime/components/page/PageEditor.vue +52 -26
- package/dist/runtime/components/page/PageEditor.vue.d.ts +2 -2
- package/dist/runtime/components/page/PagePropertiesEditor.vue +46 -61
- package/dist/runtime/components/page/PagePropertiesRenderer.d.vue.ts +12 -2
- package/dist/runtime/components/page/PagePropertiesRenderer.vue +91 -88
- package/dist/runtime/components/page/PagePropertiesRenderer.vue.d.ts +12 -2
- package/dist/runtime/components/page/PageRenderer.d.vue.ts +21 -0
- package/dist/runtime/components/page/PageRenderer.vue +57 -0
- package/dist/runtime/components/page/PageRenderer.vue.d.ts +21 -0
- package/dist/runtime/types/pages.d.ts +3 -2
- package/dist/runtime/utils/page.d.ts +16 -2
- package/dist/types.d.mts +2 -0
- package/package.json +1 -1
package/dist/module.d.mts
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { readdirSync } from 'node:fs';
|
|
|
4
4
|
import { basename } from 'node:path';
|
|
5
5
|
|
|
6
6
|
const name = "rimelight-components";
|
|
7
|
-
const version = "2.0.
|
|
7
|
+
const version = "2.0.99";
|
|
8
8
|
const homepage = "https://rimelight.com/tools/rimelight-components";
|
|
9
9
|
|
|
10
10
|
const defaultOptions = {
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { ref, computed, useTemplateRef } from "vue";
|
|
3
3
|
import { usePageEditor } from "../../composables";
|
|
4
|
+
import { getLocalizedContent } from "../../utils";
|
|
4
5
|
const page = defineModel({ type: null, ...{ required: true } });
|
|
5
6
|
const { undo, redo, canUndo, canRedo, captureSnapshot } = usePageEditor(page);
|
|
7
|
+
const { isSaving } = defineProps({
|
|
8
|
+
isSaving: { type: Boolean, required: true }
|
|
9
|
+
});
|
|
6
10
|
const emit = defineEmits(["save"]);
|
|
7
11
|
const handleSave = () => {
|
|
8
12
|
const dataToPersist = JSON.parse(JSON.stringify(page.value));
|
|
@@ -14,9 +18,6 @@ defineExpose({
|
|
|
14
18
|
canUndo,
|
|
15
19
|
canRedo
|
|
16
20
|
});
|
|
17
|
-
defineProps({
|
|
18
|
-
isSaving: { type: Boolean, required: true }
|
|
19
|
-
});
|
|
20
21
|
const editorRef = useTemplateRef("editor");
|
|
21
22
|
const showPreview = ref(false);
|
|
22
23
|
const editorPanelClass = computed(() => ({
|
|
@@ -71,33 +72,58 @@ const editorPanelClass = computed(() => ({
|
|
|
71
72
|
</div>
|
|
72
73
|
</template>
|
|
73
74
|
</UHeader>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
<UContainer class="mt-24 grid gap-xl" :class="showPreview ? 'grid-cols-2 max-w-full' : 'grid-cols-1'">
|
|
76
|
+
<div :class="editorPanelClass" class="grid grid-cols-1 lg:grid-cols-4 gap-8">
|
|
77
|
+
<UPageAside class="order-1 lg:order-2 lg:col-span-1">
|
|
78
|
+
<RCPagePropertiesEditor v-model="page" />
|
|
79
|
+
</UPageAside>
|
|
80
|
+
<div class="order-2 lg:order-1 lg:col-span-3">
|
|
81
|
+
<UPageHeader :title="getLocalizedContent(page.title, 'en')" :description="getLocalizedContent(page.description, 'en') ?? ''" />
|
|
79
82
|
<RCBlockEditor
|
|
80
83
|
ref="editor"
|
|
81
84
|
v-model="page.blocks"
|
|
82
85
|
:class="editorPanelClass"
|
|
83
86
|
@mutation="captureSnapshot"
|
|
84
87
|
/>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
<div class="flex flex-col gap-xs text-xs">
|
|
89
|
+
<h6>Metadata</h6>
|
|
90
|
+
<span>Page ID: {{ page.id }}</span>
|
|
91
|
+
<span>Created At: <NuxtTime
|
|
92
|
+
:datetime="page.created_at ?? ''"
|
|
93
|
+
year="numeric"
|
|
94
|
+
month="numeric"
|
|
95
|
+
day="numeric"
|
|
96
|
+
hour="numeric"
|
|
97
|
+
minute="numeric"
|
|
98
|
+
second="numeric"
|
|
99
|
+
time-zone-name="short"
|
|
100
|
+
/></span>
|
|
101
|
+
<span>Posted At: <NuxtTime
|
|
102
|
+
:datetime="page.created_at ?? ''"
|
|
103
|
+
year="numeric"
|
|
104
|
+
month="numeric"
|
|
105
|
+
day="numeric"
|
|
106
|
+
hour="numeric"
|
|
107
|
+
minute="numeric"
|
|
108
|
+
second="numeric"
|
|
109
|
+
time-zone-name="short"
|
|
110
|
+
/></span>
|
|
111
|
+
<span>Updated At: <NuxtTime
|
|
112
|
+
:datetime="page.created_at ?? ''"
|
|
113
|
+
year="numeric"
|
|
114
|
+
month="numeric"
|
|
115
|
+
day="numeric"
|
|
116
|
+
hour="numeric"
|
|
117
|
+
minute="numeric"
|
|
118
|
+
second="numeric"
|
|
119
|
+
time-zone-name="short"
|
|
120
|
+
/></span>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
<div class="flex flex-row gap-xl">
|
|
125
|
+
<USeparator orientation="vertical" />
|
|
126
|
+
<RCPageRenderer v-if="showPreview" v-model="page"/>
|
|
127
|
+
</div>
|
|
128
|
+
</UContainer>
|
|
103
129
|
</template>
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed } from "vue";
|
|
3
2
|
import { useI18n } from "vue-i18n";
|
|
3
|
+
import { getLocalizedContent } from "../../utils";
|
|
4
4
|
import {} from "../../types";
|
|
5
5
|
const page = defineModel({ type: null, ...{ required: true } });
|
|
6
6
|
const locale = useI18n().locale;
|
|
7
|
-
const properties = computed(() => page.value.properties);
|
|
8
|
-
const groups = computed(() => {
|
|
9
|
-
return page.value.properties;
|
|
10
|
-
});
|
|
11
7
|
const isFieldVisible = (fieldSchema) => {
|
|
12
8
|
if (!fieldSchema.visibleIf) return true;
|
|
13
9
|
return fieldSchema.visibleIf(page.value.properties);
|
|
@@ -18,17 +14,18 @@ const getSortedFields = (fields) => {
|
|
|
18
14
|
</script>
|
|
19
15
|
|
|
20
16
|
<template>
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
<h3
|
|
24
|
-
{{ page.
|
|
17
|
+
<UCard variant="soft" :ui="{ root: 'divide-none', header: 'bg-elevated text-center', body: 'bg-muted' }">
|
|
18
|
+
<template #header>
|
|
19
|
+
<h3>
|
|
20
|
+
{{ getLocalizedContent(page.title, locale) }}
|
|
25
21
|
</h3>
|
|
26
|
-
<UBadge variant="subtle" size="sm" color="primary"
|
|
27
|
-
|
|
28
|
-
</UBadge>
|
|
29
|
-
</div>
|
|
22
|
+
<UBadge variant="subtle" size="sm" color="primary" :label="page.type"/>
|
|
23
|
+
</template>
|
|
30
24
|
|
|
31
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
v-for="(group, groupId) in page.properties"
|
|
27
|
+
:key="groupId"
|
|
28
|
+
>
|
|
32
29
|
<div class="flex items-center gap-3">
|
|
33
30
|
<span class="text-[10px] font-bold uppercase tracking-widest text-primary">
|
|
34
31
|
{{ group.label[locale] }}
|
|
@@ -40,76 +37,64 @@ const getSortedFields = (fields) => {
|
|
|
40
37
|
<template v-for="[fieldKey, schema] in getSortedFields(group.fields)" :key="fieldKey">
|
|
41
38
|
|
|
42
39
|
<UFormField
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
v-if="isFieldVisible(schema)"
|
|
41
|
+
:label="getLocalizedContent(schema.label, locale)"
|
|
42
|
+
:name="fieldKey"
|
|
46
43
|
>
|
|
47
44
|
<UInput
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
v-if="schema.type === 'text'"
|
|
46
|
+
v-model="schema.value[locale]"
|
|
47
|
+
variant="subtle"
|
|
48
|
+
placeholder="..."
|
|
52
49
|
/>
|
|
53
50
|
|
|
54
51
|
<UInput
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
v-else-if="schema.type === 'number'"
|
|
53
|
+
v-model.number="schema.value"
|
|
54
|
+
type="number"
|
|
55
|
+
variant="subtle"
|
|
59
56
|
/>
|
|
60
57
|
|
|
61
58
|
<USelect
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
v-else-if="schema.type === 'enum'"
|
|
60
|
+
v-model="schema.value"
|
|
61
|
+
:items="schema.options || []"
|
|
62
|
+
variant="subtle"
|
|
66
63
|
/>
|
|
67
64
|
|
|
68
65
|
<UInputMenu
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
v-else-if="schema.type === 'text-array'"
|
|
67
|
+
:model-value="schema.value.map((v) => v[locale])"
|
|
68
|
+
@update:model-value="(vals) => schema.value = vals.map((str) => ({ [locale]: str }))"
|
|
69
|
+
multiple
|
|
70
|
+
creatable
|
|
71
|
+
variant="subtle"
|
|
72
|
+
placeholder="Add item..."
|
|
75
73
|
/>
|
|
76
74
|
|
|
77
75
|
<UInput
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
v-else-if="schema.type === 'page'"
|
|
77
|
+
v-model="schema.value"
|
|
78
|
+
icon="lucide:link-2"
|
|
79
|
+
variant="subtle"
|
|
80
|
+
:placeholder="`Select ${schema.allowedPageTypes?.join('/')}`"
|
|
83
81
|
/>
|
|
84
82
|
</UFormField>
|
|
85
83
|
</template>
|
|
86
84
|
</div>
|
|
87
85
|
</div>
|
|
88
86
|
|
|
89
|
-
<USeparator />
|
|
87
|
+
<USeparator class="my-6" />
|
|
90
88
|
|
|
91
89
|
<UFormField label="Global Search Tags">
|
|
92
90
|
<UInputMenu
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
v-model="page.tags"
|
|
92
|
+
multiple
|
|
93
|
+
creatable
|
|
94
|
+
icon="lucide:tag"
|
|
95
|
+
variant="subtle"
|
|
96
|
+
placeholder="Add tags..."
|
|
99
97
|
/>
|
|
100
98
|
</UFormField>
|
|
101
|
-
|
|
102
|
-
<div class="mt-auto pt-6 text-[9px] font-mono text-muted-foreground/60 space-y-1">
|
|
103
|
-
<div class="flex justify-between">
|
|
104
|
-
<span>ID:</span>
|
|
105
|
-
<span>{{ page.id }}</span>
|
|
106
|
-
</div>
|
|
107
|
-
<ClientOnly>
|
|
108
|
-
<div class="flex justify-between">
|
|
109
|
-
<span>Last Updated:</span>
|
|
110
|
-
<span>{{ page.updated_at }}</span>
|
|
111
|
-
</div>
|
|
112
|
-
</ClientOnly>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
99
|
+
</UCard>
|
|
115
100
|
</template>
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { type Page } from '../../types/index.js';
|
|
2
|
-
type
|
|
2
|
+
type __VLS_ModelProps = {
|
|
3
3
|
modelValue: Page;
|
|
4
4
|
};
|
|
5
|
-
declare const __VLS_export: import("vue").DefineComponent<
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
"update:modelValue": (value: {
|
|
7
|
+
type: "Default";
|
|
8
|
+
properties: import("../../types/index.js").BasePageProperties;
|
|
9
|
+
} & import("../../types/index.js").BasePage) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
11
|
+
"onUpdate:modelValue"?: ((value: {
|
|
12
|
+
type: "Default";
|
|
13
|
+
properties: import("../../types/index.js").BasePageProperties;
|
|
14
|
+
} & import("../../types/index.js").BasePage) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
16
|
declare const _default: typeof __VLS_export;
|
|
7
17
|
export default _default;
|
|
@@ -1,99 +1,102 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {
|
|
2
|
+
import { getLocalizedContent } from "../../utils";
|
|
3
3
|
import { useI18n } from "vue-i18n";
|
|
4
4
|
import {
|
|
5
5
|
} from "../../types";
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
6
|
+
const page = defineModel({ type: null, ...{ required: true } });
|
|
7
|
+
const { t, locale } = useI18n();
|
|
8
|
+
const shouldRenderField = (schema) => {
|
|
9
|
+
const isVisible = !schema.visibleIf || schema.visibleIf(page.value.properties);
|
|
10
|
+
if (!isVisible) return false;
|
|
11
|
+
const val = schema.value;
|
|
12
|
+
if (schema.type === "text") {
|
|
13
|
+
return !!val?.[locale.value];
|
|
14
|
+
}
|
|
15
|
+
if (schema.type === "text-array") {
|
|
16
|
+
return Array.isArray(val) && val.length > 0;
|
|
17
|
+
}
|
|
18
|
+
return val !== void 0 && val !== null && val !== "";
|
|
19
|
+
};
|
|
20
|
+
const shouldRenderGroup = (group) => {
|
|
21
|
+
return Object.values(group.fields || {}).some((schema) => shouldRenderField(schema));
|
|
22
|
+
};
|
|
23
|
+
const getSortedFields = (fields) => {
|
|
24
|
+
return Object.entries(fields).sort(([, a], [, b]) => (a.order ?? 0) - (b.order ?? 0));
|
|
25
|
+
};
|
|
27
26
|
</script>
|
|
28
27
|
|
|
29
28
|
<template>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class="grid grid-cols-3 gap-x-3 items-baseline"
|
|
50
|
-
>
|
|
51
|
-
<dt class="text-[11px] font-semibold text-muted-foreground leading-tight">
|
|
52
|
-
{{ schema.label }}
|
|
53
|
-
</dt>
|
|
54
|
-
|
|
55
|
-
<dd class="text-xs col-span-2 text-foreground leading-snug">
|
|
56
|
-
<div v-if="schema.type === 'text-array'" class="flex flex-wrap gap-1">
|
|
57
|
-
<template v-for="(item, index) in properties[group.groupId].fields[fieldKey].value[locale]" :key="index">
|
|
58
|
-
<span class="font-medium">{{ item }}</span>
|
|
59
|
-
<span v-if="index < properties[group.groupId].fields[fieldKey].value[locale].length - 1" class="text-muted-foreground/50">, </span>
|
|
60
|
-
</template>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<span v-else-if="schema.type === 'page'" class="text-primary font-bold hover:underline cursor-pointer">
|
|
64
|
-
{{ properties[group.groupId].fields[fieldKey].value }}
|
|
65
|
-
</span>
|
|
66
|
-
|
|
67
|
-
<span v-else-if="schema.type === 'text'" class="font-medium">
|
|
68
|
-
{{ properties[group.groupId].fields[fieldKey].value[locale] }}
|
|
69
|
-
</span>
|
|
70
|
-
|
|
71
|
-
<span v-else class="font-medium">
|
|
72
|
-
{{ properties[group.groupId].fields[fieldKey].value }}
|
|
73
|
-
</span>
|
|
74
|
-
</dd>
|
|
29
|
+
<aside class="flex flex-col gap-xl">
|
|
30
|
+
<UCard variant="soft" :ui="{ root: 'divide-none', header: 'bg-accented text-center', body: 'p-0 sm:p-0 bg-muted' }">
|
|
31
|
+
<template #header>
|
|
32
|
+
<div class="flex flex-col gap-xs items-center">
|
|
33
|
+
<h3>
|
|
34
|
+
{{ getLocalizedContent(page.title, locale) }}
|
|
35
|
+
</h3>
|
|
36
|
+
<span class="text-xs">{{ page.type }}</span>
|
|
37
|
+
<div v-if="page.tags?.length" class="flex flex-row flex-wrap gap-xs">
|
|
38
|
+
<UBadge
|
|
39
|
+
v-for="tag in page.tags"
|
|
40
|
+
:key="tag[locale]"
|
|
41
|
+
variant="soft"
|
|
42
|
+
size="xs"
|
|
43
|
+
color="neutral"
|
|
44
|
+
>
|
|
45
|
+
{{ tag[locale] }}
|
|
46
|
+
</UBadge>
|
|
47
|
+
</div>
|
|
75
48
|
</div>
|
|
76
|
-
</
|
|
77
|
-
</div>
|
|
49
|
+
</template>
|
|
78
50
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
51
|
+
<template #default>
|
|
52
|
+
<template v-for="(group, groupId) in page.properties" :key="groupId">
|
|
53
|
+
<UCollapsible v-if="shouldRenderGroup(group)" :default-open="group.defaultOpen">
|
|
54
|
+
<template #default>
|
|
55
|
+
<UButton
|
|
56
|
+
:label="getLocalizedContent(group.label, locale)"
|
|
57
|
+
variant="soft"
|
|
58
|
+
trailing-icon="lucide:chevron-down"
|
|
59
|
+
:ui="{
|
|
60
|
+
trailingIcon: 'group-data-[state=open]:rotate-180 transition-transform duration-200'
|
|
61
|
+
}"
|
|
62
|
+
block
|
|
63
|
+
class="group rounded-none bg-elevated text-default"
|
|
64
|
+
/>
|
|
65
|
+
</template>
|
|
93
66
|
|
|
94
|
-
|
|
95
|
-
|
|
67
|
+
<template #content>
|
|
68
|
+
<dl class="p-sm flex flex-col gap-xs">
|
|
69
|
+
<template v-for="[fieldKey, schema] in getSortedFields(group.fields)" :key="fieldKey">
|
|
70
|
+
<div
|
|
71
|
+
v-if="shouldRenderField(schema)"
|
|
72
|
+
class="grid grid-cols-3 gap-xs items-baseline"
|
|
73
|
+
>
|
|
74
|
+
<dt class="text-xs font-semibold text-dimmed">
|
|
75
|
+
{{ getLocalizedContent(schema.label, locale) }}
|
|
76
|
+
</dt>
|
|
96
77
|
|
|
97
|
-
<
|
|
98
|
-
.
|
|
99
|
-
|
|
78
|
+
<dd class="text-xs col-span-2">
|
|
79
|
+
<ul v-if="schema.type === 'text-array'" class="flex flex-wrap">
|
|
80
|
+
<li v-for="(item, index) in schema.value" :key="index">
|
|
81
|
+
<span class="font-medium">
|
|
82
|
+
{{ getLocalizedContent(item, locale) }}
|
|
83
|
+
</span>
|
|
84
|
+
</li>
|
|
85
|
+
</ul>
|
|
86
|
+
<span v-else-if="schema.type === 'text'">
|
|
87
|
+
{{ getLocalizedContent(schema.value, locale) }}
|
|
88
|
+
</span>
|
|
89
|
+
<span v-else>
|
|
90
|
+
{{ schema.value }}
|
|
91
|
+
</span>
|
|
92
|
+
</dd>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
</dl>
|
|
96
|
+
</template>
|
|
97
|
+
</UCollapsible>
|
|
98
|
+
</template>
|
|
99
|
+
</template>
|
|
100
|
+
</UCard>
|
|
101
|
+
</aside>
|
|
102
|
+
</template>
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { type Page } from '../../types/index.js';
|
|
2
|
-
type
|
|
2
|
+
type __VLS_ModelProps = {
|
|
3
3
|
modelValue: Page;
|
|
4
4
|
};
|
|
5
|
-
declare const __VLS_export: import("vue").DefineComponent<
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
"update:modelValue": (value: {
|
|
7
|
+
type: "Default";
|
|
8
|
+
properties: import("../../types/index.js").BasePageProperties;
|
|
9
|
+
} & import("../../types/index.js").BasePage) => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
11
|
+
"onUpdate:modelValue"?: ((value: {
|
|
12
|
+
type: "Default";
|
|
13
|
+
properties: import("../../types/index.js").BasePageProperties;
|
|
14
|
+
} & import("../../types/index.js").BasePage) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
16
|
declare const _default: typeof __VLS_export;
|
|
7
17
|
export default _default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Page } from "../../types/index.js";
|
|
2
|
+
interface PageRendererProps {
|
|
3
|
+
}
|
|
4
|
+
type __VLS_Props = PageRendererProps;
|
|
5
|
+
type __VLS_ModelProps = {
|
|
6
|
+
modelValue: Page;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
"update:modelValue": (value: {
|
|
11
|
+
type: "Default";
|
|
12
|
+
properties: import("#imports").BasePageProperties;
|
|
13
|
+
} & import("#imports").BasePage) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
|
+
"onUpdate:modelValue"?: ((value: {
|
|
16
|
+
type: "Default";
|
|
17
|
+
properties: import("#imports").BasePageProperties;
|
|
18
|
+
} & import("#imports").BasePage) => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { getLocalizedContent } from "../../utils";
|
|
3
|
+
import { useI18n } from "#imports";
|
|
4
|
+
const page = defineModel({ type: null, ...{ required: true } });
|
|
5
|
+
const { t, locale } = useI18n();
|
|
6
|
+
const {} = defineProps({});
|
|
7
|
+
const emit = defineEmits([]);
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<UContainer class="flex flex-col">
|
|
12
|
+
<div class="grid grid-cols-1 lg:grid-cols-4 gap-xl p-xl bg-muted">
|
|
13
|
+
<RCPagePropertiesRenderer v-model="page" class="order-1 lg:order-2 lg:col-span-1" />
|
|
14
|
+
<div class="order-2 lg:order-1 lg:col-span-3 flex flex-col gap-xl">
|
|
15
|
+
<UPageHeader
|
|
16
|
+
:title="getLocalizedContent(page.title, 'en')"
|
|
17
|
+
:description="getLocalizedContent(page.description, 'en') ?? ''"
|
|
18
|
+
/>
|
|
19
|
+
<RCBlockViewRenderer :blocks="page.blocks" />
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="flex flex-col gap-xs text-xs p-xl">
|
|
23
|
+
<h6>Metadata</h6>
|
|
24
|
+
<span>Page ID: {{ page.id }}</span>
|
|
25
|
+
<span>Created At: <NuxtTime
|
|
26
|
+
:datetime="page.created_at ?? ''"
|
|
27
|
+
year="numeric"
|
|
28
|
+
month="numeric"
|
|
29
|
+
day="numeric"
|
|
30
|
+
hour="numeric"
|
|
31
|
+
minute="numeric"
|
|
32
|
+
second="numeric"
|
|
33
|
+
time-zone-name="short"
|
|
34
|
+
/></span>
|
|
35
|
+
<span>Posted At: <NuxtTime
|
|
36
|
+
:datetime="page.created_at ?? ''"
|
|
37
|
+
year="numeric"
|
|
38
|
+
month="numeric"
|
|
39
|
+
day="numeric"
|
|
40
|
+
hour="numeric"
|
|
41
|
+
minute="numeric"
|
|
42
|
+
second="numeric"
|
|
43
|
+
time-zone-name="short"
|
|
44
|
+
/></span>
|
|
45
|
+
<span>Updated At: <NuxtTime
|
|
46
|
+
:datetime="page.created_at ?? ''"
|
|
47
|
+
year="numeric"
|
|
48
|
+
month="numeric"
|
|
49
|
+
day="numeric"
|
|
50
|
+
hour="numeric"
|
|
51
|
+
minute="numeric"
|
|
52
|
+
second="numeric"
|
|
53
|
+
time-zone-name="short"
|
|
54
|
+
/></span>
|
|
55
|
+
</div>
|
|
56
|
+
</UContainer>
|
|
57
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Page } from "../../types/index.js";
|
|
2
|
+
interface PageRendererProps {
|
|
3
|
+
}
|
|
4
|
+
type __VLS_Props = PageRendererProps;
|
|
5
|
+
type __VLS_ModelProps = {
|
|
6
|
+
modelValue: Page;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
"update:modelValue": (value: {
|
|
11
|
+
type: "Default";
|
|
12
|
+
properties: import("#imports").BasePageProperties;
|
|
13
|
+
} & import("#imports").BasePage) => any;
|
|
14
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
|
+
"onUpdate:modelValue"?: ((value: {
|
|
16
|
+
type: "Default";
|
|
17
|
+
properties: import("#imports").BasePageProperties;
|
|
18
|
+
} & import("#imports").BasePage) => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
@@ -6,8 +6,8 @@ declare global {
|
|
|
6
6
|
}
|
|
7
7
|
export type PageType = keyof RegisterPageTypes;
|
|
8
8
|
export interface Property<T = any> {
|
|
9
|
-
value: T;
|
|
10
|
-
label: string
|
|
9
|
+
value: T extends never[] ? Localized[] : T;
|
|
10
|
+
label: Localized<string>;
|
|
11
11
|
type: "number" | "text" | "text-array" | "enum" | "page" | "page-array";
|
|
12
12
|
options?: string[];
|
|
13
13
|
allowedPageTypes?: PageType[];
|
|
@@ -19,6 +19,7 @@ export interface PropertyGroup {
|
|
|
19
19
|
label: Localized<string>;
|
|
20
20
|
order?: number;
|
|
21
21
|
fields: Record<string, Property>;
|
|
22
|
+
defaultOpen: boolean;
|
|
22
23
|
}
|
|
23
24
|
/**
|
|
24
25
|
* A PageTemplate is the single definition for a page's properties and initial blocks.
|
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import { type MaybeRefOrGetter } from 'vue';
|
|
2
|
-
import type
|
|
2
|
+
import { type Page, type Localized, type PageDefinition, type Property } from "../types/index.js";
|
|
3
3
|
export declare const getLocalizedContent: <T = string>(field: Localized<T> | undefined, currentLocale: MaybeRefOrGetter<string>) => T | string;
|
|
4
|
+
type WidenProperty<T> = T extends string ? string : T extends number ? number : T extends never[] ? Localized[] : T extends object ? {
|
|
5
|
+
[K in keyof T]: WidenProperty<T[K]>;
|
|
6
|
+
} : T;
|
|
4
7
|
/**
|
|
5
8
|
* Helper to define a page with full type safety and literal preservation.
|
|
6
9
|
* This is used by consuming apps to define their custom page types.
|
|
7
10
|
*/
|
|
8
|
-
export declare function definePageDefinition<T extends PageDefinition>(def: T):
|
|
11
|
+
export declare function definePageDefinition<T extends PageDefinition>(def: T): {
|
|
12
|
+
[K in keyof T]: K extends 'properties' ? {
|
|
13
|
+
[G in keyof T['properties']]: {
|
|
14
|
+
label: Localized<string>;
|
|
15
|
+
defaultOpen: boolean;
|
|
16
|
+
fields: {
|
|
17
|
+
[F in keyof T['properties'][G]['fields']]: Property<WidenProperty<T['properties'][G]['fields'][F]['value']>>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
} : T[K];
|
|
21
|
+
};
|
|
9
22
|
/**
|
|
10
23
|
* Ensures a page strictly adheres to its PageDefinition.
|
|
11
24
|
* - Adds missing properties and groups in the correct order.
|
|
@@ -14,3 +27,4 @@ export declare function definePageDefinition<T extends PageDefinition>(def: T):
|
|
|
14
27
|
* - Removes templated blocks no longer in the definition.
|
|
15
28
|
*/
|
|
16
29
|
export declare function syncPageWithDefinition(page: Page, definition?: PageDefinition): Page;
|
|
30
|
+
export {};
|
package/dist/types.d.mts
CHANGED