CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-strapi--helper-plugin

Helper library for Strapi plugins development providing React components, hooks, utilities, and TypeScript types for building plugin interfaces

Pending
Overview
Eval results
Files

content-manager.mddocs/

Content Manager

The @strapi/helper-plugin package provides content manager utilities and React context for managing content types, relations, and CRUD operations within the Strapi admin interface. These exports enable plugins to integrate seamlessly with Strapi's content management system.

Context & Hook

React context and hook for accessing content manager state and operations.

// Content manager context hook
interface CMEditViewDataManagerContextValue {
  // Core data
  initialData: ContentType;
  modifiedData: ContentType;
  formErrors: Record<string, TranslationMessage>;
  
  // Layout and permissions
  layout?: Schema.CollectionType | Schema.SingleType;
  allLayoutData: {
    components: Record<string, Schema.Component>;
    contentType?: Schema.ContentType;
  };
  createActionAllowedFields: string[];
  readActionAllowedFields: string[];
  updateActionAllowedFields: string[];
  
  // State flags
  isCreatingEntry: boolean;
  isSingleType: boolean;
  hasDraftAndPublish: boolean;
  shouldNotRunValidations?: boolean;
  slug?: string;
  status?: string;
  
  // Publishing
  publishConfirmation?: {
    show: boolean;
    draftCount: number;
  };
  onPublish?: () => Promise<unknown>;
  onPublishPromptDismissal?: (e: React.SyntheticEvent) => Promise<void>;
  onUnpublish?: () => Promise<unknown>;
  
  // Form operations
  onChange?: <TAttribute extends Attribute.Any>(
    payload: {
      target: { name: string; type: string; value: Attribute.GetValue<TAttribute> };
    },
    shouldSetInitialValue?: boolean
  ) => void;
  
  // Component operations
  addComponentToDynamicZone?: (
    keys: string,
    componentLayoutData: Record<string, unknown>,
    allComponents: Record<string, unknown>,
    shouldCheckErrors?: boolean,
    position?: number
  ) => void;
  addNonRepeatableComponentToField?: (
    keys: string,
    componentLayoutData: Schema.Component,
    allComponents: Record<string, Schema.Component>
  ) => void;
  addRepeatableComponentToField?: (
    keys: string,
    componentLayoutData: Record<string, unknown>,
    allComponents: Record<string, unknown>,
    shouldCheckErrors?: boolean,
    position?: number
  ) => void;
  removeComponentFromDynamicZone?: (dynamicZoneName: string, index: number) => void;
  removeComponentFromField?: (key: string, uid: string) => void;
  removeRepeatableField?: (key: string, uid?: string) => void;
  
  // Component movement
  moveComponentDown?: (dynamicZoneName: string, currentIndex: number) => void;
  moveComponentUp?: (dynamicZoneName: string, currentIndex: number) => void;
  moveComponentField?: (payload: { name: string; newIndex: number; currentIndex: number }) => void;
  
  // Relations
  relationConnect?: (payload: {
    name: string;
    value: { id: Entity['id'] };
    toOneRelation?: boolean;
  }) => void;
  relationDisconnect?: (payload: { name: string; id: Entity['id'] }) => void;
  relationLoad?: (payload: {
    target: {
      initialDataPath: string[];
      modifiedDataPath: string[];
      value: { id: Entity['id'] }[];
      modifiedDataOnly?: boolean;
    };
  }) => void;
  relationReorder?: (payload: { name: string; oldIndex: number; newIndex: number }) => void;
}

function useCMEditViewDataManager(): CMEditViewDataManagerContextValue;

// React context instance
const ContentManagerEditViewDataManagerContext: React.Context<CMEditViewDataManagerContextValue>;

Usage Examples:

// Access content manager state and operations
const {
  initialData,
  modifiedData,
  onChange,
  onPublish,
  isCreatingEntry,
  hasDraftAndPublish,
  formErrors
} = useCMEditViewDataManager();

// Handle form field changes
const handleFieldChange = (event) => {
  onChange({
    target: {
      name: event.target.name,
      type: event.target.type,
      value: event.target.value
    }
  });
};

// Check if creating new entry
if (isCreatingEntry) {
  // Show create-specific UI
}

// Handle publishing
const handlePublish = async () => {
  if (onPublish) {
    await onPublish();
  }
};

Content Type Interface

TypeScript interface for content type data structures.

// Content type data interface
interface ContentType extends Partial<Entity> {
  publishedAt?: string | null;
  publishedBy?: User | null;
  [key: string]: Attribute.GetValue<Attribute.Any> | null;
}

// Base entity interface
interface Entity {
  id: StrapiEntity.ID;
  createdAt: string | null;
  createdBy: User | null;
  updatedAt: string | null;
  updatedBy: User | null;
}

// User interface for created/updated by fields
interface User {
  id: StrapiEntity.ID;
  createdAt: string;
  createdBy: User | null;
  updatedAt: string;
  updatedBy: User | null;
  firstname?: string;
  lastname?: string;
  username?: string;
  email?: string;
  isActive: boolean;
  blocked: boolean;
  roles: [];
}

Usage Examples:

