mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-10 06:42:52 +02:00
Move portal to shared ui lib
This commit is contained in:
@@ -4,7 +4,7 @@ import type { ReactNode } from 'react';
|
|||||||
import { hideToast, toastsAtom } from '../lib/toast';
|
import { hideToast, toastsAtom } from '../lib/toast';
|
||||||
import { Toast, type ToastProps } from './core/Toast';
|
import { Toast, type ToastProps } from './core/Toast';
|
||||||
import { ErrorBoundary } from './ErrorBoundary';
|
import { ErrorBoundary } from './ErrorBoundary';
|
||||||
import { Portal } from './Portal';
|
import { Portal } from '@yaakapp-internal/ui';
|
||||||
|
|
||||||
export type ToastInstance = {
|
export type ToastInstance = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type } from '@tauri-apps/plugin-os';
|
import { type } from '@tauri-apps/plugin-os';
|
||||||
import { settingsAtom, workspacesAtom } from '@yaakapp-internal/models';
|
import { settingsAtom, workspacesAtom } from '@yaakapp-internal/models';
|
||||||
|
import { HeaderSize, Overlay, SidebarLayout } from '@yaakapp-internal/ui';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import * as m from 'motion/react-m';
|
import * as m from 'motion/react-m';
|
||||||
@@ -39,15 +40,12 @@ import { HStack } from './core/Stacks';
|
|||||||
import { ErrorBoundary } from './ErrorBoundary';
|
import { ErrorBoundary } from './ErrorBoundary';
|
||||||
import { FolderLayout } from './FolderLayout';
|
import { FolderLayout } from './FolderLayout';
|
||||||
import { GrpcConnectionLayout } from './GrpcConnectionLayout';
|
import { GrpcConnectionLayout } from './GrpcConnectionLayout';
|
||||||
import { HeaderSize, SidebarLayout } from '@yaakapp-internal/ui';
|
|
||||||
import { HttpRequestLayout } from './HttpRequestLayout';
|
import { HttpRequestLayout } from './HttpRequestLayout';
|
||||||
import { Overlay } from './Overlay';
|
|
||||||
import Sidebar from './Sidebar';
|
import Sidebar from './Sidebar';
|
||||||
import { SidebarActions } from './SidebarActions';
|
import { SidebarActions } from './SidebarActions';
|
||||||
import { WebsocketRequestLayout } from './WebsocketRequestLayout';
|
import { WebsocketRequestLayout } from './WebsocketRequestLayout';
|
||||||
import { WorkspaceHeader } from './WorkspaceHeader';
|
import { WorkspaceHeader } from './WorkspaceHeader';
|
||||||
|
|
||||||
const head = { gridArea: 'head' };
|
|
||||||
const body = { gridArea: 'body' };
|
const body = { gridArea: 'body' };
|
||||||
|
|
||||||
export function Workspace() {
|
export function Workspace() {
|
||||||
@@ -85,10 +83,7 @@ export function Workspace() {
|
|||||||
interfaceScale={settings.interfaceScale}
|
interfaceScale={settings.interfaceScale}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 pointer-events-none">
|
<div className="absolute inset-0 pointer-events-none">
|
||||||
<div
|
<div style={environmentBgStyle} className="absolute inset-0 opacity-[0.07]" />
|
||||||
style={environmentBgStyle}
|
|
||||||
className="absolute inset-0 opacity-[0.07]"
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
style={environmentBgStyle}
|
style={environmentBgStyle}
|
||||||
className="absolute left-0 right-0 -bottom-[1px] h-[1px] opacity-20"
|
className="absolute left-0 right-0 -bottom-[1px] h-[1px] opacity-20"
|
||||||
@@ -132,7 +127,15 @@ export function Workspace() {
|
|||||||
'grid grid-rows-[auto_1fr]',
|
'grid grid-rows-[auto_1fr]',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<HeaderSize hideControls size="lg" className="border-transparent flex items-center" osType={osType} hideWindowControls={settings.hideWindowControls} useNativeTitlebar={settings.useNativeTitlebar} interfaceScale={settings.interfaceScale}>
|
<HeaderSize
|
||||||
|
hideControls
|
||||||
|
size="lg"
|
||||||
|
className="border-transparent flex items-center"
|
||||||
|
osType={osType}
|
||||||
|
hideWindowControls={settings.hideWindowControls}
|
||||||
|
useNativeTitlebar={settings.useNativeTitlebar}
|
||||||
|
interfaceScale={settings.interfaceScale}
|
||||||
|
>
|
||||||
<SidebarActions />
|
<SidebarActions />
|
||||||
</HeaderSize>
|
</HeaderSize>
|
||||||
<ErrorBoundary name="Sidebar (Floating)">
|
<ErrorBoundary name="Sidebar (Floating)">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import classNames from 'classnames';
|
|||||||
import * as m from 'motion/react-m';
|
import * as m from 'motion/react-m';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Overlay } from '../Overlay';
|
import { Overlay } from '@yaakapp-internal/ui';
|
||||||
import { Heading } from './Heading';
|
import { Heading } from './Heading';
|
||||||
import { IconButton } from './IconButton';
|
import { IconButton } from './IconButton';
|
||||||
import type { DialogSize } from '@yaakapp-internal/plugins';
|
import type { DialogSize } from '@yaakapp-internal/plugins';
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import { generateId } from '../../lib/generateId';
|
|||||||
import { getNodeText } from '../../lib/getNodeText';
|
import { getNodeText } from '../../lib/getNodeText';
|
||||||
import { jotaiStore } from '../../lib/jotai';
|
import { jotaiStore } from '../../lib/jotai';
|
||||||
import { ErrorBoundary } from '../ErrorBoundary';
|
import { ErrorBoundary } from '../ErrorBoundary';
|
||||||
import { Overlay } from '../Overlay';
|
import { Overlay } from '@yaakapp-internal/ui';
|
||||||
import { Button } from './Button';
|
import { Button } from './Button';
|
||||||
import { Hotkey } from './Hotkey';
|
import { Hotkey } from './Hotkey';
|
||||||
import { Icon, LoadingIcon, type IconProps } from '@yaakapp-internal/ui';
|
import { Icon, LoadingIcon, type IconProps } from '@yaakapp-internal/ui';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import classNames from 'classnames';
|
|||||||
import type { CSSProperties, KeyboardEvent, ReactNode } from 'react';
|
import type { CSSProperties, KeyboardEvent, ReactNode } from 'react';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { generateId } from '../../lib/generateId';
|
import { generateId } from '../../lib/generateId';
|
||||||
import { Portal } from '../Portal';
|
import { Portal } from '@yaakapp-internal/ui';
|
||||||
|
|
||||||
export interface TooltipProps {
|
export interface TooltipProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ interface Props {
|
|||||||
onWidthChange: (width: number) => void;
|
onWidthChange: (width: number) => void;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
onHiddenChange?: (hidden: boolean) => void;
|
onHiddenChange?: (hidden: boolean) => void;
|
||||||
|
floating?: boolean;
|
||||||
|
floatingWidth?: number;
|
||||||
defaultWidth?: number;
|
defaultWidth?: number;
|
||||||
minWidth?: number;
|
minWidth?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -25,6 +27,8 @@ export function SidebarLayout({
|
|||||||
onWidthChange,
|
onWidthChange,
|
||||||
hidden = false,
|
hidden = false,
|
||||||
onHiddenChange,
|
onHiddenChange,
|
||||||
|
floating = false,
|
||||||
|
floatingWidth = 320,
|
||||||
defaultWidth = 250,
|
defaultWidth = 250,
|
||||||
minWidth = 50,
|
minWidth = 50,
|
||||||
className,
|
className,
|
||||||
@@ -75,6 +79,28 @@ export function SidebarLayout({
|
|||||||
onWidthChange(defaultWidth);
|
onWidthChange(defaultWidth);
|
||||||
}, [onWidthChange, defaultWidth]);
|
}, [onWidthChange, defaultWidth]);
|
||||||
|
|
||||||
|
if (floating) {
|
||||||
|
return (
|
||||||
|
<div className={classNames(className, 'relative w-full h-full overflow-hidden')}>
|
||||||
|
{children}
|
||||||
|
{!hidden && (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-black/50 z-20 transition-opacity"
|
||||||
|
onClick={() => onHiddenChange?.(true)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{ width: floatingWidth }}
|
||||||
|
className="absolute top-0 left-0 bottom-0 z-20 animate-slide-in-left"
|
||||||
|
>
|
||||||
|
{sidebar}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={styles}
|
style={styles}
|
||||||
|
|||||||
@@ -8,10 +8,16 @@ export function usePortal(name: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOrCreatePortal(name: string) {
|
function getOrCreatePortal(name: string) {
|
||||||
const portalContainer = document.getElementById(PORTAL_CONTAINER_ID) as HTMLDivElement;
|
let portalContainer = document.getElementById(PORTAL_CONTAINER_ID);
|
||||||
|
if (!portalContainer) {
|
||||||
|
portalContainer = document.createElement('div');
|
||||||
|
portalContainer.id = PORTAL_CONTAINER_ID;
|
||||||
|
document.body.appendChild(portalContainer);
|
||||||
|
}
|
||||||
|
|
||||||
let existing = portalContainer.querySelector(`:scope > [data-portal-name="${name}"]`);
|
let existing = portalContainer.querySelector(`:scope > [data-portal-name="${name}"]`);
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
const el: HTMLDivElement = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.setAttribute('data-portal-name', name);
|
el.setAttribute('data-portal-name', name);
|
||||||
portalContainer.appendChild(el);
|
portalContainer.appendChild(el);
|
||||||
existing = el;
|
existing = el;
|
||||||
@@ -28,3 +28,6 @@ export type { SplitLayoutLayout, SlotProps } from "./components/SplitLayout";
|
|||||||
export { Table, TableBody, TableHead, TableRow, TableCell, TruncatedWideTableCell, TableHeaderCell } from "./components/Table";
|
export { Table, TableBody, TableHead, TableRow, TableCell, TruncatedWideTableCell, TableHeaderCell } from "./components/Table";
|
||||||
export { clamp } from "./lib/clamp";
|
export { clamp } from "./lib/clamp";
|
||||||
export { useContainerSize } from "./hooks/useContainerSize";
|
export { useContainerSize } from "./hooks/useContainerSize";
|
||||||
|
export { Overlay } from "./components/Overlay";
|
||||||
|
export { Portal } from "./components/Portal";
|
||||||
|
export { usePortal } from "./hooks/usePortal";
|
||||||
|
|||||||
Reference in New Issue
Block a user