From 1bc420c2101a147e09b8bdbbd84113a28c4ffd2d Mon Sep 17 00:00:00 2001 From: Mikkel RINGAUD Date: Sun, 13 Aug 2023 12:19:02 +0200 Subject: [PATCH] feat: add `createModal` primitive --- package.json | 1 + pnpm-lock.yaml | 13 +++ src/primitives/modal.tsx | 70 +++++++++++++++ src/routes/dashboard/[workspace_id].tsx | 115 +++++++++++------------- uno.config.ts | 14 ++- 5 files changed, 149 insertions(+), 64 deletions(-) create mode 100644 src/primitives/modal.tsx diff --git a/package.json b/package.json index 4ace38f..83b217a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "typescript": "^4.9.4", "unocss": "^0.54.2", "unocss-catppuccin": "^0.2.0", + "unocss-preset-primitives": "0.0.1-beta.10", "unplugin-icons": "^0.16.5", "vite": "^4.4.6" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a84f266..8e2da6a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,6 +64,9 @@ devDependencies: unocss-catppuccin: specifier: ^0.2.0 version: 0.2.0 + unocss-preset-primitives: + specifier: 0.0.1-beta.10 + version: 0.0.1-beta.10 unplugin-icons: specifier: ^0.16.5 version: 0.16.5 @@ -2164,6 +2167,10 @@ packages: unconfig: 0.3.10 dev: true + /@unocss/core@0.53.6: + resolution: {integrity: sha512-wuaLjWCzKUisHUxo4pjIdzcimdSmVa2hMHA3V7wVFBiSFX96/s7l0bvhHGFF/gMjbOnvJ+y+lBl3VKqcj9kwbA==} + dev: true + /@unocss/core@0.54.2: resolution: {integrity: sha512-PyyJOJtZ2K0BVSawAA/5X46w3Vgj/39jy+2EGKrT0KD4pbYid8oQo84OkXEEms5gAnIAAZHayGqs43zi/FRp0A==} dev: true @@ -4178,6 +4185,12 @@ packages: '@catppuccin/palette': 0.2.0 dev: true + /unocss-preset-primitives@0.0.1-beta.10: + resolution: {integrity: sha512-dN+2DsFtXEmk51tj9MBpVdk49U9BTGfE9T8j4mKihj+k53PIroeNddFwTuv1pEVj9FyGQKFglS+qm0p3l6FHvg==} + dependencies: + '@unocss/core': 0.53.6 + dev: true + /unocss@0.54.2(postcss@8.4.27)(rollup@3.27.2)(vite@4.4.6): resolution: {integrity: sha512-a3l1xAyIP59REem85IHSA+vDu4qovD7HwhUcEbUSX/NKmOZrm1OhUNKbSIzuQQWGdBa8ffagFBNfyXk2b8qSEg==} engines: {node: '>=14'} diff --git a/src/primitives/modal.tsx b/src/primitives/modal.tsx new file mode 100644 index 0000000..4219612 --- /dev/null +++ b/src/primitives/modal.tsx @@ -0,0 +1,70 @@ +import { type JSX, type FlowComponent, createSignal, onCleanup, batch } from "solid-js"; +import { render } from "solid-js/web"; +import { Dialog } from "@kobalte/core"; + +export interface ModalProps { + open: boolean + onOpenChange: (open: boolean) => void +} + +const Modal: FlowComponent & { + Title: typeof Dialog["Title"] + Description: typeof Dialog["Description"] + CloseButton: typeof Dialog["CloseButton"] +} = (props) => ( + + + +
+ + {props.children} + +
+
+
+); + +Modal.Title = Dialog.Title; +Modal.Description = Dialog.Description; +Modal.CloseButton = Dialog.CloseButton; + +export const createModal = (createModalContent: (components: { + Title: typeof Modal["Title"] + Description: typeof Modal["Description"] + CloseButton: typeof Modal["CloseButton"], + data: T | null +}) => JSX.Element) => { + const [data, setData] = createSignal(null); + const [open, setOpen] = createSignal(false); + + const portal = document.createElement("div"); + document.body.appendChild(portal); + + const dispose = render(() => ( + + {createModalContent({ + Title: Modal.Title, + Description: Modal.Description, + CloseButton: Modal.CloseButton, + data: data() + })} + + ), portal); + + const show = (new_data?: T) => batch(() => { + setOpen(true); + setData(() => (new_data ?? null)); + }); + + const hide = () => batch(() => { + setOpen(false); + setData(null); + }); + + onCleanup(() => { + dispose(); + portal.remove(); + }); + + return [show, hide] as const; +}; \ No newline at end of file diff --git a/src/routes/dashboard/[workspace_id].tsx b/src/routes/dashboard/[workspace_id].tsx index 7bbab5e..9c01909 100644 --- a/src/routes/dashboard/[workspace_id].tsx +++ b/src/routes/dashboard/[workspace_id].tsx @@ -40,6 +40,8 @@ import { DropdownMenu, Dialog } from "@kobalte/core"; import { useParams } from "solid-start"; +import { createModal } from "@/primitives/modal"; + import { createFileImporter, downloadUploadedFile, @@ -50,7 +52,7 @@ import { import { getContentOfWorkspace, createWorkspace } from "@/utils/workspaces"; -import type { WorkspaceContent } from "@/types/api"; +import type { UploadedFile, WorkspaceContent } from "@/types/api"; import { Switch } from "solid-js"; const Page: Component = () => { @@ -108,7 +110,50 @@ const Page: Component = () => { window.scrollTo(0, 0); }); - const [openDeletion, setOpenDeletion] = createSignal(false); + const [openDeleteModal] = createModal(({ Description, CloseButton, data: file }) => ( + <> +
+

+ Delete file +

+ + + +
+ + Are you sure you want to + permanently delete this file? You + won't be able to restore this from + the trash bin later on. + +
{ + event.preventDefault(); + await removePermanentlyFile(file!.id); + + setWorkspaceContent((prev) => prev + ? prev.filter(item => + item.type === "workspace" || + (item.type === "file" && item.data.id !== file!.id) + ) + : [] + ); + }} + > + + Yes + + + No + +
+ + )) return ( <> @@ -360,68 +405,12 @@ const Page: Component = () => { Favorite - openDeleteModal(file())} > - - - Delete permanently - - - -
- -
-

- Delete file -

- - - -
- - Are you sure you want to - permanently delete this file? You - won't be able to restore this from - the trash bin later on. - -
- - - - - No - -
-
-
-
-
+ + Delete permanently + diff --git a/uno.config.ts b/uno.config.ts index 3a084e6..7863038 100644 --- a/uno.config.ts +++ b/uno.config.ts @@ -1,15 +1,27 @@ -import { defineConfig, presetUno } from "unocss"; +import { type Preset, defineConfig, presetUno } from "unocss"; import { extendCatppuccin } from "unocss-catppuccin"; import presetRemToPx from "@unocss/preset-rem-to-px"; +import { presetKobalte } from "unocss-preset-primitives"; + import transformerVariantGroup from "@unocss/transformer-variant-group"; export default defineConfig({ presets: [ presetUno(), presetRemToPx(), + presetKobalte() as Preset, extendCatppuccin({ prefix: "", defaultVariant: "latte" }), ], transformers: [transformerVariantGroup()], + + theme: { + animation: { + keyframes: { + "scale-in": "{from{opacity:0;transform:scale(0.96)}to{opacity:1;transform:scale(1)}}", + "scale-out": "{from{opacity:1;transform:scale(&)}to{opacity:0;transform:scale(0.96)}}" + } + } + } });