myoperator-mcp 0.2.349 → 0.2.350

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.
Files changed (2) hide show
  1. package/dist/index.js +65 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1511,6 +1511,11 @@ export interface CreatableMultiSelectProps extends Omit<
1511
1511
  * If the raw value differs from the sanitized value, \`onInvalidCharacters\` is called.
1512
1512
  */
1513
1513
  sanitizeInput?: (raw: string) => string;
1514
+ /**
1515
+ * Applied after \`sanitizeInput\` on typed draft values (e.g. collapse spaces).
1516
+ * Does not affect invalid-character detection.
1517
+ */
1518
+ normalizeInput?: (sanitized: string) => string;
1514
1519
  /** Fired when \`sanitizeInput\` removed one or more characters from the raw input. */
1515
1520
  onInvalidCharacters?: () => void;
1516
1521
  /**
@@ -1600,6 +1605,12 @@ function isValueAlreadySelected(
1600
1605
  });
1601
1606
  }
1602
1607
 
1608
+ function restoreInputCursor(input: HTMLInputElement, cursorPosition: number) {
1609
+ window.requestAnimationFrame(() => {
1610
+ input.setSelectionRange(cursorPosition, cursorPosition);
1611
+ });
1612
+ }
1613
+
1603
1614
  const CreatableMultiSelect = React.forwardRef(
1604
1615
  (
1605
1616
  {
@@ -1617,6 +1628,7 @@ const CreatableMultiSelect = React.forwardRef(
1617
1628
  showPerItemCharacterCounter = true,
1618
1629
  triggerDisplay = "chips",
1619
1630
  sanitizeInput,
1631
+ normalizeInput,
1620
1632
  onInvalidCharacters,
1621
1633
  onValidInput,
1622
1634
  onInputValueChange,
@@ -1641,6 +1653,17 @@ const CreatableMultiSelect = React.forwardRef(
1641
1653
  maxLengthPerItem
1642
1654
  );
1643
1655
 
1656
+ const normalizeDraftValue = React.useCallback(
1657
+ (raw: string) => {
1658
+ const sanitized = sanitizeInput ? sanitizeInput(raw) : raw;
1659
+ const normalized = normalizeInput ? normalizeInput(sanitized) : sanitized;
1660
+ return maxLengthPerItem != null
1661
+ ? normalized.slice(0, maxLengthPerItem)
1662
+ : normalized;
1663
+ },
1664
+ [maxLengthPerItem, normalizeInput, sanitizeInput]
1665
+ );
1666
+
1644
1667
  const addValue = (val: string) => {
1645
1668
  const isPreset = options.some((o) => o.value === val);
1646
1669
  const afterSanitize = isPreset
@@ -1648,7 +1671,9 @@ const CreatableMultiSelect = React.forwardRef(
1648
1671
  : sanitizeInput
1649
1672
  ? sanitizeInput(val)
1650
1673
  : val;
1651
- const trimmed = afterSanitize.trim();
1674
+ const afterNormalize =
1675
+ isPreset || !normalizeInput ? afterSanitize : normalizeInput(afterSanitize);
1676
+ const trimmed = afterNormalize.trim();
1652
1677
  if (
1653
1678
  !trimmed ||
1654
1679
  isValueAlreadySelected(
@@ -1837,12 +1862,19 @@ const CreatableMultiSelect = React.forwardRef(
1837
1862
  if (raw !== sanitized) onInvalidCharacters?.();
1838
1863
  else onValidInput?.();
1839
1864
  }
1840
- const nextInput =
1841
- maxLengthPerItem != null
1842
- ? sanitized.slice(0, maxLengthPerItem)
1843
- : sanitized;
1865
+ const nextInput = normalizeDraftValue(raw);
1844
1866
  setInputValue(nextInput);
1845
1867
  onInputValueChange?.(nextInput);
1868
+
1869
+ if (nextInput !== raw) {
1870
+ const input = e.currentTarget;
1871
+ const rawCursor = input.selectionStart ?? raw.length;
1872
+ const nextCursor = Math.min(
1873
+ normalizeDraftValue(raw.slice(0, rawCursor)).length,
1874
+ nextInput.length
1875
+ );
1876
+ restoreInputCursor(input, nextCursor);
1877
+ }
1846
1878
  }}
1847
1879
  maxLength={maxLengthPerItem}
1848
1880
  onKeyDown={handleKeyDown}
@@ -2104,6 +2136,12 @@ export const creatableToneHintRowClassName = cn(
2104
2136
  "flex shrink-0 items-center justify-between gap-2 px-4 py-2"
2105
2137
  )
2106
2138
 
2139
+ function restoreInputCursor(input: HTMLInputElement, cursorPosition: number) {
2140
+ window.requestAnimationFrame(() => {
2141
+ input.setSelectionRange(cursorPosition, cursorPosition)
2142
+ })
2143
+ }
2144
+
2107
2145
  export interface CreatableSelectOption {
2108
2146
  value: string
2109
2147
  label: string
@@ -2183,6 +2221,17 @@ const CreatableSelect = React.forwardRef(
2183
2221
  // Merge forwarded ref with internal ref
2184
2222
  React.useImperativeHandle(ref, () => containerRef.current!)
2185
2223
 
2224
+ const normalizeSearchValue = React.useCallback(
2225
+ (raw: string) => {
2226
+ const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
2227
+ const normalized = normalizeComboboxInput
2228
+ ? normalizeComboboxInput(sanitized)
2229
+ : sanitized
2230
+ return maxLength != null ? normalized.slice(0, maxLength) : normalized
2231
+ },
2232
+ [maxLength, normalizeComboboxInput, sanitizeInput]
2233
+ )
2234
+
2186
2235
  const selectedLabel = React.useMemo(() => {
2187
2236
  const found = options.find((o) => o.value === value)
2188
2237
  return found ? found.label : value || ""
@@ -2335,13 +2384,19 @@ const CreatableSelect = React.forwardRef(
2335
2384
  if (raw !== sanitized) onInvalidCharacters?.()
2336
2385
  else onValidInput?.()
2337
2386
  }
2338
- const next = normalizeComboboxInput
2339
- ? normalizeComboboxInput(sanitized)
2340
- : sanitized
2341
- const nextSearch =
2342
- maxLength != null ? next.slice(0, maxLength) : next
2387
+ const nextSearch = normalizeSearchValue(raw)
2343
2388
  setSearch(nextSearch)
2344
2389
  onInputValueChange?.(nextSearch)
2390
+
2391
+ if (nextSearch !== raw) {
2392
+ const input = e.currentTarget
2393
+ const rawCursor = input.selectionStart ?? raw.length
2394
+ const nextCursor = Math.min(
2395
+ normalizeSearchValue(raw.slice(0, rawCursor)).length,
2396
+ nextSearch.length
2397
+ )
2398
+ restoreInputCursor(input, nextCursor)
2399
+ }
2345
2400
  }}
2346
2401
  maxLength={maxLength}
2347
2402
  onKeyDown={handleKeyDown}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myoperator-mcp",
3
- "version": "0.2.349",
3
+ "version": "0.2.350",
4
4
  "description": "MCP server for myOperator UI components - enables AI assistants to access component metadata, examples, and design tokens",
5
5
  "type": "module",
6
6
  "bin": "./dist/index.js",