Skip to content

Commit 3072ad7

Browse files
committed
feat: enhance ShadowObjectCreationAPI with implicit event target support for on() and once() methods
1 parent 370ce70 commit 3072ad7

4 files changed

Lines changed: 37 additions & 7 deletions

File tree

packages/shadow-objects/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## unreleased
99

10+
- **API Update:** `on()` and `once()` in `ShadowObjectCreationAPI` now support an implicit event target.
11+
- If the first argument is a `string`, `symbol`, or `string[]`, the `entity` is automatically used as the event source.
12+
- Example: `on('eventName', callback)` is equivalent to `on(entity, 'eventName', callback)`.
13+
- This simplifies the common case of listening to entity events.
1014
- sharpen the `EntityApi` type definitions
1115
- **Documentation:** Comprehensive update to the documentation structure and content.
1216
- Added dedicated documentation for Web Components (`<shae-worker>`, `<shae-ent>`, `<shae-prop>`) at `docs/03-api/04-web-components.md`.

packages/shadow-objects/docs/03-api/01-shadow-object-api.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,23 +141,32 @@ Shadow Objects can communicate via an event system that mirrors standard DOM eve
141141

142142
Listens for an event on a target.
143143

144-
* **Signature:** `on(target: object, event: string, callback: (type: string, data: any) => void): void`
144+
* **Signature:**
145+
* `on(target: object, event: string, callback: Listener): void`
146+
* `on(event: string | symbol | string[], callback: Listener): void` (implicitly uses `entity` as target)
145147
* **Targets:** Usually `entity` (the current entity instance).
148+
* **Automatic Cleanup:** Subscriptions created via `on()` are automatically removed when the Shadow Object is destroyed.
146149

147150
#### Listening to View Events
148151
To listen to events dispatched from the DOM (View Layer), listen to the special event name `'onViewEvent'` on the `entity` target.
149152

150153
```typescript
151-
on(entity, 'onViewEvent', (type, data) => {
154+
// Implicitly listens on the entity
155+
on('onViewEvent', (type, data) => {
152156
if (type === 'click') {
153157
console.log('Clicked!', data);
154158
}
155159
});
160+
161+
// Explicit target (equivalent to above)
162+
on(entity, 'onViewEvent', (type, data) => {
163+
// ...
164+
});
156165
```
157166

158167
### `once(target, eventName, callback)`
159168

160-
Same as `on`, but the listener is automatically removed after the first trigger.
169+
Same as `on`, but the listener is automatically removed after the first trigger. Like `on`, if the first argument is a string, symbol, or array of strings/symbols, the `entity` is used as the event target.
161170

162171
---
163172

packages/shadow-objects/src/in-the-dark/Kernel.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,14 +586,28 @@ export class Kernel {
586586
return sig;
587587
},
588588

589-
on(...args: Parameters<typeof on>): ReturnType<typeof on> {
589+
on(...args: any[]): ReturnType<typeof on> {
590+
const [firstArg] = args;
591+
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
592+
// @ts-ignore
593+
const unsub = on(entry.entity, ...args);
594+
unsubscribeSecondary.add(unsub);
595+
return unsub;
596+
}
590597
// @ts-ignore
591598
const unsub = on(...args);
592599
unsubscribeSecondary.add(unsub);
593600
return unsub;
594601
},
595602

596-
once(...args: Parameters<typeof once>): ReturnType<typeof once> {
603+
once(...args: any[]): ReturnType<typeof once> {
604+
const [firstArg] = args;
605+
if (typeof firstArg === 'string' || typeof firstArg === 'symbol' || Array.isArray(firstArg)) {
606+
// @ts-ignore
607+
const unsub = once(entry.entity, ...args);
608+
unsubscribeSecondary.add(unsub);
609+
return unsub;
610+
}
597611
// @ts-ignore
598612
const unsub = once(...args);
599613
unsubscribeSecondary.add(unsub);

packages/shadow-objects/src/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,11 @@ export interface ShadowObjectCreationAPI {
140140
createSignal<T = unknown>(...args: Parameters<typeof createSignal<T>>): ReturnType<typeof createSignal<T>>;
141141
createMemo<T = unknown>(...args: Parameters<typeof createMemo<T>>): SignalReader<T>;
142142

143-
on(...args: Parameters<typeof on>): ReturnType<typeof on>; // TODO fix args type
144-
once(...args: Parameters<typeof once>): ReturnType<typeof once>; // TODO fix args type
143+
on(eventName: string | symbol | Array<string | symbol>, ...args: any[]): ReturnType<typeof on>;
144+
on(...args: Parameters<typeof on>): ReturnType<typeof on>;
145+
146+
once(eventName: string | symbol | Array<string | symbol>, ...args: any[]): ReturnType<typeof once>;
147+
once(...args: Parameters<typeof once>): ReturnType<typeof once>;
145148

146149
onDestroy(callback: () => any): void;
147150
}

0 commit comments

Comments
 (0)