/// import { CodeComponentElement, CSSProperties } from "./element-types"; import { ComponentContextConfig, ProjectData, PropType, RestrictPropType, StudioOps } from "./types/component-types"; import { InferDataType } from "./types/shared-controls"; import { TupleUnion } from "./types/type-utils"; export type * from "./prop-types"; export interface ActionProps

{ componentProps: P; /** * `contextData` can be `null` if the prop controls are rendering before * the component instance itself (it will re-render once the component * calls `setControlContextData`) */ contextData: InferDataType

| null; /** * Operations available to the editor that allow modifying the entire component. */ studioOps: StudioOps; /** * Metadata from the studio project. */ projectData: ProjectData; /** * The document that the component will be rendered into; instead of using * `document` directly (for, say, `document.querySelector()` etc.), you * should use this instead. */ studioDocument: typeof document; } export type Action

= { type: "button-action"; label: string; onClick: (props: ActionProps

) => void; hidden?: ComponentContextConfig; } | { type: "custom-action"; control: React.ComponentType>; hidden?: ComponentContextConfig; }; type DistributedKeyOf = T extends any ? keyof T : never; interface ComponentTemplate

extends Omit, "type" | "name"> { /** * A preview picture for the template. */ previewImg?: string; } export interface ComponentTemplates

{ [name: string]: ComponentTemplate

; } export type StateSpec

= { onChangeProp: string; /** * If true, will hide the state on studio. */ hidden?: ComponentContextConfig; /** * If true, will hide the state in a collapsed section; good for states that * should not usually be used. */ advanced?: ComponentContextConfig; } & ({ type: "readonly"; variableType: "text"; initVal?: string; } | { type: "readonly"; variableType: "number"; initVal?: number; } | { type: "readonly"; variableType: "boolean"; initVal?: boolean; } | { type: "readonly"; variableType: "array"; initVal?: any[]; } | { type: "readonly"; variableType: "object"; initVal?: object; } | { type: "readonly"; variableType: "dateString"; initVal?: string; } | { type: "readonly"; variableType: "dateRangeStrings"; initVal?: [string, string]; } | { type: "writable"; variableType: "text" | "number" | "boolean" | "array" | "object" | "dateString" | "dateRangeStrings"; valueProp: string; }); export interface StateHelpers { initFunc?: ($props: P) => T; onChangeArgsToValue?: (...args: any) => T; onMutate?: (stateValue: T, $ref: any) => void; } export declare const stateHelpersKeys: TupleUnion>; export type ComponentHelpers

= { states: Record>; }; export type ExternalComponentHelpers

= { helpers: ComponentHelpers

; importPath: string; } & ({ importName: string; } | { isDefaultExport: true; }); export type StyleSection = "visibility" | "typography" | "sizing" | "spacing" | "background" | "transform" | "transitions" | "layout" | "overflow" | "border" | "shadows" | "effects"; export interface CodeComponentMeta

