intable 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/docs/index-BaMALNy6.css +1 -0
- package/docs/index-CDN48t9E.js +3 -0
- package/docs/index-Cc4RNkLY.css +1 -0
- package/docs/index-MRnbkYmU.js +3 -0
- package/docs/index.html +15 -0
- package/docs/vite.svg +1 -0
- package/index.html +14 -0
- package/package.json +30 -37
- package/packages/intable/README.md +379 -0
- package/packages/intable/package.json +51 -0
- package/packages/intable/src/assets/ClearFormat.svg +3 -0
- package/packages/intable/src/assets/Forms.svg +4 -0
- package/packages/intable/src/assets/MergeCell.svg +4 -0
- package/packages/intable/src/assets/SplitCell.svg +4 -0
- package/packages/intable/src/assets/gap.svg +3 -0
- package/packages/intable/src/assets/loading.svg +12 -0
- package/packages/intable/src/assets/paint.svg +9 -0
- package/packages/intable/src/assets/solid.svg +1 -0
- package/packages/intable/src/components/Columns.tsx +86 -0
- package/packages/intable/src/components/DocTree.tsx +36 -0
- package/packages/intable/src/components/Menu.tsx +109 -0
- package/packages/intable/src/components/Popover.tsx +55 -0
- package/packages/intable/src/components/RecycleList.tsx +99 -0
- package/packages/intable/src/components/Render.tsx +26 -0
- package/packages/intable/src/components/Split.tsx +56 -0
- package/packages/intable/src/components/Tree.tsx +115 -0
- package/packages/intable/src/components/utils.tsx +12 -0
- package/packages/intable/src/hooks/index.ts +200 -0
- package/packages/intable/src/hooks/useDir.ts +78 -0
- package/packages/intable/src/hooks/useSelector.ts +91 -0
- package/packages/intable/src/hooks/useSort.tsx +118 -0
- package/packages/intable/src/hooks/useVirtualizer.ts +180 -0
- package/packages/intable/src/index.tsx +481 -0
- package/packages/intable/src/plugins/CellChangeHighlightPlugin.tsx +5 -0
- package/packages/intable/src/plugins/CellMergePlugin.tsx +153 -0
- package/packages/intable/src/plugins/CellSelectionPlugin.tsx +175 -0
- package/packages/intable/src/plugins/CommandPlugin.tsx +74 -0
- package/packages/intable/src/plugins/CopyPastePlugin.tsx +63 -0
- package/packages/intable/src/plugins/DiffPlugin.tsx +107 -0
- package/packages/intable/src/plugins/DragPlugin.tsx +81 -0
- package/packages/intable/src/plugins/EditablePlugin.tsx +252 -0
- package/packages/intable/src/plugins/ExpandPlugin.tsx +80 -0
- package/packages/intable/src/plugins/HeaderGroup.tsx +289 -0
- package/packages/intable/src/plugins/HistoryPlugin.tsx +49 -0
- package/packages/intable/src/plugins/MenuPlugin.tsx +195 -0
- package/packages/intable/src/plugins/RenderPlugin/components.tsx +51 -0
- package/packages/intable/src/plugins/RenderPlugin/index.tsx +81 -0
- package/packages/intable/src/plugins/ResizePlugin.tsx +122 -0
- package/packages/intable/src/plugins/RowGroupPlugin.tsx +122 -0
- package/packages/intable/src/plugins/RowSelectionPlugin.tsx +65 -0
- package/packages/intable/src/plugins/TreePlugin.tsx +212 -0
- package/packages/intable/src/plugins/VirtualScrollPlugin.tsx +190 -0
- package/packages/intable/src/plugins/ZodValidatorPlugin.tsx +61 -0
- package/packages/intable/src/style.scss +244 -0
- package/{dist → packages/intable/src}/theme/antd.scss +14 -5
- package/{dist → packages/intable/src}/theme/element-plus.scss +6 -5
- package/packages/intable/src/tree.ts +13 -0
- package/packages/intable/src/types/auto-imports.d.ts +13 -0
- package/packages/intable/src/utils.ts +122 -0
- package/packages/intable/src/wc.tsx +35 -0
- package/packages/intable/src/web-component.ts +1 -0
- package/packages/react/package.json +31 -0
- package/packages/react/src/index.ts +44 -0
- package/packages/react/src/plugins/antd.ts +94 -0
- package/packages/react/src/style.scss +12 -0
- package/packages/react/src/types/auto-imports.d.ts +10 -0
- package/packages/vue/package.json +34 -0
- package/packages/vue/src/index.ts +63 -0
- package/packages/vue/src/plugins/element-plus.ts +69 -0
- package/packages/vue/src/style.scss +12 -0
- package/packages/vue/src/types/auto-imports.d.ts +10 -0
- package/pnpm-workspace.yaml +2 -0
- package/public/vite.svg +1 -0
- package/scripts/build.js +184 -0
- package/scripts/publish.js +95 -0
- package/src/assets/ClearFormat.svg +3 -0
- package/src/assets/Forms.svg +4 -0
- package/src/assets/MergeCell.svg +4 -0
- package/src/assets/SplitCell.svg +4 -0
- package/src/assets/gap.svg +3 -0
- package/src/assets/loading.svg +12 -0
- package/src/assets/paint.svg +9 -0
- package/src/assets/solid.svg +1 -0
- package/src/demo-vue.ts +54 -0
- package/src/demo.tsx +107 -0
- package/src/index.scss +105 -0
- package/src/styles/index.scss +172 -0
- package/src/types/auto-imports.d.ts +13 -0
- package/stats.html +4949 -0
- package/tsconfig.app.json +34 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +63 -0
- package/dist/__uno.css +0 -1
- package/dist/chevron-right.js +0 -6
- package/dist/components/Columns.d.ts +0 -3
- package/dist/components/Columns.js +0 -71
- package/dist/components/DocTree.d.ts +0 -4
- package/dist/components/DocTree.js +0 -32
- package/dist/components/Menu.d.ts +0 -1
- package/dist/components/Menu.js +0 -107
- package/dist/components/Popover.d.ts +0 -14
- package/dist/components/Popover.js +0 -41
- package/dist/components/Render.d.ts +0 -4
- package/dist/components/Render.js +0 -20
- package/dist/components/Split.d.ts +0 -15
- package/dist/components/Split.js +0 -76
- package/dist/components/Tree.d.ts +0 -37
- package/dist/components/Tree.js +0 -82
- package/dist/components/utils.d.ts +0 -3
- package/dist/components/utils.js +0 -8
- package/dist/hooks/index.d.ts +0 -40
- package/dist/hooks/index.js +0 -157
- package/dist/hooks/useDir.d.ts +0 -11
- package/dist/hooks/useDir.js +0 -42
- package/dist/hooks/useSelector.d.ts +0 -16
- package/dist/hooks/useSelector.js +0 -35
- package/dist/hooks/useSort.d.ts +0 -18
- package/dist/hooks/useSort.js +0 -83
- package/dist/hooks/useVirtualizer.d.ts +0 -25
- package/dist/hooks/useVirtualizer.js +0 -67
- package/dist/index.d.ts +0 -130
- package/dist/index.js +0 -347
- package/dist/loading.js +0 -6
- package/dist/plugins/CellChangeHighlightPlugin.d.ts +0 -2
- package/dist/plugins/CellChangeHighlightPlugin.js +0 -4
- package/dist/plugins/CellMergePlugin.d.ts +0 -12
- package/dist/plugins/CellMergePlugin.js +0 -2
- package/dist/plugins/CellSelectionPlugin.d.ts +0 -15
- package/dist/plugins/CellSelectionPlugin.js +0 -115
- package/dist/plugins/CommandPlugin.d.ts +0 -14
- package/dist/plugins/CommandPlugin.js +0 -12
- package/dist/plugins/CopyPastePlugin.d.ts +0 -14
- package/dist/plugins/CopyPastePlugin.js +0 -42
- package/dist/plugins/DiffPlugin.d.ts +0 -23
- package/dist/plugins/DiffPlugin.js +0 -56
- package/dist/plugins/DragPlugin.d.ts +0 -14
- package/dist/plugins/DragPlugin.js +0 -47
- package/dist/plugins/EditablePlugin.d.ts +0 -48
- package/dist/plugins/EditablePlugin.js +0 -141
- package/dist/plugins/ExpandPlugin.d.ts +0 -18
- package/dist/plugins/ExpandPlugin.js +0 -50
- package/dist/plugins/HistoryPlugin.d.ts +0 -10
- package/dist/plugins/HistoryPlugin.js +0 -30
- package/dist/plugins/MenuPlugin.d.ts +0 -18
- package/dist/plugins/MenuPlugin.js +0 -107
- package/dist/plugins/RenderPlugin/components.d.ts +0 -5
- package/dist/plugins/RenderPlugin/components.js +0 -87
- package/dist/plugins/RenderPlugin/index.d.ts +0 -30
- package/dist/plugins/RenderPlugin/index.js +0 -49
- package/dist/plugins/ResizePlugin.d.ts +0 -27
- package/dist/plugins/ResizePlugin.js +0 -81
- package/dist/plugins/RowGroupPlugin.d.ts +0 -17
- package/dist/plugins/RowGroupPlugin.js +0 -83
- package/dist/plugins/RowSelectionPlugin.d.ts +0 -20
- package/dist/plugins/RowSelectionPlugin.js +0 -42
- package/dist/plugins/VirtualScrollPlugin.d.ts +0 -15
- package/dist/plugins/VirtualScrollPlugin.js +0 -96
- package/dist/plus.js +0 -6
- package/dist/style.css +0 -3
- package/dist/types/auto-imports.d.js +0 -0
- package/dist/utils.d.ts +0 -30
- package/dist/utils.js +0 -70
- package/dist/wc.d.ts +0 -1
- package/dist/wc.js +0 -21
- package/dist/web-component.d.ts +0 -1
- package/dist/web-component.js +0 -2
- package/dist/x.js +0 -6
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Editor, NodeType } from '@tiptap/core'
|
|
2
|
+
import { useMemoAsync } from '../hooks'
|
|
3
|
+
import { createEffect, createMemo, createSignal, splitProps } from 'solid-js'
|
|
4
|
+
import { delay } from 'es-toolkit'
|
|
5
|
+
import { Tree } from './Tree'
|
|
6
|
+
|
|
7
|
+
export function DocTree(_: { editor: Editor }) {
|
|
8
|
+
const [props, attrs] = splitProps(_, ['editor'])
|
|
9
|
+
|
|
10
|
+
const [count, setCount] = createSignal(0)
|
|
11
|
+
createEffect(() => props.editor.on('update', () => setCount(v => ++v)))
|
|
12
|
+
|
|
13
|
+
const json = useMemoAsync(() => (count(), delay(300).then(() => props.editor.getJSON())), {})
|
|
14
|
+
|
|
15
|
+
const headings = createMemo(() => {
|
|
16
|
+
return (function walker (node: NodeType, queue = [], queue2 = []) {
|
|
17
|
+
if (node.type === 'heading') {
|
|
18
|
+
let i = queue.length
|
|
19
|
+
while (i--) if (queue[i].level < node.attrs.level) break
|
|
20
|
+
const item = { label: node.content?.map(e => e.text).join(''), level: node.attrs.level }
|
|
21
|
+
queue.push(item)
|
|
22
|
+
if (i > -1) (queue[i].children ??= []).push(item)
|
|
23
|
+
else queue2.push(item)
|
|
24
|
+
} else {
|
|
25
|
+
node.content?.forEach(e => walker(e, queue, queue2))
|
|
26
|
+
}
|
|
27
|
+
return queue2
|
|
28
|
+
})(json())
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div class="doc-tree" {...attrs}>
|
|
33
|
+
<Tree data={headings()} class='min-h-40 max-h-100 overflow-auto' />
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { children, createContext, createEffect, createMemo, createResource, createSignal, mergeProps, onMount, splitProps, useContext } from "solid-js"
|
|
2
|
+
import { isEmpty } from 'es-toolkit/compat'
|
|
3
|
+
import { createRender } from "./Render"
|
|
4
|
+
import { autoUpdate, createFloating, offset } from "floating-ui-solid"
|
|
5
|
+
import { combineProps } from '@solid-primitives/props'
|
|
6
|
+
import { pointerHover } from "@solid-primitives/pointer"
|
|
7
|
+
import { createMutable } from "solid-js/store"
|
|
8
|
+
import { delay } from "es-toolkit"
|
|
9
|
+
import { log, unFn } from "../utils"
|
|
10
|
+
import { VDir } from "../hooks/useDir"
|
|
11
|
+
import { Popover } from "./Popover"
|
|
12
|
+
import { useSignle2 } from "../hooks"
|
|
13
|
+
|
|
14
|
+
export function Menu(props) {
|
|
15
|
+
const MenuCtx = createContext({ deep: 0 })
|
|
16
|
+
|
|
17
|
+
const _Li = _e => {
|
|
18
|
+
const ctx = useContext(MenuCtx)
|
|
19
|
+
const [e, attrs] = splitProps(_e, ['children', 'label', 'icon', 'isActive', 'cb', 'menu', 'popover'])
|
|
20
|
+
|
|
21
|
+
const x = createMemo(() => props.x && ctx.deep == 1)
|
|
22
|
+
|
|
23
|
+
let el!: HTMLDivElement
|
|
24
|
+
const [floating, setFloating] = createSignal<HTMLElement>()
|
|
25
|
+
const [hover, setHover] = useSignle2(false, { before: () => delay(100) })
|
|
26
|
+
pointerHover
|
|
27
|
+
|
|
28
|
+
const style = createMemo(() => floating() ? createFloating({
|
|
29
|
+
strategy: 'fixed',
|
|
30
|
+
placement: x() ? 'bottom-start' : 'right-start',
|
|
31
|
+
...e.menu,
|
|
32
|
+
elements: { reference: () => el, floating },
|
|
33
|
+
whileElementsMounted(ref, float, update) {
|
|
34
|
+
return autoUpdate(ref, float, update, { ancestorResize: true, elementResize: true, layoutShift: true, ancestorScroll: true })
|
|
35
|
+
}
|
|
36
|
+
}).floatingStyles : void 0)
|
|
37
|
+
|
|
38
|
+
createEffect(() => {
|
|
39
|
+
floating() && Object.assign(floating()!.style, style()?.() ?? {})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const req = createMutable({ loading: false })
|
|
43
|
+
|
|
44
|
+
async function onClick() {
|
|
45
|
+
if (req.loading) return
|
|
46
|
+
const ret = e.cb?.()
|
|
47
|
+
if (ret instanceof Promise) {
|
|
48
|
+
try {
|
|
49
|
+
await ret
|
|
50
|
+
req.loading = true
|
|
51
|
+
} finally {
|
|
52
|
+
req.loading = false
|
|
53
|
+
props.onAction?.(e)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
props.onAction?.(e)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
onMount(() => {
|
|
62
|
+
<Popover strategy='fixed' reference={el} portal={el} {..._e.popover} middleware={[offset({ mainAxis: 4 })]} />
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const child = children(() => e.children)
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
ref={el}
|
|
69
|
+
use:pointerHover={setHover}
|
|
70
|
+
{...combineProps({ class: `li flex aic rd-2 ${x() ? 'my-1 p-1' : 'mx-1 pl-1 pr-4 py-1'} ${unFn(e.isActive) && 'active'}` }, attrs)}
|
|
71
|
+
on:click={onClick}
|
|
72
|
+
>
|
|
73
|
+
<div class={`flex aic ${x() ? '' : props.density == 'comfortable' ? 'ml-1 mr-2.5' : 'ml-.5 mr-1'} `}>
|
|
74
|
+
{req.loading ? <IMyLoading /> : e.icon}
|
|
75
|
+
</div>
|
|
76
|
+
{e.label}
|
|
77
|
+
{/* {hover() && child() && <_Menu ref={setFloating}>{child()}</_Menu>} */}
|
|
78
|
+
{hover() && e.children && <_Menu ref={setFloating} class='z-1'>{e.children}</_Menu>}
|
|
79
|
+
</div>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const Li = createRender({
|
|
84
|
+
is: _Li,
|
|
85
|
+
processProps: props => {
|
|
86
|
+
let i = 0
|
|
87
|
+
Array.isArray(props.children) && props.children.forEach((e) => !e.is && typeof e == 'object' && (e['data-index'] = i++))
|
|
88
|
+
return props
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
const _Menu = e => {
|
|
93
|
+
const parent = useContext(MenuCtx)
|
|
94
|
+
const ctx = createMutable({ deep: parent.deep + 1 })
|
|
95
|
+
return (
|
|
96
|
+
<MenuCtx.Provider value={ctx}>
|
|
97
|
+
<div
|
|
98
|
+
{...combineProps({ class: `${props.x && ctx.deep == 1 ? 'tt-menu-x flex' : 'tt-menu max-h-100'} overflow-auto` }, e)}
|
|
99
|
+
use:VDir={e.usedir}
|
|
100
|
+
on:click={e => e.stopPropagation()}
|
|
101
|
+
>
|
|
102
|
+
{(el => isEmpty(el) ? <div class='px-4 py-2 op40'>无内容</div> : el)(e.children)}
|
|
103
|
+
</div>
|
|
104
|
+
</MenuCtx.Provider>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return <Li {...combineProps({}, props)} is={_Menu} items={null} children={props.items} />
|
|
109
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { children, createEffect, createMemo, createSignal, type JSX, splitProps } from 'solid-js'
|
|
2
|
+
import { Portal } from 'solid-js/web'
|
|
3
|
+
import { autoUpdate, createFloating, type createFloatingProps, type ReferenceType } from 'floating-ui-solid'
|
|
4
|
+
import type { AutoUpdateOptions } from '@floating-ui/dom'
|
|
5
|
+
import { delay } from 'es-toolkit'
|
|
6
|
+
import { useClicked, useHover, useMemoAsync } from '../hooks'
|
|
7
|
+
|
|
8
|
+
export function Popover(attrs: FloatingProps) {
|
|
9
|
+
const [_, props] = splitProps(attrs, ['reference', 'floating'])
|
|
10
|
+
|
|
11
|
+
const show = (attrs.trigger == 'click' ? useClicked : useHover)(() => [reference(), floating()].filter(e => e))
|
|
12
|
+
const show2 = useMemoAsync(() => (
|
|
13
|
+
attrs.trigger == 'click'
|
|
14
|
+
? show()
|
|
15
|
+
: show() ? delay(100).then(() => true) : delay(200).then(() => false)
|
|
16
|
+
))
|
|
17
|
+
|
|
18
|
+
const reference = children(() => attrs.reference as HTMLElement)
|
|
19
|
+
const floating = children(() => show2() ? attrs.floating as HTMLElement : void 0)
|
|
20
|
+
|
|
21
|
+
return <Floating {...props} reference={reference} floating={floating} />
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type FloatingProps = {
|
|
25
|
+
reference: ReferenceType
|
|
26
|
+
floating?: JSX.Element | (() => JSX.Element)
|
|
27
|
+
portal?: HTMLElement
|
|
28
|
+
trigger?: 'click' | 'hover'
|
|
29
|
+
} & createFloatingProps
|
|
30
|
+
|
|
31
|
+
export function Floating(attrs: FloatingProps & { update?: Partial<AutoUpdateOptions> }) {
|
|
32
|
+
const [_, props] = splitProps(attrs, ['reference', 'floating'])
|
|
33
|
+
const reference = children(() => attrs.reference)
|
|
34
|
+
const floating = children(() => attrs.floating)
|
|
35
|
+
|
|
36
|
+
const style = createMemo(() => floating() ? createFloating({
|
|
37
|
+
whileElementsMounted(ref, float, update) {
|
|
38
|
+
return autoUpdate(ref, float, update, { ancestorResize: true, elementResize: true, layoutShift: true, ancestorScroll: true, ...attrs.update })
|
|
39
|
+
},
|
|
40
|
+
...props,
|
|
41
|
+
elements: { reference, floating },
|
|
42
|
+
}).floatingStyles : void 0)
|
|
43
|
+
|
|
44
|
+
createEffect(() => {
|
|
45
|
+
// console.log(props.floating)
|
|
46
|
+
floating() && Object.assign(floating().style, style()?.() ?? {})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
{reference()}
|
|
52
|
+
{props.portal && floating() ? <Portal mount={props.portal}>{floating()}</Portal> : floating()}
|
|
53
|
+
</>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createMemo, type JSX, onCleanup, For, getOwner, runWithOwner, children, Show, createRoot } from 'solid-js'
|
|
2
|
+
import { createMutable } from 'solid-js/store'
|
|
3
|
+
import { log } from '../utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RecycleList — a keyed list component with DOM recycling.
|
|
7
|
+
*
|
|
8
|
+
* Works like SolidJS `<For>` (keyed by reference identity) but instead of
|
|
9
|
+
* destroying DOM when items leave the list, it hides and pools those DOM
|
|
10
|
+
* nodes. When new items enter, a pooled slot is reused by swapping the
|
|
11
|
+
* reactive signals, avoiding the cost of creating & hydrating fresh DOM.
|
|
12
|
+
*
|
|
13
|
+
* Each slot gets its own `createRoot` so that its inner reactive tree
|
|
14
|
+
* (memos, effects) is NOT owned by the reconciliation memo — preventing
|
|
15
|
+
* SolidJS from disposing child computations when the outer memo re-runs.
|
|
16
|
+
*
|
|
17
|
+
* Ideal for virtual-scroll scenarios where items constantly enter/leave
|
|
18
|
+
* the viewport but the DOM structure per item is identical.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <RecycleList each={visibleItems()}>
|
|
22
|
+
* {(item, index) => <div>{item().name} at {index()}</div>}
|
|
23
|
+
* </RecycleList>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function RecycleList<T>(props: {
|
|
27
|
+
each: T[]
|
|
28
|
+
children: (item: () => T, index: () => number) => JSX.Element
|
|
29
|
+
}): JSX.Element {
|
|
30
|
+
interface Val {
|
|
31
|
+
v: any
|
|
32
|
+
i: number
|
|
33
|
+
active: boolean
|
|
34
|
+
el?: any
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Active slots keyed by identity reference
|
|
38
|
+
const active = new Map<T, Val>()
|
|
39
|
+
// Pool of inactive (hidden) slots ready for reuse
|
|
40
|
+
const pool: Val[] = []
|
|
41
|
+
const owner = getOwner()
|
|
42
|
+
|
|
43
|
+
function state<T extends Object>(initial: T): T {
|
|
44
|
+
return runWithOwner(owner, () => createMutable(initial))!
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const list = createMemo(() => {
|
|
48
|
+
const items = props.each || []
|
|
49
|
+
const nextKeys = new Set(items)
|
|
50
|
+
|
|
51
|
+
// 1. Deactivate slots whose keys left the list → move to pool
|
|
52
|
+
for (const [key, val] of active) {
|
|
53
|
+
if (!nextKeys.has(key)) {
|
|
54
|
+
pool.push(val)
|
|
55
|
+
active.delete(key)
|
|
56
|
+
// val.v = null
|
|
57
|
+
// val.i = -1
|
|
58
|
+
val.active = false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 2. For each item: reuse existing active slot, recycle from pool, or create new
|
|
63
|
+
const list = [] as Val[]
|
|
64
|
+
for (let i = 0; i < items.length; i++) {
|
|
65
|
+
const item = items[i]
|
|
66
|
+
if (active.has(item)) {
|
|
67
|
+
const slot = active.get(item)!
|
|
68
|
+
slot.i = i
|
|
69
|
+
slot.v = item
|
|
70
|
+
} else if (pool.length > 0) {
|
|
71
|
+
const slot = pool.pop()!
|
|
72
|
+
slot.i = i
|
|
73
|
+
slot.v = item
|
|
74
|
+
slot.active = true
|
|
75
|
+
active.set(item, slot)
|
|
76
|
+
} else {
|
|
77
|
+
active.set(item, state({ v: item, i, active: true }))
|
|
78
|
+
}
|
|
79
|
+
list.push(active.get(item)!)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return list.concat(...pool)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
onCleanup(() => {
|
|
86
|
+
active.clear()
|
|
87
|
+
pool.length = 0
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<For each={list()}>{(val) => {
|
|
92
|
+
return <>
|
|
93
|
+
{val.active && runWithOwner(owner, () => (
|
|
94
|
+
val.el ??= props.children(() => val.v, () => val.i)
|
|
95
|
+
))}
|
|
96
|
+
</>
|
|
97
|
+
}}</For>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { splitProps } from "solid-js"
|
|
2
|
+
import { Dynamic } from "solid-js/web"
|
|
3
|
+
|
|
4
|
+
const unFn = (fn, ...arg) => typeof fn == 'function' ? fn(...arg) : fn
|
|
5
|
+
|
|
6
|
+
export function createRender({ is, processProps = e => e } = {}) {
|
|
7
|
+
const Render = (props: any) => {
|
|
8
|
+
const [reserve, attrs] = splitProps(processProps?.(props), ['is', 'vIf', 'children'])
|
|
9
|
+
return (<>
|
|
10
|
+
{ (!('vIf' in reserve) || !!unFn(reserve.vIf)) &&
|
|
11
|
+
<Dynamic component={reserve.is ?? is} {...attrs}>
|
|
12
|
+
{List(reserve.children)}
|
|
13
|
+
</Dynamic>
|
|
14
|
+
}
|
|
15
|
+
</>)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const List = children => (
|
|
19
|
+
Array.isArray(children) ? children.map(e => typeof e == 'object' ? Render(e) : e) :
|
|
20
|
+
children
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return Render
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Render = createRender({ is: 'div' })
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { unFn } from '../utils'
|
|
2
|
+
import { createElementBounds } from '@solid-primitives/bounds'
|
|
3
|
+
import { children, createComputed, createEffect, createMemo, For, Index, mapArray, mergeProps, onMount, splitProps, type JSXElement } from 'solid-js'
|
|
4
|
+
import { Portal } from 'solid-js/web'
|
|
5
|
+
|
|
6
|
+
type SplitProps = {
|
|
7
|
+
container?: Element
|
|
8
|
+
cells: () => Element[]
|
|
9
|
+
handle?: (i: number) => JSXElement
|
|
10
|
+
size?: number
|
|
11
|
+
dir?: 'x' | 'y'
|
|
12
|
+
leading?: boolean
|
|
13
|
+
trailing?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Split = (props: SplitProps & { children?: JSXElement }) => {
|
|
17
|
+
let el!: Element
|
|
18
|
+
const child = children(() => props.children)
|
|
19
|
+
|
|
20
|
+
onMount(() => {
|
|
21
|
+
useSplit({
|
|
22
|
+
...props,
|
|
23
|
+
container: el,
|
|
24
|
+
cells: () => props.cells ? props.cells() : child()
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return <div ref={el} class='relative' {...props}>{child()}</div>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const useSplit = (props: SplitProps) => {
|
|
32
|
+
props = mergeProps({ dir: 'x', size: 4 }, props) as SplitProps
|
|
33
|
+
|
|
34
|
+
let el!: HTMLDivElement
|
|
35
|
+
// const bounds = createMemo(() => props.cells().map()
|
|
36
|
+
const bounds = mapArray(() => props.cells(), el => createElementBounds(el))
|
|
37
|
+
const rect = createElementBounds(() => el)
|
|
38
|
+
createEffect(() => el.style.position = 'absolute')
|
|
39
|
+
|
|
40
|
+
const style = (e, bool) => props.dir == 'x'
|
|
41
|
+
? `transform: translate(${(bool ? e.left + e.width : e.left) - (props.size! / 2)}px, ${e.top}px); width: ${props.size}px; height: ${e.height}px;`
|
|
42
|
+
: `transform: translate(${e.left}px, ${(bool ? e.top + e.height : e.top) - (props.size! / 2)}px); width: ${e.width}px; height: ${props.size}px;`
|
|
43
|
+
|
|
44
|
+
const Handle = (e) => (
|
|
45
|
+
<div class='absolute z-1' style={style({ ...e.e, left: e.e.left - rect.left, top: e.e.top - rect.top }, e.bool)}>{props.handle?.(e.i)}</div>
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
; //
|
|
49
|
+
<Portal ref={el} mount={props.container || document.body}>
|
|
50
|
+
<For each={bounds().slice(0, -1)}>
|
|
51
|
+
{(e, i) => <Handle e={unFn(e)} bool={1} i={unFn(i)} />}
|
|
52
|
+
</For>
|
|
53
|
+
{!!bounds().length && props.leading && <Handle e={bounds()[0]} i={-1} />}
|
|
54
|
+
{!!bounds().length && props.trailing && <Handle e={bounds()[bounds().length - 1]} bool={1} i={bounds().length - 1} />}
|
|
55
|
+
</Portal>
|
|
56
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createEffect, createMemo, createSignal, For, Index, on, onCleanup, splitProps } from 'solid-js'
|
|
2
|
+
import { Dynamic } from 'solid-js/web'
|
|
3
|
+
import { createLazyMemo } from '@solid-primitives/memo'
|
|
4
|
+
import { combineProps } from '@solid-primitives/props'
|
|
5
|
+
import { castArray } from 'es-toolkit/compat'
|
|
6
|
+
|
|
7
|
+
function define(that, key) {
|
|
8
|
+
const signal = createSignal()
|
|
9
|
+
Object.defineProperty(that, key, {
|
|
10
|
+
get() { return signal[0]() },
|
|
11
|
+
set(v) { signal[1](v) }
|
|
12
|
+
})
|
|
13
|
+
return signal
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function memo<T>(that, key, fn: () => T) {
|
|
17
|
+
const signal = createLazyMemo(fn)
|
|
18
|
+
Object.defineProperty(that, key, {
|
|
19
|
+
get() { return signal() },
|
|
20
|
+
})
|
|
21
|
+
return signal
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export abstract class $Node {
|
|
25
|
+
data: any
|
|
26
|
+
constructor(data: any) {
|
|
27
|
+
this.data = data
|
|
28
|
+
|
|
29
|
+
createEffect(() => {
|
|
30
|
+
const children = this.children
|
|
31
|
+
children?.map(e => e.parent = this)
|
|
32
|
+
onCleanup(() => children?.map(e => e.parent = undefined))
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// abstract get Node(data): $Node
|
|
37
|
+
// abstract get id(): any
|
|
38
|
+
get label() { return this.data.label }
|
|
39
|
+
abstract getChildren(): $Node[] | undefined
|
|
40
|
+
|
|
41
|
+
declare children: $Node[] | undefined
|
|
42
|
+
$children = memo(this, 'children', () => this.getChildren())
|
|
43
|
+
|
|
44
|
+
declare parent: $Node | undefined
|
|
45
|
+
$parent = define(this, 'parent')
|
|
46
|
+
|
|
47
|
+
declare deep: number
|
|
48
|
+
$deep = memo(this, 'deep', () => this.parent ? this.parent.deep + 1 : 0)
|
|
49
|
+
|
|
50
|
+
declare index: number
|
|
51
|
+
$index = memo(this, 'index', () => this.parent?.children?.indexOf(this))
|
|
52
|
+
|
|
53
|
+
declare prev: $Node | undefined
|
|
54
|
+
$prev = memo(this, 'prev', () => this.parent?.children?.[this.index - 1])
|
|
55
|
+
|
|
56
|
+
declare next: $Node | undefined
|
|
57
|
+
$next = memo(this, 'next', () => this.parent?.children?.[this.index + 1])
|
|
58
|
+
|
|
59
|
+
declare root: $Node
|
|
60
|
+
$root = memo(this, 'root', () => this.parent ? this.parent.root : this)
|
|
61
|
+
|
|
62
|
+
declare path: $Node[]
|
|
63
|
+
$path = memo(this, 'path', () => {
|
|
64
|
+
const ret = [this] as $Node[]
|
|
65
|
+
let e: $Node = this
|
|
66
|
+
while (e.parent) ret.push(e = e.parent)
|
|
67
|
+
return ret.reverse()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
get descendants(): $Node[] {
|
|
71
|
+
return this.children?.flatMap(e => [e, ...e.descendants]) || []
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
contains(node: $Node) {
|
|
75
|
+
return node.path.includes(this)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
remove() {
|
|
79
|
+
// this.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class $TreeItem extends $Node {
|
|
84
|
+
get is() { return this.data.is }
|
|
85
|
+
get props() { return this.data }
|
|
86
|
+
get id() { return this.data.id }
|
|
87
|
+
getChildren() { return this.data.children?.map(e => new $TreeItem(e)) }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function Tree(_: { data: any; Node: { new (data: any): $TreeItem } }) {
|
|
91
|
+
const [props, attrs] = splitProps(_, ['data', 'Node'])
|
|
92
|
+
|
|
93
|
+
const Node = props.Node ?? $TreeItem
|
|
94
|
+
|
|
95
|
+
const root = createMemo(() => new (class extends Node {
|
|
96
|
+
getChildren() { return castArray(this.data || []).map(e => new Node(e)) }
|
|
97
|
+
})(props.data))
|
|
98
|
+
|
|
99
|
+
const flated = createMemo(() => root().descendants as $TreeItem[])
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div {...combineProps({ class: 'tt-menu' }, attrs)}>
|
|
103
|
+
<Index each={flated()}>
|
|
104
|
+
{(node, index) => (
|
|
105
|
+
<Dynamic
|
|
106
|
+
component={node().is ?? 'div'}
|
|
107
|
+
{...combineProps({ class: 'li py-1 px-4', style: `padding-left: ${(node().deep) * 16}px` }, node().props)}
|
|
108
|
+
>
|
|
109
|
+
{node().label}
|
|
110
|
+
</Dynamic>
|
|
111
|
+
)}
|
|
112
|
+
</Index>
|
|
113
|
+
</div>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js'
|
|
2
|
+
|
|
3
|
+
export function solidComponent<T extends (...arg) => JSX.Element>(comp: T) {
|
|
4
|
+
comp.__solid = 1
|
|
5
|
+
return comp
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function renderComponent(Comp: any, props: any, renderer: any) {
|
|
9
|
+
if (!Comp) return null
|
|
10
|
+
if (!Comp.__solid) Comp = renderer(Comp)
|
|
11
|
+
return <Comp {...props} />
|
|
12
|
+
}
|