'use strict';

var chunkWBLPQ375_cjs = require('./chunk-WBLPQ375.cjs');
var chunkASBETQHB_cjs = require('./chunk-ASBETQHB.cjs');
var chunkFDRFBFI7_cjs = require('./chunk-FDRFBFI7.cjs');
var chunkHNBSGCSZ_cjs = require('./chunk-HNBSGCSZ.cjs');
var chunk7LXS66DW_cjs = require('./chunk-7LXS66DW.cjs');
var chunkQP2LHBCZ_cjs = require('./chunk-QP2LHBCZ.cjs');
var chunkUCTQICPR_cjs = require('./chunk-UCTQICPR.cjs');
var chunkOWBDRWL6_cjs = require('./chunk-OWBDRWL6.cjs');
var react = require('@osdk/react');
var React17 = require('react');
var icons = require('@blueprintjs/icons');
var classnames = require('classnames');
var reactHookForm = require('react-hook-form');
var popover = require('@base-ui/react/popover');
var button = require('@base-ui/react/button');
var input = require('@base-ui/react/input');
var lodashEs = require('lodash-es');
var radio = require('@base-ui/react/radio');
var radioGroup = require('@base-ui/react/radio-group');
var collapsible = require('@base-ui/react/collapsible');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var React17__default = /*#__PURE__*/_interopDefault(React17);
var classnames__default = /*#__PURE__*/_interopDefault(classnames);

function useIsMounted() {
  const isMountedRef = React17.useRef(true);
  React17.useEffect(function trackMountedState() {
    return () => {
      isMountedRef.current = false;
    };
  }, []);
  return isMountedRef;
}

// src/shared/hooks/useAsyncAction.ts
function useAsyncAction(action) {
  const [isPending, setIsPending] = React17.useState(false);
  const [error, setError] = React17.useState(void 0);
  const isMountedRef = useIsMounted();
  const execute = React17.useCallback(async (...args) => {
    setError(void 0);
    setIsPending(true);
    try {
      await action(...args);
    } catch (err) {
      if (isMountedRef.current) {
        setError(err);
      }
    } finally {
      if (isMountedRef.current) {
        setIsPending(false);
      }
    }
  }, [action, isMountedRef]);
  const clearError = React17.useCallback(() => {
    setError(void 0);
  }, []);
  return {
    isPending,
    error,
    execute,
    clearError
  };
}

// src/action-form/utils/extractValidationRules.ts
function extractValidationRules(fieldDef) {
  const rules = {};
  if (fieldDef.isRequired) {
    rules.required = getMessage(fieldDef, {
      type: "required"
    });
  }
  const validateFns = {};
  switch (fieldDef.fieldComponent) {
    case "NUMBER_INPUT": {
      const {
        min,
        max
      } = fieldDef.fieldComponentProps;
      if (min != null) {
        const msg = getMessage(fieldDef, {
          type: "min",
          min
        });
        validateFns.min = (value) => typeof value === "number" && value < min ? msg : true;
      }
      if (max != null) {
        const msg = getMessage(fieldDef, {
          type: "max",
          max
        });
        validateFns.max = (value) => typeof value === "number" && value > max ? msg : true;
      }
      break;
    }
    case "TEXT_INPUT":
    case "TEXT_AREA": {
      const {
        minLength,
        maxLength
      } = fieldDef.fieldComponentProps;
      if (minLength != null) {
        rules.minLength = {
          value: minLength,
          message: getMessage(fieldDef, {
            type: "minLength",
            minLength
          })
        };
      }
      if (maxLength != null) {
        rules.maxLength = {
          value: maxLength,
          message: getMessage(fieldDef, {
            type: "maxLength",
            maxLength
          })
        };
      }
      break;
    }
    case "DATETIME_PICKER": {
      const {
        min,
        max
      } = fieldDef.fieldComponentProps;
      if (min != null) {
        const msg = getMessage(fieldDef, {
          type: "min",
          min
        });
        validateFns.min = (value) => value instanceof Date && value.getTime() < min.getTime() ? msg : true;
      }
      if (max != null) {
        const msg = getMessage(fieldDef, {
          type: "max",
          max
        });
        validateFns.max = (value) => value instanceof Date && value.getTime() > max.getTime() ? msg : true;
      }
      break;
    }
    case "FILE_PICKER": {
      const {
        maxSize
      } = fieldDef.fieldComponentProps;
      if (maxSize != null) {
        const msg = getMessage(fieldDef, {
          type: "maxSize",
          maxSize
        });
        validateFns.maxSize = (value) => {
          if (value instanceof File) {
            return value.size > maxSize ? msg : true;
          }
          if (Array.isArray(value)) {
            const oversized = value.some((f) => f instanceof File && f.size > maxSize);
            return oversized ? msg : true;
          }
          return true;
        };
      }
      break;
    }
  }
  if (fieldDef.validate != null) {
    const userValidate = fieldDef.validate;
    validateFns.custom = async (value) => {
      const result = await userValidate(value);
      if (result == null) {
        return true;
      }
      return getMessage(fieldDef, {
        type: "validate",
        message: result
      });
    };
  }
  if (Object.keys(validateFns).length > 0) {
    rules.validate = validateFns;
  }
  return rules;
}
function getMessage(fieldDef, error) {
  return fieldDef.onValidationError?.(error) ?? getDefaultMessage(error);
}
function getDefaultMessage(error) {
  switch (error.type) {
    case "required":
      return "This field is required";
    case "min":
      return `Must be at least ${formatConstraint(error.min)}`;
    case "max":
      return `Must be at most ${formatConstraint(error.max)}`;
    case "minLength":
      return `Must be at least ${error.minLength} characters`;
    case "maxLength":
      return `Must be at most ${error.maxLength} characters`;
    case "maxSize":
      return `File must be smaller than ${formatBytes(error.maxSize)}`;
    case "validate":
      return error.message;
  }
}
function formatConstraint(value) {
  if (value instanceof Date) {
    return value.toLocaleDateString();
  }
  return String(value);
}
function formatBytes(bytes) {
  if (bytes < 1024) {
    return `${bytes} B`;
  }
  if (bytes < 1024 * 1024) {
    return `${(bytes / 1024).toFixed(1)} KB`;
  }
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

// src/action-form/FormField.module.css
var FormField_default = {};

// src/action-form/FormField.tsx
var FormField = /* @__PURE__ */ React17.memo(function FormFieldFn({
  fieldKey,
  label,
  isRequired,
  helperText,
  helperTextPlacement = "tooltip",
  isEdited,
  error,
  onBlur,
  children
}) {
  const hasHelperText = helperText != null && helperText !== "";
  const showTooltip = hasHelperText && helperTextPlacement === "tooltip";
  const showBottomText = hasHelperText && helperTextPlacement === "bottom";
  const showEditedTag = isEdited === true;
  const labelElement = label != null ? /* @__PURE__ */ React17__default.default.createElement("label", {
    className: FormField_default.osdkFormFieldLabel,
    htmlFor: fieldKey
  }, label, isRequired === true && /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormField_default.osdkFormFieldRequired,
    "aria-label": "required"
  }, " ", "*")) : null;
  const labelRow = labelElement != null || showTooltip || showEditedTag ? /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormField_default.osdkFormFieldLabelRow
  }, labelElement, showTooltip && /* @__PURE__ */ React17__default.default.createElement(InfoTip, {
    label
  }, helperText), showEditedTag && /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormField_default.osdkFormFieldEditedTag
  }, "Edited")) : null;
  return /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormField_default.osdkFormField,
    onBlur
  }, labelRow, showBottomText && /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormField_default.osdkFormFieldHelperText
  }, helperText), children, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormField_default.osdkFormFieldErrorSlot,
    "data-osdk-form-field-error-slot": ""
  }, error != null && /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormField_default.osdkFormFieldError,
    role: "alert"
  }, error)));
});
function InfoTip({
  label,
  children
}) {
  return /* @__PURE__ */ React17__default.default.createElement(popover.Popover.Root, null, /* @__PURE__ */ React17__default.default.createElement(popover.Popover.Trigger, {
    render: /* @__PURE__ */ React17__default.default.createElement("span", {
      className: FormField_default.osdkFormFieldInfoIcon
    }),
    nativeButton: false,
    openOnHover: true,
    "aria-label": label != null ? `Info about ${label}` : "More information"
  }, /* @__PURE__ */ React17__default.default.createElement(icons.InfoSign, {
    size: 12
  })), /* @__PURE__ */ React17__default.default.createElement(popover.Popover.Portal, null, /* @__PURE__ */ React17__default.default.createElement(popover.Popover.Positioner, {
    sideOffset: 4
  }, /* @__PURE__ */ React17__default.default.createElement(popover.Popover.Popup, {
    className: FormField_default.osdkFormFieldInfoPopup
  }, children))));
}
var CustomField = /* @__PURE__ */ React17.memo(function CustomFieldFn({
  customRenderer: CustomRenderer,
  ...baseProps
}) {
  return /* @__PURE__ */ React17__default.default.createElement(CustomRenderer, baseProps);
});

