@umami/shiso 1.1.8 → 1.1.10
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/CHANGELOG.md +16 -0
- package/dist/chunks/App.js +5627 -5571
- package/mdx.config.ts +38 -0
- package/package.json +1 -1
- package/src/App.tsx +1 -0
- package/src/components/Header.tsx +1 -5
- package/src/components/docs/Frame.tsx +3 -1
- package/src/components/docs/ZoomableImage.tsx +79 -0
- package/src/components/docs/index.ts +1 -0
- package/src/components/docs/styles.ts +1 -1
package/mdx.config.ts
CHANGED
|
@@ -101,6 +101,43 @@ function rehypeRemoveHighlightingFragments() {
|
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
function rehypeZoomableImages() {
|
|
105
|
+
return (tree: MdNode) => {
|
|
106
|
+
const visit = (node: MdNode, insideLink = false) => {
|
|
107
|
+
const isMdxElement = node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';
|
|
108
|
+
const isLink = node.tagName === 'a' || (isMdxElement && node.name === 'a');
|
|
109
|
+
const linked = insideLink || isLink;
|
|
110
|
+
|
|
111
|
+
if (isMdxElement && node.name === 'img') {
|
|
112
|
+
node.name = 'ZoomableImage';
|
|
113
|
+
|
|
114
|
+
if (linked) {
|
|
115
|
+
const attributes = Array.isArray(node.attributes) ? node.attributes : [];
|
|
116
|
+
const hasNoZoom = attributes.some(
|
|
117
|
+
attribute =>
|
|
118
|
+
typeof attribute === 'object' && attribute !== null && attribute.name === 'noZoom',
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (!hasNoZoom) {
|
|
122
|
+
node.attributes = [
|
|
123
|
+
...attributes,
|
|
124
|
+
{ type: 'mdxJsxAttribute', name: 'noZoom', value: null },
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} else if (node.tagName === 'img' && linked) {
|
|
129
|
+
node.properties = { ...(node.properties as Record<string, unknown>), noZoom: true };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
node.children?.forEach(child => {
|
|
133
|
+
visit(child, linked);
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
visit(tree);
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
104
141
|
/**
|
|
105
142
|
* The MDX compilation pipeline, shared by the app build and the test runner so
|
|
106
143
|
* tests exercise the same transforms the site ships with.
|
|
@@ -122,6 +159,7 @@ export function shisoMdx(): Plugin {
|
|
|
122
159
|
rehypeWrapJsxForHighlighting,
|
|
123
160
|
rehypeHighlight,
|
|
124
161
|
rehypeRemoveHighlightingFragments,
|
|
162
|
+
rehypeZoomableImages,
|
|
125
163
|
rehypeSlug,
|
|
126
164
|
[
|
|
127
165
|
// Must follow rehypeSlug: the anchor href points at the id it sets.
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -53,11 +53,7 @@ export function Header({ site }: { site: SiteModel }) {
|
|
|
53
53
|
<img src={logo.light} alt="" className="h-6 w-auto dark:hidden" />
|
|
54
54
|
) : null}
|
|
55
55
|
{logo?.dark ? (
|
|
56
|
-
<img
|
|
57
|
-
src={logo.dark}
|
|
58
|
-
alt=""
|
|
59
|
-
className={`hidden h-6 w-auto dark:block ${logo.light === logo.dark ? 'dark:invert' : ''}`}
|
|
60
|
-
/>
|
|
56
|
+
<img src={logo.dark} alt="" className="hidden h-6 w-auto dark:block" />
|
|
61
57
|
) : null}
|
|
62
58
|
{name ? <span>{name}</span> : null}
|
|
63
59
|
</a>
|
|
@@ -46,7 +46,9 @@ export function Frame({ caption, hint, children }: FrameProps) {
|
|
|
46
46
|
</div>
|
|
47
47
|
) : null}
|
|
48
48
|
<figure className={styles.frame}>
|
|
49
|
-
<div className={styles.frameContent}>
|
|
49
|
+
<div data-slot="frame-content" className={styles.frameContent}>
|
|
50
|
+
{enhanceAutoplayVideos(children)}
|
|
51
|
+
</div>
|
|
50
52
|
{caption ? (
|
|
51
53
|
<figcaption className={styles.frameCaption}>{renderFrameText(caption)}</figcaption>
|
|
52
54
|
) : null}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { XIcon } from 'lucide-react';
|
|
2
|
+
import type { ImgHTMLAttributes } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogClose,
|
|
6
|
+
DialogContent,
|
|
7
|
+
DialogTitle,
|
|
8
|
+
DialogTrigger,
|
|
9
|
+
} from '@/components/ui/dialog';
|
|
10
|
+
import { cn } from '@/lib/utils';
|
|
11
|
+
|
|
12
|
+
export interface ZoomableImageProps extends ImgHTMLAttributes<HTMLImageElement> {
|
|
13
|
+
noZoom?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function ZoomableImage({
|
|
17
|
+
noZoom = false,
|
|
18
|
+
className,
|
|
19
|
+
alt,
|
|
20
|
+
src,
|
|
21
|
+
...props
|
|
22
|
+
}: ZoomableImageProps) {
|
|
23
|
+
const image = (
|
|
24
|
+
<img
|
|
25
|
+
{...props}
|
|
26
|
+
src={src}
|
|
27
|
+
alt={alt}
|
|
28
|
+
className={cn('block h-auto max-w-full rounded-lg', noZoom && 'my-6', className)}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (noZoom || !src) {
|
|
33
|
+
return image;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const label = alt ? `View “${alt}” full size` : 'View image full size';
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Dialog>
|
|
40
|
+
<DialogTrigger
|
|
41
|
+
render={
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
data-slot="zoomable-image"
|
|
45
|
+
className="my-6 block w-fit max-w-full cursor-zoom-in rounded-lg text-left outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
|
|
46
|
+
aria-label={label}
|
|
47
|
+
/>
|
|
48
|
+
}
|
|
49
|
+
>
|
|
50
|
+
{image}
|
|
51
|
+
</DialogTrigger>
|
|
52
|
+
<DialogContent
|
|
53
|
+
showCloseButton={false}
|
|
54
|
+
overlayClassName="bg-black/80 supports-backdrop-filter:backdrop-blur-sm"
|
|
55
|
+
className="flex max-h-[calc(100vh-2rem)] w-auto max-w-[calc(100vw-2rem)] items-center justify-center bg-transparent p-0 ring-0 shadow-none sm:max-w-[calc(100vw-2rem)]"
|
|
56
|
+
>
|
|
57
|
+
<DialogTitle className="sr-only">{alt || 'Full-size image'}</DialogTitle>
|
|
58
|
+
<img
|
|
59
|
+
src={src}
|
|
60
|
+
srcSet={props.srcSet}
|
|
61
|
+
sizes={props.sizes}
|
|
62
|
+
alt={alt || ''}
|
|
63
|
+
className="max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] rounded-lg object-contain"
|
|
64
|
+
/>
|
|
65
|
+
<DialogClose
|
|
66
|
+
render={
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
className="fixed top-4 right-4 inline-flex size-9 items-center justify-center rounded-full bg-black/60 text-white outline-none backdrop-blur-sm hover:bg-black/80 focus-visible:ring-3 focus-visible:ring-white/60"
|
|
70
|
+
aria-label="Close full-size image"
|
|
71
|
+
/>
|
|
72
|
+
}
|
|
73
|
+
>
|
|
74
|
+
<XIcon className="size-5" />
|
|
75
|
+
</DialogClose>
|
|
76
|
+
</DialogContent>
|
|
77
|
+
</Dialog>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -58,7 +58,7 @@ export const styles = {
|
|
|
58
58
|
'flex h-5 shrink-0 items-center text-muted-foreground [&_svg]:size-4 [&_svg]:fill-current',
|
|
59
59
|
frame: 'relative overflow-hidden rounded-2xl border border-border bg-muted/25 p-2',
|
|
60
60
|
frameContent:
|
|
61
|
-
'relative flex justify-center overflow-hidden rounded-xl [&_p]:m-0 [&_img]:w-full [&_video]:w-full',
|
|
61
|
+
'relative flex justify-center overflow-hidden rounded-xl [&_p]:m-0 [&_img]:m-0 [&_img]:w-full [&_video]:w-full [&_[data-slot=zoomable-image]]:m-0 [&_[data-slot=zoomable-image]]:w-full',
|
|
62
62
|
frameCaption:
|
|
63
63
|
'relative mt-3 px-4 pb-1 text-center text-sm leading-5 text-muted-foreground [&_p]:m-0 [&_a]:font-semibold',
|
|
64
64
|
|