[skip ci] feat: prepare for public release
This commit is contained in:
@@ -40,7 +40,7 @@ class FocusManager {
|
||||
this.initialized = true;
|
||||
|
||||
this.disposer = autorun(() => {
|
||||
this.notifyListeners(WindowStore.focused);
|
||||
this.notifyListeners(this.isForeground());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class FocusManager {
|
||||
|
||||
subscribe(listener: FocusChangeListener): () => void {
|
||||
this.listeners.add(listener);
|
||||
listener(WindowStore.isFocused());
|
||||
listener(this.isForeground());
|
||||
|
||||
return () => {
|
||||
this.listeners.delete(listener);
|
||||
@@ -70,8 +70,12 @@ class FocusManager {
|
||||
});
|
||||
}
|
||||
|
||||
private isForeground(): boolean {
|
||||
return WindowStore.isFocused() && WindowStore.isVisible();
|
||||
}
|
||||
|
||||
isFocused(): boolean {
|
||||
return WindowStore.isFocused();
|
||||
return WindowStore.isFocused() && WindowStore.isVisible();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,13 +52,16 @@ function computeRowConstraints(el: HTMLTextAreaElement, minRows?: number, maxRow
|
||||
}
|
||||
|
||||
export const TextareaAutosize = React.forwardRef<HTMLTextAreaElement, TextareaAutosizeProps>((props, forwardedRef) => {
|
||||
const {minRows: minRowsProp, maxRows, style, onHeightChange, rows, ...rest} = props;
|
||||
const {minRows: minRowsProp, maxRows, style, onHeightChange, rows, onInput, ...rest} = props;
|
||||
|
||||
const minRows = minRowsProp ?? (typeof rows === 'number' ? rows : undefined);
|
||||
const resolvedRows = rows ?? 1;
|
||||
const minRows = minRowsProp ?? (typeof resolvedRows === 'number' ? resolvedRows : undefined);
|
||||
|
||||
const elRef = React.useRef<HTMLTextAreaElement | null>(null);
|
||||
const onHeightChangeRef = React.useRef(onHeightChange);
|
||||
const lastWidthRef = React.useRef<number | null>(null);
|
||||
const lastHeightRef = React.useRef<number | null>(null);
|
||||
const resizeScheduledRef = React.useRef(false);
|
||||
|
||||
const setRef = React.useCallback(
|
||||
(node: HTMLTextAreaElement | null) => {
|
||||
@@ -84,10 +87,44 @@ export const TextareaAutosize = React.forwardRef<HTMLTextAreaElement, TextareaAu
|
||||
}
|
||||
if (maxHeight != null) {
|
||||
el.style.maxHeight = `${maxHeight}px`;
|
||||
el.style.overflowY = 'auto';
|
||||
}
|
||||
}, [minRows, maxRows]);
|
||||
|
||||
const resize = React.useCallback(() => {
|
||||
const el = elRef.current;
|
||||
if (!el) return;
|
||||
|
||||
const cs = window.getComputedStyle(el);
|
||||
const {minHeight, maxHeight, lineHeight} = computeRowConstraints(el, minRows, maxRows);
|
||||
const borderBlock = getNumber(cs.borderTopWidth) + getNumber(cs.borderBottomWidth);
|
||||
const isBorderBox = cs.boxSizing === 'border-box';
|
||||
|
||||
el.style.height = 'auto';
|
||||
|
||||
let nextHeight = el.scrollHeight + (isBorderBox ? borderBlock : 0);
|
||||
if (minHeight != null) nextHeight = Math.max(nextHeight, minHeight);
|
||||
if (maxHeight != null) nextHeight = Math.min(nextHeight, maxHeight);
|
||||
|
||||
const heightPx = `${nextHeight}px`;
|
||||
if (el.style.height !== heightPx) {
|
||||
el.style.height = heightPx;
|
||||
}
|
||||
|
||||
if (lastHeightRef.current !== nextHeight) {
|
||||
lastHeightRef.current = nextHeight;
|
||||
onHeightChangeRef.current?.(nextHeight, {rowHeight: lineHeight});
|
||||
}
|
||||
}, [maxRows, minRows]);
|
||||
|
||||
const scheduleResize = React.useCallback(() => {
|
||||
if (resizeScheduledRef.current) return;
|
||||
resizeScheduledRef.current = true;
|
||||
requestAnimationFrame(() => {
|
||||
resizeScheduledRef.current = false;
|
||||
resize();
|
||||
});
|
||||
}, [resize]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const el = elRef.current;
|
||||
if (!el || typeof ResizeObserver === 'undefined') return;
|
||||
@@ -96,27 +133,38 @@ export const TextareaAutosize = React.forwardRef<HTMLTextAreaElement, TextareaAu
|
||||
const entry = entries[0];
|
||||
if (!entry) return;
|
||||
|
||||
const height = entry.borderBoxSize?.[0]?.blockSize ?? el.getBoundingClientRect().height;
|
||||
if (height !== lastHeightRef.current) {
|
||||
lastHeightRef.current = height;
|
||||
const cs = window.getComputedStyle(el);
|
||||
onHeightChangeRef.current?.(height, {rowHeight: getLineHeight(cs)});
|
||||
const width = entry.borderBoxSize?.[0]?.inlineSize ?? el.getBoundingClientRect().width;
|
||||
if (width !== lastWidthRef.current) {
|
||||
lastWidthRef.current = width;
|
||||
scheduleResize();
|
||||
}
|
||||
});
|
||||
|
||||
ro.observe(el);
|
||||
return () => ro.disconnect();
|
||||
}, []);
|
||||
}, [scheduleResize]);
|
||||
|
||||
const computedStyle = React.useMemo(
|
||||
(): React.CSSProperties => ({
|
||||
fieldSizing: 'content',
|
||||
overflow: maxRows ? 'auto' : 'hidden',
|
||||
...style,
|
||||
}),
|
||||
[style],
|
||||
[maxRows, style],
|
||||
);
|
||||
|
||||
return <textarea {...rest} ref={setRef} rows={rows} style={computedStyle} />;
|
||||
const handleInput = React.useCallback(
|
||||
(event: React.FormEvent<HTMLTextAreaElement>) => {
|
||||
resize();
|
||||
onInput?.(event);
|
||||
},
|
||||
[onInput, resize],
|
||||
);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
resize();
|
||||
}, [resize, props.value, props.defaultValue, rows]);
|
||||
|
||||
return <textarea {...rest} ref={setRef} rows={resolvedRows} style={computedStyle} onInput={handleInput} />;
|
||||
});
|
||||
|
||||
TextareaAutosize.displayName = 'TextareaAutosize';
|
||||
|
||||
@@ -723,10 +723,8 @@ function findFormattingEnd(
|
||||
|
||||
if (currentChar === markerChar) {
|
||||
if (markerChar === BACKTICK && position + 1 < textLength && text.charCodeAt(position + 1) === BACKTICK) {
|
||||
let _backtickCount = 0;
|
||||
let checkPos = position;
|
||||
while (checkPos < textLength && text.charCodeAt(checkPos) === BACKTICK) {
|
||||
_backtickCount++;
|
||||
checkPos++;
|
||||
}
|
||||
position = checkPos;
|
||||
|
||||
Reference in New Issue
Block a user