Skip to content

Commit abbd01e

Browse files
committedFeb 4, 2025
chore: Initial poc for dialog
1 parent 25be332 commit abbd01e

File tree

13 files changed

+622
-23
lines changed

13 files changed

+622
-23
lines changed
 

‎apps/solid/src/routes/components/layout/container.route.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export const ContainerRoute = () => {
1717
<Container class="my-4" variant="contained" color="primary">
1818
<p>contained, primary color</p>
1919
</Container>
20+
<Container class="my-4" variant="contained" color="gradient">
21+
<p>contained, gradient</p>
22+
</Container>
2023
<Container class="my-4" variant="outlined">
2124
<p>outlined</p>
2225
</Container>
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {
2+
Button,
3+
Container,
4+
Divider,
5+
Heading,
6+
Dialog,
7+
ConfirmDialog,
8+
DialogContainer,
9+
} from '@spuxx/solid';
10+
import { Component } from 'solid-js';
11+
12+
export const DialogRoute: Component = () => {
13+
return (
14+
<Container tag="article">
15+
<DialogContainer />
16+
17+
<Heading level={1}>Dialog</Heading>
18+
<Divider color="gradient" />
19+
<Container tag="section" class="my-4">
20+
<Heading level={2}>Confirm Dialog</Heading>
21+
<Divider color="gradient" />
22+
<Button
23+
onClick={() => {
24+
Dialog.show(ConfirmDialog, {});
25+
}}
26+
>
27+
Open Confirm Dialog
28+
</Button>
29+
</Container>
30+
</Container>
31+
);
32+
};

‎apps/solid/src/routes/routes.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IndexRoute } from './index.route';
33
import { ButtonRoute } from './components/input/button.route';
44
import { ContainerRoute } from './components/layout/container.route';
55
import { DividerRoute } from './components/layout/divider.route';
6+
import { DialogRoute } from './dialog.route';
67

78
export const routes: RouteProps[] = [
89
{
@@ -21,4 +22,8 @@ export const routes: RouteProps[] = [
2122
path: '/components/layout/divider',
2223
component: () => DividerRoute,
2324
},
25+
{
26+
path: '/dialog',
27+
component: () => DialogRoute,
28+
},
2429
];

‎packages/solid/package.json

+8-2
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,24 @@
4646
"devDependencies": {
4747
"@iconify-icon/solid": "2.3.0",
4848
"@spuxx/browser-utils": "workspace:@spuxx/browser-utils@*",
49+
"@vitest/browser": "3.0.4",
4950
"csstype": "3.1.3",
51+
"playwright": "1.50.1",
5052
"solid-js": "1.9.3",
5153
"typescript": "5.7.2",
5254
"vite": "6.0.0",
55+
"vite-plugin-dts": "4.5.0",
5356
"vite-plugin-solid": "2.11.0",
5457
"vite-tsconfig-paths": "5.1.2",
55-
"vite-plugin-dts": "4.5.0"
58+
"vitest": "2.0.5"
5659
},
5760
"peerDependencies": {
5861
"@iconify-icon/solid": "^2.3.0",
59-
"@spuxx/js-utils": "^1.3.0",
6062
"@spuxx/browser-utils": "workspace:@spuxx/browser-utils@*",
63+
"@spuxx/js-utils": "^1.3.0",
6164
"solid-js": "^1.9.0"
65+
},
66+
"dependencies": {
67+
"@corvu/dialog": "^0.2.4"
6268
}
6369
}

