📦 了解更多
diff --git a/docs/docs/api/atom-ctx/use-state-x.md b/docs/docs/api/atom-ctx/use-state-x.md
index a4d2d2d2..e718d76a 100644
--- a/docs/docs/api/atom-ctx/use-state-x.md
+++ b/docs/docs/api/atom-ctx/use-state-x.md
@@ -12,5 +12,5 @@ order: 1
---
:::info
-更多用法查阅[Hooks/useAtomX](/api/hooks/use-atom-x)
+更多用法查阅[Hooks/useAtomX](/api/hooks/use-atomx)
:::
diff --git a/docs/docs/api/base/index.md b/docs/docs/api/base/index.md
index 787cc3fd..239fe5f6 100644
--- a/docs/docs/api/base/index.md
+++ b/docs/docs/api/base/index.md
@@ -8,9 +8,9 @@ nav:
包含以下基础函数
- [atom](/api/base/atom) 创建`atom`对象,返回元组
-- [atomx](/api/base/atom-x) 创建`atom`对象,返回字典
+- [atomx](/api/base/atomx) 创建`atom`对象,返回字典
- [share](/api/base/share) 创建字典型`atom`对象,返回元组
-- [sharex](/api/base/share-x) 创建字典型`atom`对象,返回字典
+- [sharex](/api/base/sharex) 创建字典型`atom`对象,返回字典
- [signal](/api/base/signal) 创建`signal`响应区域,实现dom粒度更新
- [block](/api/base/block) 创建`block`块响应区域,实现块粒度更新
- [dynamicBlock](/api/base/dynamic-block) 组件渲染过程中创建动态`block`块响应区域,实现块粒度更新
diff --git a/docs/docs/api/hooks/index.md b/docs/docs/api/hooks/index.md
index 4b7aa45f..12aeed2c 100644
--- a/docs/docs/api/hooks/index.md
+++ b/docs/docs/api/hooks/index.md
@@ -7,7 +7,7 @@ order: 0
包含以下常用钩子
- [useAtom](/api/hooks/use-atom) 使用`atom`对象,返回元组
-- [useAtomX](/api/hooks/use-atom-x) 使用`atom`对象,返回字典
+- [useAtomX](/api/hooks/use-atomx) 使用`atom`对象,返回字典
- [useReactive](/api/hooks/use-reactive) 使用`reactive`对象,返回元组
- [useReactiveX](/api/hooks/use-reactive-x) 使用`reactive`对象,返回字典
- [useDerived](/api/hooks/use-derived) 使用全量派生结果
diff --git a/docs/docs/api/index.md b/docs/docs/api/index.md
index 2d734dc3..dc32073a 100644
--- a/docs/docs/api/index.md
+++ b/docs/docs/api/index.md
@@ -9,9 +9,9 @@ nav:
- [基础](/api/base/atom)
> - [atom](/api/base/atom) 创建`atom`对象,返回元组
-> - [atomx](/api/base/atom-x) 创建`atom`对象,返回字典
+> - [atomx](/api/base/atomx) 创建`atom`对象,返回字典
> - [share](/api/base/share) 创建字典型`atom`对象,返回元组
-> - [sharex](/api/base/share-x) 创建字典型`atom`对象,返回字典
+> - [sharex](/api/base/sharex) 创建字典型`atom`对象,返回字典
> - [signal](/api/base/signal) 创建`signal`响应区域,实现dom粒度更新
> - [block](/api/base/block) 创建`block`块响应区域,实现块粒度更新
> - [dynamicBlock](/api/base/dynamic-block) 组件渲染过程中创建动态`block`块响应区域,实现块粒度更新
@@ -51,7 +51,7 @@ ctx.aciton()(/** action 函数定义 */)
- [Hooks](/api/hooks/)
> - [useAtom](/api/hooks/use-atom) 使用`atom`对象,返回元组
-> - [useAtomX](/api/hooks/use-atom-x) 使用`atom`对象,返回字典
+> - [useAtomX](/api/hooks/use-atomx) 使用`atom`对象,返回字典
> - [useReactive](/api/hooks/use-reactive) 使用`reactive`对象,返回元组
> - [useReactiveX](/api/hooks/use-reactive-x) 使用`reactive`对象,返回字典
> - [useDerived](/api/hooks/use-derived) 使用全量派生结果
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 44662f0b..683b2da7 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -9,19 +9,11 @@ hero:
link: /playground
- text: Github
link: https://github.com/heluxjs/helux
-features:
- - title: atom
- description: atom 支持任意数据结构,对非原始类型数据内置依赖收集功能, 意味着 atom 不用拆分的很细,天然对 DDD 领域驱动设计友好
- - title: signal
- description: 内置 signal 响应机制,可实现 0 hook 编码 + dom 粒度的更新
- - title: 依赖追踪
- description: 基于最快的不可变 js 库 limu 做到运行时对视图渲染实时收集数据依赖,提供超强渲染性能
- - title: reactive
- description: 提供全局响应式对象,数据变更直接驱动关联ui渲染(默认在下一个事件循环微任务开始前提交,支持人工提交变更数据)
- - title: modular
- description: 支持对状态模块化抽象,并内置 actions、derive、watch、loading 等特性,轻松驾驭大型前端应用架构
- - title: middleware&plugin
- description: 内置中间件和插件系统,无缝衔接redux生态优秀组件
+# 此处已转移到 ContactAuthor 里的 Features 渲染
+# features:
+ # - title: atom
+ # description: atom 支持任意数据结构,对非原始类型数据内置依赖收集功能, 意味着 atom 不用拆分的很细,天然对 DDD 领域驱动设计友好
+ # ...
---
diff --git a/docs/docs/playground/demos/Playground/ApiMenus.tsx b/docs/docs/playground/demos/Playground/ApiMenus.tsx
index 99a524bc..067134b2 100644
--- a/docs/docs/playground/demos/Playground/ApiMenus.tsx
+++ b/docs/docs/playground/demos/Playground/ApiMenus.tsx
@@ -6,6 +6,7 @@ import * as codes from './codes';
const c = '#e8ae56';
const orderedKeys = [
+ 'quickStart',
'atom',
'derive',
'watch',
diff --git a/docs/docs/playground/demos/Playground/Console.tsx b/docs/docs/playground/demos/Playground/Console.tsx
index 1ad371a3..a6dc9698 100644
--- a/docs/docs/playground/demos/Playground/Console.tsx
+++ b/docs/docs/playground/demos/Playground/Console.tsx
@@ -1,4 +1,5 @@
import React from 'react'
+import * as helux from 'helux'
import { Hook, Console, Decode } from 'console-feed';
import './index.less';
@@ -11,7 +12,7 @@ class HeluxConsole extends React.Component {
Hook(window.console, (log) => {
this.setState(({ logs }) => ({ logs: [...logs, Decode(log)] }))
});
- console.log('Welcome to helux playground ^_^');
+ console.log(`Welcome to helux playground (helux ver: ${helux.cst.VER})^_^`);
}
render() {
diff --git a/docs/docs/playground/demos/Playground/TopBar.tsx b/docs/docs/playground/demos/Playground/TopBar.tsx
index 3306a775..4b70a661 100644
--- a/docs/docs/playground/demos/Playground/TopBar.tsx
+++ b/docs/docs/playground/demos/Playground/TopBar.tsx
@@ -32,10 +32,7 @@ function renderItems(name: string, subName: string) {
));
}
-
-
export default React.memo(({ onClick, name, subName }: any) => {
-
const handleClick = e => {
const subName = e.target.dataset.name;
if (subName) {
diff --git a/docs/docs/playground/demos/Playground/codes/atom.ts b/docs/docs/playground/demos/Playground/codes/atom.ts
index 7b597e40..cd14b78a 100644
--- a/docs/docs/playground/demos/Playground/codes/atom.ts
+++ b/docs/docs/playground/demos/Playground/codes/atom.ts
@@ -1,5 +1,4 @@
-
const primitive = `
const [ num, setNum ] = atom(1);
diff --git a/docs/docs/playground/demos/Playground/codes/index.ts b/docs/docs/playground/demos/Playground/codes/index.ts
index 1c16b629..c6648034 100644
--- a/docs/docs/playground/demos/Playground/codes/index.ts
+++ b/docs/docs/playground/demos/Playground/codes/index.ts
@@ -1,3 +1,4 @@
+export { default as quickStart } from './quickStart';
export { default as atom } from './atom';
export { default as derive } from './derive';
export { default as watch } from './watch';
diff --git a/docs/docs/playground/demos/Playground/codes/quickStart.ts b/docs/docs/playground/demos/Playground/codes/quickStart.ts
new file mode 100644
index 00000000..6454b0f0
--- /dev/null
+++ b/docs/docs/playground/demos/Playground/codes/quickStart.ts
@@ -0,0 +1,171 @@
+const HelloHelux = `
+const [str, setStr, ctx] = atom('hello helux'); // define atom, str is boxed with {val:T} strcture
+const reversedStr = derive(() => str.val.split('').reverse().join('')); // define derive
+
+function HelloHelux(){
+ const [strVal] = useAtom(str); // strVal is auto unboxed
+ const [reversedStrVal] = useDerived(reversedStr);
+ return (
+ setStr(e.target.value)} />
+
+
reversed: {reversedStrVal}
+
);
+}
+
+render();
+`;
+
+const HelloHeluxDict = `
+// no { val: T } wrapped with share api, so using share is better than atom at this situation
+const [dict, setDict, ctx] = share({str: 'hello helux'}); // define share
+const reversedStr = derive(() => dict.str.split('').reverse().join('')); // define derive
+
+function HelloHeluxDict(){
+ const [dictState] = useAtom(dict);
+ const [reversedStrVal] = useDerived(reversedStr);
+ return (
+ setDict(draft=>draft.str=e.target.value)} />
+
+
reversed: {reversedStrVal}
+ );
+}
+
+render();
+`;
+
+const DataBindWidthHook = `
+const [num, setNum] = atom(1);
+const numDouble = derive(() => num.val * 2); // derive num
+const change = () => { // change num
+ setNum(prev => prev + 1);
+};
+
+function DataBindWidthHook() {
+ const [numVal] = useAtom(num);
+ const [numDoubleVal] = useDerived(numDouble);
+
+ return (
+
+
numVal {numVal}
+ numDoubleVal {numDoubleVal}
+
+
+ );
+}
+
+render(<>>);
+`;
+
+const DataBindWidthNoHook = `
+const [num, setNum] = atom(1);
+const numDouble = derive(() => num.val * 2); // derive num
+const change = () => { // change num
+ setNum(prev => prev + 1);
+};
+// pass primitive data to ui with $
+function DataBindWidthNoHook() { // DOM granularity update
+ return (
+
+
numVal {$(num)}
+ numDoubleVal {$(numDouble)}
+
+
+ );
+}
+
+render(<>dom粒度更新
>);
+`;
+
+const DictDataBindWidthHook = `
+// const [dict, setState] = atom({ a: 1, b: { b1: 1, b2: { b2_1: 'cool' } } });
+// const numDouble = derive(() => dict.val.a + 100 ); // dict.val.a
+
+// no { val: T } wrapped with share api, so using share is better than atom at this situation
+const [dict, setState] = share({ a: 1, b: { b1: 1, b2: { b2_1: 'cool' } } });
+const aPlus = derive(() => dict.a + 100 ); // dict.a
+
+const change = () => { // change num
+ setState(prev => prev.a += 100 );
+};
+
+function DictDataBindWidthHook() {
+ const [dictState] = useAtom(dict);
+ const [aPlusVal] = useDerived(aPlus);
+
+ return (
+
+
dictState {dictState.a}
+ aPlusVal {aPlusVal}
+
+
+ );
+}
+
+render();
+`
+
+const DictDataBindWidthNoHookUsingBlock = `
+const [dict, setState] = share({ a: 1, b: { b1: 1, b2: { b2_1: 'cool' } } });
+const aPlus = derive(() => dict.a + 100 ); // dict.a
+
+const change = () => { // change num
+ setState(prev => prev.a += 100 );
+};
+// create a block component
+const DictDataBindWidthNoHookUsingBlock = block(()=>(
+
+
dictState {dict.a}
+ aPlusVal {aPlus.val}
+
+
+));
+
+render(<>block粒度更新
>);
+`
+
+
+const ChangeStateWithActions = `
+const ctx = sharex({str: 'hello helux', asyncClicked: 0});
+const delay = (ms=1000)=> new Promise(r=>setTimeout(r, ms));
+const { actions, useLoading } = ctx.defineActions()({
+ // sync action
+ changeStr({ draft }) {
+ draft.str = \`changed at \${Date.now()}\`;
+ },
+ // async action
+ async changeStrAsync({ draft }) {
+ await delay();
+ draft.str = \`async changed at \${Date.now()}\`;
+ draft.asyncClicked += 1;
+ if(draft.asyncClicked === 3){
+ throw new Error('a fake error occurred!');
+ }
+ },
+});
+
+function ChangeStateWithActions(){
+ const [state] = ctx.useState();
+ const ret = useLoading();
+ const { changeStrAsync } = useLoading();
+
+ return (
+ {changeStrAsync.loading && 'loading'}
+ {changeStrAsync.ok &&
str: {state.str}
}
+ {changeStrAsync.err && err: {changeStrAsync.err.message}
}
+
+
+ );
+}
+
+render();
+`;
+
+export default {
+ HelloHelux,
+ HelloHeluxDict,
+ DataBindWidthHook,
+ DataBindWidthNoHook,
+ DictDataBindWidthHook,
+ DictDataBindWidthNoHookUsingBlock,
+ ChangeStateWithActions,
+} as Record;
diff --git a/docs/docs/playground/demos/Playground/index.less b/docs/docs/playground/demos/Playground/index.less
index c13e3bdb..81a3aebd 100644
--- a/docs/docs/playground/demos/Playground/index.less
+++ b/docs/docs/playground/demos/Playground/index.less
@@ -1,3 +1,49 @@
+.simple-playground-wrap {
+ height: 800px;
+ background-color: #ffffff;
+ padding: 12px 0;
+}
+
+.simple-playground-wrap .prism-code {
+ height: 740px;
+}
+
+.simple-playground-wrap .topBarItem {
+ display: inline-block;
+ height: 22px;
+ color: #fff;
+ padding: 0 6px;
+ font-size: 14px;
+ line-height: 22px;
+ margin: 2px 5px;
+}
+
+.simple-playground-wrap .topBarItem:hover {
+ cursor: pointer;
+}
+
+.simple-playground-wrap .menuWrap:hover {
+ cursor: pointer;
+}
+
+.simple-playground-wrap .liveConsoleWrap {
+ position: relative;
+ height: 50%;
+}
+
+.simple-playground-wrap .liveConsole {
+ background-color: #242424;
+ height: 100%;
+ overflow-y: auto;
+}
+
+.leftMenuWrap {
+ width: 120px;
+ display: inline-block;
+ vertical-align: top;
+ padding: 38px 0 0 12px;
+ box-sizing: border-box;
+}
.playground-wrap {
width: 100vw;
@@ -79,12 +125,11 @@
display: flex;
}
-.playground-wrap .topBar>.samples {
+.playground-wrap .topBar>.samples {
display: flex;
flex-grow: 1;
}
-
.playground-wrap .topBarItem {
display: inline-block;
height: 22px;
diff --git a/docs/docs/playground/demos/Playground/index.tsx b/docs/docs/playground/demos/Playground/index.tsx
index 45243922..53be08fe 100644
--- a/docs/docs/playground/demos/Playground/index.tsx
+++ b/docs/docs/playground/demos/Playground/index.tsx
@@ -42,7 +42,8 @@ function loadCode(name: any, subName: any, setCode: any) {
}
})
}
-export default () => {
+
+function useLogic(name = 'atom', subName = 'primitive') {
const [info, setInfo] = React.useState({ name, subName });
const [code, setCode] = React.useState(initCode);
@@ -57,8 +58,6 @@ export default () => {
}
}, () => [codeContext.code])
-
-
const changeCode = useCallback((name: string) => {
const subName = cachedSubNames[name] || subNames[name] || 'primitive';
setCodeContext(draft => { draft.key = `${name}_${subName}` })
@@ -77,6 +76,40 @@ export default () => {
loadCode(name, subName, setCode);
}, [info.name, info.subName]);
+ return { info, code, changeCode, changeSubName };
+}
+
+export function SimplePlayground() {
+ const { info, code, changeCode, changeSubName } = useLogic('quickStart', 'HelloHelux');
+
+ return (
+
+
+
+ );
+}
+
+export default () => {
+ const { info, code, changeCode, changeSubName } = useLogic(name, subName);
return (
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index accc80b8..31b1276a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -223,7 +223,7 @@ importers:
hel-micro: ^4.8.11
hel-micro-core: ^4.8.7
hel-types: ^4.3.3
- helux: ^4.3.6
+ helux: ^4.4.0
react: '>=16.10.2'
react-dom: '>=16.10.2'
rollup: ^2.23.0
@@ -284,7 +284,7 @@ importers:
packages/helux-plugin-devtool:
specifiers:
- helux: ^4.3.6
+ helux: ^4.4.0
redux: ^4.2.1
terser: ^5.29.1
dependencies: