@magicx-eng/ai-autocomplete-vanilla 0.36.1 → 0.37.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/README.md CHANGED
@@ -14,7 +14,7 @@ A framework-agnostic vanilla JS/TypeScript library that provides a guided AI-pow
14
14
  - **Access token auth** — short-lived tokens with automatic refresh, single-flight deduplication, and 401 retry
15
15
  - **Keyboard navigation** — arrow keys, enter to submit, tab to autocomplete, backspace to un-bold the last completed param
16
16
  - **Client-side filtering** — instant substring filtering on every keystroke
17
- - **Datepicker** — date parameters are answered with a calendar instead of an option list. Click a day or navigate with the arrow keys; the date is committed the way it would be written — `Tuesday` for a date inside the next week, `March 23` for one later this year, `March 23 2027` for another year. Tapping a committed date re-opens the calendar on the month that text names now — for a weekday name, that is the next such day, not the one originally picked. A parameter whose options are written as spans (`September 11 - October 13`) gets the same calendar answered in two clicks, committed as one range.
17
+ - **Datepicker** — date parameters are answered with a calendar instead of an option list. Click a day or navigate with the arrow keys; the date is committed the way it would be written — `Tuesday` for a date inside the next week, `March 23` for one later this year, `March 23 2027` for another year. Tapping a committed date re-opens the calendar on the month that text names now — for a weekday name, that is the next such day, not the one originally picked. A date-range parameter gets the same calendar answered in two clicks, committed as one range.
18
18
  - **Option overrides** — supply the options for a parameter yourself: a fixed list, a computed one, or one fetched from your own search endpoint as the user types
19
19
  - **Product strip** — the dropdown renders a horizontal row of product cards below the options, filled by default with the items the `/suggest` response reports as matching the query; plug in your own product search instead with `products`, or turn the strip off with `showProducts: false`
20
20
  - **Catalog report** — every response says which of the query's constraints the catalog applied, which it had to drop, and how many items are left, on `customFields` / `custom_fields`
@@ -431,11 +431,9 @@ new AIAutocomplete(container, { ..., submitButton: null });
431
431
  ### Datepicker
432
432
 
433
433
  When the next parameter is a date, the dropdown shows a calendar instead of a
434
- list of options. A parameter counts as a date when its name says so, or when at
435
- least three of the options it offers are themselves written as dates — so a
436
- parameter called `when` or `arrival` still gets a calendar. Options written as
437
- relative phrases (`today`, `next week`) are not read as dates; a parameter
438
- offering those needs a name that says date.
434
+ list of options. Which parameters are dates is the server's call: one whose
435
+ `type` is `date` gets a calendar, and one without a date type keeps its option
436
+ list, however date-like its name or options look.
439
437
 
440
438
  Nothing is required to switch it on — a date parameter renders this way
441
439
  automatically, and every other parameter is unaffected. Tier 1 and Tier 2 render
@@ -503,19 +501,15 @@ say which, and phrases like `next friday`. Those still open the calendar, just
503
501
  on the current month with nothing marked, so the user picks rather than being
504
502
  shown a guess that might be wrong.
505
503
 
506
- **Date ranges.** A parameter whose options are written as spans — `September 11
507
- - October 13`, `September 11 to November 16` — is answered by the same calendar
508
- in two clicks: the first sets the start, the second the end, and the pair
504
+ **Date ranges.** A parameter whose `type` is `date_range` is answered by the
505
+ same calendar in two clicks: the first sets the start, the second the end, and the pair
509
506
  commits as one answer. The days between them band as the user moves across the
510
507
  calendar, so the span being chosen is visible before it is committed. Paging the
511
508
  month between the two clicks is expected — that is how a span crosses months —
512
509
  and <kbd>Esc</kbd> drops the start and lets them begin again. Clicking the end
513
510
  before the start is fine; the two are ordered on the way in.
514
511
 
515
- The span is read off the options the same way a single date is read off its own:
516
- either separator (`-`, `–`, `—`, `to`, `through`, `until`), either half in any
517
- date format the SDK reads, and a name that says so (`date_range`, `dateRange`)
518
- counts too. It commits as one parameter, written the way it was offered —
512
+ It commits as one parameter, written as a span —
519
513
  `September 11 - October 13`, with the year on whichever end needs it — and both
520
514
  ends are also recorded on the completed parameter's `metadata` as `YYYY-MM-DD`,
