feat(flux): add createListDirective factory for zero-boilerplate dynamic lists#1840
feat(flux): add createListDirective factory for zero-boilerplate dynamic lists#1840alimd wants to merge 2 commits into
Conversation
…mic lists Introduce `createListDirective`, a factory that captures the repetitive "subscribe to a list signal and render rows with lit-html repeat" pattern into a single declarative config (name, source thunk, key, row, empty). It returns a lazyDirective-compatible registration function, builds on lit-html's keyed `repeat` for surgical reconciliation, resolves the source signal lazily inside init_() to keep the module side-effect free, and stays headless (the App layer supplies the row template). - Add pkg/flux/src/list-directive.ts (full JSDoc) and export from main. - Document the feature and API in the flux README. - Add a Scope & Boundaries note to the bind README clarifying that dynamic lists belong to createListDirective, not bind. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t1nbKp6daS49fbfN3NRCC
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a new utility, createListDirective, to the @alwatr/flux package. Its primary purpose is to reduce boilerplate when rendering dynamic lists that depend on signal state. By providing a declarative factory, it allows developers to implement keyed list reconciliation efficiently without manually authoring repetitive LitDirective classes, while maintaining strict adherence to the project's lazy-loading and side-effect-free architecture. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. A list that grows and shifts its place, With keyed rows in a steady grace. No boilerplate to cloud the view, Just config objects, clean and new. Footnotes
|
There was a problem hiding this comment.
Code Review
این درخواست ادغام قابلیت جدیدی به نام createListDirective را به بسته @alwatr/flux اضافه میکند که یک کارخانه (factory) برای ایجاد دایرکتیوهای لیست پویا با حداقل کدنویسی تکراری است و از سیستم تطبیق کلیددار repeat در lit-html استفاده میکند. همچنین مستندات مربوطه بهروزرسانی شدهاند. در بازبینی کد، پیشنهاد شده است که برای افزایش امنیت در زمان اجرا و اطمینان از آرایه بودن دادهها، به جای عملگر ?? از بررسی Array.isArray استفاده شود تا از خطاهای احتمالی جلوگیری به عمل آید.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| // The signal invokes the callback immediately with its current value, so the first render is | ||
| // scheduled right after `init_()` — no separate priming step needed. | ||
| this.subscribe_(source(), (items) => { | ||
| this.items_ = items ?? []; |
There was a problem hiding this comment.
برای افزایش امنیت کد در برابر مقادیر غیرمنتظره در زمان اجرا (Runtime)، پیشنهاد میشود به جای استفاده از عملگر ?? از Array.isArray استفاده کنید. این کار تضمین میکند که this.items_ همیشه یک آرایه معتبر است و از خطاهای احتمالی هنگام خواندن length یا اجرای repeat جلوگیری میکند.
| this.items_ = items ?? []; | |
| this.items_ = Array.isArray(items) ? items : []; |
Replace the nullish-only guard with an Array.isArray check so a hydrated or serialized source (e.g. EmbeddedDataCollector JSON) that yields a non-array value cannot break `length` access or `repeat`. Addresses PR review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t1nbKp6daS49fbfN3NRCC
Summary
Adds
createListDirectiveto@alwatr/flux— a factory that collapses the repetitive "subscribe to a list signal and render its rows withlit-htmlrepeat" boilerplate into a single declarative configuration object.Motivation: rendering a dynamic list the manual way means writing a dedicated
LitDirectivesubclass per list (@stateaccessor +init_()subscription +render_()callingrepeat(...)). The only parts that ever change are the signal, the key, and the row template. This factory captures exactly those three and returns a ready-to-register lazy directive.This is the chosen design (Path B) after evaluating the alternatives:
bind_repeatin@alwatr/bind(would reimplement keyed reconciliation thatlit-htmlalready provides;bindis intentionally for flat, surgical primitive updates).lit-html's proven keyedrepeat, living influx(which already bundleslit-html+directive+signal).Changes
pkg/flux/src/list-directive.ts(new) —createListDirective(config)+ListDirectiveConfig<T>, fully JSDoc-documented.pkg/flux/src/main.ts— export the new module.pkg/flux/README.md— Key Features section, arepeatentry in the Template section, and a full API reference forcreateListDirective.pkg/nanolib/bind/README.md— a Scope & Boundaries note clarifying that dynamic lists belong tocreateListDirective, notbind.Design notes
sourceis a thunk (() => signal.instance) resolved insideinit_(), preserving thelazy().instanceguarantee; importing the module triggers nothing.lit-html'srepeat, so only changed rows are created/removed/moved (focus, input state, scroll, and transitions survive reorders).rowtemplate; intents fire up viaon-<event>delegation; the directive never owns or mutates state.bfcacheteardown).Verification
lerna run build:ts --scope @alwatr/flux --include-dependencies✅ (19 packages,noEmitOnError—dist/list-directive.d.tsemitted cleanly).Usage
🤖 Generated with Claude Code
Generated by Claude Code