Skip to main content

lui-reactive

LUI reactive API rules for view/example code (OCaml + lui_ppx). Use whenever writing or editing code that builds Lui_elements views: reactive sugar, dyn ban, if_/keyed usage, signal conventions.

소스 정보

저장소
logseq/lui
최근 소스 활동
2026년 10월 9일 07:27
감지된 SKILL.md 언어
영어
스타
5
포크
0

설치 방법

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

소스 파일 검토

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

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
lui-reactive
description
LUI reactive API rules for view/example code (OCaml + lui_ppx). Use whenever writing or editing code that builds Lui_elements views: reactive sugar, dyn ban, if_/keyed usage, signal conventions.
# LUI Reactive API Rules `lui_ppx` is enabled for view code. `reactive` is the single reactive form; `dyn` is a ppx expansion target and is never called directly. ## Hard rules 1. **Never call `Lui_elements.dyn` directly.** It exists only as the ppx expansion target for children-position `reactive`. Writing `dyn` in view code is a bug. 2. **Never write `Signal.map` / `~p_signal:` / `Signal.value` plumbing by hand for reactive props or test/source signals** — `reactive` covers all of it. ## The reactive vocabulary ```ocaml (* prop position: derived signals are created and owned by the mounted view *) button ~icon:(reactive (fun v -> if v then `eye_off else `eye) visible) [] (* children position: model -> subtree (this IS dyn, via ppx) *) column [ reactive (fun m -> pane_of m.tab) model_s ] (* custom comparator — ~equal leads, matching `dyn ~equal f s` order. Omit ~equal when (=) suffices (the default). *) reactive ~equal:(fun a b -> a.id = b.id) (fun m -> view_of m) model_s (* signal of elements / multi-signal tuple *) reactive elements_s reactive (fun (a, b) -> combined a b) s1 s2 ``` ## Structural primitives (only when signal-driven) ```ocaml if_ ~test:(reactive (fun v -> v <> "") value) (button ...) (* mount/unmount *) keyed ~source:items_s ~key:(fun it -> it.id) ~cmp:Int.compare ~mount:(fun item_s -> row item_s) (* list identity *) ``` - `if_ ~test` / `keyed ~source` take signals directly; no `_signal` suffix (they have no static twin). - **Static structure uses plain OCaml**: `if` for static branches, `List.map`/`for` for static lists. Never wrap static branching in `if_`/`reactive`. ## Decision rules - Value changes (text, icon, disabled, class, attrs) → `reactive` prop. - Whole subtree switches shape on a signal → `reactive` in children. - Mount/unmount on a bool signal → `if_ ~test`. - List membership/order changes on a signal → `keyed ~source`. - Anything else → plain OCaml. - `dyn`-inside-`dyn`/`if_` nesting is almost always wrong: the inner layer usually changes only props — demote it to `reactive` props. ## Signals and ownership - Caller-provided signals are borrowed by `dyn`/`if_`/`keyed` and property bindings; their owner must keep them alive for the view's lifetime. - PPX-created `reactive` derivations are created per mount and owned by that view scope, including derived `if_ ~test` and `keyed ~source` signals. Library-created property conversions follow the same ownership rule. - Do not dispose a shared caller-owned source when one consumer unmounts. Handwritten derivations in lifecycle callbacks must explicitly register ownership with the appropriate scope. ## Comments All code comments and PR descriptions must be in English.
GitHub에서 보기