// src/action-form/fields/FilePickerField.module.css
var FilePickerField_default = {};

// src/action-form/fields/FilePickerField.tsx
var FilePickerField = /* @__PURE__ */ React17.memo(function FilePickerFieldFn({
  id,
  value,
  onChange,
  error,
  isMulti,
  accept,
  // maxSize is enforced by form-level validation (extractValidationRules),
  // not here. Silently dropping oversized files would leave the user with
  // no indication of why their selection disappeared.
  maxSize: _maxSize,
  text = "No file chosen",
  buttonText = "Browse",
  disabled
}) {
  const inputRef = React17.useRef(null);
  const fileTriggerRef = React17.useRef(null);
  const openFileDialog = React17.useCallback(() => {
    inputRef.current?.click();
  }, []);
  const focusFileTrigger = React17.useCallback(() => {
    fileTriggerRef.current?.focus();
  }, []);
  const handleBrowsePointerDown = React17.useCallback((event) => {
    event.preventDefault();
    focusFileTrigger();
  }, [focusFileTrigger]);
  const handleBrowseClick = React17.useCallback(() => {
    focusFileTrigger();
    openFileDialog();
  }, [focusFileTrigger, openFileDialog]);
  const handleInputChange = React17.useCallback((event) => {
    const files = event.target.files;
    if (files == null || files.length === 0) {
      onChange?.(null);
      return;
    }
    if (isMulti) {
      onChange?.(Array.from(files));
    } else {
      onChange?.(files[0] ?? null);
    }
  }, [onChange, isMulti]);
  const handleClear = React17.useCallback((event) => {
    event.preventDefault();
    onChange?.(null);
    if (inputRef.current != null) {
      inputRef.current.value = "";
    }
  }, [onChange]);
  const handleKeyDown = React17.useCallback((event) => {
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      openFileDialog();
    }
  }, [openFileDialog]);
  const displayText = React17.useMemo(() => getDisplayText(value), [value]);
  const hasValue = displayText != null;
  const acceptString = React17.useMemo(() => normalizeAccept(accept), [accept]);
  return /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FilePickerField_default.osdkFilePickerTrigger,
    "aria-invalid": error != null || void 0
  }, /* @__PURE__ */ React17__default.default.createElement("input", {
    ref: inputRef,
    type: "file",
    className: FilePickerField_default.osdkFilePickerHiddenInput,
    multiple: isMulti,
    accept: acceptString,
    onChange: handleInputChange,
    tabIndex: -1,
    disabled
  }), /* @__PURE__ */ React17__default.default.createElement(button.Button, {
    ref: fileTriggerRef,
    id,
    type: "button",
    className: classnames__default.default(FilePickerField_default.osdkFilePickerText, !hasValue && FilePickerField_default.osdkFilePickerPlaceholder),
    onClick: openFileDialog,
    onKeyDown: handleKeyDown,
    "aria-label": "Choose file",
    "aria-invalid": error != null || void 0,
    disabled
  }, displayText ?? text), hasValue && /* @__PURE__ */ React17__default.default.createElement(button.Button, {
    type: "button",
    className: FilePickerField_default.osdkFilePickerClear,
    onClick: handleClear,
    "aria-label": "Clear selection",
    disabled
  }, /* @__PURE__ */ React17__default.default.createElement(icons.Cross, null)), /* @__PURE__ */ React17__default.default.createElement(chunkQP2LHBCZ_cjs.ActionButton, {
    type: "button",
    tabIndex: -1,
    className: FilePickerField_default.osdkFilePickerBrowse,
    onPointerDown: handleBrowsePointerDown,
    onClick: handleBrowseClick,
    disabled
  }, buttonText));
});
function normalizeAccept(accept) {
  if (accept == null) {
    return void 0;
  }
  return Array.isArray(accept) ? accept.join(",") : accept;
}
function getDisplayText(value) {
  if (value == null) {
    return void 0;
  }
  if (Array.isArray(value)) {
    return value.map((f) => f.name).join(", ");
  }
  return value.name;
}

// src/action-form/fields/NumberInputField.module.css
var NumberInputField_default = {};

