@elementor/editor-components 3.35.0-465 → 3.35.0-467

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;
1090
- }
1091
- return groups?.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
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;
1092
837
  }
1093
- },
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"
1103
- },
1104
- ctaLabel
1105
- ))));
1106
- }
1107
-
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
838
+ const ownOverrides = this.#componentRenderContext.overrides ?? {};
839
+ const parentOverrides = parentComponentContext?.overrides ?? {};
840
+ return {
841
+ ...parentContext,
842
+ [namespaceKey]: {
843
+ overrides: {
844
+ ...parentOverrides,
845
+ ...ownOverrides
846
+ }
1146
847
  }
1147
- },
1148
- children({
1149
- isDragged,
1150
- isDragPlaceholder,
1151
- triggerProps,
1152
- triggerStyle
1153
- }),
1154
- showDropIndication && /* @__PURE__ */ React4.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1155
- )
1156
- }
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
- `;
1171
-
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"
1184
- });
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);
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
+ }
1194
964
  };
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"
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);
1227
995
  }
1228
996
  }
997
+ this.set("isGlobal", true);
1229
998
  },
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%" }
999
+ getTitle() {
1000
+ const editorSettings = this.get("editor_settings");
1001
+ const instanceTitle = editorSettings?.title;
1002
+ if (instanceTitle) {
1003
+ return instanceTitle;
1256
1004
  }
1257
- )
1258
- ));
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;
1013
+ },
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
+ });
1259
1025
  }
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";
1265
- }
1266
- const widgetConfig = widgetsCache[elType];
1267
- return widgetConfig?.icon || "eicon-apps";
1026
+
1027
+ // src/utils/is-component-instance.ts
1028
+ function isComponentInstance(elementModel) {
1029
+ return [elementModel.widgetType, elementModel.elType].includes(COMPONENT_WIDGET_TYPE);
1268
1030
  }
1269
1031
 
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
1282
- }) {
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
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;
1037
+ }
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
1287
1046
  });
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);
1298
- };
1299
- return /* @__PURE__ */ React6.createElement(
1300
- import_ui6.Box,
1301
- {
1302
- sx: {
1303
- opacity: isDragPlaceholder ? 0.5 : 1
1304
- }
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
- }
1325
- },
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,
1372
- {
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)
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
+ }
1082
+
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
1380
1103
  }
1381
- )))))),
1382
- /* @__PURE__ */ React6.createElement(
1383
- import_ui6.Menu,
1384
- {
1385
- ...(0, import_ui6.bindMenu)(popupState),
1386
- anchorOrigin: { vertical: "bottom", horizontal: "right" },
1387
- transformOrigin: { vertical: "top", horizontal: "right" }
1388
- },
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
- )
1104
+ })
1406
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
1115
+ });
1407
1116
  }
1408
1117
 
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");
1414
-
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);
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);
1419
1122
  if (!overridableProps) {
1420
- return false;
1123
+ return;
1421
1124
  }
1422
1125
  const group = overridableProps.groups.items[groupId];
1423
1126
  if (!group) {
1424
- return false;
1127
+ return;
1425
1128
  }
1426
- const updatedGroups = renameGroup(overridableProps.groups, groupId, label);
1427
- (0, import_store23.__dispatch)(
1129
+ (0, import_store17.__dispatch)(
1428
1130
  slice.actions.setOverridableProps({
1429
1131
  componentId,
1430
1132
  overridableProps: {
1431
1133
  ...overridableProps,
1432
- groups: updatedGroups
1134
+ groups: {
1135
+ ...overridableProps.groups,
1136
+ items: {
1137
+ ...overridableProps.groups.items,
1138
+ [groupId]: {
1139
+ ...group,
1140
+ props: newPropsOrder
1141
+ }
1142
+ }
1143
+ }
1433
1144
  }
1434
1145
  })
1435
1146
  );
1436
- return true;
1437
1147
  }
1438
1148
 
1439
- // src/components/component-properties-panel/utils/validate-group-label.ts
1440
- 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;
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;
1453
1155
  }
1454
- return "";
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
+ );
1455
1168
  }
1456
1169
 
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
- }
1504
-
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;
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
1177
+ }) {
1178
+ const overridableProps = selectOverridableProps((0, import_store21.__getState)(), componentId);
1179
+ if (!overridableProps) {
1180
+ return;
1511
1181
  }
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}`;
1182
+ const prop = overridableProps.props[overrideKey];
1183
+ if (!prop) {
1184
+ return;
1517
1185
  }
1518
- return newLabel;
1186
+ const oldGroupId = prop.groupId;
1187
+ const newGroupId = groupId ?? oldGroupId;
1188
+ const updatedProp = {
1189
+ ...prop,
1190
+ label,
1191
+ groupId: newGroupId
1192
+ };
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
1204
+ }
1205
+ })
1206
+ );
1207
+ return updatedProp;
1519
1208
  }
