This repository has been archived by the owner on Oct 16, 2024. It is now read-only.
generated from hemengke1997/ts-starter
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b6a7ead
commit ba66ff9
Showing
20 changed files
with
8,786 additions
and
7,003 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
# @minko-fe/react-hook | ||
|
||
## 0.4.0 | ||
|
||
### Minor Changes | ||
|
||
- feat: add more hook | ||
|
||
## 0.3.7 | ||
|
||
### Patch Changes | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { isBrowser } from '@minko-fe/lodash-pro' | ||
import { render as ReactRender, unmount as ReactUnmount } from './render' | ||
|
||
const destroyFns: Array<() => void> = [] | ||
|
||
type ConfigUpdate<T> = Partial<T> | ((prev: T) => Partial<T>) | ||
|
||
type Config<T = any> = { | ||
/** | ||
* @description 声明式组件 | ||
*/ | ||
RC: React.FC<T> | ||
keys: { | ||
/** | ||
* 显隐 key | ||
*/ | ||
visible: keyof T | ||
/** | ||
* 关闭回调 key | ||
*/ | ||
onClosed: keyof T | ||
} | ||
/** | ||
* @description 组件的runtime props | ||
*/ | ||
props: Partial<T> | ||
} | ||
|
||
/** | ||
* @description 把显隐的声明式tsx转换为命令式 | ||
* 如 antd 的 Modal | ||
* 如 vant 的 Dialog | ||
*/ | ||
function imperative<T>(config: Config<T>) { | ||
if (!isBrowser()) return null | ||
const { | ||
RC, | ||
keys: { visible: visibleKey, onClosed: onClosedKey }, | ||
props, | ||
} = config | ||
|
||
const container = document.createDocumentFragment() | ||
|
||
let currentProps = { ...props, [visibleKey]: true } as any | ||
let timeoutId: ReturnType<typeof setTimeout> | ||
|
||
function destroy() { | ||
for (let i = 0; i < destroyFns.length; i++) { | ||
const fn = destroyFns[i] | ||
if (fn === close) { | ||
destroyFns.splice(i, 1) | ||
break | ||
} | ||
} | ||
ReactUnmount(container) | ||
} | ||
|
||
function render(props: any) { | ||
clearTimeout(timeoutId) | ||
|
||
timeoutId = setTimeout(() => { | ||
ReactRender(<RC {...props} />, container) | ||
}) | ||
} | ||
|
||
function close(...args: any[]) { | ||
currentProps = { | ||
...currentProps, | ||
[visibleKey]: false, | ||
[onClosedKey]: () => { | ||
if (typeof props[onClosedKey] === 'function') { | ||
;(props[onClosedKey] as Function)() | ||
} | ||
// @ts-expect-error | ||
destroy.apply(this, args) | ||
}, | ||
} | ||
render(currentProps) | ||
} | ||
|
||
function update(configUpdate: ConfigUpdate<T>) { | ||
if (typeof configUpdate === 'function') { | ||
currentProps = configUpdate(currentProps) | ||
} else { | ||
currentProps = { | ||
...currentProps, | ||
...configUpdate, | ||
} | ||
} | ||
render(currentProps) | ||
} | ||
|
||
render(currentProps) | ||
|
||
destroyFns.push(close) | ||
|
||
return { | ||
destroy: close, | ||
update, | ||
} | ||
} | ||
|
||
export { imperative } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { type ReactElement } from 'react' | ||
import * as ReactDOM from 'react-dom' | ||
import { version as _reactDomVersion } from 'react-dom' | ||
import { type Root } from 'react-dom/client' | ||
|
||
const reactDomVersion = Number((_reactDomVersion || '').split('.')[0]) | ||
|
||
// 移植自rc-util: https://github.com/react-component/util/blob/master/src/React/render.ts | ||
|
||
type CreateRoot = (container: ContainerType) => Root | ||
|
||
// Let compiler not to search module usage | ||
const fullClone = { | ||
...ReactDOM, | ||
} as typeof ReactDOM & { | ||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?: { | ||
usingClientEntryPoint?: boolean | ||
} | ||
createRoot?: CreateRoot | ||
} | ||
|
||
const { render: reactRender, unmountComponentAtNode } = fullClone | ||
|
||
let createRoot: CreateRoot | ||
try { | ||
if (reactDomVersion >= 18 && fullClone.createRoot) { | ||
createRoot = fullClone.createRoot | ||
} | ||
} catch { | ||
// Do nothing; | ||
} | ||
|
||
function toggleWarning(skip: boolean) { | ||
const { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED } = fullClone | ||
|
||
if ( | ||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED && | ||
typeof __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED === 'object' | ||
) { | ||
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint = skip | ||
} | ||
} | ||
|
||
const MARK = '__react_root__' | ||
|
||
// ========================== Render ========================== | ||
type ContainerType = (Element | DocumentFragment) & { | ||
[MARK]?: Root | ||
} | ||
|
||
function legacyRender(node: ReactElement, container: ContainerType) { | ||
reactRender(node, container) | ||
} | ||
|
||
function concurrentRender(node: ReactElement, container: ContainerType) { | ||
toggleWarning(true) | ||
const root = container[MARK] || createRoot(container) | ||
toggleWarning(false) | ||
root.render(node) | ||
container[MARK] = root | ||
} | ||
|
||
export function render(node: ReactElement, container: ContainerType) { | ||
if (createRoot as unknown) { | ||
concurrentRender(node, container) | ||
return | ||
} | ||
legacyRender(node, container) | ||
} | ||
|
||
// ========================== Unmount ========================= | ||
function legacyUnmount(container: ContainerType) { | ||
return unmountComponentAtNode(container) | ||
} | ||
|
||
async function concurrentUnmount(container: ContainerType) { | ||
// Delay to unmount to avoid React 18 sync warning | ||
return Promise.resolve().then(() => { | ||
container[MARK]?.unmount() | ||
delete container[MARK] | ||
}) | ||
} | ||
|
||
export function unmount(container: ContainerType) { | ||
if (createRoot as unknown) { | ||
return concurrentUnmount(container) | ||
} | ||
|
||
return legacyUnmount(container) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { useMemoizedFn } from 'ahooks' | ||
import { useEffect, useState } from 'react' | ||
|
||
/** | ||
* @description 在多个步骤中切换。如果当前步骤是最后一个步骤,则下一个步骤将是第一个步骤。 | ||
* @param steps 步骤列表 | ||
* @param defaultValue 默认步骤 | ||
* @param onChange 步骤变化时的回调 | ||
*/ | ||
export default function useStep<T extends string>( | ||
steps: T[], | ||
{ | ||
defaultValue, | ||
onChange, | ||
}: { | ||
defaultValue?: T | ||
onChange?: (step: T) => void | ||
}, | ||
) { | ||
const [currentStep, setCurrentStep] = useState(defaultValue || steps[0]) | ||
|
||
const next = useMemoizedFn(() => { | ||
const currentIndex = steps.indexOf(currentStep) | ||
if (steps.length && currentIndex !== -1) { | ||
if (currentIndex < steps.length - 1) { | ||
setCurrentStep(steps[currentIndex + 1]) | ||
} else { | ||
setCurrentStep(steps[0]) | ||
} | ||
} | ||
}) | ||
|
||
useEffect(() => { | ||
onChange?.(currentStep) | ||
}, [currentStep, onChange]) | ||
|
||
return [currentStep, next] as const | ||
} |
Oops, something went wrong.