@plasmicapp/host 1.0.112 → 1.0.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -183,6 +183,13 @@ export declare type DataPickerType<P> = ({
183
183
  type: "exprEditor";
184
184
  data: Record<string, any> | ContextDependentConfig<P, Record<string, any>>;
185
185
  } & DefaultValueOrExpr<P, DataPickerValueType> & PropTypeBase<P>);
186
+ export declare type EventHandlerType<P> = {
187
+ type: "eventHandler";
188
+ argTypes: {
189
+ name: string;
190
+ type: PropType<any>;
191
+ }[];
192
+ } & DefaultValueOrExpr<P, (...args: any) => any> & PropTypeBase<P>;
186
193
  interface ChoiceTypeBase<P> extends PropTypeBase<P> {
187
194
  type: "choice";
188
195
  options: string[] | {
@@ -281,7 +288,7 @@ declare type ControlTypeBase = {
281
288
  uncontrolledProp?: string;
282
289
  };
283
290
  export declare type SupportControlled<T> = Extract<T, String | CustomControl<any>> | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);
284
- export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P>> | SlotType<P>;
291
+ export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P> | EventHandlerType<P>> | SlotType<P>;
285
292
  declare type RestrictPropType<T, P> = T extends string ? SupportControlled<StringType<P> | ChoiceType<P> | JSONLikeType<P> | ImageUrlType<P> | CustomType<P> | DataPickerType<P>> : T extends boolean ? SupportControlled<BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : T extends number ? SupportControlled<NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : PropType<P>;
286
293
  export interface ActionProps<P> {
287
294
  componentProps: P;
@@ -325,16 +332,47 @@ interface ComponentTemplate<P> extends Omit<CodeComponentElement<P>, "type" | "n
325
332
  export interface ComponentTemplates<P> {
326
333
  [name: string]: ComponentTemplate<P>;
327
334
  }
328
- interface $State {
329
- [key: string]: any;
330
- }
331
- interface $StateSpec<T> {
332
- type: "private" | "readonly" | "writable";
333
- initFunc?: ($props: Record<string, any>, $state: $State) => T;
334
- initVal?: T;
335
- valueProp?: string;
336
- onChangeProp?: string;
335
+ export declare type StateSpec = {
336
+ onChangeProp: string;
337
+ } & ({
338
+ type: "readonly";
339
+ variableType: "text";
340
+ initVal?: string;
341
+ } | {
342
+ type: "readonly";
343
+ variableType: "number";
344
+ initVal?: number;
345
+ } | {
346
+ type: "readonly";
347
+ variableType: "boolean";
348
+ initVal?: boolean;
349
+ } | {
350
+ type: "readonly";
351
+ variableType: "array";
352
+ initVal?: any[];
353
+ } | {
354
+ type: "readonly";
355
+ variableType: "object";
356
+ initVal?: object;
357
+ } | {
358
+ type: "writable";
359
+ variableType: "text" | "number" | "boolean" | "array" | "object";
360
+ valueProp: string;
361
+ });
362
+ export interface StateHelpers<P, T> {
363
+ initFunc?: ($props: P) => T;
364
+ onChangeArgsToValue?: (...args: any) => T;
337
365
  }
366
+ export declare type ComponentHelpers<P> = {
367
+ helpers: {
368
+ states: Record<string, StateHelpers<P, any>>;
369
+ };
370
+ importPath: string;
371
+ } & ({
372
+ importName: string;
373
+ } | {
374
+ isDefaultExport: true;
375
+ });
338
376
  export declare type StyleSection = "visibility" | "typography" | "sizing" | "spacing" | "background" | "transform" | "transitions" | "layout" | "overflow" | "border" | "shadows" | "effects";
339
377
  export interface ComponentMeta<P> {
340
378
  /**
@@ -368,9 +406,16 @@ export interface ComponentMeta<P> {
368
406
  [prop: string]: PropType<P>;
369
407
  };
370
408
  /**
371
- * WIP: An object describing the component states to be used in Studio.
409
+ * An object describing the component states to be used in Studio.
410
+ */
411
+ states?: Record<string, StateSpec>;
412
+ /**
413
+ * An object describing the components helpers to be used in Studio.
414
+ * 1. states helpers: Each state can receive an "initFunc" prop to initialize
415
+ * the implicit state in Studio, and an "onChangeArgsToValue" prop to
416
+ * transform the event handler arguments into a value
372
417
  */
373
- unstable__states?: Record<string, $StateSpec<any>>;
418
+ componentHelpers?: ComponentHelpers<P>;
374
419
  /**
375
420
  * An array describing the component actions to be used in Studio.
376
421
  */
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const hostVersion = "1.0.112";
1
+ export declare const hostVersion = "1.0.113";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasmicapp/host",
3
- "version": "1.0.112",
3
+ "version": "1.0.113",
4
4
  "description": "plasmic library for app hosting",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -76,5 +76,5 @@
76
76
  "react": ">=16.8.0",
77
77
  "react-dom": ">=16.8.0"
78
78
  },
79
- "gitHead": "67e119ae46c42a2b4440cd98b4d168d0b69ca229"
79
+ "gitHead": "256694dd227acca3600d2475b0985713252d99cb"
80
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../src/registerComponent.ts"],"sourcesContent":["import {\n CodeComponentElement,\n CSSProperties,\n PlasmicElement,\n} from \"./element-types\";\n\nconst root = globalThis as any;\n\nexport interface CanvasComponentProps<Data = any> {\n /**\n * This prop is only provided within the canvas of Plasmic Studio.\n * Allows the component to set data to be consumed by the props' controls.\n */\n setControlContextData?: (data: Data) => void;\n}\n\ntype InferDataType<P> = P extends CanvasComponentProps<infer Data> ? Data : any;\n\n/**\n * Config option that takes the context (e.g., props) of the component instance\n * to dynamically set its value.\n */\nexport type ContextDependentConfig<P, R> = (\n props: P,\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null\n) => R;\n\nexport interface PropTypeBase<P> {\n displayName?: string;\n description?: string;\n helpText?: string;\n /**\n * If the user has chosen to use a dynamic expression for this prop, provide\n * a hint as to the expected values that the expression should evaluate to.\n * This hint will be displayed alongside the code editor. You may use\n * markdown in the text here.\n */\n exprHint?: string;\n hidden?: ContextDependentConfig<P, boolean>;\n readOnly?: boolean | ContextDependentConfig<P, boolean>;\n advanced?: boolean;\n disableDynamicValue?: boolean;\n}\n\nexport type DefaultValueOrExpr<P, T> =\n | {\n defaultExpr?: undefined;\n defaultExprHint?: undefined;\n defaultValue?: T;\n defaultValueHint?: T | ContextDependentConfig<P, T | undefined>;\n }\n | {\n defaultValue?: undefined;\n defaultValueHint?: undefined;\n defaultExpr?: string;\n defaultExprHint?: string;\n };\n\ntype StringTypeBase<P> = PropTypeBase<P> & DefaultValueOrExpr<P, string>;\n\nexport type StringType<P> =\n | \"string\"\n | ((\n | {\n type: \"string\";\n control?: \"default\" | \"large\";\n }\n | {\n type: \"code\";\n lang: \"css\" | \"html\" | \"javascript\" | \"json\";\n }\n | {\n type: \"richText\";\n }\n | {\n type: \"color\";\n /**\n * If specified, and the user picks a color token in the Studio, then\n * the value passed in as prop is a css variable reference, like\n * `var(--TOKEN_ID)`, instead of the resolved hex value of the token.\n * You should take care in using this in the proper css context --\n * the css token is only defined if you are rendering under some\n * Plasmic component in the DOM tree, which is usually the case,\n * unless you are using a React portal.\n */\n keepCssVar?: boolean;\n }\n | {\n type: \"class\";\n /**\n * Additional css selectors that can change how this style should look.\n * Some examples:\n *\n * * `:hover` -- on hover\n * * `[data-something=\"blah\"] -- when the element with this class has\n * an html attribute \"data-something=blah\"\n * * :component[data-something=\"blah\"] :self -- when the root of the\n * component has an html attribute \"data-something=blah\". Note that\n * the non-standard `:component` selector is used to select the\n * component root, and the non-standard `:self` selector is used\n * to select the element that this class is attached to.\n */\n selectors?: {\n /**\n * A css selector, like `:hover` or `[data-something=\"blah\"]`.\n */\n selector: string;\n /**\n * An optional human-friendly label for the selector, so the studio user\n * knows what this selector means.\n */\n label?: string;\n }[];\n /**\n * If specified, then only shows these style sections for styling this class\n */\n styleSections?: StyleSection[];\n }\n | {\n type: \"themeResetClass\";\n /**\n * Normally, theme reset class will only target Plasmic-generated tags\n * with the default tag styles. If you also want to target non-Plasmic-generated\n * tags (say, rendered by your code components, or fetched as an HTML blob\n * from somewhere), then specify `true` here.\n */\n targetAllTags?: boolean;\n }\n | {\n type: \"cardPicker\";\n modalTitle?:\n | React.ReactNode\n | ContextDependentConfig<P, React.ReactNode>;\n options:\n | {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n | ContextDependentConfig<\n P,\n {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n >;\n showInput?: boolean | ContextDependentConfig<P, boolean>;\n onSearch?: ContextDependentConfig<\n P,\n ((value: string) => void) | undefined\n >;\n }\n ) &\n StringTypeBase<P>);\n\nexport type BooleanType<P> =\n | \"boolean\"\n | ({\n type: \"boolean\";\n } & DefaultValueOrExpr<P, boolean> &\n PropTypeBase<P>);\n\ntype GraphQLValue = {\n query: string;\n variables?: Record<string, any>;\n};\n\nexport type GraphQLType<P> = {\n type: \"code\";\n lang: \"graphql\";\n endpoint: string | ContextDependentConfig<P, string>;\n method?: string | ContextDependentConfig<P, string>;\n headers?: object | ContextDependentConfig<P, object>;\n} & DefaultValueOrExpr<P, GraphQLValue> &\n PropTypeBase<P>;\n\ntype NumberTypeBase<P> = PropTypeBase<P> &\n DefaultValueOrExpr<P, number> & {\n type: \"number\";\n };\n\nexport type NumberType<P> =\n | \"number\"\n | ((\n | {\n control?: \"default\";\n min?: number | ContextDependentConfig<P, number>;\n max?: number | ContextDependentConfig<P, number>;\n }\n | {\n control: \"slider\";\n min: number | ContextDependentConfig<P, number>;\n max: number | ContextDependentConfig<P, number>;\n step?: number | ContextDependentConfig<P, number>;\n }\n ) &\n NumberTypeBase<P>);\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type JSONLikeType<P> =\n | \"object\"\n | ({\n type: \"object\";\n fields?: {\n [p: string]: PropType<P>;\n };\n } & DefaultValueOrExpr<P, any> &\n PropTypeBase<P>)\n | ({\n type: \"array\";\n itemType?: {\n type: \"object\";\n fields: {\n [p: string]: PropType<P>;\n };\n /**\n * Optional function that generates a name for this item in the array\n */\n nameFunc?: (item: any) => string | undefined;\n };\n } & DefaultValueOrExpr<P, any[]> &\n PropTypeBase<P>)\n | ({\n type: \"dataSource\";\n dataSource: \"airtable\" | \"cms\";\n } & PropTypeBase<P>);\n\ntype DataPickerValueType = string | number | (string | number)[];\n\nexport type DataPickerType<P> =\n | ({\n type: \"dataSelector\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n alwaysShowValuePathAsLabel?: boolean;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>)\n | ({\n type: \"exprEditor\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>);\n\ninterface ChoiceTypeBase<P> extends PropTypeBase<P> {\n type: \"choice\";\n options:\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n | ContextDependentConfig<\n P,\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n >;\n allowSearch?: boolean;\n filterOption?: boolean;\n onSearch?: ContextDependentConfig<P, ((value: string) => void) | undefined>;\n}\n\nexport type ChoiceType<P> = (\n | ({\n multiSelect?: false;\n } & DefaultValueOrExpr<P, string | number | boolean>)\n | ({\n multiSelect: true;\n } & DefaultValueOrExpr<P, (string | number | boolean)[]>)\n | ({\n multiSelect: ContextDependentConfig<P, boolean>;\n } & DefaultValueOrExpr<\n P,\n string | number | boolean | (string | number | boolean)[]\n >)\n) &\n ChoiceTypeBase<P>;\n\nexport interface ModalProps {\n show?: boolean;\n children?: React.ReactNode;\n onClose: () => void;\n style?: CSSProperties;\n}\n\ninterface CustomControlProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n value: any;\n /**\n * Sets the value to be passed to the prop. Expects a JSON-compatible value.\n */\n updateValue: (newVal: any) => void;\n /**\n * Full screen modal component\n */\n FullscreenModal: React.ComponentType<ModalProps>;\n /**\n * Modal component for the side pane\n */\n SideModal: React.ComponentType<ModalProps>;\n\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\nexport type CustomControl<P> = React.ComponentType<CustomControlProps<P>>;\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type CustomType<P> =\n | CustomControl<P>\n | ({\n type: \"custom\";\n control: CustomControl<P>;\n } & PropTypeBase<P> &\n DefaultValueOrExpr<P, any>);\n\ntype SlotType<P> =\n | \"slot\"\n | ({\n type: \"slot\";\n /**\n * The unique names of all code components that can be placed in the slot\n */\n allowedComponents?: string[];\n /**\n * Whether the \"empty slot\" placeholder should be hidden in the canvas.\n */\n hidePlaceholder?: boolean;\n /**\n * Whether the slot is repeated, i.e., is rendered multiple times using\n * repeatedElement().\n */\n isRepeated?: boolean;\n\n /**\n * If slot is a render prop (accepts a function that takes in some\n * arguments and returns some JSX), then specify the names of the\n * arguments expected by the render prop function.\n */\n renderPropParams?: string[];\n } & Omit<\n DefaultValueOrExpr<P, PlasmicElement | PlasmicElement[]>,\n \"defaultValueHint\" | \"defaultExpr\" | \"defaultExprHint\"\n >);\n\ntype ImageUrlType<P> =\n | \"imageUrl\"\n | ({\n type: \"imageUrl\";\n } & DefaultValueOrExpr<P, string> &\n PropTypeBase<P>);\n\nexport type PrimitiveType<P = any> = Extract<\n StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P>,\n String\n>;\n\ntype ControlTypeBase =\n | {\n editOnly?: false;\n }\n | {\n editOnly: true;\n /**\n * The prop where the values should be mapped to\n */\n uncontrolledProp?: string;\n };\n\nexport type SupportControlled<T> =\n | Extract<T, String | CustomControl<any>>\n | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);\n\nexport type PropType<P> =\n | SupportControlled<\n | StringType<P>\n | BooleanType<P>\n | NumberType<P>\n | JSONLikeType<P>\n | ChoiceType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | GraphQLType<P>\n | DataPickerType<P>\n >\n | SlotType<P>;\n\ntype RestrictPropType<T, P> = T extends string\n ? SupportControlled<\n | StringType<P>\n | ChoiceType<P>\n | JSONLikeType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | DataPickerType<P>\n >\n : T extends boolean\n ? SupportControlled<\n BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : T extends number\n ? SupportControlled<\n NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : PropType<P>;\n\nexport interface ActionProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n studioOps: {\n showModal: (\n modalProps: Omit<ModalProps, \"onClose\"> & { onClose?: () => void }\n ) => void;\n refreshQueryData: () => void;\n appendToSlot: (element: PlasmicElement, slotName: string) => void;\n removeFromSlotAt: (pos: number, slotName: string) => void;\n updateProps: (newValues: any) => void;\n };\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\n\nexport type Action<P> =\n | {\n type: \"button-action\";\n label: string;\n onClick: (props: ActionProps<P>) => void;\n }\n | {\n type: \"custom-action\";\n control: React.ComponentType<ActionProps<P>>;\n };\n\ntype DistributedKeyOf<T> = T extends any ? keyof T : never;\n\ninterface ComponentTemplate<P>\n extends Omit<CodeComponentElement<P>, \"type\" | \"name\"> {\n /**\n * A preview picture for the template.\n */\n previewImg?: string;\n}\n\nexport interface ComponentTemplates<P> {\n [name: string]: ComponentTemplate<P>;\n}\ninterface $State {\n [key: string]: any;\n}\n\ninterface $StateSpec<T> {\n // Whether this state is private, readonly, or writable in\n // this component\n type: \"private\" | \"readonly\" | \"writable\";\n // if initial value is defined by a js expression\n initFunc?: ($props: Record<string, any>, $state: $State) => T;\n\n // if initial value is a hard-coded value\n initVal?: T;\n // Whether this state is private, readonly, or writable in\n // this component\n\n // If writable, there should be a valueProp that maps props[valueProp]\n // to the value of the state\n valueProp?: string;\n\n // If writable or readonly, there should be an onChangeProp where\n // props[onChangeProp] is invoked whenever the value changes\n onChangeProp?: string;\n}\n\nexport type StyleSection =\n | \"visibility\"\n | \"typography\"\n | \"sizing\"\n | \"spacing\"\n | \"background\"\n | \"transform\"\n | \"transitions\"\n | \"layout\"\n | \"overflow\"\n | \"border\"\n | \"shadows\"\n | \"effects\";\n\nexport interface ComponentMeta<P> {\n /**\n * Any unique string name used to identify that component. Each component\n * should be registered with a different `meta.name`, even if they have the\n * same name in the code.\n */\n name: string;\n /**\n * The name to be displayed for the component in Studio. Optional: if not\n * specified, `meta.name` is used.\n */\n displayName?: string;\n /**\n * The description of the component to be shown in Studio.\n */\n description?: string;\n /**\n * The javascript name to be used when generating code. Optional: if not\n * provided, `meta.name` is used.\n */\n importName?: string;\n /**\n * An object describing the component properties to be used in Studio.\n * For each `prop`, there should be an entry `meta.props[prop]` describing\n * its type.\n */\n props: { [prop in DistributedKeyOf<P>]?: RestrictPropType<P[prop], P> } & {\n [prop: string]: PropType<P>;\n };\n /**\n * WIP: An object describing the component states to be used in Studio.\n */\n unstable__states?: Record<string, $StateSpec<any>>;\n /**\n * An array describing the component actions to be used in Studio.\n */\n actions?: Action<P>[];\n /**\n * Whether style sections should be shown in Studio. For styles to work, the\n * component must accept a `className` prop. If unset, defaults to all styles.\n * Set to `false` if this component cannot be styled (for example, if it doesn't\n * render any DOM elements).\n */\n styleSections?: StyleSection[] | boolean;\n /**\n * Whether the element can be repeated in Studio. If unset, defaults to true.\n */\n isRepeatable?: boolean;\n /**\n * The path to be used when importing the component in the generated code.\n * It can be the name of the package that contains the component, or the path\n * to the file in the project (relative to the root directory).\n */\n importPath: string;\n /**\n * Whether the component is the default export from that path. Optional: if\n * not specified, it's considered `false`.\n */\n isDefaultExport?: boolean;\n /**\n * The prop that expects the CSS classes with styles to be applied to the\n * component. Optional: if not specified, Plasmic will expect it to be\n * `className`. Notice that if the component does not accept CSS classes, the\n * component will not be able to receive styles from the Studio.\n */\n classNameProp?: string;\n /**\n * The prop that receives and forwards a React `ref`. Plasmic only uses `ref`\n * to interact with components, so it's not used in the generated code.\n * Optional: If not provided, the usual `ref` is used.\n */\n refProp?: string;\n /**\n * Default styles to start with when instantiating the component in Plasmic.\n */\n defaultStyles?: CSSProperties;\n /**\n * Component templates to start with on Plasmic.\n */\n templates?: ComponentTemplates<P>;\n /**\n * Registered name of parent component, used for grouping related components.\n */\n parentComponentName?: string;\n /**\n * Whether the component can be used as an attachment to an element.\n */\n isAttachment?: boolean;\n /**\n * Whether the component provides data to its slots using DataProvider.\n */\n providesData?: boolean;\n\n /**\n * If specified, then Figma components with the specified names will be mapped\n * to this component when you paste Figma content into Plasmic\n */\n figmaMappings?: {\n figmaComponentName: string;\n }[];\n\n /**\n * If true, when an instance of this component is added, the element\n * will always be named by the name of this component.\n */\n alwaysAutoName?: boolean;\n\n unstable__refActions?: Record<string, RefActionRegistration<P>>;\n}\n\nexport interface FunctionParam<P> {\n name: string;\n displayName?: string;\n type: PropType<P>;\n}\n\nexport interface RefActionRegistration<P> {\n displayName?: string;\n description?: string;\n parameters: FunctionParam<P>[];\n}\n\nexport interface ComponentRegistration {\n component: React.ComponentType<any>;\n meta: ComponentMeta<any>;\n}\n\ndeclare global {\n interface Window {\n __PlasmicComponentRegistry: ComponentRegistration[];\n }\n}\n\nif (root.__PlasmicComponentRegistry == null) {\n root.__PlasmicComponentRegistry = [];\n}\n\nexport default function registerComponent<T extends React.ComponentType<any>>(\n component: T,\n meta: ComponentMeta<React.ComponentProps<T>>\n) {\n // Check for duplicates\n if (\n root.__PlasmicComponentRegistry.some(\n (r: ComponentRegistration) =>\n r.component === component && r.meta.name === meta.name\n )\n ) {\n return;\n }\n root.__PlasmicComponentRegistry.push({ component, meta });\n}\n"],"names":[],"mappings":";;;;;AAMA,IAAM,IAAI,GAAG,UAAiB,CAAC;AAuoB/B,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;IAC3C,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAC;CACtC;SAEuB,iBAAiB,CACvC,SAAY,EACZ,IAA4C;;IAG5C,IACE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAClC,UAAC,CAAwB;QACvB,OAAA,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;KAAA,CACzD,EACD;QACA,OAAO;KACR;IACD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,SAAS,WAAA,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;AAC5D;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../src/registerComponent.ts"],"sourcesContent":["import {\n CodeComponentElement,\n CSSProperties,\n PlasmicElement,\n} from \"./element-types\";\n\nconst root = globalThis as any;\n\nexport interface CanvasComponentProps<Data = any> {\n /**\n * This prop is only provided within the canvas of Plasmic Studio.\n * Allows the component to set data to be consumed by the props' controls.\n */\n setControlContextData?: (data: Data) => void;\n}\n\ntype InferDataType<P> = P extends CanvasComponentProps<infer Data> ? Data : any;\n\n/**\n * Config option that takes the context (e.g., props) of the component instance\n * to dynamically set its value.\n */\nexport type ContextDependentConfig<P, R> = (\n props: P,\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null\n) => R;\n\nexport interface PropTypeBase<P> {\n displayName?: string;\n description?: string;\n helpText?: string;\n /**\n * If the user has chosen to use a dynamic expression for this prop, provide\n * a hint as to the expected values that the expression should evaluate to.\n * This hint will be displayed alongside the code editor. You may use\n * markdown in the text here.\n */\n exprHint?: string;\n hidden?: ContextDependentConfig<P, boolean>;\n readOnly?: boolean | ContextDependentConfig<P, boolean>;\n advanced?: boolean;\n disableDynamicValue?: boolean;\n}\n\nexport type DefaultValueOrExpr<P, T> =\n | {\n defaultExpr?: undefined;\n defaultExprHint?: undefined;\n defaultValue?: T;\n defaultValueHint?: T | ContextDependentConfig<P, T | undefined>;\n }\n | {\n defaultValue?: undefined;\n defaultValueHint?: undefined;\n defaultExpr?: string;\n defaultExprHint?: string;\n };\n\ntype StringTypeBase<P> = PropTypeBase<P> & DefaultValueOrExpr<P, string>;\n\nexport type StringType<P> =\n | \"string\"\n | ((\n | {\n type: \"string\";\n control?: \"default\" | \"large\";\n }\n | {\n type: \"code\";\n lang: \"css\" | \"html\" | \"javascript\" | \"json\";\n }\n | {\n type: \"richText\";\n }\n | {\n type: \"color\";\n /**\n * If specified, and the user picks a color token in the Studio, then\n * the value passed in as prop is a css variable reference, like\n * `var(--TOKEN_ID)`, instead of the resolved hex value of the token.\n * You should take care in using this in the proper css context --\n * the css token is only defined if you are rendering under some\n * Plasmic component in the DOM tree, which is usually the case,\n * unless you are using a React portal.\n */\n keepCssVar?: boolean;\n }\n | {\n type: \"class\";\n /**\n * Additional css selectors that can change how this style should look.\n * Some examples:\n *\n * * `:hover` -- on hover\n * * `[data-something=\"blah\"] -- when the element with this class has\n * an html attribute \"data-something=blah\"\n * * :component[data-something=\"blah\"] :self -- when the root of the\n * component has an html attribute \"data-something=blah\". Note that\n * the non-standard `:component` selector is used to select the\n * component root, and the non-standard `:self` selector is used\n * to select the element that this class is attached to.\n */\n selectors?: {\n /**\n * A css selector, like `:hover` or `[data-something=\"blah\"]`.\n */\n selector: string;\n /**\n * An optional human-friendly label for the selector, so the studio user\n * knows what this selector means.\n */\n label?: string;\n }[];\n /**\n * If specified, then only shows these style sections for styling this class\n */\n styleSections?: StyleSection[];\n }\n | {\n type: \"themeResetClass\";\n /**\n * Normally, theme reset class will only target Plasmic-generated tags\n * with the default tag styles. If you also want to target non-Plasmic-generated\n * tags (say, rendered by your code components, or fetched as an HTML blob\n * from somewhere), then specify `true` here.\n */\n targetAllTags?: boolean;\n }\n | {\n type: \"cardPicker\";\n modalTitle?:\n | React.ReactNode\n | ContextDependentConfig<P, React.ReactNode>;\n options:\n | {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n | ContextDependentConfig<\n P,\n {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n >;\n showInput?: boolean | ContextDependentConfig<P, boolean>;\n onSearch?: ContextDependentConfig<\n P,\n ((value: string) => void) | undefined\n >;\n }\n ) &\n StringTypeBase<P>);\n\nexport type BooleanType<P> =\n | \"boolean\"\n | ({\n type: \"boolean\";\n } & DefaultValueOrExpr<P, boolean> &\n PropTypeBase<P>);\n\ntype GraphQLValue = {\n query: string;\n variables?: Record<string, any>;\n};\n\nexport type GraphQLType<P> = {\n type: \"code\";\n lang: \"graphql\";\n endpoint: string | ContextDependentConfig<P, string>;\n method?: string | ContextDependentConfig<P, string>;\n headers?: object | ContextDependentConfig<P, object>;\n} & DefaultValueOrExpr<P, GraphQLValue> &\n PropTypeBase<P>;\n\ntype NumberTypeBase<P> = PropTypeBase<P> &\n DefaultValueOrExpr<P, number> & {\n type: \"number\";\n };\n\nexport type NumberType<P> =\n | \"number\"\n | ((\n | {\n control?: \"default\";\n min?: number | ContextDependentConfig<P, number>;\n max?: number | ContextDependentConfig<P, number>;\n }\n | {\n control: \"slider\";\n min: number | ContextDependentConfig<P, number>;\n max: number | ContextDependentConfig<P, number>;\n step?: number | ContextDependentConfig<P, number>;\n }\n ) &\n NumberTypeBase<P>);\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type JSONLikeType<P> =\n | \"object\"\n | ({\n type: \"object\";\n fields?: {\n [p: string]: PropType<P>;\n };\n } & DefaultValueOrExpr<P, any> &\n PropTypeBase<P>)\n | ({\n type: \"array\";\n itemType?: {\n type: \"object\";\n fields: {\n [p: string]: PropType<P>;\n };\n /**\n * Optional function that generates a name for this item in the array\n */\n nameFunc?: (item: any) => string | undefined;\n };\n } & DefaultValueOrExpr<P, any[]> &\n PropTypeBase<P>)\n | ({\n type: \"dataSource\";\n dataSource: \"airtable\" | \"cms\";\n } & PropTypeBase<P>);\n\ntype DataPickerValueType = string | number | (string | number)[];\n\nexport type DataPickerType<P> =\n | ({\n type: \"dataSelector\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n alwaysShowValuePathAsLabel?: boolean;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>)\n | ({\n type: \"exprEditor\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>);\n\nexport type EventHandlerType<P> = {\n type: \"eventHandler\";\n argTypes: { name: string; type: PropType<any> }[];\n} & DefaultValueOrExpr<P, (...args: any) => any> &\n PropTypeBase<P>;\n\ninterface ChoiceTypeBase<P> extends PropTypeBase<P> {\n type: \"choice\";\n options:\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n | ContextDependentConfig<\n P,\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n >;\n allowSearch?: boolean;\n filterOption?: boolean;\n onSearch?: ContextDependentConfig<P, ((value: string) => void) | undefined>;\n}\n\nexport type ChoiceType<P> = (\n | ({\n multiSelect?: false;\n } & DefaultValueOrExpr<P, string | number | boolean>)\n | ({\n multiSelect: true;\n } & DefaultValueOrExpr<P, (string | number | boolean)[]>)\n | ({\n multiSelect: ContextDependentConfig<P, boolean>;\n } & DefaultValueOrExpr<\n P,\n string | number | boolean | (string | number | boolean)[]\n >)\n) &\n ChoiceTypeBase<P>;\n\nexport interface ModalProps {\n show?: boolean;\n children?: React.ReactNode;\n onClose: () => void;\n style?: CSSProperties;\n}\n\ninterface CustomControlProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n value: any;\n /**\n * Sets the value to be passed to the prop. Expects a JSON-compatible value.\n */\n updateValue: (newVal: any) => void;\n /**\n * Full screen modal component\n */\n FullscreenModal: React.ComponentType<ModalProps>;\n /**\n * Modal component for the side pane\n */\n SideModal: React.ComponentType<ModalProps>;\n\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\nexport type CustomControl<P> = React.ComponentType<CustomControlProps<P>>;\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type CustomType<P> =\n | CustomControl<P>\n | ({\n type: \"custom\";\n control: CustomControl<P>;\n } & PropTypeBase<P> &\n DefaultValueOrExpr<P, any>);\n\ntype SlotType<P> =\n | \"slot\"\n | ({\n type: \"slot\";\n /**\n * The unique names of all code components that can be placed in the slot\n */\n allowedComponents?: string[];\n /**\n * Whether the \"empty slot\" placeholder should be hidden in the canvas.\n */\n hidePlaceholder?: boolean;\n /**\n * Whether the slot is repeated, i.e., is rendered multiple times using\n * repeatedElement().\n */\n isRepeated?: boolean;\n\n /**\n * If slot is a render prop (accepts a function that takes in some\n * arguments and returns some JSX), then specify the names of the\n * arguments expected by the render prop function.\n */\n renderPropParams?: string[];\n } & Omit<\n DefaultValueOrExpr<P, PlasmicElement | PlasmicElement[]>,\n \"defaultValueHint\" | \"defaultExpr\" | \"defaultExprHint\"\n >);\n\ntype ImageUrlType<P> =\n | \"imageUrl\"\n | ({\n type: \"imageUrl\";\n } & DefaultValueOrExpr<P, string> &\n PropTypeBase<P>);\n\nexport type PrimitiveType<P = any> = Extract<\n StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P>,\n String\n>;\n\ntype ControlTypeBase =\n | {\n editOnly?: false;\n }\n | {\n editOnly: true;\n /**\n * The prop where the values should be mapped to\n */\n uncontrolledProp?: string;\n };\n\nexport type SupportControlled<T> =\n | Extract<T, String | CustomControl<any>>\n | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);\n\nexport type PropType<P> =\n | SupportControlled<\n | StringType<P>\n | BooleanType<P>\n | NumberType<P>\n | JSONLikeType<P>\n | ChoiceType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | GraphQLType<P>\n | DataPickerType<P>\n | EventHandlerType<P>\n >\n | SlotType<P>;\n\ntype RestrictPropType<T, P> = T extends string\n ? SupportControlled<\n | StringType<P>\n | ChoiceType<P>\n | JSONLikeType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | DataPickerType<P>\n >\n : T extends boolean\n ? SupportControlled<\n BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : T extends number\n ? SupportControlled<\n NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : PropType<P>;\n\nexport interface ActionProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n studioOps: {\n showModal: (\n modalProps: Omit<ModalProps, \"onClose\"> & { onClose?: () => void }\n ) => void;\n refreshQueryData: () => void;\n appendToSlot: (element: PlasmicElement, slotName: string) => void;\n removeFromSlotAt: (pos: number, slotName: string) => void;\n updateProps: (newValues: any) => void;\n };\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\n\nexport type Action<P> =\n | {\n type: \"button-action\";\n label: string;\n onClick: (props: ActionProps<P>) => void;\n }\n | {\n type: \"custom-action\";\n control: React.ComponentType<ActionProps<P>>;\n };\n\ntype DistributedKeyOf<T> = T extends any ? keyof T : never;\n\ninterface ComponentTemplate<P>\n extends Omit<CodeComponentElement<P>, \"type\" | \"name\"> {\n /**\n * A preview picture for the template.\n */\n previewImg?: string;\n}\n\nexport interface ComponentTemplates<P> {\n [name: string]: ComponentTemplate<P>;\n}\n\nexport type StateSpec = {\n onChangeProp: string;\n} & (\n | {\n type: \"readonly\";\n variableType: \"text\";\n initVal?: string;\n }\n | {\n type: \"readonly\";\n variableType: \"number\";\n initVal?: number;\n }\n | {\n type: \"readonly\";\n variableType: \"boolean\";\n initVal?: boolean;\n }\n | {\n type: \"readonly\";\n variableType: \"array\";\n initVal?: any[];\n }\n | {\n type: \"readonly\";\n variableType: \"object\";\n initVal?: object;\n }\n | {\n type: \"writable\";\n variableType: \"text\" | \"number\" | \"boolean\" | \"array\" | \"object\";\n valueProp: string;\n }\n);\n\n\nexport interface StateHelpers<P, T> {\n initFunc?: ($props: P) => T;\n onChangeArgsToValue?: (...args: any) => T;\n}\n\nexport type ComponentHelpers<P> = {\n helpers: {\n states: Record<string, StateHelpers<P, any>>;\n };\n importPath: string;\n} & (\n | {\n importName: string;\n }\n | {\n isDefaultExport: true;\n }\n);\n\nexport type StyleSection =\n | \"visibility\"\n | \"typography\"\n | \"sizing\"\n | \"spacing\"\n | \"background\"\n | \"transform\"\n | \"transitions\"\n | \"layout\"\n | \"overflow\"\n | \"border\"\n | \"shadows\"\n | \"effects\";\n\nexport interface ComponentMeta<P> {\n /**\n * Any unique string name used to identify that component. Each component\n * should be registered with a different `meta.name`, even if they have the\n * same name in the code.\n */\n name: string;\n /**\n * The name to be displayed for the component in Studio. Optional: if not\n * specified, `meta.name` is used.\n */\n displayName?: string;\n /**\n * The description of the component to be shown in Studio.\n */\n description?: string;\n /**\n * The javascript name to be used when generating code. Optional: if not\n * provided, `meta.name` is used.\n */\n importName?: string;\n /**\n * An object describing the component properties to be used in Studio.\n * For each `prop`, there should be an entry `meta.props[prop]` describing\n * its type.\n */\n props: { [prop in DistributedKeyOf<P>]?: RestrictPropType<P[prop], P> } & {\n [prop: string]: PropType<P>;\n };\n /**\n * An object describing the component states to be used in Studio.\n */\n states?: Record<string, StateSpec>;\n /**\n * An object describing the components helpers to be used in Studio.\n * 1. states helpers: Each state can receive an \"initFunc\" prop to initialize\n * the implicit state in Studio, and an \"onChangeArgsToValue\" prop to\n * transform the event handler arguments into a value\n */\n componentHelpers?: ComponentHelpers<P>;\n /**\n * An array describing the component actions to be used in Studio.\n */\n actions?: Action<P>[];\n /**\n * Whether style sections should be shown in Studio. For styles to work, the\n * component must accept a `className` prop. If unset, defaults to all styles.\n * Set to `false` if this component cannot be styled (for example, if it doesn't\n * render any DOM elements).\n */\n styleSections?: StyleSection[] | boolean;\n /**\n * Whether the element can be repeated in Studio. If unset, defaults to true.\n */\n isRepeatable?: boolean;\n /**\n * The path to be used when importing the component in the generated code.\n * It can be the name of the package that contains the component, or the path\n * to the file in the project (relative to the root directory).\n */\n importPath: string;\n /**\n * Whether the component is the default export from that path. Optional: if\n * not specified, it's considered `false`.\n */\n isDefaultExport?: boolean;\n /**\n * The prop that expects the CSS classes with styles to be applied to the\n * component. Optional: if not specified, Plasmic will expect it to be\n * `className`. Notice that if the component does not accept CSS classes, the\n * component will not be able to receive styles from the Studio.\n */\n classNameProp?: string;\n /**\n * The prop that receives and forwards a React `ref`. Plasmic only uses `ref`\n * to interact with components, so it's not used in the generated code.\n * Optional: If not provided, the usual `ref` is used.\n */\n refProp?: string;\n /**\n * Default styles to start with when instantiating the component in Plasmic.\n */\n defaultStyles?: CSSProperties;\n /**\n * Component templates to start with on Plasmic.\n */\n templates?: ComponentTemplates<P>;\n /**\n * Registered name of parent component, used for grouping related components.\n */\n parentComponentName?: string;\n /**\n * Whether the component can be used as an attachment to an element.\n */\n isAttachment?: boolean;\n /**\n * Whether the component provides data to its slots using DataProvider.\n */\n providesData?: boolean;\n\n /**\n * If specified, then Figma components with the specified names will be mapped\n * to this component when you paste Figma content into Plasmic\n */\n figmaMappings?: {\n figmaComponentName: string;\n }[];\n\n /**\n * If true, when an instance of this component is added, the element\n * will always be named by the name of this component.\n */\n alwaysAutoName?: boolean;\n\n unstable__refActions?: Record<string, RefActionRegistration<P>>;\n}\n\nexport interface FunctionParam<P> {\n name: string;\n displayName?: string;\n type: PropType<P>;\n}\n\nexport interface RefActionRegistration<P> {\n displayName?: string;\n description?: string;\n parameters: FunctionParam<P>[];\n}\n\nexport interface ComponentRegistration {\n component: React.ComponentType<any>;\n meta: ComponentMeta<any>;\n}\n\ndeclare global {\n interface Window {\n __PlasmicComponentRegistry: ComponentRegistration[];\n }\n}\n\nif (root.__PlasmicComponentRegistry == null) {\n root.__PlasmicComponentRegistry = [];\n}\n\nexport default function registerComponent<T extends React.ComponentType<any>>(\n component: T,\n meta: ComponentMeta<React.ComponentProps<T>>\n) {\n // Check for duplicates\n if (\n root.__PlasmicComponentRegistry.some(\n (r: ComponentRegistration) =>\n r.component === component && r.meta.name === meta.name\n )\n ) {\n return;\n }\n root.__PlasmicComponentRegistry.push({ component, meta });\n}\n"],"names":[],"mappings":";;;;;AAMA,IAAM,IAAI,GAAG,UAAiB,CAAC;AAorB/B,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;IAC3C,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAC;CACtC;SAEuB,iBAAiB,CACvC,SAAY,EACZ,IAA4C;;IAG5C,IACE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAClC,UAAC,CAAwB;QACvB,OAAA,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;KAAA,CACzD,EACD;QACA,OAAO;KACR;IACD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,SAAS,WAAA,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;AAC5D;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../src/registerComponent.ts"],"sourcesContent":["import {\n CodeComponentElement,\n CSSProperties,\n PlasmicElement,\n} from \"./element-types\";\n\nconst root = globalThis as any;\n\nexport interface CanvasComponentProps<Data = any> {\n /**\n * This prop is only provided within the canvas of Plasmic Studio.\n * Allows the component to set data to be consumed by the props' controls.\n */\n setControlContextData?: (data: Data) => void;\n}\n\ntype InferDataType<P> = P extends CanvasComponentProps<infer Data> ? Data : any;\n\n/**\n * Config option that takes the context (e.g., props) of the component instance\n * to dynamically set its value.\n */\nexport type ContextDependentConfig<P, R> = (\n props: P,\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null\n) => R;\n\nexport interface PropTypeBase<P> {\n displayName?: string;\n description?: string;\n helpText?: string;\n /**\n * If the user has chosen to use a dynamic expression for this prop, provide\n * a hint as to the expected values that the expression should evaluate to.\n * This hint will be displayed alongside the code editor. You may use\n * markdown in the text here.\n */\n exprHint?: string;\n hidden?: ContextDependentConfig<P, boolean>;\n readOnly?: boolean | ContextDependentConfig<P, boolean>;\n advanced?: boolean;\n disableDynamicValue?: boolean;\n}\n\nexport type DefaultValueOrExpr<P, T> =\n | {\n defaultExpr?: undefined;\n defaultExprHint?: undefined;\n defaultValue?: T;\n defaultValueHint?: T | ContextDependentConfig<P, T | undefined>;\n }\n | {\n defaultValue?: undefined;\n defaultValueHint?: undefined;\n defaultExpr?: string;\n defaultExprHint?: string;\n };\n\ntype StringTypeBase<P> = PropTypeBase<P> & DefaultValueOrExpr<P, string>;\n\nexport type StringType<P> =\n | \"string\"\n | ((\n | {\n type: \"string\";\n control?: \"default\" | \"large\";\n }\n | {\n type: \"code\";\n lang: \"css\" | \"html\" | \"javascript\" | \"json\";\n }\n | {\n type: \"richText\";\n }\n | {\n type: \"color\";\n /**\n * If specified, and the user picks a color token in the Studio, then\n * the value passed in as prop is a css variable reference, like\n * `var(--TOKEN_ID)`, instead of the resolved hex value of the token.\n * You should take care in using this in the proper css context --\n * the css token is only defined if you are rendering under some\n * Plasmic component in the DOM tree, which is usually the case,\n * unless you are using a React portal.\n */\n keepCssVar?: boolean;\n }\n | {\n type: \"class\";\n /**\n * Additional css selectors that can change how this style should look.\n * Some examples:\n *\n * * `:hover` -- on hover\n * * `[data-something=\"blah\"] -- when the element with this class has\n * an html attribute \"data-something=blah\"\n * * :component[data-something=\"blah\"] :self -- when the root of the\n * component has an html attribute \"data-something=blah\". Note that\n * the non-standard `:component` selector is used to select the\n * component root, and the non-standard `:self` selector is used\n * to select the element that this class is attached to.\n */\n selectors?: {\n /**\n * A css selector, like `:hover` or `[data-something=\"blah\"]`.\n */\n selector: string;\n /**\n * An optional human-friendly label for the selector, so the studio user\n * knows what this selector means.\n */\n label?: string;\n }[];\n /**\n * If specified, then only shows these style sections for styling this class\n */\n styleSections?: StyleSection[];\n }\n | {\n type: \"themeResetClass\";\n /**\n * Normally, theme reset class will only target Plasmic-generated tags\n * with the default tag styles. If you also want to target non-Plasmic-generated\n * tags (say, rendered by your code components, or fetched as an HTML blob\n * from somewhere), then specify `true` here.\n */\n targetAllTags?: boolean;\n }\n | {\n type: \"cardPicker\";\n modalTitle?:\n | React.ReactNode\n | ContextDependentConfig<P, React.ReactNode>;\n options:\n | {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n | ContextDependentConfig<\n P,\n {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n >;\n showInput?: boolean | ContextDependentConfig<P, boolean>;\n onSearch?: ContextDependentConfig<\n P,\n ((value: string) => void) | undefined\n >;\n }\n ) &\n StringTypeBase<P>);\n\nexport type BooleanType<P> =\n | \"boolean\"\n | ({\n type: \"boolean\";\n } & DefaultValueOrExpr<P, boolean> &\n PropTypeBase<P>);\n\ntype GraphQLValue = {\n query: string;\n variables?: Record<string, any>;\n};\n\nexport type GraphQLType<P> = {\n type: \"code\";\n lang: \"graphql\";\n endpoint: string | ContextDependentConfig<P, string>;\n method?: string | ContextDependentConfig<P, string>;\n headers?: object | ContextDependentConfig<P, object>;\n} & DefaultValueOrExpr<P, GraphQLValue> &\n PropTypeBase<P>;\n\ntype NumberTypeBase<P> = PropTypeBase<P> &\n DefaultValueOrExpr<P, number> & {\n type: \"number\";\n };\n\nexport type NumberType<P> =\n | \"number\"\n | ((\n | {\n control?: \"default\";\n min?: number | ContextDependentConfig<P, number>;\n max?: number | ContextDependentConfig<P, number>;\n }\n | {\n control: \"slider\";\n min: number | ContextDependentConfig<P, number>;\n max: number | ContextDependentConfig<P, number>;\n step?: number | ContextDependentConfig<P, number>;\n }\n ) &\n NumberTypeBase<P>);\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type JSONLikeType<P> =\n | \"object\"\n | ({\n type: \"object\";\n fields?: {\n [p: string]: PropType<P>;\n };\n } & DefaultValueOrExpr<P, any> &\n PropTypeBase<P>)\n | ({\n type: \"array\";\n itemType?: {\n type: \"object\";\n fields: {\n [p: string]: PropType<P>;\n };\n /**\n * Optional function that generates a name for this item in the array\n */\n nameFunc?: (item: any) => string | undefined;\n };\n } & DefaultValueOrExpr<P, any[]> &\n PropTypeBase<P>)\n | ({\n type: \"dataSource\";\n dataSource: \"airtable\" | \"cms\";\n } & PropTypeBase<P>);\n\ntype DataPickerValueType = string | number | (string | number)[];\n\nexport type DataPickerType<P> =\n | ({\n type: \"dataSelector\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n alwaysShowValuePathAsLabel?: boolean;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>)\n | ({\n type: \"exprEditor\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>);\n\ninterface ChoiceTypeBase<P> extends PropTypeBase<P> {\n type: \"choice\";\n options:\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n | ContextDependentConfig<\n P,\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n >;\n allowSearch?: boolean;\n filterOption?: boolean;\n onSearch?: ContextDependentConfig<P, ((value: string) => void) | undefined>;\n}\n\nexport type ChoiceType<P> = (\n | ({\n multiSelect?: false;\n } & DefaultValueOrExpr<P, string | number | boolean>)\n | ({\n multiSelect: true;\n } & DefaultValueOrExpr<P, (string | number | boolean)[]>)\n | ({\n multiSelect: ContextDependentConfig<P, boolean>;\n } & DefaultValueOrExpr<\n P,\n string | number | boolean | (string | number | boolean)[]\n >)\n) &\n ChoiceTypeBase<P>;\n\nexport interface ModalProps {\n show?: boolean;\n children?: React.ReactNode;\n onClose: () => void;\n style?: CSSProperties;\n}\n\ninterface CustomControlProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n value: any;\n /**\n * Sets the value to be passed to the prop. Expects a JSON-compatible value.\n */\n updateValue: (newVal: any) => void;\n /**\n * Full screen modal component\n */\n FullscreenModal: React.ComponentType<ModalProps>;\n /**\n * Modal component for the side pane\n */\n SideModal: React.ComponentType<ModalProps>;\n\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\nexport type CustomControl<P> = React.ComponentType<CustomControlProps<P>>;\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type CustomType<P> =\n | CustomControl<P>\n | ({\n type: \"custom\";\n control: CustomControl<P>;\n } & PropTypeBase<P> &\n DefaultValueOrExpr<P, any>);\n\ntype SlotType<P> =\n | \"slot\"\n | ({\n type: \"slot\";\n /**\n * The unique names of all code components that can be placed in the slot\n */\n allowedComponents?: string[];\n /**\n * Whether the \"empty slot\" placeholder should be hidden in the canvas.\n */\n hidePlaceholder?: boolean;\n /**\n * Whether the slot is repeated, i.e., is rendered multiple times using\n * repeatedElement().\n */\n isRepeated?: boolean;\n\n /**\n * If slot is a render prop (accepts a function that takes in some\n * arguments and returns some JSX), then specify the names of the\n * arguments expected by the render prop function.\n */\n renderPropParams?: string[];\n } & Omit<\n DefaultValueOrExpr<P, PlasmicElement | PlasmicElement[]>,\n \"defaultValueHint\" | \"defaultExpr\" | \"defaultExprHint\"\n >);\n\ntype ImageUrlType<P> =\n | \"imageUrl\"\n | ({\n type: \"imageUrl\";\n } & DefaultValueOrExpr<P, string> &\n PropTypeBase<P>);\n\nexport type PrimitiveType<P = any> = Extract<\n StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P>,\n String\n>;\n\ntype ControlTypeBase =\n | {\n editOnly?: false;\n }\n | {\n editOnly: true;\n /**\n * The prop where the values should be mapped to\n */\n uncontrolledProp?: string;\n };\n\nexport type SupportControlled<T> =\n | Extract<T, String | CustomControl<any>>\n | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);\n\nexport type PropType<P> =\n | SupportControlled<\n | StringType<P>\n | BooleanType<P>\n | NumberType<P>\n | JSONLikeType<P>\n | ChoiceType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | GraphQLType<P>\n | DataPickerType<P>\n >\n | SlotType<P>;\n\ntype RestrictPropType<T, P> = T extends string\n ? SupportControlled<\n | StringType<P>\n | ChoiceType<P>\n | JSONLikeType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | DataPickerType<P>\n >\n : T extends boolean\n ? SupportControlled<\n BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : T extends number\n ? SupportControlled<\n NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : PropType<P>;\n\nexport interface ActionProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n studioOps: {\n showModal: (\n modalProps: Omit<ModalProps, \"onClose\"> & { onClose?: () => void }\n ) => void;\n refreshQueryData: () => void;\n appendToSlot: (element: PlasmicElement, slotName: string) => void;\n removeFromSlotAt: (pos: number, slotName: string) => void;\n updateProps: (newValues: any) => void;\n };\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\n\nexport type Action<P> =\n | {\n type: \"button-action\";\n label: string;\n onClick: (props: ActionProps<P>) => void;\n }\n | {\n type: \"custom-action\";\n control: React.ComponentType<ActionProps<P>>;\n };\n\ntype DistributedKeyOf<T> = T extends any ? keyof T : never;\n\ninterface ComponentTemplate<P>\n extends Omit<CodeComponentElement<P>, \"type\" | \"name\"> {\n /**\n * A preview picture for the template.\n */\n previewImg?: string;\n}\n\nexport interface ComponentTemplates<P> {\n [name: string]: ComponentTemplate<P>;\n}\ninterface $State {\n [key: string]: any;\n}\n\ninterface $StateSpec<T> {\n // Whether this state is private, readonly, or writable in\n // this component\n type: \"private\" | \"readonly\" | \"writable\";\n // if initial value is defined by a js expression\n initFunc?: ($props: Record<string, any>, $state: $State) => T;\n\n // if initial value is a hard-coded value\n initVal?: T;\n // Whether this state is private, readonly, or writable in\n // this component\n\n // If writable, there should be a valueProp that maps props[valueProp]\n // to the value of the state\n valueProp?: string;\n\n // If writable or readonly, there should be an onChangeProp where\n // props[onChangeProp] is invoked whenever the value changes\n onChangeProp?: string;\n}\n\nexport type StyleSection =\n | \"visibility\"\n | \"typography\"\n | \"sizing\"\n | \"spacing\"\n | \"background\"\n | \"transform\"\n | \"transitions\"\n | \"layout\"\n | \"overflow\"\n | \"border\"\n | \"shadows\"\n | \"effects\";\n\nexport interface ComponentMeta<P> {\n /**\n * Any unique string name used to identify that component. Each component\n * should be registered with a different `meta.name`, even if they have the\n * same name in the code.\n */\n name: string;\n /**\n * The name to be displayed for the component in Studio. Optional: if not\n * specified, `meta.name` is used.\n */\n displayName?: string;\n /**\n * The description of the component to be shown in Studio.\n */\n description?: string;\n /**\n * The javascript name to be used when generating code. Optional: if not\n * provided, `meta.name` is used.\n */\n importName?: string;\n /**\n * An object describing the component properties to be used in Studio.\n * For each `prop`, there should be an entry `meta.props[prop]` describing\n * its type.\n */\n props: { [prop in DistributedKeyOf<P>]?: RestrictPropType<P[prop], P> } & {\n [prop: string]: PropType<P>;\n };\n /**\n * WIP: An object describing the component states to be used in Studio.\n */\n unstable__states?: Record<string, $StateSpec<any>>;\n /**\n * An array describing the component actions to be used in Studio.\n */\n actions?: Action<P>[];\n /**\n * Whether style sections should be shown in Studio. For styles to work, the\n * component must accept a `className` prop. If unset, defaults to all styles.\n * Set to `false` if this component cannot be styled (for example, if it doesn't\n * render any DOM elements).\n */\n styleSections?: StyleSection[] | boolean;\n /**\n * Whether the element can be repeated in Studio. If unset, defaults to true.\n */\n isRepeatable?: boolean;\n /**\n * The path to be used when importing the component in the generated code.\n * It can be the name of the package that contains the component, or the path\n * to the file in the project (relative to the root directory).\n */\n importPath: string;\n /**\n * Whether the component is the default export from that path. Optional: if\n * not specified, it's considered `false`.\n */\n isDefaultExport?: boolean;\n /**\n * The prop that expects the CSS classes with styles to be applied to the\n * component. Optional: if not specified, Plasmic will expect it to be\n * `className`. Notice that if the component does not accept CSS classes, the\n * component will not be able to receive styles from the Studio.\n */\n classNameProp?: string;\n /**\n * The prop that receives and forwards a React `ref`. Plasmic only uses `ref`\n * to interact with components, so it's not used in the generated code.\n * Optional: If not provided, the usual `ref` is used.\n */\n refProp?: string;\n /**\n * Default styles to start with when instantiating the component in Plasmic.\n */\n defaultStyles?: CSSProperties;\n /**\n * Component templates to start with on Plasmic.\n */\n templates?: ComponentTemplates<P>;\n /**\n * Registered name of parent component, used for grouping related components.\n */\n parentComponentName?: string;\n /**\n * Whether the component can be used as an attachment to an element.\n */\n isAttachment?: boolean;\n /**\n * Whether the component provides data to its slots using DataProvider.\n */\n providesData?: boolean;\n\n /**\n * If specified, then Figma components with the specified names will be mapped\n * to this component when you paste Figma content into Plasmic\n */\n figmaMappings?: {\n figmaComponentName: string;\n }[];\n\n /**\n * If true, when an instance of this component is added, the element\n * will always be named by the name of this component.\n */\n alwaysAutoName?: boolean;\n\n unstable__refActions?: Record<string, RefActionRegistration<P>>;\n}\n\nexport interface FunctionParam<P> {\n name: string;\n displayName?: string;\n type: PropType<P>;\n}\n\nexport interface RefActionRegistration<P> {\n displayName?: string;\n description?: string;\n parameters: FunctionParam<P>[];\n}\n\nexport interface ComponentRegistration {\n component: React.ComponentType<any>;\n meta: ComponentMeta<any>;\n}\n\ndeclare global {\n interface Window {\n __PlasmicComponentRegistry: ComponentRegistration[];\n }\n}\n\nif (root.__PlasmicComponentRegistry == null) {\n root.__PlasmicComponentRegistry = [];\n}\n\nexport default function registerComponent<T extends React.ComponentType<any>>(\n component: T,\n meta: ComponentMeta<React.ComponentProps<T>>\n) {\n // Check for duplicates\n if (\n root.__PlasmicComponentRegistry.some(\n (r: ComponentRegistration) =>\n r.component === component && r.meta.name === meta.name\n )\n ) {\n return;\n }\n root.__PlasmicComponentRegistry.push({ component, meta });\n}\n"],"names":[],"mappings":";AAMA,IAAM,IAAI,GAAG,UAAiB,CAAC;AAuoB/B,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;IAC3C,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAC;CACtC;SAEuB,iBAAiB,CACvC,SAAY,EACZ,IAA4C;;IAG5C,IACE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAClC,UAAC,CAAwB;QACvB,OAAA,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;KAAA,CACzD,EACD;QACA,OAAO;KACR;IACD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,SAAS,WAAA,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;AAC5D;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/registerComponent.ts"],"sourcesContent":["import {\n CodeComponentElement,\n CSSProperties,\n PlasmicElement,\n} from \"./element-types\";\n\nconst root = globalThis as any;\n\nexport interface CanvasComponentProps<Data = any> {\n /**\n * This prop is only provided within the canvas of Plasmic Studio.\n * Allows the component to set data to be consumed by the props' controls.\n */\n setControlContextData?: (data: Data) => void;\n}\n\ntype InferDataType<P> = P extends CanvasComponentProps<infer Data> ? Data : any;\n\n/**\n * Config option that takes the context (e.g., props) of the component instance\n * to dynamically set its value.\n */\nexport type ContextDependentConfig<P, R> = (\n props: P,\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null\n) => R;\n\nexport interface PropTypeBase<P> {\n displayName?: string;\n description?: string;\n helpText?: string;\n /**\n * If the user has chosen to use a dynamic expression for this prop, provide\n * a hint as to the expected values that the expression should evaluate to.\n * This hint will be displayed alongside the code editor. You may use\n * markdown in the text here.\n */\n exprHint?: string;\n hidden?: ContextDependentConfig<P, boolean>;\n readOnly?: boolean | ContextDependentConfig<P, boolean>;\n advanced?: boolean;\n disableDynamicValue?: boolean;\n}\n\nexport type DefaultValueOrExpr<P, T> =\n | {\n defaultExpr?: undefined;\n defaultExprHint?: undefined;\n defaultValue?: T;\n defaultValueHint?: T | ContextDependentConfig<P, T | undefined>;\n }\n | {\n defaultValue?: undefined;\n defaultValueHint?: undefined;\n defaultExpr?: string;\n defaultExprHint?: string;\n };\n\ntype StringTypeBase<P> = PropTypeBase<P> & DefaultValueOrExpr<P, string>;\n\nexport type StringType<P> =\n | \"string\"\n | ((\n | {\n type: \"string\";\n control?: \"default\" | \"large\";\n }\n | {\n type: \"code\";\n lang: \"css\" | \"html\" | \"javascript\" | \"json\";\n }\n | {\n type: \"richText\";\n }\n | {\n type: \"color\";\n /**\n * If specified, and the user picks a color token in the Studio, then\n * the value passed in as prop is a css variable reference, like\n * `var(--TOKEN_ID)`, instead of the resolved hex value of the token.\n * You should take care in using this in the proper css context --\n * the css token is only defined if you are rendering under some\n * Plasmic component in the DOM tree, which is usually the case,\n * unless you are using a React portal.\n */\n keepCssVar?: boolean;\n }\n | {\n type: \"class\";\n /**\n * Additional css selectors that can change how this style should look.\n * Some examples:\n *\n * * `:hover` -- on hover\n * * `[data-something=\"blah\"] -- when the element with this class has\n * an html attribute \"data-something=blah\"\n * * :component[data-something=\"blah\"] :self -- when the root of the\n * component has an html attribute \"data-something=blah\". Note that\n * the non-standard `:component` selector is used to select the\n * component root, and the non-standard `:self` selector is used\n * to select the element that this class is attached to.\n */\n selectors?: {\n /**\n * A css selector, like `:hover` or `[data-something=\"blah\"]`.\n */\n selector: string;\n /**\n * An optional human-friendly label for the selector, so the studio user\n * knows what this selector means.\n */\n label?: string;\n }[];\n /**\n * If specified, then only shows these style sections for styling this class\n */\n styleSections?: StyleSection[];\n }\n | {\n type: \"themeResetClass\";\n /**\n * Normally, theme reset class will only target Plasmic-generated tags\n * with the default tag styles. If you also want to target non-Plasmic-generated\n * tags (say, rendered by your code components, or fetched as an HTML blob\n * from somewhere), then specify `true` here.\n */\n targetAllTags?: boolean;\n }\n | {\n type: \"cardPicker\";\n modalTitle?:\n | React.ReactNode\n | ContextDependentConfig<P, React.ReactNode>;\n options:\n | {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n | ContextDependentConfig<\n P,\n {\n value: string;\n label?: string;\n imgUrl: string;\n footer?: React.ReactNode;\n }[]\n >;\n showInput?: boolean | ContextDependentConfig<P, boolean>;\n onSearch?: ContextDependentConfig<\n P,\n ((value: string) => void) | undefined\n >;\n }\n ) &\n StringTypeBase<P>);\n\nexport type BooleanType<P> =\n | \"boolean\"\n | ({\n type: \"boolean\";\n } & DefaultValueOrExpr<P, boolean> &\n PropTypeBase<P>);\n\ntype GraphQLValue = {\n query: string;\n variables?: Record<string, any>;\n};\n\nexport type GraphQLType<P> = {\n type: \"code\";\n lang: \"graphql\";\n endpoint: string | ContextDependentConfig<P, string>;\n method?: string | ContextDependentConfig<P, string>;\n headers?: object | ContextDependentConfig<P, object>;\n} & DefaultValueOrExpr<P, GraphQLValue> &\n PropTypeBase<P>;\n\ntype NumberTypeBase<P> = PropTypeBase<P> &\n DefaultValueOrExpr<P, number> & {\n type: \"number\";\n };\n\nexport type NumberType<P> =\n | \"number\"\n | ((\n | {\n control?: \"default\";\n min?: number | ContextDependentConfig<P, number>;\n max?: number | ContextDependentConfig<P, number>;\n }\n | {\n control: \"slider\";\n min: number | ContextDependentConfig<P, number>;\n max: number | ContextDependentConfig<P, number>;\n step?: number | ContextDependentConfig<P, number>;\n }\n ) &\n NumberTypeBase<P>);\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type JSONLikeType<P> =\n | \"object\"\n | ({\n type: \"object\";\n fields?: {\n [p: string]: PropType<P>;\n };\n } & DefaultValueOrExpr<P, any> &\n PropTypeBase<P>)\n | ({\n type: \"array\";\n itemType?: {\n type: \"object\";\n fields: {\n [p: string]: PropType<P>;\n };\n /**\n * Optional function that generates a name for this item in the array\n */\n nameFunc?: (item: any) => string | undefined;\n };\n } & DefaultValueOrExpr<P, any[]> &\n PropTypeBase<P>)\n | ({\n type: \"dataSource\";\n dataSource: \"airtable\" | \"cms\";\n } & PropTypeBase<P>);\n\ntype DataPickerValueType = string | number | (string | number)[];\n\nexport type DataPickerType<P> =\n | ({\n type: \"dataSelector\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n alwaysShowValuePathAsLabel?: boolean;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>)\n | ({\n type: \"exprEditor\";\n data:\n | Record<string, any>\n | ContextDependentConfig<P, Record<string, any>>;\n } & DefaultValueOrExpr<P, DataPickerValueType> &\n PropTypeBase<P>);\n\nexport type EventHandlerType<P> = {\n type: \"eventHandler\";\n argTypes: { name: string; type: PropType<any> }[];\n} & DefaultValueOrExpr<P, (...args: any) => any> &\n PropTypeBase<P>;\n\ninterface ChoiceTypeBase<P> extends PropTypeBase<P> {\n type: \"choice\";\n options:\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n | ContextDependentConfig<\n P,\n | string[]\n | {\n label: string;\n value: string | number | boolean;\n }[]\n >;\n allowSearch?: boolean;\n filterOption?: boolean;\n onSearch?: ContextDependentConfig<P, ((value: string) => void) | undefined>;\n}\n\nexport type ChoiceType<P> = (\n | ({\n multiSelect?: false;\n } & DefaultValueOrExpr<P, string | number | boolean>)\n | ({\n multiSelect: true;\n } & DefaultValueOrExpr<P, (string | number | boolean)[]>)\n | ({\n multiSelect: ContextDependentConfig<P, boolean>;\n } & DefaultValueOrExpr<\n P,\n string | number | boolean | (string | number | boolean)[]\n >)\n) &\n ChoiceTypeBase<P>;\n\nexport interface ModalProps {\n show?: boolean;\n children?: React.ReactNode;\n onClose: () => void;\n style?: CSSProperties;\n}\n\ninterface CustomControlProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n value: any;\n /**\n * Sets the value to be passed to the prop. Expects a JSON-compatible value.\n */\n updateValue: (newVal: any) => void;\n /**\n * Full screen modal component\n */\n FullscreenModal: React.ComponentType<ModalProps>;\n /**\n * Modal component for the side pane\n */\n SideModal: React.ComponentType<ModalProps>;\n\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\nexport type CustomControl<P> = React.ComponentType<CustomControlProps<P>>;\n\n/**\n * Expects defaultValue to be a JSON-compatible value\n */\nexport type CustomType<P> =\n | CustomControl<P>\n | ({\n type: \"custom\";\n control: CustomControl<P>;\n } & PropTypeBase<P> &\n DefaultValueOrExpr<P, any>);\n\ntype SlotType<P> =\n | \"slot\"\n | ({\n type: \"slot\";\n /**\n * The unique names of all code components that can be placed in the slot\n */\n allowedComponents?: string[];\n /**\n * Whether the \"empty slot\" placeholder should be hidden in the canvas.\n */\n hidePlaceholder?: boolean;\n /**\n * Whether the slot is repeated, i.e., is rendered multiple times using\n * repeatedElement().\n */\n isRepeated?: boolean;\n\n /**\n * If slot is a render prop (accepts a function that takes in some\n * arguments and returns some JSX), then specify the names of the\n * arguments expected by the render prop function.\n */\n renderPropParams?: string[];\n } & Omit<\n DefaultValueOrExpr<P, PlasmicElement | PlasmicElement[]>,\n \"defaultValueHint\" | \"defaultExpr\" | \"defaultExprHint\"\n >);\n\ntype ImageUrlType<P> =\n | \"imageUrl\"\n | ({\n type: \"imageUrl\";\n } & DefaultValueOrExpr<P, string> &\n PropTypeBase<P>);\n\nexport type PrimitiveType<P = any> = Extract<\n StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P>,\n String\n>;\n\ntype ControlTypeBase =\n | {\n editOnly?: false;\n }\n | {\n editOnly: true;\n /**\n * The prop where the values should be mapped to\n */\n uncontrolledProp?: string;\n };\n\nexport type SupportControlled<T> =\n | Extract<T, String | CustomControl<any>>\n | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);\n\nexport type PropType<P> =\n | SupportControlled<\n | StringType<P>\n | BooleanType<P>\n | NumberType<P>\n | JSONLikeType<P>\n | ChoiceType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | GraphQLType<P>\n | DataPickerType<P>\n | EventHandlerType<P>\n >\n | SlotType<P>;\n\ntype RestrictPropType<T, P> = T extends string\n ? SupportControlled<\n | StringType<P>\n | ChoiceType<P>\n | JSONLikeType<P>\n | ImageUrlType<P>\n | CustomType<P>\n | DataPickerType<P>\n >\n : T extends boolean\n ? SupportControlled<\n BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : T extends number\n ? SupportControlled<\n NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>\n >\n : PropType<P>;\n\nexport interface ActionProps<P> {\n componentProps: P;\n /**\n * `contextData` can be `null` if the prop controls are rendering before\n * the component instance itself (it will re-render once the component\n * calls `setControlContextData`)\n */\n contextData: InferDataType<P> | null;\n studioOps: {\n showModal: (\n modalProps: Omit<ModalProps, \"onClose\"> & { onClose?: () => void }\n ) => void;\n refreshQueryData: () => void;\n appendToSlot: (element: PlasmicElement, slotName: string) => void;\n removeFromSlotAt: (pos: number, slotName: string) => void;\n updateProps: (newValues: any) => void;\n };\n /**\n * The document that the component will be rendered into; instead of using\n * `document` directly (for, say, `document.querySelector()` etc.), you\n * should use this instead.\n */\n studioDocument: typeof document;\n}\n\nexport type Action<P> =\n | {\n type: \"button-action\";\n label: string;\n onClick: (props: ActionProps<P>) => void;\n }\n | {\n type: \"custom-action\";\n control: React.ComponentType<ActionProps<P>>;\n };\n\ntype DistributedKeyOf<T> = T extends any ? keyof T : never;\n\ninterface ComponentTemplate<P>\n extends Omit<CodeComponentElement<P>, \"type\" | \"name\"> {\n /**\n * A preview picture for the template.\n */\n previewImg?: string;\n}\n\nexport interface ComponentTemplates<P> {\n [name: string]: ComponentTemplate<P>;\n}\n\nexport type StateSpec = {\n onChangeProp: string;\n} & (\n | {\n type: \"readonly\";\n variableType: \"text\";\n initVal?: string;\n }\n | {\n type: \"readonly\";\n variableType: \"number\";\n initVal?: number;\n }\n | {\n type: \"readonly\";\n variableType: \"boolean\";\n initVal?: boolean;\n }\n | {\n type: \"readonly\";\n variableType: \"array\";\n initVal?: any[];\n }\n | {\n type: \"readonly\";\n variableType: \"object\";\n initVal?: object;\n }\n | {\n type: \"writable\";\n variableType: \"text\" | \"number\" | \"boolean\" | \"array\" | \"object\";\n valueProp: string;\n }\n);\n\n\nexport interface StateHelpers<P, T> {\n initFunc?: ($props: P) => T;\n onChangeArgsToValue?: (...args: any) => T;\n}\n\nexport type ComponentHelpers<P> = {\n helpers: {\n states: Record<string, StateHelpers<P, any>>;\n };\n importPath: string;\n} & (\n | {\n importName: string;\n }\n | {\n isDefaultExport: true;\n }\n);\n\nexport type StyleSection =\n | \"visibility\"\n | \"typography\"\n | \"sizing\"\n | \"spacing\"\n | \"background\"\n | \"transform\"\n | \"transitions\"\n | \"layout\"\n | \"overflow\"\n | \"border\"\n | \"shadows\"\n | \"effects\";\n\nexport interface ComponentMeta<P> {\n /**\n * Any unique string name used to identify that component. Each component\n * should be registered with a different `meta.name`, even if they have the\n * same name in the code.\n */\n name: string;\n /**\n * The name to be displayed for the component in Studio. Optional: if not\n * specified, `meta.name` is used.\n */\n displayName?: string;\n /**\n * The description of the component to be shown in Studio.\n */\n description?: string;\n /**\n * The javascript name to be used when generating code. Optional: if not\n * provided, `meta.name` is used.\n */\n importName?: string;\n /**\n * An object describing the component properties to be used in Studio.\n * For each `prop`, there should be an entry `meta.props[prop]` describing\n * its type.\n */\n props: { [prop in DistributedKeyOf<P>]?: RestrictPropType<P[prop], P> } & {\n [prop: string]: PropType<P>;\n };\n /**\n * An object describing the component states to be used in Studio.\n */\n states?: Record<string, StateSpec>;\n /**\n * An object describing the components helpers to be used in Studio.\n * 1. states helpers: Each state can receive an \"initFunc\" prop to initialize\n * the implicit state in Studio, and an \"onChangeArgsToValue\" prop to\n * transform the event handler arguments into a value\n */\n componentHelpers?: ComponentHelpers<P>;\n /**\n * An array describing the component actions to be used in Studio.\n */\n actions?: Action<P>[];\n /**\n * Whether style sections should be shown in Studio. For styles to work, the\n * component must accept a `className` prop. If unset, defaults to all styles.\n * Set to `false` if this component cannot be styled (for example, if it doesn't\n * render any DOM elements).\n */\n styleSections?: StyleSection[] | boolean;\n /**\n * Whether the element can be repeated in Studio. If unset, defaults to true.\n */\n isRepeatable?: boolean;\n /**\n * The path to be used when importing the component in the generated code.\n * It can be the name of the package that contains the component, or the path\n * to the file in the project (relative to the root directory).\n */\n importPath: string;\n /**\n * Whether the component is the default export from that path. Optional: if\n * not specified, it's considered `false`.\n */\n isDefaultExport?: boolean;\n /**\n * The prop that expects the CSS classes with styles to be applied to the\n * component. Optional: if not specified, Plasmic will expect it to be\n * `className`. Notice that if the component does not accept CSS classes, the\n * component will not be able to receive styles from the Studio.\n */\n classNameProp?: string;\n /**\n * The prop that receives and forwards a React `ref`. Plasmic only uses `ref`\n * to interact with components, so it's not used in the generated code.\n * Optional: If not provided, the usual `ref` is used.\n */\n refProp?: string;\n /**\n * Default styles to start with when instantiating the component in Plasmic.\n */\n defaultStyles?: CSSProperties;\n /**\n * Component templates to start with on Plasmic.\n */\n templates?: ComponentTemplates<P>;\n /**\n * Registered name of parent component, used for grouping related components.\n */\n parentComponentName?: string;\n /**\n * Whether the component can be used as an attachment to an element.\n */\n isAttachment?: boolean;\n /**\n * Whether the component provides data to its slots using DataProvider.\n */\n providesData?: boolean;\n\n /**\n * If specified, then Figma components with the specified names will be mapped\n * to this component when you paste Figma content into Plasmic\n */\n figmaMappings?: {\n figmaComponentName: string;\n }[];\n\n /**\n * If true, when an instance of this component is added, the element\n * will always be named by the name of this component.\n */\n alwaysAutoName?: boolean;\n\n unstable__refActions?: Record<string, RefActionRegistration<P>>;\n}\n\nexport interface FunctionParam<P> {\n name: string;\n displayName?: string;\n type: PropType<P>;\n}\n\nexport interface RefActionRegistration<P> {\n displayName?: string;\n description?: string;\n parameters: FunctionParam<P>[];\n}\n\nexport interface ComponentRegistration {\n component: React.ComponentType<any>;\n meta: ComponentMeta<any>;\n}\n\ndeclare global {\n interface Window {\n __PlasmicComponentRegistry: ComponentRegistration[];\n }\n}\n\nif (root.__PlasmicComponentRegistry == null) {\n root.__PlasmicComponentRegistry = [];\n}\n\nexport default function registerComponent<T extends React.ComponentType<any>>(\n component: T,\n meta: ComponentMeta<React.ComponentProps<T>>\n) {\n // Check for duplicates\n if (\n root.__PlasmicComponentRegistry.some(\n (r: ComponentRegistration) =>\n r.component === component && r.meta.name === meta.name\n )\n ) {\n return;\n }\n root.__PlasmicComponentRegistry.push({ component, meta });\n}\n"],"names":[],"mappings":";AAMA,IAAM,IAAI,GAAG,UAAiB,CAAC;AAorB/B,IAAI,IAAI,CAAC,0BAA0B,IAAI,IAAI,EAAE;IAC3C,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAC;CACtC;SAEuB,iBAAiB,CACvC,SAAY,EACZ,IAA4C;;IAG5C,IACE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAClC,UAAC,CAAwB;QACvB,OAAA,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;KAAA,CACzD,EACD;QACA,OAAO;KACR;IACD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,SAAS,WAAA,EAAE,IAAI,MAAA,EAAE,CAAC,CAAC;AAC5D;;;;"}
@@ -183,6 +183,13 @@ export declare type DataPickerType<P> = ({
183
183
  type: "exprEditor";
184
184
  data: Record<string, any> | ContextDependentConfig<P, Record<string, any>>;
185
185
  } & DefaultValueOrExpr<P, DataPickerValueType> & PropTypeBase<P>);
