kopia lustrzana https://github.com/wagtail/wagtail
Implement block previews in StreamField block chooser
rodzic
efc73a649d
commit
d25a67a4b8
client
scss
src
components
ComboBox
ComboBoxPreview
StreamField/blocks
__snapshots__
wagtail/admin/templatetags
|
@ -56,6 +56,7 @@ module.exports = {
|
|||
'none',
|
||||
'unset',
|
||||
'transparent',
|
||||
'normal',
|
||||
// System colors for forced-colors styling.
|
||||
// See https://drafts.csswg.org/css-color-4/#css-system-colors.
|
||||
'Canvas',
|
||||
|
|
|
@ -80,6 +80,7 @@ These are classes for components.
|
|||
@import '../src/components/LoadingSpinner/LoadingSpinner';
|
||||
@import '../src/components/PublicationStatus/PublicationStatus';
|
||||
@import '../src/components/ComboBox/ComboBox';
|
||||
@import '../src/components/ComboBoxPreview/ComboBoxPreview';
|
||||
@import '../src/components/PageExplorer/PageExplorer';
|
||||
@import '../src/components/CommentApp/main';
|
||||
|
||||
|
|
|
@ -3,15 +3,21 @@
|
|||
$spacing: theme('spacing.[2.5]');
|
||||
$spacing-sm: theme('spacing.5');
|
||||
|
||||
.w-combobox {
|
||||
width: min(400px, 80vw);
|
||||
.w-combobox-container {
|
||||
@include dark-theme() {
|
||||
background-color: theme('colors.surface-tooltip');
|
||||
}
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
@include media-breakpoint-up(sm) {
|
||||
grid-template-columns: min(400px, 80vw) 1fr;
|
||||
}
|
||||
|
||||
min-height: min(320px, 70vh);
|
||||
background: theme('colors.surface-page');
|
||||
color: theme('colors.text-context');
|
||||
border-radius: theme('borderRadius.DEFAULT');
|
||||
font-size: theme('fontSize.18');
|
||||
box-shadow: theme('boxShadow.md');
|
||||
outline: 10px solid transparent;
|
||||
}
|
||||
|
@ -19,6 +25,7 @@ $spacing-sm: theme('spacing.5');
|
|||
.w-combobox__field {
|
||||
padding: $spacing;
|
||||
padding-bottom: 0;
|
||||
font-size: theme('fontSize.18');
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: $spacing-sm;
|
||||
|
@ -48,7 +55,7 @@ $spacing-sm: theme('spacing.5');
|
|||
padding-top: 0;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
width: 400px;
|
||||
width: 100%;
|
||||
padding: $spacing-sm;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import { useCombobox, UseComboboxStateChange } from 'downshift';
|
||||
|
||||
import { gettext } from '../../utils/gettext';
|
||||
import ComboBoxPreview from '../ComboBoxPreview/ComboBoxPreview';
|
||||
import Icon from '../Icon/Icon';
|
||||
|
||||
import findMatches from './findMatches';
|
||||
|
@ -21,6 +22,7 @@ export interface ComboBoxItem {
|
|||
label?: string | null;
|
||||
description?: string | null;
|
||||
icon?: string | JSX.Element | null;
|
||||
blockDefId?: string;
|
||||
category?: string;
|
||||
render?: (props: { option: ComboBoxItem }) => JSX.Element | string;
|
||||
}
|
||||
|
@ -84,6 +86,7 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
getMenuProps,
|
||||
getInputProps,
|
||||
getItemProps,
|
||||
highlightedIndex,
|
||||
setHighlightedIndex,
|
||||
setInputValue,
|
||||
openMenu,
|
||||
|
@ -151,6 +154,9 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
},
|
||||
});
|
||||
|
||||
const [lastHighlightedIndex, setLastHighlightedIndex] =
|
||||
useState(highlightedIndex);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputValue) {
|
||||
openMenu();
|
||||
|
@ -170,96 +176,111 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
|
|||
}
|
||||
}, [inputValue]);
|
||||
|
||||
if (
|
||||
inputItems[highlightedIndex] &&
|
||||
highlightedIndex !== lastHighlightedIndex
|
||||
) {
|
||||
setLastHighlightedIndex(highlightedIndex);
|
||||
}
|
||||
|
||||
const selectedBlock =
|
||||
inputItems[highlightedIndex] || inputItems[lastHighlightedIndex];
|
||||
|
||||
return (
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
<div className="w-combobox-container">
|
||||
<div className="w-combobox">
|
||||
{/* downshift does the label-field association itself. */}
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label {...getLabelProps()} className="w-sr-only">
|
||||
{label}
|
||||
</label>
|
||||
<div className="w-combobox__field">
|
||||
<input
|
||||
{...getInputProps()}
|
||||
type="text"
|
||||
// Prevent the field from receiving focus if it’s not visible.
|
||||
disabled={inlineCombobox}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</div>
|
||||
{noResults ? (
|
||||
<div className="w-combobox__status">{noResultsText}</div>
|
||||
) : null}
|
||||
<div {...getMenuProps()} className="w-combobox__menu">
|
||||
{categories.map((category) => {
|
||||
const categoryItems = (category.items || []).filter((item) =>
|
||||
inputItems.find((i) => i.type === item.type),
|
||||
);
|
||||
const itemColumns = Math.ceil(categoryItems.length / 2);
|
||||
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (categoryItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
if (Array.isArray(item.icon)) {
|
||||
icon = (
|
||||
<Icon name="custom" viewBox="0 0 1024 1024">
|
||||
{item.icon.map((pathData: string) => (
|
||||
<path key={pathData} d={pathData} />
|
||||
))}
|
||||
</Icon>
|
||||
);
|
||||
} else {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className={`w-combobox__option w-combobox__option--col${itemColumn}`}
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? <span>{itemLabel}</span> : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
return (
|
||||
<div className="w-combobox__optgroup" key={category.type}>
|
||||
{category.label ? (
|
||||
<div className="w-combobox__optgroup-label">
|
||||
{category.label}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
) : null}
|
||||
{categoryItems.map((item, index) => {
|
||||
const itemLabel = getItemLabel(item.type, item);
|
||||
const description = getItemDescription(item);
|
||||
const itemIndex = inputItems.findIndex(
|
||||
(i) => i.type === item.type,
|
||||
);
|
||||
const itemColumn = index + 1 <= itemColumns ? 1 : 2;
|
||||
const hasIcon =
|
||||
typeof item.icon !== 'undefined' && item.icon !== null;
|
||||
let icon: JSX.Element | null | undefined = null;
|
||||
|
||||
if (hasIcon) {
|
||||
if (Array.isArray(item.icon)) {
|
||||
icon = (
|
||||
<Icon name="custom" viewBox="0 0 1024 1024">
|
||||
{item.icon.map((pathData: string) => (
|
||||
<path key={pathData} d={pathData} />
|
||||
))}
|
||||
</Icon>
|
||||
);
|
||||
} else {
|
||||
icon =
|
||||
typeof item.icon === 'string' ? (
|
||||
<Icon name={item.icon} />
|
||||
) : (
|
||||
item.icon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.type}
|
||||
{...getItemProps({ item, index: itemIndex })}
|
||||
className={`w-combobox__option w-combobox__option--col${itemColumn}`}
|
||||
>
|
||||
<div className="w-combobox__option-icon">
|
||||
{icon}
|
||||
{/* Support for rich text options using text as an icon (for example "B" for bold). */}
|
||||
{itemLabel && !hasIcon ? (
|
||||
<span>{itemLabel}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="w-combobox__option-text">
|
||||
{item.render
|
||||
? item.render({ option: item })
|
||||
: description}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{selectedBlock ? <ComboBoxPreview item={selectedBlock} /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,182 +2,186 @@
|
|||
|
||||
exports[`ComboBox rendering matches the snapshot 1`] = `
|
||||
<div
|
||||
className="w-combobox"
|
||||
className="w-combobox-container"
|
||||
>
|
||||
<label
|
||||
className="w-sr-only"
|
||||
htmlFor="downshift-1-input"
|
||||
id="downshift-1-label"
|
||||
>
|
||||
Search options…
|
||||
</label>
|
||||
<div
|
||||
className="w-combobox__field"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant=""
|
||||
aria-autocomplete="list"
|
||||
aria-controls="downshift-1-menu"
|
||||
aria-expanded={false}
|
||||
aria-labelledby="downshift-1-label"
|
||||
autoComplete="off"
|
||||
disabled={false}
|
||||
id="downshift-1-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Search options…"
|
||||
role="combobox"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-labelledby="downshift-1-label"
|
||||
className="w-combobox__menu"
|
||||
id="downshift-1-menu"
|
||||
onMouseLeave={[Function]}
|
||||
role="listbox"
|
||||
className="w-combobox"
|
||||
>
|
||||
<label
|
||||
className="w-sr-only"
|
||||
htmlFor="downshift-1-input"
|
||||
id="downshift-1-label"
|
||||
>
|
||||
Search options…
|
||||
</label>
|
||||
<div
|
||||
className="w-combobox__optgroup"
|
||||
key="blockTypes"
|
||||
className="w-combobox__field"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant=""
|
||||
aria-autocomplete="list"
|
||||
aria-controls="downshift-1-menu"
|
||||
aria-expanded={false}
|
||||
aria-labelledby="downshift-1-label"
|
||||
autoComplete="off"
|
||||
disabled={false}
|
||||
id="downshift-1-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Search options…"
|
||||
role="combobox"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-labelledby="downshift-1-label"
|
||||
className="w-combobox__menu"
|
||||
id="downshift-1-menu"
|
||||
onMouseLeave={[Function]}
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__optgroup-label"
|
||||
>
|
||||
Blocks
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-0"
|
||||
key="blockquote"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
className="w-combobox__optgroup"
|
||||
key="blockTypes"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
className="w-combobox__optgroup-label"
|
||||
>
|
||||
<Icon
|
||||
name="blockquote"
|
||||
/>
|
||||
Blocks
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-0"
|
||||
key="blockquote"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
Blockquote
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-1"
|
||||
key="paragraph"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span
|
||||
className="my-icon"
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
P
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Paragraph
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-2"
|
||||
key="heading-one"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="custom"
|
||||
viewBox="0 0 1024 1024"
|
||||
>
|
||||
<path
|
||||
d="M 83.625 "
|
||||
key="M 83.625 "
|
||||
<Icon
|
||||
name="blockquote"
|
||||
/>
|
||||
<path
|
||||
d="L 232.535156 "
|
||||
key="L 232.535156 "
|
||||
/>
|
||||
</Icon>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Heading 1
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col2"
|
||||
id="downshift-1-item-3"
|
||||
key="heading-two"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
<span
|
||||
className="custom-text"
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col2"
|
||||
id="downshift-1-item-4"
|
||||
key="link"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
🔗
|
||||
</span>
|
||||
Blockquote
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-1"
|
||||
key="paragraph"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
Link
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span
|
||||
className="my-icon"
|
||||
>
|
||||
P
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Paragraph
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col1"
|
||||
id="downshift-1-item-2"
|
||||
key="heading-one"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<Icon
|
||||
name="custom"
|
||||
viewBox="0 0 1024 1024"
|
||||
>
|
||||
<path
|
||||
d="M 83.625 "
|
||||
key="M 83.625 "
|
||||
/>
|
||||
<path
|
||||
d="L 232.535156 "
|
||||
key="L 232.535156 "
|
||||
/>
|
||||
</Icon>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Heading 1
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col2"
|
||||
id="downshift-1-item-3"
|
||||
key="heading-two"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
<span
|
||||
className="custom-text"
|
||||
>
|
||||
H2
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-selected="false"
|
||||
className="w-combobox__option w-combobox__option--col2"
|
||||
id="downshift-1-item-4"
|
||||
key="link"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseMove={[Function]}
|
||||
role="option"
|
||||
>
|
||||
<div
|
||||
className="w-combobox__option-icon"
|
||||
>
|
||||
<span>
|
||||
🔗
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-combobox__option-text"
|
||||
>
|
||||
Link
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
.w-combobox-preview {
|
||||
padding: theme('spacing.5');
|
||||
display: grid;
|
||||
grid-template-rows: 6fr 4fr;
|
||||
gap: theme('spacing.5');
|
||||
background-color: theme('colors.surface-header');
|
||||
border-block-start: 1px solid theme('colors.border-furniture');
|
||||
border-end-end-radius: inherit;
|
||||
border-end-start-radius: inherit;
|
||||
@include media-breakpoint-up(sm) {
|
||||
border-block-start: 0;
|
||||
border-start-end-radius: inherit;
|
||||
border-end-start-radius: 0;
|
||||
border-inline-start: 1px solid theme('colors.border-furniture');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid theme('colors.border-furniture');
|
||||
border-radius: theme('borderRadius.sm');
|
||||
|
||||
// Ensure iframe is always opaque
|
||||
color-scheme: normal;
|
||||
background-color: Canvas;
|
||||
|
||||
@include more-contrast() {
|
||||
border-color: theme('colors.border-furniture-more-contrast');
|
||||
}
|
||||
}
|
||||
|
||||
.w-combobox-preview__label {
|
||||
@apply w-label-1;
|
||||
}
|
||||
|
||||
.w-combobox-preview__description {
|
||||
@apply w-help-text;
|
||||
margin-top: theme('spacing.3');
|
||||
margin-bottom: 0;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
import { WAGTAIL_CONFIG } from '../../config/wagtailConfig';
|
||||
|
||||
interface ComboBoxItem {
|
||||
label?: string | null;
|
||||
description?: string | null;
|
||||
// icon?: string | JSX.Element | null;
|
||||
blockDefId?: string;
|
||||
}
|
||||
|
||||
export interface ComboBoxPreviewProps {
|
||||
item: ComboBoxItem;
|
||||
}
|
||||
|
||||
export default function ComboBoxPreview({
|
||||
item: { label, description, blockDefId },
|
||||
}: ComboBoxPreviewProps) {
|
||||
const previewURL = blockDefId
|
||||
? new URL(WAGTAIL_CONFIG.ADMIN_URLS.BLOCK_PREVIEW, window.location.href)
|
||||
: undefined;
|
||||
previewURL?.searchParams.append('id', blockDefId || '');
|
||||
return (
|
||||
<div className="w-combobox-preview">
|
||||
<iframe
|
||||
className="w-combobox-preview__iframe"
|
||||
title="Preview"
|
||||
src={previewURL?.toString()}
|
||||
/>
|
||||
<div className="w-combobox-preview__label">{label}</div>
|
||||
{description ? (
|
||||
<p className="w-combobox-preview__description">{description}</p>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -104,6 +104,7 @@ class StreamBlockMenu extends BaseInsertionControl {
|
|||
content: this.combobox,
|
||||
trigger: 'click',
|
||||
interactive: true,
|
||||
maxWidth: 'none',
|
||||
theme: 'dropdown',
|
||||
arrow: false,
|
||||
placement: 'bottom',
|
||||
|
@ -120,7 +121,9 @@ class StreamBlockMenu extends BaseInsertionControl {
|
|||
const groupItems = blockDefs.map((blockDef) => ({
|
||||
type: blockDef.name,
|
||||
label: blockDef.meta.label,
|
||||
description: blockDef.meta.description,
|
||||
icon: blockDef.meta.icon,
|
||||
blockDefId: blockDef.meta.blockDefId,
|
||||
}));
|
||||
|
||||
return {
|
||||
|
|
|
@ -751,7 +751,7 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
|
|||
<button type="button" title="Insert a block" class="c-sf-add-button" aria-expanded="true">
|
||||
<svg class="icon icon-plus" aria-hidden="true"><use href="#icon-plus"></use></svg>
|
||||
</button>
|
||||
<div data-tippy-root="" id="tippy-5" style="z-index: 9999; visibility: visible; transition: none; position: absolute; left: 0px; top: 0px; margin: 0px;"><div class="tippy-box" data-state="hidden" tabindex="-1" data-theme="dropdown" data-animation="fade" style="max-width: 350px; transition-duration: 0ms;" role="tooltip"><div class="tippy-content" data-state="hidden" style="transition-duration: 0ms;"><div><div class="w-combobox"><label id="downshift-0-label" for="downshift-0-input" class="w-sr-only">Search options…</label><div class="w-combobox__field"><input aria-activedescendant="" aria-autocomplete="list" aria-controls="downshift-0-menu" aria-expanded="false" aria-labelledby="downshift-0-label" autocomplete="off" id="downshift-0-input" role="combobox" type="text" placeholder="Search options…" value=""></div><div id="downshift-0-menu" role="listbox" aria-labelledby="downshift-0-label" class="w-combobox__menu"><div class="w-combobox__optgroup"><div role="option" aria-selected="false" id="downshift-0-item-0" class="w-combobox__option w-combobox__option--col1"><div class="w-combobox__option-icon"><svg class="icon icon-placeholder" aria-hidden="true"><use href="#icon-placeholder"></use></svg></div><div class="w-combobox__option-text">Test Block A</div></div><div role="option" aria-selected="false" id="downshift-0-item-1" class="w-combobox__option w-combobox__option--col2"><div class="w-combobox__option-icon"><svg class="icon icon-pilcrow" aria-hidden="true"><use href="#icon-pilcrow"></use></svg></div><div class="w-combobox__option-text">Test Block B</div></div></div></div></div></div></div></div></div></div><div data-streamfield-child="" data-contentpath="2">
|
||||
<div data-tippy-root="" id="tippy-5" style="z-index: 9999; visibility: visible; transition: none; position: absolute; left: 0px; top: 0px; margin: 0px;"><div class="tippy-box" data-state="hidden" tabindex="-1" data-theme="dropdown" data-animation="fade" style="max-width: none; transition-duration: 0ms;" role="tooltip"><div class="tippy-content" data-state="hidden" style="transition-duration: 0ms;"><div><div class="w-combobox-container"><div class="w-combobox"><label id="downshift-0-label" for="downshift-0-input" class="w-sr-only">Search options…</label><div class="w-combobox__field"><input aria-activedescendant="" aria-autocomplete="list" aria-controls="downshift-0-menu" aria-expanded="false" aria-labelledby="downshift-0-label" autocomplete="off" id="downshift-0-input" role="combobox" type="text" placeholder="Search options…" value=""></div><div id="downshift-0-menu" role="listbox" aria-labelledby="downshift-0-label" class="w-combobox__menu"><div class="w-combobox__optgroup"><div role="option" aria-selected="false" id="downshift-0-item-0" class="w-combobox__option w-combobox__option--col1"><div class="w-combobox__option-icon"><svg class="icon icon-placeholder" aria-hidden="true"><use href="#icon-placeholder"></use></svg></div><div class="w-combobox__option-text">Test Block A</div></div><div role="option" aria-selected="false" id="downshift-0-item-1" class="w-combobox__option w-combobox__option--col2"><div class="w-combobox__option-icon"><svg class="icon icon-pilcrow" aria-hidden="true"><use href="#icon-pilcrow"></use></svg></div><div class="w-combobox__option-text">Test Block B</div></div></div></div></div></div></div></div></div></div></div><div data-streamfield-child="" data-contentpath="2">
|
||||
<input type="hidden" name="the-prefix-1-deleted" value="">
|
||||
<input type="hidden" name="the-prefix-1-order" value="1">
|
||||
<input type="hidden" name="the-prefix-1-type" value="test_block_b">
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface WagtailConfig {
|
|||
ADMIN_URLS: {
|
||||
DISMISSIBLES: string;
|
||||
PAGES: string;
|
||||
BLOCK_PREVIEW: string;
|
||||
};
|
||||
CSRF_HEADER_NAME: string;
|
||||
CSRF_TOKEN: string;
|
||||
|
|
|
@ -983,6 +983,7 @@ def wagtail_config(context):
|
|||
"ADMIN_URLS": {
|
||||
"DISMISSIBLES": reverse("wagtailadmin_dismissibles"),
|
||||
"PAGES": reverse("wagtailadmin_explore_root"),
|
||||
"BLOCK_PREVIEW": reverse("wagtailadmin_block_preview"),
|
||||
},
|
||||
"I18N_ENABLED": i18n_enabled(),
|
||||
"LOCALES": locales(serialize=False),
|
||||
|
|
Ładowanie…
Reference in New Issue