@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.
Files changed (41) hide show
  1. package/dist/BlockNodes.d.ts +2 -0
  2. package/dist/BlockNodes.d.ts.map +1 -1
  3. package/dist/ComposerTriggers.d.ts +8 -0
  4. package/dist/ComposerTriggers.d.ts.map +1 -1
  5. package/dist/EditorBlockHandle.d.ts +53 -4
  6. package/dist/EditorBlockHandle.d.ts.map +1 -1
  7. package/dist/LinkChips.d.ts +2 -0
  8. package/dist/LinkChips.d.ts.map +1 -1
  9. package/dist/ReferenceMenu.d.ts.map +1 -1
  10. package/dist/editor.d.ts +1 -1
  11. package/dist/editor.d.ts.map +1 -1
  12. package/dist/editor.js +373 -264
  13. package/dist/editor.js.map +4 -4
  14. package/dist/widgets-2/fixtures.d.ts +100 -0
  15. package/dist/widgets-2/fixtures.d.ts.map +1 -0
  16. package/dist/widgets-2/proposed.d.ts +130 -0
  17. package/dist/widgets-2/proposed.d.ts.map +1 -0
  18. package/dist/widgets-2.d.ts +11 -0
  19. package/dist/widgets-2.d.ts.map +1 -0
  20. package/dist/widgets-2.js +418 -0
  21. package/dist/widgets-2.js.map +7 -0
  22. package/package.json +5 -1
  23. package/registry.json +62 -5
  24. package/src/BlockHandle.test.tsx +1 -1
  25. package/src/BlockNodes.tsx +2 -0
  26. package/src/ComposerTriggers.tsx +3 -1
  27. package/src/EditorBlockHandle.mdx +14 -9
  28. package/src/EditorBlockHandle.stories.tsx +5 -11
  29. package/src/EditorBlockHandle.test.tsx +200 -0
  30. package/src/EditorBlockHandle.tsx +181 -10
  31. package/src/LinkChips.ts +2 -0
  32. package/src/ReferenceMenu.tsx +2 -0
  33. package/src/editor.ts +15 -1
  34. package/src/gates/gates.test.ts +2 -1
  35. package/src/registry/registry.test.ts +3 -3
  36. package/src/widgets-2/fixtures.ts +159 -0
  37. package/src/widgets-2/proposed.tsx +596 -0
  38. package/src/widgets-2.ts +10 -0
  39. package/stories/widgets-2/ReadMe.mdx +60 -0
  40. package/stories/widgets-2/Widgets.stories.tsx +504 -0
  41. package/stories/widgets-2/today.tsx +352 -0
@@ -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 { EditorBlockHandle, blockDropCursor, deleteBlock, moveBlock, duplicateBlock, startBlockDrag, type EditorBlockHandleProps, type BlockTurnInto } from './EditorBlockHandle'
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,
@@ -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
- expect(json.engine).toMatch(/^@estiva-app\/ui@\d+\.\d+\.\d+$/)
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 163 names over 81 files: 115 components, 46 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)', () => {
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: 46, hook: 2 })
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(86)
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
+ )