### Install solid-events Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Provides instructions for installing the solid-events package using common package managers like npm, pnpm, and bun. ```bash npm install solid-events or pnpm install solid-events or bun install solid-events ``` -------------------------------- ### Imperative Drag and Drop Logic Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Presents an example of handling drag-and-drop events with imperative logic. This includes conditional side effects and state mutations directly within event handlers, which can be hard to follow. ```ts const [acceptDrop, setAcceptDrop] = createSignal<"top" | "bottom" | false>( false ); onDragOver={(e) => { // check if a valid note is dragged over if (!e.dataTransfer?.types.includes(DragTypes.Note)) { // mutate state setAcceptDrop(false); return; } // calculate and mutate state based on position const isTop = ...calculation; setAcceptDrop(isTop ? "top" : "bottom"); }} onDrop={(e) => { // check if the dropped element is a valid note if (e.dataTransfer?.types.includes(DragTypes.Note)) { const noteId = e.dataTransfer?.getData(DragTypes.Note) action: if (noteId && noteId !== props.note.id) { // note is valid, run side effect if (acceptDrop() === "top") { if (props.previous && props.previous?.id === noteId) { break action; } moveNoteAction(...); } if (acceptDrop() === "bottom") { if (props.previous && props.next?.id === noteId) { break action; } moveNoteAction(...); } } } // mutate state setAcceptDrop(false); }} ``` -------------------------------- ### Create and Emit Events with createEvent Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Demonstrates the fundamental usage of `createEvent` to generate an event handler and an emitter. It covers subscribing to events and emitting data payloads. ```ts const [onEvent, emitEvent] = createEvent() onEvent(payload => console.log(`Event emitted:`, payload)) ... emitEvent(`Hello World!`) // logs "Event emitted: Hello World!" ``` -------------------------------- ### Comparison of Reactive Primitives: RxJS vs. SolidJS Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Discusses the fundamental differences between RxJS observables (push-based) and SolidJS signals (pull-based) in the context of functional reactive programming. It touches upon the historical evolution of FRP primitives. ```APIDOC Reactive Primitive Comparison: RxJS Observables: - Paradigm: Push-based. - Characteristics: Handles event composition, reactive state, lifecycles, higher-order streaming. - Usage: Requires knowledge of operators and pipe syntax. - Complexity: Can be complex due to the versatility of operators. SolidJS Signals: - Paradigm: Pull-based. - Characteristics: Designed for specific roles (state, side effects, caching, lifecycles). - Usage: Integrates seamlessly with Solid's declarative component model. - Simplicity: Built using multiple, focused reactive primitives. createEvent (SolidJS): - Role: Reintroduces a push-based primitive into SolidJS. - Goal: To complement signals and bring Solid closer to classic FRP semantics. - Design: Lean and easy to learn, focusing solely on event composition. ``` -------------------------------- ### Conceptual Overview of createEvent in SolidJS Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Explains the purpose of `createEvent` in SolidJS, highlighting its role in event composition and its difference from RxJS observables. It positions `createEvent` as a complementary primitive to Solid's signals, effects, and memos. ```APIDOC createEvent: Purpose: Fills the void in SolidJS's reactive primitives for event composition. Approach: Introduces a push-based primitive to complement Solid's pull-based signals. Comparison to RxJS: Simpler, less powerful than RxJS observables, avoids complex operator chains. Benefits: Easier to learn and integrate into Solid's existing system. Limitations: Does not handle state management or higher-order streaming directly, relying on Solid's primitives for those tasks. Context: Mentioned in conjunction with 'use socket' and server signals for full-stack reactivity. ``` -------------------------------- ### Fine-Grained Mutations: Subject Store for State Updates Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Simplifies fine-grained optimistic mutations by using a `createSubjectStore` to colocate and manage various state update events (notes, columns) in a single run. ```ts const boardStore = createSubjectStore( () => boardData(), onCreateNote(([note]) => (board) => { const index = board.notes.findIndex((n) => n.id === note.id); if (index === -1) board.notes.push(note); }), onMoveNote(([noteId, columnId, order]) => (board) => { const index = board.notes.findIndex((n) => n.id === noteId); if (index !== -1) { board.notes[index].column = columnId; board.notes[index].order = order; } }), onEditNote(...), onDeleteNote(...), onCreateColumn(...), onRenameColumn(...), onMoveColumn(...), onDeleteColumn(...) ); ``` -------------------------------- ### Create mutable state store with createSubjectStore Source: https://github.com/devagrawal09/solid-events/blob/master/README.md createSubjectStore provides a mutable store for state management, leveraging `produce` for direct state mutation within event handlers. It can be initialized with a signal and supports resetting and reconciliation. ```ts const boardStore = createSubjectStore( () => boardData(), onCreateNote((createdNote) => (board) => { const index = board.notes.findIndex((n) => n.id === note.id); if (index === -1) board.notes.push(note); }), onDeleteNote(([id]) => (board) => { const index = board.notes.findIndex((n) => n.id === id); if (index !== -1) board.notes.splice(index, 1); }) ... ) ``` -------------------------------- ### Imperative State Update with createSignal in SolidJS Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Demonstrates a typical SolidJS component using `createSignal` for managing state imperatively. This approach allows direct mutation via setters, but tracking all mutations can become complex in larger applications. ```tsx function Component() { const [count, setCount] = createSignal(0) const doubleCount = () => count() * 2 return
Count: {count()}
double Count: {doubleCount()}
} ``` -------------------------------- ### Combine multiple events with createTopic Source: https://github.com/devagrawal09/solid-events/blob/master/README.md createTopic merges multiple event handlers into a single event stream. This simplifies handling multiple distinct events by providing a unified listener for all combined events. ```ts const [onIncrement, emitIncrement] = createEvent() const [onDecrement, emitDecrement] = createEvent() const onMessage = createTopic( onIncrement(() => `Increment by ${delta}`), onDecrement(() => `Decrement by ${delta}`) ); onMessage(message => console.log(`Message emitted:`, message)) ... emitIncrement(2) // logs "Message emitted: Increment by 2" emitDecrement(1) // logs "Message emitted: Decrement by 1" ``` -------------------------------- ### Transform Event Data with createEvent Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Illustrates chaining transformations on event data by utilizing the return value of the event callback. This enables sequential processing of event payloads. ```ts const [onIncrement, emitIncrement] = createEvent() const onMessage = onIncrement((delta) => `Increment by ${delta}`) onMessage(message => console.log(`Message emitted:`, message)) ... emitIncrement(2) // logs "Message emitted: Increment by 2" ``` -------------------------------- ### Event-Driven State Update with createEvent and createSubject in SolidJS Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Illustrates an event-driven approach using `createEvent` and `createSubject` to derive state. All state changes are tied to specific events, making mutations explicit and easier to trace at declaration time. ```tsx function Component() { const [onIncrement, emitIncrement] = createEvent() const count = createSubject( 0, onIncrement(() => c => c + 1) ) const doubleCount = () => count() * 2 return
Count: {count()}
double Count: {doubleCount()}
} ``` -------------------------------- ### Optimistic Board Deletion with Async Subject Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Achieves optimistic board deletion using an async subject and event handlers, simplifying state management compared to submission-based filtering. ```ts const [onDeleteBoard, emitDeleteBoard] = createEvent(); onDeleteBoard(useAction(deleteBoard)); const boards = createAsyncSubject( () => getBoards(), onDeleteBoard( (boardId) => (boards) => boards.filter((board) => board.id !== boardId) ) ); ``` -------------------------------- ### Handle Async Events with createEvent Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Explains how `createEvent` automatically handles promises returned from event callbacks. The event emission waits for the promise to resolve, effectively flattening asynchronous operations. ```ts async function createBoard(boardData) { "use server" const boardId = await db.boards.create(boardData) return boardId } const [onCreateBoard, emitCreateBoard] = createEvent() const onBoardCreated = onCreateBoard(boardData => createBoard(boardData)) onBoardCreated(boardId => navigate(`/board/${boardId}`)) // If createBoard returns a promise, onBoardCreated will wait for it to resolve before navigating. ``` -------------------------------- ### Manage Event Subscription Lifecycles in Components Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Shows how event subscriptions created with `createEvent` are automatically managed and cleaned up when used within SolidJS components, preventing memory leaks. ```tsx function Counter() { const [onIncrement, emitIncrement] = createEvent() const onMessage = onIncrement((delta) => `Increment by ${delta}`) onMessage(message => console.log(`Message emitted:`, message)) return
....
} // Calling onIncrement and onMessage registers stateful subscriptions tied to the component's lifecycle. ``` -------------------------------- ### Optimistic Board Deletion with Submissions Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Implements optimistic deletion of boards by filtering out deleted boards based on inflight submissions. Relies on `useSubmissions` and `createAsync`. ```ts const serverBoards = createAsync(() => getBoards()); const deleteBoardSubmissions = useSubmissions(deleteBoard); const boards = () => { if (deleteBoardSubmissions.pending) { const deletedBoards: number[] = []; for (const sub of deleteBoardSubmissions) { deletedBoards.push(sub.input[0]); } return serverBoards()?.filter( (board) => !deletedBoards.includes(board.id) ); } return serverBoards(); }; ``` -------------------------------- ### Create and manage state with createSubject Source: https://github.com/devagrawal09/solid-events/blob/master/README.md createSubject creates a reactive signal that can be updated by event handlers. It can be initialized with a static value or a signal, and event handlers can return new values or updater functions. It supports resetting based on a source signal. ```ts const [onIncrement, emitIncrement] = createEvent() const [onReset, emitReset] = createEvent() const onMessage = onIncrement((delta) => `Increment by ${delta}`) onMessage(message => console.log(`Message emitted:`, message)) const count = createSubject( 0, onIncrement(delta => currentCount => currentCount + delta), onReset(() => 0) ) createEffect(() => console.log(`count`, count())) emitIncrement(2) // logs "Message emitted: Increment by 2" // logs "count 2" emitReset() // logs "count 0" ``` ```tsx function Counter(props) { const [onIncrement, emitIncrement] = createEvent() const [onReset, emitReset] = createEvent() const count = createSubject( () => props.count, onIncrement(delta => currentCount => currentCount + delta), onReset(() => 0) ) return
...
} ``` -------------------------------- ### Fine-Grained Mutations: Applying Mutations with Effects Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Applies mutations to notes and columns using `createEffect` and `untrack`, updating the store with `reconcile` and `batch`. Handles state updates based on timestamps. ```ts createEffect(() => { const mutations = untrack(() => getMutations()); const { notes, columns } = props.board; applyMutations(mutations, notes, columns); batch(() => { setBoardStore("notes", reconcile(notes)); setBoardStore("columns", reconcile(columns)); }); }); createEffect(() => { const mutations = getMutations(); const prevTimestamp = untrack(() => boardStore.timestamp); const latestMutations = mutations.filter( (m) => m.timestamp > prevTimestamp ); setBoardStore( produce((b) => { applyMutations(latestMutations, b.notes, b.columns); b.timestamp = Date.now(); }) ); }); ``` -------------------------------- ### Halt Event Propagation with createEvent Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Demonstrates how to stop event propagation at any point within the event handler chain using the `halt()` function. This prevents subsequent handlers from being executed. ```ts const [onIncrement, emitIncrement] = createEvent() const onValidIncrement = onIncrement(delta => delta < 1 ? halt() : delta) const onMessage = onValidIncrement((delta) => `Increment by ${delta}`) onMessage(message => console.log(`Message emitted:`, message)) ... emitIncrement(2) // logs "Message emitted: Increment by 2" ... emitIncrement(0) // Doesn't log anything ``` -------------------------------- ### Event Composition for Drag and Drop Logic Source: https://github.com/devagrawal09/solid-events/blob/master/README.md Refactors the drag-and-drop logic using event composition. This approach separates concerns, making decisions explicit events and moving side effects to the end of the flow for better readability and maintainability. ```ts const onDropNote = onDrop((e) => { // check if the dropped element is a valid note if (!e.dataTransfer?.types.includes(DragTypes.Note)) halt(); const noteId = e.dataTransfer?.getData(DragTypes.Note); if (!noteId || noteId === props.note.id) halt(); return noteId; }); onDropNote((noteId) => { // when a valid note is dropped, run side effect if (acceptDrop() === "top" && props.previous?.id !== noteId) { return moveNoteAction(...); } if (acceptDrop() === "bottom" && props.next?.id !== noteId) { return moveNoteAction(...); } }); // check if a valid note is dragged over const [onDragOverValidEl, onDragOverInvalidEl] = createPartition( onDragOver, (e) => !!e.dataTransfer?.types.includes(DragTypes.Note) ); // derive highlight state based on element and position const acceptDrop = createSubject<"top" | "bottom" | false>( false, onDrop(() => false), onDragOverInvalidEl(() => false), onDragOverValidEl((e) => { const isTop = ...calculation return isTop ? "top" : "bottom"; }) ); ``` -------------------------------- ### Conditionally split events with createPartition Source: https://github.com/devagrawal09/solid-events/blob/master/README.md createPartition splits a single event into two based on a condition, offering a cleaner alternative to `halt()`. It creates two new event handlers: one for events that meet the condition and one for those that don't. ```ts const [onIncrement, emitIncrement] = createEvent() const [onValidIncrement, onInvalidIncrement] = createPartition( onIncrement, delta => delta > 0 ) onValidIncrement(delta => console.log(`Valid increment by ${delta}`)) onInvalidIncrement(delta => console.log(`Please use a number greater than 0`)) ... emitIncrement(2) // logs "Valid increment by 2" emitIncrement(0) // logs "Please use a number greater than 0" ``` -------------------------------- ### Create async state with createAsyncSubject Source: https://github.com/devagrawal09/solid-events/blob/master/README.md createAsyncSubject manages asynchronous operations, accepting a reactive async function. It automatically resets when the source function reruns. Event handlers can be used to update the derived state, such as filtering results. ```ts const getBoards = cache(async () => { "use server"; // fetch from database }, "get-boards"); export default function HomePage() { const [onDeleteBoard, emitDeleteBoard] = createEvent(); const boards = createAsyncSubject( () => getBoards(), onDeleteBoard( (boardId) => (boards) => boards.filter((board) => board.id !== boardId) ) ); ... } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.