1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-20 10:54:44 +00:00

42 Commits

Author SHA1 Message Date
renovate[bot]
8ced5feae1 chore(deps): update vitest monorepo to v4 2026-01-31 01:45:30 +00:00
renovate[bot]
6fcc9d5a51 chore(deps): update all non-major dependencies (#116)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-31 01:44:27 +00:00
renovate[bot]
289d0d5af1 chore(deps): update all non-major dependencies (#115)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-17 01:52:33 +00:00
4bade839e7 Merge pull request #107 from robonen/renovate/renovate-42.x
chore(deps): update devdependency renovate to v42
2026-01-13 15:58:01 +03:00
renovate[bot]
c4321a2039 chore(deps): update devdependency renovate to v42 2026-01-13 12:56:13 +00:00
f6b3bfbca6 Merge pull request #109 from robonen/renovate/actions-checkout-6.x
chore(deps): update actions/checkout action to v6
2026-01-13 15:55:02 +03:00
renovate[bot]
7541e6aad4 chore(deps): update actions/checkout action to v6 2026-01-04 01:09:12 +00:00
renovate[bot]
a4d9b4c88a chore(deps): update all non-major dependencies (#114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-04 01:08:54 +00:00
renovate[bot]
3b39f64734 chore(deps): update all non-major dependencies (#113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 01:03:01 +00:00
renovate[bot]
6ab2d5cebf chore(deps): update all non-major dependencies (#112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-17 01:02:35 +00:00
renovate[bot]
54f1facc4f chore(deps): update all non-major dependencies (#111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 01:05:02 +00:00
renovate[bot]
717c41ef88 chore(deps): update all non-major dependencies (#110)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 01:51:25 +00:00
renovate[bot]
3747f5213e chore(deps): update all non-major dependencies (#108)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-16 01:48:53 +00:00
daf18871a0 Merge pull request #106 from robonen/renovate/node-24.x
chore(deps): update node.js to v24
2025-11-05 19:09:26 +03:00
renovate[bot]
8bf9943e9e chore(deps): update node.js to v24 2025-11-03 06:47:48 +00:00
renovate[bot]
0e67715d9e chore(deps): update all non-major dependencies (#105)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-03 01:29:17 +00:00
renovate[bot]
3e43e4db3d chore(deps): update all non-major dependencies (#103)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-25 01:44:03 +00:00
b8308e383c Merge pull request #99 from robonen/renovate/jsdom-27.x
chore(deps): update pnpm.catalog.default jsdom to v27
2025-10-23 09:58:09 +03:00
renovate[bot]
93c878cc35 chore(deps): update pnpm.catalog.default jsdom to v27 2025-10-23 06:56:36 +00:00
7653975fa4 Merge pull request #102 from robonen/renovate/actions-setup-node-6.x
chore(deps): update actions/setup-node action to v6
2025-10-23 09:52:09 +03:00
renovate[bot]
e2cb3f5a75 chore(deps): update actions/setup-node action to v6 2025-10-14 05:25:23 +00:00
renovate[bot]
67fbad8930 chore(deps): update all non-major dependencies (#101)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 01:41:58 +00:00
renovate[bot]
e49c49e320 chore(deps): update all non-major dependencies (#100)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-26 01:45:40 +00:00
renovate[bot]
43cdc3b5e6 chore(deps): update all non-major dependencies (#98)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-15 01:40:15 +00:00
a9a6c04176 Merge pull request #97 from robonen/renovate/actions-setup-node-5.x
chore(deps): update actions/setup-node action to v5
2025-09-06 15:37:33 +03:00
a6d3e8971f Merge branch 'master' into renovate/actions-setup-node-5.x 2025-09-06 15:36:20 +03:00
40dfdabd08 Merge pull request #96 from robonen/chore/deps
chore: update deps
2025-09-06 15:36:02 +03:00
renovate[bot]
876a815fd3 chore(deps): update actions/setup-node action to v5 2025-09-06 12:35:00 +00:00
b1b9889ad2 chore: update deps 2025-09-06 19:34:30 +07:00
renovate[bot]
9d2a393372 chore(deps): update all non-major dependencies (#95)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-22 01:07:02 +00:00
renovate[bot]
4071e49ad6 chore(deps): update all non-major dependencies (#92)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-16 01:13:12 +00:00
88bd87f9b0 Merge pull request #93 from robonen/renovate/actions-checkout-5.x
chore(deps): update actions/checkout action to v5
2025-08-15 00:45:05 +03:00
renovate[bot]
ac265c05a8 chore(deps): update actions/checkout action to v5 2025-08-14 21:44:00 +00:00
69e5ebc085 Merge pull request #94 from robonen/feat/vue/unrefElement
feat(web/vue): unrefElement
2025-08-15 00:41:59 +03:00
48a85dbae2 build(web/vue): bump version to 0.0.11 2025-08-15 04:39:37 +07:00
0cfdce7456 docs(web/vue): update examples in unrefElement documentation to include type parameters 2025-08-15 04:38:46 +07:00
e035d1abca docs(web/vue): update documentation for unrefElement function 2025-08-15 04:37:58 +07:00
1851d5c80c feat(web/vue): add unrefElement function and tests for element handling 2025-08-15 04:33:47 +07:00
48626a9fe5 Merge pull request #91 from robonen/refactor/web/vue
refactor(web/vue): reuse injection context composable in injection store
2025-08-07 05:28:14 +07:00
04aa9e4721 build(web/vue): bump version to 0.0.10 2025-08-07 05:26:02 +07:00
d55e3989f3 refactor(web/vue): reuse inject context composable in context state 2025-08-07 05:25:04 +07:00
renovate[bot]
acee7e4167 chore(deps): update all non-major dependencies (#90)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-02 01:50:33 +00:00
14 changed files with 2755 additions and 2744 deletions

View File

@@ -16,14 +16,14 @@ jobs:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm

View File

@@ -13,7 +13,7 @@ jobs:
name: Check version changes and publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
@@ -22,7 +22,7 @@ jobs:
with:
run_install: false
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm

View File

@@ -15,9 +15,9 @@
"url": "git+https://github.com/robonen/tools.git",
"directory": "packages/tsconfig"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"files": [
"**tsconfig.json"

View File

@@ -18,9 +18,9 @@
"url": "git+https://github.com/robonen/tools.git",
"directory": "packages/platform"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"type": "module",
"files": [

View File

@@ -18,9 +18,9 @@
"url": "git+https://github.com/robonen/tools.git",
"directory": "packages/stdlib"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"type": "module",
"files": [

View File

@@ -16,9 +16,9 @@
"url": "git+https://github.com/robonen/tools.git",
"directory": "packages/renovate"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"files": [
"default.json"
@@ -27,6 +27,6 @@
"test": "renovate-config-validator ./default.json"
},
"devDependencies": {
"renovate": "^41.43.5"
"renovate": "^42.95.2"
}
}

View File

@@ -15,20 +15,20 @@
"type": "git",
"url": "git+https://github.com/robonen/tools.git"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"type": "module",
"devDependencies": {
"@types/node": "^22.16.5",
"citty": "^0.1.6",
"jiti": "^2.5.1",
"scule": "^1.3.0",
"jsdom": "catalog:",
"vitest": "catalog:",
"@types/node": "^24.10.9",
"@vitest/coverage-v8": "catalog:",
"@vitest/ui": "catalog:"
"@vitest/ui": "catalog:",
"citty": "^0.2.0",
"jiti": "^2.6.1",
"jsdom": "catalog:",
"scule": "^1.3.0",
"vitest": "catalog:"
},
"scripts": {
"build": "pnpm -r build",

5294
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,11 +5,11 @@ packages:
- web/*
catalog:
'@vitest/coverage-v8': ^3.2.4
'@vitest/coverage-v8': ^4.0.18
'@vue/test-utils': ^2.4.6
jsdom: ^26.1.0
jsdom: ^27.4.0
pathe: ^2.0.3
unbuild: 3.6.0
vitest: ^3.2.4
'@vitest/ui': ^3.2.4
vue: ^3.5.18
unbuild: 3.6.1
vitest: ^4.0.18
'@vitest/ui': ^4.0.18
vue: ^3.5.27

View File

@@ -1,6 +1,6 @@
{
"name": "@robonen/vue",
"version": "0.0.9",
"version": "0.0.11",
"license": "Apache-2.0",
"description": "Collection of powerful tools for Vue",
"keywords": [
@@ -16,9 +16,9 @@
"url": "git+https://github.com/robonen/tools.git",
"directory": "./packages/vue"
},
"packageManager": "pnpm@10.13.1",
"packageManager": "pnpm@10.28.2",
"engines": {
"node": ">=22.17.1"
"node": ">=24.13.0"
},
"type": "module",
"files": [
@@ -37,13 +37,13 @@
"build": "unbuild"
},
"devDependencies": {
"@robonen/platform": "workspace:*",
"@robonen/stdlib": "workspace:*",
"@robonen/tsconfig": "workspace:*",
"@vue/test-utils": "catalog:",
"unbuild": "catalog:"
},
"dependencies": {
"@robonen/platform": "workspace:*",
"@robonen/stdlib": "workspace:*",
"vue": "catalog:"
}
}

View File

@@ -0,0 +1,61 @@
import { describe, expect, it } from 'vitest';
import { computed, defineComponent, nextTick, ref, shallowRef } from 'vue';
import { mount } from '@vue/test-utils'
import { unrefElement } from '.';
describe('unrefElement', () => {
it('returns a plain element when passed a raw element', () => {
const htmlEl = document.createElement('div');
const svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
expect(unrefElement(htmlEl)).toBe(htmlEl);
expect(unrefElement(svgEl)).toBe(svgEl);
});
it('returns element when passed a ref or shallowRef to an element', () => {
const el = document.createElement('div');
const elRef = ref<HTMLElement | null>(el);
const shallowElRef = shallowRef<HTMLElement | null>(el);
expect(unrefElement(elRef)).toBe(el);
expect(unrefElement(shallowElRef)).toBe(el);
});
it('returns element when passed a computed ref or getter function', () => {
const el = document.createElement('div');
const computedElRef = computed(() => el);
const elGetter = () => el;
expect(unrefElement(computedElRef)).toBe(el);
expect(unrefElement(elGetter)).toBe(el);
});
it('returns component $el when passed a component instance', async () => {
const Child = defineComponent({
template: `<span class="child-el">child</span>`,
});
const Parent = defineComponent({
components: { Child },
template: `<Child ref="childRef" />`,
});
const wrapper = mount(Parent);
await nextTick();
const childInstance = (wrapper.vm as any).$refs.childRef;
const result = unrefElement(childInstance);
expect(result).toBe(childInstance.$el);
expect((result as HTMLElement).classList.contains('child-el')).toBe(true);
});
it('handles null and undefined values', () => {
expect(unrefElement(undefined)).toBe(undefined);
expect(unrefElement(null)).toBe(null);
expect(unrefElement(ref(null))).toBe(null);
expect(unrefElement(ref(undefined))).toBe(undefined);
expect(unrefElement(() => null)).toBe(null);
expect(unrefElement(() => undefined)).toBe(undefined);
});
});

View File

@@ -0,0 +1,33 @@
import type { ComponentPublicInstance, MaybeRef, MaybeRefOrGetter } from 'vue';
import { toValue } from 'vue';
export type VueInstance = ComponentPublicInstance;
export type MaybeElement = HTMLElement | SVGElement | VueInstance | undefined | null;
export type MaybeElementRef<El extends MaybeElement = MaybeElement> = MaybeRef<El>;
export type MaybeComputedElementRef<El extends MaybeElement = MaybeElement> = MaybeRefOrGetter<El>;
export type UnRefElementReturn<T extends MaybeElement = MaybeElement> = T extends VueInstance ? Exclude<MaybeElement, VueInstance> : T | undefined;
/**
* @name unrefElement
* @category Components
* @description Unwraps a Vue element reference to get the underlying instance or DOM element.
*
* @param {MaybeComputedElementRef<El>} elRef - The element reference to unwrap.
* @returns {UnRefElementReturn<El>} - The unwrapped element or undefined.
*
* @example
* const element = useTemplateRef<HTMLElement>('element');
* const result = unrefElement(element); // result is the element instance
*
* @example
* const component = useTemplateRef<Component>('component');
* const result = unrefElement(component); // result is the component instance
*
* @since 0.0.11
*/
export function unrefElement<El extends MaybeElement>(elRef: MaybeComputedElementRef<El>): UnRefElementReturn<El> {
const plain = toValue(elRef);
return (plain as VueInstance)?.$el ?? plain;
}

View File

@@ -1,4 +1,4 @@
import { inject, provide, type InjectionKey, type App } from 'vue';
import { inject as vueInject, provide as vueProvide, type InjectionKey, type App } from 'vue';
import { VueToolsError } from '../..';
/**
@@ -34,8 +34,8 @@ import { VueToolsError } from '../..';
export function useContextFactory<ContextValue>(name: string) {
const injectionKey: InjectionKey<ContextValue> = Symbol(name);
const injectContext = <Fallback extends ContextValue = ContextValue>(fallback?: Fallback) => {
const context = inject(injectionKey, fallback);
const inject = <Fallback extends ContextValue = ContextValue>(fallback?: Fallback) => {
const context = vueInject(injectionKey, fallback);
if (context !== undefined)
return context;
@@ -43,8 +43,8 @@ export function useContextFactory<ContextValue>(name: string) {
throw new VueToolsError(`useContextFactory: '${name}' context is not provided`);
};
const provideContext = (context: ContextValue) => {
provide(injectionKey, context);
const provide = (context: ContextValue) => {
vueProvide(injectionKey, context);
return context;
};
@@ -54,8 +54,8 @@ export function useContextFactory<ContextValue>(name: string) {
};
return {
inject: injectContext,
provide: provideContext,
inject,
provide,
appProvide,
key: injectionKey,
}

View File

@@ -1,7 +1,8 @@
import { inject, provide, type App, type InjectionKey } from 'vue';
import { useContextFactory } from '../useContextFactory';
import type { App, InjectionKey } from 'vue';
export interface useInjectionStoreOptions<Return> {
injectionKey: string | InjectionKey<Return>;
injectionName?: string;
defaultValue?: Return;
}
@@ -9,28 +10,28 @@ export interface useInjectionStoreOptions<Return> {
* @name useInjectionStore
* @category State
* @description Create a global state that can be injected into components
*
*
* @param {Function} stateFactory A factory function that creates the state
* @param {useInjectionStoreOptions} options An object with the following properties
* @param {string | InjectionKey} options.injectionKey The key to use for the injection
* @param {any} options.defaultValue The default value to use when the state is not provided
* @returns {Object} An object with `useProvidingState`, `useAppProvidingState`, and `useInjectedState` functions
*
*
* @example
* const { useProvidingState, useInjectedState } = useInjectionStore(() => ref('Hello World'));
*
*
* // In a parent component
* const state = useProvidingState();
*
*
* // In a child component
* const state = useInjectedState();
*
*
* @example
* const { useProvidingState, useInjectedState } = useInjectionStore(() => ref('Hello World'), {
* injectionKey: 'MyState',
* defaultValue: 'Default Value'
* });
*
*
* // In a plugin
* {
* install(app) {
@@ -38,31 +39,31 @@ export interface useInjectionStoreOptions<Return> {
* state.value = 'Hello World';
* }
* }
*
*
* // In a component
* const state = useInjectedState();
*
*
* @since 0.0.5
*/
export function useInjectionStore<Args extends any[], Return>(
stateFactory: (...args: Args) => Return,
options?: useInjectionStoreOptions<Return>,
options?: useInjectionStoreOptions<Return>
) {
const key = options?.injectionKey ?? Symbol(stateFactory.name ?? 'InjectionStore');
const ctx = useContextFactory<Return>(options?.injectionName ?? stateFactory.name ?? 'InjectionStore');
const useProvidingState = (...args: Args) => {
const state = stateFactory(...args);
provide(key, state);
ctx.provide(state);
return state;
};
const useAppProvidingState = (app: App) => (...args: Args) => {
const state = stateFactory(...args);
app.provide(key, state);
ctx.appProvide(app)(state);
return state;
};
const useInjectedState = () => inject(key, options?.defaultValue);
const useInjectedState = () => ctx.inject(options?.defaultValue);
return {
useProvidingState,