521
515
  under the `DATE_RANGE_META_START` / `DATE_RANGE_META_END` keys this package
package/dist/index.d.mts CHANGED
@@ -57,8 +57,9 @@ interface SuggestionOption {
57
57
  parameter?: string;
58
58
  }
59
59
  /**
60
- * The value type of a suggestion's parameter — which picker it needs. Present
61
- * only for a date or date-range parameter.
60
+ * The value type of a parameter — which picker it needs. The server sends it
61
+ * for every date or date-range parameter; a parameter without one is answered
62
+ * from its options.
62
63
  */
63
64
  interface SuggestionType {
64
65
  kind: "string" | "numeric" | "date" | "date_range" | "boolean";
@@ -81,6 +82,11 @@ interface InputItem {
81
82
  state: "completed" | "in_progress";
82
83
  /** Absent or "selected" = echo of client params; "identified" = LLM-inferred. */
83
84
  source?: "selected" | "identified";
85
+ /**
86
+ * The value type of the parameter this span was identified as. A span whose
87
+ * type names a date or date range opens a calendar when tapped.
88
+ */
89
+ type?: SuggestionType;
84
90
  }
85
91
  /** Wire shape for an LLM-identified param echoed back to the server. */
86
92
  interface IdentifiedParam {
@@ -295,6 +301,8 @@ interface IdentifiedParamState {
295
301
  id: string;
296
302
  parameter: string;
297
303
  text: string;
304
+ /** The span's value type, from its `input` item. */
305
+ type?: SuggestionType;
298
306
  }
299
307
  type Segment = {
300
308
  type: "text";
@@ -592,30 +600,20 @@ type FormatType = "options" | "date" | "date-range";
592
600
  /** Whether this format is answered by a calendar rather than by a list. */
593
601
  declare function isCalendarFormat(format: FormatType): boolean;
594
602
  /**
595
- * Decide how a suggestion should be answered.
603
+ * Decide how a parameter should be answered — from the value type the server
604
+ * names on it, and nothing else.
596
605
  *
597
- * The server cannot send a `formatType` yet, so a suggestion that holds a date
598
- * is detected here — by the options it offers, and failing that by its name —
599
- * and rendered as a calendar with those options ignored.
606
+ * The server sets `type` on every date and date-range parameter, so one
607
+ * without it is an option list, whatever its name, options or text look like.
608
+ * The SDK never guesses: guessing from options read a "Ring size" offering
609
+ * "4.75", "7.25" and "8.5" as three dates and replaced its sizes with a
610
+ * calendar.
600
611
  *
601
- * The detection is deliberately the LAST resort. A `formatType` that *is* on
602
- * the wire always wins, so the day the server starts sending one this function
603
- * needs a single block deleted — the datepicker itself, and every gate that
604
- * consults this, keep working untouched.
605
- *
606
- * Options are read before the name because they are the stronger evidence:
607
- * they are the values themselves, while a name is what someone chose to call
608
- * them. A parameter called `travel_date` whose options are all spans is a span
609
- * parameter, whatever its name says.
610
- *
611
- * Accepts anything with a `parameter`, not a `Suggestion`, so re-edit can ask
612
- * the same question about a completed param via its `suggestionParameter`.
613
- * A suggestion whose `type` names a date or date-range parameter is that,
614
- * whatever its options and name say.
612
+ * Accepts anything with a `type`, not a `Suggestion`, so re-edit can ask the
613
+ * same question about a completed param via its `suggestionValueType`, and an
614
+ * identified span via its own `type`.
615
615
  */
616
616
  declare function resolveFormatType(source: {
617
- parameter: string;
618
- options?: SuggestionOption[];
619
617
  type?: SuggestionType;
620
618
  } | undefined | null): FormatType;
621
619
 
@@ -1231,8 +1229,8 @@ declare class AIAutocomplete {
1231
1229
  /**
1232
1230
  * Open the calendar for a span the server identified as a date.
1233
1231
  *
1234
- * Returns false for anything else — an identified span whose type isn't a
1235
- * date stays inert, exactly as every identified span did before.
1232
+ * Returns false for anything else — an identified span whose `type` the
1233
+ * server didn't name as a date or date range stays inert.
1236
1234
  *
1237
1235
  * The span's own text is read for a starting month (`parseLooseDate`), but
1238
1236
  * failing to read it is not a failure: the calendar opens either way, and
package/dist/index.d.ts CHANGED
@@ -57,8 +57,9 @@ interface SuggestionOption {
57
57
  parameter?: string;
58
58
  }
59
59
  /**
60
- * The value type of a suggestion's parameter — which picker it needs. Present
61
- * only for a date or date-range parameter.
60
+ * The value type of a parameter — which picker it needs. The server sends it
61
+ * for every date or date-range parameter; a parameter without one is answered
62
+ * from its options.
62
63
  */
63
64
  interface SuggestionType {
64
65
  kind: "string" | "numeric" | "date" | "date_range" | "boolean";
@@ -81,6 +82,11 @@ interface InputItem {
81
82
  state: "completed" | "in_progress";
82
83
  /** Absent or "selected" = echo of client params; "identified" = LLM-inferred. */
83
84
  source?: "selected" | "identified";
85
+ /**
86
+ * The value type of the parameter this span was identified as. A span whose
87
+ * type names a date or date range opens a calendar when tapped.
88
+ */
89
+ type?: SuggestionType;
84
90
  }
85
91
  /** Wire shape for an LLM-identified param echoed back to the server. */
86
92
  interface IdentifiedParam {
@@ -295,6 +301,8 @@ interface IdentifiedParamState {
295
301
  id: string;
296
302
  parameter: string;
297
303
  text: string;
304
+ /** The span's value type, from its `input` item. */
305
+ type?: SuggestionType;
298
306
  }
299
307
  type Segment = {
300
308
  type: "text";
@@ -592,30 +600,20 @@ type FormatType = "options" | "date" | "date-range";
592
600
  /** Whether this format is answered by a calendar rather than by a list. */
593
601
  declare function isCalendarFormat(format: FormatType): boolean;
594
602
  /**
595
- * Decide how a suggestion should be answered.
603
+ * Decide how a parameter should be answered — from the value type the server
604
+ * names on it, and nothing else.
596
605
  *
597
- * The server cannot send a `formatType` yet, so a suggestion that holds a date
598
- * is detected here — by the options it offers, and failing that by its name —
599
- * and rendered as a calendar with those options ignored.
606
+ * The server sets `type` on every date and date-range parameter, so one
607
+ * without it is an option list, whatever its name, options or text look like.
608
+ * The SDK never guesses: guessing from options read a "Ring size" offering
609
+ * "4.75", "7.25" and "8.5" as three dates and replaced its sizes with a
610
+ * calendar.
600
611
  *
601
- * The detection is deliberately the LAST resort. A `formatType` that *is* on
602
- * the wire always wins, so the day the server starts sending one this function
603
- * needs a single block deleted — the datepicker itself, and every gate that
604
- * consults this, keep working untouched.
605
- *
606
- * Options are read before the name because they are the stronger evidence:
607
- * they are the values themselves, while a name is what someone chose to call
608
- * them. A parameter called `travel_date` whose options are all spans is a span
609
- * parameter, whatever its name says.
610
- *
611
- * Accepts anything with a `parameter`, not a `Suggestion`, so re-edit can ask
612
- * the same question about a completed param via its `suggestionParameter`.
613
- * A suggestion whose `type` names a date or date-range parameter is that,
614
- * whatever its options and name say.
612
+ * Accepts anything with a `type`, not a `Suggestion`, so re-edit can ask the
613
+ * same question about a completed param via its `suggestionValueType`, and an
614
+ * identified span via its own `type`.
615
615
  */
616
616
  declare function resolveFormatType(source: {
617
- parameter: string;
618
- options?: SuggestionOption[];
619
617
  type?: SuggestionType;
620
618
  } | undefined | null): FormatType;
621
619
 
@@ -1231,8 +1229,8 @@ declare class AIAutocomplete {
1231
1229
  /**
1232
1230
  * Open the calendar for a span the server identified as a date.
1233
1231
  *
1234
- * Returns false for anything else — an identified span whose type isn't a
1235
- * date stays inert, exactly as every identified span did before.
1232
+ * Returns false for anything else — an identified span whose `type` the
1233
+ * server didn't name as a date or date range stays inert.
1236
1234
  *
1237
1235
  * The span's own text is read for a starting month (`parseLooseDate`), but
1238
1236
  * failing to read it is not a failure: the calendar opens either way, and