Skip to content

Commit eb68654

Browse files
committed
chore(noti): update typing and add progress proxy methods
1 parent 11a6526 commit eb68654

5 files changed

Lines changed: 82 additions & 54 deletions

File tree

.changeset/unlucky-beans-invent.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@svelte-put/noti': minor
3+
---
4+
5+
update Component typing, add `pause` & `resume` proxies on `NotificationController`, and return `resolution` in `resolve`

packages/noti/src/notification-controller-builder.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NotificationController } from './notification-controller.svelte.js';
22

33
/**
4-
* @template {Record<string, import('svelte').SvelteComponent<any>>} [VariantMap={}]
4+
* @template {Record<string, import('svelte').Component>} [VariantMap={}]
55
*/
66
export class NotificationControllerBuilder {
77
/** @type {Record<string, import('./types').NotificationVariantConfig<any, any, any>>} */
@@ -23,10 +23,10 @@ export class NotificationControllerBuilder {
2323
* add config for a notification variant
2424
* @template Resolved
2525
* @template {string} Variant
26-
* @template {import('svelte').SvelteComponent<import('./types').NotificationProps<Resolved>>} Component
26+
* @template {import('svelte').Component} UserComponent
2727
* @param {Variant} variant
28-
* @param {import('svelte').ComponentType<Component> | Omit<import('./types').NotificationVariantConfig<Resolved, Variant, Component>, 'variant'>} config
29-
* @returns {NotificationControllerBuilder<VariantMap & Record<Variant, Component>> }
28+
* @param {UserComponent | Omit<import('./types').NotificationVariantConfig<Resolved, Variant, UserComponent>, 'variant'>} config
29+
* @returns {NotificationControllerBuilder<VariantMap & Record<Variant, UserComponent>> }
3030
*/
3131
addVariant(variant, config) {
3232
if ('component' in config) {

packages/noti/src/notification-controller.svelte.js

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { MissingComponentInCustomPush, NotFoundVariantConfig } from './errors.js
44
import { Notification } from './notification.svelte.js';
55

66
/**
7-
* @template {Record<string, import('svelte').SvelteComponent>} [VariantMap={}]
7+
* @template {Record<string, import('svelte').Component>} [VariantMap={}]
88
*/
99
export class NotificationController {
10-
/** @type {Record<string, import('./types.js').NotificationVariantConfig<any, any, any>>} */
10+
/** @type {Record<string, import('./types.d.ts').NotificationVariantConfig<any, any, any>>} */
1111
#variantConfigMap = {};
1212
#counter = 0;
1313

@@ -19,7 +19,7 @@ export class NotificationController {
1919
notifications = $state([]);
2020

2121
/**
22-
* @type {Required<import('./types.js').NotificationCommonConfig<any, any, any>>}
22+
* @type {Required<import('./types.d.ts').NotificationCommonConfig<any, any, any>>}
2323
*/
2424
// eslint-disable-next-line no-undef
2525
config = $state({
@@ -32,7 +32,7 @@ export class NotificationController {
3232
* register the element to render a notification into
3333
* @param {HTMLElement} node
3434
* @param {Notification<any>} notification
35-
* @returns {import('./types.js').NotificationPortalActionReturn}
35+
* @returns {import('./types.d.ts').NotificationPortalActionReturn}
3636
*/
3737
render: (node, notification) => {
3838
mount(notification.config.component, {
@@ -48,8 +48,8 @@ export class NotificationController {
4848
};
4949

5050
/**
51-
* @param {Record<keyof VariantMap, import('./types.js').NotificationVariantConfig<any, any, any>>} variantConfigMap
52-
* @param {import('./types.js').NotificationCommonConfig<any, any, any>} [init]
51+
* @param {Record<keyof VariantMap, import('./types.d.ts').NotificationVariantConfig<any, any, any>>} variantConfigMap
52+
* @param {import('./types.d.ts').NotificationCommonConfig<any, any, any>} [init]
5353
*/
5454
constructor(variantConfigMap, init) {
5555
if (init?.id) this.config.id = init.id;
@@ -60,36 +60,36 @@ export class NotificationController {
6060

6161
/**
6262
* @template {Extract<keyof VariantMap, string>} Variant
63-
* @template {VariantMap[Variant]} [Component=VariantMap[Variant]]
64-
* @template [Resolved=undefined|Awaited<import('svelte').ComponentProps<Component>['notification']['resolution']>]
63+
* @template {VariantMap[Variant]} [UserComponent=VariantMap[Variant]]
64+
* @template [Resolved=undefined|Awaited<import('svelte').ComponentProps<UserComponent>['notification']['resolution']>]
6565
* @overload
6666
* @param {Variant} variant
67-
* @param {import('./types.js').NotificationByVariantPushConfig<Resolved, Variant, Component>} [config]
67+
* @param {import('./types.d.ts').NotificationByVariantPushConfig<Resolved, Variant, UserComponent>} [config]
6868
* @returns {Notification<Resolved>}
6969
*/
7070
/**
71-
* @template {import('svelte').SvelteComponent} Component
72-
* @template [Resolved=undefined|Awaited<import('svelte').ComponentProps<Component>['notification']['resolution']>]
71+
* @template {import('svelte').Component} UserComponent
72+
* @template [Resolved=undefined|Awaited<import('svelte').ComponentProps<UserComponent>['notification']['resolution']>]
7373
* @overload
7474
* @param {'custom'} variant
75-
* @param {import('./types.js').NotificationCustomPushConfig<Resolved, Component>} config
75+
* @param {import('./types.d.ts').NotificationCustomPushConfig<Resolved, UserComponent>} config
7676
* @returns {Notification<Resolved>}
7777
*/
7878
/**
7979
* @param {string} variant
80-
* @param {import('./types.js').NotificationByVariantPushConfig<any, string, import('svelte').SvelteComponent<any>> | import('./types.js').NotificationCustomPushConfig<any, import('svelte').SvelteComponent<any>>} [config]
80+
* @param {import('./types.d.ts').NotificationByVariantPushConfig<any, string, import('svelte').Component> | import('./types.d.ts').NotificationCustomPushConfig<any, import('svelte').Component>} [config]
8181
* @returns {Notification<any>}
8282
*/
8383
push(variant, config) {
8484
// STEP 1: resolve instance config, merge with common config and variant config, if any
85-
/** @type {import('./types.js').NotificationInstanceConfig<any, any, any>} */
85+
/** @type {import('./types.d.ts').NotificationInstanceConfig<any, any, any>} */
8686
let instanceConfig;
87-
/** @type {NonNullable<import('./types.js').NotificationCommonConfig<Resolved, string, import('svelte').SvelteComponent<any>>['id']>} */
87+
/** @type {NonNullable<import('./types.d.ts').NotificationCommonConfig<Resolved, string, import('svelte').Component>['id']>} */
8888
let idResolver;
8989

9090
if (variant === 'custom') {
9191
const rConfig =
92-
/** @type {import('./types.js').NotificationCustomPushConfig<any, any>} */ (
92+
/** @type {import('./types.d.ts').NotificationCustomPushConfig<any, any>} */ (
9393
config
9494
);
9595
if (!rConfig || !rConfig.component) {
@@ -158,12 +158,12 @@ export class NotificationController {
158158
*/
159159
/**
160160
* @overload
161-
* @param {import('./types.js').NotificationPopVerboseInput} [config]
161+
* @param {import('./types.d.ts').NotificationPopVerboseInput} [config]
162162
* @returns {void}
163163
*/
164164
/**
165165
*
166-
* @param {string | import('./types.js').NotificationPopVerboseInput} [config]
166+
* @param {string | import('./types.d.ts').NotificationPopVerboseInput} [config]
167167
* @param {any} [resolved]
168168
* @returns {void}
169169
*/
@@ -192,4 +192,24 @@ export class NotificationController {
192192
this.notifications = this.notifications.filter((n) => n.config.id !== pushed.config.id);
193193
}
194194
}
195+
196+
/**
197+
* pause a notification, if it has a timeout
198+
* @param {string} id
199+
* @returns {void}
200+
*/
201+
pause(id) {
202+
const pushed = this.notifications.find((n) => n.config.id === id);
203+
return pushed?.pause();
204+
}
205+
206+
/**
207+
* resume a notification, if it has been paused
208+
* @param {string} id
209+
* @returns {void}
210+
*/
211+
resume(id) {
212+
const pushed = this.notifications.find((n) => n.config.id === id);
213+
return pushed?.resume();
214+
}
195215
}

packages/noti/src/notification.svelte.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/**
22
* @template Resolved
3-
* @template {import('svelte').SvelteComponent<import('./types').NotificationProps<Resolved>>} [Component=import('svelte').SvelteComponent<any, any, any>]
3+
* @template {import('svelte').Component} [UserComponent=import('svelte').Component<import('./types.d.ts').NotificationProps<Resolved>>]
44
*/
55
export class Notification {
6-
/** @type {import('./types').NotificationState} */
6+
/** @type {import('./types.d.ts').NotificationState} */
77
// eslint-disable-next-line no-undef
88
state = $state('idle');
9-
/** @type {Required<import('./types').NotificationInstanceConfig<Resolved, string, Component>>} */
9+
/** @type {Required<import('./types.d.ts').NotificationInstanceConfig<Resolved, string, UserComponent>>} */
1010
// eslint-disable-next-line no-undef
1111
config;
1212

@@ -26,7 +26,7 @@ export class Notification {
2626
resolution;
2727

2828
/**
29-
* @param {Required<import('./types').NotificationInstanceConfig<Resolved, string, Component>>} config
29+
* @param {Required<import('./types.d.ts').NotificationInstanceConfig<Resolved, string, UserComponent>>} config
3030
*/
3131
constructor(config) {
3232
this.config = config;
@@ -58,10 +58,12 @@ export class Notification {
5858

5959
/**
6060
* @param {Resolved} [resolved]
61+
* @returns {Promise<Resolved | undefined>}
6162
*/
6263
resolve = (resolved) => {
63-
if (this.state === 'resolved') return;
64+
if (this.state === 'resolved') return this.resolution;
6465
this.#internals.resolve(resolved);
6566
this.state = 'resolved';
67+
return this.resolution;
6668
}
6769
}

packages/noti/src/types.d.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
import type { SvelteComponent, ComponentType, ComponentProps } from 'svelte';
2+
import type { Component, ComponentProps } from 'svelte';
33
import { ActionReturn } from 'svelte/action';
44

55
import type { Notification } from './notification.svelte.js';
66

7-
type NotificationCommonConfig<
7+
export type NotificationCommonConfig<
88
Resolved,
99
Variant extends string,
10-
Component extends SvelteComponent<NotificationProps<Resolved>>,
10+
UserComponent extends Component,
1111
> = {
1212
/**
1313
* milliseconds to wait and automatically pop the notification.
@@ -17,70 +17,71 @@ type NotificationCommonConfig<
1717
/**
1818
* id generator for notifications. Defaults to 'uuid'.
1919
*
20-
* - counter: use an auto-incremented counter that is scoped to the store
20+
* - counter: use an auto-incremented counter that is scoped to the controller
2121
* - uuid: use `crypto.randomUUID()`, fallback to `counter` if not available
2222
* - callback: a custom function that accepts {@link NotificationInstanceConfig} and returns a string as the id
2323
*/
2424
id?:
2525
| 'counter'
2626
| 'uuid'
27-
| ((config: Required<Omit<NotificationInstanceConfig<Resolved, Variant, Component>, 'id'>>) => string);
27+
| ((config: Required<Omit<NotificationInstanceConfig<Resolved, Variant, UserComponent>, 'id'>>) => string);
2828
};
2929

30-
type NotificationProps<Resolved> = {
30+
export declare type NotificationProps<Resolved> = {
31+
/** the notification instance injected by the notification controller */
3132
notification: Omit<Notification<Resolved>, '#internals'>;
3233
}
3334

3435
/** predefined variant config provided while building a {@link Noti} instance */
35-
type NotificationVariantConfig<
36+
export type NotificationVariantConfig<
3637
Resolved,
3738
Variant extends string,
38-
Component extends SvelteComponent<NotificationProps<Resolved>>,
39-
> = NotificationCommonConfig<Resolved, Variant, Component> & {
39+
UserComponent extends Component,
40+
> = NotificationCommonConfig<Resolved, Variant, UserComponent> & {
4041
/** string variant representing this config, must be unique within a {@link Noti} instance */
4142
variant: Variant;
4243
/** any Svelte component used for rendering notification UI */
43-
component: ComponentType<Component>;
44+
component: UserComponent;
4445
/** inferred props from `component` */
45-
props?: Omit<ComponentProps<Component>, 'notification'>;
46+
props?: Omit<ComponentProps<UserComponent>, 'notification'>;
4647
};
4748

4849
/** a resolved config for a {@link NotificationInstance} */
49-
type NotificationInstanceConfig<
50+
export type NotificationInstanceConfig<
5051
Resolved,
5152
Variant extends string,
52-
Component extends SvelteComponent<NotificationProps<Resolved>>,
53-
> = Required<Omit<NotificationVariantConfig<Resolved, Variant, Component>, 'id'>> & {
53+
UserComponent extends Component,
54+
> = Required<Omit<NotificationVariantConfig<Resolved, Variant, UserComponent>, 'id'>> & {
5455
id: string;
5556
timeout: number;
5657
};
5758

58-
type NotificationState = 'idle' | 'elapsing' | 'paused' | 'timeout' | 'resolved';
59+
export type NotificationState = 'idle' | 'elapsing' | 'paused' | 'timeout' | 'resolved';
5960

60-
type NotificationByVariantPushConfig<
61+
export type NotificationByVariantPushConfig<
6162
Resolved,
6263
Variant extends string,
63-
Component extends SvelteComponent<NotificationProps<Resolved>>,
64-
> = NotificationCommonConfig<Resolved, Variant, Component> & {
65-
props?: Omit<ComponentProps<Component>, 'notification'>;
64+
UserComponent extends Component,
65+
> = NotificationCommonConfig<Resolved, Variant, UserComponent> & {
66+
props?: Omit<ComponentProps<UserComponent>, 'notification'>;
6667
};
6768

68-
type NotificationCustomPushConfig<
69+
export type NotificationCustomPushConfig<
6970
Resolved,
70-
Component extends SvelteComponent<NotificationProps<Resolved>>,
71-
> = NotificationCommonConfig<Resolved, 'custom', Component> & {
72-
component: ComponentType<Component>;
73-
props?: Omit<ComponentProps<Component>, 'notification'>;
71+
UserComponent extends Component,
72+
> = NotificationCommonConfig<Resolved, 'custom', UserComponent> & {
73+
component: UserComponent;
74+
props?: Omit<ComponentProps<UserComponent>, 'notification'>;
7475
};
7576

76-
type NotificationPopVerboseInput = {
77+
export type NotificationPopVerboseInput = {
7778
id?: string;
7879
resolved?: any;
7980
};
8081

81-
type NotificationPortalAttributes = {
82+
export type NotificationPortalAttributes = {
8283
onnotipush?: (event: CustomEvent<Notification<any>>) => void;
8384
onnotipop?: (event: CustomEvent<Notification<any>>) => void;
8485
};
8586

86-
type NotificationPortalActionReturn = ActionReturn<Notification<any>, NotificationPortalAttributes>;
87+
export type NotificationPortalActionReturn = ActionReturn<Notification<any>, NotificationPortalAttributes>;

0 commit comments

Comments
 (0)