1520
1209
 
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 [];
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;
1531
1216
  }
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) {
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) {
1539
1240
  return null;
1540
1241
  }
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);
1584
- };
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,
1242
+ return /* @__PURE__ */ React.createElement(
1243
+ import_ui.Popover,
1587
1244
  {
1588
- size: "tiny",
1589
- "aria-label": (0, import_i18n9.__)("Add new group", "elementor"),
1590
- onClick: handleAddGroupClick
1245
+ anchorEl: anchorRef.current,
1246
+ open: shouldShowIntroduction,
1247
+ anchorOrigin: {
1248
+ vertical: "top",
1249
+ horizontal: "right"
1250
+ },
1251
+ transformOrigin: {
1252
+ vertical: "top",
1253
+ horizontal: -30
1254
+ },
1255
+ onClose
1591
1256
  },
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,
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,
1259
+ {
1260
+ sx: { width: "296px", height: "160px" },
1261
+ src: "https://assets.elementor.com/packages/v1/images/components-properties-intro.png",
1262
+ alt: ""
1263
+ }
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,
1272
+ {
1273
+ href: "http://go.elementor.com/components-guide",
1274
+ target: "_blank",
1275
+ sx: { mt: 2 },
1276
+ color: "info.main",
1277
+ variant: "body2"
1278
+ },
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"))))))
1281
+ );
1282
+ };
1283
+
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,
1595
1289
  {
1596
- ref: introductionRef,
1597
- size: "tiny",
1598
- "aria-label": (0, import_i18n9.__)("Close panel", "elementor"),
1599
- onClick: onClose
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
1600
1296
  },
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,
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,
1604
1313
  {
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
1314
+ anchorRef: introductionRef,
1315
+ shouldShowIntroduction: isOpen,
1316
+ onClose: () => setIsOpen(false)
1617
1317
  }
1618
- )))))));
1318
+ ));
1619
1319
  }
1620
1320
 
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;
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");
1326
+ var import_i18n7 = require("@wordpress/i18n");
1327
+
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");
1333
+
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");
1340
+
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 };
1633
1351
  }
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
- }
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;
1641
1358
  }
1642
- )))));
1359
+ return normalizedExisting === normalizedLabel;
1360
+ });
1361
+ if (isDuplicate) {
1362
+ return { isValid: false, errorMessage: ERROR_MESSAGES.DUPLICATE_NAME };
1363
+ }
1364
+ return { isValid: true, errorMessage: null };
1643
1365
  }
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"))));
1645
1366
 
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,
1657
- {
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)
1665
- },
1666
- /* @__PURE__ */ React9.createElement(
1667
- import_ui9.ToggleButton,
1668
- {
1669
- value: "exposed properties",
1670
- size: "tiny",
1671
- onClick,
1672
- "aria-label": (0, import_i18n11.__)("View exposed properties", "elementor")
1673
- },
1674
- /* @__PURE__ */ React9.createElement(import_icons6.ComponentPropListIcon, { fontSize: "tiny" })
1675
- )
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"
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;
1687
1384
  }
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;
1696
- }
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;
1721
- }
1722
- const handleCloseIntroduction = () => {
1723
- suppressMessage();
1724
- setShouldShowIntroduction(false);
1725
- };
1726
- const handleOpenPropertiesPanel = () => {
1727
- openPropertiesPanel();
1728
- trackComponentEvent({
1729
- action: "propertiesPanelOpened",
1730
- source: "user",
1731
- component_uid: componentUid,
1732
- properties_count: overridablePropsCount
1733
- });
1385
+ onSubmit({ label: propLabel ?? "", group });
1734
1386
  };
1735
- return /* @__PURE__ */ React10.createElement(import_ui10.Box, null, /* @__PURE__ */ React10.createElement(
1736
- import_ui10.Stack,
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,
1737
1389
  {
1738
1390
  direction: "row",
1739
1391
  alignItems: "center",
1740
- justifyContent: "space-between",
1741
- sx: { height: 48, pl: 1.5, pr: 2, py: 1 }
1392
+ py: 1,
1393
+ px: 1.5,
1394
+ sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
1742
1395
  },
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,
1746
- {
1747
- overridablePropsCount,
1748
- ref: anchorRef,
1749
- onClick: handleOpenPropertiesPanel
1750
- }
1751
- )
1752
- ), /* @__PURE__ */ React10.createElement(import_ui10.Divider, null), /* @__PURE__ */ React10.createElement(
1753
- ComponentIntroduction,
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,
1754
1399
  {
1755
- anchorRef,
1756
- shouldShowIntroduction,
1757
- onClose: handleCloseIntroduction
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
1758
1417
  }
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") ?? "";
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
+ }
1434
+ },
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,
1438
+ {
1439
+ type: "submit",
1440
+ disabled: !propLabel || Boolean(error),
1441
+ variant: "contained",
1442
+ color: "primary",
1443
+ size: "small"
1444
+ },
1445
+ ctaLabel
1446
+ ))));
1771
1447
  }
