diff --git a/packages/duoyun-ui/docs/en/01-guide/60-integrate.md b/packages/duoyun-ui/docs/en/01-guide/60-integrate.md index 6b6648fc..0dd09ba6 100644 --- a/packages/duoyun-ui/docs/en/01-guide/60-integrate.md +++ b/packages/duoyun-ui/docs/en/01-guide/60-integrate.md @@ -6,12 +6,81 @@ However, there is no [type hint](https://code.visualstudio.com/docs/editor/intel ## React > [!NOTE] -> Only the experimental version of React supports custom elements. Use `npm install react@experimental react-dom@experimental` to install the experimental version of React. +> Only the React 19 supports custom elements. Use `npm install react@canary react-dom@canary` to install the React 19. Use DuoyunUI like any other React component library: +### Use React Component in `` + +`` only supports rendering `TemplateResult`: + +```ts +const routes = { + about: { + pattern: '/about', + title: `About`, + getContent(_, ele) { + return html``; + }, + }, +} satisfies RoutesObject; +``` + +To render the React component, need to manually mount it onto the ``: + +```ts +function renderReactNode(ele: any, node: ReactNode) { + ele.react?.unmount(); + ele.react = createRoot(ele); + ele.react.render(node); +} + +const routes = { + about: { + pattern: '/about', + title: `About`, + getContent(_, ele) { + renderReactNode(ele, ); + }, + }, +} satisfies RoutesObject; +``` + +### Using the React component as Property + +Some elements support custom rendering content, such as the `header` of ``: + +```ts +function Page() { + return No.`}>; +} +``` + +If want to render the React component, need to first mount it to the `HTMLElement`, which can be achieved through custom Hooks: + +```tsx +function useReactNode(node: ReactNode) { + const ref = useRef<{ root: Root; container: HTMLElement }>(); + useEffect(() => () => ref.current?.root.unmount(), []); + if (ref.current) { + ref.current.root.render(node); + return ref.current.container; + } + const container = document.createElement('div'); + container.style.display = 'contents'; + const root = createRoot(container); + ref.current = { root, container }; + root.render(node); + return container; +} + +function Page() { + return No)}>; +} +``` + ## Vue DuoyunUI also exports Vue components, which are used the same as React. The only difference is that the path is changed from `react` to `vue`, @@ -33,7 +102,7 @@ In the Vue project, it also supports directly writing custom elements, but [dist DuoyunUI does not re-export as a Svelte component, and you can use the custom element directly: - + > [!NOTE] > Use the `Sveltekit`, please make sure the `Svelte` is installed as a `dependencies` instead of `DevDependenCies`, otherwise the type cannot be import successfully; diff --git a/packages/duoyun-ui/docs/zh/01-guide/60-integrate.md b/packages/duoyun-ui/docs/zh/01-guide/60-integrate.md index 53f2c7d5..33a7d46e 100644 --- a/packages/duoyun-ui/docs/zh/01-guide/60-integrate.md +++ b/packages/duoyun-ui/docs/zh/01-guide/60-integrate.md @@ -6,12 +6,81 @@ ## React > [!NOTE] -> React 的实验版才支持自定义元素,使用 `npm install react@experimental react-dom@experimental` 安装 React 实验版。 +> React 19 才支持自定义元素,当前使用 `npm install react@canary react-dom@canary` 安装 React 19。 跟使用其他 React 组件库一样使用 DuoyunUI: +### 在 `` 中使用 React 组件 + +`` 只支持渲染 `TemplateResult`: + +```ts +const routes = { + about: { + pattern: '/about', + title: `About`, + getContent(_, ele) { + return html``; + }, + }, +} satisfies RoutesObject; +``` + +要渲染 React 组件需要手动挂载到 `` 上: + +```ts +function renderReactNode(ele: any, node: ReactNode) { + ele.react?.unmount(); + ele.react = createRoot(ele); + ele.react.render(node); +} + +const routes = { + about: { + pattern: '/about', + title: `About`, + getContent(_, ele) { + renderReactNode(ele, ); + }, + }, +} satisfies RoutesObject; +``` + +### 在 Property 上使用 React 组件 + +一些元素支持自定义渲染内容,例如 `` 的 `header`: + +```ts +function Page() { + return No.`}>; +} +``` + +如果要渲染 React 组件,则需要先渲染到 `HTMLElement` 上,可以通过自定义 Hooks 实现: + +```tsx +function useReactNode(node: ReactNode) { + const ref = useRef<{ root: Root; container: HTMLElement }>(); + useEffect(() => () => ref.current?.root.unmount(), []); + if (ref.current) { + ref.current.root.render(node); + return ref.current.container; + } + const container = document.createElement('div'); + container.style.display = 'contents'; + const root = createRoot(container); + ref.current = { root, container }; + root.render(node); + return container; +} + +function Page() { + return No)}>; +} +``` + ## Vue DuoyunUI 也导出了 Vue 组件,使用和 React 一样,唯一的区别是路径将 `react` 改成 `vue`, @@ -33,7 +102,7 @@ DuoyunUI 也导出了 Vue 组件,使用和 React 一样,唯一的区别是 DuoyunUI 没有重导出为 Svelte 组件,直接使用自定义元素即可: - + > [!NOTE] > 使用 `SvelteKit` 请确保 `svelte` 安装成 `dependencies` 而非 `devDependencies`,否则类型不能成功导入; diff --git a/packages/duoyun-ui/src/elements/card.ts b/packages/duoyun-ui/src/elements/card.ts index 8fe869eb..1293d5b6 100644 --- a/packages/duoyun-ui/src/elements/card.ts +++ b/packages/duoyun-ui/src/elements/card.ts @@ -71,7 +71,8 @@ const style = createCSSSheet(css` .actions:where(:hover, [data-active], :state(active)) { background-color: ${theme.hoverBackgroundColor}; } - slot[name='body']::slotted(*) { + slot[name='body']::slotted(*), + slot:not([name])::slotted(*) { hyphens: auto; margin-block-end: 0em !important; } diff --git a/packages/duoyun-ui/src/elements/paragraph.ts b/packages/duoyun-ui/src/elements/paragraph.ts index a46a4c78..81bf0534 100644 --- a/packages/duoyun-ui/src/elements/paragraph.ts +++ b/packages/duoyun-ui/src/elements/paragraph.ts @@ -13,38 +13,31 @@ const style = createCSSSheet(css` :where(dy-paragraph):where(:lang(zh), :lang(ja), :lang(kr)) { line-height: 1.7; } - :where(gem-link, dy-link):where(:not([hidden])) { - display: inline-block; - color: ${theme.primaryColor}; - text-decoration: underline; - } - :where(gem-link, dy-link):where(:lang(zh), :lang(ja), :lang(kr)) { - text-underline-offset: 0.125em; - } - ul, - ol { - margin-block: 0 1em; - padding: 0; - list-style-position: inside; - } - li { - padding-inline-start: 0.5em; - } - code, - kbd { - font-family: ${theme.codeFont}; - margin-inline: 0.2em; - padding: 0.15em 0.4em 0.1em; - font-size: 0.9em; - border: 1px solid ${theme.borderColor}; - border-radius: ${theme.smallRound}; - } - code { - background: ${theme.hoverBackgroundColor}; - } - kbd { - background: ${theme.lightBackgroundColor}; - border-bottom-width: 2px; + :where(dy-paragraph) { + :where(gem-link, dy-link):where(:not([hidden])) { + display: inline-block; + color: ${theme.primaryColor}; + text-decoration: underline; + } + :where(gem-link, dy-link):where(:lang(zh), :lang(ja), :lang(kr)) { + text-underline-offset: 0.125em; + } + code, + kbd { + font-family: ${theme.codeFont}; + margin-inline: 0.2em; + padding: 0.15em 0.4em 0.1em; + font-size: 0.9em; + border: 1px solid ${theme.borderColor}; + border-radius: ${theme.smallRound}; + } + code { + background: ${theme.hoverBackgroundColor}; + } + kbd { + background: ${theme.lightBackgroundColor}; + border-bottom-width: 2px; + } } `); diff --git a/packages/gem-examples/src/console/index.ts b/packages/gem-examples/src/console/index.ts index 07ec9574..f94cc9f6 100644 --- a/packages/gem-examples/src/console/index.ts +++ b/packages/gem-examples/src/console/index.ts @@ -7,6 +7,8 @@ import { type ContextMenus, type Routes, type UserInfo, type NavItems } from 'du import 'duoyun-ui/patterns/console'; import 'duoyun-ui/elements/badge'; import 'duoyun-ui/elements/code-block'; +import 'duoyun-ui/elements/paragraph'; +import 'duoyun-ui/elements/card'; import 'duoyun-ui/helper/error'; @@ -57,7 +59,13 @@ const routes = { about: { pattern: '/about', title: `About`, - content: html`About`, + content: html` + + + Elit aute excepteur dolore occaecat esse F aliqua mollit duis culpa aliqua adipisicing culpa. + + + `, }, } satisfies Routes;