myoperator-mcp 0.2.357 → 0.2.358
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 +253 -72
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2812,6 +2812,129 @@ function isPointerInsideElement(
|
|
|
2812
2812
|
return false;
|
|
2813
2813
|
}
|
|
2814
2814
|
|
|
2815
|
+
// Floating sub-dropdowns (Month / Year / Time) are portaled to document.body
|
|
2816
|
+
// so they escape the popover's overflow clipping. Because they live outside the
|
|
2817
|
+
// popover in the DOM, the picker's own outside-click handler can't recognize
|
|
2818
|
+
// them via \`contains\`. Tagging each portaled panel with this attribute lets the
|
|
2819
|
+
// handler detect clicks that land inside an open sub-dropdown.
|
|
2820
|
+
const DROPDOWN_MARKER_ATTR = "data-dtp-dropdown";
|
|
2821
|
+
const DROPDOWN_GAP = 4;
|
|
2822
|
+
const DROPDOWN_MARGIN = 8;
|
|
2823
|
+
const DROPDOWN_MAX_HEIGHT = 256;
|
|
2824
|
+
const DROPDOWN_Z_INDEX = 10060;
|
|
2825
|
+
const DROPDOWN_PLACEMENT: Placement = "bottom-start";
|
|
2826
|
+
const DROPDOWN_WIDTH_VAR = "--date-time-picker-dropdown-width";
|
|
2827
|
+
const DROPDOWN_HEIGHT_VAR = "--date-time-picker-dropdown-height";
|
|
2828
|
+
|
|
2829
|
+
function isPointerInsideDropdown(event: MouseEvent) {
|
|
2830
|
+
const target = event.target;
|
|
2831
|
+
|
|
2832
|
+
return (
|
|
2833
|
+
target instanceof Element &&
|
|
2834
|
+
target.closest(\`[\${DROPDOWN_MARKER_ATTR}]\`) !== null
|
|
2835
|
+
);
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
// Shared floating + dismissal behavior for the Month, Year, and Time dropdowns.
|
|
2839
|
+
// Each instance positions its panel against its trigger, mirrors the picker's
|
|
2840
|
+
// portal strategy, and closes itself on an outside click or Escape \u2014 without
|
|
2841
|
+
// collapsing the parent picker (Escape is captured so it doesn't bubble to the
|
|
2842
|
+
// picker's own Escape handler).
|
|
2843
|
+
function useFloatingDropdown({
|
|
2844
|
+
open,
|
|
2845
|
+
onOpenChange,
|
|
2846
|
+
strategy,
|
|
2847
|
+
}: {
|
|
2848
|
+
open: boolean;
|
|
2849
|
+
onOpenChange: (open: boolean) => void;
|
|
2850
|
+
strategy: Strategy;
|
|
2851
|
+
}) {
|
|
2852
|
+
const middleware = React.useMemo(
|
|
2853
|
+
() => [
|
|
2854
|
+
offset(DROPDOWN_GAP),
|
|
2855
|
+
flip({ padding: DROPDOWN_MARGIN }),
|
|
2856
|
+
shift({ padding: DROPDOWN_MARGIN }),
|
|
2857
|
+
floatingSize({
|
|
2858
|
+
padding: DROPDOWN_MARGIN,
|
|
2859
|
+
apply({ availableHeight, rects, elements }) {
|
|
2860
|
+
const maxHeight = Math.max(
|
|
2861
|
+
1,
|
|
2862
|
+
Math.min(DROPDOWN_MAX_HEIGHT, availableHeight)
|
|
2863
|
+
);
|
|
2864
|
+
elements.floating.style.setProperty(
|
|
2865
|
+
DROPDOWN_HEIGHT_VAR,
|
|
2866
|
+
\`\${maxHeight}px\`
|
|
2867
|
+
);
|
|
2868
|
+
elements.floating.style.setProperty(
|
|
2869
|
+
DROPDOWN_WIDTH_VAR,
|
|
2870
|
+
\`\${rects.reference.width}px\`
|
|
2871
|
+
);
|
|
2872
|
+
},
|
|
2873
|
+
}),
|
|
2874
|
+
],
|
|
2875
|
+
[]
|
|
2876
|
+
);
|
|
2877
|
+
|
|
2878
|
+
const floating = useFloating<HTMLButtonElement>({
|
|
2879
|
+
open,
|
|
2880
|
+
placement: DROPDOWN_PLACEMENT,
|
|
2881
|
+
strategy,
|
|
2882
|
+
transform: false,
|
|
2883
|
+
middleware,
|
|
2884
|
+
whileElementsMounted: (reference, floatingEl, update) =>
|
|
2885
|
+
autoUpdate(reference, floatingEl, update, { animationFrame: true }),
|
|
2886
|
+
});
|
|
2887
|
+
|
|
2888
|
+
const { refs, floatingStyles, isPositioned } = floating;
|
|
2889
|
+
|
|
2890
|
+
React.useEffect(() => {
|
|
2891
|
+
if (!open) return;
|
|
2892
|
+
|
|
2893
|
+
const handlePointerDown = (event: MouseEvent) => {
|
|
2894
|
+
const reference = refs.reference.current as HTMLElement | null;
|
|
2895
|
+
if (
|
|
2896
|
+
!isPointerInsideElement(event, reference) &&
|
|
2897
|
+
!isPointerInsideElement(event, refs.floating.current)
|
|
2898
|
+
) {
|
|
2899
|
+
onOpenChange(false);
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
2904
|
+
if (event.key === "Escape") {
|
|
2905
|
+
// Capture phase + stopPropagation keeps Escape from also reaching the
|
|
2906
|
+
// picker's handler, so it dismisses just this dropdown.
|
|
2907
|
+
event.stopPropagation();
|
|
2908
|
+
onOpenChange(false);
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
|
|
2912
|
+
// Capture phase: the popover container calls stopPropagation on its own
|
|
2913
|
+
// mousedown, which would otherwise swallow clicks inside it before they
|
|
2914
|
+
// reach a bubble-phase document listener. Listening on capture runs this
|
|
2915
|
+
// handler top-down \u2014 before that stopPropagation \u2014 so clicks anywhere
|
|
2916
|
+
// outside the dropdown (including elsewhere in the popover) dismiss it.
|
|
2917
|
+
document.addEventListener("mousedown", handlePointerDown, true);
|
|
2918
|
+
document.addEventListener("keydown", handleKeyDown, true);
|
|
2919
|
+
|
|
2920
|
+
return () => {
|
|
2921
|
+
document.removeEventListener("mousedown", handlePointerDown, true);
|
|
2922
|
+
document.removeEventListener("keydown", handleKeyDown, true);
|
|
2923
|
+
};
|
|
2924
|
+
}, [open, onOpenChange, refs]);
|
|
2925
|
+
|
|
2926
|
+
const setReference = React.useCallback(
|
|
2927
|
+
(node: HTMLButtonElement | null) => refs.setReference(node),
|
|
2928
|
+
[refs]
|
|
2929
|
+
);
|
|
2930
|
+
const setFloating = React.useCallback(
|
|
2931
|
+
(node: HTMLDivElement | null) => refs.setFloating(node),
|
|
2932
|
+
[refs]
|
|
2933
|
+
);
|
|
2934
|
+
|
|
2935
|
+
return { setReference, setFloating, floatingStyles, isPositioned };
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2815
2938
|
function timeHasVisibleSeconds(time?: string) {
|
|
2816
2939
|
const [, , second = "00"] = (time ?? "").split(":");
|
|
2817
2940
|
return /^\\d{1,2}$/.test(second) && Number(second) !== 0;
|
|
@@ -3459,6 +3582,8 @@ function CalendarDropdown({
|
|
|
3459
3582
|
open,
|
|
3460
3583
|
onOpenChange,
|
|
3461
3584
|
onValueChange,
|
|
3585
|
+
portalMount,
|
|
3586
|
+
strategy,
|
|
3462
3587
|
}: {
|
|
3463
3588
|
id: string;
|
|
3464
3589
|
label: string;
|
|
@@ -3467,8 +3592,16 @@ function CalendarDropdown({
|
|
|
3467
3592
|
open: boolean;
|
|
3468
3593
|
onOpenChange: (open: boolean) => void;
|
|
3469
3594
|
onValueChange: (value: string) => void;
|
|
3595
|
+
portalMount: HTMLElement | null;
|
|
3596
|
+
strategy: Strategy;
|
|
3470
3597
|
}) {
|
|
3471
3598
|
const selectedOption = options.find((option) => option.value === value);
|
|
3599
|
+
const { setReference, setFloating, floatingStyles, isPositioned } =
|
|
3600
|
+
useFloatingDropdown({
|
|
3601
|
+
open,
|
|
3602
|
+
onOpenChange,
|
|
3603
|
+
strategy,
|
|
3604
|
+
});
|
|
3472
3605
|
|
|
3473
3606
|
return (
|
|
3474
3607
|
<div className="relative">
|
|
@@ -3476,6 +3609,7 @@ function CalendarDropdown({
|
|
|
3476
3609
|
{label}
|
|
3477
3610
|
</label>
|
|
3478
3611
|
<button
|
|
3612
|
+
ref={setReference}
|
|
3479
3613
|
id={id}
|
|
3480
3614
|
type="button"
|
|
3481
3615
|
role="combobox"
|
|
@@ -3495,37 +3629,51 @@ function CalendarDropdown({
|
|
|
3495
3629
|
aria-hidden="true"
|
|
3496
3630
|
/>
|
|
3497
3631
|
</button>
|
|
3498
|
-
{open &&
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3632
|
+
{open &&
|
|
3633
|
+
portalMount &&
|
|
3634
|
+
createPortal(
|
|
3635
|
+
<div
|
|
3636
|
+
ref={setFloating}
|
|
3637
|
+
id={\`\${id}-options\`}
|
|
3638
|
+
role="listbox"
|
|
3639
|
+
aria-label={\`\${label} options\`}
|
|
3640
|
+
data-dtp-dropdown=""
|
|
3641
|
+
className="flex flex-col gap-0.5 overflow-y-auto rounded-md border border-solid border-semantic-border-layout bg-semantic-bg-primary p-1 shadow-lg [scrollbar-width:thin] [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-semantic-border-secondary [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar]:w-1.5"
|
|
3642
|
+
style={{
|
|
3643
|
+
...floatingStyles,
|
|
3644
|
+
width: \`var(\${DROPDOWN_WIDTH_VAR}, auto)\`,
|
|
3645
|
+
maxHeight: \`var(\${DROPDOWN_HEIGHT_VAR}, \${DROPDOWN_MAX_HEIGHT}px)\`,
|
|
3646
|
+
zIndex: DROPDOWN_Z_INDEX,
|
|
3647
|
+
visibility: isPositioned ? undefined : "hidden",
|
|
3648
|
+
}}
|
|
3649
|
+
>
|
|
3650
|
+
{options.map((option) => (
|
|
3651
|
+
<button
|
|
3652
|
+
key={option.value}
|
|
3653
|
+
type="button"
|
|
3654
|
+
role="option"
|
|
3655
|
+
aria-label={option.label}
|
|
3656
|
+
aria-selected={option.value === value}
|
|
3657
|
+
disabled={option.disabled}
|
|
3658
|
+
className={cn(
|
|
3659
|
+
"flex w-full shrink-0 items-center rounded-md border border-solid px-2 py-1.5 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-40",
|
|
3660
|
+
option.value === value
|
|
3661
|
+
? "border-semantic-info-border bg-semantic-info-surface font-semibold text-semantic-text-primary"
|
|
3662
|
+
: "border-transparent text-semantic-text-secondary hover:bg-semantic-bg-hover"
|
|
3663
|
+
)}
|
|
3664
|
+
onClick={() => {
|
|
3665
|
+
if (option.disabled) return;
|
|
3519
3666
|
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3667
|
+
onValueChange(option.value);
|
|
3668
|
+
onOpenChange(false);
|
|
3669
|
+
}}
|
|
3670
|
+
>
|
|
3671
|
+
{option.label}
|
|
3672
|
+
</button>
|
|
3673
|
+
))}
|
|
3674
|
+
</div>,
|
|
3675
|
+
portalMount
|
|
3676
|
+
)}
|
|
3529
3677
|
</div>
|
|
3530
3678
|
);
|
|
3531
3679
|
}
|
|
@@ -3604,6 +3752,8 @@ function TimeField({
|
|
|
3604
3752
|
open,
|
|
3605
3753
|
onOpenChange,
|
|
3606
3754
|
onChange,
|
|
3755
|
+
portalMount,
|
|
3756
|
+
strategy,
|
|
3607
3757
|
}: {
|
|
3608
3758
|
id: string;
|
|
3609
3759
|
label: string;
|
|
@@ -3614,8 +3764,16 @@ function TimeField({
|
|
|
3614
3764
|
open: boolean;
|
|
3615
3765
|
onOpenChange: (open: boolean) => void;
|
|
3616
3766
|
onChange: (time: string) => void;
|
|
3767
|
+
portalMount: HTMLElement | null;
|
|
3768
|
+
strategy: Strategy;
|
|
3617
3769
|
}) {
|
|
3618
3770
|
const { hour12, minute, second, meridiem } = decomposeTime(value);
|
|
3771
|
+
const { setReference, setFloating, floatingStyles, isPositioned } =
|
|
3772
|
+
useFloatingDropdown({
|
|
3773
|
+
open,
|
|
3774
|
+
onOpenChange,
|
|
3775
|
+
strategy,
|
|
3776
|
+
});
|
|
3619
3777
|
// When seconds are hidden they are not editable, so normalize to :00 on any
|
|
3620
3778
|
// change rather than carrying a stale seconds value forward.
|
|
3621
3779
|
const effectiveSecond = showSeconds ? second : 0;
|
|
@@ -3660,6 +3818,7 @@ function TimeField({
|
|
|
3660
3818
|
{label}
|
|
3661
3819
|
</span>
|
|
3662
3820
|
<button
|
|
3821
|
+
ref={setReference}
|
|
3663
3822
|
id={id}
|
|
3664
3823
|
type="button"
|
|
3665
3824
|
aria-label={label}
|
|
@@ -3687,51 +3846,64 @@ function TimeField({
|
|
|
3687
3846
|
aria-hidden="true"
|
|
3688
3847
|
/>
|
|
3689
3848
|
</button>
|
|
3690
|
-
{open &&
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
onSelect={(key) =>
|
|
3710
|
-
onChange(composeTime(hour12, Number(key), effectiveSecond, meridiem))
|
|
3711
|
-
}
|
|
3712
|
-
/>
|
|
3713
|
-
{showSeconds && (
|
|
3849
|
+
{open &&
|
|
3850
|
+
portalMount &&
|
|
3851
|
+
createPortal(
|
|
3852
|
+
<div
|
|
3853
|
+
ref={setFloating}
|
|
3854
|
+
role="listbox"
|
|
3855
|
+
aria-label={\`\${label} options\`}
|
|
3856
|
+
data-dtp-dropdown=""
|
|
3857
|
+
className={cn(
|
|
3858
|
+
"grid overflow-hidden rounded-lg border border-solid border-semantic-border-layout bg-semantic-bg-primary shadow-lg",
|
|
3859
|
+
showSeconds ? "grid-cols-4" : "grid-cols-3"
|
|
3860
|
+
)}
|
|
3861
|
+
style={{
|
|
3862
|
+
...floatingStyles,
|
|
3863
|
+
width: \`var(\${DROPDOWN_WIDTH_VAR}, auto)\`,
|
|
3864
|
+
zIndex: DROPDOWN_Z_INDEX,
|
|
3865
|
+
visibility: isPositioned ? undefined : "hidden",
|
|
3866
|
+
}}
|
|
3867
|
+
>
|
|
3714
3868
|
<TimeColumn
|
|
3715
|
-
header="
|
|
3716
|
-
ariaLabel={\`\${label}
|
|
3717
|
-
options={
|
|
3869
|
+
header="Hours"
|
|
3870
|
+
ariaLabel={\`\${label} hours\`}
|
|
3871
|
+
options={hourOptions}
|
|
3718
3872
|
onSelect={(key) =>
|
|
3719
|
-
onChange(composeTime(
|
|
3873
|
+
onChange(composeTime(Number(key), minute, effectiveSecond, meridiem))
|
|
3720
3874
|
}
|
|
3721
3875
|
/>
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3876
|
+
<TimeColumn
|
|
3877
|
+
header="Minutes"
|
|
3878
|
+
ariaLabel={\`\${label} minutes\`}
|
|
3879
|
+
options={minuteOptions}
|
|
3880
|
+
onSelect={(key) =>
|
|
3881
|
+
onChange(composeTime(hour12, Number(key), effectiveSecond, meridiem))
|
|
3882
|
+
}
|
|
3883
|
+
/>
|
|
3884
|
+
{showSeconds && (
|
|
3885
|
+
<TimeColumn
|
|
3886
|
+
header="Seconds"
|
|
3887
|
+
ariaLabel={\`\${label} seconds\`}
|
|
3888
|
+
options={secondOptions}
|
|
3889
|
+
onSelect={(key) =>
|
|
3890
|
+
onChange(composeTime(hour12, minute, Number(key), meridiem))
|
|
3891
|
+
}
|
|
3892
|
+
/>
|
|
3893
|
+
)}
|
|
3894
|
+
<TimeColumn
|
|
3895
|
+
header="AM/PM"
|
|
3896
|
+
ariaLabel={\`\${label} meridiem\`}
|
|
3897
|
+
options={meridiemOptions}
|
|
3898
|
+
onSelect={(key) =>
|
|
3899
|
+
onChange(
|
|
3900
|
+
composeTime(hour12, minute, effectiveSecond, key as Meridiem)
|
|
3901
|
+
)
|
|
3902
|
+
}
|
|
3903
|
+
/>
|
|
3904
|
+
</div>,
|
|
3905
|
+
portalMount
|
|
3906
|
+
)}
|
|
3735
3907
|
</div>
|
|
3736
3908
|
);
|
|
3737
3909
|
}
|
|
@@ -3938,7 +4110,8 @@ const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerProps>(
|
|
|
3938
4110
|
const handlePointerDown = (event: MouseEvent) => {
|
|
3939
4111
|
if (
|
|
3940
4112
|
!isPointerInsideElement(event, rootRef.current) &&
|
|
3941
|
-
!isPointerInsideElement(event, popoverRef.current)
|
|
4113
|
+
!isPointerInsideElement(event, popoverRef.current) &&
|
|
4114
|
+
!isPointerInsideDropdown(event)
|
|
3942
4115
|
) {
|
|
3943
4116
|
setOpen(false);
|
|
3944
4117
|
}
|
|
@@ -4284,6 +4457,8 @@ const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerProps>(
|
|
|
4284
4457
|
id={\`\${triggerId}-month\`}
|
|
4285
4458
|
label="Month"
|
|
4286
4459
|
value={visibleMonth.getMonth().toString()}
|
|
4460
|
+
portalMount={portalMount}
|
|
4461
|
+
strategy={floatingStrategy}
|
|
4287
4462
|
open={openCalendarDropdown === "month"}
|
|
4288
4463
|
onOpenChange={(nextOpen) =>
|
|
4289
4464
|
setOpenCalendarDropdown(nextOpen ? "month" : null)
|
|
@@ -4319,6 +4494,8 @@ const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerProps>(
|
|
|
4319
4494
|
id={\`\${triggerId}-year\`}
|
|
4320
4495
|
label="Year"
|
|
4321
4496
|
value={visibleMonth.getFullYear().toString()}
|
|
4497
|
+
portalMount={portalMount}
|
|
4498
|
+
strategy={floatingStrategy}
|
|
4322
4499
|
open={openCalendarDropdown === "year"}
|
|
4323
4500
|
onOpenChange={(nextOpen) =>
|
|
4324
4501
|
setOpenCalendarDropdown(nextOpen ? "year" : null)
|
|
@@ -4429,6 +4606,8 @@ const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerProps>(
|
|
|
4429
4606
|
showSeconds={resolvedShowSeconds}
|
|
4430
4607
|
minuteStep={minuteStep}
|
|
4431
4608
|
secondStep={secondStep}
|
|
4609
|
+
portalMount={portalMount}
|
|
4610
|
+
strategy={floatingStrategy}
|
|
4432
4611
|
open={openTimeField === "start"}
|
|
4433
4612
|
onOpenChange={(nextOpen) =>
|
|
4434
4613
|
setOpenTimeField(nextOpen ? "start" : null)
|
|
@@ -4449,6 +4628,8 @@ const DateTimePicker = React.forwardRef<HTMLDivElement, DateTimePickerProps>(
|
|
|
4449
4628
|
showSeconds={resolvedShowSeconds}
|
|
4450
4629
|
minuteStep={minuteStep}
|
|
4451
4630
|
secondStep={secondStep}
|
|
4631
|
+
portalMount={portalMount}
|
|
4632
|
+
strategy={floatingStrategy}
|
|
4452
4633
|
open={openTimeField === "end"}
|
|
4453
4634
|
onOpenChange={(nextOpen) =>
|
|
4454
4635
|
setOpenTimeField(nextOpen ? "end" : null)
|
package/package.json
CHANGED