@terrafirmagreg-team/ui 0.1.0 → 1.2.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/package.json +14 -14
- package/src/components/blocks/button/icon-button.tsx +1 -0
- package/src/components/blocks/canvas/chevron-edge.tsx +126 -18
- package/src/components/blocks/canvas/flow-canvas.tsx +4 -0
- package/src/components/blocks/canvas/flow-toolbar.tsx +1 -0
- package/src/components/blocks/canvas/flow-viewport.tsx +1 -0
- package/src/components/blocks/fit-box.tsx +26 -0
- package/src/components/blocks/git/github-info.tsx +1 -0
- package/src/components/blocks/lang/content.tsx +40 -10
- package/src/components/blocks/lang/flag.tsx +1 -0
- package/src/components/blocks/lang/link.tsx +1 -0
- package/src/components/blocks/lang/redirect.tsx +2 -1
- package/src/components/blocks/lang/switcher.tsx +1 -0
- package/src/components/blocks/lang/untranslated-callout.tsx +4 -3
- package/src/components/blocks/lang/untranslated-chip.tsx +53 -0
- package/src/components/blocks/link/link-preview.tsx +2 -1
- package/src/components/blocks/list/row.tsx +1 -0
- package/src/components/blocks/media/glb/model.tsx +1 -0
- package/src/components/blocks/media/glb/scene.tsx +13 -12
- package/src/components/blocks/media/glb/viewer.tsx +1 -0
- package/src/components/blocks/media/image.tsx +3 -2
- package/src/components/blocks/media/slideshow.tsx +4 -3
- package/src/components/blocks/nav/breadcrumb.tsx +1 -0
- package/src/components/blocks/nav/copy-menu.tsx +37 -0
- package/src/components/blocks/nav/link.tsx +1 -0
- package/src/components/blocks/nav/site-menu.tsx +1 -0
- package/src/components/blocks/nav/site-title.tsx +1 -0
- package/src/components/blocks/nav/switcher.tsx +1 -0
- package/src/components/blocks/page/empty-state.tsx +1 -0
- package/src/components/blocks/page/heading.tsx +3 -2
- package/src/components/blocks/page/pager.tsx +110 -2
- package/src/components/blocks/readability/fields.tsx +250 -0
- package/src/components/blocks/readability/menu.tsx +74 -258
- package/src/components/blocks/readability/track.tsx +2 -1
- package/src/components/blocks/search/command.tsx +1 -0
- package/src/components/blocks/search/dialog.tsx +21 -9
- package/src/components/blocks/search/provider.tsx +2 -1
- package/src/components/blocks/sidebar.tsx +5 -5
- package/src/components/blocks/sprite.tsx +231 -0
- package/src/components/blocks/text/format-text.tsx +110 -0
- package/src/components/blocks/theme/toggle.tsx +4 -0
- package/src/components/blocks/tooltip/hint.tsx +1 -0
- package/src/components/blocks/tooltip/lazy.tsx +41 -0
- package/src/components/blocks/viewer/controls.tsx +11 -6
- package/src/components/blocks/viewer/float-bar.tsx +1 -0
- package/src/components/layouts/layout.tsx +2 -1
- package/src/components/layouts/left-sidebar/content.tsx +1 -0
- package/src/components/layouts/left-sidebar/context.tsx +1 -0
- package/src/components/layouts/left-sidebar/expand.tsx +2 -1
- package/src/components/layouts/left-sidebar/footer.tsx +10 -4
- package/src/components/layouts/left-sidebar/index.ts +1 -0
- package/src/components/layouts/left-sidebar/items.tsx +2 -1
- package/src/components/layouts/left-sidebar/search.tsx +4 -3
- package/src/components/layouts/left-sidebar/sidebar.tsx +3 -2
- package/src/components/layouts/left-sidebar/tree.tsx +1 -0
- package/src/components/layouts/right-sidebar.tsx +1 -0
- package/src/components/layouts/tree-context.tsx +1 -0
- package/src/components/mdx/accordion.tsx +3 -2
- package/src/components/mdx/banner.tsx +15 -12
- package/src/components/mdx/callout.tsx +1 -0
- package/src/components/mdx/card.tsx +12 -5
- package/src/components/mdx/codeblock.tsx +5 -4
- package/src/components/mdx/collapsible.tsx +1 -0
- package/src/components/mdx/files.tsx +1 -0
- package/src/components/mdx/glow-header.tsx +17 -3
- package/src/components/mdx/gradient-text.tsx +1 -0
- package/src/components/mdx/icon.tsx +35 -0
- package/src/components/mdx/image-zoom.tsx +5 -4
- package/src/components/mdx/math.tsx +30 -0
- package/src/components/mdx/mermaid.tsx +8 -1
- package/src/components/mdx/multiblock.tsx +1 -0
- package/src/components/mdx/preview.tsx +2 -1
- package/src/components/mdx/steps.tsx +1 -0
- package/src/components/mdx/table.tsx +1 -0
- package/src/components/mdx/tabs.tsx +2 -1
- package/src/components/mdx/type-table.tsx +7 -6
- package/src/{provider.tsx → components/provider.tsx} +1 -3
- package/src/hooks/canvas/use-flow-hover.ts +1 -0
- package/src/hooks/canvas/use-flow-viewport-persist.ts +1 -0
- package/src/hooks/page/use-fit-pages.ts +1 -0
- package/src/hooks/page/use-location-search.ts +8 -2
- package/src/hooks/page/use-page-preview.ts +2 -1
- package/src/hooks/page/use-paged-list.ts +1 -0
- package/src/hooks/readability/{provider.ts → use-readability.ts} +1 -0
- package/src/hooks/search/{dialog.ts → use-dialog.ts} +1 -0
- package/src/hooks/search/use-highlight-query.ts +8 -1
- package/src/hooks/search/{provider.ts → use-provider.ts} +1 -0
- package/src/hooks/use-async-value.ts +6 -3
- package/src/hooks/use-close-on-scroll.ts +1 -0
- package/src/hooks/use-copy-button.ts +1 -0
- package/src/hooks/use-cycle-index.ts +1 -0
- package/src/hooks/use-document-title.ts +1 -0
- package/src/hooks/use-element-size.ts +1 -0
- package/src/hooks/use-external-meta.ts +2 -1
- package/src/hooks/use-hot-key.ts +1 -0
- package/src/hooks/use-hover-follow.ts +1 -0
- package/src/hooks/use-in-view.ts +1 -0
- package/src/hooks/{lang.ts → use-lang.ts} +1 -0
- package/src/hooks/use-last-value.ts +1 -0
- package/src/hooks/{layout.ts → use-layout.ts} +1 -0
- package/src/hooks/use-marquee.ts +1 -0
- package/src/hooks/use-media-query.ts +1 -0
- package/src/hooks/use-mobile.ts +1 -0
- package/src/hooks/use-modifier-keys.ts +1 -0
- package/src/hooks/use-on-change.ts +1 -0
- package/src/hooks/use-pane-keys.ts +1 -0
- package/src/hooks/{sidebar.ts → use-sidebar.ts} +1 -0
- package/src/hooks/use-swipe.ts +1 -0
- package/src/hooks/use-tree.ts +1 -3
- package/src/hooks/viewer/use-in-float-bar.ts +1 -0
- package/src/hooks/viewer/use-viewer-prefs.ts +1 -0
- package/src/lib/canvas/edge.ts +78 -49
- package/src/lib/canvas/geometry.ts +1 -0
- package/src/lib/canvas/state.ts +1 -0
- package/src/lib/canvas/viewport.ts +1 -0
- package/src/lib/canvas/xyflow.ts +1 -0
- package/src/lib/config.ts +25 -0
- package/src/lib/mdx/callout.ts +1 -0
- package/src/lib/mdx/gradient.ts +1 -0
- package/src/lib/mdx/mermaid.ts +1 -0
- package/src/lib/media/crop-opaque.ts +1 -0
- package/src/lib/media/nearby-indexes.ts +1 -0
- package/src/lib/media/trim-transparent.ts +1 -0
- package/src/lib/readability/config.ts +1 -0
- package/src/lib/readability/spotlight.ts +1 -0
- package/src/lib/readability/store.ts +1 -0
- package/src/lib/tree.ts +1 -3
- package/src/lib/utils/cn.ts +1 -0
- package/src/lib/utils/format.ts +3 -3
- package/src/lib/utils/highlight-style.ts +10 -0
- package/src/lib/utils/history.ts +1 -0
- package/src/lib/utils/merge-refs.ts +1 -0
- package/src/lib/utils/nav-active.ts +1 -0
- package/src/lib/utils/stored-value.ts +1 -0
- package/src/lib/utils/urls.ts +2 -1
- package/src/locales/en_us.json +108 -117
- package/src/locales/pl_pl.json +33 -35
- package/src/locales/ru_ru.json +108 -117
- package/src/locales/uk_ua.json +33 -35
- package/src/locales/zh_cn.json +15 -17
- package/src/locales/zh_tw.json +15 -17
- package/src/locales.ts +1 -0
- package/src/types/canvas.ts +6 -1
- package/src/types/glb.ts +1 -0
- package/src/types/mdx-directives.ts +106 -0
- package/src/types/nav.ts +1 -0
- package/src/types/preview.ts +7 -1
- package/src/types/readability.ts +1 -0
- package/src/types/search.ts +1 -0
- package/src/types/tree.ts +1 -0
- package/src/types/viewer.ts +1 -0
- package/styles/content/base.css +198 -194
- package/styles/content/shiki.css +107 -108
- package/styles/content/typography.mjs +3637 -3941
- package/styles/content.css +5 -7
- package/styles.css +430 -413
- package/src/lib/utils/async-cache.ts +0 -32
|
@@ -8,6 +8,17 @@ import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-transl
|
|
|
8
8
|
|
|
9
9
|
type BannerVariant = 'rainbow' | 'normal';
|
|
10
10
|
|
|
11
|
+
export type BannerProps = HTMLAttributes<HTMLDivElement> & {
|
|
12
|
+
|
|
13
|
+
height?: string;
|
|
14
|
+
|
|
15
|
+
variant?: BannerVariant;
|
|
16
|
+
|
|
17
|
+
rainbowColors?: string[];
|
|
18
|
+
|
|
19
|
+
changeLayout?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
11
22
|
export function Banner({
|
|
12
23
|
id,
|
|
13
24
|
variant = 'normal',
|
|
@@ -20,16 +31,7 @@ export function Banner({
|
|
|
20
31
|
'rgba(131,255,166,0.66)',
|
|
21
32
|
],
|
|
22
33
|
...props
|
|
23
|
-
}:
|
|
24
|
-
|
|
25
|
-
height?: string;
|
|
26
|
-
|
|
27
|
-
variant?: BannerVariant;
|
|
28
|
-
|
|
29
|
-
rainbowColors?: string[];
|
|
30
|
-
|
|
31
|
-
changeLayout?: boolean;
|
|
32
|
-
}) {
|
|
34
|
+
}: BannerProps) {
|
|
33
35
|
const t = useTranslations();
|
|
34
36
|
const [open, setOpen] = useState(true);
|
|
35
37
|
const globalKey = id ? `banner-${encodeBase32(id)}` : null;
|
|
@@ -50,7 +52,7 @@ export function Banner({
|
|
|
50
52
|
id={id}
|
|
51
53
|
{...props}
|
|
52
54
|
className={cn(
|
|
53
|
-
'sticky top-0 z-40 flex flex-row items-center justify-center px-4 text-center text-sm font-medium',
|
|
55
|
+
'sticky top-0 z-40 flex flex-row items-center justify-center rounded-xl px-4 text-center text-sm font-medium',
|
|
54
56
|
variant === 'normal' && 'bg-secondary',
|
|
55
57
|
variant === 'rainbow' && 'bg-background',
|
|
56
58
|
!open && 'hidden',
|
|
@@ -85,7 +87,7 @@ export function Banner({
|
|
|
85
87
|
{id ? (
|
|
86
88
|
<button
|
|
87
89
|
type="button"
|
|
88
|
-
aria-label={t('
|
|
90
|
+
aria-label={t('Close Banner', { note: 'ui.banner_close' })}
|
|
89
91
|
onClick={onClose}
|
|
90
92
|
className={cn(
|
|
91
93
|
buttonVariants({
|
|
@@ -152,3 +154,4 @@ function encodeBase32(str: string) {
|
|
|
152
154
|
|
|
153
155
|
return encoded;
|
|
154
156
|
}
|
|
157
|
+
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { useUiComponents } from '@terrafirmagreg-team/ui/provider';
|
|
3
3
|
import type { ComponentProps, ComponentType, HTMLAttributes, ReactNode } from 'react';
|
|
4
4
|
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
5
|
+
import { Icon } from '@terrafirmagreg-team/ui/components/mdx/icon';
|
|
5
6
|
|
|
6
7
|
export function Cards(props: HTMLAttributes<HTMLDivElement>) {
|
|
7
8
|
return (
|
|
@@ -12,7 +13,7 @@ export function Cards(props: HTMLAttributes<HTMLDivElement>) {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export type CardProps = Omit<HTMLAttributes<HTMLElement>, 'title'> & {
|
|
15
|
-
icon?: ReactNode;
|
|
16
|
+
icon?: ReactNode | string;
|
|
16
17
|
title: ReactNode;
|
|
17
18
|
description?: ReactNode;
|
|
18
19
|
|
|
@@ -22,11 +23,16 @@ export type CardProps = Omit<HTMLAttributes<HTMLElement>, 'title'> & {
|
|
|
22
23
|
|
|
23
24
|
export function Card({ icon, title, description, ...props }: CardProps) {
|
|
24
25
|
const { Link } = useUiComponents();
|
|
25
|
-
const
|
|
26
|
+
const { external, href, ...rest } = props;
|
|
27
|
+
const E = (href ? Link : 'div') as ComponentType<ComponentProps<'a'>>;
|
|
26
28
|
|
|
27
29
|
return (
|
|
28
30
|
<E
|
|
29
|
-
{...
|
|
31
|
+
{...rest}
|
|
32
|
+
href={href}
|
|
33
|
+
{...(external
|
|
34
|
+
? { target: '_blank', rel: 'noopener noreferrer' }
|
|
35
|
+
: {})}
|
|
30
36
|
data-card
|
|
31
37
|
className={cn(
|
|
32
38
|
'block rounded-xl border bg-card p-4 text-card-foreground transition-colors @max-lg:col-span-full',
|
|
@@ -35,8 +41,8 @@ export function Card({ icon, title, description, ...props }: CardProps) {
|
|
|
35
41
|
)}
|
|
36
42
|
>
|
|
37
43
|
{icon ? (
|
|
38
|
-
<div className="not-prose mb-2 w-
|
|
39
|
-
{icon}
|
|
44
|
+
<div className="not-prose mb-2 inline-flex h-7 min-w-8 items-center justify-center rounded-lg border bg-muted px-2 text-muted-foreground shadow-md [&_svg]:size-4">
|
|
45
|
+
{typeof icon === 'string' ? <Icon name={icon} /> : icon}
|
|
40
46
|
</div>
|
|
41
47
|
) : null}
|
|
42
48
|
<h3 className="not-prose mb-1 text-sm font-medium">{title}</h3>
|
|
@@ -47,3 +53,4 @@ export function Card({ icon, title, description, ...props }: CardProps) {
|
|
|
47
53
|
</E>
|
|
48
54
|
);
|
|
49
55
|
}
|
|
56
|
+
|
|
@@ -142,7 +142,7 @@ function CopyButton({
|
|
|
142
142
|
if (!pre) return;
|
|
143
143
|
|
|
144
144
|
const clone = pre.cloneNode(true) as HTMLElement;
|
|
145
|
-
clone.querySelectorAll('.copy-ignore').forEach((node) => {
|
|
145
|
+
clone.querySelectorAll('.copy-ignore, .nd-copy-ignore').forEach((node) => {
|
|
146
146
|
node.replaceWith('\n');
|
|
147
147
|
});
|
|
148
148
|
|
|
@@ -168,8 +168,8 @@ function CopyButton({
|
|
|
168
168
|
{checked ? <Check /> : <Clipboard />}
|
|
169
169
|
<span className="sr-only">
|
|
170
170
|
{checked
|
|
171
|
-
? t('
|
|
172
|
-
: t('
|
|
171
|
+
? t('Copied Text', { note: 'ui.copied_text' })
|
|
172
|
+
: t('Copy Text', { note: 'ui.copy_text' })}
|
|
173
173
|
</span>
|
|
174
174
|
</button>
|
|
175
175
|
);
|
|
@@ -232,7 +232,7 @@ export function CodeBlockTabsTrigger({
|
|
|
232
232
|
{...props}
|
|
233
233
|
className={(s) =>
|
|
234
234
|
cn(
|
|
235
|
-
'relative group inline-flex text-sm font-medium text-nowrap items-center transition-colors gap-2 px-2 py-1.5 [&_svg]:size-3.5',
|
|
235
|
+
'relative group inline-flex text-sm font-medium text-nowrap items-center transition-colors gap-2 px-2 py-1.5 [&_svg]:size-3.5 border-b-0',
|
|
236
236
|
s.active ? 'text-primary' : 'hover:text-accent-foreground',
|
|
237
237
|
typeof className === 'function' ? className(s) : className,
|
|
238
238
|
)
|
|
@@ -247,3 +247,4 @@ export function CodeBlockTabsTrigger({
|
|
|
247
247
|
export function CodeBlockTab(props: ComponentProps<typeof TabsContent>) {
|
|
248
248
|
return <TabsContent {...props} />;
|
|
249
249
|
}
|
|
250
|
+
|
|
@@ -11,6 +11,7 @@ export function GlowHeader({
|
|
|
11
11
|
image,
|
|
12
12
|
style,
|
|
13
13
|
className,
|
|
14
|
+
children,
|
|
14
15
|
...props
|
|
15
16
|
}: GradientProps & { fade?: boolean; gradient?: boolean } & ComponentProps<'span'>) {
|
|
16
17
|
const boxFrom = from ?? '#fa18cf';
|
|
@@ -20,7 +21,7 @@ export function GlowHeader({
|
|
|
20
21
|
return (
|
|
21
22
|
<span
|
|
22
23
|
className={cn(
|
|
23
|
-
'mb-6 inline-block rounded-[20px]
|
|
24
|
+
'relative mb-6 inline-block rounded-[20px] px-4 py-2.5 text-center',
|
|
24
25
|
className,
|
|
25
26
|
)}
|
|
26
27
|
style={{
|
|
@@ -31,10 +32,23 @@ export function GlowHeader({
|
|
|
31
32
|
WebkitTextFillColor: 'transparent',
|
|
32
33
|
}),
|
|
33
34
|
boxShadow: `0 10px 20px color-mix(in srgb, ${boxFrom} 25%, transparent)`,
|
|
34
|
-
...(fade && { borderImage: `${gradientBg} 1` }),
|
|
35
35
|
...style,
|
|
36
36
|
}}
|
|
37
37
|
{...props}
|
|
38
|
-
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
{fade && (
|
|
41
|
+
<span
|
|
42
|
+
aria-hidden
|
|
43
|
+
className="pointer-events-none absolute inset-x-4 -bottom-0.5 h-0.5 rounded-full"
|
|
44
|
+
style={{
|
|
45
|
+
backgroundImage: gradientBg,
|
|
46
|
+
maskImage:
|
|
47
|
+
'linear-gradient(to right, transparent, black 25%, black 75%, transparent)',
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
</span>
|
|
39
52
|
);
|
|
40
53
|
}
|
|
54
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { icons, type LucideProps } from 'lucide-react';
|
|
2
|
+
import * as SI from '@icons-pack/react-simple-icons';
|
|
3
|
+
import type { ComponentType } from 'react';
|
|
4
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
5
|
+
|
|
6
|
+
const registry = icons as Record<string, ComponentType<LucideProps>>;
|
|
7
|
+
const brands = SI as unknown as Record<string, ComponentType<LucideProps>>;
|
|
8
|
+
|
|
9
|
+
function toPascal(name: string): string {
|
|
10
|
+
return name
|
|
11
|
+
.split(/[-_\s]+/)
|
|
12
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
13
|
+
.join('');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function Icon({
|
|
17
|
+
name,
|
|
18
|
+
className,
|
|
19
|
+
...props
|
|
20
|
+
}: { name: string } & LucideProps) {
|
|
21
|
+
const Component =
|
|
22
|
+
registry[name] ?? registry[toPascal(name)] ?? brands[`Si${toPascal(name)}`];
|
|
23
|
+
if (!Component) return null;
|
|
24
|
+
return (
|
|
25
|
+
<Component
|
|
26
|
+
className={cn(
|
|
27
|
+
'inline-block align-[-0.125em]',
|
|
28
|
+
props.size === undefined && 'size-[1em]',
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
@@ -163,7 +163,7 @@ export function Lightbox({ children }: { children: ReactNode }) {
|
|
|
163
163
|
<dialog
|
|
164
164
|
ref={initDialog}
|
|
165
165
|
tabIndex={-1}
|
|
166
|
-
aria-label={t('
|
|
166
|
+
aria-label={t('Image Viewer', { note: 'ui.image_viewer' })}
|
|
167
167
|
onCancel={(e) => {
|
|
168
168
|
e.preventDefault();
|
|
169
169
|
close();
|
|
@@ -179,7 +179,7 @@ export function Lightbox({ children }: { children: ReactNode }) {
|
|
|
179
179
|
>
|
|
180
180
|
<button
|
|
181
181
|
type="button"
|
|
182
|
-
aria-label={t('
|
|
182
|
+
aria-label={t('Close', { note: 'ui.close' })}
|
|
183
183
|
onClick={close}
|
|
184
184
|
className={cn(
|
|
185
185
|
buttonVariants({
|
|
@@ -226,7 +226,7 @@ export function Lightbox({ children }: { children: ReactNode }) {
|
|
|
226
226
|
<>
|
|
227
227
|
<button
|
|
228
228
|
type="button"
|
|
229
|
-
aria-label={t('
|
|
229
|
+
aria-label={t('Previous Image', { note: 'ui.prev_image' })}
|
|
230
230
|
onClick={() => navigate(-1)}
|
|
231
231
|
className={cn(
|
|
232
232
|
buttonVariants({
|
|
@@ -240,7 +240,7 @@ export function Lightbox({ children }: { children: ReactNode }) {
|
|
|
240
240
|
</button>
|
|
241
241
|
<button
|
|
242
242
|
type="button"
|
|
243
|
-
aria-label={t('
|
|
243
|
+
aria-label={t('Next Image', { note: 'ui.next_image' })}
|
|
244
244
|
onClick={() => navigate(1)}
|
|
245
245
|
className={cn(
|
|
246
246
|
buttonVariants({
|
|
@@ -312,3 +312,4 @@ function transition(from: HTMLElement, update: () => HTMLElement) {
|
|
|
312
312
|
if (to) to.style.viewTransitionName = '';
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import katex from 'katex';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
4
|
+
|
|
5
|
+
export function Math({
|
|
6
|
+
children,
|
|
7
|
+
block = false,
|
|
8
|
+
className,
|
|
9
|
+
}: {
|
|
10
|
+
children?: string;
|
|
11
|
+
block?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
}) {
|
|
14
|
+
const html = useMemo(
|
|
15
|
+
() =>
|
|
16
|
+
katex.renderToString(children ?? '', {
|
|
17
|
+
displayMode: block,
|
|
18
|
+
throwOnError: false,
|
|
19
|
+
}),
|
|
20
|
+
[children, block],
|
|
21
|
+
);
|
|
22
|
+
const Tag = block ? 'div' : 'span';
|
|
23
|
+
return (
|
|
24
|
+
<Tag
|
|
25
|
+
className={cn(block && 'my-4 overflow-x-auto text-center', className)}
|
|
26
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -7,10 +7,17 @@ export function Mermaid({ chart }: { chart: string }) {
|
|
|
7
7
|
if (svg === null) {
|
|
8
8
|
return (
|
|
9
9
|
<CodeBlock title="Mermaid">
|
|
10
|
-
<Pre>
|
|
10
|
+
<Pre>
|
|
11
|
+
{chart.split('\n').map((line, i) => (
|
|
12
|
+
<span key={i} className="line">
|
|
13
|
+
{line}
|
|
14
|
+
</span>
|
|
15
|
+
))}
|
|
16
|
+
</Pre>
|
|
11
17
|
</CodeBlock>
|
|
12
18
|
);
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
return <div dangerouslySetInnerHTML={{ __html: svg }} />;
|
|
16
22
|
}
|
|
23
|
+
|
|
@@ -17,7 +17,7 @@ function Pane({
|
|
|
17
17
|
}) {
|
|
18
18
|
const t = useTranslations();
|
|
19
19
|
const text =
|
|
20
|
-
label ?? (kind === 'input' ? t('ui.input') : t('ui.output'));
|
|
20
|
+
label ?? (kind === 'input' ? t('Input', { note: 'ui.input' }) : t('Output', { note: 'ui.output' }));
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<div className={cn('min-w-0', className)}>
|
|
@@ -98,3 +98,4 @@ function Output({
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export { Preview, Input, Output };
|
|
101
|
+
|
|
@@ -224,7 +224,7 @@ export function TabsList({ className, ...props }: React.ComponentProps<typeof Ba
|
|
|
224
224
|
{...props}
|
|
225
225
|
className={(s) =>
|
|
226
226
|
cn(
|
|
227
|
-
'flex gap-3.5 text-secondary-foreground overflow-x-auto px-4 not-prose',
|
|
227
|
+
'flex gap-3.5 text-secondary-foreground overflow-x-auto px-4 not-prose border-b border-border',
|
|
228
228
|
typeof className === 'function' ? className(s) : className,
|
|
229
229
|
)
|
|
230
230
|
}
|
|
@@ -351,3 +351,4 @@ function useCollectionIndex() {
|
|
|
351
351
|
function escapeValue(v: string): string {
|
|
352
352
|
return v.toLowerCase().replace(/\s/, '-');
|
|
353
353
|
}
|
|
354
|
+
|
|
@@ -53,8 +53,8 @@ export function TypeTable({
|
|
|
53
53
|
{...props}
|
|
54
54
|
>
|
|
55
55
|
<div className="flex font-medium items-center px-3 py-1 not-prose text-muted-foreground">
|
|
56
|
-
<p className="w-1/4">{t('ui.prop')}</p>
|
|
57
|
-
<p className="@max-xl:hidden">{t('ui.type')}</p>
|
|
56
|
+
<p className="w-1/4">{t('Prop', { note: 'ui.prop' })}</p>
|
|
57
|
+
<p className="@max-xl:hidden">{t('Type', { note: 'ui.type' })}</p>
|
|
58
58
|
</div>
|
|
59
59
|
{Object.entries(type).map(([key, value]) => (
|
|
60
60
|
<Item key={key} parentId={id} name={key} item={value} />
|
|
@@ -134,19 +134,19 @@ function Item({
|
|
|
134
134
|
</div>
|
|
135
135
|
{typeDescription && (
|
|
136
136
|
<>
|
|
137
|
-
<p className={cn(fieldVariants())}>{t('ui.type')}</p>
|
|
137
|
+
<p className={cn(fieldVariants())}>{t('Type', { note: 'ui.type' })}</p>
|
|
138
138
|
<p className="my-auto not-prose">{typeDescription}</p>
|
|
139
139
|
</>
|
|
140
140
|
)}
|
|
141
141
|
{defaultValue && (
|
|
142
142
|
<>
|
|
143
|
-
<p className={cn(fieldVariants())}>{t('ui.default')}</p>
|
|
143
|
+
<p className={cn(fieldVariants())}>{t('Default', { note: 'ui.default' })}</p>
|
|
144
144
|
<p className="my-auto not-prose">{defaultValue}</p>
|
|
145
145
|
</>
|
|
146
146
|
)}
|
|
147
147
|
{parameters.length > 0 && (
|
|
148
148
|
<>
|
|
149
|
-
<p className={cn(fieldVariants())}>{t('ui.parameters')}</p>
|
|
149
|
+
<p className={cn(fieldVariants())}>{t('Parameters', { note: 'ui.parameters' })}</p>
|
|
150
150
|
<div className="flex flex-col gap-2">
|
|
151
151
|
{parameters.map((param) => (
|
|
152
152
|
<div key={param.name} className="inline-flex items-center flex-wrap gap-1">
|
|
@@ -159,7 +159,7 @@ function Item({
|
|
|
159
159
|
)}
|
|
160
160
|
{returns && (
|
|
161
161
|
<>
|
|
162
|
-
<p className={cn(fieldVariants())}>{t('ui.returns')}</p>
|
|
162
|
+
<p className={cn(fieldVariants())}>{t('Returns', { note: 'ui.returns' })}</p>
|
|
163
163
|
<div className="my-auto prose prose-sm prose-no-margin">{returns}</div>
|
|
164
164
|
</>
|
|
165
165
|
)}
|
|
@@ -168,3 +168,4 @@ function Item({
|
|
|
168
168
|
</Collapsible>
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
|
+
|
|
@@ -68,11 +68,9 @@ export interface ThemeOptions extends ThemeProviderProps {
|
|
|
68
68
|
|
|
69
69
|
enabled?: boolean;
|
|
70
70
|
|
|
71
|
-
|
|
72
71
|
hotKey?: string | ((e: KeyboardEvent) => boolean) | false;
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
|
|
76
74
|
function ThemeHotKey({
|
|
77
75
|
hotKey,
|
|
78
76
|
}: {
|
|
@@ -106,7 +104,6 @@ function ThemeHotKey({
|
|
|
106
104
|
return null;
|
|
107
105
|
}
|
|
108
106
|
|
|
109
|
-
|
|
110
107
|
export function UiRootProvider({
|
|
111
108
|
children,
|
|
112
109
|
dir = 'ltr',
|
|
@@ -139,3 +136,4 @@ export function UiRootProvider({
|
|
|
139
136
|
|
|
140
137
|
return <DirectionProvider direction={dir}>{body}</DirectionProvider>;
|
|
141
138
|
}
|
|
139
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useSyncExternalStore } from 'react';
|
|
3
|
+
import { useMemo, useSyncExternalStore } from 'react';
|
|
4
4
|
|
|
5
|
-
let search = '';
|
|
5
|
+
let search = typeof window === 'undefined' ? '' : window.location.search.slice(1);
|
|
6
6
|
const listeners = new Set<() => void>();
|
|
7
7
|
|
|
8
8
|
export function publishLocationSearch(value: string) {
|
|
@@ -23,3 +23,9 @@ export function useLocationSearch(): string {
|
|
|
23
23
|
() => '',
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
export function useLocationSearchParams(): URLSearchParams {
|
|
28
|
+
const search = useLocationSearch();
|
|
29
|
+
return useMemo(() => new URLSearchParams(search), [search]);
|
|
30
|
+
}
|
|
31
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { uiConfig } from '@terrafirmagreg-team/ui/lib/config';
|
|
4
|
-
import { createAsyncCache } from '@terrafirmagreg-team/
|
|
4
|
+
import { createAsyncCache } from '@terrafirmagreg-team/data/lib/async-cache';
|
|
5
5
|
import type { PagePreviewData } from '@terrafirmagreg-team/ui/types/preview';
|
|
6
6
|
|
|
7
7
|
const previewCache = createAsyncCache(
|
|
@@ -38,3 +38,4 @@ export function usePagePreview(
|
|
|
38
38
|
}, [href, active, lang]);
|
|
39
39
|
return preview;
|
|
40
40
|
}
|
|
41
|
+
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
|
+
import { injectHighlightStyle } from '@terrafirmagreg-team/ui/lib/utils/highlight-style';
|
|
3
4
|
|
|
4
5
|
function buildRegexFromQuery(query: string): RegExp | null {
|
|
5
6
|
const source = query
|
|
@@ -16,8 +17,13 @@ export function useHighlightQuery(query: string) {
|
|
|
16
17
|
if (!element || !regex || typeof Highlight === 'undefined')
|
|
17
18
|
return () => {};
|
|
18
19
|
let highlight = CSS.highlights.get('search-hit');
|
|
19
|
-
if (!highlight)
|
|
20
|
+
if (!highlight) {
|
|
20
21
|
CSS.highlights.set('search-hit', (highlight = new Highlight()));
|
|
22
|
+
injectHighlightStyle(
|
|
23
|
+
'search-hit',
|
|
24
|
+
'color:var(--color-primary);text-decoration-line:underline',
|
|
25
|
+
);
|
|
26
|
+
}
|
|
21
27
|
const walker = document.createTreeWalker(
|
|
22
28
|
element,
|
|
23
29
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
|
|
@@ -49,3 +55,4 @@ export function useHighlightQuery(query: string) {
|
|
|
49
55
|
[query],
|
|
50
56
|
);
|
|
51
57
|
}
|
|
58
|
+
|
|
@@ -32,18 +32,19 @@ export function useAsyncValue<T>(
|
|
|
32
32
|
export function useAsyncResult<T>(
|
|
33
33
|
factory: (() => Promise<T>) | false | null | undefined,
|
|
34
34
|
deps: DependencyList,
|
|
35
|
-
): { value: T | undefined; pending: boolean } {
|
|
35
|
+
): { value: T | undefined; pending: boolean; error: unknown } {
|
|
36
36
|
const [entry, setEntry] = useState<{
|
|
37
37
|
deps: DependencyList;
|
|
38
38
|
value: T | undefined;
|
|
39
|
+
error?: unknown;
|
|
39
40
|
}>();
|
|
40
41
|
useAsyncEffect(async (isCancelled) => {
|
|
41
42
|
if (!factory) return;
|
|
42
43
|
try {
|
|
43
44
|
const next = await factory();
|
|
44
45
|
if (!isCancelled()) setEntry({ deps, value: next });
|
|
45
|
-
} catch {
|
|
46
|
-
if (!isCancelled()) setEntry({ deps, value: undefined });
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (!isCancelled()) setEntry({ deps, value: undefined, error });
|
|
47
48
|
}
|
|
48
49
|
}, deps);
|
|
49
50
|
const resolved =
|
|
@@ -53,5 +54,7 @@ export function useAsyncResult<T>(
|
|
|
53
54
|
return {
|
|
54
55
|
value: factory && resolved ? entry?.value : undefined,
|
|
55
56
|
pending: Boolean(factory) && !resolved,
|
|
57
|
+
error: factory && resolved ? entry?.error : undefined,
|
|
56
58
|
};
|
|
57
59
|
}
|
|
60
|
+
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
uiConfig,
|
|
6
6
|
type ExternalMetaProvider,
|
|
7
7
|
} from '@terrafirmagreg-team/ui/lib/config';
|
|
8
|
-
import { createAsyncCache } from '@terrafirmagreg-team/
|
|
8
|
+
import { createAsyncCache } from '@terrafirmagreg-team/data/lib/async-cache';
|
|
9
9
|
|
|
10
10
|
export interface ExternalMeta {
|
|
11
11
|
title: string;
|
|
@@ -130,3 +130,4 @@ export function useExternalMeta(
|
|
|
130
130
|
}, [href, active]);
|
|
131
131
|
return meta;
|
|
132
132
|
}
|
|
133
|
+
|
package/src/hooks/use-hot-key.ts
CHANGED
package/src/hooks/use-in-view.ts
CHANGED