@overmap-ai/core 1.0.38 → 1.0.39

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.
@@ -1677,6 +1677,22 @@ const componentStageSlice = createSlice({
1677
1677
  action.payload.forEach((id) => {
1678
1678
  delete state.stages[id];
1679
1679
  });
1680
+ },
1681
+ linkStageToForm: (state, action) => {
1682
+ const { stageId, formId: formId2 } = action.payload;
1683
+ const stage = state.stages[stageId];
1684
+ if (!stage) {
1685
+ throw new Error("No stage exists with the id " + stageId);
1686
+ }
1687
+ stage.user_form = formId2;
1688
+ },
1689
+ unlinkStageToForm: (state, action) => {
1690
+ const { stageId } = action.payload;
1691
+ const stage = state.stages[stageId];
1692
+ if (!stage) {
1693
+ throw new Error("No stage exists with the id " + stageId);
1694
+ }
1695
+ delete stage.user_form;
1680
1696
  }
1681
1697
  }
1682
1698
  });
@@ -1721,7 +1737,22 @@ const selectStagesFromStageIds = restructureCreateSelectorWithArgs(
1721
1737
  return stageIds.map((offline_id) => stageMapping[offline_id]).filter((stage) => !!stage);
1722
1738
  })
1723
1739
  );
1724
- const { addStages, updateStages, removeStages } = componentStageSlice.actions;
1740
+ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1741
+ createSelector([selectStageMapping, (_state, stageIds) => stageIds], (stageMapping, stageIds) => {
1742
+ const ret = {};
1743
+ for (const stageId of stageIds) {
1744
+ const stage = stageMapping[stageId];
1745
+ if (!stage) {
1746
+ throw new Error("No stage exists with the id " + stageId);
1747
+ }
1748
+ if (stage.user_form) {
1749
+ ret[stageId] = stage.user_form;
1750
+ }
1751
+ }
1752
+ return ret;
1753
+ })
1754
+ );
1755
+ const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1725
1756
  const componentStageReducer = componentStageSlice.reducer;
1726
1757
  const initialState$g = {
1727
1758
  componentTypes: {},
@@ -3017,7 +3048,7 @@ const userFormSlice = createSlice({
3017
3048
  delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3018
3049
  }
3019
3050
  },
3020
- addUserFormSubmission: (state, action) => {
3051
+ updateOrCreateUserFormSubmission: (state, action) => {
3021
3052
  state.submissions[action.payload.offline_id] = action.payload;
3022
3053
  },
3023
3054
  addUserFormSubmissionAttachment: (state, action) => {
@@ -3106,7 +3137,7 @@ const {
3106
3137
  addUserForm,
3107
3138
  addUserForms,
3108
3139
  addUserFormRevisions,
3109
- addUserFormSubmission,
3140
+ updateOrCreateUserFormSubmission,
3110
3141
  addUserFormSubmissions,
3111
3142
  deleteUserFormSubmission,
3112
3143
  deleteUserFormSubmissions,
@@ -3198,7 +3229,6 @@ const selectUserForm = (formId2) => (state) => {
3198
3229
  const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3199
3230
  const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3200
3231
  const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3201
- const selectRevisionAttachmentsMapping = (state) => state.userFormReducer.revisionAttachments;
3202
3232
  const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
3203
3233
  const selectRevisionsForForm = restructureCreateSelectorWithArgs(
3204
3234
  createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
@@ -3241,6 +3271,33 @@ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3241
3271
  const selectUserFormMapping = (state) => {
3242
3272
  return state.userFormReducer.userForms;
3243
3273
  };
3274
+ const selectComponentTypeForm = restructureCreateSelectorWithArgs(
3275
+ createSelector(
3276
+ [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3277
+ (userForms, componentTypeId) => {
3278
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3279
+ }
3280
+ )
3281
+ );
3282
+ const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3283
+ createSelector(
3284
+ [
3285
+ selectUserFormMapping,
3286
+ selectRevisionMapping,
3287
+ (_state, componentTypeIds) => componentTypeIds
3288
+ ],
3289
+ (userForms, revisions, componentTypeIds) => {
3290
+ const componentTypeIdsSet = new Set(componentTypeIds);
3291
+ const ret = {};
3292
+ for (const form of Object.values(userForms)) {
3293
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3294
+ ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3295
+ }
3296
+ }
3297
+ return ret;
3298
+ }
3299
+ )
3300
+ );
3244
3301
  const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (revisions) => {
3245
3302
  const latestRevisions = {};
3246
3303
  for (const revision of Object.values(revisions)) {
@@ -3252,22 +3309,12 @@ const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (re
3252
3309
  }
3253
3310
  return latestRevisions;
3254
3311
  });
3255
- const selectAllRevisionAttachmentsByLatestRevisionId = createSelector(
3256
- [selectUserFormMapping, selectRevisionMapping, selectRevisionAttachmentsMapping],
3257
- (forms, revisions, attachments) => {
3258
- const mappedAttachments = {};
3259
- for (const form of Object.values(forms)) {
3260
- const latestRevision = _selectLatestFormRevision(revisions, form.offline_id);
3261
- if (attachments[latestRevision.offline_id] !== void 0) {
3262
- mappedAttachments[latestRevision.offline_id] = attachments[latestRevision.offline_id];
3263
- }
3264
- }
3265
- return mappedAttachments;
3266
- }
3267
- );
3268
3312
  const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
3269
3313
  return Object.keys(userForms).length;
3270
3314
  });
3315
+ const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
3316
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3317
+ });
3271
3318
  const userFormReducer = userFormSlice.reducer;
3272
3319
  const initialState$1 = {
3273
3320
  emailDomains: {}
@@ -4633,6 +4680,39 @@ class ComponentStageService extends BaseApiService {
4633
4680
  blocks: [componentStage.offline_id]
4634
4681
  });
4635
4682
  }
4683
+ async linkForm(stageId, formId2) {
4684
+ const { store } = this.client;
4685
+ store.dispatch(linkStageToForm({ stageId, formId: formId2 }));
4686
+ try {
4687
+ await this.enqueueRequest({
4688
+ description: "Link component stage to form",
4689
+ method: HttpMethod.POST,
4690
+ url: `/components/stages/${stageId}/associate-with-form/`,
4691
+ payload: { user_form: formId2 },
4692
+ blockers: [stageId, formId2],
4693
+ blocks: [stageId]
4694
+ });
4695
+ } catch (e) {
4696
+ store.dispatch(unlinkStageToForm({ stageId }));
4697
+ throw e;
4698
+ }
4699
+ }
4700
+ async unlinkForm(stageId, formId2) {
4701
+ const { store } = this.client;
4702
+ store.dispatch(unlinkStageToForm({ stageId }));
4703
+ try {
4704
+ await this.enqueueRequest({
4705
+ description: "Unlink component stage from form",
4706
+ method: HttpMethod.DELETE,
4707
+ url: `/components/stages/${stageId}/associate-with-form/`,
4708
+ blockers: [stageId, formId2],
4709
+ blocks: [stageId]
4710
+ });
4711
+ } catch (e) {
4712
+ store.dispatch(linkStageToForm({ stageId, formId: formId2 }));
4713
+ throw e;
4714
+ }
4715
+ }
4636
4716
  async refreshStore() {
4637
4717
  const { store } = this.client;
4638
4718
  const result = await this.enqueueRequest({
@@ -5418,7 +5498,7 @@ class UserFormService extends BaseApiService {
5418
5498
  });
5419
5499
  });
5420
5500
  }
