Skip to main content

aidd-lit

Enforces Lit element authoring best practices. Use when creating Lit elements, binding elements, presentations, DatabaseElement, useObservableValues, or when the user asks about Lit UI patterns, reactive binding, or action callbacks.

소스 정보

저장소
paralleldrive/riteway
최근 소스 활동
2026년 3월 17일 20:30
감지된 SKILL.md 언어
영어
스타
1,196
포크
40

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
aidd-lit
description
Enforces Lit element authoring best practices. Use when creating Lit elements, binding elements, presentations, DatabaseElement, useObservableValues, or when the user asks about Lit UI patterns, reactive binding, or action callbacks.
# Lit element authoring Lit elements live in the `components/` layer per [structure](../aidd-structure/SKILL.md). Consume Observe and void actions from plugins per [service](../aidd-service/SKILL.md). --- ## Extending DatabaseElement Binding elements extend `DatabaseElement<typeof myPlugin>` — either directly or via an intermediate base class. The required plugin must be specified in the generic. This ensures the plugin's services are extended onto the main database **before** the element renders, so `this.service` exposes the correct Observe APIs and actions. ```ts // Direct export class HelloWorldElement extends DatabaseElement<typeof helloWorldPlugin> { get plugin() { return helloWorldPlugin; } } // Indirect — base extends DatabaseElement, leaf specifies plugin export class LayoutElement<T extends MyApplicationPlugin = MyApplicationPlugin> extends CoreApplicationElement<T> { } export class ToolbarElement extends LayoutElement<typeof toolbarPlugin> { } ``` --- ## Binding element vs presentation ```sudolang BindingElement { injects: "observed values via useObservableValues" triggers: "re-render when those values change" binds: "action callbacks to the presentation" } Presentation { type: "pure function (no hooks)" receives: "data and action callbacks as props" returns: "TemplateResult" constraint: "Keep reactive logic in binding element; presentation stays pure" } ``` --- ## Testing ```sudolang Testing { presentation: "add *.test.ts when appropriate; unit test the presentation" bindingElement: "not unit tested — no business logic; uses Database service (already unit tested)" } ``` --- ## useObservableValues *Most* binding elements use a **single** `useObservableValues` call. Collect all observed values in one object. **Observe only what you need** — the minimal values required for rendering. For values that may resolve slowly, wrap with `Observe.withDefault` so you can render a skeleton (or placeholder) immediately while waiting. See [observe](../aidd-observe/SKILL.md). ```ts render() { const values = useObservableValues(() => ({ visible: this.service.actions.isViewVisible(name), userProfile: this.service.services.authentication.userProfile, })); if (!values) return; return presentation.render({ ...values, toggleView: () => this.toggleView(name) }); } ``` --- ## Presentation exports ```sudolang Constraints { Presentation files ONLY export render (and unlocalized bundles where appropriate) Nothing else ever exported from a presentation file For render args type externally: use Parameters<typeof render>[0] } ``` --- ## Action callbacks (not events) ```sudolang PresentationCallbacks { are: "action calls, not events" semantics: "verbNoun — not onClick/onToggle/onSignOut style" bindingElement: "passes action callbacks (e.g. toggleView, signOut) as props" presentation: "invokes them when user intent occurs" callback: "calls the service/transaction directly" } ``` ```ts // Binding element: binds the action (verbNoun) toggleView: () => this.toggleToolbarChild(name) // Presentation: receives and invokes when user acts item.toggleView() ``` --- ## Lit properties ```sudolang PropertyRules { default: "Almost never use @property on binding elements" exception: "Use properties ONLY when needed to bind to the correct entity in the database (e.g. entity for table rows, layer for view hosts)" multipleInstances: "need a property to identify which entity they represent" singleInstanceElements: "have no properties; observe values directly; re-render only when those values change" } ``` --- ## Execute ```sudolang fn whenCreatingOrModifyingLitElement() { Constraints { Extend DatabaseElement<typeof myPlugin> (directly or indirectly) with required plugin specified Split into binding element (reactive) and presentation (pure) Use single useObservableValues in binding element; Observe only minimal values; use Observe.withDefault for slow-resolving values Pass observed values and action callbacks to presentation Keep presentation pure — no hooks Add @property only when entity binding requires it (multiple instances) Presentation exports only render (and localization bundles where appropriate) Add *-presentation.test.ts for presentation when appropriate; do not unit test binding elements Never include business logic within binding elements — move into computed values or action handlers Good binding elements should be extremely small } } ```
GitHub에서 보기