Skip to content

Commit

Permalink
Feature/toast (#82)
Browse files Browse the repository at this point in the history
* Init toast

* add event bus #76 (initial approach only)
  • Loading branch information
CKGrafico committed May 12, 2023
1 parent 75a0275 commit e2ae3a1
Show file tree
Hide file tree
Showing 20 changed files with 825 additions and 9 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"release": "lerna publish from-package --force-publish"
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/preact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/qwik/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
357 changes: 357 additions & 0 deletions packages/react/yarn.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}
},
"dependencies": {
"@trutoo/event-bus": "^2.2.0",
"codejar": "^3.7.0",
"copy-to-clipboard": "^3.3.3",
"highlight.js": "^11.7.0",
Expand Down
2 changes: 2 additions & 0 deletions src/elements/extensions/toast/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useToastExtension } from './toast.hook';
export { default } from './toast.lite';
23 changes: 23 additions & 0 deletions src/elements/extensions/toast/toast.bus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { EventBus } from '@trutoo/event-bus';
import { ToastCallback, ToastPayload } from './toast.model';

const BUS_NAME = 'toast';
const bus = new EventBus();
const state: ToastPayload[] = [];

// TODO: If more buses in the future, move to generic
const subscribe = (callback: ToastCallback<ToastPayload>) => bus.subscribe(BUS_NAME, callback);
const register = (optionsType = { type: Object }) => bus.register(BUS_NAME, optionsType);
const publish = (payload: ToastPayload) => {
state.push(payload);
bus.publish(BUS_NAME, payload);
};

// TODO: Can i move all the logic to the service??

export const toastBus = {
subscribe,
register,
publish,
state: () => state
};
4 changes: 4 additions & 0 deletions src/elements/extensions/toast/toast.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@import '~/styles/build.css';

.pa-toast {
}
43 changes: 43 additions & 0 deletions src/elements/extensions/toast/toast.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { debug } from '~/helpers';
import { toastBus } from './toast.bus';
import './toast.css';
import { ToastPayload } from './toast.model';

const themes = {};

const actions: {
[key: string]: (payload: ToastPayload) => void;
} = {};

function actionFactory(name) {
return (payload: ToastPayload) => {
toastBus.publish({
id: `${Math.random()}`,
...payload
});
};
}

function createTheme(name: string) {
const properties = ['background', 'foreground'];
const theme = {};

properties.forEach((property) => (theme[property] = `var(--pa-toast-${property}-${name})`));

debug(`ToastService createTheme: ${name}: ${JSON.stringify(theme)}`);

toastBus.register();
themes[name] = theme;
actions[name] = actionFactory(name);
}

function triggerCustomAction(name: string, payload: ToastPayload) {
return actions[name](payload);
}

export default function useToastExtension() {
createTheme('success');
createTheme('error');

return { success: actions.success, error: actions.error, createTheme, trigger: triggerCustomAction };
}
42 changes: 42 additions & 0 deletions src/elements/extensions/toast/toast.lite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { For, onMount, onUnMount, useMetadata, useStore } from '@builder.io/mitosis';
import './toast.css';
import type { ToastProps, ToastState } from './toast.model';
import { toastService } from './toast.service';

useMetadata({ isAttachedToShadowDom: true });

export default function Toast(props: ToastProps) {
const state = useStore<ToastState>({
get classes() {
return toastService.getClasses(props.disabled, props.className || props.classList);
},
get toasts() {
return toastService.getToasts();
},
toastSubscription: null
});

onMount(() => {
if (state.toastSubscription) {
return;
}

// TODO: This approach doesnt work looks like is not reactive enough I will try other approach
state.toastSubscription = toastService.subscribe();
});

onUnMount(() => {
if (!state.toastSubscription) {
return;
}

state.toastSubscription.unsubscribe();
});

return (
<div class={state.classes.base}>
<For each={state.toasts}>{(toast) => <div>{toast.message}</div>}</For>
{props.children}
</div>
);
}
26 changes: 26 additions & 0 deletions src/elements/extensions/toast/toast.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { BaseProps, BaseState } from '~/models';

