Skip to content

Instantly share code, notes, and snippets.

@yang
Last active July 29, 2022 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yang/6c535bdef13086cad047fa3df0dbf48f to your computer and use it in GitHub Desktop.
Save yang/6c535bdef13086cad047fa3df0dbf48f to your computer and use it in GitHub Desktop.
import {ReactNode, useState} from "react";
export function Section({
children,
hideHeading,
className
}: { children?: ReactNode, className?: string, hideHeading?: boolean }) {
return <div style={{padding: 64}} className={className}>
{!hideHeading && <h1>My Hero</h1>}
{children}
</div>
}
PLASMIC.registerComponent(
Section,
{
name: "Section",
props: {
children: 'slot',
hideHeading: 'boolean',
}
}
);
export function Collapse({
title,
children,
previewShown,
className
}: { title?: ReactNode, children?: ReactNode, className?: string, previewShown?: boolean }) {
const [shown, setShown] = useState(false);
return <div className={className}>
<div style={{padding: 16}} onClick={() => setShown(!shown)}>{title}</div>
{(shown || previewShown) && <div style={{padding: 16}}>{children}</div>}
</div>
}
PLASMIC.registerComponent(
Collapse,
{
name: "Collapse",
props: {
title: {
type: 'slot',
defaultValue: "This is the title"
},
children: {
type: 'slot',
defaultValue: "This is the body"
},
forceShown: "boolean",
}
}
);
import * as React from "react";
import { DataProvider, repeatedElement, useSelector } from "@plasmicapp/host";
import Table from "antd/lib/table/Table";
import {ReactNode, useEffect, useState} from "react";
import "@plasmicpkgs/antd/dist/antd.css";
interface ColumnProps {
columnIndex: number;
// The title text to show in the column headers
title?: string;
// The path for the data field to get the value from
// Display field of the data record, support nest path by string array
dataIndex: string | string[];
// Plasmic - Custom column template
columnTemplate: React.ReactNode;
}
// This is an empty virtual component used to allow users to define column
// properties in plasmic.
export function TableColumn() {
return null;
}
export function TableValue(props: { className: string }) {
const column = useSelector("currentColumn");
return <div className={props.className}>{column?.toString() ?? ""}</div>;
}
type TableProps = {
className?: string;
items: Array<any>;
columns: React.ReactNode;
};
export function DataTable(props: TableProps) {
const { className, columns, items } = props;
// Plasmic Studio Canvas currently renders items in a slightly different way than the generated code:
// - In the studio:
// - The `columns` prop value is an array of nested react <Column /> nodes.
// - In the generated code (preview mode):
// - The `columns` prop value is a React Node with a `children` property that contains
// an array of the nested react <Column /> components.
const tableColumns = (columns as any)?.props?.children ?? (columns as any);
// Convert the props.columns slot children to an array of column definitions
const columnDefinitions = React.useMemo(() => {
return React.Children.map(
tableColumns,
(column: { props: ColumnProps }, columnIndex) => {
const { columnTemplate, title, dataIndex } = column.props;
const columnDefinition = {
columnIndex,
title,
dataIndex,
key: columnIndex,
render: (value: any, record: any, rowIndex: any) => {
return (
<DataProvider name="currentRow" data={record}>
<DataProvider name="currentRowIndex" data={rowIndex}>
<DataProvider name="currentColumn" data={value}>
{repeatedElement(rowIndex, columnTemplate)}
</DataProvider>
</DataProvider>
</DataProvider>
);
},
};
return columnDefinition;
}
);
}, [tableColumns]);
return (
// <DataProvider name="tableColumns" data={items[0] ?? {}} hidden={true}>
<Table
className={className || ""}
columns={columnDefinitions}
dataSource={items}
/>
// </DataProvider>
);
}
export type HttpMethod = "GET" | "POST";
export interface RestQueryProps {
className?: string;
children?: ReactNode;
url?: string;
method?: HttpMethod;
body?: string;
}
export function RestQuery({
className,
children,
url,
body,
method = "GET",
}: RestQueryProps) {
const [data, setData] = useState(null);
useEffect(() => {
(async () => {
if (url) {
const response = await fetch(url, {
method,
body
})
const data = await response.json();
setData(data)
}
})()
}, [url, method]);
return (
<div className={className}><DataProvider name={"fetchedData"} data={data} label={"Fetched data"}>
{children}
</DataProvider></div>
);
}
function capitalizeFirstLetter(input: string) {
return input.charAt(0).toUpperCase() + input.slice(1);
}
const DEFAULT_ITEMS = [
{
name: "John Brown",
age: 19,
address: "New York No. 1 Lake Park",
tags: ["student", "developer"],
},
{
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
tags: ["teacher"],
},
{
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
tags: ["cool", "teacher"],
},
];
PLASMIC.registerComponent(DataTable, {
name: "DataTable",
props: {
items: {
type: "array",
defaultValue: DEFAULT_ITEMS,
},
columns: {
type: "slot",
allowedComponents: ["TableColumn"],
defaultValue: Object.keys(DEFAULT_ITEMS[0]).map((columnName) => ({
type: "component",
name: "TableColumn",
props: {
title: capitalizeFirstLetter(columnName),
dataIndex: columnName,
},
})) ,
},
},
});
PLASMIC.registerComponent(TableColumn, {
name: "TableColumn",
parentComponentName: "DataTable",
providesData: true,
props: {
// The title text to show in the column headers
title: {
type: "string",
defaultValue: "Name",
},
// The path for the data field to get the value from
// Display field of the data record, support nest path by string array
dataIndex: {
type: "string",
defaultValue: "name",
},
// TODO: Debug why the ctx object is empty (expected to be ctx = {tableColumn})
// dataIndex: {
// type: "dataSelector",
// data: (props, ctx) => {
// console.log(">>> M dataSelector", {props, ctx});
// return ctx?.tableColumns ?? {}}
// ,
// displayName: "Field",
// description: "Field to be displayed.",
// defaultValue: ["name"],
// },
// Plasmic - Custom column template
columnTemplate: {
type: "slot",
defaultValue: {
type: "vbox",
styles: {
padding: 0,
},
children: [
{
type: "component",
name: "TableValue",
},
],
},
} ,
},
});
PLASMIC.registerComponent(TableValue, {
name: "TableValue",
parentComponentName: "TableColumn",
props: {},
});
PLASMIC.registerComponent(RestQuery, {
name: "RestQuery",
providesData: true,
props: {
url: {
type: "string",
defaultValue: "https://jsonplaceholder.typicode.com/posts"
},
method: {
type: 'choice',
options: [
'GET',
'POST'
],
defaultValueHint: 'GET'
},
children: {
type: 'slot',
defaultValue: [
{
type: 'vbox',
children: [
{
type: 'text',
value: 'Insert some contents here'
}
]
}
]
}
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment