Skip to content

Commit

Permalink
Better demo (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin authored Dec 1, 2023
1 parent 6869b0b commit dbdc9ae
Show file tree
Hide file tree
Showing 23 changed files with 596 additions and 372 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ Of course, that's a very simple application, the [full demo](https://fastui-demo

### Components

FastUI already defines the following components:
FastUI already defines the following components, all are shown in the [demo app](https://fastui-demo.onrender.com):

- `Text` - renders a string
- `Paragraph` - renders a string as a paragraph
- `PageTitle` - renders nothing, sets the HTML page title
- `Div` - renders a `<div>` with arbitrary components inside
- `Page` - a container for components, [example](https://fastui-demo.onrender.com)
- `Heading` - renders a heading `<h1>` to `<h6>`, [example](https://fastui-demo.onrender.com)
- `Page` - a container for components
- `Heading` - renders a heading `<h1>` to `<h6>`
- `Markdown` - renders markdown, [example](https://fastui-demo.onrender.com)
- `Code` - renders code with highlighting in a `<pre>`
- `Button` - renders a `<button>`
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/fastui-bootstrap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pydantic/fastui-bootstrap",
"version": "0.0.8",
"version": "0.0.9",
"description": "Boostrap renderer for FastUI",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -29,6 +29,6 @@
"sass": "^1.69.5"
},
"peerDependencies": {
"@pydantic/fastui": "0.0.8"
"@pydantic/fastui": "0.0.9"
}
}
11 changes: 1 addition & 10 deletions packages/fastui-bootstrap/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { pathMatch } from 'fastui'

import type { components, ClassNameGenerator, CustomRender, ClassName } from 'fastui'
import type { ClassNameGenerator, CustomRender, ClassName } from 'fastui'

import { Modal } from './modal'
import { Navbar } from './navbar'
Expand All @@ -9,8 +9,6 @@ import { Pagination } from './pagination'
export const customRender: CustomRender = (props) => {
const { type } = props
switch (type) {
case 'DisplayPrimitive':
return displayPrimitiveRender(props)
case 'Navbar':
return () => <Navbar {...props} />
case 'Modal':
Expand All @@ -20,13 +18,6 @@ export const customRender: CustomRender = (props) => {
}
}

function displayPrimitiveRender(props: components.DisplayPrimitiveProps) {
const { value } = props
if (typeof value === 'boolean') {
return () => <>{value ? '👍' : '👎'}</>
}
}

export const classNameGenerator: ClassNameGenerator = ({ props, fullPath, subElement }): ClassName => {
const { type } = props
switch (type) {
Expand Down
2 changes: 1 addition & 1 deletion packages/fastui-prebuilt/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pydantic/fastui-prebuilt",
"version": "0.0.8",
"version": "0.0.9",
"description": "Pre-built files for FastUI",
"main": "dist/index.html",
"type": "module",
Expand Down
34 changes: 26 additions & 8 deletions packages/fastui-prebuilt/src/main.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
$primary: black;
$link-color: #0d6efd; // bootstrap primary
$link-color: #0d6efd; // bootstrap primary

@import 'bootstrap/scss/bootstrap';

:root {
--bs-font-sans-serif: 'IBM Plex Sans', sans-serif;
--bs-code-color: rgb(31, 35, 40);
//
}
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;1,400&display=swap');

body {
margin-bottom: 60px;
}

.bg-body {
--bs-bg-opacity: 0.6;
backdrop-filter: blur(8px);
}

.top-offset {
margin-top: 70px;
h1, h2, h3, h4, h5, h6 {
scroll-margin-top: 60px;
}
}

.transition-overlay {
position: fixed;
top: 0;
Expand All @@ -27,13 +45,13 @@ $link-color: #0d6efd; // bootstrap primary
}
}

.bg-body {
--bs-bg-opacity: 0.6;
backdrop-filter: blur(8px);
}

.top-offset {
margin-top: 80px;
.fastui-markdown code {
padding: 0.2em 0.4em;
margin: 0;
font-size: 85%;
white-space: break-spaces;
background-color: rgba(175, 184, 193, 0.2);
border-radius: 6px;
}

// custom spinner from https://cssloaders.github.io/
Expand Down
2 changes: 1 addition & 1 deletion packages/fastui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pydantic/fastui",
"version": "0.0.8",
"version": "0.0.9",
"description": "Build better UIs faster.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
25 changes: 23 additions & 2 deletions packages/fastui/src/components/MarkdownLazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const MarkdownComp: FC<MarkdownProps> = (props) => {
}

return (
<Markdown className={useClassName(props)} remarkPlugins={[remarkGfm]} components={components}>
<Markdown
className={useClassName(props, { dft: 'fastui-markdown' })}
remarkPlugins={[remarkGfm]}
components={components}
>
{text}
</Markdown>
)
Expand Down Expand Up @@ -75,7 +79,24 @@ interface MarkdownCodeProps {

const MarkdownCode: FC<MarkdownCodeProps> = ({ children, className, codeStyle }) => {
const match = /language-(\w+)/.exec(className || '')
const language = match ? match[1] : undefined
if (match) {
return (
<MarkdownCodeHighlight codeStyle={codeStyle} language={match[1]}>
{children}
</MarkdownCodeHighlight>
)
} else {
return <code className={className}>{children}</code>
}
}

interface MarkdownCodeHighlightProps {
children: ReactNode
language?: string
codeStyle?: string
}

const MarkdownCodeHighlight: FC<MarkdownCodeHighlightProps> = ({ children, codeStyle, language }) => {
const codeProps: CodeProps = {
type: 'Code',
text: String(children).replace(/\n$/, ''),
Expand Down
19 changes: 18 additions & 1 deletion packages/fastui/src/components/ServerLoad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ export const ServerLoadFetch: FC<{ path: string; devReload?: number }> = ({ path
promise.then(([status, data]) => {
if (status === 200) {
setComponentProps(data as FastProps[])
// if there's a fragment, scroll to that ID once the page is loaded
const fragment = getFragment(path)
if (fragment) {
setTimeout(() => {
const element = document.getElementById(fragment)
if (element) {
element.scrollIntoView()
}
}, 50)
}
} else {
setNotFoundUrl(url)
}
Expand All @@ -71,7 +81,7 @@ export const ServerLoadFetch: FC<{ path: string; devReload?: number }> = ({ path
return () => {
promise.then(() => null)
}
}, [url, request, devReload])
}, [url, path, request, devReload])

useEffect(() => {
setNotFoundUrl(undefined)
Expand Down Expand Up @@ -129,3 +139,10 @@ function useServerUrl(path: string): string {
return rootUrl + requestPath
}
}

function getFragment(path: string): string | undefined {
const index = path.indexOf('#')
if (index !== -1) {
return path.slice(index + 1)
}
}
3 changes: 2 additions & 1 deletion packages/fastui/src/components/heading.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FC } from 'react'

import { ClassName, useClassName } from '../hooks/className'
import { slugify } from '../tools'

export interface HeadingProps {
type: 'Heading'
Expand All @@ -13,7 +14,7 @@ export interface HeadingProps {
export const HeadingComp: FC<HeadingProps> = (props) => {
const { level, text, htmlId } = props
const HeadingComponent = getComponent(level)
return <HeadingComponent text={text} id={htmlId} className={useClassName(props)} />
return <HeadingComponent text={text} id={htmlId || slugify(text)} className={useClassName(props)} />
}

function getComponent(level: 1 | 2 | 3 | 4 | 5 | 6): FC<{ text: string; id?: string; className?: string }> {
Expand Down
8 changes: 6 additions & 2 deletions packages/fastui/src/hooks/locationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,12 @@ export function LocationProvider({ children }: { children: ReactNode }) {
fullPath,
goto: useCallback(
(newPath) => {
const path = pushPath(newPath)
fireLoadEvent({ path })
if (newPath.startsWith('http')) {
window.location.href = newPath
} else {
const path = pushPath(newPath)
fireLoadEvent({ path })
}
},
[pushPath],
),
Expand Down
9 changes: 9 additions & 0 deletions packages/fastui/src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,12 @@ export async function sleep(ms: number): Promise<void> {

// usage `as_title('what_ever') > 'What Ever'`
export const asTitle = (s: string): string => s.replace(/[_-]/g, ' ').replace(/(_|\b)\w/g, (l) => l.toUpperCase())

export const slugify = (s: string): string =>
s
.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w-]+/g, '') // Remove all non-word characters
.replace(/--+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, '') // Trim - from end of text
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ classifiers = [
"Framework :: FastAPI",
]
requires-python = ">=3.8"
dependencies = ["pydantic>=2.5.2"]
dependencies = ["pydantic[email]>=2.5.2"]
dynamic = ["version"]

[project.optional-dependencies]
Expand Down
4 changes: 4 additions & 0 deletions python/demo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from fastui.dev import dev_fastapi_app
from httpx import AsyncClient

from .components_list import router as components_router
from .forms import router as forms_router
from .main import router as main_router
from .tables import router as table_router

Expand All @@ -27,7 +29,9 @@ async def lifespan(app_: FastAPI):
else:
app = FastAPI(lifespan=lifespan)

app.include_router(components_router, prefix='/api/components')
app.include_router(table_router, prefix='/api/table')
app.include_router(forms_router, prefix='/api/forms')
app.include_router(main_router, prefix='/api')


Expand Down
Loading

0 comments on commit dbdc9ae

Please sign in to comment.