vue-unwrap 1.1.0 → 2.0.0

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 CHANGED
@@ -31,11 +31,14 @@ import { getNodeElement, Unwrap } from 'vue-unwrap'
31
31
 
32
32
  const ctx = useTemplateRef<typeof Unwrap>('ctx')
33
33
 
34
- const $children = computed(() => ctx.value?.children.map(getNodeElement))
34
+ const childElements = computed(() => ctx.value?.children.map(getNodeElement))
35
+ const rootElement = computed(() => ctx.value?.root)
35
36
  </script>
36
37
 
37
38
  <template>
38
- <Unwrap ref="ctx" />
39
+ <Unwrap ref="ctx" is="div">
40
+ <p>Lorem ipsum</p>
41
+ </Unwrap>
39
42
  </template>
40
43
 
41
44
  ```
@@ -45,25 +48,21 @@ const $children = computed(() => ctx.value?.children.map(getNodeElement))
45
48
  ```vue
46
49
  <script setup lang="ts">
47
50
  import type { ComponentPublicInstance } from 'vue'
48
- import { useUnwrap } from 'vue-unwrap'
51
+ import { computed } from 'vue'
52
+ import { useUnwrap, type NodeRef } from 'vue-unwrap'
49
53
 
50
54
  // your component props definition
51
- type PropsType = { foo: string }
55
+ type PropsType = { foo: string }
52
56
 
53
57
  // your child nodes definition
54
- type CustomNodeType = (
55
- | ComponentPublicInstance<{ bar: string }>
56
- | ComponentPublicInstance
57
- | Element
58
- | null
59
- )
58
+ type CustomNodeType = ComponentPublicInstance<{ bar: string }> | NodeRef
60
59
 
61
60
  const props = defineProps<PropsType>()
62
61
 
63
- const { $el, children, Unwrap } = useUnwrap<CustomNodeType, PropsType>()
62
+ const { root, children, Unwrap } = useUnwrap<CustomNodeType, PropsType>()
64
63
 
