@pyreon/document-primitives 0.11.0 → 0.11.2

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.
@@ -0,0 +1,104 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import DocButton from "../primitives/DocButton"
3
+ import DocCode from "../primitives/DocCode"
4
+ import DocColumn from "../primitives/DocColumn"
5
+ import DocDivider from "../primitives/DocDivider"
6
+ import DocDocument from "../primitives/DocDocument"
7
+ import DocHeading from "../primitives/DocHeading"
8
+ import DocImage from "../primitives/DocImage"
9
+ import DocLink from "../primitives/DocLink"
10
+ import DocList from "../primitives/DocList"
11
+ import DocListItem from "../primitives/DocListItem"
12
+ import DocPage from "../primitives/DocPage"
13
+ import DocPageBreak from "../primitives/DocPageBreak"
14
+ import DocQuote from "../primitives/DocQuote"
15
+ import DocRow from "../primitives/DocRow"
16
+ import DocSection from "../primitives/DocSection"
17
+ import DocSpacer from "../primitives/DocSpacer"
18
+ import DocTable from "../primitives/DocTable"
19
+ import DocText from "../primitives/DocText"
20
+
21
+ describe("document primitives _documentType markers", () => {
22
+ const components = [
23
+ { name: "DocDocument", component: DocDocument, type: "document" },
24
+ { name: "DocPage", component: DocPage, type: "page" },
25
+ { name: "DocSection", component: DocSection, type: "section" },
26
+ { name: "DocRow", component: DocRow, type: "row" },
27
+ { name: "DocColumn", component: DocColumn, type: "column" },
28
+ { name: "DocHeading", component: DocHeading, type: "heading" },
29
+ { name: "DocText", component: DocText, type: "text" },
30
+ { name: "DocLink", component: DocLink, type: "link" },
31
+ { name: "DocImage", component: DocImage, type: "image" },
32
+ { name: "DocTable", component: DocTable, type: "table" },
33
+ { name: "DocList", component: DocList, type: "list" },
34
+ { name: "DocListItem", component: DocListItem, type: "list-item" },
35
+ { name: "DocCode", component: DocCode, type: "code" },
36
+ { name: "DocDivider", component: DocDivider, type: "divider" },
37
+ { name: "DocSpacer", component: DocSpacer, type: "spacer" },
38
+ { name: "DocButton", component: DocButton, type: "button" },
39
+ { name: "DocQuote", component: DocQuote, type: "quote" },
40
+ { name: "DocPageBreak", component: DocPageBreak, type: "page-break" },
41
+ ]
42
+
43
+ for (const { name, component, type } of components) {
44
+ it(`${name} has _documentType = "${type}"`, () => {
45
+ expect((component as any)._documentType).toBe(type)
46
+ })
47
+ }
48
+
49
+ it("all 18 node types are covered", () => {
50
+ expect(components).toHaveLength(18)
51
+ const types = new Set(components.map((c) => c.type))
52
+ expect(types.size).toBe(18)
53
+ })
54
+ })
55
+
56
+ describe("document primitives have displayName", () => {
57
+ it("DocHeading", () => {
58
+ expect(DocHeading.displayName).toBe("DocHeading")
59
+ })
60
+
61
+ it("DocText", () => {
62
+ expect(DocText.displayName).toBe("DocText")
63
+ })
64
+
65
+ it("DocSection", () => {
66
+ expect(DocSection.displayName).toBe("DocSection")
67
+ })
68
+
69
+ it("DocTable", () => {
70
+ expect(DocTable.displayName).toBe("DocTable")
71
+ })
72
+ })
73
+
74
+ describe("document primitives are callable", () => {
75
+ it("DocHeading is a function", () => {
76
+ expect(typeof DocHeading).toBe("function")
77
+ })
78
+
79
+ it("DocText is a function", () => {
80
+ expect(typeof DocText).toBe("function")
81
+ })
82
+
83
+ it("DocTable is a function", () => {
84
+ expect(typeof DocTable).toBe("function")
85
+ })
86
+
87
+ it("DocDocument is a function", () => {
88
+ expect(typeof DocDocument).toBe("function")
89
+ })
90
+ })
91
+
92
+ describe("document primitives IS_ROCKETSTYLE", () => {
93
+ it("DocHeading is a rocketstyle component", () => {
94
+ expect((DocHeading as any).IS_ROCKETSTYLE).toBe(true)
95
+ })
96
+
97
+ it("DocText is a rocketstyle component", () => {
98
+ expect((DocText as any).IS_ROCKETSTYLE).toBe(true)
99
+ })
100
+
101
+ it("DocSection is a rocketstyle component", () => {
102
+ expect((DocSection as any).IS_ROCKETSTYLE).toBe(true)
103
+ })
104
+ })
@@ -0,0 +1,92 @@
1
+ import type { DocumentMarker } from "@pyreon/connector-document"
2
+ import { describe, expect, it } from "vitest"
3
+ import { createDocumentExport } from "../useDocumentExport"
4
+
5
+ // Mock VNode
6
+ const vnode = (
7
+ type: string | ((...args: any[]) => any),
8
+ props: Record<string, any> = {},
9
+ children: unknown[] = [],
10
+ ) => ({ type, props, children })
11
+
12
+ // Mock document-marked component
13
+ const docComponent = (docType: string) => {
14
+ const fn = (props: any) => vnode("div", props, props.children ? [props.children] : [])
15
+ ;(fn as any)._documentType = docType
16
+ return fn as ((...args: any[]) => any) & DocumentMarker
17
+ }
18
+
19
+ const DocDocument = docComponent("document")
20
+ const DocHeading = docComponent("heading")
21
+ const DocText = docComponent("text")
22
+
23
+ describe("createDocumentExport", () => {
24
+ it("extracts a document tree from template function", () => {
25
+ const doc = createDocumentExport(() =>
26
+ vnode(DocDocument, { _documentProps: { title: "Test" } }, [
27
+ vnode(
28
+ DocHeading,
29
+ {
30
+ $rocketstyle: { fontSize: 24, fontWeight: "bold" },
31
+ _documentProps: { level: 1 },
32
+ },
33
+ ["Hello"],
34
+ ),
35
+ vnode(
36
+ DocText,
37
+ {
38
+ $rocketstyle: { fontSize: 14, color: "#333" },
39
+ },
40
+ ["World"],
41
+ ),
42
+ ]),
43
+ )
44
+
45
+ const tree = doc.getDocNode()
46
+
47
+ expect(tree.type).toBe("document")
48
+ expect(tree.props.title).toBe("Test")
49
+ expect(tree.children).toHaveLength(2)
50
+
51
+ const heading = tree.children[0] as any
52
+ expect(heading.type).toBe("heading")
53
+ expect(heading.props.level).toBe(1)
54
+ expect(heading.styles?.fontSize).toBe(24)
55
+ expect(heading.children).toEqual(["Hello"])
56
+
57
+ const text = tree.children[1] as any
58
+ expect(text.type).toBe("text")
59
+ expect(text.styles?.fontSize).toBe(14)
60
+ expect(text.styles?.color).toBe("#333")
61
+ })
62
+
63
+ it("can be called multiple times", () => {
64
+ const doc = createDocumentExport(() =>
65
+ vnode(DocText, { $rocketstyle: { fontSize: 14 } }, ["Static"]),
66
+ )
67
+
68
+ const tree1 = doc.getDocNode()
69
+ const tree2 = doc.getDocNode()
70
+
71
+ expect(tree1.type).toBe("text")
72
+ expect(tree2.type).toBe("text")
73
+ })
74
+
75
+ it("respects includeStyles option", () => {
76
+ const doc = createDocumentExport(
77
+ () => vnode(DocHeading, { $rocketstyle: { fontSize: 24 } }, ["Hello"]),
78
+ { includeStyles: false },
79
+ )
80
+
81
+ const tree = doc.getDocNode()
82
+ expect(tree.styles).toBeUndefined()
83
+ })
84
+
85
+ it("handles empty template", () => {
86
+ const doc = createDocumentExport(() => null)
87
+
88
+ const tree = doc.getDocNode()
89
+ expect(tree.type).toBe("document")
90
+ expect(tree.children).toEqual([])
91
+ })
92
+ })
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ // Re-export connector utilities
2
+
3
+ export type {
4
+ DocChild,
5
+ DocNode,
6
+ ExtractOptions,
7
+ NodeType,
8
+ ResolvedStyles,
9
+ } from "@pyreon/connector-document"
10
+ export { extractDocumentTree, resolveStyles } from "@pyreon/connector-document"
11
+ // Preview
12
+ export { default as DocumentPreview } from "./DocumentPreview"
13
+ // Primitives
14
+ export { default as DocButton } from "./primitives/DocButton"
15
+ export { default as DocCode } from "./primitives/DocCode"
16
+ export { default as DocColumn } from "./primitives/DocColumn"
17
+ export { default as DocDivider } from "./primitives/DocDivider"
18
+ export { default as DocDocument } from "./primitives/DocDocument"
19
+ export { default as DocHeading } from "./primitives/DocHeading"
20
+ export { default as DocImage } from "./primitives/DocImage"
21
+ export { default as DocLink } from "./primitives/DocLink"
22
+ export { default as DocList } from "./primitives/DocList"
23
+ export { default as DocListItem } from "./primitives/DocListItem"
24
+ export { default as DocPage } from "./primitives/DocPage"
25
+ export { default as DocPageBreak } from "./primitives/DocPageBreak"
26
+ export { default as DocQuote } from "./primitives/DocQuote"
27
+ export { default as DocRow } from "./primitives/DocRow"
28
+ export { default as DocSection } from "./primitives/DocSection"
29
+ export { default as DocSpacer } from "./primitives/DocSpacer"
30
+ export { default as DocTable } from "./primitives/DocTable"
31
+ export { default as DocText } from "./primitives/DocText"
32
+ // Theme
33
+ export type { DocumentTheme } from "./theme"
34
+ export { documentTheme } from "./theme"
35
+ // Export helper
36
+ export type { DocumentExport, DocumentExportOptions } from "./useDocumentExport"
37
+ export { createDocumentExport } from "./useDocumentExport"
@@ -0,0 +1,37 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocButton = rocketstyle({
5
+ dimensions: {
6
+ variants: "variant",
7
+ },
8
+ useBooleans: true,
9
+ })({ name: "DocButton", component: Text })
10
+ .theme({
11
+ fontSize: 14,
12
+ fontWeight: "bold",
13
+ padding: "10px 24px",
14
+ borderRadius: 4,
15
+ textAlign: "center",
16
+ textDecoration: "none",
17
+ })
18
+ .variants({
19
+ primary: {
20
+ backgroundColor: "#4f46e5",
21
+ color: "#ffffff",
22
+ },
23
+ secondary: {
24
+ backgroundColor: "#ffffff",
25
+ color: "#4f46e5",
26
+ borderWidth: 1,
27
+ borderColor: "#4f46e5",
28
+ borderStyle: "solid",
29
+ },
30
+ })
31
+ .statics({ _documentType: "button" as const })
32
+ .attrs<{ href?: string; tag: string; _documentProps: { href: string } }>((props) => ({
33
+ tag: "a",
34
+ _documentProps: { href: props.href ?? "#" },
35
+ }))
36
+
37
+ export default DocButton
@@ -0,0 +1,18 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocCode = rocketstyle()({ name: "DocCode", component: Text })
5
+ .theme({
6
+ fontFamily: "ui-monospace, monospace",
7
+ fontSize: 13,
8
+ backgroundColor: "#f5f5f5",
9
+ padding: "8px 12px",
10
+ borderRadius: 4,
11
+ })
12
+ .statics({ _documentType: "code" as const })
13
+ .attrs<{ language?: string; tag: string; _documentProps: Record<string, unknown> }>((props) => ({
14
+ tag: "pre",
15
+ _documentProps: props.language ? { language: props.language } : {},
16
+ }))
17
+
18
+ export default DocCode
@@ -0,0 +1,13 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocColumn = rocketstyle()({ name: "DocColumn", component: Element })
5
+ .statics({ _documentType: "column" as const })
6
+ .attrs<{ width?: number | string; tag: string; _documentProps: Record<string, unknown> }>(
7
+ (props) => ({
8
+ tag: "div",
9
+ _documentProps: props.width != null ? { width: props.width } : {},
10
+ }),
11
+ )
12
+
13
+ export default DocColumn
@@ -0,0 +1,23 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocDivider = rocketstyle()({ name: "DocDivider", component: Element })
5
+ .theme({
6
+ borderColor: "#dddddd",
7
+ borderWidth: 1,
8
+ })
9
+ .statics({ _documentType: "divider" as const })
10
+ .attrs<{
11
+ color?: string
12
+ thickness?: number
13
+ tag: string
14
+ _documentProps: Record<string, unknown>
15
+ }>((props) => ({
16
+ tag: "hr",
17
+ _documentProps: {
18
+ ...(props.color ? { color: props.color } : {}),
19
+ ...(props.thickness ? { thickness: props.thickness } : {}),
20
+ },
21
+ }))
22
+
23
+ export default DocDivider
@@ -0,0 +1,21 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocDocument = rocketstyle()({ name: "DocDocument", component: Element })
5
+ .statics({ _documentType: "document" as const })
6
+ .attrs<{
7
+ title?: string
8
+ author?: string
9
+ subject?: string
10
+ tag: string
11
+ _documentProps: Record<string, unknown>
12
+ }>((props) => ({
13
+ tag: "div",
14
+ _documentProps: {
15
+ ...(props.title ? { title: props.title } : {}),
16
+ ...(props.author ? { author: props.author } : {}),
17
+ ...(props.subject ? { subject: props.subject } : {}),
18
+ },
19
+ }))
20
+
21
+ export default DocDocument
@@ -0,0 +1,33 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocHeading = rocketstyle({
5
+ dimensions: {
6
+ levels: "level",
7
+ },
8
+ useBooleans: true,
9
+ })({ name: "DocHeading", component: Text })
10
+ .theme({
11
+ fontWeight: "bold",
12
+ color: "#1a1a2e",
13
+ marginBottom: 12,
14
+ })
15
+ .levels({
16
+ h1: { fontSize: 32, lineHeight: 1.2 },
17
+ h2: { fontSize: 24, lineHeight: 1.3 },
18
+ h3: { fontSize: 20, lineHeight: 1.4 },
19
+ h4: { fontSize: 18, lineHeight: 1.4 },
20
+ h5: { fontSize: 16, lineHeight: 1.5 },
21
+ h6: { fontSize: 14, lineHeight: 1.5 },
22
+ })
23
+ .statics({ _documentType: "heading" as const })
24
+ .attrs<{ level?: string; tag: string; _documentProps: { level: number } }>((props) => {
25
+ const lvl = props.level ?? "h1"
26
+ const num = Number.parseInt(String(lvl).replace("h", ""), 10) || 1
27
+ return {
28
+ tag: lvl,
29
+ _documentProps: { level: num },
30
+ }
31
+ })
32
+
33
+ export default DocHeading
@@ -0,0 +1,25 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocImage = rocketstyle()({ name: "DocImage", component: Element })
5
+ .statics({ _documentType: "image" as const })
6
+ .attrs<{
7
+ src?: string
8
+ alt?: string
9
+ width?: number | string
10
+ height?: number | string
11
+ caption?: string
12
+ tag: string
13
+ _documentProps: Record<string, unknown>
14
+ }>((props) => ({
15
+ tag: "img",
16
+ _documentProps: {
17
+ src: props.src ?? "",
18
+ ...(props.alt ? { alt: props.alt } : {}),
19
+ ...(props.width ? { width: props.width } : {}),
20
+ ...(props.height ? { height: props.height } : {}),
21
+ ...(props.caption ? { caption: props.caption } : {}),
22
+ },
23
+ }))
24
+
25
+ export default DocImage
@@ -0,0 +1,15 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocLink = rocketstyle()({ name: "DocLink", component: Text })
5
+ .theme({
6
+ color: "#4f46e5",
7
+ textDecoration: "underline",
8
+ })
9
+ .statics({ _documentType: "link" as const })
10
+ .attrs<{ href?: string; tag: string; _documentProps: { href: string } }>((props) => ({
11
+ tag: "a",
12
+ _documentProps: { href: props.href ?? "#" },
13
+ }))
14
+
15
+ export default DocLink
@@ -0,0 +1,15 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocList = rocketstyle()({ name: "DocList", component: Element })
5
+ .theme({
6
+ marginBottom: 8,
7
+ paddingLeft: 20,
8
+ })
9
+ .statics({ _documentType: "list" as const })
10
+ .attrs<{ ordered?: boolean; tag: string; _documentProps: Record<string, unknown> }>((props) => ({
11
+ tag: props.ordered ? "ol" : "ul",
12
+ _documentProps: props.ordered ? { ordered: props.ordered } : {},
13
+ }))
14
+
15
+ export default DocList
@@ -0,0 +1,15 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocListItem = rocketstyle()({ name: "DocListItem", component: Text })
5
+ .theme({
6
+ fontSize: 14,
7
+ lineHeight: 1.5,
8
+ })
9
+ .statics({ _documentType: "list-item" as const })
10
+ .attrs<{ tag: string; _documentProps: Record<string, unknown> }>((_props) => ({
11
+ tag: "li",
12
+ _documentProps: {},
13
+ }))
14
+
15
+ export default DocListItem
@@ -0,0 +1,23 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocPage = rocketstyle()({ name: "DocPage", component: Element })
5
+ .theme({
6
+ backgroundColor: "#ffffff",
7
+ padding: "25mm",
8
+ })
9
+ .statics({ _documentType: "page" as const })
10
+ .attrs<{
11
+ size?: string
12
+ orientation?: string
13
+ tag: string
14
+ _documentProps: Record<string, unknown>
15
+ }>((props) => ({
16
+ tag: "div",
17
+ _documentProps: {
18
+ ...(props.size ? { size: props.size } : {}),
19
+ ...(props.orientation ? { orientation: props.orientation } : {}),
20
+ },
21
+ }))
22
+
23
+ export default DocPage
@@ -0,0 +1,11 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocPageBreak = rocketstyle()({ name: "DocPageBreak", component: Element })
5
+ .statics({ _documentType: "page-break" as const })
6
+ .attrs<{ tag: string; _documentProps: Record<string, unknown> }>((_props) => ({
7
+ tag: "div",
8
+ _documentProps: {},
9
+ }))
10
+
11
+ export default DocPageBreak
@@ -0,0 +1,19 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocQuote = rocketstyle()({ name: "DocQuote", component: Element })
5
+ .theme({
6
+ borderColor: "#4f46e5",
7
+ padding: "8px 16px",
8
+ fontStyle: "italic",
9
+ color: "#666666",
10
+ })
11
+ .statics({ _documentType: "quote" as const })
12
+ .attrs<{ borderColor?: string; tag: string; _documentProps: Record<string, unknown> }>(
13
+ (props) => ({
14
+ tag: "blockquote",
15
+ _documentProps: props.borderColor ? { borderColor: props.borderColor } : {},
16
+ }),
17
+ )
18
+
19
+ export default DocQuote
@@ -0,0 +1,14 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocRow = rocketstyle()({ name: "DocRow", component: Element })
5
+ .theme({
6
+ direction: "row",
7
+ })
8
+ .statics({ _documentType: "row" as const })
9
+ .attrs<{ tag: string; _documentProps: Record<string, unknown> }>((_props) => ({
10
+ tag: "div",
11
+ _documentProps: {},
12
+ }))
13
+
14
+ export default DocRow
@@ -0,0 +1,23 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocSection = rocketstyle({
5
+ dimensions: {
6
+ directions: "direction",
7
+ },
8
+ useBooleans: false,
9
+ })({ name: "DocSection", component: Element })
10
+ .theme({
11
+ padding: 0,
12
+ })
13
+ .directions({
14
+ column: {},
15
+ row: { direction: "row" },
16
+ })
17
+ .statics({ _documentType: "section" as const })
18
+ .attrs<{ direction?: string; tag: string; _documentProps: { direction: string } }>((props) => ({
19
+ tag: "div",
20
+ _documentProps: { direction: props.direction ?? "column" },
21
+ }))
22
+
23
+ export default DocSection
@@ -0,0 +1,11 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocSpacer = rocketstyle()({ name: "DocSpacer", component: Element })
5
+ .statics({ _documentType: "spacer" as const })
6
+ .attrs<{ height?: number; tag: string; _documentProps: { height: number } }>((props) => ({
7
+ tag: "div",
8
+ _documentProps: { height: props.height ?? 16 },
9
+ }))
10
+
11
+ export default DocSpacer
@@ -0,0 +1,36 @@
1
+ import { Element } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocTable = rocketstyle({
5
+ dimensions: {
6
+ variants: "variant",
7
+ },
8
+ useBooleans: true,
9
+ })({ name: "DocTable", component: Element })
10
+ .theme({
11
+ fontSize: 14,
12
+ borderColor: "#dddddd",
13
+ })
14
+ .statics({ _documentType: "table" as const })
15
+ .attrs<{
16
+ columns?: unknown[]
17
+ rows?: unknown[]
18
+ headerStyle?: Record<string, unknown>
19
+ striped?: boolean
20
+ bordered?: boolean
21
+ caption?: string
22
+ tag: string
23
+ _documentProps: Record<string, unknown>
24
+ }>((props) => ({
25
+ tag: "table",
26
+ _documentProps: {
27
+ columns: props.columns ?? [],
28
+ rows: props.rows ?? [],
29
+ ...(props.headerStyle ? { headerStyle: props.headerStyle } : {}),
30
+ ...(props.striped ? { striped: props.striped } : {}),
31
+ ...(props.bordered ? { bordered: props.bordered } : {}),
32
+ ...(props.caption ? { caption: props.caption } : {}),
33
+ },
34
+ }))
35
+
36
+ export default DocTable
@@ -0,0 +1,35 @@
1
+ import { Text } from "@pyreon/elements"
2
+ import rocketstyle from "@pyreon/rocketstyle"
3
+
4
+ const DocText = rocketstyle({
5
+ dimensions: {
6
+ variants: "variant",
7
+ weights: "weight",
8
+ },
9
+ useBooleans: true,
10
+ })({ name: "DocText", component: Text })
11
+ .theme({
12
+ color: "#333333",
13
+ lineHeight: 1.5,
14
+ marginBottom: 8,
15
+ })
16
+ .variants({
17
+ body: { fontSize: 14 },
18
+ caption: { fontSize: 12, color: "#666666" },
19
+ label: { fontSize: 11, fontWeight: "bold" },
20
+ })
21
+ .weights({
22
+ normal: { fontWeight: "normal" },
23
+ bold: { fontWeight: "bold" },
24
+ })
25
+ .statics({ _documentType: "text" as const })
26
+ // .attrs(
27
+ // (props: any) =>
28
+ // ({
29
+ // tag: "p",
30
+ .attrs<{ tag: string; _documentProps: Record<string, unknown> }>((_props) => ({
31
+ tag: "p",
32
+ _documentProps: {},
33
+ }))
34
+
35
+ export default DocText