@estiva-app/ui 0.51.0 → 0.53.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/ComposerTriggers.d.ts +191 -0
- package/dist/ComposerTriggers.d.ts.map +1 -0
- package/dist/SuggestionMenu.d.ts.map +1 -1
- package/dist/editor.d.ts +1 -0
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +341 -13
- package/dist/editor.js.map +4 -4
- package/dist/index.js +7 -2
- package/dist/index.js.map +3 -3
- package/dist/suggestionPopup.d.ts +9 -0
- package/dist/suggestionPopup.d.ts.map +1 -1
- package/package.json +6 -1
- package/registry.json +326 -3
- package/src/ComposerTriggers.mdx +115 -0
- package/src/ComposerTriggers.stories.tsx +99 -0
- package/src/ComposerTriggers.test.tsx +268 -0
- package/src/ComposerTriggers.tsx +547 -0
- package/src/SuggestionMenu.tsx +13 -3
- package/src/editor.ts +29 -0
- package/src/registry/registry.test.ts +8 -7
- package/src/suggestionPopup.tsx +29 -1
- package/stories/Choosing.mdx +1 -0
package/src/suggestionPopup.tsx
CHANGED
|
@@ -44,6 +44,15 @@ export interface SuggestionPopupOptions<T> {
|
|
|
44
44
|
sections?: (items: T[], query: string) => readonly SuggestionMenuSection<T>[]
|
|
45
45
|
itemKey: (item: T) => string
|
|
46
46
|
row: (item: T) => SuggestionMenuRow
|
|
47
|
+
/**
|
|
48
|
+
* With `refresh`: called with a listener while the list is open; the app
|
|
49
|
+
* calls it when its data has changed (a search landing), and the open list is
|
|
50
|
+
* drawn again for the same query. Returns the unsubscribe, run when the list
|
|
51
|
+
* closes however it closes.
|
|
52
|
+
*/
|
|
53
|
+
subscribe?: (listener: () => void) => () => void
|
|
54
|
+
/** The items for a query, as the plugin's `items` answers — asked again when `subscribe` fires. */
|
|
55
|
+
refresh?: (query: string) => T[]
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
type Props<T> = SuggestionProps<T> & { options: SuggestionPopupOptions<T> }
|
|
@@ -88,7 +97,12 @@ export function suggestionPopup<T>(options: SuggestionPopupOptions<T>): NonNulla
|
|
|
88
97
|
return () => {
|
|
89
98
|
let component: ReactRenderer<SuggestionMenuHandle, Props<T>> | null = null
|
|
90
99
|
let container: HTMLDivElement | null = null
|
|
100
|
+
let last: SuggestionProps<T> | null = null
|
|
101
|
+
let unsubscribe: (() => void) | undefined
|
|
91
102
|
const exit = () => {
|
|
103
|
+
unsubscribe?.()
|
|
104
|
+
unsubscribe = undefined
|
|
105
|
+
last = null
|
|
92
106
|
if (!component) return
|
|
93
107
|
openCount = Math.max(0, openCount - 1)
|
|
94
108
|
lastClose = Date.now()
|
|
@@ -104,8 +118,22 @@ export function suggestionPopup<T>(options: SuggestionPopupOptions<T>): NonNulla
|
|
|
104
118
|
container = document.createElement('div')
|
|
105
119
|
document.body.appendChild(container)
|
|
106
120
|
container.appendChild(component.element)
|
|
121
|
+
last = props
|
|
122
|
+
const { subscribe, refresh } = options
|
|
123
|
+
if (subscribe && refresh) {
|
|
124
|
+
// The plugin asks for items only when the query changes; an answer
|
|
125
|
+
// landing later draws the open list again with the same props.
|
|
126
|
+
unsubscribe = subscribe(() => {
|
|
127
|
+
if (!last || !component) return
|
|
128
|
+
last = { ...last, items: refresh(last.query) }
|
|
129
|
+
component.updateProps({ ...last, options })
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
onUpdate: (props) => {
|
|
134
|
+
last = props
|
|
135
|
+
component?.updateProps({ ...props, options })
|
|
107
136
|
},
|
|
108
|
-
onUpdate: (props) => component?.updateProps({ ...props, options }),
|
|
109
137
|
onKeyDown: ({ event }: SuggestionKeyDownProps) => {
|
|
110
138
|
if (event.key === 'Escape') {
|
|
111
139
|
exit()
|
package/stories/Choosing.mdx
CHANGED
|
@@ -68,6 +68,7 @@ fork freely, owe nothing back, mention it on the package's ticket.
|
|
|
68
68
|
| One window to find something and act on it, opened by a shortcut | **CommandPalette** — rows, forms and written answers, one level at a time |
|
|
69
69
|
| A list that opens as you type in an editor — `/` for commands, `@` for people | **SuggestionMenu** — the editor keeps the caret and hands it the arrow keys; `suggestionPopup` from `@estiva-app/ui/editor` wires it to a Tiptap plugin |
|
|
70
70
|
| Bold, italic and the like over selected text in an editor | **SelectionToolbar**, from `@estiva-app/ui/editor` — it follows the selection by itself |
|
|
71
|
+
| A composer's `@`, `!@`, `[` and `/` — mention a person, reference something, format or insert | **ComposerTriggers** — `PersonMention`, `UrgentPersonMention`, `CaptionedReference`, `ReferenceTrigger` and `SlashCommands` from `@estiva-app/ui/editor`; the app passes its people, its items and its own `/` rows |
|
|
71
72
|
| An editor that saves a block document and must keep its block ids | **BlockNodes** — `BlockId`, `UnknownBlock`, `ReferenceNode` and `AttachmentNode` from `@estiva-app/ui/editor`, beside StarterKit and TableKit |
|
|
72
73
|
| Anything with a title, body and footer | **DialogShell** |
|
|
73
74
|
| "Are you sure?" | **ConfirmDialog** |
|