65
64
  const bars = computed(() => (
66
- children?
65
+ children
67
66
  .map(child => (
68
67
  (child && 'bar' in child)
69
68
  ? `${props.foo}-${child.bar}`
@@ -79,6 +78,63 @@ const bars = computed(() => (
79
78
 
80
79
  ```
81
80
 
81
+ ## API
82
+
83
+ ### `Unwrap`
84
+
85
+ Conditional wrapper component. Pass **`is`** to render a wrapper element or component; omit it to render slot children directly with no extra DOM node.
86
+
87
+ When used with a template ref, the component instance exposes:
88
+
89
+ | Property | Type | Description |
90
+ | --- | --- | --- |
91
+ | `children` | `NodeRef[]` | Reactive refs to each unwrapped child node |
92
+ | `root` | `Element \| null` | The wrapper DOM element when `is` is set; otherwise `null` |
93
+
94
+ Remaining attributes (except `is`) are forwarded to the wrapper when one is rendered.
95
+
96
+ ### `useUnwrap<N, P>(propTypes?)`
97
+
98
+ Composable for building custom wrapper components. Returns `{ children, root, Unwrap }` with the same semantics as the component above.
99
+
100
+ - **`N`** — type of each entry in `children` (defaults to `NodeRef`)
101
+ - **`P`** — props type passed to the default slot render function
102
+ - **`propTypes`** — optional Vue props definition merged onto the returned `Unwrap` render function, so declared props are forwarded to slot content
103
+
104
+ ```vue
105
+ <script setup lang="ts">
106
+ import { useUnwrap, type NodeRef } from 'vue-unwrap'
107
+
108
+ const { Unwrap } = useUnwrap<NodeRef, { count: number }>({
109
+ count: { type: Number, default: 0 },
110
+ })
111
+ </script>
112
+
113
+ <template>
114
+ <Unwrap :count="3" v-slot="{ count }">
115
+ <span>{{ count }} items</span>
116
+ </Unwrap>
117
+ </template>
118
+ ```
119
+
120
+ Use the returned **`Unwrap`** in your template as the render target (typically with `<Unwrap />` and a default slot).
121
+
122
+ ### `NodeRef`
123
+
124
+ ```ts
125
+ type NodeRef = Element | ComponentPublicInstance | null
126
+ ```
127
+
128
+ Default type for entries in `children`.
129
+
130
+ ### `getNodeElement(node)`
131
+
132
+ Resolves a child ref to its DOM `Element`. For component instances, returns `$el`; for plain elements, returns the element itself; otherwise returns `null`.
133
+
134
+ ### `unwrapVNodes(vnodes)`
135
+
136
+ Utility that flattens slot VNodes into a flat array, unwrapping `Fragment` nodes and skipping comments and empty values. Used internally by `useUnwrap`; exported for advanced custom render logic.
137
+
82
138
  ## Development
83
139
 
84
140
  - Install dependencies:
@@ -90,7 +146,7 @@ npm install
90
146
  - Run the playground:
91
147
 
92
148
  ```bash
93
- npm run playground
149
+ npm run play
94
150
  ```
95
151
 
96
152
  - Run the unit tests:
package/dist/index.d.ts CHANGED
@@ -1,21 +1,17 @@
1
1
  import * as _$vue from "vue";
2
2
  import { ComponentPublicInstance, SetupContext, VNode, VNodeArrayChildren } from "vue";
3
3
 
4
- //#region src/useUnwrap.d.ts
4
+ //#region src/types.d.ts
5
5
  type NodeRef = Element | ComponentPublicInstance | null;
6
- declare function getNodeElement<N = NodeRef>(node: N): Element | null;
7
- declare function unwrapVNodes(vnodes: VNodeArrayChildren): VNode[];
6
+ //#endregion
7
+ //#region src/useUnwrap.d.ts
8
8
  declare function useUnwrap<N = NodeRef, P = Record<string, any>>(propTypes?: Record<string, any>): {
9
- $el: _$vue.ShallowRef<Element | null, Element | null>;
10
9
  children: _$vue.ShallowReactive<N[]>;
11
- dom: _$vue.ComputedRef<{
12
- el: Element | null;
13
- children: _$vue.ShallowReactive<N[]>;
14
- }>;
10
+ root: _$vue.ShallowRef<Element | null, Element | null>;
15
11
  Unwrap: {
16
- (props: P, context: SetupContext): VNode<_$vue.RendererNode, _$vue.RendererElement, {
12
+ (props: P, context: SetupContext): _$vue.VNode<_$vue.RendererNode, _$vue.RendererElement, {
17
13
  [key: string]: any;
18
- }> | VNode<_$vue.RendererNode, _$vue.RendererElement, {
14
+ }> | _$vue.VNode<_$vue.RendererNode, _$vue.RendererElement, {
19
15
  [key: string]: any;
20
16
  }>[];
21
17
  inheritAttrs: boolean;
@@ -25,30 +21,15 @@ declare function useUnwrap<N = NodeRef, P = Record<string, any>>(propTypes?: Rec
25
21
  };
26
22
  };
27
23
  //#endregion
24
+ //#region src/utils.d.ts
25
+ declare function getNodeElement<N = NodeRef>(node: N): Element | null;
26
+ declare function unwrapVNodes(vnodes: VNodeArrayChildren): VNode[];
27
+ //#endregion
28
28
  //#region src/Unwrap.vue.d.ts
29
- declare const dom: _$vue.ComputedRef<{
30
- el: Element | null;
31
- children: _$vue.ShallowReactive<NodeRef[]>;
32
- }>;
33
- type __VLS_Slots = {
34
- default(props: {
35
- dom: typeof dom;
36
- }): any;
37
- };
38
- declare const __VLS_base: _$vue.DefineComponent<{}, {
39
- $el: _$vue.ShallowRef<Element | null, Element | null>;
29
+ declare const __VLS_export: _$vue.DefineComponent<{}, {
40
30
  children: _$vue.ShallowReactive<NodeRef[]>;
41
- dom: _$vue.ComputedRef<{
42
- el: Element | null;
43
- children: _$vue.ShallowReactive<NodeRef[]>;
44
- }>;
31
+ root: _$vue.ShallowRef<Element | null, Element | null>;
45
32
  }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
46
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
47
33
  declare const _default: typeof __VLS_export;
48
- type __VLS_WithSlots<T, S> = T & {
49
- new (): {
50
- $slots: S;
51
- };
52
- };
53
34
  //#endregion
54
35
  export { NodeRef, _default as Unwrap, getNodeElement, unwrapVNodes, useUnwrap };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Comment, Fragment, cloneVNode, computed, createBlock, defineComponent, h, isVNode, openBlock, shallowReactive, shallowRef, unref, useSlots } from "vue";
2
- //#region src/useUnwrap.ts
1
+ import { Comment, Fragment, cloneVNode, createBlock, defineComponent, h, isVNode, openBlock, shallowReactive, shallowRef, unref, useSlots } from "vue";
2
+ //#region src/utils.ts
3
3
  function getNodeElement(node) {
4
4
  const el = node?.$el || node;
5
5
  return el instanceof Element ? el : null;
@@ -18,29 +18,26 @@ function unwrapVNodes(vnodes) {
18
18
  }
19
19
  return nodes;
20
20
  }
21
+ //#endregion
22
+ //#region src/useUnwrap.ts
21
23
  function useUnwrap(propTypes) {
22
- const $el = shallowRef(null);
23
24
  const children = shallowReactive([]);
24
- const dom = computed(() => ({
25
- el: $el.value,
26
- children
27
- }));
25
+ const root = shallowRef(null);
28
26
  const slots = useSlots();
29
27
  const trackChildRef = (index) => (node) => children[index] = node;
30
- const trackWrapperRef = (node) => $el.value = getNodeElement(node);
28
+ const trackRootRef = (node) => root.value = getNodeElement(node);
31
29
  function Unwrap(props, context) {
32
30
  const { is, ...attrs } = context.attrs;
33
- const nodes = unwrapVNodes(slots.default?.(props) ?? []).map((node, i) => cloneVNode(node, { ref: trackChildRef(i) }, true));
34
- const wrapper = is ? cloneVNode(h(is, attrs, nodes), { ref: trackWrapperRef }, true) : null;
35
- children.splice(nodes.length);
36
- return wrapper || nodes;
31
+ const childNodes = unwrapVNodes(slots.default?.(props) ?? []).map((node, i) => cloneVNode(node, { ref: trackChildRef(i) }, true));
32
+ const rootNode = is ? cloneVNode(h(is, attrs, childNodes), { ref: trackRootRef }, true) : null;
33
+ children.splice(childNodes.length);
34
+ return rootNode || childNodes;
37
35
  }
38
36
  Unwrap.inheritAttrs = false;
39
37
  Unwrap.props = { ...propTypes };
40
38
  return {
41
- $el,
42
39
  children,
43
- dom,
40
+ root,
44
41
  Unwrap
45
42
  };
46
43
  }
@@ -49,14 +46,13 @@ function useUnwrap(propTypes) {
49
46
  var Unwrap_default = /* @__PURE__ */ defineComponent({
50
47
  __name: "Unwrap",
51
48
  setup(__props, { expose: __expose }) {
52
- const { $el, children, dom, Unwrap } = useUnwrap();
49
+ const { children, root, Unwrap } = useUnwrap();
53
50
  __expose({
54
- $el,
55
51
  children,
56
- dom
52
+ root
57
53
  });
58
54
  return (_ctx, _cache) => {
59
- return openBlock(), createBlock(unref(Unwrap), { dom: unref(dom) }, null, 8, ["dom"]);
55
+ return openBlock(), createBlock(unref(Unwrap));
60
56
  };
61
57
  }
62
58
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vue-unwrap",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "2.0.0",
5
5
  "description": "Conditional wrapper component for Vue 3 with child ref aggregation.",
6
6
  "author": "Andrea 'Fiad' Fiadone <hello@fiad.one>",
7
7
  "license": "MIT",