@elementor/editor-components 4.0.0-666 → 4.0.0-668

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/index.js +191 -3870
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +184 -3904
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +23 -23
  6. package/src/init.ts +0 -13
  7. package/src/extended/components/component-introduction.tsx +0 -77
  8. package/src/extended/components/component-panel-header/component-badge.tsx +0 -73
  9. package/src/extended/components/component-panel-header/component-panel-header.tsx +0 -98
  10. package/src/extended/components/component-properties-panel/component-properties-panel-content.tsx +0 -176
  11. package/src/extended/components/component-properties-panel/component-properties-panel.tsx +0 -43
  12. package/src/extended/components/component-properties-panel/properties-empty-state.tsx +0 -51
  13. package/src/extended/components/component-properties-panel/properties-group.tsx +0 -196
  14. package/src/extended/components/component-properties-panel/property-item.tsx +0 -124
  15. package/src/extended/components/component-properties-panel/sortable.tsx +0 -92
  16. package/src/extended/components/component-properties-panel/use-current-editable-item.ts +0 -73
  17. package/src/extended/components/component-properties-panel/utils/generate-unique-label.ts +0 -21
  18. package/src/extended/components/component-properties-panel/utils/validate-group-label.ts +0 -24
  19. package/src/extended/components/components-tab/component-item.tsx +0 -180
  20. package/src/extended/components/components-tab/components.tsx +0 -58
  21. package/src/extended/components/components-tab/delete-confirmation-dialog.tsx +0 -26
  22. package/src/extended/components/create-component-form/create-component-form.tsx +0 -281
  23. package/src/extended/components/create-component-form/hooks/use-form.ts +0 -72
  24. package/src/extended/components/create-component-form/utils/get-component-event-data.ts +0 -54
  25. package/src/extended/components/edit-component/component-modal.tsx +0 -133
  26. package/src/extended/components/edit-component/edit-component.tsx +0 -166
  27. package/src/extended/components/edit-component/use-canvas-document.ts +0 -9
  28. package/src/extended/components/edit-component/use-element-rect.ts +0 -81
  29. package/src/extended/components/instance-editing-panel/instance-editing-panel.tsx +0 -60
  30. package/src/extended/components/overridable-props/indicator.tsx +0 -83
  31. package/src/extended/components/overridable-props/overridable-prop-control.tsx +0 -127
  32. package/src/extended/components/overridable-props/overridable-prop-form.tsx +0 -135
  33. package/src/extended/components/overridable-props/overridable-prop-indicator.tsx +0 -138
  34. package/src/extended/components/overridable-props/utils/validate-prop-label.ts +0 -38
  35. package/src/extended/consts.ts +0 -3
  36. package/src/extended/hooks/use-navigate-back.ts +0 -24
  37. package/src/extended/init.ts +0 -108
  38. package/src/extended/mcp/index.ts +0 -14
  39. package/src/extended/mcp/save-as-component-tool.ts +0 -436
  40. package/src/extended/shortcuts/create-component-shortcut.ts +0 -121
  41. package/src/extended/store/actions/add-overridable-group.ts +0 -53
  42. package/src/extended/store/actions/archive-component.ts +0 -18
  43. package/src/extended/store/actions/create-unpublished-component.ts +0 -99
  44. package/src/extended/store/actions/delete-overridable-group.ts +0 -32
  45. package/src/extended/store/actions/delete-overridable-prop.ts +0 -64
  46. package/src/extended/store/actions/rename-component.ts +0 -48
  47. package/src/extended/store/actions/rename-overridable-group.ts +0 -33
  48. package/src/extended/store/actions/reorder-group-props.ts +0 -37
  49. package/src/extended/store/actions/reorder-overridable-groups.ts +0 -24
  50. package/src/extended/store/actions/reset-sanitized-components.ts +0 -5
  51. package/src/extended/store/actions/set-overridable-prop.ts +0 -109
  52. package/src/extended/store/actions/update-component-sanitized-attribute.ts +0 -7
  53. package/src/extended/store/actions/update-current-component.ts +0 -12
  54. package/src/extended/store/actions/update-overridable-prop-params.ts +0 -52
  55. package/src/extended/store/utils/groups-transformers.ts +0 -187
  56. package/src/extended/sync/before-save.ts +0 -52
  57. package/src/extended/sync/cleanup-overridable-props-on-delete.ts +0 -78
  58. package/src/extended/sync/create-components-before-save.ts +0 -111
  59. package/src/extended/sync/handle-component-edit-mode-container.ts +0 -114
  60. package/src/extended/sync/prevent-non-atomic-nesting.ts +0 -198
  61. package/src/extended/sync/revert-overridables-on-copy-or-duplicate.ts +0 -66
  62. package/src/extended/sync/sanitize-overridable-props.ts +0 -32
  63. package/src/extended/sync/set-component-overridable-props-settings-before-save.ts +0 -22
  64. package/src/extended/sync/update-archived-component-before-save.ts +0 -31
  65. package/src/extended/sync/update-component-title-before-save.ts +0 -18
  66. package/src/extended/utils/component-form-schema.ts +0 -32
  67. package/src/extended/utils/component-name-validation.ts +0 -25
  68. package/src/extended/utils/create-component-model.ts +0 -28
  69. package/src/extended/utils/get-container-for-new-element.ts +0 -49
  70. package/src/extended/utils/is-editing-component.ts +0 -5
  71. package/src/extended/utils/replace-element-with-component.ts +0 -11
  72. package/src/extended/utils/revert-overridable-settings.ts +0 -207