186
+ export declare type EventHandlerType<P> = {
187
+ type: "eventHandler";
188
+ argTypes: {
189
+ name: string;
190
+ type: PropType<any>;
191
+ }[];
192
+ } & DefaultValueOrExpr<P, (...args: any) => any> & PropTypeBase<P>;
186
193
  interface ChoiceTypeBase<P> extends PropTypeBase<P> {
187
194
  type: "choice";
188
195
  options: string[] | {
@@ -281,7 +288,7 @@ declare type ControlTypeBase = {
281
288
  uncontrolledProp?: string;
282
289
  };
283
290
  export declare type SupportControlled<T> = Extract<T, String | CustomControl<any>> | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);
284
- export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P>> | SlotType<P>;
291
+ export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P> | EventHandlerType<P>> | SlotType<P>;
285
292
  declare type RestrictPropType<T, P> = T extends string ? SupportControlled<StringType<P> | ChoiceType<P> | JSONLikeType<P> | ImageUrlType<P> | CustomType<P> | DataPickerType<P>> : T extends boolean ? SupportControlled<BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : T extends number ? SupportControlled<NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : PropType<P>;
286
293
  export interface ActionProps<P> {
287
294
  componentProps: P;
@@ -325,16 +332,47 @@ interface ComponentTemplate<P> extends Omit<CodeComponentElement<P>, "type" | "n
325
332
  export interface ComponentTemplates<P> {
326
333
  [name: string]: ComponentTemplate<P>;
327
334
  }
328
- interface $State {
329
- [key: string]: any;
330
- }
331
- interface $StateSpec<T> {
332
- type: "private" | "readonly" | "writable";
333
- initFunc?: ($props: Record<string, any>, $state: $State) => T;
334
- initVal?: T;
335
- valueProp?: string;
336
- onChangeProp?: string;
335
+ export declare type StateSpec = {
336
+ onChangeProp: string;
337
+ } & ({
338
+ type: "readonly";
339
+ variableType: "text";
340
+ initVal?: string;
341
+ } | {
342
+ type: "readonly";
343
+ variableType: "number";
344
+ initVal?: number;
345
+ } | {
346
+ type: "readonly";
347
+ variableType: "boolean";
348
+ initVal?: boolean;
349
+ } | {
350
+ type: "readonly";
351
+ variableType: "array";
352
+ initVal?: any[];
353
+ } | {
354
+ type: "readonly";
355
+ variableType: "object";
356
+ initVal?: object;
357
+ } | {
358
+ type: "writable";
359
+ variableType: "text" | "number" | "boolean" | "array" | "object";
360
+ valueProp: string;
361
+ });
362
+ export interface StateHelpers<P, T> {
363
+ initFunc?: ($props: P) => T;
364
+ onChangeArgsToValue?: (...args: any) => T;
337
365
  }
366
+ export declare type ComponentHelpers<P> = {
367
+ helpers: {
368
+ states: Record<string, StateHelpers<P, any>>;
369
+ };
370
+ importPath: string;
371
+ } & ({
372
+ importName: string;
373
+ } | {
374
+ isDefaultExport: true;
375
+ });
338
376
  export declare type StyleSection = "visibility" | "typography" | "sizing" | "spacing" | "background" | "transform" | "transitions" | "layout" | "overflow" | "border" | "shadows" | "effects";
339
377
  export interface ComponentMeta<P> {
340
378
  /**
@@ -368,9 +406,16 @@ export interface ComponentMeta<P> {
368
406
  [prop: string]: PropType<P>;
369
407
  };
370
408
  /**
371
- * WIP: An object describing the component states to be used in Studio.
409
+ * An object describing the component states to be used in Studio.
410
+ */
411
+ states?: Record<string, StateSpec>;
412
+ /**
413
+ * An object describing the components helpers to be used in Studio.
414
+ * 1. states helpers: Each state can receive an "initFunc" prop to initialize
415
+ * the implicit state in Studio, and an "onChangeArgsToValue" prop to
416
+ * transform the event handler arguments into a value
372
417
  */
373
- unstable__states?: Record<string, $StateSpec<any>>;
418
+ componentHelpers?: ComponentHelpers<P>;
374
419
  /**
375
420
  * An array describing the component actions to be used in Studio.
376
421
  */
@@ -183,6 +183,13 @@ export declare type DataPickerType<P> = ({
183
183
  type: "exprEditor";
184
184
  data: Record<string, any> | ContextDependentConfig<P, Record<string, any>>;
185
185
  } & DefaultValueOrExpr<P, DataPickerValueType> & PropTypeBase<P>);
186
+ export declare type EventHandlerType<P> = {
187
+ type: "eventHandler";
188
+ argTypes: {
189
+ name: string;
190
+ type: PropType<any>;
191
+ }[];
192
+ } & DefaultValueOrExpr<P, (...args: any) => any> & PropTypeBase<P>;
186
193
  interface ChoiceTypeBase<P> extends PropTypeBase<P> {
187
194
  type: "choice";
188
195
  options: string[] | {
@@ -281,7 +288,7 @@ declare type ControlTypeBase = {
281
288
  uncontrolledProp?: string;
282
289
  };
283
290
  export declare type SupportControlled<T> = Extract<T, String | CustomControl<any>> | (Exclude<T, String | CustomControl<any>> & ControlTypeBase);
284
- export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P>> | SlotType<P>;
291
+ export declare type PropType<P> = SupportControlled<StringType<P> | BooleanType<P> | NumberType<P> | JSONLikeType<P> | ChoiceType<P> | ImageUrlType<P> | CustomType<P> | GraphQLType<P> | DataPickerType<P> | EventHandlerType<P>> | SlotType<P>;
285
292
  declare type RestrictPropType<T, P> = T extends string ? SupportControlled<StringType<P> | ChoiceType<P> | JSONLikeType<P> | ImageUrlType<P> | CustomType<P> | DataPickerType<P>> : T extends boolean ? SupportControlled<BooleanType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : T extends number ? SupportControlled<NumberType<P> | JSONLikeType<P> | CustomType<P> | DataPickerType<P>> : PropType<P>;
286
293
  export interface ActionProps<P> {
287
294
  componentProps: P;
@@ -325,16 +332,47 @@ interface ComponentTemplate<P> extends Omit<CodeComponentElement<P>, "type" | "n
325
332
  export interface ComponentTemplates<P> {
326
333
  [name: string]: ComponentTemplate<P>;
327
334
  }
328
- interface $State {
329
- [key: string]: any;
330
- }
331
- interface $StateSpec<T> {
332
- type: "private" | "readonly" | "writable";
333
- initFunc?: ($props: Record<string, any>, $state: $State) => T;
334
- initVal?: T;
335
- valueProp?: string;
336
- onChangeProp?: string;
335
+ export declare type StateSpec = {
336
+ onChangeProp: string;
337
+ } & ({
338
+ type: "readonly";
339
+ variableType: "text";
340
+ initVal?: string;
341
+ } | {
342
+ type: "readonly";
343
+ variableType: "number";
344
+ initVal?: number;
345
+ } | {
346
+ type: "readonly";
347
+ variableType: "boolean";
348
+ initVal?: boolean;
349
+ } | {
350
+ type: "readonly";
351
+ variableType: "array";
352
+ initVal?: any[];
353
+ } | {
354
+ type: "readonly";
355
+ variableType: "object";
356
+ initVal?: object;
357
+ } | {
358
+ type: "writable";
359
+ variableType: "text" | "number" | "boolean" | "array" | "object";
360
+ valueProp: string;
361
+ });
362
+ export interface StateHelpers<P, T> {
363
+ initFunc?: ($props: P) => T;
364
+ onChangeArgsToValue?: (...args: any) => T;
337
365
  }
366
+ export declare type ComponentHelpers<P> = {
367
+ helpers: {
368
+ states: Record<string, StateHelpers<P, any>>;
369
+ };
370
+ importPath: string;
371
+ } & ({
372
+ importName: string;
373
+ } | {
374
+ isDefaultExport: true;
375
+ });
338
376
  export declare type StyleSection = "visibility" | "typography" | "sizing" | "spacing" | "background" | "transform" | "transitions" | "layout" | "overflow" | "border" | "shadows" | "effects";
339
377
  export interface ComponentMeta<P> {
340
378
  /**
@@ -368,9 +406,16 @@ export interface ComponentMeta<P> {
368
406
  [prop: string]: PropType<P>;
369
407
  };
370
408
  /**
371
- * WIP: An object describing the component states to be used in Studio.
409
+ * An object describing the component states to be used in Studio.
410
+ */
411
+ states?: Record<string, StateSpec>;
412
+ /**
413
+ * An object describing the components helpers to be used in Studio.
414
+ * 1. states helpers: Each state can receive an "initFunc" prop to initialize
415
+ * the implicit state in Studio, and an "onChangeArgsToValue" prop to
416
+ * transform the event handler arguments into a value
372
417
  */
373
- unstable__states?: Record<string, $StateSpec<any>>;
418
+ componentHelpers?: ComponentHelpers<P>;
374
419
  /**
375
420
  * An array describing the component actions to be used in Studio.
376
421
  */