import { importShared } from '../../__federation_fn_import-UR7U68uv.js';
import { j as jsxRuntimeExports } from '../../jsx-runtime-XI9uIe3W.js';
import { F as FeatureUtils, M as ModelUtils, y as modelMergerDefinitionDiffConfig, i as isEqual, c as createPluginSpec } from '../../model-merger-ADni4OiK.js';
import { c as create } from '../../react-0fPna-xD.js';
import { u as useFormState, a as useForm } from '../../index.esm-CfkbVR3O.js';

function capitalize(str) {
    return (str.charAt(0).toUpperCase() + str.slice(1).toLowerCase());
}

const React = await importShared('react');

const ProjectDefinitionContext = React.createContext(null);
function useProjectDefinition() {
    const result = React.useContext(ProjectDefinitionContext);
    if (!result) {
        throw new Error(`useProjectDefinition must be used within a <ProjectDefinitionProvider>`);
    }
    return result;
}

const {ComboboxField: ComboboxField$1,useControllerMerged: useControllerMerged$1} = await importShared('@baseplate-dev/ui-components');

const {useMemo: useMemo$2,useState: useState$1} = await importShared('react');
function createCreateOption$1(value) {
    return {
        label: `Create "${value}"`,
        value,
    };
}
function FeatureComboboxField({ canCreate, value, ...rest }) {
    const { definition } = useProjectDefinition();
    const [searchQuery, setSearchQuery] = useState$1('');
    const featureOptions = useMemo$2(() => {
        const baseFeatures = definition.features.map((feature) => ({
            label: feature.name,
            value: feature.id,
        }));
        if (!canCreate)
            return baseFeatures;
        const newFeatureName = searchQuery ? searchQuery : value;
        const doesNewFeatureExist = !!baseFeatures.some((option) => option.label === newFeatureName || option.value === newFeatureName);
        return !doesNewFeatureExist &&
            newFeatureName &&
            FeatureUtils.validateFeatureName(newFeatureName)
            ? [...baseFeatures, createCreateOption$1(newFeatureName)]
            : baseFeatures;
    }, [definition.features, searchQuery, value, canCreate]);
    return (jsxRuntimeExports.jsx(ComboboxField$1, { placeholder: "Select a feature", ...rest, searchQuery: canCreate ? searchQuery : undefined, onSearchQueryChange: setSearchQuery, options: featureOptions, value: value }));
}
function FeatureComboboxFieldController({ name, control, ...rest }) {
    const { field, fieldState: { error }, } = useControllerMerged$1({ name, control }, rest);
    const restProps = rest;
    return (jsxRuntimeExports.jsx(FeatureComboboxField, { error: error?.message, ...restProps, ...field, value: field.value ?? null }));
}

const {ComboboxField,useControllerMerged} = await importShared('@baseplate-dev/ui-components');

const {useMemo: useMemo$1,useState} = await importShared('react');
function createCreateOption(value) {
    return {
        label: `Create "${value}"`,
        value,
    };
}
function ModelComboboxField({ canCreate, value, ...rest }) {
    const { definition } = useProjectDefinition();
    const [searchQuery, setSearchQuery] = useState('');
    const modelOptions = useMemo$1(() => {
        const baseModels = definition.models.map((model) => ({
            label: model.name,
            value: model.id,
        }));
        if (!canCreate)
            return baseModels;
        const newModelName = searchQuery ? searchQuery : value;
        const doesNewModelExist = !!baseModels.some((option) => option.label === newModelName || option.value === newModelName);
        return !doesNewModelExist &&
            newModelName &&
            ModelUtils.validateModelName(newModelName)
            ? [...baseModels, createCreateOption(newModelName)]
            : baseModels;
    }, [definition.models, searchQuery, value, canCreate]);
    return (jsxRuntimeExports.jsx(ComboboxField, { placeholder: "Select a model", ...rest, searchQuery: canCreate ? searchQuery : undefined, onSearchQueryChange: setSearchQuery, options: modelOptions, value: value }));
}
function ModelComboboxFieldController({ name, control, ...rest }) {
    const { field, fieldState: { error }, } = useControllerMerged({ name, control }, rest);
    const restProps = rest;
    return (jsxRuntimeExports.jsx(ModelComboboxField, { error: error?.message, ...restProps, ...field, value: field.value ?? null }));
}

