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.
Files changed (169) hide show
  1. package/README.md +1 -2
  2. package/docs/index-BaMALNy6.css +1 -0
  3. package/docs/index-CDN48t9E.js +3 -0
  4. package/docs/index-Cc4RNkLY.css +1 -0
  5. package/docs/index-MRnbkYmU.js +3 -0
  6. package/docs/index.html +15 -0
  7. package/docs/vite.svg +1 -0
  8. package/index.html +14 -0
  9. package/package.json +30 -37
  10. package/packages/intable/README.md +379 -0
  11. package/packages/intable/package.json +51 -0
  12. package/packages/intable/src/assets/ClearFormat.svg +3 -0
  13. package/packages/intable/src/assets/Forms.svg +4 -0
  14. package/packages/intable/src/assets/MergeCell.svg +4 -0
  15. package/packages/intable/src/assets/SplitCell.svg +4 -0
  16. package/packages/intable/src/assets/gap.svg +3 -0
  17. package/packages/intable/src/assets/loading.svg +12 -0
  18. package/packages/intable/src/assets/paint.svg +9 -0
  19. package/packages/intable/src/assets/solid.svg +1 -0
  20. package/packages/intable/src/components/Columns.tsx +86 -0
  21. package/packages/intable/src/components/DocTree.tsx +36 -0
  22. package/packages/intable/src/components/Menu.tsx +109 -0
  23. package/packages/intable/src/components/Popover.tsx +55 -0
  24. package/packages/intable/src/components/RecycleList.tsx +99 -0
  25. package/packages/intable/src/components/Render.tsx +26 -0
  26. package/packages/intable/src/components/Split.tsx +56 -0
  27. package/packages/intable/src/components/Tree.tsx +115 -0
  28. package/packages/intable/src/components/utils.tsx +12 -0
  29. package/packages/intable/src/hooks/index.ts +200 -0
  30. package/packages/intable/src/hooks/useDir.ts +78 -0
  31. package/packages/intable/src/hooks/useSelector.ts +91 -0
  32. package/packages/intable/src/hooks/useSort.tsx +118 -0
  33. package/packages/intable/src/hooks/useVirtualizer.ts +180 -0
  34. package/packages/intable/src/index.tsx +481 -0
  35. package/packages/intable/src/plugins/CellChangeHighlightPlugin.tsx +5 -0
  36. package/packages/intable/src/plugins/CellMergePlugin.tsx +153 -0
  37. package/packages/intable/src/plugins/CellSelectionPlugin.tsx +175 -0
  38. package/packages/intable/src/plugins/CommandPlugin.tsx +74 -0
  39. package/packages/intable/src/plugins/CopyPastePlugin.tsx +63 -0
  40. package/packages/intable/src/plugins/DiffPlugin.tsx +107 -0
  41. package/packages/intable/src/plugins/DragPlugin.tsx +81 -0
  42. package/packages/intable/src/plugins/EditablePlugin.tsx +252 -0
  43. package/packages/intable/src/plugins/ExpandPlugin.tsx +80 -0
  44. package/packages/intable/src/plugins/HeaderGroup.tsx +289 -0
  45. package/packages/intable/src/plugins/HistoryPlugin.tsx +49 -0
  46. package/packages/intable/src/plugins/MenuPlugin.tsx +195 -0
  47. package/packages/intable/src/plugins/RenderPlugin/components.tsx +51 -0
  48. package/packages/intable/src/plugins/RenderPlugin/index.tsx +81 -0
  49. package/packages/intable/src/plugins/ResizePlugin.tsx +122 -0
  50. package/packages/intable/src/plugins/RowGroupPlugin.tsx +122 -0
  51. package/packages/intable/src/plugins/RowSelectionPlugin.tsx +65 -0
  52. package/packages/intable/src/plugins/TreePlugin.tsx +212 -0
  53. package/packages/intable/src/plugins/VirtualScrollPlugin.tsx +190 -0
  54. package/packages/intable/src/plugins/ZodValidatorPlugin.tsx +61 -0
  55. package/packages/intable/src/style.scss +244 -0
  56. package/{dist → packages/intable/src}/theme/antd.scss +14 -5
  57. package/{dist → packages/intable/src}/theme/element-plus.scss +6 -5
  58. package/packages/intable/src/tree.ts +13 -0
  59. package/packages/intable/src/types/auto-imports.d.ts +13 -0
  60. package/packages/intable/src/utils.ts +122 -0
  61. package/packages/intable/src/wc.tsx +35 -0
  62. package/packages/intable/src/web-component.ts +1 -0
  63. package/packages/react/package.json +31 -0
  64. package/packages/react/src/index.ts +44 -0
  65. package/packages/react/src/plugins/antd.ts +94 -0
  66. package/packages/react/src/style.scss +12 -0
  67. package/packages/react/src/types/auto-imports.d.ts +10 -0
  68. package/packages/vue/package.json +34 -0
  69. package/packages/vue/src/index.ts +63 -0
  70. package/packages/vue/src/plugins/element-plus.ts +69 -0
  71. package/packages/vue/src/style.scss +12 -0
  72. package/packages/vue/src/types/auto-imports.d.ts +10 -0
  73. package/pnpm-workspace.yaml +2 -0
  74. package/public/vite.svg +1 -0
  75. package/scripts/build.js +184 -0
  76. package/scripts/publish.js +95 -0
  77. package/src/assets/ClearFormat.svg +3 -0
  78. package/src/assets/Forms.svg +4 -0
  79. package/src/assets/MergeCell.svg +4 -0
  80. package/src/assets/SplitCell.svg +4 -0
  81. package/src/assets/gap.svg +3 -0
  82. package/src/assets/loading.svg +12 -0
  83. package/src/assets/paint.svg +9 -0
  84. package/src/assets/solid.svg +1 -0
  85. package/src/demo-vue.ts +54 -0
  86. package/src/demo.tsx +107 -0
  87. package/src/index.scss +105 -0
  88. package/src/styles/index.scss +172 -0
  89. package/src/types/auto-imports.d.ts +13 -0
  90. package/stats.html +4949 -0
  91. package/tsconfig.app.json +34 -0
  92. package/tsconfig.json +7 -0
  93. package/tsconfig.node.json +26 -0
  94. package/vite.config.ts +63 -0
  95. package/dist/__uno.css +0 -1
  96. package/dist/chevron-right.js +0 -6
  97. package/dist/components/Columns.d.ts +0 -3
  98. package/dist/components/Columns.js +0 -71
  99. package/dist/components/DocTree.d.ts +0 -4
  100. package/dist/components/DocTree.js +0 -32
  101. package/dist/components/Menu.d.ts +0 -1
  102. package/dist/components/Menu.js +0 -107
  103. package/dist/components/Popover.d.ts +0 -14
  104. package/dist/components/Popover.js +0 -41
  105. package/dist/components/Render.d.ts +0 -4
  106. package/dist/components/Render.js +0 -20
  107. package/dist/components/Split.d.ts +0 -15
  108. package/dist/components/Split.js +0 -76
  109. package/dist/components/Tree.d.ts +0 -37
  110. package/dist/components/Tree.js +0 -82
  111. package/dist/components/utils.d.ts +0 -3
  112. package/dist/components/utils.js +0 -8
  113. package/dist/hooks/index.d.ts +0 -40
  114. package/dist/hooks/index.js +0 -157
  115. package/dist/hooks/useDir.d.ts +0 -11
  116. package/dist/hooks/useDir.js +0 -42
  117. package/dist/hooks/useSelector.d.ts +0 -16
  118. package/dist/hooks/useSelector.js +0 -35
  119. package/dist/hooks/useSort.d.ts +0 -18
  120. package/dist/hooks/useSort.js +0 -83
  121. package/dist/hooks/useVirtualizer.d.ts +0 -25
  122. package/dist/hooks/useVirtualizer.js +0 -67
  123. package/dist/index.d.ts +0 -130
  124. package/dist/index.js +0 -347
  125. package/dist/loading.js +0 -6
  126. package/dist/plugins/CellChangeHighlightPlugin.d.ts +0 -2
  127. package/dist/plugins/CellChangeHighlightPlugin.js +0 -4
  128. package/dist/plugins/CellMergePlugin.d.ts +0 -12
  129. package/dist/plugins/CellMergePlugin.js +0 -2
  130. package/dist/plugins/CellSelectionPlugin.d.ts +0 -15
  131. package/dist/plugins/CellSelectionPlugin.js +0 -115
  132. package/dist/plugins/CommandPlugin.d.ts +0 -14
  133. package/dist/plugins/CommandPlugin.js +0 -12
  134. package/dist/plugins/CopyPastePlugin.d.ts +0 -14
  135. package/dist/plugins/CopyPastePlugin.js +0 -42
  136. package/dist/plugins/DiffPlugin.d.ts +0 -23
  137. package/dist/plugins/DiffPlugin.js +0 -56
  138. package/dist/plugins/DragPlugin.d.ts +0 -14
  139. package/dist/plugins/DragPlugin.js +0 -47
  140. package/dist/plugins/EditablePlugin.d.ts +0 -48
  141. package/dist/plugins/EditablePlugin.js +0 -141
  142. package/dist/plugins/ExpandPlugin.d.ts +0 -18
  143. package/dist/plugins/ExpandPlugin.js +0 -50
  144. package/dist/plugins/HistoryPlugin.d.ts +0 -10
  145. package/dist/plugins/HistoryPlugin.js +0 -30
  146. package/dist/plugins/MenuPlugin.d.ts +0 -18
  147. package/dist/plugins/MenuPlugin.js +0 -107
  148. package/dist/plugins/RenderPlugin/components.d.ts +0 -5
  149. package/dist/plugins/RenderPlugin/components.js +0 -87
  150. package/dist/plugins/RenderPlugin/index.d.ts +0 -30
  151. package/dist/plugins/RenderPlugin/index.js +0 -49
  152. package/dist/plugins/ResizePlugin.d.ts +0 -27
  153. package/dist/plugins/ResizePlugin.js +0 -81
  154. package/dist/plugins/RowGroupPlugin.d.ts +0 -17
  155. package/dist/plugins/RowGroupPlugin.js +0 -83
  156. package/dist/plugins/RowSelectionPlugin.d.ts +0 -20
  157. package/dist/plugins/RowSelectionPlugin.js +0 -42
  158. package/dist/plugins/VirtualScrollPlugin.d.ts +0 -15
  159. package/dist/plugins/VirtualScrollPlugin.js +0 -96
  160. package/dist/plus.js +0 -6
  161. package/dist/style.css +0 -3
  162. package/dist/types/auto-imports.d.js +0 -0
  163. package/dist/utils.d.ts +0 -30
  164. package/dist/utils.js +0 -70
  165. package/dist/wc.d.ts +0 -1
  166. package/dist/wc.js +0 -21
  167. package/dist/web-component.d.ts +0 -1
  168. package/dist/web-component.js +0 -2
  169. 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
+ }