slice-machine-ui 2.10.5 → 2.10.6-alpha.repeatable-link.2

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 (61) hide show
  1. package/out/404.html +1 -1
  2. package/out/_next/static/YhDUoK9aVB-OyGIW41CsE/_buildManifest.js +1 -0
  3. package/out/_next/static/chunks/150-f6a12f89ea09c1e5.js +1 -0
  4. package/out/_next/static/chunks/372-fd971fefdcfe1dac.js +1 -0
  5. package/out/_next/static/chunks/429-07478a7a570323f9.js +8 -0
  6. package/out/_next/static/chunks/764-be7b99befbe83b94.js +1 -0
  7. package/out/_next/static/chunks/772-fefbf53257be472d.js +1 -0
  8. package/out/_next/static/chunks/882-567b4220cf2aade1.js +1 -0
  9. package/out/_next/static/chunks/pages/_app-7a3e25479c20abbd.js +644 -0
  10. package/out/_next/static/chunks/pages/changelog-b2494ca2d17f3afe.js +1 -0
  11. package/out/_next/static/chunks/pages/changes-f78e766881db10ec.js +1 -0
  12. package/out/_next/static/chunks/pages/labs-b2e68f81bf4c9dae.js +1 -0
  13. package/out/_next/static/chunks/pages/settings-88c3d839c41b306d.js +1 -0
  14. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-d44e3fd7658f7587.js +1 -0
  15. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-39b77d9eff3edf0e.js +1 -0
  16. package/out/_next/static/chunks/pages/{slices-6cfac30e3c77980d.js → slices-5efd50cb6b8ab6b1.js} +1 -1
  17. package/out/_next/static/css/fa5a1c6141f55814.css +1 -0
  18. package/out/changelog.html +1 -1
  19. package/out/changes.html +1 -1
  20. package/out/custom-types/[customTypeId].html +1 -1
  21. package/out/custom-types.html +1 -1
  22. package/out/index.html +1 -1
  23. package/out/labs.html +1 -1
  24. package/out/page-types/[pageTypeId].html +1 -1
  25. package/out/settings.html +1 -1
  26. package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
  27. package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
  28. package/out/slices.html +1 -1
  29. package/package.json +10 -9
  30. package/src/features/sync/actions/trackPushChangesSuccess.ts +88 -0
  31. package/src/legacy/components/ListItem/Header.tsx +3 -0
  32. package/src/legacy/components/ListItem/index.tsx +19 -2
  33. package/src/legacy/lib/builders/CustomTypeBuilder/TabZone/index.tsx +2 -13
  34. package/src/legacy/lib/builders/SliceBuilder/FieldZones/index.tsx +3 -15
  35. package/src/legacy/lib/builders/common/Zone/Card/components/Hints/index.tsx +1 -0
  36. package/src/legacy/lib/builders/common/Zone/index.jsx +1 -1
  37. package/src/legacy/lib/models/common/widgets/ContentRelationship/index.ts +1 -0
  38. package/src/legacy/lib/models/common/widgets/Group/ListItem/index.jsx +3 -12
  39. package/src/legacy/lib/models/common/widgets/Link/Form.jsx +35 -37
  40. package/src/legacy/lib/models/common/widgets/Link/components.tsx +52 -11
  41. package/src/legacy/lib/models/common/widgets/Link/index.ts +9 -3
  42. package/src/legacy/lib/models/common/widgets/LinkToMedia/Form.jsx +12 -15
  43. package/src/legacy/lib/models/common/widgets/LinkToMedia/index.ts +1 -0
  44. package/src/utils/tracking/trackFieldAdded.ts +33 -0
  45. package/out/_next/static/-W9HS13l1a39Ytz6Gj69n/_buildManifest.js +0 -1
  46. package/out/_next/static/chunks/150-57d904e6c95df911.js +0 -1
  47. package/out/_next/static/chunks/372-1608c5e5b72cce7b.js +0 -1
  48. package/out/_next/static/chunks/429-6b3405d9cee75624.js +0 -10
  49. package/out/_next/static/chunks/764-30e2601a1647371a.js +0 -1
  50. package/out/_next/static/chunks/772-936f6233f8a2b1f1.js +0 -1
  51. package/out/_next/static/chunks/882-e9ccd4aa9d3ac48a.js +0 -1
  52. package/out/_next/static/chunks/pages/_app-3f803fc8588552c9.js +0 -619
  53. package/out/_next/static/chunks/pages/changelog-365aa7a2d23e3fdf.js +0 -1
  54. package/out/_next/static/chunks/pages/changes-9e1acd7a02b2cbcb.js +0 -1
  55. package/out/_next/static/chunks/pages/labs-1a00abe937ba05e7.js +0 -1
  56. package/out/_next/static/chunks/pages/settings-8f999bb96b738ab6.js +0 -1
  57. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-d5df6446669f32d9.js +0 -1
  58. package/out/_next/static/chunks/pages/slices/[lib]/[sliceName]/[variation]-5acaf1fca398a36c.js +0 -1
  59. package/out/_next/static/css/6523b5bbc256dae9.css +0 -1
  60. /package/out/_next/static/{-W9HS13l1a39Ytz6Gj69n → YhDUoK9aVB-OyGIW41CsE}/_ssgManifest.js +0 -0
  61. /package/src/utils/{getContentTypeForTracking.ts → tracking/getContentTypeForTracking.ts} +0 -0
