@hywax/cms 3.5.0 → 3.6.0
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/.nuxt/cms/prose/uplora-image.ts +11 -1
- package/.nuxt/cms/toc.ts +5 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +19 -5
- package/dist/runtime/components/Toc.d.vue.ts +3 -2
- package/dist/runtime/components/Toc.vue +12 -3
- package/dist/runtime/components/Toc.vue.d.ts +3 -2
- package/dist/runtime/components/UploraImage.d.vue.ts +2 -1
- package/dist/runtime/components/UploraImage.vue +3 -3
- package/dist/runtime/components/UploraImage.vue.d.ts +2 -1
- package/dist/runtime/components/prose/UploraImage.d.vue.ts +3 -2
- package/dist/runtime/components/prose/UploraImage.vue +61 -12
- package/dist/runtime/components/prose/UploraImage.vue.d.ts +3 -2
- package/dist/runtime/utils/uplora.d.ts +3 -2
- package/dist/runtime/utils/uplora.js +5 -2
- package/package.json +1 -1
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"slots": {
|
|
3
|
-
"base": "rounded-lg"
|
|
3
|
+
"base": "rounded-lg",
|
|
4
|
+
"overlay": "fixed inset-0 bg-default/75 backdrop-blur-sm will-change-opacity",
|
|
5
|
+
"content": "fixed inset-0 flex items-center justify-center cursor-zoom-out focus:outline-none",
|
|
6
|
+
"zoomedImage": "w-full h-auto max-w-[95vw] max-h-[95vh] object-contain rounded-md"
|
|
7
|
+
},
|
|
8
|
+
"variants": {
|
|
9
|
+
"open": {
|
|
10
|
+
"false": {
|
|
11
|
+
"base": "cursor-zoom-in"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
4
14
|
}
|
|
5
15
|
}
|
package/.nuxt/cms/toc.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"slots": {
|
|
3
3
|
"root": "",
|
|
4
|
-
"
|
|
4
|
+
"header": "flex items-center gap-2 text-sm font-medium mb-2",
|
|
5
|
+
"icon": "size-4",
|
|
6
|
+
"title": "text-sm font-medium",
|
|
7
|
+
"list": "min-w-0 border-default border-l-2 pl-4 ml-0.5",
|
|
5
8
|
"listWithChildren": "ms-3",
|
|
6
9
|
"item": "min-w-0",
|
|
7
10
|
"itemWithChildren": "",
|
|
8
|
-
"link": "group relative text-sm flex items-center focus-visible:outline-primary py-1 text-muted hover:text-default transition-colors",
|
|
11
|
+
"link": "group relative text-sm flex items-center focus-visible:outline-primary py-1 font-medium text-muted hover:text-default transition-colors",
|
|
9
12
|
"linkText": "truncate"
|
|
10
13
|
},
|
|
11
14
|
"variants": {
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { pascalCase, kebabCase, camelCase } from 'scule';
|
|
|
7
7
|
import { globSync } from 'tinyglobby';
|
|
8
8
|
|
|
9
9
|
const name = "@hywax/cms";
|
|
10
|
-
const version = "3.
|
|
10
|
+
const version = "3.6.0";
|
|
11
11
|
|
|
12
12
|
function createContext(options, nuxt) {
|
|
13
13
|
const { resolve } = createResolver(import.meta.url);
|
|
@@ -182,7 +182,8 @@ const icons = {
|
|
|
182
182
|
code: "i-lucide-code",
|
|
183
183
|
image: "i-lucide-image",
|
|
184
184
|
editLine: "i-lucide-pen-line",
|
|
185
|
-
save: "i-lucide-cloud-check"
|
|
185
|
+
save: "i-lucide-cloud-check",
|
|
186
|
+
toc: "i-lucide-text-align-start"
|
|
186
187
|
};
|
|
187
188
|
|
|
188
189
|
async function buildComponentDependencyGraph(componentDir, componentPattern) {
|
|
@@ -539,11 +540,14 @@ const tableSearchInput = {
|
|
|
539
540
|
const toc = {
|
|
540
541
|
slots: {
|
|
541
542
|
root: "",
|
|
542
|
-
|
|
543
|
+
header: "flex items-center gap-2 text-sm font-medium mb-2",
|
|
544
|
+
icon: "size-4",
|
|
545
|
+
title: "text-sm font-medium",
|
|
546
|
+
list: "min-w-0 border-default border-l-2 pl-4 ml-0.5",
|
|
543
547
|
listWithChildren: "ms-3",
|
|
544
548
|
item: "min-w-0",
|
|
545
549
|
itemWithChildren: "",
|
|
546
|
-
link: "group relative text-sm flex items-center focus-visible:outline-primary py-1 text-muted hover:text-default transition-colors",
|
|
550
|
+
link: "group relative text-sm flex items-center focus-visible:outline-primary py-1 font-medium text-muted hover:text-default transition-colors",
|
|
547
551
|
linkText: "truncate"
|
|
548
552
|
},
|
|
549
553
|
variants: {
|
|
@@ -583,7 +587,17 @@ const theme = {
|
|
|
583
587
|
|
|
584
588
|
const uploraImage = {
|
|
585
589
|
slots: {
|
|
586
|
-
base: "rounded-lg"
|
|
590
|
+
base: "rounded-lg",
|
|
591
|
+
overlay: "fixed inset-0 bg-default/75 backdrop-blur-sm will-change-opacity",
|
|
592
|
+
content: "fixed inset-0 flex items-center justify-center cursor-zoom-out focus:outline-none",
|
|
593
|
+
zoomedImage: "w-full h-auto max-w-[95vw] max-h-[95vh] object-contain rounded-md"
|
|
594
|
+
},
|
|
595
|
+
variants: {
|
|
596
|
+
open: {
|
|
597
|
+
false: {
|
|
598
|
+
base: "cursor-zoom-in"
|
|
599
|
+
}
|
|
600
|
+
}
|
|
587
601
|
}
|
|
588
602
|
};
|
|
589
603
|
|
|
@@ -4,8 +4,9 @@ import type { ComponentConfig } from '../types';
|
|
|
4
4
|
import theme from '#build/cms/toc';
|
|
5
5
|
type Toc = ComponentConfig<typeof theme, AppConfig, 'toc'>;
|
|
6
6
|
export interface TocProps {
|
|
7
|
+
title?: string;
|
|
7
8
|
links: TocLink[];
|
|
8
|
-
|
|
9
|
+
container?: string;
|
|
9
10
|
class?: any;
|
|
10
11
|
ui?: Toc['slots'];
|
|
11
12
|
}
|
|
@@ -17,7 +18,7 @@ declare const __VLS_export: import("vue").DefineComponent<TocProps, {}, {}, {},
|
|
|
17
18
|
}, string, import("vue").PublicProps, Readonly<TocProps> & Readonly<{
|
|
18
19
|
onMove?: ((args_0: string) => any) | undefined;
|
|
19
20
|
}>, {
|
|
20
|
-
|
|
21
|
+
title: string;
|
|
21
22
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
23
|
declare const _default: typeof __VLS_export;
|
|
23
24
|
export default _default;
|
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
</DefineListTemplate>
|
|
22
22
|
|
|
23
23
|
<div :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
24
|
+
<div :class="ui.header({ class: props.ui?.header })">
|
|
25
|
+
<UIcon :class="ui.icon({ class: props.ui?.icon })" :name="appConfig.ui.icons.toc" />
|
|
26
|
+
|
|
27
|
+
<span :class="ui.title({ class: props.ui?.title })">
|
|
28
|
+
{{ title }}
|
|
29
|
+
</span>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
24
32
|
<ReuseListTemplate :links="props.links" :level="0" />
|
|
25
33
|
</div>
|
|
26
34
|
</template>
|
|
@@ -32,8 +40,9 @@ import { createReusableTemplate } from "@vueuse/core";
|
|
|
32
40
|
import { computed } from "vue";
|
|
33
41
|
import { tv } from "../tv";
|
|
34
42
|
const props = defineProps({
|
|
43
|
+
title: { type: String, required: false, default: "\u0421\u043E\u0434\u0435\u0440\u0436\u0430\u043D\u0438\u0435" },
|
|
35
44
|
links: { type: Array, required: true },
|
|
36
|
-
|
|
45
|
+
container: { type: String, required: false },
|
|
37
46
|
class: { type: null, required: false },
|
|
38
47
|
ui: { type: null, required: false }
|
|
39
48
|
});
|
|
@@ -55,11 +64,11 @@ function scrollToHeading(id) {
|
|
|
55
64
|
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.toc || {} })());
|
|
56
65
|
const nuxtApp = useNuxtApp();
|
|
57
66
|
nuxtApp.hooks.hook("page:loading:end", () => {
|
|
58
|
-
const headings = Array.from((props.
|
|
67
|
+
const headings = Array.from(document.querySelector(props.container ?? "body")?.querySelectorAll("h2, h3") ?? []);
|
|
59
68
|
updateHeadings(headings);
|
|
60
69
|
});
|
|
61
70
|
nuxtApp.hooks.hook("page:transition:finish", () => {
|
|
62
|
-
const headings = Array.from((props.
|
|
71
|
+
const headings = Array.from(document.querySelector(props.container ?? "body")?.querySelectorAll("h2, h3") ?? []);
|
|
63
72
|
updateHeadings(headings);
|
|
64
73
|
});
|
|
65
74
|
</script>
|
|
@@ -4,8 +4,9 @@ import type { ComponentConfig } from '../types';
|
|
|
4
4
|
import theme from '#build/cms/toc';
|
|
5
5
|
type Toc = ComponentConfig<typeof theme, AppConfig, 'toc'>;
|
|
6
6
|
export interface TocProps {
|
|
7
|
+
title?: string;
|
|
7
8
|
links: TocLink[];
|
|
8
|
-
|
|
9
|
+
container?: string;
|
|
9
10
|
class?: any;
|
|
10
11
|
ui?: Toc['slots'];
|
|
11
12
|
}
|
|
@@ -17,7 +18,7 @@ declare const __VLS_export: import("vue").DefineComponent<TocProps, {}, {}, {},
|
|
|
17
18
|
}, string, import("vue").PublicProps, Readonly<TocProps> & Readonly<{
|
|
18
19
|
onMove?: ((args_0: string) => any) | undefined;
|
|
19
20
|
}>, {
|
|
20
|
-
|
|
21
|
+
title: string;
|
|
21
22
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
23
|
declare const _default: typeof __VLS_export;
|
|
23
24
|
export default _default;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { AppConfig } from '@nuxt/schema';
|
|
2
2
|
import type { ImgHTMLAttributes } from 'vue';
|
|
3
3
|
import type { ComponentConfig, ImageFormat, ImageSize } from '../types';
|
|
4
|
+
import type { BuildUploraImage } from '../utils';
|
|
4
5
|
import theme from '#build/cms/uplora-image';
|
|
5
6
|
export type UploraImage = ComponentConfig<typeof theme, AppConfig, 'uploraImage'>;
|
|
6
7
|
export interface UploraImageProps {
|
|
7
|
-
image: string;
|
|
8
|
+
image: string | BuildUploraImage;
|
|
8
9
|
alt?: string;
|
|
9
10
|
formats?: ImageFormat[];
|
|
10
11
|
sizes?: ImageSize[];
|
|
@@ -41,7 +41,7 @@ import { buildUploraImage } from "../utils";
|
|
|
41
41
|
|
|
42
42
|
<script setup>
|
|
43
43
|
const props = defineProps({
|
|
44
|
-
image: { type: String, required: true },
|
|
44
|
+
image: { type: [String, Object], required: true },
|
|
45
45
|
alt: { type: String, required: false },
|
|
46
46
|
formats: { type: Array, required: false },
|
|
47
47
|
sizes: { type: Array, required: false },
|
|
@@ -59,11 +59,11 @@ const appConfig = useAppConfig();
|
|
|
59
59
|
const cmsConfig = getCmsConfig();
|
|
60
60
|
const nuxtApp = useNuxtApp();
|
|
61
61
|
const initialLoad = nuxtApp.isHydrating;
|
|
62
|
-
const image = computed(() => buildUploraImage({
|
|
62
|
+
const image = computed(() => typeof props.image === "string" ? buildUploraImage({
|
|
63
63
|
id: props.image,
|
|
64
64
|
formats: props.formats ?? cmsConfig?.components?.uploraImage?.formats,
|
|
65
65
|
sizes: props.sizes
|
|
66
|
-
}));
|
|
66
|
+
}) : props.image);
|
|
67
67
|
const sources = computed(() => {
|
|
68
68
|
if (image.value.sources.length > 1) {
|
|
69
69
|
return image.value.sources.slice(1);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { AppConfig } from '@nuxt/schema';
|
|
2
2
|
import type { ImgHTMLAttributes } from 'vue';
|
|
3
3
|
import type { ComponentConfig, ImageFormat, ImageSize } from '../types';
|
|
4
|
+
import type { BuildUploraImage } from '../utils';
|
|
4
5
|
import theme from '#build/cms/uplora-image';
|
|
5
6
|
export type UploraImage = ComponentConfig<typeof theme, AppConfig, 'uploraImage'>;
|
|
6
7
|
export interface UploraImageProps {
|
|
7
|
-
image: string;
|
|
8
|
+
image: string | BuildUploraImage;
|
|
8
9
|
alt?: string;
|
|
9
10
|
formats?: ImageFormat[];
|
|
10
11
|
sizes?: ImageSize[];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
-
import type { ComponentConfig, ImageSize } from '../../types';
|
|
2
|
+
import type { ComponentConfig, ImageFormat, ImageSize } from '../../types';
|
|
3
3
|
import theme from '#build/cms/prose/uplora-image';
|
|
4
4
|
export type ProseUploraImage = ComponentConfig<typeof theme, AppConfig, 'uploraImage', 'cms.prose'>;
|
|
5
5
|
export interface ProseUploraImageProps {
|
|
6
|
-
image
|
|
6
|
+
image: string;
|
|
7
|
+
formats?: ImageFormat[];
|
|
7
8
|
alt?: string;
|
|
8
9
|
color?: string;
|
|
9
10
|
sizes?: ImageSize[];
|
|
@@ -1,25 +1,61 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
v-
|
|
4
|
-
:
|
|
5
|
-
:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<DialogRoot
|
|
3
|
+
v-slot="{ close }"
|
|
4
|
+
v-model:open="open"
|
|
5
|
+
:modal="false"
|
|
6
|
+
>
|
|
7
|
+
<DialogTrigger as-child>
|
|
8
|
+
<Motion :layout-id="layoutId" as-child :transition="{ type: 'spring', bounce: 0.15, duration: 0.5, ease: 'easeInOut' }">
|
|
9
|
+
<BaseUploraImage
|
|
10
|
+
v-if="image"
|
|
11
|
+
:image="image"
|
|
12
|
+
:class="ui.base({ class: [props.ui?.base, props.class] })"
|
|
13
|
+
:alt="alt"
|
|
14
|
+
:color="color"
|
|
15
|
+
/>
|
|
16
|
+
</Motion>
|
|
17
|
+
</DialogTrigger>
|
|
18
|
+
|
|
19
|
+
<DialogPortal>
|
|
20
|
+
<AnimatePresence>
|
|
21
|
+
<Motion
|
|
22
|
+
v-if="open"
|
|
23
|
+
:initial="{ opacity: 0 }"
|
|
24
|
+
:animate="{ opacity: 1 }"
|
|
25
|
+
:exit="{ opacity: 0 }"
|
|
26
|
+
:class="ui.overlay({ class: [props.ui?.overlay] })"
|
|
27
|
+
/>
|
|
28
|
+
|
|
29
|
+
<div v-if="open" :class="ui.content({ class: [props.ui?.content] })" @click="close">
|
|
30
|
+
<Motion as-child :layout-id="layoutId" :transition="{ type: 'spring', bounce: 0.15, duration: 0.5, ease: 'easeInOut' }">
|
|
31
|
+
<img
|
|
32
|
+
:src="image.original"
|
|
33
|
+
:alt="alt"
|
|
34
|
+
:class="ui.zoomedImage({ class: props.ui?.zoomedImage })"
|
|
35
|
+
>
|
|
36
|
+
</Motion>
|
|
37
|
+
</div>
|
|
38
|
+
</AnimatePresence>
|
|
39
|
+
</DialogPortal>
|
|
40
|
+
</DialogRoot>
|
|
10
41
|
</template>
|
|
11
42
|
|
|
12
43
|
<script>
|
|
13
44
|
import theme from "#build/cms/prose/uplora-image";
|
|
14
45
|
import { getCmsConfig, useAppConfig } from "#imports";
|
|
15
|
-
import {
|
|
46
|
+
import { useEventListener } from "@vueuse/core";
|
|
47
|
+
import { AnimatePresence, Motion } from "motion-v";
|
|
48
|
+
import { DialogPortal, DialogRoot, DialogTrigger } from "reka-ui";
|
|
49
|
+
import { computed, onMounted, ref, useId } from "vue";
|
|
16
50
|
import { tv } from "../../tv";
|
|
51
|
+
import { buildUploraImage } from "../../utils";
|
|
17
52
|
import BaseUploraImage from "../UploraImage.vue";
|
|
18
53
|
</script>
|
|
19
54
|
|
|
20
55
|
<script setup>
|
|
21
56
|
const props = defineProps({
|
|
22
|
-
image: { type: String, required:
|
|
57
|
+
image: { type: String, required: true },
|
|
58
|
+
formats: { type: Array, required: false },
|
|
23
59
|
alt: { type: String, required: false },
|
|
24
60
|
color: { type: String, required: false },
|
|
25
61
|
sizes: { type: Array, required: false },
|
|
@@ -28,6 +64,19 @@ const props = defineProps({
|
|
|
28
64
|
});
|
|
29
65
|
const appConfig = useAppConfig();
|
|
30
66
|
const cmsConfig = getCmsConfig();
|
|
31
|
-
const
|
|
32
|
-
const
|
|
67
|
+
const layoutId = computed(() => `${props.image}::${useId()}`);
|
|
68
|
+
const open = ref(false);
|
|
69
|
+
const image = computed(() => buildUploraImage({
|
|
70
|
+
id: props.image,
|
|
71
|
+
formats: props.formats ?? cmsConfig?.components?.uploraImage?.formats,
|
|
72
|
+
sizes: props.sizes ?? cmsConfig?.components?.prose?.uploraImage?.sizes
|
|
73
|
+
}));
|
|
74
|
+
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.cms?.prose?.uploraImage || {} })({
|
|
75
|
+
open: open.value
|
|
76
|
+
}));
|
|
77
|
+
onMounted(() => {
|
|
78
|
+
useEventListener(window, "scroll", () => {
|
|
79
|
+
open.value = false;
|
|
80
|
+
});
|
|
81
|
+
});
|
|
33
82
|
</script>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { AppConfig } from '@nuxt/schema';
|
|
2
|
-
import type { ComponentConfig, ImageSize } from '../../types';
|
|
2
|
+
import type { ComponentConfig, ImageFormat, ImageSize } from '../../types';
|
|
3
3
|
import theme from '#build/cms/prose/uplora-image';
|
|
4
4
|
export type ProseUploraImage = ComponentConfig<typeof theme, AppConfig, 'uploraImage', 'cms.prose'>;
|
|
5
5
|
export interface ProseUploraImageProps {
|
|
6
|
-
image
|
|
6
|
+
image: string;
|
|
7
|
+
formats?: ImageFormat[];
|
|
7
8
|
alt?: string;
|
|
8
9
|
color?: string;
|
|
9
10
|
sizes?: ImageSize[];
|
|
@@ -9,8 +9,9 @@ export interface BuildUploraImageOptions {
|
|
|
9
9
|
id: string;
|
|
10
10
|
formats?: ImageFormat[];
|
|
11
11
|
sizes?: ImageSize[];
|
|
12
|
+
originalWithFormat?: boolean;
|
|
12
13
|
}
|
|
13
|
-
export interface
|
|
14
|
+
export interface BuildUploraImage {
|
|
14
15
|
img: string;
|
|
15
16
|
original: string;
|
|
16
17
|
sources: ImageSource[];
|
|
@@ -19,7 +20,7 @@ export interface BuildUploraImageReturn {
|
|
|
19
20
|
/**
|
|
20
21
|
* Создает URL изображения из Uplora
|
|
21
22
|
*/
|
|
22
|
-
export declare function buildUploraImage(options: BuildUploraImageOptions):
|
|
23
|
+
export declare function buildUploraImage(options: BuildUploraImageOptions): BuildUploraImage;
|
|
23
24
|
export interface GenerateImageSizesOptions {
|
|
24
25
|
width: number;
|
|
25
26
|
minWidth?: number;
|
|
@@ -14,7 +14,7 @@ export function createUploraImageResolver() {
|
|
|
14
14
|
}
|
|
15
15
|
export function buildUploraImage(options) {
|
|
16
16
|
const resolver = createUploraImageResolver();
|
|
17
|
-
|
|
17
|
+
let original = resolver(options.id);
|
|
18
18
|
const sizes = options.sizes ?? [{ descriptor: "1x" }];
|
|
19
19
|
const sources = [];
|
|
20
20
|
function makeSrcset(format) {
|
|
@@ -23,7 +23,7 @@ export function buildUploraImage(options) {
|
|
|
23
23
|
}
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
|
-
if (options.formats) {
|
|
26
|
+
if (options.formats?.length) {
|
|
27
27
|
for (const format of options.formats) {
|
|
28
28
|
const srcset = makeSrcset(format);
|
|
29
29
|
sources.push({
|
|
@@ -38,6 +38,9 @@ export function buildUploraImage(options) {
|
|
|
38
38
|
type: imagesExtensionsToMimeTypes[format]
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
+
if (options.originalWithFormat) {
|
|
42
|
+
original = resolver(options.id, { format: options.formats[0] });
|
|
43
|
+
}
|
|
41
44
|
} else {
|
|
42
45
|
const srcset = makeSrcset();
|
|
43
46
|
sources.push({
|