slice-machine-ui 1.25.1-beta.5 → 1.25.1-beta.7

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 (70) hide show
  1. package/components/Navigation/ChangesItem.tsx +48 -7
  2. package/components/Navigation/index.test.tsx +1 -1
  3. package/components/Navigation/index.tsx +4 -1
  4. package/lib/builders/CustomTypeBuilder/TabZone/index.tsx +8 -6
  5. package/lib/builders/SliceBuilder/FieldZones/index.tsx +17 -2
  6. package/lib/builders/common/Zone/index.jsx +18 -0
  7. package/lib/models/common/widgets/Group/ListItem/index.jsx +21 -0
  8. package/out/404.html +1 -1
  9. package/out/_next/static/chunks/{183-4feb6bb3eddbc768.js → 183-ebd633fed7c74545.js} +1 -1
  10. package/out/_next/static/chunks/318-d6f1200138628ec3.js +1 -0
  11. package/out/_next/static/chunks/{727-df23c133f7cbf952.js → 727-2c302be2def92786.js} +1 -1
  12. package/out/_next/static/chunks/{799-9bea9069969f5fe0.js → 799-7b910b896ff60ebe.js} +1 -1
  13. package/out/_next/static/chunks/{904-1a755ebb0f5ee4ac.js → 904-c9221a5cb09524e8.js} +1 -1
  14. package/out/_next/static/chunks/pages/{_app-4500c5314e33c7aa.js → _app-30f8a579c4d383f3.js} +52 -52
  15. package/out/_next/static/chunks/pages/{changelog-57289ca6bc99702b.js → changelog-5c9ac93faf0df06b.js} +1 -1
  16. package/out/_next/static/chunks/pages/{changes-94c1a3379fc3dac5.js → changes-3e4989e09fd412a8.js} +1 -1
  17. package/out/_next/static/chunks/pages/{labs-49bed0a08da3772c.js → labs-6f5925cd6cdcee9e.js} +1 -1
  18. package/out/_next/static/chunks/pages/{settings-12f209f1d5d42b1c.js → settings-f0620e5b727cda03.js} +1 -1
  19. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-8d7043e6638d65cd.js +1 -0
  20. package/out/_next/static/chunks/pages/{slices-01aa9c2bc7c192be.js → slices-77cff50b1df13579.js} +1 -1
  21. package/out/_next/static/css/{4f1e84c70ef0e169.css → 21654235130d0806.css} +1 -1
  22. package/out/_next/static/{QbkBgzWD1MMQdeEUWvKYu → vNxSAIw3P6M_wdZBPWPUk}/_buildManifest.js +1 -1
  23. package/out/changelog.html +1 -1
  24. package/out/changes.html +1 -1
  25. package/out/custom-types/[customTypeId].html +1 -1
  26. package/out/custom-types.html +1 -1
  27. package/out/index.html +1 -1
  28. package/out/labs.html +1 -1
  29. package/out/page-types/[pageTypeId].html +1 -1
  30. package/out/settings.html +1 -1
  31. package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  32. package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
  33. package/out/slices.html +1 -1
  34. package/package.json +3 -3
  35. package/src/components/BaseHoverCard/BaseHoverCard.tsx +3 -2
  36. package/src/components/BlankSlate/BlankSlate.tsx +1 -1
  37. package/src/components/Divider/Divider.tsx +2 -2
  38. package/src/components/HoverCard/HoverCard.tsx +11 -11
  39. package/src/components/PageLayout/PageLayout.module.css +82 -0
  40. package/src/components/PageLayout/PageLayout.module.css.d.ts +14 -0
  41. package/src/components/PageLayout/PageLayout.stories.tsx +3 -6
  42. package/src/components/PageLayout/PageLayout.tsx +11 -8
  43. package/src/components/SideNav/SideNav.module.css +318 -0
  44. package/src/components/SideNav/SideNav.module.css.d.ts +29 -0
  45. package/src/components/SideNav/SideNav.stories.tsx +10 -1
  46. package/src/components/SideNav/SideNav.tsx +37 -38
  47. package/src/components/SideNav/SideNavEnvironmentSelector.module.css +59 -0
  48. package/src/components/SideNav/SideNavEnvironmentSelector.module.css.d.ts +13 -0
  49. package/src/components/SideNav/SideNavEnvironmentSelector.tsx +97 -66
  50. package/src/components/TextLink/TextLink.tsx +2 -4
  51. package/src/features/sync/components/AutoSyncStatusIndicator.module.css +6 -0
  52. package/src/features/sync/components/AutoSyncStatusIndicator.module.css.d.ts +1 -0
  53. package/src/features/sync/components/AutoSyncStatusIndicator.tsx +4 -2
  54. package/src/icons/ChangesIcon.tsx +19 -0
  55. package/src/icons/DatabaseIcon.tsx +1 -0
  56. package/src/icons/FolderIcon.tsx +1 -0
  57. package/src/icons/Lightning.tsx +1 -0
  58. package/src/icons/LogoIcon.tsx +27 -23
  59. package/src/icons/MathPlusIcon.tsx +1 -1
  60. package/src/icons/OpenIcon.tsx +1 -1
  61. package/src/icons/PageStackIcon.tsx +1 -0
  62. package/src/icons/RadarIcon.tsx +1 -0
  63. package/test/__setup__.ts +15 -0
  64. package/test/__testutils__/index.tsx +8 -5
  65. package/out/_next/static/chunks/318-2426f74a0d6c3b89.js +0 -1
  66. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-ba6c3e2624f32fcd.js +0 -1
  67. package/src/components/PageLayout/PageLayout.css.ts +0 -69
  68. package/src/components/SideNav/SideNav.css.ts +0 -381
  69. package/src/components/SideNav/SideNavEnvironmentSelector.css.ts +0 -65
  70. /package/out/_next/static/{QbkBgzWD1MMQdeEUWvKYu → vNxSAIw3P6M_wdZBPWPUk}/_ssgManifest.js +0 -0