@@ -1,5 +1,12 @@
1
+ import {
2
+ FieldType,
3
+ NestableWidget,
4
+ UID,
5
+ } from "@prismicio/types-internal/lib/customtypes";
6
+
1
7
  import { telemetry } from "@/apiClient";
2
8
  import { countMissingScreenshots } from "@/domain/slice";
9
+ import { GroupSM } from "@/legacy/lib/models/common/Group";
3
10
  import {
4
11
  ChangedCustomType,
5
12
  ChangedSlice,
@@ -94,4 +101,85 @@ export function trackPushChangesSuccess(args: TrackPushChangesSuccessArgs) {
94
101
  hasDeletedDocuments,
95
102
  _includeEnvironmentKind: true,
96
103
  });
104
+
105
+ trackPushedGroups({ changedCustomTypes, changedSlices });
106
+ }
107
+
108
+ type TrackPushedGroupsArgs = {
109
+ changedSlices: ReadonlyArray<ChangedSlice>;
110
+ changedCustomTypes: ReadonlyArray<ChangedCustomType>;
111
+ };
112
+ type FieldsCount = {
113
+ [key in FieldType]?: number;
114
+ };
115
+ type FieldStats = {
116
+ isInStaticZone: boolean;
117
+ isInSlice: boolean;
118
+ } & FieldsCount;
119
+
120
+ function trackPushedGroups(args: TrackPushedGroupsArgs) {
121
+ const { changedCustomTypes, changedSlices } = args;
122
+
123
+ const groupsInStaticZone = changedCustomTypes.reduce<FieldStats[]>(
124
+ (acc, customType) => {
125
+ if (customType.status !== ModelStatus.New) return acc;
126
+
127
+ customType.customType.tabs.forEach((tab) => {
128
+ const fieldsCount = countGroupFields(acc, tab.value, "custom-type");
129
+ acc.push(...fieldsCount);
130
+ });
131
+
132
+ return acc;
133
+ },
134
+ [],
135
+ );
136
+
137
+ const groupsInSlices = changedSlices.reduce<FieldStats[]>((acc, slice) => {
138
+ if (slice.status !== ModelStatus.New) return acc;
139
+
140
+ slice.slice.model.variations.forEach((variation) => {
141
+ const fieldsCount = countGroupFields(acc, variation.primary, "slice");
142
+ acc.push(...fieldsCount);
143
+ });
144
+
145
+ return acc;
146
+ }, []);
147
+ [...groupsInSlices, ...groupsInStaticZone].forEach((group) => {
148
+ void telemetry.track({
149
+ event: "changes:group-pushed",
150
+ ...group,
151
+ });
152
+ });
153
+ }
154
+
155
+ interface Field {
156
+ key: string;
157
+ value: GroupSM | UID | NestableWidget;
158
+ }
159
+ function countGroupFields<TField extends Field>(
160
+ fieldStats: FieldStats[],
161
+ fields: TField[] | undefined,
162
+ groupParent: "custom-type" | "slice",
163
+ ) {
164
+ if (!fields) return fieldStats;
165
+
166
+ const newFieldState = fieldStats.slice();
167
+
168
+ fields.forEach((field) => {
169
+ if (field.value.type === "Group" && field.value.config?.fields) {
170
+ const fieldsCount: FieldsCount = {};
171
+ field.value.config.fields.forEach(({ value: fieldValue }) => {
172
+ const value = fieldsCount[fieldValue.type] ?? 0;
173
+ fieldsCount[fieldValue.type] = value + 1;
174
+ });
175
+
176
+ newFieldState.push({
177
+ isInStaticZone: groupParent === "custom-type",
178
+ isInSlice: groupParent === "slice",
179
+ ...fieldsCount,
180
+ });
181
+ }
182
+ });
183
+
184
+ return newFieldState;
97
185
  }
