feat: enhancements and fixes (#810)

This commit is contained in:
Daniel Lautzenheiser 2023-05-18 16:25:14 -04:00 committed by GitHub
parent f64f20231e
commit 6d1ce609aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 352 additions and 237 deletions

View File

@ -82,6 +82,7 @@ collections:
create: true create: true
editor: editor:
frame: false frame: false
size: half
fields: fields:
- label: Question - label: Question
name: title name: title

View File

@ -18,7 +18,7 @@ import {
hasI18n, hasI18n,
} from './lib/i18n'; } from './lib/i18n';
import { getBackend, invokeEvent } from './lib/registry'; import { getBackend, invokeEvent } from './lib/registry';
import { sanitizeChar } from './lib/urlHelper'; import { joinUrlPath, sanitizeChar } from './lib/urlHelper';
import { import {
CURSOR_COMPATIBILITY_SYMBOL, CURSOR_COMPATIBILITY_SYMBOL,
Cursor, Cursor,
@ -39,7 +39,11 @@ import {
selectInferredField, selectInferredField,
selectMediaFolders, selectMediaFolders,
} from './lib/util/collection.util'; } from './lib/util/collection.util';
import { selectMediaFilePath, selectMediaFilePublicPath } from './lib/util/media.util'; import {
DRAFT_MEDIA_FILES,
selectMediaFilePath,
selectMediaFilePublicPath,
} from './lib/util/media.util';
import { selectCustomPath, slugFromCustomPath } from './lib/util/nested.util'; import { selectCustomPath, slugFromCustomPath } from './lib/util/nested.util';
import { set } from './lib/util/object.util'; import { set } from './lib/util/object.util';
import { dateParsers, expandPath, extractTemplateVars } from './lib/widgets/stringTemplate'; import { dateParsers, expandPath, extractTemplateVars } from './lib/widgets/stringTemplate';
@ -84,7 +88,19 @@ function updateAssetProxies(
// update media files path based on entry path // update media files path based on entry path
const oldPath = asset.path; const oldPath = asset.path;
entryDraft.entry.path = path; entryDraft.entry.path = path;
const newPath = selectMediaFilePath(config, collection, entryDraft.entry, oldPath, asset.field);
const folderPath = joinUrlPath(
collection && 'folder' in collection ? collection.folder : '',
DRAFT_MEDIA_FILES,
);
const newPath = selectMediaFilePath(
config,
collection,
entryDraft.entry,
oldPath.replace(folderPath, ''),
asset.field,
);
asset.path = newPath; asset.path = newPath;
}); });
} }

View File