// src/action-form/fields/NumberInputField.tsx
var VALID_NUMERIC_REGEX = /^[+-.]?(\d+\.?\d*|\d*\.?\d+)?([eE][+-]?\d*)?$/u;
var DEFAULT_STEP = 1;
var CHEVRON_SIZE = 12;
function NumberInputField({
  id,
  value,
  onChange,
  error,
  placeholder,
  min,
  max,
  step,
  disabled
}) {
  const [displayValue, setDisplayValue] = React17.useState(() => formatNumberForDisplay(value));
  const prevValueRef = React17.useRef(value);
  if (prevValueRef.current !== value) {
    prevValueRef.current = value;
    const currentParsed = parseNumericValue(displayValue);
    if (value !== currentParsed) {
      setDisplayValue(formatNumberForDisplay(value));
    }
  }
  const handleValueChange = React17.useCallback((newValue) => {
    if (!isValidInput(newValue)) {
      return;
    }
    setDisplayValue(newValue);
    onChange?.(parseNumericValue(newValue));
  }, [onChange]);
  const applyStep = React17.useCallback((direction) => {
    const current = parseNumericValue(displayValue) ?? 0;
    const delta = direction * (step ?? DEFAULT_STEP);
    const next = clamp(current + delta, min, max);
    const formatted = formatNumberForDisplay(next);
    setDisplayValue(formatted);
    onChange?.(next);
  }, [displayValue, onChange, step, min, max]);
  const handleKeyDown = React17.useCallback((e) => {
    if (e.key !== "ArrowUp" && e.key !== "ArrowDown") {
      return;
    }
    e.preventDefault();
    applyStep(e.key === "ArrowUp" ? 1 : -1);
  }, [applyStep]);
  const handleStepUp = React17.useCallback(() => {
    applyStep(1);
  }, [applyStep]);
  const handleStepDown = React17.useCallback(() => {
    applyStep(-1);
  }, [applyStep]);
  return /* @__PURE__ */ React17__default.default.createElement("div", {
    className: NumberInputField_default.osdkNumberInputWrapper,
    "aria-invalid": error != null || void 0
  }, /* @__PURE__ */ React17__default.default.createElement(input.Input, {
    id,
    className: NumberInputField_default.osdkNumberInputField,
    type: "text",
    inputMode: "decimal",
    value: displayValue,
    onValueChange: handleValueChange,
    onKeyDown: handleKeyDown,
    placeholder,
    disabled
  }), /* @__PURE__ */ React17__default.default.createElement("div", {
    className: NumberInputField_default.osdkNumberInputStepper
  }, /* @__PURE__ */ React17__default.default.createElement(button.Button, {
    className: NumberInputField_default.osdkNumberInputStepButton,
    "aria-label": "Increment",
    tabIndex: -1,
    disabled,
    onClick: handleStepUp
  }, /* @__PURE__ */ React17__default.default.createElement(icons.ChevronUp, {
    size: CHEVRON_SIZE
  })), /* @__PURE__ */ React17__default.default.createElement(button.Button, {
    className: NumberInputField_default.osdkNumberInputStepButton,
    "aria-label": "Decrement",
    tabIndex: -1,
    disabled,
    onClick: handleStepDown
  }, /* @__PURE__ */ React17__default.default.createElement(icons.ChevronDown, {
    size: CHEVRON_SIZE
  }))));
}
function isValidInput(text) {
  return VALID_NUMERIC_REGEX.test(text);
}
function parseNumericValue(text) {
  if (text === "") {
    return null;
  }
  const parsed = Number(text);
  return Number.isNaN(parsed) ? null : parsed;
}
function formatNumberForDisplay(value) {
  return value != null ? String(value) : "";
}
function clamp(value, min, max) {
  if (min != null && value < min) return min;
  if (max != null && value > max) return max;
  return value;
}
function useDebouncedValue(value, debounceMs) {
  const [debouncedValue, setDebouncedValue] = React17.useState(value);
  React17.useEffect(function debounceValue() {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, debounceMs);
    return () => {
      clearTimeout(timer);
    };
  }, [value, debounceMs]);
  return debouncedValue;
}
var THRESHOLD = 0.5;
var OPTIONS = {
  threshold: THRESHOLD
};
function useInfiniteScroll({
  callback,
  loadedCount
}) {
  const observer = React17.useRef();
  const targetRef = React17.useRef();
  const eventCallback = chunkASBETQHB_cjs.useEventCallback(callback);
  const throttledCallback = React17.useCallback(lodashEs.throttle(eventCallback), []);
  const handleObserverUpdate = React17.useCallback(
    (entries) => {
      const ent = entries[0];
      if (ent && ent.isIntersecting) {
        throttledCallback();
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []
  );
  React17.useEffect(() => {
    const {
      current: targetElement
    } = targetRef;
    if (observer.current == null || targetElement == null) {
      return;
    }
    observer.current.observe(targetElement);
    return () => {
      observer.current?.unobserve(targetElement);
    };
  }, [loadedCount]);
  const setRef = (node) => {
    if (node != null) {
      targetRef.current = node;
      if (observer.current == null) {
        observer.current = new IntersectionObserver(handleObserverUpdate, OPTIONS);
      }
      observer.current.observe(node);
    } else if (targetRef.current != null) {
      observer.current?.unobserve(targetRef.current);
    }
  };
  return setRef;
}

// src/action-form/fields/AsyncDropdownField.module.css
var AsyncDropdownField_default = {};

// src/action-form/fields/AsyncDropdownField.tsx
function _extends() {
  return _extends = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends.apply(null, arguments);
}
var AsyncDropdownField = chunkASBETQHB_cjs.typedReactMemo(function AsyncDropdownFieldFn({
  isLoading,
  hasMore,
  isSearching,
  onFetchMore,
  fetchError,
  ...dropdownProps
}) {
  const itemCount = dropdownProps.items.length;
  const popupStatus = React17.useMemo(() => {
    if (fetchError != null) {
      return /* @__PURE__ */ React17__default.default.createElement("div", {
        className: AsyncDropdownField_default.osdkAsyncDropdownError,
        role: "alert"
      }, fetchError.message);
    }
    if (isSearching) {
      return /* @__PURE__ */ React17__default.default.createElement("div", {
        className: AsyncDropdownField_default.osdkAsyncDropdownStatus
      }, "Searching\u2026");
    }
    if (isLoading && itemCount === 0) {
      return /* @__PURE__ */ React17__default.default.createElement("div", {
        className: AsyncDropdownField_default.osdkAsyncDropdownStatus
      }, "Loading\u2026");
    }
    return null;
  }, [fetchError, isSearching, isLoading, itemCount]);
  const infiniteScrollRef = useInfiniteScroll({
    callback: onFetchMore,
    loadedCount: itemCount
  });
  return /* @__PURE__ */ React17__default.default.createElement(chunkASBETQHB_cjs.DropdownField, _extends({}, dropdownProps, {
    isSearchable: true,
    popupStatus,
    trailingItem: hasMore ? /* @__PURE__ */ React17__default.default.createElement(InfiniteScrollSentinel, {
      key: "sentinel",
      infiniteScrollRef
    }) : null,
    disableClientSideFiltering: dropdownProps.onQueryChange != null
  }));
});
function InfiniteScrollSentinel({
  infiniteScrollRef
}) {
  return /* @__PURE__ */ React17__default.default.createElement("div", {
    ref: infiniteScrollRef,
    role: "presentation"
  }, /* @__PURE__ */ React17__default.default.createElement(chunk7LXS66DW_cjs.SkeletonBar, {
    className: AsyncDropdownField_default.osdkAsyncDropdownSkeleton
  }));
}

// src/action-form/fields/ObjectSelectField.tsx
function _extends2() {
  return _extends2 = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends2.apply(null, arguments);
}
var SEARCH_DEBOUNCE_MS = 300;
var PAGE_SIZE = 50;
var EMPTY_OBJECT_SELECT_ITEMS = [];
var ObjectSelectField = /* @__PURE__ */ React17.memo(function ObjectSelectFieldFn(props) {
  const source = resolveObjectSelectSource(props);
  return /* @__PURE__ */ React17__default.default.createElement(ObjectSelectInner, _extends2({}, props, {
    source
  }));
});
var ObjectSelectInner = /* @__PURE__ */ React17.memo(function ObjectSelectInnerFn({
  source,
  value,
  onChange,
  error,
  id,
  placeholder,
  isMultiple,
  portalRef,
  portalContainer,
  disabled
}) {
  const [query, setQuery] = React17.useState("");
  const debouncedQuery = useDebouncedValue(query, SEARCH_DEBOUNCE_MS);
  const handleChange = React17.useCallback((newValue) => {
    onChange?.(newValue);
    setQuery("");
  }, [onChange]);
  const where = React17.useMemo(() => {
    const trimmed = debouncedQuery.trim();
    if (trimmed === "") {
      return void 0;
    }
    return {
      $title: {
        $containsAllTermsInOrder: trimmed
      }
    };
  }, [debouncedQuery]);
  const objectSetResult = react.useObjectSet(source.objectSet, {
    where,
    pageSize: PAGE_SIZE,
    enabled: source.kind === "objectSet"
  });
  const objectTypeResult = react.useOsdkObjects(source.objectType, {
    where,
    pageSize: PAGE_SIZE,
    enabled: source.kind === "objectType"
  });
  const {
    data,
    isLoading,
    error: fetchError,
    fetchMore,
    hasMore
  } = source.kind === "objectSet" ? objectSetResult : objectTypeResult;
  const items = data ?? EMPTY_OBJECT_SELECT_ITEMS;
  const handleFetchMore = React17.useCallback(() => {
    void fetchMore?.();
  }, [fetchMore]);
  return /* @__PURE__ */ React17__default.default.createElement(AsyncDropdownField, {
    id,
    value,
    onChange: handleChange,
    error,
    items,
    itemToStringLabel,
    itemToKey,
    isItemEqual,
    placeholder: placeholder ?? "Search\u2026",
    isMultiple,
    portalRef,
    portalContainer,
    disabled,
    onQueryChange: setQuery,
    isLoading,
    isSearching: debouncedQuery.trim() !== "" && isLoading,
    hasMore,
    onFetchMore: handleFetchMore,
    fetchError
  });
});
function resolveObjectSelectSource(props) {
  if ("objectSet" in props && props.objectSet != null) {
    return {
      kind: "objectSet",
      objectSet: props.objectSet,
      objectType: props.objectSet.$objectSetInternals.def
    };
  }
  return {
    kind: "objectType",
    objectType: props.objectType
  };
}
function itemToStringLabel(obj) {
  return obj.$title ?? String(obj.$primaryKey);
}
function itemToKey(obj) {
  return String(obj.$primaryKey);
}
function isItemEqual(a, b) {
  return a.$primaryKey === b.$primaryKey;
}
var BlueprintIcon = /* @__PURE__ */ React17__default.default.memo(function BlueprintIconFn({
  icon,
  size
}) {
  const paths = useIcon(icon.name, size);
  return /* @__PURE__ */ React17__default.default.createElement(icons.SVGIconContainer, {
    iconName: icon.name,
    color: icon.color
  }, paths != null ? paths.map((d, i) => /* @__PURE__ */ React17__default.default.createElement("path", {
    key: i,
    d,
    fillRule: "evenodd"
  })) : []);
});
function useIcon(icon, size) {
  const [iconPaths, setIconPaths] = React17__default.default.useState(() => icons.Icons.getPaths(icon, size));
  React17__default.default.useEffect(function loadIconPaths() {
    let isMounted = true;
    const loadedIconPaths = icons.Icons.getPaths(icon, size);
    if (loadedIconPaths != null) {
      setIconPaths(loadedIconPaths);
    } else {
      void icons.Icons.load(icon, size).then(() => {
        if (isMounted) {
          setIconPaths(icons.Icons.getPaths(icon, size));
        }
      });
    }
    return () => {
      isMounted = false;
    };
  }, [icon, size]);
  return iconPaths;
}

// src/action-form/fields/ObjectSetField.module.css
var ObjectSetField_default = {};

// src/action-form/fields/ObjectSetField.tsx
var DEFAULT_OBJECT_ICON = {
  name: "cube",
  color: "#4C90F0"
};
var ICON_SIZE = icons.IconSize.STANDARD;
var DEFAULT_EMPTY_MESSAGE = "Object set is not defined";
var ObjectSetField = chunkASBETQHB_cjs.typedReactMemo(function ObjectSetFieldFn({
  value,
  emptyMessage = DEFAULT_EMPTY_MESSAGE,
  disabled
}) {
  if (value == null) {
    return /* @__PURE__ */ React17__default.default.createElement("div", {
      className: classnames__default.default(ObjectSetField_default.osdkObjectSetField, ObjectSetField_default.osdkObjectSetFieldEmpty),
      "aria-disabled": disabled === true || void 0
    }, emptyMessage);
  }
  return /* @__PURE__ */ React17__default.default.createElement(ObjectSetFieldContent, {
    objectSet: value,
    disabled
  });
});
var ObjectSetFieldContent = /* @__PURE__ */ React17__default.default.memo(function ObjectSetFieldContentFn({
  objectSet,
  disabled
}) {
  const objectTypeDef = objectSet.$objectSetInternals.def;
  const {
    metadata,
    loading: metadataLoading
  } = react.useOsdkMetadata(objectTypeDef);
  const {
    totalCount,
    data,
    isLoading: objectSetLoading,
    error: objectSetError
  } = react.useObjectSet(objectSet, {
    // Fetching a page size of one is enough to get the totalCount
    pageSize: 1
  });
  const hasMetadata = metadata != null;
  const icon = React17__default.default.useMemo(() => metadata != null && "icon" in metadata && metadata.icon != null ? toComponentIcon(metadata.icon) : DEFAULT_OBJECT_ICON, [metadata]);
  const displayName = totalCount === "1" || !hasMetadata || !("pluralDisplayName" in metadata) ? metadata?.displayName : metadata.pluralDisplayName;
  const showLoadingState = metadataLoading && !hasMetadata;
  return /* @__PURE__ */ React17__default.default.createElement("div", {
    className: ObjectSetField_default.osdkObjectSetField,
    "aria-disabled": disabled === true || void 0
  }, showLoadingState ? /* @__PURE__ */ React17__default.default.createElement(React17__default.default.Fragment, null, OBJECT_SET_ICON_SKELETON, OBJECT_SET_LABEL_SKELETON) : /* @__PURE__ */ React17__default.default.createElement(React17__default.default.Fragment, null, /* @__PURE__ */ React17__default.default.createElement(BlueprintIcon, {
    icon,
    size: ICON_SIZE
  }), /* @__PURE__ */ React17__default.default.createElement(ObjectSetLabel, {
    displayName,
    totalCount,
    error: objectSetError,
    isLoading: objectSetLoading
  })));
});
var ObjectSetLabel = /* @__PURE__ */ React17__default.default.memo(function ObjectSetLabelFn({
  displayName,
  totalCount,
  isLoading,
  error
}) {
  const hasData = totalCount != null;
  const label = displayName ?? (totalCount === "1" ? "object" : "objects");
  const showSkeleton = isLoading && !hasData;
  const showError = error != null && !hasData && !isLoading;
  return /* @__PURE__ */ React17__default.default.createElement(React17__default.default.Fragment, null, showSkeleton && OBJECT_SET_LABEL_SKELETON, showError && /* @__PURE__ */ React17__default.default.createElement("span", {
    className: ObjectSetField_default.osdkObjectSetFieldError,
    role: "alert"
  }, `Failed to load: ${error.message}`), !showSkeleton && !showError && /* @__PURE__ */ React17__default.default.createElement("span", null, `${formatCount(totalCount)} ${label}`));
});
var OBJECT_SET_ICON_SKELETON = /* @__PURE__ */ React17__default.default.createElement(chunk7LXS66DW_cjs.SkeletonBar, {
  className: ObjectSetField_default.osdkObjectSetIconSkeleton
});
var OBJECT_SET_LABEL_SKELETON = /* @__PURE__ */ React17__default.default.createElement(chunk7LXS66DW_cjs.SkeletonBar, {
  className: ObjectSetField_default.osdkObjectSetLabelSkeleton
});
function formatCount(count) {
  if (count == null) {
    return "\u2013";
  }
  const num = Number(count);
  return Number.isNaN(num) ? count : num.toLocaleString();
}
function toComponentIcon(apiIcon) {
  return {
    name: apiIcon.name,
    color: apiIcon.color
  };
}

// src/action-form/fields/RadioButtonsField.module.css
var RadioButtonsField_default = {};

// src/action-form/fields/RadioButtonsField.tsx
var RadioButtonsField = chunkASBETQHB_cjs.typedReactMemo(function RadioButtonsFieldFn({
  id,
  value,
  onChange,
  options,
  orientation,
  disabled
}) {
  const selectedLabel = React17.useMemo(() => value != null ? options.find((opt) => opt.value === value)?.label : void 0, [options, value]);
  const handleValueChange = React17.useCallback((nextLabel) => {
    const match = options.find((opt) => opt.label === nextLabel);
    onChange?.(match?.value ?? null);
  }, [options, onChange]);
  return /* @__PURE__ */ React17__default.default.createElement(radioGroup.RadioGroup, {
    id,
    className: RadioButtonsField_default.osdkRadioGroup,
    "data-orientation": orientation ?? "vertical",
    value: selectedLabel,
    onValueChange: handleValueChange,
    disabled
  }, options.map((option) => /* @__PURE__ */ React17__default.default.createElement(RadioItem, {
    key: option.label,
    option,
    disabled
  })));
});
var RadioItem = /* @__PURE__ */ React17.memo(function RadioItemFn({
  option,
  disabled
}) {
  const labelId = React17.useId();
  return /* @__PURE__ */ React17__default.default.createElement("label", {
    className: RadioButtonsField_default.osdkRadioItem
  }, /* @__PURE__ */ React17__default.default.createElement(radio.Radio.Root, {
    value: option.label,
    className: RadioButtonsField_default.osdkRadioRoot,
    disabled,
    "aria-labelledby": labelId,
    tabIndex: disabled === true ? -1 : void 0
  }, /* @__PURE__ */ React17__default.default.createElement(radio.Radio.Indicator, {
    className: RadioButtonsField_default.osdkRadioIndicator
  })), /* @__PURE__ */ React17__default.default.createElement("span", {
    id: labelId,
    className: RadioButtonsField_default.osdkRadioLabel
  }, option.label));
});
var SwitchField = /* @__PURE__ */ React17__default.default.memo(function SwitchFieldFn({
  id,
  label,
  value,
  onChange,
  error,
  disabled
}) {
  return /* @__PURE__ */ React17__default.default.createElement(chunkWBLPQ375_cjs.Switch, {
    id,
    checked: value ?? false,
    onCheckedChange: onChange,
    "aria-invalid": error != null || void 0,
    "aria-label": label,
    disabled
  });
});

// src/action-form/fields/BaseInput.module.css
var BaseInput_default = {};

// src/action-form/fields/TextAreaField.tsx
function _extends3() {
  return _extends3 = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends3.apply(null, arguments);
}
var TEXTAREA_STYLE = {
  resize: "vertical"
};
function TextAreaField({
  id,
  value,
  onChange,
  error,
  placeholder,
  rows,
  wrap,
  minLength,
  maxLength,
  disabled
}) {
  const renderTextarea = React17.useCallback((props) => /* @__PURE__ */ React17__default.default.createElement("textarea", _extends3({}, props, {
    rows,
    wrap,
    style: TEXTAREA_STYLE
  })), [rows, wrap]);
  return /* @__PURE__ */ React17__default.default.createElement(input.Input, {
    id,
    className: BaseInput_default.osdkBaseInput,
    value: value ?? "",
    onValueChange: onChange,
    placeholder,
    minLength,
    maxLength,
    disabled,
    render: renderTextarea,
    "aria-invalid": error != null || void 0
  });
}
function TextInputField({
  id,
  value,
  onChange,
  error,
  placeholder,
  minLength,
  maxLength,
  disabled
}) {
  return /* @__PURE__ */ React17__default.default.createElement(input.Input, {
    id,
    className: BaseInput_default.osdkBaseInput,
    type: "text",
    value: value ?? "",
    onValueChange: onChange,
    placeholder,
    minLength,
    maxLength,
    disabled,
    "aria-invalid": error != null || void 0
  });
}

// src/action-form/fields/FormFieldRenderer.tsx
function _extends4() {
  return _extends4 = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends4.apply(null, arguments);
}
var UNSUPPORTED_FIELD_MESSAGE = "Unsupported field type. Use a CUSTOM field instead";
var FormFieldRenderer = /* @__PURE__ */ React17.memo(function FormFieldRendererFn({
  fieldDefinition,
  value,
  onFieldValueChange,
  onBlur,
  onFieldBlur,
  isEdited,
  error,
  portalContainer
}) {
  const {
    label,
    isRequired,
    helperText,
    helperTextPlacement
  } = fieldDefinition;
  return /* @__PURE__ */ React17__default.default.createElement(FormField, {
    label,
    isRequired,
    fieldKey: fieldDefinition.fieldKey,
    helperText,
    helperTextPlacement,
    isEdited,
    error,
    onBlur
  }, renderFieldComponent(fieldDefinition, value, onFieldValueChange, error, portalContainer, onFieldBlur));
});
function renderFieldComponent(fieldDefinition, value, onChange, error, portalContainer, onFieldBlur) {
  const disabled = fieldDefinition.disabled === true;
  switch (fieldDefinition.fieldComponent) {
    case "DATE_RANGE_INPUT":
      return /* @__PURE__ */ React17__default.default.createElement(chunkFDRFBFI7_cjs.DateRangePicker, _extends4({
        id: fieldDefinition.fieldKey,
        value: coerceToDateRange(value),
        onChange,
        placeholderStart: fieldDefinition.placeholder
      }, fieldDefinition.fieldComponentProps, {
        disabled,
        portalContainer: resolvePortalContainer(fieldDefinition.fieldComponentProps, portalContainer)
      }));
    case "TEXT_INPUT":
      return /* @__PURE__ */ React17__default.default.createElement(TextInputField, _extends4({
        id: fieldDefinition.fieldKey,
        value: value != null ? String(value) : "",
        onChange,
        placeholder: fieldDefinition.placeholder,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "UNSUPPORTED":
      return /* @__PURE__ */ React17__default.default.createElement(TextInputField, _extends4({}, fieldDefinition.fieldComponentProps, {
        id: fieldDefinition.fieldKey,
        value: UNSUPPORTED_FIELD_MESSAGE,
        error,
        disabled: true
      }));
    case "TEXT_AREA":
      return /* @__PURE__ */ React17__default.default.createElement(TextAreaField, _extends4({
        id: fieldDefinition.fieldKey,
        value: value != null ? String(value) : "",
        onChange,
        placeholder: fieldDefinition.placeholder,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "DROPDOWN": {
      return /* @__PURE__ */ React17__default.default.createElement(chunkASBETQHB_cjs.DropdownField, _extends4({
        id: fieldDefinition.fieldKey,
        value,
        onChange,
        placeholder: fieldDefinition.placeholder,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled,
        portalContainer: resolvePortalContainer(fieldDefinition.fieldComponentProps, portalContainer),
        onBlur: onFieldBlur
      }));
    }
    case "DATETIME_PICKER":
      return /* @__PURE__ */ React17__default.default.createElement(chunkFDRFBFI7_cjs.DatePicker, _extends4({
        id: fieldDefinition.fieldKey,
        placeholder: fieldDefinition.placeholder,
        value: value instanceof Date ? value : null,
        onChange,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled,
        portalContainer: resolvePortalContainer(fieldDefinition.fieldComponentProps, portalContainer)
      }));
    case "RADIO_BUTTONS":
      return /* @__PURE__ */ React17__default.default.createElement(RadioButtonsField, _extends4({
        id: fieldDefinition.fieldKey,
        value,
        onChange,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "SWITCH":
      return /* @__PURE__ */ React17__default.default.createElement(SwitchField, _extends4({
        id: fieldDefinition.fieldKey,
        label: fieldDefinition.label,
        value: !!value,
        onChange,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "CUSTOM":
      return /* @__PURE__ */ React17__default.default.createElement(CustomField, _extends4({
        id: fieldDefinition.fieldKey,
        value,
        onChange,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "NUMBER_INPUT":
      return /* @__PURE__ */ React17__default.default.createElement(NumberInputField, _extends4({
        id: fieldDefinition.fieldKey,
        value: typeof value === "number" ? value : null,
        onChange,
        placeholder: fieldDefinition.placeholder,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "FILE_PICKER":
      return /* @__PURE__ */ React17__default.default.createElement(FilePickerField, _extends4({
        id: fieldDefinition.fieldKey,
        value: coerceToFileValue(value),
        onChange,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    case "OBJECT_SELECT":
      return /* @__PURE__ */ React17__default.default.createElement(ObjectSelectField, _extends4({
        id: fieldDefinition.fieldKey,
        value: narrowToOsdkObject(value),
        onChange,
        placeholder: fieldDefinition.placeholder,
        error
      }, fieldDefinition.fieldComponentProps, {
        disabled,
        portalContainer: resolvePortalContainer(fieldDefinition.fieldComponentProps, portalContainer)
      }));
    case "OBJECT_SET":
      return /* @__PURE__ */ React17__default.default.createElement(ObjectSetField, _extends4({
        id: fieldDefinition.fieldKey
      }, fieldDefinition.fieldComponentProps, {
        disabled
      }));
    default:
      return assertUnreachableFieldComponent(fieldDefinition);
  }
}
function resolvePortalContainer(fieldComponentProps, formPortalContainer) {
  return Object.hasOwn(fieldComponentProps, "portalContainer") ? fieldComponentProps.portalContainer : formPortalContainer;
}
function coerceToDateRange(value) {
  if (!Array.isArray(value) || value.length !== 2) return chunkFDRFBFI7_cjs.EMPTY_RANGE;
  const start = value[0] instanceof Date ? value[0] : null;
  const end = value[1] instanceof Date ? value[1] : null;
  if (start == null && end == null) return chunkFDRFBFI7_cjs.EMPTY_RANGE;
  return [start, end];
}
function isFileArray(value) {
  return value.every((v) => v instanceof File);
}
function coerceToFileValue(value) {
  if (value instanceof File) {
    return value;
  }
  if (Array.isArray(value) && isFileArray(value)) {
    return value;
  }
  return null;
}
function narrowToOsdkObject(value) {
  if (value != null && typeof value === "object" && "$primaryKey" in value) {
    return value;
  }
  return null;
}
function assertUnreachableFieldComponent(value) {
  throw new Error(`Unhandled field component: ${String(value)}`);
}

// src/action-form/fields/FieldBridge.tsx
var SELECT_LIKE_FIELDS = /* @__PURE__ */ new Set(["RADIO_BUTTONS", "SWITCH"]);
var FieldBridge = /* @__PURE__ */ React17.memo(function FieldBridgeFn({
  fieldDef,
  control,
  onExternalChange,
  portalContainer
}) {
  const rules = React17.useMemo(() => extractValidationRules(fieldDef), [fieldDef]);
  const {
    field: {
      onChange,
      onBlur,
      value
    },
    fieldState: {
      error: fieldError
    }
  } = reactHookForm.useController({
    name: fieldDef.fieldKey,
    control,
    rules
  });
  const isSelectLike = SELECT_LIKE_FIELDS.has(fieldDef.fieldComponent);
  const isDropdown = fieldDef.fieldComponent === "DROPDOWN";
  const [isEdited, setIsEdited] = React17.useState(false);
  const handleChange = React17.useCallback((newValue) => {
    onChange(newValue);
    setIsEdited(true);
    onExternalChange?.(fieldDef.fieldKey, newValue);
    if (isSelectLike) {
      onBlur();
    }
  }, [onChange, onBlur, onExternalChange, fieldDef.fieldKey, isSelectLike]);
  const handleBlur = React17.useCallback((e) => {
    if (e.currentTarget.contains(e.relatedTarget)) {
      return;
    }
    onBlur();
  }, [onBlur]);
  return /* @__PURE__ */ React17__default.default.createElement(FormFieldRenderer, {
    value,
    fieldDefinition: fieldDef,
    onFieldValueChange: handleChange,
    onBlur: isDropdown ? void 0 : handleBlur,
    onFieldBlur: isDropdown ? onBlur : void 0,
    isEdited,
    error: fieldError?.message,
    portalContainer
  });
});

// src/action-form/FormHeader.module.css
var FormHeader_default = {};

// src/action-form/FormHeader.tsx
var FormHeader = /* @__PURE__ */ React17.memo(function FormHeaderFn({
  title
}) {
  return /* @__PURE__ */ React17__default.default.createElement("h2", {
    className: FormHeader_default.osdkFormHeader
  }, title);
});

// src/action-form/FormSection.module.css
var FormSection_default = {};

// src/action-form/FormSection.tsx
var FormSection = /* @__PURE__ */ React17.memo(function FormSectionFn({
  definition,
  errorCount,
  children
}) {
  const {
    title,
    description,
    collapsedByDefault = false,
    showTitleBar = true,
    columnCount = 1,
    style = "box"
  } = definition;
  const isMinimal = style === "minimal";
  if (isMinimal) {
    return /* @__PURE__ */ React17__default.default.createElement(MinimalSection, {
      title,
      description
    }, children);
  }
  const contentClassName = classnames__default.default(columnCount === 2 ? FormSection_default.osdkFormSectionGrid : FormSection_default.osdkFormSectionContent, FormSection_default.osdkFormSectionDivider);
  if (!showTitleBar) {
    return /* @__PURE__ */ React17__default.default.createElement("div", {
      className: FormSection_default.osdkFormSectionBox
    }, /* @__PURE__ */ React17__default.default.createElement("div", {
      className: contentClassName
    }, children));
  }
  return /* @__PURE__ */ React17__default.default.createElement(collapsible.Collapsible.Root, {
    // Inverted: Base UI uses "open" semantics, our API uses "collapsed" semantics
    defaultOpen: !collapsedByDefault,
    className: FormSection_default.osdkFormSectionBox
  }, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionHeader
  }, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionTitleArea
  }, /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormSection_default.osdkFormSectionTitle
  }, title), description != null && /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormSection_default.osdkFormSectionDescription
  }, description)), /* @__PURE__ */ React17__default.default.createElement(collapsible.Collapsible.Trigger, {
    className: FormSection_default.osdkFormSectionTrigger,
    "aria-label": title
  }, errorCount > 0 && /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormSection_default.osdkFormSectionErrorBadge,
    role: "status"
  }, errorCount === 1 ? "1 error" : `${errorCount} errors`), /* @__PURE__ */ React17__default.default.createElement("span", {
    className: FormSection_default.osdkFormSectionChevron
  }, /* @__PURE__ */ React17__default.default.createElement(icons.CaretDown, {
    size: 16
  })))), /* @__PURE__ */ React17__default.default.createElement(collapsible.Collapsible.Panel, {
    keepMounted: true
  }, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: contentClassName
  }, children)));
});
var MinimalSection = /* @__PURE__ */ React17.memo(function MinimalSectionFn({
  title,
  description,
  children
}) {
  return /* @__PURE__ */ React17__default.default.createElement("div", null, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionMinimalHeader
  }, /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionMinimalTitle
  }, title), description != null && /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionMinimalDescription
  }, description)), /* @__PURE__ */ React17__default.default.createElement("div", {
    className: FormSection_default.osdkFormSectionMinimalContent
  }, children));
});

// src/action-form/BaseForm.module.css
var BaseForm_default = {};

// src/action-form/BaseForm.tsx
var BaseForm = /* @__PURE__ */ React17.memo(function BaseFormFn({
  formTitle,
  formContent,
  formState: controlledFormState,
  onFieldValueChange,
  onSubmit,
  isSubmitDisabled = false,
  isPending = false,
  isLoading = false,
  className,
  submitButtonText = "Submit",
  submitButtonVariant = "primary"
}) {
  const portalContainerRef = React17.useRef(null);
  const isControlled = controlledFormState != null;
  const allFieldDefinitions = React17.useMemo(() => flattenFieldDefinitions(formContent), [formContent]);
  const defaultValues = React17.useMemo(() => buildDefaultValues(allFieldDefinitions), [allFieldDefinitions]);
  const {
    control,
    trigger,
    getValues,
    formState: {
      errors
    }
  } = reactHookForm.useForm({
    // Validate on blur first, then revalidate on change after the first
    // error. This gives the user a chance to finish typing before seeing
    // errors, while staying responsive once an error is surfaced.
    mode: "onTouched",
    ...isControlled ? {
      values: controlledFormState
    } : {
      defaultValues
    }
  });
  const [hasAttemptedSubmit, setHasAttemptedSubmit] = React17.useState(false);
  const {
    isPending: isSubmitting,
    error: submissionError,
    execute: executeSubmit,
    clearError
  } = useAsyncAction(onSubmit);
  const submissionErrorMessage = submissionError != null ? submissionError instanceof Error ? submissionError.message : (
    // TODO: provide better error message
    "Submission failed"
  ) : void 0;
  const submitForm = React17.useCallback(async () => {
    setHasAttemptedSubmit(true);
    const isValid = await trigger();
    if (!isValid) {
      return;
    }
    await executeSubmit(controlledFormState ?? getValues());
  }, [trigger, executeSubmit, controlledFormState, getValues]);
  const handleFieldChange = React17.useCallback((fieldKey, value) => {
    clearError();
    onFieldValueChange?.(fieldKey, value);
  }, [clearError, onFieldValueChange]);
  const labelByFieldKey = React17.useMemo(() => new Map(allFieldDefinitions.map((d) => [d.fieldKey, d.label])), [allFieldDefinitions]);
  const errorEntries = Object.entries(errors).map(([key, entry]) => ({
    label: labelByFieldKey.get(key) ?? key,
    message: entry?.message ?? "Invalid"
  }));
  const areErrorsPresent = errorEntries.length > 0;
  const buttonErrorMessage = areErrorsPresent ? "Some fields are invalid" : submissionErrorMessage;
  const isFormPending = isPending || isSubmitting;
  const isSubmitButtonDisabled = isSubmitDisabled || hasAttemptedSubmit && areErrorsPresent;
  return /* @__PURE__ */ React17__default.default.createElement("form", {
    ref: portalContainerRef,
    className: classnames__default.default(BaseForm_default.osdkForm, className)
    // Workshop widgets can run in iframes without `allow-forms`, where
    // native form submission is blocked. Keep the form landmark, but do not
    // wire any form-level submit handlers; the submit button invokes our
    // JavaScript submit path directly.
  }, formTitle != null && /* @__PURE__ */ React17__default.default.createElement(FormHeader, {
    title: formTitle
  }), isLoading && allFieldDefinitions.length === 0 && /* @__PURE__ */ React17__default.default.createElement("div", {
    role: "status",
    "aria-label": "Loading form fields",
    className: BaseForm_default.osdkFormFields
  }, FORM_SKELETON), /* @__PURE__ */ React17__default.default.createElement("div", {
    className: BaseForm_default.osdkFormFields
  }, formContent.map((item) => {
    if (item.type === "field") {
      return /* @__PURE__ */ React17__default.default.createElement(FieldBridge, {
        key: item.definition.fieldKey,
        fieldDef: item.definition,
        control,
        onExternalChange: handleFieldChange,
        portalContainer: portalContainerRef
      });
    }
    const sectionErrorCount = item.definition.fields.reduce((count, field) => count + (errors[field.fieldKey] != null ? 1 : 0), 0);
    return /* @__PURE__ */ React17__default.default.createElement(FormSection, {
      key: item.key,
      definition: item.definition,
      errorCount: sectionErrorCount
    }, item.definition.fields.map((fieldDef) => /* @__PURE__ */ React17__default.default.createElement(FieldBridge, {
      key: fieldDef.fieldKey,
      fieldDef,
      control,
      onExternalChange: handleFieldChange,
      portalContainer: portalContainerRef
    })));
  })), /* @__PURE__ */ React17__default.default.createElement("div", {
    className: BaseForm_default.osdkFormFooter
  }, /* @__PURE__ */ React17__default.default.createElement(ErrorIndicator, {
    errorEntries
  }), /* @__PURE__ */ React17__default.default.createElement("div", {
    className: BaseForm_default.osdkFormSubmitButton
  }, /* @__PURE__ */ React17__default.default.createElement(SubmitButton, {
    isPending: isFormPending,
    isSubmitDisabled: isSubmitButtonDisabled,
    errorMessage: buttonErrorMessage,
    buttonText: submitButtonText,
    buttonVariant: submitButtonVariant,
    onClick: submitForm
  }))));
});
function flattenFieldDefinitions(formContent) {
  const result = [];
  for (const item of formContent) {
    if (item.type === "field") {
      result.push(item.definition);
    } else {
      for (const fieldDef of item.definition.fields) {
        result.push(fieldDef);
      }
    }
  }
  return result;
}
var SKELETON_FIELD_COUNT = 3;
var FORM_SKELETON = Array.from({
  length: SKELETON_FIELD_COUNT
}, (_, i) => /* @__PURE__ */ React17__default.default.createElement("div", {
  key: i,
  className: BaseForm_default.osdkFormSkeletonField
}, /* @__PURE__ */ React17__default.default.createElement(chunk7LXS66DW_cjs.SkeletonBar, {
  className: BaseForm_default.osdkFormSkeletonLabel
}), /* @__PURE__ */ React17__default.default.createElement(chunk7LXS66DW_cjs.SkeletonBar, {
  className: BaseForm_default.osdkFormSkeletonInput
})));
function buildDefaultValues(fieldDefinitions) {
  const values = {};
  for (const def of fieldDefinitions) {
    const props = def.fieldComponentProps;
    if ("defaultValue" in props) {
      values[def.fieldKey] = props.defaultValue;
    }
  }
  return values;
}
var SubmitButton = /* @__PURE__ */ React17.memo(function SubmitButtonFn({
  isPending,
  isSubmitDisabled,
  errorMessage,
  buttonText,
  buttonVariant,
  onClick
}) {
  const buttonLabel = isPending ? "Submitting\u2026" : buttonText;
  const button = /* @__PURE__ */ React17__default.default.createElement(chunkQP2LHBCZ_cjs.ActionButton, {
    type: "button",
    variant: buttonVariant,
    disabled: isSubmitDisabled || isPending,
    onClick
  }, buttonLabel);
  if (errorMessage == null) {
    return button;
  }
  return /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Root, {
    defaultOpen: true
  }, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Trigger, {
    render: /* @__PURE__ */ React17__default.default.createElement("span", {
      className: BaseForm_default.osdkTooltipTriggerWrapper
    })
  }, button), /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Portal, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Positioner, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Popup, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Arrow, null), errorMessage))));
});
function ErrorIndicator({
  errorEntries
}) {
  if (errorEntries.length === 0) {
    return null;
  }
  const count = errorEntries.length;
  return /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Root, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Trigger, null, /* @__PURE__ */ React17__default.default.createElement("span", {
    className: BaseForm_default.osdkFormErrorIndicator
  }, /* @__PURE__ */ React17__default.default.createElement(icons.Error, {
    size: 14
  }), count === 1 ? "1 issue" : `${count} issues`)), /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Portal, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Positioner, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Popup, null, /* @__PURE__ */ React17__default.default.createElement(chunkHNBSGCSZ_cjs.Tooltip.Arrow, null), /* @__PURE__ */ React17__default.default.createElement("ul", {
    className: BaseForm_default.osdkFormErrorList
  }, errorEntries.map((entry) => /* @__PURE__ */ React17__default.default.createElement("li", {
    key: entry.label
  }, /* @__PURE__ */ React17__default.default.createElement("strong", null, entry.label, ":"), " ", entry.message)))))));
}

