@rimelight/ui 0.0.43 → 0.0.44
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/LICENSE +21 -0
- package/README.md +14 -12
- package/package.json +11 -14
- package/src/components/avatar/RLAAvatar.astro +4 -12
- package/src/components/badge/RLABadge.astro +2 -1
- package/src/components/badge/badge.theme.ts +0 -4
- package/src/components/banner/RLABanner.astro +1 -1
- package/src/components/banner/banner.theme.ts +1 -1
- package/src/components/breadcrumb/RLABreadcrumb.astro +2 -2
- package/src/components/button/RLAButton.astro +4 -1
- package/src/components/button/button.theme.ts +1 -5
- package/src/components/callout/RLACallout.astro +7 -5
- package/src/components/callout/callout.theme.ts +1 -5
- package/src/components/card/card.theme.ts +3 -3
- package/src/components/carousel/RLACarousel.astro +2 -2
- package/src/components/carousel/carousel.theme.ts +2 -2
- package/src/components/chart/RLAChart.astro +1 -1
- package/src/components/checkbox/RLACheckbox.astro +2 -1
- package/src/components/checkbox/checkbox.theme.ts +0 -4
- package/src/components/chip/RLAChip.astro +2 -1
- package/src/components/chip/chip.theme.ts +0 -4
- package/src/components/collapsible/RLACollapsible.astro +1 -1
- package/src/components/color-area/RLAColorArea.astro +1 -0
- package/src/components/color-area/color-area.theme.ts +1 -5
- package/src/components/color-field/RLAColorField.astro +1 -0
- package/src/components/color-field/color-field.theme.ts +1 -5
- package/src/components/color-slider/RLAColorSlider.astro +1 -0
- package/src/components/color-slider/color-slider.theme.ts +1 -5
- package/src/components/dashboard-group/RLADashboardGroup.astro +5 -7
- package/src/components/dashboard-group/dashboard-group.theme.ts +1 -1
- package/src/components/dashboard-group/dashboard-group.ts +1 -1
- package/src/components/dashboard-navbar/RLADashboardNavbar.astro +4 -4
- package/src/components/dashboard-navbar/dashboard-navbar.theme.ts +3 -3
- package/src/components/dashboard-navbar/dashboard-navbar.ts +1 -1
- package/src/components/dashboard-panel/RLADashboardPanel.astro +9 -8
- package/src/components/dashboard-panel/dashboard-panel.theme.ts +1 -1
- package/src/components/dashboard-sidebar/RLADashboardSidebar.astro +7 -4
- package/src/components/dashboard-sidebar/dashboard-sidebar.theme.ts +6 -5
- package/src/components/dashboard-sidebar-collapse/RLADashboardSidebarCollapse.astro +1 -0
- package/src/components/drawer/RLADrawer.astro +1 -1
- package/src/components/dropdown-menu/dropdown-menu.theme.ts +2 -2
- package/src/components/footer/RLAFooter.astro +2 -0
- package/src/components/footer/footer.theme.ts +0 -8
- package/src/components/gamepad/RLAGamepad.astro +1 -1
- package/src/components/head/UIHead.astro +1 -2
- package/src/components/header/header.theme.ts +1 -1
- package/src/components/icon/RLAIcon.astro +2 -5
- package/src/components/icon/RLSIcon.tsx +2 -2
- package/src/components/icon/RLVIcon.vue +18 -6
- package/src/components/icon/icon.theme.ts +1 -1
- package/src/components/image/image.theme.ts +1 -1
- package/src/components/input/RLAInput.astro +2 -1
- package/src/components/input/input.theme.ts +0 -4
- package/src/components/input-menu/RLAInputMenu.astro +2 -2
- package/src/components/input-menu/input-menu.theme.ts +1 -1
- package/src/components/input-rating/input-rating.theme.ts +2 -2
- package/src/components/kbd/RLAKbd.astro +2 -1
- package/src/components/kbd/kbd.theme.ts +0 -4
- package/src/components/keyboard/RLAKeyboard.astro +1 -1
- package/src/components/link/RLALink.astro +1 -0
- package/src/components/link/link.theme.ts +0 -4
- package/src/components/link-group/RLALinkGroup.astro +1 -1
- package/src/components/link-group/link-group.theme.ts +1 -10
- package/src/components/locale-selector/RLALocaleSelector.astro +4 -36
- package/src/components/locale-selector/locale-selector.theme.ts +3 -11
- package/src/components/logo/RLALogo.astro +1 -2
- package/src/components/modal/RLAModal.astro +1 -1
- package/src/components/modal/RLSModal.tsx +2 -2
- package/src/components/navigation-menu/RLANavigationMenu.astro +17 -21
- package/src/components/navigation-menu/navigation-menu.theme.ts +3 -7
- package/src/components/pagination/RLAPagination.astro +2 -2
- package/src/components/pagination/pagination.theme.ts +1 -1
- package/src/components/popover/RLAPopover.astro +39 -0
- package/src/components/progress/RLAProgress.astro +2 -0
- package/src/components/progress/progress.theme.ts +0 -4
- package/src/components/scroll-area/scroll-area.theme.ts +1 -1
- package/src/components/scroll-to-top/RLAScrollToTop.astro +6 -5
- package/src/components/scroll-to-top/RLVScrollToTop.vue +7 -7
- package/src/components/scroll-to-top/scroll-to-top.theme.ts +3 -7
- package/src/components/search/RLASearch.astro +3 -3
- package/src/components/select/RLASelect.astro +96 -528
- package/src/components/select/RLSSelect.tsx +68 -14
- package/src/components/select/RLVSelect.vue +57 -0
- package/src/components/select/select.theme.ts +11 -96
- package/src/components/shortcuts/RLAShortcuts.astro +9 -9
- package/src/components/sidebar/RLASidebar.astro +3 -3
- package/src/components/slideover/RLASlideover.astro +1 -1
- package/src/components/slider/RLASlider.astro +2 -1
- package/src/components/slider/slider.theme.ts +1 -5
- package/src/components/spinner/RLASpinner.astro +2 -1
- package/src/components/spinner/spinner.theme.ts +1 -5
- package/src/components/splitter/splitter.theme.ts +1 -1
- package/src/components/stepper/RLAStepper.astro +8 -8
- package/src/components/stepper/stepper.theme.ts +6 -7
- package/src/components/steps/RLASteps.astro +3 -3
- package/src/components/switch/RLASwitch.astro +2 -1
- package/src/components/switch/switch.theme.ts +0 -4
- package/src/components/table/table.theme.ts +1 -1
- package/src/components/table-of-contents/RLATableOfContents.astro +5 -5
- package/src/components/theme-selector/RLAThemeSelector.astro +16 -14
- package/src/components/theme-selector/theme-selector.theme.ts +2 -2
- package/src/components/toast/RLAToast.astro +6 -6
- package/src/components/toast/store.ts +1 -1
- package/src/components/tooltip/tooltip.theme.ts +1 -1
- package/src/icons.raw.ts +67 -0
- package/src/icons.ts +31 -64
- package/src/index.ts +19 -18
- package/src/preset.ts +110 -108
- package/src/resolver.ts +127 -15
- package/src/shortcuts.ts +103 -84
- package/src/stores.ts +22 -0
- package/src/types.ts +27 -9
- package/src/virtual.d.ts +4 -0
- package/src/components/editor/PageEditor.vue +0 -459
- package/src/components/editor/PageMention.vue +0 -87
- package/src/components/editor/PagePropertiesEditor.vue +0 -358
- package/src/components/editor/PagePropertiesRenderer.vue +0 -285
- package/src/components/editor/PageRenderer.vue +0 -155
- package/src/components/editor/PageSurround.vue +0 -130
- package/src/components/editor/PageVersionSelector.vue +0 -371
- package/src/components/editor/blocks/AddBlockModal.vue +0 -196
- package/src/components/editor/blocks/Block.vue +0 -142
- package/src/components/editor/blocks/BlockEditRenderer.vue +0 -26
- package/src/components/editor/blocks/BlockEditor.vue +0 -141
- package/src/components/editor/blocks/BlockViewRenderer.vue +0 -71
- package/src/components/editor/blocks/TextRenderer.vue +0 -31
- package/src/components/editor/blocks/editor/CalloutBlockEditor.vue +0 -53
- package/src/components/editor/blocks/editor/ImageBlockEditor.vue +0 -55
- package/src/components/editor/blocks/editor/ParagraphBlockEditor.vue +0 -31
- package/src/components/editor/blocks/editor/SectionBlockEditor.vue +0 -65
- package/src/components/editor/blocks/nodes/LinkNode.vue +0 -28
- package/src/components/editor/blocks/nodes/TextNode.vue +0 -22
- package/src/components/editor/blocks/renderer/CalloutBlockRenderer.vue +0 -65
- package/src/components/editor/blocks/renderer/ImageBlockRenderer.vue +0 -20
- package/src/components/editor/blocks/renderer/ParagraphBlockRenderer.vue +0 -21
- package/src/components/editor/blocks/renderer/SectionBlockRenderer.vue +0 -55
- package/src/components/editor/composables/injectionKeys.ts +0 -3
- package/src/components/editor/composables/useBlockEditor.ts +0 -261
- package/src/components/editor/composables/usePageEditor.ts +0 -97
- package/src/components/editor/modals/CreatePageModal.vue +0 -160
- package/src/components/editor/modals/DeletePageModal.vue +0 -116
- package/src/components/editor/modals/PageTreeModal.vue +0 -275
- package/src/components/editor/types/blocks.ts +0 -100
- package/src/components/editor/types/pages.ts +0 -89
- package/src/components/editor/types/schemas.ts +0 -36
- package/src/components/editor/utils/blocks.ts +0 -42
- package/src/components/editor/utils/editorHelpers.ts +0 -24
- package/src/components/editor/utils/page.ts +0 -219
- package/src/components/editor/utils/richTextHelpers.ts +0 -35
- package/src/components/editor/views/PageEditView.vue +0 -195
- package/src/components/editor/views/PageLiveView.vue +0 -90
- package/src/components/editor/views/PageReviewView.vue +0 -308
- package/src/components/icon/resolver.ts +0 -23
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
|
|
2
|
-
|
|
3
|
-
export type BlockType = "SectionBlock" | "ParagraphBlock" | "CalloutBlock" | "ImageBlock"
|
|
4
|
-
|
|
5
|
-
export interface BaseBlock {
|
|
6
|
-
id: string
|
|
7
|
-
type: BlockType
|
|
8
|
-
isTemplated?: boolean
|
|
9
|
-
props: Record<string, any>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface SectionBlockProps {
|
|
13
|
-
level: HeadingLevel
|
|
14
|
-
title: string
|
|
15
|
-
description?: string
|
|
16
|
-
children: Block[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface ParagraphBlockProps {
|
|
20
|
-
text: RichTextContent
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type CalloutVariant =
|
|
24
|
-
| "info"
|
|
25
|
-
| "success"
|
|
26
|
-
| "warning"
|
|
27
|
-
| "error"
|
|
28
|
-
| "commentary"
|
|
29
|
-
| "ideation"
|
|
30
|
-
| "source"
|
|
31
|
-
|
|
32
|
-
export interface CalloutBlockProps {
|
|
33
|
-
variant: CalloutVariant
|
|
34
|
-
children: Block[]
|
|
35
|
-
to?: string
|
|
36
|
-
target?: string
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface ImageBlockProps {
|
|
40
|
-
src: string
|
|
41
|
-
alt: string
|
|
42
|
-
caption?: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface SectionBlock extends BaseBlock {
|
|
46
|
-
type: "SectionBlock"
|
|
47
|
-
props: SectionBlockProps
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface ParagraphContentBlock extends BaseBlock {
|
|
51
|
-
type: "ParagraphBlock"
|
|
52
|
-
props: ParagraphBlockProps
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface CalloutContentBlock extends BaseBlock {
|
|
56
|
-
type: "CalloutBlock"
|
|
57
|
-
props: CalloutBlockProps
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface ImageContentBlock extends BaseBlock {
|
|
61
|
-
type: "ImageBlock"
|
|
62
|
-
props: ImageBlockProps
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type Block = SectionBlock | ParagraphContentBlock | CalloutContentBlock | ImageContentBlock
|
|
66
|
-
|
|
67
|
-
export type InlineContentType = "text" | "link" | "mention"
|
|
68
|
-
|
|
69
|
-
export interface BaseInlineContent {
|
|
70
|
-
type: InlineContentType
|
|
71
|
-
id: string
|
|
72
|
-
props: Record<string, any>
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface InlineText extends BaseInlineContent {
|
|
76
|
-
type: "text"
|
|
77
|
-
props: {
|
|
78
|
-
content: string
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface InlineLink extends BaseInlineContent {
|
|
83
|
-
type: "link"
|
|
84
|
-
props: {
|
|
85
|
-
href: string
|
|
86
|
-
target?: "_blank" | "_self"
|
|
87
|
-
content: string
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface InlineMention extends BaseInlineContent {
|
|
92
|
-
type: "mention"
|
|
93
|
-
props: {
|
|
94
|
-
pageId: string
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export type InlineContent = InlineText | InlineLink | InlineMention
|
|
99
|
-
|
|
100
|
-
export type RichTextContent = InlineContent[]
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { type Block } from "./blocks"
|
|
2
|
-
export type { Block }
|
|
3
|
-
import { type Image, type Link } from "./schemas"
|
|
4
|
-
|
|
5
|
-
export type Localized<T = string> = Record<string, T>
|
|
6
|
-
|
|
7
|
-
declare global {
|
|
8
|
-
interface RimelightRegisterPageTypes {}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface RegisterPageTypes extends RimelightRegisterPageTypes {
|
|
12
|
-
Default: BasePageProperties
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type PageType = keyof RegisterPageTypes
|
|
16
|
-
|
|
17
|
-
export interface Property<T = any> {
|
|
18
|
-
defaultValue: T | string | string[] | number | Localized | Localized[]
|
|
19
|
-
label: Localized
|
|
20
|
-
type: "number" | "text" | "text-array" | "enum" | "page" | "page-array"
|
|
21
|
-
options?: string[] | Localized[]
|
|
22
|
-
allowedPageTypes?: PageType[]
|
|
23
|
-
order?: number
|
|
24
|
-
visibleIf?: (properties: any) => boolean
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface PropertyGroup {
|
|
28
|
-
label: Localized
|
|
29
|
-
order?: number
|
|
30
|
-
fields: Record<string, Property>
|
|
31
|
-
defaultOpen: boolean
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface PageDefinition {
|
|
35
|
-
typeLabelKey: string
|
|
36
|
-
properties: Record<string, PropertyGroup>
|
|
37
|
-
initialBlocks?: () => Block[]
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface BasePageProperties {
|
|
41
|
-
[key: string]: PropertyGroup | undefined
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface BasePage {
|
|
45
|
-
id: string
|
|
46
|
-
slug: string
|
|
47
|
-
icon?: Image
|
|
48
|
-
banner?: Image
|
|
49
|
-
images?: Image[]
|
|
50
|
-
title: Localized
|
|
51
|
-
description?: Localized
|
|
52
|
-
tags?: Localized[]
|
|
53
|
-
links?: Link[]
|
|
54
|
-
authorsIds?: string[]
|
|
55
|
-
blocks: Block[]
|
|
56
|
-
postedAt?: Date | string | null
|
|
57
|
-
createdAt: Date | string
|
|
58
|
-
updatedAt: Date | string
|
|
59
|
-
status?: "published" | "draft" | "archived" | (string & {})
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface Page extends BasePage {
|
|
63
|
-
type: PageType
|
|
64
|
-
properties: RegisterPageTypes[PageType]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export type SurroundItem = Pick<BasePage, "id" | "slug" | "title" | "description">
|
|
68
|
-
|
|
69
|
-
export interface PageSurround {
|
|
70
|
-
previous: SurroundItem | null
|
|
71
|
-
next: SurroundItem | null
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface PageVersion extends BasePage {
|
|
75
|
-
pageId: string
|
|
76
|
-
status: "pending" | "approved" | "rejected"
|
|
77
|
-
type: PageType
|
|
78
|
-
content: {
|
|
79
|
-
blocks: Block[]
|
|
80
|
-
properties: RegisterPageTypes[PageType]
|
|
81
|
-
}
|
|
82
|
-
createdBy: string
|
|
83
|
-
approvedBy?: string | null
|
|
84
|
-
approvedAt?: Date | string | null
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function definePageDefinition(definition: PageDefinition): PageDefinition {
|
|
88
|
-
return definition
|
|
89
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { z } from "astro/zod"
|
|
2
|
-
|
|
3
|
-
export const LocalizedSchema = (schema: z.ZodTypeAny) => z.record(z.string(), schema)
|
|
4
|
-
|
|
5
|
-
export const linkVariantEnum = z.enum(["solid", "outline", "subtle", "soft", "ghost", "link"])
|
|
6
|
-
|
|
7
|
-
export const linkColorEnum = z.enum([
|
|
8
|
-
"primary",
|
|
9
|
-
"secondary",
|
|
10
|
-
"neutral",
|
|
11
|
-
"error",
|
|
12
|
-
"warning",
|
|
13
|
-
"success",
|
|
14
|
-
"info"
|
|
15
|
-
])
|
|
16
|
-
|
|
17
|
-
export const ImageSchema = z.object({
|
|
18
|
-
src: z.string().min(1, "Image source must be provided."),
|
|
19
|
-
alt: z.string().min(1, "Image alt text must be provided."),
|
|
20
|
-
width: z.number().int().min(1).optional(),
|
|
21
|
-
height: z.number().int().min(1).optional(),
|
|
22
|
-
name: LocalizedSchema(z.string()).optional()
|
|
23
|
-
})
|
|
24
|
-
export type Image = z.infer<typeof ImageSchema>
|
|
25
|
-
|
|
26
|
-
export const LinkSchema = z.object({
|
|
27
|
-
label: z.string().min(1, "Link label must be provided."),
|
|
28
|
-
to: z.string().min(1, "Link destination must be provided."),
|
|
29
|
-
icon: z.string().optional(),
|
|
30
|
-
trailing: z.boolean().optional(),
|
|
31
|
-
color: linkColorEnum.optional(),
|
|
32
|
-
variant: linkVariantEnum.optional()
|
|
33
|
-
})
|
|
34
|
-
export type Link = z.infer<typeof LinkSchema>
|
|
35
|
-
|
|
36
|
-
export type UserAvailability = "available" | "busy" | "invisible"
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { BlockType } from "../types/blocks"
|
|
2
|
-
|
|
3
|
-
export interface BlockDefinition {
|
|
4
|
-
type: BlockType
|
|
5
|
-
label: string
|
|
6
|
-
icon: string
|
|
7
|
-
category: string
|
|
8
|
-
description?: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const CATEGORY_ORDER = ["Layout", "Text", "Media", "Special"]
|
|
12
|
-
|
|
13
|
-
export const BLOCK_DEFINITIONS: BlockDefinition[] = [
|
|
14
|
-
{
|
|
15
|
-
type: "SectionBlock",
|
|
16
|
-
label: "blocks.SectionBlock.label",
|
|
17
|
-
icon: "i-lucide-heading",
|
|
18
|
-
category: "Layout",
|
|
19
|
-
description: "blocks.SectionBlock.description"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
type: "ParagraphBlock",
|
|
23
|
-
label: "blocks.ParagraphBlock.label",
|
|
24
|
-
icon: "i-lucide-pilcrow",
|
|
25
|
-
category: "Text",
|
|
26
|
-
description: "blocks.ParagraphBlock.description"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
type: "ImageBlock",
|
|
30
|
-
label: "blocks.ImageBlock.label",
|
|
31
|
-
icon: "i-lucide-image",
|
|
32
|
-
category: "Media",
|
|
33
|
-
description: "blocks.ImageBlock.description"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: "CalloutBlock",
|
|
37
|
-
label: "blocks.CalloutBlock.label",
|
|
38
|
-
icon: "i-lucide-info",
|
|
39
|
-
category: "Special",
|
|
40
|
-
description: "blocks.CalloutBlock.description"
|
|
41
|
-
}
|
|
42
|
-
]
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { ref } from "vue"
|
|
2
|
-
|
|
3
|
-
function translate(key: string, fallback?: string) {
|
|
4
|
-
if (fallback !== undefined) return fallback
|
|
5
|
-
const parts = key.split(".")
|
|
6
|
-
return parts[parts.length - 1] || key
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function useI18n() {
|
|
10
|
-
const locale = ref("en")
|
|
11
|
-
return { t: translate, locale }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function addToast(options: { title?: string; description?: string; color?: string }) {
|
|
15
|
-
if (typeof window !== "undefined") {
|
|
16
|
-
console.log(
|
|
17
|
-
`[Toast ${options.color || "info"}]: ${options.title || ""} ${options.description || ""}`
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function useToast() {
|
|
23
|
-
return { add: addToast }
|
|
24
|
-
}
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { type MaybeRefOrGetter, toValue } from "vue"
|
|
2
|
-
import type {
|
|
3
|
-
Localized,
|
|
4
|
-
Page,
|
|
5
|
-
PageVersion,
|
|
6
|
-
BasePageProperties,
|
|
7
|
-
PageDefinition,
|
|
8
|
-
Property,
|
|
9
|
-
PropertyGroup
|
|
10
|
-
} from "../types/pages"
|
|
11
|
-
import type { Block, SectionBlock } from "../types/blocks"
|
|
12
|
-
|
|
13
|
-
function getValue(value: object, key: string): unknown {
|
|
14
|
-
return Reflect.get(value, key)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const getLocalizedContent = <T = string>(
|
|
18
|
-
field: Localized<T> | T | undefined,
|
|
19
|
-
currentLocale: MaybeRefOrGetter<string>
|
|
20
|
-
): T | string => {
|
|
21
|
-
if (field === undefined || field === null) return ""
|
|
22
|
-
if (typeof field !== "object") return String(field)
|
|
23
|
-
|
|
24
|
-
const locale = toValue(currentLocale)
|
|
25
|
-
|
|
26
|
-
if (Object.keys(field).length === 0) return ""
|
|
27
|
-
|
|
28
|
-
const val = getValue(field, locale) ?? getValue(field, "en")
|
|
29
|
-
if (val !== undefined && val !== null) {
|
|
30
|
-
if (typeof val === "string") return val
|
|
31
|
-
if (typeof val === "object") {
|
|
32
|
-
const innerVal = getValue(val, locale) ?? getValue(val, "en")
|
|
33
|
-
if (typeof innerVal === "string") return innerVal
|
|
34
|
-
const firstString = Object.values(val).find((v) => typeof v === "string")
|
|
35
|
-
if (firstString !== undefined) return firstString
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const firstVal = Object.values(field).find((v) => typeof v === "string" && v.trim() !== "")
|
|
40
|
-
if (firstVal !== undefined) return String(firstVal)
|
|
41
|
-
|
|
42
|
-
return ""
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function syncPageWithDefinition(page: Page, definition?: PageDefinition): Page {
|
|
46
|
-
if (!definition) return page
|
|
47
|
-
|
|
48
|
-
const updatedProperties: BasePageProperties = {}
|
|
49
|
-
const definitionGroups = definition.properties
|
|
50
|
-
const existingProperties: Record<string, PropertyGroup | undefined> = page.properties || {}
|
|
51
|
-
|
|
52
|
-
for (const [groupId, group] of Object.entries(definitionGroups)) {
|
|
53
|
-
const definitionGroup = group
|
|
54
|
-
let existingGroup = existingProperties[groupId]
|
|
55
|
-
|
|
56
|
-
if (!existingGroup) {
|
|
57
|
-
const lowerGroupId = groupId.toLowerCase()
|
|
58
|
-
const foundGroupKey = Object.keys(existingProperties).find(
|
|
59
|
-
(k) => k.toLowerCase() === lowerGroupId
|
|
60
|
-
)
|
|
61
|
-
if (foundGroupKey) {
|
|
62
|
-
existingGroup = existingProperties[foundGroupKey]
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const updatedGroupFields: Record<string, Property> = {}
|
|
67
|
-
const definitionFields = definitionGroup.fields || {}
|
|
68
|
-
|
|
69
|
-
for (const [fieldId, field] of Object.entries(definitionFields)) {
|
|
70
|
-
const definitionField = field
|
|
71
|
-
let value = definitionField.defaultValue
|
|
72
|
-
|
|
73
|
-
if (existingGroup) {
|
|
74
|
-
if (existingGroup.fields?.[fieldId]?.defaultValue !== undefined) {
|
|
75
|
-
value = existingGroup.fields[fieldId].defaultValue
|
|
76
|
-
} else if (getValue(existingGroup, fieldId) !== undefined) {
|
|
77
|
-
value = getValue(existingGroup, fieldId)
|
|
78
|
-
} else {
|
|
79
|
-
const lowerFieldId = fieldId.toLowerCase()
|
|
80
|
-
const foundKey = Object.keys(existingGroup).find((k) => k.toLowerCase() === lowerFieldId)
|
|
81
|
-
if (foundKey && getValue(existingGroup, foundKey) !== undefined) {
|
|
82
|
-
value = getValue(existingGroup, foundKey)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
updatedGroupFields[fieldId] = {
|
|
88
|
-
...JSON.parse(JSON.stringify(definitionField)),
|
|
89
|
-
defaultValue: value
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
updatedProperties[groupId] = {
|
|
94
|
-
...definitionGroup,
|
|
95
|
-
fields: updatedGroupFields
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
page.properties = updatedProperties
|
|
100
|
-
|
|
101
|
-
if (definition.initialBlocks) {
|
|
102
|
-
const templateBlocks = definition.initialBlocks()
|
|
103
|
-
const currentBlocks = page.blocks || []
|
|
104
|
-
const definitionTemplatedBlocks = templateBlocks.filter((b) => b.isTemplated)
|
|
105
|
-
|
|
106
|
-
let updatedBlocks = currentBlocks.filter((b: Block) => {
|
|
107
|
-
if (!b.isTemplated) return true
|
|
108
|
-
return definitionTemplatedBlocks.some((db: Block) => isSameBlock(b, db))
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
for (const db of definitionTemplatedBlocks) {
|
|
112
|
-
const existingIdx = updatedBlocks.findIndex((b: Block) => isSameBlock(b, db))
|
|
113
|
-
const dbIndexAtStart = templateBlocks.findIndex((b: Block) => b.id === db.id)
|
|
114
|
-
|
|
115
|
-
if (existingIdx === -1) {
|
|
116
|
-
updatedBlocks.splice(dbIndexAtStart, 0, { ...db })
|
|
117
|
-
} else {
|
|
118
|
-
const existing = updatedBlocks[existingIdx]
|
|
119
|
-
if (!existing) {
|
|
120
|
-
updatedBlocks.splice(dbIndexAtStart, 0, { ...db })
|
|
121
|
-
continue
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (existing.type === "SectionBlock" && db.type === "SectionBlock") {
|
|
125
|
-
const updated: SectionBlock = {
|
|
126
|
-
...existing,
|
|
127
|
-
...db,
|
|
128
|
-
props: {
|
|
129
|
-
...db.props,
|
|
130
|
-
children: existing.props.children || db.props.children || []
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
updatedBlocks[existingIdx] = updated
|
|
134
|
-
} else {
|
|
135
|
-
updatedBlocks[existingIdx] = { ...db }
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
page.blocks = updatedBlocks
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return page
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function isSameBlock(a: any, b: any) {
|
|
147
|
-
if (a.id === b.id) return true
|
|
148
|
-
if (a.type !== b.type) return false
|
|
149
|
-
if (a.type === "SectionBlock" && b.type === "SectionBlock") {
|
|
150
|
-
return a.props.title === b.props.title
|
|
151
|
-
}
|
|
152
|
-
return false
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export function dehydratePageProperties(properties: BasePageProperties): any {
|
|
156
|
-
const dehydrated: any = {}
|
|
157
|
-
for (const [groupKey, group] of Object.entries(properties)) {
|
|
158
|
-
if (!group?.fields) continue
|
|
159
|
-
dehydrated[groupKey] = {}
|
|
160
|
-
for (const [fieldKey, field] of Object.entries(group.fields)) {
|
|
161
|
-
dehydrated[groupKey][fieldKey] = field.defaultValue
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return dehydrated
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export function convertVersionToPage(version: PageVersion): Page {
|
|
168
|
-
const blocks = version.content?.blocks || version.blocks || []
|
|
169
|
-
const properties = version.content?.properties || getValue(version, "properties")
|
|
170
|
-
const rawAuthorIds = getValue(version, "authorIds")
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
id: version.pageId || version.id,
|
|
174
|
-
type: version.type,
|
|
175
|
-
blocks: JSON.parse(JSON.stringify(blocks)),
|
|
176
|
-
properties: properties ? JSON.parse(JSON.stringify(properties)) : {},
|
|
177
|
-
authorsIds:
|
|
178
|
-
version.authorsIds ??
|
|
179
|
-
(Array.isArray(rawAuthorIds)
|
|
180
|
-
? rawAuthorIds.filter((s): s is string => typeof s === "string")
|
|
181
|
-
: []),
|
|
182
|
-
createdAt: version.createdAt ? new Date(version.createdAt) : new Date(),
|
|
183
|
-
updatedAt: version.updatedAt ? new Date(version.updatedAt) : new Date(),
|
|
184
|
-
postedAt: version.postedAt ? new Date(version.postedAt) : null,
|
|
185
|
-
...(version.banner ? { banner: version.banner } : {}),
|
|
186
|
-
...(version.icon ? { icon: version.icon } : {}),
|
|
187
|
-
images: version.images || [],
|
|
188
|
-
title: version.title || { en: "" },
|
|
189
|
-
slug: version.slug || "",
|
|
190
|
-
description: version.description || { en: "" },
|
|
191
|
-
tags: version.tags || [],
|
|
192
|
-
links: version.links || []
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export function getPageResolutionPath(idOrSlug: string): string {
|
|
197
|
-
if (
|
|
198
|
-
!idOrSlug ||
|
|
199
|
-
idOrSlug === "undefined" ||
|
|
200
|
-
idOrSlug === "null" ||
|
|
201
|
-
idOrSlug === "[object Object]"
|
|
202
|
-
)
|
|
203
|
-
return ""
|
|
204
|
-
|
|
205
|
-
let clean = idOrSlug.replace(/^(?:.*\/)?api\/pages\/(?:id|find)\//, "")
|
|
206
|
-
clean = clean.replace(/^\/|\/$/g, "")
|
|
207
|
-
|
|
208
|
-
const parts = clean.split("/")
|
|
209
|
-
if (parts.length >= 4) {
|
|
210
|
-
const threePart = parts.slice(0, 3).join("/")
|
|
211
|
-
const nextThreePart = parts.slice(3, 6).join("/")
|
|
212
|
-
if (threePart === nextThreePart) {
|
|
213
|
-
clean = parts.slice(3).join("/")
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(clean)
|
|
218
|
-
return isUuid ? `/api/pages/id/${clean}` : `/api/pages/find/${clean}`
|
|
219
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { RichTextContent, InlineText } from "../types/blocks"
|
|
2
|
-
|
|
3
|
-
export function richTextToHtml(content: RichTextContent): string {
|
|
4
|
-
if (!Array.isArray(content)) return ""
|
|
5
|
-
return content
|
|
6
|
-
.map((item) => {
|
|
7
|
-
if (item.type === "text" || item.type === "link") {
|
|
8
|
-
return item.props.content
|
|
9
|
-
}
|
|
10
|
-
if (item.type === "mention") {
|
|
11
|
-
return ""
|
|
12
|
-
}
|
|
13
|
-
return ""
|
|
14
|
-
})
|
|
15
|
-
.join("")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function parseHtmlToRichText(html: string): RichTextContent {
|
|
19
|
-
if (!html || html.trim().length === 0) {
|
|
20
|
-
return []
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const newTextNode: InlineText = {
|
|
24
|
-
id:
|
|
25
|
-
typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
26
|
-
? crypto.randomUUID()
|
|
27
|
-
: Math.random().toString(36).substring(2, 15),
|
|
28
|
-
type: "text",
|
|
29
|
-
props: {
|
|
30
|
-
content: html.trim()
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return [newTextNode]
|
|
35
|
-
}
|