chore: wiki and artificats cleanups (#56)
* chore: document OpenAPI support * chore: update readme * refactor: use scrollArea wherever applicable * chore: update demo video * build: exclude more files from the release * style: apply TS style fixes
This commit is contained in:
@@ -29,6 +29,23 @@
|
||||
[role='button']:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global Scrollbar Styling.
|
||||
*/
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: transparent transparent;
|
||||
}
|
||||
|
||||
*:hover {
|
||||
scrollbar-color: var(--color-zinc-400) transparent;
|
||||
}
|
||||
|
||||
.dark *:hover {
|
||||
scrollbar-color: var(--color-zinc-600) transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { cn } from '@/utils/ui';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
import type { ScrollAreaRootProps } from 'reka-ui';
|
||||
import { ScrollAreaCorner, ScrollAreaRoot, ScrollAreaViewport } from 'reka-ui';
|
||||
import type { HTMLAttributes } from 'vue';
|
||||
import { type HTMLAttributes, ref } from 'vue';
|
||||
import AppScrollBar from './AppScrollBar.vue';
|
||||
|
||||
/*
|
||||
@@ -23,8 +23,13 @@ export interface AppScrollAreaProps extends ScrollAreaRootProps {
|
||||
*/
|
||||
|
||||
const props = defineProps<AppScrollAreaProps>();
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const viewport = ref<HTMLElement | null>(null);
|
||||
|
||||
defineExpose({
|
||||
viewport,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,6 +39,7 @@ const delegatedProps = reactiveOmit(props, 'class');
|
||||
:class="cn('relative', props.class)"
|
||||
>
|
||||
<ScrollAreaViewport
|
||||
ref="viewport"
|
||||
data-slot="scroll-area-viewport"
|
||||
class="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&>div]:h-full"
|
||||
>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @component RequestBodyContent
|
||||
* @description Dynamic content renderer for the request body based on the selected payload type.
|
||||
*/
|
||||
import { AppScrollArea } from '@/components/base/scroll-area';
|
||||
import { RequestBodyTypeEnum } from '@/interfaces/http';
|
||||
import type { JSONSchema7 } from 'json-schema';
|
||||
import RequestBodyFormData from './RequestBodyFormData.vue';
|
||||
@@ -42,7 +43,7 @@ const updatePayload = (value: FormData | string | null) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-0 w-full flex-1">
|
||||
<AppScrollArea class="min-h-0 w-full flex-1">
|
||||
<RequestBodyJson
|
||||
v-if="payloadType === RequestBodyTypeEnum.JSON"
|
||||
:model-value="payload as string"
|
||||
@@ -60,5 +61,5 @@ const updatePayload = (value: FormData | string | null) => {
|
||||
@update:model-value="updatePayload"
|
||||
/>
|
||||
<RequestBodyFormNone v-else @update:model-value="updatePayload" />
|
||||
</div>
|
||||
</AppScrollArea>
|
||||
</template>
|
||||
|
||||
@@ -27,5 +27,6 @@ defineProps<AppResponseBodyProps>();
|
||||
:placeholder="content === '' ? 'Empty' : 'Response JSON Payload'"
|
||||
:model-value="content"
|
||||
:disabled="content === ''"
|
||||
:auto-height="false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @description Renders the successful response details, including body, headers, and cookies.
|
||||
*/
|
||||
import { AppBadge } from '@/components/base/badge';
|
||||
import { AppScrollArea } from '@/components/base/scroll-area';
|
||||
import {
|
||||
AppTabs,
|
||||
AppTabsContent,
|
||||
@@ -141,11 +142,15 @@ const handleTabClick = (event: Event) => {
|
||||
value="response"
|
||||
class="mt-0 flex min-h-0 flex-1 flex-col overflow-hidden"
|
||||
>
|
||||
<ResponseBody
|
||||
<AppScrollArea
|
||||
v-if="lastLog?.response?.status !== STATUS.DUMP_AND_DIE"
|
||||
class="min-h-0 overflow-auto"
|
||||
:content="lastLog?.response?.body ?? ''"
|
||||
/>
|
||||
class="min-h-0 flex-1"
|
||||
>
|
||||
<ResponseBody
|
||||
class="min-h-0"
|
||||
:content="lastLog?.response?.body ?? ''"
|
||||
/>
|
||||
</AppScrollArea>
|
||||
|
||||
<ResponseDumpAndDie
|
||||
v-else
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface AppCodeEditorProps extends PrimitiveProps {
|
||||
readonly?: boolean;
|
||||
disabled?: boolean;
|
||||
validationSchema?: JSONSchema7;
|
||||
autoHeight?: boolean;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -35,6 +36,7 @@ const props = withDefaults(defineProps<AppCodeEditorProps>(), {
|
||||
disabled: false,
|
||||
class: '',
|
||||
validationSchema: undefined,
|
||||
autoHeight: false,
|
||||
});
|
||||
|
||||
const model = defineModel<string>({
|
||||
@@ -61,7 +63,7 @@ const updateModel = (value: string) => {
|
||||
<template>
|
||||
<Codemirror
|
||||
:placeholder="placeholder"
|
||||
:style="{ height: '100%' }"
|
||||
:style="{ height: autoHeight ? 'auto' : '100%', minHeight: '100%' }"
|
||||
:extensions="extensions"
|
||||
:indent-with-tab="true"
|
||||
:tab-size="4"
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
AppCollapsibleContent,
|
||||
AppCollapsibleTrigger,
|
||||
} from '@/components/base/collapsible';
|
||||
import { AppScrollArea } from '@/components/base/scroll-area';
|
||||
import {
|
||||
AppSidebarGroup,
|
||||
AppSidebarGroupContent,
|
||||
@@ -31,11 +32,16 @@ const tabsStore = useTabsStore();
|
||||
* Vertical Scroll.
|
||||
*/
|
||||
|
||||
const { scrollContainer, showTopMask, showBottomMask, scrollTabIntoView } =
|
||||
useTabVerticalScroll({
|
||||
SCROLL_PADDING: 20,
|
||||
MASK_HEIGHT: 32,
|
||||
});
|
||||
const {
|
||||
scrollContainer,
|
||||
showTopMask,
|
||||
showBottomMask,
|
||||
updateScrollMasks,
|
||||
scrollTabIntoView,
|
||||
} = useTabVerticalScroll({
|
||||
SCROLL_PADDING: 20,
|
||||
MASK_HEIGHT: 32,
|
||||
});
|
||||
|
||||
const tabElements = ref<Record<string, HTMLElement>>({});
|
||||
|
||||
@@ -96,6 +102,16 @@ const handleCloseTab = (id: string) => {
|
||||
*/
|
||||
|
||||
const isOpen = defineModel<boolean>('isOpen');
|
||||
const scrollAreaRef = ref<InstanceType<typeof AppScrollArea> | null>(null);
|
||||
|
||||
watch(
|
||||
() => scrollAreaRef.value?.viewport,
|
||||
viewport => {
|
||||
if (viewport) {
|
||||
scrollContainer.value = viewport;
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -136,9 +152,10 @@ const isOpen = defineModel<boolean>('isOpen');
|
||||
:class="[showTopMask && isOpen ? 'opacity-100' : 'opacity-0']"
|
||||
/>
|
||||
|
||||
<div
|
||||
ref="scrollContainer"
|
||||
class="no-scrollbar min-h-0 flex-1 overflow-y-scroll"
|
||||
<AppScrollArea
|
||||
ref="scrollAreaRef"
|
||||
class="min-h-0 flex-1"
|
||||
@scroll="updateScrollMasks"
|
||||
>
|
||||
<draggable
|
||||
v-model="tabsModel"
|
||||
@@ -177,7 +194,7 @@ const isOpen = defineModel<boolean>('isOpen');
|
||||
</AppSidebarMenuItem>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</AppScrollArea>
|
||||
|
||||
<!-- Bottom Scroll Mask -->
|
||||
<div
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
AppResizablePanel,
|
||||
AppResizablePanelGroup,
|
||||
} from '@/components/base/resizable';
|
||||
import { AppScrollArea } from '@/components/base/scroll-area';
|
||||
import {
|
||||
AppSidebar,
|
||||
AppSidebarContent,
|
||||
@@ -60,6 +61,8 @@ const isOpenTabsExpanded = useStorage(
|
||||
false,
|
||||
);
|
||||
|
||||
const scrollAreaRef = ref<InstanceType<typeof AppScrollArea> | null>(null);
|
||||
|
||||
const {
|
||||
scrollContainer: routesScrollContainer,
|
||||
showTopMask: showRoutesTopMask,
|
||||
@@ -148,6 +151,15 @@ watch(isOpenTabsExpanded, newValue => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => scrollAreaRef.value?.viewport,
|
||||
viewport => {
|
||||
if (viewport) {
|
||||
routesScrollContainer.value = viewport;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
provide('showingSearchResults', showingSearchResults);
|
||||
</script>
|
||||
|
||||
@@ -207,9 +219,9 @@ provide('showingSearchResults', showingSearchResults);
|
||||
<AppSidebarGroupContent
|
||||
class="relative min-h-0 flex-1 overflow-hidden"
|
||||
>
|
||||
<div
|
||||
ref="routesScrollContainer"
|
||||
class="h-full overflow-y-auto"
|
||||
<AppScrollArea
|
||||
ref="scrollAreaRef"
|
||||
class="h-full"
|
||||
@scroll="updateRoutesScrollMasks"
|
||||
>
|
||||
<div
|
||||
@@ -228,12 +240,11 @@ provide('showingSearchResults', showingSearchResults);
|
||||
</p>
|
||||
</div>
|
||||
</AppSidebarMenu>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-show="showRoutesBottomMask"
|
||||
class="from-sidebar pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-8 bg-gradient-to-t from-20% to-transparent transition-opacity duration-300"
|
||||
/>
|
||||
<div
|
||||
v-show="showRoutesBottomMask"
|
||||
class="from-sidebar pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-8 bg-gradient-to-t from-20% to-transparent transition-opacity duration-300"
|
||||
/>
|
||||
</AppScrollArea>
|
||||
</AppSidebarGroupContent>
|
||||
</AppSidebarGroup>
|
||||
</AppResizablePanel>
|
||||
|
||||
Reference in New Issue
Block a user