const {Alert,AlertDescription,AlertTitle} = await importShared('@baseplate-dev/ui-components');
function ModelMergerResultAlert({ pendingModelChanges, }) {
    const changes = Object.values(pendingModelChanges).filter((change) => change !== undefined);
    if (changes.length === 0) {
        return (jsxRuntimeExports.jsxs(Alert, { variant: "default", children: [jsxRuntimeExports.jsx(AlertTitle, { children: "Models Up to Date" }), jsxRuntimeExports.jsx(AlertDescription, { children: "All required models are already configured correctly. No changes needed." })] }));
    }
    return (jsxRuntimeExports.jsx("div", { className: "space-y-4", children: changes.map((change) => (jsxRuntimeExports.jsxs(Alert, { variant: change.isNewModel ? 'default' : 'warning', children: [jsxRuntimeExports.jsxs(AlertTitle, { children: [change.isNewModel ? 'New Model' : 'Model Changes', ": ", change.name] }), jsxRuntimeExports.jsx(AlertDescription, { children: jsxRuntimeExports.jsxs("div", { className: "mt-2 space-y-2", children: [change.isNewModel ? (jsxRuntimeExports.jsx("p", { children: "This is a new model that will be created with the following configuration:" })) : (jsxRuntimeExports.jsx("p", { children: "The following changes will be applied to the model:" })), jsxRuntimeExports.jsx("ul", { className: "list-disc pl-4 space-y-1", children: Object.entries(change.changes).map(([key, value]) => {
                                    const field = modelMergerDefinitionDiffConfig[key];
                                    if (!field) {
                                        return null;
                                    }
                                    if (value?.length) {
                                        return (jsxRuntimeExports.jsxs("li", { children: [value.length === 1 ? (capitalize(field.name)) : (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("span", { className: "font-medium", children: value.length }), ' ', field.name, "(s)"] })), ' ', "will be ", field.getActionVerb(change.isNewModel)] }, key));
                                    }
                                }) })] }) })] }, change.name))) }));
}

const {createContext} = await importShared('react');

const ErrorHandlerContext = createContext(null);

const {useEffect: useEffect$2,useId} = await importShared('react');
const useBlockerDialogState = create((set) => ({
    activeBlockers: [],
    addBlocker: (options) => {
        set((state) => ({
            activeBlockers: [...state.activeBlockers, options],
        }));
    },
    removeBlocker: (id) => {
        set((state) => ({
            activeBlockers: state.activeBlockers.filter((blocker) => blocker.id !== id),
        }));
    },
    requestedBlockers: [],
    requestBlocker(options) {
        set((state) => ({
            requestedBlockers: [...state.requestedBlockers, options],
        }));
    },
    clearRequestedBlockers: () => {
        set(() => ({
            requestedBlockers: [],
        }));
    },
}));
function useBlockBeforeContinue() {
    const hasActiveBlockers = useBlockerDialogState((state) => state.activeBlockers.length > 0);
    const clearRequestedBlockers = useBlockerDialogState((state) => state.clearRequestedBlockers);
    // make sure we clear any blocker requests if we navigate away
    useEffect$2(() => () => {
        clearRequestedBlockers();
    }, [clearRequestedBlockers]);
    const requestBlocker = useBlockerDialogState((state) => state.requestBlocker);
    // if no blockers, continue immediately
    if (!hasActiveBlockers) {
        return ({ onContinue }) => {
            onContinue();
        };
    }
    return requestBlocker;
}
function useBlockerDialog(options) {
    const id = useId();
    const addBlocker = useBlockerDialogState((state) => state.addBlocker);
    const removeBlocker = useBlockerDialogState((state) => state.removeBlocker);
    useEffect$2(() => {
        if (options.disableBlock) {
            return;
        }
        addBlocker({
            disableBlock: options.disableBlock,
            title: options.title,
            content: options.content,
            buttonContinueWithoutSaveText: options.buttonContinueWithoutSaveText,
            onContinueWithoutSave: options.onContinueWithoutSave,
            buttonContinueText: options.buttonContinueText,
            onContinue: options.onContinue,
            id,
        });
        return () => {
            removeBlocker(id);
        };
    }, [
        addBlocker,
        removeBlocker,
        options.disableBlock,
        options.buttonContinueWithoutSaveText,
        options.onContinueWithoutSave,
        options.buttonContinueText,
        options.content,
        options.title,
        options.onContinue,
        id,
    ]);
}