@@ -1,6 +1,14 @@
1
1
  import { type FC } from "react";
2
2
  import { useRouter } from "next/router";
3
- import { Box, Button, Text } from "@prismicio/editor-ui";
3
+ import { useMediaQuery } from "@prismicio/editor-support/React";
4
+ import {
5
+ Box,
6
+ Button,
7
+ IconButton,
8
+ Text,
9
+ Tooltip,
10
+ breakpoints,
11
+ } from "@prismicio/editor-ui";
4
12
 
5
13
  import {
6
14
  HoverCard,
@@ -13,6 +21,7 @@ import useSliceMachineActions from "@src/modules/useSliceMachineActions";
13
21
  import { useNetwork } from "@src/hooks/useNetwork";
14
22
  import { useAuthStatus } from "@src/hooks/useAuthStatus";
15
23
  import { useUnSyncChanges } from "@src/features/sync/useUnSyncChanges";
24
+ import { ChangesIcon } from "@src/icons/ChangesIcon";
16
25
  import { AuthStatus } from "@src/modules/userContext/types";
17
26
  import { useAutoSync } from "@src/features/sync/AutoSyncProvider";
18
27
  import { AutoSyncStatusIndicator } from "@src/features/sync/components/AutoSyncStatusIndicator";
@@ -22,6 +31,7 @@ export const ChangesItem: FC = () => {
22
31
  const open = useOpenChangesHoverCard();
23
32
  const router = useRouter();
24
33
  const { autoSyncStatus } = useAutoSync();
34
+ const isSmall = useMediaQuery(breakpoints.small);
25
35
 
26
36
  const onClose = () => {
27
37
  setSeenChangesToolTip();
@@ -29,18 +39,42 @@ export const ChangesItem: FC = () => {
29
39
 
30
40
  return (
31
41
  <HoverCard
42
+ align="start"
32
43
  open={open}
33
44
  openDelay={3000}
34
45
  onClose={onClose}
35
46
  side="right"
36
47
  sideOffset={24}
37
- collisionPadding={280}
38
48
  trigger={
39
- <Box padding={{ bottom: 24 }}>
49
+ <Box alignItems={isSmall ? "center" : undefined} flexDirection="column">
40
50
  {autoSyncStatus === "failed" ||
41
51
  autoSyncStatus === "synced" ||
42
52
  autoSyncStatus === "syncing" ? (
43
53
  <AutoSyncStatusIndicator autoSyncStatus={autoSyncStatus} />
54
+ ) : isSmall ? (
55
+ <Tooltip content="Review changes" side="right">
56
+ <Box position="relative">
57
+ {/*
58
+ * TODO(DT-1942): This should be an IconButton with a link
59
+ * component for accessibility
60
+ */}
61
+ <IconButton
62
+ icon={<ChangesIcon />}
63
+ onClick={() => {
64
+ void router.push("/changes");
65
+ }}
66
+ variant="solid"
67
+ />
68
+ <Box
69
+ left="100%"
70
+ position="absolute"
71
+ top={0}
72
+ transform="translate(-50%, -50%)"
73
+ >
74
+ <ChangesCount color="purple" />
75
+ </Box>
76
+ </Box>
77
+ </Tooltip>
44
78
  ) : (
45
79
  // TODO(DT-1942): This should be a Button with a link component for
46
80
  // accessibility
@@ -52,7 +86,8 @@ export const ChangesItem: FC = () => {
52
86
  sx={{ width: "100%" }}
53
87
  >
54
88
  <Box alignItems="center" gap={4}>
55
- <Text variant="bold">Review changes</Text> <ChangesCount />
89
+ <Text variant="bold">Review changes</Text>{" "}
90
+ <ChangesCount color="grey" />
56
91
  </Box>
57
92
  </Button>
58
93
  )}
@@ -70,7 +105,9 @@ export const ChangesItem: FC = () => {
70
105
  );
71
106
  };
72
107
 
73
- export const ChangesCount: FC = () => {
108
+ type ChangesCountProps = { color: "grey" | "purple" };
109
+
110
+ export const ChangesCount: FC<ChangesCountProps> = ({ color }) => {
74
111
  const isOnline = useNetwork();
75
112
  const authStatus = useAuthStatus();
76
113
  const { unSyncedSlices, unSyncedCustomTypes } = useUnSyncChanges();
@@ -91,8 +128,12 @@ export const ChangesCount: FC = () => {
91
128
  const formattedNumberOfChanges = numberOfChanges > 9 ? "+9" : numberOfChanges;
92
129
 
93
130
  return (
94
- <Box padding={{ inline: 6 }} borderRadius={10} backgroundColor="grey5">
95
- <Text color="grey11" variant="small">
131
+ <Box
132
+ padding={{ inline: 6 }}
133
+ borderRadius={10}
134
+ backgroundColor={color === "grey" ? "grey5" : "purple9"}
135
+ >
136
+ <Text color={color === "grey" ? "grey11" : "grey1"} variant="small">
96
137
  {formattedNumberOfChanges}
97
138
  </Text>
98
139
  </Box>
@@ -98,7 +98,7 @@ describe("Side Navigation", () => {
98
98
  renderSideNavigation();
99
99
  expect(await screen.findByText("foo")).toBeVisible();
100
100
  expect(await screen.findByText("foo.prismic.io")).toBeVisible();
101
- const link = await screen.findByTitle("Open Prismic repository");
101
+ const link = screen.getByTestId("prismic-repository-link");
102
102
  expect(link).toHaveAttribute("href", "https://foo.prismic.io");
103
103
  expect(link).toHaveAttribute("target", "_blank");
104
104
  });
@@ -1,3 +1,4 @@
1
+ import { Box } from "@prismicio/editor-ui";
1
2
  import { Suspense, type FC } from "react";
2
3
  import Link from "next/link";
3
4
  import { useRouter } from "next/router";
@@ -65,7 +66,9 @@ const Navigation: FC = () => {
65
66
  href={repositoryUrl}
66
67
  />
67
68
 
68
- <ChangesItem />
69
+ <Box flexDirection="column" padding={{ bottom: 24 }}>
70
+ <ChangesItem />
71
+ </Box>
69
72
 
70
73
  <SideNavList>
71
74
  <SideNavListItem>
@@ -35,6 +35,7 @@ import EditModal from "../../common/EditModal";
35
35
  import Zone from "../../common/Zone";
36
36
  import SliceZone from "../SliceZone";
37
37
  import {
38
+ FieldType,
38
39
  Group,
39
40
  NestableWidget,
40
41
  UID,
@@ -79,7 +80,7 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
79
80
  }: {
80
81
  id: string;
81
82
  label: string;
82
- widgetTypeName: string;
83
+ widgetTypeName: FieldType;
83
84
  }) => {
84
85
  // @ts-expect-error We have to create a widget map or a service instead of using export name
85
86
  if (ensureWidgetTypeExistence(Widgets, widgetTypeName)) {
@@ -119,12 +120,12 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
119
120
  setCustomType(newCustomType);
120
121
 
121
122
  void telemetry.track({
122
- event: "custom-type:field-added",
123
+ event: "field:added",
123
124
  id,
124
- name: customType.id,
125
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
126
- type: widget.TYPE_NAME,
127
- zone: "static",
125
+ name: label,
126
+ type: widgetTypeName,
127
+ isInAGroup: false,
128
+ contentType: customType.format === "page" ? "page type" : "custom type",
128
129
  });
129
130
  };
130
131
 
@@ -213,6 +214,7 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
213
214
  {query.newPageType === undefined ? (
214
215
  <Zone
215
216
  zoneType="customType"
217
+ zoneTypeFormat={customType.format}
216
218
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
217
219
  tabId={tabId}
218
220
  title="Static Zone"
@@ -1,7 +1,10 @@
1
1
  import { FC } from "react";
2
2
  import { flushSync } from "react-dom";
3
3
  import { DropResult } from "react-beautiful-dnd";
4
- import { NestableWidget } from "@prismicio/types-internal/lib/customtypes";
4
+ import {
5
+ FieldType,
6
+ NestableWidget,
7
+ } from "@prismicio/types-internal/lib/customtypes";
5
8
 
6
9
  import { ensureDnDDestination } from "@lib/utils";
7
10
  import { transformKeyAccessor } from "@utils/str";
@@ -19,6 +22,7 @@ import {
19
22
  import Zone from "@lib/builders/common/Zone";
20
23
  import EditModal from "@lib/builders/common/EditModal";
21
24
  import { AnyWidget } from "@lib/models/common/widgets/Widget";
25
+ import { telemetry } from "@src/apiClient";
22
26
 
23
27
  const dataTipText = ` The non-repeatable zone
24
28
  is for fields<br/> that should appear once, like a<br/>
@@ -76,7 +80,7 @@ const FieldZones: FC = () => {
76
80
  }: {
77
81
  id: string;
78
82
  label: string;
79
- widgetTypeName: string;
83
+ widgetTypeName: FieldType;
80
84
  }) => {
81
85
  // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
82
86
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -117,6 +121,15 @@ const FieldZones: FC = () => {
117
121
  });
118
122
 
119
123
  setSlice(newSlice);
124
+
125
+ void telemetry.track({
126
+ event: "field:added",
127
+ id,
128
+ name: label,
129
+ type: widgetTypeName,
130
+ isInAGroup: false,
131
+ contentType: "slice",
132
+ });
120
133
  };
121
134
 
122
135
  const _onDragEnd = (widgetArea: WidgetsArea) => (result: DropResult) => {
@@ -145,6 +158,7 @@ const FieldZones: FC = () => {
145
158
  <List>
146
159
  <Zone
147
160
  zoneType="slice"
161
+ zoneTypeFormat={undefined}
148
162
  tabId={undefined}
149
163
  title="Non-Repeatable Zone"
150
164
  dataTip={dataTipText}
@@ -171,6 +185,7 @@ const FieldZones: FC = () => {
171
185
  />
172
186
  <Zone
173
187
  zoneType="slice"
188
+ zoneTypeFormat={undefined}
174
189
  tabId={undefined}
175
190
  isRepeatable
176
191
  title="Repeatable Zone"
@@ -4,6 +4,7 @@ import { useState } from "react";
4
4
  import { BaseStyles } from "theme-ui";
5
5
 
6
6
  import { ListHeader } from "@src/components/List";
7
+ import { telemetry } from "@src/apiClient";
7
8
 
8
9
  import SelectFieldTypeModal from "../SelectFieldTypeModal";
9
10
  import NewField from "./Card/components/NewField";
@@ -12,6 +13,7 @@ import EmptyState from "./components/EmptyState";
12
13
 
13
14
  const Zone = ({
14
15
  zoneType /* type of the zone: customType or slice */,
16
+ zoneTypeFormat /* format of the zone: custom or page (or undefined if not a custom type) */,
15
17
  tabId,
16
18
  title /* text info to display in Card Header */,
17
19
  fields /* widgets registered in the zone */,
@@ -48,9 +50,25 @@ const Zone = ({
48
50
  const [selectModalData, setSelectModalData] = useState({ isOpen: false });
49
51
  const [newFieldData, setNewFieldData] = useState(null);
50
52
 
53
+ /** @param {[string, import("@prismicio/types-internal/lib/customtypes").NestableWidget]} field */
51
54
  const enterEditMode = (field) => {
52
55
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
53
56
  setEditModalData({ isOpen: true, field });
57
+
58
+ const [id, model] = field;
59
+ void telemetry.track({
60
+ event: "field:settings-opened",
61
+ id,
62
+ name: model.config.label,
63
+ type: model.type,
64
+ isInAGroup: false,
65
+ contentType:
66
+ zoneType === "customType"
67
+ ? zoneTypeFormat === "page"
68
+ ? "page type"
69
+ : "custom type"
70
+ : "slice",
71
+ });
54
72
  };
55
73
  const enterSelectMode = () => {
56
74
  setSelectModalData({ isOpen: true });
@@ -30,6 +30,7 @@ import {
30
30
  reorderGroupField,
31
31
  updateGroupField,
32
32
  } from "@src/domain/customType";
33
+ import { telemetry } from "@src/apiClient";
33
34
 
34
35
  /* eslint-disable */
35
36
  const CustomListItem = ({
@@ -81,6 +82,15 @@ const CustomListItem = ({
81
82
  });
82
83
 
83
84
  setCustomType(newCustomType);
85
+
86
+ void telemetry.track({
87
+ event: "field:added",
88
+ id,
89
+ name: label,
90
+ type: widgetTypeName,
91
+ isInAGroup: true,
92
+ contentType: customType.format === "page" ? "page type" : "custom type",
93
+ });
84
94
  };
85
95
 
86
96
  const onSaveField = ({ apiId: previousKey, newKey, value }) => {
@@ -141,9 +151,20 @@ const CustomListItem = ({
141
151
  setCustomType(newCustomType);
142
152
  };
143
153
 
154
+ /** @param {[string, import("@prismicio/types-internal/lib/customtypes").NestableWidget]} field */
144
155
  const enterEditMode = (field) => {
145
156
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
146
157
  setEditModalData({ isOpen: true, field });
158
+
159
+ const [id, model] = field;
160
+ void telemetry.track({
161
+ event: "field:settings-opened",
162
+ id,
163
+ name: model.config.label,
164
+ type: model.type,
165
+ isInAGroup: true,
166
+ contentType: customType.format === "page" ? "page type" : "custom type",
167
+ });
147
168
  };
148
169
  return (
149
170
  <Fragment>
package/out/404.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/css/4f1e84c70ef0e169.css" as="style"/><link rel="stylesheet" href="/_next/static/css/4f1e84c70ef0e169.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-2f903acb0cccbf9e.js" defer=""></script><script src="/_next/static/chunks/framework-cdccea7a52cc6e81.js" defer=""></script><script src="/_next/static/chunks/main-5e6780279ca21cb9.js" defer=""></script><script src="/_next/static/chunks/pages/_app-4500c5314e33c7aa.js" defer=""></script><script src="/_next/static/chunks/pages/_error-69b4f498bafdd188.js" defer=""></script><script src="/_next/static/QbkBgzWD1MMQdeEUWvKYu/_buildManifest.js" defer=""></script><script src="/_next/static/QbkBgzWD1MMQdeEUWvKYu/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"QbkBgzWD1MMQdeEUWvKYu","runtimeConfig":{"sentryEnvironment":"beta"},"nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/css/21654235130d0806.css" as="style"/><link rel="stylesheet" href="/_next/static/css/21654235130d0806.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-2f903acb0cccbf9e.js" defer=""></script><script src="/_next/static/chunks/framework-cdccea7a52cc6e81.js" defer=""></script><script src="/_next/static/chunks/main-5e6780279ca21cb9.js" defer=""></script><script src="/_next/static/chunks/pages/_app-30f8a579c4d383f3.js" defer=""></script><script src="/_next/static/chunks/pages/_error-69b4f498bafdd188.js" defer=""></script><script src="/_next/static/vNxSAIw3P6M_wdZBPWPUk/_buildManifest.js" defer=""></script><script src="/_next/static/vNxSAIw3P6M_wdZBPWPUk/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"vNxSAIw3P6M_wdZBPWPUk","runtimeConfig":{"sentryEnvironment":"beta"},"nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>