@overmap-ai/forms 1.0.32-react-flow-david-fixes.13 → 1.0.32-react-flow-david-fixes.14

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.
@@ -0,0 +1,9 @@
1
+ import { Popover } from '@overmap-ai/blocks';
2
+ import { ComponentPropsWithoutRef } from 'react';
3
+ interface MultiStringPopoverProps extends ComponentPropsWithoutRef<typeof Popover.Root>, ComponentPropsWithoutRef<typeof Popover.Content> {
4
+ placeholder?: string;
5
+ values: string[];
6
+ onValuesChange: (values: string[]) => void;
7
+ }
8
+ export declare const MultiStringPopover: import('react').NamedExoticComponent<MultiStringPopoverProps>;
9
+ export {};
@@ -0,0 +1,9 @@
1
+ import { Popover } from '@overmap-ai/blocks';
2
+ import { ComponentPropsWithoutRef } from 'react';
3
+ interface NumberInputPopoverProps extends ComponentPropsWithoutRef<typeof Popover.Root>, ComponentPropsWithoutRef<typeof Popover.Content> {
4
+ placeholder?: string;
5
+ value?: number | null;
6
+ onValueChange?: (value: number | null) => void;
7
+ }
8
+ export declare const NumberInputPopover: import('react').NamedExoticComponent<NumberInputPopoverProps>;
9
+ export {};
@@ -1,6 +1,8 @@
1
1
  export * from './ConditionModifierDropdown';
2
2
  export * from './constants';
3
3
  export * from './DayPickerPopover';
4
+ export * from './MultiStringPopover';
5
+ export * from './NumberInputPopover';
4
6
  export * from './RemoveConditionButton';
5
7
  export * from './SelectFieldOptionMultiSelectGroup';
6
8
  export * from './SelectFieldOptionSelectGroup';
package/dist/forms.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
5
- import { Card, LuIcon, Text, Spinner, ButtonGroup, Tooltip, IconButton, Separator, Input, Badge, Checkbox, CheckboxGroup, Popover, Button, DayPicker, Menu, OneTimePasswordField, RadioGroup, TextArea, useToast, stopPropagation, Heading, HoverCard, ToggleGroup } from "@overmap-ai/blocks";
5
+ import { Card, LuIcon, Text, Spinner, ButtonGroup, Tooltip, IconButton, Separator, Input, Badge, Checkbox, CheckboxGroup, Popover, Button, DayPicker, Menu, OneTimePasswordField, RadioGroup, TextArea, useToast, stopPropagation, Heading, ToggleGroup } from "@overmap-ai/blocks";
6
6
  import { cx } from "class-variance-authority";
7
7
  import * as React from "react";
8
8
  import { memo, forwardRef, createContext, useContext, useState, useRef, useCallback, useMemo, useEffect, Fragment as Fragment$1, use, useLayoutEffect, useId as useId$1 } from "react";
@@ -2425,7 +2425,7 @@ const MultiStringInput = memo((props) => {
2425
2425
  "aria-label": "Add option",
2426
2426
  disabled: !!internalError || disabled,
2427
2427
  onClick: addOption,
2428
- children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
2428
+ children: /* @__PURE__ */ jsx(Plus, {})
2429
2429
  }
2430
2430
  )
2431
2431
  ] })
@@ -33032,7 +33032,7 @@ class BaseCondition extends Observable {
33032
33032
  id: this.id,
33033
33033
  type: this.field.type,
33034
33034
  fieldId: this.field.identifier,
33035
- conditionValue: this.modifiers[this.conditionModifier].modifier.serialize(this.conditionValue),
33035
+ conditionValue: this.conditionValue !== void 0 ? this.modifiers[this.conditionModifier].modifier.serialize(this.conditionValue) : void 0,
33036
33036
  conditionModifier: this.conditionModifier
33037
33037
  };
33038
33038
  }
@@ -33121,10 +33121,150 @@ const DayPickerPopover = memo((props) => {
33121
33121
  const { children, open, onOpenChange, defaultOpen, modal, size, align, accentColor = "base", ...rest } = props;
33122
33122
  return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33123
33123
  /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children }),
33124
- /* @__PURE__ */ jsx(Popover.Content, { size, align, children: /* @__PURE__ */ jsx(DayPicker, { size, autoFocus: true, accentColor, ...rest }) })
33124
+ /* @__PURE__ */ jsx(Popover.Content, { size, align, children: /* @__PURE__ */ jsx(DayPicker, { size, accentColor, ...rest }) })
33125
33125
  ] });
33126
33126
  });
33127
33127
  DayPickerPopover.displayName = "DayPickerPopover";
