rimelight-components 2.1.1 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +69 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/app.config.mjs +4 -0
- package/dist/runtime/composables/index.mjs +4 -0
- package/dist/runtime/composables/useBlockEditor.mjs +150 -0
- package/dist/runtime/composables/useDateRange.mjs +55 -0
- package/dist/runtime/composables/usePageEditor.mjs +45 -0
- package/dist/runtime/composables/usePageRegistry.mjs +16 -0
- package/dist/runtime/db/index.mjs +10 -0
- package/dist/runtime/internal/blockMapper.mjs +29 -0
- package/dist/runtime/types/blocks.mjs +0 -0
- package/dist/runtime/types/index.mjs +3 -0
- package/dist/runtime/types/pages.mjs +0 -0
- package/dist/runtime/types/schemas.mjs +27 -0
- package/dist/runtime/utils/index.js +1 -1
- package/dist/runtime/utils/index.mjs +9 -0
- package/dist/runtime/utils/page.mjs +77 -0
- package/dist/runtime/utils/richTextHelpers.mjs +25 -0
- package/dist/types.d.mts +1 -1
- package/package.json +5 -1
- /package/dist/runtime/{utils/database.d.ts → db/index.d.ts} +0 -0
- /package/dist/runtime/{utils/database.js → db/index.js} +0 -0
package/dist/module.d.mts
CHANGED
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
export * from '../dist/runtime/types/index.mjs';
|
|
3
|
+
|
|
4
|
+
interface CalloutOptions {
|
|
5
|
+
icon: string;
|
|
6
|
+
title: string;
|
|
7
|
+
tooltip: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ModuleOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Prefix for components
|
|
13
|
+
* @defaultValue `RC`
|
|
14
|
+
*/
|
|
15
|
+
prefix?: string;
|
|
16
|
+
callouts: {
|
|
17
|
+
info: CalloutOptions;
|
|
18
|
+
success: CalloutOptions;
|
|
19
|
+
warning: CalloutOptions;
|
|
20
|
+
error: CalloutOptions;
|
|
21
|
+
commentary: CalloutOptions;
|
|
22
|
+
ideation: CalloutOptions;
|
|
23
|
+
source: CalloutOptions;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
prefix: string;
|
|
29
|
+
callouts: {
|
|
30
|
+
info: {
|
|
31
|
+
icon: string;
|
|
32
|
+
title: string;
|
|
33
|
+
tooltip: string;
|
|
34
|
+
};
|
|
35
|
+
success: {
|
|
36
|
+
icon: string;
|
|
37
|
+
title: string;
|
|
38
|
+
tooltip: string;
|
|
39
|
+
};
|
|
40
|
+
warning: {
|
|
41
|
+
icon: string;
|
|
42
|
+
title: string;
|
|
43
|
+
tooltip: string;
|
|
44
|
+
};
|
|
45
|
+
error: {
|
|
46
|
+
icon: string;
|
|
47
|
+
title: string;
|
|
48
|
+
tooltip: string;
|
|
49
|
+
};
|
|
50
|
+
commentary: {
|
|
51
|
+
icon: string;
|
|
52
|
+
title: string;
|
|
53
|
+
tooltip: string;
|
|
54
|
+
};
|
|
55
|
+
ideation: {
|
|
56
|
+
icon: string;
|
|
57
|
+
title: string;
|
|
58
|
+
tooltip: string;
|
|
59
|
+
};
|
|
60
|
+
source: {
|
|
61
|
+
icon: string;
|
|
62
|
+
title: string;
|
|
63
|
+
tooltip: string;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
}, true>;
|
|
67
|
+
|
|
68
|
+
export { _default as default };
|
|
69
|
+
export type { ModuleOptions };
|
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.1.
|
|
7
|
+
const version = "2.1.3";
|
|
8
8
|
const homepage = "https://rimelight.com/tools/rimelight-components";
|
|
9
9
|
|
|
10
10
|
const defaultOptions = {
|
|
@@ -194,10 +194,10 @@ const module$1 = defineNuxtModule().with({
|
|
|
194
194
|
prefix: options.prefix ?? void 0,
|
|
195
195
|
global: true
|
|
196
196
|
});
|
|
197
|
+
nuxt.options.alias["#rimelight"] = resolve("./runtime");
|
|
197
198
|
addImportsDir(resolve("./runtime/composables"));
|
|
198
199
|
addImportsDir(resolve("./runtime/types"));
|
|
199
200
|
addImportsDir(resolve("./runtime/utils"));
|
|
200
|
-
addServerImportsDir(resolve("./runtime/composables"));
|
|
201
201
|
addServerImportsDir(resolve("./runtime/types"));
|
|
202
202
|
addServerImportsDir(resolve("./runtime/utils"));
|
|
203
203
|
const blockRendererFiles = readdirSync(resolve("./runtime/components/blocks/renderer")).filter(
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { computed, ref, shallowRef } from "vue";
|
|
2
|
+
import { v7 as uuidv7 } from "uuid";
|
|
3
|
+
function findBlockLocation(blocks, id) {
|
|
4
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
5
|
+
const block = blocks[i];
|
|
6
|
+
if (!block) continue;
|
|
7
|
+
if (block.id === id) {
|
|
8
|
+
return { parentArray: blocks, index: i };
|
|
9
|
+
}
|
|
10
|
+
if ("children" in block.props && Array.isArray(block.props.children)) {
|
|
11
|
+
const result = findBlockLocation(block.props.children, id);
|
|
12
|
+
if (result) return result;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function regenerateIds(block) {
|
|
18
|
+
block.id = uuidv7();
|
|
19
|
+
if ("children" in block.props && Array.isArray(block.props.children)) {
|
|
20
|
+
block.props.children.forEach((child) => regenerateIds(child));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function useBlockEditor(initialBlocks, { maxHistorySize = 100, onMutation } = {}) {
|
|
24
|
+
const history = shallowRef([]);
|
|
25
|
+
const future = shallowRef([]);
|
|
26
|
+
const committedBlocks = ref(JSON.parse(JSON.stringify(initialBlocks.value)));
|
|
27
|
+
const captureSnapshot = () => {
|
|
28
|
+
const snapshot = JSON.parse(JSON.stringify(initialBlocks.value));
|
|
29
|
+
future.value = [];
|
|
30
|
+
const newHistory = [...history.value, snapshot];
|
|
31
|
+
if (newHistory.length > maxHistorySize) {
|
|
32
|
+
newHistory.shift();
|
|
33
|
+
}
|
|
34
|
+
history.value = newHistory;
|
|
35
|
+
};
|
|
36
|
+
const executeMutation = (mutationFn) => {
|
|
37
|
+
if (onMutation) {
|
|
38
|
+
onMutation();
|
|
39
|
+
} else {
|
|
40
|
+
captureSnapshot();
|
|
41
|
+
}
|
|
42
|
+
mutationFn();
|
|
43
|
+
};
|
|
44
|
+
const undo = () => {
|
|
45
|
+
if (history.value.length === 0) return;
|
|
46
|
+
const currentState = JSON.parse(JSON.stringify(initialBlocks.value));
|
|
47
|
+
future.value = [currentState, ...future.value];
|
|
48
|
+
const previousState = history.value[history.value.length - 1];
|
|
49
|
+
if (previousState) {
|
|
50
|
+
initialBlocks.value.splice(0, initialBlocks.value.length, ...previousState);
|
|
51
|
+
const newHistory = [...history.value];
|
|
52
|
+
newHistory.pop();
|
|
53
|
+
history.value = newHistory;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const redo = () => {
|
|
57
|
+
if (future.value.length === 0) return;
|
|
58
|
+
const currentState = JSON.parse(JSON.stringify(initialBlocks.value));
|
|
59
|
+
let newHistory = [...history.value, currentState];
|
|
60
|
+
if (newHistory.length > maxHistorySize) {
|
|
61
|
+
newHistory.shift();
|
|
62
|
+
}
|
|
63
|
+
history.value = newHistory;
|
|
64
|
+
const nextState = future.value[0];
|
|
65
|
+
if (nextState) {
|
|
66
|
+
initialBlocks.value.splice(0, initialBlocks.value.length, ...nextState);
|
|
67
|
+
const newFuture = [...future.value];
|
|
68
|
+
newFuture.shift();
|
|
69
|
+
future.value = newFuture;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const canUndo = computed(() => history.value.length > 0);
|
|
73
|
+
const canRedo = computed(() => future.value.length > 0);
|
|
74
|
+
const updateBlockProps = (id, newProps) => {
|
|
75
|
+
executeMutation(() => {
|
|
76
|
+
const loc = findBlockLocation(initialBlocks.value, id);
|
|
77
|
+
if (!loc) return;
|
|
78
|
+
const oldBlock = loc.parentArray[loc.index];
|
|
79
|
+
if (!oldBlock) return;
|
|
80
|
+
const newPropsObject = {
|
|
81
|
+
...oldBlock.props,
|
|
82
|
+
...newProps
|
|
83
|
+
};
|
|
84
|
+
const newBlock = {
|
|
85
|
+
id: oldBlock.id,
|
|
86
|
+
// Explicitly carry over the required BaseBlock properties
|
|
87
|
+
type: oldBlock.type,
|
|
88
|
+
// Explicitly carry over the required BaseBlock properties
|
|
89
|
+
props: newPropsObject
|
|
90
|
+
};
|
|
91
|
+
loc.parentArray.splice(loc.index, 1, newBlock);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
const removeBlock = (id) => {
|
|
95
|
+
executeMutation(() => {
|
|
96
|
+
const loc = findBlockLocation(initialBlocks.value, id);
|
|
97
|
+
if (!loc) return;
|
|
98
|
+
loc.parentArray.splice(loc.index, 1);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const moveBlock = (id, direction) => {
|
|
102
|
+
executeMutation(() => {
|
|
103
|
+
const loc = findBlockLocation(initialBlocks.value, id);
|
|
104
|
+
if (!loc) return;
|
|
105
|
+
const { parentArray, index } = loc;
|
|
106
|
+
const newIndex = index + direction;
|
|
107
|
+
if (newIndex >= 0 && newIndex < parentArray.length) {
|
|
108
|
+
const movedBlock = parentArray.splice(index, 1)[0];
|
|
109
|
+
if (movedBlock) {
|
|
110
|
+
parentArray.splice(newIndex, 0, movedBlock);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
const duplicateBlock = (id) => {
|
|
116
|
+
executeMutation(() => {
|
|
117
|
+
const loc = findBlockLocation(initialBlocks.value, id);
|
|
118
|
+
if (!loc) return;
|
|
119
|
+
const original = loc.parentArray[loc.index];
|
|
120
|
+
const clone = JSON.parse(JSON.stringify(original));
|
|
121
|
+
regenerateIds(clone);
|
|
122
|
+
loc.parentArray.splice(loc.index + 1, 0, clone);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const insertBlock = (newBlockType, targetId = null, position = "after") => {
|
|
126
|
+
executeMutation(() => {
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
const commitChanges = () => {
|
|
130
|
+
const committedSnapshot = JSON.parse(JSON.stringify(initialBlocks.value));
|
|
131
|
+
committedBlocks.value = committedSnapshot;
|
|
132
|
+
return committedSnapshot;
|
|
133
|
+
};
|
|
134
|
+
return {
|
|
135
|
+
// Mutations
|
|
136
|
+
updateBlockProps,
|
|
137
|
+
removeBlock,
|
|
138
|
+
moveBlock,
|
|
139
|
+
duplicateBlock,
|
|
140
|
+
insertBlock,
|
|
141
|
+
// History
|
|
142
|
+
undo,
|
|
143
|
+
redo,
|
|
144
|
+
canUndo,
|
|
145
|
+
canRedo,
|
|
146
|
+
// State
|
|
147
|
+
committedBlocks,
|
|
148
|
+
commitChanges
|
|
149
|
+
};
|
|
150
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useState, readonly } from "#imports";
|
|
2
|
+
import { subDays, subMonths, subYears, startOfDay, endOfDay } from "date-fns";
|
|
3
|
+
export function useDateRange() {
|
|
4
|
+
const dateRange = useState(`feedback-date-range`, () => ({
|
|
5
|
+
start: subDays(/* @__PURE__ */ new Date(), 30),
|
|
6
|
+
end: /* @__PURE__ */ new Date()
|
|
7
|
+
}));
|
|
8
|
+
const setDateRange = (range) => {
|
|
9
|
+
dateRange.value = {
|
|
10
|
+
start: startOfDay(range.start),
|
|
11
|
+
end: endOfDay(range.end)
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const setPresetRange = (preset) => {
|
|
15
|
+
const end = /* @__PURE__ */ new Date();
|
|
16
|
+
let start;
|
|
17
|
+
switch (preset) {
|
|
18
|
+
case `week`:
|
|
19
|
+
start = subDays(end, 7);
|
|
20
|
+
break;
|
|
21
|
+
case `month`:
|
|
22
|
+
start = subDays(end, 30);
|
|
23
|
+
break;
|
|
24
|
+
case `3months`:
|
|
25
|
+
start = subMonths(end, 3);
|
|
26
|
+
break;
|
|
27
|
+
case `6months`:
|
|
28
|
+
start = subMonths(end, 6);
|
|
29
|
+
break;
|
|
30
|
+
case `year`:
|
|
31
|
+
start = subYears(end, 1);
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
start = subDays(end, 30);
|
|
35
|
+
}
|
|
36
|
+
setDateRange({
|
|
37
|
+
start,
|
|
38
|
+
end
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const isDateInRange = (date) => {
|
|
42
|
+
const checkDate = typeof date === `string` ? new Date(date) : date;
|
|
43
|
+
return checkDate >= dateRange.value.start && checkDate <= dateRange.value.end;
|
|
44
|
+
};
|
|
45
|
+
const filterFeedbackByDateRange = (feedback) => {
|
|
46
|
+
return feedback.filter((item) => isDateInRange(item.createdAt));
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
dateRange: readonly(dateRange),
|
|
50
|
+
setDateRange,
|
|
51
|
+
setPresetRange,
|
|
52
|
+
isDateInRange,
|
|
53
|
+
filterFeedbackByDateRange
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { computed, shallowRef, watch } from "vue";
|
|
2
|
+
export function usePageEditor(page, maxHistorySize = 100) {
|
|
3
|
+
const history = shallowRef([]);
|
|
4
|
+
const future = shallowRef([]);
|
|
5
|
+
const captureSnapshot = () => {
|
|
6
|
+
const snapshot = JSON.stringify(page.value);
|
|
7
|
+
if (history.value.length > 0 && history.value[history.value.length - 1] === snapshot) return;
|
|
8
|
+
future.value = [];
|
|
9
|
+
const newHistory = [...history.value, snapshot];
|
|
10
|
+
if (newHistory.length > maxHistorySize) newHistory.shift();
|
|
11
|
+
history.value = newHistory;
|
|
12
|
+
};
|
|
13
|
+
const undo = () => {
|
|
14
|
+
if (history.value.length === 0) return;
|
|
15
|
+
future.value = [JSON.stringify(page.value), ...future.value];
|
|
16
|
+
const previous = JSON.parse(history.value.pop());
|
|
17
|
+
page.value = previous;
|
|
18
|
+
};
|
|
19
|
+
const redo = () => {
|
|
20
|
+
if (future.value.length === 0) return;
|
|
21
|
+
history.value = [...history.value, JSON.stringify(page.value)];
|
|
22
|
+
const next = JSON.parse(future.value.shift());
|
|
23
|
+
page.value = next;
|
|
24
|
+
};
|
|
25
|
+
const canUndo = computed(() => history.value.length > 0);
|
|
26
|
+
const canRedo = computed(() => future.value.length > 0);
|
|
27
|
+
const save = () => {
|
|
28
|
+
return JSON.parse(JSON.stringify(page.value));
|
|
29
|
+
};
|
|
30
|
+
watch(
|
|
31
|
+
() => page.value.properties,
|
|
32
|
+
() => {
|
|
33
|
+
captureSnapshot();
|
|
34
|
+
},
|
|
35
|
+
{ deep: true }
|
|
36
|
+
);
|
|
37
|
+
return {
|
|
38
|
+
undo,
|
|
39
|
+
redo,
|
|
40
|
+
canUndo,
|
|
41
|
+
canRedo,
|
|
42
|
+
save,
|
|
43
|
+
captureSnapshot
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { reactive, readonly } from "vue";
|
|
2
|
+
const PAGE_DEFINITIONS = reactive({});
|
|
3
|
+
export const usePageRegistry = () => {
|
|
4
|
+
const registerDefinitions = (definitions) => {
|
|
5
|
+
Object.assign(PAGE_DEFINITIONS, definitions);
|
|
6
|
+
};
|
|
7
|
+
const getTypeLabelKey = (type) => {
|
|
8
|
+
const definition = PAGE_DEFINITIONS[type];
|
|
9
|
+
return definition?.typeLabelKey ?? `page.type.${type.toLowerCase()}`;
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
registerDefinitions,
|
|
13
|
+
getTypeLabelKey,
|
|
14
|
+
definitions: readonly(PAGE_DEFINITIONS)
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { uuid, timestamp } from "drizzle-orm/pg-core";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
export const id = uuid("id").default(sql`uuidv7()`).notNull();
|
|
4
|
+
export const timestamps = {
|
|
5
|
+
updated_at: timestamp("updated_at", {
|
|
6
|
+
withTimezone: true
|
|
7
|
+
}).$onUpdate(() => /* @__PURE__ */ new Date()),
|
|
8
|
+
created_at: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
9
|
+
deleted_at: timestamp("deleted_at", { withTimezone: true })
|
|
10
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineAsyncComponent } from "vue";
|
|
2
|
+
import { BLOCK_RENDERER_COMPONENT_MAP } from "#build/rimelight-block-renderer-map";
|
|
3
|
+
import { BLOCK_EDITOR_COMPONENT_MAP } from "#build/rimelight-block-editor-map";
|
|
4
|
+
export const getBlockRendererComponent = (type) => {
|
|
5
|
+
const componentImporter = BLOCK_RENDERER_COMPONENT_MAP[type];
|
|
6
|
+
if (!componentImporter) {
|
|
7
|
+
console.warn(
|
|
8
|
+
`[BlockMapper] Block component not found for type: ${type}. Please check block name.`
|
|
9
|
+
);
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
return defineAsyncComponent(async () => {
|
|
13
|
+
const module = await componentImporter();
|
|
14
|
+
return module.default;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
export const getBlockEditorComponent = (type) => {
|
|
18
|
+
const componentImporter = BLOCK_EDITOR_COMPONENT_MAP[type];
|
|
19
|
+
if (!componentImporter) {
|
|
20
|
+
console.warn(
|
|
21
|
+
`[EditorBlockMapper] Editor block component not found for type: ${type}. Please check block name.`
|
|
22
|
+
);
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
return defineAsyncComponent(async () => {
|
|
26
|
+
const module = await componentImporter();
|
|
27
|
+
return module.default;
|
|
28
|
+
});
|
|
29
|
+
};
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const LocalizedSchema = (schema) => z.record(z.string(), schema);
|
|
3
|
+
export const linkVariantEnum = z.enum(["solid", "outline", "subtle", "soft", "ghost", "link"]);
|
|
4
|
+
export const linkColorEnum = z.enum([
|
|
5
|
+
"primary",
|
|
6
|
+
"secondary",
|
|
7
|
+
"neutral",
|
|
8
|
+
"error",
|
|
9
|
+
"warning",
|
|
10
|
+
"success",
|
|
11
|
+
"info"
|
|
12
|
+
]);
|
|
13
|
+
export const ImageSchema = z.object({
|
|
14
|
+
src: z.string().min(1, "Image source must be provided."),
|
|
15
|
+
alt: z.string().min(1, "Image alt text must be provided."),
|
|
16
|
+
width: z.number().int().positive().optional(),
|
|
17
|
+
height: z.number().int().positive().optional(),
|
|
18
|
+
name: LocalizedSchema(z.string()).optional()
|
|
19
|
+
});
|
|
20
|
+
export const LinkSchema = z.object({
|
|
21
|
+
label: z.string().min(1, "Link label must be provided."),
|
|
22
|
+
to: z.url("Link destination must be a valid URL.").min(1, "Link destination must be provided."),
|
|
23
|
+
icon: z.string().optional(),
|
|
24
|
+
trailing: z.boolean().optional(),
|
|
25
|
+
color: linkColorEnum.optional(),
|
|
26
|
+
variant: linkVariantEnum.optional()
|
|
27
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./richTextHelpers.mjs";
|
|
2
|
+
export * from "./page.mjs";
|
|
3
|
+
export * from "./database";
|
|
4
|
+
export function slugify(text) {
|
|
5
|
+
if (!text) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
return text.toString().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
9
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { toValue } from "vue";
|
|
2
|
+
export const getLocalizedContent = (field, currentLocale) => {
|
|
3
|
+
if (!field || typeof field !== "object") return "";
|
|
4
|
+
const locale = toValue(currentLocale);
|
|
5
|
+
return field[locale] ?? field["en"] ?? "";
|
|
6
|
+
};
|
|
7
|
+
export function definePageDefinition(def) {
|
|
8
|
+
return def;
|
|
9
|
+
}
|
|
10
|
+
export function syncPageWithDefinition(page, definition) {
|
|
11
|
+
if (!definition) return page;
|
|
12
|
+
let hasChanged = false;
|
|
13
|
+
const updatedProperties = {};
|
|
14
|
+
const definitionGroups = definition.properties;
|
|
15
|
+
for (const [groupId, definitionGroup] of Object.entries(definitionGroups)) {
|
|
16
|
+
const existingGroup = page.properties[groupId];
|
|
17
|
+
const updatedGroupFields = {};
|
|
18
|
+
for (const [fieldId, definitionField] of Object.entries(definitionGroup.fields)) {
|
|
19
|
+
if (existingGroup?.fields[fieldId]) {
|
|
20
|
+
updatedGroupFields[fieldId] = {
|
|
21
|
+
...definitionField,
|
|
22
|
+
value: existingGroup.fields[fieldId].value
|
|
23
|
+
};
|
|
24
|
+
} else {
|
|
25
|
+
updatedGroupFields[fieldId] = { ...definitionField };
|
|
26
|
+
hasChanged = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
updatedProperties[groupId] = {
|
|
30
|
+
...definitionGroup,
|
|
31
|
+
fields: updatedGroupFields
|
|
32
|
+
};
|
|
33
|
+
if (!existingGroup) {
|
|
34
|
+
hasChanged = true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (Object.keys(page.properties).length !== Object.keys(updatedProperties).length) {
|
|
38
|
+
hasChanged = true;
|
|
39
|
+
} else {
|
|
40
|
+
for (const groupId in updatedProperties) {
|
|
41
|
+
const pageGroup = page.properties[groupId];
|
|
42
|
+
if (Object.keys(pageGroup?.fields || {}).length !== Object.keys(updatedProperties[groupId].fields).length) {
|
|
43
|
+
hasChanged = true;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
page.properties = updatedProperties;
|
|
49
|
+
if (definition.initialBlocks) {
|
|
50
|
+
const idealBlocks = definition.initialBlocks();
|
|
51
|
+
const currentBlocks = [...page.blocks];
|
|
52
|
+
const idealBlocksMap = new Map(idealBlocks.map((b) => [b.id, b]));
|
|
53
|
+
const filteredCurrent = currentBlocks.filter((b) => {
|
|
54
|
+
if (!b.isTemplated) return true;
|
|
55
|
+
return idealBlocksMap.has(b.id);
|
|
56
|
+
});
|
|
57
|
+
if (filteredCurrent.length !== currentBlocks.length) {
|
|
58
|
+
hasChanged = true;
|
|
59
|
+
}
|
|
60
|
+
let lastExistingIdealIndex = -1;
|
|
61
|
+
for (const idealBlock of idealBlocks) {
|
|
62
|
+
const existingIndex = filteredCurrent.findIndex((b) => b.id === idealBlock.id);
|
|
63
|
+
if (existingIndex !== -1) {
|
|
64
|
+
lastExistingIdealIndex = existingIndex;
|
|
65
|
+
} else {
|
|
66
|
+
filteredCurrent.splice(lastExistingIdealIndex + 1, 0, { ...idealBlock });
|
|
67
|
+
lastExistingIdealIndex++;
|
|
68
|
+
hasChanged = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
page.blocks = filteredCurrent;
|
|
72
|
+
}
|
|
73
|
+
if (hasChanged) {
|
|
74
|
+
page.updated_at = /* @__PURE__ */ new Date();
|
|
75
|
+
}
|
|
76
|
+
return page;
|
|
77
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { v7 as uuidv7 } from "uuid";
|
|
2
|
+
export function richTextToHtml(content) {
|
|
3
|
+
return content.map((item) => {
|
|
4
|
+
if (item.type === "text" || item.type === "link") {
|
|
5
|
+
return item.props.content;
|
|
6
|
+
}
|
|
7
|
+
if (item.type === "mention") {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
return "";
|
|
11
|
+
}).join("");
|
|
12
|
+
}
|
|
13
|
+
export function parseHtmlToRichText(html) {
|
|
14
|
+
if (html.trim().length === 0) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const newTextNode = {
|
|
18
|
+
id: uuidv7(),
|
|
19
|
+
type: "text",
|
|
20
|
+
props: {
|
|
21
|
+
content: html.trim()
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return [newTextNode];
|
|
25
|
+
}
|
package/dist/types.d.mts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rimelight-components",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "A component library by Rimelight Entertainment.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"./utils/*": {
|
|
33
33
|
"types": "./dist/runtime/utils/*.d.mts",
|
|
34
34
|
"import": "./dist/runtime/utils/*.js"
|
|
35
|
+
},
|
|
36
|
+
"./db": {
|
|
37
|
+
"types": "./dist/runtime/utils/db.d.ts",
|
|
38
|
+
"import": "./dist/runtime/utils/db.js"
|
|
35
39
|
}
|
|
36
40
|
},
|
|
37
41
|
"typesVersions": {
|
|
File without changes
|
|
File without changes
|