myoperator-mcp 0.2.197 → 0.2.199
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 +170 -187
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1364,31 +1364,17 @@ ContactListItem.displayName = "ContactListItem";
|
|
|
1364
1364
|
export { ContactListItem };
|
|
1365
1365
|
`,
|
|
1366
1366
|
"creatable-multi-select": `import * as React from "react"
|
|
1367
|
-
import {
|
|
1368
|
-
import { ChevronDown, ChevronRight, Plus, X, Info } from "lucide-react"
|
|
1367
|
+
import { ChevronRight, Plus, Info } from "lucide-react"
|
|
1369
1368
|
|
|
1370
1369
|
import { cn } from "@/lib/utils"
|
|
1370
|
+
import {
|
|
1371
|
+
creatableSelectTriggerVariants,
|
|
1372
|
+
creatableEnterHintKbdClassName,
|
|
1373
|
+
creatableToneHintRowClassName,
|
|
1374
|
+
} from "./creatable-select"
|
|
1371
1375
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
{
|
|
1375
|
-
variants: {
|
|
1376
|
-
state: {
|
|
1377
|
-
default:
|
|
1378
|
-
"border border-solid border-semantic-border-input hover:border-semantic-border-input-focus",
|
|
1379
|
-
error:
|
|
1380
|
-
"border border-solid border-semantic-error-primary/40 hover:border-semantic-error-primary",
|
|
1381
|
-
focused:
|
|
1382
|
-
"border border-solid border-semantic-border-focus shadow-[0_0_0_1px_rgba(43,188,202,0.15)]",
|
|
1383
|
-
"focused-error":
|
|
1384
|
-
"border border-solid border-semantic-error-primary/60 shadow-[0_0_0_1px_rgba(240,68,56,0.1)]",
|
|
1385
|
-
},
|
|
1386
|
-
},
|
|
1387
|
-
defaultVariants: {
|
|
1388
|
-
state: "default",
|
|
1389
|
-
},
|
|
1390
|
-
}
|
|
1391
|
-
)
|
|
1376
|
+
/** @deprecated Use \`creatableSelectTriggerVariants\` from \`./creatable-select\` \u2014 aliases the same trigger styles as Primary Role. */
|
|
1377
|
+
const creatableMultiSelectTriggerVariants = creatableSelectTriggerVariants
|
|
1392
1378
|
|
|
1393
1379
|
export interface CreatableMultiSelectOption {
|
|
1394
1380
|
value: string
|
|
@@ -1421,6 +1407,11 @@ export interface CreatableMultiSelectProps
|
|
|
1421
1407
|
maxItems?: number
|
|
1422
1408
|
/** Max character length per item when typing/creating (default: unlimited) */
|
|
1423
1409
|
maxLengthPerItem?: number
|
|
1410
|
+
/**
|
|
1411
|
+
* When true (default), shows \`current/max\` under the trigger while typing when \`maxLengthPerItem\` is set.
|
|
1412
|
+
* Set to false to match Figma (counter lives only in the field flow / not under the control).
|
|
1413
|
+
*/
|
|
1414
|
+
showPerItemCharacterCounter?: boolean
|
|
1424
1415
|
/**
|
|
1425
1416
|
* When set, the text input is transformed (e.g. strip invalid characters).
|
|
1426
1417
|
* If the raw value differs from the sanitized value, \`onInvalidCharacters\` is called.
|
|
@@ -1435,6 +1426,15 @@ export interface CreatableMultiSelectProps
|
|
|
1435
1426
|
onValidInput?: () => void
|
|
1436
1427
|
}
|
|
1437
1428
|
|
|
1429
|
+
function joinSelectedLabels(
|
|
1430
|
+
values: string[],
|
|
1431
|
+
options: CreatableMultiSelectOption[]
|
|
1432
|
+
): string {
|
|
1433
|
+
return values
|
|
1434
|
+
.map((val) => options.find((o) => o.value === val)?.label ?? val)
|
|
1435
|
+
.join(", ")
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
1438
|
const CreatableMultiSelect = React.forwardRef(
|
|
1439
1439
|
(
|
|
1440
1440
|
{
|
|
@@ -1449,6 +1449,7 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1449
1449
|
createHintText,
|
|
1450
1450
|
maxItems,
|
|
1451
1451
|
maxLengthPerItem,
|
|
1452
|
+
showPerItemCharacterCounter = true,
|
|
1452
1453
|
sanitizeInput,
|
|
1453
1454
|
onInvalidCharacters,
|
|
1454
1455
|
onValidInput,
|
|
@@ -1464,30 +1465,39 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1464
1465
|
|
|
1465
1466
|
React.useImperativeHandle(ref, () => containerRef.current!)
|
|
1466
1467
|
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1468
|
+
const derivedState = state === "error" ? "error" : "default"
|
|
1469
|
+
|
|
1470
|
+
const selectedSummary = joinSelectedLabels(value, options)
|
|
1471
|
+
|
|
1472
|
+
const addValue = (val: string) => {
|
|
1473
|
+
const afterSanitize = sanitizeInput ? sanitizeInput(val) : val
|
|
1474
|
+
const trimmed = afterSanitize.trim()
|
|
1475
|
+
if (!trimmed || value.includes(trimmed)) return
|
|
1476
|
+
if (maxItems != null && value.length >= maxItems) return
|
|
1477
|
+
const toAdd =
|
|
1478
|
+
maxLengthPerItem != null
|
|
1479
|
+
? trimmed.slice(0, maxLengthPerItem)
|
|
1480
|
+
: trimmed
|
|
1481
|
+
if (toAdd) {
|
|
1482
|
+
onValueChange?.([...value, toAdd])
|
|
1483
|
+
setInputValue("")
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1484
1486
|
|
|
1485
|
-
const removeValue =
|
|
1486
|
-
(
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1487
|
+
const removeValue = (val: string) => {
|
|
1488
|
+
onValueChange?.(value.filter((v) => v !== val))
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
const handleOpen = React.useCallback(() => {
|
|
1492
|
+
if (disabled) return
|
|
1493
|
+
setIsOpen(true)
|
|
1494
|
+
setInputValue("")
|
|
1495
|
+
}, [disabled])
|
|
1496
|
+
|
|
1497
|
+
React.useEffect(() => {
|
|
1498
|
+
if (!isOpen) return
|
|
1499
|
+
requestAnimationFrame(() => inputRef.current?.focus())
|
|
1500
|
+
}, [isOpen])
|
|
1491
1501
|
|
|
1492
1502
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
1493
1503
|
if (e.key === "Enter") {
|
|
@@ -1542,18 +1552,11 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1542
1552
|
|
|
1543
1553
|
const hasHintCopy = Boolean(createHintText) || maxItems != null
|
|
1544
1554
|
|
|
1545
|
-
const
|
|
1546
|
-
hasHintCopy || canShowEnterAffordance
|
|
1555
|
+
const showHintsSection = hasHintCopy || canShowEnterAffordance
|
|
1547
1556
|
|
|
1548
|
-
const
|
|
1549
|
-
?
|
|
1550
|
-
|
|
1551
|
-
: "focused"
|
|
1552
|
-
: state
|
|
1553
|
-
|
|
1554
|
-
/** Must match \`CreatableSelect\` hint-row \`<kbd>\` (Primary Role) \u2014 includes \`font-sans\` to override UA monospace on \`<kbd>\`. */
|
|
1555
|
-
const creatableHintEnterKbdClassName =
|
|
1556
|
-
"inline-flex items-center gap-0.5 rounded border border-solid border-semantic-border-layout bg-semantic-bg-ui px-1.5 py-0.5 font-sans text-[10px] font-medium text-semantic-text-muted"
|
|
1557
|
+
const inputPlaceholder = isOpen
|
|
1558
|
+
? selectedSummary || placeholder
|
|
1559
|
+
: ""
|
|
1557
1560
|
|
|
1558
1561
|
return (
|
|
1559
1562
|
<div
|
|
@@ -1561,146 +1564,107 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1561
1564
|
className={cn("relative w-full", className)}
|
|
1562
1565
|
{...props}
|
|
1563
1566
|
>
|
|
1564
|
-
{/* Positioning context = trigger only so the dropdown aligns like CreatableSelect (counter sits below, not above the panel). */}
|
|
1565
1567
|
<div className="relative w-full">
|
|
1566
|
-
{
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
const raw = e.target.value
|
|
1611
|
-
const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
|
|
1612
|
-
if (sanitizeInput) {
|
|
1613
|
-
if (raw !== sanitized) onInvalidCharacters?.()
|
|
1614
|
-
else onValidInput?.()
|
|
1615
|
-
}
|
|
1616
|
-
setInputValue(
|
|
1617
|
-
maxLengthPerItem != null
|
|
1618
|
-
? sanitized.slice(0, maxLengthPerItem)
|
|
1619
|
-
: sanitized
|
|
1620
|
-
)
|
|
1621
|
-
if (!isOpen) setIsOpen(true)
|
|
1622
|
-
}}
|
|
1623
|
-
maxLength={maxLengthPerItem}
|
|
1624
|
-
onFocus={() => {
|
|
1625
|
-
if (!disabled) setIsOpen(true)
|
|
1626
|
-
}}
|
|
1627
|
-
onKeyDown={handleKeyDown}
|
|
1568
|
+
{isOpen ? (
|
|
1569
|
+
<div
|
|
1570
|
+
className={cn(
|
|
1571
|
+
creatableSelectTriggerVariants({ state: derivedState }),
|
|
1572
|
+
"cursor-text"
|
|
1573
|
+
)}
|
|
1574
|
+
onClick={() => inputRef.current?.focus()}
|
|
1575
|
+
>
|
|
1576
|
+
<input
|
|
1577
|
+
ref={inputRef}
|
|
1578
|
+
type="text"
|
|
1579
|
+
value={inputValue}
|
|
1580
|
+
onChange={(e) => {
|
|
1581
|
+
const raw = e.target.value
|
|
1582
|
+
const sanitized = sanitizeInput ? sanitizeInput(raw) : raw
|
|
1583
|
+
if (sanitizeInput) {
|
|
1584
|
+
if (raw !== sanitized) onInvalidCharacters?.()
|
|
1585
|
+
else onValidInput?.()
|
|
1586
|
+
}
|
|
1587
|
+
setInputValue(
|
|
1588
|
+
maxLengthPerItem != null
|
|
1589
|
+
? sanitized.slice(0, maxLengthPerItem)
|
|
1590
|
+
: sanitized
|
|
1591
|
+
)
|
|
1592
|
+
}}
|
|
1593
|
+
maxLength={maxLengthPerItem}
|
|
1594
|
+
onKeyDown={handleKeyDown}
|
|
1595
|
+
disabled={disabled}
|
|
1596
|
+
placeholder={inputPlaceholder}
|
|
1597
|
+
className="flex-1 min-w-0 bg-transparent outline-none text-base text-semantic-text-primary placeholder:text-semantic-text-muted"
|
|
1598
|
+
role="combobox"
|
|
1599
|
+
aria-expanded={isOpen}
|
|
1600
|
+
aria-controls={listboxId}
|
|
1601
|
+
aria-haspopup="listbox"
|
|
1602
|
+
aria-autocomplete="list"
|
|
1603
|
+
/>
|
|
1604
|
+
<ChevronRight
|
|
1605
|
+
className="size-5 text-semantic-text-muted shrink-0 opacity-70"
|
|
1606
|
+
aria-hidden
|
|
1607
|
+
/>
|
|
1608
|
+
</div>
|
|
1609
|
+
) : (
|
|
1610
|
+
<button
|
|
1611
|
+
type="button"
|
|
1628
1612
|
disabled={disabled}
|
|
1629
|
-
|
|
1630
|
-
className=
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1613
|
+
onClick={handleOpen}
|
|
1614
|
+
className={cn(
|
|
1615
|
+
creatableSelectTriggerVariants({ state: derivedState }),
|
|
1616
|
+
"cursor-pointer text-left"
|
|
1617
|
+
)}
|
|
1634
1618
|
aria-haspopup="listbox"
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1619
|
+
aria-expanded={false}
|
|
1620
|
+
aria-controls={listboxId}
|
|
1621
|
+
>
|
|
1622
|
+
<span
|
|
1623
|
+
className={cn(
|
|
1624
|
+
"flex-1 min-w-0 line-clamp-2 text-base",
|
|
1625
|
+
!selectedSummary && "text-semantic-text-muted"
|
|
1626
|
+
)}
|
|
1627
|
+
>
|
|
1628
|
+
{selectedSummary || placeholder}
|
|
1629
|
+
</span>
|
|
1630
|
+
<ChevronRight
|
|
1631
|
+
className="size-5 text-semantic-text-muted shrink-0 opacity-70"
|
|
1632
|
+
aria-hidden
|
|
1633
|
+
/>
|
|
1634
|
+
</button>
|
|
1635
|
+
)}
|
|
1644
1636
|
|
|
1645
|
-
{/* Dropdown panel
|
|
1637
|
+
{/* Dropdown panel */}
|
|
1646
1638
|
{isOpen && (
|
|
1647
1639
|
<div
|
|
1648
1640
|
id={listboxId}
|
|
1649
1641
|
role="listbox"
|
|
1650
|
-
className="absolute left-0 top-full z-[9999] mt-1 w-full rounded border border-solid border-semantic-border-layout bg-semantic-bg-primary shadow-
|
|
1642
|
+
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"
|
|
1651
1643
|
>
|
|
1652
|
-
{
|
|
1653
|
-
|
|
1654
|
-
className={
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
{hasHintCopy ? (
|
|
1662
|
-
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
1663
|
-
{createHintText ? (
|
|
1664
|
-
<span className="text-sm text-semantic-text-muted">
|
|
1665
|
-
{createHintText}
|
|
1666
|
-
</span>
|
|
1667
|
-
) : null}
|
|
1668
|
-
{maxItems != null ? (
|
|
1669
|
-
<span className="text-xs text-semantic-text-muted">
|
|
1670
|
-
Max selections allowed: {maxItems}
|
|
1671
|
-
</span>
|
|
1672
|
-
) : null}
|
|
1673
|
-
</div>
|
|
1674
|
-
) : null}
|
|
1675
|
-
<span
|
|
1676
|
-
role="button"
|
|
1677
|
-
tabIndex={canShowEnterAffordance ? 0 : -1}
|
|
1678
|
-
aria-label="Add using Enter key"
|
|
1679
|
-
aria-disabled={!canShowEnterAffordance}
|
|
1680
|
-
className={cn(
|
|
1681
|
-
"inline-flex shrink-0",
|
|
1682
|
-
!canShowEnterAffordance && "pointer-events-none"
|
|
1644
|
+
{showHintsSection && (
|
|
1645
|
+
<>
|
|
1646
|
+
<div className={creatableToneHintRowClassName}>
|
|
1647
|
+
{createHintText ? (
|
|
1648
|
+
<span className="text-sm text-semantic-text-muted">
|
|
1649
|
+
{createHintText}
|
|
1650
|
+
</span>
|
|
1651
|
+
) : (
|
|
1652
|
+
<span className="min-w-0 flex-1" />
|
|
1683
1653
|
)}
|
|
1684
|
-
|
|
1685
|
-
e.preventDefault()
|
|
1686
|
-
if (canShowEnterAffordance) addValue(inputValue)
|
|
1687
|
-
}}
|
|
1688
|
-
onKeyDown={(e) => {
|
|
1689
|
-
if (e.key !== "Enter" && e.key !== " ") return
|
|
1690
|
-
e.preventDefault()
|
|
1691
|
-
if (canShowEnterAffordance) addValue(inputValue)
|
|
1692
|
-
}}
|
|
1693
|
-
>
|
|
1694
|
-
<kbd className={creatableHintEnterKbdClassName}>
|
|
1654
|
+
<kbd className={creatableEnterHintKbdClassName}>
|
|
1695
1655
|
Enter \u21B5
|
|
1696
1656
|
</kbd>
|
|
1697
|
-
</
|
|
1698
|
-
|
|
1657
|
+
</div>
|
|
1658
|
+
{maxItems != null ? (
|
|
1659
|
+
<p className="m-0 text-left text-sm text-semantic-text-muted">
|
|
1660
|
+
Max selections allowed: {maxItems}
|
|
1661
|
+
</p>
|
|
1662
|
+
) : null}
|
|
1663
|
+
</>
|
|
1699
1664
|
)}
|
|
1700
1665
|
|
|
1701
|
-
{/* Preset option chips \u2014 pt-1 px-4 matches CreatableSelect listbox padding above first option */}
|
|
1702
1666
|
{filteredPresets.length > 0 && (
|
|
1703
|
-
<div className="flex flex-wrap gap-1.5
|
|
1667
|
+
<div className="flex flex-wrap gap-1.5">
|
|
1704
1668
|
{filteredPresets.map((option) => (
|
|
1705
1669
|
<button
|
|
1706
1670
|
key={option.value}
|
|
@@ -1709,9 +1673,13 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1709
1673
|
e.preventDefault()
|
|
1710
1674
|
addValue(option.value)
|
|
1711
1675
|
}}
|
|
1712
|
-
className="inline-flex items-center gap-
|
|
1676
|
+
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"
|
|
1713
1677
|
>
|
|
1714
|
-
<Plus
|
|
1678
|
+
<Plus
|
|
1679
|
+
className="size-2.5 shrink-0 text-semantic-text-muted"
|
|
1680
|
+
strokeWidth={2}
|
|
1681
|
+
aria-hidden
|
|
1682
|
+
/>
|
|
1715
1683
|
{option.label}
|
|
1716
1684
|
</button>
|
|
1717
1685
|
))}
|
|
@@ -1721,8 +1689,9 @@ const CreatableMultiSelect = React.forwardRef(
|
|
|
1721
1689
|
)}
|
|
1722
1690
|
</div>
|
|
1723
1691
|
|
|
1724
|
-
{
|
|
1725
|
-
|
|
1692
|
+
{maxLengthPerItem != null &&
|
|
1693
|
+
showPerItemCharacterCounter &&
|
|
1694
|
+
isOpen ? (
|
|
1726
1695
|
<div className="mt-1.5 flex items-center justify-end gap-2">
|
|
1727
1696
|
<span className="shrink-0 text-sm text-semantic-text-muted">
|
|
1728
1697
|
{inputValue.length}/{maxLengthPerItem}
|
|
@@ -1770,6 +1739,20 @@ const creatableSelectTriggerVariants = cva(
|
|
|
1770
1739
|
}
|
|
1771
1740
|
)
|
|
1772
1741
|
|
|
1742
|
+
/**
|
|
1743
|
+
* Tailwind classes for the "Enter \u21B5" hint in creatable dropdown headers (shared by Primary Role and Tone).
|
|
1744
|
+
*/
|
|
1745
|
+
export const creatableEnterHintKbdClassName =
|
|
1746
|
+
"inline-flex items-center gap-0.5 rounded border border-solid border-semantic-border-layout bg-semantic-bg-ui px-1.5 py-0.5 font-sans text-[10px] font-medium text-semantic-text-muted"
|
|
1747
|
+
|
|
1748
|
+
/** Primary Role: hint row above the options list (custom role + Enter kbd). */
|
|
1749
|
+
export const creatablePrimaryRoleHintRowClassName =
|
|
1750
|
+
"flex items-center justify-between px-4 py-2 border-b border-solid border-semantic-border-layout"
|
|
1751
|
+
|
|
1752
|
+
/** Tone / CreatableMultiSelect: hint row inside the padded dropdown panel (-mx-4 full-bleed border). */
|
|
1753
|
+
export const creatableToneHintRowClassName =
|
|
1754
|
+
"-mx-4 flex min-h-[45px] shrink-0 items-center justify-between gap-2.5 border-b border-solid border-semantic-border-layout px-4 py-2.5"
|
|
1755
|
+
|
|
1773
1756
|
export interface CreatableSelectOption {
|
|
1774
1757
|
value: string
|
|
1775
1758
|
label: string
|
|
@@ -2039,11 +2022,11 @@ const CreatableSelect = React.forwardRef(
|
|
|
2039
2022
|
{open && (
|
|
2040
2023
|
<div className="absolute left-0 top-full z-[9999] mt-1 w-full rounded border border-solid border-semantic-border-layout bg-semantic-bg-primary shadow-md animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-200">
|
|
2041
2024
|
{creatableHint ? (
|
|
2042
|
-
<div className=
|
|
2025
|
+
<div className={creatablePrimaryRoleHintRowClassName}>
|
|
2043
2026
|
<span className="text-sm text-semantic-text-muted">
|
|
2044
2027
|
{creatableHint}
|
|
2045
2028
|
</span>
|
|
2046
|
-
<kbd className=
|
|
2029
|
+
<kbd className={creatableEnterHintKbdClassName}>
|
|
2047
2030
|
Enter \u21B5
|
|
2048
2031
|
</kbd>
|
|
2049
2032
|
</div>
|
package/package.json
CHANGED