@elementor/editor-components 3.35.0-464 → 3.35.0-466

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.
package/dist/index.js CHANGED
@@ -377,11 +377,11 @@ var componentOverrideTransformer = (0, import_editor_canvas3.createTransformer)(
377
377
  // src/components/component-panel-header/component-panel-header.tsx
378
378
  var React10 = __toESM(require("react"));
379
379
  var import_editor_current_user = require("@elementor/editor-current-user");
380
- var import_editor_documents5 = require("@elementor/editor-documents");
380
+ var import_editor_documents6 = require("@elementor/editor-documents");
381
381
  var import_icons7 = require("@elementor/icons");
382
- var import_store27 = require("@elementor/store");
382
+ var import_store29 = require("@elementor/store");
383
383
  var import_ui10 = require("@elementor/ui");
384
- var import_i18n12 = require("@wordpress/i18n");
384
+ var import_i18n13 = require("@wordpress/i18n");
385
385
 
386
386
  // src/hooks/use-navigate-back.ts
387
387
  var import_react = require("react");
@@ -501,17 +501,17 @@ var import_editor_elements4 = require("@elementor/editor-elements");
501
501
  var import_editor_panels2 = require("@elementor/editor-panels");
502
502
  var import_editor_ui5 = require("@elementor/editor-ui");
503
503
  var import_ui8 = require("@elementor/ui");
504
- var import_i18n10 = require("@wordpress/i18n");
504
+ var import_i18n11 = require("@wordpress/i18n");
505
505
 
506
506
  // src/components/component-properties-panel/component-properties-panel-content.tsx
507
507
  var React7 = __toESM(require("react"));
508
508
  var import_react5 = require("react");
509
- var import_editor_documents4 = require("@elementor/editor-documents");
509
+ var import_editor_documents5 = require("@elementor/editor-documents");
510
510
  var import_editor_panels = require("@elementor/editor-panels");
511
511
  var import_icons5 = require("@elementor/icons");
512
512
  var import_ui7 = require("@elementor/ui");
513
513
  var import_utils2 = require("@elementor/utils");
514
- var import_i18n9 = require("@wordpress/i18n");
514
+ var import_i18n10 = require("@wordpress/i18n");
515
515
 
516
516
  // src/store/actions/add-overridable-group.ts
517
517
  var import_store9 = require("@elementor/store");
@@ -727,1388 +727,1485 @@ function deleteOverridableGroup({ componentId, groupId }) {
727
727
  }
728
728
 
729
729
  // src/store/actions/delete-overridable-prop.ts
730
+ var import_store15 = require("@elementor/store");
731
+
732
+ // src/utils/revert-element-overridable-setting.ts
730
733
  var import_editor_elements2 = require("@elementor/editor-elements");
731
- var import_store13 = require("@elementor/store");
732
- function deleteOverridableProp({ componentId, propKey, source }) {
733
- const overridableProps = selectOverridableProps((0, import_store13.__getState)(), componentId);
734
- if (!overridableProps) {
735
- return;
736
- }
737
- const prop = overridableProps.props[propKey];
738
- if (!prop) {
739
- return;
740
- }
741
- revertElementSetting(prop.elementId, prop.propKey, prop.originValue);
742
- const { [propKey]: removedProp, ...remainingProps } = overridableProps.props;
743
- const updatedGroups = removePropFromAllGroups(overridableProps.groups, propKey);
744
- (0, import_store13.__dispatch)(
745
- slice.actions.setOverridableProps({
746
- componentId,
747
- overridableProps: {
748
- ...overridableProps,
749
- props: remainingProps,
750
- groups: updatedGroups
751
- }
752
- })
753
- );
754
- const currentComponent = selectCurrentComponent((0, import_store13.__getState)());
755
- trackComponentEvent({
756
- action: "propertyRemoved",
757
- source,
758
- component_uid: currentComponent?.uid,
759
- property_id: removedProp.overrideKey,
760
- property_path: removedProp.propKey,
761
- property_name: removedProp.label,
762
- element_type: removedProp.widgetType ?? removedProp.elType
763
- });
764
- }
765
- function revertElementSetting(elementId, settingKey, originValue) {
766
- const container = (0, import_editor_elements2.getContainer)(elementId);
767
- if (!container) {
768
- return;
769
- }
770
- (0, import_editor_elements2.updateElementSettings)({
771
- id: elementId,
772
- props: { [settingKey]: originValue ?? null },
773
- withHistory: false
774
- });
775
- }
776
734
 
777
- // src/store/actions/reorder-group-props.ts
778
- var import_store15 = require("@elementor/store");
779
- function reorderGroupProps({ componentId, groupId, newPropsOrder }) {
780
- const overridableProps = selectOverridableProps((0, import_store15.__getState)(), componentId);
781
- if (!overridableProps) {
782
- return;
783
- }
784
- const group = overridableProps.groups.items[groupId];
785
- if (!group) {
786
- return;
787
- }
788
- (0, import_store15.__dispatch)(
789
- slice.actions.setOverridableProps({
790
- componentId,
791
- overridableProps: {
792
- ...overridableProps,
793
- groups: {
794
- ...overridableProps.groups,
795
- items: {
796
- ...overridableProps.groups.items,
797
- [groupId]: {
798
- ...group,
799
- props: newPropsOrder
800
- }
801
- }
802
- }
803
- }
735
+ // src/prop-types/component-instance-override-prop-type.ts
736
+ var import_editor_props = require("@elementor/editor-props");
737
+ var import_schema = require("@elementor/schema");
738
+ var componentInstanceOverridePropTypeUtil = (0, import_editor_props.createPropUtils)(
739
+ "override",
740
+ import_schema.z.object({
741
+ override_key: import_schema.z.string(),
742
+ override_value: import_schema.z.unknown(),
743
+ schema_source: import_schema.z.object({
744
+ type: import_schema.z.literal("component"),
745
+ id: import_schema.z.number()
804
746
  })
805
- );
806
- }
747
+ })
748
+ );
807
749
 
808
- // src/store/actions/reorder-overridable-groups.ts
809
- var import_store17 = require("@elementor/store");
810
- function reorderOverridableGroups({ componentId, newOrder }) {
811
- const overridableProps = selectOverridableProps((0, import_store17.__getState)(), componentId);
812
- if (!overridableProps) {
813
- return;
814
- }
815
- (0, import_store17.__dispatch)(
816
- slice.actions.setOverridableProps({
817
- componentId,
818
- overridableProps: {
819
- ...overridableProps,
820
- groups: {
821
- ...overridableProps.groups,
822
- order: newOrder
823
- }
824
- }
825
- })
826
- );
827
- }
750
+ // src/prop-types/component-instance-overrides-prop-type.ts
751
+ var import_editor_props3 = require("@elementor/editor-props");
752
+ var import_schema3 = require("@elementor/schema");
828
753
 
829
- // src/store/actions/update-overridable-prop-params.ts
830
- var import_store19 = require("@elementor/store");
831
- function updateOverridablePropParams({
832
- componentId,
833
- overrideKey,
834
- label,
835
- groupId
836
- }) {
837
- const overridableProps = selectOverridableProps((0, import_store19.__getState)(), componentId);
838
- if (!overridableProps) {
839
- return;
840
- }
841
- const prop = overridableProps.props[overrideKey];
842
- if (!prop) {
843
- return;
844
- }
845
- const oldGroupId = prop.groupId;
846
- const newGroupId = groupId ?? oldGroupId;
847
- const updatedProp = {
848
- ...prop,
849
- label,
850
- groupId: newGroupId
851
- };
852
- const updatedGroups = movePropBetweenGroups(overridableProps.groups, overrideKey, oldGroupId, newGroupId);
853
- (0, import_store19.__dispatch)(
854
- slice.actions.setOverridableProps({
855
- componentId,
856
- overridableProps: {
857
- ...overridableProps,
858
- props: {
859
- ...overridableProps.props,
860
- [overrideKey]: updatedProp
861
- },
862
- groups: updatedGroups
863
- }
864
- })
865
- );
866
- return updatedProp;
867
- }
754
+ // src/prop-types/component-overridable-prop-type.ts
755
+ var import_editor_props2 = require("@elementor/editor-props");
756
+ var import_schema2 = require("@elementor/schema");
757
+ var componentOverridablePropTypeUtil = (0, import_editor_props2.createPropUtils)(
758
+ "overridable",
759
+ import_schema2.z.object({
760
+ override_key: import_schema2.z.string(),
761
+ origin_value: import_schema2.z.object({
762
+ $$type: import_schema2.z.string(),
763
+ value: import_schema2.z.unknown()
764
+ }).nullable()
765
+ })
766
+ );
868
767
 
869
- // src/components/component-panel-header/use-overridable-props.ts
870
- var import_store21 = require("@elementor/store");
871
- function useOverridableProps2(componentId) {
872
- return (0, import_store21.__useSelector)((state) => {
873
- if (!componentId) {
874
- return void 0;
875
- }
876
- return selectOverridableProps(state, componentId);
877
- });
878
- }
768
+ // src/prop-types/component-instance-overrides-prop-type.ts
769
+ var componentInstanceOverridesPropTypeUtil = (0, import_editor_props3.createPropUtils)(
770
+ "overrides",
771
+ import_schema3.z.array(import_schema3.z.union([componentInstanceOverridePropTypeUtil.schema, componentOverridablePropTypeUtil.schema])).optional().default([])
772
+ );
879
773
 
880
- // src/components/component-properties-panel/properties-empty-state.tsx
881
- var React2 = __toESM(require("react"));
882
- var import_react2 = require("react");
883
- var import_icons = require("@elementor/icons");
884
- var import_ui2 = require("@elementor/ui");
885
- var import_i18n3 = require("@wordpress/i18n");
774
+ // src/prop-types/component-instance-prop-type.ts
775
+ var import_editor_props4 = require("@elementor/editor-props");
776
+ var import_schema4 = require("@elementor/schema");
777
+ var componentInstancePropTypeUtil = (0, import_editor_props4.createPropUtils)(
778
+ "component-instance",
779
+ import_schema4.z.object({
780
+ component_id: import_editor_props4.numberPropTypeUtil.schema,
781
+ overrides: import_schema4.z.optional(componentInstanceOverridesPropTypeUtil.schema)
782
+ })
783
+ );
886
784
 
887
- // src/components/components-tab/component-introduction.tsx
888
- var React = __toESM(require("react"));
889
- var import_editor_controls = require("@elementor/editor-controls");
890
- var import_editor_ui = require("@elementor/editor-ui");
891
- var import_ui = require("@elementor/ui");
785
+ // src/create-component-type.ts
786
+ var import_editor_canvas4 = require("@elementor/editor-canvas");
787
+ var import_editor_documents3 = require("@elementor/editor-documents");
788
+ var import_store13 = require("@elementor/store");
892
789
  var import_i18n2 = require("@wordpress/i18n");
893
- var ComponentIntroduction = ({
894
- anchorRef,
895
- shouldShowIntroduction,
896
- onClose
897
- }) => {
898
- if (!anchorRef.current || !shouldShowIntroduction) {
899
- return null;
900
- }
901
- return /* @__PURE__ */ React.createElement(
902
- import_ui.Popover,
903
- {
904
- anchorEl: anchorRef.current,
905
- open: shouldShowIntroduction,
906
- anchorOrigin: {
907
- vertical: "top",
908
- horizontal: "right"
909
- },
910
- transformOrigin: {
911
- vertical: "top",
912
- horizontal: -30
913
- },
914
- onClose
915
- },
916
- /* @__PURE__ */ React.createElement(import_ui.Box, { sx: { width: "296px" } }, /* @__PURE__ */ React.createElement(import_editor_ui.PopoverHeader, { title: (0, import_i18n2.__)("Add your first property", "elementor"), onClose }), /* @__PURE__ */ React.createElement(
917
- import_ui.Image,
918
- {
919
- sx: { width: "296px", height: "160px" },
920
- src: "https://assets.elementor.com/packages/v1/images/components-properties-intro.png",
921
- alt: ""
922
- }
923
- ), /* @__PURE__ */ React.createElement(import_editor_controls.PopoverContent, null, /* @__PURE__ */ React.createElement(import_ui.Stack, { sx: { p: 2 } }, /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2" }, (0, import_i18n2.__)("Properties make instances flexible.", "elementor")), /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2" }, (0, import_i18n2.__)(
924
- "Click next to any setting you want users to customize - like text, images, or links.",
925
- "elementor"
926
- )), /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2", sx: { mt: 2 } }, (0, import_i18n2.__)(
927
- "Your properties will appear in the Properties panel, where you can organize and manage them anytime.",
928
- "elementor"
929
- )), /* @__PURE__ */ React.createElement(
930
- import_ui.Link,
931
- {
932
- href: "http://go.elementor.com/components-guide",
933
- target: "_blank",
934
- sx: { mt: 2 },
935
- color: "info.main",
936
- variant: "body2"
937
- },
938
- (0, import_i18n2.__)("Learn more", "elementor")
939
- ), /* @__PURE__ */ React.createElement(import_ui.Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", sx: { pt: 1 } }, /* @__PURE__ */ React.createElement(import_ui.Button, { size: "medium", variant: "contained", onClick: onClose }, (0, import_i18n2.__)("Got it", "elementor"))))))
940
- );
790
+ var COMPONENT_WIDGET_TYPE = "e-component";
791
+ var updateGroups = (groups, config) => {
792
+ const disableMap = new Map(Object.entries(config.disable ?? {}));
793
+ const addMap = new Map(Object.entries(config.add ?? {}));
794
+ return groups.map((group) => {
795
+ const disabledActions = disableMap.get(group.name) ?? [];
796
+ const addConfig = addMap.get(group.name);
797
+ const updatedActions = group.actions.map(
798
+ (action) => disabledActions.includes(action.name) ? { ...action, isEnabled: () => false } : action
799
+ );
800
+ if (addConfig) {
801
+ updatedActions.splice(addConfig.index, 0, addConfig.action);
802
+ }
803
+ return { ...group, actions: updatedActions };
804
+ });
941
805
  };
942
-
943
- // src/components/component-properties-panel/properties-empty-state.tsx
944
- function PropertiesEmptyState({ introductionRef }) {
945
- const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
946
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
947
- import_ui2.Stack,
948
- {
949
- alignItems: "center",
950
- justifyContent: "flex-start",
951
- height: "100%",
952
- color: "text.secondary",
953
- sx: { px: 2.5, pt: 10, pb: 5.5 },
954
- gap: 1
955
- },
956
- /* @__PURE__ */ React2.createElement(import_icons.ComponentPropListIcon, { fontSize: "large" }),
957
- /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "subtitle2" }, (0, import_i18n3.__)("Add your first property", "elementor")),
958
- /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "caption" }, (0, import_i18n3.__)("Make instances flexible while keeping design synced.", "elementor")),
959
- /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "caption" }, (0, import_i18n3.__)("Select any element, then click + next to a setting to expose it.", "elementor")),
960
- /* @__PURE__ */ React2.createElement(
961
- import_ui2.Link,
962
- {
963
- variant: "caption",
964
- color: "secondary",
965
- sx: { textDecorationLine: "underline" },
966
- onClick: () => setIsOpen(true)
967
- },
968
- (0, import_i18n3.__)("Learn more", "elementor")
969
- )
970
- ), /* @__PURE__ */ React2.createElement(
971
- ComponentIntroduction,
972
- {
973
- anchorRef: introductionRef,
974
- shouldShowIntroduction: isOpen,
975
- onClose: () => setIsOpen(false)
806
+ function createComponentType(options) {
807
+ const legacyWindow = window;
808
+ const WidgetType = legacyWindow.elementor.modules.elements.types.Widget;
809
+ const view = createComponentView({ ...options });
810
+ return class extends WidgetType {
811
+ getType() {
812
+ return options.type;
976
813
  }
977
- ));
978
- }
979
-
980
- // src/components/component-properties-panel/properties-group.tsx
981
- var React6 = __toESM(require("react"));
982
- var import_editor_ui3 = require("@elementor/editor-ui");
983
- var import_icons4 = require("@elementor/icons");
984
- var import_ui6 = require("@elementor/ui");
985
- var import_i18n6 = require("@wordpress/i18n");
986
-
987
- // src/components/component-properties-panel/property-item.tsx
988
- var React5 = __toESM(require("react"));
989
- var import_editor_elements3 = require("@elementor/editor-elements");
990
- var import_icons3 = require("@elementor/icons");
991
- var import_ui5 = require("@elementor/ui");
992
-
993
- // src/components/overridable-props/overridable-prop-form.tsx
994
- var React3 = __toESM(require("react"));
995
- var import_react3 = require("react");
996
- var import_editor_ui2 = require("@elementor/editor-ui");
997
- var import_ui3 = require("@elementor/ui");
998
- var import_i18n5 = require("@wordpress/i18n");
999
-
1000
- // src/components/overridable-props/utils/validate-prop-label.ts
1001
- var import_i18n4 = require("@wordpress/i18n");
1002
- var ERROR_MESSAGES = {
1003
- EMPTY_NAME: (0, import_i18n4.__)("Property name is required", "elementor"),
1004
- DUPLICATE_NAME: (0, import_i18n4.__)("Property name already exists", "elementor")
1005
- };
1006
- function validatePropLabel(label, existingLabels, currentLabel) {
1007
- const trimmedLabel = label.trim();
1008
- if (!trimmedLabel) {
1009
- return { isValid: false, errorMessage: ERROR_MESSAGES.EMPTY_NAME };
1010
- }
1011
- const normalizedLabel = trimmedLabel.toLowerCase();
1012
- const normalizedCurrentLabel = currentLabel?.trim().toLowerCase();
1013
- const isDuplicate = existingLabels.some((existingLabel) => {
1014
- const normalizedExisting = existingLabel.trim().toLowerCase();
1015
- if (normalizedCurrentLabel && normalizedExisting === normalizedCurrentLabel) {
1016
- return false;
814
+ getView() {
815
+ return view;
1017
816
  }
1018
- return normalizedExisting === normalizedLabel;
1019
- });
1020
- if (isDuplicate) {
1021
- return { isValid: false, errorMessage: ERROR_MESSAGES.DUPLICATE_NAME };
1022
- }
1023
- return { isValid: true, errorMessage: null };
1024
- }
1025
-
1026
- // src/components/overridable-props/overridable-prop-form.tsx
1027
- var SIZE = "tiny";
1028
- var DEFAULT_GROUP = { value: null, label: (0, import_i18n5.__)("Default", "elementor") };
1029
- function OverridablePropForm({ onSubmit, groups, currentValue, existingLabels = [], sx }) {
1030
- const [propLabel, setPropLabel] = (0, import_react3.useState)(currentValue?.label ?? null);
1031
- const [group, setGroup] = (0, import_react3.useState)(currentValue?.groupId ?? groups?.[0]?.value ?? null);
1032
- const [error, setError] = (0, import_react3.useState)(null);
1033
- const name = (0, import_i18n5.__)("Name", "elementor");
1034
- const groupName = (0, import_i18n5.__)("Group Name", "elementor");
1035
- const isCreate = currentValue === void 0;
1036
- const title = isCreate ? (0, import_i18n5.__)("Create new property", "elementor") : (0, import_i18n5.__)("Update property", "elementor");
1037
- const ctaLabel = isCreate ? (0, import_i18n5.__)("Create", "elementor") : (0, import_i18n5.__)("Update", "elementor");
1038
- const handleSubmit = () => {
1039
- const validationResult = validatePropLabel(propLabel ?? "", existingLabels, currentValue?.label);
1040
- if (!validationResult.isValid) {
1041
- setError(validationResult.errorMessage);
1042
- return;
817
+ getModel() {
818
+ return createComponentModel();
1043
819
  }
1044
- onSubmit({ label: propLabel ?? "", group });
1045
820
  };
1046
- return /* @__PURE__ */ React3.createElement(import_editor_ui2.Form, { onSubmit: handleSubmit }, /* @__PURE__ */ React3.createElement(import_ui3.Stack, { alignItems: "start", sx: { width: "268px", ...sx } }, /* @__PURE__ */ React3.createElement(
1047
- import_ui3.Stack,
1048
- {
1049
- direction: "row",
1050
- alignItems: "center",
1051
- py: 1,
1052
- px: 1.5,
1053
- sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
1054
- },
1055
- /* @__PURE__ */ React3.createElement(import_ui3.Typography, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, title)
1056
- ), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(import_ui3.FormLabel, { size: "tiny" }, name)), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(
1057
- import_ui3.TextField,
1058
- {
1059
- name,
1060
- size: SIZE,
1061
- fullWidth: true,
1062
- placeholder: (0, import_i18n5.__)("Enter value", "elementor"),
1063
- value: propLabel ?? "",
1064
- onChange: (e) => {
1065
- const newValue = e.target.value;
1066
- setPropLabel(newValue);
1067
- const validationResult = validatePropLabel(
1068
- newValue,
1069
- existingLabels,
1070
- currentValue?.label
1071
- );
1072
- setError(validationResult.errorMessage);
1073
- },
1074
- error: Boolean(error),
1075
- helperText: error
821
+ }
822
+ function createComponentView(options) {
823
+ const legacyWindow = window;
824
+ return class extends (0, import_editor_canvas4.createTemplatedElementView)(options) {
825
+ eventsManagerConfig = legacyWindow.elementorCommon.eventsManager.config;
826
+ #componentRenderContext;
827
+ isComponentCurrentlyEdited() {
828
+ const currentDocument = (0, import_editor_documents3.getCurrentDocument)();
829
+ return currentDocument?.id === this.getComponentId();
1076
830
  }
1077
- ))), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(import_ui3.FormLabel, { size: "tiny" }, groupName)), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(
1078
- import_ui3.Select,
1079
- {
1080
- name: groupName,
1081
- size: SIZE,
1082
- fullWidth: true,
1083
- value: group ?? null,
1084
- onChange: (e) => setGroup(e.target.value),
1085
- displayEmpty: true,
1086
- renderValue: (selectedValue) => {
1087
- if (!selectedValue || selectedValue === "") {
1088
- const [firstGroup = DEFAULT_GROUP] = groups ?? [];
1089
- return firstGroup.label;
831
+ getRenderContext() {
832
+ const namespaceKey = this.getNamespaceKey();
833
+ const parentContext = this._parent?.getRenderContext?.();
834
+ const parentComponentContext = parentContext?.[namespaceKey];
835
+ if (!this.#componentRenderContext) {
836
+ return parentContext;
837
+ }
838
+ const ownOverrides = this.#componentRenderContext.overrides ?? {};
839
+ const parentOverrides = parentComponentContext?.overrides ?? {};
840
+ return {
841
+ ...parentContext,
842
+ [namespaceKey]: {
843
+ overrides: {
844
+ ...parentOverrides,
845
+ ...ownOverrides
846
+ }
847
+ }
848
+ };
849
+ }
850
+ getResolverRenderContext() {
851
+ const namespaceKey = this.getNamespaceKey();
852
+ const context = this.getRenderContext();
853
+ return context?.[namespaceKey];
854
+ }
855
+ afterSettingsResolve(settings) {
856
+ const componentInstance = settings.component_instance;
857
+ if (componentInstance) {
858
+ this.#componentRenderContext = {
859
+ overrides: componentInstance.overrides ?? {}
860
+ };
861
+ this.collection = legacyWindow.elementor.createBackboneElementsCollection(componentInstance.elements);
862
+ this.collection.models.forEach(setInactiveRecursively);
863
+ settings.component_instance = "<template data-children-placeholder></template>";
864
+ }
865
+ return settings;
866
+ }
867
+ getDomElement() {
868
+ return this.children.findByIndex(0)?.getDomElement() ?? this.$el;
869
+ }
870
+ attachBuffer(collectionView, buffer) {
871
+ const childrenPlaceholder = collectionView.$el.find("[data-children-placeholder]").get(0);
872
+ if (!childrenPlaceholder) {
873
+ super.attachBuffer(collectionView, buffer);
874
+ return;
875
+ }
876
+ childrenPlaceholder.replaceWith(buffer);
877
+ }
878
+ getComponentId() {
879
+ const componentInstance = this.options?.model?.get("settings")?.get("component_instance")?.value;
880
+ return componentInstance.component_id.value;
881
+ }
882
+ getContextMenuGroups() {
883
+ const filteredGroups = super.getContextMenuGroups().filter((group) => group.name !== "save");
884
+ const componentId = this.getComponentId();
885
+ if (!componentId) {
886
+ return filteredGroups;
887
+ }
888
+ const newGroups = updateGroups(
889
+ filteredGroups,
890
+ this._getContextMenuConfig()
891
+ );
892
+ return newGroups;
893
+ }
894
+ _getContextMenuConfig() {
895
+ const isAdministrator = isUserAdministrator();
896
+ const addedGroup = {
897
+ general: {
898
+ index: 1,
899
+ action: {
900
+ name: "edit component",
901
+ icon: "eicon-edit",
902
+ title: () => (0, import_i18n2.__)("Edit Component", "elementor"),
903
+ isEnabled: () => true,
904
+ callback: (_, eventData) => this.editComponent(eventData)
905
+ }
906
+ }
907
+ };
908
+ const disabledGroup = {
909
+ clipboard: ["pasteStyle", "resetStyle"]
910
+ };
911
+ return { add: isAdministrator ? addedGroup : {}, disable: disabledGroup };
912
+ }
913
+ async switchDocument() {
914
+ const { isAllowedToSwitchDocument, lockedBy } = await apiClient.getComponentLockStatus(
915
+ this.getComponentId()
916
+ );
917
+ if (!isAllowedToSwitchDocument) {
918
+ options.showLockedByModal?.(lockedBy || "");
919
+ } else {
920
+ switchToComponent(this.getComponentId(), this.model.get("id"), this.el);
921
+ }
922
+ }
923
+ editComponent({ trigger, location, secondaryLocation }) {
924
+ if (this.isComponentCurrentlyEdited()) {
925
+ return;
926
+ }
927
+ this.switchDocument();
928
+ const editorSettings = this.model.get("editor_settings");
929
+ trackComponentEvent({
930
+ action: "edited",
931
+ source: "user",
932
+ component_uid: editorSettings?.component_uid,
933
+ component_name: editorSettings?.title,
934
+ location,
935
+ secondary_location: secondaryLocation,
936
+ trigger
937
+ });
938
+ }
939
+ handleDblClick(e) {
940
+ e.stopPropagation();
941
+ const isAdministrator = isUserAdministrator();
942
+ if (!isAdministrator) {
943
+ return;
944
+ }
945
+ const { triggers, locations, secondaryLocations } = this.eventsManagerConfig;
946
+ this.editComponent({
947
+ trigger: triggers.doubleClick,
948
+ location: locations.canvas,
949
+ secondaryLocation: secondaryLocations.canvasElement
950
+ });
951
+ }
952
+ events() {
953
+ return {
954
+ ...super.events(),
955
+ dblclick: this.handleDblClick
956
+ };
957
+ }
958
+ attributes() {
959
+ return {
960
+ ...super.attributes(),
961
+ "data-elementor-id": this.getComponentId()
962
+ };
963
+ }
964
+ };
965
+ }
966
+ function setInactiveRecursively(model) {
967
+ const editSettings = model.get("editSettings");
968
+ if (editSettings) {
969
+ editSettings.set("inactive", true);
970
+ }
971
+ const elements = model.get("elements");
972
+ if (elements) {
973
+ elements.forEach((childModel) => {
974
+ setInactiveRecursively(childModel);
975
+ });
976
+ }
977
+ }
978
+ function isUserAdministrator() {
979
+ const legacyWindow = window;
980
+ return legacyWindow.elementor.config?.user?.is_administrator ?? false;
981
+ }
982
+ function createComponentModel() {
983
+ const legacyWindow = window;
984
+ const WidgetType = legacyWindow.elementor.modules.elements.types.Widget;
985
+ const widgetTypeInstance = new WidgetType();
986
+ const BaseWidgetModel = widgetTypeInstance.getModel();
987
+ return BaseWidgetModel.extend({
988
+ initialize(attributes, options) {
989
+ BaseWidgetModel.prototype.initialize.call(this, attributes, options);
990
+ const componentInstance = this.get("settings")?.get("component_instance");
991
+ if (componentInstance?.value) {
992
+ const componentId = componentInstance.value.component_id?.value;
993
+ if (componentId && typeof componentId === "number") {
994
+ this.set("componentId", componentId);
1090
995
  }
1091
- return groups?.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
1092
996
  }
997
+ this.set("isGlobal", true);
1093
998
  },
1094
- (groups ?? [DEFAULT_GROUP]).map(({ label: groupLabel, ...props }) => /* @__PURE__ */ React3.createElement(import_editor_ui2.MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, groupLabel))
1095
- ))), /* @__PURE__ */ React3.createElement(import_ui3.Stack, { direction: "row", justifyContent: "flex-end", alignSelf: "end", mt: 1.5, py: 1, px: 1.5 }, /* @__PURE__ */ React3.createElement(
1096
- import_ui3.Button,
1097
- {
1098
- type: "submit",
1099
- disabled: !propLabel || Boolean(error),
1100
- variant: "contained",
1101
- color: "primary",
1102
- size: "small"
999
+ getTitle() {
1000
+ const editorSettings = this.get("editor_settings");
1001
+ const instanceTitle = editorSettings?.title;
1002
+ if (instanceTitle) {
1003
+ return instanceTitle;
1004
+ }
1005
+ const componentUid = editorSettings?.component_uid;
1006
+ if (componentUid) {
1007
+ const component = selectComponentByUid((0, import_store13.__getState)(), componentUid);
1008
+ if (component?.name) {
1009
+ return component.name;
1010
+ }
1011
+ }
1012
+ return window.elementor.getElementData(this).title;
1103
1013
  },
1104
- ctaLabel
1105
- ))));
1014
+ getComponentId() {
1015
+ return this.get("componentId") || null;
1016
+ },
1017
+ getComponentName() {
1018
+ return this.getTitle();
1019
+ },
1020
+ getComponentUid() {
1021
+ const editorSettings = this.get("editor_settings");
1022
+ return editorSettings?.component_uid || null;
1023
+ }
1024
+ });
1106
1025
  }
1107
1026
 
1108
- // src/components/component-properties-panel/sortable.tsx
1109
- var React4 = __toESM(require("react"));
1110
- var import_icons2 = require("@elementor/icons");
1111
- var import_ui4 = require("@elementor/ui");
1112
- var SortableProvider = (props) => /* @__PURE__ */ React4.createElement(import_ui4.UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
1113
- var SortableTrigger = ({ triggerClassName, ...props }) => /* @__PURE__ */ React4.createElement(
1114
- StyledSortableTrigger,
1115
- {
1116
- ...props,
1117
- role: "button",
1118
- className: `sortable-trigger ${triggerClassName ?? ""}`.trim(),
1119
- "aria-label": "sort"
1120
- },
1121
- /* @__PURE__ */ React4.createElement(import_icons2.GripVerticalIcon, { fontSize: "tiny" })
1122
- );
1123
- var SortableItem = ({ children, id: id2 }) => /* @__PURE__ */ React4.createElement(
1124
- import_ui4.UnstableSortableItem,
1125
- {
1126
- id: id2,
1127
- render: ({
1128
- itemProps,
1129
- isDragged,
1130
- triggerProps,
1131
- itemStyle,
1132
- triggerStyle,
1133
- dropIndicationStyle,
1134
- showDropIndication,
1135
- isDragOverlay,
1136
- isDragPlaceholder
1137
- }) => /* @__PURE__ */ React4.createElement(
1138
- import_ui4.Box,
1139
- {
1140
- ...itemProps,
1141
- style: itemStyle,
1142
- component: "div",
1143
- role: "listitem",
1144
- sx: {
1145
- backgroundColor: isDragOverlay ? "background.paper" : void 0
1146
- }
1147
- },
1148
- children({
1149
- isDragged,
1150
- isDragPlaceholder,
1151
- triggerProps,
1152
- triggerStyle
1153
- }),
1154
- showDropIndication && /* @__PURE__ */ React4.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1155
- )
1027
+ // src/utils/is-component-instance.ts
1028
+ function isComponentInstance(elementModel) {
1029
+ return [elementModel.widgetType, elementModel.elType].includes(COMPONENT_WIDGET_TYPE);
1030
+ }
1031
+
1032
+ // src/utils/revert-element-overridable-setting.ts
1033
+ function revertElementOverridableSetting(elementId, settingKey, originValue, overrideKey) {
1034
+ const container = (0, import_editor_elements2.getContainer)(elementId);
1035
+ if (!container) {
1036
+ return;
1156
1037
  }
1157
- );
1158
- var StyledSortableTrigger = (0, import_ui4.styled)("div")(({ theme }) => ({
1159
- position: "absolute",
1160
- left: "-2px",
1161
- top: "50%",
1162
- transform: `translate( -${theme.spacing(1.5)}, -50% )`,
1163
- color: theme.palette.action.active,
1164
- cursor: "grab"
1165
- }));
1166
- var SortableItemIndicator = (0, import_ui4.styled)(import_ui4.Box)`
1167
- width: 100%;
1168
- height: 1px;
1169
- background-color: ${({ theme }) => theme.palette.text.primary};
1170
- `;
1038
+ if (isComponentInstance(container.model.toJSON())) {
1039
+ revertComponentInstanceSetting(elementId, overrideKey);
1040
+ return;
1041
+ }
1042
+ (0, import_editor_elements2.updateElementSettings)({
1043
+ id: elementId,
1044
+ props: { [settingKey]: originValue ?? null },
1045
+ withHistory: false
1046
+ });
1047
+ }
1048
+ function revertComponentInstanceSetting(elementId, overrideKey) {
1049
+ const setting = (0, import_editor_elements2.getElementSetting)(elementId, "component_instance");
1050
+ const componentInstance = componentInstancePropTypeUtil.extract(setting);
1051
+ const overrides = componentInstanceOverridesPropTypeUtil.extract(componentInstance?.overrides);
1052
+ if (!overrides) {
1053
+ return;
1054
+ }
1055
+ const updatedOverrides = getUpdatedComponentInstanceOverrides(overrides, overrideKey);
1056
+ const updatedSetting = componentInstancePropTypeUtil.create({
1057
+ ...componentInstance,
1058
+ overrides: componentInstanceOverridesPropTypeUtil.create(updatedOverrides)
1059
+ });
1060
+ (0, import_editor_elements2.updateElementSettings)({
1061
+ id: elementId,
1062
+ props: { component_instance: updatedSetting },
1063
+ withHistory: false
1064
+ });
1065
+ }
1066
+ function getUpdatedComponentInstanceOverrides(overrides, overrideKey) {
1067
+ return overrides.map((item) => {
1068
+ const isOverridable = componentOverridablePropTypeUtil.isValid(item);
1069
+ if (!isOverridable) {
1070
+ return item;
1071
+ }
1072
+ const isOriginValueOverride2 = componentInstanceOverridePropTypeUtil.isValid(item.value.origin_value);
1073
+ if (!isOriginValueOverride2) {
1074
+ return null;
1075
+ }
1076
+ if (item.value.override_key !== overrideKey) {
1077
+ return item;
1078
+ }
1079
+ return item.value.origin_value;
1080
+ }).filter((item) => item !== null);
1081
+ }
1171
1082
 
1172
- // src/components/component-properties-panel/property-item.tsx
1173
- function PropertyItem({
1174
- prop,
1175
- sortableTriggerProps,
1176
- isDragPlaceholder,
1177
- groups,
1178
- existingLabels,
1179
- onDelete,
1180
- onUpdate
1181
- }) {
1182
- const popoverState = (0, import_ui5.usePopupState)({
1183
- variant: "popover"
1083
+ // src/store/actions/delete-overridable-prop.ts
1084
+ function deleteOverridableProp({ componentId, propKey, source }) {
1085
+ const overridableProps = selectOverridableProps((0, import_store15.__getState)(), componentId);
1086
+ if (!overridableProps) {
1087
+ return;
1088
+ }
1089
+ const prop = overridableProps.props[propKey];
1090
+ if (!prop) {
1091
+ return;
1092
+ }
1093
+ revertElementOverridableSetting(prop.elementId, prop.propKey, prop.originValue, propKey);
1094
+ const { [propKey]: removedProp, ...remainingProps } = overridableProps.props;
1095
+ const updatedGroups = removePropFromAllGroups(overridableProps.groups, propKey);
1096
+ (0, import_store15.__dispatch)(
1097
+ slice.actions.setOverridableProps({
1098
+ componentId,
1099
+ overridableProps: {
1100
+ ...overridableProps,
1101
+ props: remainingProps,
1102
+ groups: updatedGroups
1103
+ }
1104
+ })
1105
+ );
1106
+ const currentComponent = selectCurrentComponent((0, import_store15.__getState)());
1107
+ trackComponentEvent({
1108
+ action: "propertyRemoved",
1109
+ source,
1110
+ component_uid: currentComponent?.uid,
1111
+ property_id: removedProp.overrideKey,
1112
+ property_path: removedProp.propKey,
1113
+ property_name: removedProp.label,
1114
+ element_type: removedProp.widgetType ?? removedProp.elType
1184
1115
  });
1185
- const icon = getElementIcon(prop);
1186
- const popoverProps = (0, import_ui5.bindPopover)(popoverState);
1187
- const handleSubmit = (data) => {
1188
- onUpdate(data);
1189
- popoverState.close();
1190
- };
1191
- const handleDelete = (event) => {
1192
- event.stopPropagation();
1193
- onDelete(prop.overrideKey);
1194
- };
1195
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(
1196
- import_ui5.Box,
1197
- {
1198
- ...(0, import_ui5.bindTrigger)(popoverState),
1199
- sx: {
1200
- position: "relative",
1201
- pl: 0.5,
1202
- pr: 1,
1203
- py: 0.25,
1204
- minHeight: 28,
1205
- borderRadius: 1,
1206
- border: "1px solid",
1207
- borderColor: "divider",
1208
- display: "flex",
1209
- alignItems: "center",
1210
- gap: 0.5,
1211
- opacity: isDragPlaceholder ? 0.5 : 1,
1212
- cursor: "pointer",
1213
- "&:hover": {
1214
- backgroundColor: "action.hover"
1215
- },
1216
- "&:hover .sortable-trigger": {
1217
- visibility: "visible"
1218
- },
1219
- "& .sortable-trigger": {
1220
- visibility: "hidden"
1221
- },
1222
- "&:hover .delete-button": {
1223
- visibility: "visible"
1224
- },
1225
- "& .delete-button": {
1226
- visibility: "hidden"
1116
+ }
1117
+
1118
+ // src/store/actions/reorder-group-props.ts
1119
+ var import_store17 = require("@elementor/store");
1120
+ function reorderGroupProps({ componentId, groupId, newPropsOrder }) {
1121
+ const overridableProps = selectOverridableProps((0, import_store17.__getState)(), componentId);
1122
+ if (!overridableProps) {
1123
+ return;
1124
+ }
1125
+ const group = overridableProps.groups.items[groupId];
1126
+ if (!group) {
1127
+ return;
1128
+ }
1129
+ (0, import_store17.__dispatch)(
1130
+ slice.actions.setOverridableProps({
1131
+ componentId,
1132
+ overridableProps: {
1133
+ ...overridableProps,
1134
+ groups: {
1135
+ ...overridableProps.groups,
1136
+ items: {
1137
+ ...overridableProps.groups.items,
1138
+ [groupId]: {
1139
+ ...group,
1140
+ props: newPropsOrder
1141
+ }
1142
+ }
1227
1143
  }
1228
1144
  }
1229
- },
1230
- /* @__PURE__ */ React5.createElement(SortableTrigger, { ...sortableTriggerProps }),
1231
- /* @__PURE__ */ React5.createElement(
1232
- import_ui5.Box,
1233
- {
1234
- sx: { display: "flex", alignItems: "center", color: "text.primary", fontSize: 12, padding: 0.25 }
1235
- },
1236
- /* @__PURE__ */ React5.createElement("i", { className: icon })
1237
- ),
1238
- /* @__PURE__ */ React5.createElement(import_ui5.Typography, { variant: "caption", sx: { color: "text.primary", flexGrow: 1, fontSize: 10 } }, prop.label),
1239
- /* @__PURE__ */ React5.createElement(import_ui5.IconButton, { size: "tiny", onClick: handleDelete, "aria-label": "Delete property", sx: { p: 0.25 } }, /* @__PURE__ */ React5.createElement(import_icons3.XIcon, { fontSize: "tiny" }))
1240
- ), /* @__PURE__ */ React5.createElement(
1241
- import_ui5.Popover,
1242
- {
1243
- ...popoverProps,
1244
- anchorOrigin: { vertical: "bottom", horizontal: "left" },
1245
- transformOrigin: { vertical: "top", horizontal: "left" },
1246
- PaperProps: { sx: { width: popoverState.anchorEl?.getBoundingClientRect().width } }
1247
- },
1248
- /* @__PURE__ */ React5.createElement(
1249
- OverridablePropForm,
1250
- {
1251
- onSubmit: handleSubmit,
1252
- currentValue: prop,
1253
- groups,
1254
- existingLabels,
1255
- sx: { width: "100%" }
1256
- }
1257
- )
1258
- ));
1145
+ })
1146
+ );
1259
1147
  }
1260
- function getElementIcon(prop) {
1261
- const elType = prop.elType === "widget" ? prop.widgetType : prop.elType;
1262
- const widgetsCache = (0, import_editor_elements3.getWidgetsCache)();
1263
- if (!widgetsCache) {
1264
- return "eicon-apps";
1148
+
1149
+ // src/store/actions/reorder-overridable-groups.ts
1150
+ var import_store19 = require("@elementor/store");
1151
+ function reorderOverridableGroups({ componentId, newOrder }) {
1152
+ const overridableProps = selectOverridableProps((0, import_store19.__getState)(), componentId);
1153
+ if (!overridableProps) {
1154
+ return;
1265
1155
  }
1266
- const widgetConfig = widgetsCache[elType];
1267
- return widgetConfig?.icon || "eicon-apps";
1156
+ (0, import_store19.__dispatch)(
1157
+ slice.actions.setOverridableProps({
1158
+ componentId,
1159
+ overridableProps: {
1160
+ ...overridableProps,
1161
+ groups: {
1162
+ ...overridableProps.groups,
1163
+ order: newOrder
1164
+ }
1165
+ }
1166
+ })
1167
+ );
1268
1168
  }
1269
1169
 
1270
- // src/components/component-properties-panel/properties-group.tsx
1271
- function PropertiesGroup({
1272
- group,
1273
- props,
1274
- allGroups,
1275
- sortableTriggerProps,
1276
- isDragPlaceholder,
1277
- onPropsReorder,
1278
- onPropertyDelete,
1279
- onPropertyUpdate,
1280
- onGroupDelete,
1281
- editableLabelProps
1170
+ // src/store/actions/update-overridable-prop-params.ts
1171
+ var import_store21 = require("@elementor/store");
1172
+ function updateOverridablePropParams({
1173
+ componentId,
1174
+ overrideKey,
1175
+ label,
1176
+ groupId
1282
1177
  }) {
1283
- const groupProps = group.props.map((propId) => props[propId]).filter((prop) => Boolean(prop));
1284
- const popupState = (0, import_ui6.usePopupState)({
1285
- variant: "popover",
1286
- disableAutoFocus: true
1287
- });
1288
- const { editableRef, isEditing, error, getEditableProps, setEditingGroupId, editingGroupId } = editableLabelProps;
1289
- const hasProperties = group.props.length > 0;
1290
- const isThisGroupEditing = isEditing && editingGroupId === group.id;
1291
- const handleRenameClick = () => {
1292
- popupState.close();
1293
- setEditingGroupId(group.id);
1294
- };
1295
- const handleDeleteClick = () => {
1296
- popupState.close();
1297
- onGroupDelete(group.id);
1178
+ const overridableProps = selectOverridableProps((0, import_store21.__getState)(), componentId);
1179
+ if (!overridableProps) {
1180
+ return;
1181
+ }
1182
+ const prop = overridableProps.props[overrideKey];
1183
+ if (!prop) {
1184
+ return;
1185
+ }
1186
+ const oldGroupId = prop.groupId;
1187
+ const newGroupId = groupId ?? oldGroupId;
1188
+ const updatedProp = {
1189
+ ...prop,
1190
+ label,
1191
+ groupId: newGroupId
1298
1192
  };
1299
- return /* @__PURE__ */ React6.createElement(
1300
- import_ui6.Box,
1301
- {
1302
- sx: {
1303
- opacity: isDragPlaceholder ? 0.5 : 1
1193
+ const updatedGroups = movePropBetweenGroups(overridableProps.groups, overrideKey, oldGroupId, newGroupId);
1194
+ (0, import_store21.__dispatch)(
1195
+ slice.actions.setOverridableProps({
1196
+ componentId,
1197
+ overridableProps: {
1198
+ ...overridableProps,
1199
+ props: {
1200
+ ...overridableProps.props,
1201
+ [overrideKey]: updatedProp
1202
+ },
1203
+ groups: updatedGroups
1304
1204
  }
1305
- },
1306
- /* @__PURE__ */ React6.createElement(import_ui6.Stack, { gap: 1 }, /* @__PURE__ */ React6.createElement(
1307
- import_ui6.Box,
1308
- {
1309
- className: "group-header",
1310
- sx: {
1311
- position: "relative",
1312
- "&:hover .group-sortable-trigger": {
1313
- visibility: "visible"
1314
- },
1315
- "& .group-sortable-trigger": {
1316
- visibility: "hidden"
1317
- },
1318
- "&:hover .group-menu": {
1319
- visibility: "visible"
1320
- },
1321
- "& .group-menu": {
1322
- visibility: "hidden"
1323
- }
1324
- }
1205
+ })
1206
+ );
1207
+ return updatedProp;
1208
+ }
1209
+
1210
+ // src/components/component-panel-header/use-overridable-props.ts
1211
+ var import_store23 = require("@elementor/store");
1212
+ function useOverridableProps2(componentId) {
1213
+ return (0, import_store23.__useSelector)((state) => {
1214
+ if (!componentId) {
1215
+ return void 0;
1216
+ }
1217
+ return selectOverridableProps(state, componentId);
1218
+ });
1219
+ }
1220
+
1221
+ // src/components/component-properties-panel/properties-empty-state.tsx
1222
+ var React2 = __toESM(require("react"));
1223
+ var import_react2 = require("react");
1224
+ var import_icons = require("@elementor/icons");
1225
+ var import_ui2 = require("@elementor/ui");
1226
+ var import_i18n4 = require("@wordpress/i18n");
1227
+
1228
+ // src/components/components-tab/component-introduction.tsx
1229
+ var React = __toESM(require("react"));
1230
+ var import_editor_controls = require("@elementor/editor-controls");
1231
+ var import_editor_ui = require("@elementor/editor-ui");
1232
+ var import_ui = require("@elementor/ui");
1233
+ var import_i18n3 = require("@wordpress/i18n");
1234
+ var ComponentIntroduction = ({
1235
+ anchorRef,
1236
+ shouldShowIntroduction,
1237
+ onClose
1238
+ }) => {
1239
+ if (!anchorRef.current || !shouldShowIntroduction) {
1240
+ return null;
1241
+ }
1242
+ return /* @__PURE__ */ React.createElement(
1243
+ import_ui.Popover,
1244
+ {
1245
+ anchorEl: anchorRef.current,
1246
+ open: shouldShowIntroduction,
1247
+ anchorOrigin: {
1248
+ vertical: "top",
1249
+ horizontal: "right"
1325
1250
  },
1326
- /* @__PURE__ */ React6.createElement(SortableTrigger, { triggerClassName: "group-sortable-trigger", ...sortableTriggerProps }),
1327
- /* @__PURE__ */ React6.createElement(import_ui6.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", gap: 2 }, isThisGroupEditing ? /* @__PURE__ */ React6.createElement(
1328
- import_ui6.Box,
1329
- {
1330
- sx: {
1331
- flex: 1,
1332
- height: 28,
1333
- display: "flex",
1334
- alignItems: "center",
1335
- border: 2,
1336
- borderColor: "text.secondary",
1337
- borderRadius: 1,
1338
- pl: 0.5
1339
- }
1340
- },
1341
- /* @__PURE__ */ React6.createElement(
1342
- import_editor_ui3.EditableField,
1343
- {
1344
- ref: editableRef,
1345
- as: import_ui6.Typography,
1346
- variant: "caption",
1347
- error: error ?? void 0,
1348
- sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 },
1349
- ...getEditableProps()
1350
- }
1351
- )
1352
- ) : /* @__PURE__ */ React6.createElement(
1353
- import_ui6.Typography,
1354
- {
1355
- variant: "caption",
1356
- sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 }
1357
- },
1358
- group.label
1359
- ), /* @__PURE__ */ React6.createElement(
1360
- import_ui6.IconButton,
1361
- {
1362
- className: "group-menu",
1363
- size: "tiny",
1364
- sx: { p: 0.25, visibility: isThisGroupEditing ? "visible" : void 0 },
1365
- "aria-label": (0, import_i18n6.__)("Group actions", "elementor"),
1366
- ...(0, import_ui6.bindTrigger)(popupState)
1367
- },
1368
- /* @__PURE__ */ React6.createElement(import_icons4.DotsVerticalIcon, { fontSize: "tiny" })
1369
- ))
1370
- ), /* @__PURE__ */ React6.createElement(import_ui6.List, { sx: { p: 0, display: "flex", flexDirection: "column", gap: 1 } }, /* @__PURE__ */ React6.createElement(SortableProvider, { value: group.props, onChange: onPropsReorder }, groupProps.map((prop) => /* @__PURE__ */ React6.createElement(SortableItem, { key: prop.overrideKey, id: prop.overrideKey }, ({ triggerProps, triggerStyle, isDragPlaceholder: isItemDragPlaceholder }) => /* @__PURE__ */ React6.createElement(
1371
- PropertyItem,
1251
+ transformOrigin: {
1252
+ vertical: "top",
1253
+ horizontal: -30
1254
+ },
1255
+ onClose
1256
+ },
1257
+ /* @__PURE__ */ React.createElement(import_ui.Box, { sx: { width: "296px" } }, /* @__PURE__ */ React.createElement(import_editor_ui.PopoverHeader, { title: (0, import_i18n3.__)("Add your first property", "elementor"), onClose }), /* @__PURE__ */ React.createElement(
1258
+ import_ui.Image,
1372
1259
  {
1373
- prop,
1374
- sortableTriggerProps: { ...triggerProps, style: triggerStyle },
1375
- isDragPlaceholder: isItemDragPlaceholder,
1376
- groups: allGroups,
1377
- existingLabels: Object.values(props).map((p) => p.label),
1378
- onDelete: onPropertyDelete,
1379
- onUpdate: (data) => onPropertyUpdate(prop.overrideKey, data)
1260
+ sx: { width: "296px", height: "160px" },
1261
+ src: "https://assets.elementor.com/packages/v1/images/components-properties-intro.png",
1262
+ alt: ""
1380
1263
  }
1381
- )))))),
1382
- /* @__PURE__ */ React6.createElement(
1383
- import_ui6.Menu,
1264
+ ), /* @__PURE__ */ React.createElement(import_editor_controls.PopoverContent, null, /* @__PURE__ */ React.createElement(import_ui.Stack, { sx: { p: 2 } }, /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2" }, (0, import_i18n3.__)("Properties make instances flexible.", "elementor")), /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2" }, (0, import_i18n3.__)(
1265
+ "Click next to any setting you want users to customize - like text, images, or links.",
1266
+ "elementor"
1267
+ )), /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "body2", sx: { mt: 2 } }, (0, import_i18n3.__)(
1268
+ "Your properties will appear in the Properties panel, where you can organize and manage them anytime.",
1269
+ "elementor"
1270
+ )), /* @__PURE__ */ React.createElement(
1271
+ import_ui.Link,
1384
1272
  {
1385
- ...(0, import_ui6.bindMenu)(popupState),
1386
- anchorOrigin: { vertical: "bottom", horizontal: "right" },
1387
- transformOrigin: { vertical: "top", horizontal: "right" }
1273
+ href: "http://go.elementor.com/components-guide",
1274
+ target: "_blank",
1275
+ sx: { mt: 2 },
1276
+ color: "info.main",
1277
+ variant: "body2"
1388
1278
  },
1389
- /* @__PURE__ */ React6.createElement(import_editor_ui3.MenuListItem, { sx: { minWidth: "160px" }, onClick: handleRenameClick }, /* @__PURE__ */ React6.createElement(import_ui6.Typography, { variant: "caption", sx: { color: "text.primary" } }, (0, import_i18n6.__)("Rename", "elementor"))),
1390
- /* @__PURE__ */ React6.createElement(
1391
- import_ui6.Tooltip,
1392
- {
1393
- title: hasProperties ? (0, import_i18n6.__)("To delete the group, first remove all the properties", "elementor") : "",
1394
- placement: "right"
1395
- },
1396
- /* @__PURE__ */ React6.createElement("span", null, /* @__PURE__ */ React6.createElement(import_editor_ui3.MenuListItem, { onClick: handleDeleteClick, disabled: hasProperties }, /* @__PURE__ */ React6.createElement(
1397
- import_ui6.Typography,
1398
- {
1399
- variant: "caption",
1400
- sx: { color: hasProperties ? "text.disabled" : "error.light" }
1401
- },
1402
- (0, import_i18n6.__)("Delete", "elementor")
1403
- )))
1404
- )
1405
- )
1279
+ (0, import_i18n3.__)("Learn more", "elementor")
1280
+ ), /* @__PURE__ */ React.createElement(import_ui.Stack, { direction: "row", alignItems: "center", justifyContent: "flex-end", sx: { pt: 1 } }, /* @__PURE__ */ React.createElement(import_ui.Button, { size: "medium", variant: "contained", onClick: onClose }, (0, import_i18n3.__)("Got it", "elementor"))))))
1406
1281
  );
1407
- }
1408
-
1409
- // src/components/component-properties-panel/use-current-editable-item.ts
1410
- var import_react4 = require("react");
1411
- var import_editor_documents3 = require("@elementor/editor-documents");
1412
- var import_editor_ui4 = require("@elementor/editor-ui");
1413
- var import_i18n8 = require("@wordpress/i18n");
1282
+ };
1414
1283
 
1415
- // src/store/actions/rename-overridable-group.ts
1416
- var import_store23 = require("@elementor/store");
1417
- function renameOverridableGroup({ componentId, groupId, label }) {
1418
- const overridableProps = selectOverridableProps((0, import_store23.__getState)(), componentId);
1419
- if (!overridableProps) {
1420
- return false;
1421
- }
1422
- const group = overridableProps.groups.items[groupId];
1423
- if (!group) {
1424
- return false;
1425
- }
1426
- const updatedGroups = renameGroup(overridableProps.groups, groupId, label);
1427
- (0, import_store23.__dispatch)(
1428
- slice.actions.setOverridableProps({
1429
- componentId,
1430
- overridableProps: {
1431
- ...overridableProps,
1432
- groups: updatedGroups
1433
- }
1434
- })
1435
- );
1436
- return true;
1284
+ // src/components/component-properties-panel/properties-empty-state.tsx
1285
+ function PropertiesEmptyState({ introductionRef }) {
1286
+ const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
1287
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
1288
+ import_ui2.Stack,
1289
+ {
1290
+ alignItems: "center",
1291
+ justifyContent: "flex-start",
1292
+ height: "100%",
1293
+ color: "text.secondary",
1294
+ sx: { px: 2.5, pt: 10, pb: 5.5 },
1295
+ gap: 1
1296
+ },
1297
+ /* @__PURE__ */ React2.createElement(import_icons.ComponentPropListIcon, { fontSize: "large" }),
1298
+ /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "subtitle2" }, (0, import_i18n4.__)("Add your first property", "elementor")),
1299
+ /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "caption" }, (0, import_i18n4.__)("Make instances flexible while keeping design synced.", "elementor")),
1300
+ /* @__PURE__ */ React2.createElement(import_ui2.Typography, { align: "center", variant: "caption" }, (0, import_i18n4.__)("Select any element, then click + next to a setting to expose it.", "elementor")),
1301
+ /* @__PURE__ */ React2.createElement(
1302
+ import_ui2.Link,
1303
+ {
1304
+ variant: "caption",
1305
+ color: "secondary",
1306
+ sx: { textDecorationLine: "underline" },
1307
+ onClick: () => setIsOpen(true)
1308
+ },
1309
+ (0, import_i18n4.__)("Learn more", "elementor")
1310
+ )
1311
+ ), /* @__PURE__ */ React2.createElement(
1312
+ ComponentIntroduction,
1313
+ {
1314
+ anchorRef: introductionRef,
1315
+ shouldShowIntroduction: isOpen,
1316
+ onClose: () => setIsOpen(false)
1317
+ }
1318
+ ));
1437
1319
  }
1438
1320
 
1439
- // src/components/component-properties-panel/utils/validate-group-label.ts
1321
+ // src/components/component-properties-panel/properties-group.tsx
1322
+ var React6 = __toESM(require("react"));
1323
+ var import_editor_ui3 = require("@elementor/editor-ui");
1324
+ var import_icons4 = require("@elementor/icons");
1325
+ var import_ui6 = require("@elementor/ui");
1440
1326
  var import_i18n7 = require("@wordpress/i18n");
1441
- var ERROR_MESSAGES2 = {
1442
- EMPTY_NAME: (0, import_i18n7.__)("Group name is required", "elementor"),
1443
- DUPLICATE_NAME: (0, import_i18n7.__)("Group name already exists", "elementor")
1444
- };
1445
- function validateGroupLabel(label, existingGroups) {
1446
- const trimmedLabel = label.trim();
1447
- if (!trimmedLabel) {
1448
- return ERROR_MESSAGES2.EMPTY_NAME;
1449
- }
1450
- const isDuplicate = Object.values(existingGroups).some((group) => group.label === trimmedLabel);
1451
- if (isDuplicate) {
1452
- return ERROR_MESSAGES2.DUPLICATE_NAME;
1453
- }
1454
- return "";
1455
- }
1456
1327
 
1457
- // src/components/component-properties-panel/use-current-editable-item.ts
1458
- function useCurrentEditableItem() {
1459
- const [editingGroupId, setEditingGroupId] = (0, import_react4.useState)(null);
1460
- const currentComponentId = useCurrentComponentId();
1461
- const overridableProps = useOverridableProps2(currentComponentId);
1462
- const allGroupsRecord = overridableProps?.groups?.items ?? {};
1463
- const currentGroup = editingGroupId ? allGroupsRecord[editingGroupId] : null;
1464
- const validateLabel = (newLabel) => {
1465
- const otherGroups = Object.fromEntries(
1466
- Object.entries(allGroupsRecord).filter(([id2]) => id2 !== editingGroupId)
1467
- );
1468
- return validateGroupLabel(newLabel, otherGroups) || null;
1469
- };
1470
- const handleSubmit = (newLabel) => {
1471
- if (!editingGroupId || !currentComponentId) {
1472
- throw new Error((0, import_i18n8.__)("Group ID or component ID is missing", "elementor"));
1473
- }
1474
- renameOverridableGroup({
1475
- componentId: currentComponentId,
1476
- groupId: editingGroupId,
1477
- label: newLabel
1478
- });
1479
- (0, import_editor_documents3.setDocumentModifiedStatus)(true);
1480
- };
1481
- const {
1482
- ref: editableRef,
1483
- openEditMode,
1484
- isEditing,
1485
- error,
1486
- getProps: getEditableProps
1487
- } = (0, import_editor_ui4.useEditable)({
1488
- value: currentGroup?.label ?? "",
1489
- onSubmit: handleSubmit,
1490
- validation: validateLabel
1491
- });
1492
- return {
1493
- editableRef,
1494
- isEditing,
1495
- error,
1496
- getEditableProps,
1497
- setEditingGroupId: (groupId) => {
1498
- setEditingGroupId(groupId);
1499
- openEditMode();
1500
- },
1501
- editingGroupId
1502
- };
1503
- }
1328
+ // src/components/component-properties-panel/property-item.tsx
1329
+ var React5 = __toESM(require("react"));
1330
+ var import_editor_elements3 = require("@elementor/editor-elements");
1331
+ var import_icons3 = require("@elementor/icons");
1332
+ var import_ui5 = require("@elementor/ui");
1504
1333
 
1505
- // src/components/component-properties-panel/utils/generate-unique-label.ts
1506
- var DEFAULT_NEW_GROUP_LABEL = "New group";
1507
- function generateUniqueLabel(groups) {
1508
- const existingLabels = new Set(groups.map((group) => group.label));
1509
- if (!existingLabels.has(DEFAULT_NEW_GROUP_LABEL)) {
1510
- return DEFAULT_NEW_GROUP_LABEL;
1511
- }
1512
- let index = 1;
1513
- let newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
1514
- while (existingLabels.has(newLabel)) {
1515
- index++;
1516
- newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
1517
- }
1518
- return newLabel;
1519
- }
1334
+ // src/components/overridable-props/overridable-prop-form.tsx
1335
+ var React3 = __toESM(require("react"));
1336
+ var import_react3 = require("react");
1337
+ var import_editor_ui2 = require("@elementor/editor-ui");
1338
+ var import_ui3 = require("@elementor/ui");
1339
+ var import_i18n6 = require("@wordpress/i18n");
1520
1340
 
1521
- // src/components/component-properties-panel/component-properties-panel-content.tsx
1522
- function ComponentPropertiesPanelContent({ onClose }) {
1523
- const currentComponentId = useCurrentComponentId();
1524
- const overridableProps = useOverridableProps2(currentComponentId);
1525
- const [isAddingGroup, setIsAddingGroup] = (0, import_react5.useState)(false);
1526
- const introductionRef = (0, import_react5.useRef)(null);
1527
- const groupLabelEditable = useCurrentEditableItem();
1528
- const groups = (0, import_react5.useMemo)(() => {
1529
- if (!overridableProps) {
1530
- return [];
1531
- }
1532
- return overridableProps.groups.order.map((groupId) => overridableProps.groups.items[groupId] ?? null).filter(Boolean);
1533
- }, [overridableProps]);
1534
- const allGroupsForSelect = (0, import_react5.useMemo)(
1535
- () => groups.map((group) => ({ value: group.id, label: group.label })),
1536
- [groups]
1537
- );
1538
- if (!currentComponentId || !overridableProps) {
1539
- return null;
1341
+ // src/components/overridable-props/utils/validate-prop-label.ts
1342
+ var import_i18n5 = require("@wordpress/i18n");
1343
+ var ERROR_MESSAGES = {
1344
+ EMPTY_NAME: (0, import_i18n5.__)("Property name is required", "elementor"),
1345
+ DUPLICATE_NAME: (0, import_i18n5.__)("Property name already exists", "elementor")
1346
+ };
1347
+ function validatePropLabel(label, existingLabels, currentLabel) {
1348
+ const trimmedLabel = label.trim();
1349
+ if (!trimmedLabel) {
1350
+ return { isValid: false, errorMessage: ERROR_MESSAGES.EMPTY_NAME };
1540
1351
  }
1541
- const hasGroups = groups.length > 0;
1542
- const showEmptyState = !hasGroups && !isAddingGroup;
1543
- const groupIds = overridableProps.groups.order;
1544
- const handleAddGroupClick = () => {
1545
- if (isAddingGroup) {
1546
- return;
1547
- }
1548
- const newGroupId = (0, import_utils2.generateUniqueId)("group");
1549
- const newLabel = generateUniqueLabel(groups);
1550
- addOverridableGroup({
1551
- componentId: currentComponentId,
1552
- groupId: newGroupId,
1553
- label: newLabel,
1554
- source: "user"
1555
- });
1556
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1557
- setIsAddingGroup(false);
1558
- groupLabelEditable.setEditingGroupId(newGroupId);
1559
- };
1560
- const handleGroupsReorder = (newOrder) => {
1561
- reorderOverridableGroups({ componentId: currentComponentId, newOrder });
1562
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1563
- };
1564
- const handlePropsReorder = (groupId, newPropsOrder) => {
1565
- reorderGroupProps({ componentId: currentComponentId, groupId, newPropsOrder });
1566
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1567
- };
1568
- const handlePropertyDelete = (propKey) => {
1569
- deleteOverridableProp({ componentId: currentComponentId, propKey, source: "user" });
1570
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1571
- };
1572
- const handlePropertyUpdate = (overrideKey, data) => {
1573
- updateOverridablePropParams({
1574
- componentId: currentComponentId,
1575
- overrideKey,
1576
- label: data.label,
1577
- groupId: data.group
1578
- });
1579
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1580
- };
1581
- const handleGroupDelete = (groupId) => {
1582
- deleteOverridableGroup({ componentId: currentComponentId, groupId });
1583
- (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1352
+ const normalizedLabel = trimmedLabel.toLowerCase();
1353
+ const normalizedCurrentLabel = currentLabel?.trim().toLowerCase();
1354
+ const isDuplicate = existingLabels.some((existingLabel) => {
1355
+ const normalizedExisting = existingLabel.trim().toLowerCase();
1356
+ if (normalizedCurrentLabel && normalizedExisting === normalizedCurrentLabel) {
1357
+ return false;
1358
+ }
1359
+ return normalizedExisting === normalizedLabel;
1360
+ });
1361
+ if (isDuplicate) {
1362
+ return { isValid: false, errorMessage: ERROR_MESSAGES.DUPLICATE_NAME };
1363
+ }
1364
+ return { isValid: true, errorMessage: null };
1365
+ }
1366
+
1367
+ // src/components/overridable-props/overridable-prop-form.tsx
1368
+ var SIZE = "tiny";
1369
+ var DEFAULT_GROUP = { value: null, label: (0, import_i18n6.__)("Default", "elementor") };
1370
+ function OverridablePropForm({ onSubmit, groups, currentValue, existingLabels = [], sx }) {
1371
+ const [propLabel, setPropLabel] = (0, import_react3.useState)(currentValue?.label ?? null);
1372
+ const [group, setGroup] = (0, import_react3.useState)(currentValue?.groupId ?? groups?.[0]?.value ?? null);
1373
+ const [error, setError] = (0, import_react3.useState)(null);
1374
+ const name = (0, import_i18n6.__)("Name", "elementor");
1375
+ const groupName = (0, import_i18n6.__)("Group Name", "elementor");
1376
+ const isCreate = currentValue === void 0;
1377
+ const title = isCreate ? (0, import_i18n6.__)("Create new property", "elementor") : (0, import_i18n6.__)("Update property", "elementor");
1378
+ const ctaLabel = isCreate ? (0, import_i18n6.__)("Create", "elementor") : (0, import_i18n6.__)("Update", "elementor");
1379
+ const handleSubmit = () => {
1380
+ const validationResult = validatePropLabel(propLabel ?? "", existingLabels, currentValue?.label);
1381
+ if (!validationResult.isValid) {
1382
+ setError(validationResult.errorMessage);
1383
+ return;
1384
+ }
1385
+ onSubmit({ label: propLabel ?? "", group });
1584
1386
  };
1585
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(import_editor_panels.PanelHeader, { sx: { justifyContent: "start", pl: 1.5, pr: 1, py: 1 } }, /* @__PURE__ */ React7.createElement(import_ui7.Stack, { direction: "row", alignItems: "center", gap: 0.5, flexGrow: 1 }, /* @__PURE__ */ React7.createElement(import_icons5.ComponentPropListIcon, { fontSize: "tiny" }), /* @__PURE__ */ React7.createElement(import_editor_panels.PanelHeaderTitle, { variant: "subtitle2" }, (0, import_i18n9.__)("Component properties", "elementor"))), !showEmptyState && /* @__PURE__ */ React7.createElement(import_ui7.Tooltip, { title: (0, import_i18n9.__)("Add new group", "elementor") }, /* @__PURE__ */ React7.createElement(
1586
- import_ui7.IconButton,
1387
+ return /* @__PURE__ */ React3.createElement(import_editor_ui2.Form, { onSubmit: handleSubmit }, /* @__PURE__ */ React3.createElement(import_ui3.Stack, { alignItems: "start", sx: { width: "268px", ...sx } }, /* @__PURE__ */ React3.createElement(
1388
+ import_ui3.Stack,
1587
1389
  {
1588
- size: "tiny",
1589
- "aria-label": (0, import_i18n9.__)("Add new group", "elementor"),
1590
- onClick: handleAddGroupClick
1390
+ direction: "row",
1391
+ alignItems: "center",
1392
+ py: 1,
1393
+ px: 1.5,
1394
+ sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
1591
1395
  },
1592
- /* @__PURE__ */ React7.createElement(import_icons5.FolderPlusIcon, { fontSize: "tiny" })
1593
- )), /* @__PURE__ */ React7.createElement(import_ui7.Tooltip, { title: (0, import_i18n9.__)("Close panel", "elementor") }, /* @__PURE__ */ React7.createElement(
1594
- import_ui7.IconButton,
1396
+ /* @__PURE__ */ React3.createElement(import_ui3.Typography, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, title)
1397
+ ), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(import_ui3.FormLabel, { size: "tiny" }, name)), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(
1398
+ import_ui3.TextField,
1595
1399
  {
1596
- ref: introductionRef,
1597
- size: "tiny",
1598
- "aria-label": (0, import_i18n9.__)("Close panel", "elementor"),
1599
- onClick: onClose
1400
+ name,
1401
+ size: SIZE,
1402
+ fullWidth: true,
1403
+ placeholder: (0, import_i18n6.__)("Enter value", "elementor"),
1404
+ value: propLabel ?? "",
1405
+ onChange: (e) => {
1406
+ const newValue = e.target.value;
1407
+ setPropLabel(newValue);
1408
+ const validationResult = validatePropLabel(
1409
+ newValue,
1410
+ existingLabels,
1411
+ currentValue?.label
1412
+ );
1413
+ setError(validationResult.errorMessage);
1414
+ },
1415
+ error: Boolean(error),
1416
+ helperText: error
1417
+ }
1418
+ ))), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(import_ui3.FormLabel, { size: "tiny" }, groupName)), /* @__PURE__ */ React3.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React3.createElement(
1419
+ import_ui3.Select,
1420
+ {
1421
+ name: groupName,
1422
+ size: SIZE,
1423
+ fullWidth: true,
1424
+ value: group ?? null,
1425
+ onChange: (e) => setGroup(e.target.value),
1426
+ displayEmpty: true,
1427
+ renderValue: (selectedValue) => {
1428
+ if (!selectedValue || selectedValue === "") {
1429
+ const [firstGroup = DEFAULT_GROUP] = groups ?? [];
1430
+ return firstGroup.label;
1431
+ }
1432
+ return groups?.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
1433
+ }
1600
1434
  },
1601
- /* @__PURE__ */ React7.createElement(import_icons5.XIcon, { fontSize: "tiny" })
1602
- ))), /* @__PURE__ */ React7.createElement(import_ui7.Divider, null), /* @__PURE__ */ React7.createElement(import_editor_panels.PanelBody, null, showEmptyState ? /* @__PURE__ */ React7.createElement(PropertiesEmptyState, { introductionRef }) : /* @__PURE__ */ React7.createElement(import_ui7.List, { sx: { p: 2, display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ React7.createElement(SortableProvider, { value: groupIds, onChange: handleGroupsReorder }, groups.map((group) => /* @__PURE__ */ React7.createElement(SortableItem, { key: group.id, id: group.id }, ({ triggerProps, triggerStyle, isDragPlaceholder }) => /* @__PURE__ */ React7.createElement(
1603
- PropertiesGroup,
1435
+ (groups ?? [DEFAULT_GROUP]).map(({ label: groupLabel, ...props }) => /* @__PURE__ */ React3.createElement(import_editor_ui2.MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, groupLabel))
1436
+ ))), /* @__PURE__ */ React3.createElement(import_ui3.Stack, { direction: "row", justifyContent: "flex-end", alignSelf: "end", mt: 1.5, py: 1, px: 1.5 }, /* @__PURE__ */ React3.createElement(
1437
+ import_ui3.Button,
1604
1438
  {
1605
- group,
1606
- props: overridableProps.props,
1607
- allGroups: allGroupsForSelect,
1608
- allGroupsRecord: overridableProps.groups.items,
1609
- sortableTriggerProps: { ...triggerProps, style: triggerStyle },
1610
- isDragPlaceholder,
1611
- setIsAddingGroup,
1612
- onPropsReorder: (newOrder) => handlePropsReorder(group.id, newOrder),
1613
- onPropertyDelete: handlePropertyDelete,
1614
- onPropertyUpdate: handlePropertyUpdate,
1615
- editableLabelProps: groupLabelEditable,
1616
- onGroupDelete: handleGroupDelete
1617
- }
1618
- )))))));
1439
+ type: "submit",
1440
+ disabled: !propLabel || Boolean(error),
1441
+ variant: "contained",
1442
+ color: "primary",
1443
+ size: "small"
1444
+ },
1445
+ ctaLabel
1446
+ ))));
1619
1447
  }
