If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React, { useCallback, useState } from 'react';
import Toolbar, { Item } from 'devextreme-react/toolbar';
import Button from 'devextreme-react/button';
import ButtonGroup, { ButtonGroupTypes } from 'devextreme-react/button-group';
import Resizable from 'devextreme-react/resizable';
import CheckBox from 'devextreme-react/check-box';
import DropDownButton, { DropDownButtonTypes } from 'devextreme-react/drop-down-button';
import SelectBox, { SelectBoxTypes } from 'devextreme-react/select-box';
import themes from 'devextreme/ui/themes';
import notify from 'devextreme/ui/notify';
import 'devextreme/ui/select_box';
import {
fontSizes,
lineHeights,
fontFamilies,
fontStyles,
headings,
textAlignItems,
textAlignItemsExtended,
listTypes,
fontInputAttr,
textStyleInputAttr,
} from './data.ts';
const stylingMode = !themes.current().startsWith('generic') ? 'text' : undefined;
const lineHeightDefault = lineHeights[1].lineHeight;
const textAlignDefault = [textAlignItems[0].alignment];
const fontSizeDefault = fontSizes[2].size;
const headingDefault = headings[0].text;
function onButtonClick(name: string) {
notify(`The "${name}" button has been clicked`);
}
function onSelectionChanged(name: string) {
notify(`The "${name}" value has been changed`);
}
function App() {
const [lineHeight, setLineHeight] = useState(lineHeightDefault);
const [textAlign, setTextAlign] = useState(textAlignDefault);
const [fontSize, setFontSize] = useState(fontSizeDefault);
const [heading, setHeading] = useState(headingDefault);
const [multiline, setMultiline] = useState(true);
const onFontFamilyClick = useCallback(() => {
notify('The "Font Family" value has been changed');
}, []);
const onUndoButtonClick = useCallback(() => {
onButtonClick('Undo');
}, []);
const onButtonGroupClick = useCallback((e: ButtonGroupTypes.ItemClickEvent) => {
onButtonClick(e.itemData.hint);
}, []);
const onRedoButtonClick = useCallback(() => {
onButtonClick('Redo');
}, []);
const onLinkButtonClick = useCallback(() => {
onButtonClick('Link');
}, []);
const onAddImageButtonClick = useCallback(() => {
onButtonClick('Add Image');
}, []);
const onClearButtonClick = useCallback(() => {
onButtonClick('Clear Formating');
}, []);
const onCodeBlockButtonClick = useCallback(() => {
onButtonClick('Code Block');
}, []);
const onQuoteButtonClick = useCallback(() => {
onButtonClick('Blockquote');
}, []);
const onAttachButtonClick = useCallback(() => {
onButtonClick('Attach');
}, []);
const onAboutButtonClick = useCallback(() => {
onButtonClick('Attach');
}, []);
const onHeadingClick = useCallback(
(e: SelectBoxTypes.ItemClickEvent) => {
setHeading(e.itemData.text);
notify('The "Heading" value has been changed');
},
[setHeading],
);
const onLineHeightChanged = useCallback(
(e: DropDownButtonTypes.SelectionChangedEvent) => {
setLineHeight(e.item.lineHeight);
onSelectionChanged('Line Height');
},
[setLineHeight],
);
const onFontSizeChange = useCallback(
(e: DropDownButtonTypes.SelectionChangedEvent) => {
setFontSize(e.item.size);
onSelectionChanged('Font Size');
},
[setFontSize],
);
const onTextAlignChanged = useCallback(
(e: ButtonGroupTypes.ItemClickEvent) => {
const { alignment, hint } = e.itemData;
setTextAlign([alignment]);
onButtonClick(hint);
},
[setTextAlign],
);
const onToolbarLineModeChanged = useCallback(
({ value }) => {
setMultiline(value);
},
[setMultiline],
);
const renderFontSize = useCallback(
(itemData) => (
<div style={{ fontSize: `${itemData.size}px` }}>{itemData.text}</div>
),
[],
);
const renderTextAlign = useCallback(
() => (
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={textAlignItems}
selectedItemKeys={textAlign}
onItemClick={onTextAlignChanged}
></ButtonGroup>
),
[textAlign, onTextAlignChanged],
);
const renderTextAlignMenu = useCallback(
() => (
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={textAlignItemsExtended}
selectedItemKeys={textAlign}
onItemClick={onTextAlignChanged}
></ButtonGroup>
),
[textAlign, onTextAlignChanged],
);
const renderMenuSeparator = useCallback(
() => <div className="toolbar-menu-separator"></div>,
[],
);
return (
<React.Fragment>
<div className="widget-container">
<Resizable
className="resizable-container"
minWidth={500}
minHeight={150}
maxHeight={370}
handles="right"
area=".widget-container"
>
<Toolbar multiline={multiline}>
<Item location="before">
<Button
icon="undo"
stylingMode={stylingMode}
onClick={onUndoButtonClick}
></Button>
</Item>
<Item location="before">
<Button
icon="redo"
stylingMode={stylingMode}
onClick={onRedoButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item location="before" locateInMenu="auto">
<DropDownButton
width="100%"
displayExpr="text"
keyExpr="size"
useSelectMode={true}
stylingMode={stylingMode}
items={fontSizes}
selectedItemKey={fontSize}
itemRender={renderFontSize}
onSelectionChanged={onFontSizeChange}
></DropDownButton>
</Item>
<Item location="before" locateInMenu="auto">
<DropDownButton
width="100%"
icon="indent"
displayExpr="text"
keyExpr="lineHeight"
useSelectMode={true}
stylingMode={stylingMode}
items={lineHeights}
selectedItemKey={lineHeight}
onSelectionChanged={onLineHeightChanged}
></DropDownButton>
</Item>
<Item location="before" locateInMenu="auto">
<SelectBox
placeholder="Font"
displayExpr="text"
inputAttr={fontInputAttr}
dataSource={fontFamilies}
onItemClick={onFontFamilyClick}
></SelectBox>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item location="before">
<ButtonGroup
keyExpr="icon"
stylingMode="outlined"
selectionMode="multiple"
items={fontStyles}
onItemClick={onButtonGroupClick}
></ButtonGroup>
</Item>
<Item location="before">
<div className="toolbar-separator"></div>
</Item>
<Item
widget="dxButtonGroup"
location="before"
locateInMenu="auto"
render={renderTextAlign}
menuItemRender={renderTextAlignMenu}
></Item>
<Item location="before">
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={listTypes}
onItemClick={onButtonGroupClick}
></ButtonGroup>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item location="before" locateInMenu="auto">
<SelectBox
displayExpr="text"
valueExpr="text"
inputAttr={textStyleInputAttr}
dataSource={headings}
defaultValue={heading}
onItemClick={onHeadingClick}
></SelectBox>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="link"
text="Link"
stylingMode={stylingMode}
onClick={onLinkButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="image"
text="Add image"
stylingMode={stylingMode}
onClick={onAddImageButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="clearformat"
text="Clear formating"
stylingMode={stylingMode}
onClick={onClearButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="codeblock"
text="Code block"
stylingMode={stylingMode}
onClick={onCodeBlockButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="blockquote"
text="Blockquote"
stylingMode={stylingMode}
onClick={onQuoteButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item location="after" showText="inMenu" widget="dxButton">
<Button
icon="attach"
text="Attach"
stylingMode={stylingMode}
onClick={onAttachButtonClick}
></Button>
</Item>
<Item locateInMenu="always" showText="inMenu" widget="dxButton">
<Button
icon="help"
text="About"
stylingMode={stylingMode}
onClick={onAboutButtonClick}
></Button>
</Item>
</Toolbar>
</Resizable>
</div>
<div className="options-container">
<div className="caption">Options</div>
<CheckBox
text="Multiline mode"
value={multiline}
onValueChanged={onToolbarLineModeChanged}
/>
</div>
</React.Fragment>
);
}
export default App;
xxxxxxxxxx
import React, { useCallback, useState } from 'react';
import Toolbar, { Item } from 'devextreme-react/toolbar';
import Button from 'devextreme-react/button';
import ButtonGroup from 'devextreme-react/button-group';
import Resizable from 'devextreme-react/resizable';
import CheckBox from 'devextreme-react/check-box';
import DropDownButton from 'devextreme-react/drop-down-button';
import SelectBox from 'devextreme-react/select-box';
import themes from 'devextreme/ui/themes';
import notify from 'devextreme/ui/notify';
import 'devextreme/ui/select_box';
import {
fontSizes,
lineHeights,
fontFamilies,
fontStyles,
headings,
textAlignItems,
textAlignItemsExtended,
listTypes,
fontInputAttr,
textStyleInputAttr,
} from './data.js';
const stylingMode = !themes.current().startsWith('generic') ? 'text' : undefined;
const lineHeightDefault = lineHeights[1].lineHeight;
const textAlignDefault = [textAlignItems[0].alignment];
const fontSizeDefault = fontSizes[2].size;
const headingDefault = headings[0].text;
function onButtonClick(name) {
notify(`The "${name}" button has been clicked`);
}
function onSelectionChanged(name) {
notify(`The "${name}" value has been changed`);
}
function App() {
const [lineHeight, setLineHeight] = useState(lineHeightDefault);
const [textAlign, setTextAlign] = useState(textAlignDefault);
const [fontSize, setFontSize] = useState(fontSizeDefault);
const [heading, setHeading] = useState(headingDefault);
const [multiline, setMultiline] = useState(true);
const onFontFamilyClick = useCallback(() => {
notify('The "Font Family" value has been changed');
}, []);
const onUndoButtonClick = useCallback(() => {
onButtonClick('Undo');
}, []);
const onButtonGroupClick = useCallback((e) => {
onButtonClick(e.itemData.hint);
}, []);
const onRedoButtonClick = useCallback(() => {
onButtonClick('Redo');
}, []);
const onLinkButtonClick = useCallback(() => {
onButtonClick('Link');
}, []);
const onAddImageButtonClick = useCallback(() => {
onButtonClick('Add Image');
}, []);
const onClearButtonClick = useCallback(() => {
onButtonClick('Clear Formating');
}, []);
const onCodeBlockButtonClick = useCallback(() => {
onButtonClick('Code Block');
}, []);
const onQuoteButtonClick = useCallback(() => {
onButtonClick('Blockquote');
}, []);
const onAttachButtonClick = useCallback(() => {
onButtonClick('Attach');
}, []);
const onAboutButtonClick = useCallback(() => {
onButtonClick('Attach');
}, []);
const onHeadingClick = useCallback(
(e) => {
setHeading(e.itemData.text);
notify('The "Heading" value has been changed');
},
[setHeading],
);
const onLineHeightChanged = useCallback(
(e) => {
setLineHeight(e.item.lineHeight);
onSelectionChanged('Line Height');
},
[setLineHeight],
);
const onFontSizeChange = useCallback(
(e) => {
setFontSize(e.item.size);
onSelectionChanged('Font Size');
},
[setFontSize],
);
const onTextAlignChanged = useCallback(
(e) => {
const { alignment, hint } = e.itemData;
setTextAlign([alignment]);
onButtonClick(hint);
},
[setTextAlign],
);
const onToolbarLineModeChanged = useCallback(
({ value }) => {
setMultiline(value);
},
[setMultiline],
);
const renderFontSize = useCallback(
(itemData) => <div style={{ fontSize: `${itemData.size}px` }}>{itemData.text}</div>,
[],
);
const renderTextAlign = useCallback(
() => (
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={textAlignItems}
selectedItemKeys={textAlign}
onItemClick={onTextAlignChanged}
></ButtonGroup>
),
[textAlign, onTextAlignChanged],
);
const renderTextAlignMenu = useCallback(
() => (
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={textAlignItemsExtended}
selectedItemKeys={textAlign}
onItemClick={onTextAlignChanged}
></ButtonGroup>
),
[textAlign, onTextAlignChanged],
);
const renderMenuSeparator = useCallback(() => <div className="toolbar-menu-separator"></div>, []);
return (
<React.Fragment>
<div className="widget-container">
<Resizable
className="resizable-container"
minWidth={500}
minHeight={150}
maxHeight={370}
handles="right"
area=".widget-container"
>
<Toolbar multiline={multiline}>
<Item location="before">
<Button
icon="undo"
stylingMode={stylingMode}
onClick={onUndoButtonClick}
></Button>
</Item>
<Item location="before">
<Button
icon="redo"
stylingMode={stylingMode}
onClick={onRedoButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
>
<DropDownButton
width="100%"
displayExpr="text"
keyExpr="size"
useSelectMode={true}
stylingMode={stylingMode}
items={fontSizes}
selectedItemKey={fontSize}
itemRender={renderFontSize}
onSelectionChanged={onFontSizeChange}
></DropDownButton>
</Item>
<Item
location="before"
locateInMenu="auto"
>
<DropDownButton
width="100%"
icon="indent"
displayExpr="text"
keyExpr="lineHeight"
useSelectMode={true}
stylingMode={stylingMode}
items={lineHeights}
selectedItemKey={lineHeight}
onSelectionChanged={onLineHeightChanged}
></DropDownButton>
</Item>
<Item
location="before"
locateInMenu="auto"
>
<SelectBox
placeholder="Font"
displayExpr="text"
inputAttr={fontInputAttr}
dataSource={fontFamilies}
onItemClick={onFontFamilyClick}
></SelectBox>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item location="before">
<ButtonGroup
keyExpr="icon"
stylingMode="outlined"
selectionMode="multiple"
items={fontStyles}
onItemClick={onButtonGroupClick}
></ButtonGroup>
</Item>
<Item location="before">
<div className="toolbar-separator"></div>
</Item>
<Item
widget="dxButtonGroup"
location="before"
locateInMenu="auto"
render={renderTextAlign}
menuItemRender={renderTextAlignMenu}
></Item>
<Item location="before">
<ButtonGroup
keyExpr="alignment"
stylingMode="outlined"
items={listTypes}
onItemClick={onButtonGroupClick}
></ButtonGroup>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
>
<SelectBox
displayExpr="text"
valueExpr="text"
inputAttr={textStyleInputAttr}
dataSource={headings}
defaultValue={heading}
onItemClick={onHeadingClick}
></SelectBox>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="link"
text="Link"
stylingMode={stylingMode}
onClick={onLinkButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="image"
text="Add image"
stylingMode={stylingMode}
onClick={onAddImageButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="clearformat"
text="Clear formating"
stylingMode={stylingMode}
onClick={onClearButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="codeblock"
text="Code block"
stylingMode={stylingMode}
onClick={onCodeBlockButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
showText="inMenu"
widget="dxButton"
>
<Button
icon="blockquote"
text="Blockquote"
stylingMode={stylingMode}
onClick={onQuoteButtonClick}
></Button>
</Item>
<Item
location="before"
locateInMenu="auto"
menuItemRender={renderMenuSeparator}
>
<div className="toolbar-separator"></div>
</Item>
<Item
location="after"
showText="inMenu"
widget="dxButton"
>
<Button
icon="attach"
text="Attach"
stylingMode={stylingMode}
onClick={onAttachButtonClick}
></Button>
</Item>
<Item
locateInMenu="always"
showText="inMenu"
widget="dxButton"
>
<Button
icon="help"
text="About"
stylingMode={stylingMode}
onClick={onAboutButtonClick}
></Button>
</Item>
</Toolbar>
</Resizable>
</div>
<div className="options-container">
<div className="caption">Options</div>
<CheckBox
text="Multiline mode"
value={multiline}
onValueChanged={onToolbarLineModeChanged}
/>
</div>
</React.Fragment>
);
}
export default App;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
xxxxxxxxxx
export const fontSizes = [
{ size: 10, text: '10px' },
{ size: 12, text: '12px' },
{ size: 14, text: '14px' },
{ size: 16, text: '16px' },
{ size: 18, text: '18px' },
];
export const lineHeights = [
{ lineHeight: 1, text: '1' },
{ lineHeight: 1.35, text: '1.35' },
{ lineHeight: 1.5, text: '1.5' },
{ lineHeight: 2, text: '2' },
];
export const fontFamilies = [
{ text: 'Arial' },
{ text: 'Courier New' },
{ text: 'Georgia' },
{ text: 'Impact' },
{ text: 'Lucida Console' },
{ text: 'Tahoma' },
{ text: 'Times New Roman' },
];
export const headings = [
{ text: 'Normal text' },
{ text: 'Heading 1' },
{ text: 'Heading 2' },
{ text: 'Heading 3' },
{ text: 'Heading 4' },
{ text: 'Heading 5' },
];
export const fontStyles = [
{
icon: 'bold',
hint: 'Bold',
},
{
icon: 'italic',
hint: 'Italic',
},
{
icon: 'underline',
hint: 'Underlined',
},
{
icon: 'strike',
hint: 'Strikethrough',
},
];
export const textAlignItemsExtended = [
{
icon: 'alignleft',
alignment: 'left',
hint: 'Align Left',
text: 'Align left',
},
{
icon: 'aligncenter',
alignment: 'center',
hint: 'Center',
text: 'Center',
},
{
icon: 'alignright',
alignment: 'right',
hint: 'Align Right',
text: 'Align right',
},
{
icon: 'alignjustify',
alignment: 'justify',
hint: 'Justify',
text: 'Justify',
},
];
export const textAlignItems = textAlignItemsExtended.map((item) => {
const { icon, alignment, hint } = item;
return {
icon,
alignment,
hint,
};
});
export const listTypes = [
{
icon: 'orderedlist',
alignment: 'orderedlist',
hint: 'Ordered',
},
{
icon: 'bulletlist',
alignment: 'bulletlist',
hint: 'Bullet',
},
];
export const fontInputAttr = { 'aria-label': 'Font' };
export const textStyleInputAttr = { 'aria-label': 'Text Style' };
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@24.2.5/cjs',
'devextreme-react': 'npm:devextreme-react@24.2.5/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
export const fontSizes = [
{ size: 10, text: '10px' },
{ size: 12, text: '12px' },
{ size: 14, text: '14px' },
{ size: 16, text: '16px' },
{ size: 18, text: '18px' },
];
export const lineHeights = [
{ lineHeight: 1, text: '1' },
{ lineHeight: 1.35, text: '1.35' },
{ lineHeight: 1.5, text: '1.5' },
{ lineHeight: 2, text: '2' },
];
export const fontFamilies = [
{ text: 'Arial' },
{ text: 'Courier New' },
{ text: 'Georgia' },
{ text: 'Impact' },
{ text: 'Lucida Console' },
{ text: 'Tahoma' },
{ text: 'Times New Roman' },
];
export const headings = [
{ text: 'Normal text' },
{ text: 'Heading 1' },
{ text: 'Heading 2' },
{ text: 'Heading 3' },
{ text: 'Heading 4' },
{ text: 'Heading 5' },
];
export const fontStyles = [
{
icon: 'bold',
hint: 'Bold',
},
{
icon: 'italic',
hint: 'Italic',
},
{
icon: 'underline',
hint: 'Underlined',
},
{
icon: 'strike',
hint: 'Strikethrough',
},
];
export const textAlignItemsExtended = [
{
icon: 'alignleft',
alignment: 'left',
hint: 'Align Left',
text: 'Align left',
},
{
icon: 'aligncenter',
alignment: 'center',
hint: 'Center',
text: 'Center',
},
{
icon: 'alignright',
alignment: 'right',
hint: 'Align Right',
text: 'Align right',
},
{
icon: 'alignjustify',
alignment: 'justify',
hint: 'Justify',
text: 'Justify',
},
];
export const textAlignItems = textAlignItemsExtended.map((item) => {
const { icon, alignment, hint } = item;
return {
icon,
alignment,
hint,
};
});
export const listTypes = [
{
icon: 'orderedlist',
alignment: 'orderedlist',
hint: 'Ordered',
},
{
icon: 'bulletlist',
alignment: 'bulletlist',
hint: 'Bullet',
},
];
export const fontInputAttr = { 'aria-label': 'Font' };
export const textStyleInputAttr = { 'aria-label': 'Text Style' };
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
.dx-resizable-handle::after {
content: "";
position: absolute;
width: 9px;
height: 36px;
border: none;
border-radius: 50px;
background-color: #fff;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.24);
}
.dx-resizable-handle-right::after {
top: 50%;
right: -5px;
transform: translateY(-50%);
}
.dx-toolbar.dx-toolbar-multiline .dx-toolbar-item {
margin-bottom: 5px;
}
.widget-container {
margin-right: 10px;
}
.resizable-container {
padding: 10px;
height: 300px;
border: 1px dotted #999;
border-radius: 4px;
box-sizing: border-box;
}
.options-container {
margin-top: 20px;
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
position: relative;
}
.caption {
font-size: 18px;
font-weight: 500;
margin-bottom: 10px;
}
.toolbar-separator {
height: 36px;
margin: 0 5px;
border-left: 1px solid #ddd;
}
.toolbar-menu-separator {
height: 1px;
border-bottom: 1px solid #ddd;
}
In this demo, you can drag our Toolbar container's resizing handle to visualize resize operations and view our rendering implementation on different screens. When used in single-line mode (default), our Toolbar does not wrap content and displays an overflow menu for items that do not fit within the container. Use the locateInMenu property to control whether items appear in the overflow menu.
If Toolbar width exceeds container width (and if you enable the component’s multiline property), our Toolbar wraps content across multiple lines.