From 38df5338df6d901a05b5f8204211129c35074f42 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 12:25:02 +0200 Subject: [PATCH 01/12] chore(deps): add new deps --- packages/roadplan-ui/package.json | 3 +- pnpm-lock.yaml | 110 +++++++++--------------------- 2 files changed, 36 insertions(+), 77 deletions(-) diff --git a/packages/roadplan-ui/package.json b/packages/roadplan-ui/package.json index ce3063b..def0abf 100644 --- a/packages/roadplan-ui/package.json +++ b/packages/roadplan-ui/package.json @@ -1,5 +1,5 @@ { - "name": "my-qwik-library-name", + "name": "roadplan-ui", "version": "0.0.1", "description": "Create a reusable Qwik component library", "main": "./lib/index.qwik.mjs", @@ -37,6 +37,7 @@ }, "devDependencies": { "@builder.io/qwik": "1.5.5", + "@builder.io/qwik-city": "^1.5.5", "@types/eslint": "^8.56.10", "@types/node": "^20.12.7", "@typescript-eslint/eslint-plugin": "^7.7.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2761290..4593064 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,85 +40,14 @@ importers: specifier: ^5.2.2 version: 5.2.2 - packages/create-roadplan/template: - devDependencies: - '@builder.io/qwik': - specifier: ^1.5.2 - version: 1.5.2(@types/node@20.12.7)(sass@1.74.1)(undici@6.12.0) - '@builder.io/qwik-city': - specifier: ^1.5.2 - version: 1.5.2(@types/node@20.12.7)(rollup@4.14.1)(sass@1.74.1) - '@types/eslint': - specifier: ^8.56.7 - version: 8.56.7 - '@types/estree-jsx': - specifier: ^1.0.5 - version: 1.0.5 - '@types/node': - specifier: ^20.12.7 - version: 20.12.7 - '@typescript-eslint/eslint-plugin': - specifier: ^7.6.0 - version: 7.6.0(@typescript-eslint/parser@7.6.0(eslint@8.54.0)(typescript@5.4.5))(eslint@8.54.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.6.0 - version: 7.6.0(eslint@8.54.0)(typescript@5.4.5) - autoprefixer: - specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.38) - eslint: - specifier: ^8.51.0 - version: 8.54.0 - eslint-plugin-qwik: - specifier: 1.5.2 - version: 1.5.2(eslint@8.54.0) - postcss: - specifier: ^8.4.38 - version: 8.4.38 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prettier-plugin-tailwindcss: - specifier: ^0.5.13 - version: 0.5.13(prettier@3.2.5) - rehype-pretty-code: - specifier: ^0.13.1 - version: 0.13.1(shiki@1.3.0) - sass: - specifier: ^1.74.1 - version: 1.74.1 - shiki: - specifier: ^1.3.0 - version: 1.3.0 - tailwindcss: - specifier: 3.4.3 - version: 3.4.3 - typescript: - specifier: ^5.4.5 - version: 5.4.5 - undici: - specifier: ^6.12.0 - version: 6.12.0 - unified: - specifier: ^11.0.4 - version: 11.0.4 - unist-util-visit: - specifier: ^5.0.0 - version: 5.0.0 - vite: - specifier: ^5.2.8 - version: 5.2.8(@types/node@20.12.7)(sass@1.74.1) - vite-tsconfig-paths: - specifier: ^4.3.2 - version: 4.3.2(typescript@5.4.5)(vite@5.2.8(@types/node@20.12.7)(sass@1.74.1)) - - packages/create-roadplan/template/server: {} - packages/roadplan-ui: devDependencies: '@builder.io/qwik': specifier: 1.5.5 version: 1.5.5(@types/node@20.12.7)(sass@1.74.1)(undici@6.12.0) + '@builder.io/qwik-city': + specifier: ^1.5.5 + version: 1.5.5(@types/node@20.12.7)(rollup@4.14.1)(sass@1.74.1) '@types/eslint': specifier: ^8.56.10 version: 8.56.10 @@ -231,8 +160,6 @@ importers: specifier: ^4.3.2 version: 4.3.2(typescript@5.4.5)(vite@5.2.8(@types/node@20.12.7)(sass@1.74.1)) - packages/template/server: {} - packages: '@aashutoshrathi/word-wrap@1.2.6': @@ -262,6 +189,10 @@ packages: resolution: {integrity: sha512-hQ9OxIgfMg7msfPV/oowlzT6sOSJqtZD+8svEzPFsTeYwxkZZV7g0QEudsO0xX5htWj9bcDlE19SCPI2kvL/qA==} engines: {node: '>=16.8.0 <18.0.0 || >=18.11'} + '@builder.io/qwik-city@1.5.5': + resolution: {integrity: sha512-Xi/1WqrB91CpZcAXs43OC87+7h89hJczJp43FXUMrvTHGeUsR/udhpz6SZWI/mHh0PFNx6f0A59tPmtDDzYl0Q==} + engines: {node: '>=16.8.0 <18.0.0 || >=18.11'} + '@builder.io/qwik@1.5.2': resolution: {integrity: sha512-dUz61FEhC7NjJx0xDnCz6+F6uSBZgJUeur9+EYekpP/BNe2pr4ZH5FORcEOLetJtmxezR6EwTU3GeDLl5159Jg==} engines: {node: '>=16.8.0 <18.0.0 || >=18.11'} @@ -801,6 +732,9 @@ packages: '@types/mdx@2.0.12': resolution: {integrity: sha512-H9VZ9YqE+H28FQVchC83RCs5xQ2J7mAAv6qdDEaWmXEVl3OpdH+xfrSUzQ1lp7U7oSTRZ0RvW08ASPJsYBi7Cw==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} @@ -3684,6 +3618,28 @@ snapshots: - supports-color - terser + '@builder.io/qwik-city@1.5.5(@types/node@20.12.7)(rollup@4.14.1)(sass@1.74.1)': + dependencies: + '@mdx-js/mdx': 3.0.1 + '@types/mdx': 2.0.13 + source-map: 0.7.4 + svgo: 3.2.0 + undici: 6.12.0 + vfile: 6.0.1 + vite: 5.2.11(@types/node@20.12.7)(sass@1.74.1) + vite-imagetools: 6.2.9(rollup@4.14.1) + zod: 3.22.4 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - rollup + - sass + - stylus + - sugarss + - supports-color + - terser + '@builder.io/qwik@1.5.2(@types/node@20.12.7)(sass@1.74.1)(undici@6.12.0)': dependencies: csstype: 3.1.3 @@ -4151,6 +4107,8 @@ snapshots: '@types/mdx@2.0.12': {} + '@types/mdx@2.0.13': {} + '@types/ms@0.7.34': {} '@types/node@20.12.7': From 54b6e7507823d465a9f6b24ddc3c41fd38a9a312 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 12:27:01 +0200 Subject: [PATCH 02/12] feat(docs-components): add components related to the layout of the doc site --- .../src/docs-components/Aside/Aside.tsx | 31 +++++ .../src/docs-components/Footer/Footer.tsx | 24 ++++ .../src/docs-components/Header/Header.tsx | 125 ++++++++++++++++++ .../ThemeSelector/ThemeSelector.tsx | 26 ++++ .../src/docs-components/Toc/Toc.tsx | 22 +++ .../VersionSelector/VersionSelector.tsx | 77 +++++++++++ 6 files changed, 305 insertions(+) create mode 100644 packages/roadplan-ui/src/docs-components/Aside/Aside.tsx create mode 100644 packages/roadplan-ui/src/docs-components/Footer/Footer.tsx create mode 100644 packages/roadplan-ui/src/docs-components/Header/Header.tsx create mode 100644 packages/roadplan-ui/src/docs-components/ThemeSelector/ThemeSelector.tsx create mode 100644 packages/roadplan-ui/src/docs-components/Toc/Toc.tsx create mode 100644 packages/roadplan-ui/src/docs-components/VersionSelector/VersionSelector.tsx diff --git a/packages/roadplan-ui/src/docs-components/Aside/Aside.tsx b/packages/roadplan-ui/src/docs-components/Aside/Aside.tsx new file mode 100644 index 0000000..129a9b3 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/Aside/Aside.tsx @@ -0,0 +1,31 @@ +import { component$ } from "@builder.io/qwik"; +import { useContent } from "@builder.io/qwik-city"; + +export const Aside = component$(() => { + const { menu } = useContent(); + + return ( +
+ {(menu?.items || []).map(({ text, items }, idx) => ( +
    +
  • +
    {text}
    + {(items || []).map(({ text, href }, idx) => ( + + ))} +
  • +
+ ))} +
+ ); +}); diff --git a/packages/roadplan-ui/src/docs-components/Footer/Footer.tsx b/packages/roadplan-ui/src/docs-components/Footer/Footer.tsx new file mode 100644 index 0000000..6135ae4 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/Footer/Footer.tsx @@ -0,0 +1,24 @@ +import { component$ } from "@builder.io/qwik"; +import { GitHubIcon } from "../../Icons/GitHubIcon"; + +export const Footer = component$(() => { + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/docs-components/Header/Header.tsx b/packages/roadplan-ui/src/docs-components/Header/Header.tsx new file mode 100644 index 0000000..7c076f4 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/Header/Header.tsx @@ -0,0 +1,125 @@ +/* eslint-disable qwik/jsx-img */ +import { component$, useSignal } from "@builder.io/qwik"; + +import { CloseIcon } from "../../Icons/CloseIcon"; +import { GitHubIcon } from "../../Icons/GitHubIcon"; +import { MenuIcon } from "../../Icons/MenuIcon"; +import { Aside } from "../Aside/Aside"; +import { ThemeSelector } from "../ThemeSelector/ThemeSelector"; +import { VersionSelector } from "../VersionSelector/VersionSelector"; + +type Props = { + links?: { name: string; href: string }[]; + showMenu?: boolean; + siteTitle?: string; + isVersionSelector?: boolean; +}; +export const Header = component$( + ({ links = [], showMenu = true, siteTitle, isVersionSelector = false }) => { + const showAsideSig = useSignal(false); + return ( +
+
+
+ {showMenu && ( + + )} + +
+
+ +
+ logo-black +
+
+ logo-white +
+
+ +
+
+ {isVersionSelector && } + + +
+
+ {showAsideSig.value && ( +
+
+
+
+
+
(showAsideSig.value = false)} + > + +
+
+
+
+
+ )} +
+ ); + }, +); diff --git a/packages/roadplan-ui/src/docs-components/ThemeSelector/ThemeSelector.tsx b/packages/roadplan-ui/src/docs-components/ThemeSelector/ThemeSelector.tsx new file mode 100644 index 0000000..09bb970 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/ThemeSelector/ThemeSelector.tsx @@ -0,0 +1,26 @@ +import { component$, useContext } from "@builder.io/qwik"; +import { StoreContext } from "../../docs-layout/classic-layout"; +import { ThemeDarkIcon } from "../../Icons/ThemeDarkIcon"; +import { ThemeLightIcon } from "../../Icons/ThemeLightIcon"; + +export const ThemeSelector = component$(() => { + const store = useContext(StoreContext); + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/docs-components/Toc/Toc.tsx b/packages/roadplan-ui/src/docs-components/Toc/Toc.tsx new file mode 100644 index 0000000..d185bd4 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/Toc/Toc.tsx @@ -0,0 +1,22 @@ +import { component$ } from "@builder.io/qwik"; +import { useContent } from "@builder.io/qwik-city"; + +export const Toc = component$(() => { + const { headings } = useContent(); + + return ( +
+ On this page + {(headings || []).map(({ text, id }, idx) => ( + + ))} +
+ ); +}); diff --git a/packages/roadplan-ui/src/docs-components/VersionSelector/VersionSelector.tsx b/packages/roadplan-ui/src/docs-components/VersionSelector/VersionSelector.tsx new file mode 100644 index 0000000..e33d845 --- /dev/null +++ b/packages/roadplan-ui/src/docs-components/VersionSelector/VersionSelector.tsx @@ -0,0 +1,77 @@ +import { component$, useComputed$, useSignal } from "@builder.io/qwik"; +import { useLocation, useNavigate } from "@builder.io/qwik-city"; +import { ChevronIcon } from "../../Icons/ChevronIcon"; + +const paths = import.meta.glob("/src/routes/versions/**/*", { eager: true }); + +let versions = Object.keys(paths) + .filter((path) => path.indexOf("/src/routes/versions/") === 0) + .map((path) => { + path = path.replace("/src/routes/versions/", ""); + const folders = path.split("/"); + return folders[0]; + }) + .filter((path) => path.indexOf(".mdx") === -1) + .sort((a, b) => (b === "latest" ? 1 : a > b ? -1 : 1)); + +versions = [...new Set(versions)]; + +export const VersionSelector = component$(() => { + const location = useLocation(); + const versionSig = useComputed$( + () => location.url.pathname.replace("/versions/", "").split("/")[0], + ); + const navigate = useNavigate(); + const showSig = useSignal(false); + return ( +
+ + {showSig.value && ( + + )} +
+ ); +}); From 823feb9fe998a63087d24e2018f022bafc610494 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 12:27:45 +0200 Subject: [PATCH 03/12] feat(icons): add icons --- packages/roadplan-ui/src/Icons/CheckIcon.tsx | 20 ++++++++++++++++++ .../roadplan-ui/src/Icons/ChevronIcon.tsx | 18 ++++++++++++++++ packages/roadplan-ui/src/Icons/CloseIcon.tsx | 20 ++++++++++++++++++ packages/roadplan-ui/src/Icons/CopyIcon.tsx | 21 +++++++++++++++++++ packages/roadplan-ui/src/Icons/ForkIcon.tsx | 17 +++++++++++++++ packages/roadplan-ui/src/Icons/GitHubIcon.tsx | 21 +++++++++++++++++++ packages/roadplan-ui/src/Icons/MenuIcon.tsx | 21 +++++++++++++++++++ packages/roadplan-ui/src/Icons/StarIcon.tsx | 17 +++++++++++++++ .../roadplan-ui/src/Icons/ThemeDarkIcon.tsx | 19 +++++++++++++++++ .../roadplan-ui/src/Icons/ThemeLightIcon.tsx | 19 +++++++++++++++++ 10 files changed, 193 insertions(+) create mode 100644 packages/roadplan-ui/src/Icons/CheckIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/ChevronIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/CloseIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/CopyIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/ForkIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/GitHubIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/MenuIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/StarIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/ThemeDarkIcon.tsx create mode 100644 packages/roadplan-ui/src/Icons/ThemeLightIcon.tsx diff --git a/packages/roadplan-ui/src/Icons/CheckIcon.tsx b/packages/roadplan-ui/src/Icons/CheckIcon.tsx new file mode 100644 index 0000000..f02110f --- /dev/null +++ b/packages/roadplan-ui/src/Icons/CheckIcon.tsx @@ -0,0 +1,20 @@ +import { component$ } from "@builder.io/qwik"; + +export const CheckIcon = component$(() => { + return ( + + + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/ChevronIcon.tsx b/packages/roadplan-ui/src/Icons/ChevronIcon.tsx new file mode 100644 index 0000000..9ed5fac --- /dev/null +++ b/packages/roadplan-ui/src/Icons/ChevronIcon.tsx @@ -0,0 +1,18 @@ +import { component$ } from "@builder.io/qwik"; + +export const ChevronIcon = component$(() => { + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/CloseIcon.tsx b/packages/roadplan-ui/src/Icons/CloseIcon.tsx new file mode 100644 index 0000000..321f169 --- /dev/null +++ b/packages/roadplan-ui/src/Icons/CloseIcon.tsx @@ -0,0 +1,20 @@ +import { component$ } from "@builder.io/qwik"; + +export const CloseIcon = component$(() => { + return ( + + + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/CopyIcon.tsx b/packages/roadplan-ui/src/Icons/CopyIcon.tsx new file mode 100644 index 0000000..4fe7e84 --- /dev/null +++ b/packages/roadplan-ui/src/Icons/CopyIcon.tsx @@ -0,0 +1,21 @@ +import { component$ } from "@builder.io/qwik"; + +export const CopyIcon = component$(() => { + return ( + + + + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/ForkIcon.tsx b/packages/roadplan-ui/src/Icons/ForkIcon.tsx new file mode 100644 index 0000000..e98c24f --- /dev/null +++ b/packages/roadplan-ui/src/Icons/ForkIcon.tsx @@ -0,0 +1,17 @@ +import { component$ } from "@builder.io/qwik"; + +export const ForkIcon = component$(() => { + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/GitHubIcon.tsx b/packages/roadplan-ui/src/Icons/GitHubIcon.tsx new file mode 100644 index 0000000..c21fed5 --- /dev/null +++ b/packages/roadplan-ui/src/Icons/GitHubIcon.tsx @@ -0,0 +1,21 @@ +import { component$ } from "@builder.io/qwik"; + +export const GitHubIcon = component$<{ classes?: string }>( + ({ classes = "w-8 h8" }) => { + return ( + + ); + }, +); diff --git a/packages/roadplan-ui/src/Icons/MenuIcon.tsx b/packages/roadplan-ui/src/Icons/MenuIcon.tsx new file mode 100644 index 0000000..42e9676 --- /dev/null +++ b/packages/roadplan-ui/src/Icons/MenuIcon.tsx @@ -0,0 +1,21 @@ +import { component$ } from "@builder.io/qwik"; + +export const MenuIcon = component$(() => { + return ( + + + + + + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/StarIcon.tsx b/packages/roadplan-ui/src/Icons/StarIcon.tsx new file mode 100644 index 0000000..384a4c7 --- /dev/null +++ b/packages/roadplan-ui/src/Icons/StarIcon.tsx @@ -0,0 +1,17 @@ +import { component$ } from "@builder.io/qwik"; + +export const StarIcon = component$(() => { + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/ThemeDarkIcon.tsx b/packages/roadplan-ui/src/Icons/ThemeDarkIcon.tsx new file mode 100644 index 0000000..decebfe --- /dev/null +++ b/packages/roadplan-ui/src/Icons/ThemeDarkIcon.tsx @@ -0,0 +1,19 @@ +import { component$ } from "@builder.io/qwik"; + +export const ThemeDarkIcon = component$(() => { + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/Icons/ThemeLightIcon.tsx b/packages/roadplan-ui/src/Icons/ThemeLightIcon.tsx new file mode 100644 index 0000000..426046d --- /dev/null +++ b/packages/roadplan-ui/src/Icons/ThemeLightIcon.tsx @@ -0,0 +1,19 @@ +import { component$ } from "@builder.io/qwik"; + +export const ThemeLightIcon = component$(() => { + return ( + + ); +}); From 37c725547b2bcad5f6933892c3df690675631ed2 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 12:28:20 +0200 Subject: [PATCH 04/12] feat(state): add state --- .../roadplan-ui/src/state/MDXProvider.tsx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/roadplan-ui/src/state/MDXProvider.tsx diff --git a/packages/roadplan-ui/src/state/MDXProvider.tsx b/packages/roadplan-ui/src/state/MDXProvider.tsx new file mode 100644 index 0000000..e1a2502 --- /dev/null +++ b/packages/roadplan-ui/src/state/MDXProvider.tsx @@ -0,0 +1,50 @@ +import { + Slot, + component$, + createContextId, + useContext, + useContextProvider, + type Component, +} from "@builder.io/qwik"; + +export const MDXContext = createContextId("MDXContext"); + +export interface Components { + [tag: string]: Component; +} + +/** + * Get current components from the MDX Context. + */ +export function useMDXComponents() { + return useContext(MDXContext, {}); +} + +export const DefaultWrapper = component$(() => { + return ; +}); + +/** + * Provider for MDX context + */ +export const MDXProvider = component$( + ({ + components, + disableParentContext, + }: { + components: Components; + disableParentContext?: boolean; + }) => { + let allComponents = useMDXComponents(); + if (disableParentContext) { + allComponents = components; + } else { + allComponents = { ...allComponents, ...components }; + } + useContextProvider(MDXContext, { + wrapper: DefaultWrapper, + ...allComponents, + }); + return ; + }, +); From 02e7d8a74fedf1853660b6ece34ae376b3d52fb1 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 12:29:24 +0200 Subject: [PATCH 05/12] feat(user-components): add components to within the docs site --- .../CodeSnippet/CodeSnippet.tsx | 46 ++++++++++ .../user-components/CopyButton/CopyButton.tsx | 40 +++++++++ .../user-components/Highlight/Highlight.tsx | 84 +++++++++++++++++++ .../MdxComponents/MdxComponents.tsx | 32 +++++++ 4 files changed, 202 insertions(+) create mode 100644 packages/roadplan-ui/src/user-components/CodeSnippet/CodeSnippet.tsx create mode 100644 packages/roadplan-ui/src/user-components/CopyButton/CopyButton.tsx create mode 100644 packages/roadplan-ui/src/user-components/Highlight/Highlight.tsx create mode 100644 packages/roadplan-ui/src/user-components/MdxComponents/MdxComponents.tsx diff --git a/packages/roadplan-ui/src/user-components/CodeSnippet/CodeSnippet.tsx b/packages/roadplan-ui/src/user-components/CodeSnippet/CodeSnippet.tsx new file mode 100644 index 0000000..66f98f8 --- /dev/null +++ b/packages/roadplan-ui/src/user-components/CodeSnippet/CodeSnippet.tsx @@ -0,0 +1,46 @@ +import type { PropsOf } from "@builder.io/qwik"; +import { component$, useSignal, useTask$ } from "@builder.io/qwik"; +import { useLocation } from "@builder.io/qwik-city"; +import { isDev } from "@builder.io/qwik/build"; +import { Highlight } from "../Highlight/Highlight"; + +// The below `/src/routes/docs/**/**/snippets/*.tsx` pattern is here so that import.meta.glob works both for styled and headless routes. +// For example: +// /src/routes/docs/components/styled/modal/snippets/building-blocks.tsx +// /src/routes/docs/components/headless/modal/snippets/building-blocks.tsx + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const codeSnippets: any = import.meta.glob(`/src/**/snippets/*`, { + query: "?raw", + eager: isDev ? false : true, +}); + +type CodeSnippetProps = PropsOf<"div"> & { + name: string; +}; + +export const CodeSnippet = component$(({ name }) => { + const location = useLocation(); + + // Determine the file extension if not specified + const fileExtension = + name.endsWith(".tsx") || name.endsWith(".ts") || name.endsWith(".css") + ? "" + : ".tsx"; + const snippetPath = `/src/routes${location.url.pathname}snippets/${name}${fileExtension}`; + + const codeSnippetSig = useSignal(); + + useTask$(async () => { + const code = isDev + ? await codeSnippets[snippetPath]() // We need to call `await codeSnippets[snippetPath]()` in development as it is `eager:false` + : codeSnippets[snippetPath]; // We need to directly access the `codeSnippets[snippetPath]` expression in preview/production as it is `eager:true` + codeSnippetSig.value = code.default; + }); + + return ( +
+ +
+ ); +}); diff --git a/packages/roadplan-ui/src/user-components/CopyButton/CopyButton.tsx b/packages/roadplan-ui/src/user-components/CopyButton/CopyButton.tsx new file mode 100644 index 0000000..6a81d5f --- /dev/null +++ b/packages/roadplan-ui/src/user-components/CopyButton/CopyButton.tsx @@ -0,0 +1,40 @@ +import type { QwikIntrinsicElements } from "@builder.io/qwik"; +import { $, component$, useSignal, useTask$ } from "@builder.io/qwik"; +import { CheckIcon } from "../../Icons/CheckIcon"; +import { CopyIcon } from "../../Icons/CopyIcon"; + +type CopyButtonProps = QwikIntrinsicElements["button"] & { + code: string; + src?: string; +}; +export async function copyToClipboardWithMeta(value: string) { + navigator.clipboard.writeText(value); +} + +export const CopyButton = component$(({ code, ...props }) => { + const hasCopied = useSignal(false); + + useTask$(({ track }) => { + track(() => hasCopied.value); + setTimeout( + $(() => { + hasCopied.value = false; + }), + 2000, + ); + }); + + return ( + + ); +}); diff --git a/packages/roadplan-ui/src/user-components/Highlight/Highlight.tsx b/packages/roadplan-ui/src/user-components/Highlight/Highlight.tsx new file mode 100644 index 0000000..4b29661 --- /dev/null +++ b/packages/roadplan-ui/src/user-components/Highlight/Highlight.tsx @@ -0,0 +1,84 @@ +import type { ClassList, PropsOf } from "@builder.io/qwik"; +import { $, component$, useSignal, useTask$ } from "@builder.io/qwik"; +import { getHighlighterCore } from "shiki"; +import css from "shiki/langs/css.mjs"; +import html from "shiki/langs/html.mjs"; +import tsx from "shiki/langs/tsx.mjs"; +import poimandres from "shiki/themes/poimandres.mjs"; +import { CopyButton } from "../CopyButton/CopyButton"; + +export type HighlightProps = PropsOf<"div"> & { + code: string; + copyCodeClass?: ClassList; + language?: "tsx" | "html" | "css"; + splitCommentStart?: string; + splitCommentEnd?: string; +}; + +export const Highlight = component$( + ({ + code, + copyCodeClass, + language = "tsx", + splitCommentStart = "{/* start */}", + splitCommentEnd = "{/* end */}", + ...props + }: HighlightProps) => { + const codeSig = useSignal(""); + + const addShiki$ = $(async () => { + let modifiedCode: string = code; + + let partsOfCode = modifiedCode.split(splitCommentStart); + if (partsOfCode.length > 1) { + modifiedCode = partsOfCode[1]; + } + + partsOfCode = modifiedCode.split(splitCommentEnd); + if (partsOfCode.length > 1) { + modifiedCode = partsOfCode[0]; + } + + const highlighter = await getHighlighterCore({ + themes: [poimandres], + langs: [html, css, tsx], + loadWasm: import("shiki/wasm"), + }); + + const str = highlighter.codeToHtml(modifiedCode, { + lang: language, + themes: { + light: "poimandres", + dark: "poimandres", + }, + }); + codeSig.value = str.toString(); + }); + + useTask$(async ({ track }) => { + track(() => code); + await addShiki$(); + }); + + return ( +
+ +
+
+
+
+ ); + }, +); diff --git a/packages/roadplan-ui/src/user-components/MdxComponents/MdxComponents.tsx b/packages/roadplan-ui/src/user-components/MdxComponents/MdxComponents.tsx new file mode 100644 index 0000000..8feb757 --- /dev/null +++ b/packages/roadplan-ui/src/user-components/MdxComponents/MdxComponents.tsx @@ -0,0 +1,32 @@ +import type { QwikIntrinsicElements } from "@builder.io/qwik"; +import { Slot, component$ } from "@builder.io/qwik"; +import { CodeSnippet } from "../CodeSnippet/CodeSnippet"; +import { CopyButton } from "../CopyButton/CopyButton"; + +export const components: Record = { + pre: component$< + QwikIntrinsicElements["div"] & { + __rawString__?: string; + } + >(({ __rawString__ }) => { + return ( +
+
+          
+          
+        
+
+ ); + }), + code: component$(({ ...props }) => { + return ( + + + + ); + }), + CodeSnippet, +}; From 591626f02de85dbf663d89b00bdfaa0c3ce63cc9 Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 13:11:47 +0200 Subject: [PATCH 06/12] chore(deps): add qwikcity --- packages/roadplan-ui/package.json | 3 ++- packages/roadplan-ui/vite.config.ts | 7 ++++--- pnpm-lock.yaml | 7 +++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/roadplan-ui/package.json b/packages/roadplan-ui/package.json index def0abf..0018246 100644 --- a/packages/roadplan-ui/package.json +++ b/packages/roadplan-ui/package.json @@ -49,6 +49,7 @@ "typescript": "5.4.5", "undici": "*", "vite": "^5.2.10", - "vite-tsconfig-paths": "^4.2.1" + "vite-tsconfig-paths": "^4.2.1", + "shiki": "^1.3.0" } } diff --git a/packages/roadplan-ui/vite.config.ts b/packages/roadplan-ui/vite.config.ts index dab77fb..7c13ca4 100644 --- a/packages/roadplan-ui/vite.config.ts +++ b/packages/roadplan-ui/vite.config.ts @@ -1,7 +1,8 @@ -import { defineConfig } from "vite"; -import pkg from "./package.json"; +import { qwikCity } from "@builder.io/qwik-city/vite"; import { qwikVite } from "@builder.io/qwik/optimizer"; +import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; +import pkg from "./package.json"; const { dependencies = {}, peerDependencies = {} } = pkg as any; const makeRegex = (dep) => new RegExp(`^${dep}(/.*)?$`); @@ -25,6 +26,6 @@ export default defineConfig(() => { ], }, }, - plugins: [qwikVite(), tsconfigPaths()], + plugins: [qwikVite(), qwikCity(), tsconfigPaths()], }; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4593064..8dc01ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,6 +72,9 @@ importers: prettier: specifier: ^3.2.5 version: 3.2.5 + shiki: + specifier: ^1.3.0 + version: 1.3.0 typescript: specifier: 5.4.5 version: 5.4.5 @@ -3644,7 +3647,7 @@ snapshots: dependencies: csstype: 3.1.3 undici: 6.12.0 - vite: 5.2.8(@types/node@20.12.7)(sass@1.74.1) + vite: 5.2.11(@types/node@20.12.7)(sass@1.74.1) transitivePeerDependencies: - '@types/node' - less @@ -3931,7 +3934,7 @@ snapshots: '@types/estree': 1.0.5 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 - '@types/mdx': 2.0.12 + '@types/mdx': 2.0.13 collapse-white-space: 2.1.0 devlop: 1.1.0 estree-util-build-jsx: 3.0.1 From 96a557627fe19b87ddc8ec903996967bf50f3eac Mon Sep 17 00:00:00 2001 From: Benjamin Vinterberg Date: Fri, 24 May 2024 13:12:09 +0200 Subject: [PATCH 07/12] chore(qwikcity): setup routes --- packages/roadplan-ui/src/root.tsx | 23 +++++++++++++++-------- packages/roadplan-ui/src/routes/index.tsx | 4 ++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 packages/roadplan-ui/src/routes/index.tsx diff --git a/packages/roadplan-ui/src/root.tsx b/packages/roadplan-ui/src/root.tsx index cde5946..ae55ecc 100644 --- a/packages/roadplan-ui/src/root.tsx +++ b/packages/roadplan-ui/src/root.tsx @@ -1,15 +1,22 @@ -import { Button } from "./components/Button/Button"; +import { + QwikCityProvider, + RouterOutlet, + ServiceWorkerRegister, +} from "@builder.io/qwik-city"; export default () => { return ( <> - - - Qwik Blank App - - -