Skip to content

Commit

Permalink
WIP: add rfc
Browse files Browse the repository at this point in the history
  • Loading branch information
nihgwu committed Aug 12, 2022
1 parent 5597108 commit 5b148e4
Show file tree
Hide file tree
Showing 15 changed files with 487 additions and 30 deletions.
37 changes: 37 additions & 0 deletions example/components/RFCItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useId } from 'react'
import { createHost, createSlot } from 'create-slots/rfc'

type ItemProps = Omit<React.ComponentPropsWithoutRef<'li'>, 'value'> & {
value: string
}

const ItemTitle = createSlot<'h4'>()
const ItemDescription = createSlot<'div'>()

export const Item = (props: ItemProps) => {
const id = useId()

return createHost(props.children, (slots) => {
const titleSlot = slots.find((slot) => slot.type === ItemTitle)
const descriptionSlot = slots.find((slot) => slot.type === ItemDescription)
const titleId = titleSlot ? `${id}-title` : undefined
const descId = descriptionSlot ? `${id}-desc` : undefined
return (
<li aria-describedby={descId} aria-label={titleId} {...props}>
{titleSlot && (
<h4 id={titleId} ref={(titleSlot as any).ref} {...titleSlot.props} />
)}
{descriptionSlot && (
<div
id={descId}
ref={(descriptionSlot as any).ref}
{...descriptionSlot.props}
/>
)}
</li>
)
})
}

Item.Title = ItemTitle
Item.Description = ItemDescription
59 changes: 59 additions & 0 deletions example/components/RFCSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useState } from 'react'
import { createHost, createSlot } from 'create-slots/rfc'

import { Item } from './RFCItem'

const SelectItem = createSlot<typeof Item>()
const SelectDivider = createSlot<'hr'>()

export const Select = (props: React.ComponentProps<'ul'>) => {
const [selected, setSelected] = useState<React.ReactNode>(null)

return (
<div>
<div>Selected: {selected}</div>
{createHost(props.children, (slots) => {
let index = 0
return (
<ul {...props}>
{slots.map((slot) => {
if (slot.type === SelectItem) {
const itemProps = slot.props

return (
<Item
key={slot.key}
{...slot.props}
{...{
role: 'button',
tabIndex: 0,
'data-index': index,
'aria-selected': itemProps.children === selected,
onClick: () => {
setSelected(itemProps.value)
},
onKeyDown: (
event: React.KeyboardEvent<HTMLButtonElement>
) => {
if (event.key === 'Enter' || event.key === ' ') {
setSelected(itemProps.value)
}
},
}}
/>
)
}
return <hr key={slot.key} {...slot.props} />
})}
</ul>
)
})}
</div>
)
}

Select.Item = SelectItem
Select.Divider = SelectDivider

Select.Item.Title = Item.Title
Select.Item.Description = Item.Description
60 changes: 60 additions & 0 deletions example/components/SimpleField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useId, useState } from 'react'
import { createHost, createSlot } from 'create-slots/simple'

const Description = (props: React.ComponentPropsWithoutRef<'div'>) => (
<div
{...props}
style={{ borderLeft: '4px solid lightgray', paddingLeft: 4 }}
/>
)

const FieldLabel = createSlot('label')
const FieldInput = createSlot('input')
const FieldDescription = createSlot(Description)

const StyledLabel = (props: React.ComponentPropsWithoutRef<'label'>) => (
<FieldLabel {...props} style={{ color: 'red' }} />
)

export const Field = (props: React.ComponentPropsWithoutRef<'div'>) => {
const id = useId()
const [value, setValue] = useState('')

if (value === 'a') return null

return (
<div {...props}>
{createHost(props.children, (Slots) => {
const labelProps = Slots.getProps(FieldLabel)
const inputProps = Slots.getProps(FieldInput)
const descriptionIdProps = Slots.getProps(FieldDescription)

const inputId = inputProps?.id || `${id}-label`
const descriptionId = descriptionIdProps ? `${id}-desc` : undefined

return (
<>
{labelProps && <label {...labelProps} htmlFor={inputId} />}
{inputProps && (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
id={inputId}
aria-describedby={descriptionId}
{...inputProps}
/>
)}
{descriptionIdProps && (
<Description id={descriptionId} {...descriptionIdProps} />
)}
</>
)
})}
</div>
)
}

Field.Label = FieldLabel
Field.Input = FieldInput
Field.Description = FieldDescription
Field.StyledLabel = StyledLabel
102 changes: 76 additions & 26 deletions example/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import styles from '../styles/Home.module.css'
import { Field } from '../components/Field'
import { StaticField } from '../components/StaticField'
import { Select } from '../components/Select'
import { Field as SimpleField } from '../components/SimpleField'
import { Select as RFCSelect } from '../components/RFCSelect'