1620
1448
 
1621
- // src/components/component-properties-panel/component-properties-panel.tsx
1622
- var id = "component-properties-panel";
1623
- var { panel, usePanelActions } = (0, import_editor_panels2.__createPanel)({
1624
- id,
1625
- component: ComponentPropertiesPanel
1626
- });
1627
- function ComponentPropertiesPanel() {
1628
- const { element, elementType } = (0, import_editor_elements4.useSelectedElement)();
1629
- const { close: closePanel } = usePanelActions();
1630
- const { open: openEditingPanel } = (0, import_editor_editing_panel.usePanelActions)();
1631
- if (!element || !elementType) {
1632
- return null;
1449
+ // src/components/component-properties-panel/sortable.tsx
1450
+ var React4 = __toESM(require("react"));
1451
+ var import_icons2 = require("@elementor/icons");
1452
+ var import_ui4 = require("@elementor/ui");
1453
+ var SortableProvider = (props) => /* @__PURE__ */ React4.createElement(import_ui4.UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
1454
+ var SortableTrigger = ({ triggerClassName, ...props }) => /* @__PURE__ */ React4.createElement(
1455
+ StyledSortableTrigger,
1456
+ {
1457
+ ...props,
1458
+ role: "button",
1459
+ className: `sortable-trigger ${triggerClassName ?? ""}`.trim(),
1460
+ "aria-label": "sort"
1461
+ },
1462
+ /* @__PURE__ */ React4.createElement(import_icons2.GripVerticalIcon, { fontSize: "tiny" })
1463
+ );
1464
+ var SortableItem = ({ children, id: id2 }) => /* @__PURE__ */ React4.createElement(
1465
+ import_ui4.UnstableSortableItem,
1466
+ {
1467
+ id: id2,
1468
+ render: ({
1469
+ itemProps,
1470
+ isDragged,
1471
+ triggerProps,
1472
+ itemStyle,
1473
+ triggerStyle,
1474
+ dropIndicationStyle,
1475
+ showDropIndication,
1476
+ isDragOverlay,
1477
+ isDragPlaceholder
1478
+ }) => /* @__PURE__ */ React4.createElement(
1479
+ import_ui4.Box,
1480
+ {
1481
+ ...itemProps,
1482
+ style: itemStyle,
1483
+ component: "div",
1484
+ role: "listitem",
1485
+ sx: {
1486
+ backgroundColor: isDragOverlay ? "background.paper" : void 0
1487
+ }
1488
+ },
1489
+ children({
1490
+ isDragged,
1491
+ isDragPlaceholder,
1492
+ triggerProps,
1493
+ triggerStyle
1494
+ }),
1495
+ showDropIndication && /* @__PURE__ */ React4.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1496
+ )
1633
1497
  }
1634
- return /* @__PURE__ */ React8.createElement(import_editor_ui5.ThemeProvider, null, /* @__PURE__ */ React8.createElement(import_ui8.ErrorBoundary, { fallback: /* @__PURE__ */ React8.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React8.createElement(import_editor_editing_panel.ElementProvider, { element, elementType }, /* @__PURE__ */ React8.createElement(import_editor_panels2.Panel, null, /* @__PURE__ */ React8.createElement(
1635
- ComponentPropertiesPanelContent,
1636
- {
1637
- onClose: () => {
1638
- closePanel();
1639
- openEditingPanel();
1640
- }
1641
- }
1642
- )))));
1643
- }
1644
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React8.createElement(import_ui8.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React8.createElement(import_ui8.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React8.createElement("strong", null, (0, import_i18n10.__)("Something went wrong", "elementor"))));
1498
+ );
1499
+ var StyledSortableTrigger = (0, import_ui4.styled)("div")(({ theme }) => ({
1500
+ position: "absolute",
1501
+ left: "-2px",
1502
+ top: "50%",
1503
+ transform: `translate( -${theme.spacing(1.5)}, -50% )`,
1504
+ color: theme.palette.action.active,
1505
+ cursor: "grab"
1506
+ }));
1507
+ var SortableItemIndicator = (0, import_ui4.styled)(import_ui4.Box)`
1508
+ width: 100%;
1509
+ height: 1px;
1510
+ background-color: ${({ theme }) => theme.palette.text.primary};
1511
+ `;
1645
1512
 
1646
- // src/components/component-panel-header/component-badge.tsx
1647
- var React9 = __toESM(require("react"));
1648
- var import_react6 = require("react");
1649
- var import_icons6 = require("@elementor/icons");
1650
- var import_ui9 = require("@elementor/ui");
1651
- var import_i18n11 = require("@wordpress/i18n");
1652
- var ComponentsBadge = React9.forwardRef(({ overridablePropsCount, onClick }, ref) => {
1653
- const prevCount = usePrevious(overridablePropsCount);
1654
- const isFirstExposedProperty = prevCount === 0 && overridablePropsCount === 1;
1655
- return /* @__PURE__ */ React9.createElement(
1656
- StyledBadge,
1513
+ // src/components/component-properties-panel/property-item.tsx
1514
+ function PropertyItem({
1515
+ prop,
1516
+ sortableTriggerProps,
1517
+ isDragPlaceholder,
1518
+ groups,
1519
+ existingLabels,
1520
+ onDelete,
1521
+ onUpdate
1522
+ }) {
1523
+ const popoverState = (0, import_ui5.usePopupState)({
1524
+ variant: "popover"
1525
+ });
1526
+ const icon = getElementIcon(prop);
1527
+ const popoverProps = (0, import_ui5.bindPopover)(popoverState);
1528
+ const handleSubmit = (data) => {
1529
+ onUpdate(data);
1530
+ popoverState.close();
1531
+ };
1532
+ const handleDelete = (event) => {
1533
+ event.stopPropagation();
1534
+ onDelete(prop.overrideKey);
1535
+ };
1536
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(
1537
+ import_ui5.Box,
1657
1538
  {
1658
- ref,
1659
- color: "primary",
1660
- key: overridablePropsCount,
1661
- invisible: overridablePropsCount === 0,
1662
- animate: isFirstExposedProperty,
1663
- anchorOrigin: { vertical: "top", horizontal: "right" },
1664
- badgeContent: /* @__PURE__ */ React9.createElement(import_ui9.Box, { sx: { animation: !isFirstExposedProperty ? `${slideUp} 300ms ease-out` : "none" } }, overridablePropsCount)
1539
+ ...(0, import_ui5.bindTrigger)(popoverState),
1540
+ sx: {
1541
+ position: "relative",
1542
+ pl: 0.5,
1543
+ pr: 1,
1544
+ py: 0.25,
1545
+ minHeight: 28,
1546
+ borderRadius: 1,
1547
+ border: "1px solid",
1548
+ borderColor: "divider",
1549
+ display: "flex",
1550
+ alignItems: "center",
1551
+ gap: 0.5,
1552
+ opacity: isDragPlaceholder ? 0.5 : 1,
1553
+ cursor: "pointer",
1554
+ "&:hover": {
1555
+ backgroundColor: "action.hover"
1556
+ },
1557
+ "&:hover .sortable-trigger": {
1558
+ visibility: "visible"
1559
+ },
1560
+ "& .sortable-trigger": {
1561
+ visibility: "hidden"
1562
+ },
1563
+ "&:hover .delete-button": {
1564
+ visibility: "visible"
1565
+ },
1566
+ "& .delete-button": {
1567
+ visibility: "hidden"
1568
+ }
1569
+ }
1665
1570
  },
1666
- /* @__PURE__ */ React9.createElement(
1667
- import_ui9.ToggleButton,
1571
+ /* @__PURE__ */ React5.createElement(SortableTrigger, { ...sortableTriggerProps }),
1572
+ /* @__PURE__ */ React5.createElement(
1573
+ import_ui5.Box,
1668
1574
  {
1669
- value: "exposed properties",
1670
- size: "tiny",
1671
- onClick,
1672
- "aria-label": (0, import_i18n11.__)("View exposed properties", "elementor")
1575
+ sx: { display: "flex", alignItems: "center", color: "text.primary", fontSize: 12, padding: 0.25 }
1673
1576
  },
1674
- /* @__PURE__ */ React9.createElement(import_icons6.ComponentPropListIcon, { fontSize: "tiny" })
1577
+ /* @__PURE__ */ React5.createElement("i", { className: icon })
1578
+ ),
1579
+ /* @__PURE__ */ React5.createElement(import_ui5.Typography, { variant: "caption", sx: { color: "text.primary", flexGrow: 1, fontSize: 10 } }, prop.label),
1580
+ /* @__PURE__ */ React5.createElement(import_ui5.IconButton, { size: "tiny", onClick: handleDelete, "aria-label": "Delete property", sx: { p: 0.25 } }, /* @__PURE__ */ React5.createElement(import_icons3.XIcon, { fontSize: "tiny" }))
1581
+ ), /* @__PURE__ */ React5.createElement(
1582
+ import_ui5.Popover,
1583
+ {
1584
+ ...popoverProps,
1585
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
1586
+ transformOrigin: { vertical: "top", horizontal: "left" },
1587
+ PaperProps: { sx: { width: popoverState.anchorEl?.getBoundingClientRect().width } }
1588
+ },
1589
+ /* @__PURE__ */ React5.createElement(
1590
+ OverridablePropForm,
1591
+ {
1592
+ onSubmit: handleSubmit,
1593
+ currentValue: prop,
1594
+ groups,
1595
+ existingLabels,
1596
+ sx: { width: "100%" }
1597
+ }
1675
1598
  )
1676
- );
1677
- });
1678
- var StyledBadge = (0, import_ui9.styled)(import_ui9.Badge, { shouldForwardProp: (prop) => prop !== "animate" })(
1679
- ({ theme, animate }) => ({
1680
- "& .MuiBadge-badge": {
1681
- minWidth: theme.spacing(2),
1682
- height: theme.spacing(2),
1683
- minHeight: theme.spacing(2),
1684
- maxWidth: theme.spacing(2),
1685
- fontSize: theme.typography.caption.fontSize,
1686
- animation: animate ? `${bounceIn} 300ms ease-out` : "none"
1687
- }
1688
- })
1689
- );
1690
- function usePrevious(value) {
1691
- const ref = (0, import_react6.useRef)(value);
1692
- (0, import_react6.useEffect)(() => {
1693
- ref.current = value;
1694
- }, [value]);
1695
- return ref.current;
1599
+ ));
1696
1600
  }
1697
- var bounceIn = import_ui9.keyframes`
1698
- 0% { transform: scale(0) translate(50%, 50%); opacity: 0; }
1699
- 70% { transform: scale(1.1) translate(50%, -50%); opacity: 1; }
1700
- 100% { transform: scale(1) translate(50%, -50%); opacity: 1; }
1701
- `;
1702
- var slideUp = import_ui9.keyframes`
1703
- from { transform: translateY(100%); opacity: 0; }
1704
- to { transform: translateY(0); opacity: 1; }
1705
- `;
1706
-
1707
- // src/components/component-panel-header/component-panel-header.tsx
1708
- var MESSAGE_KEY = "components-properties-introduction";
1709
- var ComponentPanelHeader = () => {
1710
- const { id: currentComponentId, uid: componentUid } = useCurrentComponent() ?? { id: null, uid: null };
1711
- const overridableProps = useOverridableProps2(currentComponentId);
1712
- const onBack = useNavigateBack();
1713
- const componentName = getComponentName();
1714
- const [isMessageSuppressed, suppressMessage] = (0, import_editor_current_user.useSuppressedMessage)(MESSAGE_KEY);
1715
- const [shouldShowIntroduction, setShouldShowIntroduction] = React10.useState(!isMessageSuppressed);
1716
- const { open: openPropertiesPanel } = usePanelActions();
1717
- const overridablePropsCount = overridableProps ? Object.keys(overridableProps.props).length : 0;
1718
- const anchorRef = React10.useRef(null);
1719
- if (!currentComponentId) {
1720
- return null;
1601
+ function getElementIcon(prop) {
1602
+ const elType = prop.elType === "widget" ? prop.widgetType : prop.elType;
1603
+ const widgetsCache = (0, import_editor_elements3.getWidgetsCache)();
1604
+ if (!widgetsCache) {
1605
+ return "eicon-apps";
1721
1606
  }
1722
- const handleCloseIntroduction = () => {
1723
- suppressMessage();
1724
- setShouldShowIntroduction(false);
1607
+ const widgetConfig = widgetsCache[elType];
1608
+ return widgetConfig?.icon || "eicon-apps";
1609
+ }
1610
+
1611
+ // src/components/component-properties-panel/properties-group.tsx
1612
+ function PropertiesGroup({
1613
+ group,
1614
+ props,
1615
+ allGroups,
1616
+ sortableTriggerProps,
1617
+ isDragPlaceholder,
1618
+ onPropsReorder,
1619
+ onPropertyDelete,
1620
+ onPropertyUpdate,
1621
+ onGroupDelete,
1622
+ editableLabelProps
1623
+ }) {
1624
+ const groupProps = group.props.map((propId) => props[propId]).filter((prop) => Boolean(prop));
1625
+ const popupState = (0, import_ui6.usePopupState)({
1626
+ variant: "popover",
1627
+ disableAutoFocus: true
1628
+ });
1629
+ const { editableRef, isEditing, error, getEditableProps, setEditingGroupId, editingGroupId } = editableLabelProps;
1630
+ const hasProperties = group.props.length > 0;
1631
+ const isThisGroupEditing = isEditing && editingGroupId === group.id;
1632
+ const handleRenameClick = () => {
1633
+ popupState.close();
1634
+ setEditingGroupId(group.id);
1725
1635
  };
1726
- const handleOpenPropertiesPanel = () => {
1727
- openPropertiesPanel();
1728
- trackComponentEvent({
1729
- action: "propertiesPanelOpened",
1730
- source: "user",
1731
- component_uid: componentUid,
1732
- properties_count: overridablePropsCount
1733
- });
1636
+ const handleDeleteClick = () => {
1637
+ popupState.close();
1638
+ onGroupDelete(group.id);
1734
1639
  };
1735
- return /* @__PURE__ */ React10.createElement(import_ui10.Box, null, /* @__PURE__ */ React10.createElement(
1736
- import_ui10.Stack,
1640
+ return /* @__PURE__ */ React6.createElement(
1641
+ import_ui6.Box,
1737
1642
  {
1738
- direction: "row",
1739
- alignItems: "center",
1740
- justifyContent: "space-between",
1741
- sx: { height: 48, pl: 1.5, pr: 2, py: 1 }
1643
+ sx: {
1644
+ opacity: isDragPlaceholder ? 0.5 : 1
1645
+ }
1742
1646
  },
1743
- /* @__PURE__ */ React10.createElement(import_ui10.Stack, { direction: "row", alignItems: "center" }, /* @__PURE__ */ React10.createElement(import_ui10.Tooltip, { title: (0, import_i18n12.__)("Back", "elementor") }, /* @__PURE__ */ React10.createElement(import_ui10.IconButton, { size: "tiny", onClick: onBack, "aria-label": (0, import_i18n12.__)("Back", "elementor") }, /* @__PURE__ */ React10.createElement(import_icons7.ArrowLeftIcon, { fontSize: "tiny" }))), /* @__PURE__ */ React10.createElement(import_ui10.Stack, { direction: "row", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ React10.createElement(import_icons7.ComponentsFilledIcon, { fontSize: "tiny", stroke: "currentColor" }), /* @__PURE__ */ React10.createElement(import_ui10.Typography, { variant: "caption", sx: { fontWeight: 500 } }, componentName))),
1744
- /* @__PURE__ */ React10.createElement(
1745
- ComponentsBadge,
1647
+ /* @__PURE__ */ React6.createElement(import_ui6.Stack, { gap: 1 }, /* @__PURE__ */ React6.createElement(
1648
+ import_ui6.Box,
1746
1649
  {
1747
- overridablePropsCount,
1748
- ref: anchorRef,
1749
- onClick: handleOpenPropertiesPanel
1650
+ className: "group-header",
1651
+ sx: {
1652
+ position: "relative",
1653
+ "&:hover .group-sortable-trigger": {
1654
+ visibility: "visible"
1655
+ },
1656
+ "& .group-sortable-trigger": {
1657
+ visibility: "hidden"
1658
+ },
1659
+ "&:hover .group-menu": {
1660
+ visibility: "visible"
1661
+ },
1662
+ "& .group-menu": {
1663
+ visibility: "hidden"
1664
+ }
1665
+ }
1666
+ },
1667
+ /* @__PURE__ */ React6.createElement(SortableTrigger, { triggerClassName: "group-sortable-trigger", ...sortableTriggerProps }),
1668
+ /* @__PURE__ */ React6.createElement(import_ui6.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", gap: 2 }, isThisGroupEditing ? /* @__PURE__ */ React6.createElement(
1669
+ import_ui6.Box,
1670
+ {
1671
+ sx: {
1672
+ flex: 1,
1673
+ height: 28,
1674
+ display: "flex",
1675
+ alignItems: "center",
1676
+ border: 2,
1677
+ borderColor: "text.secondary",
1678
+ borderRadius: 1,
1679
+ pl: 0.5
1680
+ }
1681
+ },
1682
+ /* @__PURE__ */ React6.createElement(
1683
+ import_editor_ui3.EditableField,
1684
+ {
1685
+ ref: editableRef,
1686
+ as: import_ui6.Typography,
1687
+ variant: "caption",
1688
+ error: error ?? void 0,
1689
+ sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 },
1690
+ ...getEditableProps()
1691
+ }
1692
+ )
1693
+ ) : /* @__PURE__ */ React6.createElement(
1694
+ import_ui6.Typography,
1695
+ {
1696
+ variant: "caption",
1697
+ sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 }
1698
+ },
1699
+ group.label
1700
+ ), /* @__PURE__ */ React6.createElement(
1701
+ import_ui6.IconButton,
1702
+ {
1703
+ className: "group-menu",
1704
+ size: "tiny",
1705
+ sx: { p: 0.25, visibility: isThisGroupEditing ? "visible" : void 0 },
1706
+ "aria-label": (0, import_i18n7.__)("Group actions", "elementor"),
1707
+ ...(0, import_ui6.bindTrigger)(popupState)
1708
+ },
1709
+ /* @__PURE__ */ React6.createElement(import_icons4.DotsVerticalIcon, { fontSize: "tiny" })
1710
+ ))
1711
+ ), /* @__PURE__ */ React6.createElement(import_ui6.List, { sx: { p: 0, display: "flex", flexDirection: "column", gap: 1 } }, /* @__PURE__ */ React6.createElement(SortableProvider, { value: group.props, onChange: onPropsReorder }, groupProps.map((prop) => /* @__PURE__ */ React6.createElement(SortableItem, { key: prop.overrideKey, id: prop.overrideKey }, ({ triggerProps, triggerStyle, isDragPlaceholder: isItemDragPlaceholder }) => /* @__PURE__ */ React6.createElement(
1712
+ PropertyItem,
1713
+ {
1714
+ prop,
1715
+ sortableTriggerProps: { ...triggerProps, style: triggerStyle },
1716
+ isDragPlaceholder: isItemDragPlaceholder,
1717
+ groups: allGroups,
1718
+ existingLabels: Object.values(props).map((p) => p.label),
1719
+ onDelete: onPropertyDelete,
1720
+ onUpdate: (data) => onPropertyUpdate(prop.overrideKey, data)
1750
1721
  }
1722
+ )))))),
1723
+ /* @__PURE__ */ React6.createElement(
1724
+ import_ui6.Menu,
1725
+ {
1726
+ ...(0, import_ui6.bindMenu)(popupState),
1727
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
1728
+ transformOrigin: { vertical: "top", horizontal: "right" }
1729
+ },
1730
+ /* @__PURE__ */ React6.createElement(import_editor_ui3.MenuListItem, { sx: { minWidth: "160px" }, onClick: handleRenameClick }, /* @__PURE__ */ React6.createElement(import_ui6.Typography, { variant: "caption", sx: { color: "text.primary" } }, (0, import_i18n7.__)("Rename", "elementor"))),
1731
+ /* @__PURE__ */ React6.createElement(
1732
+ import_ui6.Tooltip,
1733
+ {
1734
+ title: hasProperties ? (0, import_i18n7.__)("To delete the group, first remove all the properties", "elementor") : "",
1735
+ placement: "right"
1736
+ },
1737
+ /* @__PURE__ */ React6.createElement("span", null, /* @__PURE__ */ React6.createElement(import_editor_ui3.MenuListItem, { onClick: handleDeleteClick, disabled: hasProperties }, /* @__PURE__ */ React6.createElement(
1738
+ import_ui6.Typography,
1739
+ {
1740
+ variant: "caption",
1741
+ sx: { color: hasProperties ? "text.disabled" : "error.light" }
1742
+ },
1743
+ (0, import_i18n7.__)("Delete", "elementor")
1744
+ )))
1745
+ )
1751
1746
  )
1752
- ), /* @__PURE__ */ React10.createElement(import_ui10.Divider, null), /* @__PURE__ */ React10.createElement(
1753
- ComponentIntroduction,
1754
- {
1755
- anchorRef,
1756
- shouldShowIntroduction,
1757
- onClose: handleCloseIntroduction
1758
- }
1759
- ));
1760
- };
1761
- function getComponentName() {
1762
- const state = (0, import_store27.__getState)();
1763
- const path = state[SLICE_NAME].path;
1764
- const { instanceTitle } = path.at(-1) ?? {};
1765
- if (instanceTitle) {
1766
- return instanceTitle;
1767
- }
1768
- const documentsManager = (0, import_editor_documents5.getV1DocumentsManager)();
1769
- const currentDocument = documentsManager.getCurrent();
1770
- return currentDocument?.container?.settings?.get("post_title") ?? "";
1747
+ );
1771
1748
  }
1772
1749
 
1773
- // src/components/components-tab/components.tsx
1774
- var React19 = __toESM(require("react"));
1775
- var import_editor_ui9 = require("@elementor/editor-ui");
1776
-
1777
- // src/hooks/use-components.ts
1778
- var import_store29 = require("@elementor/store");
1779
- var useComponents = () => {
1780
- const components = (0, import_store29.__useSelector)(selectComponents);
1781
- const isLoading = (0, import_store29.__useSelector)(selectLoadIsPending);
1782
- return { components, isLoading };
1783
- };
1750
+ // src/components/component-properties-panel/use-current-editable-item.ts
1751
+ var import_react4 = require("react");
1752
+ var import_editor_documents4 = require("@elementor/editor-documents");
1753
+ var import_editor_ui4 = require("@elementor/editor-ui");
1754
+ var import_i18n9 = require("@wordpress/i18n");
1784
1755
 
1785
- // src/utils/is-pro-user.ts
1786
- function isProUser() {
1787
- const extendedWindow = window;
1788
- const hasPro = extendedWindow.elementor?.helpers?.hasPro?.() ?? false;
1789
- if (!hasPro) {
1756
+ // src/store/actions/rename-overridable-group.ts
1757
+ var import_store25 = require("@elementor/store");
1758
+ function renameOverridableGroup({ componentId, groupId, label }) {
1759
+ const overridableProps = selectOverridableProps((0, import_store25.__getState)(), componentId);
1760
+ if (!overridableProps) {
1790
1761
  return false;
1791
1762
  }
1792
- const isProActive = extendedWindow.elementorPro?.config?.isActive ?? false;
1793
- return isProActive;
1794
- }
1795
-
1796
- // src/components/components-tab/component-search.tsx
1797
- var React12 = __toESM(require("react"));
1798
- var import_icons8 = require("@elementor/icons");
1799
- var import_ui11 = require("@elementor/ui");
1800
- var import_i18n13 = require("@wordpress/i18n");
1801
-
1802
- // src/components/components-tab/search-provider.tsx
1803
- var React11 = __toESM(require("react"));
1804
- var import_react7 = require("react");
1805
- var import_utils3 = require("@elementor/utils");
1806
- var SearchContext = (0, import_react7.createContext)(void 0);
1807
- var SearchProvider = ({
1808
- children,
1809
- localStorageKey
1810
- }) => {
1811
- const { debouncedValue, handleChange, inputValue } = (0, import_utils3.useSearchState)({ localStorageKey });
1812
- const clearSearch = () => {
1813
- handleChange("");
1814
- };
1815
- return /* @__PURE__ */ React11.createElement(SearchContext.Provider, { value: { handleChange, clearSearch, searchValue: debouncedValue, inputValue } }, children);
1816
- };
1817
- var useSearch = () => {
1818
- const context = (0, import_react7.useContext)(SearchContext);
1819
- if (!context) {
1820
- throw new Error("useSearch must be used within a SearchProvider");
1763
+ const group = overridableProps.groups.items[groupId];
1764
+ if (!group) {
1765
+ return false;
1821
1766
  }
1822
- return context;
1823
- };
1824
-
1825
- // src/components/components-tab/component-search.tsx
1826
- var ComponentSearch = () => {
1827
- const { inputValue, handleChange } = useSearch();
1828
- return /* @__PURE__ */ React12.createElement(import_ui11.Stack, { direction: "row", gap: 0.5, sx: { width: "100%", px: 2, py: 1.5 } }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React12.createElement(
1829
- import_ui11.TextField,
1830
- {
1831
- role: "search",
1832
- fullWidth: true,
1833
- size: "tiny",
1834
- value: inputValue,
1835
- placeholder: (0, import_i18n13.__)("Search", "elementor"),
1836
- onChange: (e) => handleChange(e.target.value),
1837
- InputProps: {
1838
- startAdornment: /* @__PURE__ */ React12.createElement(import_ui11.InputAdornment, { position: "start" }, /* @__PURE__ */ React12.createElement(import_icons8.SearchIcon, { fontSize: "tiny" }))
1767
+ const updatedGroups = renameGroup(overridableProps.groups, groupId, label);
1768
+ (0, import_store25.__dispatch)(
1769
+ slice.actions.setOverridableProps({
1770
+ componentId,
1771
+ overridableProps: {
1772
+ ...overridableProps,
1773
+ groups: updatedGroups
1839
1774
  }
1840
- }
1841
- )));
1842
- };
1843
-
1844
- // src/components/components-tab/components-list.tsx
1845
- var React17 = __toESM(require("react"));
1846
- var import_react9 = require("react");
1847
- var import_editor_mcp = require("@elementor/editor-mcp");
1848
- var import_icons10 = require("@elementor/icons");
1849
- var import_ui15 = require("@elementor/ui");
1850
- var import_i18n20 = require("@wordpress/i18n");
1775
+ })
1776
+ );
1777
+ return true;
1778
+ }
1851
1779
 
1852
- // src/hooks/use-components-permissions.ts
1853
- var import_editor_current_user2 = require("@elementor/editor-current-user");
1854
- var useComponentsPermissions = () => {
1855
- const { isAdmin } = (0, import_editor_current_user2.useCurrentUserCapabilities)();
1856
- return {
1857
- canCreate: isAdmin,
1858
- canEdit: isAdmin,
1859
- canDelete: isAdmin,
1860
- canRename: isAdmin
1861
- };
1780
+ // src/components/component-properties-panel/utils/validate-group-label.ts
1781
+ var import_i18n8 = require("@wordpress/i18n");
1782
+ var ERROR_MESSAGES2 = {
1783
+ EMPTY_NAME: (0, import_i18n8.__)("Group name is required", "elementor"),
1784
+ DUPLICATE_NAME: (0, import_i18n8.__)("Group name already exists", "elementor")
1862
1785
  };
1786
+ function validateGroupLabel(label, existingGroups) {
1787
+ const trimmedLabel = label.trim();
1788
+ if (!trimmedLabel) {
1789
+ return ERROR_MESSAGES2.EMPTY_NAME;
1790
+ }
1791
+ const isDuplicate = Object.values(existingGroups).some((group) => group.label === trimmedLabel);
1792
+ if (isDuplicate) {
1793
+ return ERROR_MESSAGES2.DUPLICATE_NAME;
1794
+ }
1795
+ return "";
1796
+ }
1863
1797
 
1864
- // src/store/actions/rename-component.ts
1865
- var import_editor_documents7 = require("@elementor/editor-documents");
1866
- var import_editor_elements5 = require("@elementor/editor-elements");
1867
- var import_store33 = require("@elementor/store");
1868
-
1869
- // src/create-component-type.ts
1870
- var import_editor_canvas4 = require("@elementor/editor-canvas");
1871
- var import_editor_documents6 = require("@elementor/editor-documents");
1872
- var import_store31 = require("@elementor/store");
1873
- var import_i18n14 = require("@wordpress/i18n");
1874
- var COMPONENT_WIDGET_TYPE = "e-component";
1875
- var updateGroups = (groups, config) => {
1876
- const disableMap = new Map(Object.entries(config.disable ?? {}));
1877
- const addMap = new Map(Object.entries(config.add ?? {}));
1878
- return groups.map((group) => {
1879
- const disabledActions = disableMap.get(group.name) ?? [];
1880
- const addConfig = addMap.get(group.name);
1881
- const updatedActions = group.actions.map(
1882
- (action) => disabledActions.includes(action.name) ? { ...action, isEnabled: () => false } : action
1798
+ // src/components/component-properties-panel/use-current-editable-item.ts
1799
+ function useCurrentEditableItem() {
1800
+ const [editingGroupId, setEditingGroupId] = (0, import_react4.useState)(null);
1801
+ const currentComponentId = useCurrentComponentId();
1802
+ const overridableProps = useOverridableProps2(currentComponentId);
1803
+ const allGroupsRecord = overridableProps?.groups?.items ?? {};
1804
+ const currentGroup = editingGroupId ? allGroupsRecord[editingGroupId] : null;
1805
+ const validateLabel = (newLabel) => {
1806
+ const otherGroups = Object.fromEntries(
1807
+ Object.entries(allGroupsRecord).filter(([id2]) => id2 !== editingGroupId)
1883
1808
  );
1884
- if (addConfig) {
1885
- updatedActions.splice(addConfig.index, 0, addConfig.action);
1886
- }
1887
- return { ...group, actions: updatedActions };
1888
- });
1889
- };
1890
- function createComponentType(options) {
1891
- const legacyWindow = window;
1892
- const WidgetType = legacyWindow.elementor.modules.elements.types.Widget;
1893
- const view = createComponentView({ ...options });
1894
- return class extends WidgetType {
1895
- getType() {
1896
- return options.type;
1897
- }
1898
- getView() {
1899
- return view;
1900
- }
1901
- getModel() {
1902
- return createComponentModel();
1903
- }
1809
+ return validateGroupLabel(newLabel, otherGroups) || null;
1904
1810
  };
1905
- }
1906
- function createComponentView(options) {
1907
- const legacyWindow = window;
1908
- return class extends (0, import_editor_canvas4.createTemplatedElementView)(options) {
1909
- eventsManagerConfig = legacyWindow.elementorCommon.eventsManager.config;
1910
- #componentRenderContext;
1911
- isComponentCurrentlyEdited() {
1912
- const currentDocument = (0, import_editor_documents6.getCurrentDocument)();
1913
- return currentDocument?.id === this.getComponentId();
1914
- }
1915
- getRenderContext() {
1916
- const namespaceKey = this.getNamespaceKey();
1917
- const parentContext = this._parent?.getRenderContext?.();
1918
- const parentComponentContext = parentContext?.[namespaceKey];
1919
- if (!this.#componentRenderContext) {
1920
- return parentContext;
1921
- }
1922
- const ownOverrides = this.#componentRenderContext.overrides ?? {};
1923
- const parentOverrides = parentComponentContext?.overrides ?? {};
1924
- return {
1925
- ...parentContext,
1926
- [namespaceKey]: {
1927
- overrides: {
1928
- ...parentOverrides,
1929
- ...ownOverrides
1930
- }
1931
- }
1932
- };
1933
- }
1934
- getResolverRenderContext() {
1935
- const namespaceKey = this.getNamespaceKey();
1936
- const context = this.getRenderContext();
1937
- return context?.[namespaceKey];
1938
- }
1939
- afterSettingsResolve(settings) {
1940
- const componentInstance = settings.component_instance;
1941
- if (componentInstance) {
1942
- this.#componentRenderContext = {
1943
- overrides: componentInstance.overrides ?? {}
1944
- };
1945
- this.collection = legacyWindow.elementor.createBackboneElementsCollection(componentInstance.elements);
1946
- this.collection.models.forEach(setInactiveRecursively);
1947
- settings.component_instance = "<template data-children-placeholder></template>";
1948
- }
1949
- return settings;
1950
- }
1951
- getDomElement() {
1952
- return this.children.findByIndex(0)?.getDomElement() ?? this.$el;
1953
- }
1954
- attachBuffer(collectionView, buffer) {
1955
- const childrenPlaceholder = collectionView.$el.find("[data-children-placeholder]").get(0);
1956
- if (!childrenPlaceholder) {
1957
- super.attachBuffer(collectionView, buffer);
1958
- return;
1959
- }
1960
- childrenPlaceholder.replaceWith(buffer);
1961
- }
1962
- getComponentId() {
1963
- const componentInstance = this.options?.model?.get("settings")?.get("component_instance")?.value;
1964
- return componentInstance.component_id.value;
1965
- }
1966
- getContextMenuGroups() {
1967
- const filteredGroups = super.getContextMenuGroups().filter((group) => group.name !== "save");
1968
- const componentId = this.getComponentId();
1969
- if (!componentId) {
1970
- return filteredGroups;
1971
- }
1972
- const newGroups = updateGroups(
1973
- filteredGroups,
1974
- this._getContextMenuConfig()
1975
- );
1976
- return newGroups;
1811
+ const handleSubmit = (newLabel) => {
1812
+ if (!editingGroupId || !currentComponentId) {
1813
+ throw new Error((0, import_i18n9.__)("Group ID or component ID is missing", "elementor"));
1977
1814
  }
1978
- _getContextMenuConfig() {
1979
- const isAdministrator = isUserAdministrator();
1980
- const addedGroup = {
1981
- general: {
1982
- index: 1,
1983
- action: {
1984
- name: "edit component",
1985
- icon: "eicon-edit",
1986
- title: () => (0, import_i18n14.__)("Edit Component", "elementor"),
1987
- isEnabled: () => true,
1988
- callback: (_, eventData) => this.editComponent(eventData)
1989
- }
1990
- }
1991
- };
1992
- const disabledGroup = {
1993
- clipboard: ["pasteStyle", "resetStyle"]
1994
- };
1995
- return { add: isAdministrator ? addedGroup : {}, disable: disabledGroup };
1815
+ renameOverridableGroup({
1816
+ componentId: currentComponentId,
1817
+ groupId: editingGroupId,
1818
+ label: newLabel
1819
+ });
1820
+ (0, import_editor_documents4.setDocumentModifiedStatus)(true);
1821
+ };
1822
+ const {
1823
+ ref: editableRef,
1824
+ openEditMode,
1825
+ isEditing,
1826
+ error,
1827
+ getProps: getEditableProps
1828
+ } = (0, import_editor_ui4.useEditable)({
1829
+ value: currentGroup?.label ?? "",
1830
+ onSubmit: handleSubmit,
1831
+ validation: validateLabel
1832
+ });
1833
+ return {
1834
+ editableRef,
1835
+ isEditing,
1836
+ error,
1837
+ getEditableProps,
1838
+ setEditingGroupId: (groupId) => {
1839
+ setEditingGroupId(groupId);
1840
+ openEditMode();
1841
+ },
1842
+ editingGroupId
1843
+ };
1844
+ }
1845
+
1846
+ // src/components/component-properties-panel/utils/generate-unique-label.ts
1847
+ var DEFAULT_NEW_GROUP_LABEL = "New group";
1848
+ function generateUniqueLabel(groups) {
1849
+ const existingLabels = new Set(groups.map((group) => group.label));
1850
+ if (!existingLabels.has(DEFAULT_NEW_GROUP_LABEL)) {
1851
+ return DEFAULT_NEW_GROUP_LABEL;
1852
+ }
1853
+ let index = 1;
1854
+ let newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
1855
+ while (existingLabels.has(newLabel)) {
1856
+ index++;
1857
+ newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
1858
+ }
1859
+ return newLabel;
1860
+ }
1861
+
1862
+ // src/components/component-properties-panel/component-properties-panel-content.tsx
1863
+ function ComponentPropertiesPanelContent({ onClose }) {
1864
+ const currentComponentId = useCurrentComponentId();
1865
+ const overridableProps = useOverridableProps2(currentComponentId);
1866
+ const [isAddingGroup, setIsAddingGroup] = (0, import_react5.useState)(false);
1867
+ const introductionRef = (0, import_react5.useRef)(null);
1868
+ const groupLabelEditable = useCurrentEditableItem();
1869
+ const groups = (0, import_react5.useMemo)(() => {
1870
+ if (!overridableProps) {
1871
+ return [];
1996
1872
  }
1997
- async switchDocument() {
1998
- const { isAllowedToSwitchDocument, lockedBy } = await apiClient.getComponentLockStatus(
1999
- this.getComponentId()
2000
- );
2001
- if (!isAllowedToSwitchDocument) {
2002
- options.showLockedByModal?.(lockedBy || "");
2003
- } else {
2004
- switchToComponent(this.getComponentId(), this.model.get("id"), this.el);
2005
- }
1873
+ return overridableProps.groups.order.map((groupId) => overridableProps.groups.items[groupId] ?? null).filter(Boolean);
1874
+ }, [overridableProps]);
1875
+ const allGroupsForSelect = (0, import_react5.useMemo)(
1876
+ () => groups.map((group) => ({ value: group.id, label: group.label })),
1877
+ [groups]
1878
+ );
1879
+ if (!currentComponentId || !overridableProps) {
1880
+ return null;
1881
+ }
1882
+ const hasGroups = groups.length > 0;
1883
+ const showEmptyState = !hasGroups && !isAddingGroup;
1884
+ const groupIds = overridableProps.groups.order;
1885
+ const handleAddGroupClick = () => {
1886
+ if (isAddingGroup) {
1887
+ return;
2006
1888
  }
2007
- editComponent({ trigger, location, secondaryLocation }) {
2008
- if (this.isComponentCurrentlyEdited()) {
2009
- return;
2010
- }
2011
- this.switchDocument();
2012
- const editorSettings = this.model.get("editor_settings");
2013
- trackComponentEvent({
2014
- action: "edited",
2015
- source: "user",
2016
- component_uid: editorSettings?.component_uid,
2017
- component_name: editorSettings?.title,
2018
- location,
2019
- secondary_location: secondaryLocation,
2020
- trigger
2021
- });
1889
+ const newGroupId = (0, import_utils2.generateUniqueId)("group");
1890
+ const newLabel = generateUniqueLabel(groups);
1891
+ addOverridableGroup({
1892
+ componentId: currentComponentId,
1893
+ groupId: newGroupId,
1894
+ label: newLabel,
1895
+ source: "user"
1896
+ });
1897
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1898
+ setIsAddingGroup(false);
1899
+ groupLabelEditable.setEditingGroupId(newGroupId);
1900
+ };
1901
+ const handleGroupsReorder = (newOrder) => {
1902
+ reorderOverridableGroups({ componentId: currentComponentId, newOrder });
1903
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1904
+ };
1905
+ const handlePropsReorder = (groupId, newPropsOrder) => {
1906
+ reorderGroupProps({ componentId: currentComponentId, groupId, newPropsOrder });
1907
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1908
+ };
1909
+ const handlePropertyDelete = (propKey) => {
1910
+ deleteOverridableProp({ componentId: currentComponentId, propKey, source: "user" });
1911
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1912
+ };
1913
+ const handlePropertyUpdate = (overrideKey, data) => {
1914
+ updateOverridablePropParams({
1915
+ componentId: currentComponentId,
1916
+ overrideKey,
1917
+ label: data.label,
1918
+ groupId: data.group
1919
+ });
1920
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1921
+ };
1922
+ const handleGroupDelete = (groupId) => {
1923
+ deleteOverridableGroup({ componentId: currentComponentId, groupId });
1924
+ (0, import_editor_documents5.setDocumentModifiedStatus)(true);
1925
+ };
1926
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(import_editor_panels.PanelHeader, { sx: { justifyContent: "start", pl: 1.5, pr: 1, py: 1 } }, /* @__PURE__ */ React7.createElement(import_ui7.Stack, { direction: "row", alignItems: "center", gap: 0.5, flexGrow: 1 }, /* @__PURE__ */ React7.createElement(import_icons5.ComponentPropListIcon, { fontSize: "tiny" }), /* @__PURE__ */ React7.createElement(import_editor_panels.PanelHeaderTitle, { variant: "subtitle2" }, (0, import_i18n10.__)("Component properties", "elementor"))), !showEmptyState && /* @__PURE__ */ React7.createElement(import_ui7.Tooltip, { title: (0, import_i18n10.__)("Add new group", "elementor") }, /* @__PURE__ */ React7.createElement(
1927
+ import_ui7.IconButton,
1928
+ {
1929
+ size: "tiny",
1930
+ "aria-label": (0, import_i18n10.__)("Add new group", "elementor"),
1931
+ onClick: handleAddGroupClick
1932
+ },
1933
+ /* @__PURE__ */ React7.createElement(import_icons5.FolderPlusIcon, { fontSize: "tiny" })
1934
+ )), /* @__PURE__ */ React7.createElement(import_ui7.Tooltip, { title: (0, import_i18n10.__)("Close panel", "elementor") }, /* @__PURE__ */ React7.createElement(
1935
+ import_ui7.IconButton,
1936
+ {
1937
+ ref: introductionRef,
1938
+ size: "tiny",
1939
+ "aria-label": (0, import_i18n10.__)("Close panel", "elementor"),
1940
+ onClick: onClose
1941
+ },
1942
+ /* @__PURE__ */ React7.createElement(import_icons5.XIcon, { fontSize: "tiny" })
1943
+ ))), /* @__PURE__ */ React7.createElement(import_ui7.Divider, null), /* @__PURE__ */ React7.createElement(import_editor_panels.PanelBody, null, showEmptyState ? /* @__PURE__ */ React7.createElement(PropertiesEmptyState, { introductionRef }) : /* @__PURE__ */ React7.createElement(import_ui7.List, { sx: { p: 2, display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ React7.createElement(SortableProvider, { value: groupIds, onChange: handleGroupsReorder }, groups.map((group) => /* @__PURE__ */ React7.createElement(SortableItem, { key: group.id, id: group.id }, ({ triggerProps, triggerStyle, isDragPlaceholder }) => /* @__PURE__ */ React7.createElement(
1944
+ PropertiesGroup,
1945
+ {
1946
+ group,
1947
+ props: overridableProps.props,
1948
+ allGroups: allGroupsForSelect,
1949
+ allGroupsRecord: overridableProps.groups.items,
1950
+ sortableTriggerProps: { ...triggerProps, style: triggerStyle },
1951
+ isDragPlaceholder,
1952
+ setIsAddingGroup,
1953
+ onPropsReorder: (newOrder) => handlePropsReorder(group.id, newOrder),
1954
+ onPropertyDelete: handlePropertyDelete,
1955
+ onPropertyUpdate: handlePropertyUpdate,
1956
+ editableLabelProps: groupLabelEditable,
1957
+ onGroupDelete: handleGroupDelete
2022
1958
  }
2023
- handleDblClick(e) {
2024
- e.stopPropagation();
2025
- const isAdministrator = isUserAdministrator();
2026
- if (!isAdministrator) {
2027
- return;
1959
+ )))))));
1960
+ }
1961
+
1962
+ // src/components/component-properties-panel/component-properties-panel.tsx
1963
+ var id = "component-properties-panel";
1964
+ var { panel, usePanelActions } = (0, import_editor_panels2.__createPanel)({
1965
+ id,
1966
+ component: ComponentPropertiesPanel
1967
+ });
1968
+ function ComponentPropertiesPanel() {
1969
+ const { element, elementType } = (0, import_editor_elements4.useSelectedElement)();
1970
+ const { close: closePanel } = usePanelActions();
1971
+ const { open: openEditingPanel } = (0, import_editor_editing_panel.usePanelActions)();
1972
+ if (!element || !elementType) {
1973
+ return null;
1974
+ }
1975
+ return /* @__PURE__ */ React8.createElement(import_editor_ui5.ThemeProvider, null, /* @__PURE__ */ React8.createElement(import_ui8.ErrorBoundary, { fallback: /* @__PURE__ */ React8.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React8.createElement(import_editor_editing_panel.ElementProvider, { element, elementType }, /* @__PURE__ */ React8.createElement(import_editor_panels2.Panel, null, /* @__PURE__ */ React8.createElement(
1976
+ ComponentPropertiesPanelContent,
1977
+ {
1978
+ onClose: () => {
1979
+ closePanel();
1980
+ openEditingPanel();
2028
1981
  }
2029
- const { triggers, locations, secondaryLocations } = this.eventsManagerConfig;
2030
- this.editComponent({
2031
- trigger: triggers.doubleClick,
2032
- location: locations.canvas,
2033
- secondaryLocation: secondaryLocations.canvasElement
2034
- });
2035
- }
2036
- events() {
2037
- return {
2038
- ...super.events(),
2039
- dblclick: this.handleDblClick
2040
- };
2041
1982
  }
2042
- attributes() {
2043
- return {
2044
- ...super.attributes(),
2045
- "data-elementor-id": this.getComponentId()
2046
- };
1983
+ )))));
1984
+ }
1985
+ var ErrorBoundaryFallback = () => /* @__PURE__ */ React8.createElement(import_ui8.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React8.createElement(import_ui8.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React8.createElement("strong", null, (0, import_i18n11.__)("Something went wrong", "elementor"))));
1986
+
1987
+ // src/components/component-panel-header/component-badge.tsx
1988
+ var React9 = __toESM(require("react"));
1989
+ var import_react6 = require("react");
1990
+ var import_icons6 = require("@elementor/icons");
1991
+ var import_ui9 = require("@elementor/ui");
1992
+ var import_i18n12 = require("@wordpress/i18n");
1993
+ var ComponentsBadge = React9.forwardRef(({ overridablePropsCount, onClick }, ref) => {
1994
+ const prevCount = usePrevious(overridablePropsCount);
1995
+ const isFirstExposedProperty = prevCount === 0 && overridablePropsCount === 1;
1996
+ return /* @__PURE__ */ React9.createElement(
1997
+ StyledBadge,
1998
+ {
1999
+ ref,
2000
+ color: "primary",
2001
+ key: overridablePropsCount,
2002
+ invisible: overridablePropsCount === 0,
2003
+ animate: isFirstExposedProperty,
2004
+ anchorOrigin: { vertical: "top", horizontal: "right" },
2005
+ badgeContent: /* @__PURE__ */ React9.createElement(import_ui9.Box, { sx: { animation: !isFirstExposedProperty ? `${slideUp} 300ms ease-out` : "none" } }, overridablePropsCount)
2006
+ },
2007
+ /* @__PURE__ */ React9.createElement(
2008
+ import_ui9.ToggleButton,
2009
+ {
2010
+ value: "exposed properties",
2011
+ size: "tiny",
2012
+ onClick,
2013
+ "aria-label": (0, import_i18n12.__)("View exposed properties", "elementor")
2014
+ },
2015
+ /* @__PURE__ */ React9.createElement(import_icons6.ComponentPropListIcon, { fontSize: "tiny" })
2016
+ )
2017
+ );
2018
+ });
2019
+ var StyledBadge = (0, import_ui9.styled)(import_ui9.Badge, { shouldForwardProp: (prop) => prop !== "animate" })(
2020
+ ({ theme, animate }) => ({
2021
+ "& .MuiBadge-badge": {
2022
+ minWidth: theme.spacing(2),
2023
+ height: theme.spacing(2),
2024
+ minHeight: theme.spacing(2),
2025
+ maxWidth: theme.spacing(2),
2026
+ fontSize: theme.typography.caption.fontSize,
2027
+ animation: animate ? `${bounceIn} 300ms ease-out` : "none"
2047
2028
  }
2048
- };
2029
+ })
2030
+ );
2031
+ function usePrevious(value) {
2032
+ const ref = (0, import_react6.useRef)(value);
2033
+ (0, import_react6.useEffect)(() => {
2034
+ ref.current = value;
2035
+ }, [value]);
2036
+ return ref.current;
2049
2037
  }
2050
- function setInactiveRecursively(model) {
2051
- const editSettings = model.get("editSettings");
2052
- if (editSettings) {
2053
- editSettings.set("inactive", true);
2038
+ var bounceIn = import_ui9.keyframes`
2039
+ 0% { transform: scale(0) translate(50%, 50%); opacity: 0; }
2040
+ 70% { transform: scale(1.1) translate(50%, -50%); opacity: 1; }
2041
+ 100% { transform: scale(1) translate(50%, -50%); opacity: 1; }
2042
+ `;
2043
+ var slideUp = import_ui9.keyframes`
2044
+ from { transform: translateY(100%); opacity: 0; }
2045
+ to { transform: translateY(0); opacity: 1; }
2046
+ `;
2047
+
2048
+ // src/components/component-panel-header/component-panel-header.tsx
2049
+ var MESSAGE_KEY = "components-properties-introduction";
2050
+ var ComponentPanelHeader = () => {
2051
+ const { id: currentComponentId, uid: componentUid } = useCurrentComponent() ?? { id: null, uid: null };
2052
+ const overridableProps = useOverridableProps2(currentComponentId);
2053
+ const onBack = useNavigateBack();
2054
+ const componentName = getComponentName();
2055
+ const [isMessageSuppressed, suppressMessage] = (0, import_editor_current_user.useSuppressedMessage)(MESSAGE_KEY);
2056
+ const [shouldShowIntroduction, setShouldShowIntroduction] = React10.useState(!isMessageSuppressed);
2057
+ const { open: openPropertiesPanel } = usePanelActions();
2058
+ const overridablePropsCount = overridableProps ? Object.keys(overridableProps.props).length : 0;
2059
+ const anchorRef = React10.useRef(null);
2060
+ if (!currentComponentId) {
2061
+ return null;
2054
2062
  }
2055
- const elements = model.get("elements");
2056
- if (elements) {
2057
- elements.forEach((childModel) => {
2058
- setInactiveRecursively(childModel);
2063
+ const handleCloseIntroduction = () => {
2064
+ suppressMessage();
2065
+ setShouldShowIntroduction(false);
2066
+ };
2067
+ const handleOpenPropertiesPanel = () => {
2068
+ openPropertiesPanel();
2069
+ trackComponentEvent({
2070
+ action: "propertiesPanelOpened",
2071
+ source: "user",
2072
+ component_uid: componentUid,
2073
+ properties_count: overridablePropsCount
2059
2074
  });
2075
+ };
2076
+ return /* @__PURE__ */ React10.createElement(import_ui10.Box, null, /* @__PURE__ */ React10.createElement(
2077
+ import_ui10.Stack,
2078
+ {
2079
+ direction: "row",
2080
+ alignItems: "center",
2081
+ justifyContent: "space-between",
2082
+ sx: { height: 48, pl: 1.5, pr: 2, py: 1 }
2083
+ },
2084
+ /* @__PURE__ */ React10.createElement(import_ui10.Stack, { direction: "row", alignItems: "center" }, /* @__PURE__ */ React10.createElement(import_ui10.Tooltip, { title: (0, import_i18n13.__)("Back", "elementor") }, /* @__PURE__ */ React10.createElement(import_ui10.IconButton, { size: "tiny", onClick: onBack, "aria-label": (0, import_i18n13.__)("Back", "elementor") }, /* @__PURE__ */ React10.createElement(import_icons7.ArrowLeftIcon, { fontSize: "tiny" }))), /* @__PURE__ */ React10.createElement(import_ui10.Stack, { direction: "row", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ React10.createElement(import_icons7.ComponentsFilledIcon, { fontSize: "tiny", stroke: "currentColor" }), /* @__PURE__ */ React10.createElement(import_ui10.Typography, { variant: "caption", sx: { fontWeight: 500 } }, componentName))),
2085
+ /* @__PURE__ */ React10.createElement(
2086
+ ComponentsBadge,
2087
+ {
2088
+ overridablePropsCount,
2089
+ ref: anchorRef,
2090
+ onClick: handleOpenPropertiesPanel
2091
+ }
2092
+ )
2093
+ ), /* @__PURE__ */ React10.createElement(import_ui10.Divider, null), /* @__PURE__ */ React10.createElement(
2094
+ ComponentIntroduction,
2095
+ {
2096
+ anchorRef,
2097
+ shouldShowIntroduction,
2098
+ onClose: handleCloseIntroduction
2099
+ }
2100
+ ));
2101
+ };
2102
+ function getComponentName() {
2103
+ const state = (0, import_store29.__getState)();
2104
+ const path = state[SLICE_NAME].path;
2105
+ const { instanceTitle } = path.at(-1) ?? {};
2106
+ if (instanceTitle) {
2107
+ return instanceTitle;
2060
2108
  }
2109
+ const documentsManager = (0, import_editor_documents6.getV1DocumentsManager)();
2110
+ const currentDocument = documentsManager.getCurrent();
2111
+ return currentDocument?.container?.settings?.get("post_title") ?? "";
2061
2112
  }
2062
- function isUserAdministrator() {
2063
- const legacyWindow = window;
2064
- return legacyWindow.elementor.config?.user?.is_administrator ?? false;
2113
+
2114
+ // src/components/components-tab/components.tsx
2115
+ var React19 = __toESM(require("react"));
2116
+ var import_editor_ui9 = require("@elementor/editor-ui");
2117
+
2118
+ // src/hooks/use-components.ts
2119
+ var import_store31 = require("@elementor/store");
2120
+ var useComponents = () => {
2121
+ const components = (0, import_store31.__useSelector)(selectComponents);
2122
+ const isLoading = (0, import_store31.__useSelector)(selectLoadIsPending);
2123
+ return { components, isLoading };
2124
+ };
2125
+
2126
+ // src/utils/is-pro-user.ts
2127
+ function isProUser() {
2128
+ const extendedWindow = window;
2129
+ const hasPro = extendedWindow.elementor?.helpers?.hasPro?.() ?? false;
2130
+ if (!hasPro) {
2131
+ return false;
2132
+ }
2133
+ const isProActive = extendedWindow.elementorPro?.config?.isActive ?? false;
2134
+ return isProActive;
2065
2135
  }
2066
- function createComponentModel() {
2067
- const legacyWindow = window;
2068
- const WidgetType = legacyWindow.elementor.modules.elements.types.Widget;
2069
- const widgetTypeInstance = new WidgetType();
2070
- const BaseWidgetModel = widgetTypeInstance.getModel();
2071
- return BaseWidgetModel.extend({
2072
- initialize(attributes, options) {
2073
- BaseWidgetModel.prototype.initialize.call(this, attributes, options);
2074
- const componentInstance = this.get("settings")?.get("component_instance");
2075
- if (componentInstance?.value) {
2076
- const componentId = componentInstance.value.component_id?.value;
2077
- if (componentId && typeof componentId === "number") {
2078
- this.set("componentId", componentId);
2079
- }
2080
- }
2081
- this.set("isGlobal", true);
2082
- },
2083
- getTitle() {
2084
- const editorSettings = this.get("editor_settings");
2085
- const instanceTitle = editorSettings?.title;
2086
- if (instanceTitle) {
2087
- return instanceTitle;
2088
- }
2089
- const componentUid = editorSettings?.component_uid;
2090
- if (componentUid) {
2091
- const component = selectComponentByUid((0, import_store31.__getState)(), componentUid);
2092
- if (component?.name) {
2093
- return component.name;
2094
- }
2136
+
2137
+ // src/components/components-tab/component-search.tsx
2138
+ var React12 = __toESM(require("react"));
2139
+ var import_icons8 = require("@elementor/icons");
2140
+ var import_ui11 = require("@elementor/ui");
2141
+ var import_i18n14 = require("@wordpress/i18n");
2142
+
2143
+ // src/components/components-tab/search-provider.tsx
2144
+ var React11 = __toESM(require("react"));
2145
+ var import_react7 = require("react");
2146
+ var import_utils3 = require("@elementor/utils");
2147
+ var SearchContext = (0, import_react7.createContext)(void 0);
2148
+ var SearchProvider = ({
2149
+ children,
2150
+ localStorageKey
2151
+ }) => {
2152
+ const { debouncedValue, handleChange, inputValue } = (0, import_utils3.useSearchState)({ localStorageKey });
2153
+ const clearSearch = () => {
2154
+ handleChange("");
2155
+ };
2156
+ return /* @__PURE__ */ React11.createElement(SearchContext.Provider, { value: { handleChange, clearSearch, searchValue: debouncedValue, inputValue } }, children);
2157
+ };
2158
+ var useSearch = () => {
2159
+ const context = (0, import_react7.useContext)(SearchContext);
2160
+ if (!context) {
2161
+ throw new Error("useSearch must be used within a SearchProvider");
2162
+ }
2163
+ return context;
2164
+ };
2165
+
2166
+ // src/components/components-tab/component-search.tsx
2167
+ var ComponentSearch = () => {
2168
+ const { inputValue, handleChange } = useSearch();
2169
+ return /* @__PURE__ */ React12.createElement(import_ui11.Stack, { direction: "row", gap: 0.5, sx: { width: "100%", px: 2, py: 1.5 } }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React12.createElement(
2170
+ import_ui11.TextField,
2171
+ {
2172
+ role: "search",
2173
+ fullWidth: true,
2174
+ size: "tiny",
2175
+ value: inputValue,
2176
+ placeholder: (0, import_i18n14.__)("Search", "elementor"),
2177
+ onChange: (e) => handleChange(e.target.value),
2178
+ InputProps: {
2179
+ startAdornment: /* @__PURE__ */ React12.createElement(import_ui11.InputAdornment, { position: "start" }, /* @__PURE__ */ React12.createElement(import_icons8.SearchIcon, { fontSize: "tiny" }))
2095
2180
  }
2096
- return window.elementor.getElementData(this).title;
2097
- },
2098
- getComponentId() {
2099
- return this.get("componentId") || null;
2100
- },
2101
- getComponentName() {
2102
- return this.getTitle();
2103
- },
2104
- getComponentUid() {
2105
- const editorSettings = this.get("editor_settings");
2106
- return editorSettings?.component_uid || null;
2107
2181
  }
2108
- });
2109
- }
2182
+ )));
2183
+ };
2184
+
2185
+ // src/components/components-tab/components-list.tsx
2186
+ var React17 = __toESM(require("react"));
2187
+ var import_react9 = require("react");
2188
+ var import_editor_mcp = require("@elementor/editor-mcp");
2189
+ var import_icons10 = require("@elementor/icons");
2190
+ var import_ui15 = require("@elementor/ui");
2191
+ var import_i18n20 = require("@wordpress/i18n");
2192
+
2193
+ // src/hooks/use-components-permissions.ts
2194
+ var import_editor_current_user2 = require("@elementor/editor-current-user");
2195
+ var useComponentsPermissions = () => {
2196
+ const { isAdmin } = (0, import_editor_current_user2.useCurrentUserCapabilities)();
2197
+ return {
2198
+ canCreate: isAdmin,
2199
+ canEdit: isAdmin,
2200
+ canDelete: isAdmin,
2201
+ canRename: isAdmin
2202
+ };
2203
+ };
2110
2204
 
2111
2205
  // src/store/actions/rename-component.ts
2206
+ var import_editor_documents7 = require("@elementor/editor-documents");
2207
+ var import_editor_elements5 = require("@elementor/editor-elements");
2208
+ var import_store33 = require("@elementor/store");
2112
2209
  var TITLE_EXTERNAL_CHANGE_COMMAND = "title_external_change";
2113
2210
  var renameComponent = (componentUid, newName) => {
2114
2211
  (0, import_store33.__dispatch)(slice.actions.rename({ componentUid, name: newName }));
@@ -2204,11 +2301,6 @@ var archiveComponent = (componentId, componentName) => {
2204
2301
  // src/store/actions/load-components-assets.ts
2205
2302
  var import_editor_documents9 = require("@elementor/editor-documents");
2206
2303
 
2207
- // src/utils/is-component-instance.ts
2208
- function isComponentInstance(elementModel) {
2209
- return [elementModel.widgetType, elementModel.elType].includes(COMPONENT_WIDGET_TYPE);
2210
- }
2211
-
2212
2304
  // src/utils/get-component-ids.ts
2213
2305
  var getComponentIds = async (elements) => {
2214
2306
  const components = elements.map(async ({ widgetType, elType, elements: childElements, settings }) => {
@@ -2313,13 +2405,13 @@ async function updateDocumentState(componentIds) {
2313
2405
  var import_store41 = require("@elementor/store");
2314
2406
 
2315
2407
  // src/components/create-component-form/utils/component-form-schema.ts
2316
- var import_schema = require("@elementor/schema");
2408
+ var import_schema5 = require("@elementor/schema");
2317
2409
  var import_i18n17 = require("@wordpress/i18n");
2318
2410
  var MIN_NAME_LENGTH = 2;
2319
2411
  var MAX_NAME_LENGTH = 50;
2320
- var baseComponentSchema = import_schema.z.string().trim().max(MAX_NAME_LENGTH, (0, import_i18n17.__)("Component name is too long. Please keep it under 50 characters.", "elementor"));
2412
+ var baseComponentSchema = import_schema5.z.string().trim().max(MAX_NAME_LENGTH, (0, import_i18n17.__)("Component name is too long. Please keep it under 50 characters.", "elementor"));
2321
2413
  var createBaseComponentSchema = (existingNames) => {
2322
- return import_schema.z.object({
2414
+ return import_schema5.z.object({
2323
2415
  componentName: baseComponentSchema.refine((value) => !existingNames.includes(value), {
2324
2416
  message: (0, import_i18n17.__)("Component name already exists", "elementor")
2325
2417
  })
@@ -3541,60 +3633,6 @@ var import_i18n27 = require("@wordpress/i18n");
3541
3633
  // src/hooks/use-component-instance-settings.ts
3542
3634
  var import_editor_editing_panel2 = require("@elementor/editor-editing-panel");
3543
3635
  var import_editor_elements11 = require("@elementor/editor-elements");
3544
-
3545
- // src/prop-types/component-instance-prop-type.ts
3546
- var import_editor_props4 = require("@elementor/editor-props");
3547
- var import_schema5 = require("@elementor/schema");
3548
-
3549
- // src/prop-types/component-instance-overrides-prop-type.ts
3550
- var import_editor_props3 = require("@elementor/editor-props");
3551
- var import_schema4 = require("@elementor/schema");
3552
-
3553
- // src/prop-types/component-instance-override-prop-type.ts
3554
- var import_editor_props = require("@elementor/editor-props");
3555
- var import_schema2 = require("@elementor/schema");
3556
- var componentInstanceOverridePropTypeUtil = (0, import_editor_props.createPropUtils)(
3557
- "override",
3558
- import_schema2.z.object({
3559
- override_key: import_schema2.z.string(),
3560
- override_value: import_schema2.z.unknown(),
3561
- schema_source: import_schema2.z.object({
3562
- type: import_schema2.z.literal("component"),
3563
- id: import_schema2.z.number()
3564
- })
3565
- })
3566
- );
3567
-
3568
- // src/prop-types/component-overridable-prop-type.ts
3569
- var import_editor_props2 = require("@elementor/editor-props");
3570
- var import_schema3 = require("@elementor/schema");
3571
- var componentOverridablePropTypeUtil = (0, import_editor_props2.createPropUtils)(
3572
- "overridable",
3573
- import_schema3.z.object({
3574
- override_key: import_schema3.z.string(),
3575
- origin_value: import_schema3.z.object({
3576
- $$type: import_schema3.z.string(),
3577
- value: import_schema3.z.unknown()
3578
- }).nullable()
3579
- })
3580
- );
3581
-
3582
- // src/prop-types/component-instance-overrides-prop-type.ts
3583
- var componentInstanceOverridesPropTypeUtil = (0, import_editor_props3.createPropUtils)(
3584
- "overrides",
3585
- import_schema4.z.array(import_schema4.z.union([componentInstanceOverridePropTypeUtil.schema, componentOverridablePropTypeUtil.schema])).optional().default([])
3586
- );
3587
-
3588
- // src/prop-types/component-instance-prop-type.ts
3589
- var componentInstancePropTypeUtil = (0, import_editor_props4.createPropUtils)(
3590
- "component-instance",
3591
- import_schema5.z.object({
3592
- component_id: import_editor_props4.numberPropTypeUtil.schema,
3593
- overrides: import_schema5.z.optional(componentInstanceOverridesPropTypeUtil.schema)
3594
- })
3595
- );
3596
-
3597
- // src/hooks/use-component-instance-settings.ts
3598
3636
  function useComponentInstanceSettings() {
3599
3637
  const { element } = (0, import_editor_editing_panel2.useElement)();
3600
3638
  const settings = (0, import_editor_elements11.useElementSetting)(element.id, "component_instance");
@@ -4039,7 +4077,6 @@ function OverridablePropControl({
4039
4077
  ...props
4040
4078
  }) {
4041
4079
  const { elementType } = (0, import_editor_editing_panel6.useElement)();
4042
- const Control = (0, import_editor_controls5.createControl)(OriginalControl2);
4043
4080
  const { value, bind, setValue, placeholder, ...propContext } = (0, import_editor_controls5.useBoundProp)(componentOverridablePropTypeUtil);
4044
4081
  const componentId = useCurrentComponentId();
4045
4082
  const overridableProps = useOverridableProps(componentId);
@@ -4088,9 +4125,20 @@ function OverridablePropControl({
4088
4125
  },
4089
4126
  placeholder: objectPlaceholder
4090
4127
  },
4091
- /* @__PURE__ */ React30.createElement(import_editor_controls5.PropKeyProvider, { bind }, /* @__PURE__ */ React30.createElement(import_editor_controls5.ControlReplacementsProvider, { replacements: filteredReplacements }, /* @__PURE__ */ React30.createElement(Control, { ...props })))
4128
+ /* @__PURE__ */ React30.createElement(import_editor_controls5.PropKeyProvider, { bind }, /* @__PURE__ */ React30.createElement(import_editor_controls5.ControlReplacementsProvider, { replacements: filteredReplacements }, /* @__PURE__ */ React30.createElement(ControlWithReplacements, { OriginalControl: OriginalControl2, props })))
4092
4129
  ));
4093
4130
  }
4131
+ function ControlWithReplacements({
4132
+ OriginalControl: OriginalControl2,
4133
+ props
4134
+ }) {
4135
+ const { ControlToRender, isReplaced } = (0, import_editor_controls5.useControlReplacement)(OriginalControl2);
4136
+ if (isReplaced) {
4137
+ const ReplacementControl = ControlToRender;
4138
+ return /* @__PURE__ */ React30.createElement(ReplacementControl, { ...props, OriginalControl: OriginalControl2 });
4139
+ }
4140
+ return /* @__PURE__ */ React30.createElement(OriginalControl2, { ...props });
4141
+ }
4094
4142
 
4095
4143
  // src/components/overridable-props/overridable-prop-indicator.tsx
4096
4144
  var React32 = __toESM(require("react"));