export interface ToastProps extends BaseProps {
disabled?: boolean;
}

export interface ToastState extends BaseState {
classes: { base: string };
toasts: ToastPayload[];
toastSubscription: {
unsubscribe(): void;
};
}

export type ToastPayload = {
id?: string;
message: string;
};

// TODO Move to generic
export type ToastChannelEvent<T> = {
channel: string;
payload: T | undefined;
};

export type ToastCallback<T> = (event: ToastChannelEvent<T>) => void;
30 changes: 30 additions & 0 deletions src/elements/extensions/toast/toast.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { classesToString, debug } from '~/helpers';
import { toastBus } from './toast.bus';
import { ToastChannelEvent, ToastPayload } from './toast.model';

class ToastService {
private toasts: ToastPayload[] = [];

private onChangeToasts(event: ToastChannelEvent<ToastPayload>) {
this.toasts = toastBus.state();
debug(`ToastService onChangeToasts: toasts: ${this.toasts}`);
}

public getClasses(disabled: boolean, className: string) {
const base = classesToString(['pa-toast', [disabled, 'is-disabled'], className || '']);

debug(`ToastService getClasses: base: ${base}`);
return { base };
}

public getToasts() {
return this.toasts;
}

public subscribe() {
debug('ToastService subscribe');
return toastBus.subscribe(this.onChangeToasts);
}
}

export const toastService = new ToastService();
133 changes: 133 additions & 0 deletions src/elements/extensions/toast/toast.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
import { Customization, Codesandbox } from '../../../../.storybook/components';
import { Toast, useToastExtension } from '../../../../packages/react/src';

<Meta
title="🧩Elements/Extensions/Toast"
argTypes={{
title: {
name: 'title',
description: 'A sample of attribute title',
table: {},
control: 'text'
}
}}
/>

export const Template = (args) => (
<div className="toast-example">
{(() => {
window.toast = useToastExtension();
return '';
})()}
<div>
<Toast />
<span
onClick={() => {
// toast.success({ message: 'example' })
window.toast.success({ message: 'example' + Math.random() });
}}
>
Click me
</span>
</div>
</div>
);

# Toast

TODO

## Showcase

<Canvas>
<Story
name="Toast"
args={{
title: 'Title of my tooltip'
}}
>
{Template.bind({})}
</Story>
</Canvas>

### Customization

<Customization showCode={false} />

### Properties

<ArgsTable story="Tooltip" />

## How to use this extension

### Angular

<Codesandbox
extensions={['useTooltipExtension']}
platform="angular"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Preact

<Codesandbox
extensions={['useTooltipExtension']}
platform="preact"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Qwik

<Codesandbox
extensions={['useTooltipExtension']}
platform="qwik"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### React

<Codesandbox
extensions={['useTooltipExtension']}
platform="react"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Solid

<Codesandbox
extensions={['useTooltipExtension']}
platform="solid"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Svelte

<Codesandbox
extensions={['useTooltipExtension']}
platform="svelte"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Vue

<Codesandbox
extensions={['useTooltipExtension']}
platform="vue"
code={`
<span title="Example of a tooltip">Hover me</span>`}
/>

### Web Components

<Codesandbox
extensions={['useTooltipExtension']}
platform="webcomponents"
code={`<span title="Example of a tooltip">Hover me</span>`}
/>
2 changes: 1 addition & 1 deletion src/elements/extensions/tooltip/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default } from './tooltip';
export { default } from './tooltip.hook';
File renamed without changes.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export { default as Pill } from './elements/components/pill';
export { default as Spinner } from './elements/components/spinner';
export { default as Itchio } from './elements/enterprise/itchio';
export { default as useTooltipExtension } from './elements/extensions/tooltip';
// TODO this breaks command --element
export { default as Toast, useToastExtension } from './elements/extensions/toast';
export { default as Column } from './elements/layout/column';
export { default as Container } from './elements/layout/container';
export { default as Row } from './elements/layout/row';
Expand Down
Loading

0 comments on commit e2ae3a1

Please sign in to comment.