function useBlockDirtyFormNavigate(formState, reset) {
    useBlockerDialog({
        disableBlock: !formState.isDirty,
        title: 'Unsaved Changes',
        content: 'You have unsaved changes. Are you sure you want to continue?',
        buttonContinueText: 'Discard Changes',
        onContinue: () => {
            reset();
            return true;
        },
    });
}

const {toast: toast$1} = await importShared('@baseplate-dev/ui-components');
const {useEffect: useEffect$1,useRef: useRef$1} = await importShared('react');
function useBlockUnsavedChangesNavigate({ control, reset, onSubmit }) {
  const isDirtyRef = useRef$1(false);
  const formState = useFormState({ control });
  isDirtyRef.current = formState.isDirty;
  useBlockerDialog({
    disableBlock: !formState.isDirty,
    title: "Unsaved Changes",
    content: "You have unsaved changes. Do you want to save your changes?",
    buttonContinueWithoutSaveText: "Discard Changes",
    onContinueWithoutSave: () => {
      reset();
      return true;
    },
    buttonContinueText: "Save",
    onContinue: async () => {
      await onSubmit();
      await new Promise((resolve) => setTimeout(resolve, 1));
      return !isDirtyRef.current;
    }
  });
}

const {useMemo} = await importShared('react');
function useDefinitionSchema(schemaCreator) {
    const { definitionSchemaParserContext } = useProjectDefinition();
    return useMemo(() => schemaCreator(definitionSchemaParserContext), [definitionSchemaParserContext, schemaCreator]);
}

const {useContext} = await importShared('react');
function useErrorHandler() {
    const context = useContext(ErrorHandlerContext);
    if (!context) {
        throw new Error('useErrorHandler must be used within an ErrorHandlerContext');
    }
    return context;
}

const {toast} = await importShared('@baseplate-dev/ui-components');
const {useEffect,useRef} = await importShared('react');
function useResettableForm(props) {
    const formProps = useForm(props);
    const { reset, formState } = formProps;
    const { isDirty } = formState;
    const { updatedExternally } = useProjectDefinition();
    const oldValues = useRef(undefined);
    useEffect(() => {
        if (oldValues.current &&
            !isEqual(oldValues.current.oldDefaultValues, props?.defaultValues)) {
            reset(props?.defaultValues);
            if (isDirty && updatedExternally) {
                toast.warning('Contents were updated externally so form was reset!');
            }
        }
        if (!oldValues.current ||
            !isEqual(oldValues.current.oldDefaultValues, props?.defaultValues)) {
            oldValues.current = {
                oldDefaultValues: props?.defaultValues,
            };
        }
    }, [props?.defaultValues, reset, updatedExternally, isDirty]);
    return formProps;
}

function createAdminCrudActionWebConfig(config) {
    return config;
}
function createAdminCrudActionWebImplementation() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const actions = new Map();
    return {
        registerActionWebConfig(action) {
            if (actions.has(action.name)) {
                throw new Error(`Admin CRUD action with name ${action.name} is already registered`);
            }
            actions.set(action.name, action);
        },
        getActionWebConfig(name, builtInActions = []) {
            const builtInAction = builtInActions.find((b) => b.name === name);
            if (builtInAction) {
                return builtInAction;
            }
            const action = actions.get(name);
            if (!action) {
                throw new Error(`Unable to find action with name ${name}`);
            }
            return action;
        },
        getActionWebConfigs(builtInActions = []) {
            return [...builtInActions, ...actions.values()];
        },
    };
}
/**
 * Spec for adding config component for plugin
 */
const adminCrudActionWebSpec = createPluginSpec('core/admin-crud-action-web', { defaultInitializer: createAdminCrudActionWebImplementation });

