diff --git a/packages/core/package.json b/packages/core/package.json index 530c72b2..1d44bc1d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -26,6 +26,10 @@ "types": "./dist/index.d.ts", "default": "./dist/index.js" }, + "./angular": { + "types": "./dist/index.angular.d.ts", + "default": "./dist/index.angular.js" + }, "./preact": { "types": "./dist/index.preact.d.ts", "default": "./dist/index.preact.js" @@ -68,6 +72,7 @@ "build": "tsdown" }, "devDependencies": { + "@angular/core": "^21.0.0", "@formisch/eslint-config": "workspace:*", "@preact/signals": "^2.2.1", "@qwik.dev/core": "2.0.0-beta.5", @@ -86,6 +91,7 @@ "vue": "^3.5.17" }, "peerDependencies": { + "@angular/core": ">=17.0.0", "@qwik.dev/core": "^2.0.0", "solid-js": "^1.6.0", "svelte": "^5.29.0", @@ -94,6 +100,9 @@ "vue": "^3.3.0" }, "peerDependenciesMeta": { + "@angular/core": { + "optional": true + }, "@preact/signals": { "optional": true }, diff --git a/packages/core/src/framework/index.angular.ts b/packages/core/src/framework/index.angular.ts new file mode 100644 index 00000000..8b1b81f0 --- /dev/null +++ b/packages/core/src/framework/index.angular.ts @@ -0,0 +1,52 @@ +import { signal } from '@angular/core'; +import type { Signal } from '../types/signal/index.ts'; +import type { Framework } from './index.ts'; + +export { untracked as untrack } from '@angular/core'; + +/** + * The current framework being used. + */ +export const framework: Framework = 'angular'; + +/** + * Creates a unique identifier string. + * + * @returns The unique identifier. + */ +// @__NO_SIDE_EFFECTS__ +export function createId(): string { + return Math.random().toString(36).slice(2); +} + +/** + * Creates a reactive signal with an initial value. + * + * @param initialValue The initial value. + * + * @returns The created signal. + */ +// @__NO_SIDE_EFFECTS__ +export function createSignal(initialValue: T): Signal { + const writableSignal = signal(initialValue); + return { + get value() { + return writableSignal(); + }, + set value(nextValue: T) { + writableSignal.set(nextValue); + }, + }; +} + +/** + * Batches multiple signal updates into a single update cycle. This is a + * no-op in Angular as batching is handled automatically. + * + * @param fn The function to execute. + * + * @returns The return value of the function. + */ +export function batch(fn: () => T): T { + return fn(); +} diff --git a/packages/core/src/framework/index.ts b/packages/core/src/framework/index.ts index 92ca0daa..05a119c1 100644 --- a/packages/core/src/framework/index.ts +++ b/packages/core/src/framework/index.ts @@ -6,6 +6,7 @@ import type { Signal } from '../types/index.ts'; * Framework type. */ export type Framework = + | 'angular' | 'preact' | 'qwik' | 'react' diff --git a/packages/core/tsdown.config.ts b/packages/core/tsdown.config.ts index e323f2ce..113b6da9 100644 --- a/packages/core/tsdown.config.ts +++ b/packages/core/tsdown.config.ts @@ -4,7 +4,7 @@ import { join } from 'node:path'; import type { RolldownPluginOption } from 'rolldown'; import { defineConfig, type UserConfig, type UserConfigFn } from 'tsdown'; -type Framework = 'preact' | 'qwik' | 'react' | 'solid' | 'svelte' | 'vue'; +type Framework = 'angular' | 'preact' | 'qwik' | 'react' | 'solid' | 'svelte' | 'vue'; /** * Rolldown plugin to rewrite framework-specific imports. @@ -85,6 +85,7 @@ function defineFrameworkConfig( return defineConfig({ entry: ['./src/index.ts'], external: [ + '@angular/core', '@preact/signals', '@qwik.dev/core', 'solid-js', @@ -115,6 +116,7 @@ function defineFrameworkConfig( const config: (UserConfig | UserConfigFn)[] = [ defineFrameworkConfig(null), + defineFrameworkConfig('angular'), defineFrameworkConfig('preact'), defineFrameworkConfig('qwik'), defineFrameworkConfig('react'), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bcb4a392..e8dd7142 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -395,6 +395,9 @@ importers: packages/core: devDependencies: + '@angular/core': + specifier: ^21.0.0 + version: 21.2.13(rxjs@7.8.2) '@formisch/eslint-config': specifier: workspace:* version: link:../eslint-config @@ -976,6 +979,19 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@angular/core@21.2.13': + resolution: {integrity: sha512-23tS4oNL8nvkHcI4l9rbruQs2WS4yqQmBVQxWakqS9cmRpArLGgveR+hKNU5tPXm5EAi8oLO34/Zy7z70jUpCg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@angular/compiler': 21.2.13 + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.15.0 || ~0.16.0 + peerDependenciesMeta: + '@angular/compiler': + optional: true + zone.js: + optional: true + '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} @@ -10638,6 +10654,11 @@ snapshots: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 + '@angular/core@21.2.13(rxjs@7.8.2)': + dependencies: + rxjs: 7.8.2 + tslib: 2.8.1 + '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)