myoperator-mcp 0.2.260 → 0.2.261
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 +145 -70
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1492,6 +1492,11 @@ export interface CreatableMultiSelectProps
|
|
|
1492
1492
|
* Set to false to match Figma (counter lives only in the field flow / not under the control).
|
|
1493
1493
|
*/
|
|
1494
1494
|
showPerItemCharacterCounter?: boolean
|
|
1495
|
+
/**
|
|
1496
|
+
* Closed trigger: show removable chips (default) or a single comma-separated summary line (Figma Tone).
|
|
1497
|
+
* While open, the trigger always shows the summary line; selected chips with remove controls appear in the panel.
|
|
1498
|
+
*/
|
|
1499
|
+
triggerDisplay?: "chips" | "summary"
|
|
1495
1500
|
/**
|
|
1496
1501
|
* When set, the text input is transformed (e.g. strip invalid characters).
|
|
1497
1502
|
* If the raw value differs from the sanitized value, \`onInvalidCharacters\` is called.
|
|
@@ -1537,6 +1542,7 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1537
1542
|
maxItems,
|
|
1538
1543
|
maxLengthPerItem,
|
|
1539
1544
|
showPerItemCharacterCounter = true,
|
|
1545
|
+
triggerDisplay = "chips",
|
|
1540
1546
|
sanitizeInput,
|
|
1541
1547
|
onInvalidCharacters,
|
|
1542
1548
|
onValidInput,
|
|
@@ -1637,13 +1643,10 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1637
1643
|
!value.includes(draftForCreate) &&
|
|
1638
1644
|
(maxItems == null || value.length < maxItems)
|
|
1639
1645
|
|
|
1640
|
-
const
|
|
1646
|
+
const panelInputPlaceholder = createHintText ?? placeholder
|
|
1641
1647
|
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
const inputPlaceholder = isOpen
|
|
1645
|
-
? selectedSummary || placeholder
|
|
1646
|
-
: ""
|
|
1648
|
+
const summaryTriggerLabel =
|
|
1649
|
+
value.length === 0 ? placeholder : selectedSummary
|
|
1647
1650
|
|
|
1648
1651
|
return (
|
|
1649
1652
|
<div
|
|
@@ -1652,48 +1655,33 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1652
1655
|
{...props}
|
|
1653
1656
|
>
|
|
1654
1657
|
<div className="relative w-full">
|
|
1655
|
-
{isOpen
|
|
1658
|
+
{isOpen && (
|
|
1656
1659
|
<div
|
|
1657
1660
|
className={cn(
|
|
1658
1661
|
creatableSelectTriggerVariants({ state: derivedState }),
|
|
1659
|
-
"cursor-text"
|
|
1662
|
+
"flex h-auto min-h-[42px] cursor-text items-start gap-2 py-2 text-left"
|
|
1660
1663
|
)}
|
|
1661
|
-
onClick={() => inputRef.current?.focus()}
|
|
1664
|
+
onClick={() => !disabled && inputRef.current?.focus()}
|
|
1665
|
+
aria-hidden="true"
|
|
1662
1666
|
>
|
|
1663
|
-
<
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
}
|
|
1674
|
-
setInputValue(
|
|
1675
|
-
maxLengthPerItem != null
|
|
1676
|
-
? sanitized.slice(0, maxLengthPerItem)
|
|
1677
|
-
: sanitized
|
|
1678
|
-
)
|
|
1679
|
-
}}
|
|
1680
|
-
maxLength={maxLengthPerItem}
|
|
1681
|
-
onKeyDown={handleKeyDown}
|
|
1682
|
-
disabled={disabled}
|
|
1683
|
-
placeholder={inputPlaceholder}
|
|
1684
|
-
className="flex-1 min-w-0 bg-transparent outline-none text-base text-semantic-text-primary placeholder:text-semantic-text-muted"
|
|
1685
|
-
role="combobox"
|
|
1686
|
-
aria-expanded={isOpen}
|
|
1687
|
-
aria-controls={listboxId}
|
|
1688
|
-
aria-haspopup="listbox"
|
|
1689
|
-
aria-autocomplete="list"
|
|
1690
|
-
/>
|
|
1667
|
+
<span
|
|
1668
|
+
className={cn(
|
|
1669
|
+
"line-clamp-2 min-w-0 flex-1 text-base",
|
|
1670
|
+
value.length === 0
|
|
1671
|
+
? "text-semantic-text-muted"
|
|
1672
|
+
: "text-semantic-text-primary"
|
|
1673
|
+
)}
|
|
1674
|
+
>
|
|
1675
|
+
{summaryTriggerLabel}
|
|
1676
|
+
</span>
|
|
1691
1677
|
<ChevronRight
|
|
1692
|
-
className="size-5 text-semantic-text-muted
|
|
1678
|
+
className="mt-1 size-5 shrink-0 self-start text-semantic-text-muted opacity-70"
|
|
1693
1679
|
aria-hidden
|
|
1694
1680
|
/>
|
|
1695
1681
|
</div>
|
|
1696
|
-
)
|
|
1682
|
+
)}
|
|
1683
|
+
|
|
1684
|
+
{!isOpen && (
|
|
1697
1685
|
<div
|
|
1698
1686
|
role="combobox"
|
|
1699
1687
|
tabIndex={disabled ? -1 : 0}
|
|
@@ -1717,12 +1705,23 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1717
1705
|
}}
|
|
1718
1706
|
className={cn(
|
|
1719
1707
|
creatableSelectTriggerVariants({ state: derivedState }),
|
|
1720
|
-
"flex min-h-[42px] cursor-pointer items-
|
|
1708
|
+
"flex h-auto min-h-[42px] cursor-pointer items-start gap-2 py-2 text-left outline-none focus-visible:ring-2 focus-visible:ring-semantic-border-focus focus-visible:ring-offset-2 focus-visible:ring-offset-semantic-bg-primary",
|
|
1721
1709
|
disabled && "pointer-events-none cursor-not-allowed"
|
|
1722
1710
|
)}
|
|
1723
1711
|
>
|
|
1724
|
-
<div className="flex min-h-0 min-w-0 flex-1 flex-wrap items-center gap-1.5">
|
|
1725
|
-
{
|
|
1712
|
+
<div className="flex min-h-0 min-w-0 flex-1 flex-wrap content-start items-center gap-1.5">
|
|
1713
|
+
{triggerDisplay === "summary" ? (
|
|
1714
|
+
<span
|
|
1715
|
+
className={cn(
|
|
1716
|
+
"line-clamp-2 flex-1 text-base",
|
|
1717
|
+
value.length === 0
|
|
1718
|
+
? "text-semantic-text-muted"
|
|
1719
|
+
: "text-semantic-text-primary"
|
|
1720
|
+
)}
|
|
1721
|
+
>
|
|
1722
|
+
{summaryTriggerLabel}
|
|
1723
|
+
</span>
|
|
1724
|
+
) : value.length === 0 ? (
|
|
1726
1725
|
<span
|
|
1727
1726
|
className={cn(
|
|
1728
1727
|
"line-clamp-2 flex-1 text-base",
|
|
@@ -1766,52 +1765,128 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1766
1765
|
)}
|
|
1767
1766
|
</div>
|
|
1768
1767
|
<ChevronRight
|
|
1769
|
-
className="size-5 shrink-0 text-semantic-text-muted opacity-70"
|
|
1768
|
+
className="mt-1 size-5 shrink-0 self-start text-semantic-text-muted opacity-70"
|
|
1770
1769
|
aria-hidden
|
|
1771
1770
|
/>
|
|
1772
1771
|
</div>
|
|
1773
1772
|
)}
|
|
1774
1773
|
|
|
1775
|
-
{/* Dropdown panel */}
|
|
1774
|
+
{/* Dropdown panel: input + limits + presets (Figma: summary row stays above; type-to-create lives here) */}
|
|
1776
1775
|
{isOpen && (
|
|
1777
1776
|
<div
|
|
1778
|
-
|
|
1779
|
-
role="listbox"
|
|
1780
|
-
className="absolute left-0 top-full z-[9999] mt-1 flex w-full flex-col gap-2.5 overflow-hidden rounded border border-solid border-semantic-border-layout bg-semantic-bg-primary px-4 pb-4 pt-0 shadow-sm animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200"
|
|
1777
|
+
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"
|
|
1781
1778
|
>
|
|
1782
|
-
|
|
1783
|
-
<div className=
|
|
1784
|
-
<
|
|
1785
|
-
{
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1779
|
+
<div className="-mx-0 flex shrink-0 flex-col border-b border-solid border-semantic-border-layout">
|
|
1780
|
+
<div className={creatableToneHintRowClassName}>
|
|
1781
|
+
<input
|
|
1782
|
+
ref={inputRef}
|
|
1783
|
+
type="text"
|
|
1784
|
+
value={inputValue}
|
|
1785
|
+
onChange={(e) => {
|
|
1786
|
+
const raw = e.target.value
|
|
1787
|
+
const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
|
|
1788
|
+
if (sanitizeInput) {
|
|
1789
|
+
if (raw !== sanitized) onInvalidCharacters?.()
|
|
1790
|
+
else onValidInput?.()
|
|
1791
|
+
}
|
|
1792
|
+
setInputValue(
|
|
1793
|
+
maxLengthPerItem != null
|
|
1794
|
+
? sanitized.slice(0, maxLengthPerItem)
|
|
1795
|
+
: sanitized
|
|
1796
|
+
)
|
|
1797
|
+
}}
|
|
1798
|
+
maxLength={maxLengthPerItem}
|
|
1799
|
+
onKeyDown={handleKeyDown}
|
|
1800
|
+
disabled={disabled}
|
|
1801
|
+
placeholder={panelInputPlaceholder}
|
|
1802
|
+
className="min-w-0 flex-1 bg-transparent text-base text-semantic-text-primary outline-none placeholder:text-semantic-text-muted"
|
|
1803
|
+
role="combobox"
|
|
1804
|
+
aria-expanded={isOpen}
|
|
1805
|
+
aria-controls={listboxId}
|
|
1806
|
+
aria-haspopup="listbox"
|
|
1807
|
+
aria-autocomplete="list"
|
|
1808
|
+
/>
|
|
1809
|
+
<button
|
|
1810
|
+
type="button"
|
|
1811
|
+
disabled={disabled || !canShowEnterAffordance}
|
|
1812
|
+
onMouseDown={(e) => {
|
|
1813
|
+
e.preventDefault()
|
|
1814
|
+
}}
|
|
1815
|
+
onClick={() => {
|
|
1816
|
+
if (draftForCreate) addValue(inputValue)
|
|
1817
|
+
}}
|
|
1818
|
+
className={cn(
|
|
1819
|
+
creatableEnterHintKbdClassName,
|
|
1820
|
+
"shrink-0 enabled:cursor-pointer enabled:hover:bg-semantic-bg-hover disabled:opacity-50"
|
|
1791
1821
|
)}
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
</div>
|
|
1796
|
-
{maxItems != null ? (
|
|
1797
|
-
<div className="border-t border-solid border-semantic-border-layout bg-semantic-bg-ui px-4 py-2 text-left text-sm text-semantic-text-muted">
|
|
1798
|
-
Max selections allowed: {maxItems}
|
|
1799
|
-
</div>
|
|
1800
|
-
) : null}
|
|
1822
|
+
>
|
|
1823
|
+
Enter \u21B5
|
|
1824
|
+
</button>
|
|
1801
1825
|
</div>
|
|
1802
|
-
|
|
1826
|
+
</div>
|
|
1803
1827
|
|
|
1804
|
-
|
|
1805
|
-
|
|
1828
|
+
<div className="flex flex-col gap-2.5 px-4 pb-4 pt-0">
|
|
1829
|
+
{maxItems != null ? (
|
|
1830
|
+
<p className="m-0 py-1 text-sm text-semantic-text-muted">
|
|
1831
|
+
Max selections allowed: {maxItems}
|
|
1832
|
+
</p>
|
|
1833
|
+
) : null}
|
|
1834
|
+
|
|
1835
|
+
{value.length > 0 ? (
|
|
1836
|
+
<div
|
|
1837
|
+
className="flex flex-wrap gap-1.5 border-b border-solid border-semantic-border-layout pb-2.5"
|
|
1838
|
+
aria-label="Selected values"
|
|
1839
|
+
>
|
|
1840
|
+
{value.map((val) => (
|
|
1841
|
+
<span
|
|
1842
|
+
key={val}
|
|
1843
|
+
className="inline-flex max-w-full items-center gap-0.5 rounded bg-semantic-bg-ui py-1 pl-2 pr-0.5 text-sm text-semantic-text-primary"
|
|
1844
|
+
>
|
|
1845
|
+
<span className="min-w-0 truncate">
|
|
1846
|
+
{labelForValue(val, options)}
|
|
1847
|
+
</span>
|
|
1848
|
+
<button
|
|
1849
|
+
type="button"
|
|
1850
|
+
data-chip-remove
|
|
1851
|
+
disabled={disabled}
|
|
1852
|
+
aria-label={\`Remove \${labelForValue(val, options)}\`}
|
|
1853
|
+
className={cn(
|
|
1854
|
+
"inline-flex size-6 shrink-0 items-center justify-center rounded text-semantic-text-muted transition-colors",
|
|
1855
|
+
!disabled &&
|
|
1856
|
+
"hover:bg-semantic-bg-hover hover:text-semantic-text-primary"
|
|
1857
|
+
)}
|
|
1858
|
+
onMouseDown={(e) => {
|
|
1859
|
+
e.preventDefault()
|
|
1860
|
+
e.stopPropagation()
|
|
1861
|
+
}}
|
|
1862
|
+
onClick={(e) => {
|
|
1863
|
+
e.stopPropagation()
|
|
1864
|
+
if (!disabled) removeValue(val)
|
|
1865
|
+
}}
|
|
1866
|
+
>
|
|
1867
|
+
<X className="size-3.5" strokeWidth={2} aria-hidden />
|
|
1868
|
+
</button>
|
|
1869
|
+
</span>
|
|
1870
|
+
))}
|
|
1871
|
+
</div>
|
|
1872
|
+
) : null}
|
|
1873
|
+
|
|
1874
|
+
<div
|
|
1875
|
+
id={listboxId}
|
|
1876
|
+
role="listbox"
|
|
1877
|
+
className="flex flex-wrap gap-1.5"
|
|
1878
|
+
>
|
|
1806
1879
|
{filteredPresets.map((option) => (
|
|
1807
1880
|
<button
|
|
1808
1881
|
key={option.value}
|
|
1809
1882
|
type="button"
|
|
1883
|
+
role="option"
|
|
1884
|
+
aria-selected={false}
|
|
1810
1885
|
onMouseDown={(e) => {
|
|
1811
1886
|
e.preventDefault()
|
|
1812
1887
|
addValue(option.value)
|
|
1813
1888
|
}}
|
|
1814
|
-
className="inline-flex items-center gap-2.5 whitespace-nowrap rounded border-0 bg-semantic-bg-ui px-2 py-1 text-sm text-semantic-text-primary transition-colors hover:bg-semantic-bg-hover"
|
|
1889
|
+
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"
|
|
1815
1890
|
>
|
|
1816
1891
|
<Plus
|
|
1817
1892
|
className="size-2.5 shrink-0 text-semantic-text-muted"
|
|
@@ -1822,7 +1897,7 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1822
1897
|
</button>
|
|
1823
1898
|
))}
|
|
1824
1899
|
</div>
|
|
1825
|
-
|
|
1900
|
+
</div>
|
|
1826
1901
|
</div>
|
|
1827
1902
|
)}
|
|
1828
1903
|
</div>
|
package/package.json
CHANGED