glimmerjs/glimmer-vm

curry method for JS use

Opened this issue · 0 comments

import { type ComponentLike } from '@glint/template';
import {
	type ComponentSignatureArgs,
	type ComponentSignatureBlocks,
	type ComponentSignatureElement,
} from '@glint/template/-private/signature';

import type Owner from '@ember/owner';
import { createPrimitiveRef } from '@glimmer/reference';
import { curry } from '@glimmer/runtime';

// From @glimmer/interfaces
export const enum CurriedType {
	Component = 0,
	Helper = 1,
	Modifier = 2,
}

export class CurriedValue<_T extends CurriedType = CurriedType> {}

/**
 * Attaches arguments to a component.
 *
 * This function behaves like the `{{component}}` helper but without the string lookup
 * behavior.
 */
export function curryComponent<S, ArgKeys extends keyof ComponentSignatureArgs<S>['Named']>(
	component: ComponentLike<S>,
	owner: Owner,
	args: { [K in ArgKeys]: ComponentSignatureArgs<S>['Named'][K] },
): ComponentLike<{
	Element: ComponentSignatureElement<S>;
	Args: {
		Named: Omit<ComponentSignatureArgs<S>['Named'], ArgKeys> &
			Partial<Pick<ComponentSignatureArgs<S>['Named'], ArgKeys>>;
		Positional: ComponentSignatureArgs<S>['Positional'];
	};
	Blocks: ComponentSignatureBlocks<S>;
}> {
	const mappedArgs = Object.fromEntries(Object.entries(args).map(([key, value]) => [key, createPrimitiveRef(value)]));
	// SAFETY: Not actually safe, but it should be correct in practice
	return curry(0, component, owner, { named: mappedArgs, positional: [] }) as any;
}