@fieldia/chatter 0.8.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/LICENSE +21 -0
- package/README.md +32 -0
- package/package.json +39 -0
- package/src/index.d.mts +6 -0
- package/src/index.d.ts +6 -0
- package/src/index.js +10 -0
- package/src/index.js.map +1 -0
- package/src/index.mjs +7 -0
- package/src/index.mjs.map +1 -0
- package/src/lib/activities.d.mts +19 -0
- package/src/lib/activities.d.ts +19 -0
- package/src/lib/activities.js +145 -0
- package/src/lib/activities.js.map +1 -0
- package/src/lib/activities.mjs +140 -0
- package/src/lib/activities.mjs.map +1 -0
- package/src/lib/attachments.d.mts +19 -0
- package/src/lib/attachments.d.ts +19 -0
- package/src/lib/attachments.js +93 -0
- package/src/lib/attachments.js.map +1 -0
- package/src/lib/attachments.mjs +89 -0
- package/src/lib/attachments.mjs.map +1 -0
- package/src/lib/chatter.d.mts +45 -0
- package/src/lib/chatter.d.ts +45 -0
- package/src/lib/chatter.js +222 -0
- package/src/lib/chatter.js.map +1 -0
- package/src/lib/chatter.mjs +217 -0
- package/src/lib/chatter.mjs.map +1 -0
- package/src/lib/followers.d.mts +15 -0
- package/src/lib/followers.d.ts +15 -0
- package/src/lib/followers.js +96 -0
- package/src/lib/followers.js.map +1 -0
- package/src/lib/followers.mjs +93 -0
- package/src/lib/followers.mjs.map +1 -0
- package/src/lib/labels.d.mts +43 -0
- package/src/lib/labels.d.ts +43 -0
- package/src/lib/labels.js +166 -0
- package/src/lib/labels.js.map +1 -0
- package/src/lib/labels.mjs +163 -0
- package/src/lib/labels.mjs.map +1 -0
- package/src/lib/memory.d.mts +22 -0
- package/src/lib/memory.d.ts +22 -0
- package/src/lib/memory.js +131 -0
- package/src/lib/memory.js.map +1 -0
- package/src/lib/memory.mjs +128 -0
- package/src/lib/memory.mjs.map +1 -0
- package/src/lib/mentions.d.mts +18 -0
- package/src/lib/mentions.d.ts +18 -0
- package/src/lib/mentions.js +94 -0
- package/src/lib/mentions.js.map +1 -0
- package/src/lib/mentions.mjs +90 -0
- package/src/lib/mentions.mjs.map +1 -0
- package/src/lib/reactions.d.mts +10 -0
- package/src/lib/reactions.d.ts +10 -0
- package/src/lib/reactions.js +53 -0
- package/src/lib/reactions.js.map +1 -0
- package/src/lib/reactions.mjs +49 -0
- package/src/lib/reactions.mjs.map +1 -0
- package/src/lib/slot.d.mts +17 -0
- package/src/lib/slot.d.ts +17 -0
- package/src/lib/slot.js +37 -0
- package/src/lib/slot.js.map +1 -0
- package/src/lib/slot.mjs +34 -0
- package/src/lib/slot.mjs.map +1 -0
- package/src/lib/source.d.mts +114 -0
- package/src/lib/source.d.ts +114 -0
- package/src/lib/source.js +9 -0
- package/src/lib/source.js.map +1 -0
- package/src/lib/source.mjs +8 -0
- package/src/lib/source.mjs.map +1 -0
- package/src/lib/styles.d.mts +4 -0
- package/src/lib/styles.d.ts +4 -0
- package/src/lib/styles.js +108 -0
- package/src/lib/styles.js.map +1 -0
- package/src/lib/styles.mjs +104 -0
- package/src/lib/styles.mjs.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.mjs","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChatterContext } from './chatter.mjs';
|
|
2
|
+
import type { Person } from './source.mjs';
|
|
3
|
+
/** What is being typed after an @, up to the cursor; null when the cursor is not in one. */
|
|
4
|
+
export declare function mentionAt(text: string, caret: number): {
|
|
5
|
+
start: number;
|
|
6
|
+
query: string;
|
|
7
|
+
} | null;
|
|
8
|
+
/**
|
|
9
|
+
* @mentions in a composer's box: people suggested as a name is typed after an
|
|
10
|
+
* @, picked with the arrows and Enter (or a click), and kept as long as their
|
|
11
|
+
* "@Name" is still in the text. Without a source of people, nothing happens.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mentions(context: ChatterContext, box: HTMLTextAreaElement): {
|
|
14
|
+
list: HTMLUListElement;
|
|
15
|
+
/** The people still mentioned in the text. */
|
|
16
|
+
picked: () => Person[];
|
|
17
|
+
reset(): void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChatterContext } from './chatter';
|
|
2
|
+
import type { Person } from './source';
|
|
3
|
+
/** What is being typed after an @, up to the cursor; null when the cursor is not in one. */
|
|
4
|
+
export declare function mentionAt(text: string, caret: number): {
|
|
5
|
+
start: number;
|
|
6
|
+
query: string;
|
|
7
|
+
} | null;
|
|
8
|
+
/**
|
|
9
|
+
* @mentions in a composer's box: people suggested as a name is typed after an
|
|
10
|
+
* @, picked with the arrows and Enter (or a click), and kept as long as their
|
|
11
|
+
* "@Name" is still in the text. Without a source of people, nothing happens.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mentions(context: ChatterContext, box: HTMLTextAreaElement): {
|
|
14
|
+
list: HTMLUListElement;
|
|
15
|
+
/** The people still mentioned in the text. */
|
|
16
|
+
picked: () => Person[];
|
|
17
|
+
reset(): void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mentionAt = mentionAt;
|
|
4
|
+
exports.mentions = mentions;
|
|
5
|
+
/** What is being typed after an @, up to the cursor; null when the cursor is not in one. */
|
|
6
|
+
function mentionAt(text, caret) {
|
|
7
|
+
const before = text.slice(0, caret);
|
|
8
|
+
const match = /(?:^|\s)@([\p{L}\p{N}._-]*)$/u.exec(before);
|
|
9
|
+
return match ? { start: caret - match[1].length - 1, query: match[1] } : null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @mentions in a composer's box: people suggested as a name is typed after an
|
|
13
|
+
* @, picked with the arrows and Enter (or a click), and kept as long as their
|
|
14
|
+
* "@Name" is still in the text. Without a source of people, nothing happens.
|
|
15
|
+
*/
|
|
16
|
+
function mentions(context, box) {
|
|
17
|
+
const { el, labels, source } = context;
|
|
18
|
+
const list = el('ul', { class: 'fd-mentions', role: 'listbox', hidden: '', 'aria-label': labels.search });
|
|
19
|
+
let picked = [];
|
|
20
|
+
let found = [];
|
|
21
|
+
let active = 0;
|
|
22
|
+
let asking = 0;
|
|
23
|
+
const close = () => {
|
|
24
|
+
list.hidden = true;
|
|
25
|
+
found = [];
|
|
26
|
+
box.removeAttribute('aria-activedescendant');
|
|
27
|
+
};
|
|
28
|
+
function draw() {
|
|
29
|
+
list.replaceChildren(...(found.length
|
|
30
|
+
? found.map((person, i) => {
|
|
31
|
+
const option = el('li', { role: 'option', id: `fd-mention-${i}`, 'aria-selected': String(i === active), class: i === active ? 'fd-active' : '' }, person.name);
|
|
32
|
+
option.addEventListener('mousedown', (event) => event.preventDefault()); // the box keeps the focus
|
|
33
|
+
option.addEventListener('click', () => pick(person));
|
|
34
|
+
return option;
|
|
35
|
+
})
|
|
36
|
+
: [el('li', { class: 'fd-empty' }, labels.noOneFound)]));
|
|
37
|
+
list.hidden = false;
|
|
38
|
+
}
|
|
39
|
+
function pick(person) {
|
|
40
|
+
const at = mentionAt(box.value, box.selectionStart ?? box.value.length);
|
|
41
|
+
if (!at)
|
|
42
|
+
return close();
|
|
43
|
+
const inserted = `@${person.name} `;
|
|
44
|
+
box.value = box.value.slice(0, at.start) + inserted + box.value.slice(box.selectionStart ?? box.value.length);
|
|
45
|
+
const caret = at.start + inserted.length;
|
|
46
|
+
box.setSelectionRange(caret, caret);
|
|
47
|
+
if (!picked.some((p) => p.id === person.id))
|
|
48
|
+
picked.push(person);
|
|
49
|
+
close();
|
|
50
|
+
box.focus();
|
|
51
|
+
}
|
|
52
|
+
box.addEventListener('input', async () => {
|
|
53
|
+
const at = source.people ? mentionAt(box.value, box.selectionStart ?? box.value.length) : null;
|
|
54
|
+
if (!at || !source.people)
|
|
55
|
+
return close();
|
|
56
|
+
const mine = ++asking;
|
|
57
|
+
const people = await source.people(at.query);
|
|
58
|
+
if (mine !== asking)
|
|
59
|
+
return; // a newer question is on its way
|
|
60
|
+
found = people.slice(0, 8);
|
|
61
|
+
active = 0;
|
|
62
|
+
draw();
|
|
63
|
+
});
|
|
64
|
+
box.addEventListener('keydown', (event) => {
|
|
65
|
+
if (list.hidden || !found.length)
|
|
66
|
+
return;
|
|
67
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
active = (active + (event.key === 'ArrowDown' ? 1 : -1) + found.length) % found.length;
|
|
70
|
+
draw();
|
|
71
|
+
box.setAttribute('aria-activedescendant', `fd-mention-${active}`);
|
|
72
|
+
}
|
|
73
|
+
else if ((event.key === 'Enter' && !event.ctrlKey && !event.metaKey) || event.key === 'Tab') {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
event.stopImmediatePropagation();
|
|
76
|
+
pick(found[active]);
|
|
77
|
+
}
|
|
78
|
+
else if (event.key === 'Escape') {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
event.stopImmediatePropagation();
|
|
81
|
+
close();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
list,
|
|
86
|
+
/** The people still mentioned in the text. */
|
|
87
|
+
picked: () => picked.filter((person) => box.value.includes(`@${person.name}`)),
|
|
88
|
+
reset() {
|
|
89
|
+
picked = [];
|
|
90
|
+
close();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=mentions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.js","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/mentions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/** What is being typed after an @, up to the cursor; null when the cursor is not in one. */
|
|
2
|
+
export function mentionAt(text, caret) {
|
|
3
|
+
const before = text.slice(0, caret);
|
|
4
|
+
const match = /(?:^|\s)@([\p{L}\p{N}._-]*)$/u.exec(before);
|
|
5
|
+
return match ? { start: caret - match[1].length - 1, query: match[1] } : null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* @mentions in a composer's box: people suggested as a name is typed after an
|
|
9
|
+
* @, picked with the arrows and Enter (or a click), and kept as long as their
|
|
10
|
+
* "@Name" is still in the text. Without a source of people, nothing happens.
|
|
11
|
+
*/
|
|
12
|
+
export function mentions(context, box) {
|
|
13
|
+
const { el, labels, source } = context;
|
|
14
|
+
const list = el('ul', { class: 'fd-mentions', role: 'listbox', hidden: '', 'aria-label': labels.search });
|
|
15
|
+
let picked = [];
|
|
16
|
+
let found = [];
|
|
17
|
+
let active = 0;
|
|
18
|
+
let asking = 0;
|
|
19
|
+
const close = () => {
|
|
20
|
+
list.hidden = true;
|
|
21
|
+
found = [];
|
|
22
|
+
box.removeAttribute('aria-activedescendant');
|
|
23
|
+
};
|
|
24
|
+
function draw() {
|
|
25
|
+
list.replaceChildren(...(found.length
|
|
26
|
+
? found.map((person, i) => {
|
|
27
|
+
const option = el('li', { role: 'option', id: `fd-mention-${i}`, 'aria-selected': String(i === active), class: i === active ? 'fd-active' : '' }, person.name);
|
|
28
|
+
option.addEventListener('mousedown', (event) => event.preventDefault()); // the box keeps the focus
|
|
29
|
+
option.addEventListener('click', () => pick(person));
|
|
30
|
+
return option;
|
|
31
|
+
})
|
|
32
|
+
: [el('li', { class: 'fd-empty' }, labels.noOneFound)]));
|
|
33
|
+
list.hidden = false;
|
|
34
|
+
}
|
|
35
|
+
function pick(person) {
|
|
36
|
+
const at = mentionAt(box.value, box.selectionStart ?? box.value.length);
|
|
37
|
+
if (!at)
|
|
38
|
+
return close();
|
|
39
|
+
const inserted = `@${person.name} `;
|
|
40
|
+
box.value = box.value.slice(0, at.start) + inserted + box.value.slice(box.selectionStart ?? box.value.length);
|
|
41
|
+
const caret = at.start + inserted.length;
|
|
42
|
+
box.setSelectionRange(caret, caret);
|
|
43
|
+
if (!picked.some((p) => p.id === person.id))
|
|
44
|
+
picked.push(person);
|
|
45
|
+
close();
|
|
46
|
+
box.focus();
|
|
47
|
+
}
|
|
48
|
+
box.addEventListener('input', async () => {
|
|
49
|
+
const at = source.people ? mentionAt(box.value, box.selectionStart ?? box.value.length) : null;
|
|
50
|
+
if (!at || !source.people)
|
|
51
|
+
return close();
|
|
52
|
+
const mine = ++asking;
|
|
53
|
+
const people = await source.people(at.query);
|
|
54
|
+
if (mine !== asking)
|
|
55
|
+
return; // a newer question is on its way
|
|
56
|
+
found = people.slice(0, 8);
|
|
57
|
+
active = 0;
|
|
58
|
+
draw();
|
|
59
|
+
});
|
|
60
|
+
box.addEventListener('keydown', (event) => {
|
|
61
|
+
if (list.hidden || !found.length)
|
|
62
|
+
return;
|
|
63
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
active = (active + (event.key === 'ArrowDown' ? 1 : -1) + found.length) % found.length;
|
|
66
|
+
draw();
|
|
67
|
+
box.setAttribute('aria-activedescendant', `fd-mention-${active}`);
|
|
68
|
+
}
|
|
69
|
+
else if ((event.key === 'Enter' && !event.ctrlKey && !event.metaKey) || event.key === 'Tab') {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
event.stopImmediatePropagation();
|
|
72
|
+
pick(found[active]);
|
|
73
|
+
}
|
|
74
|
+
else if (event.key === 'Escape') {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
event.stopImmediatePropagation();
|
|
77
|
+
close();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
list,
|
|
82
|
+
/** The people still mentioned in the text. */
|
|
83
|
+
picked: () => picked.filter((person) => box.value.includes(`@${person.name}`)),
|
|
84
|
+
reset() {
|
|
85
|
+
picked = [];
|
|
86
|
+
close();
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=mentions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mentions.mjs","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/mentions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatterContext } from './chatter.mjs';
|
|
2
|
+
import type { ChatterId, Reaction } from './source.mjs';
|
|
3
|
+
/** The reactions offered at a click: the ones teams use most. */
|
|
4
|
+
export declare const REACTION_CHOICES: string[];
|
|
5
|
+
/**
|
|
6
|
+
* A message's reactions: a chip for each, pressed when the person's own is
|
|
7
|
+
* among them and toggled by a click, and a button that offers the others.
|
|
8
|
+
* Nothing is shown when the source cannot keep reactions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function reactionBar(context: ChatterContext, messageId: ChatterId, reactions: readonly Reaction[]): HTMLElement | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatterContext } from './chatter';
|
|
2
|
+
import type { ChatterId, Reaction } from './source';
|
|
3
|
+
/** The reactions offered at a click: the ones teams use most. */
|
|
4
|
+
export declare const REACTION_CHOICES: string[];
|
|
5
|
+
/**
|
|
6
|
+
* A message's reactions: a chip for each, pressed when the person's own is
|
|
7
|
+
* among them and toggled by a click, and a button that offers the others.
|
|
8
|
+
* Nothing is shown when the source cannot keep reactions.
|
|
9
|
+
*/
|
|
10
|
+
export declare function reactionBar(context: ChatterContext, messageId: ChatterId, reactions: readonly Reaction[]): HTMLElement | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REACTION_CHOICES = void 0;
|
|
4
|
+
exports.reactionBar = reactionBar;
|
|
5
|
+
/** The reactions offered at a click: the ones teams use most. */
|
|
6
|
+
exports.REACTION_CHOICES = ['👍', '❤️', '😄', '🎉', '👀', '✅'];
|
|
7
|
+
/**
|
|
8
|
+
* A message's reactions: a chip for each, pressed when the person's own is
|
|
9
|
+
* among them and toggled by a click, and a button that offers the others.
|
|
10
|
+
* Nothing is shown when the source cannot keep reactions.
|
|
11
|
+
*/
|
|
12
|
+
function reactionBar(context, messageId, reactions) {
|
|
13
|
+
const { el, labels, source } = context;
|
|
14
|
+
if (!source.react)
|
|
15
|
+
return null;
|
|
16
|
+
const react = source.react.bind(source);
|
|
17
|
+
const bar = el('div', { class: 'fd-reactions' });
|
|
18
|
+
const picker = el('div', { class: 'fd-reaction-picker', hidden: '', role: 'group', 'aria-label': labels.react });
|
|
19
|
+
const toggle = async (emoji) => {
|
|
20
|
+
const record = context.record();
|
|
21
|
+
if (!record)
|
|
22
|
+
return;
|
|
23
|
+
picker.hidden = true;
|
|
24
|
+
draw(await react(record, messageId, emoji));
|
|
25
|
+
};
|
|
26
|
+
for (const emoji of exports.REACTION_CHOICES) {
|
|
27
|
+
const choice = el('button', { type: 'button', 'data-emoji': emoji, 'aria-label': emoji }, emoji);
|
|
28
|
+
choice.addEventListener('click', () => void toggle(emoji));
|
|
29
|
+
picker.append(choice);
|
|
30
|
+
}
|
|
31
|
+
const add = el('button', { type: 'button', class: 'fd-reaction-add', 'aria-label': labels.react, 'aria-expanded': 'false' }, '☺');
|
|
32
|
+
add.addEventListener('click', () => {
|
|
33
|
+
picker.hidden = !picker.hidden;
|
|
34
|
+
add.setAttribute('aria-expanded', String(!picker.hidden));
|
|
35
|
+
});
|
|
36
|
+
picker.addEventListener('keydown', (event) => {
|
|
37
|
+
if (event.key === 'Escape') {
|
|
38
|
+
picker.hidden = true;
|
|
39
|
+
add.focus();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
function draw(list) {
|
|
43
|
+
const chips = list.map((reaction) => {
|
|
44
|
+
const chip = el('button', { type: 'button', class: 'fd-reaction', 'aria-pressed': String(reaction.mine) }, `${reaction.emoji} ${reaction.count}`);
|
|
45
|
+
chip.addEventListener('click', () => void toggle(reaction.emoji));
|
|
46
|
+
return chip;
|
|
47
|
+
});
|
|
48
|
+
bar.replaceChildren(...chips, add, picker);
|
|
49
|
+
}
|
|
50
|
+
draw(reactions);
|
|
51
|
+
return bar;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=reactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactions.js","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/reactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** The reactions offered at a click: the ones teams use most. */
|
|
2
|
+
export const REACTION_CHOICES = ['👍', '❤️', '😄', '🎉', '👀', '✅'];
|
|
3
|
+
/**
|
|
4
|
+
* A message's reactions: a chip for each, pressed when the person's own is
|
|
5
|
+
* among them and toggled by a click, and a button that offers the others.
|
|
6
|
+
* Nothing is shown when the source cannot keep reactions.
|
|
7
|
+
*/
|
|
8
|
+
export function reactionBar(context, messageId, reactions) {
|
|
9
|
+
const { el, labels, source } = context;
|
|
10
|
+
if (!source.react)
|
|
11
|
+
return null;
|
|
12
|
+
const react = source.react.bind(source);
|
|
13
|
+
const bar = el('div', { class: 'fd-reactions' });
|
|
14
|
+
const picker = el('div', { class: 'fd-reaction-picker', hidden: '', role: 'group', 'aria-label': labels.react });
|
|
15
|
+
const toggle = async (emoji) => {
|
|
16
|
+
const record = context.record();
|
|
17
|
+
if (!record)
|
|
18
|
+
return;
|
|
19
|
+
picker.hidden = true;
|
|
20
|
+
draw(await react(record, messageId, emoji));
|
|
21
|
+
};
|
|
22
|
+
for (const emoji of REACTION_CHOICES) {
|
|
23
|
+
const choice = el('button', { type: 'button', 'data-emoji': emoji, 'aria-label': emoji }, emoji);
|
|
24
|
+
choice.addEventListener('click', () => void toggle(emoji));
|
|
25
|
+
picker.append(choice);
|
|
26
|
+
}
|
|
27
|
+
const add = el('button', { type: 'button', class: 'fd-reaction-add', 'aria-label': labels.react, 'aria-expanded': 'false' }, '☺');
|
|
28
|
+
add.addEventListener('click', () => {
|
|
29
|
+
picker.hidden = !picker.hidden;
|
|
30
|
+
add.setAttribute('aria-expanded', String(!picker.hidden));
|
|
31
|
+
});
|
|
32
|
+
picker.addEventListener('keydown', (event) => {
|
|
33
|
+
if (event.key === 'Escape') {
|
|
34
|
+
picker.hidden = true;
|
|
35
|
+
add.focus();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
function draw(list) {
|
|
39
|
+
const chips = list.map((reaction) => {
|
|
40
|
+
const chip = el('button', { type: 'button', class: 'fd-reaction', 'aria-pressed': String(reaction.mine) }, `${reaction.emoji} ${reaction.count}`);
|
|
41
|
+
chip.addEventListener('click', () => void toggle(reaction.emoji));
|
|
42
|
+
return chip;
|
|
43
|
+
});
|
|
44
|
+
bar.replaceChildren(...chips, add, picker);
|
|
45
|
+
}
|
|
46
|
+
draw(reactions);
|
|
47
|
+
return bar;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=reactions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactions.mjs","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/reactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Form } from '@fieldia/core';
|
|
2
|
+
import { type ChatterOptions } from './chatter.mjs';
|
|
3
|
+
export interface ChatterSlotOptions extends Omit<ChatterOptions, 'record'> {
|
|
4
|
+
/** The model the conversation is about; the page's own by default. */
|
|
5
|
+
model?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What fills a sheet's chatter slot: the conversation of the record the form
|
|
9
|
+
* shows. It waits while the record is new, starts once it is saved, follows
|
|
10
|
+
* the form to another record, and fetches again after each save, when a
|
|
11
|
+
* backend posts what changed.
|
|
12
|
+
*
|
|
13
|
+
* mountViewer(host, { page, dataSource, slots: { chatter: chatterSlot({ source }) } })
|
|
14
|
+
*/
|
|
15
|
+
export declare function chatterSlot(options: ChatterSlotOptions): (element: HTMLElement, context: {
|
|
16
|
+
form: Form;
|
|
17
|
+
}) => () => void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Form } from '@fieldia/core';
|
|
2
|
+
import { type ChatterOptions } from './chatter';
|
|
3
|
+
export interface ChatterSlotOptions extends Omit<ChatterOptions, 'record'> {
|
|
4
|
+
/** The model the conversation is about; the page's own by default. */
|
|
5
|
+
model?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What fills a sheet's chatter slot: the conversation of the record the form
|
|
9
|
+
* shows. It waits while the record is new, starts once it is saved, follows
|
|
10
|
+
* the form to another record, and fetches again after each save, when a
|
|
11
|
+
* backend posts what changed.
|
|
12
|
+
*
|
|
13
|
+
* mountViewer(host, { page, dataSource, slots: { chatter: chatterSlot({ source }) } })
|
|
14
|
+
*/
|
|
15
|
+
export declare function chatterSlot(options: ChatterSlotOptions): (element: HTMLElement, context: {
|
|
16
|
+
form: Form;
|
|
17
|
+
}) => () => void;
|
package/src/lib/slot.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chatterSlot = chatterSlot;
|
|
4
|
+
const chatter_1 = require("./chatter");
|
|
5
|
+
/**
|
|
6
|
+
* What fills a sheet's chatter slot: the conversation of the record the form
|
|
7
|
+
* shows. It waits while the record is new, starts once it is saved, follows
|
|
8
|
+
* the form to another record, and fetches again after each save, when a
|
|
9
|
+
* backend posts what changed.
|
|
10
|
+
*
|
|
11
|
+
* mountViewer(host, { page, dataSource, slots: { chatter: chatterSlot({ source }) } })
|
|
12
|
+
*/
|
|
13
|
+
function chatterSlot(options) {
|
|
14
|
+
return (element, { form }) => {
|
|
15
|
+
const model = options.model ?? (form.page.data.kind === 'record' ? form.page.data.model : null);
|
|
16
|
+
const recordOf = (state) => (model && state.recordId != null ? { model, id: state.recordId } : null);
|
|
17
|
+
let shown = recordOf(form.getState());
|
|
18
|
+
let status = form.getState().status;
|
|
19
|
+
const chatter = (0, chatter_1.mountChatter)(element, { ...options, record: shown });
|
|
20
|
+
const unsubscribe = form.subscribe((state) => {
|
|
21
|
+
const next = recordOf(state);
|
|
22
|
+
if (next?.id !== shown?.id) {
|
|
23
|
+
shown = next;
|
|
24
|
+
void chatter.setRecord(next);
|
|
25
|
+
}
|
|
26
|
+
else if (state.status === 'saved' && status !== 'saved') {
|
|
27
|
+
void chatter.refresh();
|
|
28
|
+
}
|
|
29
|
+
status = state.status;
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
unsubscribe();
|
|
33
|
+
chatter.destroy();
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=slot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot.js","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/slot.ts"],"names":[],"mappings":";;AAiBA,kCAsBC;AAtCD,uCAA8D;AAQ9D;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,OAA2B;IACrD,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAoB,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClI,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC;QACpC,MAAM,OAAO,GAAG,IAAA,sBAAY,EAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,IAAI,EAAE,EAAE,KAAK,KAAK,EAAE,EAAE,EAAE,CAAC;gBAC3B,KAAK,GAAG,IAAI,CAAC;gBACb,KAAK,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC1D,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzB,CAAC;YACD,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
package/src/lib/slot.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { mountChatter } from './chatter.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* What fills a sheet's chatter slot: the conversation of the record the form
|
|
4
|
+
* shows. It waits while the record is new, starts once it is saved, follows
|
|
5
|
+
* the form to another record, and fetches again after each save, when a
|
|
6
|
+
* backend posts what changed.
|
|
7
|
+
*
|
|
8
|
+
* mountViewer(host, { page, dataSource, slots: { chatter: chatterSlot({ source }) } })
|
|
9
|
+
*/
|
|
10
|
+
export function chatterSlot(options) {
|
|
11
|
+
return (element, { form }) => {
|
|
12
|
+
const model = options.model ?? (form.page.data.kind === 'record' ? form.page.data.model : null);
|
|
13
|
+
const recordOf = (state) => (model && state.recordId != null ? { model, id: state.recordId } : null);
|
|
14
|
+
let shown = recordOf(form.getState());
|
|
15
|
+
let status = form.getState().status;
|
|
16
|
+
const chatter = mountChatter(element, { ...options, record: shown });
|
|
17
|
+
const unsubscribe = form.subscribe((state) => {
|
|
18
|
+
const next = recordOf(state);
|
|
19
|
+
if (next?.id !== shown?.id) {
|
|
20
|
+
shown = next;
|
|
21
|
+
void chatter.setRecord(next);
|
|
22
|
+
}
|
|
23
|
+
else if (state.status === 'saved' && status !== 'saved') {
|
|
24
|
+
void chatter.refresh();
|
|
25
|
+
}
|
|
26
|
+
status = state.status;
|
|
27
|
+
});
|
|
28
|
+
return () => {
|
|
29
|
+
unsubscribe();
|
|
30
|
+
chatter.destroy();
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=slot.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot.mjs","sourceRoot":"","sources":["../../../../../libs/chatter/src/lib/slot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAuB,MAAM,WAAW,CAAC;AAQ9D;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,CAAC,KAAgB,EAAoB,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClI,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC;QACpC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,IAAI,EAAE,EAAE,KAAK,KAAK,EAAE,EAAE,EAAE,CAAC;gBAC3B,KAAK,GAAG,IAAI,CAAC;gBACb,KAAK,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC1D,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzB,CAAC;YACD,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the chatter reaches the server: an object the app writes for its own
|
|
3
|
+
* backend, as it writes a data source. Reading and posting messages are all a
|
|
4
|
+
* chatter needs; each other method adds a part (uploads, reactions, mentions,
|
|
5
|
+
* activities, followers), and a part whose method is missing is not shown.
|
|
6
|
+
*/
|
|
7
|
+
export type ChatterId = string | number;
|
|
8
|
+
/** The record the conversation is about. */
|
|
9
|
+
export interface RecordRef {
|
|
10
|
+
model: string;
|
|
11
|
+
id: ChatterId;
|
|
12
|
+
}
|
|
13
|
+
export interface Person {
|
|
14
|
+
id: ChatterId;
|
|
15
|
+
name: string;
|
|
16
|
+
/** An image address; without one, the person's initials stand in. */
|
|
17
|
+
avatar?: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface Attachment {
|
|
20
|
+
id: ChatterId;
|
|
21
|
+
name: string;
|
|
22
|
+
/** Its media type, such as `image/png`: an image gets a preview. */
|
|
23
|
+
type: string;
|
|
24
|
+
size: number;
|
|
25
|
+
/** Where to open or download it. */
|
|
26
|
+
url?: string | null;
|
|
27
|
+
}
|
|
28
|
+
export interface Reaction {
|
|
29
|
+
emoji: string;
|
|
30
|
+
count: number;
|
|
31
|
+
/** Whether the person using the chatter is among those who reacted. */
|
|
32
|
+
mine: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** A field's change, as a record's history keeps it. */
|
|
35
|
+
export interface TrackedChange {
|
|
36
|
+
field: string;
|
|
37
|
+
label: string;
|
|
38
|
+
from: string | null;
|
|
39
|
+
to: string | null;
|
|
40
|
+
}
|
|
41
|
+
export interface ChatterMessage {
|
|
42
|
+
id: ChatterId;
|
|
43
|
+
/** A message the record's followers get, a note for the team only, or an event such as a tracked change. */
|
|
44
|
+
kind: 'message' | 'note' | 'event';
|
|
45
|
+
author: Person | null;
|
|
46
|
+
/** When it was posted, as an ISO date and time. */
|
|
47
|
+
date: string;
|
|
48
|
+
/** HTML. The chatter cleans it before it shows it. */
|
|
49
|
+
body: string;
|
|
50
|
+
tracking?: TrackedChange[];
|
|
51
|
+
attachments?: Attachment[];
|
|
52
|
+
reactions?: Reaction[];
|
|
53
|
+
/** The message this one answers. */
|
|
54
|
+
parentId?: ChatterId | null;
|
|
55
|
+
/** The people it @mentions. */
|
|
56
|
+
mentions?: Person[];
|
|
57
|
+
}
|
|
58
|
+
export interface NewMessage {
|
|
59
|
+
kind: 'message' | 'note';
|
|
60
|
+
/** HTML made from what was typed, every character escaped. */
|
|
61
|
+
body: string;
|
|
62
|
+
attachments?: Attachment[];
|
|
63
|
+
parentId?: ChatterId | null;
|
|
64
|
+
/** The people @mentioned. */
|
|
65
|
+
mentions?: Person[];
|
|
66
|
+
}
|
|
67
|
+
export interface ActivityType {
|
|
68
|
+
id: ChatterId;
|
|
69
|
+
name: string;
|
|
70
|
+
/** An icon by name, one of Fieldia's own or the app's. */
|
|
71
|
+
icon?: string;
|
|
72
|
+
/** Days from today an activity of this type is due, unless a date is chosen. */
|
|
73
|
+
daysUntilDue?: number;
|
|
74
|
+
}
|
|
75
|
+
export interface Activity {
|
|
76
|
+
id: ChatterId;
|
|
77
|
+
type: ActivityType;
|
|
78
|
+
summary?: string | null;
|
|
79
|
+
note?: string | null;
|
|
80
|
+
/** The day it is due: `YYYY-MM-DD`. */
|
|
81
|
+
due: string;
|
|
82
|
+
assignee: Person;
|
|
83
|
+
}
|
|
84
|
+
export interface NewActivity {
|
|
85
|
+
typeId: ChatterId;
|
|
86
|
+
summary?: string;
|
|
87
|
+
note?: string;
|
|
88
|
+
due: string;
|
|
89
|
+
assigneeId: ChatterId;
|
|
90
|
+
}
|
|
91
|
+
export interface Follower {
|
|
92
|
+
id: ChatterId;
|
|
93
|
+
person: Person;
|
|
94
|
+
}
|
|
95
|
+
export interface ChatterSource {
|
|
96
|
+
/** The record's messages, notes and events, newest first. */
|
|
97
|
+
messages(record: RecordRef): Promise<ChatterMessage[]>;
|
|
98
|
+
post(record: RecordRef, message: NewMessage): Promise<ChatterMessage>;
|
|
99
|
+
/** Store a file, to send with a message. */
|
|
100
|
+
upload?(record: RecordRef, file: File): Promise<Attachment>;
|
|
101
|
+
/** Add the person's reaction, or take it away when it is there already. Returns the message's reactions. */
|
|
102
|
+
react?(record: RecordRef, messageId: ChatterId, emoji: string): Promise<Reaction[]>;
|
|
103
|
+
/** People to @mention, to give an activity to, or to add as followers. */
|
|
104
|
+
people?(query: string): Promise<Person[]>;
|
|
105
|
+
activityTypes?(): Promise<ActivityType[]>;
|
|
106
|
+
activities?(record: RecordRef): Promise<Activity[]>;
|
|
107
|
+
schedule?(record: RecordRef, activity: NewActivity): Promise<Activity>;
|
|
108
|
+
/** Done, with what came of it: the backend usually posts it as a message. */
|
|
109
|
+
markDone?(record: RecordRef, activityId: ChatterId, feedback?: string): Promise<void>;
|
|
110
|
+
cancel?(record: RecordRef, activityId: ChatterId): Promise<void>;
|
|
111
|
+
followers?(record: RecordRef): Promise<Follower[]>;
|
|
112
|
+
follow?(record: RecordRef, personId: ChatterId): Promise<Follower>;
|
|
113
|
+
unfollow?(record: RecordRef, followerId: ChatterId): Promise<void>;
|
|
114
|
+
}
|