@surrealdb/ui 1.2.11 → 1.2.13
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/.claude/launch.json +17 -0
- package/.oxfmtrc.json +27 -0
- package/.oxlintrc.json +23 -0
- package/.zed/settings.json +34 -34
- package/AGENTS.md +21 -19
- package/README.md +15 -10
- package/dist/assets/245b1ccaa4927818.svg +3 -0
- package/dist/assets/333e1fe6e67ca4a2.svg +10 -0
- package/dist/assets/4b0e10c655814886.svg +21 -0
- package/dist/assets/9932da008ea5dd32.svg +3 -0
- package/dist/assets/a372168d5789daa2.svg +4 -0
- package/dist/assets/b140e44ee4ae7e35.svg +5 -0
- package/dist/assets/e028075817d928e4.svg +3 -0
- package/dist/assets/ee1065ad5a8f7f14.svg +6 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.ts +579 -1
- package/dist/ui.js +11553 -8988
- package/dist/ui.js.map +1 -1
- package/doc/code-style.md +264 -0
- package/doc/stacker-plan.md +219 -0
- package/package.json +119 -115
- package/res/_mixins.scss +15 -11
- package/tests/_setup/e2e-helpers.tsx +85 -85
- package/tests/_setup/portable-stories.ts +11 -10
- package/tests/e2e/MarkdownEditor/content-blocks.test.tsx +140 -139
- package/tests/e2e/MarkdownEditor/edits.test.tsx +101 -100
- package/tests/e2e/MarkdownEditor/heading-fold.test.tsx +35 -34
- package/tests/e2e/MarkdownEditor/hybrid-widgets.test.tsx +178 -177
- package/tests/e2e/MarkdownEditor/image-on-image.test.tsx +50 -49
- package/tests/e2e/MarkdownEditor/jsx-block-content.test.tsx +195 -194
- package/tests/e2e/MarkdownEditor/jsx-highlight.test.tsx +47 -46
- package/tests/e2e/MarkdownEditor/jsx-inline-badges.test.tsx +35 -34
- package/tests/e2e/MarkdownEditor/jsx-inline-click.test.tsx +39 -38
- package/tests/e2e/MarkdownEditor/jsx-selection.test.tsx +28 -27
- package/tests/e2e/MarkdownEditor/link-placeholder.test.tsx +49 -48
- package/tests/e2e/MarkdownEditor/media-align.test.tsx +40 -39
- package/tests/e2e/MarkdownEditor/media-edit.test.tsx +49 -48
- package/tests/e2e/MarkdownEditor/media-sizing.test.tsx +108 -107
- package/tests/e2e/MarkdownEditor/modes.test.tsx +79 -78
- package/tests/e2e/MarkdownEditor/onimage-parity.test.tsx +29 -28
- package/tests/e2e/MarkdownEditor/regressions.test.tsx +194 -193
- package/tests/e2e/MarkdownEditor/slash-commands.test.tsx +81 -80
- package/tests/e2e/MarkdownEditor/table-click.test.tsx +36 -35
- package/tests/e2e/MarkdownEditor/table-controls.test.tsx +44 -43
- package/tests/e2e/MarkdownEditor/table-format.test.tsx +28 -27
- package/tests/e2e/MarkdownEditor/undo-redo.test.tsx +22 -21
- package/tests/e2e/MarkdownViewer/parity.test.tsx +144 -143
- package/tests/e2e/MarkdownViewer/render.test.tsx +20 -19
- package/tests/e2e/Stacker/stacker.test.tsx +304 -0
- package/tests/unit/Editor/helpers.test.ts +26 -26
- package/tests/unit/MarkdownConformance/error-isolation.test.tsx +26 -25
- package/tests/unit/MarkdownConformance/indentation.test.tsx +20 -19
- package/tests/unit/MarkdownConformance/inline-code-fuzz.test.tsx +255 -0
- package/tests/unit/MarkdownConformance/jsx-attributes.test.tsx +39 -38
- package/tests/unit/MarkdownConformance/jsx-fuzz.test.tsx +122 -122
- package/tests/unit/MarkdownConformance/links.test.tsx +78 -54
- package/tests/unit/MarkdownConformance/render-helpers.tsx +60 -60
- package/tests/unit/MarkdownEditor/code-info.test.ts +58 -58
- package/tests/unit/MarkdownEditor/decorations.test.ts +423 -421
- package/tests/unit/MarkdownEditor/editor-ready.test.ts +22 -22
- package/tests/unit/MarkdownEditor/html-descriptors.test.ts +70 -70
- package/tests/unit/MarkdownEditor/indented-fence.test.ts +80 -80
- package/tests/unit/MarkdownEditor/jsx-attr-scan.test.ts +87 -87
- package/tests/unit/MarkdownEditor/jsx-block-widget.test.ts +51 -51
- package/tests/unit/MarkdownEditor/jsx-tag-grammar.test.ts +63 -63
- package/tests/unit/MarkdownEditor/list-indent.test.ts +67 -67
- package/tests/unit/MarkdownEditor/slash-commands.test.ts +150 -150
- package/tests/unit/MarkdownEditor/table-format.test.ts +67 -67
- package/tests/unit/MarkdownEditor/table.test.ts +96 -96
- package/tests/unit/MarkdownEditor/triggers.test.ts +167 -167
- package/tests/unit/MarkdownEditor/widget-store.test.ts +90 -90
- package/tests/unit/MarkdownViewer/callout.test.tsx +42 -42
- package/tests/unit/MarkdownViewer/code-highlight.test.tsx +41 -41
- package/tests/unit/MarkdownViewer/code-title.test.tsx +45 -45
- package/tests/unit/MarkdownViewer/features.test.tsx +129 -129
- package/tests/unit/MarkdownViewer/headings.test.tsx +28 -28
- package/tests/unit/MarkdownViewer/indented-jsx-children.test.tsx +53 -53
- package/tests/unit/MarkdownViewer/jsx-block-nesting.test.tsx +137 -137
- package/tests/unit/MarkdownViewer/jsx.test.tsx +188 -188
- package/tests/unit/MarkdownViewer/list-bullets.test.tsx +31 -31
- package/tests/unit/MarkdownViewer/list-code.test.tsx +45 -45
- package/tests/unit/MarkdownViewer/preserve-newlines.test.tsx +109 -109
- package/tests/unit/MarkdownViewer/read-time.test.ts +13 -13
- package/tests/unit/MarkdownViewer/renderers.test.tsx +75 -75
- package/tests/unit/MarkdownViewer/runnable.test.tsx +51 -51
- package/tests/unit/MarkdownViewer/ssr.test.tsx +56 -55
- package/tests/unit/MarkdownViewer/syntax-highlighting.test.tsx +43 -42
- package/tests/unit/MarkdownViewer/tabs-fenced-code.test.tsx +120 -120
- package/tests/unit/MarkdownViewer/tabs.test.tsx +83 -82
- package/tests/unit/Stacker/drag.test.ts +21 -0
- package/tests/unit/Stacker/helpers.test.ts +105 -0
- package/tests/unit/Stacker/reducer.test.ts +107 -0
- package/tools/duplicate-vector-mappings.json +141 -141
- package/tools/glass-export-overrides.json +6 -6
- package/tools/icon-parser.ts +41 -40
- package/tools/integration-gradient-exports.json +55 -55
- package/tools/picto-compare.ts +32 -32
- package/tools/picto-merge-urls.ts +19 -19
- package/tools/picto-sync.ts +543 -543
- package/tools/picto-verify-gradients.ts +50 -50
- package/tools/vector-export-nodes.json +975 -975
|
@@ -7,33 +7,33 @@ import { renderToString } from "react-dom/server";
|
|
|
7
7
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
8
8
|
|
|
9
9
|
beforeAll(() => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
|
|
11
|
+
Object.defineProperty(window, "matchMedia", {
|
|
12
|
+
writable: true,
|
|
13
|
+
value: (query: string) => ({
|
|
14
|
+
matches: false,
|
|
15
|
+
media: query,
|
|
16
|
+
onchange: null,
|
|
17
|
+
addListener: () => {},
|
|
18
|
+
removeListener: () => {},
|
|
19
|
+
addEventListener: () => {},
|
|
20
|
+
removeEventListener: () => {},
|
|
21
|
+
dispatchEvent: () => false,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
function shell(node: ReactElement): string {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
return renderToString(
|
|
29
|
+
<MantineProvider
|
|
30
|
+
theme={MANTINE_THEME}
|
|
31
|
+
cssVariablesResolver={v8CssVariablesResolver}
|
|
32
|
+
forceColorScheme="dark"
|
|
33
|
+
>
|
|
34
|
+
{node}
|
|
35
|
+
</MantineProvider>,
|
|
36
|
+
);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -42,40 +42,40 @@ function shell(node: ReactElement): string {
|
|
|
42
42
|
* `renderToString` assert the full parsed structure of all tab bodies.
|
|
43
43
|
*/
|
|
44
44
|
function EagerGroup({ children }: { children?: ReactNode }): ReactElement {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
const items = Children.toArray(children).filter(isValidElement);
|
|
46
|
+
return (
|
|
47
|
+
<div data-eager-group>
|
|
48
|
+
<div
|
|
49
|
+
data-labels={items.map((el) => (el.props as { label?: string }).label).join("|")}
|
|
50
|
+
/>
|
|
51
|
+
{items.map((el, i) => (
|
|
52
|
+
<section
|
|
53
|
+
data-panel={i}
|
|
54
|
+
key={(el.props as { label?: string }).label ?? i}
|
|
55
|
+
>
|
|
56
|
+
{(el.props as { children?: ReactNode }).children}
|
|
57
|
+
</section>
|
|
58
|
+
))}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function EagerItem({ children }: { children?: ReactNode }): ReactElement {
|
|
64
|
-
|
|
64
|
+
return <>{children}</>;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
const EAGER_COMPONENTS: MarkdownComponents = {
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
Tabs: { component: EagerGroup, block: true },
|
|
69
|
+
TabItem: { component: EagerItem, block: true },
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
function stripTags(html: string): string {
|
|
73
|
-
|
|
73
|
+
return html.replace(/<[^>]+>/g, "");
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
describe("MarkdownViewer / JSX block nesting", () => {
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
it("pairs a Tabs block into exactly its authored TabItems (no synthetic tabs)", () => {
|
|
78
|
+
const content = `<Tabs syncKey="demo">
|
|
79
79
|
<TabItem label="Create an instance">
|
|
80
80
|
\tSurrealDB Cloud allows you to connect.
|
|
81
81
|
|
|
@@ -89,24 +89,24 @@ describe("MarkdownViewer / JSX block nesting", () => {
|
|
|
89
89
|
\tSince SurrealDB Cloud is closely integrated.
|
|
90
90
|
</TabItem>
|
|
91
91
|
</Tabs>`;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
92
|
+
const html = shell(<MarkdownViewer content={content} />);
|
|
93
|
+
|
|
94
|
+
// Exactly two tab buttons with the authored labels — no paragraphs
|
|
95
|
+
// leaking out as extra "Tab N" children.
|
|
96
|
+
const tabButtons = html.match(/mantine-Tabs-tab\b/g) ?? [];
|
|
97
|
+
expect(tabButtons).toHaveLength(2);
|
|
98
|
+
const labels = [...html.matchAll(/mantine-Tabs-tabLabel">([^<]*)</g)].map((m) => m[1]);
|
|
99
|
+
expect(labels).toEqual(["Create an instance", "Connect to your instance"]);
|
|
100
|
+
|
|
101
|
+
// The active tab renders its full multi-paragraph markdown body.
|
|
102
|
+
const text = stripTags(html);
|
|
103
|
+
expect(text).toContain("SurrealDB Cloud allows you to connect.");
|
|
104
|
+
expect(text).toContain("1. Create Instance.");
|
|
105
|
+
expect(text).toContain("When creating an instance");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("renders full multi-paragraph markdown for every TabItem (via eager group)", () => {
|
|
109
|
+
const content = `<Tabs syncKey="demo">
|
|
110
110
|
<TabItem label="Create an instance">
|
|
111
111
|
\tSurrealDB Cloud allows you to connect.
|
|
112
112
|
|
|
@@ -122,30 +122,30 @@ describe("MarkdownViewer / JSX block nesting", () => {
|
|
|
122
122
|
\tSince SurrealDB Cloud is closely integrated.
|
|
123
123
|
</TabItem>
|
|
124
124
|
</Tabs>`;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
125
|
+
const html = shell(
|
|
126
|
+
<MarkdownViewer
|
|
127
|
+
content={content}
|
|
128
|
+
components={EAGER_COMPONENTS}
|
|
129
|
+
/>,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(html).toContain('data-labels="Create an instance|Connect to your instance"');
|
|
133
|
+
expect(html).not.toContain("Tab 2");
|
|
134
|
+
|
|
135
|
+
// Both panels rendered, in order, with all their paragraphs.
|
|
136
|
+
const text = stripTags(html);
|
|
137
|
+
expect(text).toContain("SurrealDB Cloud allows you to connect.");
|
|
138
|
+
expect(text).toContain("1. Create Instance.");
|
|
139
|
+
expect(text).toContain("When creating an instance");
|
|
140
|
+
expect(text).toContain("You can connect via Surrealist");
|
|
141
|
+
expect(text).toContain("closely integrated");
|
|
142
|
+
// Links inside both tabs survive.
|
|
143
|
+
expect(html).toContain('href="/docs/x"');
|
|
144
|
+
expect(html).toContain('href="/docs/y"');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("renders a single-paragraph Tabs block (regression)", () => {
|
|
148
|
+
const content = `<Tabs syncKey="s">
|
|
149
149
|
<TabItem label="First">
|
|
150
150
|
Alpha content.
|
|
151
151
|
</TabItem>
|
|
@@ -153,21 +153,21 @@ Alpha content.
|
|
|
153
153
|
Beta content.
|
|
154
154
|
</TabItem>
|
|
155
155
|
</Tabs>`;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
156
|
+
const html = shell(
|
|
157
|
+
<MarkdownViewer
|
|
158
|
+
content={content}
|
|
159
|
+
components={EAGER_COMPONENTS}
|
|
160
|
+
/>,
|
|
161
|
+
);
|
|
162
|
+
expect(html).toContain('data-labels="First|Second"');
|
|
163
|
+
expect(html).not.toContain("Tab 2");
|
|
164
|
+
const text = stripTags(html);
|
|
165
|
+
expect(text).toContain("Alpha content.");
|
|
166
|
+
expect(text).toContain("Beta content.");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("renders block content around a Tabs block", () => {
|
|
170
|
+
const content = `# Heading
|
|
171
171
|
|
|
172
172
|
Intro paragraph.
|
|
173
173
|
|
|
@@ -181,23 +181,23 @@ Second tab.
|
|
|
181
181
|
</Tabs>
|
|
182
182
|
|
|
183
183
|
Outro paragraph.`;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
184
|
+
const html = shell(
|
|
185
|
+
<MarkdownViewer
|
|
186
|
+
content={content}
|
|
187
|
+
components={EAGER_COMPONENTS}
|
|
188
|
+
/>,
|
|
189
|
+
);
|
|
190
|
+
const text = stripTags(html);
|
|
191
|
+
expect(text).toContain("Heading");
|
|
192
|
+
expect(text).toContain("Intro paragraph.");
|
|
193
|
+
expect(text).toContain("Outro paragraph.");
|
|
194
|
+
expect(html).toContain('data-labels="One|Two"');
|
|
195
|
+
expect(text).toContain("First tab.");
|
|
196
|
+
expect(text).toContain("Second tab.");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("renders nested block components (Tabs inside a TabItem)", () => {
|
|
200
|
+
const content = `<Tabs syncKey="outer">
|
|
201
201
|
<TabItem label="Outer A">
|
|
202
202
|
Outer A body.
|
|
203
203
|
|
|
@@ -214,21 +214,21 @@ Inner Y body.
|
|
|
214
214
|
Outer B body.
|
|
215
215
|
</TabItem>
|
|
216
216
|
</Tabs>`;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
217
|
+
const html = shell(
|
|
218
|
+
<MarkdownViewer
|
|
219
|
+
content={content}
|
|
220
|
+
components={EAGER_COMPONENTS}
|
|
221
|
+
/>,
|
|
222
|
+
);
|
|
223
|
+
// Outer group has exactly the two authored tabs.
|
|
224
|
+
expect(html).toContain('data-labels="Outer A|Outer B"');
|
|
225
|
+
// Inner group nested inside Outer A has its own two tabs.
|
|
226
|
+
expect(html).toContain('data-labels="Inner X|Inner Y"');
|
|
227
|
+
expect(html).not.toContain("Tab 2");
|
|
228
|
+
const text = stripTags(html);
|
|
229
|
+
expect(text).toContain("Outer A body.");
|
|
230
|
+
expect(text).toContain("Outer B body.");
|
|
231
|
+
expect(text).toContain("Inner X body.");
|
|
232
|
+
expect(text).toContain("Inner Y body.");
|
|
233
|
+
});
|
|
234
234
|
});
|