@ -151,7 +151,7 @@ const CollectionSearch = ({
p-1.5 p-1.5
pl-10 pl-10
text-sm text-sm
text-gray-900 text-gray-800
border border
border-gray-300 border-gray-300
rounded-lg rounded-lg
@ -185,7 +185,7 @@ const CollectionSearch = ({
rounded-md rounded-md
bg-white bg-white
text-base text-base
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
@ -193,6 +193,7 @@ const CollectionSearch = ({
sm:text-sm sm:text-sm
z-40 z-40
dark:bg-slate-700 dark:bg-slate-700
dark:shadow-lg
" "
> >
<div <div

View File

@ -52,7 +52,7 @@ const FilterControl = ({
/> />
<label <label
htmlFor={labelId} htmlFor={labelId}
className="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300" className="ml-2 text-sm font-medium text-gray-800 dark:text-gray-300"
> >
{viewFilter.label} {viewFilter.label}
</label> </label>

View File

@ -106,13 +106,6 @@ const EntryListingCardGrid: FC<EntryListingCardGridProps> = ({
}, []); }, []);
const getDefaultHeight = useCallback((data?: CollectionEntryData) => { const getDefaultHeight = useCallback((data?: CollectionEntryData) => {
console.log(
'DEFAULT HEIGHT',
data,
isNotNullish(data?.imageFieldName)
? COLLECTION_CARD_HEIGHT
: COLLECTION_CARD_HEIGHT_WITHOUT_IMAGE,
);
return isNotNullish(data?.imageFieldName) return isNotNullish(data?.imageFieldName)
? COLLECTION_CARD_HEIGHT ? COLLECTION_CARD_HEIGHT
: COLLECTION_CARD_HEIGHT_WITHOUT_IMAGE; : COLLECTION_CARD_HEIGHT_WITHOUT_IMAGE;
@ -187,13 +180,6 @@ const EntryListingCardGrid: FC<EntryListingCardGridProps> = ({
if (cardHeights[i] > rowHeight && cardHeights[i]) { if (cardHeights[i] > rowHeight && cardHeights[i]) {
rowHeight = cardHeights[i] + COLLECTION_CARD_MARGIN; rowHeight = cardHeights[i] + COLLECTION_CARD_MARGIN;
console.log(
'HEIGHT @index',
i,
cardHeights[i],
cardHeights[i] + COLLECTION_CARD_MARGIN,
);
} }
} }
@ -201,8 +187,6 @@ const EntryListingCardGrid: FC<EntryListingCardGridProps> = ({
rowHeight = getDefaultHeight() + COLLECTION_CARD_MARGIN; rowHeight = getDefaultHeight() + COLLECTION_CARD_MARGIN;
} }
console.log('HEIGHT', index, rowHeight);
return rowHeight; return rowHeight;
}} }}
width={width} width={width}

View File

@ -77,7 +77,12 @@ const EntryListingTable: FC<EntryListingTableProps> = ({
overflow-hidden overflow-hidden
p-1.5 p-1.5
bg-white bg-white
shadow-sm
border
border-gray-100
dark:bg-slate-800 dark:bg-slate-800
dark:border-gray-700/40
dark:shadow-md
rounded-xl rounded-xl
" "
> >

View File

@ -70,7 +70,7 @@ const Autocomplete = function <T>(
min-h-8 min-h-8
p-0 p-0
w-full w-full
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
" "
data-testid="autocomplete-input-wrapper" data-testid="autocomplete-input-wrapper"
@ -99,7 +99,7 @@ const Autocomplete = function <T>(
dark:text-gray-500 dark:text-gray-500
` `
: ` : `
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
`, `,
)} )}
@ -144,7 +144,7 @@ const Autocomplete = function <T>(
bg-white bg-white
py-1 py-1
text-base text-base
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
@ -152,10 +152,11 @@ const Autocomplete = function <T>(
sm:text-sm sm:text-sm
z-30 z-30
dark:bg-slate-700 dark:bg-slate-700
dark:shadow-lg
`} `}
> >
{options.length === 0 ? ( {options.length === 0 ? (
<div className="relative cursor-default select-none py-2 px-4 text-gray-700"> <div className="relative cursor-default select-none py-2 px-4 text-gray-800">
Nothing found. Nothing found.
</div> </div>
) : ( ) : (
@ -179,7 +180,7 @@ const Autocomplete = function <T>(
pl-10 pl-10
pr-4 pr-4
cursor-pointer cursor-pointer
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
`, `,
(selected || active) && (selected || active) &&

View File

@ -14,12 +14,14 @@ const Card = ({ children, className }: CardProps) => {
<div <div
className={classNames( className={classNames(
` `
bg-white border bg-white
border-gray-200 border
border-gray-100
rounded-lg rounded-lg
shadow-md shadow-sm
dark:bg-slate-800 dark:bg-slate-800
dark:border-gray-700/40 dark:border-gray-700/40
dark:shadow-md
flex flex
flex-col flex-col
h-full h-full

View File

@ -7,7 +7,7 @@ interface CardContentProps {
} }
const CardContent = ({ children }: CardContentProps) => { const CardContent = ({ children }: CardContentProps) => {
return <p className="w-full p-5 font-normal text-gray-700 dark:text-gray-300">{children}</p>; return <p className="w-full p-5 font-normal text-gray-800 dark:text-gray-300">{children}</p>;
}; };
export default CardContent; export default CardContent;

View File

@ -8,7 +8,7 @@ interface CardHeaderProps {
const CardHeader = ({ children }: CardHeaderProps) => { const CardHeader = ({ children }: CardHeaderProps) => {
return ( return (
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"> <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-800 dark:text-white">
{children} {children}
</h5> </h5>
); );

View File

@ -97,7 +97,7 @@ const Menu = ({
rounded-md rounded-md
bg-white bg-white
dark:bg-slate-800 dark:bg-slate-800
shadow-lg shadow-md
border border
border-gray-200 border-gray-200
focus:outline-none focus:outline-none
@ -105,6 +105,7 @@ const Menu = ({
divide-gray-100 divide-gray-100
dark:border-gray-700 dark:border-gray-700
dark:divide-gray-600 dark:divide-gray-600
dark:shadow-lg
`, `,
onClick: handleClose, onClick: handleClose,
}, },

View File

@ -46,11 +46,11 @@ const MenuItemButton = ({
items-center items-center
justify-between justify-between
cursor-pointer cursor-pointer
dark:disabled:text-gray-700 dark:disabled:text-gray-800
`, `,
color === 'default' && color === 'default' &&
` `
text-gray-700 text-gray-800
dark:text-gray-300 dark:text-gray-300
hover:bg-gray-200 hover:bg-gray-200
dark:hover:bg-slate-600 dark:hover:bg-slate-600

View File

@ -36,7 +36,7 @@ const MenuItemLink = ({
px-4 px-4
py-2 py-2
text-sm text-sm
text-gray-700 text-gray-800
dark:text-gray-300 dark:text-gray-300
w-full w-full
text-left text-left

View File

@ -45,7 +45,7 @@ const Pill: FC<PillProps> = ({
` `
: ` : `
bg-gray-200 bg-gray-200
text-gray-900 text-gray-800
dark:bg-gray-700 dark:bg-gray-700
dark:text-gray-100 dark:text-gray-100
`; `;

View File

@ -40,7 +40,7 @@ const Option = function <T>({
py-2 py-2
px-4 px-4
cursor-pointer cursor-pointer
text-gray-900 text-gray-800
hover:bg-blue-500 hover:bg-blue-500
dark:text-gray-100 dark:text-gray-100
`, `,

View File

@ -136,7 +136,7 @@ const Select = forwardRef(
px-4 px-4
py-1.5 py-1.5
w-full w-full
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
`, `,
disabled && disabled &&
@ -154,7 +154,7 @@ const Select = forwardRef(
bg-white bg-white
py-1 py-1
text-base text-base
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
@ -162,6 +162,7 @@ const Select = forwardRef(
sm:text-sm sm:text-sm
z-50 z-50
dark:bg-slate-700 dark:bg-slate-700
dark:shadow-lg
`, `,
style: { width }, style: { width },
disablePortal: false, disablePortal: false,

View File

@ -86,7 +86,7 @@ const Switch = forwardRef<HTMLInputElement | null, SwitchProps>(
ml-3 ml-3
text-sm text-sm
font-medium font-medium
text-gray-900 text-gray-800
dark:text-gray-300 dark:text-gray-300
" "
> >

View File

@ -13,13 +13,12 @@ const TableCell = ({ columns, children }: TableCellProps) => {
return ( return (
<div <div
className=" className="
shadow-md
z-[2] z-[2]
" "
> >
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-300"> <table className="w-full text-sm text-left text-gray-500 dark:text-gray-300">
<thead className="text-xs"> <thead className="text-xs">
<tr> <tr className="shadow-sm">
{columns.map((column, index) => ( {columns.map((column, index) => (
<TableHeaderCell key={index}>{column}</TableHeaderCell> <TableHeaderCell key={index}>{column}</TableHeaderCell>
))} ))}

View File

@ -42,7 +42,7 @@ const TableCell = ({ children, emphasis = false, to, shrink = false }: TableCell
text-gray-500 text-gray-500
dark:text-gray-300 dark:text-gray-300
`, `,
emphasis && 'font-medium text-gray-900 whitespace-nowrap dark:text-white', emphasis && 'font-medium text-gray-800 whitespace-nowrap dark:text-white',
shrink && 'w-0', shrink && 'w-0',
)} )}
> >

View File

@ -27,14 +27,13 @@ const TableHeaderCell = ({ children }: TableHeaderCellProps) => {
className=" className="
px-4 px-4
py-3 py-3
text-gray-900 text-gray-800
border-gray-100 border-gray-100
border-b border-b
bg-white bg-white
dark:text-white dark:text-white
dark:border-gray-700 dark:border-gray-700
dark:bg-slate-800 dark:bg-slate-800
shadow-sm
text-[14px] text-[14px]
" "
> >

View File

@ -75,7 +75,7 @@ const TextArea = forwardRef<HTMLInputElement | null, TextAreaProps>(
outline-none outline-none
text-sm text-sm
font-medium font-medium
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
disabled:text-gray-300 disabled:text-gray-300
dark:disabled:text-gray-500 dark:disabled:text-gray-500

View File

@ -86,7 +86,7 @@ const TextField: FC<TextFieldProps> = ({
bg-transparent bg-transparent
outline-none outline-none
font-medium font-medium
text-gray-900 text-gray-800
disabled:text-gray-300 disabled:text-gray-300
dark:text-gray-100 dark:text-gray-100
dark:disabled:text-gray-500 dark:disabled:text-gray-500
@ -96,7 +96,7 @@ const TextField: FC<TextFieldProps> = ({
bg-gray-50 bg-gray-50
border border
border-gray-300 border-gray-300
text-gray-900 text-gray-800
rounded-lg rounded-lg
focus:ring-blue-500 focus:ring-blue-500
focus:border-blue-500 focus:border-blue-500

View File

@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { ScrollSyncPane } from 'react-scroll-sync'; import { ScrollSyncPane } from 'react-scroll-sync';
import { EDITOR_SIZE_COMPACT } from '@staticcms/core/constants/views';
import useBreadcrumbs from '@staticcms/core/lib/hooks/useBreadcrumbs'; import useBreadcrumbs from '@staticcms/core/lib/hooks/useBreadcrumbs';
import { getI18nInfo, getPreviewEntry, hasI18n } from '@staticcms/core/lib/i18n'; import { getI18nInfo, getPreviewEntry, hasI18n } from '@staticcms/core/lib/i18n';
import classNames from '@staticcms/core/lib/util/classNames.util'; import classNames from '@staticcms/core/lib/util/classNames.util';
@ -138,9 +139,10 @@ const EditorInterface = ({
setSelectedLocale(locale); setSelectedLocale(locale);
}, []); }, []);
const [showPreviewToggle, previewInFrame] = useMemo(() => { const [showPreviewToggle, previewInFrame, editorSize] = useMemo(() => {
let preview = collection.editor?.preview ?? true; let preview = collection.editor?.preview ?? true;
let frame = collection.editor?.frame ?? true; let frame = collection.editor?.frame ?? true;
let size = collection.editor?.size ?? EDITOR_SIZE_COMPACT;
if ('files' in collection) { if ('files' in collection) {
const file = getFileFromSlug(collection, entry.slug); const file = getFileFromSlug(collection, entry.slug);
@ -151,9 +153,13 @@ const EditorInterface = ({
if (file?.editor?.frame !== undefined) { if (file?.editor?.frame !== undefined) {
frame = file.editor.frame; frame = file.editor.frame;
} }
if (file?.editor?.size !== undefined) {
size = file.editor.size;
}
} }
return [preview, frame]; return [preview, frame, size];
}, [collection, entry.slug]); }, [collection, entry.slug]);
const finalPreviewActive = useMemo( const finalPreviewActive = useMemo(
@ -226,13 +232,22 @@ const EditorInterface = ({
: entry; : entry;
const editorWithPreview = ( const editorWithPreview = (
<div className="grid grid-cols-editor h-full"> <div
className={classNames(
`
grid
h-full
`,
editorSize === EDITOR_SIZE_COMPACT ? 'grid-cols-editor' : 'grid-cols-2',
)}
>
<ScrollSyncPane>{editor}</ScrollSyncPane> <ScrollSyncPane>{editor}</ScrollSyncPane>
<EditorPreviewPane <EditorPreviewPane
collection={collection} collection={collection}
previewInFrame={previewInFrame} previewInFrame={previewInFrame}
entry={previewEntry} entry={previewEntry}
fields={fields} fields={fields}
editorSize={editorSize}
/> />
</div> </div>
); );

View File

@ -4,17 +4,20 @@ import Frame from 'react-frame-component';
import { translate } from 'react-polyglot'; import { translate } from 'react-polyglot';
import { ScrollSyncPane } from 'react-scroll-sync'; import { ScrollSyncPane } from 'react-scroll-sync';
import { EDITOR_SIZE_COMPACT } from '@staticcms/core/constants/views';
import { getPreviewStyles, getPreviewTemplate } from '@staticcms/core/lib/registry'; import { getPreviewStyles, getPreviewTemplate } from '@staticcms/core/lib/registry';
import classNames from '@staticcms/core/lib/util/classNames.util';
import { selectTemplateName } from '@staticcms/core/lib/util/collection.util'; import { selectTemplateName } from '@staticcms/core/lib/util/collection.util';
import { selectConfig } from '@staticcms/core/reducers/selectors/config'; import { selectConfig } from '@staticcms/core/reducers/selectors/config';
import { selectTheme } from '@staticcms/core/reducers/selectors/globalUI'; import { selectTheme } from '@staticcms/core/reducers/selectors/globalUI';
import { useAppSelector } from '@staticcms/core/store/hooks'; import { useAppSelector } from '@staticcms/core/store/hooks';
import useWidgetsFor from '../../common/widget/useWidgetsFor';
import ErrorBoundary from '../../ErrorBoundary'; import ErrorBoundary from '../../ErrorBoundary';
import useWidgetsFor from '../../common/widget/useWidgetsFor';
import EditorPreview from './EditorPreview'; import EditorPreview from './EditorPreview';
import EditorPreviewContent from './EditorPreviewContent'; import EditorPreviewContent from './EditorPreviewContent';
import PreviewFrameContent from './PreviewFrameContent'; import PreviewFrameContent from './PreviewFrameContent';
import type { EditorSize } from '@staticcms/core/constants/views';
import type { import type {
Collection, Collection,
Entry, Entry,
@ -51,7 +54,7 @@ const FrameGlobalStyles = `
color: rgb(59 130 246); color: rgb(59 130 246);
} }
.text-gray-900 { .text-gray-800 {
color: rgb(17 24 39); color: rgb(17 24 39);
} }
@ -103,10 +106,11 @@ export interface EditorPreviewPaneProps {
fields: Field[]; fields: Field[];
entry: Entry; entry: Entry;
previewInFrame: boolean; previewInFrame: boolean;
editorSize: EditorSize;
} }
const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => { const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
const { entry, collection, fields, previewInFrame, t } = props; const { editorSize, entry, collection, fields, previewInFrame, t } = props;
const config = useAppSelector(selectConfig); const config = useAppSelector(selectConfig);
@ -168,7 +172,17 @@ const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
} }
return createPortal( return createPortal(
<div className="w-preview h-main absolute top-16 right-0"> <div
className={classNames(
`
h-main
absolute
top-16
right-0
`,
editorSize === EDITOR_SIZE_COMPACT ? 'w-preview' : 'w-6/12',
)}
>
{!entry || !entry.data ? null : ( {!entry || !entry.data ? null : (
<ErrorBoundary config={config}> <ErrorBoundary config={config}>
{previewInFrame ? ( {previewInFrame ? (
@ -191,7 +205,15 @@ const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
</Frame> </Frame>
) : ( ) : (
<ScrollSyncPane key="preview-wrapper-scroll-sync"> <ScrollSyncPane key="preview-wrapper-scroll-sync">
<div key="preview-wrapper" id="preview-pane"> <div
key="preview-wrapper"
id="preview-pane"
className="
overflow-y-auto
styled-scrollbars
h-full
"
>
{!collection ? ( {!collection ? (
t('collection.notFound') t('collection.notFound')
) : ( ) : (
@ -216,6 +238,7 @@ const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
}, [ }, [
collection, collection,
config, config,
editorSize,
element, element,
entry, entry,
initialFrameContent, initialFrameContent,

View File

@ -40,7 +40,7 @@ const PreviewFrameContent: FC<PreviewFrameContentProps> = ({ previewComponent, p
<div> <div>
<div <div
className=" className="
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
" "
> >

View File

@ -10,7 +10,7 @@ const UnknownControl = ({ field, t }: TranslatedProps<WidgetControlProps<unknown
px-4 px-4
py-2 py-2
text-small text-small
text-gray-900 text-gray-800
dark:text-gray-100 dark:text-gray-100
" "
> >

View File

@ -65,7 +65,7 @@ const FolderCreationDialog: FC<TranslatedProps<FolderCreationDialogProps>> = ({
className=" className="
text-xl text-xl
font-semibold font-semibold
text-gray-900 text-gray-800
dark:text-white dark:text-white
" "
> >

View File

@ -140,7 +140,7 @@ const InlineEditTextField: FC<InlineEditTextFieldProps> = ({
p-1.5 p-1.5
-ml-1.5 -ml-1.5
text-sm text-sm
text-gray-900 text-gray-800
border border
border-gray-300 border-gray-300
rounded-md rounded-md

View File

@ -27,7 +27,7 @@ const MediaLibrarySearch = ({
> >
<label <label
htmlFor="default-search" htmlFor="default-search"
className="text-sm font-medium text-gray-900 sr-only dark:text-white" className="text-sm font-medium text-gray-800 sr-only dark:text-white"
> >
Search Search
</label> </label>
@ -44,7 +44,7 @@ const MediaLibrarySearch = ({
p-1.5 p-1.5
pl-10 pl-10
text-sm text-sm
text-gray-900 text-gray-800
border border
border-gray-300 border-gray-300
rounded-lg rounded-lg

View File

@ -41,7 +41,16 @@ const Navbar = ({
}, [dispatch]); }, [dispatch]);
return ( return (
<nav className="bg-white dark:bg-slate-800 drop-shadow-lg z-40 relative"> <nav
className="
z-40
relative
bg-white
drop-shadow-md
dark:bg-slate-800
dark:drop-shadow-lg
"
>
<div key="nav" className="mx-auto pr-2 sm:pr-4 lg:pr-5"> <div key="nav" className="mx-auto pr-2 sm:pr-4 lg:pr-5">
<div className="relative flex h-16 items-center justify-between"> <div className="relative flex h-16 items-center justify-between">
<div className="flex flex-1 items-center justify-center h-full sm:items-stretch sm:justify-start gap-4"> <div className="flex flex-1 items-center justify-center h-full sm:items-stretch sm:justify-start gap-4">

View File

@ -56,7 +56,7 @@ const SnackbarAlert = forwardRef<HTMLDivElement, TranslatedProps<SnackbarAlertPr
text-gray-500 text-gray-500
bg-white bg-white
rounded-lg rounded-lg
shadow shadow-md
dark:text-gray-300 dark:text-gray-300
dark:bg-gray-800 dark:bg-gray-800
dark:shadow-lg dark:shadow-lg

View File

@ -2,9 +2,16 @@ export const VIEW_STYLE_TABLE = 'table';
export const VIEW_STYLE_GRID = 'grid'; export const VIEW_STYLE_GRID = 'grid';
export type ViewStyle = typeof VIEW_STYLE_TABLE | typeof VIEW_STYLE_GRID; export type ViewStyle = typeof VIEW_STYLE_TABLE | typeof VIEW_STYLE_GRID;
export const VIEW_STYLES = [VIEW_STYLE_TABLE, VIEW_STYLE_GRID];
export const COLLECTION_CARD_WIDTH = 240; export const COLLECTION_CARD_WIDTH = 240;
export const COLLECTION_CARD_HEIGHT = 204; export const COLLECTION_CARD_HEIGHT = 204;
export const COLLECTION_CARD_IMAGE_HEIGHT = 140; export const COLLECTION_CARD_IMAGE_HEIGHT = 140;
export const COLLECTION_CARD_HEIGHT_WITHOUT_IMAGE = 64; export const COLLECTION_CARD_HEIGHT_WITHOUT_IMAGE = 64;
export const COLLECTION_CARD_MARGIN = 10; export const COLLECTION_CARD_MARGIN = 10;
export const EDITOR_SIZE_COMPACT = 'compact';
export const EDITOR_SIZE_HALF = 'half';
export type EditorSize = typeof EDITOR_SIZE_COMPACT | typeof EDITOR_SIZE_HALF;
export const EDITOR_SIZES = [EDITOR_SIZE_COMPACT, EDITOR_SIZE_HALF];

View File

@ -37,7 +37,7 @@ import type {
STRIKETHROUGH_TOOLBAR_BUTTON, STRIKETHROUGH_TOOLBAR_BUTTON,
UNORDERED_LIST_TOOLBAR_BUTTON, UNORDERED_LIST_TOOLBAR_BUTTON,
} from './constants/toolbar_buttons'; } from './constants/toolbar_buttons';
import type { ViewStyle } from './constants/views'; import type { EditorSize, ViewStyle } from './constants/views';
import type { formatExtensions } from './formats/formats'; import type { formatExtensions } from './formats/formats';
import type { import type {
I18N_FIELD_DUPLICATE, I18N_FIELD_DUPLICATE,
@ -178,6 +178,7 @@ export interface FilterRule {
export interface EditorConfig { export interface EditorConfig {
preview?: boolean; preview?: boolean;
frame?: boolean; frame?: boolean;
size?: EditorSize;
} }
export interface CollectionFile<EF extends BaseField = UnknownField> { export interface CollectionFile<EF extends BaseField = UnknownField> {

View File

@ -2,7 +2,7 @@ export { default as useEntries } from './useEntries';
export { default as useFolderSupport } from './useFolderSupport'; export { default as useFolderSupport } from './useFolderSupport';
export { default as useHasChildErrors } from './useHasChildErrors'; export { default as useHasChildErrors } from './useHasChildErrors';
export { default as useIsMediaAsset } from './useIsMediaAsset'; export { default as useIsMediaAsset } from './useIsMediaAsset';
export { default as useMediaAsset } from './useMediaAsset'; export { default as useMediaAsset, useGetMediaAsset } from './useMediaAsset';
export { default as useMediaFiles } from './useMediaFiles'; export { default as useMediaFiles } from './useMediaFiles';
export { default as useMediaInsert } from './useMediaInsert'; export { default as useMediaInsert } from './useMediaInsert';
export { default as useMediaPersist } from './useMediaPersist'; export { default as useMediaPersist } from './useMediaPersist';

View File

@ -14,7 +14,7 @@ export function getIcon(iconName: string | undefined): ReactNode {
} }
} }
return <div className="h-6 w-6 flex">{icon}</div>; return <div className="h-6 w-6 flex items-center justify-center cms-icon">{icon}</div>;
} }
export default function useIcon(iconName: string | undefined) { export default function useIcon(iconName: string | undefined) {

View File

@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { emptyAsset, getAsset } from '@staticcms/core/actions/media'; import { emptyAsset, getAsset } from '@staticcms/core/actions/media';
import { useAppDispatch } from '@staticcms/core/store/hooks'; import { useAppDispatch } from '@staticcms/core/store/hooks';
@ -13,6 +13,33 @@ import type {
UnknownField, UnknownField,
} from '@staticcms/core/interface'; } from '@staticcms/core/interface';
export function useGetMediaAsset<T extends MediaField, EF extends BaseField = UnknownField>(
collection?: Collection<EF>,
field?: T,
entry?: Entry,
currentFolder?: string,
isDirectory = false,
): (url: string | undefined | null) => Promise<string | undefined | null> {
const dispatch = useAppDispatch();
return useCallback(
async (url: string | undefined | null): Promise<string | undefined | null> => {
const isAbsolute = isNotEmpty(url) ? /^(?:[a-z+]+:)?\/\//g.test(url) : false;
if (!url || isAbsolute || url.startsWith('blob:') || isDirectory) {
return url;
}
const asset = await dispatch(getAsset<T, EF>(collection, entry, url, field, currentFolder));
if (asset !== emptyAsset) {
return asset?.toString() ?? '';
}
},
[collection, currentFolder, dispatch, entry, field, isDirectory],
);
}
export default function useMediaAsset<T extends MediaField, EF extends BaseField = UnknownField>( export default function useMediaAsset<T extends MediaField, EF extends BaseField = UnknownField>(
url: string | undefined | null, url: string | undefined | null,
collection?: Collection<EF>, collection?: Collection<EF>,

View File

@ -13,8 +13,14 @@ import type {
} from '@staticcms/core/interface'; } from '@staticcms/core/interface';
import type { MouseEvent } from 'react'; import type { MouseEvent } from 'react';
export interface OpenMediaLibraryProps {
forImage?: boolean;
forFolder?: boolean;
replaceIndex?: number;
}
export default function useMediaInsert<T extends string | string[], F extends MediaField>( export default function useMediaInsert<T extends string | string[], F extends MediaField>(
value: MediaPath<T>, value: MediaPath<T> | undefined,
options: { options: {
collection: Collection<F>; collection: Collection<F>;
field: F; field: F;
@ -23,8 +29,8 @@ export default function useMediaInsert<T extends string | string[], F extends Me
forFolder?: boolean; forFolder?: boolean;
insertOptions?: MediaLibrarInsertOptions; insertOptions?: MediaLibrarInsertOptions;
}, },
callback: (newValue: MediaPath<T>) => void, callback: (newValue: MediaPath<T>) => void | Promise<void>,
): (e?: MouseEvent, options?: { replaceIndex?: number }) => void { ): (e?: MouseEvent, options?: OpenMediaLibraryProps) => void {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { const {
@ -41,7 +47,7 @@ export default function useMediaInsert<T extends string | string[], F extends Me
const mediaPath = useAppSelector(mediaPathSelector); const mediaPath = useAppSelector(mediaPathSelector);
useEffect(() => { useEffect(() => {
if (mediaPath && (mediaPath.path !== value.path || mediaPath.alt !== value.alt)) { if (mediaPath && (!value || mediaPath.path !== value.path || mediaPath.alt !== value.alt)) {
setTimeout(() => { setTimeout(() => {
callback(mediaPath as MediaPath<T>); callback(mediaPath as MediaPath<T>);
dispatch(removeInsertedMedia(finalControlID)); dispatch(removeInsertedMedia(finalControlID));
@ -50,17 +56,27 @@ export default function useMediaInsert<T extends string | string[], F extends Me
}, [callback, finalControlID, dispatch, mediaPath, value]); }, [callback, finalControlID, dispatch, mediaPath, value]);
const handleOpenMediaLibrary = useCallback( const handleOpenMediaLibrary = useCallback(
(e?: MouseEvent, { replaceIndex }: { replaceIndex?: number } = {}) => { (
e?: MouseEvent,
{
replaceIndex,
forImage: forImageOverride,
forFolder: forFolderOverride,
}: OpenMediaLibraryProps = {},
) => {
e?.preventDefault(); e?.preventDefault();
dispatch( dispatch(
openMediaLibrary({ openMediaLibrary({
controlID: finalControlID, controlID: finalControlID,
forImage, forImage: forImageOverride ?? forImage,
forFolder, forFolder: forFolderOverride ?? forFolder,
value: Array.isArray(value.path) ? [...value.path] : value.path, value: field.multiple
alt: value.alt, ? value
? [...(Array.isArray(value.path) ? value.path : [value.path])]
: []
: value?.path,
alt: value?.alt,
replaceIndex, replaceIndex,
allowMultiple: false,
config: field.media_library, config: field.media_library,
collection, collection,
field, field,
@ -68,17 +84,7 @@ export default function useMediaInsert<T extends string | string[], F extends Me
}), }),
); );
}, },
[ [dispatch, finalControlID, forImage, forFolder, value, collection, field, insertOptions],
dispatch,
finalControlID,
forImage,
forFolder,
value.path,
value.alt,
collection,
field,
insertOptions,
],
); );
return handleOpenMediaLibrary; return handleOpenMediaLibrary;

View File

@ -22,7 +22,7 @@ import {
SORT_ENTRIES_REQUEST, SORT_ENTRIES_REQUEST,
SORT_ENTRIES_SUCCESS, SORT_ENTRIES_SUCCESS,
} from '../constants'; } from '../constants';
import { VIEW_STYLE_TABLE } from '../constants/views'; import { VIEW_STYLES, VIEW_STYLE_TABLE } from '../constants/views';
import { set } from '../lib/util/object.util'; import { set } from '../lib/util/object.util';
import type { EntriesAction } from '../actions/entries'; import type { EntriesAction } from '../actions/entries';
@ -93,7 +93,7 @@ function persistSort(sort: Sort | undefined) {
const loadViewStyle = once(() => { const loadViewStyle = once(() => {
const viewStyle = localStorage.getItem(viewStyleKey) as ViewStyle; const viewStyle = localStorage.getItem(viewStyleKey) as ViewStyle;
if (viewStyle) { if (viewStyle && VIEW_STYLES.includes(viewStyle)) {
return viewStyle; return viewStyle;
} }

View File

@ -7,9 +7,14 @@
@tailwind utilities; @tailwind utilities;
@layer components { @layer components {
html {
@apply overflow-hidden;
}
body { body {
@apply text-gray-900 @apply text-gray-800
dark:text-gray-100; dark:text-gray-100
overflow-hidden;
} }
/** /**
@ -73,7 +78,7 @@
} }
.btn-outlined-primary { .btn-outlined-primary {
@apply text-gray-900 @apply text-gray-800
bg-transparent bg-transparent
border border
border-gray-200 border-gray-200
@ -96,7 +101,7 @@
.btn-text-primary { .btn-text-primary {
@apply bg-transparent @apply bg-transparent
text-gray-700 text-gray-800
hover:text-blue-700 hover:text-blue-700
hover:bg-blue-100 hover:bg-blue-100
disabled:text-gray-300 disabled:text-gray-300
@ -115,7 +120,7 @@
text-gray-600 text-gray-600
bg-white bg-white
border-gray-200/75 border-gray-200/75
hover:text-gray-700 hover:text-gray-800
hover:bg-gray-100 hover:bg-gray-100
hover:border-gray-200/50 hover:border-gray-200/50
disabled:text-gray-300/75 disabled:text-gray-300/75
@ -133,12 +138,12 @@
} }
.btn-outlined-secondary { .btn-outlined-secondary {
@apply text-gray-900 @apply text-gray-800
bg-transparent bg-transparent
border border
border-gray-200 border-gray-200
hover:bg-gray-100 hover:bg-gray-100
hover:text-gray-700 hover:text-gray-800
hover:border-gray-200/50 hover:border-gray-200/50
disabled:text-gray-300/75 disabled:text-gray-300/75
disabled:border-gray-200/40 disabled:border-gray-200/40
@ -156,8 +161,8 @@
.btn-text-secondary { .btn-text-secondary {
@apply bg-transparent @apply bg-transparent
text-gray-900 text-gray-800
hover:text-gray-700 hover:text-gray-800
hover:bg-gray-100 hover:bg-gray-100
disabled:text-gray-300/75 disabled:text-gray-300/75
disabled:hover:bg-transparent disabled:hover:bg-transparent
@ -408,3 +413,10 @@ table {
} }
} }
} }
.cms-icon {
& > * {
width: 24px;
height: 24px;
}
}

View File

@ -266,7 +266,7 @@ const BalloonToolbar: FC<BalloonToolbarProps> = ({
bg-white bg-white
p-1 p-1
text-base text-base
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
@ -274,6 +274,7 @@ const BalloonToolbar: FC<BalloonToolbarProps> = ({
sm:text-sm sm:text-sm
z-40 z-40
dark:bg-slate-700 dark:bg-slate-700
dark:shadow-lg
" "
> >
<div <div

View File

@ -151,7 +151,7 @@ const FontTypeSelect: FC<FontTypeSelectProps> = ({ disabled = false }) => {
dark:text-gray-500 dark:text-gray-500
` `
: ` : `
text-gray-900 text-gray-800
border-gray-600 border-gray-600
dark:border-gray-200 dark:border-gray-200
dark:text-gray-100 dark:text-gray-100
@ -166,13 +166,14 @@ const FontTypeSelect: FC<FontTypeSelectProps> = ({ disabled = false }) => {
overflow-auto overflow-auto
rounded-md rounded-md
bg-white bg-white
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
focus:outline-none focus:outline-none
sm:text-sm sm:text-sm
dark:bg-slate-800 dark:bg-slate-800
dark:shadow-lg
`, `,
}, },
}} }}

View File

@ -91,7 +91,7 @@ const MediaPopover = <T extends FileOrImageField | MarkdownField>({
bg-white bg-white
p-1 p-1
text-base text-base
shadow-lg shadow-md
ring-1 ring-1
ring-black ring-black
ring-opacity-5 ring-opacity-5
@ -99,6 +99,7 @@ const MediaPopover = <T extends FileOrImageField | MarkdownField>({
sm:text-sm sm:text-sm
z-40 z-40
dark:bg-slate-700 dark:bg-slate-700
dark:shadow-lg
" "
> >
<div <div

View File

@ -81,9 +81,10 @@ const Toolbar: FC<ToolbarProps> = ({ collection, field, disabled }) => {
border-bottom-2 border-bottom-2
border-gray-400 border-gray-400
gap-0.5 gap-0.5
shadow-md shadow-sm
bg-slate-50 bg-slate-50
dark:bg-slate-900 dark:bg-slate-900
dark:shadow-md
sticky sticky
top-0 top-0
z-10 z-10

View File

@ -425,12 +425,12 @@ describe(RelationControl.name, () => {
const option5 = 'autocomplete-option-Post 5'; const option5 = 'autocomplete-option-Post 5';
const option6 = 'autocomplete-option-Post 6'; const option6 = 'autocomplete-option-Post 6';
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option3)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option3)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option4)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option4)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option5)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option5)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option6)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option6)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.type(input, 'ost body text for Post 3'); await userEvent.type(input, 'ost body text for Post 3');
@ -441,7 +441,7 @@ describe(RelationControl.name, () => {
await waitFor(() => expect(queryByTestId(option1)).not.toBeInTheDocument()); await waitFor(() => expect(queryByTestId(option1)).not.toBeInTheDocument());
expect(queryByTestId(option2)).not.toBeInTheDocument(); expect(queryByTestId(option2)).not.toBeInTheDocument();
expect(getByTestId(option3)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option3)).toHaveClass('text-gray-800'); // Not selected
expect(queryByTestId(option4)).not.toBeInTheDocument(); expect(queryByTestId(option4)).not.toBeInTheDocument();
expect(queryByTestId(option5)).not.toBeInTheDocument(); expect(queryByTestId(option5)).not.toBeInTheDocument();
expect(queryByTestId(option6)).not.toBeInTheDocument(); expect(queryByTestId(option6)).not.toBeInTheDocument();
@ -469,11 +469,11 @@ describe(RelationControl.name, () => {
expect(input).toHaveValue('P'); expect(input).toHaveValue('P');
expect(getByTestId('autocomplete-option-Post 1')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 1')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 2')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 2')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 3')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 3')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 4')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 4')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 5')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 5')).toHaveClass('text-gray-800'); // Not selected
expect(queryByTestId('autocomplete-option-Post 6')).not.toBeInTheDocument(); expect(queryByTestId('autocomplete-option-Post 6')).not.toBeInTheDocument();
}); });
@ -504,12 +504,12 @@ describe(RelationControl.name, () => {
await userEvent.type(input, 'P'); await userEvent.type(input, 'P');
}); });
expect(getByTestId('autocomplete-option-Post 1')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 1')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 2')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 2')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 3')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 3')).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId('autocomplete-option-Post 4')).toHaveClass('text-gray-900'); // Not selected expect(getByTestId('autocomplete-option-Post 4')).toHaveClass('text-gray-800'); // Not selected
expect(queryByTestId('autocomplete-option-Post 5')).not.toBeInTheDocument(); expect(queryByTestId('autocomplete-option-Post 5')).not.toBeInTheDocument();
expect(getByTestId('autocomplete-option-Post 6')).toHaveClass('bg-gray-100', 'text-gray-900'); // Selected expect(getByTestId('autocomplete-option-Post 6')).toHaveClass('bg-gray-100', 'text-gray-800'); // Selected
}); });
it('should call onChange when option is selected', async () => { it('should call onChange when option is selected', async () => {
@ -604,8 +604,8 @@ describe(RelationControl.name, () => {
const option1 = 'autocomplete-option-Post 1'; const option1 = 'autocomplete-option-Post 1';
const option2 = 'autocomplete-option-Post 2'; const option2 = 'autocomplete-option-Post 2';
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -619,8 +619,8 @@ describe(RelationControl.name, () => {
await userEvent.type(input, 'o'); await userEvent.type(input, 'o');
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-gray-100', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-gray-100', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -633,8 +633,8 @@ describe(RelationControl.name, () => {
await userEvent.type(input, 's'); await userEvent.type(input, 's');
}); });
expect(getByTestId(option1)).toHaveClass('bg-gray-100', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-gray-100', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-gray-100', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-gray-100', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -647,8 +647,8 @@ describe(RelationControl.name, () => {
await userEvent.type(input, 't'); await userEvent.type(input, 't');
}); });
expect(getByTestId(option1)).toHaveClass('bg-gray-100', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-gray-100', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });

View File

@ -132,8 +132,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -146,8 +146,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -160,8 +160,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
it('should show error', async () => { it('should show error', async () => {
@ -236,8 +236,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -250,8 +250,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -264,8 +264,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
}); });
@ -324,8 +324,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -338,8 +338,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -352,8 +352,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
}); });
@ -425,8 +425,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -439,8 +439,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -453,8 +453,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
}); });
@ -526,8 +526,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -540,8 +540,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -554,8 +554,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
}); });
@ -627,8 +627,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -641,8 +641,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -655,8 +655,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not selected
}); });
}); });
@ -716,8 +716,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -730,8 +730,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -744,8 +744,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -758,8 +758,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
@ -819,8 +819,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -833,8 +833,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -847,8 +847,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -861,8 +861,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
@ -922,8 +922,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -936,8 +936,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -950,8 +950,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -964,8 +964,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
@ -1029,8 +1029,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1043,8 +1043,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -1057,8 +1057,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1071,8 +1071,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
@ -1136,8 +1136,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1150,8 +1150,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -1164,8 +1164,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1178,8 +1178,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
@ -1243,8 +1243,8 @@ describe(SelectControl.name, () => {
expect(queryByTestId(option2)).toBeInTheDocument(); expect(queryByTestId(option2)).toBeInTheDocument();
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1257,8 +1257,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option1)).toHaveClass('text-gray-800'); // Not Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option1)); await userEvent.click(getByTestId(option1));
@ -1271,8 +1271,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option2)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
await act(async () => { await act(async () => {
await userEvent.click(getByTestId(option2)); await userEvent.click(getByTestId(option2));
@ -1285,8 +1285,8 @@ describe(SelectControl.name, () => {
await userEvent.click(input); await userEvent.click(input);
}); });
expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-900'); // Selected expect(getByTestId(option1)).toHaveClass('bg-blue-400/75', 'text-gray-800'); // Selected
expect(getByTestId(option2)).toHaveClass('text-gray-900'); // Not Selected expect(getByTestId(option2)).toHaveClass('text-gray-800'); // Not Selected
}); });
}); });
}); });

View File

@ -171,9 +171,10 @@ fields: [
The `editor` setting changes options for the editor view of a collection or a file inside a files collection. It has the following options: The `editor` setting changes options for the editor view of a collection or a file inside a files collection. It has the following options:
| Name | Type | Default | Description | | Name | Type | Default | Description |
| ------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------ | | ------- | ----------------------- | --------- | ------------------------------------------------------------------------------------------------------------ |
| preview | boolean | `true` | Set to `false` to disable the preview pane for this collection or file | | preview | boolean | `true` | Set to `false` to disable the preview pane for this collection or file |
| frame | boolean | `true` | <ul><li>`true` - Previews render in a frame</li><li>`false` - Previews render directly in your app</li></ul> | | frame | boolean | `true` | <ul><li>`true` - Previews render in a frame</li><li>`false` - Previews render directly in your app</li></ul> |
| size | 'compact'<br />\|'half' | `compact` | The size of the editor:<ul><li>`compact` - `450px`</li><li>`half` - `50%` of the screen width </li></ul> |
<CodeTabs> <CodeTabs>
```yaml ```yaml