33128
+ const MultiStringPopover = memo((props) => {
33129
+ const {
33130
+ children,
33131
+ open,
33132
+ onOpenChange,
33133
+ defaultOpen,
33134
+ modal,
33135
+ size,
33136
+ accentColor = "base",
33137
+ values,
33138
+ onValuesChange,
33139
+ placeholder = "Enter text",
33140
+ ...rest
33141
+ } = props;
33142
+ const [inputValue, setInputValue] = useState("");
33143
+ const handleInputValueChange = useCallback((e) => {
33144
+ setInputValue(e.target.value);
33145
+ }, []);
33146
+ const handleInputKeyDown = useCallback(
33147
+ (e) => {
33148
+ if (e.key !== "Enter") return;
33149
+ e.preventDefault();
33150
+ e.stopPropagation();
33151
+ onValuesChange([...values, inputValue]);
33152
+ setInputValue("");
33153
+ },
33154
+ [inputValue, onValuesChange, values]
33155
+ );
33156
+ const handleAddValueClick = useCallback(() => {
33157
+ onValuesChange([...values, inputValue]);
33158
+ setInputValue("");
33159
+ }, [inputValue, onValuesChange, values]);
33160
+ const handleRemoveValueClick = useCallback(
33161
+ (index) => {
33162
+ const valuesCopy = [...values];
33163
+ valuesCopy.splice(index, 1);
33164
+ onValuesChange(valuesCopy);
33165
+ },
33166
+ [onValuesChange, values]
33167
+ );
33168
+ return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33169
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children }),
33170
+ /* @__PURE__ */ jsx(Popover.Content, { size, onClick: stopPropagation, accentColor, ...rest, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
33171
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
33172
+ /* @__PURE__ */ jsx(Input.Root, { className: "grow", accentColor: "base", variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(
33173
+ Input.Field,
33174
+ {
33175
+ value: inputValue,
33176
+ onChange: handleInputValueChange,
33177
+ onKeyDown: handleInputKeyDown,
33178
+ placeholder,
33179
+ ...rest
33180
+ }
33181
+ ) }),
33182
+ /* @__PURE__ */ jsx(
33183
+ IconButton,
33184
+ {
33185
+ size: "sm",
33186
+ accentColor: "base",
33187
+ variant: "soft",
33188
+ type: "button",
33189
+ onClick: handleAddValueClick,
33190
+ children: /* @__PURE__ */ jsx(LuIcon, { icon: "plus" })
33191
+ }
33192
+ )
33193
+ ] }),
33194
+ values.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children: values.map((value, index) => /* @__PURE__ */ jsxs(
33195
+ Badge,
33196
+ {
33197
+ className: "flex items-center justify-between gap-2",
33198
+ accentColor: "base",
33199
+ size: "sm",
33200
+ variant: "soft",
33201
+ children: [
33202
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: value }),
33203
+ /* @__PURE__ */ jsx(
33204
+ IconButton,
33205
+ {
33206
+ size: "xs",
33207
+ variant: "ghost",
33208
+ type: "button",
33209
+ accentColor: "base",
33210
+ onClick: () => {
33211
+ handleRemoveValueClick(index);
33212
+ },
33213
+ children: /* @__PURE__ */ jsx(LuIcon, { icon: "x" })
33214
+ }
33215
+ )
33216
+ ]
33217
+ },
33218
+ `${value}-${index}`
33219
+ )) })
33220
+ ] }) })
33221
+ ] });
33222
+ });
33223
+ MultiStringPopover.displayName = "NumberInputPopover";
33224
+ const NumberInputPopover = memo((props) => {
33225
+ const {
33226
+ children,
33227
+ open,
33228
+ onOpenChange,
33229
+ defaultOpen,
33230
+ modal,
33231
+ size,
33232
+ accentColor = "base",
33233
+ value: controlledValue,
33234
+ onValueChange,
33235
+ placeholder = "Enter a number",
33236
+ ...rest
33237
+ } = props;
33238
+ const [value, setValue] = useState(null);
33239
+ useEffect(() => {
33240
+ if (controlledValue !== void 0) setValue(controlledValue);
33241
+ }, [controlledValue]);
33242
+ const handleChange = useCallback((e) => {
33243
+ const valueAsNumber = e.target.valueAsNumber;
33244
+ setValue(!isNaN(valueAsNumber) ? valueAsNumber : null);
33245
+ }, []);
33246
+ const handleBlur = useCallback(
33247
+ (e) => {
33248
+ const valueAsNumber = e.target.valueAsNumber;
33249
+ onValueChange == null ? void 0 : onValueChange(!isNaN(valueAsNumber) ? valueAsNumber : null);
33250
+ },
33251
+ [onValueChange]
33252
+ );
33253
+ return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33254
+ /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children }),
33255
+ /* @__PURE__ */ jsx(Popover.Content, { size, onClick: stopPropagation, ...rest, children: /* @__PURE__ */ jsx(Input.Root, { size, accentColor, children: /* @__PURE__ */ jsx(
33256
+ Input.Field,
33257
+ {
33258
+ placeholder,
33259
+ type: "number",
33260
+ value: value ?? "",
33261
+ onChange: handleChange,
33262
+ onBlur: handleBlur
33263
+ }
33264
+ ) }) })
33265
+ ] });
33266
+ });
33267
+ NumberInputPopover.displayName = "NumberInputPopover";
33128
33268
  const RemoveConditionButton = (props) => {
33129
33269
  const { condition, onClick, ...rest } = props;
33130
33270
  const handleRemoveFilter = useCallback(() => {
@@ -33592,11 +33732,18 @@ class MultiSelectFieldCondition extends BaseCondition {
33592
33732
  return /* @__PURE__ */ jsx(MultiSelectFieldConditionCell, { condition: this, ...props }, this.id);
33593
33733
  }
33594
33734
  }
33735
+ const EMPTY_ARRAY = [];
33595
33736
  const MultiStringFieldConditionCell = (props) => {
33596
33737
  const { condition, onRemove } = props;
33597
33738
  const field = condition.field;
33598
33739
  const conditionValue = condition.getConditionValue();
33599
33740
  const conditionModifier = condition.getConditionModifier();
33741
+ const handleValuesChange = useCallback(
33742
+ (values) => {
33743
+ condition.setConditionValue(values.length > 0 ? values : void 0);
33744
+ },
33745
+ [condition]
33746
+ );
33600
33747
  const getFilterValueRender = () => {
33601
33748
  if (conditionValue === void 0) return "...";
33602
33749
  if (conditionValue === null) return "empty";
@@ -33611,15 +33758,15 @@ const MultiStringFieldConditionCell = (props) => {
33611
33758
  return `${conditionValue.length} values`;
33612
33759
  }
33613
33760
  };
33614
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex w-max max-w-full min-w-0 gap-0.5", size: "sm", variant: "fill", accentColor: "base", children: [
33761
+ return /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex w-max max-w-full min-w-0 gap-0.5", size: "sm", variant: "fill", accentColor: "base", children: [
33615
33762
  /* @__PURE__ */ jsxs(Badge, { className: "min-w-0 shrink-1", size: "sm", variant: "fill", accentColor: "base", children: [
33616
33763
  /* @__PURE__ */ jsx(LuIcon, { icon: fieldIcons[field.type] }),
33617
33764
  /* @__PURE__ */ jsx("span", { className: "truncate", children: field.label || UNLABELLED_FIELD_LABEL })
33618
33765
  ] }),
33619
33766
  /* @__PURE__ */ jsx(ConditionModifierDropdown, { condition, children: /* @__PURE__ */ jsx(Button, { type: "button", children: condition.modifiers[conditionModifier].modifier.label }) }),
33620
- /* @__PURE__ */ jsx(Button, { type: "button", className: "truncate", children: getFilterValueRender() }),
33767
+ /* @__PURE__ */ jsx(MultiStringPopover, { values: conditionValue ?? EMPTY_ARRAY, onValuesChange: handleValuesChange, children: /* @__PURE__ */ jsx(Button, { type: "button", className: "truncate", children: getFilterValueRender() }) }),
33621
33768
  /* @__PURE__ */ jsx(RemoveConditionButton, { condition, onClick: onRemove })
33622
- ] }) });
33769
+ ] });
33623
33770
  };
