@xyd-js/components 0.1.0-xyd.2 → 0.1.0-xyd.3
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 +13 -0
- package/dist/{CTABanner-DVtDluuG.js → CTABanner-CAp2EJcY.js} +1 -1
- package/dist/{CTABanner-DVtDluuG.js.map → CTABanner-CAp2EJcY.js.map} +1 -1
- package/dist/CodeSample-OUrk_l-U.js +2 -0
- package/dist/CodeSample-OUrk_l-U.js.map +1 -0
- package/dist/{HomeView-JIjSATBR.js → HomeView-t6Cljv0B.js} +1 -1
- package/dist/{HomeView-JIjSATBR.js.map → HomeView-t6Cljv0B.js.map} +1 -1
- package/dist/{UnderlineNav-Ck16YRuC.js → UnderlineNav-4pD9CR2B.js} +2 -2
- package/dist/{UnderlineNav-Ck16YRuC.js.map → UnderlineNav-4pD9CR2B.js.map} +1 -1
- package/dist/_rollupPluginBabelHelpers-CDahOOgk.js +2 -0
- package/dist/_rollupPluginBabelHelpers-CDahOOgk.js.map +1 -0
- package/dist/brand.d.ts +2 -1
- package/dist/brand.js +1 -1
- package/dist/coder/themes/cosmo-light.d.ts +5 -0
- package/dist/coder/themes/cosmo-light.js +2 -0
- package/dist/coder/themes/cosmo-light.js.map +1 -0
- package/dist/coder.d.ts +50 -3
- package/dist/coder.js +1 -1
- package/dist/coder.js.map +1 -1
- package/dist/content.d.ts +46 -6
- package/dist/content.js +1 -1
- package/dist/content.js.map +1 -1
- package/dist/index-P2Ntn1sE.js +2 -0
- package/dist/index-P2Ntn1sE.js.map +1 -0
- package/dist/index.css +57 -55
- package/dist/index.d.ts +1 -1
- package/dist/layouts.d.ts +2 -1
- package/dist/layouts.js +1 -1
- package/dist/layouts.js.map +1 -1
- package/dist/pages.d.ts +2 -1
- package/dist/pages.js +1 -1
- package/dist/pages.js.map +1 -1
- package/dist/{tslib.es6-DNxqyfMY.js → tslib.es6-DIxZJ0kO.js} +1 -1
- package/dist/tslib.es6-DIxZJ0kO.js.map +1 -0
- package/dist/views.d.ts +2 -1
- package/dist/views.js +1 -1
- package/dist/writer.d.ts +14 -2
- package/dist/writer.js +1 -1
- package/dist/writer.js.map +1 -1
- package/package.json +5 -2
- package/rollup.config.js +24 -3
- package/src/coder/Code/Code.styles.tsx +50 -0
- package/src/coder/Code/Code.tsx +79 -0
- package/src/coder/Code/annotations.tsx +31 -0
- package/src/coder/Code/highlight.ts +170 -0
- package/src/coder/Code/index.ts +12 -0
- package/src/coder/CodeSample/CodeSample.tsx +30 -133
- package/src/coder/CodeSample/index.ts +0 -1
- package/src/coder/CodeSample/withLocalStored.tsx +1 -1
- package/src/coder/{CodeSample/CodeSample.styles.tsx → CodeTabs/CodeTabs.styles.tsx} +0 -48
- package/src/coder/CodeTabs/CodeTabs.tsx +82 -0
- package/src/coder/CodeTabs/index.ts +6 -0
- package/src/coder/CodeTheme/CodeTheme.tsx +78 -0
- package/src/coder/CodeTheme/index.ts +8 -0
- package/src/coder/index.ts +31 -1
- package/src/coder/{CodeSample/default-theme.ts → themes/cosmo-light.ts} +3 -2
- package/src/content/Content/Content.tsx +1 -0
- package/src/content/Content.tsx +35 -1
- package/src/pages/index.ts +1 -0
- package/src/views/index.ts +1 -0
- package/src/writer/Badge/Badge.styles.tsx +4 -0
- package/src/writer/Badge/Badge.tsx +3 -1
- package/src/writer/Icon/index.tsx +230 -0
- package/dist/CodeSample-CB5kEkeK.js +0 -2
- package/dist/CodeSample-CB5kEkeK.js.map +0 -1
- package/dist/_rollupPluginBabelHelpers-DFryr8Hb.js +0 -2
- package/dist/_rollupPluginBabelHelpers-DFryr8Hb.js.map +0 -1
- package/dist/index-CCn_Wv4c.js +0 -2
- package/dist/index-CCn_Wv4c.js.map +0 -1
- package/dist/tslib.es6-DNxqyfMY.js.map +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {css} from "@linaria/core";
|
|
2
|
+
|
|
3
|
+
export const $mark = {
|
|
4
|
+
host: css`
|
|
5
|
+
display: flex;
|
|
6
|
+
border-left-width: 4px;
|
|
7
|
+
border-color: transparent;
|
|
8
|
+
margin: 4px 0;
|
|
9
|
+
`,
|
|
10
|
+
line: css`
|
|
11
|
+
flex: 1 1 0%;
|
|
12
|
+
`,
|
|
13
|
+
$$annotated: css`
|
|
14
|
+
border-color: #60A5FA;
|
|
15
|
+
background-color: #EEF2FF;
|
|
16
|
+
`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const $lineNumber = {
|
|
20
|
+
host: css`
|
|
21
|
+
margin: 0 12px 0px 4px;
|
|
22
|
+
//text-align: right;
|
|
23
|
+
user-select: none;
|
|
24
|
+
opacity: 0.5;
|
|
25
|
+
`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const $code = {
|
|
29
|
+
host: css`
|
|
30
|
+
max-height: 400px;
|
|
31
|
+
background: linear-gradient(45deg, rgb(247, 247, 248) 0%, rgb(247, 247, 248) 100%) !important;
|
|
32
|
+
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 8px 16px;
|
|
35
|
+
|
|
36
|
+
border-top: 1px solid rgb(236, 236, 241);
|
|
37
|
+
border-bottom-left-radius: 10px;
|
|
38
|
+
border-bottom-right-radius: 10px;
|
|
39
|
+
|
|
40
|
+
font-size: 12px;
|
|
41
|
+
line-height: 20px;
|
|
42
|
+
white-space: pre-wrap;
|
|
43
|
+
word-break: break-all;
|
|
44
|
+
|
|
45
|
+
overflow-y: scroll;
|
|
46
|
+
`,
|
|
47
|
+
host$$full: css`
|
|
48
|
+
max-height: 100%;
|
|
49
|
+
`
|
|
50
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, {Suspense} from "react";
|
|
2
|
+
import type {HighlightedCode, AnnotationHandler} from "codehike/code";
|
|
3
|
+
import {InnerLine, Pre} from "codehike/code";
|
|
4
|
+
import {Theme} from "@code-hike/lighter";
|
|
5
|
+
|
|
6
|
+
import {CodeTheme, type CodeThemeBlockProps} from "../CodeTheme";
|
|
7
|
+
import {$lineNumber, $mark, $code} from "./Code.styles.tsx";
|
|
8
|
+
|
|
9
|
+
export interface CodeProps {
|
|
10
|
+
codeblocks: CodeThemeBlockProps[];
|
|
11
|
+
theme?: Theme
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function Code(props: CodeProps) {
|
|
16
|
+
return <Suspense fallback={<$Loading/>}>
|
|
17
|
+
<CodeTheme codeblocks={props.codeblocks} theme={props.theme}>
|
|
18
|
+
{props.children}
|
|
19
|
+
</CodeTheme>
|
|
20
|
+
</Suspense>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function $Loading() {
|
|
24
|
+
return <>
|
|
25
|
+
loading...
|
|
26
|
+
</>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// TODO: fix any
|
|
30
|
+
Code.LineNumber = function LineNumber(props: any) {
|
|
31
|
+
if (!props.children || !props.children.length) {
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<span
|
|
37
|
+
style={{minWidth: `${props.width}ch`}}
|
|
38
|
+
className={$lineNumber.host}
|
|
39
|
+
>
|
|
40
|
+
{props.lineNumber}
|
|
41
|
+
</span>
|
|
42
|
+
<InnerLine merge={props}/>
|
|
43
|
+
</>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// TODO: fix any
|
|
48
|
+
Code.Mark = function Mark(props: any) {
|
|
49
|
+
return <div className={`${$mark.host} ${props.annotation && $mark.$$annotated}`}>
|
|
50
|
+
<InnerLine
|
|
51
|
+
merge={props}
|
|
52
|
+
className={$mark.line}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// TODO: fix any
|
|
58
|
+
Code.Bg = function CodeLine(props: any) {
|
|
59
|
+
return <span className={`${props.annotation && $mark.$$annotated}`}>
|
|
60
|
+
{props.children}
|
|
61
|
+
</span>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Code.Pre = function CodePre(props: {
|
|
65
|
+
codeblock: HighlightedCode,
|
|
66
|
+
size?: "full",
|
|
67
|
+
handlers: AnnotationHandler[]
|
|
68
|
+
}
|
|
69
|
+
) {
|
|
70
|
+
return <Pre
|
|
71
|
+
className={`
|
|
72
|
+
${$code.host}
|
|
73
|
+
${props?.size === "full" && $code.host$$full}
|
|
74
|
+
`}
|
|
75
|
+
style={props.codeblock?.style || props.codeblock?.style}
|
|
76
|
+
code={props.codeblock}
|
|
77
|
+
handlers={props.handlers}
|
|
78
|
+
/>
|
|
79
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {AnnotationHandler} from "codehike/code";
|
|
3
|
+
|
|
4
|
+
import {Code} from "./Code.tsx";
|
|
5
|
+
|
|
6
|
+
const markAnnotation: AnnotationHandler = {
|
|
7
|
+
name: "mark",
|
|
8
|
+
Line: (props) => {
|
|
9
|
+
return <Code.Mark {...props}/>
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const bgAnnotation: AnnotationHandler = {
|
|
14
|
+
name: "bg",
|
|
15
|
+
Inline: (props) => {
|
|
16
|
+
return <Code.Bg {...props}/>
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const lineNumberAnnotation: AnnotationHandler = {
|
|
21
|
+
name: "line-numbers",
|
|
22
|
+
Line: ({annotation, ...props}) => {
|
|
23
|
+
return <Code.LineNumber {...props}/>
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const annotations = {
|
|
28
|
+
mark: markAnnotation,
|
|
29
|
+
bg: bgAnnotation,
|
|
30
|
+
lineNumbers: lineNumberAnnotation
|
|
31
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CodeAnnotation,
|
|
3
|
+
type RawCode,
|
|
4
|
+
type HighlightedCode,
|
|
5
|
+
type Token
|
|
6
|
+
} from 'codehike/code';
|
|
7
|
+
import {
|
|
8
|
+
type Lines,
|
|
9
|
+
type Tokens,
|
|
10
|
+
highlightSync as lighter,
|
|
11
|
+
LANG_NAMES,
|
|
12
|
+
type Theme
|
|
13
|
+
} from '@code-hike/lighter';
|
|
14
|
+
|
|
15
|
+
type Whitespace = string
|
|
16
|
+
|
|
17
|
+
type AnyToken = Token | Whitespace
|
|
18
|
+
|
|
19
|
+
function isWhitespace(token: Token | Whitespace): token is Whitespace {
|
|
20
|
+
return typeof token === 'string';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function highlight(
|
|
24
|
+
data: RawCode,
|
|
25
|
+
theme: Theme,
|
|
26
|
+
lang: string
|
|
27
|
+
): HighlightedCode {
|
|
28
|
+
if (!LANG_NAMES.includes(lang)) {
|
|
29
|
+
console.warn(`Unknown language "${lang}"`);
|
|
30
|
+
lang = 'txt';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
lines,
|
|
35
|
+
lang: lighterLang,
|
|
36
|
+
style
|
|
37
|
+
} = lighter(data.value, lang, theme as any, {
|
|
38
|
+
annotations: [],
|
|
39
|
+
scopes: false // true for better token transitions, but breaks css themes
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const tokens = joinLines(lines);
|
|
43
|
+
// split surrounding whitespace for each token
|
|
44
|
+
const splitTokens = splitWhitespace(tokens);
|
|
45
|
+
// join consecutive whitespace tokens
|
|
46
|
+
const joinedTokens = joinWhitespace(splitTokens);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...data,
|
|
50
|
+
code: data.value,
|
|
51
|
+
tokens: joinedTokens,
|
|
52
|
+
lang: lighterLang,
|
|
53
|
+
annotations: [], // TODO: in the future
|
|
54
|
+
// annotations: compatAnnotations(annotations),
|
|
55
|
+
themeName: typeof theme === 'string' ? theme : theme?.name || 'unknown',
|
|
56
|
+
style
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function compatAnnotations(annotations: any[]): CodeAnnotation[] {
|
|
61
|
+
const newAnnotations: CodeAnnotation[] = [];
|
|
62
|
+
for (const a of annotations) {
|
|
63
|
+
const {name, query, ranges} = a;
|
|
64
|
+
for (const r of ranges) {
|
|
65
|
+
if (r.lineNumber) {
|
|
66
|
+
const {lineNumber, fromColumn, toColumn} = r;
|
|
67
|
+
newAnnotations.push({
|
|
68
|
+
name,
|
|
69
|
+
query,
|
|
70
|
+
lineNumber,
|
|
71
|
+
fromColumn,
|
|
72
|
+
toColumn
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
const {fromLineNumber, toLineNumber} = r;
|
|
76
|
+
newAnnotations.push({
|
|
77
|
+
name,
|
|
78
|
+
query,
|
|
79
|
+
fromLineNumber,
|
|
80
|
+
toLineNumber
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return newAnnotations;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// group the Lines into one array
|
|
89
|
+
function joinLines(lines: Lines): AnyToken[] {
|
|
90
|
+
const joinedTokens: AnyToken[] = [];
|
|
91
|
+
lines.forEach((lineOrGroup, i) => {
|
|
92
|
+
if ('lines' in lineOrGroup) {
|
|
93
|
+
throw new Error('Shouldnt be groups');
|
|
94
|
+
} else {
|
|
95
|
+
const tokens = joinTokens(lineOrGroup.tokens);
|
|
96
|
+
joinedTokens.push(...tokens);
|
|
97
|
+
if (i < lines.length - 1) {
|
|
98
|
+
joinedTokens.push('\n');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return joinedTokens;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function joinTokens(tokens: Tokens): AnyToken[] {
|
|
106
|
+
return tokens.map((tokenOrGroup) => {
|
|
107
|
+
if ('tokens' in tokenOrGroup) {
|
|
108
|
+
throw new Error('Shouldnt be groups');
|
|
109
|
+
} else {
|
|
110
|
+
const t = [tokenOrGroup.content] as Token;
|
|
111
|
+
const {color, ...rest} = tokenOrGroup.style || {};
|
|
112
|
+
t.push(color);
|
|
113
|
+
if (Object.keys(rest).length) {
|
|
114
|
+
t.push(rest);
|
|
115
|
+
}
|
|
116
|
+
return t;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function splitWhitespace(tokens: AnyToken[]) {
|
|
122
|
+
const ejected: AnyToken[] = [];
|
|
123
|
+
tokens.forEach((tokenOrGroup) => {
|
|
124
|
+
if (isWhitespace(tokenOrGroup)) {
|
|
125
|
+
ejected.push(tokenOrGroup);
|
|
126
|
+
} else {
|
|
127
|
+
const [before, content, after] = splitSurroundingWhitespace(
|
|
128
|
+
tokenOrGroup[0]
|
|
129
|
+
);
|
|
130
|
+
if (before?.length) {
|
|
131
|
+
ejected.push(before);
|
|
132
|
+
}
|
|
133
|
+
if (content.length) {
|
|
134
|
+
const copy = [...tokenOrGroup] as Token;
|
|
135
|
+
copy[0] = content;
|
|
136
|
+
ejected.push(copy);
|
|
137
|
+
}
|
|
138
|
+
if (after?.length) {
|
|
139
|
+
ejected.push(after);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return ejected;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function joinWhitespace(tokens: AnyToken[]) {
|
|
147
|
+
const joinedTokens: AnyToken[] = [];
|
|
148
|
+
tokens.forEach((tokenOrGroup) => {
|
|
149
|
+
if (isWhitespace(tokenOrGroup)) {
|
|
150
|
+
let last = joinedTokens[joinedTokens.length - 1];
|
|
151
|
+
if (last && isWhitespace(last)) {
|
|
152
|
+
joinedTokens[joinedTokens.length - 1] += tokenOrGroup;
|
|
153
|
+
} else if (tokenOrGroup !== '') {
|
|
154
|
+
joinedTokens.push(tokenOrGroup);
|
|
155
|
+
}
|
|
156
|
+
} else if (tokenOrGroup[0].length > 0) {
|
|
157
|
+
joinedTokens.push(tokenOrGroup);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return joinedTokens;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// splits " \t foo bar \n" into [" \t ","foo bar"," \n"]
|
|
164
|
+
// "foo bar" -> ["","foo bar",""]
|
|
165
|
+
function splitSurroundingWhitespace(content: string) {
|
|
166
|
+
const trimmed = content.trim();
|
|
167
|
+
const before = content.slice(0, content.indexOf(trimmed));
|
|
168
|
+
const after = content.slice(content.indexOf(trimmed) + trimmed.length);
|
|
169
|
+
return [before, trimmed, after];
|
|
170
|
+
}
|
|
@@ -1,150 +1,47 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
InnerLine,
|
|
6
|
-
Pre,
|
|
7
|
-
highlight,
|
|
8
|
-
HighlightedCode,
|
|
9
|
-
} from "codehike/code"
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {Theme} from "@code-hike/lighter";
|
|
3
|
+
|
|
4
|
+
import type {CodeThemeBlockProps} from "../CodeTheme";
|
|
10
5
|
|
|
11
6
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import {withLocalStored} from "./withLocalStored";
|
|
7
|
+
Code,
|
|
8
|
+
annotations,
|
|
9
|
+
} from "../Code"
|
|
16
10
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
$mark,
|
|
21
|
-
$lineNumber
|
|
22
|
-
} from "./CodeSample.styles";
|
|
23
|
-
|
|
24
|
-
// TODO: try to use codehiki in build time / ASYNC !!! - we need rr server-components
|
|
25
|
-
// TODO: separate highlight
|
|
26
|
-
|
|
27
|
-
export interface MDXCodeSampleBlock {
|
|
28
|
-
/** This is the raw code. May include annotation comments. */
|
|
29
|
-
value: string;
|
|
30
|
-
/** The programming language. */
|
|
31
|
-
lang: string;
|
|
32
|
-
/** Metadata string (the content after the language name in a markdown codeblock). */
|
|
33
|
-
meta: string;
|
|
34
|
-
}
|
|
11
|
+
withCodeTabs
|
|
12
|
+
} from "../CodeTabs";
|
|
13
|
+
import {useCodeTheme} from "../CodeTheme";
|
|
35
14
|
|
|
36
15
|
export interface CodeSampleProps {
|
|
37
16
|
name: string;
|
|
38
17
|
description: string;
|
|
39
|
-
codeblocks:
|
|
18
|
+
codeblocks: CodeThemeBlockProps[];
|
|
40
19
|
size?: "full"
|
|
20
|
+
theme?: Theme
|
|
41
21
|
}
|
|
42
22
|
|
|
43
23
|
export function CodeSample(props: CodeSampleProps) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
async function fetchHighlight() {
|
|
48
|
-
const result = await Promise.all(
|
|
49
|
-
props.codeblocks?.map((codeblock) => highlight(codeblock, defaultTheme))
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
setHighlighted(result);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
fetchHighlight();
|
|
56
|
-
}, [props.codeblocks]);
|
|
57
|
-
|
|
58
|
-
if (highlighted.length === 0) {
|
|
59
|
-
return <div>Loading</div>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!highlighted) {
|
|
63
|
-
return <div>Loading</div>;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<TabsPrimitive.Root
|
|
68
|
-
className={$sample.host}
|
|
69
|
-
style={highlighted[0]?.style}
|
|
70
|
-
defaultValue={highlighted[0]?.meta}
|
|
71
|
-
// localStorageKey={`preferredLanguage[${name}]`}
|
|
72
|
-
>
|
|
73
|
-
<div className={$languages.host}>
|
|
74
|
-
<$Description description={props.description}/>
|
|
75
|
-
|
|
76
|
-
<TabsPrimitive.List className={$languages.list}>
|
|
77
|
-
{props.codeblocks?.map(({meta}, i) => (
|
|
78
|
-
<TabsPrimitive.Trigger value={meta!} key={i} className={$languages.button}>
|
|
79
|
-
{meta}
|
|
80
|
-
</TabsPrimitive.Trigger>
|
|
81
|
-
))}
|
|
82
|
-
</TabsPrimitive.List>
|
|
83
|
-
|
|
84
|
-
<div className={$languages.copy}>
|
|
85
|
-
{props.codeblocks?.map((codeblock, i) => (
|
|
86
|
-
<TabsPrimitive.Content value={codeblock.meta!} asChild key={i}>
|
|
87
|
-
<CodeCopy text={codeblock.value}/>
|
|
88
|
-
</TabsPrimitive.Content>
|
|
89
|
-
))}
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
{highlighted?.map((codeblock, i) => (
|
|
94
|
-
<TabsPrimitive.Content value={codeblock.meta} key={i}>
|
|
95
|
-
<Pre
|
|
96
|
-
className={`
|
|
97
|
-
${$code.host}
|
|
98
|
-
${props?.size === "full" && $code.host$$full}
|
|
99
|
-
`}
|
|
100
|
-
style={codeblock?.style || codeblock?.style}
|
|
101
|
-
code={codeblock}
|
|
102
|
-
handlers={[mark, lineNumber]}
|
|
103
|
-
/>
|
|
104
|
-
</TabsPrimitive.Content>
|
|
105
|
-
))}
|
|
106
|
-
</TabsPrimitive.Root>
|
|
107
|
-
)
|
|
24
|
+
return <Code codeblocks={props.codeblocks} theme={props.theme}>
|
|
25
|
+
<$ThemedCodeSample {...props}/>
|
|
26
|
+
</Code>
|
|
108
27
|
}
|
|
109
28
|
|
|
110
|
-
function $
|
|
111
|
-
|
|
112
|
-
<div className={$languages.description$item}>
|
|
113
|
-
{props.description}
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
}
|
|
29
|
+
function $ThemedCodeSample(props: CodeSampleProps) {
|
|
30
|
+
const {highlighted} = useCodeTheme()
|
|
117
31
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<InnerLine
|
|
124
|
-
merge={props}
|
|
125
|
-
className={$mark.line}
|
|
126
|
-
/>
|
|
127
|
-
</div>
|
|
128
|
-
)
|
|
129
|
-
},
|
|
32
|
+
return <$CodeSampleTabs
|
|
33
|
+
description={props.description}
|
|
34
|
+
highlighted={highlighted}
|
|
35
|
+
size={props.size}
|
|
36
|
+
/>
|
|
130
37
|
}
|
|
131
38
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
style={{minWidth: `${width}ch`}}
|
|
141
|
-
className={$lineNumber.host}
|
|
142
|
-
>
|
|
143
|
-
{props.lineNumber}
|
|
144
|
-
</span>
|
|
145
|
-
<InnerLine merge={props}/>
|
|
146
|
-
</>
|
|
147
|
-
)
|
|
148
|
-
},
|
|
149
|
-
}
|
|
39
|
+
const $CodeSampleTabs = withCodeTabs((props) => <Code.Pre
|
|
40
|
+
{...props}
|
|
41
|
+
handlers={[
|
|
42
|
+
annotations.mark,
|
|
43
|
+
annotations.bg,
|
|
44
|
+
annotations.lineNumbers
|
|
45
|
+
]}
|
|
46
|
+
/>)
|
|
150
47
|
|
|
@@ -7,7 +7,7 @@ export interface CodeTabsProps {
|
|
|
7
7
|
children: React.ReactNode
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
// TODO:
|
|
10
|
+
// TODO: move to CodeTabs?
|
|
11
11
|
export function withLocalStored(Component: any) {
|
|
12
12
|
return function LocalStored(props: CodeTabsProps) {
|
|
13
13
|
const [value, setValue] = useState(
|
|
@@ -87,51 +87,3 @@ export const $languages = {
|
|
|
87
87
|
`
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
export const $code = {
|
|
91
|
-
host: css`
|
|
92
|
-
max-height: 400px;
|
|
93
|
-
background: linear-gradient(45deg, rgb(247, 247, 248) 0%, rgb(247, 247, 248) 100%) !important;
|
|
94
|
-
|
|
95
|
-
margin: 0;
|
|
96
|
-
padding: 8px 16px;
|
|
97
|
-
|
|
98
|
-
border-top: 1px solid rgb(236, 236, 241);
|
|
99
|
-
border-bottom-left-radius: 10px;
|
|
100
|
-
border-bottom-right-radius: 10px;
|
|
101
|
-
|
|
102
|
-
font-size: 12px;
|
|
103
|
-
line-height: 20px;
|
|
104
|
-
white-space: pre-wrap;
|
|
105
|
-
word-break: break-all;
|
|
106
|
-
|
|
107
|
-
overflow-y: scroll;
|
|
108
|
-
`,
|
|
109
|
-
host$$full: css`
|
|
110
|
-
max-height: 100%;
|
|
111
|
-
`
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export const $mark = {
|
|
115
|
-
host: css`
|
|
116
|
-
display: flex;
|
|
117
|
-
border-left-width: 4px;
|
|
118
|
-
border-color: transparent;
|
|
119
|
-
margin: 4px 0;
|
|
120
|
-
`,
|
|
121
|
-
line: css`
|
|
122
|
-
flex: 1 1 0%;
|
|
123
|
-
`,
|
|
124
|
-
$$annotated: css`
|
|
125
|
-
border-color: #60A5FA;
|
|
126
|
-
background-color: #EEF2FF;
|
|
127
|
-
`
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export const $lineNumber = {
|
|
131
|
-
host: css`
|
|
132
|
-
margin: 0 4px;
|
|
133
|
-
//text-align: right;
|
|
134
|
-
user-select: none;
|
|
135
|
-
opacity: 0.5;
|
|
136
|
-
`
|
|
137
|
-
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, {} from "react";
|
|
2
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
3
|
+
import {
|
|
4
|
+
HighlightedCode,
|
|
5
|
+
} from "codehike/code"
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
CodeCopy,
|
|
9
|
+
} from "../CodeCopy";
|
|
10
|
+
import {
|
|
11
|
+
$sample,
|
|
12
|
+
$languages,
|
|
13
|
+
} from "./CodeTabs.styles.tsx"; // TODO: style by highlighted?
|
|
14
|
+
|
|
15
|
+
export interface CodeTabsProps {
|
|
16
|
+
description: string;
|
|
17
|
+
highlighted: HighlightedCode[]
|
|
18
|
+
size?: "full"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function withCodeTabs(PreComponent) {
|
|
22
|
+
return function CodeTabs(props: CodeTabsProps) {
|
|
23
|
+
return (
|
|
24
|
+
<TabsPrimitive.Root
|
|
25
|
+
className={$sample.host}
|
|
26
|
+
style={props.highlighted[0]?.style}
|
|
27
|
+
defaultValue={props.highlighted[0]?.meta}
|
|
28
|
+
>
|
|
29
|
+
<$LanguageTabSwitcher
|
|
30
|
+
description={props.description}
|
|
31
|
+
highlighted={props.highlighted}
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
{props.highlighted?.map((codeblock, i) => (
|
|
35
|
+
<TabsPrimitive.Content value={codeblock.meta} key={i}>
|
|
36
|
+
<PreComponent
|
|
37
|
+
style={codeblock?.style || codeblock?.style}
|
|
38
|
+
codeblock={codeblock}
|
|
39
|
+
/>
|
|
40
|
+
</TabsPrimitive.Content>
|
|
41
|
+
))}
|
|
42
|
+
</TabsPrimitive.Root>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface LanguageTabSwitcherProps {
|
|
48
|
+
description: string;
|
|
49
|
+
highlighted: HighlightedCode[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function $LanguageTabSwitcher(props: LanguageTabSwitcherProps) {
|
|
53
|
+
return <div className={$languages.host}>
|
|
54
|
+
<$Description description={props.description}/>
|
|
55
|
+
|
|
56
|
+
<TabsPrimitive.List className={$languages.list}>
|
|
57
|
+
{props.highlighted?.map(({meta}, i) => (
|
|
58
|
+
<TabsPrimitive.Trigger value={meta!} key={i} className={$languages.button}>
|
|
59
|
+
{meta}
|
|
60
|
+
</TabsPrimitive.Trigger>
|
|
61
|
+
))}
|
|
62
|
+
</TabsPrimitive.List>
|
|
63
|
+
|
|
64
|
+
<div className={$languages.copy}>
|
|
65
|
+
{props.highlighted?.map((codeblock, i) => (
|
|
66
|
+
<TabsPrimitive.Content value={codeblock.meta!} asChild key={i}>
|
|
67
|
+
<CodeCopy text={codeblock.value}/>
|
|
68
|
+
</TabsPrimitive.Content>
|
|
69
|
+
))}
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function $Description(props: { description: string }) {
|
|
75
|
+
return <div className={$languages.description}>
|
|
76
|
+
<div className={$languages.description$item}>
|
|
77
|
+
{props.description}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|