@intentface/ui 0.0.0 → 0.7.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 +145 -2
- package/dist/ask-user/ask-user.d.ts +104 -0
- package/dist/ask-user/ask-user.js +245 -0
- package/dist/ask-user/index.d.ts +3 -0
- package/dist/ask-user/index.js +3 -0
- package/dist/ask-user/index.parts.d.ts +1 -0
- package/dist/ask-user/index.parts.js +5 -0
- package/dist/attachments/attachments.d.ts +73 -0
- package/dist/attachments/attachments.js +121 -0
- package/dist/attachments/index.d.ts +3 -0
- package/dist/attachments/index.js +3 -0
- package/dist/attachments/index.parts.d.ts +1 -0
- package/dist/attachments/index.parts.js +5 -0
- package/dist/chip/chip.d.ts +45 -0
- package/dist/chip/chip.js +43 -0
- package/dist/chip/index.d.ts +2 -0
- package/dist/chip/index.js +2 -0
- package/dist/chip/index.parts.d.ts +1 -0
- package/dist/chip/index.parts.js +5 -0
- package/dist/chip-markdown.d.ts +25 -0
- package/dist/chip-markdown.js +54 -0
- package/dist/composer/actions.d.ts +35 -0
- package/dist/composer/actions.js +76 -0
- package/dist/composer/ask-user-machine.d.ts +52 -0
- package/dist/composer/ask-user-machine.js +164 -0
- package/dist/composer/attachments-machine.d.ts +34 -0
- package/dist/composer/attachments-machine.js +91 -0
- package/dist/composer/attachments.d.ts +16 -0
- package/dist/composer/attachments.js +32 -0
- package/dist/composer/command-list.d.ts +49 -0
- package/dist/composer/command-list.js +360 -0
- package/dist/composer/commands.d.ts +28 -0
- package/dist/composer/commands.js +56 -0
- package/dist/composer/container.d.ts +3 -0
- package/dist/composer/container.js +32 -0
- package/dist/composer/controller.d.ts +3 -0
- package/dist/composer/controller.js +6 -0
- package/dist/composer/editor-dom.d.ts +57 -0
- package/dist/composer/editor-dom.js +517 -0
- package/dist/composer/fuzzy.d.ts +4 -0
- package/dist/composer/fuzzy.js +49 -0
- package/dist/composer/index.d.ts +25 -0
- package/dist/composer/index.js +13 -0
- package/dist/composer/index.parts.d.ts +11 -0
- package/dist/composer/index.parts.js +15 -0
- package/dist/composer/internals.d.ts +30 -0
- package/dist/composer/internals.js +102 -0
- package/dist/composer/keyboard.d.ts +61 -0
- package/dist/composer/keyboard.js +75 -0
- package/dist/composer/panel.d.ts +28 -0
- package/dist/composer/panel.js +76 -0
- package/dist/composer/placeholder.d.ts +10 -0
- package/dist/composer/placeholder.js +8 -0
- package/dist/composer/popover.d.ts +12 -0
- package/dist/composer/popover.js +62 -0
- package/dist/composer/prefix-detection.d.ts +23 -0
- package/dist/composer/prefix-detection.js +67 -0
- package/dist/composer/root.d.ts +21 -0
- package/dist/composer/root.js +124 -0
- package/dist/composer/segments.d.ts +108 -0
- package/dist/composer/segments.js +366 -0
- package/dist/composer/store.d.ts +98 -0
- package/dist/composer/store.js +457 -0
- package/dist/composer/textarea.d.ts +39 -0
- package/dist/composer/textarea.js +64 -0
- package/dist/composer/trigger-tracker.d.ts +12 -0
- package/dist/composer/trigger-tracker.js +90 -0
- package/dist/composer/types.d.ts +127 -0
- package/dist/composer/types.js +4 -0
- package/dist/composer/use-composer-editor.d.ts +43 -0
- package/dist/composer/use-composer-editor.js +653 -0
- package/dist/generative/catalog.d.ts +177 -0
- package/dist/generative/catalog.js +20 -0
- package/dist/generative/index.d.ts +26 -0
- package/dist/generative/index.js +20 -0
- package/dist/generative/json-schema.d.ts +45 -0
- package/dist/generative/json-schema.js +216 -0
- package/dist/generative/markdown.d.ts +21 -0
- package/dist/generative/markdown.js +76 -0
- package/dist/generative/tree.d.ts +56 -0
- package/dist/generative/tree.js +365 -0
- package/dist/generative/use-tree.d.ts +12 -0
- package/dist/generative/use-tree.js +64 -0
- package/dist/internal/change-event-details.d.ts +12 -0
- package/dist/internal/change-event-details.js +16 -0
- package/dist/internal/collapsible.d.ts +22 -0
- package/dist/internal/collapsible.js +94 -0
- package/dist/internal/collection.d.ts +32 -0
- package/dist/internal/collection.js +72 -0
- package/dist/internal/iso-layout-effect.d.ts +2 -0
- package/dist/internal/iso-layout-effect.js +6 -0
- package/dist/internal/portal.d.ts +6 -0
- package/dist/internal/portal.js +18 -0
- package/dist/internal/primitive-props.d.ts +4 -0
- package/dist/internal/primitive-props.js +3 -0
- package/dist/internal/render/baseTypes.d.ts +18 -0
- package/dist/internal/render/baseTypes.js +4 -0
- package/dist/internal/render/empty.d.ts +3 -0
- package/dist/internal/render/empty.js +5 -0
- package/dist/internal/render/getReactElementRef.d.ts +5 -0
- package/dist/internal/render/getReactElementRef.js +15 -0
- package/dist/internal/render/getStateAttributesProps.d.ts +4 -0
- package/dist/internal/render/getStateAttributesProps.js +23 -0
- package/dist/internal/render/mergeObjects.d.ts +1 -0
- package/dist/internal/render/mergeObjects.js +14 -0
- package/dist/internal/render/mergeProps.d.ts +55 -0
- package/dist/internal/render/mergeProps.js +183 -0
- package/dist/internal/render/positioning.d.ts +33 -0
- package/dist/internal/render/positioning.js +112 -0
- package/dist/internal/render/reactVersion.d.ts +3 -0
- package/dist/internal/render/reactVersion.js +7 -0
- package/dist/internal/render/resolveClassName.d.ts +8 -0
- package/dist/internal/render/resolveClassName.js +12 -0
- package/dist/internal/render/resolveStyle.d.ts +8 -0
- package/dist/internal/render/resolveStyle.js +12 -0
- package/dist/internal/render/transition.d.ts +47 -0
- package/dist/internal/render/transition.js +259 -0
- package/dist/internal/render/types.d.ts +74 -0
- package/dist/internal/render/types.js +3 -0
- package/dist/internal/render/useMergedRefs.d.ts +21 -0
- package/dist/internal/render/useMergedRefs.js +102 -0
- package/dist/internal/render/useRefWithInit.d.ts +10 -0
- package/dist/internal/render/useRefWithInit.js +12 -0
- package/dist/internal/render/useRender.d.ts +71 -0
- package/dist/internal/render/useRender.js +12 -0
- package/dist/internal/render/useRenderElement.d.ts +62 -0
- package/dist/internal/render/useRenderElement.js +157 -0
- package/dist/internal/render/warn.d.ts +1 -0
- package/dist/internal/render/warn.js +15 -0
- package/dist/internal/safe-polygon.d.ts +21 -0
- package/dist/internal/safe-polygon.js +179 -0
- package/dist/internal/scroll-into-view-within.d.ts +1 -0
- package/dist/internal/scroll-into-view-within.js +26 -0
- package/dist/internal/standard-schema.d.ts +38 -0
- package/dist/internal/standard-schema.js +4 -0
- package/dist/internal/state-mappings.d.ts +8 -0
- package/dist/internal/state-mappings.js +17 -0
- package/dist/internal/use-controlled.d.ts +19 -0
- package/dist/internal/use-controlled.js +33 -0
- package/dist/message/index.d.ts +3 -0
- package/dist/message/index.js +3 -0
- package/dist/message/index.parts.d.ts +1 -0
- package/dist/message/index.parts.js +5 -0
- package/dist/message/message.d.ts +58 -0
- package/dist/message/message.js +93 -0
- package/dist/message-utils.d.ts +55 -0
- package/dist/message-utils.js +79 -0
- package/dist/nav/index.d.ts +4 -0
- package/dist/nav/index.js +5 -0
- package/dist/nav/index.parts.d.ts +3 -0
- package/dist/nav/index.parts.js +7 -0
- package/dist/nav/nav.d.ts +152 -0
- package/dist/nav/nav.js +660 -0
- package/dist/nav/store.d.ts +50 -0
- package/dist/nav/store.js +95 -0
- package/dist/reasoning/index.d.ts +3 -0
- package/dist/reasoning/index.js +3 -0
- package/dist/reasoning/index.parts.d.ts +1 -0
- package/dist/reasoning/index.parts.js +5 -0
- package/dist/reasoning/reasoning.d.ts +38 -0
- package/dist/reasoning/reasoning.js +67 -0
- package/dist/shell/index.d.ts +5 -0
- package/dist/shell/index.js +5 -0
- package/dist/shell/index.parts.d.ts +3 -0
- package/dist/shell/index.parts.js +7 -0
- package/dist/shell/shell.d.ts +108 -0
- package/dist/shell/shell.js +390 -0
- package/dist/shell/store.d.ts +112 -0
- package/dist/shell/store.js +134 -0
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +2 -0
- package/dist/steps/index.parts.d.ts +1 -0
- package/dist/steps/index.parts.js +5 -0
- package/dist/steps/steps.d.ts +90 -0
- package/dist/steps/steps.js +116 -0
- package/dist/tabs/anchored.d.ts +59 -0
- package/dist/tabs/anchored.js +109 -0
- package/dist/tabs/hover.d.ts +33 -0
- package/dist/tabs/hover.js +169 -0
- package/dist/tabs/index.d.ts +5 -0
- package/dist/tabs/index.js +4 -0
- package/dist/tabs/index.parts.d.ts +4 -0
- package/dist/tabs/index.parts.js +8 -0
- package/dist/tabs/store.d.ts +131 -0
- package/dist/tabs/store.js +248 -0
- package/dist/tabs/tabs.d.ts +217 -0
- package/dist/tabs/tabs.js +458 -0
- package/dist/thread/geometry.d.ts +23 -0
- package/dist/thread/geometry.js +48 -0
- package/dist/thread/index.d.ts +4 -0
- package/dist/thread/index.js +3 -0
- package/dist/thread/index.parts.d.ts +1 -0
- package/dist/thread/index.parts.js +5 -0
- package/dist/thread/stores.d.ts +21 -0
- package/dist/thread/stores.js +63 -0
- package/dist/thread/thread.d.ts +57 -0
- package/dist/thread/thread.js +663 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +17 -0
- package/package.json +120 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Prefix detection — the engine-agnostic kernel of the command system: the
|
|
2
|
+
// active-token state shape and the pure scan that derives it from the text
|
|
3
|
+
// around the caret. Sticky range tracking and dismissal memory live one layer
|
|
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/;
|
|
10
|
+
export const CLOSED_COMMAND_STATE = {
|
|
11
|
+
isOpen: false,
|
|
12
|
+
trigger: null,
|
|
13
|
+
query: "",
|
|
14
|
+
triggerStartPosition: 0,
|
|
15
|
+
triggerEndPosition: 0,
|
|
16
|
+
dismissedAt: null,
|
|
17
|
+
};
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Prefix detection — scan the block around the caret for a registered trigger
|
|
20
|
+
// and derive the active-token state (pure; engine integrations call it).
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
export const detectActivePrefix = (args) => {
|
|
23
|
+
const { registered, blockStart, blockEnd, cursorPosition, textBeforeCursor, textAfterCursor, fullDocText, } = args;
|
|
24
|
+
for (const entry of registered) {
|
|
25
|
+
if (entry.triggerRule === "doc-start") {
|
|
26
|
+
if (fullDocText.startsWith(entry.prefix)) {
|
|
27
|
+
return {
|
|
28
|
+
isOpen: true,
|
|
29
|
+
trigger: entry.prefix,
|
|
30
|
+
query: fullDocText.slice(entry.prefix.length),
|
|
31
|
+
triggerStartPosition: blockStart,
|
|
32
|
+
triggerEndPosition: blockEnd,
|
|
33
|
+
dismissedAt: null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// The token is the contiguous non-whitespace run the caret sits inside,
|
|
39
|
+
// taken from both sides of the caret so it stays whole as the caret moves
|
|
40
|
+
// within it. Text chars map 1:1 to positions and an atomic chip can never
|
|
41
|
+
// sit inside a run, so the run length is the position delta on each side.
|
|
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.
|
|
49
|
+
const rightRun = textAfterCursor.match(/^\S*/)?.[0] ?? "";
|
|
50
|
+
const runText = leftRun + rightRun;
|
|
51
|
+
if (!runText.startsWith(entry.prefix))
|
|
52
|
+
continue;
|
|
53
|
+
// The prefix must sit at a word boundary: line start or after whitespace.
|
|
54
|
+
const charBeforeRun = runStart > 0 ? textBeforeCursor[runStart - 1] : undefined;
|
|
55
|
+
if (charBeforeRun !== undefined && !WHITESPACE.test(charBeforeRun))
|
|
56
|
+
continue;
|
|
57
|
+
return {
|
|
58
|
+
isOpen: true,
|
|
59
|
+
trigger: entry.prefix,
|
|
60
|
+
query: runText.slice(entry.prefix.length),
|
|
61
|
+
triggerStartPosition: cursorPosition - leftRun.length,
|
|
62
|
+
triggerEndPosition: cursorPosition + rightRun.length,
|
|
63
|
+
dismissedAt: null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return CLOSED_COMMAND_STATE;
|
|
67
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PrimitiveProps } from "../internal/primitive-props.js";
|
|
2
|
+
import { type ComposerStore } from "./store.js";
|
|
3
|
+
import type { AskUserQuestion, ComposerCommandsMap, ComposerSnapshot, ComposerSubmitData } from "./types.js";
|
|
4
|
+
export type ComposerRootState = {
|
|
5
|
+
/** Present as data-submitting while a submission is in flight. */
|
|
6
|
+
submitting: boolean;
|
|
7
|
+
/** Present as data-dragging while files are dragged over the drop scope. */
|
|
8
|
+
dragging: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type ComposerRootProps = Omit<PrimitiveProps<"form", ComposerRootState>, "onSubmit"> & {
|
|
11
|
+
onSubmit?: (data: ComposerSubmitData) => void | Promise<void>;
|
|
12
|
+
isSubmitting?: boolean;
|
|
13
|
+
commands?: ComposerCommandsMap;
|
|
14
|
+
questions?: AskUserQuestion[];
|
|
15
|
+
defaultValue?: ComposerSnapshot;
|
|
16
|
+
value?: ComposerSnapshot;
|
|
17
|
+
onValueChange?: (snapshot: ComposerSnapshot) => void;
|
|
18
|
+
/** Explicit Composer.createStore() handle; defaults to a per-mount instance. */
|
|
19
|
+
store?: ComposerStore;
|
|
20
|
+
};
|
|
21
|
+
export declare const ComposerRoot: ({ onSubmit, isSubmitting, commands, questions, defaultValue, value, onValueChange, store: storeProp, className, render, style, ...elementProps }: ComposerRootProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
// Composer.Root — the form element that owns the submit flow, prop→store
|
|
4
|
+
// bridges, drag-drop scope, and the per-instance store resolution: an explicit
|
|
5
|
+
// Composer.createStore() handle via the store prop, or an instance created for
|
|
6
|
+
// this mount. Every bare <Composer> is fully isolated.
|
|
7
|
+
import { useEffect, useId, useMemo, useRef, useSyncExternalStore } from "react";
|
|
8
|
+
import { useRefWithInit } from "../internal/render/useRefWithInit.js";
|
|
9
|
+
import { useRenderElement } from "../internal/render/useRenderElement.js";
|
|
10
|
+
import { ComposerInternalsContext, useAsRef, useCommandRegistry, useComposerSnapshot, useDragDropFiles, } from "./internals.js";
|
|
11
|
+
import { ComposerStoreContext, createComposerStore } from "./store.js";
|
|
12
|
+
const EMPTY_COMMANDS = {};
|
|
13
|
+
export const ComposerRoot = ({ onSubmit, isSubmitting = false, commands = EMPTY_COMMANDS, questions, defaultValue, value, onValueChange, store: storeProp, className, render, style, ...elementProps }) => {
|
|
14
|
+
// SSR-stable per-mount id for the command listbox (aria-controls target +
|
|
15
|
+
// option-id root). Assigned onto the store in init below — the factory
|
|
16
|
+
// can't mint it because explicit handles are created outside React.
|
|
17
|
+
const listboxId = useId();
|
|
18
|
+
// Resolved once at mount (lazy-init ref, not reactive state): an explicit
|
|
19
|
+
// handle, or an instance this mount creates and owns. Swapping the store
|
|
20
|
+
// prop after mount is not supported.
|
|
21
|
+
const { store, ownsStore } = useRefWithInit(() => {
|
|
22
|
+
const resolved = storeProp ?? createComposerStore();
|
|
23
|
+
resolved.listboxId = listboxId;
|
|
24
|
+
return { store: resolved, ownsStore: !storeProp };
|
|
25
|
+
}).current;
|
|
26
|
+
const formRef = useRef(null);
|
|
27
|
+
const onSubmitRef = useAsRef(onSubmit);
|
|
28
|
+
// Register this mount on the store: answers submit through this mount's
|
|
29
|
+
// onSubmit. React also runs the cleanup without a real unmount (StrictMode,
|
|
30
|
+
// a hidden <Activity>), where the state lives on, so it only resets an owned
|
|
31
|
+
// store once React has removed the form — that happens on a real unmount only.
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const form = formRef.current;
|
|
34
|
+
store.submitAnswersRef.current = (answers) => onSubmitRef.current?.({ kind: "answers", answers });
|
|
35
|
+
return () => {
|
|
36
|
+
store.submitAnswersRef.current = null;
|
|
37
|
+
if (ownsStore && form && !form.isConnected)
|
|
38
|
+
store.reset();
|
|
39
|
+
};
|
|
40
|
+
}, [store, ownsStore]);
|
|
41
|
+
// Prop → store bridges. Actions and refs on the snapshot are identity-stable,
|
|
42
|
+
// so reading them here without subscribing is safe.
|
|
43
|
+
const { add: addAttachments, globalDropRef } = store.getSnapshot().attachments;
|
|
44
|
+
// Subscribed on the resolved store (not through useComposer — a `store` prop
|
|
45
|
+
// may differ from the nearest context) to surface drag state as data-dragging.
|
|
46
|
+
const getIsDragging = () => store.getSnapshot().attachments.isDragging;
|
|
47
|
+
const isDragging = useSyncExternalStore(store.subscribe, getIsDragging, getIsDragging);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
store.setIsSubmitting(isSubmitting);
|
|
50
|
+
}, [store, isSubmitting]);
|
|
51
|
+
// Sync the questions prop into the store and arm ask-user mode (editor blur
|
|
52
|
+
// + document-level keyboard handling) while questions are active.
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
store.setQuestions(questions ?? null);
|
|
55
|
+
if (!questions?.length)
|
|
56
|
+
return;
|
|
57
|
+
return store.activateAskUser();
|
|
58
|
+
}, [store, questions]);
|
|
59
|
+
const { getRegisteredPrefixes } = useCommandRegistry(commands);
|
|
60
|
+
useDragDropFiles({
|
|
61
|
+
rootRef: formRef,
|
|
62
|
+
globalDropRef,
|
|
63
|
+
onFiles: addAttachments,
|
|
64
|
+
setDragging: store.setDragging,
|
|
65
|
+
});
|
|
66
|
+
const { reportEditorUpdate } = useComposerSnapshot({
|
|
67
|
+
editorRef: store.editorRef,
|
|
68
|
+
defaultValue,
|
|
69
|
+
value,
|
|
70
|
+
onValueChange,
|
|
71
|
+
});
|
|
72
|
+
const handleFormSubmit = async (event) => {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
const { askUser, attachments } = store.getSnapshot();
|
|
75
|
+
if (askUser.questions?.length) {
|
|
76
|
+
askUser.continueStep(store.controller.getText());
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (isSubmitting)
|
|
80
|
+
return;
|
|
81
|
+
const serialized = store.controller.serialize();
|
|
82
|
+
const trimmedText = serialized.text.trim();
|
|
83
|
+
if (!trimmedText && !attachments.items.length)
|
|
84
|
+
return;
|
|
85
|
+
// Emit the generic attachment descriptors; the consumer's onSubmit adapts
|
|
86
|
+
// them to its wire format (e.g. FilePart via prepareAttachmentsForSend).
|
|
87
|
+
// Text may be empty on an attachments-only submit — any placeholder copy
|
|
88
|
+
// is the consumer's.
|
|
89
|
+
const files = attachments.items;
|
|
90
|
+
store.resetAttachments();
|
|
91
|
+
store.controller.clear();
|
|
92
|
+
await onSubmitRef.current?.({
|
|
93
|
+
kind: "message",
|
|
94
|
+
text: trimmedText,
|
|
95
|
+
files,
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
// Escape stops generating. React bubbles keys from portaled parts (a positioned
|
|
99
|
+
// Panel) here too; a consumer's onKeyDown can skip it with preventPrimitiveHandler().
|
|
100
|
+
const handleKeyDown = (event) => {
|
|
101
|
+
const stopGenerating = store.stopGeneratingRef.current;
|
|
102
|
+
if (event.key !== "Escape" || event.defaultPrevented || !stopGenerating)
|
|
103
|
+
return;
|
|
104
|
+
// While a question is open, Escape dismisses its step instead.
|
|
105
|
+
if (store.getSnapshot().askUser.questions?.length)
|
|
106
|
+
return;
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
stopGenerating();
|
|
109
|
+
};
|
|
110
|
+
const internalsValue = useMemo(() => ({
|
|
111
|
+
commands,
|
|
112
|
+
getRegisteredPrefixes,
|
|
113
|
+
reportEditorUpdate,
|
|
114
|
+
}), [commands, getRegisteredPrefixes, reportEditorUpdate]);
|
|
115
|
+
const formElement = useRenderElement("form", { className, render, style }, {
|
|
116
|
+
state: { submitting: isSubmitting, dragging: isDragging },
|
|
117
|
+
ref: formRef,
|
|
118
|
+
props: [
|
|
119
|
+
{ "data-composer-root": "", onSubmit: handleFormSubmit, onKeyDown: handleKeyDown },
|
|
120
|
+
elementProps,
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
return (_jsx(ComposerStoreContext, { value: store, children: _jsx(ComposerInternalsContext, { value: internalsValue, children: formElement }) }));
|
|
124
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type ChipData, type ChipSegment } from "../chip-markdown.js";
|
|
2
|
+
export type Segment = {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: "chip";
|
|
7
|
+
id: string;
|
|
8
|
+
chip: ChipData;
|
|
9
|
+
};
|
|
10
|
+
export type SegmentDoc = Segment[];
|
|
11
|
+
export type TextChange = {
|
|
12
|
+
rangeStart: number;
|
|
13
|
+
rangeEnd: number;
|
|
14
|
+
insertedLength: number;
|
|
15
|
+
};
|
|
16
|
+
export declare const nextChipId: () => string;
|
|
17
|
+
export declare const documentLength: (doc: SegmentDoc) => number;
|
|
18
|
+
/** Chips contribute nothing — the getText()/onValueChange contract. */
|
|
19
|
+
export declare const getPlainText: (doc: SegmentDoc) => string;
|
|
20
|
+
/** Chips as the sentinel char — positions stay 1:1 for diffing. */
|
|
21
|
+
export declare const toFlatText: (doc: SegmentDoc) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Chips as a single space — positions stay 1:1 for prefix detection, and the
|
|
24
|
+
* whitespace guarantees an active token can never span a chip.
|
|
25
|
+
*/
|
|
26
|
+
export declare const toScanText: (doc: SegmentDoc) => string;
|
|
27
|
+
export declare const chipRangesOf: (doc: SegmentDoc) => Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
start: number;
|
|
30
|
+
end: number;
|
|
31
|
+
}>;
|
|
32
|
+
/** The "\n"-delimited line around a position in scan text. */
|
|
33
|
+
export declare const lineBoundsAt: (scanText: string, position: number) => {
|
|
34
|
+
lineStart: number;
|
|
35
|
+
lineEnd: number;
|
|
36
|
+
};
|
|
37
|
+
export declare const segmentsFromText: (text: string) => SegmentDoc;
|
|
38
|
+
export declare const segmentsFromChipSegments: (segments: readonly ChipSegment[], makeId?: () => string) => SegmentDoc;
|
|
39
|
+
/**
|
|
40
|
+
* The {text} submit payload — text as-is, chips as chip-markdown tokens.
|
|
41
|
+
* Byte-identical to the legacy serializeDocument for equivalent content.
|
|
42
|
+
*/
|
|
43
|
+
export declare const serializeSegments: (doc: SegmentDoc) => {
|
|
44
|
+
text: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Replace the logical range [from, to) with the inserted segments. A chip is
|
|
48
|
+
* atomic: it is removed iff its position falls inside the range (range edges
|
|
49
|
+
* never split it).
|
|
50
|
+
*/
|
|
51
|
+
export declare const spliceSegments: (doc: SegmentDoc, from: number, to: number, insert: SegmentDoc) => SegmentDoc;
|
|
52
|
+
/** Extract [from, to) as a sub-document. Chips are included iff fully inside. */
|
|
53
|
+
export declare const sliceSegments: (doc: SegmentDoc, from: number, to: number) => SegmentDoc;
|
|
54
|
+
/**
|
|
55
|
+
* Fit segments into `room` logical units for maxLength: text is sliced at the
|
|
56
|
+
* boundary; a chip that doesn't fit whole is dropped entirely.
|
|
57
|
+
*/
|
|
58
|
+
export declare const truncateToFit: (insert: SegmentDoc, room: number) => SegmentDoc;
|
|
59
|
+
export declare const mapPositionResult: (position: number, change: TextChange, bias: -1 | 1) => {
|
|
60
|
+
position: number;
|
|
61
|
+
deleted: boolean;
|
|
62
|
+
};
|
|
63
|
+
export declare const mapPosition: (position: number, change: TextChange, bias: -1 | 1) => number;
|
|
64
|
+
export declare const diffFlatText: (oldFlat: string, newFlat: string, caretHint?: number) => TextChange | null;
|
|
65
|
+
export type BeforeInputPlan = {
|
|
66
|
+
kind: "native";
|
|
67
|
+
} | {
|
|
68
|
+
kind: "block";
|
|
69
|
+
} | {
|
|
70
|
+
kind: "splice";
|
|
71
|
+
from: number;
|
|
72
|
+
to: number;
|
|
73
|
+
insert: SegmentDoc;
|
|
74
|
+
caret: number;
|
|
75
|
+
};
|
|
76
|
+
export declare const planBeforeInput: (args: {
|
|
77
|
+
inputType: string;
|
|
78
|
+
data: string | null;
|
|
79
|
+
/** The event's first target range in logical positions; null when unavailable. */
|
|
80
|
+
targetRange: {
|
|
81
|
+
start: number;
|
|
82
|
+
end: number;
|
|
83
|
+
} | null;
|
|
84
|
+
doc: SegmentDoc;
|
|
85
|
+
caret: {
|
|
86
|
+
start: number;
|
|
87
|
+
end: number;
|
|
88
|
+
};
|
|
89
|
+
maxLength?: number;
|
|
90
|
+
}) => BeforeInputPlan;
|
|
91
|
+
export type SnapshotInlineNode = {
|
|
92
|
+
type: "text";
|
|
93
|
+
text: string;
|
|
94
|
+
} | {
|
|
95
|
+
type: "mentionChip";
|
|
96
|
+
attrs: {
|
|
97
|
+
prefix: string;
|
|
98
|
+
value: string;
|
|
99
|
+
label: string;
|
|
100
|
+
icon?: string;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export type SnapshotParagraphNode = {
|
|
104
|
+
type: "paragraph";
|
|
105
|
+
content?: SnapshotInlineNode[];
|
|
106
|
+
};
|
|
107
|
+
export declare const segmentsToParagraphJSON: (doc: SegmentDoc) => SnapshotParagraphNode[];
|
|
108
|
+
export declare const segmentsFromParagraphJSON: (paragraphs: readonly SnapshotParagraphNode[], makeId?: () => string) => SegmentDoc;
|