‎packages/solid/src/components/input/button/button.component.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const Button: Component<ButtonProps> = (props) => {
1616
spx-color={color}
1717
spx-rounded={rounded}
1818
disabled={disabled}
19+
onClick={props.onClick}
1920
{...classNames('spx-button', props.class)}
2021
>
2122
{/* Loader */}

‎packages/solid/src/components/input/button/button.types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ export interface ButtonProps extends ComponentProps<HTMLButtonElement>, ParentPr
4343
* @default undefined
4444
*/
4545
loader?: boolean;
46+
/**
47+
* A callback that will be called when the button is clicked.
48+
* @param event The click event.
49+
*/
50+
onClick?: (event: MouseEvent) => void;
4651
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Dialog from '@corvu/dialog';
2+
import { DialogComponent, DialogOptions } from '../dialog.types';
3+
import { IconifyIconName } from '@iconify-icon/solid';
4+
5+
export interface ConfirmDialogOptions extends DialogOptions {
6+
title?: string;
7+
icon?: IconifyIconName;
8+
onConfirm?: () => void;
9+
}
10+
11+
export const ConfirmDialog: DialogComponent<ConfirmDialogOptions> = (options) => {
12+
return (
13+
<>
14+
<Dialog.Close />
15+
<Dialog.Label>Heyo whatsup!</Dialog.Label>
16+
<Dialog.Description />
17+
</>
18+
);
19+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Root, Trigger, Portal, Overlay, Content, Label, Description } from '@corvu/dialog';
2+
import { Dialog } from './dialog.service';
3+
import { createEffect, createSignal, Show, type Component } from 'solid-js';
4+
import { Dynamic } from 'solid-js/web';
5+
import { DialogComponent, DialogOptions } from './dialog.types';
6+
import { ConfirmDialog } from '@spuxx/solid';
7+
8+
export const DialogContainer: Component = () => {
9+
// const [component, setComponent] = createSignal<Component | null>(null);
10+
const [props, setProps] = createSignal<DialogOptions | undefined>(undefined);
11+
12+
createEffect(() => {
13+
// setComponent(Dialog.currentDialog);
14+
console.log(Dialog.currentDialog);
15+
console.log(Dialog.currentOptions);
16+
});
17+
18+
console.log(Dialog.currentDialog);
19+
20+
// return (
21+
// <>
22+
// {typeof DialogService.currentDialog === 'function' ? 'function' : 'not a function'}
23+
// <br />
24+
// {JSON.stringify(DialogService.currentOptions) ?? 'undefined'}
25+
// </>
26+
// );
27+
// if (typeof DialogService.currentDialog !== 'function') return null;
28+
return (
29+
// <Show when={typeof Dialog.currentDialog === 'function'}>
30+
<Root open={typeof Dialog.currentDialog === 'function'}>
31+
{/* <Trigger>Open Dialog</Trigger> */}
32+
<Portal>
33+
{/* <Overlay /> */}
34+
<Content>
35+
<Label>foo</Label>
36+
<Description>awdawd</Description>
37+
{/* <Dynamic component={DialogService.currentDialog!} {...DialogService.currentOptions} /> */}
38+
</Content>
39+
</Portal>
40+
</Root>
41+
// </Show>
42+
);
43+
// <Dynamic component={DialogService.currentDialog} {...DialogService.currentOptions} />
44+
// <Dynamic component={DialogService.currentDialog} {...DialogService.currentOptions} />
45+
// <Dialog>
46+
// <Dialog.Portal>
47+
// <Dialog.Overlay />
48+
// <Dialog.Content>
49+
// yolo
50+
// <Dynamic component={DialogService.currentDialog} {...DialogService.currentOptions} />
51+
// </Dialog.Content>
52+
// </Dialog.Portal>
53+
// </Dialog>
54+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ServiceMixin } from '@spuxx/js-utils';
2+
import { Component, ComponentProps, createSignal } from 'solid-js';
3+
import { DialogComponent, DialogOptions } from './dialog.types';
4+
5+
interface State {
6+
current: Component | null;
7+
options: DialogOptions | undefined;
8+
}
9+
10+
export class Dialog extends ServiceMixin<Dialog>() {
11+
protected state = createSignal<State>({ current: null, options: undefined });
12+
13+
/**
14+
* Shows the modal dialog of the given type and with the given options.
15+
* @param key The key of the modal to open.
16+
* @param options The options to pass to the modal.
17+
*/
18+
static show<TDialog extends DialogComponent<DialogOptions>>(
19+
dialog: TDialog,
20+
options?: ComponentProps<TDialog>,
21+
) {
22+
const [_state, setState] = this.instance.state;
23+
setState({ current: dialog, options });
24+
}
25+
26+
/**
27+
* Returns the current state of the dialog service.
28+
*/
29+
static get currentDialog() {
30+
const [state] = this.instance.state;
31+
return state().current;
32+
}
33+
34+
static get currentOptions() {
35+
const [state] = this.instance.state;
36+
return state().options;
37+
}
38+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Component } from 'solid-js';
2+
3+
export const DialogSize = {
4+
small: 'small',
5+
medium: 'medium',
6+
large: 'large',
7+
auto: 'auto',
8+
max: 'max',
9+
};
10+
export type DialogSize = (typeof DialogSize)[keyof typeof DialogSize];
11+
12+
export interface DialogOptions {
13+
/**
14+
* The size of the dialog. Defaults to 'auto'.
15+
*/
16+
size?: DialogSize;
17+
/**
18+
* Whether the dialog can be closed by clicking outside of it or pressing escape.
19+
* When enabled, the close button will not be visible. Defaults to `false`.
20+
*/
21+
preventClose?: boolean;
22+
/**
23+
* Will be called when the dialog is closed.
24+
*/
25+
onClose?: () => void;
26+
}
27+
28+
/**
29+
* The `DialogRegistry` interface represents a registry of dialog types. Whenever you create
30+
* a new dialog component, you need to add it to the registry.
31+
*/
32+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
33+
export interface DialogRegistry {}
34+
export type DialogComponent<Options extends DialogOptions> = Component<Options>;
35+
export type Dialogs = Record<string, Component>;

‎packages/solid/src/dialog/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './dialog.types';
2+
export * from './dialog.service';
3+
export * from './dialog-container.component';
4+
export * from './built-in/confirm.dialog';

‎packages/solid/src/main.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ export * from './components/layout/container';
99
export * from './components/layout/divider';
1010
export * from './components/typography/heading';
1111

12+
export * from './dialog';
13+
1214
export * from './utils/component.utils';

0 commit comments

Comments
 (0)
Failed to load comments.