@elementor/editor-controls 3.33.0-99 → 3.35.0-325

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 (94) hide show
  1. package/dist/index.d.mts +276 -85
  2. package/dist/index.d.ts +276 -85
  3. package/dist/index.js +2491 -1783
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +2304 -1592
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +31 -17
  8. package/src/bound-prop-context/prop-context.tsx +7 -1
  9. package/src/bound-prop-context/use-bound-prop.ts +19 -5
  10. package/src/components/autocomplete.tsx +34 -3
  11. package/src/components/conditional-control-infotip.tsx +64 -0
  12. package/src/components/{unstable-repeater → control-repeater}/actions/disable-item-action.tsx +2 -2
  13. package/src/components/{unstable-repeater → control-repeater}/actions/duplicate-item-action.tsx +10 -4
  14. package/src/components/{unstable-repeater → control-repeater}/actions/remove-item-action.tsx +2 -2
  15. package/src/components/control-repeater/context/item-context.tsx +8 -0
  16. package/src/components/{unstable-repeater → control-repeater}/context/repeater-context.tsx +24 -15
  17. package/src/components/control-repeater/control-repeater.tsx +29 -0
  18. package/src/components/{unstable-repeater → control-repeater}/index.ts +1 -2
  19. package/src/components/{unstable-repeater → control-repeater}/items/edit-item-popover.tsx +6 -20
  20. package/src/components/control-repeater/items/item.tsx +75 -0
  21. package/src/components/{unstable-repeater → control-repeater}/items/items-container.tsx +8 -13
  22. package/src/components/{unstable-repeater → control-repeater}/locations.ts +0 -4
  23. package/src/components/{unstable-repeater → control-repeater}/types.ts +1 -2
  24. package/src/components/control-toggle-button-group.tsx +79 -69
  25. package/src/components/enable-unfiltered-modal.tsx +1 -26
  26. package/src/components/icon-buttons/clear-icon-button.tsx +23 -0
  27. package/src/components/inline-editor-toolbar.tsx +137 -0
  28. package/src/components/inline-editor.tsx +111 -0
  29. package/src/components/item-selector.tsx +10 -4
  30. package/src/components/{unstable-repeater/header/header.tsx → repeater/repeater-header.tsx} +4 -12
  31. package/src/components/repeater/repeater-popover.tsx +19 -0
  32. package/src/components/repeater/repeater-tag.tsx +16 -0
  33. package/src/components/repeater/repeater.tsx +405 -0
  34. package/src/components/{sortable.tsx → repeater/sortable.tsx} +1 -1
  35. package/src/components/size-control/size-input.tsx +20 -14
  36. package/src/components/size-control/text-field-inner-selection.tsx +15 -2
  37. package/src/control-adornments/control-adornments-context.tsx +5 -4
  38. package/src/control-replacements.tsx +12 -47
  39. package/src/controls/background-control/background-control.tsx +43 -12
  40. package/src/controls/background-control/background-gradient-color-control.tsx +5 -8
  41. package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +18 -13
  42. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +25 -16
  43. package/src/controls/box-shadow-repeater-control.tsx +38 -21
  44. package/src/controls/color-control.tsx +3 -1
  45. package/src/controls/date-time-control.tsx +108 -0
  46. package/src/controls/filter-control/drop-shadow/drop-shadow-item-content.tsx +1 -0
  47. package/src/controls/filter-control/drop-shadow/drop-shadow-item-label.tsx +10 -6
  48. package/src/controls/filter-control/filter-content.tsx +1 -1
  49. package/src/controls/filter-control/filter-repeater-control.tsx +24 -21
  50. package/src/controls/filter-control/single-size/single-size-item-content.tsx +1 -1
  51. package/src/controls/filter-control/single-size/single-size-item-label.tsx +2 -1
  52. package/src/controls/font-family-control/font-family-control.tsx +66 -55
  53. package/src/controls/html-tag-control.tsx +90 -0
  54. package/src/controls/image-media-control.tsx +2 -2
  55. package/src/controls/inline-editing-control.tsx +18 -0
  56. package/src/controls/key-value-control.tsx +8 -2
  57. package/src/controls/link-control.tsx +23 -123
  58. package/src/controls/query-control.tsx +168 -0
  59. package/src/controls/repeatable-control.tsx +62 -27
  60. package/src/controls/select-control-wrapper.tsx +57 -0
  61. package/src/controls/select-control.tsx +9 -5
  62. package/src/controls/selection-size-control.tsx +13 -2
  63. package/src/controls/size-control.tsx +43 -25
  64. package/src/controls/svg-media-control.tsx +33 -10
  65. package/src/controls/text-area-control.tsx +5 -1
  66. package/src/controls/text-control.tsx +5 -0
  67. package/src/controls/toggle-control.tsx +11 -2
  68. package/src/controls/transform-control/functions/axis-row.tsx +1 -0
  69. package/src/controls/transform-control/transform-icon.tsx +2 -2
  70. package/src/controls/transform-control/transform-label.tsx +15 -32
  71. package/src/controls/transform-control/transform-repeater-control.tsx +42 -36
  72. package/src/controls/transform-control/{transform-base-control.tsx → transform-settings-control.tsx} +2 -2
  73. package/src/controls/transform-control/use-transform-tabs-history.tsx +1 -1
  74. package/src/controls/transition-control/data.ts +16 -1
  75. package/src/controls/transition-control/trainsition-events.ts +2 -2
  76. package/src/controls/transition-control/transition-repeater-control.tsx +137 -13
  77. package/src/controls/transition-control/transition-selector.tsx +37 -14
  78. package/src/controls/url-control.tsx +21 -16
  79. package/src/create-control.tsx +3 -2
  80. package/src/hooks/use-filtered-items-list.ts +3 -2
  81. package/src/hooks/use-repeatable-control-context.ts +3 -0
  82. package/src/hooks/use-sync-external-state.tsx +0 -1
  83. package/src/index.ts +21 -5
  84. package/src/utils/convert-toggle-options-to-atomic.tsx +33 -0
  85. package/src/utils/escape-html-attr.ts +11 -0
  86. package/src/components/css-code-editor/css-editor.styles.ts +0 -52
  87. package/src/components/css-code-editor/css-editor.tsx +0 -142
  88. package/src/components/css-code-editor/css-validation.ts +0 -75
  89. package/src/components/css-code-editor/resize-handle.tsx +0 -55
  90. package/src/components/css-code-editor/visual-content-change-protection.ts +0 -69
  91. package/src/components/repeater.tsx +0 -343
  92. package/src/components/unstable-repeater/items/item.tsx +0 -77
  93. package/src/components/unstable-repeater/unstable-repeater.tsx +0 -26
  94. /package/src/components/{unstable-repeater → control-repeater}/actions/tooltip-add-item-action.tsx +0 -0
