@inspectorhub/field-ui 0.6.2 → 0.7.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.
@@ -1109,13 +1109,22 @@ interface PendingMediaTarget {
1109
1109
  * `upload-photo` form fields of the inspection-edit action: `itemId` always;
1110
1110
  * `customId` and `defectKind` only with `targetType: 'defect'`.
1111
1111
  */
1112
- type PhotoUploadMeta = (PendingMediaTarget & {
1112
+ type PhotoUploadMeta = (PendingMediaTarget & PhotoSourceField & {
1113
1113
  targetType: 'item';
1114
- }) | (PendingMediaTarget & {
1114
+ }) | (PendingMediaTarget & PhotoSourceField & {
1115
1115
  targetType: 'defect';
1116
1116
  customId: string;
1117
1117
  defectKind: 'canned' | 'custom';
1118
1118
  });
1119
+ /**
1120
+ * Where a photo came from: the camera input ('camera'), the in-editor burst camera ('burst'), or the device's photo
1121
+ * library ('library'). A host that copies new photos to the device gallery skips 'library', which is already there.
1122
+ */
1123
+ type PhotoSource = 'camera' | 'library' | 'burst';
1124
+ /** The editor always sets `source`; it is optional in the type so a host's own fixtures and older records still fit. */
1125
+ interface PhotoSourceField {
1126
+ source?: PhotoSource;
1127
+ }
1119
1128
  /**
1120
1129
  * A baked crop of an existing photo. Cropping always re-derives from the ORIGINAL `photoKey`.
1121
1130
  *
@@ -1602,5 +1611,5 @@ interface FieldDataSource {
1602
1611
  platform: 'web' | 'ios' | 'android';
1603
1612
  }
1604
1613
 
1605
- export { METADATA_PRESETS as M, isDecodeImageError as ax, resolvePcaNarrative as ay, DecodeImageError as t };
1606
- export type { PropertyMetaField as $, AiAssistInput as A, BulkCreateUnitsBody as B, CommandResult as C, DateFormat as D, EditorData as E, FieldCommand as F, FieldResources as G, FieldUrls as H, InspectionPrefs as I, GalleryPhoto as J, InspectionUnit as K, MediaFileResult as L, MediaPoolListing as N, MediaUploader as O, NotifyOptions as P, NotifyVariant as Q, OutboundCoolingWindow as R, PcaNarrative as S, PcaNarrativeData as T, PendingMediaRecord as U, PendingMediaStore as V, PhotoAnnotateMeta as W, PhotoCropMeta as X, PhotoCropTransform as Y, PhotoSize as Z, PhotoUploadMeta as _, CommandData as a, PsqView as a0, PublishBlockingDefect as a1, PublishReadiness as a2, RatingLevel as a3, RelianceText as a4, RepairItemOption as a5, ReportLinkTtl as a6, ReportProfileOption as a7, ReportSignoffView as a8, ResultMap as a9, ResultsDocHandle as aa, RevisionStatus as ab, SaveStructureTemplateCommand as ac, SchemaItem as ad, SchemaSection as ae, SessionInfo as af, SettingsSheetData as ag, StatutoryCoverage as ah, StatutoryDetails as ai, TagLibraryEntry as aj, TemplateItemBody as ak, TemplateSchema as al, TemplateSearchResult as am, TemplateSnapshot as an, TemplateSummary as ao, TimeFormat as ap, UnitCommand as aq, UnitProgress as ar, VersionSnapshotContent as as, VersionSnapshotEntry as at, VideoFinalizeInput as au, VideoUploadRef as av, VideoUploadTicket as aw, FieldDataSource as b, AiAssistResult as c, AutoAdvanceMode as d, AutofillReason as e, CollabConnector as f, CommandDataMap as g, CommandKey as h, CommentsLibraryEntry as i, CommentsLibraryQuery as j, CommentsLibraryRow as k, CommercialPresets as l, ComplianceCommand as m, CompliancePanelData as n, CostItemView as o, CostItemWrite as p, CostItemsListing as q, CoverPhotoOption as r, DecodeImage as s, DecodeImageOptions as u, DecodedImage as v, DefectCategory as w, DocumentReviewItemView as x, EditorInspection as y, ExecuteOptions as z };
1614
+ export { METADATA_PRESETS as M, isDecodeImageError as aA, resolvePcaNarrative as aB, DecodeImageError as u };
1615
+ export type { PhotoSize as $, AiAssistInput as A, BulkCreateUnitsBody as B, CommandResult as C, DateFormat as D, EditorData as E, FieldCommand as F, ExecuteOptions as G, FieldResources as H, InspectionPrefs as I, FieldUrls as J, GalleryPhoto as K, InspectionUnit as L, MediaFileResult as N, MediaPoolListing as O, PhotoEntry as P, MediaUploader as Q, NotifyOptions as R, NotifyVariant as S, OutboundCoolingWindow as T, PcaNarrative as U, PcaNarrativeData as V, PendingMediaRecord as W, PendingMediaStore as X, PhotoAnnotateMeta as Y, PhotoCropMeta as Z, PhotoCropTransform as _, CommandData as a, PhotoSource as a0, PhotoUploadMeta as a1, PropertyMetaField as a2, PsqView as a3, PublishBlockingDefect as a4, PublishReadiness as a5, RatingLevel as a6, RelianceText as a7, RepairItemOption as a8, ReportLinkTtl as a9, ReportProfileOption as aa, ReportSignoffView as ab, ResultMap as ac, ResultsDocHandle as ad, RevisionStatus as ae, SaveStructureTemplateCommand as af, SchemaItem as ag, SchemaSection as ah, SessionInfo as ai, SettingsSheetData as aj, StatutoryCoverage as ak, StatutoryDetails as al, TagLibraryEntry as am, TemplateItemBody as an, TemplateSchema as ao, TemplateSearchResult as ap, TemplateSnapshot as aq, TemplateSummary as ar, TimeFormat as as, UnitCommand as at, UnitProgress as au, VersionSnapshotContent as av, VersionSnapshotEntry as aw, VideoFinalizeInput as ax, VideoUploadRef as ay, VideoUploadTicket as az, FieldDataSource as b, FindingKey as c, AiAssistResult as d, AutoAdvanceMode as e, AutofillReason as f, CollabConnector as g, CommandDataMap as h, CommandKey as i, CommentsLibraryEntry as j, CommentsLibraryQuery as k, CommentsLibraryRow as l, CommercialPresets as m, ComplianceCommand as n, CompliancePanelData as o, CostItemView as p, CostItemWrite as q, CostItemsListing as r, CoverPhotoOption as s, DecodeImage as t, DecodeImageOptions as v, DecodedImage as w, DefectCategory as x, DocumentReviewItemView as y, EditorInspection as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FieldCommand, C as CommandResult, a as CommandData, b as FieldDataSource, E as EditorData, I as InspectionPrefs } from './data-source-Do9_Rv50.js';
2
- export { A as AiAssistInput, c as AiAssistResult, d as AutoAdvanceMode, e as AutofillReason, B as BulkCreateUnitsBody, f as CollabConnector, g as CommandDataMap, h as CommandKey, i as CommentsLibraryEntry, j as CommentsLibraryQuery, k as CommentsLibraryRow, l as CommercialPresets, m as ComplianceCommand, n as CompliancePanelData, o as CostItemView, p as CostItemWrite, q as CostItemsListing, r as CoverPhotoOption, D as DateFormat, s as DecodeImage, t as DecodeImageError, u as DecodeImageOptions, v as DecodedImage, w as DefectCategory, x as DocumentReviewItemView, y as EditorInspection, z as ExecuteOptions, G as FieldResources, H as FieldUrls, J as GalleryPhoto, K as InspectionUnit, M as METADATA_PRESETS, L as MediaFileResult, N as MediaPoolListing, O as MediaUploader, P as NotifyOptions, Q as NotifyVariant, R as OutboundCoolingWindow, S as PcaNarrative, T as PcaNarrativeData, U as PendingMediaRecord, V as PendingMediaStore, W as PhotoAnnotateMeta, X as PhotoCropMeta, Y as PhotoCropTransform, Z as PhotoSize, _ as PhotoUploadMeta, $ as PropertyMetaField, a0 as PsqView, a1 as PublishBlockingDefect, a2 as PublishReadiness, a3 as RatingLevel, a4 as RelianceText, a5 as RepairItemOption, a6 as ReportLinkTtl, a7 as ReportProfileOption, a8 as ReportSignoffView, a9 as ResultMap, aa as ResultsDocHandle, ab as RevisionStatus, ac as SaveStructureTemplateCommand, ad as SchemaItem, ae as SchemaSection, af as SessionInfo, ag as SettingsSheetData, ah as StatutoryCoverage, ai as StatutoryDetails, aj as TagLibraryEntry, ak as TemplateItemBody, al as TemplateSchema, am as TemplateSearchResult, an as TemplateSnapshot, ao as TemplateSummary, ap as TimeFormat, aq as UnitCommand, ar as UnitProgress, as as VersionSnapshotContent, at as VersionSnapshotEntry, au as VideoFinalizeInput, av as VideoUploadRef, aw as VideoUploadTicket, ax as isDecodeImageError, ay as resolvePcaNarrative } from './data-source-Do9_Rv50.js';
1
+ import { F as FieldCommand, C as CommandResult, a as CommandData, b as FieldDataSource, E as EditorData, c as FindingKey, P as PhotoEntry, I as InspectionPrefs } from './data-source-C64MWI32.js';
2
+ export { A as AiAssistInput, d as AiAssistResult, e as AutoAdvanceMode, f as AutofillReason, B as BulkCreateUnitsBody, g as CollabConnector, h as CommandDataMap, i as CommandKey, j as CommentsLibraryEntry, k as CommentsLibraryQuery, l as CommentsLibraryRow, m as CommercialPresets, n as ComplianceCommand, o as CompliancePanelData, p as CostItemView, q as CostItemWrite, r as CostItemsListing, s as CoverPhotoOption, D as DateFormat, t as DecodeImage, u as DecodeImageError, v as DecodeImageOptions, w as DecodedImage, x as DefectCategory, y as DocumentReviewItemView, z as EditorInspection, G as ExecuteOptions, H as FieldResources, J as FieldUrls, K as GalleryPhoto, L as InspectionUnit, M as METADATA_PRESETS, N as MediaFileResult, O as MediaPoolListing, Q as MediaUploader, R as NotifyOptions, S as NotifyVariant, T as OutboundCoolingWindow, U as PcaNarrative, V as PcaNarrativeData, W as PendingMediaRecord, X as PendingMediaStore, Y as PhotoAnnotateMeta, Z as PhotoCropMeta, _ as PhotoCropTransform, $ as PhotoSize, a0 as PhotoSource, a1 as PhotoUploadMeta, a2 as PropertyMetaField, a3 as PsqView, a4 as PublishBlockingDefect, a5 as PublishReadiness, a6 as RatingLevel, a7 as RelianceText, a8 as RepairItemOption, a9 as ReportLinkTtl, aa as ReportProfileOption, ab as ReportSignoffView, ac as ResultMap, ad as ResultsDocHandle, ae as RevisionStatus, af as SaveStructureTemplateCommand, ag as SchemaItem, ah as SchemaSection, ai as SessionInfo, aj as SettingsSheetData, ak as StatutoryCoverage, al as StatutoryDetails, am as TagLibraryEntry, an as TemplateItemBody, ao as TemplateSchema, ap as TemplateSearchResult, aq as TemplateSnapshot, ar as TemplateSummary, as as TimeFormat, at as UnitCommand, au as UnitProgress, av as VersionSnapshotContent, aw as VersionSnapshotEntry, ax as VideoFinalizeInput, ay as VideoUploadRef, az as VideoUploadTicket, aA as isDecodeImageError, aB as resolvePcaNarrative } from './data-source-C64MWI32.js';
3
3
  import * as React from 'react';
4
4
  import { ReactNode } from 'react';
5
5
  import * as Y from 'yjs';
@@ -189,6 +189,45 @@ declare function resolvePendingPhoto(doc: Y.Doc, findingKey: string, pendingId:
189
189
  annotatedKey?: string;
190
190
  }): void;
191
191
 
192
+ /**
193
+ * Pure Yjs helpers for the inspection results collaborative document.
194
+ *
195
+ * No DB, no I/O — all functions operate on a Y.Doc in memory.
196
+ * A Durable Object will call these helpers to manage the live document state.
197
+ *
198
+ * The three exports implement Condition A of the migration design (#181):
199
+ * - `seedResultsDoc` — pre-creates full nested structure so two clients can
200
+ * never lazily create the same Y.Map and race to overwrite each other.
201
+ * - `applyItemPatch` — mutates a single field inside a transaction.
202
+ * - `projectResults` — converts the Y.Doc to the exact `inspection_results.data`
203
+ * JSON shape that existing readers (report service, PDF renderer) consume,
204
+ * omitting empty optionals so the output matches the legacy blob.
205
+ */
206
+
207
+ /**
208
+ * Public API for hosts (re-exported from the package root), not only a test helper:
209
+ * a by-`key` upsert, so the same key twice is one entry.
210
+ * Append (or merge) a photo into the item's `photos` Y.Array.
211
+ * If a photo Y.Map with the same `key` exists, its fields are replaced/merged;
212
+ * otherwise a new photo Y.Map is pushed.
213
+ */
214
+ declare function appendPhoto(doc: Y.Doc, findingKey: FindingKey, photo: PhotoEntry): void;
215
+ /**
216
+ * #181 PR-G — push a brand-new PENDING photo entry, deduped by `pendingId`
217
+ * (NOT by `key`).
218
+ *
219
+ * Public API for hosts (re-exported from the package root), not only a test helper:
220
+ * a by-`pendingId` upsert.
221
+ *
222
+ * A brand-new offline photo has an EMPTY `key`, so `appendPhoto`'s upsert-by-key
223
+ * would merge two concurrent offline adds into one element. This mutator instead
224
+ * keys on the unique `pendingId`: an entry with the same `pendingId` is merged,
225
+ * otherwise a fresh element is pushed — so two offline adds yield two entries.
226
+ */
227
+ declare function pushPendingPhoto(doc: Y.Doc, findingKey: FindingKey, photo: PhotoEntry & {
228
+ pendingId: string;
229
+ }): void;
230
+
192
231
  /**
193
232
  * Commercial PCA Phase M — seeded reliance / point-in-time / site-specific
194
233
  * disclaimer text (ASTM §4.2.1–4.2.4). Defaults the Phase S §2.5 (User Reliance)
@@ -238,5 +277,5 @@ declare function setFieldLocale(locale: string): void;
238
277
  */
239
278
  declare function bindFieldLocaleSource(read: (() => string) | null): void;
240
279
 
241
- export { CommandData, CommandResult, DEFAULT_INSPECTION_PREFS, EditorData, FieldCommand, FieldDataSource, FieldDataSourceProvider, FieldEditor, InspectionPrefs, RELIANCE_TEMPLATES, appendPendingPhoto, bindFieldLocaleSource, escapeWillBeHandled, findingKey, findingsForUnit, hasOpenLayer, isIgnored, isMetaKey, resolvePendingPhoto, setFieldLocale, useFieldCommand, useFieldDataSource, useFieldEnsureHuman, useFieldSlots };
280
+ export { CommandData, CommandResult, DEFAULT_INSPECTION_PREFS, EditorData, FieldCommand, FieldDataSource, FieldDataSourceProvider, FieldEditor, FindingKey, InspectionPrefs, PhotoEntry, RELIANCE_TEMPLATES, appendPendingPhoto, appendPhoto, bindFieldLocaleSource, escapeWillBeHandled, findingKey, findingsForUnit, hasOpenLayer, isIgnored, isMetaKey, pushPendingPhoto, resolvePendingPhoto, setFieldLocale, useFieldCommand, useFieldDataSource, useFieldEnsureHuman, useFieldSlots };
242
281
  export type { FieldCommandRunner, FieldDataSourceProviderProps, FieldHostSlots, FieldRunResult, IgnoredRun };
package/dist/index.js CHANGED
@@ -69610,7 +69610,7 @@ function newPendingId() {
69610
69610
  return `photo-${Date.now()}-${Math.random().toString(36).slice(2)}`;
69611
69611
  }
69612
69612
  function metaOf(batch) {
69613
- const base = { findingKey: batch.findingKey, itemId: batch.itemId };
69613
+ const base = { findingKey: batch.findingKey, itemId: batch.itemId, source: batch.source };
69614
69614
  return batch.target === null ? { ...base, targetType: "item" } : { ...base, targetType: "defect", customId: batch.target.id, defectKind: batch.target.kind };
69615
69615
  }
69616
69616
  function usePhotoBatchUpload(inspectionId, doc) {
@@ -70127,7 +70127,7 @@ async function addOfflinePhotos(store, doc, target, files) {
70127
70127
  inspectionId: target.inspectionId,
70128
70128
  kind: "photo",
70129
70129
  blob,
70130
- meta: { targetType: "item", findingKey: target.findingKey, itemId: target.itemId },
70130
+ meta: { targetType: "item", findingKey: target.findingKey, itemId: target.itemId, source: target.source },
70131
70131
  createdAt: Date.now()
70132
70132
  });
70133
70133
  stored = true;
@@ -73578,18 +73578,22 @@ function ItemPhotoStrip({
73578
73578
  dk || p.pendingId || `idx-${i}`
73579
73579
  );
73580
73580
  }),
73581
- onAddPhoto && /* @__PURE__ */ jsx59(
73581
+ onAddPhoto && /* @__PURE__ */ jsxs47(
73582
73582
  "button",
73583
73583
  {
73584
73584
  type: "button",
73585
- ...pendingProps(photoUploading, onAddPhoto),
73585
+ onClick: onAddPhoto,
73586
+ "aria-busy": photoUploading ? true : void 0,
73586
73587
  "aria-label": index_exports.media_strip_add_photo_aria(),
73587
73588
  "data-testid": "photo-add",
73588
- className: `strip-add w-16 h-16 shrink-0 rounded-lg border-2 border-dashed border-ih-border flex items-center justify-center text-ih-fg-4 hover:border-ih-primary hover:text-ih-primary-text transition-colors ${PENDING_CLASS}`,
73589
- children: photoUploading ? /* @__PURE__ */ jsxs47("svg", { className: "w-5 h-5 animate-spin", fill: "none", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
73590
- /* @__PURE__ */ jsx59("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
73591
- /* @__PURE__ */ jsx59("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
73592
- ] }) : /* @__PURE__ */ jsx59("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx59("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) })
73589
+ className: "strip-add relative w-16 h-16 shrink-0 rounded-lg border-2 border-dashed border-ih-border flex items-center justify-center text-ih-fg-4 hover:border-ih-primary hover:text-ih-primary-text transition-colors",
73590
+ children: [
73591
+ /* @__PURE__ */ jsx59("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx59("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) }),
73592
+ photoUploading && /* @__PURE__ */ jsxs47("svg", { "data-testid": "photo-add-uploading", className: "absolute right-1 top-1 w-3.5 h-3.5 animate-spin text-ih-primary-text", fill: "none", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
73593
+ /* @__PURE__ */ jsx59("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
73594
+ /* @__PURE__ */ jsx59("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
73595
+ ] })
73596
+ ]
73593
73597
  }
73594
73598
  )
73595
73599
  ]
