@joewinke/jatui 0.35.0 → 0.36.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/CLAUDE.md +9 -4
- package/dist/actions/reveal.d.ts +72 -11
- package/dist/actions/reveal.js +103 -14
- package/dist/components/AudioRecorder.svelte +23 -1
- package/dist/components/AudioRecorder.svelte.d.ts +13 -1
- package/dist/components/BulkActionBar.svelte +17 -2
- package/dist/components/BulkActionBar.svelte.d.ts +5 -0
- package/dist/components/Drawer.svelte +20 -1
- package/dist/components/Drawer.svelte.d.ts +11 -0
- package/dist/components/FloatingActionBar.svelte +26 -11
- package/dist/components/FloatingActionBar.svelte.d.ts +5 -0
- package/dist/components/KeyboardShortcutsOverlay.svelte +180 -7
- package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +21 -0
- package/dist/components/ListenControl.svelte +455 -152
- package/dist/components/ListenControl.svelte.d.ts +12 -3
- package/dist/components/ThumbnailGrid.svelte +34 -7
- package/dist/components/ThumbnailGrid.svelte.d.ts +17 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/motion/index.d.ts +1 -1
- package/dist/motion/index.js +1 -1
- package/dist/utils/audioRecorder.d.ts +6 -1
- package/dist/utils/audioRecorder.js +5 -0
- package/dist/utils/audioRecorderCore.d.ts +34 -0
- package/dist/utils/audioRecorderCore.js +43 -6
- package/dist/utils/keyboardShortcutHub.d.ts +73 -0
- package/dist/utils/keyboardShortcutHub.js +89 -0
- package/dist/utils/mentionParser.d.ts +44 -2
- package/dist/utils/mentionParser.js +84 -4
- package/package.json +2 -1
|
@@ -4,8 +4,16 @@
|
|
|
4
4
|
* Handles parsing and rendering of @-mentions in messages.
|
|
5
5
|
* Format: [@Display Name](type:id) -> clickable links
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* URL routing has three layers (most specific first):
|
|
8
|
+
* 1. the `urlGenerator` parameter on a given parse/render call
|
|
9
|
+
* 2. a per-type registration — registerMentionType(type, generator) —
|
|
10
|
+
* so each mention type carries its own routing (e.g. @agent mentions
|
|
11
|
+
* route to /admin/settings/agent while @user routes elsewhere)
|
|
12
|
+
* 3. the single app-wide default — setMentionUrlGenerator
|
|
13
|
+
*
|
|
14
|
+
* The per-type registry is what lets a consuming app retire a local
|
|
15
|
+
* mentionParser copy (mos-i8nnd.18): one default generator cannot express
|
|
16
|
+
* per-type routing.
|
|
9
17
|
*/
|
|
10
18
|
export interface MentionMatch {
|
|
11
19
|
type: string;
|
|
@@ -17,6 +25,22 @@ export interface MentionMatch {
|
|
|
17
25
|
fullMatch: string;
|
|
18
26
|
}
|
|
19
27
|
export type MentionUrlGenerator = (type: string, id: string) => string;
|
|
28
|
+
/** The mention type used to reference agents (extractAgentMentions). */
|
|
29
|
+
export declare const AGENT_MENTION_TYPE = "agent";
|
|
30
|
+
/** Per-type registration record held by the registry. */
|
|
31
|
+
export interface MentionTypeConfig {
|
|
32
|
+
urlGenerator: MentionUrlGenerator;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Register a URL generator for a specific mention type.
|
|
36
|
+
*
|
|
37
|
+
* Call once at app startup per routed type (e.g. registerMentionType('agent',
|
|
38
|
+
* () => '/admin/settings/agent')). Re-registering a type replaces its
|
|
39
|
+
* generator; the returned function unregisters exactly that registration.
|
|
40
|
+
* The type must be an identifier token — the mention regex only accepts
|
|
41
|
+
* `[A-Za-z0-9_-]+`, so anything else could never match a mention.
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerMentionType(type: string, urlGenerator: MentionUrlGenerator): () => void;
|
|
20
44
|
/**
|
|
21
45
|
* Set the default URL generator for mentions.
|
|
22
46
|
* Call this once at app startup to configure mention link routing.
|
|
@@ -73,6 +97,24 @@ export declare function replaceMentionInContent(content: string, startIndex: num
|
|
|
73
97
|
newContent: string;
|
|
74
98
|
newCursorPosition: number;
|
|
75
99
|
};
|
|
100
|
+
/**
|
|
101
|
+
* Extract only agent mentions (type='agent').
|
|
102
|
+
*/
|
|
103
|
+
export declare function extractAgentMentions(content: string): MentionMatch[];
|
|
104
|
+
/**
|
|
105
|
+
* Cheap boolean check — does the content contain at least one mention?
|
|
106
|
+
*/
|
|
107
|
+
export declare function hasMentions(content: string): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Unique ids of @user mentions, in order of first appearance.
|
|
110
|
+
* Agent mentions are separate — use extractAgentMentions.
|
|
111
|
+
*/
|
|
112
|
+
export declare function getMentionedUserIds(content: string): string[];
|
|
113
|
+
/**
|
|
114
|
+
* Mentions deduped by type+id (first occurrence wins, appearance order
|
|
115
|
+
* preserved), optionally filtered to a single type.
|
|
116
|
+
*/
|
|
117
|
+
export declare function getUniqueMentionsByType(content: string, type?: string): MentionMatch[];
|
|
76
118
|
/**
|
|
77
119
|
* Simple HTML escape function
|
|
78
120
|
*/
|
|
@@ -4,9 +4,43 @@
|
|
|
4
4
|
* Handles parsing and rendering of @-mentions in messages.
|
|
5
5
|
* Format: [@Display Name](type:id) -> clickable links
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* URL routing has three layers (most specific first):
|
|
8
|
+
* 1. the `urlGenerator` parameter on a given parse/render call
|
|
9
|
+
* 2. a per-type registration — registerMentionType(type, generator) —
|
|
10
|
+
* so each mention type carries its own routing (e.g. @agent mentions
|
|
11
|
+
* route to /admin/settings/agent while @user routes elsewhere)
|
|
12
|
+
* 3. the single app-wide default — setMentionUrlGenerator
|
|
13
|
+
*
|
|
14
|
+
* The per-type registry is what lets a consuming app retire a local
|
|
15
|
+
* mentionParser copy (mos-i8nnd.18): one default generator cannot express
|
|
16
|
+
* per-type routing.
|
|
17
|
+
*/
|
|
18
|
+
/** The mention type used to reference agents (extractAgentMentions). */
|
|
19
|
+
export const AGENT_MENTION_TYPE = 'agent';
|
|
20
|
+
// Per-type registry — populated by registerMentionType; wins over the
|
|
21
|
+
// app-wide default for that type, loses to an explicit generator argument.
|
|
22
|
+
const mentionTypes = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* Register a URL generator for a specific mention type.
|
|
25
|
+
*
|
|
26
|
+
* Call once at app startup per routed type (e.g. registerMentionType('agent',
|
|
27
|
+
* () => '/admin/settings/agent')). Re-registering a type replaces its
|
|
28
|
+
* generator; the returned function unregisters exactly that registration.
|
|
29
|
+
* The type must be an identifier token — the mention regex only accepts
|
|
30
|
+
* `[A-Za-z0-9_-]+`, so anything else could never match a mention.
|
|
9
31
|
*/
|
|
32
|
+
export function registerMentionType(type, urlGenerator) {
|
|
33
|
+
if (!/^[A-Za-z0-9_-]+$/.test(type)) {
|
|
34
|
+
throw new TypeError(`mention type ${JSON.stringify(type)} must match /^[A-Za-z0-9_-]+$/ — ` +
|
|
35
|
+
'the mention regex only matches identifier tokens');
|
|
36
|
+
}
|
|
37
|
+
mentionTypes.set(type, { urlGenerator });
|
|
38
|
+
return () => {
|
|
39
|
+
// Only remove OUR registration — a later re-registration must survive.
|
|
40
|
+
if (mentionTypes.get(type)?.urlGenerator === urlGenerator)
|
|
41
|
+
mentionTypes.delete(type);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
10
44
|
// Regex to match mention pattern: [@Display Name](type:id)
|
|
11
45
|
//
|
|
12
46
|
// `type` is an identifier token, never free text (mos-3xvn1): it lands in
|
|
@@ -28,7 +62,6 @@ export function setMentionUrlGenerator(generator) {
|
|
|
28
62
|
*/
|
|
29
63
|
export function parseMentions(content, urlGenerator) {
|
|
30
64
|
const mentions = [];
|
|
31
|
-
const gen = urlGenerator ?? defaultUrlGenerator;
|
|
32
65
|
let match;
|
|
33
66
|
MENTION_REGEX.lastIndex = 0;
|
|
34
67
|
while ((match = MENTION_REGEX.exec(content)) !== null) {
|
|
@@ -37,7 +70,9 @@ export function parseMentions(content, urlGenerator) {
|
|
|
37
70
|
type,
|
|
38
71
|
id,
|
|
39
72
|
displayName,
|
|
40
|
-
|
|
73
|
+
// Resolution: explicit call-site generator > per-type registered
|
|
74
|
+
// generator > the app-wide default.
|
|
75
|
+
url: (urlGenerator ?? mentionTypes.get(type)?.urlGenerator ?? defaultUrlGenerator)(type, id),
|
|
41
76
|
startIndex: match.index,
|
|
42
77
|
endIndex: match.index + fullMatch.length,
|
|
43
78
|
fullMatch
|
|
@@ -147,6 +182,51 @@ export function replaceMentionInContent(content, startIndex, endIndex, mentionSt
|
|
|
147
182
|
const newCursorPosition = startIndex + mentionString.length;
|
|
148
183
|
return { newContent, newCursorPosition };
|
|
149
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Extract only agent mentions (type='agent').
|
|
187
|
+
*/
|
|
188
|
+
export function extractAgentMentions(content) {
|
|
189
|
+
return parseMentions(content).filter((mention) => mention.type === AGENT_MENTION_TYPE);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Cheap boolean check — does the content contain at least one mention?
|
|
193
|
+
*/
|
|
194
|
+
export function hasMentions(content) {
|
|
195
|
+
MENTION_REGEX.lastIndex = 0;
|
|
196
|
+
return MENTION_REGEX.test(content);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Unique ids of @user mentions, in order of first appearance.
|
|
200
|
+
* Agent mentions are separate — use extractAgentMentions.
|
|
201
|
+
*/
|
|
202
|
+
export function getMentionedUserIds(content) {
|
|
203
|
+
const ids = [];
|
|
204
|
+
for (const mention of parseMentions(content)) {
|
|
205
|
+
if (mention.type !== 'user')
|
|
206
|
+
continue;
|
|
207
|
+
if (!ids.includes(mention.id))
|
|
208
|
+
ids.push(mention.id);
|
|
209
|
+
}
|
|
210
|
+
return ids;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Mentions deduped by type+id (first occurrence wins, appearance order
|
|
214
|
+
* preserved), optionally filtered to a single type.
|
|
215
|
+
*/
|
|
216
|
+
export function getUniqueMentionsByType(content, type) {
|
|
217
|
+
const seen = new Set();
|
|
218
|
+
const out = [];
|
|
219
|
+
for (const mention of parseMentions(content)) {
|
|
220
|
+
if (type && mention.type !== type)
|
|
221
|
+
continue;
|
|
222
|
+
const key = `${mention.type}:${mention.id}`;
|
|
223
|
+
if (seen.has(key))
|
|
224
|
+
continue;
|
|
225
|
+
seen.add(key);
|
|
226
|
+
out.push(mention);
|
|
227
|
+
}
|
|
228
|
+
return out;
|
|
229
|
+
}
|
|
150
230
|
/**
|
|
151
231
|
* Simple HTML escape function
|
|
152
232
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joewinke/jatui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared Svelte 5 component library for JAT projects",
|
|
6
6
|
"type": "module",
|
|
@@ -188,6 +188,7 @@
|
|
|
188
188
|
"lenis": "^1.3.25",
|
|
189
189
|
"livekit-client": "^2.20.1",
|
|
190
190
|
"motion": "^12.42.2",
|
|
191
|
+
"@playwright/test": "^1.62.1",
|
|
191
192
|
"playwright": "^1.62.1",
|
|
192
193
|
"svelte": "^5.0.0",
|
|
193
194
|
"tailwindcss": "^4.0.0",
|