mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 01:49:13 +01:00
Markdown documentation for HTTP requests (#145)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
interface Props {
|
||||
count: number;
|
||||
count: number | true;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@ export function CountBadge({ count, className }: Props) {
|
||||
aria-hidden
|
||||
className={classNames(
|
||||
className,
|
||||
'flex items-center',
|
||||
'opacity-70 border border-border-subtle text-4xs rounded mb-0.5 px-1 ml-1 h-4 font-mono',
|
||||
)}
|
||||
>
|
||||
{count}
|
||||
{count === true ? <div aria-hidden className="rounded-full h-1 w-1 bg-text-subtle" /> : count}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
.cm-line {
|
||||
@apply w-full;
|
||||
/* Important! Ensure it spans the entire width */
|
||||
@apply w-full text-text pl-1 pr-1.5;
|
||||
@apply w-full text-text px-0;
|
||||
}
|
||||
|
||||
.cm-placeholder {
|
||||
@@ -51,7 +51,7 @@
|
||||
/* Style gutters */
|
||||
|
||||
.cm-gutters {
|
||||
@apply border-0 text-text-subtlest bg-surface;
|
||||
@apply border-0 text-text-subtlest bg-surface pr-1.5;
|
||||
/* Not sure why, but there's a tiny gap left of the gutter that you can see text
|
||||
through. Move left slightly to fix that. */
|
||||
@apply -left-[1px];
|
||||
@@ -114,12 +114,6 @@
|
||||
|
||||
.cm-scroller {
|
||||
@apply font-mono text-editor;
|
||||
/*
|
||||
* Round corners or they'll stick out of the editor bounds of editor is rounded.
|
||||
* Could potentially be pushed up from the editor like we do with bg color but this
|
||||
* is probably fine.
|
||||
*/
|
||||
@apply rounded-lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ import classNames from 'classnames';
|
||||
import { EditorView } from 'codemirror';
|
||||
import type { MutableRefObject, ReactNode } from 'react';
|
||||
import {
|
||||
useEffect,
|
||||
Children,
|
||||
cloneElement,
|
||||
forwardRef,
|
||||
isValidElement,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
@@ -45,7 +45,16 @@ export interface EditorProps {
|
||||
type?: 'text' | 'password';
|
||||
className?: string;
|
||||
heightMode?: 'auto' | 'full';
|
||||
language?: 'javascript' | 'json' | 'html' | 'xml' | 'graphql' | 'url' | 'pairs' | 'text';
|
||||
language?:
|
||||
| 'javascript'
|
||||
| 'json'
|
||||
| 'html'
|
||||
| 'xml'
|
||||
| 'graphql'
|
||||
| 'url'
|
||||
| 'pairs'
|
||||
| 'text'
|
||||
| 'markdown';
|
||||
forceUpdateKey?: string | number;
|
||||
autoFocus?: boolean;
|
||||
autoSelect?: boolean;
|
||||
@@ -66,6 +75,7 @@ export interface EditorProps {
|
||||
autocompleteVariables?: boolean;
|
||||
extraExtensions?: Extension[];
|
||||
actions?: ReactNode;
|
||||
hideGutter?: boolean;
|
||||
}
|
||||
|
||||
const emptyVariables: EnvironmentVariable[] = [];
|
||||
@@ -96,6 +106,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
autocompleteVariables,
|
||||
actions,
|
||||
wrapLines,
|
||||
hideGutter,
|
||||
}: EditorProps,
|
||||
ref,
|
||||
) {
|
||||
@@ -310,6 +321,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
container,
|
||||
readOnly,
|
||||
singleLine,
|
||||
hideGutter,
|
||||
onChange: handleChange,
|
||||
onPaste: handlePaste,
|
||||
onPasteOverwrite: handlePasteOverwrite,
|
||||
@@ -374,7 +386,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
const decoratedActions = useMemo(() => {
|
||||
const results = [];
|
||||
const actionClassName = classNames(
|
||||
'bg-surface transition-opacity opacity-0 group-hover:opacity-100 hover:!opacity-100 shadow',
|
||||
'bg-surface transition-opacity transform-gpu opacity-0 group-hover:opacity-100 hover:!opacity-100 shadow',
|
||||
);
|
||||
|
||||
if (format) {
|
||||
@@ -455,13 +467,14 @@ function getExtensions({
|
||||
container,
|
||||
readOnly,
|
||||
singleLine,
|
||||
hideGutter,
|
||||
onChange,
|
||||
onPaste,
|
||||
onPasteOverwrite,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onKeyDown,
|
||||
}: Pick<EditorProps, 'singleLine' | 'readOnly'> & {
|
||||
}: Pick<EditorProps, 'singleLine' | 'readOnly' | 'hideGutter'> & {
|
||||
container: HTMLDivElement | null;
|
||||
onChange: MutableRefObject<EditorProps['onChange']>;
|
||||
onPaste: MutableRefObject<EditorProps['onPaste']>;
|
||||
@@ -499,7 +512,7 @@ function getExtensions({
|
||||
tooltips({ parent }),
|
||||
keymap.of(singleLine ? defaultKeymap.filter((k) => k.key !== 'Enter') : defaultKeymap),
|
||||
...(singleLine ? [singleLineExt()] : []),
|
||||
...(!singleLine ? [multiLineExtensions] : []),
|
||||
...(!singleLine ? [multiLineExtensions({ hideGutter })] : []),
|
||||
...(readOnly
|
||||
? [EditorState.readOnly.of(true), EditorView.contentAttributes.of({ tabindex: '-1' })]
|
||||
: []),
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from '@codemirror/autocomplete';
|
||||
import { history, historyKeymap, indentWithTab } from '@codemirror/commands';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import type { LanguageSupport } from '@codemirror/language';
|
||||
@@ -79,6 +80,7 @@ const syntaxExtensions: Record<NonNullable<EditorProps['language']>, LanguageSup
|
||||
url: url(),
|
||||
pairs: pairs(),
|
||||
text: text(),
|
||||
markdown: markdown(),
|
||||
};
|
||||
|
||||
export function getLanguageExtension({
|
||||
@@ -138,21 +140,25 @@ export const baseExtensions = [
|
||||
keymap.of([...historyKeymap, ...completionKeymap]),
|
||||
];
|
||||
|
||||
export const multiLineExtensions = [
|
||||
lineNumbers(),
|
||||
foldGutter({
|
||||
markerDOM: (open) => {
|
||||
const el = document.createElement('div');
|
||||
el.classList.add('fold-gutter-icon');
|
||||
el.tabIndex = -1;
|
||||
if (open) {
|
||||
el.setAttribute('data-open', '');
|
||||
}
|
||||
return el;
|
||||
},
|
||||
}),
|
||||
export const multiLineExtensions = ({ hideGutter }: { hideGutter?: boolean }) => [
|
||||
hideGutter
|
||||
? []
|
||||
: [
|
||||
lineNumbers(),
|
||||
foldGutter({
|
||||
markerDOM: (open) => {
|
||||
const el = document.createElement('div');
|
||||
el.classList.add('fold-gutter-icon');
|
||||
el.tabIndex = -1;
|
||||
if (open) {
|
||||
el.setAttribute('data-open', '');
|
||||
}
|
||||
return el;
|
||||
},
|
||||
}),
|
||||
],
|
||||
codeFolding({
|
||||
placeholderDOM(view, onclick, prepared) {
|
||||
placeholderDOM(_view, onclick, prepared) {
|
||||
const el = document.createElement('span');
|
||||
el.onclick = onclick;
|
||||
el.className = 'cm-foldPlaceholder';
|
||||
|
||||
@@ -30,6 +30,7 @@ const icons = {
|
||||
circle_alert: lucide.CircleAlertIcon,
|
||||
clock: lucide.ClockIcon,
|
||||
code: lucide.CodeIcon,
|
||||
columns_2: lucide.Columns2Icon,
|
||||
cookie: lucide.CookieIcon,
|
||||
copy: lucide.CopyIcon,
|
||||
copy_check: lucide.CopyCheck,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import useResizeObserver from '@react-hook/resize-observer';
|
||||
import useSize from '@react-hook/size';
|
||||
import classNames from 'classnames';
|
||||
import type { CSSProperties, MouseEvent as ReactMouseEvent, ReactNode } from 'react';
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
@@ -43,7 +43,6 @@ export function SplitLayout({
|
||||
}: Props) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const activeWorkspace = useActiveWorkspace();
|
||||
const [verticalBasedOnSize, setVerticalBasedOnSize] = useState<boolean>(false);
|
||||
const [widthRaw, setWidth] = useLocalStorage<number>(
|
||||
`${name}_width::${activeWorkspace?.id ?? 'n/a'}`,
|
||||
);
|
||||
@@ -62,10 +61,7 @@ export function SplitLayout({
|
||||
minHeightPx = 0;
|
||||
}
|
||||
|
||||
useResizeObserver(containerRef.current, ({ contentRect }) => {
|
||||
setVerticalBasedOnSize(contentRect.width < STACK_VERTICAL_WIDTH);
|
||||
});
|
||||
|
||||
const verticalBasedOnSize = useSize(containerRef.current)[0] < STACK_VERTICAL_WIDTH;
|
||||
const vertical = layout !== 'horizontal' && (layout === 'vertical' || verticalBasedOnSize);
|
||||
|
||||
const styles = useMemo<CSSProperties>(() => {
|
||||
|
||||
@@ -40,6 +40,8 @@ export function Tabs({
|
||||
}: Props) {
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
value = value ?? tabs[0]?.value;
|
||||
|
||||
// Update tabs when value changes
|
||||
useEffect(() => {
|
||||
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
|
||||
@@ -61,7 +63,7 @@ export function Tabs({
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={classNames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1')}
|
||||
className={classNames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1 overflow-x-hidden')}
|
||||
>
|
||||
<div
|
||||
aria-label={label}
|
||||
|
||||
Reference in New Issue
Block a user