@estiva-app/ui 0.69.0 → 0.69.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.
- package/dist/AttachmentCard.d.ts.map +1 -1
- package/dist/LinkChips.d.ts.map +1 -1
- package/dist/editor.js +2 -0
- package/dist/editor.js.map +2 -2
- package/dist/index.js +9 -1
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/registry.json +1 -1
- package/src/AttachmentCard.tsx +8 -2
- package/src/LinkChips.mdx +2 -1
- package/src/LinkChips.test.tsx +17 -0
- package/src/LinkChips.ts +4 -0
package/package.json
CHANGED
package/registry.json
CHANGED
package/src/AttachmentCard.tsx
CHANGED
|
@@ -429,9 +429,15 @@ export function AttachmentCard({
|
|
|
429
429
|
return (
|
|
430
430
|
// `role="status"`: a plain box may not carry a name (axe, aria-prohibited-attr), and a
|
|
431
431
|
// status says what it is doing — loading — to a reader that cannot see the pulse.
|
|
432
|
+
// The ready picture's shell — its 112px area and the name row under it — so nothing below moves as it
|
|
433
|
+
// arrives (Peek OPT-10: a loading box 34px shorter than the card it became pushed the conversation).
|
|
432
434
|
// @estiva-escape(no-restyled-part): the loading pulse is AttachmentCard's own state; Card has no loading state (UIG-9, Katerina 17 September)
|
|
433
|
-
<Card role="status" fill="inset" aria-busy="true" aria-label={`Loading ${name}`} className={cn('w-[180px]
|
|
434
|
-
|
|
435
|
+
<Card role="status" fill="inset" aria-busy="true" aria-label={`Loading ${name}`} clip className={cn('flex flex-col w-[180px] animate-pulse', className)} {...props}>
|
|
436
|
+
<div className="w-full h-28" />
|
|
437
|
+
<div className="flex items-center gap-1 pl-2 pr-1 py-1 min-w-0">
|
|
438
|
+
<Truncating text={name} className="flex-1 text-caption text-text-primary truncate" wrapperClassName="flex-1" />
|
|
439
|
+
{downloadControl}
|
|
440
|
+
</div>
|
|
435
441
|
</Card>
|
|
436
442
|
)
|
|
437
443
|
}
|
package/src/LinkChips.mdx
CHANGED
|
@@ -48,7 +48,8 @@ LinkChips.configure({
|
|
|
48
48
|
is asked about and becomes its chip at once, with the caret at its end, so
|
|
49
49
|
**ReferenceMenu** can open its menu.
|
|
50
50
|
- A URL in code or in a code block stays text, and so does a link on words.
|
|
51
|
-
- Each URL is asked about once
|
|
51
|
+
- Each URL is asked about once while the document holds it, and one editor
|
|
52
|
+
asks about at most `limit` of the URLs it holds unanswered at a time
|
|
52
53
|
(24 by default), the first ones: an answer can cost the app a query.
|
|
53
54
|
- A pasted URL's chip is its own undo step: undo gives the URL back, and a
|
|
54
55
|
second undo takes the paste away. A typed URL's chip is not a step: undo
|
package/src/LinkChips.test.tsx
CHANGED
|
@@ -83,6 +83,23 @@ describe('LinkChips', () => {
|
|
|
83
83
|
expect(asked).toEqual([['https://a.example/1', 'https://a.example/2']])
|
|
84
84
|
})
|
|
85
85
|
|
|
86
|
+
it('counts its limit over the URLs the document holds: a message box keeps asking after the last message is sent', async () => {
|
|
87
|
+
const asked: string[][] = []
|
|
88
|
+
editor = new Editor({
|
|
89
|
+
extensions: [
|
|
90
|
+
StarterKit.configure({ link: false }),
|
|
91
|
+
BlockId,
|
|
92
|
+
ReferenceNode,
|
|
93
|
+
LinkChips.configure({ referenceOf: () => undefined, ask: (urls) => void asked.push(urls), limit: 2 }),
|
|
94
|
+
],
|
|
95
|
+
content: para({ type: 'text', text: 'https://a.example/1 https://a.example/2 ' }),
|
|
96
|
+
})
|
|
97
|
+
await tick()
|
|
98
|
+
// Sent: the box is emptied, and the next message's links are asked about.
|
|
99
|
+
editor.commands.setContent(para({ type: 'text', text: 'https://a.example/3 ' }))
|
|
100
|
+
expect(asked).toEqual([['https://a.example/1', 'https://a.example/2'], ['https://a.example/3']])
|
|
101
|
+
})
|
|
102
|
+
|
|
86
103
|
it('turns the URL into its chip once the answer comes back', async () => {
|
|
87
104
|
const known = new Map<string, string>()
|
|
88
105
|
const ed = make(para({ type: 'text', text: `See ${URL_} now` }), known)
|
package/src/LinkChips.ts
CHANGED
|
@@ -215,6 +215,10 @@ export const LinkChips = Extension.create<LinkChipsOptions>({
|
|
|
215
215
|
const look = (state: EditorState) => {
|
|
216
216
|
if (!options.ask) return
|
|
217
217
|
const { open } = findLinkChips(state.doc, state.selection, options.referenceOf, key.getState(state)?.pasted)
|
|
218
|
+
// The limit counts the URLs the document still holds unanswered: a message box lives across many messages,
|
|
219
|
+
// and one that counted every URL it was ever asked would stop making chips after a day's links (OPT-19).
|
|
220
|
+
const waiting = new Set(open)
|
|
221
|
+
for (const url of asked) if (!waiting.has(url)) asked.delete(url)
|
|
218
222
|
const fresh = open.filter((url) => !asked.has(url)).slice(0, Math.max(0, options.limit - asked.size))
|
|
219
223
|
if (!fresh.length) return
|
|
220
224
|
for (const url of fresh) asked.add(url)
|