slice-machine-ui 1.22.3-beta.1 → 1.22.3-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/components/DeleteVariationModal/index.tsx +12 -11
  2. package/components/Forms/CreateSliceModal/CreateSliceModal.tsx +2 -5
  3. package/components/Forms/RenameCustomTypeModal/RenameCustomTypeModal.tsx +9 -5
  4. package/components/Forms/RenameVariationModal/RenameVariationModal.tsx +12 -11
  5. package/components/ItemHeader/index.tsx +1 -0
  6. package/components/ListItem/index.tsx +5 -2
  7. package/components/ScreenshotChangesModal/VariationDropZone.tsx +31 -9
  8. package/components/ScreenshotChangesModal/index.tsx +3 -0
  9. package/components/ScreenshotChangesModal/useCustomScreenshot.tsx +5 -5
  10. package/components/Simulator/index.tsx +9 -3
  11. package/lib/builders/CustomTypeBuilder/SliceZone/SlicesTemplatesModal.tsx +2 -2
  12. package/lib/builders/CustomTypeBuilder/SliceZone/UpdateSliceZoneModal.tsx +2 -2
  13. package/lib/builders/CustomTypeBuilder/SliceZone/index.tsx +12 -20
  14. package/lib/builders/CustomTypeBuilder/TabModal/update.tsx +3 -1
  15. package/lib/builders/CustomTypeBuilder/TabZone/index.tsx +119 -52
  16. package/lib/builders/CustomTypeBuilder/index.tsx +39 -42
  17. package/lib/builders/SliceBuilder/FieldZones/index.tsx +81 -56
  18. package/lib/builders/SliceBuilder/Sidebar/AddVariationModal.tsx +24 -16
  19. package/lib/builders/SliceBuilder/Sidebar/index.tsx +44 -46
  20. package/lib/builders/SliceBuilder/SimulatorButton/index.tsx +4 -28
  21. package/lib/builders/SliceBuilder/index.tsx +10 -96
  22. package/lib/builders/common/Zone/Card/components/Hints/CodeBlock.tsx +5 -1
  23. package/lib/builders/common/Zone/Card/components/NewField.tsx +16 -15
  24. package/lib/builders/common/Zone/Card/index.jsx +2 -0
  25. package/lib/builders/common/Zone/index.jsx +3 -1
  26. package/lib/models/common/ComponentUI.ts +0 -14
  27. package/lib/models/common/CustomType/sliceZone.ts +0 -29
  28. package/lib/models/common/CustomType/tab.ts +10 -142
  29. package/lib/models/common/widgets/Group/ListItem/index.jsx +61 -23
  30. package/out/404.html +1 -1
  31. package/out/_next/static/chunks/065a3ddb-9a38ca0d60f0bf2f.js +1 -0
  32. package/out/_next/static/chunks/183-4feb6bb3eddbc768.js +1 -0
  33. package/out/_next/static/chunks/18539003-7b2711e6c51d6fac.js +97 -0
  34. package/out/_next/static/chunks/1cc2734a-2c5b6c0367fcde86.js +1 -0
  35. package/out/_next/static/chunks/25-8fedd33ad9b6de5b.js +1 -0
  36. package/out/_next/static/chunks/318-541db69860d31138.js +1 -0
  37. package/out/_next/static/chunks/{505-3f1cf09a086dcba8.js → 376-0ed5822f8afcaa7c.js} +3 -3
  38. package/out/_next/static/chunks/4c744e84-e3161d754618373f.js +1 -0
  39. package/out/_next/static/chunks/50-cfc2514205b86001.js +1 -0
  40. package/out/_next/static/chunks/543-f8766685f7f451e2.js +1 -0
  41. package/out/_next/static/chunks/59b4e022-7a3b5554b806349f.js +1 -0
  42. package/out/_next/static/chunks/696-b12edad30a3617e5.js +31 -0
  43. package/out/_next/static/chunks/727-15cf3f2fea9a37e5.js +1 -0
  44. package/out/_next/static/chunks/731-501990ebe6a71b32.js +1 -0
  45. package/out/_next/static/chunks/787-727e3aef5d2a10a8.js +1 -0
  46. package/out/_next/static/chunks/904-ccd8ca3368ce29fc.js +1 -0
  47. package/out/_next/static/chunks/{918-38d08f1e885b222d.js → 918-5bb55fb464e34768.js} +1 -1
  48. package/out/_next/static/chunks/f36c6662-03bb5e9d9aa0b0aa.js +1 -0
  49. package/out/_next/static/chunks/pages/_app-20876abeebe0fda7.js +430 -0
  50. package/out/_next/static/chunks/pages/changelog-68d115a14f1423d7.js +1 -0
  51. package/out/_next/static/chunks/pages/changes-6f62ae7b6243a1c7.js +1 -0
  52. package/out/_next/static/chunks/pages/custom-types/{[customTypeId]-3a37eb3373bb8823.js → [customTypeId]-3f862ad6111a1fc0.js} +1 -1
  53. package/out/_next/static/chunks/pages/{custom-types-2f5664d9492b13fb.js → custom-types-94b8f8dbf7727412.js} +1 -1
  54. package/out/_next/static/chunks/pages/{index-d8e3a2c0d712904f.js → index-64cfb8b0948ba8ef.js} +1 -1
  55. package/out/_next/static/chunks/pages/page-types/{[pageTypeId]-733f3890c0466a05.js → [pageTypeId]-d1ffca11c42f2603.js} +1 -1
  56. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-897ca93c114a1435.js +1 -0
  57. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-e89e2e6f772a3454.js +1 -0
  58. package/out/_next/static/chunks/pages/slices-9628f8aa54968d6a.js +1 -0
  59. package/out/_next/static/css/{1bbf650dfd37ce69.css → 1aa04669758c24f4.css} +1 -1
  60. package/out/_next/static/j_voPTrYzsuLCERqtl3Hn/_buildManifest.js +1 -0
  61. package/out/changelog.html +1 -1
  62. package/out/changes.html +1 -1
  63. package/out/custom-types/[customTypeId].html +1 -1
  64. package/out/custom-types.html +1 -1
  65. package/out/index.html +1 -1
  66. package/out/labs.html +1 -1
  67. package/out/page-types/[pageTypeId].html +1 -1
  68. package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  69. package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
  70. package/out/slices.html +1 -1
  71. package/package.json +6 -6
  72. package/pages/slices/[lib]/[sliceName]/[variation]/index.tsx +25 -11
  73. package/pages/slices/[lib]/[sliceName]/[variation]/simulator.tsx +12 -9
  74. package/src/apiClient.ts +7 -6
  75. package/src/components/CodeBlock/CodeBlock.tsx +1 -0
  76. package/src/components/Window/Window.tsx +7 -1
  77. package/src/domain/__tests__/customType.test.ts +785 -0
  78. package/src/domain/customType.ts +519 -6
  79. package/src/domain/slice.ts +166 -1
  80. package/src/features/autoSave/AutoSaveStatusIndicator.tsx +43 -0
  81. package/src/features/autoSave/useAutoSave.tsx +177 -0
  82. package/src/features/customTypes/EditDropdown.tsx +3 -0
  83. package/src/features/customTypes/actions/convertCustomToPageType.ts +2 -4
  84. package/src/features/customTypes/customTypesBuilder/CustomTypeProvider.tsx +90 -0
  85. package/src/features/customTypes/customTypesBuilder/CustomTypesBuilderPage.tsx +46 -79
  86. package/src/features/customTypes/customTypesMessages.ts +4 -0
  87. package/src/features/slices/actions/addSlicesToSliceZone.ts +2 -7
  88. package/src/features/slices/actions/uploadSliceScreenshot.ts +45 -0
  89. package/src/features/slices/convertLegacySlice/ConvertLegacySliceAsNewVariationDialog.tsx +5 -5
  90. package/src/features/slices/convertLegacySlice/ConvertLegacySliceButton.tsx +4 -10
  91. package/src/features/slices/sliceBuilder/SliceBuilderProvider.tsx +110 -0
  92. package/src/features/slices/sliceBuilder/actions/deleteVariation.ts +8 -24
  93. package/src/features/slices/sliceBuilder/actions/renameVariation.ts +8 -24
  94. package/src/features/slices/sliceCards/SharedSliceCard.tsx +1 -0
  95. package/src/hooks/useCurrentSlice.tsx +4 -16
  96. package/src/hooks/useScreenshotChangesModal.ts +1 -0
  97. package/src/hooks/useServerState.ts +1 -58
  98. package/src/modules/availableCustomTypes/index.ts +8 -3
  99. package/src/modules/simulator/index.ts +0 -2
  100. package/src/modules/slices/index.ts +32 -25
  101. package/src/modules/slices/selector.ts +30 -0
  102. package/src/modules/useSliceMachineActions.ts +20 -270
  103. package/src/redux/reducer.ts +0 -4
  104. package/src/redux/saga.ts +0 -6
  105. package/src/redux/type.ts +0 -4
  106. package/test/src/modules/availableCustomTypes/index.test.ts +8 -10
  107. package/test/src/modules/simulator.test.ts +0 -2
  108. package/lib/models/common/CustomType/group.ts +0 -80
  109. package/lib/models/common/Variation.ts +0 -100
  110. package/out/_next/static/ZrWICkLApT4ZATA_akn-2/_buildManifest.js +0 -1
  111. package/out/_next/static/chunks/18539003-4460ccbfe3109578.js +0 -97
  112. package/out/_next/static/chunks/482-34cee2a2071c235f.js +0 -1
  113. package/out/_next/static/chunks/550-c80fd46fb64d1eef.js +0 -1
  114. package/out/_next/static/chunks/80-7b8a97d0122ff74a.js +0 -1
  115. package/out/_next/static/chunks/840-163f8a1040e6820d.js +0 -1
  116. package/out/_next/static/chunks/904-519dbf0f7e8c6243.js +0 -1
  117. package/out/_next/static/chunks/958-8aca174b80cb0c35.js +0 -1
  118. package/out/_next/static/chunks/pages/_app-132564608e9a9502.js +0 -458
  119. package/out/_next/static/chunks/pages/changelog-4d0f2f1222e403fe.js +0 -1
  120. package/out/_next/static/chunks/pages/changes-52c9d917808d1461.js +0 -1
  121. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-7b17cb59d0db03b5.js +0 -1
  122. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-ef11594ce026b650.js +0 -1
  123. package/out/_next/static/chunks/pages/slices-884a936a9a062a65.js +0 -1
  124. package/src/domain/__tests__/CustomTypeModel.test.ts +0 -247
  125. package/src/layouts/WithSlice.tsx +0 -26
  126. package/src/modules/screenshots/actions.ts +0 -21
  127. package/src/modules/screenshots/sagas.ts +0 -70
  128. package/src/modules/selectedCustomType/actions.ts +0 -147
  129. package/src/modules/selectedCustomType/index.ts +0 -11
  130. package/src/modules/selectedCustomType/reducer.ts +0 -287
  131. package/src/modules/selectedCustomType/sagas.ts +0 -72
  132. package/src/modules/selectedCustomType/selectors.ts +0 -33
  133. package/src/modules/selectedCustomType/stateHelpers.ts +0 -42
  134. package/src/modules/selectedCustomType/types.ts +0 -9
  135. package/src/modules/selectedSlice/actions.ts +0 -106
  136. package/src/modules/selectedSlice/reducer.ts +0 -175
  137. package/src/modules/selectedSlice/sagas.ts +0 -72
  138. package/src/modules/selectedSlice/selectors.ts +0 -55
  139. package/src/modules/selectedSlice/types.ts +0 -3
  140. package/src/modules/toaster/utils.tsx +0 -23
  141. package/test/lib/models/common/CustomType/sliceZone.test.ts +0 -49
  142. package/test/pages/custom-types.test.tsx +0 -625
  143. package/test/src/modules/selectedCustomType/__fixtures__/model.json +0 -119
  144. package/test/src/modules/selectedCustomType/reducer.test.ts +0 -322
  145. package/test/src/modules/selectedCustomType/sagas.test.ts +0 -89
  146. package/test/src/modules/selectedCustomType/selectors.test.ts +0 -54
  147. package/test/src/modules/selectedSlice/__fixtures__/mocks.json +0 -171
  148. package/test/src/modules/selectedSlice/__fixtures__/model.json +0 -35
  149. package/test/src/modules/selectedSlice/__testutils__/getRefreshStateCreatorPayloadData.ts +0 -72
  150. package/test/src/modules/selectedSlice/__testutils__/getSelectedSliceDummyData.ts +0 -30
  151. package/test/src/modules/selectedSlice/reducer.test.ts +0 -170
  152. package/test/src/modules/selectedSlice/sagas.test.ts +0 -82
  153. package/test/src/modules/toaster/utils.test.ts +0 -50
  154. /package/out/_next/static/{ZrWICkLApT4ZATA_akn-2 → j_voPTrYzsuLCERqtl3Hn}/_ssgManifest.js +0 -0
