Files
ob248.com/node_modules/@radix-ui/react-password-toggle-field/dist/index.mjs
2026-02-05 17:31:20 +00:00

308 lines
10 KiB
JavaScript

"use client";
// src/password-toggle-field.tsx
import * as React from "react";
import { flushSync } from "react-dom";
import { composeEventHandlers } from "@radix-ui/primitive";
import { useControllableState } from "@radix-ui/react-use-controllable-state";
import { Primitive } from "@radix-ui/react-primitive";
import { useComposedRefs } from "@radix-ui/react-compose-refs";
import { useId } from "@radix-ui/react-id";
import { useIsHydrated } from "@radix-ui/react-use-is-hydrated";
import { useEffectEvent } from "@radix-ui/react-use-effect-event";
import { createContextScope } from "@radix-ui/react-context";
import { jsx } from "react/jsx-runtime";
var PASSWORD_TOGGLE_FIELD_NAME = "PasswordToggleField";
var [createPasswordToggleFieldContext] = createContextScope(PASSWORD_TOGGLE_FIELD_NAME);
var [PasswordToggleFieldProvider, usePasswordToggleFieldContext] = createPasswordToggleFieldContext(PASSWORD_TOGGLE_FIELD_NAME);
var INITIAL_FOCUS_STATE = {
clickTriggered: false,
selectionStart: null,
selectionEnd: null
};
var PasswordToggleField = ({
__scopePasswordToggleField,
...props
}) => {
const baseId = useId(props.id);
const defaultInputId = `${baseId}-input`;
const [inputIdState, setInputIdState] = React.useState(defaultInputId);
const inputId = inputIdState ?? defaultInputId;
const syncInputId = React.useCallback(
(providedId) => setInputIdState(providedId != null ? String(providedId) : null),
[]
);
const { visible: visibleProp, defaultVisible, onVisiblityChange, children } = props;
const [visible = false, setVisible] = useControllableState({
caller: PASSWORD_TOGGLE_FIELD_NAME,
prop: visibleProp,
defaultProp: defaultVisible ?? false,
onChange: onVisiblityChange
});
const inputRef = React.useRef(null);
const focusState = React.useRef(INITIAL_FOCUS_STATE);
return /* @__PURE__ */ jsx(
PasswordToggleFieldProvider,
{
scope: __scopePasswordToggleField,
inputId,
inputRef,
setVisible,
syncInputId,
visible,
focusState,
children
}
);
};
PasswordToggleField.displayName = PASSWORD_TOGGLE_FIELD_NAME;
var PASSWORD_TOGGLE_FIELD_INPUT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Input";
var PasswordToggleFieldInput = React.forwardRef(
({
__scopePasswordToggleField,
autoComplete = "current-password",
autoCapitalize = "off",
spellCheck = false,
id: idProp,
...props
}, forwardedRef) => {
const { visible, inputRef, inputId, syncInputId, setVisible, focusState } = usePasswordToggleFieldContext(PASSWORD_TOGGLE_FIELD_INPUT_NAME, __scopePasswordToggleField);
React.useEffect(() => {
syncInputId(idProp);
}, [idProp, syncInputId]);
const _setVisible = useEffectEvent(setVisible);
React.useEffect(() => {
const inputElement = inputRef.current;
const form = inputElement?.form;
if (!form) {
return;
}
const controller = new AbortController();
form.addEventListener(
"reset",
(event) => {
if (!event.defaultPrevented) {
_setVisible(false);
}
},
{ signal: controller.signal }
);
form.addEventListener(
"submit",
() => {
_setVisible(false);
},
{ signal: controller.signal }
);
return () => {
controller.abort();
};
}, [inputRef, _setVisible]);
return /* @__PURE__ */ jsx(
Primitive.input,
{
...props,
id: idProp ?? inputId,
autoCapitalize,
autoComplete,
ref: useComposedRefs(forwardedRef, inputRef),
spellCheck,
type: visible ? "text" : "password",
onBlur: composeEventHandlers(props.onBlur, (event) => {
const { selectionStart, selectionEnd } = event.currentTarget;
focusState.current.selectionStart = selectionStart;
focusState.current.selectionEnd = selectionEnd;
})
}
);
}
);
PasswordToggleFieldInput.displayName = PASSWORD_TOGGLE_FIELD_INPUT_NAME;
var PASSWORD_TOGGLE_FIELD_TOGGLE_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Toggle";
var PasswordToggleFieldToggle = React.forwardRef(
({
__scopePasswordToggleField,
onClick,
onPointerDown,
onPointerCancel,
onPointerUp,
onFocus,
children,
"aria-label": ariaLabelProp,
"aria-controls": ariaControls,
"aria-hidden": ariaHidden,
tabIndex,
...props
}, forwardedRef) => {
const { setVisible, visible, inputRef, inputId, focusState } = usePasswordToggleFieldContext(
PASSWORD_TOGGLE_FIELD_TOGGLE_NAME,
__scopePasswordToggleField
);
const [internalAriaLabel, setInternalAriaLabel] = React.useState(void 0);
const elementRef = React.useRef(null);
const ref = useComposedRefs(forwardedRef, elementRef);
const isHydrated = useIsHydrated();
React.useEffect(() => {
const element = elementRef.current;
if (!element || ariaLabelProp) {
setInternalAriaLabel(void 0);
return;
}
const DEFAULT_ARIA_LABEL = visible ? "Hide password" : "Show password";
function checkForInnerTextLabel(textContent) {
const text = textContent ? textContent : void 0;
setInternalAriaLabel(text ? void 0 : DEFAULT_ARIA_LABEL);
}
checkForInnerTextLabel(element.textContent);
const observer = new MutationObserver((entries) => {
let textContent;
for (const entry of entries) {
if (entry.type === "characterData") {
if (element.textContent) {
textContent = element.textContent;
}
}
}
checkForInnerTextLabel(textContent);
});
observer.observe(element, { characterData: true, subtree: true });
return () => {
observer.disconnect();
};
}, [visible, ariaLabelProp]);
const ariaLabel = ariaLabelProp || internalAriaLabel;
if (!isHydrated) {
ariaHidden ??= true;
tabIndex ??= -1;
} else {
ariaControls ??= inputId;
}
React.useEffect(() => {
let cleanup = () => {
};
const ownerWindow = elementRef.current?.ownerDocument?.defaultView || window;
const reset = () => focusState.current.clickTriggered = false;
const handlePointerUp = () => cleanup = requestIdleCallback(ownerWindow, reset);
ownerWindow.addEventListener("pointerup", handlePointerUp);
return () => {
cleanup();
ownerWindow.removeEventListener("pointerup", handlePointerUp);
};
}, [focusState]);
return /* @__PURE__ */ jsx(
Primitive.button,
{
"aria-controls": ariaControls,
"aria-hidden": ariaHidden,
"aria-label": ariaLabel,
ref,
id: inputId,
...props,
onPointerDown: composeEventHandlers(onPointerDown, () => {
focusState.current.clickTriggered = true;
}),
onPointerCancel: (event) => {
onPointerCancel?.(event);
focusState.current = INITIAL_FOCUS_STATE;
},
onClick: (event) => {
onClick?.(event);
if (event.defaultPrevented) {
focusState.current = INITIAL_FOCUS_STATE;
return;
}
flushSync(() => {
setVisible((s) => !s);
});
if (focusState.current.clickTriggered) {
const input = inputRef.current;
if (input) {
const { selectionStart, selectionEnd } = focusState.current;
input.focus();
if (selectionStart !== null || selectionEnd !== null) {
requestAnimationFrame(() => {
if (input.ownerDocument.activeElement === input) {
input.selectionStart = selectionStart;
input.selectionEnd = selectionEnd;
}
});
}
}
}
focusState.current = INITIAL_FOCUS_STATE;
},
onPointerUp: (event) => {
onPointerUp?.(event);
setTimeout(() => {
focusState.current = INITIAL_FOCUS_STATE;
}, 50);
},
type: "button",
children
}
);
}
);
PasswordToggleFieldToggle.displayName = PASSWORD_TOGGLE_FIELD_TOGGLE_NAME;
var PASSWORD_TOGGLE_FIELD_SLOT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Slot";
var PasswordToggleFieldSlot = ({
__scopePasswordToggleField,
...props
}) => {
const { visible } = usePasswordToggleFieldContext(
PASSWORD_TOGGLE_FIELD_SLOT_NAME,
__scopePasswordToggleField
);
return "render" in props ? (
//
props.render({ visible })
) : visible ? props.visible : props.hidden;
};
PasswordToggleFieldSlot.displayName = PASSWORD_TOGGLE_FIELD_SLOT_NAME;
var PASSWORD_TOGGLE_FIELD_ICON_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Icon";
var PasswordToggleFieldIcon = React.forwardRef(
({
__scopePasswordToggleField,
// @ts-expect-error
children,
...props
}, forwardedRef) => {
const { visible } = usePasswordToggleFieldContext(
PASSWORD_TOGGLE_FIELD_ICON_NAME,
__scopePasswordToggleField
);
const { visible: visibleIcon, hidden: hiddenIcon, ...domProps } = props;
return /* @__PURE__ */ jsx(Primitive.svg, { ...domProps, ref: forwardedRef, "aria-hidden": true, asChild: true, children: visible ? visibleIcon : hiddenIcon });
}
);
PasswordToggleFieldIcon.displayName = PASSWORD_TOGGLE_FIELD_ICON_NAME;
function requestIdleCallback(window2, callback, options) {
if (window2.requestIdleCallback) {
const id2 = window2.requestIdleCallback(callback, options);
return () => {
window2.cancelIdleCallback(id2);
};
}
const start = Date.now();
const id = window2.setTimeout(() => {
const timeRemaining = () => Math.max(0, 50 - (Date.now() - start));
callback({ didTimeout: false, timeRemaining });
}, 1);
return () => {
window2.clearTimeout(id);
};
}
export {
PasswordToggleFieldIcon as Icon,
PasswordToggleFieldInput as Input,
PasswordToggleField,
PasswordToggleFieldIcon,
PasswordToggleFieldInput,
PasswordToggleFieldSlot,
PasswordToggleFieldToggle,
PasswordToggleField as Root,
PasswordToggleFieldSlot as Slot,
PasswordToggleFieldToggle as Toggle
};
//# sourceMappingURL=index.mjs.map