Skip to content

Commit dc232a2

Browse files
Merge pull request #692 from studiometa/bugfix/register-child-components
[Bugfix] Add child components to the registry
2 parents ad4c38a + cf900d7 commit dc232a2

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format
44

55
## [Unreleased]
66

7+
### Fixed
8+
9+
- Fix registering child components ([#690](https://github.com/studiometa/js-toolkit/issues/690), [#692](https://github.com/studiometa/js-toolkit/pull/692), [3ee1cc3b](https://github.com/studiometa/js-toolkit/commit/3ee1cc3b))
10+
711
## [v3.4.0](https://github.com/studiometa/js-toolkit/compare/3.3.0..3.4.0) (2025-11-03)
812

913
### Added

packages/global.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
import { Base, BaseConstructor } from './js-toolkit/Base/Base.js';
2+
13
declare global {
24
// eslint-disable-next-line vars-on-top, no-var
35
var __DEV__: boolean;
6+
var __JS_TOOLKIT_REGISTRY__: Map<string, BaseConstructor>;
7+
var __JS_TOOLKIT_INSTANCES__: Set<Base>;
8+
49
interface Window {
510
__DEV__: typeof __DEV__;
611
ResizeObserver?: (callback: () => void) => void;
12+
13+
__JS_TOOLKIT_REGISTRY__: Map<string, BaseConstructor>;
14+
__JS_TOOLKIT_INSTANCES__: Set<Base>;
715
}
816

917
interface CSSStyleDeclaration {

packages/js-toolkit/Base/Base.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,16 @@ export class Base<T extends BaseProps = BaseProps> {
301301
return;
302302
}
303303

304+
// Add current component to the registry
304305
addToRegistry($config.name, this.constructor);
305306

307+
// Add children components to the registry
308+
for (const [selector, ctor] of Object.entries($config.components)) {
309+
if ('$isBase' in ctor && ctor.$isBase) {
310+
addToRegistry(selector, ctor);
311+
}
312+
}
313+
306314
this.$id = `${$config.name}-${id}`;
307315
id += 1;
308316

packages/tests/Base/Base.spec.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
import { describe, it, expect, vi } from 'vitest';
2-
import { Base, BaseConfig, BaseProps, getInstanceFromElement } from '@studiometa/js-toolkit';
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import {
3+
Base,
4+
BaseConfig,
5+
BaseProps,
6+
getInstanceFromElement,
7+
withExtraConfig,
8+
withName,
9+
} from '@studiometa/js-toolkit';
310
import { h } from '#test-utils';
411

512
let mockedIsDev = true;
@@ -36,6 +43,10 @@ async function getContext() {
3643
return { Foo, element, foo };
3744
}
3845

46+
beforeEach(() => {
47+
globalThis['__JS_TOOLKIT_REGISTRY__'] = new Map();
48+
});
49+
3950
describe('The abstract Base class', () => {
4051
it('must be extended', () => {
4152
expect(() => {
@@ -349,6 +360,44 @@ describe('A Base instance methods', () => {
349360
expect(fn).toHaveBeenNthCalledWith(2, 'method');
350361
});
351362

363+
it('should register itself on instantiation', async () => {
364+
const TestComponent = withName(Base, 'TestComponent');
365+
const registry = globalThis.__JS_TOOLKIT_REGISTRY__;
366+
const component = new TestComponent(h('div'));
367+
368+
expect(registry.has('TestComponent')).toBe(true);
369+
expect(registry.get('TestComponent')).toBe(TestComponent);
370+
371+
registry.delete('TestComponent');
372+
});
373+
374+
it('should register sync configured children components on instantiation', async () => {
375+
const Child = withName(Base, 'Child');
376+
const Parent = withExtraConfig(Base, {
377+
name: 'Parent',
378+
components: {
379+
Child,
380+
div: Child,
381+
AsyncChild: () => new Promise(() => {}),
382+
},
383+
});
384+
385+
const registry = globalThis.__JS_TOOLKIT_REGISTRY__;
386+
const component = new Parent(h('div'));
387+
388+
// Check that it's in the registry
389+
expect(registry.has('Parent')).toBe(true);
390+
expect(registry.get('Parent')).toBe(Parent);
391+
392+
expect(registry.has('Child')).toBe(true);
393+
expect(registry.get('Child')).toBe(Child);
394+
395+
expect(registry.has('div')).toBe(true);
396+
expect(registry.get('div')).toBe(Child);
397+
398+
expect(registry.has('AsyncChild')).toBe(false);
399+
});
400+
352401
it('should not find children if none provided', async () => {
353402
const { foo } = await getContext();
354403

0 commit comments

Comments
 (0)