const Home: NextPage = () => {
const [count, setCount] = React.useState(0)
Expand All @@ -27,6 +29,80 @@ const Home: NextPage = () => {
</div>

<div className={styles.grid}>
<div className={styles.card}>
<h2>RFC</h2>
<div>
<RFCSelect>
<RFCSelect.Item value="foo">
<RFCSelect.Item.Title>Foo</RFCSelect.Item.Title>
</RFCSelect.Item>
<RFCSelect.Divider />
{count % 3 !== 2 && (
<>
<RFCSelect.Item value="bar">
<RFCSelect.Item.Title>Bar</RFCSelect.Item.Title>
</RFCSelect.Item>
<RFCSelect.Divider />
</>
)}
<RFCSelect.Item value="baz">
<RFCSelect.Item.Title>Baz</RFCSelect.Item.Title>
<RFCSelect.Item.Description>
count {count}
</RFCSelect.Item.Description>
</RFCSelect.Item>
</RFCSelect>
</div>
</div>

<div className={styles.card}>
<h2>List</h2>
<div>
<Select>
<Select.Item value="foo">
<Select.Item.Title>Foo</Select.Item.Title>
</Select.Item>
<Select.Divider />
{count % 3 !== 2 && (
<>
<Select.Item value="bar">
<Select.Item.Title>Bar</Select.Item.Title>
</Select.Item>
<Select.Divider />
</>
)}
<Select.Item value="baz">
<Select.Item.Title>Baz</Select.Item.Title>
<Select.Item.Description>
count {count}
</Select.Item.Description>
</Select.Item>
</Select>
</div>
</div>

<div className={styles.card}>
<h2>Simple</h2>
<div>
<SimpleField>
<SimpleField.Input />
<SimpleField.Label>Label</SimpleField.Label>
{count % 3 !== 0 && (
<SimpleField.Description>
Description {count}
<SimpleField>
<SimpleField.Input />
<SimpleField.Label>Label</SimpleField.Label>
<SimpleField.Description>
Nested SimpleField {count}
</SimpleField.Description>
</SimpleField>
</SimpleField.Description>
)}
</SimpleField>
</div>
</div>

<div className={styles.card}>
<h2>Dynamic</h2>
<div>
Expand Down Expand Up @@ -71,32 +147,6 @@ const Home: NextPage = () => {
</StaticField>
</div>
</div>

<div className={styles.card}>
<h2>List</h2>
<div>
<Select>
<Select.Item value="foo">
<Select.Item.Title>Foo</Select.Item.Title>
</Select.Item>
<Select.Divider />
{count % 3 !== 2 && (
<>
<Select.Item value="bar">
<Select.Item.Title>Bar</Select.Item.Title>
</Select.Item>
<Select.Divider />
</>
)}
<Select.Item value="baz">
<Select.Item.Title>Baz</Select.Item.Title>
<Select.Item.Description>
count {count}
</Select.Item.Description>
</Select.Item>
</Select>
</div>
</div>
</div>
</main>
</div>
Expand Down
2 changes: 1 addition & 1 deletion example/styles/Home.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;

width: 300px;
}

.card:hover,
Expand Down
24 changes: 23 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,26 @@
"import": "./dist/static/index.mjs",
"require": "./dist/static/index.js"
}
},
"./simple": {
"development": {
"import": "./dev/simple/index.mjs",
"require": "./dev/simple/index.js"
},
"default": {
"import": "./dist/simple/index.mjs",
"require": "./dist/simple/index.js"
}
},
"./rfc": {
"development": {
"import": "./dev/rfc/index.mjs",
"require": "./dev/rfc/index.js"
},
"default": {
"import": "./dist/rfc/index.mjs",
"require": "./dist/rfc/index.js"
}
}
},
"sideEffects": false,
Expand All @@ -60,7 +80,9 @@
"entry": [
"src/index.tsx",
"src/list/index.tsx",
"src/static/index.tsx"
"src/static/index.tsx",
"src/simple/index.tsx",
"src/rfc/index.tsx"
],
"format": [
"esm",
Expand Down
15 changes: 15 additions & 0 deletions rfc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"main": "../dist/rfc/index.js",
"module": "../dist/rfc/index.mjs",
"types": "../dist/rfc/index.d.ts",
"exports": {
"development": {
"import": "./../dev/rfc/index.mjs",
"require": "./../dev/rfc/index.js"
},
"default": {
"import": "./../dist/rfc/index.mjs",
"require": "./../dist/rfc/index.js"
}
}
}
15 changes: 15 additions & 0 deletions simple/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"main": "../dist/simple/index.js",
"module": "../dist/simple/index.mjs",
"types": "../dist/simple/index.d.ts",
"exports": {
"development": {
"import": "./../dev/simple/index.mjs",
"require": "./../dev/simple/index.js"
},
"default": {
"import": "./../dist/simple/index.mjs",
"require": "./../dist/simple/index.js"
}
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion src/list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import React, {

import { createSlotsContext, getComponentName, hoistStatics } from '../utils'
import { DevChildren } from '../DevChildren'
import { ScanContext, ScanProvider } from '../ScanContext'
import { createSlotsManager } from './SlotsManager'
import { ScanContext, ScanProvider } from './ScanContext'
export type { GetPropsArgs } from './SlotsManager'

const createSlots = <T extends Record<string, React.ElementType>>(
Expand Down
Loading

0 comments on commit 5b148e4

Please sign in to comment.