33624
33771
  const modifiers$8 = {
33625
33772
  equals: createConditionModifierConfig({
@@ -33678,88 +33825,55 @@ const NumberFieldConditionCell = (props) => {
33678
33825
  const getFilterValueUi = () => {
33679
33826
  switch (conditionModifier) {
33680
33827
  case "equals":
33681
- case "notEquals": {
33682
- const equalsModifier = condition.modifiers.equals;
33683
- const equalsFilterValue = conditionValue !== void 0 && equalsModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33684
- return /* @__PURE__ */ jsxs(Menu.Root, { children: [
33685
- /* @__PURE__ */ jsx(Menu.ClickTrigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", className: "truncate", children: equalsFilterValue !== void 0 ? equalsFilterValue ?? "empty" : "..." }) }),
33686
- /* @__PURE__ */ jsx(Menu.Content, { size: "sm", children: /* @__PURE__ */ jsx(Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsx(
33687
- Input.Field,
33688
- {
33689
- placeholder: "Enter a number",
33690
- type: "number",
33691
- value: equalsFilterValue ?? "",
33692
- onChange: (e) => {
33693
- const value = e.target.valueAsNumber;
33694
- condition.setConditionValue(isNaN(value) ? void 0 : value);
33695
- }
33696
- }
33697
- ) }) })
33698
- ] });
33699
- }
33700
33828
  case "greaterThanOrEquals":
33701
33829
  case "lessThanOrEquals":
33702
33830
  case "greaterThan":
33703
33831
  case "lessThan": {
33704
33832
  const greaterThanModifier = condition.modifiers.greaterThan;
33705
33833
  const greaterThanFitlerValue = conditionValue !== void 0 && greaterThanModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33706
- return /* @__PURE__ */ jsxs(Popover.Root, { children: [
33707
- /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { type: "button", className: "truncate", children: greaterThanFitlerValue ?? "..." }) }),
33708
- /* @__PURE__ */ jsx(Popover.Content, { size: "sm", children: /* @__PURE__ */ jsx(Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsx(
33709
- Input.Field,
33710
- {
33711
- placeholder: "Enter a number",
33712
- type: "number",
33713
- value: greaterThanFitlerValue ?? "",
33714
- onChange: (e) => {
33715
- const value = e.target.valueAsNumber;
33716
- condition.setConditionValue(isNaN(value) ? void 0 : value);
33717
- }
33718
- }
33719
- ) }) })
33720
- ] });
33834
+ return /* @__PURE__ */ jsx(
33835
+ NumberInputPopover,
33836
+ {
33837
+ value: greaterThanFitlerValue ?? null,
33838
+ onValueChange: (value) => condition.setConditionValue(value ?? void 0),
33839
+ size: "sm",
33840
+ children: /* @__PURE__ */ jsx(Button, { type: "button", className: "truncate", children: greaterThanFitlerValue !== void 0 ? greaterThanFitlerValue ?? "empty" : "..." })
33841
+ }
33842
+ );
33721
33843
  }
33722
33844
  case "inRange":
33723
33845
  case "notInRange": {
33724
33846
  const inRangeModifier = condition.modifiers.inRange;
33725
33847
  const rangeFilterValue = conditionValue !== void 0 && inRangeModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33726
33848
  return /* @__PURE__ */ jsxs(Fragment, { children: [
33727
- /* @__PURE__ */ jsxs(Popover.Root, { children: [
33728
- /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "..." }) }),
33729
- /* @__PURE__ */ jsx(Popover.Content, { size: "sm", children: /* @__PURE__ */ jsx(Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsx(
33730
- Input.Field,
33731
- {
33732
- placeholder: "Enter a number",
33733
- type: "number",
33734
- value: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "",
33735
- onChange: (e) => {
33736
- const value = e.target.valueAsNumber;
33737
- condition.setConditionValue({
33738
- from: !isNaN(value) ? value : null,
33739
- to: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null
33740
- });
33741
- }
33742
- }
33743
- ) }) })
33744
- ] }),
33745
- /* @__PURE__ */ jsxs(Popover.Root, { children: [
33746
- /* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "..." }) }),
33747
- /* @__PURE__ */ jsx(Popover.Content, { size: "sm", children: /* @__PURE__ */ jsx(Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsx(
33748
- Input.Field,
33749
- {
33750
- placeholder: "Enter a number",
33751
- type: "number",
33752
- value: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "",
33753
- onChange: (e) => {
33754
- const value = e.target.valueAsNumber;
33755
- condition.setConditionValue({
33756
- from: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33757
- to: !isNaN(value) ? value : null
33758
- });
33759
- }
33760
- }
33761
- ) }) })
33762
- ] })
33849
+ /* @__PURE__ */ jsx(
33850
+ NumberInputPopover,
33851
+ {
33852
+ value: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33853
+ onValueChange: (value) => {
33854
+ condition.setConditionValue({
33855
+ from: value,
33856
+ to: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null
33857
+ });
33858
+ },
33859
+ size: "sm",
33860
+ children: /* @__PURE__ */ jsx(Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "..." })
33861
+ }
33862
+ ),
33863
+ /* @__PURE__ */ jsx(
33864
+ NumberInputPopover,
33865
+ {
33866
+ value: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null,
33867
+ onValueChange: (value) => {
33868
+ condition.setConditionValue({
33869
+ from: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33870
+ to: value
33871
+ });
33872
+ },
33873
+ size: "sm",
33874
+ children: /* @__PURE__ */ jsx(Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "..." })
33875
+ }
33876
+ )
33763
33877
  ] });
