@magicx-eng/ai-autocomplete-vanilla 0.1.19 → 0.1.20

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.
@@ -19,6 +19,37 @@ interface Suggestion {
19
19
  required: boolean;
20
20
  options?: SuggestionOption[];
21
21
  }
22
+ interface InputItem {
23
+ type: string;
24
+ text: string;
25
+ state: "completed" | "in_progress";
26
+ }
27
+ interface AutocompleteRequest {
28
+ data: {
29
+ raw_query: string;
30
+ completed_params: CompletedParam[];
31
+ contact_account_count?: number;
32
+ };
33
+ meta: {
34
+ request_id: string;
35
+ request_at: string;
36
+ language: string;
37
+ client_version: string;
38
+ session_id: string;
39
+ };
40
+ }
41
+ interface AutocompleteResponse {
42
+ data: {
43
+ raw_query: string;
44
+ input: InputItem[];
45
+ suggestions: Suggestion[];
46
+ is_ready?: boolean;
47
+ };
48
+ meta: {
49
+ request_id: string;
50
+ request_at: string;
51
+ };
52
+ }
22
53
  interface CompletedParamState extends CompletedParam {
23
54
  id: string;
24
55
  text: string;
@@ -303,6 +334,65 @@ declare class AIAutocomplete {
303
334
  private maybePromoteExactMatch;
304
335
  }
305
336
 
337
+ /**
338
+ * Plain-text caret utilities for contentEditable elements.
339
+ *
340
+ * Offsets are measured in plain-text characters that come from the editable
341
+ * region only — subtrees inside `[contenteditable="false"]` (e.g. pills)
342
+ * contribute zero characters. Callers can think in string offsets without
343
+ * touching DOM Ranges directly.
344
+ */
345
+ declare function extractPlainText(root: HTMLElement): string;
346
+ declare function plainTextLength(root: HTMLElement): number;
347
+ /**
348
+ * Read the current caret offset (in plain-text characters) within `root`.
349
+ * Returns null when no selection is anchored inside `root`.
350
+ */
351
+ declare function getCursorOffset(root: HTMLElement): number | null;
352
+ /**
353
+ * Set the caret at the given plain-text offset within `root`.
354
+ *
355
+ * Boundary policy: when the offset falls at the seam between text nodes, the
356
+ * caret is placed at the START of the *following* text node so newly typed
357
+ * characters do not inherit a preceding `<strong>`'s bold styling. When the
358
+ * caret would land at the trailing edge of a text node inside a `<strong>`
359
+ * with no following text node, we use `setStartAfter(strong)` so the caret
360
+ * sits OUTSIDE the bold subtree — otherwise a caret at the end of a strong's
361
+ * text is still "inside" the strong, which would falsely trigger re-edit mode.
362
+ */
363
+ declare function setCursorOffset(root: HTMLElement, offset: number): void;
364
+ /**
365
+ * True when the caret offset equals the editable's plain-text length —
366
+ * meaning the only content to the right is non-editable (e.g. trailing pills).
367
+ */
368
+ declare function cursorIsAtEnd(root: HTMLElement): boolean;
369
+ /**
370
+ * Step back one grapheme from a plain-text offset, falling back to one UTF-16
371
+ * code unit when Intl.Segmenter is unavailable. Used by Backspace handling so
372
+ * emoji and combining marks are deleted as a single user-perceived character.
373
+ */
374
+ declare function previousGraphemeBoundary(text: string, offset: number): number;
375
+
376
+ interface RenderEditableArgs {
377
+ input: HTMLElement;
378
+ segments: Segment[];
379
+ newParamId: string | null;
380
+ /** When set, the matching `<strong>` is decorated with the editing class. */
381
+ editingParamId: string | null;
382
+ placeholderText: string;
383
+ isFocused: boolean;
384
+ }
385
+ /**
386
+ * Renders text segments — including bold `<strong>` runs for completed params
387
+ * — into the contentEditable input. Pills are NOT rendered here; they live as
388
+ * a sibling element so the editable's subtree never contains non-editable
389
+ * children. See renderInput.ts for the pill list placement.
390
+ *
391
+ * Skips rebuilds when the segment key is unchanged so an in-flight shimmer
392
+ * animation isn't interrupted by unrelated state churn.
393
+ */
394
+ declare function renderEditableContent(args: RenderEditableArgs): void;
395
+
306
396
  type Listener<S> = (next: S, prev: S) => void;
307
397
  interface Store<S> {
308
398
  get: () => S;
@@ -311,4 +401,30 @@ interface Store<S> {
311
401
  }
312
402
  declare function createStore<S>(initial: S): Store<S>;
313
403
 
314
- export { AIAutocomplete, type APIConfig, type APIKeyConfig, type AccessTokenConfig, type AccessTokenResult, type AppearanceMode, type AutocompleteResult, type CompletedParam, type CompletedParamState, type CoreOptions, type CoreState, type RenderMode, type Segment, type Store, type Suggestion, type SuggestionOption, createStore };
404
+ interface BuildQueryResult {
405
+ rawQuery: string;
406
+ completedParams: CompletedParamState[];
407
+ }
408
+ /**
409
+ * Takes the raw input text and completed params (without placeholders),
410
+ * replaces each completed param's text in the string with a {{TYPE_N}} token,
411
+ * and returns the transformed query + params with placeholders filled in.
412
+ *
413
+ * Replacements happen left-to-right, first occurrence only per param.
414
+ * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).
415
+ */
416
+ declare function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult;
417
+
418
+ declare class ModeController {
419
+ private container;
420
+ private mode;
421
+ private mediaQuery;
422
+ constructor(container: HTMLElement, mode?: AppearanceMode);
423
+ setMode(mode: AppearanceMode): void;
424
+ destroy(): void;
425
+ private apply;
426
+ private onSystemChange;
427
+ private detachListener;
428
+ }
429
+
430
+ export { AIAutocomplete, type APIConfig, type APIKeyConfig, type AccessTokenConfig, type AccessTokenResult, type AppearanceMode, type AutocompleteRequest, type AutocompleteResponse, type AutocompleteResult, type CompletedParam, type CompletedParamState, type CoreOptions, type CoreState, type InputItem, ModeController, type OptionOverrides, type RenderMode, type Segment, type Store, type Suggestion, type SuggestionOption, type TaskKind, buildQuery, createStore, cursorIsAtEnd, extractPlainText, getCursorOffset, plainTextLength, previousGraphemeBoundary, renderEditableContent, setCursorOffset };
@@ -19,6 +19,37 @@ interface Suggestion {
19
19
  required: boolean;
20
20
  options?: SuggestionOption[];
21
21
  }
22
+ interface InputItem {
23
+ type: string;
24
+ text: string;
25
+ state: "completed" | "in_progress";
26
+ }
27
+ interface AutocompleteRequest {
28
+ data: {
29
+ raw_query: string;
30
+ completed_params: CompletedParam[];
31
+ contact_account_count?: number;
32
+ };
33
+ meta: {
34
+ request_id: string;
35
+ request_at: string;
36
+ language: string;
37
+ client_version: string;
38
+ session_id: string;
39
+ };
40
+ }
41
+ interface AutocompleteResponse {
42
+ data: {
43
+ raw_query: string;
44
+ input: InputItem[];
45
+ suggestions: Suggestion[];
46
+ is_ready?: boolean;
47
+ };
48
+ meta: {
49
+ request_id: string;
50
+ request_at: string;
51
+ };
52
+ }
22
53
  interface CompletedParamState extends CompletedParam {
23
54
  id: string;
24
55
  text: string;
@@ -303,6 +334,65 @@ declare class AIAutocomplete {
303
334
  private maybePromoteExactMatch;
304
335
  }
305
336
 
337
+ /**
338
+ * Plain-text caret utilities for contentEditable elements.
339
+ *
340
+ * Offsets are measured in plain-text characters that come from the editable
341
+ * region only — subtrees inside `[contenteditable="false"]` (e.g. pills)
342
+ * contribute zero characters. Callers can think in string offsets without
343
+ * touching DOM Ranges directly.
344
+ */
345
+ declare function extractPlainText(root: HTMLElement): string;
346
+ declare function plainTextLength(root: HTMLElement): number;
347
+ /**
348
+ * Read the current caret offset (in plain-text characters) within `root`.
349
+ * Returns null when no selection is anchored inside `root`.
350
+ */
351
+ declare function getCursorOffset(root: HTMLElement): number | null;
352
+ /**
353
+ * Set the caret at the given plain-text offset within `root`.
354
+ *
355
+ * Boundary policy: when the offset falls at the seam between text nodes, the
356
+ * caret is placed at the START of the *following* text node so newly typed
357
+ * characters do not inherit a preceding `<strong>`'s bold styling. When the
358
+ * caret would land at the trailing edge of a text node inside a `<strong>`
359
+ * with no following text node, we use `setStartAfter(strong)` so the caret
360
+ * sits OUTSIDE the bold subtree — otherwise a caret at the end of a strong's
361
+ * text is still "inside" the strong, which would falsely trigger re-edit mode.
362
+ */
363
+ declare function setCursorOffset(root: HTMLElement, offset: number): void;
364
+ /**
365
+ * True when the caret offset equals the editable's plain-text length —
366
+ * meaning the only content to the right is non-editable (e.g. trailing pills).
367
+ */
368
+ declare function cursorIsAtEnd(root: HTMLElement): boolean;
369
+ /**
370
+ * Step back one grapheme from a plain-text offset, falling back to one UTF-16
371
+ * code unit when Intl.Segmenter is unavailable. Used by Backspace handling so
372
+ * emoji and combining marks are deleted as a single user-perceived character.
373
+ */
374
+ declare function previousGraphemeBoundary(text: string, offset: number): number;
375
+
376
+ interface RenderEditableArgs {
377
+ input: HTMLElement;
378
+ segments: Segment[];
379
+ newParamId: string | null;
380
+ /** When set, the matching `<strong>` is decorated with the editing class. */
381
+ editingParamId: string | null;
382
+ placeholderText: string;
383
+ isFocused: boolean;
384
+ }
385
+ /**
386
+ * Renders text segments — including bold `<strong>` runs for completed params
387
+ * — into the contentEditable input. Pills are NOT rendered here; they live as
388
+ * a sibling element so the editable's subtree never contains non-editable
389
+ * children. See renderInput.ts for the pill list placement.
390
+ *
391
+ * Skips rebuilds when the segment key is unchanged so an in-flight shimmer
392
+ * animation isn't interrupted by unrelated state churn.
393
+ */
394
+ declare function renderEditableContent(args: RenderEditableArgs): void;
395
+
306
396
  type Listener<S> = (next: S, prev: S) => void;
307
397
  interface Store<S> {
308
398
  get: () => S;
@@ -311,4 +401,30 @@ interface Store<S> {
311
401
  }
312
402
  declare function createStore<S>(initial: S): Store<S>;
313
403
 
314
- export { AIAutocomplete, type APIConfig, type APIKeyConfig, type AccessTokenConfig, type AccessTokenResult, type AppearanceMode, type AutocompleteResult, type CompletedParam, type CompletedParamState, type CoreOptions, type CoreState, type RenderMode, type Segment, type Store, type Suggestion, type SuggestionOption, createStore };
404
+ interface BuildQueryResult {
405
+ rawQuery: string;
406
+ completedParams: CompletedParamState[];
407
+ }
408
+ /**
409
+ * Takes the raw input text and completed params (without placeholders),
410
+ * replaces each completed param's text in the string with a {{TYPE_N}} token,
411
+ * and returns the transformed query + params with placeholders filled in.
412
+ *
413
+ * Replacements happen left-to-right, first occurrence only per param.
414
+ * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).
415
+ */
416
+ declare function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult;
417
+
418
+ declare class ModeController {
419
+ private container;
420
+ private mode;
421
+ private mediaQuery;
422
+ constructor(container: HTMLElement, mode?: AppearanceMode);
423
+ setMode(mode: AppearanceMode): void;
424
+ destroy(): void;
425
+ private apply;
426
+ private onSystemChange;
427
+ private detachListener;
428
+ }
429
+
430
+ export { AIAutocomplete, type APIConfig, type APIKeyConfig, type AccessTokenConfig, type AccessTokenResult, type AppearanceMode, type AutocompleteRequest, type AutocompleteResponse, type AutocompleteResult, type CompletedParam, type CompletedParamState, type CoreOptions, type CoreState, type InputItem, ModeController, type OptionOverrides, type RenderMode, type Segment, type Store, type Suggestion, type SuggestionOption, type TaskKind, buildQuery, createStore, cursorIsAtEnd, extractPlainText, getCursorOffset, plainTextLength, previousGraphemeBoundary, renderEditableContent, setCursorOffset };