Export template source from 99b2868b7e974441744657b35049f5baae4a499b:quixos-instance/packages/todo-react-runtime

This commit is contained in:
Quixos Template Publisher
2000-01-01 00:00:00 +00:00
commit cf33959ceb
31 changed files with 1838 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
declare module "*?browser-source" {
const source: string;
export default source;
}
@@ -0,0 +1,29 @@
// @generated by camino-codegen-ts-runtime. Do not edit.
import {
createWebStudioComponent,
type ReactComponentHostProps,
type ObjectRef,
} from "@quixos/web-studio-react-runtime";
export type TodoReactComponentRenderProps = {
"selected"?: boolean;
"compact"?: boolean;
};
export type TodoReactComponentAction = {
"type"?: TodoReactComponentActionType;
};
export type TodoReactComponentActionType = "TODO_REACT_COMPONENT_ACTION_TYPE_UNSPECIFIED" | "SELECT";
export type TodoComponentProps = {
forObject: ObjectRef<"atom:task">;
} & TodoReactComponentRenderProps & ReactComponentHostProps<TodoReactComponentAction>;
export const TodoComponent = createWebStudioComponent<
ObjectRef<"atom:task">,
TodoReactComponentRenderProps,
TodoReactComponentAction
>({
expectedAtomId: "atom:task",
});
+381
View File
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
// Generated from checked QX contracts. Do not edit.
import type {ObjectRef, InterfaceReference, ReadableField, WritableField} from "@quixos/web-studio-react-runtime";
export type Interface0 = InterfaceReference<"interface:task-data@1", {"title": WritableField<string>;"status": WritableField<string>;"priority": WritableField<string>;"notes": WritableField<string>;"dueDate": WritableField<string>;"energy": WritableField<string>}> ;
export type ReactResults = {"propsGet": {"data": Interface0}};
type CheckedComponent<K extends keyof ReactResults, C extends (props: {camino: ReactResults[K]; render: any; dispatch: (action: any) => void}) => unknown> = C;
type Component0 = CheckedComponent<"propsGet", typeof import("../todo-component.js")["default"]>;
+45
View File
@@ -0,0 +1,45 @@
// Generated by the Quixos React platform contract. Do not edit.
declare module "@quixos/web-studio-react-runtime" {
import type * as React from "react";
export function useComponentOverlayContainer(): HTMLElement;
export function useComponentStyleRoot(): ShadowRoot;
export type ObjectRef<AtomId extends string> = string & {
readonly $quixosAtom: AtomId;
};
export type FieldCapability = {objectId: string; interfaceRevisionId: string; getOperationId: string; watchOperationId?: string; setOperationId?: string; inputKind?: "fields" | "value"};
export type ReadableField<T> = {readonly value?: T; readonly capability: FieldCapability};
/** set(T) uses the resolved capability: native CRDT fields send incremental edits;
* custom/manual setters receive semantic values. Storage provenance grants no authority. */
export type WritableField<T> = ReadableField<T> & {readonly $writeType?: (value: T) => T; readonly writable: true; readonly capability: FieldCapability & {setOperationId: string}};
export type LiveFieldProp<T> = ReadableField<T>;
export type InterfaceReference<I extends string, Fields> = {readonly $quixosRef: string; readonly interfaceRevisionId: I; readonly fields: Fields};
export type ReactComponentHostProps<Action> = {
onAction?: (action: Action) => void;
fallback?: React.ReactNode;
className?: string;
style?: React.CSSProperties;
/** Optional extra action. The host still displays and reports errors by default. */
extraErrorAction?: (error: Error) => void;
};
export type ReactComponentImplementationProps<CaminoProps, RenderProps, Action> = {
camino: CaminoProps;
render: RenderProps;
dispatch: (action: Action) => void;
};
export const createWebStudioComponent: <
ForObject extends ObjectRef<string>, RenderProps extends object, Action,
>(config: { expectedAtomId: string }) => (props: {
forObject: ForObject;
} & RenderProps & ReactComponentHostProps<Action>) => any;
export const invokeCapability: <Result = unknown>(
objectId: string,
interfaceRevisionId: string,
operationId: string,
value?: unknown,
options?: {clientMutationId?: string; signal?: AbortSignal},
) => Promise<Result>;
export const h: typeof React.createElement;
export function useLiveField<T>(field: ReadableField<T>, options: {write: (value: T) => Promise<void>}): readonly [T, (value: T) => Promise<void>];
export function useLiveField<T>(field: WritableField<T>): readonly [T, (value: T) => Promise<void>];
export function useLiveField<T>(field: ReadableField<T>): readonly [T];
}
+2
View File
@@ -0,0 +1,2 @@
// This adapter keeps the implementation file hand-authored.
export { createComponent as handler } from "../todo-react.impl.js";
+2
View File
@@ -0,0 +1,2 @@
// This adapter keeps the implementation file hand-authored.
export { props as handler } from "../todo-react.impl.js";
+2
View File
@@ -0,0 +1,2 @@
// This adapter keeps the implementation file hand-authored.
export { props as handler } from "../todo-react.impl.js";
+2
View File
@@ -0,0 +1,2 @@
// This adapter keeps the implementation file hand-authored.
export { stopWatch as handler } from "../todo-react.impl.js";
+2
View File
@@ -0,0 +1,2 @@
// This adapter keeps the implementation file hand-authored.
export { source as handler } from "../todo-react.impl.js";
+3
View File
@@ -0,0 +1,3 @@
// Generated by qx-scaffold-v1
import { serveMigration } from "@quixos/camino-package-runtime";
await serveMigration({});
+17
View File
@@ -0,0 +1,17 @@
// Generated by qx-scaffold-v1
import { servePackageRuntime } from "@quixos/camino-package-runtime";
import { createRuntime } from "./gen/qx.js";
import { handler as impl0 } from "./impl/createComponent.js";
import { handler as impl1 } from "./impl/sourceGet.js";
import { handler as impl2 } from "./impl/propsGet.js";
import { handler as impl3 } from "./impl/propsWatch.js";
import { handler as impl4 } from "./impl/propsWatchStop.js";
servePackageRuntime(
createRuntime({
createComponent: impl0,
sourceGet: impl1,
propsGet: impl2,
propsWatch: impl3,
propsWatchStop: impl4,
}),
);
+217
View File
@@ -0,0 +1,217 @@
import { useLiveField, type ReactComponentImplementationProps } from "@quixos/web-studio-react-runtime";
import type {
TodoReactComponentAction,
TodoReactComponentRenderProps,
} from "./gen/quixos.todo.TodoReactComponent.react.js";
import type { ReactResults } from "./gen/react-props.gen.js";
type TodoReactComponentCaminoProps = ReactResults["propsGet"];
const palette = {
ink: "#28362d",
muted: "#6f776e",
cream: "#fffdf5",
line: "#d9d0ba",
moss: "#5f7f63",
honey: "#d99b3d",
berry: "#a9544f",
};
const statusTone = (status: string) =>
status === "DONE" ? palette.moss : status === "ARCHIVED" ? palette.muted : "#52749a";
const fieldLabelStyle = {
display: "grid",
gap: "4px",
color: palette.muted,
fontSize: "10px",
fontWeight: 750,
letterSpacing: "0.08em",
textTransform: "uppercase" as const,
};
const controlStyle = {
minWidth: 0,
width: "100%",
border: `1px solid ${palette.line}`,
borderRadius: "7px",
background: "#fff",
color: palette.ink,
fontSize: "11px",
padding: "6px 8px",
};
type TodoComponentImplementationProps = ReactComponentImplementationProps<
TodoReactComponentCaminoProps,
TodoReactComponentRenderProps,
TodoReactComponentAction
>;
export default function TodoComponent({ camino: props, render, dispatch }: TodoComponentImplementationProps) {
const [title, setTitle] = useLiveField(props.data.fields.title);
const [status, setStatus] = useLiveField(props.data.fields.status);
const [priority, setPriority] = useLiveField(props.data.fields.priority);
const [notes, setNotes] = useLiveField(props.data.fields.notes);
const [dueDate, setDueDate] = useLiveField(props.data.fields.dueDate);
const [energy, setEnergy] = useLiveField(props.data.fields.energy);
const done = status === "DONE";
return (
<div
style={{
display: "grid",
gap: render.compact ? "9px" : "13px",
minWidth: 0,
height: "100%",
padding: render.compact ? "11px" : "15px",
border: render.selected ? `2px solid ${palette.honey}` : `1px solid ${palette.line}`,
borderRadius: "12px",
background: palette.cream,
boxShadow: render.selected ? "0 0 0 3px rgba(217,155,61,.14)" : "none",
color: palette.ink,
fontFamily: "Avenir Next, Nunito, ui-sans-serif, system-ui, sans-serif",
overflow: "auto",
}}
>
<div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "10px" }}>
<button
type="button"
aria-label={done ? "Reopen task" : "Complete task"}
onClick={() => void setStatus(done ? "OPEN" : "DONE")}
style={{
flex: "0 0 auto",
width: "26px",
height: "26px",
border: `1px solid ${done ? palette.moss : palette.line}`,
borderRadius: "8px",
background: done ? palette.moss : "#fff",
color: "#fff",
fontWeight: 900,
cursor: "pointer",
}}
>
{done ? "✓" : ""}
</button>
<div style={{ display: "grid", flex: 1, gap: "3px", minWidth: 0 }}>
<strong
style={{
overflow: "hidden",
fontSize: render.compact ? "14px" : "17px",
lineHeight: 1.25,
textDecoration: done ? "line-through" : "none",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{title || "Untitled task"}
</strong>
<span style={{ color: statusTone(status), fontSize: "10px", fontWeight: 800, letterSpacing: ".08em" }}>
{status || "OPEN"} · {priority || "NORMAL"}
</span>
</div>
<button
type="button"
onClick={() => dispatch({ type: "SELECT" })}
style={{
border: "none",
background: "transparent",
color: palette.muted,
cursor: "pointer",
fontSize: "12px",
}}
>
{render.selected ? "Pinned" : "Open"}
</button>
</div>
{!render.compact ? (
<div style={{ display: "contents" }}>
<label style={fieldLabelStyle}>
Title
<input
value={title}
onInput={(event: { currentTarget: HTMLInputElement }) => void setTitle(event.currentTarget.value)}
style={controlStyle}
/>
</label>
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(112px, 1fr))", gap: "8px" }}>
<label style={fieldLabelStyle}>
Status
<select
style={controlStyle}
value={status}
onChange={(event: { currentTarget: HTMLSelectElement }) => void setStatus(event.currentTarget.value)}
>
<option value="OPEN">Open</option>
<option value="DONE">Done</option>
<option value="ARCHIVED">Archived</option>
</select>
</label>
<label style={fieldLabelStyle}>
Priority
<select
style={controlStyle}
value={priority}
onChange={(event: { currentTarget: HTMLSelectElement }) => void setPriority(event.currentTarget.value)}
>
<option value="LOW">Low</option>
<option value="NORMAL">Normal</option>
<option value="HIGH">High</option>
</select>
</label>
<label style={fieldLabelStyle}>
Energy
<select
style={controlStyle}
value={energy}
onChange={(event: { currentTarget: HTMLSelectElement }) => void setEnergy(event.currentTarget.value)}
>
<option value="LOW">Low</option>
<option value="MEDIUM">Medium</option>
<option value="HIGH">High</option>
</select>
</label>
<label style={fieldLabelStyle}>
Due
<input
style={controlStyle}
type="date"
value={dueDate}
onInput={(event: { currentTarget: HTMLInputElement }) => void setDueDate(event.currentTarget.value)}
/>
</label>
</div>
<label style={fieldLabelStyle}>
Notes
<textarea
aria-label="Notes"
value={notes}
onInput={(event: { currentTarget: HTMLTextAreaElement }) => void setNotes(event.currentTarget.value)}
rows={4}
placeholder="Leave a trail for your future self…"
style={{ ...controlStyle, minHeight: "78px", resize: "vertical" }}
/>
</label>
</div>
) : (
<div style={{ display: "flex", flexWrap: "wrap", gap: "6px", color: palette.muted, fontSize: "11px" }}>
{dueDate ? <span>Due {dueDate}</span> : <span>No due date</span>}
<span>·</span>
<span>{energy || "MEDIUM"} energy</span>
</div>
)}
<div
style={{
color: palette.muted,
fontSize: "10px",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{props.data.$quixosRef}
</div>
</div>
);
}
+10
View File
@@ -0,0 +1,10 @@
import componentSource from "./todo-component.js?browser-source";
import type { Contexts, Results } from "./gen/qx.js";
export const source = () => componentSource;
export const createComponent = ({ objectId }: Contexts["createComponent"]) => objectId;
export const props = {
kind: "derived" as const,
get: async ({ ports }: Contexts["propsGet"]): Promise<Results["propsGet"]> => ({ data: ports.data.objectId }),
};
export const stopWatch = () => null;