@@ -7,21 +7,19 @@ import {
7
7
  Text,
8
8
  } from "@prismicio/editor-ui";
9
9
  import { useRouter } from "next/router";
10
- import type { Dispatch, FC, PropsWithChildren, SetStateAction } from "react";
10
+ import { useState, type FC, type PropsWithChildren } from "react";
11
11
 
12
- import type { SliceBuilderState } from "@builders/SliceBuilder";
13
12
  import type { ComponentUI } from "@lib/models/common/ComponentUI";
14
13
  import type { VariationSM } from "@lib/models/common/Slice";
15
14
  import { deleteVariation } from "@src/features/slices/sliceBuilder/actions/deleteVariation";
16
15
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
16
+ import { useSliceState } from "@src/features/slices/sliceBuilder/SliceBuilderProvider";
17
17
 
18
18
  type DeleteVariationModalProps = {
19
19
  isOpen: boolean;
20
20
  onClose: () => void;
21
21
  slice: ComponentUI;
22
22
  variation: VariationSM | undefined;
23
- sliceBuilderState: SliceBuilderState;
24
- setSliceBuilderState: Dispatch<SetStateAction<SliceBuilderState>>;
25
23
  };
26
24
 
27
25
  export const DeleteVariationModal: FC<DeleteVariationModalProps> = ({
@@ -29,11 +27,12 @@ export const DeleteVariationModal: FC<DeleteVariationModalProps> = ({
29
27
  onClose,
30
28
  slice,
31
29
  variation,
32
- sliceBuilderState,
33
- setSliceBuilderState,
34
30
  }) => {
35
31
  const router = useRouter();
36
- const { updateAndSaveSlice } = useSliceMachineActions();
32
+ const [isDeleting, setIsDeleting] = useState(false);
33
+ const { saveSliceSuccess } = useSliceMachineActions();
34
+ const { setSlice } = useSliceState();
35
+
37
36
  return (
38
37
  <Dialog
39
38
  open={isOpen}
@@ -56,19 +55,21 @@ export const DeleteVariationModal: FC<DeleteVariationModalProps> = ({
56
55
  onClick: () => {
57
56
  if (!variation) return;
58
57
  void (async () => {
58
+ setIsDeleting(true);
59
59
  try {
60
- await deleteVariation({
60
+ const newSlice = await deleteVariation({
61
61
  component: slice,
62
62
  router,
63
- setSliceBuilderState,
64
- updateAndSaveSlice,
63
+ saveSliceSuccess,
65
64
  variation,
66
65
  });
66
+ setSlice(newSlice);
67
67
  } catch {}
68
+ setIsDeleting(false);
68
69
  onClose();
69
70
  })();
70
71
  },
71
- loading: sliceBuilderState.loading,
72
+ loading: isDeleting,
72
73
  }}
73
74
  cancel={{ text: "Cancel" }}
74
75
  size="medium"
@@ -15,10 +15,7 @@ import { InputBox } from "../components/InputBox";
15
15
 
16
16
  type CreateSliceModalProps = {
17
17
  onClose: () => void;
18
- onSuccess: (
19
- newSlice: SharedSlice,
20
- libraryName: string,
21
- ) => Promise<void> | void;
18
+ onSuccess: (newSlice: SharedSlice, libraryName: string) => void;
22
19
  localLibraries: readonly LibraryUI[];
23
20
  remoteSlices: ReadonlyArray<SliceSM>;
24
21
  };
@@ -49,7 +46,7 @@ export const CreateSliceModal: FC<CreateSliceModalProps> = ({
49
46
  // Update Redux store
50
47
  createSliceSuccess(serverState.libraries);
51
48
 
52
- await onSuccess(newSlice, libraryName);
49
+ onSuccess(newSlice, libraryName);
53
50
  },
54
51
  });
55
52
  };
@@ -6,8 +6,8 @@ import { InputBox } from "../components/InputBox";
6
6
  import { useSelector } from "react-redux";
7
7
  import { SliceMachineStoreType } from "@src/redux/type";
8
8
  import { FormikErrors } from "formik";
9
- import { selectAllCustomTypeLabels } from "@src/modules/availableCustomTypes";
10
9
 
10
+ import { selectAllCustomTypeLabels } from "@src/modules/availableCustomTypes";
11
11
  import { CustomType } from "@prismicio/types-internal/lib/customtypes";
12
12
  import { CustomTypeFormat } from "@slicemachine/manager";
13
13
  import { CUSTOM_TYPES_MESSAGES } from "@src/features/customTypes/customTypesMessages";
@@ -19,6 +19,7 @@ interface RenameCustomTypeModalProps {
19
19
  customType: CustomType;
20
20
  format: CustomTypeFormat;
21
21
  onClose: () => void;
22
+ setLocalCustomType?: (customType: CustomType) => void;
22
23
  }
23
24
 
24
25
  export const RenameCustomTypeModal: React.FC<RenameCustomTypeModalProps> = ({
@@ -26,18 +27,21 @@ export const RenameCustomTypeModal: React.FC<RenameCustomTypeModalProps> = ({
26
27
  customType,
27
28
  format,
28
29
  onClose,
30
+ setLocalCustomType,
29
31
  }) => {
30
32
  const customTypeName = customType?.label ?? "";
31
33
  const customTypeId = customType?.id ?? "";
32
- const { renameAvailableCustomTypeSuccess, renameSelectedCustomType } =
33
- useSliceMachineActions();
34
+ const { renameAvailableCustomTypeSuccess } = useSliceMachineActions();
34
35
 
35
36
  const [isRenaming, setIsRenaming] = useState(false);
36
37
 
37
38
  const handleOnSubmit = async (values: { customTypeName: string }) => {
38
39
  setIsRenaming(true);
39
- if (isChangesLocal) {
40
- renameSelectedCustomType(values.customTypeName);
40
+ if (isChangesLocal && setLocalCustomType) {
41
+ setLocalCustomType({
42
+ ...customType,
43
+ label: values.customTypeName,
44
+ });
41
45
  } else {
42
46
  await renameCustomType({
43
47
  model: customType,
@@ -8,23 +8,21 @@ import {
8
8
  Text,
9
9
  } from "@prismicio/editor-ui";
10
10
  import { Formik } from "formik";
11
- import type { Dispatch, FC, SetStateAction } from "react";
11
+ import { useState, type FC } from "react";
12
12
 
13
- import type { SliceBuilderState } from "@builders/SliceBuilder";
14
13
  import type { ComponentUI } from "@lib/models/common/ComponentUI";
15
14
  import type { VariationSM } from "@lib/models/common/Slice";
16
15
  import { renameVariation } from "@src/features/slices/sliceBuilder/actions/renameVariation";
17
16
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
18
17
 
19
18
  import * as styles from "./RenameVariationModal.css";
19
+ import { useSliceState } from "@src/features/slices/sliceBuilder/SliceBuilderProvider";
20
20
 
21
21
  type RenameVariationModalProps = {
22
22
  isOpen: boolean;
23
23
  onClose: () => void;
24
24
  slice: ComponentUI;
25
25
  variation: VariationSM | undefined;
26
- sliceBuilderState: SliceBuilderState;
27
- setSliceBuilderState: Dispatch<SetStateAction<SliceBuilderState>>;
28
26
  };
29
27
 
30
28
  export const RenameVariationModal: FC<RenameVariationModalProps> = ({
@@ -32,10 +30,11 @@ export const RenameVariationModal: FC<RenameVariationModalProps> = ({
32
30
  onClose,
33
31
  slice,
34
32
  variation,
35
- sliceBuilderState,
36
- setSliceBuilderState,
37
33
  }) => {
38
- const { updateAndSaveSlice } = useSliceMachineActions();
34
+ const [isRenaming, setRenaming] = useState(false);
35
+ const { setSlice } = useSliceState();
36
+ const { saveSliceSuccess } = useSliceMachineActions();
37
+
39
38
  return (
40
39
  <>
41
40
  <Dialog
@@ -56,15 +55,17 @@ export const RenameVariationModal: FC<RenameVariationModalProps> = ({
56
55
  }}
57
56
  onSubmit={async (values) => {
58
57
  if (!variation) return;
58
+ setRenaming(true);
59
59
  try {
60
- await renameVariation({
60
+ const newSlice = await renameVariation({
61
61
  component: slice,
62
- setSliceBuilderState,
63
- updateAndSaveSlice,
62
+ saveSliceSuccess,
64
63
  variation,
65
64
  variationName: values.variationName.trim(),
66
65
  });
66
+ setSlice(newSlice);
67
67
  } catch {}
68
+ setRenaming(false);
68
69
  onClose();
69
70
  }}
70
71
  >
@@ -102,7 +103,7 @@ export const RenameVariationModal: FC<RenameVariationModalProps> = ({
102
103
  ok={{
103
104
  text: "Rename",
104
105
  onClick: () => void formik.submitForm(),
105
- loading: sliceBuilderState.loading,
106
+ loading: isRenaming,
106
107
  disabled: !formik.isValid,
107
108
  }}
108
109
  cancel={{ text: "Cancel" }}
@@ -22,6 +22,7 @@ const ItemHeader: React.FC<{
22
22
  />
23
23
  <Text
24
24
  as="p"
25
+ data-cy="item-header-text"
25
26
  sx={{
26
27
  py: 0,
27
28
  px: 1,
@@ -34,6 +34,7 @@ interface ListItemProps<F extends TabField, S extends AnyObjectSchema> {
34
34
  CustomEditElements?: JSX.Element[];
35
35
  widget: Widget<F, S>;
36
36
  draggableId: string;
37
+ dataCy: string;
37
38
  isRepeatableCustomType?: boolean;
38
39
  children: React.ReactNode;
39
40
  }
@@ -50,6 +51,7 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
50
51
  CustomEditElements,
51
52
  widget,
52
53
  draggableId,
54
+ dataCy,
53
55
  isRepeatableCustomType,
54
56
  children,
55
57
  }: ListItemProps<F, S>): JSX.Element {
@@ -66,6 +68,7 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
66
68
  {(provided) => (
67
69
  <Fragment>
68
70
  <Li
71
+ data-cy={dataCy}
69
72
  ref={provided.innerRef}
70
73
  {...provided.draggableProps}
71
74
  Component={Box}
@@ -117,7 +120,7 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
117
120
  <SliceMachineIconButton
118
121
  size={22}
119
122
  Icon={AiOutlineEdit}
120
- label="Edit slice field"
123
+ label="Edit field"
121
124
  sx={{ cursor: "pointer", color: theme.colors?.icons }}
122
125
  onClick={() =>
123
126
  enterEditMode(
@@ -134,7 +137,7 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
134
137
  <Menu>
135
138
  <MenuButton
136
139
  className="sliceMenuButton"
137
- data-cy="slice-menu-button"
140
+ data-cy="field-menu-button"
138
141
  style={{
139
142
  padding: "0",
140
143
  cursor: "pointer",
@@ -14,11 +14,13 @@ import { isLoading } from "@src/modules/loading";
14
14
  import { LoadingKeysEnum } from "@src/modules/loading/types";
15
15
  import { ScreenshotPreview } from "@components/ScreenshotPreview";
16
16
  import { ComponentUI } from "@lib/models/common/ComponentUI";
17
+ import { uploadSliceScreenshot } from "@src/features/slices/actions/uploadSliceScreenshot";
17
18
 
18
19
  interface DropZoneProps {
19
20
  imageTypes?: string[];
20
21
  variationID: string;
21
22
  slice: ComponentUI;
23
+ onUploadSuccess?: (newSlice: ComponentUI) => void;
22
24
  }
23
25
 
24
26
  const DragActiveView = () => {
@@ -79,6 +81,7 @@ const DropZone: React.FC<DropZoneProps> = ({
79
81
  variationID,
80
82
  slice,
81
83
  imageTypes = acceptedImagesTypes,
84
+ onUploadSuccess,
82
85
  }) => {
83
86
  const maybeScreenshot = slice.screenshots[variationID];
84
87
 
@@ -90,7 +93,7 @@ const DropZone: React.FC<DropZoneProps> = ({
90
93
  slice,
91
94
  ]);
92
95
 
93
- const { generateSliceCustomScreenshot } = useSliceMachineActions();
96
+ const { saveSliceCustomScreenshotSuccess } = useSliceMachineActions();
94
97
 
95
98
  const { isLoadingScreenshot } = useSelector(
96
99
  (state: SliceMachineStoreType) => ({
@@ -102,25 +105,44 @@ const DropZone: React.FC<DropZoneProps> = ({
102
105
  );
103
106
 
104
107
  const { FileInputRenderer, fileInputProps } = useCustomScreenshot({
105
- onHandleFile: (file: File, isDragActive: boolean) => {
106
- generateSliceCustomScreenshot(
107
- variationID,
108
+ onHandleFile: async (file: File, isDragActive: boolean) => {
109
+ const newSlice = await uploadSliceScreenshot({
108
110
  slice,
109
111
  file,
110
- isDragActive ? "dragAndDrop" : "upload",
111
- );
112
+ method: isDragActive ? "dragAndDrop" : "upload",
113
+ variationId: variationID,
114
+ });
112
115
  setIsHover(false);
116
+
117
+ const screenshot = newSlice?.screenshots[variationID];
118
+ if (screenshot) {
119
+ // Sync with redux store
120
+ saveSliceCustomScreenshotSuccess(variationID, screenshot, newSlice);
121
+ onUploadSuccess && onUploadSuccess(newSlice);
122
+ }
113
123
  },
114
124
  });
115
125
 
116
- const handleFile = (file: File) => {
126
+ const handleFile = async (file: File) => {
117
127
  if (file.size > 128000000) {
118
128
  return openToaster(
119
129
  "File is too big. Max file size: 128Mb.",
120
130
  ToasterType.ERROR,
121
131
  );
122
132
  }
123
- generateSliceCustomScreenshot(variationID, slice, file, "dragAndDrop");
133
+ const newSlice = await uploadSliceScreenshot({
134
+ slice,
135
+ file,
136
+ method: "dragAndDrop",
137
+ variationId: variationID,
138
+ });
139
+
140
+ const screenshot = newSlice?.screenshots[variationID];
141
+ if (screenshot) {
142
+ // Sync with redux store
143
+ saveSliceCustomScreenshotSuccess(variationID, screenshot, newSlice);
144
+ onUploadSuccess && onUploadSuccess(newSlice);
145
+ }
124
146
  };
125
147
 
126
148
  const supportsClipboardRead = typeof navigator.clipboard.read === "function";
@@ -149,7 +171,7 @@ const DropZone: React.FC<DropZoneProps> = ({
149
171
  const maybeFile = event.dataTransfer.files?.[0];
150
172
  if (maybeFile !== undefined) {
151
173
  if (imageTypes.some((t) => `image/${t}` === maybeFile.type)) {
152
- return handleFile(maybeFile);
174
+ return void handleFile(maybeFile);
153
175
  }
154
176
  return openToaster(
155
177
  `Only files of type ${imageTypes.join(", ")} are accepted.`,
@@ -171,9 +171,11 @@ const variationSetter = (
171
171
  const ScreenshotChangesModal = ({
172
172
  slices,
173
173
  defaultVariationSelector,
174
+ onUploadSuccess,
174
175
  }: {
175
176
  slices: ComponentUI[];
176
177
  defaultVariationSelector?: SliceVariationSelector;
178
+ onUploadSuccess?: (newSlice: ComponentUI) => void;
177
179
  }) => {
178
180
  const { closeModals } = useSliceMachineActions();
179
181
 
@@ -275,6 +277,7 @@ const ScreenshotChangesModal = ({
275
277
  <VariationDropZone
276
278
  variationID={variationSelector.variationID}
277
279
  slice={slice}
280
+ onUploadSuccess={onUploadSuccess}
278
281
  />
279
282
  ) : null;
280
283
  })()}
@@ -6,11 +6,11 @@ import { acceptedImagesTypes } from "@lib/consts";
6
6
  type HandleFileProp = {
7
7
  inputFile: React.RefObject<HTMLInputElement>;
8
8
  children?: React.ReactNode;
9
- handleFile: (file: File | undefined, isDragActive: boolean) => void;
9
+ handleFile: (file: File | undefined, isDragActive: boolean) => Promise<void>;
10
10
  isDragActive: boolean;
11
11
  };
12
12
  type CustomScreenshotProps = {
13
- onHandleFile: (file: File, isDragActive: boolean) => void;
13
+ onHandleFile: (file: File, isDragActive: boolean) => Promise<void>;
14
14
  };
15
15
 
16
16
  const FileInputRenderer: React.FC<HandleFileProp> = ({
@@ -43,7 +43,7 @@ const FileInputRenderer: React.FC<HandleFileProp> = ({
43
43
  style={{ display: "none" }}
44
44
  accept={acceptedImagesTypes.map((type) => `image/${type}`).join(",")}
45
45
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
46
- handleFile(e.target.files?.[0], isDragActive);
46
+ void handleFile(e.target.files?.[0], isDragActive);
47
47
  }}
48
48
  />
49
49
  </>
@@ -63,9 +63,9 @@ export default function useCustomScreenshot({
63
63
  onHandleFile,
64
64
  }: CustomScreenshotProps): CustomScreenshotPayload {
65
65
  const inputFile = useRef<HTMLInputElement>(null);
66
- const handleFile = (file: File | undefined, isDragActive: boolean) => {
66
+ const handleFile = async (file: File | undefined, isDragActive: boolean) => {
67
67
  if (file) {
68
- onHandleFile(file, isDragActive);
68
+ await onHandleFile(file, isDragActive);
69
69
  if (inputFile?.current) {
70
70
  inputFile.current.value = "";
71
71
  }
@@ -1,4 +1,5 @@
1
1
  import {
2
+ FC,
2
3
  Suspense,
3
4
  useCallback,
4
5
  useEffect,
@@ -34,7 +35,6 @@ import useThrottle from "@src/hooks/useThrottle";
34
35
  import useSliceMachineActions from "@src/modules/useSliceMachineActions";
35
36
 
36
37
  import IframeRenderer from "./components/IframeRenderer";
37
- import { ComponentWithSliceProps } from "@src/layouts/WithSlice";
38
38
  import {
39
39
  selectIframeStatus,
40
40
  selectIsWaitingForIFrameCheck,
@@ -44,7 +44,8 @@ import {
44
44
  import FullPage from "./components/FullPage";
45
45
  import FailedConnect from "./components/FailedConnect";
46
46
  import SetupModal from "./components/SetupModal";
47
- import { Slices } from "@lib/models/common/Slice";
47
+ import { Slices, VariationSM } from "@lib/models/common/Slice";
48
+ import { ComponentUI } from "@lib/models/common/ComponentUI";
48
49
 
49
50
  export enum UiState {
50
51
  LOADING_SETUP = "LOADING_SETUP",
@@ -54,7 +55,12 @@ export enum UiState {
54
55
  SUCCESS = "SUCCESS",
55
56
  }
56
57
 
57
- const Simulator: ComponentWithSliceProps = ({ slice, variation }) => {
58
+ type SimulatorProps = {
59
+ slice: ComponentUI;
60
+ variation: VariationSM;
61
+ };
62
+
63
+ const Simulator: FC<SimulatorProps> = ({ slice, variation }) => {
58
64
  const { checkSimulatorSetup, connectToSimulatorIframe, saveSliceMock } =
59
65
  useSliceMachineActions();
60
66
  const {
@@ -18,7 +18,7 @@ import { sliceTemplatesComingSoon } from "./sliceTemplatesComingSoon";
18
18
  interface UpdateSliceModalProps {
19
19
  formId: string;
20
20
  close: () => void;
21
- onSuccess: (slices: SharedSlice[]) => Promise<void>;
21
+ onSuccess: (slices: SharedSlice[]) => void;
22
22
  availableSlicesTemplates: SliceTemplate[];
23
23
  localLibraries: readonly LibraryUI[];
24
24
  }
@@ -69,7 +69,7 @@ export const SlicesTemplatesModal: FC<UpdateSliceModalProps> = ({
69
69
  ) as Promise<SharedSlice>[],
70
70
  );
71
71
 
72
- await onSuccess(slices);
72
+ onSuccess(slices);
73
73
  },
74
74
  });
75
75
  }}
@@ -9,7 +9,7 @@ import UpdateSliceZoneModalList from "./UpdateSliceZoneModalList";
9
9
  interface UpdateSliceModalProps {
10
10
  formId: string;
11
11
  close: () => void;
12
- onSubmit: (slices: SharedSlice[]) => Promise<void>;
12
+ onSubmit: (slices: SharedSlice[]) => void;
13
13
  availableSlices: ReadonlyArray<ComponentUI>;
14
14
  }
15
15
 
@@ -37,7 +37,7 @@ const UpdateSliceZoneModal: React.FC<UpdateSliceModalProps> = ({
37
37
  availableSlices.find((s) => s.model.id === sliceKey)?.model,
38
38
  )
39
39
  .filter((slice) => slice !== undefined) as SharedSlice[];
40
- void onSubmit(slices);
40
+ onSubmit(slices);
41
41
  }}
42
42
  initialValues={{
43
43
  sliceKeys: [],
@@ -31,9 +31,9 @@ import {
31
31
  } from "@src/modules/slices";
32
32
  import type { SliceMachineStoreType } from "@src/redux/type";
33
33
  import { useSlicesTemplates } from "@src/features/slicesTemplates/useSlicesTemplates";
34
- import useSliceMachineActions from "@src/modules/useSliceMachineActions";
35
34
  import { addSlicesToSliceZone } from "@src/features/slices/actions/addSlicesToSliceZone";
36
35
  import { ToastMessageWithPath } from "@components/ToasterContainer";
36
+ import { useCustomTypeState } from "@src/features/customTypes/customTypesBuilder/CustomTypeProvider";
37
37
 
38
38
  import { DeleteSliceZoneModal } from "./DeleteSliceZoneModal";
39
39
  import UpdateSliceZoneModal from "./UpdateSliceZoneModal";
@@ -121,8 +121,8 @@ const SliceZone: React.FC<SliceZoneProps> = ({
121
121
  slices: getFrontendSlices(store),
122
122
  }),
123
123
  );
124
- const { initCustomTypeStore, saveCustomTypeSuccess } =
125
- useSliceMachineActions();
124
+ const { setCustomType } = useCustomTypeState();
125
+
126
126
  const localLibraries: readonly LibraryUI[] = libraries.filter(
127
127
  (library) => library.isLocal,
128
128
  );
@@ -197,14 +197,6 @@ const SliceZone: React.FC<SliceZoneProps> = ({
197
197
  setIsSlicesTemplatesModalOpen(false);
198
198
  };
199
199
 
200
- const onAddSlicesToSliceZone = (newCustomType: CustomTypeSM) => {
201
- // Reset selected custom type store to update slice zone and saving status
202
- initCustomTypeStore(newCustomType, newCustomType);
203
-
204
- // Update available custom type store with new custom type
205
- saveCustomTypeSuccess(CustomTypes.fromSM(newCustomType));
206
- };
207
-
208
200
  return (
209
201
  <>
210
202
  {query.newPageType === undefined ? (
@@ -299,13 +291,13 @@ const SliceZone: React.FC<SliceZoneProps> = ({
299
291
  <UpdateSliceZoneModal
300
292
  formId={`tab-slicezone-form-${tabId}`}
301
293
  availableSlices={availableSlicesToAdd}
302
- onSubmit={async (slices: SharedSlice[]) => {
303
- const newCustomType = await addSlicesToSliceZone({
294
+ onSubmit={(slices: SharedSlice[]) => {
295
+ const newCustomType = addSlicesToSliceZone({
304
296
  customType,
305
297
  tabId,
306
298
  slices,
307
299
  });
308
- onAddSlicesToSliceZone(newCustomType);
300
+ setCustomType(CustomTypes.fromSM(newCustomType));
309
301
  closeUpdateSliceZoneModal();
310
302
  redirectToEditMode();
311
303
  toast.success("Slice(s) added to slice zone");
@@ -318,13 +310,13 @@ const SliceZone: React.FC<SliceZoneProps> = ({
318
310
  formId={`tab-slicezone-form-${tabId}`}
319
311
  availableSlicesTemplates={availableSlicesTemplates}
320
312
  localLibraries={localLibraries}
321
- onSuccess={async (slices: SharedSlice[]) => {
322
- const newCustomType = await addSlicesToSliceZone({
313
+ onSuccess={(slices: SharedSlice[]) => {
314
+ const newCustomType = addSlicesToSliceZone({
323
315
  customType,
324
316
  tabId,
325
317
  slices,
326
318
  });
327
- onAddSlicesToSliceZone(newCustomType);
319
+ setCustomType(CustomTypes.fromSM(newCustomType));
328
320
  closeSlicesTemplatesModal();
329
321
  redirectToEditMode();
330
322
  toast.success(
@@ -350,13 +342,13 @@ const SliceZone: React.FC<SliceZoneProps> = ({
350
342
  )}
351
343
  {localLibraries?.length !== 0 && isCreateSliceModalOpen && (
352
344
  <CreateSliceModal
353
- onSuccess={async (newSlice: SharedSlice) => {
354
- const newCustomType = await addSlicesToSliceZone({
345
+ onSuccess={(newSlice: SharedSlice) => {
346
+ const newCustomType = addSlicesToSliceZone({
355
347
  customType,
356
348
  tabId,
357
349
  slices: [newSlice],
358
350
  });
359
- onAddSlicesToSliceZone(newCustomType);
351
+ setCustomType(CustomTypes.fromSM(newCustomType));
360
352
  closeCreateSliceModal();
361
353
  redirectToEditMode();
362
354
  toast.success(
@@ -10,11 +10,13 @@ const UpdateCustomTypeForm = ({
10
10
  onSubmit,
11
11
  close,
12
12
  tabIds,
13
+ initialTabKey,
13
14
  }: {
14
15
  isOpen: boolean;
15
16
  onSubmit: (values: { id: string }) => void;
16
17
  close: () => void;
17
18
  tabIds: ReadonlyArray<string>;
19
+ initialTabKey: string;
18
20
  }) => {
19
21
  return (
20
22
  <ModalFormCard
@@ -29,7 +31,7 @@ const UpdateCustomTypeForm = ({
29
31
  close();
30
32
  }}
31
33
  initialValues={{
32
- id: "",
34
+ id: initialTabKey,
33
35
  }}
34
36
  validate={({ id }) => {
35
37
  if (!id) {