{ /** * Any unique string name used to identify that component. Each component * should be registered with a different `meta.name`, even if they have the * same name in the code. */ name: string; /** * The name to be displayed for the component in Studio. Optional: if not * specified, `meta.name` is used. */ displayName?: string; /** * The description of the component to be shown in Studio. */ description?: string; /** * A specific section to which the component should be displayed in Studio. By default, the component will be displayed in the "Custom Components" section. * A new section will be created to display the components with the same `section` value. */ section?: string; /** * A link to an image that will be displayed as a thumbnail of the component in the Studio, if the component has a `section` specified. */ thumbnailUrl?: string; /** * The javascript name to be used when generating code. Optional: if not * provided, `meta.name` is used. */ importName?: string; /** * An object describing the component properties to be used in Studio. * For each `prop`, there should be an entry `meta.props[prop]` describing * its type. */ props: { [prop in DistributedKeyOf

]?: RestrictPropType; } & { [prop: string]: PropType

; }; /** * An object describing the component states to be used in Studio. */ states?: Record>; /** * An object describing the components helpers to be used in Studio. * 1. states helpers: Each state can receive an "initFunc" prop to initialize * the implicit state in Studio, and an "onChangeArgsToValue" prop to * transform the event handler arguments into a value */ componentHelpers?: ExternalComponentHelpers

; /** * An array describing the component actions to be used in Studio. */ actions?: Action

[]; /** * Whether style sections should be shown in Studio. For styles to work, the * component must accept a `className` prop. If unset, defaults to all styles. * Set to `false` if this component cannot be styled (for example, if it doesn't * render any DOM elements). */ styleSections?: StyleSection[] | boolean; /** * Whether the element can be repeated in Studio. If unset, defaults to true. */ isRepeatable?: boolean; /** * The path to be used when importing the component in the generated code. * It can be the name of the package that contains the component, or the path * to the file in the project (relative to the root directory). */ importPath: string; /** * Whether the component is the default export from that path. Optional: if * not specified, it's considered `false`. */ isDefaultExport?: boolean; /** * The prop that expects the CSS classes with styles to be applied to the * component. Optional: if not specified, Plasmic will expect it to be * `className`. Notice that if the component does not accept CSS classes, the * component will not be able to receive styles from the Studio. */ classNameProp?: string; /** * The prop that receives and forwards a React `ref`. Plasmic only uses `ref` * to interact with components, so it's not used in the generated code. * Optional: If not provided, the usual `ref` is used. */ refProp?: string; /** * Default styles to start with when instantiating the component in Plasmic. */ defaultStyles?: CSSProperties; /** * Component templates to start with on Plasmic. */ templates?: ComponentTemplates

; /** * Registered name of parent component, used for grouping related components. */ parentComponentName?: string; /** * Whether the component can be used as an attachment to an element. */ isAttachment?: boolean; /** * Whether the component provides data to its slots using DataProvider. */ providesData?: boolean; /** * If specified, then Figma components with the specified names will be mapped * to this component when you paste Figma content into Plasmic */ figmaMappings?: { figmaComponentName: string; }[]; /** * If specified, then Figma components will have their properties transformed * before being applied to this component. This is useful for transforming Figma * properties to the format expected by the component. */ figmaPropsTransform?: (props: Record) => Record>; /** * If true, when an instance of this component is added, the element * will always be named by the name of this component. */ alwaysAutoName?: boolean; /** * If true, then won't be listed in the insert menu for content creators. */ hideFromContentCreators?: boolean; refActions?: Record>; /** * Optional function that takes in component props and context, and returns * a string that will be used for labeling this element in the Outline panel * on the left of the Studio. This makes it easy to identify an element when * looking at the tree. */ treeLabel?: ComponentContextConfig; /** * The value of the CSS display property used by this component. * Plasmic passes in a class name prop to components to let users style them, * but normally this does not include layout properties like display. * However, if the user has set the components visibility to be visible * (for instance, in the base variant it was set to not visible ie display none, * but in a variant it's overridden to be visible), then Plasmic needs to know * what display property to set. * Defaults to "flex". */ defaultDisplay?: string; /** * When true, when you click for the first time anywhere in the component including its slots, the component itself is * selected, making it easier to select the component instead of slot contents. So for instance, setting this on a * Button ensures that clicking on the Button’s text will still select the Button and not the text element in its * slot. Clicking again will deep-select the slot content. */ trapsFocus?: boolean; /** * An object registering code component's variants that should be allowed in Studio, when the component is * used as the root of a Studio component. */ variants?: Record; } export type CodeComponentMode = "advanced" | "simplified" | "database-schema-driven"; export interface FunctionParam

{ name: string; displayName?: string; type: PropType

; } export interface RefActionRegistration

{ displayName?: string; description?: string; argTypes: FunctionParam

[]; } export interface ComponentRegistration { component: React.ComponentType; meta: CodeComponentMeta; } declare global { interface Window { __PlasmicComponentRegistry: ComponentRegistration[]; } } export default function registerComponent>(component: T, meta: CodeComponentMeta>): void;