Compare commits

..

5 Commits

Author SHA1 Message Date
codegen-sh[bot] be050f48c3 Fix: Pasting over inline code block breaks markdown conversion (#8825) 2025-03-28 21:25:40 +00:00
Aditya Sharma 3ffe7e7671 fix: conversion b/w checkbox & other list types (#8828) 2025-03-28 14:19:12 -07:00
Hemachandar a7fe6c9af3 Include non-deleted imports for cleanup (#8822) 2025-03-28 05:46:36 -07:00
codegen-sh[bot] 52c673261b Add JSDoc to hooks in app/hooks directory (#8819)
* Add JSDoc to hooks in app/hooks directory

* lint

---------

Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2025-03-28 02:37:32 +00:00
Tom Moor 60c0a53a1f chore: Change lint rule to trigger on actor rather than branch name (#8820) 2025-03-28 02:24:00 +00:00
12 changed files with 127 additions and 1 deletions
+5
View File
@@ -1,6 +1,11 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
/**
* Hook that provides a dictionary of translated UI strings.
*
* @returns An object containing all translated UI strings used throughout the application
*/
export default function useDictionary() {
const { t } = useTranslation();
+9
View File
@@ -1,6 +1,15 @@
import * as React from "react";
import useWindowSize from "./useWindowSize";
/**
* Hook to calculate the maximum height for an element based on its position and viewport size.
*
* @param options Configuration options
* @param options.elementRef A ref pointing to the element to calculate max height for
* @param options.maxViewportPercentage The maximum height of the element as a percentage of the viewport
* @param options.margin The margin to apply to the positioning
* @returns Object containing the calculated maxHeight and a function to recalculate it
*/
const useMaxHeight = ({
elementRef,
maxViewportPercentage = 90,
+6
View File
@@ -1,5 +1,11 @@
import { useState, useEffect } from "react";
/**
* Hook to check if a media query matches the current viewport.
*
* @param query The CSS media query to check against
* @returns boolean indicating whether the media query matches
*/
export default function useMediaQuery(query: string): boolean {
const [matches, setMatches] = useState<boolean>(false);
+5
View File
@@ -1,6 +1,11 @@
import { breakpoints } from "@shared/styles";
import useMediaQuery from "~/hooks/useMediaQuery";
/**
* Hook to detect if the current viewport is mobile-sized.
*
* @returns boolean indicating whether the current viewport is mobile-sized
*/
export default function useMobile(): boolean {
return useMediaQuery(`(max-width: ${breakpoints.tablet - 1}px)`);
}
+5
View File
@@ -1,6 +1,11 @@
import React from "react";
import { useLocation } from "react-router-dom";
/**
* Hook to access URL query parameters from the current location.
*
* @returns URLSearchParams object containing the current URL query parameters
*/
export default function useQuery() {
const location = useLocation();
+5
View File
@@ -2,6 +2,11 @@ import { MobXProviderContext } from "mobx-react";
import * as React from "react";
import RootStore from "~/stores";
/**
* Hook to access the MobX stores from the React context.
*
* @returns The root store containing all application stores
*/
export default function useStores() {
return React.useContext(MobXProviderContext) as typeof RootStore;
}
+5
View File
@@ -1,5 +1,10 @@
import * as React from "react";
/**
* Hook that executes a callback when the component unmounts.
*
* @param callback Function to be called on component unmount
*/
const useUnmount = (callback: (...args: Array<any>) => any) => {
const ref = React.useRef(callback);
ref.current = callback;
+6
View File
@@ -1,5 +1,11 @@
import { useLayoutEffect, useState } from "react";
/**
* Hook to get the current viewport height, accounting for mobile virtual keyboards.
* Uses the VisualViewport API when available, falling back to window.innerHeight.
*
* @returns The current viewport height in pixels
*/
export default function useViewportHeight(): number | void {
// https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport#browser_compatibility
// Note: No support in Firefox at time of writing, however this mainly exists
+7
View File
@@ -13,6 +13,13 @@ const defaultOptions = {
throttle: 100,
};
/**
* Hook to track the window's scroll position.
*
* @param options Configuration options
* @param options.throttle Time in milliseconds to throttle the scroll event
* @returns Object containing the current scroll position (x, y coordinates)
*/
export default function useWindowScrollPosition(options: {
throttle: number;
}): {
@@ -41,6 +41,7 @@ export default class CleanupOldImportsTask extends BaseTask<Props> {
],
batchLimit: 50,
totalLimit: maxImportsPerTask,
paranoid: false,
},
async (imports) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
+9 -1
View File
@@ -1,5 +1,5 @@
import { NodeType } from "prosemirror-model";
import { wrapInList, liftListItem } from "prosemirror-schema-list";
import { liftListItem, wrapInList } from "prosemirror-schema-list";
import { Command } from "prosemirror-state";
import { chainTransactions } from "../lib/chainTransactions";
import { findParentNode } from "../queries/findParentNode";
@@ -29,6 +29,14 @@ export default function toggleList(
return liftListItem(itemType)(state, dispatch);
}
const currentItemType = parentList.node.content.firstChild?.type;
if (currentItemType && currentItemType !== itemType) {
return chainTransactions(clearNodes(), wrapInList(listType))(
state,
dispatch
);
}
if (
isList(parentList.node, schema) &&
listType.validContent(parentList.node.content)
+64
View File
@@ -99,6 +99,7 @@ export default class Code extends Mark {
return false;
}
// Check if we're pasting inside backticks
const start = from - 1;
const end = to + 1;
if (
@@ -118,6 +119,69 @@ export default class Code extends Mark {
return true;
}
// Check if we're pasting over an existing inline code block
if (isInCode(state, { onlyMark: true })) {
// Get the range of the current code mark
const marks = state.doc.resolve(from).marks();
const codeMark = marks.find(
(mark) => mark.type === state.schema.marks.code_inline
);
if (codeMark) {
// Find the start and end of the code mark
let codeStart = from;
let codeEnd = to;
// Find the start of the code mark
for (let i = from; i > 0; i--) {
const resolvedPos = state.doc.resolve(i);
const marksAtPos = resolvedPos.marks();
const hasCodeMark = marksAtPos.some(
(mark) => mark.type === state.schema.marks.code_inline
);
if (!hasCodeMark) {
codeStart = i + 1;
break;
}
if (i === 1) {
codeStart = 1;
}
}
// Find the end of the code mark
for (let i = to; i < state.doc.nodeSize - 2; i++) {
const resolvedPos = state.doc.resolve(i);
const marksAtPos = resolvedPos.marks();
const hasCodeMark = marksAtPos.some(
(mark) => mark.type === state.schema.marks.code_inline
);
if (!hasCodeMark) {
codeEnd = i;
break;
}
if (i === state.doc.nodeSize - 3) {
codeEnd = state.doc.nodeSize - 2;
}
}
// Replace the content within the code mark
view.dispatch(
state.tr
.replaceRange(from, to, slice)
.addMark(
from,
from + slice.size,
state.schema.marks.code_inline.create()
)
);
return true;
}
}
return false;
},