33764
33878
  }
33765
33879
  }
@@ -34707,7 +34821,8 @@ const _FieldSection = class _FieldSection extends BaseFormElement {
34707
34821
  duplicate(identifier) {
34708
34822
  return new _FieldSection({
34709
34823
  ...this.getOptions(),
34710
- identifier
34824
+ identifier,
34825
+ fields: this.fields.map((field) => field.duplicate(v4()))
34711
34826
  });
34712
34827
  }
34713
34828
  setOptions(options) {
@@ -35152,7 +35267,6 @@ const FieldBuilder = memo((props) => {
35152
35267
  const error = get(errors, field2.identifier);
35153
35268
  return error && (typeof error !== "object" || Object.values(error).length > 0);
35154
35269
  });
35155
- const previewInput = useFieldInput(field, { formId, showInputOnly: false });
35156
35270
  const handleFieldImageClick = useCallback(() => {
35157
35271
  if (!resolvedImage) return;
35158
35272
  openImageViewer(() => ({
@@ -35229,15 +35343,7 @@ const FieldBuilder = memo((props) => {
35229
35343
  }
35230
35344
  )
35231
35345
  ] }),
35232
- directlyShownFields.length > 0 && /* @__PURE__ */ jsx("div", { className: "w-full", children: directlyShownInputs }),
35233
- /* @__PURE__ */ jsx(Separator, { size: "full" }),
35234
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 items-center", children: [
35235
- /* @__PURE__ */ jsxs(HoverCard.Root, { children: [
35236
- /* @__PURE__ */ jsx(HoverCard.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(Badge, { icon: true, size: "sm", variant: "soft", accentColor: "base", children: /* @__PURE__ */ jsx(LuIcon, { icon: "eye" }) }) }),
35237
- /* @__PURE__ */ jsx(HoverCard.Content, { className: "w-[225px]", size: "sm", align: "start", children: /* @__PURE__ */ jsx(Text, { size: "sm", accentColor: "base", children: "This is a preview of the field as it will be rendered in the form." }) })
35238
- ] }),
35239
- /* @__PURE__ */ jsx("div", { className: "grow h-max min-w-0", children: previewInput })
35240
- ] })
35346
+ directlyShownFields.length > 0 && /* @__PURE__ */ jsx("div", { className: "w-full", children: directlyShownInputs })
35241
35347
  ] });
35242
35348
  });
35243
35349
  FieldBuilder.displayName = "FieldBuilder";
@@ -2427,7 +2427,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
2427
2427
  "aria-label": "Add option",
2428
2428
  disabled: !!internalError || disabled,
2429
2429
  onClick: addOption,
2430
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" })
2430
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {})
2431
2431
  }
2432
2432
  )
2433
2433
  ] })
@@ -33034,7 +33034,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
33034
33034
  id: this.id,
33035
33035
  type: this.field.type,
33036
33036
  fieldId: this.field.identifier,
33037
- conditionValue: this.modifiers[this.conditionModifier].modifier.serialize(this.conditionValue),
33037
+ conditionValue: this.conditionValue !== void 0 ? this.modifiers[this.conditionModifier].modifier.serialize(this.conditionValue) : void 0,
33038
33038
  conditionModifier: this.conditionModifier
33039
33039
  };
33040
33040
  }
@@ -33123,10 +33123,150 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
33123
33123
  const { children, open, onOpenChange, defaultOpen, modal, size, align, accentColor = "base", ...rest } = props;
33124
33124
  return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33125
33125
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children }),
33126
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size, align, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.DayPicker, { size, autoFocus: true, accentColor, ...rest }) })
33126
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size, align, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.DayPicker, { size, accentColor, ...rest }) })
33127
33127
  ] });
33128
33128
  });
33129
33129
  DayPickerPopover.displayName = "DayPickerPopover";
