Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Dec 11, 2023
1 parent 993c083 commit 3614b14
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 39 deletions.
64 changes: 64 additions & 0 deletions packages/duoyun-ui/docs/en/01-guide/06-integrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Used in projects like React

[Most front-end frameworks/libraries](https://custom-elements-everywhere.com/) can seamlessly use custom elements, such as assigning Attribute/Property, registering events,
However, there is no [type hint](https://code.visualstudio.com/docs/editor/intellisense) when using custom elements directly, and ESLint is not supported, so DuoyunUI re-exported it and perfectly adapted to React/Vue/Svelte.

## 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.
Use DuoyunUI like any other React component library:

<gbp-raw range="3-19,31-" src="https://raw.githubusercontent.com/mantou132/nextjs-learn/main/pages/ce-test.tsx"></gbp-raw>

## 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`,
in addition, custom elements need to be specified in the Vue configuration file:

```js
{
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('dy-');
}
}
```

In the Vue project, it also supports directly writing custom elements, but [distinguish](../02-elements/card#api) is it Attribute or Property:

<gbp-raw codelang="html" range="34-45" src="https://raw.githubusercontent.com/mantou132/nuxtjs-learn/main/pages/test.vue"></gbp-raw>

## Svelte

DuoyunUI does not re-export as a Svelte component, and you can use the custom element directly:

<gbp-raw codelang="html" range="2-9,46-57" src="https://raw.githubusercontent.com/mantou132/sveltekit-learn/main/src/routes/ce-test/+page.svelte"></gbp-raw>

> [!NOTE]
> Use the `Sveltekit`, please make sure the `Svelte` is installed as a `dependencies` instead of `DevDependenCies`, otherwise the type cannot be import successfully;
> if you compile the error of "Unexpected token 'export'", please add the following code to `vite.config.ts`:
>
> ```js
> {
> ssr: {
> noExternal: ['@mantou/gem', 'duoyun-ui'];
> }
> }
> ```
## SSR
DuoyunUI does not support SSR, to be precise, Next/Nuxt/Svelte do not support SSR for custom elements. The ShadowDOM of custom elements is generated at runtime. To ensure proper server-side rendering, import `@mantou/gem/helper/ssr-shim` at the entry point of your front-end code.
- Next.js: `pages/_app.tsx`
- Nuxt.js: `app.config.ts`
- SvelteKit: `src/hooks.server.ts`
If you want to use DuoyunUI routing, you can use `<dy-light-route>`. To avoid layout issues on the initial page load, add the following global styles:
```css
:not(:defined) {
display: none;
}
```
65 changes: 65 additions & 0 deletions packages/duoyun-ui/docs/zh/01-guide/06-integrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 在 React 等项目中使用

[大多数前端框架/库](https://custom-elements-everywhere.com/)都能无缝使用自定义元素,比如分配 Attribute/Property,注册事件,
但是直接使用自定义元素没有[类型提示](https://code.visualstudio.com/docs/editor/intellisense)、不支持 ESLint,所以 DuoyunUI 进行了重导出,完美适配了 React/Vue/Svelte。

## React

> [!NOTE]
> React 的实验版才支持自定义元素,使用 `npm install react@experimental react-dom@experimental` 安装 React 实验版。
跟使用其他 React 组件库一样使用 DuoyunUI:

<gbp-raw range="3-19,31-" src="https://raw.githubusercontent.com/mantou132/nextjs-learn/main/pages/ce-test.tsx"></gbp-raw>

## Vue

DuoyunUI 也导出了 Vue 组件,使用和 React 一样,唯一的区别是路径将 `react` 改成 `vue`
另外需要在 Vue 配置文件中指定自定义元素:

```js
{
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('dy-');
}
}
```

在 Vue 中也支持直接写自定义元素,但是要[区分](../02-elements/card#api)是 Attribute 还是 Property:

<gbp-raw codelang="html" range="34-45" src="https://raw.githubusercontent.com/mantou132/nuxtjs-learn/main/pages/test.vue"></gbp-raw>

## Svelte

DuoyunUI 没有重导出为 Svelte 组件,直接使用自定义元素即可:

<gbp-raw codelang="html" range="2-9,46-57" src="https://raw.githubusercontent.com/mantou132/sveltekit-learn/main/src/routes/ce-test/+page.svelte"></gbp-raw>

> [!NOTE]
> 使用 `SvelteKit` 请确保 `svelte` 安装成 `dependencies` 而非 `devDependencies`,否则类型不能成功导入;
> 如果编译出现“Unexpected token 'export'”的错误请在 `vite.config.ts` 中添加下面代码:
>
> ```js
> {
> ssr: {
> noExternal: ['@mantou/gem', 'duoyun-ui'];
> }
> }
> ```
## SSR
DuoyunUI 不支持 SSR,确切的说是 Next/Nuxt/Svelte 不支持自定义元素 SSR,自定义元素的 ShadowDOM 是运行时生成,
为了能在服务端正确运行,在前端代码的入口位置导入 `@mantou/gem/helper/ssr-shim`
- Next.js: `pages/_app.tsx`
- Nuxt.js: `app.config.ts`
- SvelteKit: `src/hooks.server.ts`
如果要使用 DuoyunUI 的路由,可以使用 `<dy-light-route>`。为了避免首屏排版错误添加下面全局样式:
```css
:not(:defined) {
display: none;
}
```
2 changes: 1 addition & 1 deletion packages/duoyun-ui/gem-book.cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"icon": "../../logo.png",
"i18n": true,
"sourceBranch": "docs",
"plugin": ["media", "api", "sandpack"],
"plugin": ["media", "api", "sandpack", "raw"],
"debug": true
}
2 changes: 1 addition & 1 deletion packages/duoyun-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "duoyun-ui",
"version": "1.0.1",
"version": "1.0.2",
"description": "WebComponts UI",
"exports": {
"./elements/*": "./elements/*.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/duoyun-ui/src/elements/space.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const style = createCSSSheet(css`
@customElement('dy-space')
@adoptedStyle(style)
export class DuoyunSpaceElement extends GemElement {
@attribute size: 'nomal' | 'small' | 'large';
@attribute size: 'normal' | 'small' | 'large';

constructor() {
super({ isLight: true });
Expand Down
13 changes: 4 additions & 9 deletions packages/gem-book/src/element/elements/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,7 @@ const style = createCSSSheet(css`
opacity: 1;
}
code {
font-family:
Source Code Pro,
ui-monospace,
SFMono-Regular,
Menlo,
Monaco,
Consolas,
Liberation Mono,
Courier New,
font-family: Source Code Pro, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New,
monospace;
padding: 0.15em 0.4em 0.1em;
font-size: 0.9em;
Expand Down Expand Up @@ -244,6 +236,9 @@ export class Main extends GemElement {
.link:hover {
border-color: currentColor;
}
.link svg:last-child {
margin-inline-end: 0.2em;
}
`;

#hashChangeHandle = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/gem-book/src/element/elements/pre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ export class Pre extends GemElement {
? this.#getRanges(this.range).map(([start, end]) => {
let result = '';
for (let i = start - 1; i < (end || lines.length); i++) {
result += lines[i] + '\n';
result += (lines[i] || '') + '\n';
}
return result;
})
Expand Down
91 changes: 71 additions & 20 deletions packages/gem-book/src/plugins/raw.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,63 @@
import type { GemBookElement } from '../element';

type State = {
content: string;
error?: any;
};

customElements.whenDefined('gem-book').then(() => {
const { GemBookPluginElement } = customElements.get('gem-book') as typeof GemBookElement;
const { config, Gem, devMode } = GemBookPluginElement;
const { attribute, customElement } = Gem;
const { config, Gem, devMode, theme } = GemBookPluginElement;
const { attribute, customElement, html, createCSSSheet, css, adoptedStyle } = Gem;

const style = createCSSSheet(css`
:host {
display: contents;
}
.loading,
.error {
display: flex;
place-items: center;
place-content: center;
min-height: 20em;
background: rgba(${theme.textColorRGB}, 0.05);
}
.loading {
opacity: 0.5;
}
.error {
color: ${theme.cautionColor};
}
@keyframes display {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
gem-book-pre {
animation: display 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
`);

@customElement('gbp-raw')
class _GbpRawElement extends GemBookPluginElement {
@adoptedStyle(style)
class _GbpRawElement extends GemBookPluginElement<State> {
@attribute src: string;
@attribute codelang: string;
@attribute range: string;
@attribute highlight: string;

mounted() {
this.#renderContent();
}
state: State = {
content: '',
};

updated() {
this.#renderContent();
get #codelang() {
return this.codelang || this.src.split('.').pop() || '';
}

#getRemoteUrl() {
get #url() {
if (!this.src) return '';

let url = this.src;
Expand All @@ -35,19 +72,33 @@ customElements.whenDefined('gem-book').then(() => {
return url;
}

async #renderContent() {
if (!this.src) return;
this.innerHTML = 'Loading...';
mounted() {
this.effect(
async () => {
if (!this.src) return;
this.setState({ error: false });
try {
const resp = await fetch(this.#url);
if (resp.status === 404) throw new Error(resp.statusText || 'Not Found');
this.setState({ content: await resp.text() });
} catch (error) {
this.setState({ error });
}
},
() => [this.src],
);
}

const text = await (await fetch(this.#getRemoteUrl())).text();
const div = document.createElement('div');
div.textContent = text;
const content = div.innerHTML;
render() {
const { content, error } = this.state;
if (error) return html`<div class="error">${error}</div>`;
if (!content) return html`<div class="loading">Loading...</div>`;

const extension = this.src.split('.').pop() || '';
this.innerHTML = `<gem-book-pre codelang="${this.codelang || extension}" highlight="${this.highlight}" range="${
this.range
}">${content}</gem-book-pre>`;
return html`
<gem-book-pre codelang=${this.#codelang} highlight=${this.highlight} range=${this.range}
>${content}</gem-book-pre
>
`;
}
}
});
11 changes: 7 additions & 4 deletions packages/gem-devtools/src/elements/section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Item, Path, BuildIn, panelStore } from '../store';
import { theme } from '../theme';
import { inspectValue } from '../scripts/inspect-value';
import { execution } from '../common';
import { setValue } from '../scripts/set-value';
import { setGemPropValue } from '../scripts/set-value';

const maybeBuildInPrefix = '[[Gem?]] ';
const buildInPrefix = '[[Gem]] ';
Expand Down Expand Up @@ -214,13 +214,16 @@ export class Section extends GemElement {
? [kebabToCamelCase(item.name)]
: [item.name];
const onInput = (evt: Event) => {
execution(setValue, [path, (evt.target as HTMLInputElement).value]);
execution(setGemPropValue, [path, (evt.target as HTMLInputElement).value]);
};
const onInputNumber = (evt: Event) => {
execution(setValue, [path, Number((evt.target as HTMLInputElement).value)]);
execution(setGemPropValue, [path, Number((evt.target as HTMLInputElement).value) || 0]);
};
const toggleValue = (evt: MouseEvent) => {
execution(setValue, [path, (evt.target as HTMLInputElement).textContent?.trim() === 'true' ? false : true]);
execution(setGemPropValue, [
path,
(evt.target as HTMLInputElement).textContent?.trim() === 'true' ? false : true,
]);
};
switch (item.type) {
case 'string':
Expand Down
6 changes: 5 additions & 1 deletion packages/gem-devtools/src/scripts/set-value.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { Path } from '../store';

export const setValue = (path: Path, value: string | number | boolean | null) => {
declare let $0: any;

export const setGemPropValue = (path: Path, value: string | number | boolean | null) => {
const key = String(path.pop());

const obj = window.__GEM_DEVTOOLS__PRELOAD__.readProp(path);

obj[key] = value;

$0.update();
};
2 changes: 1 addition & 1 deletion packages/gem-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"dependencies": {
"@mantou/gem": "^1.7.1",
"duoyun-ui": "^1.0.1"
"duoyun-ui": "^1.0.2"
},
"devDependencies": {
"@gemjs/config": "^1.6.11",
Expand Down

0 comments on commit 3614b14

Please sign in to comment.