@@ -27,6 +27,7 @@ const ItemHeader: React.FC<ItemHeaderProps> = ({
27
27
  padding: "4px",
28
28
  border: "2px solid",
29
29
  borderColor: theme.colors?.primary as CSS.Property.Color,
30
+ flexShrink: 0,
30
31
  }}
31
32
  />
32
33
  <TextWithTooltip
@@ -42,6 +43,8 @@ const ItemHeader: React.FC<ItemHeaderProps> = ({
42
43
  fontSize: "14px",
43
44
  ml: 1,
44
45
  color: "textClear",
46
+ overflow: "hidden",
47
+ textOverflow: "ellipsis",
45
48
  }}
46
49
  data-testid="field-id"
47
50
  >
@@ -1,3 +1,4 @@
1
+ import { Badge } from "@prismicio/editor-ui";
1
2
  import { Menu, MenuButton, MenuItem, MenuList } from "@reach/menu-button";
2
3
  import React, { Fragment } from "react";
3
4
  import { Draggable } from "react-beautiful-dnd";
@@ -60,6 +61,10 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
60
61
  value: { config, type },
61
62
  } = item;
62
63
 
64
+ const shouldDisplayRepeatableBadge = Boolean(
65
+ (type === "Link" || type === "Group") && config?.repeat,
66
+ );
67
+
63
68
  return (
64
69
  <Fragment>
65
70
  <Draggable draggableId={draggableId} index={index}>
@@ -110,7 +115,15 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
110
115
  }
111
116
  WidgetIcon={widget.Meta.icon}
112
117
  />
113
- <Flex>
118
+ <Flex sx={{ flex: "0 0 auto" }}>
119
+ {shouldDisplayRepeatableBadge && (
120
+ <Badge
121
+ title="Repeatable"
122
+ color="purple"
123
+ size="medium"
124
+ sx={{ alignSelf: "center", marginInline: 16 }}
125
+ />
126
+ )}
114
127
  {CustomEditElements ? CustomEditElements : null}
115
128
  {CustomEditElement ? (
116
129
  CustomEditElement
@@ -119,7 +132,11 @@ function ListItem<F extends TabField, S extends AnyObjectSchema>({
119
132
  size={22}
120
133
  Icon={AiOutlineEdit}
121
134
  label="Edit field"
122
- sx={{ cursor: "pointer", color: theme.colors?.icons }}
135
+ sx={{
136
+ cursor: "pointer",
137
+ color: theme.colors?.icons,
138
+ flexShrink: 0,
139
+ }}
123
140
  onClick={() =>
124
141
  enterEditMode(
125
142
  [key, item.value],
@@ -9,7 +9,6 @@ import type { DropResult } from "react-beautiful-dnd";
9
9
  import { flushSync } from "react-dom";
10
10
  import { toast } from "react-toastify";
11
11
 
12
- import { telemetry } from "@/apiClient";
13
12
  import { List } from "@/components/List";
14
13
  import {
15
14
  addField,
@@ -36,7 +35,7 @@ import {
36
35
  ensureWidgetTypeExistence,
37
36
  } from "@/legacy/lib/utils";
38
37
  import { transformKeyAccessor } from "@/legacy/lib/utils/str";
39
- import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
38
+ import { trackFieldAdded } from "@/utils/tracking/trackFieldAdded";
40
39
 
41
40
  import EditModal from "../../common/EditModal";
42
41
  import Zone from "../../common/Zone";
@@ -140,17 +139,7 @@ const TabZone: FC<TabZoneProps> = ({ tabId }) => {
140
139
  toast.success(`${field.type === "Group" ? "Group" : "Field"} added`);
141
140
  });
142
141
 
143
- void telemetry.track({
144
- event: "field:added",
145
- id,
146
- name: label,
147
- type: newField.type,
148
- isInAGroup: false,
149
- contentType: getContentTypeForTracking(window.location.pathname),
150
- ...(newField.type === "Link" && {
151
- allowText: newField.config?.allowText,
152
- }),
153
- });
142
+ trackFieldAdded({ id, field: newField });
154
143
  };
155
144
 
156
145
  const onDragEnd = (result: DropResult) => {
@@ -16,7 +16,6 @@ import { DropResult } from "react-beautiful-dnd";
16
16
  import { flushSync } from "react-dom";
17
17
  import { toast } from "react-toastify";
18
18
 
19
- import { telemetry } from "@/apiClient";
20
19
  import { List } from "@/components/List";
21
20
  import {
22
21
  addField,
@@ -36,7 +35,7 @@ import {
36
35
  import { Widgets } from "@/legacy/lib/models/common/widgets";
37
36
  import { ensureDnDDestination } from "@/legacy/lib/utils";
38
37
  import { transformKeyAccessor } from "@/legacy/lib/utils/str";
39
- import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
38
+ import { trackFieldAdded } from "@/utils/tracking/trackFieldAdded";
40
39
 
41
40
  const dataTipText = ` The non-repeatable zone
42
41
  is for fields<br/> that should appear once, like a<br/>
@@ -128,8 +127,7 @@ const FieldZones: FC = () => {
128
127
  widgetArea: WidgetsArea,
129
128
  { apiId: id, value: newField }: OnSaveFieldProps,
130
129
  ) => {
131
- const { type: widgetTypeName, config } = newField;
132
- const label = config?.label ?? "";
130
+ const { type: widgetTypeName } = newField;
133
131
 
134
132
  const widget = primaryWidgetsArray.find(
135
133
  (sliceBuilderWidget) =>
@@ -159,17 +157,7 @@ const FieldZones: FC = () => {
159
157
  toast.success(`${widgetTypeName === "Group" ? "Group" : "Field"} added`);
160
158
  });
161
159
 
162
- void telemetry.track({
163
- event: "field:added",
164
- id,
165
- name: label,
166
- type: newField.type,
167
- isInAGroup: false,
168
- contentType: getContentTypeForTracking(window.location.pathname),
169
- ...(newField.type === "Link" && {
170
- allowText: newField.config?.allowText,
171
- }),
172
- });
160
+ trackFieldAdded({ id, field: newField });
173
161
  };
174
162
 
175
163
  const _onCreateOrSave = (widgetArea: WidgetsArea) => {
@@ -24,6 +24,7 @@ const Hint: React.FC<HintProps> = ({
24
24
  if (item.value.type === "Link") {
25
25
  if (item.value.config?.allowText ?? false)
26
26
  snippetCacheKey.push("allowText");
27
+ if (item.value.config?.repeat ?? false) snippetCacheKey.push("repeat");
27
28
  }
28
29
 
29
30
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -9,7 +9,7 @@ import { fields as allFields } from "@/domain/fields";
9
9
  import { AddFieldDropdown } from "@/features/builder/AddFieldDropdown";
10
10
  import { AddStaticFieldDropdown } from "@/features/builder/AddStaticFieldDropdown";
11
11
  import { Widgets } from "@/legacy/lib/models/common/widgets";
12
- import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
12
+ import { getContentTypeForTracking } from "@/utils/tracking/getContentTypeForTracking";
13
13
 
14
14
  import Card from "./Card";
15
15
  import { ZoneEmptyState } from "./components/ZoneEmptyState";
@@ -52,6 +52,7 @@ export const ContentRelationshipWidget: Widget<Link, typeof schema> = {
52
52
  config: {
53
53
  label,
54
54
  select: "document",
55
+ repeat: false,
55
56
  },
56
57
  }),
57
58
  Meta,
@@ -20,7 +20,8 @@ import { findWidgetByConfigOrType } from "@/legacy/lib/builders/utils";
20
20
  import { Groups } from "@/legacy/lib/models/common/Group";
21
21
  import { ensureDnDDestination } from "@/legacy/lib/utils";
22
22
  import { transformKeyAccessor } from "@/legacy/lib/utils/str";
23
- import { getContentTypeForTracking } from "@/utils/getContentTypeForTracking";
23
+ import { getContentTypeForTracking } from "@/utils/tracking/getContentTypeForTracking";
24
+ import { trackFieldAdded } from "@/utils/tracking/trackFieldAdded";
24
25
 
25
26
  /* eslint-disable */
26
27
  export const CustomListItem = ({
@@ -69,17 +70,7 @@ export const CustomListItem = ({
69
70
  isNewGroupField: true,
70
71
  });
71
72
 
72
- void telemetry.track({
73
- event: "field:added",
74
- id,
75
- name: label,
76
- type: newField.type,
77
- isInAGroup: true,
78
- contentType: getContentTypeForTracking(window.location.pathname),
79
- ...(newField.type === "Link" && {
80
- allowText: newField.config?.allowText,
81
- }),
82
- });
73
+ trackFieldAdded({ id, field: newField, isInAGroup: true });
83
74
  };
84
75
 
85
76
  const onSaveField = ({ apiId: previousKey, newKey, value }) => {
@@ -1,4 +1,4 @@
1
- import { Box, Label } from "theme-ui";
1
+ import { Flex } from "theme-ui";
2
2
 
3
3
  import { Col, Flex as FlexGrid } from "@/legacy/components/Flex";
4
4
  import WidgetFormField from "@/legacy/lib/builders/common/EditModal/Field";
@@ -6,12 +6,10 @@ import { createFieldNameFromKey } from "@/legacy/lib/forms";
6
6
  import { DefaultFields } from "@/legacy/lib/forms/defaults";
7
7
  import { CheckBox } from "@/legacy/lib/forms/fields";
8
8
 
9
- import { DisplayTextCheckbox } from "./components";
9
+ import { DisplayTextCheckbox, RepeatableCheckbox } from "./components";
10
10
 
11
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
12
11
  const FormFields = {
13
12
  ...DefaultFields,
14
- allowTargetBlank: CheckBox("Allow target blank", false, true),
15
13
  };
16
14
 
17
15
  const Form = (props) => {
@@ -20,14 +18,13 @@ const Form = (props) => {
20
18
 
21
19
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
22
20
  const {
23
- config: { allowText },
21
+ config: { allowText, repeat },
24
22
  } = formValues;
25
23
 
26
24
  return (
27
- <FlexGrid>
28
- {
29
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
30
- Object.entries(DefaultFields).map(([key, field]) => (
25
+ <>
26
+ <FlexGrid>
27
+ {Object.entries(FormFields).map(([key, field]) => (
31
28
  <Col key={key}>
32
29
  <WidgetFormField
33
30
  fieldName={createFieldNameFromKey(key)}
@@ -39,40 +36,41 @@ const Form = (props) => {
39
36
  initialValues={initialValues}
40
37
  />
41
38
  </Col>
42
- ))
43
- }
44
- <Col />
45
- <Col key="allowTargetBlank">
46
- <Box sx={{ mt: 2 }}>
47
- <Label
48
- htmlFor="allowTargetBlank"
49
- variant="label.primary"
50
- sx={{
51
- display: "flex",
52
- alignItems: "center",
39
+ ))}
40
+
41
+ <Col key="allowTargetBlank">
42
+ <Flex
43
+ sx={{ gap: 2, marginTop: 3 }}
44
+ style={{
45
+ paddingTop: "1px",
53
46
  }}
54
47
  >
55
- Link properties
56
- </Label>
57
- <WidgetFormField
58
- fieldName={createFieldNameFromKey("allowTargetBlank")}
59
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
60
- formField={CheckBox("Allow target blank", false, true)}
61
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
62
- fields={fields}
63
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
64
- initialValues={initialValues}
65
- />
66
- </Box>
67
- </Col>
68
- <DisplayTextCheckbox
48
+ <Col>
49
+ <WidgetFormField
50
+ fieldName={createFieldNameFromKey("allowTargetBlank")}
51
+ formField={CheckBox("Allow target blank", false, true)}
52
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
53
+ fields={fields}
54
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
55
+ initialValues={initialValues}
56
+ />
57
+ </Col>
58
+ <DisplayTextCheckbox
59
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
60
+ checked={allowText}
61
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
62
+ setFieldValue={setFieldValue}
63
+ />
64
+ </Flex>
65
+ </Col>
66
+ </FlexGrid>
67
+ <RepeatableCheckbox
69
68
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
70
- allowText={allowText}
71
- height={127}
69
+ checked={repeat}
72
70
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
73
71
  setFieldValue={setFieldValue}
74
72
  />
75
- </FlexGrid>
73
+ </>
76
74
  );
77
75
  };
78
76
 
@@ -1,20 +1,17 @@
1
- import { Box, Icon, Tooltip } from "@prismicio/editor-ui";
1
+ import { Box, Icon, Text, Tooltip } from "@prismicio/editor-ui";
2
2
  import { Checkbox, Flex, Label } from "theme-ui";
3
3
 
4
4
  import { Col } from "@/legacy/components/Flex";
5
5
 
6
- interface DisplayTextCheckboxProps {
7
- allowText?: boolean;
6
+ interface CommonCheckboxProps {
7
+ checked?: boolean;
8
8
  height?: 130 | 127;
9
- setFieldValue: (
10
- a: string,
11
- b?: boolean,
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- ) => void | Promise<any>;
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ setFieldValue: (name: string, checked?: boolean) => void | Promise<any>;
14
11
  }
15
12
 
16
- export function DisplayTextCheckbox(props: DisplayTextCheckboxProps) {
17
- const { allowText, height = 130, setFieldValue } = props;
13
+ export function DisplayTextCheckbox(props: CommonCheckboxProps) {
14
+ const { checked, height = 130, setFieldValue } = props;
18
15
 
19
16
  return (
20
17
  <Col>
@@ -34,7 +31,7 @@ export function DisplayTextCheckbox(props: DisplayTextCheckboxProps) {
34
31
  >
35
32
  <Flex>
36
33
  <Checkbox
37
- checked={allowText}
34
+ checked={checked}
38
35
  onChange={(event) => {
39
36
  void setFieldValue("config.allowText", event.target.checked);
40
37
  }}
@@ -54,3 +51,47 @@ export function DisplayTextCheckbox(props: DisplayTextCheckboxProps) {
54
51
  </Col>
55
52
  );
56
53
  }
54
+
55
+ export function RepeatableCheckbox(props: CommonCheckboxProps) {
56
+ const { checked, setFieldValue } = props;
57
+
58
+ return (
59
+ <Box flexDirection="column">
60
+ <Label
61
+ htmlFor="repeat"
62
+ variant="label.primary"
63
+ sx={{
64
+ mt: 2,
65
+ }}
66
+ >
67
+ Repeatable
68
+ </Label>
69
+ <Label variant="label.border" sx={{ display: "flex" }}>
70
+ <Checkbox
71
+ name="repeat"
72
+ checked={checked}
73
+ onChange={(event) => {
74
+ void setFieldValue("config.repeat", event.target.checked);
75
+ }}
76
+ />
77
+ Make this link repeatable - Allow editors to create lists of links
78
+ </Label>
79
+ <Box alignItems="center" gap={4}>
80
+ <Icon name="alert" size="medium" color="grey11" />
81
+ <Text variant="normal" color="grey11">
82
+ Repeatable link fields are returned as an array of links by the API.{" "}
83
+ <a
84
+ href="https://prismic.io/docs/field"
85
+ style={{ textDecoration: "none" }}
86
+ target="_blank"
87
+ rel="noopener noreferrer"
88
+ >
89
+ <Text variant="normal" color="indigo11">
90
+ See documentation.
91
+ </Text>
92
+ </a>
93
+ </Text>
94
+ </Box>
95
+ </Box>
96
+ );
97
+ }
@@ -7,12 +7,13 @@ import Form, { FormFields } from "./Form";
7
7
 
8
8
  /**
9
9
  * {
10
- "type": "Link",
10
+ "type": "Link",
11
11
  "config": {
12
12
  "label": "link",
13
13
  "placeholder": "Could be a link to use case, press article, signup...",
14
14
  "allowTargetBlank": true,
15
15
  "allowText": true
16
+ "repeat": true,
16
17
  }
17
18
  }
18
19
  */
@@ -25,7 +26,8 @@ import Form, { FormFields } from "./Form";
25
26
  "customtypes": ["homepage"],
26
27
  "label": "contentrrrrr",
27
28
  "placeholder": "dsfdsfsdf",
28
- "allowText": true
29
+ "allowText": true,
30
+ "repeat": true,
29
31
  }
30
32
  }
31
33
  */
@@ -36,7 +38,8 @@ import Form, { FormFields } from "./Form";
36
38
  "select" : "media",
37
39
  "label" : "tomedia",
38
40
  "placeholder" : "qsdqsdqsd",
39
- "allowText": true
41
+ "allowText": true,
42
+ "repeat": true,
40
43
  }
41
44
  } */
42
45
 
@@ -74,6 +77,7 @@ export const linkConfigSchema = yup
74
77
  tags: yup.array(yup.string()).optional(),
75
78
  allowTargetBlank: yup.boolean().strict().optional(),
76
79
  allowText: yup.boolean().strict().optional(),
80
+ repeat: yup.boolean().strict().optional(),
77
81
  })
78
82
  .required()
79
83
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -102,7 +106,9 @@ export const LinkWidget: Widget<Link, typeof schema> = {
102
106
  label,
103
107
  placeholder: "",
104
108
  select: null,
109
+ allowTargetBlank: true,
105
110
  allowText: true,
111
+ repeat: false,
106
112
  },
107
113
  }),
108
114
  TYPE_NAME: "Link",
@@ -5,7 +5,6 @@ import { DefaultFields } from "@/legacy/lib/forms/defaults";
5
5
 
6
6
  import { DisplayTextCheckbox } from "../Link/components";
7
7
 
8
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
9
8
  const FormFields = {
10
9
  ...DefaultFields,
11
10
  };
@@ -20,14 +19,12 @@ const Form = (props) => {
20
19
  } = formValues;
21
20
 
22
21
  return (
23
- <FlexGrid>
24
- {
25
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
26
- Object.entries(FormFields).map(([key, field]) => (
22
+ <>
23
+ <FlexGrid>
24
+ {Object.entries(FormFields).map(([key, field]) => (
27
25
  <Col key={key}>
28
26
  <WidgetFormField
29
27
  fieldName={createFieldNameFromKey(key)}
30
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
31
28
  formField={field}
32
29
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
33
30
  fields={fields}
@@ -35,15 +32,15 @@ const Form = (props) => {
35
32
  initialValues={initialValues}
36
33
  />
37
34
  </Col>
38
- ))
39
- }
40
- <DisplayTextCheckbox
41
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
42
- allowText={allowText}
43
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
44
- setFieldValue={setFieldValue}
45
- />
46
- </FlexGrid>
35
+ ))}
36
+ <DisplayTextCheckbox
37
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
38
+ checked={allowText}
39
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
40
+ setFieldValue={setFieldValue}
41
+ />
42
+ </FlexGrid>
43
+ </>
47
44
  );
48
45
  };
49
46
 
@@ -41,6 +41,7 @@ export const LinkToMediaWidget: Widget<Link, typeof schema> = {
41
41
  placeholder: "",
42
42
  select: "media",
43
43
  allowText: true,
44
+ repeat: false,
44
45
  },
45
46
  }),
46
47
  TYPE_NAME: "Link",
@@ -0,0 +1,33 @@
1
+ import {
2
+ Group,
3
+ NestableWidget,
4
+ UID,
5
+ } from "@prismicio/types-internal/lib/customtypes";
6
+
7
+ import { telemetry } from "@/apiClient";
8
+ import { SlicePrimaryFieldSM } from "@/legacy/lib/models/common/Slice";
9
+
10
+ import { getContentTypeForTracking } from "./getContentTypeForTracking";
11
+
12
+ type TrackFieldAddedArgs = {
13
+ id: string;
14
+ field: SlicePrimaryFieldSM | NestableWidget | UID | Group;
15
+ isInAGroup?: boolean;
16
+ };
17
+
18
+ export function trackFieldAdded(args: TrackFieldAddedArgs) {
19
+ const { id, field, isInAGroup = false } = args;
20
+
21
+ void telemetry.track({
22
+ event: "field:added",
23
+ id,
24
+ name: field.config?.label ?? "",
25
+ type: field.type,
26
+ isInAGroup,
27
+ contentType: getContentTypeForTracking(window.location.pathname),
28
+ ...(field.type === "Link" && {
29
+ allowText: field.config?.allowText,
30
+ repeat: field.config?.repeat,
31
+ }),
32
+ });
33
+ }
@@ -1 +0,0 @@
1
- self.__BUILD_MANIFEST=function(s,c,a,e,t,i,n,u,f,b,d,h,l,p,k,j,g,o){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[a,p,k,"static/chunks/pages/index-17f953c11b46cb20.js"],"/_error":["static/chunks/pages/_error-1b183d3cf5ea03f9.js"],"/changelog":[s,e,"static/chunks/870-a72b74312773efea.js","static/chunks/pages/changelog-365aa7a2d23e3fdf.js"],"/changes":[s,t,"static/chunks/8eec4907-b712959d9f984b68.js","static/chunks/918-38ab72e6ee071fec.js",c,n,"static/css/9d17b7d9f44c5c5d.css","static/chunks/pages/changes-9e1acd7a02b2cbcb.js"],"/custom-types":[a,p,k,"static/chunks/pages/custom-types-ddc20cfdd8049c04.js"],"/custom-types/[customTypeId]":[s,u,f,b,d,e,i,h,j,c,a,l,g,o,"static/chunks/pages/custom-types/[customTypeId]-2eb64c9ea82fcd0a.js"],"/labs":["static/chunks/pages/labs-1a00abe937ba05e7.js"],"/page-types/[pageTypeId]":[s,u,f,b,d,e,i,h,j,c,a,l,g,o,"static/chunks/pages/page-types/[pageTypeId]-e5a5e6b345081e0a.js"],"/settings":["static/css/e5f781f20e24a5ea.css","static/chunks/pages/settings-8f999bb96b738ab6.js"],"/slices":[s,t,i,c,n,"static/css/b5323377600915db.css","static/chunks/pages/slices-6cfac30e3c77980d.js"],"/slices/[lib]/[sliceName]/[variation]":[s,t,u,f,b,d,e,i,h,c,l,n,"static/css/9740e73b8aa87666.css","static/chunks/pages/slices/[lib]/[sliceName]/[variation]-5acaf1fca398a36c.js"],"/slices/[lib]/[sliceName]/[variation]/simulator":[t,"static/chunks/72585f70-28b4d7d5384b3703.js","static/chunks/429-6b3405d9cee75624.js","static/chunks/pages/slices/[lib]/[sliceName]/[variation]/simulator-d5df6446669f32d9.js"],sortedPages:["/","/_app","/_error","/changelog","/changes","/custom-types","/custom-types/[customTypeId]","/labs","/page-types/[pageTypeId]","/settings","/slices","/slices/[lib]/[sliceName]/[variation]","/slices/[lib]/[sliceName]/[variation]/simulator"]}}("static/chunks/59b4e022-8e544a511d670317.js","static/chunks/772-936f6233f8a2b1f1.js","static/chunks/372-1608c5e5b72cce7b.js","static/chunks/183-b1a9f55f45cb8d8e.js","static/chunks/c8eae200-966ce352f7b5d2b9.js","static/chunks/50-586dc7ab5e584e76.js","static/chunks/639-424b570eee9a37fb.js","static/chunks/f36c6662-1f3a854183168b10.js","static/chunks/4c744e84-642bc2ece03445a4.js","static/chunks/065a3ddb-9a38ca0d60f0bf2f.js","static/chunks/1cc2734a-09fb3b997ad1eb70.js","static/chunks/349-6ad3cca7ea294292.js","static/chunks/882-e9ccd4aa9d3ac48a.js","static/chunks/764-30e2601a1647371a.js","static/css/4e475d945cf8a890.css","static/chunks/479-6205c85aa978fc0b.js","static/chunks/150-57d904e6c95df911.js","static/css/850c81be38195a0f.css"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();