5421
- async add(state, initialRevision, url, ownerUser, ownerOrganization) {
5501
+ async add(state, initialRevision, url, ownerUser, ownerOrganization, componentTypeId) {
5422
5502
  if (!!ownerUser === !!ownerOrganization) {
5423
5503
  throw new Error("Exactly one of ownerUser and ownerOrganization must be defined.");
5424
5504
  }
@@ -5436,6 +5516,7 @@ class UserFormService extends BaseApiService {
5436
5516
  favorite: true,
5437
5517
  submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
5438
5518
  created_by: currentUser.id,
5519
+ ...componentTypeId && { component_type: componentTypeId },
5439
5520
  ...ownerAttrs
5440
5521
  };
5441
5522
  const { payloadWithoutImage, images } = await separateImageFromFields(offlineRevisionPayload);
@@ -5455,8 +5536,12 @@ class UserFormService extends BaseApiService {
5455
5536
  queryParams: activeWorkspaceId ? {
5456
5537
  workspace_id: activeWorkspaceId
5457
5538
  } : void 0,
5458
- payload: { ...offlineFormPayload, initial_revision: payloadWithoutImage },
5459
- blockers: [],
5539
+ payload: {
5540
+ ...offlineFormPayload,
5541
+ ...componentTypeId && { component_type: componentTypeId },
5542
+ initial_revision: payloadWithoutImage
5543
+ },
5544
+ blockers: componentTypeId ? [componentTypeId] : [],
5460
5545
  blocks: [offlineFormPayload.offline_id, payloadWithoutImage.offline_id]
5461
5546
  });
5462
5547
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
@@ -5468,7 +5553,7 @@ class UserFormService extends BaseApiService {
5468
5553
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
5469
5554
  return [retForm, retRevision, formPromise, settledPromise];
5470
5555
  }
5471
- async addForOrganization(initialRevision) {
5556
+ async addForOrganization(initialRevision, componentTypeId) {
5472
5557
  const state = this.client.store.getState();
5473
5558
  const activeOrganizationId = state.organizationReducer.activeOrganizationId;
5474
5559
  if (!activeOrganizationId) {
@@ -5479,13 +5564,14 @@ class UserFormService extends BaseApiService {
5479
5564
  initialRevision,
5480
5565
  `/forms/in-organization/${activeOrganizationId}/`,
5481
5566
  void 0,
5482
- activeOrganizationId
5567
+ activeOrganizationId,
5568
+ componentTypeId
5483
5569
  );
5484
5570
  }
5485
- async addForCurrentUser(initialRevision) {
5571
+ async addForCurrentUser(initialRevision, componentTypeId) {
5486
5572
  const state = this.client.store.getState();
5487
5573
  const currentUser = state.userReducer.currentUser;
5488
- return await this.add(state, initialRevision, "/forms/my-forms/", currentUser.id);
5574
+ return await this.add(state, initialRevision, "/forms/my-forms/", currentUser.id, void 0, componentTypeId);
5489
5575
  }
5490
5576
  async createRevision(formId2, revision) {
5491
5577
  const offlineRevision = offline(revision);
@@ -5633,6 +5719,43 @@ const separateFilesFromValues = (payload) => {
5633
5719
  return { payloadWithoutFiles, files };
5634
5720
  };
5635
5721
  class UserFormSubmissionService extends BaseApiService {
5722
+ constructor() {
5723
+ super(...arguments);
5724
+ // Attach files to submission, after uploading them to S3
5725
+ __publicField(this, "getAttachFilesPromises", (files, payload) => {
5726
+ const { store } = this.client;
5727
+ return Object.entries(files).map(async ([key, fileArray]) => {
5728
+ const attachResults = [];
5729
+ for (const file of fileArray) {
5730
+ const sha1 = await hashFile(file);
5731
+ await this.client.files.addCache(file, sha1);
5732
+ const [fileProps] = await this.client.files.uploadFileToS3(sha1);
5733
+ const submissionAttachmentPayload = offline({
5734
+ ...fileProps,
5735
+ submission: payload.offline_id,
5736
+ field_identifier: key
5737
+ });
5738
+ const attach = await this.enqueueRequest({
5739
+ description: "Attach file to form submission",
5740
+ method: HttpMethod.POST,
5741
+ url: `/forms/submission/${payload.offline_id}/attachments/`,
5742
+ payload: submissionAttachmentPayload,
5743
+ blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
5744
+ (x) => x !== void 0
5745
+ ),
5746
+ blocks: [submissionAttachmentPayload.offline_id]
5747
+ });
5748
+ const offlinePayload = {
5749
+ ...submissionAttachmentPayload,
5750
+ file: URL.createObjectURL(file)
5751
+ };
5752
+ store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
5753
+ attachResults.push(attach);
5754
+ }
5755
+ return attachResults;
5756
+ });
5757
+ });
5758
+ }
5636
5759
  add(payload) {
5637
5760
  const { store } = this.client;
5638
5761
  const state = store.getState();
@@ -5646,51 +5769,26 @@ class UserFormSubmissionService extends BaseApiService {
5646
5769
  method: HttpMethod.POST,
5647
5770
  url: `/forms/revisions/${payload.form_revision}/respond/`,
5648
5771
  payload: { ...payloadWithoutFiles, project: activeProjectId },
5649
- blockers: [payload.issue, payload.component].filter((x) => x !== void 0),
5772
+ blockers: [payload.issue, payload.component, payload.component_stage].filter(
5773
+ (x) => x !== void 0
5774
+ ),
5650
5775
  blocks: [payload.offline_id]
5651
5776
  });
5652
- const attachFilesPromises = Object.entries(files).map(async ([key, fileArray]) => {
5653
- const attachResults = [];
5654
- for (const file of fileArray) {
5655
- const sha1 = await hashFile(file);
5656
- await this.client.files.addCache(file, sha1);
5657
- const [fileProps] = await this.client.files.uploadFileToS3(sha1);
5658
- const submissionAttachmentPayload = offline({
5659
- ...fileProps,
5660
- submission: payload.offline_id,
5661
- field_identifier: key
5662
- });
5663
- const attach = await this.enqueueRequest({
5664
- description: "Attach file to form submission",
5665
- method: HttpMethod.POST,
5666
- url: `/forms/submission/${payload.offline_id}/attachments/`,
5667
- payload: submissionAttachmentPayload,
5668
- blockers: [payload.component, payload.issue, payload.form_revision].filter(
5669
- (x) => x !== void 0
5670
- ),
5671
- blocks: [submissionAttachmentPayload.offline_id]
5672
- });
5673
- const offlinePayload = {
5674
- ...submissionAttachmentPayload,
5675
- file: URL.createObjectURL(file)
5676
- };
5677
- store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
5678
- attachResults.push(attach);
5679
- }
5680
- return attachResults;
5681
- });
5777
+ const attachFilesPromises = this.getAttachFilesPromises(files, payload);
5778
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5682
5779
  const fullOfflineResult = {
5683
5780
  ...payload,
5684
5781
  created_by: state.userReducer.currentUser.id,
5685
- created_at: (/* @__PURE__ */ new Date()).toISOString()
5782
+ created_at: now,
5783
+ updated_at: now
5686
5784
  };
5687
5785
  const offlineResultWithoutFiles = {
5688
5786
  ...fullOfflineResult,
5689
5787
  ...payloadWithoutFiles
5690
5788
  };
5691
- store.dispatch(addUserFormSubmission(offlineResultWithoutFiles));
5789
+ store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
5692
5790
  void promise.then((result) => {
5693
- store.dispatch(addUserFormSubmission(result));
5791
+ store.dispatch(updateOrCreateUserFormSubmission(result));
5694
5792
  return result;
5695
5793
  }).catch(() => {
5696
5794
  store.dispatch(deleteUserFormSubmission(payload.offline_id));
@@ -5698,6 +5796,30 @@ class UserFormSubmissionService extends BaseApiService {
5698
5796
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
5699
5797
  return [fullOfflineResult, settledPromise];
5700
5798
  }
5799
+ update(submission) {
5800
+ const { store } = this.client;
5801
+ const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
5802
+ if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
5803
+ throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
5804
+ }
5805
+ const attachFilesPromises = this.getAttachFilesPromises(files, submission);
5806
+ const fullResult = {
5807
+ ...payloadWithoutFiles,
5808
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
5809
+ };
5810
+ store.dispatch(updateOrCreateUserFormSubmission(fullResult));
5811
+ const promise = this.enqueueRequest({
5812
+ description: "Patch form submission",
5813
+ method: HttpMethod.PATCH,
5814
+ url: `/forms/submissions/${submission.offline_id}/`,
5815
+ payload: fullResult,
5816
+ blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
5817
+ (x) => x !== void 0
5818
+ ),
5819
+ blocks: [fullResult.offline_id]
5820
+ });
5821
+ return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
5822
+ }
5701
5823
  async delete(submissionId) {
5702
5824
  const { store } = this.client;
5703
5825
  const state = store.getState();
@@ -5713,7 +5835,7 @@ class UserFormSubmissionService extends BaseApiService {
5713
5835
  });
5714
5836
  } catch (e) {
5715
5837
  if (submission) {
5716
- store.dispatch(addUserFormSubmission(submission));
5838
+ store.dispatch(updateOrCreateUserFormSubmission(submission));
5717
5839
  }
5718
5840
  throw e;
5719
5841
  }
@@ -6223,19 +6345,19 @@ const OvermapProvider = (props) => {
6223
6345
  }
6224
6346
  return /* @__PURE__ */ jsx(OvermapContext.Provider, { value: null, children: ret });
6225
6347
  };
6226
- const description$2 = "_description_p31lm_1";
6227
- const floatingButtonContainer$2 = "_floatingButtonContainer_p31lm_5";
6228
- const FullScreenImageContainer$2 = "_FullScreenImageContainer_p31lm_12";
6229
- const TopBarContainer$2 = "_TopBarContainer_p31lm_22";
6230
- const fileName$2 = "_fileName_p31lm_30";
6231
- const longIconButton$2 = "_longIconButton_p31lm_35";
6232
- const previewImage$3 = "_previewImage_p31lm_41";
6233
- const FullScreenImage$2 = "_FullScreenImage_p31lm_12";
6234
- const tabsList = "_tabsList_p31lm_60";
6235
- const tabTrigger = "_tabTrigger_p31lm_68";
6236
- const patchfieldBorder = "_patchfieldBorder_p31lm_72";
6237
- const title = "_title_p31lm_72";
6238
- const error = "_error_p31lm_88";
6348
+ const description$2 = "_description_1w0fq_1";
6349
+ const floatingButtonContainer$2 = "_floatingButtonContainer_1w0fq_5";
6350
+ const FullScreenImageContainer$2 = "_FullScreenImageContainer_1w0fq_12";
6351
+ const TopBarContainer$2 = "_TopBarContainer_1w0fq_22";
6352
+ const fileName$2 = "_fileName_1w0fq_31";
6353
+ const longIconButton$2 = "_longIconButton_1w0fq_36";
6354
+ const previewImage$3 = "_previewImage_1w0fq_42";
6355
+ const FullScreenImage$2 = "_FullScreenImage_1w0fq_12";
6356
+ const tabsList = "_tabsList_1w0fq_61";
6357
+ const tabTrigger = "_tabTrigger_1w0fq_69";
6358
+ const patchfieldBorder = "_patchfieldBorder_1w0fq_73";
6359
+ const title = "_title_1w0fq_73";
6360
+ const error = "_error_1w0fq_89";
6239
6361
  const styles$7 = {
6240
6362
  description: description$2,
6241
6363
  floatingButtonContainer: floatingButtonContainer$2,
@@ -6349,14 +6471,14 @@ class BaseField extends BaseFormElement {
6349
6471
  }
6350
6472
  __publicField(BaseField, "fieldTypeName");
6351
6473
  __publicField(BaseField, "fieldTypeDescription");
6352
- const description$1 = "_description_1kceu_1";
6353
- const floatingButtonContainer$1 = "_floatingButtonContainer_1kceu_5";
6354
- const FullScreenImageContainer$1 = "_FullScreenImageContainer_1kceu_12";
6355
- const TopBarContainer$1 = "_TopBarContainer_1kceu_22";
6356
- const fileName$1 = "_fileName_1kceu_30";
6357
- const longIconButton$1 = "_longIconButton_1kceu_35";
6358
- const previewImage$2 = "_previewImage_1kceu_41";
6359
- const FullScreenImage$1 = "_FullScreenImage_1kceu_12";
6474
+ const description$1 = "_description_10o76_1";
6475
+ const floatingButtonContainer$1 = "_floatingButtonContainer_10o76_5";
6476
+ const FullScreenImageContainer$1 = "_FullScreenImageContainer_10o76_12";
6477
+ const TopBarContainer$1 = "_TopBarContainer_10o76_22";
6478
+ const fileName$1 = "_fileName_10o76_31";
6479
+ const longIconButton$1 = "_longIconButton_10o76_36";
6480
+ const previewImage$2 = "_previewImage_10o76_42";
6481
+ const FullScreenImage$1 = "_FullScreenImage_10o76_12";
6360
6482
  const styles$6 = {
6361
6483
  description: description$1,
6362
6484
  floatingButtonContainer: floatingButtonContainer$1,
@@ -7618,15 +7740,15 @@ function withBreakpoints(value, classPrefix = "", valueMap) {
7618
7740
  }
7619
7741
  return classes.join(" ");
7620
7742
  }
7621
- const paddingValues = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
7743
+ const paddingValues$1 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
7622
7744
  const paddingPropDefs = {
7623
- p: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7624
- px: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7625
- py: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7626
- pt: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7627
- pr: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7628
- pb: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7629
- pl: { type: "enum", values: paddingValues, default: void 0, responsive: true }
7745
+ p: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7746
+ px: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7747
+ py: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7748
+ pt: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7749
+ pr: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7750
+ pb: { type: "enum", values: paddingValues$1, default: void 0, responsive: true },
7751
+ pl: { type: "enum", values: paddingValues$1, default: void 0, responsive: true }
7630
7752
  };
7631
7753
  function extractPaddingProps(props) {
7632
7754
  const { p = layoutPropDefs.p.default, px = layoutPropDefs.px.default, py = layoutPropDefs.py.default, pt = layoutPropDefs.pt.default, pr = layoutPropDefs.pr.default, pb = layoutPropDefs.pb.default, pl = layoutPropDefs.pl.default, ...rest } = props;
@@ -7767,6 +7889,26 @@ const flexPropDefs = {
7767
7889
  wrap: { type: "enum", values: wrapValues, default: void 0, responsive: true },
7768
7890
  gap: { type: "enum", values: gapValues, default: void 0, responsive: true }
7769
7891
  };
7892
+ const sides = ["all", "x", "y", "top", "bottom", "left", "right"];
7893
+ const clipValues = ["border-box", "padding-box"];
7894
+ const paddingValues = ["current", "0"];
7895
+ const insetPropDefs = {
7896
+ side: { type: "enum", values: sides, default: "all", responsive: true },
7897
+ clip: { type: "enum", values: clipValues, default: "border-box", responsive: true },
7898
+ p: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7899
+ px: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7900
+ py: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7901
+ pt: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7902
+ pr: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7903
+ pb: { type: "enum", values: paddingValues, default: void 0, responsive: true },
7904
+ pl: { type: "enum", values: paddingValues, default: void 0, responsive: true }
7905
+ };
7906
+ const Inset = React.forwardRef((props, forwardedRef) => {
7907
+ const { rest: marginRest, ...marginProps } = extractMarginProps(props);
7908
+ const { className, side = insetPropDefs.side.default, clip = insetPropDefs.clip.default, p, px, py, pt, pr, pb, pl, ...insetProps } = marginRest;
7909
+ return React.createElement("div", { ...insetProps, ref: forwardedRef, className: classNames("rt-Inset", className, withBreakpoints(side, "rt-r-side"), withBreakpoints(clip, "rt-r-clip"), withBreakpoints(p, "rt-r-p"), withBreakpoints(px, "rt-r-px"), withBreakpoints(py, "rt-r-py"), withBreakpoints(pt, "rt-r-pt"), withBreakpoints(pr, "rt-r-pr"), withBreakpoints(pb, "rt-r-pb"), withBreakpoints(pl, "rt-r-pl"), withMarginProps(marginProps)) });
7910
+ });
7911
+ Inset.displayName = "Inset";
7770
7912
  const sizes$4 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
7771
7913
  const headingPropDefs = {
7772
7914
  size: { type: "enum", values: sizes$4, default: "6", responsive: true },
@@ -9058,21 +9200,10 @@ const findFieldByIdentifier = (fields, identifier) => {
9058
9200
  const makeConditionalSourceFields = (sections, index2) => {
9059
9201
  return sections.filter((_, i) => i < index2).flatMap((field) => field.fields);
9060
9202
  };
9061
- const getTakenFieldLabels = (fields) => {
9062
- return fields.flatMap((field) => [...field.fields.map((f) => f.label), field.label]).filter((id) => id !== null);
9063
- };
9064
- const incrementFieldLabel = (label, takenLabels) => {
9065
- let count = 1;
9066
- let newLabel = `${label} (${count})`;
9067
- while (takenLabels.includes(newLabel)) {
9068
- newLabel = `${label} (${++count})`;
9069
- }
9070
- return newLabel;
9071
- };
9072
- const createNewField = (parentPath, index2, initialValues2, values, setFieldValue) => {
9073
- const { label } = initialValues2;
9203
+ const createNewField = (parentPath, index2, initialValues, values, setFieldValue) => {
9204
+ const { label } = initialValues;
9074
9205
  const newField = {
9075
- ...initialValues2,
9206
+ ...initialValues,
9076
9207
  identifier: makeIdentifier(null, label)
9077
9208
  };
9078
9209
  const parent = get(values, parentPath);
@@ -9086,11 +9217,11 @@ const createNewField = (parentPath, index2, initialValues2, values, setFieldValu
9086
9217
  void setFieldValue(parentPath, updatedFields).then();
9087
9218
  };
9088
9219
  const createNewEmptySection = (index2, values, setFieldValue) => {
9089
- const initialValues2 = {
9220
+ const initialValues = {
9090
9221
  ...emptySection(),
9091
9222
  label: ""
9092
9223
  };
9093
- createNewField("fields", index2, initialValues2, values, setFieldValue);
9224
+ createNewField("fields", index2, initialValues, values, setFieldValue);
9094
9225
  };
9095
9226
  const useFieldReordering = () => {
9096
9227
  const { showError } = useToast();
@@ -9568,14 +9699,18 @@ class FieldInputClonerField extends CustomField {
9568
9699
  super(options, FieldInputCloner);
9569
9700
  }
9570
9701
  }
9571
- const previewImage$1 = "_previewImage_ebhyt_1";
9572
- const nameContainer = "_nameContainer_ebhyt_9";
9573
- const hasPreview = "_hasPreview_ebhyt_14";
9574
- const useEllipsis = "_useEllipsis_ebhyt_19";
9702
+ const displayFileContainer = "_displayFileContainer_1vdfw_1";
9703
+ const infoContainer = "_infoContainer_1vdfw_6";
9704
+ const previewImage$1 = "_previewImage_1vdfw_10";
9705
+ const fileSizeText = "_fileSizeText_1vdfw_19";
9706
+ const nameContainer = "_nameContainer_1vdfw_24";
9707
+ const useEllipsis = "_useEllipsis_1vdfw_28";
9575
9708
  const styles$4 = {
9709
+ displayFileContainer,
9710
+ infoContainer,
9576
9711
  previewImage: previewImage$1,
9712
+ fileSizeText,
9577
9713
  nameContainer,
9578
- hasPreview,
9579
9714
  useEllipsis
9580
9715
  };
9581
9716
  const convertBytesToLargestUnit = (bytes) => {
@@ -9717,46 +9852,8 @@ const DisplayFile = memo((props) => {
9717
9852
  },
9718
9853
  [name, resolvedFile]
9719
9854
  );
9720
- return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: { initial: "column", sm: "row" }, gap: "3", justify: "between", children: [
9721
- /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: "3", align: "center", grow: "1", shrink: "0", children: [
9722
- /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
9723
- /* @__PURE__ */ jsx(
9724
- IconButton,
9725
- {
9726
- variant: "soft",
9727
- "aria-label": `Download ${name}`,
9728
- onClick: handleDownload,
9729
- disabled: !resolvedFile,
9730
- children: /* @__PURE__ */ jsx(DownloadIcon, {})
9731
- }
9732
- ),
9733
- /* @__PURE__ */ jsx(
9734
- IconButton,
9735
- {
9736
- severity: "info",
9737
- variant: "soft",
9738
- "aria-label": `Remove ${name}`,
9739
- disabled,
9740
- onClick: onRemove,
9741
- children: /* @__PURE__ */ jsx(Cross1Icon, {})
9742
- }
9743
- )
9744
- ] }),
9745
- /* @__PURE__ */ jsxs(
9746
- Flex,
9747
- {
9748
- className: classNames$1(styles$4.nameContainer, { [styles$4.hasPreview]: !!url }),
9749
- direction: "column",
9750
- gap: "1",
9751
- children: [
9752
- /* @__PURE__ */ jsx(Text, { className: styles$4.useEllipsis, children: name }),
9753
- /* @__PURE__ */ jsx(Text, { size: "1", children: size }),
9754
- error2 && /* @__PURE__ */ jsx(Text, { size: "1", severity: "danger", children: error2 })
9755
- ]
9756
- }
9757
- )
9758
- ] }),
9759
- url && /* @__PURE__ */ jsxs(Fragment, { children: [
9855
+ return /* @__PURE__ */ jsxs(Card, { className: styles$4.displayFileContainer, size: "1", children: [
9856
+ /* @__PURE__ */ jsx(Inset, { clip: "border-box", side: "top", pb: "0", children: url && /* @__PURE__ */ jsxs(Fragment, { children: [
9760
9857
  /* @__PURE__ */ jsx(
9761
9858
  "img",
9762
9859
  {
@@ -9777,8 +9874,38 @@ const DisplayFile = memo((props) => {
9777
9874
  setShowPreview
9778
9875
  }
9779
9876
  )
9780
- ] })
9781
- ] }) });
9877
+ ] }) }),
9878
+ /* @__PURE__ */ jsx(Flex, { className: styles$4.infoContainer, children: /* @__PURE__ */ jsxs(Flex, { align: "center", width: "100%", children: [
9879
+ /* @__PURE__ */ jsxs(Flex, { className: styles$4.nameContainer, align: "center", gap: "1", grow: "1", children: [
9880
+ /* @__PURE__ */ jsx(Text, { className: styles$4.useEllipsis, size: "1", children: name }),
9881
+ /* @__PURE__ */ jsx(Text, { size: "1", className: styles$4.fileSizeText, children: `(${size})` }),
9882
+ error2 && /* @__PURE__ */ jsx(Text, { size: "1", severity: "danger", children: error2 })
9883
+ ] }),
9884
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "2", children: [
9885
+ /* @__PURE__ */ jsx(
9886
+ IconButton,
9887
+ {
9888
+ variant: "ghost",
9889
+ "aria-label": `Download ${name}`,
9890
+ onClick: handleDownload,
9891
+ disabled: !resolvedFile,
9892
+ children: /* @__PURE__ */ jsx(DownloadIcon, {})
9893
+ }
9894
+ ),
9895
+ /* @__PURE__ */ jsx(
9896
+ IconButton,
9897
+ {
9898
+ severity: "info",
9899
+ variant: "ghost",
9900
+ "aria-label": `Remove ${name}`,
9901
+ disabled,
9902
+ onClick: onRemove,
9903
+ children: /* @__PURE__ */ jsx(Cross1Icon, {})
9904
+ }
9905
+ )
9906
+ ] })
9907
+ ] }) })
9908
+ ] });
9782
9909
  });
