refactor remote ui
All checks were successful
Build and Deploy Next.js + Nginx Docker Image / build-and-deploy (push) Successful in 50s
Build and Deploy Next.js + Nginx Docker Image / deploy (push) Successful in 7s

This commit is contained in:
Mohamadzadeh 2026-07-13 13:01:12 +03:30
parent 0974e960e7
commit fa06461e4b
7 changed files with 287 additions and 19247 deletions

15
dist/remote-ui.d.ts vendored
View File

@ -1,7 +1,22 @@
import type { ComponentType, ReactNode } from "react";
export type UikitRemoteDepsOptions = {
React?: unknown;
createRoot?: unknown;
ChakraProvider?: unknown;
Badge?: unknown;
theme?: unknown;
chakraProviderProps?: Record<string, unknown>;
remoteUrl?: string;
};
export declare function setupUikitRemoteDeps(options?: UikitRemoteDepsOptions): void;
export type GBadgeProps = {
children?: ReactNode;
remoteUrl?: string;
theme?: unknown;
chakraProviderProps?: Record<string, unknown>;
[key: string]: unknown;
};

112
dist/remote-ui.js vendored
View File

@ -1,45 +1,92 @@
import { jsx as a } from "react/jsx-runtime";
import { useRef as i, useEffect as l } from "react";
const f = "https://uikit.d.aiengines.ir/GBadge.js";
let n = null;
function m() {
return n || (n = import(
/* webpackIgnore: true */
/* @vite-ignore */
f
).catch((e) => {
throw n = null, e;
})), n;
import { jsx as h } from "react/jsx-runtime";
import v, { useRef as d, useEffect as R } from "react";
import P from "react-dom";
import { Badge as y, ChakraProvider as O } from "@chakra-ui/react";
var s, i = P;
if (process.env.NODE_ENV === "production")
s = i.createRoot, i.hydrateRoot;
else {
var p = i.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
s = function(e, r) {
p.usingClientEntryPoint = !0;
try {
return i.createRoot(e, r);
} finally {
p.usingClientEntryPoint = !1;
}
};
}
function p(e) {
const E = "https://uikit.d.aiengines.ir/GBadge.js", f = "__UIKIT_REMOTE_DEPS__", l = "__UIKIT_REMOTE_CONFIG__", a = /* @__PURE__ */ new Map();
function w(e = {}) {
if (typeof window > "u") return;
const r = window[f] || {}, o = window[l] || {};
window[f] = {
...r,
React: e.React || r.React || v,
createRoot: e.createRoot || r.createRoot || s,
ChakraProvider: e.ChakraProvider || r.ChakraProvider || O,
Badge: e.Badge || r.Badge || y,
theme: Object.prototype.hasOwnProperty.call(e, "theme") ? e.theme : r.theme,
chakraProviderProps: {
...r.chakraProviderProps || {},
...e.chakraProviderProps || {}
}
}, window[l] = {
...o,
...e.remoteUrl ? { GBadgeUrl: e.remoteUrl } : {}
};
}
function C() {
typeof window > "u" || window[f] || w();
}
function k() {
var e;
return typeof window > "u" ? E : ((e = window[l]) == null ? void 0 : e.GBadgeUrl) || E;
}
function B() {
const e = k();
return a.has(e) || a.set(
e,
import(
/* webpackIgnore: true */
/* @vite-ignore */
e
).catch((r) => {
throw a.delete(e), r;
})
), a.get(e);
}
function T(e) {
if (typeof e == "string" || typeof e == "number")
return e;
e != null && console.warn(
"[uikit/remote/ui] GBadge only accepts text/number children across the remote boundary."
);
}
const R = ({ children: e, ...s }) => {
const o = i(null), t = i(null), u = i(null);
return u.current = {
...s,
children: p(e)
}, l(() => {
let c = !0;
return m().then(() => {
if (!c || !o.current) return;
const r = document.createElement("uikit-g-badge");
r.componentProps = u.current, o.current.appendChild(r), t.current = r;
}).catch((r) => {
console.error("[uikit/remote/ui] Failed to load GBadge:", r);
const N = ({ children: e, remoteUrl: r, theme: o, chakraProviderProps: m, ...g }) => {
const u = d(null), t = d(null), c = d(null);
return c.current = {
...g,
children: T(e),
...o !== void 0 ? { theme: o } : {},
...m ? { chakraProviderProps: m } : {}
}, R(() => {
let _ = !0;
return C(), r && w({ remoteUrl: r }), B().then(() => {
if (!_ || !u.current) return;
const n = document.createElement("uikit-g-badge");
n.componentProps = c.current, u.current.appendChild(n), t.current = n;
}).catch((n) => {
console.error("[uikit/remote/ui] Failed to load GBadge:", n);
}), () => {
c = !1, t.current && (t.current.remove(), t.current = null);
_ = !1, t.current && (t.current.remove(), t.current = null);
};
}, []), l(() => {
t.current && (t.current.componentProps = u.current);
}), /* @__PURE__ */ a(
}, [r]), R(() => {
t.current && (t.current.componentProps = c.current);
}), /* @__PURE__ */ h(
"span",
{
ref: o,
ref: u,
style: {
display: "contents"
}
@ -47,5 +94,6 @@ const R = ({ children: e, ...s }) => {
);
};
export {
R as GBadge
N as GBadge,
w as setupUikitRemoteDeps
};

19215
dist/remote/GBadge.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,27 +1,49 @@
import React from "react";
import { createRoot } from "react-dom/client";
import { Badge, ChakraProvider } from "@chakra-ui/react";
import { Fonts, theme } from "../../core/style.jsx";
const GBadge = ({ children, ...props }) => {
return (
<Badge
fontSize="sm"
colorScheme="teal"
variant="subtle"
px={3}
py={2}
borderRadius="lg"
whiteSpace="nowrap"
textOverflow="ellipsis"
textTransform="none"
{...props}
>
{children}
</Badge>
);
const DEFAULT_PROPS = {
fontSize: "sm",
colorScheme: "teal",
variant: "subtle",
px: 3,
py: 2,
borderRadius: "lg",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
textTransform: "none",
};
function getRemoteDeps() {
const deps = window.__UIKIT_REMOTE_DEPS__;
const missing = [];
if (!deps?.React) missing.push("React");
if (!deps?.createRoot) missing.push("createRoot");
if (!deps?.ChakraProvider) missing.push("ChakraProvider");
if (!deps?.Badge) missing.push("Badge");
if (missing.length) {
throw new Error(
`[uikit-g-badge] Missing remote dependencies: ${missing.join(", ")}. ` +
"Set window.__UIKIT_REMOTE_DEPS__ before loading the remote component.",
);
}
return deps;
}
function normalizeBadgeProps(props = {}) {
const { children, theme, chakraProviderProps, ...badgeProps } = props;
return {
children,
theme,
chakraProviderProps,
badgeProps: {
...DEFAULT_PROPS,
...badgeProps,
fontFamily: badgeProps.fontFamily || "var(--uikit-font-family, inherit)",
},
};
}
class GBadgeElement extends HTMLElement {
constructor() {
super();
@ -31,6 +53,8 @@ class GBadgeElement extends HTMLElement {
}
connectedCallback() {
const { createRoot } = getRemoteDeps();
if (!this._root) {
this._root = createRoot(this);
}
@ -60,11 +84,22 @@ class GBadgeElement extends HTMLElement {
renderComponent() {
if (!this._root) return;
const { React, ChakraProvider, Badge, theme: defaultTheme, chakraProviderProps: defaultProviderProps } =
getRemoteDeps();
const { children, theme, chakraProviderProps, badgeProps } = normalizeBadgeProps(this._props);
this._root.render(
<ChakraProvider theme={theme}>
<Fonts />
<GBadge {...this._props} />
</ChakraProvider>,
React.createElement(
ChakraProvider,
{
theme: theme || defaultTheme,
resetCSS: false,
...(defaultProviderProps || {}),
...(chakraProviderProps || {}),
},
React.createElement(Badge, badgeProps, children),
),
);
}
}

View File

@ -1,7 +1,22 @@
import type { ComponentType, ReactNode } from "react";
export type UikitRemoteDepsOptions = {
React?: unknown;
createRoot?: unknown;
ChakraProvider?: unknown;
Badge?: unknown;
theme?: unknown;
chakraProviderProps?: Record<string, unknown>;
remoteUrl?: string;
};
export declare function setupUikitRemoteDeps(options?: UikitRemoteDepsOptions): void;
export type GBadgeProps = {
children?: ReactNode;
remoteUrl?: string;
theme?: unknown;
chakraProviderProps?: Record<string, unknown>;
[key: string]: unknown;
};

View File

@ -1,22 +1,72 @@
import { useEffect, useRef } from "react";
import React, { useEffect, useRef } from "react";
import { createRoot } from "react-dom/client";
import { Badge, ChakraProvider } from "@chakra-ui/react";
const REMOTE_URL = "https://uikit.d.aiengines.ir/GBadge.js";
const DEFAULT_REMOTE_URL = "https://uikit.d.aiengines.ir/GBadge.js";
const REMOTE_DEPS_KEY = "__UIKIT_REMOTE_DEPS__";
const REMOTE_CONFIG_KEY = "__UIKIT_REMOTE_CONFIG__";
let remotePromise = null;
const remotePromises = new Map();
export function setupUikitRemoteDeps(options = {}) {
if (typeof window === "undefined") return;
const previousDeps = window[REMOTE_DEPS_KEY] || {};
const previousConfig = window[REMOTE_CONFIG_KEY] || {};
window[REMOTE_DEPS_KEY] = {
...previousDeps,
React: options.React || previousDeps.React || React,
createRoot: options.createRoot || previousDeps.createRoot || createRoot,
ChakraProvider: options.ChakraProvider || previousDeps.ChakraProvider || ChakraProvider,
Badge: options.Badge || previousDeps.Badge || Badge,
theme: Object.prototype.hasOwnProperty.call(options, "theme")
? options.theme
: previousDeps.theme,
chakraProviderProps: {
...(previousDeps.chakraProviderProps || {}),
...(options.chakraProviderProps || {}),
},
};
window[REMOTE_CONFIG_KEY] = {
...previousConfig,
...(options.remoteUrl ? { GBadgeUrl: options.remoteUrl } : {}),
};
}
function ensureRemoteDeps() {
if (typeof window === "undefined") return;
if (!window[REMOTE_DEPS_KEY]) {
setupUikitRemoteDeps();
}
}
function getRemoteUrl() {
if (typeof window === "undefined") return DEFAULT_REMOTE_URL;
return window[REMOTE_CONFIG_KEY]?.GBadgeUrl || DEFAULT_REMOTE_URL;
}
function loadRemote() {
if (!remotePromise) {
remotePromise = import(
/* webpackIgnore: true */
/* @vite-ignore */
REMOTE_URL
).catch((error) => {
remotePromise = null;
throw error;
});
const remoteUrl = getRemoteUrl();
if (!remotePromises.has(remoteUrl)) {
remotePromises.set(
remoteUrl,
import(
/* webpackIgnore: true */
/* @vite-ignore */
remoteUrl
).catch((error) => {
remotePromises.delete(remoteUrl);
throw error;
}),
);
}
return remotePromise;
return remotePromises.get(remoteUrl);
}
function normalizeChildren(children) {
@ -35,7 +85,7 @@ function normalizeChildren(children) {
return undefined;
}
export const GBadge = ({ children, ...props }) => {
export const GBadge = ({ children, remoteUrl, theme, chakraProviderProps, ...props }) => {
const containerRef = useRef(null);
const elementRef = useRef(null);
const latestPropsRef = useRef(null);
@ -43,11 +93,19 @@ export const GBadge = ({ children, ...props }) => {
latestPropsRef.current = {
...props,
children: normalizeChildren(children),
...(theme !== undefined ? { theme } : {}),
...(chakraProviderProps ? { chakraProviderProps } : {}),
};
useEffect(() => {
let active = true;
ensureRemoteDeps();
if (remoteUrl) {
setupUikitRemoteDeps({ remoteUrl });
}
loadRemote()
.then(() => {
if (!active) return;
@ -73,7 +131,7 @@ export const GBadge = ({ children, ...props }) => {
elementRef.current = null;
}
};
}, []);
}, [remoteUrl]);
useEffect(() => {
if (!elementRef.current) return;

View File

@ -48,6 +48,8 @@ export default defineConfig(({ mode }) => {
},
rollupOptions: {
treeshake: true,
output: {
entryFileNames: "remote/GBadge.js",