33130
+ const MultiStringPopover = React.memo((props) => {
33131
+ const {
33132
+ children,
33133
+ open,
33134
+ onOpenChange,
33135
+ defaultOpen,
33136
+ modal,
33137
+ size,
33138
+ accentColor = "base",
33139
+ values,
33140
+ onValuesChange,
33141
+ placeholder = "Enter text",
33142
+ ...rest
33143
+ } = props;
33144
+ const [inputValue, setInputValue] = React.useState("");
33145
+ const handleInputValueChange = React.useCallback((e) => {
33146
+ setInputValue(e.target.value);
33147
+ }, []);
33148
+ const handleInputKeyDown = React.useCallback(
33149
+ (e) => {
33150
+ if (e.key !== "Enter") return;
33151
+ e.preventDefault();
33152
+ e.stopPropagation();
33153
+ onValuesChange([...values, inputValue]);
33154
+ setInputValue("");
33155
+ },
33156
+ [inputValue, onValuesChange, values]
33157
+ );
33158
+ const handleAddValueClick = React.useCallback(() => {
33159
+ onValuesChange([...values, inputValue]);
33160
+ setInputValue("");
33161
+ }, [inputValue, onValuesChange, values]);
33162
+ const handleRemoveValueClick = React.useCallback(
33163
+ (index) => {
33164
+ const valuesCopy = [...values];
33165
+ valuesCopy.splice(index, 1);
33166
+ onValuesChange(valuesCopy);
33167
+ },
33168
+ [onValuesChange, values]
33169
+ );
33170
+ return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33171
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children }),
33172
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size, onClick: blocks.stopPropagation, accentColor, ...rest, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
33173
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
33174
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { className: "grow", accentColor: "base", variant: "outline", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(
33175
+ blocks.Input.Field,
33176
+ {
33177
+ value: inputValue,
33178
+ onChange: handleInputValueChange,
33179
+ onKeyDown: handleInputKeyDown,
33180
+ placeholder,
33181
+ ...rest
33182
+ }
33183
+ ) }),
33184
+ /* @__PURE__ */ jsxRuntime.jsx(
33185
+ blocks.IconButton,
33186
+ {
33187
+ size: "sm",
33188
+ accentColor: "base",
33189
+ variant: "soft",
33190
+ type: "button",
33191
+ onClick: handleAddValueClick,
33192
+ children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "plus" })
33193
+ }
33194
+ )
33195
+ ] }),
33196
+ values.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: values.map((value, index) => /* @__PURE__ */ jsxRuntime.jsxs(
33197
+ blocks.Badge,
33198
+ {
33199
+ className: "flex items-center justify-between gap-2",
33200
+ accentColor: "base",
33201
+ size: "sm",
33202
+ variant: "soft",
33203
+ children: [
33204
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: value }),
33205
+ /* @__PURE__ */ jsxRuntime.jsx(
33206
+ blocks.IconButton,
33207
+ {
33208
+ size: "xs",
33209
+ variant: "ghost",
33210
+ type: "button",
33211
+ accentColor: "base",
33212
+ onClick: () => {
33213
+ handleRemoveValueClick(index);
33214
+ },
33215
+ children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "x" })
33216
+ }
33217
+ )
33218
+ ]
33219
+ },
33220
+ `${value}-${index}`
33221
+ )) })
33222
+ ] }) })
33223
+ ] });
33224
+ });
33225
+ MultiStringPopover.displayName = "NumberInputPopover";
33226
+ const NumberInputPopover = React.memo((props) => {
33227
+ const {
33228
+ children,
33229
+ open,
33230
+ onOpenChange,
33231
+ defaultOpen,
33232
+ modal,
33233
+ size,
33234
+ accentColor = "base",
33235
+ value: controlledValue,
33236
+ onValueChange,
33237
+ placeholder = "Enter a number",
33238
+ ...rest
33239
+ } = props;
33240
+ const [value, setValue] = React.useState(null);
33241
+ React.useEffect(() => {
33242
+ if (controlledValue !== void 0) setValue(controlledValue);
33243
+ }, [controlledValue]);
33244
+ const handleChange = React.useCallback((e) => {
33245
+ const valueAsNumber = e.target.valueAsNumber;
33246
+ setValue(!isNaN(valueAsNumber) ? valueAsNumber : null);
33247
+ }, []);
33248
+ const handleBlur = React.useCallback(
33249
+ (e) => {
33250
+ const valueAsNumber = e.target.valueAsNumber;
33251
+ onValueChange == null ? void 0 : onValueChange(!isNaN(valueAsNumber) ? valueAsNumber : null);
33252
+ },
33253
+ [onValueChange]
33254
+ );
33255
+ return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { open, onOpenChange, defaultOpen, modal, children: [
33256
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children }),
33257
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size, onClick: blocks.stopPropagation, ...rest, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { size, accentColor, children: /* @__PURE__ */ jsxRuntime.jsx(
33258
+ blocks.Input.Field,
33259
+ {
33260
+ placeholder,
33261
+ type: "number",
33262
+ value: value ?? "",
33263
+ onChange: handleChange,
33264
+ onBlur: handleBlur
33265
+ }
33266
+ ) }) })
33267
+ ] });
33268
+ });
33269
+ NumberInputPopover.displayName = "NumberInputPopover";
33130
33270
  const RemoveConditionButton = (props) => {
33131
33271
  const { condition, onClick, ...rest } = props;
33132
33272
  const handleRemoveFilter = React.useCallback(() => {
@@ -33594,11 +33734,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
33594
33734
  return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectFieldConditionCell, { condition: this, ...props }, this.id);
33595
33735
  }
33596
33736
  }