1772
1448
 
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
- };
1784
-
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) {
1790
- return false;
1791
- }
1792
- const isProActive = extendedWindow.elementorPro?.config?.isActive ?? false;
1793
- return isProActive;
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
+ )
1497
+ }
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
+ `;
1512
+
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,
1538
+ {
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
+ }
1570
+ },
1571
+ /* @__PURE__ */ React5.createElement(SortableTrigger, { ...sortableTriggerProps }),
1572
+ /* @__PURE__ */ React5.createElement(
1573
+ import_ui5.Box,
1574
+ {
1575
+ sx: { display: "flex", alignItems: "center", color: "text.primary", fontSize: 12, padding: 0.25 }
1576
+ },
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
+ }
1598
+ )
1599
+ ));
1600
+ }
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";
1606
+ }
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);
1635
+ };
1636
+ const handleDeleteClick = () => {
1637
+ popupState.close();
1638
+ onGroupDelete(group.id);
1639
+ };
1640
+ return /* @__PURE__ */ React6.createElement(
1641
+ import_ui6.Box,
1642
+ {
1643
+ sx: {
1644
+ opacity: isDragPlaceholder ? 0.5 : 1
1645
+ }
1646
+ },
1647
+ /* @__PURE__ */ React6.createElement(import_ui6.Stack, { gap: 1 }, /* @__PURE__ */ React6.createElement(
1648
+ import_ui6.Box,
1649
+ {
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)
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
+ )
1746
+ )
1747
+ );
1794
1748
  }
1795
1749
 
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");
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");
1801
1755
 
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");
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) {
1761
+ return false;
1821
1762
  }
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" }))
1763
+ const group = overridableProps.groups.items[groupId];
1764
+ if (!group) {
1765
+ return false;
1766
+ }
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");
1851
-
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
- };
1862
- };
1863
-
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");
1775
+ })
1776
+ );
1777
+ return true;
1778
+ }
1868
1779
 
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
1883
- );
1884
- if (addConfig) {
1885
- updatedActions.splice(addConfig.index, 0, addConfig.action);
1886
- }
1887
- return { ...group, actions: updatedActions };
1888
- });
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")
1889
1785
  };
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
- }
1904
- };
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 "";
1905
1796
  }
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;
1977
- }
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 };
1996
- }
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
- }
1797
+
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)
1808
+ );
1809
+ return validateGroupLabel(newLabel, otherGroups) || null;
1810
+ };
1811
+ const handleSubmit = (newLabel) => {
1812
+ if (!editingGroupId || !currentComponentId) {
1813
+ throw new Error((0, import_i18n9.__)("Group ID or component ID is missing", "elementor"));
2006
1814
  }
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
- });
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 [];
2022
1872
  }
2023
- handleDblClick(e) {
2024
- e.stopPropagation();
2025
- const isAdministrator = isUserAdministrator();
2026
- if (!isAdministrator) {
2027
- return;
2028
- }
2029
- const { triggers, locations, secondaryLocations } = this.eventsManagerConfig;
2030
- this.editComponent({
2031
- trigger: triggers.doubleClick,
2032
- location: locations.canvas,
2033
- secondaryLocation: secondaryLocations.canvasElement
2034
- });
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;
2035
1888
  }
2036
- events() {
2037
- return {
2038
- ...super.events(),
2039
- dblclick: this.handleDblClick
2040
- };
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
2041
1958
  }
2042
- attributes() {
2043
- return {
2044
- ...super.attributes(),
2045
- "data-elementor-id": this.getComponentId()
2046
- };
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();
1981
+ }
2047
1982
  }
2048
- };
1983
+ )))));
2049
1984
  }
2050
- function setInactiveRecursively(model) {
2051
- const editSettings = model.get("editSettings");
2052
- if (editSettings) {
2053
- editSettings.set("inactive", true);
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(import_ui9.Tooltip, { title: (0, import_i18n12.__)("Component properties", "elementor") }, /* @__PURE__ */ React9.createElement(
2008
+ import_ui9.ToggleButton,
2009
+ {
2010
+ value: "exposed properties",
2011
+ size: "tiny",
2012
+ onClick,
2013
+ "aria-label": (0, import_i18n12.__)("Component 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"
2028
+ }
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;
2037
+ }
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");