@terrafirmagreg-team/ui 1.2.7 → 1.2.8

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terrafirmagreg-team/ui",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "type": "module",
5
5
  "description": "Shared UI kit",
6
6
  "license": "LGPL-3.0-only",
@@ -44,7 +44,7 @@
44
44
  "@react-three/drei": "10.7.9",
45
45
  "@react-three/fiber": "9.8.2",
46
46
  "@shadcn/react": "^0.3.1",
47
- "@terrafirmagreg-team/translate": "^1.2.5",
47
+ "@terrafirmagreg-team/translate": "^1.2.6",
48
48
  "@xyflow/react": "12.12.0",
49
49
  "beautiful-mermaid": "^1.1.3",
50
50
  "class-variance-authority": "^0.7.1",
@@ -2,7 +2,7 @@
2
2
  import { useContext, useState } from 'react';
3
3
  import type { ComponentProps } from 'react';
4
4
  import { useUiComponents } from '@terrafirmagreg-team/ui/provider';
5
- import { Globe } from 'lucide-react';
5
+ import { Globe, SquareArrowOutUpRight } from 'lucide-react';
6
6
  import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
7
7
  import { buttonVariants } from '@terrafirmagreg-team/ui/components/ui/button';
8
8
  import { Skeleton } from '@terrafirmagreg-team/ui/components/ui/skeleton';
