/**
 * Type-Safe Content Entries
 *
 * This module provides type-safe helpers for defining content types and entries
 * in SDK site configurations. When used with `as const`, TypeScript can infer
 * the exact shape of entry data from the content type's field definitions.
 *
 * @example
 * ```typescript
 * import { defineTypedContentType, createEntry, tiptap } from '@riverbankcms/sdk/config';
 *
 * // Define content type with `as const` for type inference
 * export const testimonialType = defineTypedContentType({
 *   key: 'testimonial',
 *   name: 'Testimonial',
 *   hasPages: false,
 *   fields: [
 *     { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },
 *     { id: 'quote', type: 'richText', label: 'Quote', required: true },
 *   ],
 * } as const);
 *
 * // Create entry with full type safety
 * const entry = createEntry(testimonialType, {
 *   identifier: 'testimonial-1',
 *   data: {
 *     name: 'John Doe',      // TypeScript knows this is string
 *     quote: tiptap.paragraph('Great service!'),  // TypeScript knows this is TipTapNode
 *   },
 * });
 * ```
 */
import type { BooleanFieldDefinition, ContentTypeSelectFieldDefinition, DateFieldDefinition, DateTimeFieldDefinition, EntryPickerFieldDefinition, FieldDefinition, GroupFieldDefinition, LinkFieldDefinition, MediaFieldDefinition, ModalFieldDefinition, NumberFieldDefinition, PresetOrCustomFieldDefinition, ReferenceFieldDefinition, RepeaterFieldDefinition, RichTextFieldDefinition, SelectFieldDefinition, SlugFieldDefinition, TabGroupFieldDefinition, TextFieldDefinition, TimeFieldDefinition, UrlFieldDefinition } from './field-definitions';
import type { LinkValue, Media, TipTapNode } from '../contracts';
import type { ContentTypeConfig, EntryConfig } from './content-types';
export type { TipTapNode, Media, LinkValue, InternalLinkValue, ExternalLinkValue, CustomLinkValue, } from '../contracts';
/**
 * Infers the data object shape from tabGroup tabs (flattens all tab fields).
 * TabGroup fields flatten all their tab fields into a single data object.
 */
type InferDataFromTabs<Tabs extends readonly {
    fields: readonly FieldDefinition[];
}[]> = InferDataFromFields<Tabs[number]['fields']>;
/**
 * Maps a field definition to its TypeScript value type.
 * Uses conditional types to infer the correct type based on field.type.
 *
 * Coverage:
 * - Simple primitives: text, boolean, number
 * - Complex types: richText (TipTapNode), media (Media | null), link (LinkValue | null)
 * - Date/time: date, time, datetime (all ISO strings)
 * - String-value: slug, url, reference, presetOrCustom, contentTypeSelect
 * - Select: single (string) vs multiple (string[])
 * - Entry picker: string | null
 * - Nested: group, modal (nested InferDataFromFields)
 * - Repeater: monomorphic (array) and polymorphic (discriminated union array)
 * - TabGroup: flattened fields from all tabs
 */
export type FieldValueType<F extends FieldDefinition> = F extends {
    type: 'text';
} ? string : F extends {
    type: 'boolean';
} ? boolean : F extends {
    type: 'number';
} ? number : F extends {
    type: 'richText';
} ? TipTapNode : F extends {
    type: 'media';
} ? Media | null : F extends {
    type: 'link';
} ? LinkValue | null : F extends {
    type: 'date';
} ? string : F extends {
    type: 'time';
} ? string : F extends {
    type: 'datetime';
} ? string : F extends {
    type: 'slug';
} ? string : F extends {
    type: 'url';
} ? string : F extends {
    type: 'reference';
} ? string : F extends {
    type: 'presetOrCustom';
} ? string : F extends {
    type: 'contentTypeSelect';
} ? string : F extends {
    type: 'select';
    multiple: true;
} ? string[] : F extends {
    type: 'select';
} ? string : F extends {
    type: 'entryPicker';
} ? string | null : F extends TextFieldDefinition ? string : F extends BooleanFieldDefinition ? boolean : F extends NumberFieldDefinition ? number : F extends RichTextFieldDefinition ? TipTapNode : F extends MediaFieldDefinition ? Media | null : F extends LinkFieldDefinition ? LinkValue | null : F extends DateFieldDefinition ? string : F extends TimeFieldDefinition ? string : F extends DateTimeFieldDefinition ? string : F extends SlugFieldDefinition ? string : F extends UrlFieldDefinition ? string : F extends ReferenceFieldDefinition ? string : F extends PresetOrCustomFieldDefinition ? string : F extends ContentTypeSelectFieldDefinition ? string : F extends SelectFieldDefinition & {
    multiple: true;
} ? string[] : F extends SelectFieldDefinition ? string : F extends EntryPickerFieldDefinition ? string | null : F extends GroupFieldDefinition & {
    schema: {
        fields: infer GF;
    };
} ? GF extends readonly FieldDefinition[] ? InferDataFromFields<GF> : never : F extends ModalFieldDefinition & {
    schema: {
        fields: infer MF;
    };
} ? MF extends readonly FieldDefinition[] ? InferDataFromFields<MF> : never : F extends {
    type: 'repeater';
    polymorphic: true;
} ? unknown[] : F extends RepeaterFieldDefinition & {
    schema: {
        fields: infer RF;
    };
} ? RF extends readonly FieldDefinition[] ? InferDataFromFields<RF>[] : never : F extends TabGroupFieldDefinition & {
    tabs: infer T;
} ? T extends readonly {
    fields: readonly FieldDefinition[];
}[] ? InferDataFromTabs<T> : never : unknown;
/**
 * Infers the data object shape from an array of field definitions.
 * Required fields are non-optional, optional fields are `| undefined`.
 *
 * @example
 * ```typescript
 * const fields = [
 *   { id: 'name', type: 'text', required: true },
 *   { id: 'bio', type: 'text', required: false },
 * ] as const;
 *
 * type Data = InferDataFromFields<typeof fields>;
 * // { name: string; bio: string | undefined }
 * ```
 */
