myoperator-mcp 0.2.267 → 0.2.269
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/dist/index.js +159 -105
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1457,7 +1457,7 @@ import { cn } from "@/lib/utils"
|
|
|
1457
1457
|
import {
|
|
1458
1458
|
creatableSelectTriggerVariants,
|
|
1459
1459
|
creatableEnterHintKbdClassName,
|
|
1460
|
-
|
|
1460
|
+
creatablePrimaryRoleHintRowClassName,
|
|
1461
1461
|
} from "./creatable-select"
|
|
1462
1462
|
|
|
1463
1463
|
/** @deprecated Use \`creatableSelectTriggerVariants\` from \`./creatable-select\` \u2014 aliases the same trigger styles as Primary Role. */
|
|
@@ -1629,13 +1629,20 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1629
1629
|
const availablePresets = options.filter(
|
|
1630
1630
|
(o) => !value.includes(o.value) && !o.disabled
|
|
1631
1631
|
)
|
|
1632
|
-
const
|
|
1632
|
+
const trimmedInput = inputValue.trim()
|
|
1633
|
+
const filteredPresets = trimmedInput
|
|
1633
1634
|
? availablePresets.filter((o) =>
|
|
1634
|
-
o.label.toLowerCase().includes(
|
|
1635
|
+
o.label.toLowerCase().includes(trimmedInput.toLowerCase())
|
|
1635
1636
|
)
|
|
1636
1637
|
: availablePresets
|
|
1637
1638
|
|
|
1638
|
-
const
|
|
1639
|
+
const isCustomDraft =
|
|
1640
|
+
trimmedInput.length > 0 &&
|
|
1641
|
+
!options.some(
|
|
1642
|
+
(o) => o.label.toLowerCase() === trimmedInput.toLowerCase()
|
|
1643
|
+
) &&
|
|
1644
|
+
!value.includes(trimmedInput) &&
|
|
1645
|
+
(maxItems == null || value.length < maxItems)
|
|
1639
1646
|
|
|
1640
1647
|
const summaryTriggerLabel =
|
|
1641
1648
|
value.length === 0 ? placeholder : selectedSummary
|
|
@@ -1662,27 +1669,7 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1662
1669
|
}}
|
|
1663
1670
|
>
|
|
1664
1671
|
<div className="flex min-h-0 min-w-0 flex-1 flex-wrap content-start items-center gap-1.5">
|
|
1665
|
-
{triggerDisplay === "
|
|
1666
|
-
<span
|
|
1667
|
-
className={cn(
|
|
1668
|
-
"line-clamp-2 flex-1 text-base",
|
|
1669
|
-
value.length === 0
|
|
1670
|
-
? "text-semantic-text-muted"
|
|
1671
|
-
: "text-semantic-text-primary"
|
|
1672
|
-
)}
|
|
1673
|
-
>
|
|
1674
|
-
{summaryTriggerLabel}
|
|
1675
|
-
</span>
|
|
1676
|
-
) : value.length === 0 ? (
|
|
1677
|
-
<span
|
|
1678
|
-
className={cn(
|
|
1679
|
-
"line-clamp-2 flex-1 text-base",
|
|
1680
|
-
"text-semantic-text-muted"
|
|
1681
|
-
)}
|
|
1682
|
-
>
|
|
1683
|
-
{placeholder}
|
|
1684
|
-
</span>
|
|
1685
|
-
) : (
|
|
1672
|
+
{triggerDisplay === "chips" &&
|
|
1686
1673
|
value.map((val) => (
|
|
1687
1674
|
<span
|
|
1688
1675
|
key={val}
|
|
@@ -1713,9 +1700,45 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1713
1700
|
<X className="size-3.5" strokeWidth={2} aria-hidden />
|
|
1714
1701
|
</button>
|
|
1715
1702
|
</span>
|
|
1716
|
-
))
|
|
1717
|
-
|
|
1703
|
+
))}
|
|
1704
|
+
{triggerDisplay === "summary" && value.length > 0 ? (
|
|
1705
|
+
<span className="line-clamp-2 text-base text-semantic-text-primary">
|
|
1706
|
+
{selectedSummary}
|
|
1707
|
+
</span>
|
|
1708
|
+
) : null}
|
|
1709
|
+
<input
|
|
1710
|
+
ref={inputRef}
|
|
1711
|
+
type="text"
|
|
1712
|
+
value={inputValue}
|
|
1713
|
+
onChange={(e) => {
|
|
1714
|
+
const raw = e.target.value
|
|
1715
|
+
const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
|
|
1716
|
+
if (sanitizeInput) {
|
|
1717
|
+
if (raw !== sanitized) onInvalidCharacters?.()
|
|
1718
|
+
else onValidInput?.()
|
|
1719
|
+
}
|
|
1720
|
+
setInputValue(
|
|
1721
|
+
maxLengthPerItem != null
|
|
1722
|
+
? sanitized.slice(0, maxLengthPerItem)
|
|
1723
|
+
: sanitized
|
|
1724
|
+
)
|
|
1725
|
+
}}
|
|
1726
|
+
maxLength={maxLengthPerItem}
|
|
1727
|
+
onKeyDown={handleKeyDown}
|
|
1728
|
+
disabled={disabled}
|
|
1729
|
+
className="min-w-[120px] flex-1 bg-transparent text-base text-semantic-text-primary outline-none placeholder:text-semantic-text-muted"
|
|
1730
|
+
role="combobox"
|
|
1731
|
+
aria-expanded={isOpen}
|
|
1732
|
+
aria-controls={listboxId}
|
|
1733
|
+
aria-haspopup="listbox"
|
|
1734
|
+
aria-autocomplete="list"
|
|
1735
|
+
/>
|
|
1718
1736
|
</div>
|
|
1737
|
+
{maxLengthPerItem != null && showPerItemCharacterCounter ? (
|
|
1738
|
+
<span className="mr-2 mt-1 shrink-0 self-start text-sm text-semantic-text-muted">
|
|
1739
|
+
{inputValue.length}/{maxLengthPerItem}
|
|
1740
|
+
</span>
|
|
1741
|
+
) : null}
|
|
1719
1742
|
<ChevronDown
|
|
1720
1743
|
className="mt-1 size-4 shrink-0 self-start rotate-180 text-semantic-text-muted opacity-70 transition-transform"
|
|
1721
1744
|
aria-hidden
|
|
@@ -1813,104 +1836,94 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1813
1836
|
</div>
|
|
1814
1837
|
)}
|
|
1815
1838
|
|
|
1816
|
-
{/* Dropdown panel:
|
|
1839
|
+
{/* Dropdown panel: decorative hint row, counter, max-selections, presets. Input lives in the trigger above. */}
|
|
1817
1840
|
{isOpen && (
|
|
1818
1841
|
<div
|
|
1819
1842
|
className="absolute left-0 top-full z-[9999] mt-1 flex w-full flex-col overflow-hidden rounded border border-solid border-semantic-border-layout bg-semantic-bg-primary shadow-sm animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200"
|
|
1820
1843
|
>
|
|
1821
|
-
|
|
1822
|
-
<div className={
|
|
1823
|
-
<
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
onChange={(e) => {
|
|
1828
|
-
const raw = e.target.value
|
|
1829
|
-
const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
|
|
1830
|
-
if (sanitizeInput) {
|
|
1831
|
-
if (raw !== sanitized) onInvalidCharacters?.()
|
|
1832
|
-
else onValidInput?.()
|
|
1833
|
-
}
|
|
1834
|
-
setInputValue(
|
|
1835
|
-
maxLengthPerItem != null
|
|
1836
|
-
? sanitized.slice(0, maxLengthPerItem)
|
|
1837
|
-
: sanitized
|
|
1838
|
-
)
|
|
1839
|
-
}}
|
|
1840
|
-
maxLength={maxLengthPerItem}
|
|
1841
|
-
onKeyDown={handleKeyDown}
|
|
1842
|
-
disabled={disabled}
|
|
1843
|
-
placeholder={panelInputPlaceholder}
|
|
1844
|
-
className="min-w-0 flex-1 bg-transparent text-sm text-semantic-text-primary outline-none placeholder:text-semantic-text-muted"
|
|
1845
|
-
role="combobox"
|
|
1846
|
-
aria-expanded={isOpen}
|
|
1847
|
-
aria-controls={listboxId}
|
|
1848
|
-
aria-haspopup="listbox"
|
|
1849
|
-
aria-autocomplete="list"
|
|
1850
|
-
/>
|
|
1851
|
-
<kbd className={cn(creatableEnterHintKbdClassName, "shrink-0")}>
|
|
1844
|
+
{createHintText ? (
|
|
1845
|
+
<div className={creatablePrimaryRoleHintRowClassName}>
|
|
1846
|
+
<span className="text-sm text-semantic-text-muted">
|
|
1847
|
+
{createHintText}
|
|
1848
|
+
</span>
|
|
1849
|
+
<kbd className={creatableEnterHintKbdClassName}>
|
|
1852
1850
|
Enter \u21B5
|
|
1853
1851
|
</kbd>
|
|
1854
1852
|
</div>
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
<div className="flex flex-col gap-2.5 px-4 pb-4 pt-0">
|
|
1858
|
-
{maxItems != null ? (
|
|
1859
|
-
<p className="m-0 py-1 text-sm text-semantic-text-muted">
|
|
1860
|
-
Max selections allowed: {maxItems}
|
|
1861
|
-
</p>
|
|
1862
|
-
) : null}
|
|
1853
|
+
) : null}
|
|
1863
1854
|
|
|
1855
|
+
{(filteredPresets.length > 0 || isCustomDraft) && (
|
|
1864
1856
|
<div
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1857
|
+
className={cn(
|
|
1858
|
+
"flex flex-col px-4",
|
|
1859
|
+
filteredPresets.length > 0
|
|
1860
|
+
? "gap-2.5 pb-4 pt-2.5"
|
|
1861
|
+
: "py-1"
|
|
1862
|
+
)}
|
|
1868
1863
|
>
|
|
1869
|
-
{filteredPresets.
|
|
1864
|
+
{maxItems != null && filteredPresets.length > 0 ? (
|
|
1865
|
+
<p className="m-0 text-sm text-semantic-text-muted">
|
|
1866
|
+
Max selections allowed: {maxItems}
|
|
1867
|
+
</p>
|
|
1868
|
+
) : null}
|
|
1869
|
+
|
|
1870
|
+
{filteredPresets.length > 0 ? (
|
|
1871
|
+
<div
|
|
1872
|
+
id={listboxId}
|
|
1873
|
+
role="listbox"
|
|
1874
|
+
className="flex flex-wrap gap-1.5"
|
|
1875
|
+
>
|
|
1876
|
+
{filteredPresets.map((option) => (
|
|
1877
|
+
<button
|
|
1878
|
+
key={option.value}
|
|
1879
|
+
type="button"
|
|
1880
|
+
role="option"
|
|
1881
|
+
aria-selected={false}
|
|
1882
|
+
onMouseDown={(e) => {
|
|
1883
|
+
e.preventDefault()
|
|
1884
|
+
addValue(option.value)
|
|
1885
|
+
}}
|
|
1886
|
+
className="inline-flex items-center gap-2.5 whitespace-nowrap rounded border-0 bg-semantic-bg-ui px-2 py-1 text-left text-sm text-semantic-text-primary transition-colors hover:bg-semantic-bg-hover"
|
|
1887
|
+
>
|
|
1888
|
+
<Plus
|
|
1889
|
+
className="size-2.5 shrink-0 text-semantic-text-muted"
|
|
1890
|
+
strokeWidth={2}
|
|
1891
|
+
aria-hidden
|
|
1892
|
+
/>
|
|
1893
|
+
{option.label}
|
|
1894
|
+
</button>
|
|
1895
|
+
))}
|
|
1896
|
+
</div>
|
|
1897
|
+
) : null}
|
|
1898
|
+
|
|
1899
|
+
{isCustomDraft ? (
|
|
1870
1900
|
<button
|
|
1871
|
-
key={option.value}
|
|
1872
1901
|
type="button"
|
|
1873
1902
|
role="option"
|
|
1874
1903
|
aria-selected={false}
|
|
1875
1904
|
onMouseDown={(e) => {
|
|
1876
1905
|
e.preventDefault()
|
|
1877
|
-
addValue(
|
|
1906
|
+
addValue(inputValue)
|
|
1878
1907
|
}}
|
|
1879
|
-
className="
|
|
1908
|
+
className="-mx-4 flex w-[calc(100%+2rem)] items-center gap-2 rounded-none px-4 py-2 text-left text-base text-semantic-text-link outline-none transition-colors cursor-pointer select-none hover:bg-semantic-bg-ui"
|
|
1880
1909
|
>
|
|
1881
|
-
|
|
1882
|
-
className="size-2.5 shrink-0 text-semantic-text-muted"
|
|
1883
|
-
strokeWidth={2}
|
|
1884
|
-
aria-hidden
|
|
1885
|
-
/>
|
|
1886
|
-
{option.label}
|
|
1910
|
+
Create “{trimmedInput}”
|
|
1887
1911
|
</button>
|
|
1888
|
-
)
|
|
1912
|
+
) : null}
|
|
1889
1913
|
</div>
|
|
1890
|
-
|
|
1914
|
+
)}
|
|
1891
1915
|
</div>
|
|
1892
1916
|
)}
|
|
1893
1917
|
</div>
|
|
1894
1918
|
|
|
1895
|
-
{
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
</span>
|
|
1919
|
+
{helperText && !isOpen ? (
|
|
1920
|
+
<div className="mt-1.5 flex items-center gap-1.5">
|
|
1921
|
+
<Info className="size-[18px] shrink-0 text-semantic-text-muted" />
|
|
1922
|
+
<p className="m-0 text-sm text-semantic-text-muted">
|
|
1923
|
+
{helperText}
|
|
1924
|
+
</p>
|
|
1902
1925
|
</div>
|
|
1903
|
-
) :
|
|
1904
|
-
helperText &&
|
|
1905
|
-
!isOpen && (
|
|
1906
|
-
<div className="mt-1.5 flex items-center gap-1.5">
|
|
1907
|
-
<Info className="size-[18px] shrink-0 text-semantic-text-muted" />
|
|
1908
|
-
<p className="m-0 text-sm text-semantic-text-muted">
|
|
1909
|
-
{helperText}
|
|
1910
|
-
</p>
|
|
1911
|
-
</div>
|
|
1912
|
-
)
|
|
1913
|
-
)}
|
|
1926
|
+
) : null}
|
|
1914
1927
|
</div>
|
|
1915
1928
|
)
|
|
1916
1929
|
}
|
|
@@ -1988,7 +2001,7 @@ export interface CreatableSelectProps
|
|
|
1988
2001
|
creatableHint?: string
|
|
1989
2002
|
/** Whether the select is disabled */
|
|
1990
2003
|
disabled?: boolean
|
|
1991
|
-
/** Max character length for the value (enforced when open and when creating) */
|
|
2004
|
+
/** Max character length for the value (enforced when open and when creating). When set, an in-field \`current/max\` counter renders before the chevron while the dropdown is open. */
|
|
1992
2005
|
maxLength?: number
|
|
1993
2006
|
/**
|
|
1994
2007
|
* When set, combobox input is transformed (e.g. strip invalid characters).
|
|
@@ -2202,6 +2215,11 @@ const CreatableSelect = React.forwardRef(
|
|
|
2202
2215
|
role="combobox"
|
|
2203
2216
|
aria-autocomplete="list"
|
|
2204
2217
|
/>
|
|
2218
|
+
{maxLength != null ? (
|
|
2219
|
+
<span className="mr-2 shrink-0 text-sm text-semantic-text-muted">
|
|
2220
|
+
{search.length}/{maxLength}
|
|
2221
|
+
</span>
|
|
2222
|
+
) : null}
|
|
2205
2223
|
<ChevronDown className="size-4 text-semantic-text-muted opacity-70 shrink-0 rotate-180 transition-transform" />
|
|
2206
2224
|
</div>
|
|
2207
2225
|
) : (
|
|
@@ -3155,6 +3173,7 @@ import { Check } from "lucide-react";
|
|
|
3155
3173
|
import { cn } from "@/lib/utils";
|
|
3156
3174
|
|
|
3157
3175
|
const blockedNumberKeys = new Set(["e", "E"]);
|
|
3176
|
+
const decimalSeparatorKeys = new Set([".", ","]);
|
|
3158
3177
|
|
|
3159
3178
|
/**
|
|
3160
3179
|
* Input variants for different visual states
|
|
@@ -3203,6 +3222,15 @@ export interface InputProps
|
|
|
3203
3222
|
* Default \`true\` so amount-like fields cannot accept exponent values such as \`2e22\`.
|
|
3204
3223
|
*/
|
|
3205
3224
|
preventNumberExponent?: boolean;
|
|
3225
|
+
/**
|
|
3226
|
+
* When \`type="number"\`, whether decimal separators (\`.\` / \`,\`) are allowed.
|
|
3227
|
+
* Default \`true\`. Set \`false\` for whole-number-only fields; uses \`inputMode="numeric"\` on supported agents.
|
|
3228
|
+
*/
|
|
3229
|
+
decimal?: boolean;
|
|
3230
|
+
/**
|
|
3231
|
+
* Same as \`decimal\` for whole-number-only fields. If both are set, this wins.
|
|
3232
|
+
*/
|
|
3233
|
+
allowDecimal?: boolean;
|
|
3206
3234
|
}
|
|
3207
3235
|
|
|
3208
3236
|
const Input = React.forwardRef(
|
|
@@ -3214,19 +3242,25 @@ const Input = React.forwardRef(
|
|
|
3214
3242
|
showCheckIcon,
|
|
3215
3243
|
hideNumberSpinners = true,
|
|
3216
3244
|
preventNumberExponent = true,
|
|
3245
|
+
decimal = true,
|
|
3246
|
+
allowDecimal,
|
|
3217
3247
|
onFocus,
|
|
3218
3248
|
onBlur,
|
|
3219
3249
|
onWheel,
|
|
3220
3250
|
onKeyDown,
|
|
3221
3251
|
onPaste,
|
|
3222
3252
|
onChange,
|
|
3253
|
+
step,
|
|
3223
3254
|
...props
|
|
3224
3255
|
}: InputProps,
|
|
3225
3256
|
ref: React.Ref<HTMLInputElement>
|
|
3226
3257
|
) => {
|
|
3227
3258
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
3259
|
+
const decimalAllowed = allowDecimal ?? decimal;
|
|
3228
3260
|
const shouldPreventNumberExponent =
|
|
3229
3261
|
type === "number" && preventNumberExponent;
|
|
3262
|
+
const shouldBlockDecimals =
|
|
3263
|
+
type === "number" && !decimalAllowed;
|
|
3230
3264
|
|
|
3231
3265
|
const inputEl = (
|
|
3232
3266
|
<input
|
|
@@ -3239,6 +3273,16 @@ const Input = React.forwardRef(
|
|
|
3239
3273
|
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
3240
3274
|
)}
|
|
3241
3275
|
ref={ref}
|
|
3276
|
+
inputMode={
|
|
3277
|
+
type === "number"
|
|
3278
|
+
? decimalAllowed
|
|
3279
|
+
? "decimal"
|
|
3280
|
+
: "numeric"
|
|
3281
|
+
: undefined
|
|
3282
|
+
}
|
|
3283
|
+
step={
|
|
3284
|
+
type === "number" && !decimalAllowed ? (step ?? 1) : step
|
|
3285
|
+
}
|
|
3242
3286
|
onFocus={(e) => {
|
|
3243
3287
|
setIsFocused(true);
|
|
3244
3288
|
onFocus?.(e);
|
|
@@ -3259,13 +3303,20 @@ const Input = React.forwardRef(
|
|
|
3259
3303
|
if (shouldPreventNumberExponent && blockedNumberKeys.has(e.key)) {
|
|
3260
3304
|
e.preventDefault();
|
|
3261
3305
|
}
|
|
3306
|
+
if (
|
|
3307
|
+
shouldBlockDecimals &&
|
|
3308
|
+
decimalSeparatorKeys.has(e.key)
|
|
3309
|
+
) {
|
|
3310
|
+
e.preventDefault();
|
|
3311
|
+
}
|
|
3262
3312
|
onKeyDown?.(e);
|
|
3263
3313
|
}}
|
|
3264
3314
|
onPaste={(e) => {
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3315
|
+
const text = e.clipboardData.getData("text");
|
|
3316
|
+
if (shouldPreventNumberExponent && /[eE]/.test(text)) {
|
|
3317
|
+
e.preventDefault();
|
|
3318
|
+
}
|
|
3319
|
+
if (shouldBlockDecimals && /[.,]/.test(text)) {
|
|
3269
3320
|
e.preventDefault();
|
|
3270
3321
|
}
|
|
3271
3322
|
onPaste?.(e);
|
|
@@ -3274,6 +3325,9 @@ const Input = React.forwardRef(
|
|
|
3274
3325
|
if (shouldPreventNumberExponent && /[eE]/.test(e.target.value)) {
|
|
3275
3326
|
return;
|
|
3276
3327
|
}
|
|
3328
|
+
if (shouldBlockDecimals && /[.,]/.test(e.target.value)) {
|
|
3329
|
+
return;
|
|
3330
|
+
}
|
|
3277
3331
|
onChange?.(e);
|
|
3278
3332
|
}}
|
|
3279
3333
|
{...props}
|
package/package.json
CHANGED