@@ -1,135 +0,0 @@
1
- import * as React from 'react';
2
- import { useState } from 'react';
3
- import { Form, MenuListItem } from '@elementor/editor-ui';
4
- import { Button, FormLabel, Grid, Select, Stack, type SxProps, TextField, Typography } from '@elementor/ui';
5
- import { __ } from '@wordpress/i18n';
6
-
7
- import { type OverridableProp } from '../../../types';
8
- import { validatePropLabel } from './utils/validate-prop-label';
9
-
10
- const SIZE = 'tiny';
11
-
12
- const DEFAULT_GROUP = { value: null, label: __( 'Default', 'elementor' ) };
13
-
14
- type Props = {
15
- onSubmit: ( data: { label: string; group: string | null } ) => void;
16
- currentValue?: OverridableProp;
17
- groups?: { value: string; label: string }[];
18
- existingLabels?: string[];
19
- sx?: SxProps;
20
- };
21
-
22
- export function OverridablePropForm( { onSubmit, groups, currentValue, existingLabels = [], sx }: Props ) {
23
- const selectGroups = groups?.length ? groups : [ DEFAULT_GROUP ];
24
-
25
- const [ propLabel, setPropLabel ] = useState< string | null >( currentValue?.label ?? null );
26
- const [ group, setGroup ] = useState< string | null >( currentValue?.groupId ?? selectGroups[ 0 ]?.value ?? null );
27
- const [ error, setError ] = useState< string | null >( null );
28
-
29
- const name = __( 'Name', 'elementor' );
30
- const groupName = __( 'Group Name', 'elementor' );
31
-
32
- const isCreate = currentValue === undefined;
33
-
34
- const title = isCreate ? __( 'Create new property', 'elementor' ) : __( 'Update property', 'elementor' );
35
- const ctaLabel = isCreate ? __( 'Create', 'elementor' ) : __( 'Update', 'elementor' );
36
-
37
- const handleSubmit = () => {
38
- const validationResult = validatePropLabel( propLabel ?? '', existingLabels, currentValue?.label );
39
-
40
- if ( ! validationResult.isValid ) {
41
- setError( validationResult.errorMessage );
42
- return;
43
- }
44
-
45
- onSubmit( { label: propLabel ?? '', group } );
46
- };
47
-
48
- return (
49
- <Form onSubmit={ handleSubmit } data-testid="overridable-prop-form">
50
- <Stack alignItems="start" sx={ { width: '268px', ...sx } }>
51
- <Stack
52
- direction="row"
53
- alignItems="center"
54
- py={ 1 }
55
- px={ 1.5 }
56
- sx={ { columnGap: 0.5, borderBottom: '1px solid', borderColor: 'divider', width: '100%', mb: 1.5 } }
57
- >
58
- <Typography variant="caption" sx={ { color: 'text.primary', fontWeight: '500', lineHeight: 1 } }>
59
- { title }
60
- </Typography>
61
- </Stack>
62
- <Grid container gap={ 0.75 } alignItems="start" px={ 1.5 } mb={ 1.5 }>
63
- <Grid item xs={ 12 }>
64
- <FormLabel size="tiny">{ name }</FormLabel>
65
- </Grid>
66
- <Grid item xs={ 12 }>
67
- <TextField
68
- name={ name }
69
- size={ SIZE }
70
- fullWidth
71
- placeholder={ __( 'Enter value', 'elementor' ) }
72
- value={ propLabel ?? '' }
73
- onChange={ ( e: React.ChangeEvent< HTMLInputElement > ) => {
74
- const newValue = e.target.value;
75
- setPropLabel( newValue );
76
- const validationResult = validatePropLabel(
77
- newValue,
78
- existingLabels,
79
- currentValue?.label
80
- );
81
- setError( validationResult.errorMessage );
82
- } }
83
- error={ Boolean( error ) }
84
- helperText={ error }
85
- />
86
- </Grid>
87
- </Grid>
88
- <Grid container gap={ 0.75 } alignItems="start" px={ 1.5 } mb={ 1.5 }>
89
- <Grid item xs={ 12 }>
90
- <FormLabel size="tiny">{ groupName }</FormLabel>
91
- </Grid>
92
- <Grid item xs={ 12 }>
93
- <Select
94
- name={ groupName }
95
- size={ SIZE }
96
- fullWidth
97
- value={ group ?? null }
98
- onChange={ ( e: React.ChangeEvent< HTMLSelectElement > ) =>
99
- setGroup( e.target.value as string | null )
100
- }
101
- displayEmpty
102
- renderValue={ ( selectedValue: string | null ) => {
103
- if ( ! selectedValue ) {
104
- return selectGroups[ 0 ].label;
105
- }
106
-
107
- return (
108
- selectGroups.find( ( { value } ) => value === selectedValue )?.label ??
109
- selectedValue
110
- );
111
- } }
112
- >
113
- { selectGroups.map( ( { label: groupLabel, ...props } ) => (
114
- <MenuListItem key={ props.value } { ...props } value={ props.value ?? '' }>
115
- { groupLabel }
116
- </MenuListItem>
117
- ) ) }
118
- </Select>
119
- </Grid>
120
- </Grid>
121
- <Stack direction="row" justifyContent="flex-end" alignSelf="end" mt={ 1.5 } py={ 1 } px={ 1.5 }>
122
- <Button
123
- type="submit"
124
- disabled={ ! propLabel || Boolean( error ) }
125
- variant="contained"
126
- color="primary"
127
- size="small"
128
- >
129
- { ctaLabel }
130
- </Button>
131
- </Stack>
132
- </Stack>
133
- </Form>
134
- );
135
- }
@@ -1,138 +0,0 @@
1
- import * as React from 'react';
2
- import { useBoundProp } from '@elementor/editor-controls';
3
- import { useElement } from '@elementor/editor-editing-panel';
4
- import { getWidgetsCache } from '@elementor/editor-elements';
5
- import { type PropType, type TransformablePropValue } from '@elementor/editor-props';
6
- import { bindPopover, bindTrigger, Popover, Tooltip, usePopupState } from '@elementor/ui';
7
- import { __ } from '@wordpress/i18n';
8
-
9
- import { useSanitizeOverridableProps } from '../../../hooks/use-sanitize-overridable-props';
10
- import { componentOverridablePropTypeUtil } from '../../../prop-types/component-overridable-prop-type';
11
- import { useComponentInstanceElement, useOverridablePropValue } from '../../../provider/overridable-prop-context';
12
- import { useCurrentComponentId } from '../../../store/store';
13
- import { type OverridableProps } from '../../../types';
14
- import { getOverridableProp } from '../../../utils/get-overridable-prop';
15
- import { resolveOverridePropValue } from '../../../utils/resolve-override-prop-value';
16
- import { setOverridableProp } from '../../store/actions/set-overridable-prop';
17
- import { Indicator } from './indicator';
18
- import { OverridablePropForm } from './overridable-prop-form';
19
-
20
- export function OverridablePropIndicator() {
21
- const { propType } = useBoundProp();
22
- const componentId = useCurrentComponentId();
23
- const overridableProps = useSanitizeOverridableProps( componentId );
24
-
25
- if ( ! isPropAllowed( propType ) || ! componentId || ! overridableProps ) {
26
- return null;
27
- }
28
-
29
- return <Content componentId={ componentId } overridableProps={ overridableProps } />;
30
- }
31
-
32
- type Props = {
33
- componentId: number;
34
- overridableProps?: OverridableProps;
35
- };
36
- export function Content( { componentId, overridableProps }: Props ) {
37
- const {
38
- element: { id: elementId },
39
- elementType,
40
- } = useElement();
41
- const { value, bind, propType } = useBoundProp();
42
-
43
- const contextOverridableValue = useOverridablePropValue();
44
- const componentInstanceElement = useComponentInstanceElement();
45
-
46
- const { value: boundPropOverridableValue, setValue: setOverridableValue } = useBoundProp(
47
- componentOverridablePropTypeUtil
48
- );
49
-
50
- /**
51
- * This is intended to handle custom layout controls, such as <LinkControl />, which has <ControlLabel /> nested within it
52
- * i.e. its bound prop value would be the one manipulated by the new <PropProvider /> thus won't be considered overridable
53
- */
54
- const overridableValue = boundPropOverridableValue ?? contextOverridableValue;
55
-
56
- const popupState = usePopupState( {
57
- variant: 'popover',
58
- } );
59
-
60
- const triggerProps = bindTrigger( popupState );
61
- const popoverProps = bindPopover( popupState );
62
-
63
- const { elType } = getWidgetsCache()?.[ elementType.key ] ?? { elType: 'widget' };
64
-
65
- const handleSubmit = ( { label, group }: { label: string; group: string | null } ) => {
66
- const propTypeDefault = propType.default ?? {};
67
-
68
- const originValue = resolveOverridePropValue( overridableValue?.origin_value ) ?? value ?? propTypeDefault;
69
-
70
- const matchingOverridableProp = overridableValue
71
- ? overridableProps?.props?.[ overridableValue.override_key ]
72
- : undefined;
73
-
74
- const overridablePropConfig = setOverridableProp( {
75
- componentId,
76
- overrideKey: overridableValue?.override_key ?? null,
77
- elementId: componentInstanceElement?.element.id ?? elementId,
78
- label,
79
- groupId: group,
80
- propKey: bind,
81
- elType: elType ?? 'widget',
82
- widgetType: componentInstanceElement?.elementType.key ?? elementType.key,
83
- originValue,
84
- originPropFields: matchingOverridableProp?.originPropFields,
85
- source: 'user',
86
- } );
87
-
88
- if ( ! overridableValue && overridablePropConfig ) {
89
- setOverridableValue( {
90
- override_key: overridablePropConfig.overrideKey,
91
- origin_value: originValue as TransformablePropValue< string, unknown >,
92
- } );
93
- }
94
-
95
- popupState.close();
96
- };
97
-
98
- const overridableConfig = overridableValue
99
- ? getOverridableProp( { componentId, overrideKey: overridableValue.override_key } )
100
- : undefined;
101
-
102
- return (
103
- <>
104
- <Tooltip placement="top" title={ __( 'Override Property', 'elementor' ) }>
105
- <Indicator { ...triggerProps } isOpen={ !! popoverProps.open } isOverridable={ !! overridableValue } />
106
- </Tooltip>
107
- <Popover
108
- disableScrollLock
109
- anchorOrigin={ {
110
- vertical: 'bottom',
111
- horizontal: 'right',
112
- } }
113
- transformOrigin={ {
114
- vertical: 'top',
115
- horizontal: 'right',
116
- } }
117
- PaperProps={ {
118
- sx: { my: 2.5 },
119
- } }
120
- { ...popoverProps }
121
- >
122
- <OverridablePropForm
123
- onSubmit={ handleSubmit }
124
- groups={ overridableProps?.groups.order.map( ( groupId ) => ( {
125
- value: groupId,
126
- label: overridableProps.groups.items[ groupId ].label,
127
- } ) ) }
128
- existingLabels={ Object.values( overridableProps?.props ?? {} ).map( ( prop ) => prop.label ) }
129
- currentValue={ overridableConfig }
130
- />
131
- </Popover>
132
- </>
133
- );
134
- }
135
-
136
- function isPropAllowed( propType: PropType ) {
137
- return propType.meta.overridable !== false;
138
- }
@@ -1,38 +0,0 @@
1
- import { __ } from '@wordpress/i18n';
2
-
3
- export const ERROR_MESSAGES = {
4
- EMPTY_NAME: __( 'Property name is required', 'elementor' ),
5
- DUPLICATE_NAME: __( 'Property name already exists', 'elementor' ),
6
- } as const;
7
-
8
- type ValidationResult = {
9
- isValid: boolean;
10
- errorMessage: string | null;
11
- };
12
-
13
- export function validatePropLabel( label: string, existingLabels: string[], currentLabel?: string ): ValidationResult {
14
- const trimmedLabel = label.trim();
15
-
16
- if ( ! trimmedLabel ) {
17
- return { isValid: false, errorMessage: ERROR_MESSAGES.EMPTY_NAME };
18
- }
19
-
20
- const normalizedLabel = trimmedLabel.toLowerCase();
21
- const normalizedCurrentLabel = currentLabel?.trim().toLowerCase();
22
-
23
- const isDuplicate = existingLabels.some( ( existingLabel ) => {
24
- const normalizedExisting = existingLabel.trim().toLowerCase();
25
-
26
- if ( normalizedCurrentLabel && normalizedExisting === normalizedCurrentLabel ) {
27
- return false;
28
- }
29
-
30
- return normalizedExisting === normalizedLabel;
31
- } );
32
-
33
- if ( isDuplicate ) {
34
- return { isValid: false, errorMessage: ERROR_MESSAGES.DUPLICATE_NAME };
35
- }
36
-
37
- return { isValid: true, errorMessage: null };
38
- }
@@ -1,3 +0,0 @@
1
- export const OVERRIDABLE_PROP_REPLACEMENT_ID = 'overridable-prop';
2
-
3
- export const COMPONENT_DOCUMENT_TYPE = 'elementor_component';
@@ -1,24 +0,0 @@
1
- import { useCallback } from 'react';
2
- import { getV1DocumentsManager } from '@elementor/editor-documents';
3
- import { __useSelector as useSelector } from '@elementor/store';
4
-
5
- import { selectPath } from '../../store/store';
6
- import { switchToComponent } from '../../utils/switch-to-component';
7
-
8
- export function useNavigateBack() {
9
- const path = useSelector( selectPath );
10
-
11
- const documentsManager = getV1DocumentsManager();
12
-
13
- return useCallback( () => {
14
- const { componentId: prevComponentId, instanceId: prevComponentInstanceId } = path.at( -2 ) ?? {};
15
-
16
- if ( prevComponentId && prevComponentInstanceId ) {
17
- switchToComponent( prevComponentId, prevComponentInstanceId );
18
-
19
- return;
20
- }
21
-
22
- switchToComponent( documentsManager.getInitialId() );
23
- }, [ path, documentsManager ] );
24
- }
@@ -1,108 +0,0 @@
1
- import { injectIntoLogic, injectIntoTop } from '@elementor/editor';
2
- import { registerControlReplacement } from '@elementor/editor-controls';
3
- import { getV1CurrentDocument } from '@elementor/editor-documents';
4
- import {
5
- FIELD_TYPE,
6
- injectIntoPanelHeaderTop,
7
- registerEditingPanelReplacement,
8
- registerFieldIndicator,
9
- } from '@elementor/editor-editing-panel';
10
- import { registerTab } from '@elementor/editor-elements-panel';
11
- import { __registerPanel as registerPanel } from '@elementor/editor-panels';
12
- import { registerDataHook } from '@elementor/editor-v1-adapters';
13
- import { __ } from '@wordpress/i18n';
14
-
15
- import { componentOverridablePropTypeUtil } from '../prop-types/component-overridable-prop-type';
16
- import { type ExtendedWindow } from '../types';
17
- import { onElementDrop } from '../utils/tracking';
18
- import { ComponentPanelHeader } from './components/component-panel-header/component-panel-header';
19
- import { panel as componentPropertiesPanel } from './components/component-properties-panel/component-properties-panel';
20
- import { ExtendedComponents } from './components/components-tab/components';
21
- import { CreateComponentForm } from './components/create-component-form/create-component-form';
22
- import { EditComponent } from './components/edit-component/edit-component';
23
- import { ExtendedInstanceEditingPanel } from './components/instance-editing-panel/instance-editing-panel';
24
- import { OverridablePropControl } from './components/overridable-props/overridable-prop-control';
25
- import { OverridablePropIndicator } from './components/overridable-props/overridable-prop-indicator';
26
- import { COMPONENT_DOCUMENT_TYPE, OVERRIDABLE_PROP_REPLACEMENT_ID } from './consts';
27
- import { initMcp } from './mcp';
28
- import { beforeSave } from './sync/before-save';
29
- import { initCleanupOverridablePropsOnDelete } from './sync/cleanup-overridable-props-on-delete';
30
- import { initHandleComponentEditModeContainer } from './sync/handle-component-edit-mode-container';
31
- import { initNonAtomicNestingPrevention } from './sync/prevent-non-atomic-nesting';
32
- import { initRevertOverridablesOnCopyOrDuplicate } from './sync/revert-overridables-on-copy-or-duplicate';
33
- import { SanitizeOverridableProps } from './sync/sanitize-overridable-props';
34
-
35
- const PRIORITY = 1;
36
-
37
- export function initExtended() {
38
- registerEditingPanelReplacement( {
39
- id: 'extended-component-instance-edit-panel',
40
- priority: PRIORITY,
41
- condition: ( _, elementType ) => elementType.key === 'e-component',
42
- component: ExtendedInstanceEditingPanel,
43
- } );
44
-
45
- registerTab( {
46
- id: 'components',
47
- label: __( 'Components', 'elementor' ),
48
- component: ExtendedComponents,
49
- priority: PRIORITY,
50
- } );
51
-
52
- registerPanel( componentPropertiesPanel );
53
-
54
- registerDataHook( 'dependency', 'editor/documents/close', ( args ) => {
55
- const document = getV1CurrentDocument();
56
- if ( document.config.type === COMPONENT_DOCUMENT_TYPE ) {
57
- args.mode = 'autosave';
58
- }
59
- return true;
60
- } );
61
-
62
- registerDataHook( 'after', 'preview/drop', onElementDrop );
63
-
64
- ( window as unknown as ExtendedWindow ).elementorCommon.__beforeSave = beforeSave;
65
-
66
- injectIntoTop( {
67
- id: 'create-component-popup',
68
- component: CreateComponentForm,
69
- } );
70
-
71
- injectIntoTop( {
72
- id: 'edit-component',
73
- component: EditComponent,
74
- } );
75
-
76
- injectIntoPanelHeaderTop( {
77
- id: 'component-panel-header',
78
- component: ComponentPanelHeader,
79
- } );
80
-
81
- registerFieldIndicator( {
82
- fieldType: FIELD_TYPE.SETTINGS,
83
- id: 'component-overridable-prop',
84
- priority: 1,
85
- indicator: OverridablePropIndicator,
86
- } );
87
-
88
- registerControlReplacement( {
89
- id: OVERRIDABLE_PROP_REPLACEMENT_ID,
90
- component: OverridablePropControl,
91
- condition: ( { value } ) => componentOverridablePropTypeUtil.isValid( value ),
92
- } );
93
-
94
- initCleanupOverridablePropsOnDelete();
95
-
96
- initMcp();
97
-
98
- initNonAtomicNestingPrevention();
99
-
100
- initHandleComponentEditModeContainer();
101
-
102
- initRevertOverridablesOnCopyOrDuplicate();
103
-
104
- injectIntoLogic( {
105
- id: 'sanitize-overridable-props',
106
- component: SanitizeOverridableProps,
107
- } );
108
- }
@@ -1,14 +0,0 @@
1
- import { getMCPByDomain } from '@elementor/editor-mcp';
2
-
3
- import { initSaveAsComponentTool } from './save-as-component-tool';
4
-
5
- export function initMcp() {
6
- const { setMCPDescription } = getMCPByDomain( 'components' );
7
-
8
- setMCPDescription(
9
- `Elementor Editor Components MCP - Tools for creating and managing reusable components.
10
- Components are reusable blocks of content that can be used multiple times across the pages, its a widget which contains a set of elements and styles.`
11
- );
12
-
13
- initSaveAsComponentTool();
14
- }