Skip to content

Commit

Permalink
feat: Add onDestroy modifier (#304)
Browse files Browse the repository at this point in the history
* feat: Add `onDestroy` modifier

* chore: Add tests

* chore: Add `on-click-outside` to index

* chore: PR review
  • Loading branch information
TSenter authored Dec 11, 2024
1 parent f1109c4 commit 537a882
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
42 changes: 42 additions & 0 deletions apps/test-app/tests/integration/modifiers/on-destroy-test.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { clearRender } from '@ember/test-helpers';
import { find, render } from '@ember/test-helpers';
import { onDestroy } from '@nrg-ui/core';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';

module('Integration | Modifier | on-destroy', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
assert.expect(6);

let element: HTMLElement | null = null;

const callback = (el: HTMLElement, ...args: unknown[]) => {
assert.step('callback');
assert.strictEqual(el, element, 'Element is passed');
assert.deepEqual(
args,
[5, 'foo', 'BAR'],
'Additional arguments are passed',
);
};

assert.step('before render');

await render(<template>
<div {{onDestroy callback 5 "foo" "BAR"}}></div>
</template>);

assert.step('after render');

element = await find('div');

await clearRender();

assert.verifySteps(
['before render', 'after render', 'callback'],
'Steps are correct',
);
});
});
1 change: 1 addition & 0 deletions packages/ember-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
"./initializers/dayjs-plugins.js": "./dist/_app_/initializers/dayjs-plugins.js",
"./modifiers/index.js": "./dist/_app_/modifiers/index.js",
"./modifiers/on-click-outside.js": "./dist/_app_/modifiers/on-click-outside.js",
"./modifiers/on-destroy.js": "./dist/_app_/modifiers/on-destroy.js",
"./modifiers/on-insert.js": "./dist/_app_/modifiers/on-insert.js",
"./modifiers/on-update.js": "./dist/_app_/modifiers/on-update.js",
"./services/modal.js": "./dist/_app_/services/modal.js",
Expand Down
2 changes: 2 additions & 0 deletions packages/ember-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export { default as ThemeSwitcher } from './components/theme-switcher.gts';
export { bind, default as Bind } from './helpers/bind.ts';

/* Modifiers */
export { default as onClickOutside } from './modifiers/on-click-outside.ts';
export { default as onDestroy } from './modifiers/on-destroy.ts';
export { default as onInsert } from './modifiers/on-insert.ts';
export { default as onUpdate } from './modifiers/on-update.ts';

Expand Down
3 changes: 2 additions & 1 deletion packages/ember-core/src/modifiers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as onInsert } from './on-insert.ts';
export { default as onClickOutside } from './on-click-outside.ts';
export { default as onDestroy } from './on-destroy.ts';
export { default as onInsert } from './on-insert.ts';
export { default as onUpdate } from './on-update.ts';
42 changes: 42 additions & 0 deletions packages/ember-core/src/modifiers/on-destroy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { registerDestructor } from '@ember/destroyable';
import Modifier from 'ember-modifier';

import type Owner from '@ember/owner';
import type { ArgsFor } from 'ember-modifier';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyArray = any[];

type CallbackFn<Args extends AnyArray> = (
element: HTMLElement,
...args: Args
) => void;

export interface OnDestroySignature<Args extends AnyArray> {
Element: HTMLElement;
Args: {
Positional: [CallbackFn<Args>, ...Args];
};
}

export default class OnDestroy<Args extends AnyArray> extends Modifier<
OnDestroySignature<Args>
> {
declare callback: () => void;

constructor(owner: Owner, args: ArgsFor<OnDestroySignature<Args>>) {
super(owner, args);

registerDestructor(this, () => {
this.callback?.();
});
}

modify(
element: HTMLElement,

[callback, ...args]: [CallbackFn<Args>, ...Args],
): void {
this.callback = () => callback(element, ...args);
}
}

0 comments on commit 537a882

Please sign in to comment.