9783
9910
  DisplayFile.displayName = "DisplayFile";
9784
9911
  const emptyUploadField = {
@@ -10201,10 +10328,12 @@ const initialFormValues = (fields, values) => {
10201
10328
  };
10202
10329
  const useAttachImagesToFormRevisionFields = (revision) => {
10203
10330
  const { sdk } = useSDK();
10204
- const attachments = useAppSelector(selectRevisionAttachments(revision.offline_id));
10331
+ const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
10205
10332
  return useMemo(() => {
10333
+ if (!revision || !attachments)
10334
+ return revision;
10206
10335
  const revisionCopy = structuredClone(revision);
10207
- for (const attachment of attachments ?? []) {
10336
+ for (const attachment of attachments) {
10208
10337
  const filePromise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
10209
10338
  let sectionIndex = -1;
10210
10339
  let fieldIndex = -1;
@@ -10236,7 +10365,8 @@ const FormRenderer = memo(
10236
10365
  // if the title isn't provided, hide it by default
10237
10366
  hideTitle = !schema.title,
10238
10367
  hideDescription,
10239
- className
10368
+ className,
10369
+ buttonProps
10240
10370
  } = props;
10241
10371
  const { readonly } = schema.meta;
10242
10372
  const formId2 = useMemo(() => crypto.randomUUID(), []);
@@ -10271,8 +10401,8 @@ const FormRenderer = memo(
10271
10401
  ] }) }),
10272
10402
  inputs,
10273
10403
  !readonly && /* @__PURE__ */ jsxs(Flex, { className: styles$6.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
10274
- cancelText && /* @__PURE__ */ jsx(Button, { type: "button", variant: "solid", onClick: onCancel, children: cancelText }),
10275
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !formik.isValid, children: submitText })
10404
+ cancelText && /* @__PURE__ */ jsx(Button, { severity: "info", ...buttonProps, type: "button", onClick: onCancel, children: cancelText }),
10405
+ /* @__PURE__ */ jsx(Button, { ...buttonProps, type: "submit", disabled: !formik.isValid, children: submitText })
10276
10406
  ] })
