Skip to content

Commit

Permalink
Merge branch 'entries'
Browse files Browse the repository at this point in the history
  • Loading branch information
thetarnav committed Sep 4, 2022
2 parents d6be43c + 2a042aa commit 06c8aeb
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-numbers-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solid-primitives/keyed": minor
---

Add `Entries` control flow component.
33 changes: 33 additions & 0 deletions packages/keyed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Control Flow primitives and components that require specifying explicit keys to

- [`keyArray`](#keyArray) - Reactively maps an array by specified key with a callback function - underlying helper for the `<Key>` control flow.
- [`Key`](#Key) - Creates a list of elements by mapping items by provided key.
- [`Entries`](#Entries) - Creates a list of elements by mapping object entries.

## Installation

Expand Down Expand Up @@ -118,6 +119,38 @@ Second argument of the map function is an index signal.

https://codesandbox.io/s/solid-primitives-keyed-key-demo-gh7gd?file=/index.tsx

## `<Entries>`

Creates a list of elements by mapping object entries. Similar to Solid's `<For>` and `<Index>`, but here, render function takes three arguments, and both value and index arguments are signals.

### How to use it

```tsx
import { Entries } from "@solid-primitives/keyed";

<Entries of={object()} fallback={<div>No items</div>}>
{(key, value) => (
<div>
{key}: {value()}
</div>
)}
</Entries>;
```

### Index argument

Third argument of the map function is an index signal.

```tsx
<Entries of={object()} fallback={<div>No items</div>}>
{(key, value, index) => (
<div data-index={index()}>
{key}: {value()}
</div>
)}
</Entries>
```

## Changelog

See [CHANGELOG.md](./CHANGELOG.md)
3 changes: 2 additions & 1 deletion packages/keyed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"stage": 3,
"list": [
"keyArray",
"Key"
"Key",
"Entries"
],
"category": "Control Flow"
},
Expand Down
53 changes: 46 additions & 7 deletions packages/keyed/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,55 @@ export function keyArray<T, U, K>(
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/keyed#Key
*/
export function Key<T, U extends JSX.Element>(props: {
export function Key<T>(props: {
each?: readonly T[] | null | false;
by: ((v: T) => any) | keyof T;
fallback?: U;
children: (v: Accessor<T>, i: Accessor<number>) => U;
}): Accessor<U[]> {
const fallback = props.fallback ? () => props.fallback as U : undefined;
fallback?: JSX.Element;
children: (v: Accessor<T>, i: Accessor<number>) => JSX.Element;
}): Accessor<JSX.Element[]> {
const { by } = props;
const key = typeof by === "function" ? by : (v: T) => v[by];
const mapped = keyArray<T, U, any>(() => props.each, key, props.children, { fallback });
const mapped = keyArray<T, JSX.Element, any>(
() => props.each,
typeof by === "function" ? by : (v: T) => v[by],
props.children,
"fallback" in props ? { fallback: () => props.fallback } : undefined
);
return createMemo(mapped);
}

/**
* creates a list of elements from the entries of provided object
*
* @param props
* @param props.of object to iterate entries of (`Object.entries(object)`)
* @param props.children
* a map render function that receives an object key, **value signal** and **index signal** and returns a JSX-Element; if the list is empty, an optional fallback is returned:
* ```tsx
* <Entries of={object()} fallback={<div>No items</div>}>
* {(key, value, index) => <div data-index={index()}>{key}: {value()}</div>}
* </Entries>
* ```
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/keyed#Entries
*/
export function Entries<T extends object>(props: {
of: T | undefined | null | false;
fallback?: JSX.Element;
children: <K extends keyof T>(key: K, v: Accessor<T[K]>, i: Accessor<number>) => JSX.Element;
}): Accessor<JSX.Element[]> {
const mapFn = props.children;
const mapped = keyArray(
() => props.of && (Object.entries(props.of) as [keyof T, T[keyof T]][]),
() => 0,
mapFn.length < 3
? keyvalue =>
(mapFn as (key: keyof T, v: Accessor<T[keyof T]>) => JSX.Element)(
keyvalue()[0],
() => keyvalue()[1]
)
: (keyvalue, i) => mapFn(keyvalue()[0], () => keyvalue()[1], i),
"fallback" in props ? { fallback: () => props.fallback } : undefined
);
return createMemo(mapped);
}

Expand Down

0 comments on commit 06c8aeb

Please sign in to comment.