Skip to content

Commit

Permalink
super type overloads for toRefs() added to make it much more versatil…
Browse files Browse the repository at this point in the history
…e, docs improved
  • Loading branch information
infinite-system committed Aug 20, 2024
1 parent 03b274e commit 06c5a2d
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 41 deletions.
4 changes: 2 additions & 2 deletions docs/docs/components/usage/CounterComposables.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class Counter {
increment() {
this.count++;
}
mouse = iuse(useMouse());
pointer = iuse(usePointer());
mouse = iuse(useMouse);
pointer = iuse(usePointer);
}
const counter = ivue(Counter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Counter {
y: this.y,
sum: this.sum,
total: this.total
} = iuse(useCustomMouse(5)));
} = iuse(useCustomMouse, 5));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { CustomMouse } from './classes/CustomMouse';
import { ivue, iref, iuse } from 'ivue';
import { ivue, iref } from '../../../../src/ivue';
class Counter {
count = iref(0);
Expand All @@ -10,11 +10,10 @@ class Counter {
this.count++;
}
/**
* 'x', 'y', 'total' are Refs that will be unwrapped to their bare raw types and destructured into the class.
* Even though unwrapped (de-Refed), they will maintain their behavior as Refs and thus will maintain reactivity
* and at the same time get destructured into this class root level scope because
* Even though unwrapped (de-Refed), they will maintain their behavior as Refs and thus will maintain reactivity
* and at the same time get destructured into this class root level scope because
* Vue 3's `reactive()` Proxy will be able to resolve those Refs internally.
*/
x: CustomMouse['x']; // Unwrapped Ref<number> becomes -> number
Expand All @@ -28,7 +27,7 @@ class Counter {
y: this.y,
sum: this.sum,
total: this.total,
} = iuse(CustomMouse, 5));
} = ivue(CustomMouse, 5).toRefs(true));
}
}
Expand All @@ -41,5 +40,7 @@ const counter = ivue(Counter);
<br />
Total (computed): {{ counter.total }}
<br />
<button class="button" @click="() => counter.sum()">Click This Big Sum Button To Total X + Y</button>
<button class="button" @click="() => counter.sum()">
Click This Big Sum Button To Total X + Y
</button>
</template>
2 changes: 1 addition & 1 deletion docs/docs/components/usage/classes/CustomMouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class CustomMouse {
_sum = iref(0);

constructor(public requiredProp: number) {
({ x: this.x, y: this.y } = iuse(useMouse()));
({ x: this.x, y: this.y } = iuse(useMouse));
}

sum() {
Expand Down
51 changes: 38 additions & 13 deletions docs/docs/pages/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CounterInternalRefs from '../components/usage/CounterInternalRefs.vue'
import CounterComposables from '../components/usage/CounterComposables.vue'
import CounterComposablesDestructuring from '../components/usage/CounterComposablesDestructuring.vue'
import CounterComposablesIvueDestructuring from '../components/usage/CounterComposablesIvueDestructuring.vue'
import CounterComposablesIvue from '../components/usage/CounterComposablesIvue.vue'
import CounterInsideComposables from '../components/usage/CounterInsideComposables.vue'
import CounterComputeds from '../components/usage/CounterComputeds.vue'
import CounterComputedsDisabled from '../components/usage/CounterComputedsDisabled.vue'
Expand Down Expand Up @@ -69,7 +70,7 @@ Classic Counter example built with `ivue`

See the highlighted sections related to props.
::: code-group
<<< @/components/usage/CounterWithProps.vue{5-8,11-12,24 vue:line-numbers}
<<< @/components/usage/CounterWithProps.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -91,7 +92,7 @@ See the highlighted sections related to props.
See the highlighted sections related to using emits.

::: code-group
<<< @/components/usage/CounterWithPropsAndEmits.vue{9-11,14,17,23,31 vue:line-numbers}
<<< @/components/usage/CounterWithPropsAndEmits.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -118,7 +119,7 @@ function onIncrement(value: number) {
### Refs defined externally in the component outside of the class.

::: code-group
<<< @/components/usage/CounterExternalRefs.vue{5,8,12,16,24 vue:line-numbers}
<<< @/components/usage/CounterExternalRefs.vue{vue:line-numbers}
:::
:::details For this example we initialize the component like this:

Expand All @@ -137,7 +138,7 @@ function onIncrement(value: number) {
### Refs defined internally inside of the class.

::: code-group
<<< @/components/usage/CounterInternalRefs.vue{7,15,25 vue:line-numbers}
<<< @/components/usage/CounterInternalRefs.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -160,7 +161,7 @@ function onIncrement(value: number) {
See the highlighted sections related to `defineExpose`.

::: code-group
<<< @/components/usage/CounterDefineExpose.vue{8 vue:line-numbers}
<<< @/components/usage/CounterDefineExpose.vue{vue:line-numbers}
<<< @/components/usage/CounterDefineExposeClass.ts{ts:line-numbers}
:::

Expand Down Expand Up @@ -200,7 +201,7 @@ function decrement() {
### Pick allowed interface properties for `defineExpose()`

::: code-group
<<< @/components/usage/CounterDefineExposeAdvanced.vue{9,23 vue:line-numbers}
<<< @/components/usage/CounterDefineExposeAdvanced.vue{vue:line-numbers}
:::

## Using Composables
Expand All @@ -209,7 +210,7 @@ function decrement() {

See the highlighted sections related to composable usage.
::: code-group
<<< @/components/usage/CounterComposables.vue{4,11,19 vue:line-numbers}
<<< @/components/usage/CounterComposables.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -231,7 +232,7 @@ See the highlighted sections related to composable usage.
See the highlighted sections related to destructuring composable usage.

::: code-group
<<< @/components/usage/CounterComposablesDestructuring.vue{4,10,20-21,23-24,27-32 vue:line-numbers}
<<< @/components/usage/CounterComposablesDestructuring.vue{vue:line-numbers}
<<< @/components/usage/functions/useCustomMouse.ts{ts:line-numbers} [functions/useCustomMouse.ts]
:::

Expand All @@ -249,12 +250,36 @@ See the highlighted sections related to destructuring composable usage.

<CounterComposablesDestructuring />


### Using `ivue` Composables Directly

Using `ivue` based composables assigned to a class property:

::: code-group
<<< @/components/usage/CounterComposablesIvue.vue{vue:line-numbers}
<<< @/components/usage/classes/CustomMouse.ts{ts:line-numbers} [classes/CustomMouse.ts]
:::

:::details For this example we initialize the component like this:

```vue
<template>
<CounterComposablesIvue />
</template>
```

:::

<div style="font-size: 18px; font-weight: 500;">Result</div>

<CounterComposablesIvue />

### Using `ivue` Composables With Destructuring

See the highlighted sections related to using `ivue` based composables.
See the sections related to using `ivue` based composables initialized through class destructuring assignment.

::: code-group
<<< @/components/usage/CounterComposablesIvueDestructuring.vue{14 vue:line-numbers}
<<< @/components/usage/CounterComposablesIvueDestructuring.vue{vue:line-numbers}
<<< @/components/usage/classes/CustomMouse.ts{ts:line-numbers} [classes/CustomMouse.ts]
:::

Expand All @@ -278,7 +303,7 @@ See the highlighted sections related to using `ivue` based composables.
See the highlighted sections related to using `ivue` inside a composable.

::: code-group
<<< @/components/usage/CounterInsideComposables.vue{14 vue:line-numbers}
<<< @/components/usage/CounterInsideComposables.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -301,7 +326,7 @@ See the highlighted sections related to using `ivue` inside a composable.
See the highlighted sections related to getters.

::: code-group
<<< @/components/usage/CounterComputeds.vue{10,13,23,24 vue:line-numbers}
<<< @/components/usage/CounterComputeds.vue{vue:line-numbers}
:::

:::details For this example we initialize the component like this:
Expand All @@ -319,7 +344,7 @@ See the highlighted sections related to getters.
You can disable computed getters via `static ivue = { getter: false }`, see below:

::: code-group
<<< @/components/usage/CounterComputedsDisabled.vue{10-12 vue:line-numbers}
<<< @/components/usage/CounterComputedsDisabled.vue{vue:line-numbers}
:::

The result of this example is identical to the above.
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-vue": "^9.14.1",
"execa": "^8.0.0",
"ivue": "^1.2.0",
"ivue": "^1.2.1",
"typescript": "^4.5.4",
"vite-plugin-dynamic-import": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",
Expand Down
8 changes: 4 additions & 4 deletions docs/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2193,10 +2193,10 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==

ivue@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ivue/-/ivue-1.2.0.tgz#dfcd014c123d82f647d94bcab356179dce2ec3ff"
integrity sha512-IGhB63qOmDvp+U2mh3UnGCSstljLtyfPzQOCqqEicpHQpZIcWX/NYKDp84ykErZ0GU9Q1L9nzLH2JbVmued6+A==
ivue@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ivue/-/ivue-1.2.1.tgz#a80b8a0c660c649c9ee644e5968abe6366c87a73"
integrity sha512-pBgv8gF1UaT6Rou+NyHB6w7pIhzXQFLvZ3xz6i8ls5HQXHMKHNp5xF/qyTpgt7ug05/LauKjysq6CkIJLP81uA==

js-tokens@^4.0.0:
version "4.0.0"
Expand Down
36 changes: 23 additions & 13 deletions src/ivue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ export interface ExtendWithToRefs<T extends AnyClass> {
}

/**
* .toRefs() method type definition converts reactive class properties to composable .value properties.
*/
export type IVueToRefsFn<T extends AnyClass> = (
props?: (keyof InstanceType<T>)[]
) => IVueRefs<InstanceType<T>>;
* Type definition for `.toRefs()` method converts reactive class properties to composable .value properties.
* But if unwrap = true is specified, the refs will be unwrapped refs available to be merged with the the root class properties.
*/
export interface IVueToRefsFn<T extends AnyClass> {
<P extends keyof InstanceType<T>, B extends boolean>(
props: P[],
unwrap?: B
): B extends true
? Pick<InstanceType<T>, P>
: Pick<IVueRefs<InstanceType<T>>, P>;
(props: true): InstanceType<T>;
(props: false): IVueRefs<InstanceType<T>>;
(): IVueRefs<InstanceType<T>>;
}

/**
* Converts a class properties to a composable .value Refs using ToRef vue type,
Expand Down Expand Up @@ -315,8 +324,8 @@ export function getAllClassProperties(obj: object): Set<string> {
}

/**
* `iref()` is an alias for Vue ref() function but returns an unwrapped type without the .value
* `iref()` does not alter the behavior of ref(), but simply transforms the type to an unwrapped raw value.
* `iref()` is an alias for Vue ref() function but returns an unwrap type without the .value
* `iref()` does not alter the behavior of ref(), but simply transforms the type to an unwrap raw value.
* @param val T
* @returns {UnwrapRef<T>}
*/
Expand All @@ -325,7 +334,7 @@ export const iref = ref as <T = any>(value?: T) => T;
/**
* Three modes of operation:
* 1. `iuse(useComposable(arg, arg2, arg3, ...))` converts the return types of a Composable / Ref to pure raw type definition.
* Returns for all properties of an object an unwrapped raw type definition,
* Returns for all properties of an object an unwrap raw type definition,
* unwraps direct Refs & ComputedRefs as well down to their raw types.
*
* 2. `iuse(useComposable, arg, arg2, arg3, ...)` for cleaner syntax for #1, it does exactly the same thing but
Expand All @@ -337,7 +346,7 @@ export const iref = ref as <T = any>(value?: T) => T;
* it returns an 'ivue(AnyClass, ...args).toRefs()` object for all properties but casts
* their types as raw (no-Ref) types to fit with reactive() structure of the ivue class context.
*/
export function iuse<T extends AnyClass | AnyFn | Object>(
export function iuse<T extends AnyClass | AnyFn | Object | any>(
classFunctionObject?: T,
...args: T extends AnyClass
? InferredArgs<T>
Expand Down Expand Up @@ -375,13 +384,14 @@ function ivueToRefs<T extends AnyClass>(
computeds: Computeds
): ExtendWithToRefs<T>['toRefs'] {
return function (
props?: (keyof InstanceType<T>)[]
): IVueRefs<InstanceType<T>> {
props?: (keyof InstanceType<T>)[] | boolean,
unwrap?: boolean
): any /** @see {ReturnType<IVueToRefsFn<T>>} */ {
/** Resulting refs store. */
const result: Record<string | number | symbol, any> = {};

/** Output specific props only, if props are specified. */
if (Array.isArray(props) && props.length) {
if (Array.isArray(props)) {
for (let i = 0; i < props.length; i++) {
const prop = props[i] as any;
/** Handle descriptors. */
Expand Down Expand Up @@ -442,7 +452,7 @@ function ivueToRefs<T extends AnyClass>(
allProps = null;
}

return result as IVueRefs<InstanceType<T>>;
return result as any;
};
}

Expand Down

0 comments on commit 06c5a2d

Please sign in to comment.