// src/action-form/utils/coerceFieldValue.ts
function coerceFieldValue(parameterType, rawValue) {
  if (rawValue == null) {
    return void 0;
  }
  if (parameterType == null) {
    return rawValue;
  }
  if (typeof parameterType === "object") {
    return rawValue;
  }
  switch (parameterType) {
    case "string":
    case "marking":
    case "geohash":
    case "geoshape":
    case "objectType":
      return typeof rawValue === "string" ? rawValue : String(rawValue);
    case "integer":
    case "long": {
      const maybeNumber = extractNumber(rawValue);
      return maybeNumber != null ? Math.trunc(maybeNumber) : void 0;
    }
    case "double": {
      return extractNumber(rawValue);
    }
    case "boolean": {
      if (typeof rawValue === "boolean") {
        return rawValue;
      }
      if (rawValue === "true") return true;
      if (rawValue === "false") return false;
      return void 0;
    }
    case "datetime":
    case "timestamp": {
      if (typeof rawValue === "string") {
        return Number.isNaN(Date.parse(rawValue)) ? void 0 : rawValue;
      }
      if (rawValue instanceof Date) {
        return rawValue.toISOString();
      }
      return void 0;
    }
    case "attachment":
    case "mediaReference":
      return rawValue;
    default:
      return rawValue;
  }
}
function extractNumber(rawValue) {
  if (typeof rawValue === "number") {
    return rawValue;
  }
  if (typeof rawValue === "string") {
    const trimmed = rawValue.trim();
    if (trimmed === "") return void 0;
    const parsed = Number(trimmed);
    return Number.isNaN(parsed) ? void 0 : parsed;
  }
  return void 0;
}

