@estiva-app/ui 0.70.0 → 0.72.0-widgets2.0
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/BlockNodes.d.ts +2 -0
- package/dist/BlockNodes.d.ts.map +1 -1
- package/dist/ComposerTriggers.d.ts +8 -0
- package/dist/ComposerTriggers.d.ts.map +1 -1
- package/dist/EditorBlockHandle.d.ts +53 -4
- package/dist/EditorBlockHandle.d.ts.map +1 -1
- package/dist/LinkChips.d.ts +2 -0
- package/dist/LinkChips.d.ts.map +1 -1
- package/dist/ReferenceMenu.d.ts.map +1 -1
- package/dist/editor.d.ts +1 -1
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +373 -264
- package/dist/editor.js.map +4 -4
- package/dist/widgets-2/fixtures.d.ts +100 -0
- package/dist/widgets-2/fixtures.d.ts.map +1 -0
- package/dist/widgets-2/proposed.d.ts +130 -0
- package/dist/widgets-2/proposed.d.ts.map +1 -0
- package/dist/widgets-2.d.ts +11 -0
- package/dist/widgets-2.d.ts.map +1 -0
- package/dist/widgets-2.js +418 -0
- package/dist/widgets-2.js.map +7 -0
- package/package.json +5 -1
- package/registry.json +62 -5
- package/src/BlockHandle.test.tsx +1 -1
- package/src/BlockNodes.tsx +2 -0
- package/src/ComposerTriggers.tsx +3 -1
- package/src/EditorBlockHandle.mdx +14 -9
- package/src/EditorBlockHandle.stories.tsx +5 -11
- package/src/EditorBlockHandle.test.tsx +200 -0
- package/src/EditorBlockHandle.tsx +181 -10
- package/src/LinkChips.ts +2 -0
- package/src/ReferenceMenu.tsx +2 -0
- package/src/editor.ts +15 -1
- package/src/gates/gates.test.ts +2 -1
- package/src/registry/registry.test.ts +3 -3
- package/src/widgets-2/fixtures.ts +159 -0
- package/src/widgets-2/proposed.tsx +596 -0
- package/src/widgets-2.ts +10 -0
- package/stories/widgets-2/ReadMe.mdx +60 -0
- package/stories/widgets-2/Widgets.stories.tsx +504 -0
- package/stories/widgets-2/today.tsx +352 -0
package/src/ReferenceMenu.tsx
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* Two parts: the extension `ReferenceMenu` holds which chip the menu is open
|
|
22
22
|
* on, and `ReferenceMenuView` draws it beside `EditorContent`. Pair them with
|
|
23
23
|
* `ReferenceNode` and `ReferenceCards`.
|
|
24
|
+
*
|
|
25
|
+
* why: https://github.com/estiva-app/estiva-docs/blob/main/decisions/clicking-a-chip-while-editing-opens-a-menu.md
|
|
24
26
|
*/
|
|
25
27
|
import { useCallback } from 'react'
|
|
26
28
|
import { Extension, type Editor } from '@tiptap/core'
|
package/src/editor.ts
CHANGED
|
@@ -12,7 +12,21 @@ export { PastedImages, pastedImages, pastedImageName, type PastedImagesOptions,
|
|
|
12
12
|
export { PastedMarkdown, type PastedMarkdownOptions } from './PastedMarkdown'
|
|
13
13
|
export { CodeBlockColours } from './CodeBlockColours'
|
|
14
14
|
export { suggestionPopup, isSuggestionActive, isSuggestionOpen, type SuggestionPopupOptions } from './suggestionPopup'
|
|
15
|
-
export {
|
|
15
|
+
export {
|
|
16
|
+
EditorBlockHandle,
|
|
17
|
+
blockDropCursor,
|
|
18
|
+
deleteBlock,
|
|
19
|
+
moveBlock,
|
|
20
|
+
duplicateBlock,
|
|
21
|
+
startBlockDrag,
|
|
22
|
+
turnIntoRows,
|
|
23
|
+
turnListInto,
|
|
24
|
+
turnQuoteInto,
|
|
25
|
+
type EditorBlockHandleProps,
|
|
26
|
+
type BlockTurnInto,
|
|
27
|
+
type ListKind,
|
|
28
|
+
type QuoteKind,
|
|
29
|
+
} from './EditorBlockHandle'
|
|
16
30
|
export { EditorTableControls, appendTableRow, appendTableColumn, deleteTableRow, deleteTableColumn, type EditorTableControlsProps } from './EditorTableControls'
|
|
17
31
|
export {
|
|
18
32
|
PersonMention,
|
package/src/gates/gates.test.ts
CHANGED
|
@@ -413,7 +413,8 @@ describe('gates:status', () => {
|
|
|
413
413
|
expect(out).toContain('✅ UIG-2')
|
|
414
414
|
expect(out).toContain('⬜ UIG-9')
|
|
415
415
|
const json = JSON.parse(await runStatus({ root: dir, json: true }))
|
|
416
|
-
|
|
416
|
+
// A prerelease (`1.2.0-name.0`, published on the `concept` dist-tag) is a version too.
|
|
417
|
+
expect(json.engine).toMatch(/^@estiva-app\/ui@\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/)
|
|
417
418
|
})
|
|
418
419
|
|
|
419
420
|
it('finds the checks file beside the app, and still reads the repo from its top (Ship, UIG-32)', async () => {
|
|
@@ -48,20 +48,20 @@ describe('the registry builds', () => {
|
|
|
48
48
|
expect(registry.entries.map((one) => one.name).sort()).toEqual(values.map((one) => one.name).sort())
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
it('counts
|
|
51
|
+
it('counts 166 names over 81 files: 115 components, 49 helpers and 2 hooks (NavTree, NavTreeSection, the composer triggers and UnreadDot joined on 2 October; BlockHandle and EditorBlockHandle (RIC-18) on 2 October, moveBlock and blockDropCursor, the drop in the gutter, on 5 October, MembersPill and MembersDialog, moved from Peek (SHI-31), on 6 October, ShowMore on 7 October, AppProvider on 8 October, and KindIcon, thingKindOf and PastedImages with its two helpers, moved from Peek, on 8 October; CodeBlockColours, the coloured code block of the editor, on 9 October; Checklist, Callout, isChecklistTick and calloutLook (RIC-19) on 13 October; EditorTableControls and its four actions (RIC-21) on 13 October; ReferenceCards, useReferenceCards and its three helpers, the card a chip in a document asks for, on 14 October; LinkChips and its two helpers, a URL in a document read as its chip, on 14 October; ReferenceMenu, ReferenceMenuView and three helpers, the menu of a chip while writing, on 14 October; PastedMarkdown, markdown pasted as the blocks it spells (LEAF-10), on 15 October; turnIntoRows, turnListInto and turnQuoteInto, the block menu’s Turn into for a list and a quote (LEAF-11), on 15 October)', () => {
|
|
52
52
|
// The reconciliation GATES.md §24 explains. If this changes, that changes.
|
|
53
53
|
// The `EDITOR_EXTENSIONS` count as components by their names; they are
|
|
54
54
|
// editor extensions, documented on SelectionToolbar's, BlockNodes' and
|
|
55
55
|
// ComposerTriggers' pages.
|
|
56
56
|
const kinds = registry.entries.reduce<Record<string, number>>((all, one) => ({ ...all, [one.kind]: (all[one.kind] ?? 0) + 1 }), {})
|
|
57
|
-
expect(kinds).toEqual({ component: 115, helper:
|
|
57
|
+
expect(kinds).toEqual({ component: 115, helper: 49, hook: 2 })
|
|
58
58
|
expect(new Set(registry.entries.map((one) => one.sourceFile)).size).toBe(81)
|
|
59
59
|
})
|
|
60
60
|
|
|
61
61
|
it('gives every entry a purpose, from its own page or from the comment above it', () => {
|
|
62
62
|
expect(registry.entries.filter((one) => one.purpose.trim() === '')).toEqual([])
|
|
63
63
|
expect(registry.entries.filter((one) => one.purposeFrom === 'page').length).toBe(77)
|
|
64
|
-
expect(registry.entries.filter((one) => one.purposeFrom === 'comment').length).toBe(
|
|
64
|
+
expect(registry.entries.filter((one) => one.purposeFrom === 'comment').length).toBe(89)
|
|
65
65
|
})
|
|
66
66
|
|
|
67
67
|
it('takes a name with a page of its own from the page, and a name without one from the code', () => {
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Widgets 2 prototype: the placeholder things every widget on these pages
|
|
3
|
+
* draws. Words are placeholders (stories-and-pages.md); the kinds are named,
|
|
4
|
+
* because telling them apart is what the prototype is for.
|
|
5
|
+
*/
|
|
6
|
+
import type { ThingKind } from '../KindIcon'
|
|
7
|
+
|
|
8
|
+
/** The colours a status draws in, as the apps' manifests name them. */
|
|
9
|
+
export type StatusColour = 'neutral' | 'blue' | 'green' | 'muted'
|
|
10
|
+
|
|
11
|
+
export interface Status {
|
|
12
|
+
label: string
|
|
13
|
+
colour: StatusColour
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** One thing a link can stand for, with every field any app draws today. */
|
|
17
|
+
export interface Thing {
|
|
18
|
+
/** The kinds the prototype covers, one more than KindIcon has: a page. */
|
|
19
|
+
kind: ThingKind | 'page'
|
|
20
|
+
/** The noun a card's corner says. */
|
|
21
|
+
noun: string
|
|
22
|
+
/** The app it opens in. */
|
|
23
|
+
app: string
|
|
24
|
+
title: string
|
|
25
|
+
/** Its key, the way people say it: an issue's "WID-2". */
|
|
26
|
+
key?: string
|
|
27
|
+
/** The line under the title: the project an issue is in, a page's Folder. */
|
|
28
|
+
subtitle?: string
|
|
29
|
+
/** The opening of its description, a page's text, a message's words: what the apps draw today. */
|
|
30
|
+
body?: string
|
|
31
|
+
/**
|
|
32
|
+
* A short summary of the file, one or two sentences (Miky, 15 Oct: detailed
|
|
33
|
+
* shows the summary, not the opening of the long description). No file
|
|
34
|
+
* carries one yet; it is its own project.
|
|
35
|
+
*/
|
|
36
|
+
summary?: string
|
|
37
|
+
status?: Status
|
|
38
|
+
assignee?: string
|
|
39
|
+
author?: string
|
|
40
|
+
/** Everyone who wrote a page. */
|
|
41
|
+
authors?: string[]
|
|
42
|
+
comments?: number
|
|
43
|
+
/**
|
|
44
|
+
* The reader has something unread in its conversation: they are a member
|
|
45
|
+
* and it moved since they last read it (SPEC §11.8, membership-replaces-following).
|
|
46
|
+
*/
|
|
47
|
+
unread?: boolean
|
|
48
|
+
/** A project's issues, drawn as rows inside its detailed card. */
|
|
49
|
+
children?: { title: string; key: string; status: Status; assignee?: string }[]
|
|
50
|
+
/** A project's progress line. */
|
|
51
|
+
progress?: string
|
|
52
|
+
/** A project's progress as numbers, for the ring. */
|
|
53
|
+
done?: { done: number; total: number }
|
|
54
|
+
/** A topic: how many conversations, who is in it, and its latest one. */
|
|
55
|
+
conversations?: number
|
|
56
|
+
members?: string[]
|
|
57
|
+
latest?: { author: string; body: string; at: string }
|
|
58
|
+
updated?: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const TODO: Status = { label: 'Todo', colour: 'neutral' }
|
|
62
|
+
const DOING: Status = { label: 'In progress', colour: 'blue' }
|
|
63
|
+
const DONE: Status = { label: 'Done', colour: 'green' }
|
|
64
|
+
|
|
65
|
+
const PARAGRAPH =
|
|
66
|
+
'A description long enough to need more than one line, so the card has to choose how much of it to show and where to cut it short. The rest is there when you open it.'
|
|
67
|
+
|
|
68
|
+
const SUMMARY = 'A one-sentence summary of what this is for.'
|
|
69
|
+
|
|
70
|
+
export const ISSUE: Thing = {
|
|
71
|
+
kind: 'issue',
|
|
72
|
+
noun: 'Issue',
|
|
73
|
+
app: 'Ship',
|
|
74
|
+
title: 'Item one, with a title long enough to be cut short',
|
|
75
|
+
key: 'ABC-2',
|
|
76
|
+
subtitle: 'Group one',
|
|
77
|
+
body: PARAGRAPH,
|
|
78
|
+
summary: SUMMARY,
|
|
79
|
+
status: DOING,
|
|
80
|
+
assignee: 'Person One',
|
|
81
|
+
comments: 4,
|
|
82
|
+
unread: true,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const PROJECT: Thing = {
|
|
86
|
+
kind: 'project',
|
|
87
|
+
noun: 'Project',
|
|
88
|
+
app: 'Ship',
|
|
89
|
+
title: 'Group one',
|
|
90
|
+
body: PARAGRAPH,
|
|
91
|
+
summary: SUMMARY,
|
|
92
|
+
status: DOING,
|
|
93
|
+
assignee: 'Person Two',
|
|
94
|
+
progress: '3 of 8 done',
|
|
95
|
+
done: { done: 3, total: 8 },
|
|
96
|
+
comments: 6,
|
|
97
|
+
children: [
|
|
98
|
+
{ title: 'Item one', key: 'ABC-1', status: DONE, assignee: 'Person One' },
|
|
99
|
+
{ title: 'Item two', key: 'ABC-2', status: DOING, assignee: 'Person Two' },
|
|
100
|
+
{ title: 'Item three', key: 'ABC-3', status: TODO },
|
|
101
|
+
],
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const TOPIC: Thing = {
|
|
105
|
+
kind: 'topic',
|
|
106
|
+
noun: 'Topic',
|
|
107
|
+
app: 'Peek',
|
|
108
|
+
title: 'Place one',
|
|
109
|
+
conversations: 12,
|
|
110
|
+
unread: true,
|
|
111
|
+
members: ['Person One', 'Person Two', 'Person Three'],
|
|
112
|
+
updated: '2h ago',
|
|
113
|
+
latest: { author: 'Person Three', body: 'The latest conversation in the topic, as its first message reads. It may run to a second line before it is cut short.', at: '2h ago' },
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const MESSAGE: Thing = {
|
|
117
|
+
kind: 'message',
|
|
118
|
+
noun: 'Message',
|
|
119
|
+
app: 'Peek',
|
|
120
|
+
title: 'Person Two',
|
|
121
|
+
author: 'Person Two',
|
|
122
|
+
body: 'A message of two sentences, written by someone in a conversation. It is the words the link points to.',
|
|
123
|
+
updated: '10:42',
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export const PAGE: Thing = {
|
|
127
|
+
kind: 'page',
|
|
128
|
+
noun: 'Page',
|
|
129
|
+
app: 'Leaf',
|
|
130
|
+
title: 'Page one',
|
|
131
|
+
subtitle: 'Folder one',
|
|
132
|
+
body: PARAGRAPH,
|
|
133
|
+
summary: SUMMARY,
|
|
134
|
+
author: 'Person One',
|
|
135
|
+
authors: ['Person One', 'Person Two'],
|
|
136
|
+
comments: 2,
|
|
137
|
+
updated: 'Edited yesterday',
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** A block of a description: drawn live, as the part it is. */
|
|
141
|
+
export const PART = {
|
|
142
|
+
heading: 'Item one',
|
|
143
|
+
noun: 'Issue',
|
|
144
|
+
app: 'Ship',
|
|
145
|
+
blocks: ['Heading of the part', 'A paragraph of the part, as it reads in the description right now.', 'A point in a list', 'Another point'],
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const ATTACHMENT = { name: 'picture-one.png', size: 182_400, contentType: 'image/png' }
|
|
149
|
+
export const ATTACHMENT_FILE = { name: 'document-one.pdf', size: 1_240_000, contentType: 'application/pdf' }
|
|
150
|
+
|
|
151
|
+
/** A file the reader cannot read: only its kind and app are known, from its address. */
|
|
152
|
+
export const UNREADABLE = { kind: 'issue' as const, noun: 'Issue', app: 'Ship', address: 'naddr1qqjxgdmzxy6r2vfs95cryvmp956x2etp94sns' }
|
|
153
|
+
|
|
154
|
+
/** A small picture for the attachment, drawn rather than fetched. */
|
|
155
|
+
export const PICTURE =
|
|
156
|
+
'data:image/svg+xml;utf8,' +
|
|
157
|
+
encodeURIComponent(
|
|
158
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="480" height="300"><rect width="480" height="300" fill="#8a94a6"/><circle cx="360" cy="90" r="40" fill="#d8dde6"/><path d="M0 300 L170 120 L300 260 L380 190 L480 300 Z" fill="#5d6778"/></svg>',
|
|
159
|
+
)
|