@@ -74098,14 +74102,18 @@ function ItemEditor({
74098
74102
  return Array.isArray(row?.photos) ? row.photos.length : 0;
74099
74103
  };
74100
74104
  const addPhotoIcon = /* @__PURE__ */ jsx64("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx64("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" }) });
74105
+ const uploadingIcon = /* @__PURE__ */ jsxs52("svg", { "data-testid": "defect-photo-uploading", className: "w-3.5 h-3.5 animate-spin text-ih-primary-text", fill: "none", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
74106
+ /* @__PURE__ */ jsx64("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
74107
+ /* @__PURE__ */ jsx64("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
74108
+ ] });
74101
74109
  const defectPhotoChip = (target, count) => onAddDefectPhoto ? /* @__PURE__ */ jsx64(
74102
74110
  Button,
74103
74111
  {
74104
74112
  variant: "ghost",
74105
74113
  size: "sm",
74106
- pending: photoUploading,
74114
+ "aria-busy": photoUploading ? true : void 0,
74107
74115
  "aria-label": index_exports.editor_item_add_defect_photo_aria(),
74108
- icon: addPhotoIcon,
74116
+ icon: photoUploading ? uploadingIcon : addPhotoIcon,
74109
74117
  onClick: (e) => {
74110
74118
  e.preventDefault();
74111
74119
  e.stopPropagation();
@@ -74542,6 +74550,9 @@ import Lightbox from "yet-another-react-lightbox";
74542
74550
  import Zoom from "yet-another-react-lightbox/plugins/zoom";
74543
74551
  import "yet-another-react-lightbox/styles.css";
74544
74552
  import { jsx as jsx68 } from "react/jsx-runtime";
74553
+ var SAFE_AREA_TOOLBAR_PADDING = {
74554
+ "--yarl__toolbar_padding": "calc(8px + env(safe-area-inset-top)) calc(8px + env(safe-area-inset-right)) 8px calc(8px + env(safe-area-inset-left))"
74555
+ };
74545
74556
  function PhotoLightbox({ slides, index, open, onClose, toolbarButtons, toolbarWrap, renderSlide }) {
74546
74557
  useLayer(open, { onEscape: onClose, lockScroll: true, traps: true });
74547
74558
  return /* @__PURE__ */ jsx68(
@@ -74554,7 +74565,7 @@ function PhotoLightbox({ slides, index, open, onClose, toolbarButtons, toolbarWr
74554
74565
  plugins: [Zoom],
74555
74566
  zoom: { maxZoomPixelRatio: 3, doubleTapDelay: 300, pinchZoomDistanceFactor: 100 },
74556
74567
  toolbar: { buttons: [...toolbarButtons ?? [], "close"] },
74557
- ...toolbarWrap ? { styles: { toolbar: { flexWrap: "wrap", left: 0 } } } : {},
74568
+ styles: { toolbar: { ...toolbarWrap ? { flexWrap: "wrap", left: 0 } : {}, ...SAFE_AREA_TOOLBAR_PADDING } },
74558
74569
  render: renderSlide ? { slide: ({ slide }) => renderSlide(slide) || void 0 } : void 0
74559
74570
  }
74560
74571
  );
@@ -81290,7 +81301,22 @@ function InspectionIdentity({ address, id, date, status }) {
81290
81301
 
81291
81302
  // src/components/editor/MobileDrawerTriggers.tsx
81292
81303
  import { useEffect as useEffect49 } from "react";
81293
- import { jsx as jsx119, jsxs as jsxs100 } from "react/jsx-runtime";
81304
+ import { Fragment as Fragment32, jsx as jsx119, jsxs as jsxs100 } from "react/jsx-runtime";
81305
+ var TAB_ICONS = {
81306
+ sections: /* @__PURE__ */ jsx119("path", { d: "M4 6h16M4 12h16M4 18h16" }),
81307
+ items: /* @__PURE__ */ jsx119("path", { d: "M9 6h11M9 12h11M9 18h11M4.5 6h.01M4.5 12h.01M4.5 18h.01" }),
81308
+ preview: /* @__PURE__ */ jsxs100(Fragment32, { children: [
81309
+ /* @__PURE__ */ jsx119("path", { d: "M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7S2 12 2 12z" }),
81310
+ /* @__PURE__ */ jsx119("circle", { cx: "12", cy: "12", r: "3" })
81311
+ ] }),
81312
+ theme: /* @__PURE__ */ jsxs100(Fragment32, { children: [
81313
+ /* @__PURE__ */ jsx119("circle", { cx: "12", cy: "12", r: "9" }),
81314
+ /* @__PURE__ */ jsx119("path", { d: "M12 3a9 9 0 0 1 0 18z", fill: "currentColor" })
81315
+ ] })
81316
+ };
81317
+ function TabIcon({ id }) {
81318
+ return /* @__PURE__ */ jsx119("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", focusable: "false", children: TAB_ICONS[id] });
81319
+ }
81294
81320
  var mountedNavs = 0;
81295
81321
  function MobileDrawerTriggers({ onOpen, showTheme = true }) {
81296
81322
  useEffect49(() => {
@@ -81302,17 +81328,17 @@ function MobileDrawerTriggers({ onOpen, showTheme = true }) {
81302
81328
  };
81303
81329
  }, []);
81304
81330
  return /* @__PURE__ */ jsx119("nav", { "aria-label": index_exports.editor_mobile_nav_label(), className: "fixed left-0 right-0 bottom-0 z-30 h-[var(--ih-mobile-nav-h)] pb-[env(safe-area-inset-bottom)] pl-[env(safe-area-inset-left)] pr-[env(safe-area-inset-right)] bg-ih-bg-card border-t border-ih-border flex", children: [
81305
- { id: "sections", label: index_exports.editor_mobile_drawer_sections(), icon: "\u2630" },
81306
- { id: "items", label: index_exports.editor_mobile_drawer_items(), icon: "\u2263" },
81307
- { id: "preview", label: index_exports.editor_route_drawer_preview(), icon: "\u{1F441}" },
81308
- { id: "theme", label: index_exports.nav_theme_label(), icon: "\u25D0" }
81331
+ { id: "sections", label: index_exports.editor_mobile_drawer_sections(), icon: "sections" },
81332
+ { id: "items", label: index_exports.editor_mobile_drawer_items(), icon: "items" },
81333
+ { id: "preview", label: index_exports.editor_route_drawer_preview(), icon: "preview" },
81334
+ { id: "theme", label: index_exports.nav_theme_label(), icon: "theme" }
81309
81335
  ].filter((t) => showTheme || t.id !== "theme").map((t) => /* @__PURE__ */ jsxs100(
81310
81336
  "button",
81311
81337
  {
81312
81338
  onClick: () => onOpen(t.id),
81313
81339
  className: "flex-1 min-h-11 touch-manipulation flex flex-col items-center justify-center text-ih-fg-2 hover:bg-ih-bg-muted active:bg-ih-bg-muted",
81314
81340
  children: [
81315
- /* @__PURE__ */ jsx119("span", { className: "text-[16px]", "aria-hidden": "true", children: t.icon }),
81341
+ /* @__PURE__ */ jsx119("span", { className: "flex h-5 items-center", "aria-hidden": "true", children: /* @__PURE__ */ jsx119(TabIcon, { id: t.icon }) }),
81316
81342
  /* @__PURE__ */ jsx119("span", { className: "text-[10px] uppercase tracking-[0.1em]", children: t.label })
81317
81343
  ]
81318
81344
  },
@@ -81321,7 +81347,7 @@ function MobileDrawerTriggers({ onOpen, showTheme = true }) {
81321
81347
  }
81322
81348
 
81323
81349
  // src/components/editor/MobileFinishDrawer.tsx
81324
- import { Fragment as Fragment32, jsx as jsx120, jsxs as jsxs101 } from "react/jsx-runtime";
81350
+ import { Fragment as Fragment33, jsx as jsx120, jsxs as jsxs101 } from "react/jsx-runtime";
81325
81351
  function MobileFinishDrawer({
81326
81352
  open,
81327
81353
  onClose,
@@ -81362,7 +81388,7 @@ function MobileFinishDrawer({
81362
81388
  if (onUpdateSourceTemplate) templateRows.push({ label: index_exports.template_menu_update_source(), run: onUpdateSourceTemplate });
81363
81389
  const groupHeading = "px-1 pt-3 pb-1 text-[12px] font-bold text-ih-fg-2";
81364
81390
  return /* @__PURE__ */ jsx120(MobileBottomDrawer, { open, onClose, title: index_exports.editor_mobile_more(), heightFraction: 0.8, children: /* @__PURE__ */ jsxs101("div", { className: "p-4 space-y-2 pb-[calc(1rem+env(safe-area-inset-bottom))]", children: [
81365
- !readOnly && /* @__PURE__ */ jsxs101(Fragment32, { children: [
81391
+ !readOnly && /* @__PURE__ */ jsxs101(Fragment33, { children: [
81366
81392
  /* @__PURE__ */ jsx120(Button, { variant: "primary", className: row, onClick: () => run(onPublish), children: index_exports.editor_header_publish() }),
81367
81393
  /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(onSign), children: index_exports.editor_header_sign() })
81368
81394
  ] }),
@@ -81377,20 +81403,20 @@ function MobileFinishDrawer({
81377
81403
  }
81378
81404
  ),
81379
81405
  onPreviewReport && /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(onPreviewReport), children: index_exports.editor_header_preview_report() }),
81380
- onPreviewPdf && /* @__PURE__ */ jsxs101(Fragment32, { children: [
81406
+ onPreviewPdf && /* @__PURE__ */ jsxs101(Fragment33, { children: [
81381
81407
  /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, pending: pdfBusy, onClick: () => run(onPreviewPdf), children: pdfLabel ?? index_exports.editor_header_preview_pdf_short() }),
81382
81408
  pdfError && /* @__PURE__ */ jsx120("p", { className: "px-1 text-[12px] text-ih-bad-fg", children: pdfError })
81383
81409
  ] }),
81384
- (onSpeedMode || onBurstCamera) && /* @__PURE__ */ jsxs101(Fragment32, { children: [
81410
+ (onSpeedMode || onBurstCamera) && /* @__PURE__ */ jsxs101(Fragment33, { children: [
81385
81411
  /* @__PURE__ */ jsx120("h3", { className: groupHeading, children: index_exports.editor_mobile_group_capture() }),
81386
81412
  onSpeedMode && /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(onSpeedMode), children: index_exports.editor_dock_speed_mode() }),
81387
81413
  onBurstCamera && /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(onBurstCamera), children: index_exports.editor_mobile_burst_camera() })
81388
81414
  ] }),
81389
- inspectionRows.length > 0 && /* @__PURE__ */ jsxs101(Fragment32, { children: [
81415
+ inspectionRows.length > 0 && /* @__PURE__ */ jsxs101(Fragment33, { children: [
81390
81416
  /* @__PURE__ */ jsx120("h3", { className: groupHeading, children: index_exports.editor_mobile_group_inspection() }),
81391
81417
  inspectionRows.map((r) => /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(r.run), children: r.label }, r.label))
81392
81418
  ] }),
81393
- templateRows.length > 0 && /* @__PURE__ */ jsxs101(Fragment32, { children: [
81419
+ templateRows.length > 0 && /* @__PURE__ */ jsxs101(Fragment33, { children: [
81394
81420
  /* @__PURE__ */ jsx120("h3", { className: groupHeading, children: index_exports.template_menu_template() }),
81395
81421
  templateRows.map((r) => /* @__PURE__ */ jsx120(Button, { variant: "secondary", className: row, onClick: () => run(r.run), children: r.label }, r.label))
81396
81422
  ] }),
@@ -81800,7 +81826,7 @@ function PcaNarrativePanel({ inspectionId, narrative }) {
81800
81826
  import { useRef as useRef61, useState as useState60 } from "react";
81801
81827
 
81802
81828
  // src/components/ConfirmDialog.tsx
81803
- import { Fragment as Fragment33, jsx as jsx126, jsxs as jsxs106 } from "react/jsx-runtime";
81829
+ import { Fragment as Fragment34, jsx as jsx126, jsxs as jsxs106 } from "react/jsx-runtime";
81804
81830
  function ConfirmDialog({
81805
81831
  open,
81806
81832
  title,
@@ -81822,7 +81848,7 @@ function ConfirmDialog({
81822
81848
  onClose: onCancel,
81823
81849
  title,
81824
81850
  size: "sm",
81825
- footer: /* @__PURE__ */ jsxs106(Fragment33, { children: [
81851
+ footer: /* @__PURE__ */ jsxs106(Fragment34, { children: [
81826
81852
  /* @__PURE__ */ jsx126(
81827
81853
  "button",
81828
81854
  {
@@ -81851,7 +81877,7 @@ function ConfirmDialog({
81851
81877
  }
81852
81878
 
81853
81879
  // src/components/inspection-edit/CompliancePanel.tsx
81854
- import { Fragment as Fragment34, jsx as jsx127, jsxs as jsxs107 } from "react/jsx-runtime";
81880
+ import { Fragment as Fragment35, jsx as jsx127, jsxs as jsxs107 } from "react/jsx-runtime";
81855
81881
  function roleLabel(role) {
81856
81882
  return role === "field_observer" ? index_exports.editor_compliance_role_field_observer() : index_exports.editor_compliance_role_pcr_reviewer();
81857
81883
  }
@@ -82091,7 +82117,7 @@ function PsqPanel({ inspectionId, psq }) {
82091
82117
  onClose: () => setDeclineOpen(false),
82092
82118
  title: index_exports.editor_compliance_decline_psq_title(),
82093
82119
  size: "sm",
82094
- footer: /* @__PURE__ */ jsxs107(Fragment34, { children: [
82120
+ footer: /* @__PURE__ */ jsxs107(Fragment35, { children: [
82095
82121
  /* @__PURE__ */ jsx127(Button, { variant: "ghost", onClick: () => setDeclineOpen(false), children: index_exports.common_cancel() }),
82096
82122
  /* @__PURE__ */ jsx127(Button, { variant: "danger", onClick: confirmDecline, children: index_exports.editor_compliance_decline() })
82097
82123
  ] }),
@@ -82355,7 +82381,7 @@ var INSPECTION_PROPERTY_TYPES = [
82355
82381
  ];
82356
82382
 
82357
82383
  // src/components/editor/PropertyTypeControl.tsx
82358
- import { Fragment as Fragment35, jsx as jsx129, jsxs as jsxs109 } from "react/jsx-runtime";
82384
+ import { Fragment as Fragment36, jsx as jsx129, jsxs as jsxs109 } from "react/jsx-runtime";
82359
82385
  var LABELS = {
82360
82386
  single_family: () => index_exports.editor_property_type_single_family(),
82361
82387
  multi_unit: () => index_exports.editor_property_type_multi_unit(),
@@ -82427,7 +82453,7 @@ function PropertyTypeControl({
82427
82453
  setPending(null);
82428
82454
  }
82429
82455
  }, [pending, busy, propertyType]);
82430
- return /* @__PURE__ */ jsxs109(Fragment35, { children: [
82456
+ return /* @__PURE__ */ jsxs109(Fragment36, { children: [
82431
82457
  /* @__PURE__ */ jsx129(
82432
82458
  Select,
82433
82459
  {
@@ -82451,7 +82477,7 @@ function PropertyTypeControl({
82451
82477
  onClose: () => setPending(null),
82452
82478
  title: index_exports.editor_property_type_lossy_title(),
82453
82479
  size: "sm",
82454
- footer: /* @__PURE__ */ jsxs109(Fragment35, { children: [
82480
+ footer: /* @__PURE__ */ jsxs109(Fragment36, { children: [
82455
82481
  /* @__PURE__ */ jsx129(Button, { variant: "ghost", onClick: () => setPending(null), children: index_exports.common_cancel() }),
82456
82482
  /* @__PURE__ */ jsx129(
82457
82483
  Button,
@@ -82486,7 +82512,7 @@ function PropertyTypeControl({
82486
82512
  }
82487
82513
 
82488
82514
  // src/components/editor/InspectionOverview.tsx
82489
- import { Fragment as Fragment36, jsx as jsx130, jsxs as jsxs110 } from "react/jsx-runtime";
82515
+ import { Fragment as Fragment37, jsx as jsx130, jsxs as jsxs110 } from "react/jsx-runtime";
82490
82516
  function InspectionOverview({
82491
82517
  inspection,
82492
82518
  templateFields,
@@ -82505,7 +82531,7 @@ function InspectionOverview({
82505
82531
  const bag = inspection;
82506
82532
  const isCommercial = bag.propertyType === "commercial";
82507
82533
  const reportTier = bag.reportTier ?? null;
82508
- return /* @__PURE__ */ jsxs110(Fragment36, { children: [
82534
+ return /* @__PURE__ */ jsxs110(Fragment37, { children: [
82509
82535
  /* @__PURE__ */ jsx130(
82510
82536
  PropertyInfoForm,
82511
82537
  {
@@ -82522,7 +82548,7 @@ function InspectionOverview({
82522
82548
  previewHref: urls.statutoryPreviewPdf(String(bag.id))
82523
82549
  }
82524
82550
  ),
82525
- !readOnly && /* @__PURE__ */ jsxs110(Fragment36, { children: [
82551
+ !readOnly && /* @__PURE__ */ jsxs110(Fragment37, { children: [
82526
82552
  /* @__PURE__ */ jsx130(StatutoryDetailsHost, { inspectionId: String(bag.id), details: statutoryDetails }),
82527
82553
  /* @__PURE__ */ jsx130("div", { className: "mt-8 border-t border-ih-border pt-6", children: /* @__PURE__ */ jsx130(
82528
82554
  PropertyTypeControl,
@@ -82554,7 +82580,7 @@ function InspectionOverview({
82554
82580
 
82555
82581
  // src/components/editor/BreadcrumbDropdown.tsx
82556
82582
  import { useRef as useRef63, useState as useState62 } from "react";
82557
- import { Fragment as Fragment37, jsx as jsx131, jsxs as jsxs111 } from "react/jsx-runtime";
82583
+ import { Fragment as Fragment38, jsx as jsx131, jsxs as jsxs111 } from "react/jsx-runtime";
82558
82584
  function BreadcrumbDropdown({ units, activeUnitId, onSelect }) {
82559
82585
  const [open, setOpen] = useState62(false);
82560
82586
  const anchorRef = useRef63(null);
@@ -82566,7 +82592,7 @@ function BreadcrumbDropdown({ units, activeUnitId, onSelect }) {
82566
82592
  onSelect(id);
82567
82593
  setOpen(false);
82568
82594
  };
82569
- return /* @__PURE__ */ jsxs111(Fragment37, { children: [
82595
+ return /* @__PURE__ */ jsxs111(Fragment38, { children: [
82570
82596
  /* @__PURE__ */ jsxs111(
82571
82597
  Button,
82572
82598
  {
@@ -82873,7 +82899,7 @@ function UnitControls({ isPerUnit, units, activeUnitId, onSelectScope, onOpenUni
82873
82899
  }
82874
82900
 
82875
82901
  // src/editor/FieldEditor.tsx
82876
- import { Fragment as Fragment38, jsx as jsx136, jsxs as jsxs115 } from "react/jsx-runtime";
82902
+ import { Fragment as Fragment39, jsx as jsx136, jsxs as jsxs115 } from "react/jsx-runtime";
82877
82903
  function originalQualityEnabled() {
82878
82904
  try {
82879
82905
  return typeof localStorage !== "undefined" && localStorage.getItem(ORIGINAL_QUALITY_KEY) === "1";
@@ -83433,6 +83459,7 @@ function FieldEditorInner({ data }) {
83433
83459
  const handlePhotoUpload = useCallback49(
83434
83460
  (e) => {
83435
83461
  const all = Array.from(e.target.files ?? []);
83462
+ const source = e.target === cameraInputRef.current ? "camera" : "library";
83436
83463
  if (all.length === 0 || !state.activeItemId || readOnly) return;
83437
83464
  const itemId = state.activeItemId;
83438
83465
  const overflow = all.length > MAX_BATCH_PHOTOS;
@@ -83448,14 +83475,15 @@ function FieldEditorInner({ data }) {
83448
83475
  const sid = state.sectionIdForItem(itemId) ?? state.currentSection?.id;
83449
83476
  if (!dataSource.isOnline() && doc && sid && !target) {
83450
83477
  const fk = findingKey(activeUnitId, sid, itemId);
83451
- const batch = await addOfflinePhotos(dataSource.media.store, doc, { inspectionId: String(state.inspection.id), findingKey: fk, itemId }, bakedFiles);
83478
+ const batch = await addOfflinePhotos(dataSource.media.store, doc, { inspectionId: String(state.inspection.id), findingKey: fk, itemId, source }, bakedFiles);
83452
83479
  for (const message of offlinePhotoRejectionMessages(batch, bakedFiles.length)) notify(message, "error", { durationMs: 8e3 });
83453
83480
  } else {
83454
83481
  photoUpload.submit({
83455
83482
  itemId,
83456
83483
  findingKey: findingKey(activeUnitId, sid ?? "", itemId),
83457
83484
  files: bakedFiles,
83458
- target
83485
+ target,
83486
+ source
83459
83487
  });
83460
83488
  }
83461
83489
  })();
@@ -83480,7 +83508,7 @@ function FieldEditorInner({ data }) {
83480
83508
  files.push(orig ? f : await bakePhoto(f));
83481
83509
  }
83482
83510
  const sid = state.sectionIdForItem(itemId) ?? state.currentSection?.id;
83483
- photoUpload.submit({ itemId, findingKey: findingKey(activeUnitId, sid ?? "", itemId), files, target: null });
83511
+ photoUpload.submit({ itemId, findingKey: findingKey(activeUnitId, sid ?? "", itemId), files, target: null, source: "burst" });
83484
83512
  })();
83485
83513
  },
83486
83514
  [state.burstCameraItemId, state.sectionIdForItem, state.currentSection, activeUnitId, photoUpload.submit, notify, readOnly]
@@ -83612,7 +83640,8 @@ function FieldEditorInner({ data }) {
83612
83640
  },
83613
83641
  onLibraryClose: () => state.setShowCommentLibrary(false),
83614
83642
  onPhoto: () => {
83615
- if (!state.activeItemId || photoUpload.busy) return;
83643
+ if (!state.activeItemId) return;
83644
+ pendingPhotoTargetRef.current = null;
83616
83645
  if (isMobile) {
83617
83646
  setAddMediaChooser({ itemId: state.activeItemId });
83618
83647
  } else {
@@ -83662,7 +83691,6 @@ function FieldEditorInner({ data }) {
83662
83691
  comments,
83663
83692
  commentLibraryItems,
83664
83693
  serverComments,
83665
- photoUpload.busy,
83666
83694
  isMobile
83667
83695
  ]
83668
83696
  );
@@ -83749,9 +83777,11 @@ function FieldEditorInner({ data }) {
83749
83777
  ) : {},
83750
83778
  ratingLevels: state.ratingLevels,
83751
83779
  onRating: handleRating,
83752
- onAddPhoto: () => state.activeItemId ? setAddMediaChooser({ itemId: state.activeItemId }) : libraryInputRef.current?.click(),
83780
+ onAddPhoto: () => {
83781
+ pendingPhotoTargetRef.current = null;
83782
+ return state.activeItemId ? setAddMediaChooser({ itemId: state.activeItemId }) : libraryInputRef.current?.click();
83783
+ },
83753
83784
  onAddDefectPhoto: (target) => {
83754
- if (photoUpload.busy) return;
83755
83785
  pendingPhotoTargetRef.current = target;
83756
83786
  if (isMobile) {
83757
83787
  setAddMediaChooser({ itemId: state.activeItemId ?? "" });
@@ -83939,7 +83969,7 @@ function FieldEditorInner({ data }) {
83939
83969
  onChangeTier: commercialSave.changeTier
83940
83970
  }
83941
83971
  );
83942
- const photoInputsEl = /* @__PURE__ */ jsxs115(Fragment38, { children: [
83972
+ const photoInputsEl = /* @__PURE__ */ jsxs115(Fragment39, { children: [
83943
83973
  /* @__PURE__ */ jsx136(
83944
83974
  "input",
83945
83975
  {
@@ -83963,7 +83993,7 @@ function FieldEditorInner({ data }) {
83963
83993
  }
83964
83994
  )
83965
83995
  ] });
83966
- const addMediaOverlaysEl = /* @__PURE__ */ jsxs115(Fragment38, { children: [
83996
+ const addMediaOverlaysEl = /* @__PURE__ */ jsxs115(Fragment39, { children: [
83967
83997
  addMediaChooser && /* @__PURE__ */ jsx136(
83968
83998
  AddMediaChooser,
83969
83999
  {
@@ -83997,7 +84027,7 @@ function FieldEditorInner({ data }) {
83997
84027
  }
83998
84028
  )
83999
84029
  ] });
84000
- const finishActionsEl = /* @__PURE__ */ jsxs115(Fragment38, { children: [
84030
+ const finishActionsEl = /* @__PURE__ */ jsxs115(Fragment39, { children: [
84001
84031
  caps.settingsSheet && /* @__PURE__ */ jsx136(
84002
84032
  InspectionSettingsSheet,
84003
84033
  {
@@ -84186,7 +84216,7 @@ function FieldEditorInner({ data }) {
84186
84216
  const scopeSwitcherEl = showUnitsSurface && isPerUnit ? /* @__PURE__ */ jsx136(BreadcrumbDropdown, { units, activeUnitId, onSelect: requestScope }) : null;
84187
84217
  const saveStatusEl = /* @__PURE__ */ jsx136(WithHostStatus, { indicator: /* @__PURE__ */ jsx136(SaveStatusIndicator, { status: state.saveStatus }), renderStatus: slots.renderStatus });
84188
84218
  const { pdf } = slots;
84189
- const mobileDrawersEl = /* @__PURE__ */ jsxs115(Fragment38, { children: [
84219
+ const mobileDrawersEl = /* @__PURE__ */ jsxs115(Fragment39, { children: [
84190
84220
  /* @__PURE__ */ jsx136(MobileBottomDrawer, { open: mobileDrawer === "sections", onClose: () => setMobileDrawer(null), title: index_exports.editor_route_drawer_sections(), children: sectionRailEl }),
84191
84221
  isPhone && /* @__PURE__ */ jsxs115(MobileBottomDrawer, { open: mobileDrawer === "items", onClose: () => setMobileDrawer(null), title: index_exports.editor_route_drawer_items(), children: [
84192
84222
  scopeSwitcherEl && /* @__PURE__ */ jsx136("div", { className: "px-2 pt-2", children: scopeSwitcherEl }),
@@ -84236,7 +84266,7 @@ function FieldEditorInner({ data }) {
84236
84266
  setAddMediaChooser(null);
84237
84267
  setVideoCaptureTarget(null);
84238
84268
  }, [readOnly]);
84239
- const overlaysEl = /* @__PURE__ */ jsxs115(Fragment38, { children: [
84269
+ const overlaysEl = /* @__PURE__ */ jsxs115(Fragment39, { children: [
84240
84270
  photoInputsEl,
84241
84271
  addMediaOverlaysEl,
84242
84272
  sharedOverlaysEl,
@@ -84248,7 +84278,7 @@ function FieldEditorInner({ data }) {
84248
84278
  unsavedGuardEl
84249
84279
  ] });
84250
84280
  if (isPhone) {
84251
- return /* @__PURE__ */ jsxs115(Fragment38, { children: [
84281
+ return /* @__PURE__ */ jsxs115(Fragment39, { children: [
84252
84282
  overlaysEl,
84253
84283
  /* @__PURE__ */ jsxs115("div", { "data-layout": "phone", "data-collab-synced": collabSynced ? "true" : "false", className: "min-h-dvh pb-[var(--ih-mobile-nav-h)]", children: [
84254
84284
  /* @__PURE__ */ jsx136(
@@ -84270,7 +84300,7 @@ function FieldEditorInner({ data }) {
84270
84300
  ] });
84271
84301
  }
84272
84302
  if (layout === "tablet") {
84273
- return /* @__PURE__ */ jsxs115(Fragment38, { children: [
84303
+ return /* @__PURE__ */ jsxs115(Fragment39, { children: [
84274
84304
  overlaysEl,
84275
84305
  /* @__PURE__ */ jsx136(
84276
84306
  TabletTree,
@@ -84290,7 +84320,7 @@ function FieldEditorInner({ data }) {
84290
84320
  ),
84291
84321
  collabSynced,
84292
84322
  footer: /* @__PURE__ */ jsx136(FooterBar, { connected: presence.connected, status: presence.status, roster: presence.roster }),
84293
- listHeader: /* @__PURE__ */ jsxs115(Fragment38, { children: [
84323
+ listHeader: /* @__PURE__ */ jsxs115(Fragment39, { children: [
84294
84324
  /* @__PURE__ */ jsx136(InspectionIdentity, { address: state.inspection.propertyAddress, id: String(state.inspection.id), date: state.formattedDate, status: String(state.inspection.status) }),
84295
84325
  scopeSwitcherEl && /* @__PURE__ */ jsx136("div", { className: "px-3 py-2 border-b border-ih-border", children: scopeSwitcherEl }),
84296
84326
  itemFilterBarEl,
@@ -84298,7 +84328,7 @@ function FieldEditorInner({ data }) {
84298
84328
  ] }),
84299
84329
  sectionTitle: state.currentSection?.title ?? "",
84300
84330
  list: itemListEl,
84301
- main: /* @__PURE__ */ jsxs115(Fragment38, { children: [
84331
+ main: /* @__PURE__ */ jsxs115(Fragment39, { children: [
84302
84332
  revisionBannerEl,
84303
84333
  state.activeView === "property" ? propertyOverviewEl : itemEditorEl
84304
84334
  ] }),
@@ -84310,7 +84340,7 @@ function FieldEditorInner({ data }) {
84310
84340
  )
84311
84341
  ] });
84312
84342
  }
84313
- return /* @__PURE__ */ jsxs115(Fragment38, { children: [
84343
+ return /* @__PURE__ */ jsxs115(Fragment39, { children: [
84314
84344
  overlaysEl,
84315
84345
  /* @__PURE__ */ jsxs115(
84316
84346
  "div",
@@ -84337,7 +84367,7 @@ function FieldEditorInner({ data }) {
84337
84367
  perUnitControls: showUnitsSurface ? /* @__PURE__ */ jsx136(UnitControls, { isPerUnit, units, activeUnitId, onSelectScope: requestScope, onOpenUnits: () => setUnitsManagerOpen(true), onOpenCostItems: () => setCostItemsOpen(true) }) : void 0
84338
84368
  }
84339
84369
  ),
84340
- /* @__PURE__ */ jsx136("div", { className: "flex flex-1 pt-14 pb-9 min-w-[1024px]", children: emptyTemplateEl ? /* @__PURE__ */ jsx136("div", { className: "flex-1 flex", children: emptyTemplateEl }) : /* @__PURE__ */ jsxs115(Fragment38, { children: [
84370
+ /* @__PURE__ */ jsx136("div", { className: "flex flex-1 pt-14 pb-9 min-w-[1024px]", children: emptyTemplateEl ? /* @__PURE__ */ jsx136("div", { className: "flex-1 flex", children: emptyTemplateEl }) : /* @__PURE__ */ jsxs115(Fragment39, { children: [
84341
84371
  !state.itemFullscreen && sectionRailEl,
84342
84372
  !state.itemFullscreen && /* @__PURE__ */ jsxs115("div", { className: "w-[280px] flex-shrink-0 border-r border-ih-border flex flex-col overflow-hidden relative", children: [
84343
84373
  itemFilterBarEl,
@@ -84540,6 +84570,7 @@ export {
84540
84570
  METADATA_PRESETS,
84541
84571
  RELIANCE_TEMPLATES,
84542
84572
  appendPendingPhoto,
84573
+ appendPhoto,
84543
84574
  bindFieldLocaleSource,
84544
84575
  escapeWillBeHandled,
84545
84576
  findingKey2 as findingKey,
@@ -84548,6 +84579,7 @@ export {
84548
84579
  isDecodeImageError,
84549
84580
  isIgnored,
84550
84581
  isMetaKey,
84582
+ pushPendingPhoto,
84551
84583
  resolvePcaNarrative,
84552
84584
  resolvePendingPhoto,
84553
84585
  setFieldLocale,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inspectorhub/field-ui",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "The OpenInspection field inspection editor as an embeddable React package.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {