Rich Text (Draftail) - Ensure SVG paths are correctly handled for custom features

Ensure the documented support for providing an array of SVG paths to the 'icon' attribute when using `register_rich_text_features` is correctly supported.

Fixes 
Fixes 
Fixes 

See https://docs.wagtail.org/en/stable/extending/extending_draftail.html#creating-new-blocks
> It can also be an array of strings, to use SVG paths, or SVG symbol references for example 'icon': ['M100 100 H 900 V 900 H 100 Z'],. The paths need to be set for a 1024x1024 viewbox.
pull/12475/head
Joel William 2024-10-16 19:40:06 +05:30 zatwierdzone przez LB (Ben Johnston)
rodzic c611dd4056
commit 4a933df9fb
3 zmienionych plików z 225 dodań i 8 usunięć
client/src/components/ComboBox

Wyświetl plik

@ -40,12 +40,13 @@ describe('ComboBox', () => {
{
type: 'paragraph',
description: 'Paragraph',
icon: <span className="custom-icon">P</span>,
icon: <span className="my-icon">P</span>,
},
{
type: 'heading-one',
label: 'H1',
description: 'Heading 1',
icon: ['M 83.625 ', 'L 232.535156 '],
},
{
type: 'heading-two',
@ -70,6 +71,10 @@ describe('ComboBox', () => {
wrapper = shallow(<ComboBox {...testProps} items={items} />);
});
it('matches the snapshot', () => {
expect(wrapper).toMatchSnapshot();
});
it('shows items', () => {
const options = wrapper.find('.w-combobox__option-text');
expect(options).toHaveLength(
@ -82,8 +87,24 @@ describe('ComboBox', () => {
expect(wrapper.find(Icon).at(0).prop('name')).toBe('blockquote');
});
it('supports custom icons', () => {
expect(wrapper.find('.custom-icon').text()).toBe('P');
it('supports custom icons (as provided React component)', () => {
const paragraphOption = wrapper.findWhere(
(el) => el.key() === 'paragraph',
);
const icon = paragraphOption.find('.w-combobox__option-icon').render();
expect(icon.find('.my-icon')).toHaveLength(1);
expect(icon.text()).toBe('P');
});
it('supports custom icons (as provided path)', () => {
const paragraphOption = wrapper.findWhere(
(el) => el.key() === 'heading-one',
);
const icon = paragraphOption.find('.w-combobox__option-icon').render();
expect(icon.find('svg').hasClass('icon-custom')).toBe(true);
expect(icon.find('.icon-custom').html()).toContain('M 83.625');
});
it('supports label as icon', () => {

Wyświetl plik

@ -217,12 +217,22 @@ export default function ComboBox<ComboBoxOption extends ComboBoxItem>({
let icon: JSX.Element | null | undefined = null;
if (hasIcon) {
icon =
typeof item.icon === 'string' ? (
<Icon name={item.icon} />
) : (
item.icon
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 (

Wyświetl plik

@ -0,0 +1,186 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ComboBox rendering matches the snapshot 1`] = `
<div
className="w-combobox"
>
<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"
>
<div
className="w-combobox__optgroup"
key="blockTypes"
>
<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"
>
<div
className="w-combobox__option-icon"
>
<Icon
name="blockquote"
/>
</div>
<div
className="w-combobox__option-text"
>
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"
>
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>
</div>
`;