@@ -3,9 +3,10 @@ import { type Category } from '../components/item-selector';
3
3
  export type SelectableItem = {
4
4
  type: 'item' | 'category';
5
5
  value: string;
6
+ disabled?: boolean;
6
7
  };
7
8
 
8
- export const useFilteredItemsList = ( itemsList: Category[], searchValue: string ) => {
9
+ export const useFilteredItemsList = ( itemsList: Category[], searchValue: string, disabledItems?: string[] ) => {
9
10
  return itemsList.reduce< SelectableItem[] >( ( acc, category ) => {
10
11
  const filteredItems = category.items.filter( ( item ) =>
11
12
  item.toLowerCase().includes( searchValue.toLowerCase() )
@@ -15,7 +16,7 @@ export const useFilteredItemsList = ( itemsList: Category[], searchValue: string
15
16
  acc.push( { type: 'category', value: category.label } );
16
17
 
17
18
  filteredItems.forEach( ( item ) => {
18
- acc.push( { type: 'item', value: item } );
19
+ acc.push( { type: 'item', value: item, disabled: disabledItems?.includes( item ) ?? false } );
19
20
  } );
20
21
  }
21
22
 
@@ -1,12 +1,15 @@
1
1
  import { createContext, useContext } from 'react';
2
2
  import { type PropTypeUtil } from '@elementor/editor-props';
3
3
 
4
+ import type { Item, RepeatablePropValue } from '../components/control-repeater/types';
5
+
4
6
  export type ChildControlConfig = {
5
7
  component: React.ComponentType;
6
8
  props?: Record< string, unknown >;
7
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
10
  propTypeUtil: PropTypeUtil< string, any >;
9
11
  label?: string;
12
+ isItemDisabled?: ( item: Item< RepeatablePropValue > ) => boolean;
10
13
  };
11
14
 
12
15
  type RepeatableControlContextType = ChildControlConfig & {
@@ -37,7 +37,6 @@ export const useSyncExternalState = < TValue, >( {
37
37
  useEffect( () => {
38
38
  setInternal( ( prevInternal ) => toInternal( external, prevInternal ) );
39
39
 
40
- // eslint-disable-next-line react-compiler/react-compiler
41
40
  // eslint-disable-next-line react-hooks/exhaustive-deps
42
41
  }, [ external ] );
43
42
 
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export { StrokeControl } from './controls/stroke-control';
7
7
  export { BoxShadowRepeaterControl } from './controls/box-shadow-repeater-control';
8
8
  export { FilterRepeaterControl } from './controls/filter-control/filter-repeater-control';
9
9
  export { SelectControl } from './controls/select-control';
10
+ export { SelectControlWrapper } from './controls/select-control-wrapper';
10
11
  export { ColorControl } from './controls/color-control';
11
12
  export { ToggleControl } from './controls/toggle-control';
12
13
  export { NumberControl } from './controls/number-control';
@@ -16,6 +17,8 @@ export { FontFamilyControl } from './controls/font-family-control/font-family-co
16
17
  export { ItemSelector } from './components/item-selector';
17
18
  export { UrlControl } from './controls/url-control';
18
19
  export { LinkControl } from './controls/link-control';
20
+ export { HtmlTagControl } from './controls/html-tag-control';
21
+ export { QueryControl } from './controls/query-control';
19
22
  export { GapControl } from './controls/gap-control';
20
23
  export { AspectRatioControl } from './controls/aspect-ratio-control';
21
24
  export { SvgMediaControl } from './controls/svg-media-control';
@@ -25,24 +28,38 @@ export { RepeatableControl } from './controls/repeatable-control';
25
28
  export { KeyValueControl } from './controls/key-value-control';
26
29
  export { PositionControl } from './controls/position-control';
27
30
  export { TransformRepeaterControl } from './controls/transform-control/transform-repeater-control';
28
- export { TransformBaseControl } from './controls/transform-control/transform-base-control';
31
+ export { TransformSettingsControl } from './controls/transform-control/transform-settings-control';
29
32
  export { TransitionRepeaterControl } from './controls/transition-control/transition-repeater-control';
30
33
  export { PopoverContent } from './components/popover-content';
31
34
  export { enqueueFont } from './controls/font-family-control/enqueue-font';
32
35
  export { transitionProperties, transitionsItemsList } from './controls/transition-control/data';
36
+ export { DateTimeControl } from './controls/date-time-control';
37
+ export { InlineEditingControl } from './controls/inline-editing-control';
38
+ export { InlineEditor } from './components/inline-editor';
39
+ export { InlineEditorToolbar } from './components/inline-editor-toolbar';
33
40
 
34
41
  // components
35
42
  export { ControlFormLabel } from './components/control-form-label';
36
43
  export { ControlToggleButtonGroup } from './components/control-toggle-button-group';
37
- export { CssEditor } from './components/css-code-editor/css-editor';
44
+ export { ToggleButtonGroupUi } from './components/control-toggle-button-group';
45
+ export { ClearIconButton } from './components/icon-buttons/clear-icon-button';
46
+ export {
47
+ Repeater,
48
+ type SetRepeaterValuesMeta,
49
+ type ItemsActionPayload,
50
+ type RepeaterItem,
51
+ } from './components/repeater/repeater';
52
+ export { FloatingActionsBar } from './components/floating-bar';
53
+ export { PopoverGridContainer } from './components/popover-grid-container';
38
54
 
39
55
  // types
40
56
  export type { ControlComponent } from './create-control';
41
57
  export type { ToggleButtonGroupItem } from './components/control-toggle-button-group';
42
58
  export type { EqualUnequalItems } from './controls/equal-unequal-sizes-control';
43
59
  export type { ControlActionsItems } from './control-actions/control-actions-context';
60
+ export type { AdornmentComponent } from './control-adornments/control-adornments-context';
44
61
  export type { PropProviderProps } from './bound-prop-context';
45
- export type { SetValue } from './bound-prop-context/prop-context';
62
+ export type { SetValue, SetValueMeta } from './bound-prop-context/prop-context';
46
63
  export type { ExtendedOption, Unit, LengthUnit, AngleUnit, TimeUnit } from './utils/size-control';
47
64
  export type { ToggleControlProps } from './controls/toggle-control';
48
65
  export type { FontCategory } from './controls/font-family-control/font-family-control';
@@ -59,9 +76,8 @@ export { createControl } from './create-control';
59
76
  export {
60
77
  injectIntoRepeaterItemIcon,
61
78
  injectIntoRepeaterItemLabel,
62
- injectIntoRepeaterHeaderActions,
63
79
  injectIntoRepeaterItemActions,
64
- } from './components/unstable-repeater/locations';
80
+ } from './components/control-repeater/locations';
65
81
 
66
82
  // hooks
67
83
  export { useSyncExternalState } from './hooks/use-sync-external-state';
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+ import type { ToggleButtonGroupItem } from '@elementor/editor-controls';
3
+ import * as Icons from '@elementor/icons';
4
+
5
+ export type DynamicToggleOption = {
6
+ value: string;
7
+ label: string;
8
+ icon?: string;
9
+ showTooltip?: boolean;
10
+ exclusive?: boolean;
11
+ };
12
+
13
+ export const convertToggleOptionsToAtomic = (
14
+ options: DynamicToggleOption[]
15
+ ): Array< ToggleButtonGroupItem< string > & { exclusive?: boolean } > => {
16
+ return options.map( ( option ) => {
17
+ const iconName = option.icon;
18
+ const IconComponent = Icons[ iconName as keyof typeof Icons ];
19
+
20
+ return {
21
+ value: option.value,
22
+ label: option.label,
23
+ renderContent: ( { size } ) => {
24
+ if ( IconComponent ) {
25
+ return <IconComponent fontSize={ size } />;
26
+ }
27
+ return option.label;
28
+ },
29
+ showTooltip: option.showTooltip,
30
+ exclusive: option.exclusive,
31
+ };
32
+ } );
33
+ };
@@ -0,0 +1,11 @@
1
+ export const escapeHtmlAttr = ( value: string ): string => {
2
+ const specialChars: Record< string, string > = {
3
+ '&': '&amp;',
4
+ '<': '&lt;',
5
+ '>': '&gt;',
6
+ "'": '&#39;',
7
+ '"': '&quot;',
8
+ };
9
+
10
+ return value.replace( /[&<>'"]/g, ( char ) => specialChars[ char ] || char );
11
+ };
@@ -1,52 +0,0 @@
1
- import { Box, Button, styled } from '@elementor/ui';
2
-
3
- export const EditorWrapper = styled( Box )`
4
- border: 1px solid var( --e-a-border-color );
5
- border-radius: 8px;
6
- padding: 10px 12px;
7
- position: relative;
8
- height: 200px;
9
-
10
- .monaco-editor .suggest-widget {
11
- width: 220px !important;
12
- max-width: 220px !important;
13
- }
14
-
15
- .visual-content-dimmed {
16
- opacity: 0.6;
17
- color: #aaa !important;
18
- pointer-events: none;
19
- }
20
- `;
21
-
22
- export const ResizeHandle = styled( Button )`
23
- position: absolute;
24
- bottom: 0;
25
- left: 0;
26
- right: 0;
27
- height: 6px;
28
- cursor: ns-resize;
29
- background: transparent;
30
- border: none;
31
- padding: 0;
32
-
33
- &:hover {
34
- background: rgba( 0, 0, 0, 0.05 );
35
- }
36
-
37
- &:active {
38
- background: rgba( 0, 0, 0, 0.1 );
39
- }
40
-
41
- &::after {
42
- content: '';
43
- position: absolute;
44
- top: 50%;
45
- left: 50%;
46
- transform: translate( -50%, -50% );
47
- width: 30px;
48
- height: 2px;
49
- background: var( --e-a-border-color );
50
- border-radius: 1px;
51
- }
52
- `;
@@ -1,142 +0,0 @@
1
- import * as React from 'react';
2
- import type { editor, MonacoEditor } from 'monaco-types';
3
- import { useActiveBreakpoint } from '@elementor/editor-responsive';
4
- import { useTheme } from '@elementor/ui';
5
- import { Editor } from '@monaco-editor/react';
6
-
7
- import { EditorWrapper } from './css-editor.styles';
8
- import { clearMarkersFromVisualContent, setCustomSyntaxRules, validate } from './css-validation';
9
- import { ResizeHandleComponent } from './resize-handle';
10
- import { preventChangeOnVisualContent } from './visual-content-change-protection';
11
-
12
- type CssEditorProps = {
13
- value: string;
14
- onChange: ( value: string, isValid: boolean ) => void;
15
- };
16
-
17
- const setVisualContent = ( value: string ): string => {
18
- const trimmed = value.trim();
19
- return `element.style {\n${ trimmed ? ' ' + trimmed.replace( /\n/g, '\n ' ) + '\n' : ' \n' }}`;
20
- };
21
-
22
- const getActual = ( value: string ): string => {
23
- const lines = value.split( '\n' );
24
- if ( lines.length < 2 ) {
25
- return '';
26
- }
27
- return lines
28
- .slice( 1, -1 )
29
- .map( ( line ) => line.replace( /^ {2}/, '' ) )
30
- .join( '\n' );
31
- };
32
-
33
- const createEditorDidMountHandler = (
34
- editorRef: React.MutableRefObject< editor.IStandaloneCodeEditor | null >,
35
- monacoRef: React.MutableRefObject< MonacoEditor | null >,
36
- debounceTimer: React.MutableRefObject< NodeJS.Timeout | null >,
37
- onChange: ( value: string, isValid: boolean ) => void
38
- ) => {
39
- return ( editor: editor.IStandaloneCodeEditor, monaco: MonacoEditor ) => {
40
- editorRef.current = editor;
41
- monacoRef.current = monaco;
42
-
43
- preventChangeOnVisualContent( editor );
44
-
45
- setCustomSyntaxRules( editor, monaco );
46
-
47
- monaco.editor.onDidChangeMarkers( () => {
48
- setTimeout( () => clearMarkersFromVisualContent( editor, monaco ), 0 );
49
- } );
50
-
51
- editor.setPosition( { lineNumber: 2, column: ( editor.getModel()?.getLineContent( 2 ).length ?? 0 ) + 1 } );
52
-
53
- editor.onDidChangeModelContent( () => {
54
- const code = editor.getModel()?.getValue() ?? '';
55
- const userContent = getActual( code );
56
-
57
- setCustomSyntaxRules( editor, monaco );
58
-
59
- const currentTimer = debounceTimer.current;
60
- if ( currentTimer ) {
61
- clearTimeout( currentTimer );
62
- }
63
-
64
- const newTimer = setTimeout( () => {
65
- if ( ! editorRef.current || ! monacoRef.current ) {
66
- return;
67
- }
68
-
69
- const hasNoErrors = validate( editorRef.current, monacoRef.current );
70
-
71
- onChange( userContent, hasNoErrors );
72
- }, 500 );
73
-
74
- debounceTimer.current = newTimer;
75
- } );
76
- };
77
- };
78
-
79
- export const CssEditor = ( { value, onChange }: CssEditorProps ) => {
80
- const theme = useTheme();
81
- const containerRef = React.useRef< HTMLDivElement >( null );
82
- const editorRef = React.useRef< editor.IStandaloneCodeEditor | null >( null );
83
- const monacoRef = React.useRef< MonacoEditor | null >( null );
84
- const debounceTimer = React.useRef< NodeJS.Timeout | null >( null );
85
- const activeBreakpoint = useActiveBreakpoint();
86
-
87
- const handleResize = React.useCallback( () => {
88
- editorRef.current?.layout();
89
- }, [] );
90
-
91
- const handleHeightChange = React.useCallback( ( height: number ) => {
92
- if ( containerRef.current ) {
93
- containerRef.current.style.height = `${ height }px`;
94
- }
95
- }, [] );
96
-
97
- const handleEditorDidMount = createEditorDidMountHandler( editorRef, monacoRef, debounceTimer, onChange );
98
-
99
- React.useEffect( () => {
100
- const timerRef = debounceTimer;
101
- return () => {
102
- const timer = timerRef.current;
103
- if ( timer ) {
104
- clearTimeout( timer );
105
- }
106
- };
107
- }, [] );
108
-
109
- return (
110
- <EditorWrapper ref={ containerRef }>
111
- <Editor
112
- key={ activeBreakpoint }
113
- height="100%"
114
- language="css"
115
- theme={ theme.palette.mode === 'dark' ? 'vs-dark' : 'vs' }
116
- value={ setVisualContent( value ) }
117
- onMount={ handleEditorDidMount }
118
- options={ {
119
- lineNumbers: 'on',
120
- folding: true,
121
- minimap: { enabled: false },
122
- fontFamily: 'Roboto, Arial, Helvetica, Verdana, sans-serif',
123
- fontSize: 12,
124
- renderLineHighlight: 'none',
125
- hideCursorInOverviewRuler: true,
126
- fixedOverflowWidgets: true,
127
- suggestFontSize: 10,
128
- suggestLineHeight: 14,
129
- stickyScroll: {
130
- enabled: false,
131
- },
132
- lineDecorationsWidth: 2,
133
- } }
134
- />
135
- <ResizeHandleComponent
136
- onResize={ handleResize }
137
- containerRef={ containerRef }
138
- onHeightChange={ handleHeightChange }
139
- />
140
- </EditorWrapper>
141
- );
142
- };
@@ -1,75 +0,0 @@
1
- import type { editor, MonacoEditor } from 'monaco-types';
2
- import { __ } from '@wordpress/i18n';
3
-
4
- const forbiddenPatterns = [
5
- {
6
- pattern: ':hover',
7
- message: __(
8
- 'The use of pseudo-states is not permitted. Instead, switch to the desired pseudo state and add your custom code there.',
9
- 'elementor'
10
- ),
11
- },
12
- {
13
- pattern: ':active',
14
- message: __(
15
- 'The use of pseudo-states is not permitted. Instead, switch to the desired pseudo state and add your custom code there.',
16
- 'elementor'
17
- ),
18
- },
19
- {
20
- pattern: '@media',
21
- message: __(
22
- 'The use of @media is not permitted. Instead, switch to the desired breakpoint and add your custom code there.',
23
- 'elementor'
24
- ),
25
- },
26
- ];
27
-
28
- export function setCustomSyntaxRules( editor: editor.IStandaloneCodeEditor, monaco: MonacoEditor ): boolean {
29
- const model = editor.getModel();
30
- if ( ! model ) {
31
- return true;
32
- }
33
-
34
- const customMarkers: editor.IMarkerData[] = [];
35
-
36
- forbiddenPatterns.forEach( ( rule ) => {
37
- const matches = model.findMatches( rule.pattern, true, false, true, null, true );
38
- matches.forEach( ( match ) => {
39
- customMarkers.push( {
40
- severity: monaco.MarkerSeverity.Error,
41
- message: rule.message,
42
- startLineNumber: match.range.startLineNumber,
43
- startColumn: match.range.startColumn,
44
- endLineNumber: match.range.endLineNumber,
45
- endColumn: match.range.endColumn,
46
- source: 'custom-css-rules',
47
- } );
48
- } );
49
- } );
50
-
51
- monaco.editor.setModelMarkers( model, 'custom-css-rules', customMarkers );
52
- return customMarkers.length === 0;
53
- }
54
-
55
- export function validate( editor: editor.IStandaloneCodeEditor, monaco: MonacoEditor ): boolean {
56
- const model = editor.getModel();
57
- if ( ! model ) {
58
- return true;
59
- }
60
- const allMarkers = monaco.editor.getModelMarkers( { resource: model.uri } );
61
- return allMarkers.filter( ( marker ) => marker.severity === monaco.MarkerSeverity.Error ).length === 0;
62
- }
63
-
64
- export function clearMarkersFromVisualContent( editor: editor.IStandaloneCodeEditor, monaco: MonacoEditor ): void {
65
- const model = editor.getModel();
66
-
67
- if ( ! model ) {
68
- return;
69
- }
70
-
71
- const allMarkers = monaco.editor.getModelMarkers( { resource: model.uri } );
72
- const filteredMarkers = allMarkers.filter( ( marker ) => marker.startLineNumber !== 1 );
73
- const nonCustomMarkers = filteredMarkers.filter( ( m ) => m.source !== 'custom-css-rules' );
74
- monaco.editor.setModelMarkers( model, 'css', nonCustomMarkers );
75
- }
@@ -1,55 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { ResizeHandle } from './css-editor.styles';
4
-
5
- type ResizeHandleProps = {
6
- onResize: ( height: number ) => void;
7
- containerRef: React.RefObject< HTMLDivElement >;
8
- onHeightChange?: ( height: number ) => void;
9
- };
10
-
11
- export const ResizeHandleComponent = ( { onResize, containerRef, onHeightChange }: ResizeHandleProps ) => {
12
- const handleResizeMove = React.useCallback(
13
- ( e: MouseEvent ) => {
14
- const container = containerRef.current;
15
- if ( ! container ) {
16
- return;
17
- }
18
- const containerRect = container.getBoundingClientRect();
19
- const newHeight = Math.max( 100, e.clientY - containerRect.top );
20
- onHeightChange?.( newHeight );
21
- onResize( newHeight );
22
- },
23
- [ containerRef, onResize, onHeightChange ]
24
- );
25
-
26
- const handleResizeEnd = React.useCallback( () => {
27
- document.removeEventListener( 'mousemove', handleResizeMove );
28
- document.removeEventListener( 'mouseup', handleResizeEnd );
29
- }, [ handleResizeMove ] );
30
-
31
- const handleResizeStart = React.useCallback(
32
- ( e: React.MouseEvent ) => {
33
- e.preventDefault();
34
- e.stopPropagation();
35
- document.addEventListener( 'mousemove', handleResizeMove );
36
- document.addEventListener( 'mouseup', handleResizeEnd );
37
- },
38
- [ handleResizeMove, handleResizeEnd ]
39
- );
40
-
41
- React.useEffect( () => {
42
- return () => {
43
- document.removeEventListener( 'mousemove', handleResizeMove );
44
- document.removeEventListener( 'mouseup', handleResizeEnd );
45
- };
46
- }, [ handleResizeMove, handleResizeEnd ] );
47
-
48
- return (
49
- <ResizeHandle
50
- onMouseDown={ handleResizeStart }
51
- aria-label="Resize editor height"
52
- title="Drag to resize editor height"
53
- />
54
- );
55
- };
@@ -1,69 +0,0 @@
1
- import type { editor } from 'monaco-types';
2
-
3
- export const preventChangeOnVisualContent = ( editor: editor.IStandaloneCodeEditor ) => {
4
- const model = editor.getModel();
5
- if ( ! model ) {
6
- return;
7
- }
8
-
9
- const decorationsCollection = editor.createDecorationsCollection();
10
-
11
- const applyVisualContentStyling = () => {
12
- const totalLines = model.getLineCount();
13
- const decorations = [];
14
-
15
- decorations.push( {
16
- range: {
17
- startLineNumber: 1,
18
- startColumn: 1,
19
- endLineNumber: 1,
20
- endColumn: model.getLineContent( 1 ).length + 1,
21
- },
22
- options: {
23
- inlineClassName: 'visual-content-dimmed',
24
- isWholeLine: false,
25
- },
26
- } );
27
-
28
- if ( totalLines > 1 ) {
29
- decorations.push( {
30
- range: {
31
- startLineNumber: totalLines,
32
- startColumn: 1,
33
- endLineNumber: totalLines,
34
- endColumn: model.getLineContent( totalLines ).length + 1,
35
- },
36
- options: {
37
- inlineClassName: 'visual-content-dimmed',
38
- isWholeLine: false,
39
- },
40
- } );
41
- }
42
-
43
- decorationsCollection.set( decorations );
44
- };
45
-
46
- applyVisualContentStyling();
47
-
48
- model.onDidChangeContent( () => {
49
- applyVisualContentStyling();
50
- } );
51
-
52
- const originalPushEditOperations = model.pushEditOperations;
53
- model.pushEditOperations = function ( beforeCursorState, editOperations, cursorStateComputer ) {
54
- const totalLines = model.getLineCount();
55
-
56
- const filteredOperations = editOperations.filter( ( operation ) => {
57
- const range = operation.range;
58
- const affectsProtectedLine =
59
- range.startLineNumber === 1 ||
60
- range.endLineNumber === 1 ||
61
- range.startLineNumber === totalLines ||
62
- range.endLineNumber === totalLines;
63
-
64
- return ! affectsProtectedLine;
65
- } );
66
-
67
- return originalPushEditOperations.call( this, beforeCursorState, filteredOperations, cursorStateComputer );
68
- };
69
- };