mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-27 20:01:10 +01:00
Scrollable tables, specify multi-part filename, fix required prop in prompt, better tab padding
This commit is contained in:
@@ -69,7 +69,11 @@ export function Dialog({
|
||||
animate={{ top: 0, scale: 1 }}
|
||||
className={classNames(
|
||||
className,
|
||||
'grid grid-rows-[auto_auto_minmax(0,1fr)]',
|
||||
'grid',
|
||||
title != null && description != null && 'grid-rows-[auto_minmax(0,1fr)_minmax_(0,1fr)]',
|
||||
title == null && description != null && 'grid-rows-[auto_minmax(0,1fr)]',
|
||||
title != null && description == null && 'grid-rows-[auto_minmax(0,1fr)]',
|
||||
title == null && description == null && 'grid-rows-[minmax(0,1fr)]',
|
||||
'grid-cols-1', // must be here for inline code blocks to correctly break words
|
||||
'relative bg-surface pointer-events-auto',
|
||||
'rounded-lg',
|
||||
@@ -83,20 +87,16 @@ export function Dialog({
|
||||
size === 'dynamic' && 'min-w-[20rem] max-w-[100vw]',
|
||||
)}
|
||||
>
|
||||
{title ? (
|
||||
{title && (
|
||||
<Heading className="px-6 mt-4 mb-2" level={1} id={titleId}>
|
||||
{title}
|
||||
</Heading>
|
||||
) : (
|
||||
<span aria-hidden />
|
||||
)}
|
||||
|
||||
{description ? (
|
||||
<div className="px-6 text-text-subtle mb-3" id={descriptionId}>
|
||||
{description && (
|
||||
<div className="min-h-0 px-6 text-text-subtle mb-3" id={descriptionId}>
|
||||
{description}
|
||||
</div>
|
||||
) : (
|
||||
<span aria-hidden />
|
||||
)}
|
||||
|
||||
<div
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
import { basename } from '@tauri-apps/api/path';
|
||||
import classNames from 'classnames';
|
||||
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { WrappedEnvironmentVariable } from '../../hooks/useEnvironmentVariables';
|
||||
@@ -70,6 +71,7 @@ export type Pair = {
|
||||
name: string;
|
||||
value: string;
|
||||
contentType?: string;
|
||||
filename?: string;
|
||||
isFile?: boolean;
|
||||
readOnlyName?: boolean;
|
||||
};
|
||||
@@ -492,6 +494,11 @@ export function PairEditorRow({
|
||||
[onChange, pair],
|
||||
);
|
||||
|
||||
const handleChangeValueFilename = useMemo(
|
||||
() => (filename: string) => onChange?.({ ...pair, filename }),
|
||||
[onChange, pair],
|
||||
);
|
||||
|
||||
const handleEditMultiLineValue = useCallback(
|
||||
() =>
|
||||
showDialog({
|
||||
@@ -614,6 +621,7 @@ export function PairEditorRow({
|
||||
inline
|
||||
size="xs"
|
||||
filePath={pair.value}
|
||||
nameOverride={pair.filename || null}
|
||||
onChange={handleChangeValueFile}
|
||||
/>
|
||||
) : pair.value.includes('\n') ? (
|
||||
@@ -659,6 +667,7 @@ export function PairEditorRow({
|
||||
onChangeFile={handleChangeValueFile}
|
||||
onChangeText={handleChangeValueText}
|
||||
onChangeContentType={handleChangeValueContentType}
|
||||
onChangeFilename={handleChangeValueFilename}
|
||||
onDelete={handleDelete}
|
||||
editMultiLine={handleEditMultiLineValue}
|
||||
/>
|
||||
@@ -687,6 +696,7 @@ function FileActionsDropdown({
|
||||
onChangeFile,
|
||||
onChangeText,
|
||||
onChangeContentType,
|
||||
onChangeFilename,
|
||||
onDelete,
|
||||
editMultiLine,
|
||||
}: {
|
||||
@@ -694,6 +704,7 @@ function FileActionsDropdown({
|
||||
onChangeFile: ({ filePath }: { filePath: string | null }) => void;
|
||||
onChangeText: (text: string) => void;
|
||||
onChangeContentType: (contentType: string) => void;
|
||||
onChangeFilename: (filename: string) => void;
|
||||
onDelete: () => void;
|
||||
editMultiLine: () => void;
|
||||
}) {
|
||||
@@ -731,6 +742,26 @@ function FileActionsDropdown({
|
||||
onChangeContentType(contentType);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Set File Name',
|
||||
leftSlot: <Icon icon="file_code" />,
|
||||
onSelect: async () => {
|
||||
console.log('PAIR', pair);
|
||||
const defaultFilename = await basename(pair.value ?? '');
|
||||
const filename = await showPrompt({
|
||||
id: 'filename',
|
||||
title: 'Override Filename',
|
||||
label: 'Filename',
|
||||
required: false,
|
||||
placeholder: defaultFilename ?? 'myfile.png',
|
||||
defaultValue: pair.filename,
|
||||
confirmText: 'Set',
|
||||
description: 'Leave blank to use the name of the selected file',
|
||||
});
|
||||
if (filename == null) return;
|
||||
onChangeFilename(filename);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Unset File',
|
||||
leftSlot: <Icon icon="x" />,
|
||||
@@ -747,7 +778,17 @@ function FileActionsDropdown({
|
||||
color: 'danger',
|
||||
},
|
||||
],
|
||||
[editMultiLine, onChangeContentType, onChangeFile, onDelete, pair.contentType, pair.isFile],
|
||||
[
|
||||
editMultiLine,
|
||||
onChangeContentType,
|
||||
onChangeFile,
|
||||
onDelete,
|
||||
pair.contentType,
|
||||
pair.isFile,
|
||||
onChangeFilename,
|
||||
pair.filename,
|
||||
pair,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,20 +1,50 @@
|
||||
import classNames from 'classnames';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export function Table({ children }: { children: ReactNode }) {
|
||||
export function Table({
|
||||
children,
|
||||
className,
|
||||
scrollable,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
scrollable?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<table className="w-full text-sm mb-auto min-w-full max-w-full divide-y divide-surface-highlight">
|
||||
{children}
|
||||
</table>
|
||||
<div className={classNames('w-full', scrollable && 'h-full overflow-y-auto')}>
|
||||
<table
|
||||
className={classNames(
|
||||
className,
|
||||
'w-full text-sm mb-auto min-w-full max-w-full',
|
||||
'border-separate border-spacing-0',
|
||||
scrollable && '[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-10',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TableBody({ children }: { children: ReactNode }) {
|
||||
return <tbody className="divide-y divide-surface-highlight">{children}</tbody>;
|
||||
return (
|
||||
<tbody className="[&>tr:not(:last-child)>td]:border-b [&>tr:not(:last-child)>td]:border-b-surface-highlight">
|
||||
{children}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
export function TableHead({ children }: { children: ReactNode }) {
|
||||
return <thead>{children}</thead>;
|
||||
export function TableHead({ children, className }: { children: ReactNode; className?: string }) {
|
||||
return (
|
||||
<thead
|
||||
className={classNames(
|
||||
className,
|
||||
'bg-surface [&_th]:border-b [&_th]:border-b-surface-highlight',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</thead>
|
||||
);
|
||||
}
|
||||
|
||||
export function TableRow({ children }: { children: ReactNode }) {
|
||||
@@ -42,9 +72,7 @@ export function TruncatedWideTableCell({
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<TableCell className={classNames(className, 'w-full relative')}>
|
||||
<div className="absolute inset-0 py-2 truncate">{children}</div>
|
||||
</TableCell>
|
||||
<TableCell className={classNames(className, 'truncate max-w-0 w-full')}>{children}</TableCell>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ export function Tabs({
|
||||
addBorders && layout === 'horizontal' && 'pl-3 -ml-1',
|
||||
addBorders && layout === 'vertical' && 'ml-0 mb-2',
|
||||
'flex items-center hide-scrollbars',
|
||||
layout === 'horizontal' && 'h-full overflow-auto p-2 -mr-2',
|
||||
layout === 'horizontal' && 'h-full overflow-auto p-2',
|
||||
layout === 'vertical' && 'overflow-x-auto overflow-y-visible ',
|
||||
// Give space for button focus states within overflow boundary.
|
||||
!addBorders && layout === 'vertical' && 'py-1 pl-3 -ml-5 pr-1',
|
||||
|
||||
Reference in New Issue
Block a user