@@ -86,6 +86,7 @@ function ExternalAnchor({
86
86
  }
87
87
  >
88
88
  {children}
89
+ <SquareArrowOutUpRight className="ms-0.5 inline-block size-3 align-baseline text-muted-foreground" />
89
90
  </HoverCardTrigger>
90
91
  <HoverCardContent className="w-fit max-w-[min(18rem,90vw)]">
91
92
  <div className="flex w-full min-w-0 items-center gap-2 font-medium">
@@ -37,7 +37,7 @@ export function Heading({
37
37
  props.className,
38
38
  )}
39
39
  >
40
- {props.children}
40
+ <span className="min-w-0">{props.children}</span>
41
41
  <button
42
42
  aria-live="polite"
43
43
  className={cn(
@@ -29,6 +29,8 @@ export type LayoutProps = {
29
29
  sidebar?: ReactNode;
30
30
  navTitle?: ComponentType<ComponentProps<'a'>>;
31
31
  header?: ReactNode;
32
+ banner?: ReactNode;
33
+ defaultOpenLevel?: number;
32
34
  children?: ReactNode;
33
35
  };
34
36
 
@@ -41,23 +43,27 @@ export function Layout({
41
43
  sidebar,
42
44
  navTitle: Title = EmptyTitle,
43
45
  header = <LayoutHeader />,
46
+ banner,
47
+ defaultOpenLevel = 0,
44
48
  children,
45
49
  }: LayoutProps) {
46
50
  return (
47
51
  <LayoutContext value={useMemo(() => ({ navTitle: Title }), [Title])}>
48
52
  <TreeContextProvider tree={tree}>
49
- <SidebarProvider>
53
+ <SidebarProvider defaultOpenLevel={defaultOpenLevel}>
50
54
  <LeftSidebarPortalProvider>
51
55
  <div
52
56
  id="spacious-layout"
53
57
  data-slot="layout"
54
58
  className="relative grid min-h-(--layout-height) bg-card transition-[grid-template-columns] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none [--layout-height:calc(100dvh_-_var(--banner-height,0px))] [--header-height:--spacing(14)] [--page-width:100%] [--sidebar-width:0px] [--sidebar-col:var(--sidebar-width)] [--toc-width:0px] max-md:[--docs-row-3:calc(var(--banner-height,0px)+var(--header-height)+var(--toc-popover-height,0px))] md:h-(--layout-height) md:overflow-clip print:h-auto print:overflow-visible"
55
59
  style={{
56
- gridTemplate: `"sidebar header right" auto
60
+ gridTemplate: `"banner banner banner" auto
61
+ "sidebar header right" auto
57
62
  "sidebar toc-popover right" var(--toc-popover-height, 0px)
58
63
  "sidebar main right" 1fr / var(--sidebar-col) minmax(0, 1fr) auto`,
59
64
  }}
60
65
  >
66
+ {banner}
61
67
  {sidebar}
62
68
  {header}
63
69
  <RightSidebar>{children}</RightSidebar>
@@ -25,6 +25,29 @@ import {
25
25
  LeftSidebarItem,
26
26
  LeftSidebarLabel,
27
27
  } from './items';
28
+ import { isSkeletonTree } from '@terrafirmagreg-team/ui/lib/tree';
29
+ import { Skeleton } from '@terrafirmagreg-team/ui/components/ui/skeleton';
30
+
31
+ const TREE_SKELETON_ROWS = [
32
+ 'w-3/5',
33
+ 'w-4/5 ms-4',
34
+ 'w-2/3 ms-4',
35
+ 'w-1/2 ms-4',
36
+ 'w-3/4',
37
+ 'w-1/2 ms-4',
38
+ 'w-2/3 ms-4',
39
+ 'w-3/5',
40
+ ];
41
+
42
+ export function LeftSidebarTreeSkeleton() {
43
+ return (
44
+ <div aria-hidden className="flex flex-col gap-1 px-1 py-2">
45
+ {TREE_SKELETON_ROWS.map((width, i) => (
46
+ <Skeleton key={i} className={`h-7 ${width}`} />
47
+ ))}
48
+ </div>
49
+ );
50
+ }
28
51
 
29
52
  type TreeRenderer = (props: {
30
53
  item: PageTree.Node;
@@ -61,6 +84,7 @@ export function LeftSidebarTree({
61
84
  const search = useLocationSearch();
62
85
  const { languages } = useLocaleRegistry();
63
86
  const resolved = tree ?? root;
87
+ if (isSkeletonTree(resolved)) return <LeftSidebarTreeSkeleton />;
64
88
  return (
65
89
  <RendererContext
66
90
  value={useMemo(
@@ -13,6 +13,7 @@ import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-transl
13
13
  export function AccordionRoot({ className, ...props }: ComponentProps<typeof Primitive.Root>) {
14
14
  return (
15
15
  <Primitive.Root
16
+ data-md="accordions"
16
17
  className={(s) =>
17
18
  cn(
18
19
  'divide-y divide-border overflow-hidden rounded-lg border bg-card',
@@ -98,6 +99,12 @@ export function Accordions({
98
99
  const rootRef = useRef<HTMLDivElement>(null);
99
100
  const composedRef = mergeRefs(ref, rootRef);
100
101
  const [value, setValue] = useState<unknown[]>(defaultValue ?? []);
102
+ const initial = JSON.stringify(defaultValue);
103
+
104
+ useEffect(() => {
105
+ setValue(defaultValue ?? []);
106
+ // eslint-disable-next-line react-hooks/exhaustive-deps
107
+ }, [initial]);
101
108
 
102
109
  useEffect(() => {
103
110
  const id = window.location.hash.substring(1);
@@ -144,7 +151,7 @@ export function Accordion({
144
151
  {id ? <CopyButton id={id} /> : null}
145
152
  </AccordionHeader>
146
153
  <AccordionContent hiddenUntilFound>
147
- <div className="px-4 pb-2 text-[0.9375rem] prose-no-margin [&[hidden]:not([hidden='until-found'])]:hidden">
154
+ <div className="px-4 pb-2 text-[0.9375rem] prose-no-margin [&[hidden]:not([hidden='until-found'])]:hidden [&_[data-md=accordions]]:ms-1 [&_[data-md=accordions]]:border-s-2 [&_[data-md=accordions]]:bg-muted/40 [&_.fd-steps]:bg-muted/40 [&_.fd-steps]:rounded-md [&_.fd-steps]:pe-3">
148
155
  {children}
149
156
  </div>
150
157
  </AccordionContent>
@@ -1,39 +1,60 @@
1
1
  'use client';
2
2
 
3
- import { type HTMLAttributes, useEffect, useState } from 'react';
3
+ import { type CSSProperties, type HTMLAttributes, useEffect, useState } from 'react';
4
4
  import { X } from 'lucide-react';
5
5
  import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
6
6
  import { buttonVariants } from '@terrafirmagreg-team/ui/components/ui/button';
7
7
  import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
8
+ import {
9
+ gradientImage,
10
+ type GradientProps,
11
+ } from '@terrafirmagreg-team/ui/lib/mdx/gradient';
8
12
 
9
- type BannerVariant = 'rainbow' | 'normal';
13
+ type BannerVariant = 'rainbow' | 'normal' | 'fade' | 'glow';
10
14
 
11
- export type BannerProps = HTMLAttributes<HTMLDivElement> & {
15
+ export type BannerProps = HTMLAttributes<HTMLDivElement> &
16
+ GradientProps & {
12
17
 
13
- height?: string;
18
+ height?: string;
14
19
 
15
- variant?: BannerVariant;
20
+ variant?: BannerVariant;
16
21
 
17
- rainbowColors?: string[];
22
+ gradient?: boolean;
18
23
 
19
- changeLayout?: boolean;
20
- };
24
+ rainbowColors?: string[];
25
+
26
+ changeLayout?: boolean;
27
+ };
28
+
29
+ const fadeMask = {
30
+ WebkitMask:
31
+ 'linear-gradient(#fff 0 0) content-box, linear-gradient(to bottom, #fff 0%, transparent 100%) border-box',
32
+ WebkitMaskComposite: 'destination-out',
33
+ mask: 'linear-gradient(to bottom, #fff 0%, transparent 100%) border-box subtract, linear-gradient(#fff 0 0) content-box',
34
+ } as CSSProperties;
21
35
 
22
36
  export function Banner({
23
37
  id,
24
38
  variant = 'normal',
25
39
  changeLayout = true,
26
- height = '3rem',
40
+ height,
41
+ gradient,
42
+ from,
43
+ to,
44
+ dir,
45
+ image,
27
46
  rainbowColors = [
28
47
  'rgba(0,149,255,0.56)',
29
48
  'rgba(231,77,255,0.77)',
30
49
  'rgba(255,0,0,0.73)',
31
50
  'rgba(131,255,166,0.66)',
32
51
  ],
52
+ style,
33
53
  ...props
34
54
  }: BannerProps) {
35
55
  const t = useTranslations();
36
56
  const [open, setOpen] = useState(true);
57
+ const glow = variant === 'fade' || variant === 'glow';
37
58
  const globalKey = id ? `banner-${encodeBase32(id)}` : null;
38
59
 
39
60
  useEffect(() => {
@@ -47,19 +68,41 @@ export function Banner({
47
68
 
48
69
  if (!open) return null;
49
70
 
71
+ const gradientBg = gradientImage({ from, to, dir, image });
72
+ const textStyle: CSSProperties | undefined = gradient
73
+ ? {
74
+ backgroundImage: gradientBg,
75
+ WebkitBackgroundClip: 'text',
76
+ backgroundClip: 'text',
77
+ WebkitTextFillColor: 'transparent',
78
+ color: 'transparent',
79
+ }
80
+ : undefined;
81
+
50
82
  return (
51
83
  <div
52
84
  id={id}
53
85
  {...props}
54
86
  className={cn(
55
- 'sticky top-0 z-40 flex flex-row items-center justify-center rounded-xl px-4 text-center text-sm font-medium',
87
+ 'flex flex-row items-center justify-center px-4 text-center font-medium',
88
+ glow
89
+ ? 'relative isolate mt-10 mb-6 overflow-hidden rounded-[20px] p-2.5 text-xl font-semibold [&_:is(h1,h2,h3,h4,h5,h6)]:m-0 [&_:is(h1,h2,h3,h4,h5,h6)]:border-0 [&_:is(h1,h2,h3,h4,h5,h6)]:p-0 [&_:is(h1,h2,h3,h4,h5,h6)_button]:hidden'
90
+ : 'sticky top-0 z-40 rounded-xl text-sm',
56
91
  variant === 'normal' && 'bg-secondary',
57
92
  variant === 'rainbow' && 'bg-background',
58
93
  !open && 'hidden',
59
94
  props.className,
60
95
  )}
61
96
  style={{
62
- height,
97
+ height: height ?? (glow ? undefined : '3rem'),
98
+ ...(variant === 'glow'
99
+ ? {
100
+ backgroundImage:
101
+ 'radial-gradient(var(--header-bg-inner), var(--header-bg-outer))',
102
+ boxShadow: '0 0 20px var(--header-shadow)',
103
+ }
104
+ : {}),
105
+ ...style,
63
106
  }}
64
107
  >
65
108
  {changeLayout && open ? (
@@ -83,7 +126,16 @@ export function Banner({
83
126
  colors: rainbowColors,
84
127
  })
85
128
  : null}
86
- {props.children}
129
+ {variant === 'fade' ? (
130
+ <span
131
+ aria-hidden
132
+ className="pointer-events-none absolute inset-0 rounded-[inherit] p-px"
133
+ style={{ backgroundImage: gradientBg, ...fadeMask }}
134
+ />
135
+ ) : null}
136
+ <div className="relative" style={textStyle}>
137
+ {props.children}
138
+ </div>
87
139
  {id ? (
88
140
  <button
89
141
  type="button"
@@ -1,35 +1,68 @@
1
- import { CircleCheck, CircleX, Info, Lightbulb, StickyNote, TriangleAlert } from 'lucide-react';
1
+ import {
2
+ Bell,
3
+ Bug,
4
+ CircleAlert,
5
+ CircleCheck,
6
+ CircleHelp,
7
+ CircleX,
8
+ ClipboardList,
9
+ Info,
10
+ Lightbulb,
11
+ ListChecks,
12
+ Megaphone,
13
+ OctagonAlert,
14
+ OctagonX,
15
+ Quote,
16
+ StickyNote,
17
+ TriangleAlert,
18
+ } from 'lucide-react';
2
19
  import type { ComponentProps, CSSProperties, ReactNode } from 'react';
3
20
  import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
4
21
  import { calloutStyle } from '@terrafirmagreg-team/ui/lib/mdx/callout';
5
22
 
6
23
  export type CalloutType =
7
- | 'info'
8
24
  | 'note'
9
25
  | 'tip'
26
+ | 'info'
27
+ | 'important'
10
28
  | 'warn'
11
29
  | 'warning'
12
- | 'error'
30
+ | 'caution'
31
+ | 'attention'
13
32
  | 'danger'
33
+ | 'error'
14
34
  | 'success'
15
- | 'idea';
35
+ | 'idea'
36
+ | 'question'
37
+ | 'failure'
38
+ | 'bug'
39
+ | 'abstract'
40
+ | 'example'
41
+ | 'quote';
16
42
 
17
43
  const iconClass = 'size-5 -me-0.5 fill-(--callout-color) text-card';
44
+ const textIconClass =
45
+ 'size-5 -me-0.5 fill-(--callout-color) text-(--callout-color)';
18
46
 
19
47
  const ICONS: Record<string, ReactNode> = {
20
- info: <Info className={iconClass} />,
21
48
  note: <StickyNote className={iconClass} />,
22
- tip: (
23
- <Lightbulb className="size-5 -me-0.5 fill-(--callout-color) text-(--callout-color)" />
24
- ),
49
+ tip: <Lightbulb className={textIconClass} />,
50
+ info: <Info className={iconClass} />,
51
+ important: <Megaphone className={iconClass} />,
25
52
  warn: <TriangleAlert className={iconClass} />,
26
53
  warning: <TriangleAlert className={iconClass} />,
27
- error: <CircleX className={iconClass} />,
28
- danger: <CircleX className={iconClass} />,
54
+ caution: <OctagonAlert className={iconClass} />,
55
+ attention: <Bell className={iconClass} />,
56
+ danger: <OctagonX className={iconClass} />,
57
+ error: <CircleAlert className={iconClass} />,
29
58
  success: <CircleCheck className={iconClass} />,
30
- idea: (
31
- <Lightbulb className="size-5 -me-0.5 fill-(--callout-color) text-(--callout-color)" />
32
- ),
59
+ idea: <Lightbulb className={textIconClass} />,
60
+ question: <CircleHelp className={iconClass} />,
61
+ failure: <CircleX className={iconClass} />,
62
+ bug: <Bug className={iconClass} />,
63
+ abstract: <ClipboardList className={iconClass} />,
64
+ example: <ListChecks className={iconClass} />,
65
+ quote: <Quote className={iconClass} />,
33
66
  };
34
67
 
35
68
  export function Callout({
@@ -1,7 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { cva } from 'class-variance-authority';
4
- import { FileIcon, FolderIcon, FolderOpen } from 'lucide-react';
4
+ import { FileIcon, FolderIcon, FolderOpen, SquareArrowOutUpRight } from 'lucide-react';
5
+ import Link from 'next/link';
5
6
  import { type HTMLAttributes, type ReactNode, useState } from 'react';
6
7
  import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
7
8
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './collapsible';
@@ -19,45 +20,73 @@ export function Files({ className, ...props }: HTMLAttributes<HTMLDivElement>):
19
20
  }
20
21
 
21
22
  export interface FileProps extends HTMLAttributes<HTMLDivElement> {
22
- name: string;
23
+ name: ReactNode;
23
24
  icon?: ReactNode;
25
+ href?: string;
26
+ description?: string;
24
27
  }
25
28
 
26
29
  export interface FolderProps extends HTMLAttributes<HTMLDivElement> {
27
- name: string;
30
+ name: ReactNode;
28
31
 
29
32
  disabled?: boolean;
30
33
 
31
34
  defaultOpen?: boolean;
35
+
36
+ href?: string;
37
+
38
+ description?: string;
32
39
  }
33
40
 
34
41
  export function File({
35
42
  name,
36
43
  icon = <FileIcon />,
44
+ href,
45
+ description,
37
46
  className,
38
47
  ...rest
39
48
  }: FileProps): React.ReactElement {
40
49
  return (
41
- <div className={cn(itemVariants({ className }))} {...rest}>
50
+ <div
51
+ className={cn(itemVariants({ className }))}
52
+ title={description}
53
+ {...rest}
54
+ >
42
55
  {icon}
43
- {name}
56
+ {href ? (
57
+ <Link href={href} className="hover:underline">
58
+ {name}
59
+ </Link>
60
+ ) : (
61
+ name
62
+ )}
44
63
  </div>
45
64
  );
46
65
  }
47
66
 
48
- export function Folder({ name, defaultOpen = false, ...props }: FolderProps): React.ReactElement {
67
+ export function Folder({ name, defaultOpen = false, href, description, ...props }: FolderProps): React.ReactElement {
49
68
  const [open, setOpen] = useState(defaultOpen);
50
69
 
51
70
  return (
52
71
  <Collapsible open={open} onOpenChange={setOpen} {...props}>
53
- <CollapsibleTrigger className={cn(itemVariants({ className: 'w-full' }))}>
54
- {open ? <FolderOpen /> : <FolderIcon />}
55
- {name}
56
- </CollapsibleTrigger>
72
+ <div className="flex items-center" title={description}>
73
+ <CollapsibleTrigger className={cn(itemVariants({ className: 'w-full' }))}>
74
+ {open ? <FolderOpen /> : <FolderIcon />}
75
+ {name}
76
+ </CollapsibleTrigger>
77
+ {href ? (
78
+ <Link
79
+ href={href}
80
+ className="me-1 rounded p-1 text-muted-foreground hover:text-foreground [&_svg]:size-3.5"
81
+ aria-label={typeof name === 'string' ? name : undefined}
82
+ >
83
+ <SquareArrowOutUpRight />
84
+ </Link>
85
+ ) : null}
86
+ </div>
57
87
  <CollapsibleContent>
58
88
  <div className="ms-2 flex flex-col border-l ps-2">{props.children}</div>
59
89
  </CollapsibleContent>
60
90
  </Collapsible>
61
91
  );
62
92
  }
63
-
@@ -0,0 +1,28 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import {
3
+ gradientImage,
4
+ type GradientProps,
5
+ } from '@terrafirmagreg-team/ui/lib/mdx/gradient';
6
+
7
+ export function Gradient({
8
+ from,
9
+ to,
10
+ dir,
11
+ image,
12
+ style,
13
+ ...props
14
+ }: HTMLAttributes<HTMLDivElement> & GradientProps) {
15
+ return (
16
+ <div
17
+ {...props}
18
+ style={{
19
+ backgroundImage: gradientImage({ from, to, dir, image }),
20
+ WebkitBackgroundClip: 'text',
21
+ backgroundClip: 'text',
22
+ WebkitTextFillColor: 'transparent',
23
+ color: 'transparent',
24
+ ...style,
25
+ }}
26
+ />
27
+ );
28
+ }
@@ -0,0 +1,28 @@
1
+ import type { ComponentProps } from 'react';
2
+ import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
3
+
4
+ export function Video({
5
+ src,
6
+ title,
7
+ className,
8
+ ...props
9
+ }: ComponentProps<'div'> & { src: string; title?: string }) {
10
+ return (
11
+ <div
12
+ className={cn(
13
+ 'not-prose my-6 mx-auto w-full max-w-2xl overflow-hidden rounded-xl border bg-card',
14
+ className,
15
+ )}
16
+ {...props}
17
+ >
18
+ <iframe
19
+ src={src}
20
+ title={title}
21
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
22
+ referrerPolicy="strict-origin-when-cross-origin"
23
+ allowFullScreen
24
+ className="aspect-video w-full"
25
+ />
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+
3
+ import { useState } from 'react';
4
+
5
+ export function useLastResult<T>(result: {
6
+ value: T | undefined;
7
+ pending: boolean;
8
+ error: unknown;
9
+ }, key?: string): {
10
+ value: T | undefined;
11
+ stale: boolean;
12
+ pending: boolean;
13
+ error: unknown;
14
+ } {
15
+ const [held, setHeld] = useState<{ key?: string; value: T } | undefined>();
16
+ const keyMismatch = held !== undefined && held.key !== key;
17
+ if (
18
+ result.value !== undefined &&
19
+ (keyMismatch || !Object.is(held?.value, result.value))
20
+ ) {
21
+ setHeld({ key, value: result.value });
22
+ }
23
+ const value = result.value ?? (keyMismatch ? undefined : held?.value);
24
+ return {
25
+ value,
26
+ stale: value !== undefined && result.value === undefined,
27
+ pending: result.pending && value === undefined,
28
+ error: result.error,
29
+ };
30
+ }
package/src/lib/config.ts CHANGED
@@ -56,8 +56,10 @@ export const DEFAULT_EXTERNAL_META_PROVIDERS: ExternalMetaProvider[] = [
56
56
  },
57
57
  {
58
58
  host: /.*/,
59
- url: 'https://api.allorigins.win/raw?url={href}',
60
- kind: 'html',
59
+ url: 'https://api.microlink.io?url={href}',
60
+ kind: 'json',
61
+ title: 'data.title',
62
+ description: 'data.description',
61
63
  },
62
64
  ];
63
65
 
@@ -1,15 +1,24 @@
1
1
  import type { CSSProperties } from 'react';
2
2
 
3
3
  export const COLORS: Record<string, string> = {
4
- info: 'var(--color-info)',
5
4
  note: 'var(--color-note)',
6
5
  tip: 'var(--color-tip)',
6
+ info: 'var(--color-info)',
7
+ important: 'var(--color-important)',
7
8
  warn: 'var(--color-warning)',
8
9
  warning: 'var(--color-warning)',
10
+ caution: 'var(--color-caution)',
11
+ attention: 'var(--color-attention)',
12
+ danger: 'var(--color-danger)',
9
13
  error: 'var(--color-error)',
10
- danger: 'var(--color-error)',
11
14
  success: 'var(--color-success)',
12
15
  idea: 'var(--color-idea)',
16
+ question: 'var(--color-question)',
17
+ failure: 'var(--color-failure)',
18
+ bug: 'var(--color-bug)',
19
+ abstract: 'var(--color-abstract)',
20
+ example: 'var(--color-example)',
21
+ quote: 'var(--color-quote)',
13
22
  };
14
23
 
15
24
  export function calloutStyle(
package/src/lib/tree.ts CHANGED
@@ -1,5 +1,15 @@
1
1
  import type * as PageTree from '@terrafirmagreg-team/translate/types/tree';
2
2
 
3
+ export function skeletonTree(id = 'sidebar:skeleton'): PageTree.Root {
4
+ return { name: '', children: [], $id: id, $skeleton: true } as PageTree.Root;
5
+ }
6
+
7
+ export function isSkeletonTree(
8
+ tree: PageTree.Root | PageTree.Folder | undefined,
9
+ ): boolean {
10
+ return (tree as { $skeleton?: boolean } | undefined)?.$skeleton === true;
11
+ }
12
+
3
13
  export function normalizeUrl(url: string): string {
4
14
  if (url.startsWith('http://') || url.startsWith('https://')) return url;
5
15
  if (!url.startsWith('/')) url = `/${url}`;
@@ -17,17 +17,6 @@ export type GradientDirectiveProps = {
17
17
  className?: string;
18
18
  };
19
19
 
20
- export type GlowDirectiveProps = {
21
- from?: string;
22
- to?: string;
23
- dir?: string;
24
- image?: string;
25
- gradient?: boolean;
26
- fade?: boolean;
27
- children: string;
28
- className?: string;
29
- };
30
-
31
20
  export type CalloutDirectiveProps = {
32
21
  type?: CalloutType;
33
22
  title?: string;
@@ -48,7 +37,12 @@ export type CardDirectiveProps = {
48
37
  export type BannerDirectiveProps = {
49
38
  id?: string;
50
39
  height?: string;
51
- variant?: 'rainbow' | 'normal';
40
+ variant?: 'normal' | 'rainbow' | 'fade' | 'glow';
41
+ gradient?: boolean;
42
+ from?: string;
43
+ to?: string;
44
+ dir?: string;
45
+ image?: string;
52
46
  rainbowColors?: string[];
53
47
  changeLayout?: boolean;
54
48
  children?: string;
@@ -64,6 +58,7 @@ export type TabsDirectiveProps = {
64
58
  };
65
59
 
66
60
  export type AccordionsDirectiveProps = {
61
+ format?: 'details' | 'accordions' | 'jsx';
67
62
  multiple?: boolean;
68
63
  defaultValue?: string | string[];
69
64
  children: string;
@@ -76,6 +71,13 @@ export type StepsDirectiveProps = {
76
71
  };
77
72
 
78
73
  export type FilesDirectiveProps = {
74
+ format?: 'list' | 'fenced';
75
+ name?: string;
76
+ icon?: string;
77
+ href?: string;
78
+ description?: string;
79
+ disabled?: boolean;
80
+ defaultOpen?: boolean;
79
81
  children: string;
80
82
  className?: string;
81
83
  };
@@ -93,6 +95,13 @@ export type MermaidDirectiveProps = {
93
95
  };
94
96
 
95
97
  export type MathDirectiveProps = {
98
+ format?:
99
+ | 'inline'
100
+ | 'dollar'
101
+ | 'leaf'
102
+ | 'container'
103
+ | 'fenced'
104
+ | 'display';
96
105
  children: string;
97
106
  block?: boolean;
98
107
  };
@@ -44,6 +44,12 @@
44
44
  --color-error: oklch(63.7% 0.237 25.331);
45
45
  --color-success: oklch(72.3% 0.219 149.579);
46
46
  --color-idea: oklch(70.5% 0.209 60.849);
47
+ --color-question: oklch(80% 0.16 95);
48
+ --color-failure: oklch(60% 0.22 0);
49
+ --color-bug: oklch(57% 0.19 340);
50
+ --color-abstract: oklch(75% 0.15 195);
51
+ --color-example: oklch(62% 0.2 310);
52
+ --color-quote: oklch(60% 0.02 260);
47
53
  --color-diff-remove: rgba(200, 10, 100, 0.12);
48
54
  --color-diff-remove-symbol: rgb(230, 10, 100);
49
55
  --color-diff-add: rgba(14, 180, 100, 0.1);
package/styles.css CHANGED
@@ -40,10 +40,22 @@
40
40
  --color-sidebar-ring: hsl(0, 0%, 63.9%);
41
41
 
42
42
  --color-info: oklch(62.3% 0.214 259.815);
43
+ --color-note: oklch(65% 0.03 260);
44
+ --color-tip: oklch(70% 0.19 165);
45
+ --color-important: oklch(60% 0.22 295);
43
46
  --color-warning: oklch(76.9% 0.188 70.08);
47
+ --color-caution: oklch(68% 0.2 45);
48
+ --color-attention: oklch(65% 0.22 350);
49
+ --color-danger: oklch(56% 0.23 18);
44
50
  --color-error: oklch(63.7% 0.237 25.331);
45
51
  --color-success: oklch(72.3% 0.219 149.579);
46
- --color-idea: oklch(70.5% 0.209 60.849);
52
+ --color-idea: oklch(78% 0.17 85);
53
+ --color-question: oklch(80% 0.16 95);
54
+ --color-failure: oklch(60% 0.22 0);
55
+ --color-bug: oklch(57% 0.19 340);
56
+ --color-abstract: oklch(75% 0.15 195);
57
+ --color-example: oklch(62% 0.2 310);
58
+ --color-quote: oklch(60% 0.02 260);
47
59
  --color-diff-remove: rgba(200, 10, 100, 0.12);
48
60
  --color-diff-remove-symbol: rgb(230, 10, 100);
49
61
  --color-diff-add: rgba(14, 180, 100, 0.1);
@@ -95,6 +107,9 @@
95
107
  --color-chart-5: oklch(0.645 0.246 16.439);
96
108
 
97
109
  --color-float: hsl(0, 0%, 11.6%);
110
+
111
+ --header-bg-inner: rgb(255 255 255 / 0.07);
112
+ --header-shadow: rgb(0 0 0 / 0.7);
98
113
  }
99
114
 
100
115
  :root {
@@ -103,6 +118,9 @@
103
118
  var(--color-primary) 10%,
104
119
  transparent
105
120
  );
121
+ --header-bg-inner: rgb(0 0 0 / 0.03);
122
+ --header-bg-outer: rgb(0 0 0 / 0);
123
+ --header-shadow: rgb(94 94 94 / 0.4);
106
124
  }
107
125
 
108
126
  html {
@@ -1,54 +0,0 @@
1
- import type { ComponentProps } from 'react';
2
- import { gradientImage, type GradientProps } from '@terrafirmagreg-team/ui/lib/mdx/gradient';
3
- import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
4
-
5
- export function GlowHeader({
6
- fade,
7
- gradient,
8
- from,
9
- to,
10
- dir,
11
- image,
12
- style,
13
- className,
14
- children,
15
- ...props
16
- }: GradientProps & { fade?: boolean; gradient?: boolean } & ComponentProps<'span'>) {
17
- const boxFrom = from ?? '#fa18cf';
18
- const boxTo = to ?? '#ff7967';
19
- const gradientBg = gradientImage({ from, to, dir, image });
20
- const boxBg = `radial-gradient(color-mix(in srgb, ${boxFrom} 18%, transparent), color-mix(in srgb, ${boxTo} 8%, transparent))`;
21
- return (
22
- <span
23
- className={cn(
24
- 'relative mb-6 inline-block rounded-[20px] px-4 py-2.5 text-center',
25
- className,
26
- )}
27
- style={{
28
- backgroundImage: gradient ? `${gradientBg}, ${boxBg}` : boxBg,
29
- ...(gradient && {
30
- WebkitBackgroundClip: 'text, border-box',
31
- backgroundClip: 'text, border-box',
32
- WebkitTextFillColor: 'transparent',
33
- }),
34
- boxShadow: `0 10px 20px color-mix(in srgb, ${boxFrom} 25%, transparent)`,
35
- ...style,
36
- }}
37
- {...props}
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>
52
- );
53
- }
54
-
@@ -1,28 +0,0 @@
1
- import type { ComponentProps } from 'react';
2
- import { gradientImage, type GradientProps } from '@terrafirmagreg-team/ui/lib/mdx/gradient';
3
- import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
4
-
5
- export function GradientText({
6
- from,
7
- to,
8
- dir,
9
- image,
10
- style,
11
- className,
12
- ...props
13
- }: GradientProps & ComponentProps<'span'>) {
14
- return (
15
- <span
16
- className={cn('text-transparent', className)}
17
- style={{
18
- backgroundImage: gradientImage({ from, to, dir, image }),
19
- WebkitBackgroundClip: 'text',
20
- backgroundClip: 'text',
21
- WebkitTextFillColor: 'transparent',
22
- ...style,
23
- }}
24
- {...props}
25
- />
26
- );
27
- }
28
-