diff --git a/src/Select/Select copy.vue b/src/Select/Select copy.vue deleted file mode 100644 index 51351dbf..00000000 --- a/src/Select/Select copy.vue +++ /dev/null @@ -1,91 +0,0 @@ - - diff --git a/src/Select/Select.vue b/src/Select/Select.vue index a1a3c0d5..51351dbf 100644 --- a/src/Select/Select.vue +++ b/src/Select/Select.vue @@ -1,15 +1,16 @@ diff --git a/src/Select/SelectHeadless.vue b/src/Select/SelectHeadless.vue new file mode 100644 index 00000000..a1a3c0d5 --- /dev/null +++ b/src/Select/SelectHeadless.vue @@ -0,0 +1,129 @@ + + diff --git a/src/_pure/Listbox/Boxlist.ts b/src/_pure/Listbox/Boxlist.ts new file mode 100644 index 00000000..3553d7d0 --- /dev/null +++ b/src/_pure/Listbox/Boxlist.ts @@ -0,0 +1,20 @@ +import { defineComponent } from 'vue' + +const Listbox = defineComponent({ + name: 'TListbox', + props: { + list: { + type: Array, + required: true, + }, + render: { + type: Function, + required: true, + }, + }, + setup(props) { + return () => { + return props.list.map(item => props.render(item)) + } + }, +}) diff --git a/src/_pure/Listbox/index.tsx b/src/_pure/Listbox/index.tsx new file mode 100644 index 00000000..289e6b4f --- /dev/null +++ b/src/_pure/Listbox/index.tsx @@ -0,0 +1,25 @@ +import { defineComponent, type SlotsType } from 'vue' + +const Listbox = defineComponent( + (props: { type: string }) => { + return () => + }, + { + name: 'TListbox', + props: ['type'], + emits: ['change'], + } +) + +const ListboxOption = defineComponent({ + name: 'TListboxOption', + props: { + value: { type: null }, + }, + slots: Object as SlotsType<{ + default: { foo: string; bar: number } // i want : default: { foo: T; bar: number }; + }>, + setup(props) { + return () => <> + }, +}) diff --git a/src/_pure/Popper/Trigger.tsx b/src/_pure/Popper/Trigger.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/_pure/Popper/usePopper.ts b/src/_pure/Popper/usePopper.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/_pure/PrimitiveSlot.ts b/src/_pure/PrimitiveSlot.ts new file mode 100644 index 00000000..3ee190eb --- /dev/null +++ b/src/_pure/PrimitiveSlot.ts @@ -0,0 +1,49 @@ +import { cloneVNode, Comment, defineComponent, Fragment, mergeProps, type VNode } from 'vue' + +function renderSlotFragments(children?: VNode[]): VNode[] { + if (!children) return [] + return children.flatMap(child => { + if (child.type === Fragment) return renderSlotFragments(child.children as VNode[]) + + return [child] + }) +} + +export const Slot = defineComponent({ + name: 'PrimitiveSlot', + inheritAttrs: false, + setup(_, { attrs, slots }) { + return () => { + if (!slots.default) return null + + const children = renderSlotFragments(slots.default()) + const firstNonCommentChildrenIndex = children.findIndex(child => child.type !== Comment) + if (firstNonCommentChildrenIndex === -1) return children + + const firstNonCommentChildren = children[firstNonCommentChildrenIndex]! + + // remove props ref from being inferred + delete firstNonCommentChildren.props?.ref + + const mergedProps = firstNonCommentChildren.props ? mergeProps(attrs, firstNonCommentChildren.props) : attrs + // remove class to prevent duplicated + if (attrs.class && firstNonCommentChildren.props?.class) delete firstNonCommentChildren.props.class + const cloned = cloneVNode(firstNonCommentChildren, mergedProps) + + // Explicitly override props starting with `on`. + // It seems cloneVNode from Vue doesn't like overriding `onXXX` props. + // So we have to do it manually. + for (const prop in mergedProps) { + if (prop.startsWith('on')) { + cloned.props ||= {} + cloned.props[prop] = mergedProps[prop] + } + } + + if (children.length === 1) return cloned + + children[firstNonCommentChildrenIndex] = cloned + return children + } + }, +}) diff --git a/tsconfig.json b/tsconfig.json index 366b4ca1..5e9abd8c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "extends": "@jaskang/tsconfig/vue", "compilerOptions": { "baseUrl": ".", + "jsxImportSource": "vue", "types": ["vite/client"], "paths": { "@/*": ["./src/*"]