Skip to content

Commit

Permalink
Merge pull request #44 from mrjvs/dev
Browse files Browse the repository at this point in the history
Guider v0.1.4
  • Loading branch information
mrjvs authored Mar 31, 2024
2 parents f446127 + 478deec commit 876e703
Show file tree
Hide file tree
Showing 81 changed files with 1,816 additions and 197 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- @neato/guider - beautiful documentation generator framework based on nextjs (ALPHA)

## Upcoming packages
- @neato/router - http router based on fastify ()
- @neato/orm - mini ORM, it's just migrations, mapper and a query builder
- @neato/email - JSX based email template engine
- @neato/router - http router based on fastify
- @neato/auth - fully fledged authentication system, including permissions
- @neato/jobs - persistent job queue
- @neato/log - simple logger with good pretty defaults
15 changes: 7 additions & 8 deletions apps/docs/components/showcase-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,13 @@ export function ShowcaseCard(props: { showcase: ShowcaseType }) {
<article className="border-line border p-4 rounded-2xl">
<Link
href={props.showcase.href}
className="block hover:opacity-75 aspect-video w-full bg-bgLightest mb-6 rounded-xl overflow-hidden"
>
<img
src={props.showcase.imageUrl}
alt={props.showcase.title}
className="object-cover object-center"
/>
</Link>
className="block hover:opacity-75 border-line border aspect-video w-full bg-bgLightest mb-6 rounded-xl overflow-hidden"
style={{
backgroundImage: `url(${props.showcase.imageUrl})`,
backgroundPosition: 'center',
backgroundSize: 'cover',
}}
/>
<Link href={props.showcase.href}>
<h1 className="text-lg hover:text-primary font-bold mb-1 text-textHeading">
{props.showcase.title}
Expand Down
71 changes: 59 additions & 12 deletions apps/docs/components/themer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { ThemeColorStoreColors } from '@neato/guider/client';
import { Button } from '@neato/guider/client';
import classNames from 'classnames';
import type { ReactNode } from 'react';
import React, { useState, useCallback } from 'react';
import React, { useState, useCallback, useRef } from 'react';
import type { HsbColor } from 'hooks/color-select';
import { hsbToColorToString, useColorSelect } from 'hooks/color-select';
import { useGuideThemePicker } from 'hooks/use-guider-theme-picker';
import { makeColors, useGuideThemePicker } from 'hooks/use-guider-theme-picker';
import styles from './themer.module.css';

function ThemeColor(props: {
Expand Down Expand Up @@ -89,6 +90,7 @@ function ColorPicker(props: {
export function ThemeColorPicker(props: {
colors: [HsbColor, HsbColor];
setColors: (n: [HsbColor, HsbColor]) => void;
onGetCode?: (colors: [HsbColor, HsbColor]) => void;
}) {
const { colors, setColors } = props;
const [selectedColor, setSelectedColor] = useState(0);
Expand Down Expand Up @@ -128,27 +130,72 @@ export function ThemeColorPicker(props: {
/>
</div>
<div className="p-4">
<Button className="w-full">Get the code</Button>
<Button className="w-full" onClick={() => props.onGetCode?.(colors)}>
Get the code
</Button>
</div>
</div>
);
}

export function Themer() {
export function Themer(props: {
onGetCode?: (colors: ThemeColorStoreColors) => void;
}) {
const [colors, setColors] = useGuideThemePicker();
const onGetCode = useCallback(
(c: [HsbColor, HsbColor]) => {
props.onGetCode?.(makeColors(c));
},
[props.onGetCode],
);

return <ThemeColorPicker colors={colors} setColors={setColors} />;
return (
<ThemeColorPicker
colors={colors}
setColors={setColors}
onGetCode={onGetCode}
/>
);
}

export function ThemerContainer(props: { children?: ReactNode }) {
const ref = useRef<HTMLDivElement>(null);
const tokenRef = useRef<HTMLSpanElement | null>(null);
const [hasCode, setHasCode] = useState(false);
const onGetCode = useCallback((c: ThemeColorStoreColors) => {
if (tokenRef.current) {
tokenRef.current.innerText = JSON.stringify(c, null, 2);
return;
}
if (ref.current) {
setHasCode(true);
const token = [
...ref.current.querySelectorAll('code [data-line] span'),
].find(
(el) => (el as HTMLSpanElement).innerText === 'CODE',
) as HTMLSpanElement | null;
if (token) {
tokenRef.current = token;
token.innerText = JSON.stringify(c, null, 2);
}
}
}, []);

return (
<div className="p-8 mt-28 flex border border-line rounded-xl">
<div className="flex-1 py-12 mr-8 [&>*:first-child]:mt-0">
{props.children}
</div>
<div className="w-[17rem] relative">
<div className="absolute inset-x-0 bottom-0">
<Themer />
<div
className={hasCode ? 'relative mb-[24rem]' : 'relative [&_figure]:hidden'}
>
<div className="sm:p-8 mt-28 flex flex-col lg:flex-row sm:border sm:border-line rounded-xl">
<div
ref={ref}
className="flex-1 py-12 mr-8 [&>*:first-child]:mt-0 [&>figure]:absolute [&>figure]:inset-x-0 [&>figure]:-bottom-12 [&>figure]:translate-y-full"
>
{props.children}
</div>
<div className="lg:w-[17rem] relative">
<div className="lg:absolute inset-x-0 bottom-0">
<Themer onGetCode={onGetCode} />
</div>
</div>
</div>
</div>
Expand Down
61 changes: 58 additions & 3 deletions apps/docs/hooks/use-guider-theme-picker.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,68 @@
import type { ThemeColorStoreColors } from '@neato/guider/client';
import { useGuiderTheme } from '@neato/guider/client';
import { useCallback, useEffect, useState } from 'react';
import Color from 'color';
import type { HsbColor } from './color-select';
import { hsbToColorToString } from './color-select';

function makeColors(c: [HsbColor, HsbColor]): ThemeColorStoreColors {
const clamp = (max: number, min: number, n: number) =>
Math.max(min, Math.min(max, n));

function getContrastPoint(color: Color): [number, number] {
if (color.isDark()) return [100, 0];
return [0, 100];
}

function getDistanceToContrastPoint(bgColor: Color, color: Color): number {
const contrastPoint = getContrastPoint(bgColor);
return Math.sqrt(
Math.pow(contrastPoint[0] - color.value(), 2) +
Math.pow(contrastPoint[1] - color.saturationl(), 2),
);
}

function moveColorToContrastPoint(
bgColor: Color,
color: Color,
amount: number,
): Color {
const contrastPoint = getContrastPoint(bgColor);
const length = getDistanceToContrastPoint(bgColor, color);
const ratio = amount / length;
const currentPoint = [color.value(), color.saturationl()];
const newX = currentPoint[0] + (contrastPoint[0] - currentPoint[0]) * ratio;
const newY = currentPoint[1] + (contrastPoint[1] - currentPoint[1]) * ratio;
return color.value(clamp(100, 0, newX)).saturationl(clamp(100, 0, newY));
}

function moveRatioColorToContrastPoint(
bgColor: Color,
color: Color,
ratio: number,
): Color {
const distance = getDistanceToContrastPoint(bgColor, color);
return moveColorToContrastPoint(bgColor, color, distance * ratio);
}

export function makeColors(c: [HsbColor, HsbColor]): ThemeColorStoreColors {
const primary = Color(hsbToColorToString(c[0]));
const bg = Color(hsbToColorToString(c[1]));
const text = moveRatioColorToContrastPoint(bg, bg, 0.7);

return {
primary: hsbToColorToString(c[0]),
background: hsbToColorToString(c[1]),
primary: primary.hex(),
primaryLighter: moveColorToContrastPoint(primary, primary, -30).hex(),
primaryDarker: moveColorToContrastPoint(primary, primary, 30).hex(),

background: bg.hex(),
backgroundLighter: moveColorToContrastPoint(bg, bg, 8).hex(),
backgroundLightest: moveColorToContrastPoint(bg, bg, 16).hex(),
backgroundDarker: moveColorToContrastPoint(bg, bg, -8).hex(),
line: moveColorToContrastPoint(bg, bg, 25).hex(),

text: text.hex(),
textLighter: moveColorToContrastPoint(bg, text, 10).hex(),
textHighlight: bg.isDark() ? '#fff' : '#000',
};
}

Expand Down
2 changes: 2 additions & 0 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@repo/eslint-config": "workspace:*",
"@repo/prettier-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/color": "^3.0.6",
"@types/react": "18.2.56",
"autoprefixer": "^10.4.17",
"postcss": "^8.4.37",
Expand All @@ -28,6 +29,7 @@
"dependencies": {
"@neato/guider": "workspace:*",
"classnames": "^2.5.1",
"color": "^4.2.3",
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/pages/docs/config/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function LandingPage() {
<Hero.Actions>
<Button to="/docs/config/guide/why-neat-config">Get started</Button>
<Button to="https://github.com/mrjvs/neatojs" type="secondary">
View on github
View on GitHub
</Button>
</Hero.Actions>
</Hero>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# `<GuiderContentFooter />`

React component that will show the currently configured content footer.

It respects configured `contentFooter` in the layout settings. Read more [about partials](../theme/settings.mdx#about-partials).


## Example

```tsx
<GuiderContentFooter />
```


## Reference

```tsx
function GuiderContentFooter(): ReactNode;
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# `<GuiderHeader />`

<Caution>
This article is a stub, please help by contributing to the docs.
</Caution>
React component that will show the currently configured navigation partial.

It respects configured `navigation` in the layout settings. Read more [about partials](../theme/settings.mdx#about-partials).


## Example

```tsx
<div id="custom-header">
<GuiderHeader /> // [!code focus]
</div>
```


## Reference

```tsx
function GuiderHeader(): ReactNode;
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,61 @@
# `<GuiderLayout />`

<Caution>
This article is a stub, please help by contributing to the docs.
</Caution>
React component that will show the currently configured layout partial.

It respects configured `layout` in the layout settings. Read more [about partials](../theme/settings.mdx#about-partials).

The primary use of this component is to make a non-MDX page look like an MDX page. Don't use it if you're already in an MDX File.

## Example

```tsx
<GuiderLayout meta={{ layout: 'page' }}>
<h1>Custom page</h1>
<p>This is a custom page that doesn't use MDX</p>
</GuiderLayout>
```


## Reference

```tsx
function GuiderLayout(props);
```
<Field title="props" type="object" required>
The props for this component. Every prop is optional.

<Field.Properties defaultOpen>
<Field title="meta" type="MetaConf">
The meta configuration, see [the meta file reference](../meta/structure.mdx) for the contents.
</Field>
<Field title="excerpt" type="string">
An excerpt of the page, used in meta tags for SEO.
</Field>
<Field title="headings" type="MdxHeadings[]">
The headings of the page, first depth 1 heading is used as page title for SEO.

This is also to display the table of contents.

<Field.Properties>
<Field title="depth" type="number" required>
The depth of the heading. Equals to the amount of hashtags of the heading.
</Field>
<Field title="value" type="string" required>
Text content of the heading.
</Field>
<Field title="data" type="object" required>
Extra data associated with the heading.

<Field.Properties>
<Field title="id" type="string" required>
The ID of the heading.
</Field>
</Field.Properties>
</Field>
</Field.Properties>
</Field>
<Field title="children" type="ReactNode">
The children of the react component, it will be displayed as the page contents.
</Field>
</Field.Properties>
</Field>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# `<GuiderLogo />`

React component that will show the currently configured logo.

It respects configured `logo` in the layout settings. Read more [about partials](../theme/settings.mdx#about-partials).


## Example

```tsx
<GuiderLogo />
```


## Reference

```tsx
function GuiderLogo(): ReactNode;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# `<GuiderPageFooter />`

React component that will show the currently configured page footer.

It respects configured `pageFooter` in the layout settings. Read more [about partials](../theme/settings.mdx#about-partials).


## Example

```tsx
<GuiderPageFooter />
```


## Reference

```tsx
function GuiderPageFooter(): ReactNode;
```
Loading

0 comments on commit 876e703

Please sign in to comment.