Scenario generator for vore roleplay and story ideas. https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
vore-scenario-generator/src/common/client/GeneratedElement.tsx

103 lines
3.4 KiB

import {
reconstituteTable,
TableEmoji,
TableHeaderDataset,
tableIdentifier,
type TableProps,
TableTitle
} from './TableHeader';
import {
GeneratedResult,
type GeneratedResultProps, type GeneratedResultPropsFull,
type PartialGeneratedResultProps, type PartialGeneratedResultPropsFull,
reconstituteGeneratedResult
} from './GeneratedResult';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { pulseElement } from './pulseElement';
export type GeneratedElementPropsBase = {
table: TableProps
selected: boolean|null
} & GeneratedResultProps
export type GeneratedElementEditableProps = GeneratedElementPropsBase & { selected: boolean } & GeneratedResultPropsFull
export type GeneratedElementReadonlyProps = GeneratedElementPropsBase & { selected: null } & GeneratedResultProps
export type GeneratedElementProps = GeneratedElementEditableProps|GeneratedElementReadonlyProps
export type PartialGeneratedElementProps = PartialGeneratedElementEditableProps|PartialGeneratedElementReadonlyProps
export type PartialGeneratedElementEditableProps = {
table?: Partial<TableProps>
selected?: boolean
} & PartialGeneratedResultPropsFull
export type PartialGeneratedElementReadonlyProps = {
table?: Partial<TableProps>
selected?: null
} & PartialGeneratedResultProps
export function reconstituteGeneratedElement(element: HTMLLIElement, partial?: PartialGeneratedElementProps): GeneratedElementProps {
const result = reconstituteGeneratedResult(element.querySelector(".generatedResult")!, partial)
const selected = typeof partial?.selected !== 'undefined'
? partial.selected
: (element.querySelector<HTMLInputElement>('.generatedSelect')?.checked) ?? null
const table = reconstituteTable(element.querySelector(".tableHeader")!, partial?.table)
if (result.set) {
return {
...result,
table,
selected,
}
} else {
return {
...result,
table,
selected: null,
}
}
}
export interface GeneratedElementEvents {
onSelectionChange?: (tableId: number, selected: boolean) => void
}
export function GeneratedElement({ onSelectionChange, ...props }: GeneratedElementProps & GeneratedElementEvents) {
const ref = useRef<HTMLInputElement>(null);
const selected = props.selected
const [lastSelected, setLastSelected] = useState(selected)
const tableId = tableIdentifier(props.table)
const checkId = `selected-${tableId}`
const changeCallback = useCallback((ev: Event) => {
if (onSelectionChange && typeof props.table.id === "number") {
onSelectionChange(props.table.id, (ev.currentTarget as HTMLInputElement).checked)
}
}, [onSelectionChange])
useEffect(() => {
if (selected !== lastSelected) {
setLastSelected(selected)
if (ref.current) {
pulseElement(ref.current)
}
}
}, [ref, selected, lastSelected, setLastSelected])
return <li class="generatedElement" id={`generated-${tableIdentifier(props.table)}`}>
<h2 class="generatedHead">
<label
class="generatedLabel tableHeader"
{...(props.selected !== null ? {"for": checkId} : {})}
{...TableHeaderDataset(props.table)}>
<TableEmoji {...props.table} />
{' '}
<TableTitle {...props.table} />
</label>
<input type="checkbox" class={`generatedSelect${props.selected === null ? " unselectable" : ""}`}
id={checkId}
name={checkId}
checked={props.selected ?? false}
onChange={changeCallback}
ref={ref} />
</h2>
<GeneratedResult {...props} />
</li>
}