// src/action-form/utils/getDefaultFieldDefinitions.ts
function getDefaultFieldDefinitions(metadata) {
  return Object.entries(metadata.parameters).map(([key, param]) => buildFieldDefinition(key, param));
}
function buildFieldDefinition(key, param) {
  const base = {
    fieldKey: key,
    label: key,
    isRequired: !param.nullable,
    fieldType: param.type
  };
  const paramType = param.type;
  if (typeof paramType === "object") {
    switch (paramType.type) {
      case "objectSet":
        return {
          ...base,
          fieldComponent: "OBJECT_SET",
          fieldComponentProps: {
            value: null
          }
        };
      case "object":
        return {
          ...base,
          fieldComponent: "OBJECT_SELECT",
          fieldComponentProps: {
            // Construct a minimal ObjectTypeDefinition from the action
            // parameter metadata. At runtime useOsdkObjects only reads
            // type + apiName from the definition.
            objectType: {
              type: "object",
              apiName: paramType.object
            }
          }
        };
      case "interface":
      case "struct":
        return {
          ...base,
          fieldComponent: "UNSUPPORTED",
          fieldComponentProps: {}
        };
    }
  }
  switch (paramType) {
    case "string":
      return {
        ...base,
        fieldComponent: "TEXT_INPUT",
        fieldComponentProps: {}
      };
    case "marking":
    case "geohash":
    case "geoshape":
    case "objectType":
    case "scenarioReference":
      return {
        ...base,
        fieldComponent: "UNSUPPORTED",
        fieldComponentProps: {}
      };
    case "boolean":
      return {
        ...base,
        fieldComponent: "RADIO_BUTTONS",
        fieldComponentProps: {
          options: [{
            label: "True",
            value: true
          }, {
            label: "False",
            value: false
          }]
        }
      };
    case "integer":
    case "double":
    case "long":
      return {
        ...base,
        fieldComponent: "NUMBER_INPUT",
        fieldComponentProps: {}
      };
    case "datetime":
    case "timestamp":
      return {
        ...base,
        fieldComponent: "DATETIME_PICKER",
        fieldComponentProps: {}
      };
    case "attachment":
    case "mediaReference":
      return {
        ...base,
        fieldComponent: "FILE_PICKER",
        fieldComponentProps: {}
      };
    default:
      return chunkUCTQICPR_cjs.assertUnreachable(paramType);
  }
}

