Skip to content

Commit 6c9ae00

Browse files
authored
Merge pull request #3574 from superdoc-dev/caio/contract-templates-smart-tags
feat(demo): smart-tags palette for custom SDT fields (SD-3320)
2 parents 63c71be + 955b2a3 commit 6c9ae00

10 files changed

Lines changed: 1362 additions & 772 deletions

demos/__tests__/contract-templates-chip-anchor.spec.ts

Lines changed: 0 additions & 73 deletions
This file was deleted.

demos/__tests__/contract-templates-focus.spec.ts

Lines changed: 2 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ test('clicking a field Focus places the caret inside that control', async ({ pag
2525
{ timeout: 30_000 },
2626
);
2727

28-
// Fields tab is the default; the Focus buttons live on field rows.
28+
// Field value rows (with the Focus buttons) live on the Values tab.
29+
await page.click('.tab[data-tab="values"]');
2930
await page.waitForSelector('[data-focus-field]');
3031
const key = await page.getAttribute('[data-focus-field]', 'data-focus-field');
3132
expect(key).toBeTruthy();
@@ -62,80 +63,3 @@ test('clicking a field Focus places the caret inside that control', async ({ pag
6263
// After focus, the caret lands inside a control whose tag carries this key.
6364
await expect.poll(controlKeyAtSelection, { timeout: 5_000 }).toBe(key);
6465
});
65-
66-
test('focusing an off-screen clause scrolls it in AND lands the caret inside it', async ({ page }) => {
67-
test.skip(process.env.DEMO !== 'contract-templates', 'contract-templates demo only');
68-
69-
await page.route('**/ingest.superdoc.dev/**', (r) =>
70-
r.fulfill({ status: 204, contentType: 'application/json', body: '{}' }),
71-
);
72-
await page.goto('/');
73-
await page.waitForFunction(
74-
() => (window as any).__demo?.state?.ui?.contentControls?.getSnapshot()?.items?.length > 0,
75-
null,
76-
{ timeout: 30_000 },
77-
);
78-
79-
// Clause Focus buttons live in the (initially hidden) clauses panel.
80-
await page.click('.tab[data-tab="clauses"]');
81-
await page.waitForSelector('[data-focus-clause]');
82-
83-
// Bottom-most block clause: its painted id + sectionId (= the button's data attr).
84-
const target = await page.evaluate(() => {
85-
const ui = (window as any).__demo.state.ui;
86-
const blocks = ui.contentControls.getSnapshot().items.filter((i: any) => i.kind === 'block');
87-
const last = blocks[blocks.length - 1];
88-
let sectionId: string | null = null;
89-
try {
90-
sectionId = JSON.parse(last?.properties?.tag ?? '{}').sectionId ?? null;
91-
} catch {
92-
sectionId = null;
93-
}
94-
return { id: last?.id ?? null, sectionId };
95-
});
96-
expect(target.id).toBeTruthy();
97-
expect(target.sectionId).toBeTruthy();
98-
99-
// Scroll to the top so the bottom clause starts off-screen.
100-
await page.evaluate(() => {
101-
let node: HTMLElement | null = document.querySelector('.presentation-editor__pages');
102-
while (node && !(node.scrollHeight > node.clientHeight + 4)) node = node.parentElement;
103-
if (node) node.scrollTop = 0;
104-
else window.scrollTo(0, 0);
105-
});
106-
107-
const state = () =>
108-
page.evaluate((id) => {
109-
// caret's containing control id
110-
const ed = (window as any).__demo.superdoc.activeEditor;
111-
const from = ed?.state?.selection?.from;
112-
let caretIn: string | null = null;
113-
if (typeof from === 'number') {
114-
ed.state.doc.descendants((node: any, pos: number) => {
115-
if (
116-
(node.type.name === 'structuredContent' || node.type.name === 'structuredContentBlock') &&
117-
from > pos &&
118-
from < pos + node.nodeSize
119-
) {
120-
caretIn = String(node.attrs.id);
121-
}
122-
return true;
123-
});
124-
}
125-
// is the control's painted element in the viewport?
126-
const el = document.querySelector<HTMLElement>(`[data-sdt-id="${id}"]`);
127-
const r = el?.getBoundingClientRect();
128-
const inViewport = r ? r.top >= 0 && r.top <= window.innerHeight : false;
129-
return { caretIn, inViewport };
130-
}, target.id);
131-
132-
// Before focus: caret is not in the bottom clause and it's off-screen.
133-
const before = await state();
134-
expect(before.caretIn).not.toBe(target.id);
135-
expect(before.inViewport).toBe(false);
136-
137-
await page.click(`[data-focus-clause="${target.sectionId}"]`);
138-
139-
// After focus: the control is scrolled into view AND the caret is inside it.
140-
await expect.poll(state, { timeout: 6_000 }).toEqual({ caretIn: target.id, inViewport: true });
141-
});

demos/__tests__/contract-templates-locate.spec.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)