@overmap-ai/core 1.0.51-bulk-form-submission.4 → 1.0.51-fix-document-urls.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @overmap-ai/core
2
-
3
- The `core` package contains core functionality for the Overmap platform. It is a peer dependency of all other overmap
4
- packages.
1
+ # @overmap-ai/core
2
+
3
+ The `core` package contains core functionality for the Overmap platform. It is a peer dependency of all other overmap
4
+ packages.
@@ -12,6 +12,7 @@ export declare const CompleteFieldTypeToClsMapping: {
12
12
  text: typeof import('../fields/StringOrTextFields/TextField/TextField').TextField;
13
13
  custom: typeof import('../fields/CustomField').CustomField;
14
14
  upload: typeof import('../fields/UploadField').UploadField;
15
+ qr: typeof import('../fields/QrField/QrField').QrField;
15
16
  "multi-string": typeof import('../fields/MultiStringField/MultiStringField').MultiStringField;
16
17
  "multi-select": typeof import('../fields/SelectField/MultiSelectField').MultiSelectField;
17
18
  };
@@ -12,7 +12,7 @@ export declare function insert<T>(list: T[] | undefined, index: number, value: T
12
12
  export declare function remove<T>(list: T[], index: number): T[];
13
13
  export declare const makeIdentifier: (existing: unknown, label: string) => string;
14
14
  export declare const findFieldByIdentifier: (fields: ISerializedField[], identifier?: string) => ISerializedField | null;
15
- export declare const makeConditionalSourceFields: (sections: SerializedFieldSection[], index: number) => (import("../typings").SerializedTextField | import("../typings").SerializedBooleanField | import("../typings").SerializedNumberField | import("../typings").SerializedDateField | import("../typings").SerializedStringField | import("../typings").SerializedSelectField | import("../typings").SerializedMultiStringField | import("../typings").SerializedMultiSelectField | import("../typings").SerializedUploadField)[];
15
+ export declare const makeConditionalSourceFields: (sections: SerializedFieldSection[], index: number) => (import("../typings").SerializedTextField | import("../typings").SerializedBooleanField | import("../typings").SerializedNumberField | import("../typings").SerializedDateField | import("../typings").SerializedStringField | import("../typings").SerializedSelectField | import("../typings").SerializedMultiStringField | import("../typings").SerializedMultiSelectField | import("../typings").SerializedUploadField | import("../typings").SerializedQrField)[];
16
16
  export type NewFieldInitialValues = Omit<ISerializedField, "identifier"> & {
17
17
  label: string;
18
18
  };
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from "react";
2
+ import { RiQrCodeLine } from "react-icons/ri";
3
+ import { BaseField, ChildFieldOptions } from "../BaseField";
4
+ import { ISerializedField, SerializedQrField } from "../../typings";
5
+ import { ComponentProps } from "../typings";
6
+ export declare const emptyQrField: {
7
+ type: string;
8
+ label: string;
9
+ description: string;
10
+ required: boolean;
11
+ };
12
+ export declare class QrField extends BaseField<string, "qr"> {
13
+ static readonly fieldTypeName = "QR";
14
+ static readonly fieldTypeDescription = "Used for scanning/reading QR codes.";
15
+ readonly onlyValidateAfterTouched = false;
16
+ static Icon: typeof RiQrCodeLine;
17
+ constructor(options: ChildFieldOptions<string>);
18
+ serialize(): SerializedQrField;
19
+ static deserialize(data: ISerializedField): QrField;
20
+ getInput(props: ComponentProps<QrField>): ReactNode;
21
+ }
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { ComponentProps } from "../typings";
3
+ import { QrField } from "./QrField";
4
+ export declare const QrInput: import("react").MemoExoticComponent<(props: ComponentProps<QrField>) => import("react/jsx-runtime").JSX.Element>;
5
+ interface QrScannerProps {
6
+ onQrScan: (data: string) => void;
7
+ onClose: () => void;
8
+ }
9
+ export declare const QrScanner: import("react").MemoExoticComponent<(props: QrScannerProps) => import("react/jsx-runtime").JSX.Element>;
10
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from "./QrField";
2
+ export * from "./QrInput";
@@ -6,6 +6,7 @@ import { MultiSelectField, SelectField } from "./SelectField";
6
6
  import { CustomField } from "./CustomField";
7
7
  import { MultiStringField } from "./MultiStringField";
8
8
  import { UploadField } from "./UploadField";
9
+ import { QrField } from "./QrField";
9
10
  export declare const FieldTypeToClsMapping: {
10
11
  readonly date: typeof DateField;
11
12
  readonly number: typeof NumberField;
@@ -15,6 +16,7 @@ export declare const FieldTypeToClsMapping: {
15
16
  readonly text: typeof TextField;
16
17
  readonly custom: typeof CustomField;
17
18
  readonly upload: typeof UploadField;
19
+ readonly qr: typeof QrField;
18
20
  readonly "multi-string": typeof MultiStringField;
19
21
  readonly "multi-select": typeof MultiSelectField;
20
22
  };
@@ -77,6 +79,12 @@ export declare const FieldTypeToEmptyFieldMapping: {
77
79
  description: string;
78
80
  required: boolean;
79
81
  };
82
+ readonly qr: {
83
+ type: string;
84
+ label: string;
85
+ description: string;
86
+ required: boolean;
87
+ };
80
88
  readonly "multi-string": {
81
89
  type: string;
82
90
  minimum_length: number;
@@ -5,6 +5,7 @@ export * from "./StringOrTextFields";
5
5
  export * from "./BooleanField";
6
6
  export * from "./SelectField";
7
7
  export * from "./MultiStringField";
8
+ export * from "./QrField";
8
9
  export * from "./FieldSection";
9
10
  export * from "./utils";
10
11
  export * from "./hooks";
@@ -16,7 +16,7 @@ import { AnyField, BaseField } from "./fields";
16
16
  export type Form = Record<string, FieldValue | Promise<File>[]>;
17
17
  /** Helper type that extracts the TValue type from a BaseField. */
18
18
  export type ValueOfField<Type extends AnyField> = Type extends BaseField<infer TValue> ? TValue : never;
19
- export type FieldTypeIdentifier = "string" | "text" | "boolean" | "number" | "date" | "select" | "custom" | "section" | "multi-string" | "multi-select" | "upload";
19
+ export type FieldTypeIdentifier = "string" | "text" | "boolean" | "number" | "date" | "select" | "custom" | "section" | "multi-string" | "multi-select" | "upload" | "qr";
20
20
  export interface BaseSerializedObject<TIdentifier extends FieldTypeIdentifier = FieldTypeIdentifier> {
21
21
  description?: string | null;
22
22
  identifier: string;
@@ -50,6 +50,9 @@ export interface SerializedStringField extends BaseSerializedStringField {
50
50
  type: "string";
51
51
  input_type?: StringInputType;
52
52
  }
53
+ export interface SerializedQrField extends BaseSerializedField {
54
+ type: "qr";
55
+ }
53
56
  export interface SerializedTextField extends BaseSerializedStringField {
54
57
  type: "text";
55
58
  }
@@ -96,5 +99,5 @@ export interface SerializedUploadField extends BaseSerializedField {
96
99
  */
97
100
  maximum_files?: number;
98
101
  }
99
- export type ISerializedField = SerializedTextField | SerializedBooleanField | SerializedNumberField | SerializedDateField | SerializedStringField | SerializedSelectField | SerializedFieldSection | SerializedMultiStringField | SerializedMultiSelectField | SerializedUploadField;
102
+ export type ISerializedField = SerializedTextField | SerializedBooleanField | SerializedNumberField | SerializedDateField | SerializedStringField | SerializedSelectField | SerializedFieldSection | SerializedMultiStringField | SerializedMultiSelectField | SerializedUploadField | SerializedQrField;
100
103
  export {};
@@ -8,7 +8,7 @@ var _a;
8
8
  import * as React from "react";
9
9
  import React__default, { useState, useEffect, useRef, memo, useMemo, useCallback, createContext, createElement, useContext, forwardRef, Children, isValidElement, cloneElement, Fragment as Fragment$1, useLayoutEffect, useReducer, lazy, Suspense } from "react";
10
10
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
11
- import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, useViewportSize, Overlay, ButtonGroup, Spinner, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, Button, ButtonList, divButtonProps, OvermapDropdownMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
11
+ import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, Overlay, Button, Spinner, useViewportSize, ButtonGroup, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, ButtonList, divButtonProps, OvermapDropdownMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
12
12
  import { DepGraph } from "dependency-graph";
13
13
  import { offline as offline$1 } from "@redux-offline/redux-offline";
14
14
  import offlineConfig from "@redux-offline/redux-offline/lib/defaults";
@@ -27,6 +27,7 @@ import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
27
27
  import get from "lodash.get";
28
28
  import Linkify from "linkify-react";
29
29
  import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
30
+ import QrScannerAPI from "qr-scanner";
30
31
  import { read, utils } from "xlsx";
31
32
  import { pdfjs, Document, Page } from "react-pdf";
32
33
  import "react-pdf/dist/Page/AnnotationLayer.css";
@@ -7997,6 +7998,7 @@ class LicenseService extends BaseApiService {
7997
7998
  }
7998
7999
  }
7999
8000
  class DocumentService extends BaseApiService {
8001
+ // TODO: Support adding for project or organization
8000
8002
  add(document2) {
8001
8003
  const { store } = this.client;
8002
8004
  const currentUserId = store.getState().userReducer.currentUser.id;
@@ -8118,15 +8120,25 @@ class DocumentService extends BaseApiService {
8118
8120
  }
8119
8121
  async refreshStore() {
8120
8122
  const { store } = this.client;
8121
- const activeProjectId = store.getState().projectReducer.activeProjectId;
8122
- const result = await this.enqueueRequest({
8123
+ const state = store.getState();
8124
+ const activeProjectId = state.projectReducer.activeProjectId;
8125
+ const projectDocumentsPromise = this.enqueueRequest({
8123
8126
  description: "Get project documents",
8124
8127
  method: HttpMethod.GET,
8125
- url: `/documents/projects/${activeProjectId}/`,
8128
+ url: `/projects/${activeProjectId}/documents/`,
8129
+ blockers: [],
8130
+ blocks: []
8131
+ });
8132
+ const activeOrganizationId = state.organizationReducer.activeOrganizationId;
8133
+ const organizationDocumentsPromise = this.enqueueRequest({
8134
+ description: "Get organization documents",
8135
+ method: HttpMethod.GET,
8136
+ url: `/organizations/${activeOrganizationId}/documents/`,
8126
8137
  blockers: [],
8127
8138
  blocks: []
8128
8139
  });
8129
- store.dispatch(setDocuments(result));
8140
+ store.dispatch(setDocuments(await projectDocumentsPromise));
8141
+ store.dispatch(addDocuments(await organizationDocumentsPromise));
8130
8142
  }
8131
8143
  }
8132
8144
  class AgentService extends BaseApiService {
@@ -8231,7 +8243,7 @@ const tabTrigger = "_tabTrigger_1w0fq_69";
8231
8243
  const patchfieldBorder = "_patchfieldBorder_1w0fq_73";
8232
8244
  const title = "_title_1w0fq_73";
8233
8245
  const error = "_error_1w0fq_89";
8234
- const styles$c = {
8246
+ const styles$d = {
8235
8247
  description: description$2,
8236
8248
  floatingButtonContainer: floatingButtonContainer$2,
8237
8249
  FullScreenImageContainer: FullScreenImageContainer$2,
@@ -8352,7 +8364,7 @@ const fileName$1 = "_fileName_10o76_31";
8352
8364
  const longIconButton$1 = "_longIconButton_10o76_36";
8353
8365
  const previewImage$1 = "_previewImage_10o76_42";
8354
8366
  const FullScreenImage$1 = "_FullScreenImage_10o76_12";
8355
- const styles$b = {
8367
+ const styles$c = {
8356
8368
  description: description$1,
8357
8369
  floatingButtonContainer: floatingButtonContainer$1,
8358
8370
  FullScreenImageContainer: FullScreenImageContainer$1,
@@ -8376,7 +8388,7 @@ const FullScreenImagePreview = memo((props) => {
8376
8388
  /* @__PURE__ */ jsx(
8377
8389
  "button",
8378
8390
  {
8379
- className: styles$b.FullScreenImageContainer,
8391
+ className: styles$c.FullScreenImageContainer,
8380
8392
  type: "button",
8381
8393
  onClick: () => {
8382
8394
  setShowPreview(false);
@@ -8384,7 +8396,7 @@ const FullScreenImagePreview = memo((props) => {
8384
8396
  children: /* @__PURE__ */ jsx(
8385
8397
  "img",
8386
8398
  {
8387
- className: styles$b.FullScreenImage,
8399
+ className: styles$c.FullScreenImage,
8388
8400
  src: url,
8389
8401
  alt: name,
8390
8402
  onClick: (e) => {
@@ -8394,11 +8406,11 @@ const FullScreenImagePreview = memo((props) => {
8394
8406
  )
8395
8407
  }
8396
8408
  ),
8397
- /* @__PURE__ */ jsxs(Flex$1, { className: styles$b.TopBarContainer, align: "center", children: [
8409
+ /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.TopBarContainer, align: "center", children: [
8398
8410
  /* @__PURE__ */ jsx(
8399
8411
  IconButton,
8400
8412
  {
8401
- className: styles$b.longIconButton,
8413
+ className: styles$c.longIconButton,
8402
8414
  variant: "soft",
8403
8415
  "aria-label": "Exit preview",
8404
8416
  onClick: () => {
@@ -8407,11 +8419,11 @@ const FullScreenImagePreview = memo((props) => {
8407
8419
  children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiArrowLeftLine" })
8408
8420
  }
8409
8421
  ),
8410
- /* @__PURE__ */ jsx(Text$1, { className: styles$b.fileName, children: name }),
8422
+ /* @__PURE__ */ jsx(Text$1, { className: styles$c.fileName, children: name }),
8411
8423
  /* @__PURE__ */ jsx(
8412
8424
  IconButton,
8413
8425
  {
8414
- className: styles$b.longIconButton,
8426
+ className: styles$c.longIconButton,
8415
8427
  variant: "soft",
8416
8428
  "aria-label": `Download ${name}`,
8417
8429
  onClick: handleDownload,
@@ -8439,7 +8451,7 @@ const InputWithLabel = (props) => {
8439
8451
  /* @__PURE__ */ jsx(
8440
8452
  "img",
8441
8453
  {
8442
- className: styles$b.previewImage,
8454
+ className: styles$c.previewImage,
8443
8455
  src: resolvedImageURL,
8444
8456
  alt: resolvedImage.name,
8445
8457
  onClick: () => {
@@ -8467,7 +8479,7 @@ const InputWithHelpText = (props) => {
8467
8479
  const { helpText, children, severity } = props;
8468
8480
  return /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "1", children: [
8469
8481
  children,
8470
- /* @__PURE__ */ jsx(Flex$1, { direction: "column", children: /* @__PURE__ */ jsx(Text$1, { size: "1", severity, className: styles$b.description, children: helpText }) })
8482
+ /* @__PURE__ */ jsx(Flex$1, { direction: "column", children: /* @__PURE__ */ jsx(Text$1, { size: "1", severity, className: styles$c.description, children: helpText }) })
8471
8483
  ] });
8472
8484
  };
8473
8485
  const InputWithLabelAndHelpText = (props) => {
@@ -8701,6 +8713,9 @@ function RiArrowUpLine(props) {
8701
8713
  function RiCalendarLine(props) {
8702
8714
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z" }, "child": [] }] })(props);
8703
8715
  }
8716
+ function RiQrCodeLine(props) {
8717
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M16 17V16H13V13H16V15H18V17H17V19H15V21H13V18H15V17H16ZM21 21H17V19H19V17H21V21ZM3 3H11V11H3V3ZM5 5V9H9V5H5ZM13 3H21V11H13V3ZM15 5V9H19V5H15ZM3 13H11V21H3V13ZM5 15V19H9V15H5ZM18 13H21V15H18V13ZM6 6H8V8H6V6ZM6 16H8V18H6V16ZM16 6H18V8H16V6Z" }, "child": [] }] })(props);
8718
+ }
8704
8719
  function RiFileCopyLine(props) {
8705
8720
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M6.9998 6V3C6.9998 2.44772 7.44752 2 7.9998 2H19.9998C20.5521 2 20.9998 2.44772 20.9998 3V17C20.9998 17.5523 20.5521 18 19.9998 18H16.9998V20.9991C16.9998 21.5519 16.5499 22 15.993 22H4.00666C3.45059 22 3 21.5554 3 20.9991L3.0026 7.00087C3.0027 6.44811 3.45264 6 4.00942 6H6.9998ZM5.00242 8L5.00019 20H14.9998V8H5.00242ZM8.9998 6H16.9998V16H18.9998V4H8.9998V6Z" }, "child": [] }] })(props);
8706
8721
  }
@@ -9604,9 +9619,9 @@ const Inset = React.forwardRef((props, forwardedRef) => {
9604
9619
  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)) });
9605
9620
  });
9606
9621
  Inset.displayName = "Inset";
9607
- const sizes$7 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9622
+ const sizes$8 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9608
9623
  const headingPropDefs = {
9609
- size: { type: "enum", values: sizes$7, default: "6", responsive: true },
9624
+ size: { type: "enum", values: sizes$8, default: "6", responsive: true },
9610
9625
  weight: { ...weightProp, default: "bold" },
9611
9626
  align: alignProp,
9612
9627
  trim: trimProp,
@@ -9619,9 +9634,9 @@ const Heading = React.forwardRef((props, forwardedRef) => {
9619
9634
  return React.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, { "data-accent-color": color, ...headingProps, ref: forwardedRef, className: classNames("rt-Heading", className, withBreakpoints(size, "rt-r-size"), withBreakpoints(weight, "rt-r-weight"), withBreakpoints(align, "rt-r-ta"), withBreakpoints(trim, "rt-r-lt"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) }, asChild ? children : React.createElement(Tag, null, children));
9620
9635
  });
9621
9636
  Heading.displayName = "Heading";
9622
- const sizes$6 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9637
+ const sizes$7 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9623
9638
  const textPropDefs = {
9624
- size: { type: "enum", values: sizes$6, default: void 0, responsive: true },
9639
+ size: { type: "enum", values: sizes$7, default: void 0, responsive: true },
9625
9640
  weight: weightProp,
9626
9641
  align: alignProp,
9627
9642
  trim: trimProp,
@@ -9634,6 +9649,21 @@ const Text = React.forwardRef((props, forwardedRef) => {
9634
9649
  return React.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, { "data-accent-color": color, ...textProps, ref: forwardedRef, className: classNames("rt-Text", className, withBreakpoints(size, "rt-r-size"), withBreakpoints(weight, "rt-r-weight"), withBreakpoints(align, "rt-r-ta"), withBreakpoints(trim, "rt-r-lt"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) }, asChild ? children : React.createElement(Tag, null, children));
9635
9650
  });
9636
9651
  Text.displayName = "Text";
9652
+ const sizes$6 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9653
+ const variants$4 = ["solid", "soft", "outline", "ghost"];
9654
+ const codePropDefs = {
9655
+ size: { type: "enum", values: sizes$6, default: void 0, responsive: true },
9656
+ variant: { type: "enum", values: variants$4, default: "soft" },
9657
+ weight: weightProp,
9658
+ color: colorProp,
9659
+ highContrast: highContrastProp
9660
+ };
9661
+ const Code = React.forwardRef((props, forwardedRef) => {
9662
+ const { rest: marginRest, ...marginProps } = extractMarginProps(props);
9663
+ const { className, size = codePropDefs.size.default, variant = codePropDefs.variant.default, weight = codePropDefs.weight.default, color = codePropDefs.color.default, highContrast = codePropDefs.highContrast.default, ...codeProps } = marginRest;
9664
+ return React.createElement("code", { "data-accent-color": color, ...codeProps, ref: forwardedRef, className: classNames("rt-Code", className, withBreakpoints(size, "rt-r-size"), `rt-variant-${variant}`, withBreakpoints(weight, "rt-r-weight"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) });
9665
+ });
9666
+ Code.displayName = "Code";
9637
9667
  const Em = React.forwardRef((props, forwardedRef) => React.createElement("em", { ...props, ref: forwardedRef, className: classNames("rt-Em", props.className) }));
9638
9668
  Em.displayName = "Em";
9639
9669
  const Strong = React.forwardRef((props, forwardedRef) => React.createElement("strong", { ...props, ref: forwardedRef, className: classNames("rt-Strong", props.className) }));
@@ -12024,7 +12054,7 @@ __publicField(StringOrTextField, "_validateMax", (path) => (value, allValues) =>
12024
12054
  });
12025
12055
  const clickableLinkContainer = "_clickableLinkContainer_1ace7_1";
12026
12056
  const TextFieldInputCopy = "_TextFieldInputCopy_1ace7_5";
12027
- const styles$a = {
12057
+ const styles$b = {
12028
12058
  clickableLinkContainer,
12029
12059
  TextFieldInputCopy
12030
12060
  };
@@ -12053,13 +12083,13 @@ const StringInput = memo((props) => {
12053
12083
  placeholder: field.placeholder,
12054
12084
  color
12055
12085
  }
12056
- ) : /* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$a.clickableLinkContainer, children: [
12086
+ ) : /* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$b.clickableLinkContainer, children: [
12057
12087
  /* @__PURE__ */ jsx(
12058
12088
  "div",
12059
12089
  {
12060
12090
  className: classNames$1(
12061
12091
  "rt-TextFieldInput rt-r-size-2 rt-variant-surface",
12062
- styles$a.TextFieldInputCopy
12092
+ styles$b.TextFieldInputCopy
12063
12093
  ),
12064
12094
  children: /* @__PURE__ */ jsx(
12065
12095
  Linkify,
@@ -12751,6 +12781,158 @@ __publicField(_MultiSelectField, "fieldTypeName", "Multi-select");
12751
12781
  __publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
12752
12782
  __publicField(_MultiSelectField, "Icon", RiCheckboxLine);
12753
12783
  let MultiSelectField = _MultiSelectField;
12784
+ const QrScannerWrapper = "_QrScannerWrapper_1puz3_1";
12785
+ const styles$a = {
12786
+ QrScannerWrapper
12787
+ };
12788
+ const QrInput = memo((props) => {
12789
+ const [{ inputId, labelId, label, helpText, size, severity, showInputOnly, field, fieldProps }, rest] = useFormikInput(props);
12790
+ const [showQrScanner, setShowQrScanner] = useState(false);
12791
+ const value = fieldProps.value;
12792
+ const handleQrScan = useCallback(
12793
+ (data) => {
12794
+ fieldProps.onChange({ target: { value: data } });
12795
+ setShowQrScanner(false);
12796
+ },
12797
+ [fieldProps]
12798
+ );
12799
+ const handleClearScanResult = useCallback(() => {
12800
+ fieldProps.onChange({ target: { value: "" } });
12801
+ }, [fieldProps]);
12802
+ const handleScanButtonClicked = useCallback(() => {
12803
+ setShowQrScanner(true);
12804
+ }, []);
12805
+ const handleQrScannerClose = useCallback(() => {
12806
+ setShowQrScanner(false);
12807
+ }, []);
12808
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxs(
12809
+ InputWithLabel,
12810
+ {
12811
+ size,
12812
+ severity,
12813
+ inputId,
12814
+ labelId,
12815
+ label: showInputOnly ? label : "",
12816
+ image: showInputOnly ? void 0 : field.image,
12817
+ flexProps: { direction: "column", justify: "start", align: "start", gap: "1" },
12818
+ children: [
12819
+ /* @__PURE__ */ jsx(
12820
+ Overlay,
12821
+ {
12822
+ open: showQrScanner,
12823
+ content: () => /* @__PURE__ */ jsx(QrScanner, { onQrScan: handleQrScan, onClose: handleQrScannerClose }),
12824
+ onOpenChange: setShowQrScanner
12825
+ }
12826
+ ),
12827
+ /* @__PURE__ */ jsxs(Flex, { width: "max-content", gap: "1", align: "center", children: [
12828
+ /* @__PURE__ */ jsxs(Button, { ...rest, variant: "soft", onClick: handleScanButtonClicked, children: [
12829
+ /* @__PURE__ */ jsx(RiIcon, { icon: "RiQrCodeLine" }),
12830
+ "Scan"
12831
+ ] }),
12832
+ value && /* @__PURE__ */ jsx(Text, { color: "jade", size: "1", children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCheckLine", style: { verticalAlign: "bottom" } }) })
12833
+ ] }),
12834
+ value && /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { width: "max-content", gap: "2", align: "center", children: [
12835
+ /* @__PURE__ */ jsx(Code, { color: "gray", highContrast: true, children: value }),
12836
+ /* @__PURE__ */ jsx(
12837
+ IconButton,
12838
+ {
12839
+ severity: "info",
12840
+ variant: "ghost",
12841
+ "aria-label": "delete",
12842
+ size: "small",
12843
+ onClick: handleClearScanResult,
12844
+ children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCloseLine" })
12845
+ }
12846
+ )
12847
+ ] }) })
12848
+ ]
12849
+ }
12850
+ ) });
12851
+ });
12852
+ QrInput.displayName = "QrInput";
12853
+ const QrScanner = memo((props) => {
12854
+ const { onQrScan, onClose } = props;
12855
+ const videoRef = useRef(null);
12856
+ const [isScannerLoading, setIsScannerLoading] = useState(false);
12857
+ useEffect(() => {
12858
+ if (!videoRef.current)
12859
+ return;
12860
+ const qrScanner = new QrScannerAPI(
12861
+ videoRef.current,
12862
+ (result) => {
12863
+ const data = result.data;
12864
+ onQrScan(data);
12865
+ qrScanner.destroy();
12866
+ },
12867
+ {
12868
+ highlightCodeOutline: true,
12869
+ highlightScanRegion: true,
12870
+ maxScansPerSecond: 1
12871
+ }
12872
+ );
12873
+ setIsScannerLoading(true);
12874
+ qrScanner.start().then(() => {
12875
+ setIsScannerLoading(false);
12876
+ }).catch(() => {
12877
+ setIsScannerLoading(false);
12878
+ });
12879
+ }, [onQrScan]);
12880
+ return /* @__PURE__ */ jsxs(
12881
+ Flex,
12882
+ {
12883
+ className: styles$a.QrScannerWrapper,
12884
+ width: "100%",
12885
+ height: "100%",
12886
+ direction: "column",
12887
+ gap: "2",
12888
+ justify: "center",
12889
+ position: "relative",
12890
+ children: [
12891
+ /* @__PURE__ */ jsx(Flex, { width: "100%", position: "absolute", top: "0", p: "2", children: /* @__PURE__ */ jsx(IconButton, { "aria-label": "close", variant: "soft", severity: "info", highContrast: true, onClick: onClose, children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCloseLine" }) }) }),
12892
+ /* @__PURE__ */ jsxs(Box, { style: { maxWidth: "100%", maxHeight: "100%" }, position: "relative", children: [
12893
+ /* @__PURE__ */ jsx("video", { ref: videoRef, style: { width: "100%", height: "100%" } }),
12894
+ isScannerLoading && /* @__PURE__ */ jsx(
12895
+ Flex,
12896
+ {
12897
+ position: "absolute",
12898
+ inset: "0",
12899
+ style: { background: "var(--color-background)" },
12900
+ justify: "center",
12901
+ align: "center",
12902
+ children: /* @__PURE__ */ jsx(Spinner, {})
12903
+ }
12904
+ )
12905
+ ] })
12906
+ ]
12907
+ }
12908
+ );
12909
+ });
12910
+ QrScanner.displayName = "QrScanner";
12911
+ const emptyQrField = {
12912
+ ...emptyBaseField,
12913
+ type: "qr"
12914
+ };
12915
+ const _QrField = class _QrField extends BaseField {
12916
+ constructor(options) {
12917
+ super({ ...options, type: "qr" });
12918
+ __publicField(this, "onlyValidateAfterTouched", false);
12919
+ }
12920
+ serialize() {
12921
+ return super._serialize();
12922
+ }
12923
+ static deserialize(data) {
12924
+ if (data.type !== "qr")
12925
+ throw new Error("Type mismatch.");
12926
+ return new _QrField(data);
12927
+ }
12928
+ getInput(props) {
12929
+ return /* @__PURE__ */ jsx(QrInput, { ...props, field: this });
12930
+ }
12931
+ };
12932
+ __publicField(_QrField, "fieldTypeName", "QR");
12933
+ __publicField(_QrField, "fieldTypeDescription", "Used for scanning/reading QR codes.");
12934
+ __publicField(_QrField, "Icon", RiQrCodeLine);
12935
+ let QrField = _QrField;
12754
12936
  const FieldInputCloner = memo((props) => {
12755
12937
  const { field, ...rest } = props;
12756
12938
  const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
@@ -14008,6 +14190,7 @@ const FieldTypeToClsMapping = {
14008
14190
  text: TextField,
14009
14191
  custom: CustomField,
14010
14192
  upload: UploadField,
14193
+ qr: QrField,
14011
14194
  // TODO: Underscore
14012
14195
  "multi-string": MultiStringField,
14013
14196
  "multi-select": MultiSelectField
@@ -14021,6 +14204,7 @@ const FieldTypeToEmptyFieldMapping = {
14021
14204
  text: emptyTextField,
14022
14205
  custom: emptyCustomField,
14023
14206
  upload: emptyUploadField,
14207
+ qr: emptyQrField,
14024
14208
  // TODO: Underscore
14025
14209
  "multi-string": emptyMultiStringField,
14026
14210
  "multi-select": emptyMultiSelectField
@@ -14108,7 +14292,7 @@ const FieldSectionLayout = memo((props) => {
14108
14292
  return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "3", children: [
14109
14293
  /* @__PURE__ */ jsxs(Flex$1, { direction: "column", children: [
14110
14294
  /* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
14111
- /* @__PURE__ */ jsx(Text$1, { className: styles$b.description, children: description2 })
14295
+ /* @__PURE__ */ jsx(Text$1, { className: styles$c.description, children: description2 })
14112
14296
  ] }),
14113
14297
  inputs
14114
14298
  ] }) });
@@ -14351,7 +14535,7 @@ const FormRenderer = memo(
14351
14535
  [schema.title]
14352
14536
  );
14353
14537
  const Description = useMemo(
14354
- () => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text$1, { className: styles$b.description, children: schema.description }) : schema.description,
14538
+ () => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text$1, { className: styles$c.description, children: schema.description }) : schema.description,
14355
14539
  [schema.description]
14356
14540
  );
14357
14541
  const inputs = useFieldInputs(schema.fields, { formId: formId2, disabled: readonly });
@@ -14367,7 +14551,7 @@ const FormRenderer = memo(
14367
14551
  !hideDescription && Description
14368
14552
  ] }) }),
14369
14553
  inputs,
14370
- !readonly && /* @__PURE__ */ jsxs(Flex$1, { className: styles$b.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
14554
+ !readonly && /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
14371
14555
  cancelText && /* @__PURE__ */ jsx(Button, { severity: "info", ...buttonProps, type: "button", onClick: onCancel, children: cancelText }),
14372
14556
  /* @__PURE__ */ jsx(Button, { ...buttonProps, type: "submit", disabled: !formik.isValid, children: submitText })
14373
14557
  ] })
@@ -15715,12 +15899,12 @@ const FormBuilder = memo(
15715
15899
  });
15716
15900
  const previewSchema = useMemo(() => formRevisionToSchema(formik.values), [formik.values]);
15717
15901
  return /* @__PURE__ */ jsx(Tabs.Root, { ref, defaultValue: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "2", children: [
15718
- showTabs && /* @__PURE__ */ jsxs(Tabs.List, { className: classNames$1(styles$c.tabsList, tabsListClassName), children: [
15719
- /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$c.tabTrigger, value: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15902
+ showTabs && /* @__PURE__ */ jsxs(Tabs.List, { className: classNames$1(styles$d.tabsList, tabsListClassName), children: [
15903
+ /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$d.tabTrigger, value: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15720
15904
  /* @__PURE__ */ jsx(RiIcon, { icon: "RiPencilLine" }),
15721
15905
  "Edit"
15722
15906
  ] }) }),
15723
- /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$c.tabTrigger, value: "preview", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15907
+ /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$d.tabTrigger, value: "preview", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15724
15908
  /* @__PURE__ */ jsx(RiIcon, { icon: "RiEyeLine" }),
15725
15909
  "Preview"
15726
15910
  ] }) })
@@ -15744,8 +15928,8 @@ const FormBuilder = memo(
15744
15928
  render: ({ setValue, value, meta }) => /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: meta.error ?? null, children: /* @__PURE__ */ jsx(
15745
15929
  Input,
15746
15930
  {
15747
- className: classNames$1(styles$c.title, {
15748
- [styles$c.error]: meta.error
15931
+ className: classNames$1(styles$d.title, {
15932
+ [styles$d.error]: meta.error
15749
15933
  }),
15750
15934
  placeholder: "Form title",
15751
15935
  value,
@@ -15767,7 +15951,7 @@ const FormBuilder = memo(
15767
15951
  render: ({ setValue, value }) => /* @__PURE__ */ jsx(
15768
15952
  TextArea,
15769
15953
  {
15770
- className: styles$c.description,
15954
+ className: styles$d.description,
15771
15955
  placeholder: "Explain the purpose of this form",
15772
15956
  value,
15773
15957
  onChange: (event) => {
@@ -15785,7 +15969,7 @@ const FormBuilder = memo(
15785
15969
  /* @__PURE__ */ jsx(FieldsEditor, { fieldsOnly }),
15786
15970
  /* @__PURE__ */ jsx(Text$1, { severity: "danger", size: "1", children: typeof formik.errors.fields === "string" && formik.errors.fields })
15787
15971
  ] }),
15788
- /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
15972
+ /* @__PURE__ */ jsxs(Flex$1, { className: styles$d.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
15789
15973
  onCancel && /* @__PURE__ */ jsx(Button, { type: "button", variant: "solid", severity: "info", onClick: onCancel, children: "Cancel" }),
15790
15974
  /* @__PURE__ */ jsx(Button, { type: "submit", children: "Save form" })
15791
15975
  ] })
@@ -15820,6 +16004,9 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
15820
16004
  NumberInput,
15821
16005
  PatchField,
15822
16006
  PatchFormProvider,
16007
+ QrField,
16008
+ QrInput,
16009
+ QrScanner,
15823
16010
  SelectField,
15824
16011
  SelectInput,
15825
16012
  StringField,
@@ -15834,6 +16021,7 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
15834
16021
  emptyMultiSelectField,
15835
16022
  emptyMultiStringField,
15836
16023
  emptyNumberField,
16024
+ emptyQrField,
15837
16025
  emptySelectField,
15838
16026
  emptyStringField,
15839
16027
  emptyTextField,
@@ -15924,6 +16112,9 @@ export {
15924
16112
  ProjectFileService,
15925
16113
  ProjectService,
15926
16114
  ProjectType,
16115
+ QrField,
16116
+ QrInput,
16117
+ QrScanner,
15927
16118
  SDKContext,
15928
16119
  SDKProvider,
15929
16120
  SUPPORTED_IMAGE_FILE_TYPES,
@@ -16047,6 +16238,7 @@ export {
16047
16238
  emptyMultiSelectField,
16048
16239
  emptyMultiStringField,
16049
16240
  emptyNumberField,
16241
+ emptyQrField,
16050
16242
  emptySelectField,
16051
16243
  emptyStringField,
16052
16244
  emptyTextField,