strapi-plugin-hubspot 0.11.1 → 0.13.0
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/CHANGELOG.md +23 -0
- package/README.md +18 -0
- package/dist/_chunks/{Forms-DadTbe9Q.mjs → Forms-CHB-sKem.mjs} +218 -121
- package/dist/_chunks/{Forms-Dn2W6OS4.js → Forms-lrzuWzoB.js} +217 -120
- package/dist/_chunks/{HubspotFormInput-S_Z2t_DN.js → HubspotFormInput-Bb6it0nP.js} +1 -1
- package/dist/_chunks/{HubspotFormInput-NO59AtM_.mjs → HubspotFormInput-YI09keTC.mjs} +1 -1
- package/dist/_chunks/{HubspotObjectInput-DAo3FAMz.mjs → HubspotObjectInput-CzLKT9oj.mjs} +3 -3
- package/dist/_chunks/{HubspotObjectInput-BIgIa_Dm.js → HubspotObjectInput-D3A6xzb3.js} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-KX1Bhcsl.mjs → HubspotPropertyInput-DicskLcN.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-B-piLcIy.js → HubspotPropertyInput-Dss3eUlL.js} +3 -3
- package/dist/_chunks/{Settings-Dz0PEFOv.mjs → Settings-4CbX3SPK.mjs} +2 -2
- package/dist/_chunks/{Settings-DMu_QThB.js → Settings-Ch8tPZAV.js} +2 -2
- package/dist/_chunks/{en-CH5LSPkL.mjs → en-D8DJiSxd.mjs} +3 -1
- package/dist/_chunks/{en-BDGqW_yS.js → en-PYFibnDc.js} +3 -1
- package/dist/_chunks/{fr-65-RaB3w.mjs → fr-BMjixfXn.mjs} +3 -1
- package/dist/_chunks/{fr-C82LMqUM.js → fr-yHk4sSEl.js} +3 -1
- package/dist/_chunks/{index-B7Ru1fu5.js → index-BAvedd2m.js} +6 -6
- package/dist/_chunks/{index-DA31TY2n.mjs → index-BE2ribUL.mjs} +6 -6
- package/dist/_chunks/{objectLabels-FTh984_h.js → objectLabels-CycoU0zY.js} +1 -1
- package/dist/_chunks/{objectLabels-Bl7sO5pb.mjs → objectLabels-DGJxYjKz.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-C2_PuXEm.js → useHubspotSchema-DRfaI6mF.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-BlDilCHc.mjs → useHubspotSchema-e31UsYb2.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/builder/Sortable.d.ts +25 -0
- package/dist/admin/src/builder/__tests__/CompanyMapEditor.test.d.ts +1 -0
- package/dist/admin/src/builder/__tests__/ConditionEditor.test.d.ts +1 -0
- package/dist/admin/src/builder/__tests__/testUtils.d.ts +4 -0
- package/dist/server/index.js +101 -42
- package/dist/server/index.mjs +101 -42
- package/dist/server/src/__tests__/contract.test.d.ts +1 -0
- package/dist/server/src/__tests__/rateLimit.test.d.ts +1 -0
- package/dist/server/src/index.d.ts +12 -3
- package/dist/server/src/rateLimit.d.ts +18 -0
- package/package.json +11 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.13.0 — 2026-08-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Drag & drop in the builder** (@dnd-kit): steps reorder among themselves,
|
|
7
|
+
fields reorder within their step — grab the grip handle; an 8px activation
|
|
8
|
+
distance keeps plain clicks selecting as before. The arrow buttons stay:
|
|
9
|
+
they remain the accessible path and the way to slide a field into the
|
|
10
|
+
neighbouring step.
|
|
11
|
+
|
|
12
|
+
### Also in this release — anti-spam & frozen contract
|
|
13
|
+
- **Per-IP rate limiting** on the public routes (sliding window, in-memory):
|
|
14
|
+
submissions 6/min, company searches 30/min — `forms.rateLimit`
|
|
15
|
+
config, `0` disables one. Over the limit → `429`.
|
|
16
|
+
- **Honeypot**: a submission whose hidden `__hp` key is filled gets a normal
|
|
17
|
+
success and is neither sent nor stored — no signal for the bot to adapt to.
|
|
18
|
+
(Frontends: render a visually hidden `__hp` input.)
|
|
19
|
+
- **Contract test suite** freezing the 1.0 public surface: public form
|
|
20
|
+
payload keys, CRM mappings never leaked, submission conventions
|
|
21
|
+
(`__siret`/`__company`/`__hp`, structured `missingRequired`), the 12
|
|
22
|
+
condition operators. A failure there means "bump the major".
|
|
23
|
+
- README: *Stability & versioning* section documenting the frozen contract
|
|
24
|
+
and the `version: 2` migration promise.
|
|
25
|
+
|
|
3
26
|
## 0.11.1 — 2026-08-29
|
|
4
27
|
|
|
5
28
|
Ships the company-search sharpening that missed the 0.11.0 tarball (the
|
package/README.md
CHANGED
|
@@ -342,6 +342,24 @@ authenticated admin, since the picker needs it in the Content Manager.
|
|
|
342
342
|
> reaches the browser, but treat it like any other secret in your database. Use
|
|
343
343
|
> `HUBSPOT_API_KEY` if your deployment already manages secrets properly.
|
|
344
344
|
|
|
345
|
+
## Stability & versioning
|
|
346
|
+
|
|
347
|
+
From 1.0 onward this plugin follows semver against a **frozen public
|
|
348
|
+
contract**, enforced by a dedicated test suite (`contract.test.ts`):
|
|
349
|
+
|
|
350
|
+
- the **definition document** (`version: 1`): steps → fields → `visibleIf`
|
|
351
|
+
conditions, the 12 operators, stable `stp_`/`fld_` ids;
|
|
352
|
+
- the **public API payloads**: `GET /forms/:slug` (rendering props served,
|
|
353
|
+
CRM mappings never), `POST /forms/:slug/submit` and its structured 422,
|
|
354
|
+
`GET /company-search`;
|
|
355
|
+
- the **submission conventions**: values keyed by field `name`, company
|
|
356
|
+
companion keys `<name>__siret` / `<name>__company`, honeypot `__hp`;
|
|
357
|
+
- the exported types (`strapi-plugin-hubspot/types`).
|
|
358
|
+
|
|
359
|
+
Anything else — admin UI, internals, HubSpot plumbing — may improve in minor
|
|
360
|
+
versions. Breaking any of the above means a major version, and a `version: 2`
|
|
361
|
+
definition would ship with an automatic migration from `version: 1`.
|
|
362
|
+
|
|
345
363
|
## Install
|
|
346
364
|
|
|
347
365
|
```bash
|
|
@@ -3,11 +3,14 @@ import { useParams, useSearchParams, Link, useNavigate, Routes, Route } from "re
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
5
5
|
import { Typography, Flex, Box, SingleSelect, SingleSelectOption, MultiSelect, MultiSelectOption, TextInput, IconButton, Button, Combobox, ComboboxOption, Field, Textarea, Checkbox, Divider, Loader, Badge, Table, Thead, Tr, Th, Tbody, Td, Modal } from "@strapi/design-system";
|
|
6
|
-
import { Trash, Plus, ArrowClockwise, ArrowLeft, ArrowUp, ArrowDown, List, Duplicate, Download } from "@strapi/icons";
|
|
6
|
+
import { Trash, Plus, ArrowClockwise, ArrowLeft, Drag, ArrowUp, ArrowDown, List, Duplicate, Download } from "@strapi/icons";
|
|
7
7
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
8
|
-
import { g as getTranslation, P as PLUGIN_ID } from "./index-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-BE2ribUL.mjs";
|
|
9
|
+
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from "@dnd-kit/core";
|
|
10
|
+
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable, arrayMove } from "@dnd-kit/sortable";
|
|
11
|
+
import { CSS } from "@dnd-kit/utilities";
|
|
12
|
+
import { o as objectLabel } from "./objectLabels-DGJxYjKz.mjs";
|
|
13
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-e31UsYb2.mjs";
|
|
11
14
|
const OPERATORS = [
|
|
12
15
|
"eq",
|
|
13
16
|
"neq",
|
|
@@ -150,6 +153,48 @@ const ConditionEditor = ({ condition, candidates, onChange }) => {
|
|
|
150
153
|
] })
|
|
151
154
|
] });
|
|
152
155
|
};
|
|
156
|
+
function SortableList({
|
|
157
|
+
ids,
|
|
158
|
+
onReorder,
|
|
159
|
+
children
|
|
160
|
+
}) {
|
|
161
|
+
const sensors = useSensors(
|
|
162
|
+
// An 8px activation distance keeps clicks (selection!) from starting drags.
|
|
163
|
+
useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
|
|
164
|
+
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
165
|
+
);
|
|
166
|
+
const handleDragEnd = (event) => {
|
|
167
|
+
const { active, over } = event;
|
|
168
|
+
if (!over || active.id === over.id) return;
|
|
169
|
+
const from = ids.indexOf(String(active.id));
|
|
170
|
+
const to = ids.indexOf(String(over.id));
|
|
171
|
+
if (from === -1 || to === -1) return;
|
|
172
|
+
onReorder(arrayMove(ids, from, to));
|
|
173
|
+
};
|
|
174
|
+
return /* @__PURE__ */ jsx(DndContext, { sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items: ids, strategy: verticalListSortingStrategy, children }) });
|
|
175
|
+
}
|
|
176
|
+
function SortableItem({
|
|
177
|
+
id,
|
|
178
|
+
children
|
|
179
|
+
}) {
|
|
180
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
181
|
+
id
|
|
182
|
+
});
|
|
183
|
+
return /* @__PURE__ */ jsx(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
ref: setNodeRef,
|
|
187
|
+
style: {
|
|
188
|
+
transform: CSS.Transform.toString(transform),
|
|
189
|
+
transition,
|
|
190
|
+
opacity: isDragging ? 0.5 : void 0,
|
|
191
|
+
zIndex: isDragging ? 2 : void 0,
|
|
192
|
+
position: "relative"
|
|
193
|
+
},
|
|
194
|
+
children: children({ attributes, listeners })
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
153
198
|
const FIELD_TYPES = [
|
|
154
199
|
"text",
|
|
155
200
|
"email",
|
|
@@ -672,6 +717,10 @@ const FormEditor = () => {
|
|
|
672
717
|
}
|
|
673
718
|
return next;
|
|
674
719
|
});
|
|
720
|
+
function reorderByIds(items, ids) {
|
|
721
|
+
const byId = new Map(items.map((item) => [item.id, item]));
|
|
722
|
+
return ids.map((id) => byId.get(id)).filter((item) => Boolean(item));
|
|
723
|
+
}
|
|
675
724
|
const moveStep = (stepIndex, delta) => patchDefinition((steps) => {
|
|
676
725
|
const target = stepIndex + delta;
|
|
677
726
|
if (target < 0 || target >= steps.length) return steps;
|
|
@@ -793,154 +842,202 @@ const FormEditor = () => {
|
|
|
793
842
|
feedback && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: feedback.tone === "success" ? "success600" : "danger600", children: feedback.text }) }),
|
|
794
843
|
/* @__PURE__ */ jsxs(Flex, { gap: 6, alignItems: "flex-start", children: [
|
|
795
844
|
/* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
796
|
-
|
|
797
|
-
|
|
845
|
+
/* @__PURE__ */ jsx(
|
|
846
|
+
SortableList,
|
|
798
847
|
{
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
borderWidth: selection.kind === "step" && selection.stepId === step.id ? "1px" : void 0,
|
|
808
|
-
children: [
|
|
809
|
-
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", paddingBottom: 2, children: [
|
|
810
|
-
/* @__PURE__ */ jsxs(
|
|
811
|
-
Flex,
|
|
848
|
+
ids: definition.steps.map((s) => s.id),
|
|
849
|
+
onReorder: (ids) => patchDefinition((steps) => reorderByIds(steps, ids)),
|
|
850
|
+
children: definition.steps.map((step, stepIndex) => /* @__PURE__ */ jsx(
|
|
851
|
+
SortableItem,
|
|
852
|
+
{
|
|
853
|
+
id: step.id,
|
|
854
|
+
children: (stepHandle) => /* @__PURE__ */ jsxs(
|
|
855
|
+
Box,
|
|
812
856
|
{
|
|
813
|
-
|
|
814
|
-
|
|
857
|
+
background: "neutral0",
|
|
858
|
+
hasRadius: true,
|
|
859
|
+
shadow: "tableShadow",
|
|
860
|
+
padding: 4,
|
|
815
861
|
onClick: () => setSelection({ kind: "step", stepId: step.id }),
|
|
816
862
|
style: { cursor: "pointer" },
|
|
863
|
+
borderColor: selection.kind === "step" && selection.stepId === step.id ? "primary600" : void 0,
|
|
864
|
+
borderStyle: selection.kind === "step" && selection.stepId === step.id ? "solid" : void 0,
|
|
865
|
+
borderWidth: selection.kind === "step" && selection.stepId === step.id ? "1px" : void 0,
|
|
817
866
|
children: [
|
|
818
|
-
/* @__PURE__ */ jsxs(
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
IconButton,
|
|
848
|
-
{
|
|
849
|
-
label: t("editor.step-delete", "Delete the step and its fields"),
|
|
850
|
-
onClick: () => {
|
|
851
|
-
setSelection({ kind: "form" });
|
|
852
|
-
patchDefinition((steps) => steps.filter((s) => s.id !== step.id));
|
|
853
|
-
},
|
|
854
|
-
children: /* @__PURE__ */ jsx(Trash, {})
|
|
855
|
-
}
|
|
856
|
-
)
|
|
857
|
-
] })
|
|
858
|
-
] }),
|
|
859
|
-
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
860
|
-
step.fields.map((field, fieldIndex) => {
|
|
861
|
-
const flags = fieldFlags(field.id);
|
|
862
|
-
const isSelected = selection.kind === "field" && selection.fieldId === field.id;
|
|
863
|
-
return /* @__PURE__ */ jsx(
|
|
864
|
-
Box,
|
|
865
|
-
{
|
|
866
|
-
background: isSelected ? "primary100" : "neutral100",
|
|
867
|
-
hasRadius: true,
|
|
868
|
-
padding: 3,
|
|
869
|
-
onClick: (e) => {
|
|
870
|
-
e.stopPropagation();
|
|
871
|
-
setSelection({ kind: "field", fieldId: field.id });
|
|
872
|
-
},
|
|
873
|
-
style: { cursor: "pointer" },
|
|
874
|
-
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
|
|
875
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
876
|
-
/* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: field.label || field.name || "—" }),
|
|
877
|
-
/* @__PURE__ */ jsx(Badge, { children: field.type }),
|
|
878
|
-
field.required && /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral600", children: t("editor.required", "required") }),
|
|
879
|
-
field.hubspot?.property && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
880
|
-
field.hubspot.object ?? "contact",
|
|
881
|
-
".",
|
|
882
|
-
field.hubspot.property
|
|
883
|
-
] }),
|
|
884
|
-
field.visibleIf?.rules?.length ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "alternative100", textColor: "alternative700", children: t("editor.conditional", "Conditional") }) : null,
|
|
885
|
-
(flags.error || flags.problem) && /* @__PURE__ */ jsx(Badge, { backgroundColor: "danger100", textColor: "danger700", children: flags.error?.code ?? flags.problem?.code })
|
|
886
|
-
] }),
|
|
867
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", paddingBottom: 2, children: [
|
|
868
|
+
/* @__PURE__ */ jsxs(
|
|
869
|
+
Flex,
|
|
870
|
+
{
|
|
871
|
+
gap: 2,
|
|
872
|
+
alignItems: "center",
|
|
873
|
+
onClick: () => setSelection({ kind: "step", stepId: step.id }),
|
|
874
|
+
style: { cursor: "pointer" },
|
|
875
|
+
children: [
|
|
876
|
+
/* @__PURE__ */ jsx(
|
|
877
|
+
"span",
|
|
878
|
+
{
|
|
879
|
+
...stepHandle.attributes,
|
|
880
|
+
...stepHandle.listeners,
|
|
881
|
+
onClick: (e) => e.stopPropagation(),
|
|
882
|
+
style: { cursor: "grab", display: "inline-flex", color: "inherit" },
|
|
883
|
+
"aria-label": t("editor.drag-step", "Drag to reorder the step"),
|
|
884
|
+
children: /* @__PURE__ */ jsx(Drag, {})
|
|
885
|
+
}
|
|
886
|
+
),
|
|
887
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "delta", children: [
|
|
888
|
+
t("editor.step", "Step {n}", { n: stepIndex + 1 }),
|
|
889
|
+
step.title ? ` — ${step.title}` : ""
|
|
890
|
+
] }),
|
|
891
|
+
step.visibleIf?.rules?.length ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "alternative100", textColor: "alternative700", children: t("editor.conditional", "Conditional") }) : null,
|
|
892
|
+
errors.some((e) => e.stepId === step.id) && /* @__PURE__ */ jsx(Badge, { backgroundColor: "danger100", textColor: "danger700", children: t("editor.flag-error", "To fix") })
|
|
893
|
+
]
|
|
894
|
+
}
|
|
895
|
+
),
|
|
887
896
|
/* @__PURE__ */ jsxs(Flex, { gap: 1, onClick: (e) => e.stopPropagation(), children: [
|
|
888
897
|
/* @__PURE__ */ jsx(
|
|
889
898
|
IconButton,
|
|
890
899
|
{
|
|
891
|
-
label: t("editor.
|
|
892
|
-
onClick: () =>
|
|
893
|
-
disabled: stepIndex === 0
|
|
900
|
+
label: t("editor.step-up", "Move the step up"),
|
|
901
|
+
onClick: () => moveStep(stepIndex, -1),
|
|
902
|
+
disabled: stepIndex === 0,
|
|
894
903
|
children: /* @__PURE__ */ jsx(ArrowUp, {})
|
|
895
904
|
}
|
|
896
905
|
),
|
|
897
906
|
/* @__PURE__ */ jsx(
|
|
898
907
|
IconButton,
|
|
899
908
|
{
|
|
900
|
-
label: t("editor.
|
|
901
|
-
onClick: () =>
|
|
902
|
-
disabled: stepIndex === definition.steps.length - 1
|
|
909
|
+
label: t("editor.step-down", "Move the step down"),
|
|
910
|
+
onClick: () => moveStep(stepIndex, 1),
|
|
911
|
+
disabled: stepIndex === definition.steps.length - 1,
|
|
903
912
|
children: /* @__PURE__ */ jsx(ArrowDown, {})
|
|
904
913
|
}
|
|
905
914
|
),
|
|
906
915
|
/* @__PURE__ */ jsx(
|
|
907
916
|
IconButton,
|
|
908
917
|
{
|
|
909
|
-
label: t("editor.
|
|
918
|
+
label: t("editor.step-delete", "Delete the step and its fields"),
|
|
910
919
|
onClick: () => {
|
|
911
920
|
setSelection({ kind: "form" });
|
|
912
|
-
|
|
913
|
-
fields: step.fields.filter((f) => f.id !== field.id)
|
|
914
|
-
});
|
|
921
|
+
patchDefinition((steps) => steps.filter((s) => s.id !== step.id));
|
|
915
922
|
},
|
|
916
923
|
children: /* @__PURE__ */ jsx(Trash, {})
|
|
917
924
|
}
|
|
918
925
|
)
|
|
919
926
|
] })
|
|
927
|
+
] }),
|
|
928
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
929
|
+
/* @__PURE__ */ jsx(
|
|
930
|
+
SortableList,
|
|
931
|
+
{
|
|
932
|
+
ids: step.fields.map((f) => f.id),
|
|
933
|
+
onReorder: (ids) => patchStep(step.id, { fields: reorderByIds(step.fields, ids) }),
|
|
934
|
+
children: step.fields.map((field, fieldIndex) => {
|
|
935
|
+
const flags = fieldFlags(field.id);
|
|
936
|
+
const isSelected = selection.kind === "field" && selection.fieldId === field.id;
|
|
937
|
+
return /* @__PURE__ */ jsx(
|
|
938
|
+
SortableItem,
|
|
939
|
+
{
|
|
940
|
+
id: field.id,
|
|
941
|
+
children: (fieldHandle) => /* @__PURE__ */ jsx(
|
|
942
|
+
Box,
|
|
943
|
+
{
|
|
944
|
+
background: isSelected ? "primary100" : "neutral100",
|
|
945
|
+
hasRadius: true,
|
|
946
|
+
padding: 3,
|
|
947
|
+
onClick: (e) => {
|
|
948
|
+
e.stopPropagation();
|
|
949
|
+
setSelection({ kind: "field", fieldId: field.id });
|
|
950
|
+
},
|
|
951
|
+
style: { cursor: "pointer" },
|
|
952
|
+
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
|
|
953
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
954
|
+
/* @__PURE__ */ jsx(
|
|
955
|
+
"span",
|
|
956
|
+
{
|
|
957
|
+
...fieldHandle.attributes,
|
|
958
|
+
...fieldHandle.listeners,
|
|
959
|
+
onClick: (e) => e.stopPropagation(),
|
|
960
|
+
style: { cursor: "grab", display: "inline-flex" },
|
|
961
|
+
"aria-label": t("editor.drag-field", "Drag to reorder the field"),
|
|
962
|
+
children: /* @__PURE__ */ jsx(Drag, {})
|
|
963
|
+
}
|
|
964
|
+
),
|
|
965
|
+
/* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: field.label || field.name || "—" }),
|
|
966
|
+
/* @__PURE__ */ jsx(Badge, { children: field.type }),
|
|
967
|
+
field.required && /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral600", children: t("editor.required", "required") }),
|
|
968
|
+
field.hubspot?.property && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
969
|
+
field.hubspot.object ?? "contact",
|
|
970
|
+
".",
|
|
971
|
+
field.hubspot.property
|
|
972
|
+
] }),
|
|
973
|
+
field.visibleIf?.rules?.length ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "alternative100", textColor: "alternative700", children: t("editor.conditional", "Conditional") }) : null,
|
|
974
|
+
(flags.error || flags.problem) && /* @__PURE__ */ jsx(Badge, { backgroundColor: "danger100", textColor: "danger700", children: flags.error?.code ?? flags.problem?.code })
|
|
975
|
+
] }),
|
|
976
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 1, onClick: (e) => e.stopPropagation(), children: [
|
|
977
|
+
/* @__PURE__ */ jsx(
|
|
978
|
+
IconButton,
|
|
979
|
+
{
|
|
980
|
+
label: t("editor.field-up", "Move up"),
|
|
981
|
+
onClick: () => moveField(stepIndex, fieldIndex, -1),
|
|
982
|
+
disabled: stepIndex === 0 && fieldIndex === 0,
|
|
983
|
+
children: /* @__PURE__ */ jsx(ArrowUp, {})
|
|
984
|
+
}
|
|
985
|
+
),
|
|
986
|
+
/* @__PURE__ */ jsx(
|
|
987
|
+
IconButton,
|
|
988
|
+
{
|
|
989
|
+
label: t("editor.field-down", "Move down"),
|
|
990
|
+
onClick: () => moveField(stepIndex, fieldIndex, 1),
|
|
991
|
+
disabled: stepIndex === definition.steps.length - 1 && fieldIndex === step.fields.length - 1,
|
|
992
|
+
children: /* @__PURE__ */ jsx(ArrowDown, {})
|
|
993
|
+
}
|
|
994
|
+
),
|
|
995
|
+
/* @__PURE__ */ jsx(
|
|
996
|
+
IconButton,
|
|
997
|
+
{
|
|
998
|
+
label: t("editor.field-delete", "Delete the field"),
|
|
999
|
+
onClick: () => {
|
|
1000
|
+
setSelection({ kind: "form" });
|
|
1001
|
+
patchStep(step.id, {
|
|
1002
|
+
fields: step.fields.filter((f) => f.id !== field.id)
|
|
1003
|
+
});
|
|
1004
|
+
},
|
|
1005
|
+
children: /* @__PURE__ */ jsx(Trash, {})
|
|
1006
|
+
}
|
|
1007
|
+
)
|
|
1008
|
+
] })
|
|
1009
|
+
] })
|
|
1010
|
+
}
|
|
1011
|
+
)
|
|
1012
|
+
},
|
|
1013
|
+
field.id
|
|
1014
|
+
);
|
|
1015
|
+
})
|
|
1016
|
+
}
|
|
1017
|
+
),
|
|
1018
|
+
/* @__PURE__ */ jsx(
|
|
1019
|
+
Button,
|
|
1020
|
+
{
|
|
1021
|
+
variant: "tertiary",
|
|
1022
|
+
startIcon: /* @__PURE__ */ jsx(Plus, {}),
|
|
1023
|
+
onClick: (e) => {
|
|
1024
|
+
e.stopPropagation();
|
|
1025
|
+
const field = newField(t("editor.new-field", "New field"));
|
|
1026
|
+
patchStep(step.id, { fields: [...step.fields, field] });
|
|
1027
|
+
setSelection({ kind: "field", fieldId: field.id });
|
|
1028
|
+
},
|
|
1029
|
+
children: t("editor.add-field", "Add a field")
|
|
1030
|
+
}
|
|
1031
|
+
)
|
|
920
1032
|
] })
|
|
921
|
-
|
|
922
|
-
field.id
|
|
923
|
-
);
|
|
924
|
-
}),
|
|
925
|
-
/* @__PURE__ */ jsx(
|
|
926
|
-
Button,
|
|
927
|
-
{
|
|
928
|
-
variant: "tertiary",
|
|
929
|
-
startIcon: /* @__PURE__ */ jsx(Plus, {}),
|
|
930
|
-
onClick: (e) => {
|
|
931
|
-
e.stopPropagation();
|
|
932
|
-
const field = newField(t("editor.new-field", "New field"));
|
|
933
|
-
patchStep(step.id, { fields: [...step.fields, field] });
|
|
934
|
-
setSelection({ kind: "field", fieldId: field.id });
|
|
935
|
-
},
|
|
936
|
-
children: t("editor.add-field", "Add a field")
|
|
1033
|
+
]
|
|
937
1034
|
}
|
|
938
1035
|
)
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
)
|
|
1036
|
+
},
|
|
1037
|
+
step.id
|
|
1038
|
+
))
|
|
1039
|
+
}
|
|
1040
|
+
),
|
|
944
1041
|
/* @__PURE__ */ jsx(
|
|
945
1042
|
Button,
|
|
946
1043
|
{
|