export type InferDataFromFields<Fields extends readonly FieldDefinition[]> = {
    [F in Fields[number] as F['id']]: F extends {
        required: true;
    } ? FieldValueType<F> : FieldValueType<F> | undefined;
};
/**
 * A content type definition with preserved field types for type inference.
 * Extends ContentTypeConfig to ensure all required fields are present.
 * The generic parameters capture the literal types from `as const`.
 */
export interface TypedContentType<K extends string = string, F extends readonly FieldDefinition[] = readonly FieldDefinition[]> extends Omit<ContentTypeConfig, 'key' | 'fields'> {
    key: K;
    fields: F;
}
/**
 * Define a content type with preserved field types for type inference.
 *
 * IMPORTANT: Use `as const` on the config object to enable type inference.
 * Without `as const`, TypeScript widens literal types and inference won't work.
 *
 * @param config - The content type configuration
 * @returns The same config object with preserved types
 *
 * @example
 * ```typescript
 * export const testimonialType = defineTypedContentType({
 *   key: 'testimonial',
 *   name: 'Testimonial',
 *   hasPages: false,
 *   fields: [
 *     { id: 'name', type: 'text', label: 'Name', required: true, multiline: false },
 *     { id: 'quote', type: 'richText', label: 'Quote', required: true },
 *   ],
 * } as const);
 * ```
 */
export declare function defineTypedContentType<K extends string, F extends readonly FieldDefinition[]>(config: TypedContentType<K, F>): TypedContentType<K, F>;
/**
 * Entry configuration with typed data field.
 * Used internally by createEntry to enforce type safety.
 */
export interface TypedEntryConfig<Data extends Record<string, unknown>> {
    /** Unique identifier for this entry. Required for SDK sync. */
    identifier: string;
    /** Slug for routable entries */
    slug?: string;
    /** Status: 'draft' or 'published' */
    status?: 'draft' | 'published';
    /** Summary/description */
    summary?: string;
    /** SEO meta title */
    metaTitle?: string;
    /** SEO meta description */
    metaDescription?: string;
    /** Entry data matching the content type's field definitions */
    data: Data;
}
/**
 * Create a type-safe content entry for a typed content type.
 *
 * The data field is validated against the content type's field definitions.
 * TypeScript will error if:
 * - A required field is missing
 * - A field name is misspelled
 * - A field value has the wrong type
 * - An extra field is provided (with strict mode)
 *
 * @param contentType - The typed content type definition
 * @param entry - The entry configuration with typed data
 * @returns EntryConfig compatible with SDK content configuration
 *
 * @example
 * ```typescript
 * const entry = createEntry(testimonialType, {
 *   identifier: 'testimonial-1',
 *   status: 'published',
 *   data: {
 *     name: 'John Doe',
 *     quote: tiptap.paragraph('Great service!'),
 *   },
 * });
 * ```
 */
export declare function createEntry<K extends string, F extends readonly FieldDefinition[]>(contentType: TypedContentType<K, F>, entry: TypedEntryConfig<InferDataFromFields<F>>): EntryConfig;
/**
 * Helpers for creating TipTap document structures.
 *
 * Use these helpers when populating richText fields to avoid manually
 * constructing the TipTap JSON structure.
 *
 * @example
 * ```typescript
 * // Simple paragraph
 * const body = tiptap.paragraph('Hello, world!');
 *
 * // Empty document
 * const emptyDoc = tiptap.empty();
 *
 * // Complex document
 * const doc = tiptap.doc([
 *   tiptap.heading(1, 'Welcome'),
 *   { type: 'paragraph', content: [{ type: 'text', text: 'Introduction...' }] },
 * ]);
 * ```
 */
export declare const tiptap: {
    /**
     * Create an empty TipTap document.
     *
     * @returns An empty TipTap document node
     */
    empty(): TipTapNode;
    /**
     * Create a TipTap document with a single paragraph.
     *
     * @param text - The paragraph text content
     * @returns A TipTap document with one paragraph
     */
    paragraph(text: string): TipTapNode;
    /**
     * Create a TipTap document with custom content nodes.
     *
     * @param content - Array of TipTap nodes to include in the document
     * @returns A TipTap document wrapping the content
     */
    doc(content: TipTapNode[]): TipTapNode;
    /**
     * Create a heading node.
     *
     * Note: This returns a heading node, not a document. Use with tiptap.doc()
     * to create a complete document.
     *
     * @param level - Heading level (1-6)
     * @param text - Heading text content
     * @returns A TipTap heading node
     */
    heading(level: 1 | 2 | 3 | 4 | 5 | 6, text: string): TipTapNode;
};