// Type-safe content handling
const handleContentUpdate = (content: ContentType) => {
  // Access standard fields
  const { id, createdAt, updatedAt, publishedAt } = content;
  
  // Access custom fields (dynamically typed)
  const title = content.title as string;
  const description = content.description as string;
};

// Publishing workflow
const publishContent = (content: ContentType) => {
  if (content.publishedAt) {
    // Already published
  } else {
    // Draft content
  }
};

Utility Functions

Helper functions for content management operations and data transformation.

// Remove specified fields from content data
function contentManagementUtilRemoveFieldsFromData<
  TSchema extends Schema.ContentType,
  TData extends { [K in keyof TSchema['attributes']]: Attribute.GetValue<TSchema['attributes'][K]> }
>(
  data: TData,
  contentTypeSchema: TSchema,
  componentSchema: Record<string, Schema.Component>,
  fields?: string[]
): TData;

// Format content type data for display/editing
function formatContentTypeData<
  TSchema extends Schema.ContentType,
  TData extends { [K in keyof TSchema['attributes']]: Attribute.GetValue<TSchema['attributes'][K]> }
>(
  data: TData,
  contentTypeSchema: TSchema,
  componentSchema: Record<string, Schema.Component>
): TData;

// Get attribute information from schema
function getType(schema: Schema.Schema, attrName: string): string;
function getOtherInfos(schema: Schema.Schema, path: string[]): any;

Usage Examples:

// Remove system fields before API submission
const cleanedData = contentManagementUtilRemoveFieldsFromData(
  formData,
  contentTypeSchema,
  componentSchemas,
  ['createdBy', 'updatedBy', 'publishedAt'] // Optional custom fields to remove
);

// Format data for editing (adds temp keys for DnD)
const formattedData = formatContentTypeData(
  rawData,
  contentTypeSchema,
  componentSchemas
);

// Get attribute type information
const fieldType = getType(schema, 'myField'); // Returns: 'string', 'number', 'relation', etc.

// Get nested attribute information
const isRepeatable = getOtherInfos(schema, ['myComponent', 'repeatable']);
const componentUid = getOtherInfos(schema, ['myComponent', 'component']);

Integration Patterns

Custom Field Components

// Access content manager context in custom components
const MyCustomField = ({ name, ...props }) => {
  const { modifiedData, onChange, formErrors } = useCMEditViewDataManager();
  
  const fieldValue = modifiedData[name];
  const fieldError = formErrors[name];
  
  const handleChange = (value) => {
    onChange({
      target: { name, type: 'custom', value }
    });
  };
  
  return (
    <CustomInput
      value={fieldValue}
      onChange={handleChange}
      error={fieldError}
      {...props}
    />
  );
};

Component Management

// Add components to dynamic zones
const handleAddComponent = () => {
  const { addComponentToDynamicZone, allLayoutData } = useCMEditViewDataManager();
  
  addComponentToDynamicZone(
    'content', // Dynamic zone field name
    componentLayout,
    allLayoutData.components,
    true, // Check for errors
    0 // Position
  );
};

// Handle repeatable components
const handleAddRepeatableComponent = () => {
  const { addRepeatableComponentToField, allLayoutData } = useCMEditViewDataManager();
  
  addRepeatableComponentToField(
    'features', // Field name
    componentLayout,
    allLayoutData.components
  );
};

Relation Management

// Connect relations
const handleRelationConnect = (selectedItem) => {
  const { relationConnect } = useCMEditViewDataManager();
  
  relationConnect({
    name: 'category',
    value: { id: selectedItem.id },
    toOneRelation: true
  });
};

// Reorder relation items
const handleRelationReorder = (oldIndex, newIndex) => {
  const { relationReorder } = useCMEditViewDataManager();
  
  relationReorder({
    name: 'tags',
    oldIndex,
    newIndex
  });
};

Publishing Workflow

// Handle publish/unpublish operations
const PublishButton = () => {
  const {
    hasDraftAndPublish,
    onPublish,
    onUnpublish,
    modifiedData,
    publishConfirmation
  } = useCMEditViewDataManager();
  
  if (!hasDraftAndPublish) return null;
  
  const isPublished = !!modifiedData.publishedAt;
  
  const handlePublishToggle = async () => {
    if (isPublished && onUnpublish) {
      await onUnpublish();
    } else if (!isPublished && onPublish) {
      await onPublish();
    }
  };
  
  return (
    <Button onClick={handlePublishToggle}>
      {isPublished ? 'Unpublish' : 'Publish'}
    </Button>
  );
};

Data Flow

The content manager context follows a unidirectional data flow:

  1. Initial Data: Loaded from API into initialData
  2. Form Changes: Updates flow to modifiedData via onChange
  3. Validation: Errors stored in formErrors
  4. Submission: Clean data sent to API via utility functions
  5. Publishing: Draft/publish state managed via publish methods

This pattern ensures consistent state management and proper data handling throughout the content editing lifecycle.

Install with Tessl CLI

npx tessl i tessl/npm-strapi--helper-plugin

docs

content-manager.md

features.md

hooks.md

index.md

types.md

ui-components.md

utilities.md

tile.json