10277
10407
  ] }) }) });
10278
10408
  })
@@ -10288,6 +10418,9 @@ const FormSubmissionViewer = memo(
10288
10418
  );
10289
10419
  }
10290
10420
  const revisionWithImages = useAttachImagesToFormRevisionFields(revision);
10421
+ if (!revisionWithImages) {
10422
+ throw new Error("Expected revisionWithImages to be defined");
10423
+ }
10291
10424
  const schema = useMemo(() => {
10292
10425
  return formRevisionToSchema(revisionWithImages, { readonly: true });
10293
10426
  }, [revisionWithImages]);
@@ -10344,6 +10477,10 @@ const FormBrowser = memo(
10344
10477
  }, [filter, maxResults, ownerFilter]);
10345
10478
  const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
10346
10479
  const userFormMapping = useAppSelector(selectUserFormMapping);
10480
+ const attachableUserForms = userForms.filter((form) => !form.component_type);
10481
+ const attachableUserFormMapping = Object.values(userFormMapping).filter(
10482
+ (form) => !form.component_type
10483
+ );
10347
10484
  const handleToggleFavorite = useCallback(
10348
10485
  (form) => {
10349
10486
  if (form.favorite) {
@@ -10357,7 +10494,7 @@ const FormBrowser = memo(
10357
10494
  const options = useMemo(() => {
10358
10495
  const state = sdk.store.getState();
10359
10496
  const accumulator = {};
10360
- for (const form of Object.values(userFormMapping)) {
10497
+ for (const form of attachableUserFormMapping) {
10361
10498
  const organization = selectOrganization(form.owner_organization || -1)(state);
10362
10499
  if (organization) {
10363
10500
  accumulator[`${orgOptionPrefix}${organization.id}`] = organization.name;
@@ -10368,13 +10505,13 @@ const FormBrowser = memo(
10368
10505
  }
10369
10506
  }
10370
10507
  return Object.entries(accumulator).map(([value, label]) => ({ itemContent: label, value }));
10371
- }, [userFormMapping, sdk.store]);
10508
+ }, [sdk.store, attachableUserFormMapping]);
10372
10509
  const handleChange = useCallback((e) => {
10373
10510
  setFilter(e.currentTarget.value);
10374
10511
  }, []);
10375
- const numberOfForms = useAppSelector(selectNumberOfUserForms) || 0;
10376
- const numberOfHiddenForms = numberOfForms - userForms.length;
10377
- const overflowMessage = userForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
10512
+ const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
10513
+ const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
10514
+ const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
10378
10515
  return /* @__PURE__ */ jsxs(Flex, { ref, direction: "column", gap: "2", children: [
10379
10516
  /* @__PURE__ */ jsxs(Flex, { gap: "2", grow: "1", children: [
10380
10517
  /* @__PURE__ */ jsx(Box, { grow: "1", asChild: true, children: /* @__PURE__ */ jsx(TextField$1.Root, { size: "3", children: /* @__PURE__ */ jsx(TextField$1.Input, { placeholder: "Filter", value: filter, onChange: handleChange }) }) }),
@@ -10389,7 +10526,7 @@ const FormBrowser = memo(
10389
10526
  }
10390
10527
  )
10391
10528
  ] }),
10392
- userForms.length > 0 && /* @__PURE__ */ jsx(ButtonList.Root, { children: userForms.map((form) => /* @__PURE__ */ jsx(
10529
+ attachableUserForms.length > 0 && /* @__PURE__ */ jsx(ButtonList.Root, { children: attachableUserForms.map((form) => /* @__PURE__ */ jsx(
10393
10530
  FormBrowserEntry,
10394
10531
  {
10395
10532
  ...entryProps,
@@ -10461,7 +10598,7 @@ const styles$2 = {
10461
10598
  submissionsContainer,
10462
10599
  stopHorizontalOverflow
10463
10600
  };
10464
- const FormSubmissionBrowserEntry = memo(function FormSubmissionBrowserEntry2(props) {
10601
+ const FormSubmissionBrowserEntry = memo((props) => {
10465
10602
  var _a2;
10466
10603
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
10467
10604
  const currentUser = useAppSelector(selectCurrentUser);
@@ -10505,11 +10642,12 @@ const FormSubmissionBrowserEntry = memo(function FormSubmissionBrowserEntry2(pro
10505
10642
  }
10506
10643
  return row;
10507
10644
  });
10645
+ FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
10508
10646
  const getCreatedAtOrSubmittedAtDate = (submission) => {
10509
10647
  const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
10510
10648
  return new Date(date);
10511
10649
  };
10512
- const FormSubmissionBrowser = memo(function FormSubmissionBrowser2(props) {
10650
+ const FormSubmissionBrowser = memo((props) => {
10513
10651
  const {
10514
10652
  formId: formId2,
10515
10653
  submissions: propSubmissions,
@@ -10555,6 +10693,7 @@ const FormSubmissionBrowser = memo(function FormSubmissionBrowser2(props) {
10555
10693
  }
10556
10694
  );
10557
10695
  });
10696
+ FormSubmissionBrowser.displayName = "FormSubmissionBrowser";
10558
10697
  const PatchField = memo((props) => {
10559
10698
  const { name, render } = props;
10560
10699
  const { submitForm } = useFormikContext();
@@ -10578,19 +10717,19 @@ PatchField.displayName = "PatchField";
10578
10717
  const PatchFormProvider = memo(
10579
10718
  forwardRef((props, ref) => {
10580
10719
  const { children, schema, values, onPatch, onError, requiresDiff = true, onDirtyChange, ...rest } = props;
10581
- const initialValues2 = useMemo(() => initialFormValues(schema.fields, values), [schema.fields, values]);
10720
+ const initialValues = useMemo(() => initialFormValues(schema.fields, values), [schema.fields, values]);
10582
10721
  const getDiff = useCallback(
10583
10722
  (values2) => {
10584
10723
  const diff = {};
10585
10724
  for (const key in values2) {
10586
10725
  const value = values2[key];
10587
- if (value !== initialValues2[key] && value !== void 0) {
10726
+ if (value !== initialValues[key] && value !== void 0) {
10588
10727
  diff[key] = value;
10589
10728
  }
10590
10729
  }
10591
10730
  return diff;
10592
10731
  },
10593
- [initialValues2]
10732
+ [initialValues]
10594
10733
  );
10595
10734
  const handlePatch = useCallback(
10596
10735
  (values2) => {
@@ -10616,7 +10755,7 @@ const PatchFormProvider = memo(
10616
10755
  [schema, onDirtyChange, onError, getDiff]
10617
10756
  );
10618
10757
  const formik = useFormik({
10619
- initialValues: initialValues2,
10758
+ initialValues,
10620
10759
  onSubmit: handlePatch,
10621
10760
  validate,
10622
10761
  // only validate the entire form on submit
@@ -10634,9 +10773,9 @@ const PatchFormProvider = memo(
10634
10773
  const { errors, resetForm } = formik;
10635
10774
  useEffect(() => {
10636
10775
  if (hasKeys(errors)) {
10637
- resetForm({ values: initialValues2, errors: {} });
10776
+ resetForm({ values: initialValues, errors: {} });
10638
10777
  }
10639
- }, [errors, initialValues2, resetForm]);
10778
+ }, [errors, initialValues, resetForm]);
10640
10779
  return /* @__PURE__ */ jsx(FormikProvider, { value: formik, children: /* @__PURE__ */ jsx("form", { ...rest, ref, onSubmit: formik.handleSubmit, onChange: handleChange, children }) });
10641
10780
  })
10642
10781
  );
@@ -10744,21 +10883,21 @@ const FieldActions = memo((props) => {
10744
10883
  ] });
10745
10884
  });
10746
10885
  FieldActions.displayName = "FieldActions";
10747
- const description = "_description_o5qyx_1";
10748
- const floatingButtonContainer = "_floatingButtonContainer_o5qyx_5";
10749
- const FullScreenImageContainer = "_FullScreenImageContainer_o5qyx_12";
10750
- const TopBarContainer = "_TopBarContainer_o5qyx_22";
10751
- const fileName = "_fileName_o5qyx_30";
10752
- const longIconButton = "_longIconButton_o5qyx_35";
10753
- const previewImage = "_previewImage_o5qyx_41";
10754
- const FullScreenImage = "_FullScreenImage_o5qyx_12";
10755
- const popoverInputsContainer = "_popoverInputsContainer_o5qyx_60";
10756
- const imageContainer = "_imageContainer_o5qyx_64";
10757
- const deleteImageButton = "_deleteImageButton_o5qyx_69";
10758
- const typeBadge = "_typeBadge_o5qyx_80";
10759
- const previewInput = "_previewInput_o5qyx_85";
10760
- const directInput = "_directInput_o5qyx_89";
10761
- const grow = "_grow_o5qyx_94";
10886
+ const description = "_description_6795p_1";
10887
+ const floatingButtonContainer = "_floatingButtonContainer_6795p_5";
10888
+ const FullScreenImageContainer = "_FullScreenImageContainer_6795p_12";
10889
+ const TopBarContainer = "_TopBarContainer_6795p_22";
10890
+ const fileName = "_fileName_6795p_31";
10891
+ const longIconButton = "_longIconButton_6795p_36";
10892
+ const previewImage = "_previewImage_6795p_42";
10893
+ const FullScreenImage = "_FullScreenImage_6795p_12";
10894
+ const popoverInputsContainer = "_popoverInputsContainer_6795p_61";
10895
+ const imageContainer = "_imageContainer_6795p_65";
10896
+ const deleteImageButton = "_deleteImageButton_6795p_70";
10897
+ const typeBadge = "_typeBadge_6795p_81";
10898
+ const previewInput = "_previewInput_6795p_86";
10899
+ const directInput = "_directInput_6795p_90";
10900
+ const grow = "_grow_6795p_95";
10762
10901
  const styles = {
10763
10902
  description,
10764
10903
  floatingButtonContainer,
@@ -10840,19 +10979,24 @@ const FieldBuilder = memo((props) => {
10840
10979
  const { parentPath, index: index2, initial, conditionalSourceFields } = props;
10841
10980
  const { values, setFieldValue, errors } = useFormikContext();
10842
10981
  const fieldTypeItems = useFieldTypeItems();
10982
+ const containerRef = useRef(null);
10843
10983
  const RADIX_SM_MIN_WIDTH = 576;
10844
- const [isLargeScreen, setIsLargeScreen] = useState(
10845
- window.matchMedia(`(min-width: ${RADIX_SM_MIN_WIDTH}px)`).matches
10984
+ const [isLargeContainer, setIsLargeContainer] = useState(
10985
+ containerRef.current && containerRef.current.getBoundingClientRect().width >= RADIX_SM_MIN_WIDTH
10846
10986
  );
10847
10987
  useEffect(() => {
10848
- const mediaQuery = window.matchMedia(`(min-width: ${RADIX_SM_MIN_WIDTH}px)`);
10849
- const handleMediaQueryChange = (event) => {
10850
- setIsLargeScreen(event.matches);
10851
- };
10852
- mediaQuery.addEventListener("change", handleMediaQueryChange);
10853
- return () => {
10854
- mediaQuery.removeEventListener("change", handleMediaQueryChange);
10855
- };
10988
+ const container = containerRef.current;
10989
+ if (container) {
10990
+ const observer = new ResizeObserver((entries) => {
10991
+ if (entries[0]) {
10992
+ setIsLargeContainer(entries[0].contentRect.width >= RADIX_SM_MIN_WIDTH);
10993
+ }
10994
+ });
10995
+ observer.observe(container);
10996
+ return () => {
10997
+ observer.disconnect();
10998
+ };
10999
+ }
10856
11000
  }, []);
10857
11001
  const [resolvedImage, setResolvedImage] = useState(void 0);
10858
11002
  const [showImagePreview, setShowImagePreview] = useState(false);
@@ -10929,7 +11073,7 @@ const FieldBuilder = memo((props) => {
10929
11073
  const fieldObject = fieldCls.getFieldCreationSchema(
10930
11074
  `${parentPath}.${index2}`
10931
11075
  );
10932
- if (isLargeScreen) {
11076
+ if (isLargeContainer) {
10933
11077
  directlyShownFields2 = [
10934
11078
  ...directlyShownFields2,
10935
11079
  ...fieldObject.filter((field) => field.showDirectly).map((field) => field.field)
@@ -10943,7 +11087,7 @@ const FieldBuilder = memo((props) => {
10943
11087
  }
10944
11088
  }
10945
11089
  return [directlyShownFields2, popoverFields2];
10946
- }, [fieldCls, conditionalSourceFields, parentPath, index2, isLargeScreen]);
11090
+ }, [fieldCls, conditionalSourceFields, parentPath, index2, isLargeContainer]);
10947
11091
  const directlyShownInputs = useFieldInputs(directlyShownFields, {
10948
11092
  formId,
10949
11093
  disabled: false,
@@ -10963,7 +11107,7 @@ const FieldBuilder = memo((props) => {
10963
11107
  });
10964
11108
  const deserializedField = useMemo(() => deserialize(initial), [initial]);
10965
11109
  const previewInput2 = useFieldInput(deserializedField, { formId, disabled: true, showInputOnly: true });
10966
- return /* @__PURE__ */ jsxs(Flex, { align: "center", grow: "1", children: [
11110
+ return /* @__PURE__ */ jsxs(Flex, { ref: containerRef, align: "center", grow: "1", children: [
10967
11111
  /* @__PURE__ */ jsxs(Flex, { direction: "column", width: "100%", children: [
10968
11112
  fieldCls === FieldSection && /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", children: [
10969
11113
  directlyShownFields.length > 0 && directlyShownInputs,
@@ -11042,7 +11186,7 @@ const FieldBuilder = memo((props) => {
11042
11186
  Input,
11043
11187
  {
11044
11188
  className: styles.grow,
11045
- placeholder: `Enter a ${type === "section" ? "section" : "field"} label`,
11189
+ placeholder: type === "section" ? "Enter a section label (optional)" : "Enter your question",
11046
11190
  value,
11047
11191
  onChange: (event) => {
11048
11192
  setValue(event.target.value);
@@ -11065,7 +11209,7 @@ const FieldBuilder = memo((props) => {
11065
11209
  TextArea,
11066
11210
  {
11067
11211
  className: styles.grow,
11068
- placeholder: `Enter a ${type === "section" ? "section" : "field"} description`,
11212
+ placeholder: `Enter a ${type === "section" ? "section" : "field"} description (optional)`,
11069
11213
  value,
11070
11214
  onChange: (event) => {
11071
11215
  setValue(event.target.value);
@@ -11085,7 +11229,7 @@ const FieldBuilder = memo((props) => {
11085
11229
  });
11086
11230
  FieldBuilder.displayName = "FieldBuilder";
11087
11231
  const FieldWithActions = memo((props) => {
11088
- const { field, index: index2, sectionIndex, takenLabels, remove: remove2 } = props;
11232
+ const { field, index: index2, sectionIndex, remove: remove2 } = props;
11089
11233
  const { setFieldValue, values } = useFormikContext();
11090
11234
  const { reorderField } = useFieldReordering();
11091
11235
  const { showError } = useToast();
@@ -11102,10 +11246,10 @@ const FieldWithActions = memo((props) => {
11102
11246
  const label = field.label ?? "Unlabelled field";
11103
11247
  const duplicatedField = {
11104
11248
  ...field,
11105
- label: incrementFieldLabel(label, takenLabels)
11249
+ label
11106
11250
  };
11107
11251
  createNewField(parentPath, index2 + 1, duplicatedField, values, setFieldValue);
11108
- }, [field, takenLabels, parentPath, index2, values, setFieldValue]);
11252
+ }, [field, parentPath, index2, values, setFieldValue]);
11109
11253
  const moveField = useCallback(
11110
11254
  (direction) => {
11111
11255
  const srcSectionIndex = sectionIndex;
@@ -11187,12 +11331,11 @@ const FieldWithActions = memo((props) => {
11187
11331
  FieldWithActions.displayName = "FieldWithActions";
11188
11332
  const FieldSectionWithActions = memo((props) => {
11189
11333
  var _a2;
11190
- const { field, index: sectionIndex, dropState } = props;
11334
+ const { field, index: sectionIndex, dropState, fieldsOnly } = props;
11191
11335
  const isDropDisabled = (_a2 = dropState[field.identifier]) == null ? void 0 : _a2.disabled;
11192
11336
  const { setFieldValue, values } = useFormikContext();
11193
11337
  const alertDialog = useAlertDialog();
11194
11338
  const { reorderSection } = useFieldReordering();
11195
- const takenFieldLabels = getTakenFieldLabels(values.fields);
11196
11339
  const removeSectionConditions = useCallback(
11197
11340
  (sectionsToUpdate, allSections) => {
11198
11341
  for (const section of sectionsToUpdate) {
@@ -11296,18 +11439,15 @@ const FieldSectionWithActions = memo((props) => {
11296
11439
  );
11297
11440
  const duplicateSection = useCallback(() => {
11298
11441
  const fieldLabel = field.label ?? "Untitled section";
11299
- const newSectionLabel = incrementFieldLabel(fieldLabel, takenFieldLabels);
11300
- const newFields = field.fields.map((f) => {
11301
- const newLabel = incrementFieldLabel(f.label, takenFieldLabels);
11442
+ const newFields = field.fields.map((oldField) => {
11302
11443
  return {
11303
- ...f,
11304
- label: newLabel,
11305
- identifier: makeIdentifier(null, newLabel)
11444
+ ...oldField,
11445
+ identifier: makeIdentifier(null, oldField.label)
11306
11446
  };
11307
11447
  });
11308
- const duplicatedField = { ...field, label: newSectionLabel, fields: newFields };
11448
+ const duplicatedField = { ...field, label: fieldLabel, fields: newFields };
11309
11449
  createNewField("fields", sectionIndex + 1, duplicatedField, values, setFieldValue);
11310
- }, [field, takenFieldLabels, sectionIndex, values, setFieldValue]);
11450
+ }, [field, sectionIndex, values, setFieldValue]);
11311
11451
  const handleCreateField = useCallback(
11312
11452
  (type) => {
11313
11453
  createNewField(
@@ -11331,7 +11471,7 @@ const FieldSectionWithActions = memo((props) => {
11331
11471
  mb: "4",
11332
11472
  children: /* @__PURE__ */ jsxs(Flex, { gap: "3", justify: "between", align: "center", children: [
11333
11473
  /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", grow: "1", children: [
11334
- /* @__PURE__ */ jsx(FieldBuilder, { ...editSectionProps }),
11474
+ !fieldsOnly && /* @__PURE__ */ jsx(FieldBuilder, { ...editSectionProps }),
11335
11475
  /* @__PURE__ */ jsx(
11336
11476
  Droppable,
11337
11477
  {
@@ -11354,8 +11494,7 @@ const FieldSectionWithActions = memo((props) => {
11354
11494
  sectionIndex,
11355
11495
  remove: () => {
11356
11496
  removeField(i);
11357
- },
11358
- takenLabels: takenFieldLabels
11497
+ }
11359
11498
  },
11360
11499
  child.identifier
11361
11500
  )),
@@ -11376,7 +11515,7 @@ const FieldSectionWithActions = memo((props) => {
11376
11515
  }
11377
11516
  )
11378
11517
  ] }),
11379
- /* @__PURE__ */ jsx(
11518
+ !fieldsOnly && /* @__PURE__ */ jsx(
11380
11519
  FieldActions,
11381
11520
  {
11382
11521
  index: sectionIndex,
@@ -11453,7 +11592,8 @@ const findSection = (fields, sectionId) => {
11453
11592
  return [section, i];
11454
11593
  }
11455
11594
  };
11456
- const FieldsEditor = memo(() => {
11595
+ const FieldsEditor = memo((props) => {
11596
+ const { fieldsOnly } = props;
11457
11597
  const { values, setFieldValue } = useFormikContext();
11458
11598
  const [dropState, dispatch] = useReducer(reducer, values.fields, initializer);
11459
11599
  const { reorderSection, reorderField } = useFieldReordering();
@@ -11506,8 +11646,16 @@ const FieldsEditor = memo(() => {
11506
11646
  gap: "0",
11507
11647
  children: [
11508
11648
  values.fields.map((field, index2) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
11509
- /* @__PURE__ */ jsx(FieldSectionWithActions, { field, index: index2, dropState }),
11510
- /* @__PURE__ */ jsxs(
11649
+ /* @__PURE__ */ jsx(
11650
+ FieldSectionWithActions,
11651
+ {
11652
+ field,
11653
+ index: index2,
11654
+ dropState,
11655
+ fieldsOnly
11656
+ }
11657
+ ),
11658
+ !fieldsOnly && /* @__PURE__ */ jsxs(
11511
11659
  Button,
11512
11660
  {
11513
11661
  className: styles$1.addSectionButton,
@@ -11530,17 +11678,22 @@ const FieldsEditor = memo(() => {
11530
11678
  ) }) });
11531
11679
  });
11532
11680
  FieldsEditor.displayName = "FieldsEditor";
11533
- const initialValues = {
11534
- title: "",
11535
- description: "",
11536
- fields: [{ ...emptySection(makeIdentifier(null, "")), label: "" }]
11537
- };
11538
11681
  const previewSubmit = () => {
11539
11682
  alert("This is a form preview, your data will not be saved.");
11540
11683
  };
11541
11684
  const FormBuilder = memo(
11542
11685
  forwardRef((props, ref) => {
11543
- const { onCancel, onSave, revision } = props;
11686
+ const {
11687
+ onCancel,
11688
+ onSave,
11689
+ revision,
11690
+ initialTitle,
11691
+ showExplainerText = true,
11692
+ showFormTitle = true,
11693
+ fieldsOnly = false,
11694
+ showTabs = true,
11695
+ tabsListClassName
11696
+ } = props;
11544
11697
  const { showError } = useToast();
11545
11698
  const validate = useCallback(
11546
11699
  (form) => {
@@ -11586,8 +11739,17 @@ const FormBuilder = memo(
11586
11739
  },
11587
11740
  [showError]
11588
11741
  );
11742
+ const initialValues = useMemo(
11743
+ () => ({
11744
+ title: initialTitle ?? "",
11745
+ description: "",
11746
+ fields: [{ ...emptySection(makeIdentifier(null, "")), label: "" }]
11747
+ }),
11748
+ [initialTitle]
11749
+ );
11750
+ const revisionWithImages = useAttachImagesToFormRevisionFields(revision);
11589
11751
  const formik = useFormik({
11590
- initialValues: wrapRootFieldsWithFieldSection(revision) ?? initialValues,
11752
+ initialValues: wrapRootFieldsWithFieldSection(revisionWithImages) ?? initialValues,
11591
11753
  validate,
11592
11754
  onSubmit: onSave,
11593
11755
  validateOnChange: false,
@@ -11595,7 +11757,7 @@ const FormBuilder = memo(
11595
11757
  });
11596
11758
  const previewSchema = useMemo(() => formRevisionToSchema(formik.values), [formik.values]);
11597
11759
  return /* @__PURE__ */ jsx(Tabs.Root, { ref, defaultValue: "edit", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
11598
- /* @__PURE__ */ jsxs(Tabs.List, { className: styles$7.tabsList, children: [
11760
+ showTabs && /* @__PURE__ */ jsxs(Tabs.List, { className: classNames$1(styles$7.tabsList, tabsListClassName), children: [
11599
11761
  /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$7.tabTrigger, value: "edit", children: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "2", children: [
11600
11762
  /* @__PURE__ */ jsx(Pencil1Icon, {}),
11601
11763
  "Edit"
@@ -11606,7 +11768,7 @@ const FormBuilder = memo(
11606
11768
  ] }) })
11607
11769
  ] }),
11608
11770
  /* @__PURE__ */ jsxs(Tabs.Content, { value: "edit", children: [
11609
- /* @__PURE__ */ jsxs(Text, { children: [
11771
+ showExplainerText && /* @__PURE__ */ jsxs(Text, { children: [
11610
11772
  "Create your form using various field types. Sections can be",
11611
11773
  " ",
11612
11774
  /* @__PURE__ */ jsx("strong", { children: "conditionally rendered" }),
@@ -11616,60 +11778,62 @@ const FormBuilder = memo(
11616
11778
  ] }),
11617
11779
  /* @__PURE__ */ jsx(Flex, { asChild: true, direction: "column", gap: "2", mt: "3", children: /* @__PURE__ */ jsxs("form", { id: formId, onSubmit: formik.handleSubmit, children: [
11618
11780
  /* @__PURE__ */ jsxs(FormikProvider, { value: formik, children: [
11619
- /* @__PURE__ */ jsx(
11620
- PatchField,
11621
- {
11622
- name: "title",
11623
- render: ({ setValue, value, meta }) => /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: meta.error ?? null, children: /* @__PURE__ */ jsx(
11624
- Input,
11625
- {
11626
- className: classNames$1(styles$7.title, {
11627
- [styles$7.error]: meta.error
11628
- }),
11629
- placeholder: "Form title",
11630
- value,
11631
- onChange: (event) => {
11632
- setValue(event.target.value);
11633
- },
11634
- maxLength: 100,
11635
- showInputLength: false,
11636
- variant: "ghost",
11637
- size: "large"
11638
- }
11639
- ) })
11640
- }
11641
- ),
11642
- /* @__PURE__ */ jsx(
11643
- PatchField,
11644
- {
11645
- name: "description",
11646
- render: ({ setValue, value }) => /* @__PURE__ */ jsx(
11647
- TextArea,
11648
- {
11649
- className: styles$7.description,
11650
- placeholder: "Explain the purpose of this form",
11651
- value,
11652
- onChange: (event) => {
11653
- setValue(event.target.value);
11654
- },
11655
- resize: "vertical",
11656
- maxLength: 1e3,
11657
- showInputLength: false,
11658
- variant: "ghost"
11659
- }
11660
- )
11661
- }
11662
- ),
11663
- /* @__PURE__ */ jsx(FieldsEditor, {}),
11781
+ showFormTitle && /* @__PURE__ */ jsxs(Fragment, { children: [
11782
+ /* @__PURE__ */ jsx(
11783
+ PatchField,
11784
+ {
11785
+ name: "title",
11786
+ render: ({ setValue, value, meta }) => /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: meta.error ?? null, children: /* @__PURE__ */ jsx(
11787
+ Input,
11788
+ {
11789
+ className: classNames$1(styles$7.title, {
11790
+ [styles$7.error]: meta.error
11791
+ }),
11792
+ placeholder: "Form title",
11793
+ value,
11794
+ onChange: (event) => {
11795
+ setValue(event.target.value);
11796
+ },
11797
+ maxLength: 100,
11798
+ showInputLength: false,
11799
+ variant: "ghost",
11800
+ size: "large"
11801
+ }
11802
+ ) })
11803
+ }
11804
+ ),
11805
+ /* @__PURE__ */ jsx(
11806
+ PatchField,
11807
+ {
11808
+ name: "description",
11809
+ render: ({ setValue, value }) => /* @__PURE__ */ jsx(
11810
+ TextArea,
11811
+ {
11812
+ className: styles$7.description,
11813
+ placeholder: "Explain the purpose of this form",
11814
+ value,
11815
+ onChange: (event) => {
11816
+ setValue(event.target.value);
11817
+ },
11818
+ resize: "vertical",
11819
+ maxLength: 1e3,
11820
+ showInputLength: false,
11821
+ variant: "ghost"
11822
+ }
11823
+ )
11824
+ }
11825
+ )
11826
+ ] }),
11827
+ /* @__PURE__ */ jsx(FieldsEditor, { fieldsOnly }),
11664
11828
  /* @__PURE__ */ jsx(Text, { severity: "danger", size: "1", children: typeof formik.errors.fields === "string" && formik.errors.fields })
11665
11829
  ] }),
11666
11830
  /* @__PURE__ */ jsxs(Flex, { className: styles$7.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
11667
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "solid", severity: "info", onClick: onCancel, children: "Cancel" }),
11831
+ onCancel && /* @__PURE__ */ jsx(Button, { type: "button", variant: "solid", severity: "info", onClick: onCancel, children: "Cancel" }),
11668
11832
  /* @__PURE__ */ jsx(Button, { type: "submit", children: "Save form" })
11669
11833
  ] })
11670
11834
  ] }) })
11671
11835
  ] }),
11672
- /* @__PURE__ */ jsx(Tabs.Content, { value: "preview", children: /* @__PURE__ */ jsx(FormRenderer, { schema: previewSchema, onSubmit: previewSubmit }) })
11836
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "preview", children: /* @__PURE__ */ jsx(FormRenderer, { schema: previewSchema, onSubmit: previewSubmit, hideTitle: !showFormTitle }) })
11673
11837
  ] }) });
11674
11838
  })
11675
11839
  );
@@ -11821,7 +11985,6 @@ export {
11821
11985
  addUserFormRevision,
11822
11986
  addUserFormRevisionAttachment,
11823
11987
  addUserFormRevisions,
11824
- addUserFormSubmission,
11825
11988
  addUserFormSubmissionAttachment,
11826
11989
  addUserFormSubmissions,
11827
11990
  addUserForms,
@@ -11906,6 +12069,7 @@ export {
11906
12069
  issueReducer,
11907
12070
  issueSlice,
11908
12071
  issueToSearchResult,
12072
+ linkStageToForm,
11909
12073
  literalToCoordinates,
11910
12074
  logOnlyOnce,
11911
12075
  makeClient,
@@ -11982,7 +12146,6 @@ export {
11982
12146
  selectActiveWorkspace,
11983
12147
  selectActiveWorkspaceId,
11984
12148
  selectAllAttachments,
11985
- selectAllRevisionAttachmentsByLatestRevisionId,
11986
12149
  selectAppearance,
11987
12150
  selectCategories,
11988
12151
  selectCategoriesOfWorkspace,
@@ -11996,6 +12159,7 @@ export {
11996
12159
  selectCompletedStages,
11997
12160
  selectComponent,
11998
12161
  selectComponentType,
12162
+ selectComponentTypeForm,
11999
12163
  selectComponentTypeFromComponent,
12000
12164
  selectComponentTypeFromComponents,
12001
12165
  selectComponentTypes,
@@ -12033,10 +12197,12 @@ export {
12033
12197
  selectLatestFormRevision,
12034
12198
  selectLatestRetryTime,
12035
12199
  selectLatestRevisionByFormId,
12200
+ selectLatestRevisionsFromComponentTypeIds,
12036
12201
  selectMainWorkspace,
12037
12202
  selectMapStyle,
12038
12203
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
12039
12204
  selectNumberOfComponentsOfComponentType,
12205
+ selectNumberOfGeneralUserForms,
12040
12206
  selectNumberOfUserForms,
12041
12207
  selectOrganization,
12042
12208
  selectOrganizationAccess,
@@ -12070,6 +12236,7 @@ export {
12070
12236
  selectSortedOrganizationUsers,
12071
12237
  selectSortedProjectUsers,
12072
12238
  selectSortedProjects,
12239
+ selectStageFormIdsFromStageIds,
12073
12240
  selectStageMapping,
12074
12241
  selectStages,
12075
12242
  selectStagesFromComponentType,
@@ -12145,11 +12312,13 @@ export {
12145
12312
  unfavoriteForm,
12146
12313
  unhideAllCategories,
12147
12314
  unhideCategory,
12315
+ unlinkStageToForm,
12148
12316
  updateActiveOrganization,
12149
12317
  updateAttachment,
12150
12318
  updateComponent,
12151
12319
  updateIssue,
12152
12320
  updateOrCreateProject,
12321
+ updateOrCreateUserFormSubmission,
12153
12322
  updateOrganizationAccess,
12154
12323
  updateProjectAccess,
12155
12324
  updateStages,