// src/action-form/ActionForm.tsx
function _extends5() {
  return _extends5 = Object.assign ? Object.assign.bind() : function(n) {
    for (var e = 1; e < arguments.length; e++) {
      var t = arguments[e];
      for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
    }
    return n;
  }, _extends5.apply(null, arguments);
}
var EMPTY_FIELD_DEFINITIONS = [];
var EMPTY_FORM_CONTENT = [];
var ActionForm = chunkASBETQHB_cjs.typedReactMemo(function ActionFormFn({
  actionDefinition,
  formTitle,
  showFormTitle = false,
  formFieldDefinitions,
  formState: controlledFormState,
  onFormStateChange,
  isSubmitDisabled,
  onSubmit,
  onValidationResponse: _onValidationResponse,
  onSuccess,
  onError
}) {
  const {
    applyAction: osdkApplyAction,
    isPending
  } = react.useOsdkAction(actionDefinition);
  const {
    metadata,
    loading: metadataLoading,
    error: metadataError
  } = react.useOsdkMetadata(actionDefinition);
  React17.useEffect(function saveMetadataError() {
    if (metadataError != null) {
      onError?.({
        type: "unknown",
        error: metadataError
      });
    }
  }, [metadataError, onError]);
  const parameters = metadata?.parameters;
  const customFieldDefinitions = React17.useMemo(() => {
    if (formFieldDefinitions == null) {
      return null;
    }
    return formFieldDefinitions.map((def) => {
      const {
        defaultValue,
        ...fieldDefinition
      } = def;
      return {
        ...fieldDefinition,
        fieldKey: String(def.fieldKey),
        fieldType: parameters?.[String(def.fieldKey)]?.type,
        fieldComponentProps: defaultValue === void 0 ? def.fieldComponentProps : {
          ...def.fieldComponentProps,
          defaultValue
        }
      };
    });
  }, [formFieldDefinitions, parameters]);
  const rendererFieldDefinitions = React17.useMemo(() => customFieldDefinitions ?? (metadata != null ? getDefaultFieldDefinitions(metadata) : EMPTY_FIELD_DEFINITIONS), [customFieldDefinitions, metadata]);
  const formContent = React17.useMemo(() => rendererFieldDefinitions.length === 0 ? EMPTY_FORM_CONTENT : rendererFieldDefinitions.map((def) => ({
    type: "field",
    definition: def
  })), [rendererFieldDefinitions]);
  const coerceFormState = React17.useCallback((rawState) => {
    const coerced = {};
    for (const [key, value] of Object.entries(rawState)) {
      coerced[key] = coerceFieldValue(parameters?.[key]?.type, value);
    }
    return coerced;
  }, [parameters]);
  const handleSubmit = React17.useCallback(async (rawFormState) => {
    const formState = coerceFormState(rawFormState);
    try {
      if (onSubmit != null) {
        await onSubmit(formState, osdkApplyAction);
      } else {
        const result = await osdkApplyAction(formState);
        onSuccess?.(result);
      }
    } catch (e) {
      onError?.({
        type: "submission",
        error: e
      });
    }
  }, [coerceFormState, onSubmit, osdkApplyAction, onSuccess, onError]);
  const handleFieldValueChange = React17.useCallback((fieldKey, value) => {
    onFormStateChange?.((prev) => ({
      ...prev,
      [fieldKey]: value
    }));
  }, [onFormStateChange]);
  const resolvedTitle = showFormTitle ? formTitle ?? metadata?.displayName ?? actionDefinition.apiName : void 0;
  const isControlled = controlledFormState != null;
  const commonProps = {
    formTitle: resolvedTitle,
    formContent,
    onSubmit: handleSubmit,
    isSubmitDisabled,
    isPending,
    isLoading: metadataLoading,
    onFieldValueChange: handleFieldValueChange
  };
  if (!isControlled) {
    return /* @__PURE__ */ React17__default.default.createElement(BaseForm, commonProps);
  }
  return /* @__PURE__ */ React17__default.default.createElement(BaseForm, _extends5({}, commonProps, {
    formState: controlledFormState
  }));
});
ActionForm.displayName = "ActionForm";

// src/public/experimental/action-form.ts
var ActionForm2 = chunkOWBDRWL6_cjs.withOsdkMetrics(ActionForm, "ActionForm");

exports.ActionForm = ActionForm2;
exports.BaseForm = BaseForm;
//# sourceMappingURL=chunk-2PZPTWXN.cjs.map
//# sourceMappingURL=chunk-2PZPTWXN.cjs.map