function createAdminCrudColumnWebConfig(config) {
    return config;
}
function createAdminCrudColumnWebImplementation() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const columns = new Map();
    return {
        registerColumnWebConfig(column) {
            if (columns.has(column.name)) {
                throw new Error(`Admin CRUD column with name ${column.name} is already registered`);
            }
            columns.set(column.name, column);
        },
        getColumnWebConfig(name, builtInColumns = []) {
            const builtInColumn = builtInColumns.find((b) => b.name === name);
            if (builtInColumn) {
                return builtInColumn;
            }
            const column = columns.get(name);
            if (!column) {
                throw new Error(`Unable to find column with name ${name}`);
            }
            return column;
        },
        getColumnWebConfigs(builtInColumns = []) {
            return [...builtInColumns, ...columns.values()];
        },
    };
}
/**
 * Spec for adding config component for plugin
 */
const adminCrudColumnWebSpec = createPluginSpec('core/admin-crud-column-web', { defaultInitializer: createAdminCrudColumnWebImplementation });

function createAdminCrudInputWebConfig(config) {
    return config;
}
function createAdminCrudInputWebImplementation() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const inputs = new Map();
    return {
        registerInputWebConfig(input) {
            if (inputs.has(input.name)) {
                throw new Error(`Admin CRUD input with name ${input.name} is already registered`);
            }
            inputs.set(input.name, input);
        },
        getInputWebConfig(name, builtInInputs = []) {
            const builtInInput = builtInInputs.find((b) => b.name === name);
            if (builtInInput) {
                return builtInInput;
            }
            const input = inputs.get(name);
            if (!input) {
                throw new Error(`Unable to find input with name ${name}`);
            }
            return input;
        },
        getInputWebConfigs(builtInInputs = []) {
            return [...builtInInputs, ...inputs.values()];
        },
    };
}
/**
 * Spec for adding config component for plugin
 */
const adminCrudInputWebSpec = createPluginSpec('core/admin-crud-input-web', { defaultInitializer: createAdminCrudInputWebImplementation });

function createNewModelTransformerWebConfig(config) {
    return config;
}
function createModelTransformerWebImplementation() {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const transformers = new Map();
    return {
        registerTransformerWebConfig(transformer) {
            if (transformers.has(transformer.name)) {
                throw new Error(`Model transformer with name ${transformer.name} is already registered`);
            }
            transformers.set(transformer.name, transformer);
        },
        getTransformerWebConfig(name, builtInTransformers = []) {
            const builtInTransformer = builtInTransformers.find((b) => b.name === name);
            if (builtInTransformer) {
                return builtInTransformer;
            }
            const transformer = transformers.get(name);
            if (!transformer) {
                throw new Error(`Unable to find transformer with name ${name}`);
            }
            return transformer;
        },
        getTransformerWebConfigs(builtInTransformers = []) {
            return [...builtInTransformers, ...transformers.values()];
        },
    };
}
/**
 * Spec for adding config component for plugin
 */
const modelTransformerWebSpec = createPluginSpec('core/model-transformer-web', { defaultInitializer: createModelTransformerWebImplementation });

function setUndefinedIfEmpty(value) {
    if (value === '')
        return undefined;
    return value;
}

export { ErrorHandlerContext, FeatureComboboxField, FeatureComboboxFieldController, ModelComboboxField, ModelComboboxFieldController, ModelMergerResultAlert, ProjectDefinitionContext, adminCrudActionWebSpec, adminCrudColumnWebSpec, adminCrudInputWebSpec, createAdminCrudActionWebConfig, createAdminCrudActionWebImplementation, createAdminCrudColumnWebConfig, createAdminCrudColumnWebImplementation, createAdminCrudInputWebConfig, createAdminCrudInputWebImplementation, createModelTransformerWebImplementation, createNewModelTransformerWebConfig, modelTransformerWebSpec, setUndefinedIfEmpty, useBlockBeforeContinue, useBlockDirtyFormNavigate, useBlockUnsavedChangesNavigate, useBlockerDialog, useBlockerDialogState, useDefinitionSchema, useErrorHandler, useProjectDefinition, useResettableForm };
//# sourceMappingURL=web-DMyVa7vy.js.map