33737
+ const EMPTY_ARRAY = [];
33597
33738
  const MultiStringFieldConditionCell = (props) => {
33598
33739
  const { condition, onRemove } = props;
33599
33740
  const field = condition.field;
33600
33741
  const conditionValue = condition.getConditionValue();
33601
33742
  const conditionModifier = condition.getConditionModifier();
33743
+ const handleValuesChange = React.useCallback(
33744
+ (values) => {
33745
+ condition.setConditionValue(values.length > 0 ? values : void 0);
33746
+ },
33747
+ [condition]
33748
+ );
33602
33749
  const getFilterValueRender = () => {
33603
33750
  if (conditionValue === void 0) return "...";
33604
33751
  if (conditionValue === null) return "empty";
@@ -33613,15 +33760,15 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
33613
33760
  return `${conditionValue.length} values`;
33614
33761
  }
33615
33762
  };
33616
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex w-max max-w-full min-w-0 gap-0.5", size: "sm", variant: "fill", accentColor: "base", children: [
33763
+ return /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex w-max max-w-full min-w-0 gap-0.5", size: "sm", variant: "fill", accentColor: "base", children: [
33617
33764
  /* @__PURE__ */ jsxRuntime.jsxs(blocks.Badge, { className: "min-w-0 shrink-1", size: "sm", variant: "fill", accentColor: "base", children: [
33618
33765
  /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: fieldIcons[field.type] }),
33619
33766
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: field.label || UNLABELLED_FIELD_LABEL })
33620
33767
  ] }),
33621
33768
  /* @__PURE__ */ jsxRuntime.jsx(ConditionModifierDropdown, { condition, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", children: condition.modifiers[conditionModifier].modifier.label }) }),
33622
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", className: "truncate", children: getFilterValueRender() }),
33769
+ /* @__PURE__ */ jsxRuntime.jsx(MultiStringPopover, { values: conditionValue ?? EMPTY_ARRAY, onValuesChange: handleValuesChange, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", className: "truncate", children: getFilterValueRender() }) }),
33623
33770
  /* @__PURE__ */ jsxRuntime.jsx(RemoveConditionButton, { condition, onClick: onRemove })
33624
- ] }) });
33771
+ ] });
33625
33772
  };
33626
33773
  const modifiers$8 = {
33627
33774
  equals: createConditionModifierConfig({
@@ -33680,88 +33827,55 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
33680
33827
  const getFilterValueUi = () => {
33681
33828
  switch (conditionModifier) {
33682
33829
  case "equals":
33683
- case "notEquals": {
33684
- const equalsModifier = condition.modifiers.equals;
33685
- const equalsFilterValue = conditionValue !== void 0 && equalsModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33686
- return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Menu.Root, { children: [
33687
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Menu.ClickTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", className: "truncate", children: equalsFilterValue !== void 0 ? equalsFilterValue ?? "empty" : "..." }) }),
33688
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Menu.Content, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(
33689
- blocks.Input.Field,
33690
- {
33691
- placeholder: "Enter a number",
33692
- type: "number",
33693
- value: equalsFilterValue ?? "",
33694
- onChange: (e) => {
33695
- const value = e.target.valueAsNumber;
33696
- condition.setConditionValue(isNaN(value) ? void 0 : value);
33697
- }
33698
- }
33699
- ) }) })
33700
- ] });
33701
- }
33702
33830
  case "greaterThanOrEquals":
33703
33831
  case "lessThanOrEquals":
33704
33832
  case "greaterThan":
33705
33833
  case "lessThan": {
33706
33834
  const greaterThanModifier = condition.modifiers.greaterThan;
33707
33835
  const greaterThanFitlerValue = conditionValue !== void 0 && greaterThanModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33708
- return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { children: [
33709
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", className: "truncate", children: greaterThanFitlerValue ?? "..." }) }),
33710
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(
33711
- blocks.Input.Field,
33712
- {
33713
- placeholder: "Enter a number",
33714
- type: "number",
33715
- value: greaterThanFitlerValue ?? "",
33716
- onChange: (e) => {
33717
- const value = e.target.valueAsNumber;
33718
- condition.setConditionValue(isNaN(value) ? void 0 : value);
33719
- }
33720
- }
33721
- ) }) })
33722
- ] });
33836
+ return /* @__PURE__ */ jsxRuntime.jsx(
33837
+ NumberInputPopover,
33838
+ {
33839
+ value: greaterThanFitlerValue ?? null,
33840
+ onValueChange: (value) => condition.setConditionValue(value ?? void 0),
33841
+ size: "sm",
33842
+ children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", className: "truncate", children: greaterThanFitlerValue !== void 0 ? greaterThanFitlerValue ?? "empty" : "..." })
33843
+ }
33844
+ );
33723
33845
  }
33724
33846
  case "inRange":
33725
33847
  case "notInRange": {
33726
33848
  const inRangeModifier = condition.modifiers.inRange;
33727
33849
  const rangeFilterValue = conditionValue !== void 0 && inRangeModifier.isConditionValueValid(conditionValue) ? conditionValue : void 0;
33728
33850
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
33729
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { children: [
33730
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "..." }) }),
33731
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(
33732
- blocks.Input.Field,
33733
- {
33734
- placeholder: "Enter a number",
33735
- type: "number",
33736
- value: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "",
33737
- onChange: (e) => {
33738
- const value = e.target.valueAsNumber;
33739
- condition.setConditionValue({
33740
- from: !isNaN(value) ? value : null,
33741
- to: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null
33742
- });
33743
- }
33744
- }
33745
- ) }) })
33746
- ] }),
33747
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { children: [
33748
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "..." }) }),
33749
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Popover.Content, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Input.Root, { accentColor: "base", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(
33750
- blocks.Input.Field,
33751
- {
33752
- placeholder: "Enter a number",
33753
- type: "number",
33754
- value: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "",
33755
- onChange: (e) => {
33756
- const value = e.target.valueAsNumber;
33757
- condition.setConditionValue({
33758
- from: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33759
- to: !isNaN(value) ? value : null
33760
- });
33761
- }
33762
- }
33763
- ) }) })
33764
- ] })
33851
+ /* @__PURE__ */ jsxRuntime.jsx(
33852
+ NumberInputPopover,
33853
+ {
33854
+ value: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33855
+ onValueChange: (value) => {
33856
+ condition.setConditionValue({
33857
+ from: value,
33858
+ to: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null
33859
+ });
33860
+ },
33861
+ size: "sm",
33862
+ children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? "..." })
33863
+ }
33864
+ ),
33865
+ /* @__PURE__ */ jsxRuntime.jsx(
33866
+ NumberInputPopover,
33867
+ {
33868
+ value: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? null,
33869
+ onValueChange: (value) => {
33870
+ condition.setConditionValue({
33871
+ from: (rangeFilterValue == null ? void 0 : rangeFilterValue.from) ?? null,
33872
+ to: value
33873
+ });
33874
+ },
33875
+ size: "sm",
33876
+ children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { className: "truncate", children: (rangeFilterValue == null ? void 0 : rangeFilterValue.to) ?? "..." })
33877
+ }
33878
+ )
33765
33879
  ] });
33766
33880
  }
33767
33881
  }
@@ -34709,7 +34823,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
34709
34823
  duplicate(identifier) {
34710
34824
  return new _FieldSection({
34711
34825
  ...this.getOptions(),
34712
- identifier
34826
+ identifier,
34827
+ fields: this.fields.map((field) => field.duplicate(uuid.v4()))
34713
34828
  });
34714
34829
  }
34715
34830
  setOptions(options2) {
@@ -35154,7 +35269,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35154
35269
  const error = get(errors, field2.identifier);
35155
35270
  return error && (typeof error !== "object" || Object.values(error).length > 0);
35156
35271
  });
35157
- const previewInput = useFieldInput(field, { formId, showInputOnly: false });
35158
35272
  const handleFieldImageClick = React.useCallback(() => {
35159
35273
  if (!resolvedImage) return;
35160
35274
  openImageViewer(() => ({
@@ -35231,15 +35345,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35231
35345
  }
35232
35346
  )
35233
35347
  ] }),
35234
- directlyShownFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: directlyShownInputs }),
35235
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Separator, { size: "full" }),
35236
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
35237
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.HoverCard.Root, { children: [
35238
- /* @__PURE__ */ jsxRuntime.jsx(blocks.HoverCard.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Badge, { icon: true, size: "sm", variant: "soft", accentColor: "base", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "eye" }) }) }),
35239
- /* @__PURE__ */ jsxRuntime.jsx(blocks.HoverCard.Content, { className: "w-[225px]", size: "sm", align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "sm", accentColor: "base", children: "This is a preview of the field as it will be rendered in the form." }) })
35240
- ] }),
35241
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grow h-max min-w-0", children: previewInput })
35242
- ] })
35348
+ directlyShownFields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: directlyShownInputs })
35243
35349
  ] });
35244
35350
  });
35245
35351
  FieldBuilder.displayName = "FieldBuilder";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overmap-ai/forms",
3
- "version": "1.0.32-react-flow-david-fixes.13",
3
+ "version": "1.0.32-react-flow-david-fixes.14",
4
4
  "license": "UNLICENSED",
5
5
  "main": "dist/forms.umd.cjs",
6
6
  "module": "dist/forms.js",