mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
updated plasmic package to work with new hooks + added example
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@ packages/media/.env
|
|||||||
**/*/.env
|
**/*/.env
|
||||||
**/*/.dev.vars
|
**/*/.dev.vars
|
||||||
**/*/.wrangler
|
**/*/.wrangler
|
||||||
|
**/*/*.tgz
|
||||||
**/*/vite.config.ts.timestamp*
|
**/*/vite.config.ts.timestamp*
|
||||||
.history
|
.history
|
||||||
**/*/.db/*
|
**/*/.db/*
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"version": "0.3.3",
|
"version": "0.3.4-alpha1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:all": "bun run build && bun run build:cli",
|
"build:all": "bun run build && bun run build:cli",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ export class SystemApi extends ModuleApi<any> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readConfig() {
|
||||||
|
return this.get<{ version: number } & ModuleConfigs>("config");
|
||||||
|
}
|
||||||
|
|
||||||
readSchema(options?: { config?: boolean; secrets?: boolean }) {
|
readSchema(options?: { config?: boolean; secrets?: boolean }) {
|
||||||
return this.get<ApiSchemaResponse>("schema", {
|
return this.get<ApiSchemaResponse>("schema", {
|
||||||
config: options?.config ? 1 : 0,
|
config: options?.config ? 1 : 0,
|
||||||
|
|||||||
@@ -12,44 +12,38 @@ export type ClientProviderProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ClientProvider = ({ children, baseUrl, user }: ClientProviderProps) => {
|
export const ClientProvider = ({ children, baseUrl, user }: ClientProviderProps) => {
|
||||||
const [actualBaseUrl, setActualBaseUrl] = useState<string | null>(null);
|
//const [actualBaseUrl, setActualBaseUrl] = useState<string | null>(null);
|
||||||
const winCtx = useBkndWindowContext();
|
const winCtx = useBkndWindowContext();
|
||||||
|
const _ctx_baseUrl = useBaseUrl();
|
||||||
|
let actualBaseUrl = baseUrl ?? _ctx_baseUrl ?? "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const _ctx_baseUrl = useBaseUrl();
|
if (!baseUrl) {
|
||||||
if (_ctx_baseUrl) {
|
if (_ctx_baseUrl) {
|
||||||
console.warn("wrapped many times");
|
actualBaseUrl = _ctx_baseUrl;
|
||||||
setActualBaseUrl(_ctx_baseUrl);
|
console.warn("wrapped many times, take from context", actualBaseUrl);
|
||||||
|
} else if (typeof window !== "undefined") {
|
||||||
|
actualBaseUrl = window.location.origin;
|
||||||
|
console.log("setting from window", actualBaseUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("error", e);
|
console.error("error .....", e);
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Only set base URL if running on the client side
|
|
||||||
if (typeof window !== "undefined") {
|
|
||||||
setActualBaseUrl(baseUrl || window.location.origin);
|
|
||||||
}
|
|
||||||
}, [baseUrl]);
|
|
||||||
|
|
||||||
if (!actualBaseUrl) {
|
|
||||||
// Optionally, return a fallback during SSR rendering
|
|
||||||
return null; // or a loader/spinner if desired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = new Api({ host: actualBaseUrl, user: user ?? winCtx.user });
|
const api = new Api({ host: actualBaseUrl, user: user ?? winCtx.user });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClientContext.Provider value={{ baseUrl: actualBaseUrl, api }}>
|
<ClientContext.Provider value={{ baseUrl: api.baseUrl, api }}>
|
||||||
{children}
|
{children}
|
||||||
</ClientContext.Provider>
|
</ClientContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useApi = (host?: ApiOptions["host"]) => {
|
export const useApi = (host?: ApiOptions["host"]): Api => {
|
||||||
const context = useContext(ClientContext);
|
const context = useContext(ClientContext);
|
||||||
if (host && host !== context.baseUrl) {
|
if (!context?.api || (host && host.length > 0 && host !== context.baseUrl)) {
|
||||||
return new Api({ host });
|
return new Api({ host: host ?? "" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.api;
|
return context.api;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
// default: https://github.com/mantinedev/mantine/blob/master/src/mantine-core/src/core/MantineProvider/default-theme.ts
|
// default: https://github.com/mantinedev/mantine/blob/master/packages/%40mantine/core/src/core/MantineProvider/default-theme.ts
|
||||||
|
|
||||||
export function createMantineTheme(scheme: "light" | "dark"): {
|
export function createMantineTheme(scheme: "light" | "dark"): {
|
||||||
theme: ReturnType<typeof createTheme>;
|
theme: ReturnType<typeof createTheme>;
|
||||||
|
|||||||
1
examples/plasmic/.gitignore
vendored
Normal file
1
examples/plasmic/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.next
|
||||||
5
examples/plasmic/next-env.d.ts
vendored
Normal file
5
examples/plasmic/next-env.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||||
8
examples/plasmic/next.config.ts
Normal file
8
examples/plasmic/next.config.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
/* config options here */
|
||||||
|
reactStrictMode: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
26
examples/plasmic/package.json
Normal file
26
examples/plasmic/package.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "plasmic-nextjs",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@plasmicapp/loader-nextjs": "^1.0.409",
|
||||||
|
"bknd": "workspace:*",
|
||||||
|
"@bknd/plasmic": "workspace:*",
|
||||||
|
"next": "15.0.4",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5",
|
||||||
|
"@types/node": "^20",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"postcss": "^8"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
examples/plasmic/postcss.config.mjs
Normal file
8
examples/plasmic/postcss.config.mjs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('postcss-load-config').Config} */
|
||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
78
examples/plasmic/src/pages/[[...catchall]].tsx
Normal file
78
examples/plasmic/src/pages/[[...catchall]].tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { PLASMIC } from "@/plasmic-init";
|
||||||
|
import {
|
||||||
|
type ComponentRenderData,
|
||||||
|
PlasmicComponent,
|
||||||
|
PlasmicRootProvider,
|
||||||
|
extractPlasmicQueryData
|
||||||
|
} from "@plasmicapp/loader-nextjs";
|
||||||
|
import type { GetServerSideProps } from "next";
|
||||||
|
// biome-ignore lint/suspicious/noShadowRestrictedNames: <explanation>
|
||||||
|
import Error from "next/error";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||||
|
const { catchall } = context.params ?? {};
|
||||||
|
|
||||||
|
// Convert the catchall param into a path string
|
||||||
|
const plasmicPath =
|
||||||
|
typeof catchall === "string"
|
||||||
|
? catchall
|
||||||
|
: Array.isArray(catchall)
|
||||||
|
? `/${catchall.join("/")}`
|
||||||
|
: "/";
|
||||||
|
const plasmicData = await PLASMIC.maybeFetchComponentData(plasmicPath);
|
||||||
|
if (!plasmicData) {
|
||||||
|
// This is some non-Plasmic catch-all page
|
||||||
|
return {
|
||||||
|
props: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a path that Plasmic knows about.
|
||||||
|
const pageMeta = plasmicData.entryCompMetas[0];
|
||||||
|
|
||||||
|
// Cache the necessary data fetched for the page.
|
||||||
|
const queryCache = await extractPlasmicQueryData(
|
||||||
|
<PlasmicRootProvider
|
||||||
|
loader={PLASMIC}
|
||||||
|
prefetchedData={plasmicData}
|
||||||
|
pageRoute={pageMeta.path}
|
||||||
|
pageParams={pageMeta.params}
|
||||||
|
>
|
||||||
|
{/* @ts-ignore */}
|
||||||
|
<PlasmicComponent component={pageMeta.displayName} />
|
||||||
|
</PlasmicRootProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pass the data in as props.
|
||||||
|
return {
|
||||||
|
props: { plasmicData, queryCache }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CatchallPage(props: {
|
||||||
|
plasmicData?: ComponentRenderData;
|
||||||
|
queryCache?: Record<string, any>;
|
||||||
|
}) {
|
||||||
|
const { plasmicData, queryCache } = props;
|
||||||
|
const router = useRouter();
|
||||||
|
if (!plasmicData || plasmicData.entryCompMetas.length === 0) {
|
||||||
|
return <Error statusCode={404} />;
|
||||||
|
}
|
||||||
|
const pageMeta = plasmicData.entryCompMetas[0];
|
||||||
|
return (
|
||||||
|
// Pass in the data fetched in getStaticProps as prefetchedData
|
||||||
|
<PlasmicRootProvider
|
||||||
|
loader={PLASMIC}
|
||||||
|
prefetchedData={plasmicData}
|
||||||
|
prefetchedQueryData={queryCache}
|
||||||
|
pageRoute={pageMeta.path}
|
||||||
|
pageParams={pageMeta.params}
|
||||||
|
pageQuery={router.query}
|
||||||
|
>
|
||||||
|
{/* @ts-ignore */}
|
||||||
|
<PlasmicComponent component={pageMeta.displayName} />
|
||||||
|
</PlasmicRootProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
11
examples/plasmic/src/pages/_app.tsx
Normal file
11
examples/plasmic/src/pages/_app.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import "@/styles/globals.css";
|
||||||
|
import { ClientProvider } from "bknd/client";
|
||||||
|
import type { AppProps } from "next/app";
|
||||||
|
|
||||||
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
|
return (
|
||||||
|
<ClientProvider baseUrl="http://localhost:3000">
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</ClientProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
13
examples/plasmic/src/pages/_document.tsx
Normal file
13
examples/plasmic/src/pages/_document.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Html, Head, Main, NextScript } from "next/document";
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body className="antialiased">
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
}
|
||||||
25
examples/plasmic/src/pages/admin/[[...admin]].tsx
Normal file
25
examples/plasmic/src/pages/admin/[[...admin]].tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// pages/admin/[[...admin]].tsx
|
||||||
|
import { withApi } from "bknd/adapter/nextjs";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import "bknd/dist/styles.css";
|
||||||
|
|
||||||
|
/*export const config = {
|
||||||
|
runtime: "experimental-edge"
|
||||||
|
}*/
|
||||||
|
|
||||||
|
const Admin = dynamic(() => import("bknd/ui").then((mod) => mod.Admin), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getServerSideProps = withApi(async (context) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
user: context.api.getUser(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function AdminPage() {
|
||||||
|
if (typeof document === "undefined") return null;
|
||||||
|
return <Admin withProvider config={{ basepath: "/admin" }} />;
|
||||||
|
}
|
||||||
16
examples/plasmic/src/pages/api/[...route].ts
Normal file
16
examples/plasmic/src/pages/api/[...route].ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { serve } from "bknd/adapter/nextjs";
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
runtime: "edge",
|
||||||
|
unstable_allowDynamic: ["**/*.js"]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default serve({
|
||||||
|
connection: {
|
||||||
|
type: "libsql",
|
||||||
|
config: {
|
||||||
|
url: process.env.DB_URL!,
|
||||||
|
authToken: process.env.DB_TOKEN!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
7
examples/plasmic/src/pages/plasmic-host.tsx
Normal file
7
examples/plasmic/src/pages/plasmic-host.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { PlasmicCanvasHost } from '@plasmicapp/loader-nextjs';
|
||||||
|
import { PLASMIC } from '@/plasmic-init';
|
||||||
|
|
||||||
|
export default function PlasmicHost() {
|
||||||
|
return PLASMIC && <PlasmicCanvasHost />;
|
||||||
|
}
|
||||||
6
examples/plasmic/src/pages/test.tsx
Normal file
6
examples/plasmic/src/pages/test.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { useApi } from "bknd/client";
|
||||||
|
|
||||||
|
export default function Test() {
|
||||||
|
const api = useApi(undefined);
|
||||||
|
return <div>{api.baseUrl}</div>;
|
||||||
|
}
|
||||||
17
examples/plasmic/src/plasmic-init.ts
Normal file
17
examples/plasmic/src/plasmic-init.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { initPlasmicLoader } from "@plasmicapp/loader-nextjs";
|
||||||
|
import { loader } from "@bknd/plasmic";
|
||||||
|
|
||||||
|
export const PLASMIC = initPlasmicLoader({
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
id: process.env.PLASMIC_ID!,
|
||||||
|
token: process.env.PLASMIC_TOKEN!,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
preview: true, //process.env.NODE_ENV === "development",
|
||||||
|
})
|
||||||
|
|
||||||
|
loader(PLASMIC);
|
||||||
|
/*
|
||||||
|
PLASMIC.registerComponent(BkndData, BkndDataMeta);
|
||||||
|
PLASMIC.registerGlobalContext(BkndContext, BkndContextMeta as any);*/
|
||||||
3
examples/plasmic/src/styles/globals.css
Normal file
3
examples/plasmic/src/styles/globals.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
18
examples/plasmic/tailwind.config.ts
Normal file
18
examples/plasmic/tailwind.config.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
content: [
|
||||||
|
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: "var(--background)",
|
||||||
|
foreground: "var(--foreground)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
} satisfies Config;
|
||||||
23
examples/plasmic/tsconfig.json
Normal file
23
examples/plasmic/tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import type { CodeComponentMeta } from "@plasmicapp/host";
|
|
||||||
import { Link } from "wouter";
|
|
||||||
|
|
||||||
export function WouterLink({ href, className, children, ...props }) {
|
|
||||||
return (
|
|
||||||
<Link href={href ?? "#"} className={className} {...props}>
|
|
||||||
{children}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const WouterLinkMeta: CodeComponentMeta<any> = {
|
|
||||||
name: "WouterLink",
|
|
||||||
importPath: import.meta.dir,
|
|
||||||
props: {
|
|
||||||
href: {
|
|
||||||
type: "href",
|
|
||||||
},
|
|
||||||
children: {
|
|
||||||
type: "slot",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export { loader as loadBkndComponents, CatchAllPage, createWouterPlasmicApp } from "./loader";
|
|
||||||
|
|
||||||
export * from "./components";
|
|
||||||
export * from "./contexts";
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import { PlasmicCanvasHost, type registerComponent } from "@plasmicapp/host";
|
|
||||||
import {
|
|
||||||
type ComponentRenderData,
|
|
||||||
PlasmicComponent,
|
|
||||||
type PlasmicComponentLoader,
|
|
||||||
PlasmicRootProvider
|
|
||||||
} from "@plasmicapp/loader-react";
|
|
||||||
import { forwardRef, useEffect, useState } from "react";
|
|
||||||
import { Link, Route, Router, Switch } from "wouter";
|
|
||||||
import {
|
|
||||||
BkndData,
|
|
||||||
BkndDataMeta,
|
|
||||||
Image,
|
|
||||||
ImageMeta,
|
|
||||||
LazyRender,
|
|
||||||
LazyRenderMeta,
|
|
||||||
WouterLink,
|
|
||||||
WouterLinkMeta
|
|
||||||
} from "./components";
|
|
||||||
import { BkndContext, BkndContextMeta } from "./contexts";
|
|
||||||
|
|
||||||
export function loader(PLASMIC: PlasmicComponentLoader) {
|
|
||||||
PLASMIC.registerComponent(BkndData, BkndDataMeta);
|
|
||||||
PLASMIC.registerComponent(WouterLink, WouterLinkMeta);
|
|
||||||
PLASMIC.registerComponent(Image, ImageMeta);
|
|
||||||
PLASMIC.registerComponent(LazyRender, LazyRenderMeta);
|
|
||||||
PLASMIC.registerGlobalContext(BkndContext, BkndContextMeta as any);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CustomLink = forwardRef<any, any>((props, ref) => {
|
|
||||||
//console.log("rendering custom link", props);
|
|
||||||
//return null;
|
|
||||||
if ("data-replace" in props) {
|
|
||||||
return <a ref={ref} {...props} />;
|
|
||||||
}
|
|
||||||
//return <a ref={ref} {...props} />;
|
|
||||||
// @ts-ignore it's because of the link
|
|
||||||
return <Link ref={ref} {...props} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
const Wrapper = ({ children }) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: "100wh",
|
|
||||||
height: "100vh",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ opacity: 0.5, textTransform: "uppercase" }}>{children}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CatchAllPage({
|
|
||||||
PLASMIC,
|
|
||||||
prefix = ""
|
|
||||||
}: { PLASMIC: PlasmicComponentLoader; prefix?: string }) {
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [pageData, setPageData] = useState<ComponentRenderData | null>(null);
|
|
||||||
|
|
||||||
//const params = useParams();
|
|
||||||
const pathname = location.pathname.replace(prefix, "");
|
|
||||||
const path = pathname.length === 0 ? "/" : pathname;
|
|
||||||
//console.log("path", path, params);
|
|
||||||
useEffect(() => {
|
|
||||||
async function load() {
|
|
||||||
const pageData = await PLASMIC.maybeFetchComponentData(path);
|
|
||||||
//console.log("pageData", pageData);
|
|
||||||
setPageData(pageData);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
load();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <Wrapper>Loading ...</Wrapper>;
|
|
||||||
}
|
|
||||||
if (!pageData) {
|
|
||||||
return <Wrapper>Not found</Wrapper>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pageMeta = pageData.entryCompMetas[0];
|
|
||||||
|
|
||||||
// The page will already be cached from the `load` call above.
|
|
||||||
return (
|
|
||||||
<PlasmicRootProvider loader={PLASMIC} pageParams={pageMeta.params} Link={CustomLink}>
|
|
||||||
<PlasmicComponent component={path} />
|
|
||||||
</PlasmicRootProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createWouterPlasmicApp(PLASMIC: PlasmicComponentLoader, prefix = "") {
|
|
||||||
return function App() {
|
|
||||||
return (
|
|
||||||
<Router base={prefix}>
|
|
||||||
<Switch>
|
|
||||||
<Route path="/host" component={PlasmicCanvasHost as any} />
|
|
||||||
<Route
|
|
||||||
path="/*"
|
|
||||||
component={() => <CatchAllPage PLASMIC={PLASMIC} prefix={prefix} />}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@bknd/plasmic",
|
"name": "@bknd/plasmic",
|
||||||
|
"version": "0.3.4-alpha1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -8,41 +9,61 @@
|
|||||||
"build:only": "rm -rf dist && bun tsup",
|
"build:only": "rm -rf dist && bun tsup",
|
||||||
"types": "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
|
"types": "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
|
||||||
"build:types": "bun tsc --emitDeclarationOnly",
|
"build:types": "bun tsc --emitDeclarationOnly",
|
||||||
"updater": "bun x npm-check-updates -ui"
|
"updater": "bun x npm-check-updates -ui",
|
||||||
|
"pack": "rm -rf *.tgz && npm pack && mv *.tgz latest.tgz",
|
||||||
|
"prepublishOnly": "bun run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"publishConfig": {
|
||||||
"wouter": "^3.3.5"
|
"access": "public"
|
||||||
},
|
},
|
||||||
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
|
"bknd": "workspace:*",
|
||||||
|
"tsdx": "^0.14.1",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@plasmicapp/host": ">=1.0.0",
|
"bknd": "*",
|
||||||
"bknd": "workspace:*",
|
|
||||||
"react": ">=18",
|
"react": ">=18",
|
||||||
"react-dom": ">=18"
|
"react-dom": ">=18",
|
||||||
|
"@plasmicapp/host": ">=1.0.0",
|
||||||
|
"@plasmicapp/query": ">=0.1.0"
|
||||||
},
|
},
|
||||||
"tsup": {
|
"tsup": {
|
||||||
"entry": ["index.ts"],
|
"entry": [
|
||||||
"minify": true,
|
"src/index.ts"
|
||||||
|
],
|
||||||
|
"minify": false,
|
||||||
"clean": true,
|
"clean": true,
|
||||||
"external": ["react", "react-dom", "@plasmicapp/host", "@plasmicapp/loader-react", "@plasmicapp/loader-core"],
|
"external": [
|
||||||
"format": ["esm"],
|
"react",
|
||||||
|
"react-dom",
|
||||||
|
"@plasmicapp/host",
|
||||||
|
"@plasmicapp/query",
|
||||||
|
"swr"
|
||||||
|
],
|
||||||
|
"format": [
|
||||||
|
"esm",
|
||||||
|
"cjs"
|
||||||
|
],
|
||||||
"platform": "browser",
|
"platform": "browser",
|
||||||
"shims": true,
|
|
||||||
"bundle": true,
|
"bundle": true,
|
||||||
"metafile": true,
|
"metafile": true,
|
||||||
"splitting": false,
|
"splitting": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "dist"
|
"outDir": "dist"
|
||||||
},
|
},
|
||||||
"exports": {
|
"types": "dist/index.d.ts",
|
||||||
".": {
|
"module": "dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"main": "dist/index.cjs",
|
||||||
"import": "./dist/index.js",
|
"files": [
|
||||||
"require": "./dist/index.js"
|
"dist",
|
||||||
}
|
"README.md",
|
||||||
},
|
"!dist/*.tsbuildinfo",
|
||||||
"files": ["dist"]
|
"!dist/*.map",
|
||||||
|
"!dist/**/*.map",
|
||||||
|
"!dist/metafile*",
|
||||||
|
"!dist/**/metafile*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import type { CodeComponentMeta } from "@plasmicapp/host";
|
import type { CodeComponentMeta } from "@plasmicapp/host";
|
||||||
|
import registerComponent, { type ComponentMeta } from "@plasmicapp/host/registerComponent";
|
||||||
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
|
import React from "react";
|
||||||
//import { PlasmicCanvasContext } from "@plasmicapp/loader-react";
|
//import { PlasmicCanvasContext } from "@plasmicapp/loader-react";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ function numeric(value: number | string): number {
|
|||||||
function getDimensionDefaults(
|
function getDimensionDefaults(
|
||||||
width: number | string | undefined,
|
width: number | string | undefined,
|
||||||
height: number | string | undefined,
|
height: number | string | undefined,
|
||||||
ratio: number | undefined,
|
ratio: number | undefined
|
||||||
) {
|
) {
|
||||||
let _width = width;
|
let _width = width;
|
||||||
let _height = height;
|
let _height = height;
|
||||||
@@ -61,7 +62,7 @@ function getDimensionDefaults(
|
|||||||
function getPlaceholderStyle(
|
function getPlaceholderStyle(
|
||||||
width: number | string | undefined,
|
width: number | string | undefined,
|
||||||
height: number | string | undefined,
|
height: number | string | undefined,
|
||||||
ratio: number | undefined,
|
ratio: number | undefined
|
||||||
) {
|
) {
|
||||||
let paddingBottom = 0;
|
let paddingBottom = 0;
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
@@ -73,7 +74,7 @@ function getPlaceholderStyle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
paddingBottom: paddingBottom + "%",
|
paddingBottom: paddingBottom + "%"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ threshold: loadTreshold },
|
{ threshold: loadTreshold }
|
||||||
);
|
);
|
||||||
if (imgRef.current) {
|
if (imgRef.current) {
|
||||||
observer.observe(imgRef.current);
|
observer.observe(imgRef.current);
|
||||||
@@ -150,7 +151,7 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
const {
|
const {
|
||||||
width: _width,
|
width: _width,
|
||||||
height: _height,
|
height: _height,
|
||||||
ratio: _ratio,
|
ratio: _ratio
|
||||||
} = getDimensionDefaults(width, height, ratio);
|
} = getDimensionDefaults(width, height, ratio);
|
||||||
|
|
||||||
const imgStyle: any = {
|
const imgStyle: any = {
|
||||||
@@ -163,7 +164,7 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
height: "auto",
|
height: "auto",
|
||||||
//height: _height || "auto",
|
//height: _height || "auto",
|
||||||
//height: !transitioned ? _height || "auto" : "auto",
|
//height: !transitioned ? _height || "auto" : "auto",
|
||||||
opacity: forceLoad || loaded ? 1 : 0,
|
opacity: forceLoad || loaded ? 1 : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const placeholderStyle: any = {
|
const placeholderStyle: any = {
|
||||||
@@ -174,7 +175,7 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
width: _width || "100%",
|
width: _width || "100%",
|
||||||
height: 0,
|
height: 0,
|
||||||
//height: transitioned ? "auto" : 0,
|
//height: transitioned ? "auto" : 0,
|
||||||
...getPlaceholderStyle(_width, _height, _ratio),
|
...getPlaceholderStyle(_width, _height, _ratio)
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapperStyle: any = {
|
const wrapperStyle: any = {
|
||||||
@@ -186,7 +187,7 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
lineHeight: 0,
|
lineHeight: 0,
|
||||||
//height: _height,
|
//height: _height,
|
||||||
maxWidth: "100%",
|
maxWidth: "100%",
|
||||||
maxHeight: "100%",
|
maxHeight: "100%"
|
||||||
};
|
};
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
wrapperStyle.height = "auto";
|
wrapperStyle.height = "auto";
|
||||||
@@ -213,13 +214,24 @@ export const Image: React.FC<ImageProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ImageMeta: CodeComponentMeta<React.ComponentType<ImageProps>> = {
|
export function registerImage(
|
||||||
|
loader?: { registerComponent: typeof registerComponent },
|
||||||
|
customMeta?: ComponentMeta<ImageProps>
|
||||||
|
) {
|
||||||
|
if (loader) {
|
||||||
|
loader.registerComponent(Image, customMeta ?? ImageMeta);
|
||||||
|
} else {
|
||||||
|
registerComponent(Image, customMeta ?? ImageMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImageMeta: CodeComponentMeta<ImageProps> = {
|
||||||
name: "ImageLazy",
|
name: "ImageLazy",
|
||||||
importPath: import.meta.dir,
|
importPath: "@bknd/plasmic",
|
||||||
props: {
|
props: {
|
||||||
src: {
|
src: {
|
||||||
type: "imageUrl",
|
type: "imageUrl",
|
||||||
displayName: "Image",
|
displayName: "Image"
|
||||||
},
|
},
|
||||||
alt: "string",
|
alt: "string",
|
||||||
width: "number",
|
width: "number",
|
||||||
@@ -230,14 +242,14 @@ export const ImageMeta: CodeComponentMeta<React.ComponentType<ImageProps>> = {
|
|||||||
//backgroundColor: "color",
|
//backgroundColor: "color",
|
||||||
transitionSpeed: {
|
transitionSpeed: {
|
||||||
type: "number",
|
type: "number",
|
||||||
helpText: "How fast image should fade in. Default is 200 (ms).",
|
helpText: "How fast image should fade in. Default is 200 (ms)."
|
||||||
},
|
},
|
||||||
loadTreshold: {
|
loadTreshold: {
|
||||||
type: "number",
|
type: "number",
|
||||||
displayName: "Treshold",
|
displayName: "Treshold",
|
||||||
//defaultValue: 0.1,
|
//defaultValue: 0.1,
|
||||||
helpText:
|
helpText:
|
||||||
"Number between 0 and 1. Default is 0.1. Determines how much of the image must be in viewport before it gets loaded",
|
"Number between 0 and 1. Default is 0.1. Determines how much of the image must be in viewport before it gets loaded"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import type { CodeComponentMeta } from "@plasmicapp/host";
|
import type { CodeComponentMeta } from "@plasmicapp/host";
|
||||||
|
import registerComponent, { type ComponentMeta } from "@plasmicapp/host/registerComponent";
|
||||||
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
|
import React from "react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
interface LazyRenderProps {
|
interface LazyRenderProps {
|
||||||
@@ -22,7 +25,7 @@ export const LazyRender: React.FC<LazyRenderProps> = ({
|
|||||||
threshold = 0.1,
|
threshold = 0.1,
|
||||||
delay = 0,
|
delay = 0,
|
||||||
fallback = <DefaultFallback />,
|
fallback = <DefaultFallback />,
|
||||||
onBecomesVisible,
|
onBecomesVisible
|
||||||
}) => {
|
}) => {
|
||||||
const [isVisible, setIsVisible] = useState(forceLoad);
|
const [isVisible, setIsVisible] = useState(forceLoad);
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
@@ -43,7 +46,7 @@ export const LazyRender: React.FC<LazyRenderProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const observerOptions: IntersectionObserverInit = {
|
const observerOptions: IntersectionObserverInit = {
|
||||||
threshold: threshold < 1 ? threshold : 0.1,
|
threshold: threshold < 1 ? threshold : 0.1
|
||||||
};
|
};
|
||||||
|
|
||||||
const observerCallback: IntersectionObserverCallback = (entries) => {
|
const observerCallback: IntersectionObserverCallback = (entries) => {
|
||||||
@@ -74,38 +77,49 @@ export const LazyRender: React.FC<LazyRenderProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LazyRenderMeta: CodeComponentMeta<React.ComponentType<LazyRenderProps>> = {
|
export function registerLazyRender(
|
||||||
|
loader?: { registerComponent: typeof registerComponent },
|
||||||
|
customMeta?: ComponentMeta<LazyRenderProps>
|
||||||
|
) {
|
||||||
|
if (loader) {
|
||||||
|
loader.registerComponent(LazyRender, customMeta ?? LazyRenderMeta);
|
||||||
|
} else {
|
||||||
|
registerComponent(LazyRender, customMeta ?? LazyRenderMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LazyRenderMeta: CodeComponentMeta<LazyRenderProps> = {
|
||||||
name: "LazyRender",
|
name: "LazyRender",
|
||||||
importPath: import.meta.dir,
|
importPath: "@bknd/plasmic",
|
||||||
props: {
|
props: {
|
||||||
forceLoad: {
|
forceLoad: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
defaultValue: false,
|
defaultValue: false
|
||||||
},
|
},
|
||||||
forceFallback: {
|
forceFallback: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
defaultValue: false,
|
defaultValue: false
|
||||||
},
|
},
|
||||||
threshold: {
|
threshold: {
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: 0.1,
|
defaultValue: 0.1
|
||||||
},
|
},
|
||||||
fallback: {
|
fallback: {
|
||||||
type: "slot",
|
type: "slot"
|
||||||
//allowedComponents: ["*"],
|
//allowedComponents: ["*"],
|
||||||
},
|
},
|
||||||
delay: {
|
delay: {
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: 0,
|
defaultValue: 0
|
||||||
},
|
},
|
||||||
onBecomesVisible: {
|
onBecomesVisible: {
|
||||||
type: "code",
|
type: "code",
|
||||||
lang: "javascript",
|
lang: "javascript"
|
||||||
},
|
},
|
||||||
|
|
||||||
children: {
|
children: {
|
||||||
type: "slot",
|
type: "slot"
|
||||||
//allowedComponents: ["*"],
|
//allowedComponents: ["*"],
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import { type CodeComponentMeta, DataProvider, usePlasmicCanvasContext } from "@plasmicapp/host";
|
import { DataProvider, usePlasmicCanvasContext } from "@plasmicapp/host";
|
||||||
|
import registerComponent, { type ComponentMeta } from "@plasmicapp/host/registerComponent";
|
||||||
|
import { usePlasmicQueryData } from "@plasmicapp/query";
|
||||||
|
import { useApi, useEntityQuery } from "bknd/client";
|
||||||
import type { RepoQuery } from "bknd/data";
|
import type { RepoQuery } from "bknd/data";
|
||||||
import { useEntities, useEntity } from "bknd/ui";
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
import { encodeSearch } from "bknd/utils";
|
import React from "react";
|
||||||
import { useContext, useEffect, useState } from "react";
|
|
||||||
import { usePlasmicBkndContext } from "../../contexts/BkndContext";
|
import { usePlasmicBkndContext } from "../../contexts/BkndContext";
|
||||||
|
|
||||||
type BkndEntitiesProps = {
|
type BkndDataProps = {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
loading?: React.ReactNode;
|
loading?: React.ReactNode;
|
||||||
error?: React.ReactNode;
|
error?: React.ReactNode;
|
||||||
@@ -23,10 +25,11 @@ type BkndEntitiesProps = {
|
|||||||
dataName?: string;
|
dataName?: string;
|
||||||
entityId?: number;
|
entityId?: number;
|
||||||
entity?: string;
|
entity?: string;
|
||||||
|
select?: string[];
|
||||||
sortBy: string;
|
sortBy: string;
|
||||||
sortDir: "asc" | "desc";
|
sortDir: "asc" | "desc";
|
||||||
where?: string;
|
where?: string;
|
||||||
mode?: "fetch" | "react-query";
|
mode?: "fetch" | "swr";
|
||||||
noLayout?: boolean;
|
noLayout?: boolean;
|
||||||
preview?: boolean;
|
preview?: boolean;
|
||||||
previewSlot?: "loading" | "error" | "empty";
|
previewSlot?: "loading" | "error" | "empty";
|
||||||
@@ -61,11 +64,13 @@ export function BkndData({
|
|||||||
sortBy = "id",
|
sortBy = "id",
|
||||||
sortDir = "asc",
|
sortDir = "asc",
|
||||||
mode = "fetch",
|
mode = "fetch",
|
||||||
|
select = [],
|
||||||
noLayout,
|
noLayout,
|
||||||
preview,
|
preview,
|
||||||
previewSlot,
|
previewSlot,
|
||||||
...props
|
...props
|
||||||
}: BkndEntitiesProps) {
|
}: BkndDataProps) {
|
||||||
|
//console.log("--bknd data");
|
||||||
const inEditor = !!usePlasmicCanvasContext();
|
const inEditor = !!usePlasmicCanvasContext();
|
||||||
const plasmicContext = usePlasmicBkndContext();
|
const plasmicContext = usePlasmicBkndContext();
|
||||||
|
|
||||||
@@ -100,6 +105,7 @@ export function BkndData({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
|
select: select.length > 0 ? select : undefined,
|
||||||
limit: entityId ? undefined : limit,
|
limit: entityId ? undefined : limit,
|
||||||
offset: entityId ? undefined : offset,
|
offset: entityId ? undefined : offset,
|
||||||
where: _where,
|
where: _where,
|
||||||
@@ -108,7 +114,7 @@ export function BkndData({
|
|||||||
join: joinRefs
|
join: joinRefs
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("---context", plasmicContext);
|
//console.log("---context", plasmicContext);
|
||||||
if (plasmicContext.appConfig?.data?.entities) {
|
if (plasmicContext.appConfig?.data?.entities) {
|
||||||
const { entities, relations } = plasmicContext.appConfig.data;
|
const { entities, relations } = plasmicContext.appConfig.data;
|
||||||
console.log("entities", entities);
|
console.log("entities", entities);
|
||||||
@@ -149,8 +155,7 @@ export function BkndData({
|
|||||||
children
|
children
|
||||||
};
|
};
|
||||||
|
|
||||||
const Component =
|
const Component = mode === "swr" ? <ModeSWR {...modeProps} /> : <ModeFetch {...modeProps} />;
|
||||||
mode === "react-query" ? <ModeReactQuery {...modeProps} /> : <ModeFetch {...modeProps} />;
|
|
||||||
return noLayout ? Component : <div className={props.className}>{Component}</div>;
|
return noLayout ? Component : <div className={props.className}>{Component}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,32 +180,19 @@ const ModeFetch = ({
|
|||||||
entity,
|
entity,
|
||||||
query
|
query
|
||||||
}: ModeProps) => {
|
}: ModeProps) => {
|
||||||
const [data, setData] = useState<any[]>([]);
|
const api = useApi();
|
||||||
const [isLoading, setLoading] = useState(true);
|
const endpoint = entityId
|
||||||
const [hasError, setError] = useState<string>();
|
? api.data.readOne(entity, entityId, query)
|
||||||
const plasmicContext = usePlasmicBkndContext();
|
: api.data.readMany(entity, query);
|
||||||
const basepath = "/api/data";
|
|
||||||
const path = entityId ? `${basepath}/${entity}/${entityId}` : `${basepath}/${entity}`;
|
|
||||||
console.log("query", path, query);
|
|
||||||
const url = `${plasmicContext.baseUrl}${path}?${encodeSearch(query)}`;
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const res = await fetch(url);
|
|
||||||
const result = (await res.json()) as any;
|
|
||||||
//console.log("result", result);
|
|
||||||
setData(result.data);
|
|
||||||
setLoading(false);
|
|
||||||
setError(undefined);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
setError(String(e));
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [url]);
|
|
||||||
|
|
||||||
console.log("--data", { name: dataName ?? entity ?? "data", data, isLoading, hasError });
|
const {
|
||||||
|
data,
|
||||||
|
error: hasError,
|
||||||
|
isLoading
|
||||||
|
} = usePlasmicQueryData(endpoint.key(), async () => {
|
||||||
|
const res = await endpoint.execute();
|
||||||
|
return res.data;
|
||||||
|
});
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <LoadingComponent loading={loading} />;
|
return <LoadingComponent loading={loading} />;
|
||||||
@@ -213,7 +205,6 @@ const ModeFetch = ({
|
|||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return <EmptyComponent empty={empty} />;
|
return <EmptyComponent empty={empty} />;
|
||||||
}
|
}
|
||||||
console.log("--here1");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataProvider name={dataName ?? entity ?? "data"} data={data}>
|
<DataProvider name={dataName ?? entity ?? "data"} data={data}>
|
||||||
@@ -222,85 +213,48 @@ const ModeFetch = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModeReactQuery = (props: ModeProps) => {
|
const ModeSWR = ({ children, loading, error, dataName, entityId, empty, entity }: ModeProps) => {
|
||||||
return props.entityId ? (
|
const $q = useEntityQuery(entity, entityId);
|
||||||
<ModeReactQuerySingle {...props} />
|
|
||||||
) : (
|
|
||||||
<ModeReactQueryMultiple {...props} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ModeReactQuerySingle = ({
|
if ($q.isLoading) {
|
||||||
children,
|
|
||||||
loading,
|
|
||||||
error,
|
|
||||||
dataName,
|
|
||||||
entityId,
|
|
||||||
empty,
|
|
||||||
entity
|
|
||||||
}: ModeProps) => {
|
|
||||||
const container = useEntity(entity, entityId);
|
|
||||||
const { isLoading, isError } = container.status.fetch;
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <LoadingComponent loading={loading} />;
|
return <LoadingComponent loading={loading} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
if ($q.error) {
|
||||||
return <ErrorComponent error={error} />;
|
return <ErrorComponent error={error} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!container.data) {
|
if (!$q.data) {
|
||||||
return <EmptyComponent empty={empty} />;
|
return <EmptyComponent empty={empty} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataProvider name={dataName ?? entity ?? "data"} data={container.data}>
|
<DataProvider name={dataName ?? entity ?? "data"} data={$q.data}>
|
||||||
{children}
|
{children}
|
||||||
</DataProvider>
|
</DataProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModeReactQueryMultiple = ({
|
export function registerBkndData(
|
||||||
children,
|
loader?: { registerComponent: typeof registerComponent },
|
||||||
loading,
|
customMeta?: ComponentMeta<BkndDataProps>
|
||||||
error,
|
) {
|
||||||
empty,
|
if (loader) {
|
||||||
dataName,
|
loader.registerComponent(BkndData, customMeta ?? BkndDataMeta);
|
||||||
entity,
|
} else {
|
||||||
query
|
registerComponent(BkndData, customMeta ?? BkndDataMeta);
|
||||||
}: ModeProps) => {
|
}
|
||||||
const container = useEntities(entity, query);
|
|
||||||
const { isLoading, isError } = container.status.fetch;
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <LoadingComponent loading={loading} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
export const BkndDataMeta: ComponentMeta<BkndDataProps> = {
|
||||||
return <ErrorComponent error={error} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!container.data || container.data.length === 0) {
|
|
||||||
return <EmptyComponent empty={empty} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DataProvider name={dataName ?? entity ?? "data"} data={container.data}>
|
|
||||||
{children}
|
|
||||||
</DataProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BkndDataMeta: CodeComponentMeta<React.ComponentType<BkndEntitiesProps>> = {
|
|
||||||
name: "BKND Data",
|
name: "BKND Data",
|
||||||
section: "BKND",
|
section: "BKND",
|
||||||
importPath: import.meta.dir,
|
importPath: "@bknd/plasmic",
|
||||||
providesData: true,
|
providesData: true,
|
||||||
props: {
|
props: {
|
||||||
entity: {
|
entity: {
|
||||||
type: "choice",
|
type: "choice",
|
||||||
options: (props, ctx) => ctx.entities
|
options: (props, ctx) => ctx?.entities ?? []
|
||||||
},
|
},
|
||||||
dataName: {
|
dataName: {
|
||||||
type: "string"
|
type: "string"
|
||||||
@@ -308,6 +262,10 @@ export const BkndDataMeta: CodeComponentMeta<React.ComponentType<BkndEntitiesPro
|
|||||||
entityId: {
|
entityId: {
|
||||||
type: "number"
|
type: "number"
|
||||||
},
|
},
|
||||||
|
select: {
|
||||||
|
type: "choice",
|
||||||
|
options: (props, ctx) => ctx?.fields ?? []
|
||||||
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: "number",
|
type: "number",
|
||||||
defaultValue: 10,
|
defaultValue: 10,
|
||||||
@@ -326,13 +284,13 @@ export const BkndDataMeta: CodeComponentMeta<React.ComponentType<BkndEntitiesPro
|
|||||||
displayName: "With",
|
displayName: "With",
|
||||||
type: "choice",
|
type: "choice",
|
||||||
multiSelect: true,
|
multiSelect: true,
|
||||||
options: (props, ctx) => ctx.references
|
options: (props, ctx) => ctx?.references ?? []
|
||||||
},
|
},
|
||||||
joinRefs: {
|
joinRefs: {
|
||||||
displayName: "Join",
|
displayName: "Join",
|
||||||
type: "choice",
|
type: "choice",
|
||||||
multiSelect: true,
|
multiSelect: true,
|
||||||
options: (props, ctx) => ctx.references
|
options: (props, ctx) => ctx?.references ?? []
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
type: "code",
|
type: "code",
|
||||||
@@ -340,7 +298,7 @@ export const BkndDataMeta: CodeComponentMeta<React.ComponentType<BkndEntitiesPro
|
|||||||
},
|
},
|
||||||
sortBy: {
|
sortBy: {
|
||||||
type: "choice",
|
type: "choice",
|
||||||
options: (props, ctx) => ctx.fields
|
options: (props, ctx) => ctx?.fields ?? []
|
||||||
},
|
},
|
||||||
sortDir: {
|
sortDir: {
|
||||||
type: "choice",
|
type: "choice",
|
||||||
@@ -361,7 +319,7 @@ export const BkndDataMeta: CodeComponentMeta<React.ComponentType<BkndEntitiesPro
|
|||||||
},
|
},
|
||||||
mode: {
|
mode: {
|
||||||
type: "choice",
|
type: "choice",
|
||||||
options: ["fetch", "react-query"],
|
options: ["fetch", "swr"],
|
||||||
defaultValue: "fetch",
|
defaultValue: "fetch",
|
||||||
advanced: true
|
advanced: true
|
||||||
},
|
},
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
export { BkndData, BkndDataMeta } from "./data/BkndData";
|
export { BkndData, BkndDataMeta } from "./data/BkndData";
|
||||||
export { WouterLink, WouterLinkMeta } from "./WouterLink";
|
|
||||||
export { Image, ImageMeta } from "./Image";
|
export { Image, ImageMeta } from "./Image";
|
||||||
export { LazyRender, LazyRenderMeta } from "./LazyRender";
|
export { LazyRender, LazyRenderMeta } from "./LazyRender";
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
import { DataProvider, GlobalActionsProvider, usePlasmicCanvasContext } from "@plasmicapp/host";
|
import { DataProvider, GlobalActionsProvider, usePlasmicCanvasContext } from "@plasmicapp/host";
|
||||||
|
import registerGlobalContext, {
|
||||||
|
type GlobalContextMeta
|
||||||
|
} from "@plasmicapp/host/registerGlobalContext";
|
||||||
import type { AppConfig } from "bknd";
|
import type { AppConfig } from "bknd";
|
||||||
import { ClientProvider, useAuth, useBaseUrl } from "bknd/ui";
|
// @ts-ignore
|
||||||
|
import { ClientProvider, useApi, useAuth, useBaseUrl } from "bknd/client";
|
||||||
|
// biome-ignore lint/style/useImportType: <explanation>
|
||||||
|
import React from "react";
|
||||||
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
// Users will be able to set these props in Studio.
|
// Users will be able to set these props in Studio.
|
||||||
@@ -18,17 +24,6 @@ type BkndContextProps = {
|
|||||||
|
|
||||||
const BkndContextContext = createContext<BkndGlobalContextProps>({} as any);
|
const BkndContextContext = createContext<BkndGlobalContextProps>({} as any);
|
||||||
|
|
||||||
function getBaseUrlFromWindow() {
|
|
||||||
if (typeof window === "undefined") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const protocol = window.location.protocol;
|
|
||||||
const host = window.location.host;
|
|
||||||
|
|
||||||
return `${protocol}//${host}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo: it's an issue that we need auth, so we cannot make baseurl adjustable (maybe add an option to useAuth with a specific base url?)
|
// @todo: it's an issue that we need auth, so we cannot make baseurl adjustable (maybe add an option to useAuth with a specific base url?)
|
||||||
export const BkndContext = ({
|
export const BkndContext = ({
|
||||||
children,
|
children,
|
||||||
@@ -36,19 +31,15 @@ export const BkndContext = ({
|
|||||||
initialAuth
|
initialAuth
|
||||||
}: React.PropsWithChildren<BkndContextProps>) => {
|
}: React.PropsWithChildren<BkndContextProps>) => {
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const baseurl = useBaseUrl();
|
const baseurl = baseUrl ?? useBaseUrl();
|
||||||
|
const api = useApi({ host: baseurl });
|
||||||
|
|
||||||
const [data, setData] = useState<BkndGlobalContextProps>({
|
const [data, setData] = useState<BkndGlobalContextProps>({
|
||||||
baseUrl: baseurl,
|
baseUrl: baseurl,
|
||||||
/*baseUrl: (baseUrl && baseUrl.length > 0 ? baseUrl : getBaseUrlFromWindow()).replace(
|
|
||||||
/\/+$/,
|
|
||||||
""
|
|
||||||
),*/
|
|
||||||
auth: auth ?? initialAuth,
|
auth: auth ?? initialAuth,
|
||||||
appConfig: undefined
|
appConfig: undefined
|
||||||
});
|
});
|
||||||
const inEditor = !!usePlasmicCanvasContext();
|
const inEditor = !!usePlasmicCanvasContext();
|
||||||
console.log("context:user", data);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setData((prev) => ({ ...prev, auth: auth }));
|
setData((prev) => ({ ...prev, auth: auth }));
|
||||||
@@ -57,8 +48,10 @@ export const BkndContext = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
if (inEditor) {
|
if (inEditor) {
|
||||||
const res = await fetch(`${baseurl}/api/system/config`);
|
const result = await api.system.readConfig();
|
||||||
const result = (await res.json()) as BkndGlobalContextProps["appConfig"];
|
|
||||||
|
/*const res = await fetch(`${baseurl}/api/system/config`);
|
||||||
|
const result = (await res.json()) as BkndGlobalContextProps["appConfig"];*/
|
||||||
console.log("appconfig", result);
|
console.log("appconfig", result);
|
||||||
setData((prev) => ({ ...prev, appConfig: result }));
|
setData((prev) => ({ ...prev, appConfig: result }));
|
||||||
}
|
}
|
||||||
@@ -101,13 +94,12 @@ export const BkndContext = ({
|
|||||||
[baseUrl]
|
[baseUrl]
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("plasmic.bknd.context", data);
|
console.log("plasmic.bknd.context", { baseUrl });
|
||||||
return (
|
return (
|
||||||
<GlobalActionsProvider contextName="BkndContext" actions={actions}>
|
<GlobalActionsProvider contextName="BkndContext" actions={actions}>
|
||||||
<BkndContextContext.Provider value={data}>
|
<BkndContextContext.Provider value={data}>
|
||||||
<DataProvider name="bknd" data={data}>
|
<DataProvider name="bknd" data={data}>
|
||||||
{/*<ClientProvider baseUrl={data.baseUrl}>{children}</ClientProvider>*/}
|
<ClientProvider baseUrl={data.baseUrl}>{children}</ClientProvider>
|
||||||
{children}
|
|
||||||
</DataProvider>
|
</DataProvider>
|
||||||
</BkndContextContext.Provider>
|
</BkndContextContext.Provider>
|
||||||
</GlobalActionsProvider>
|
</GlobalActionsProvider>
|
||||||
@@ -119,8 +111,20 @@ export function usePlasmicBkndContext() {
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BkndContextMeta = {
|
export function registerBkndContext(
|
||||||
|
loader?: { registerGlobalContext: typeof registerGlobalContext },
|
||||||
|
customMeta?: GlobalContextMeta<BkndContextProps>
|
||||||
|
) {
|
||||||
|
if (loader) {
|
||||||
|
loader.registerGlobalContext(BkndContext, customMeta ?? BkndContextMeta);
|
||||||
|
} else {
|
||||||
|
registerGlobalContext(BkndContext, customMeta ?? BkndContextMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BkndContextMeta: GlobalContextMeta<BkndContextProps> = {
|
||||||
name: "BkndContext",
|
name: "BkndContext",
|
||||||
|
importPath: "@bknd/plasmic",
|
||||||
props: { baseUrl: { type: "string" }, initialAuth: { type: "object" } },
|
props: { baseUrl: { type: "string" }, initialAuth: { type: "object" } },
|
||||||
providesData: true,
|
providesData: true,
|
||||||
globalActions: {
|
globalActions: {
|
||||||
17
packages/plasmic/src/index.ts
Normal file
17
packages/plasmic/src/index.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import type { registerComponent, registerGlobalContext } from "@plasmicapp/host";
|
||||||
|
import { registerImage } from "./components/Image";
|
||||||
|
import { registerLazyRender } from "./components/LazyRender";
|
||||||
|
import { registerBkndData } from "./components/data/BkndData";
|
||||||
|
import { registerBkndContext } from "./contexts/BkndContext";
|
||||||
|
|
||||||
|
export function registerAll(loader?: {
|
||||||
|
registerComponent: typeof registerComponent;
|
||||||
|
registerGlobalContext: typeof registerGlobalContext;
|
||||||
|
}) {
|
||||||
|
registerBkndData(loader);
|
||||||
|
registerBkndContext(loader);
|
||||||
|
registerImage(loader);
|
||||||
|
registerLazyRender(loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { registerBkndData, registerBkndContext };
|
||||||
@@ -4,19 +4,23 @@
|
|||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext", "DOM"],
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": false,
|
"allowImportingTsExtensions": false,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
|
"declarationDir": "dist",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"noPropertyAccessFromIndexSignature": false
|
"noPropertyAccessFromIndexSignature": false,
|
||||||
|
"rootDir": "src",
|
||||||
|
"baseUrl": "src",
|
||||||
|
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo"
|
||||||
},
|
},
|
||||||
"include": ["index.ts", "loader.tsx", "components", "contexts"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["@bknd/app", "@bknd/core", "dist", "node_modules", "build.ts"]
|
"exclude": ["bknd", "dist", "node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user