@intentface/chat 0.1.0 → 0.1.1
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/README.md +6 -6
- package/dist/chip-markdown.js +3 -1
- package/dist/composer/prefix-detection.js +14 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @intentface/chat
|
|
2
2
|
|
|
3
3
|
Headless chat UI primitives for React — the behavior, state, and wire formats
|
|
4
|
-
for building AI chat interfaces, with no styling of their own.
|
|
5
|
-
the shadcn-style styled layer from the [docs](https://intentface.dev/docs), or
|
|
6
|
-
bring your own.
|
|
4
|
+
for building AI chat interfaces, with no styling of their own.
|
|
7
5
|
|
|
8
|
-
This is the Base UI model applied to chat: **
|
|
9
|
-
|
|
6
|
+
This is the Base UI model applied to chat: **the package owns behavior, you own
|
|
7
|
+
every class.** There is no pre-styled `@intentface/chat` package. The demos on
|
|
8
|
+
each [docs](https://intentface.dev/docs) page show how the parts fit together
|
|
9
|
+
and are meant to be copied and restyled.
|
|
10
10
|
|
|
11
11
|
## Status
|
|
12
12
|
|
|
@@ -100,7 +100,7 @@ directive and import fine anywhere.
|
|
|
100
100
|
|
|
101
101
|
## Docs
|
|
102
102
|
|
|
103
|
-
Full guides, live
|
|
103
|
+
Full guides, live demos, and the API reference at
|
|
104
104
|
[intentface.dev/docs](https://intentface.dev/docs).
|
|
105
105
|
|
|
106
106
|
## License
|
package/dist/chip-markdown.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// token, so a rendered message reconstructs the chip from its own text
|
|
4
4
|
// alone — no sidecar metadata array. Presentation that's derivable at render
|
|
5
5
|
// time (e.g. a per-prefix variant) is the renderer's job, not wire data.
|
|
6
|
-
|
|
6
|
+
// Every class excludes "[" so no group can consume past the next one — without
|
|
7
|
+
// that this backtracks quadratically, and message text is untrusted.
|
|
8
|
+
export const CHIP_REF_PATTERN = /\[([^[\]]+)\]\(chip:([^[:)]+):([^[)?]+)(?:\?([^[)]*))?\)/g;
|
|
7
9
|
export const escapeMarkdownLink = (input) => input.replace(/[[\]()\\]/g, (match) => `\\${match}`);
|
|
8
10
|
// Tolerate legacy/un-encoded values — a stray "%" would otherwise throw and
|
|
9
11
|
// take the whole message render down with it.
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
// active-token state shape and the pure scan that derives it from the text
|
|
3
3
|
// around the caret. Sticky range tracking and dismissal memory live one layer
|
|
4
4
|
// up, in trigger-tracker.ts.
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Types & constants
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Non-global: `.test` on a global regex advances lastIndex between calls.
|
|
9
|
+
const WHITESPACE = /\s/;
|
|
5
10
|
export const CLOSED_COMMAND_STATE = {
|
|
6
11
|
isOpen: false,
|
|
7
12
|
trigger: null,
|
|
@@ -34,16 +39,20 @@ export const detectActivePrefix = (args) => {
|
|
|
34
39
|
// taken from both sides of the caret so it stays whole as the caret moves
|
|
35
40
|
// within it. Text chars map 1:1 to positions and an atomic chip can never
|
|
36
41
|
// sit inside a run, so the run length is the position delta on each side.
|
|
37
|
-
|
|
42
|
+
// Scanned backwards, not /\S*$/ — that backtracks quadratically when the
|
|
43
|
+
// text ends in whitespace, on a path that runs per keystroke.
|
|
44
|
+
let runStart = textBeforeCursor.length;
|
|
45
|
+
while (runStart > 0 && !WHITESPACE.test(textBeforeCursor[runStart - 1]))
|
|
46
|
+
runStart--;
|
|
47
|
+
const leftRun = textBeforeCursor.slice(runStart);
|
|
48
|
+
// Start-anchored, so this one cannot backtrack.
|
|
38
49
|
const rightRun = textAfterCursor.match(/^\S*/)?.[0] ?? "";
|
|
39
50
|
const runText = leftRun + rightRun;
|
|
40
51
|
if (!runText.startsWith(entry.prefix))
|
|
41
52
|
continue;
|
|
42
53
|
// The prefix must sit at a word boundary: line start or after whitespace.
|
|
43
|
-
const charBeforeRun = textBeforeCursor
|
|
44
|
-
|
|
45
|
-
.at(-1);
|
|
46
|
-
if (charBeforeRun !== undefined && !/\s/.test(charBeforeRun))
|
|
54
|
+
const charBeforeRun = runStart > 0 ? textBeforeCursor[runStart - 1] : undefined;
|
|
55
|
+
if (charBeforeRun !== undefined && !WHITESPACE.test(charBeforeRun))
|
|
47
56
|
continue;
|
|
48
57
|
return {
|
|
49
58
|
isOpen: true,
|
package/package.json
CHANGED