diff --git a/packages/selectors/LICENSE b/packages/selectors/LICENSE
new file mode 100644
index 000000000..38b41d975
--- /dev/null
+++ b/packages/selectors/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Solid Primitives Working Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/packages/selectors/README.md b/packages/selectors/README.md
new file mode 100644
index 000000000..c0ccb2f4b
--- /dev/null
+++ b/packages/selectors/README.md
@@ -0,0 +1,44 @@
+
+
+
+
+# @solid-primitives/selectors
+
+[![turborepo](https://img.shields.io/badge/built%20with-turborepo-cc00ff.svg?style=for-the-badge&logo=turborepo)](https://turborepo.org/)
+[![size](https://img.shields.io/bundlephobia/minzip/@solid-primitives/selectors?style=for-the-badge&label=size)](https://bundlephobia.com/package/@solid-primitives/selectors)
+[![version](https://img.shields.io/npm/v/@solid-primitives/selectors?style=for-the-badge)](https://www.npmjs.com/package/@solid-primitives/selectors)
+[![stage](https://img.shields.io/endpoint?style=for-the-badge&url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolidjs-community%2Fsolid-primitives%2Fmain%2Fassets%2Fbadges%2Fstage-0.json)](https://github.com/solidjs-community/solid-primitives#contribution-process)
+
+A sample primitive that is made up for templating with the following options:
+
+`createArraySelcetor` - Provides a getter and setter for the primitive.
+
+## Installation
+
+```bash
+npm install @solid-primitives/selectors
+# or
+yarn add @solid-primitives/selectors
+# or
+pnpm add @solid-primitives/selectors
+```
+
+## How to use it
+
+```tsx
+const list: string[] = ["apple", "pear", "orange"]
+const [selectedItems] = createSignal(["apple"])
+const isSelected = createArraySelector(selectedItems)
+
+
+ {(item) =>
{item}
}
+
+```
+
+## Demo
+
+You can use this template for publishing your demo on CodeSandbox: https://codesandbox.io/s/solid-primitives-demo-template-sz95h
+
+## Changelog
+
+See [CHANGELOG.md](./CHANGELOG.md)
diff --git a/packages/selectors/dev/index.tsx b/packages/selectors/dev/index.tsx
new file mode 100644
index 000000000..753e8ce71
--- /dev/null
+++ b/packages/selectors/dev/index.tsx
@@ -0,0 +1,37 @@
+import { Component, For, createSignal } from "solid-js";
+import { createArraySelector } from "../src/index.js";
+
+const items = [1, 2, 3];
+
+const App: Component = () => {
+ const [selectedItems, setSelectedItems] = createSignal([]);
+ const isSelected = createArraySelector(selectedItems);
+
+ return (
+ <>
+
+ {item => (
+
}
+ *
+ */
+export function createArraySelector(
+ source: () => Array,
+ options?: { name?: string },
+): (k: T) => boolean {
+ const selector = createSelector, T>(
+ source,
+ (a, b) => {
+ return b.includes(a);
+ },
+ options,
+ );
+ return selector;
+}
diff --git a/packages/selectors/test/index.test.ts b/packages/selectors/test/index.test.ts
new file mode 100644
index 000000000..aab25f2c6
--- /dev/null
+++ b/packages/selectors/test/index.test.ts
@@ -0,0 +1,44 @@
+import { describe, test, expect } from "vitest";
+import { createRoot, createSignal } from "solid-js";
+import { createArraySelector } from "../src/index.js";
+
+describe("createArraySelector", () => {
+ test("createArraySelector select single item", () =>
+ createRoot(dispose => {
+ const [selected, setSelected] = createSignal(["a"]);
+ const isSelected = createArraySelector(selected);
+
+ expect(isSelected("a"), "initial value selected for 'a' should be true").toBe(true);
+ expect(isSelected("b"), "initial value selected for 'b' should be false").toBe(false);
+ setSelected(["c"]);
+ expect(isSelected("a"), "value after change for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change for 'b' should be false").toBe(false);
+ setSelected(["b"]);
+ expect(isSelected("a"), "value after change for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change for 'b' should be true").toBe(true);
+ dispose();
+ }));
+
+ test("createArraySelector select multiple items", () =>
+ createRoot(dispose => {
+ const [selected, setSelected] = createSignal(["a", "b"]);
+ const isSelected = createArraySelector(selected);
+
+ expect(isSelected("a"), "initial value selected for 'a' should be true").toBe(true);
+ expect(isSelected("b"), "initial value selected for 'b' should be true").toBe(true);
+ expect(isSelected("c"), "initial value selected for 'c' should be false").toBe(false);
+ setSelected(["c", "b"]);
+ expect(isSelected("a"), "value after change for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change for 'b' should be true").toBe(true);
+ expect(isSelected("c"), "value after change for 'c' should be true").toBe(true);
+ setSelected(["c", "a"]);
+ expect(isSelected("a"), "value after change for 'a' should be true").toBe(true);
+ expect(isSelected("b"), "value after change for 'b' should be false").toBe(false);
+ expect(isSelected("c"), "value after change for 'c' should be true").toBe(true);
+ setSelected([]);
+ expect(isSelected("a"), "value after change empty for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change empty for 'b' should be false").toBe(false);
+ expect(isSelected("c"), "value after change empty for 'c' should be false").toBe(false);
+ dispose();
+ }));
+});
diff --git a/packages/selectors/test/server.test.ts b/packages/selectors/test/server.test.ts
new file mode 100644
index 000000000..1d1bbd2f6
--- /dev/null
+++ b/packages/selectors/test/server.test.ts
@@ -0,0 +1,19 @@
+import { describe, test, expect } from "vitest";
+import { createSignal } from "solid-js";
+import { createArraySelector } from "../src/index.js";
+
+describe("createArraySelector", () => {
+ test("doesn't break in SSR", () => {
+ const [selected, setSelected] = createSignal(["a"]);
+ const isSelected = createArraySelector(selected);
+
+ expect(isSelected("a"), "initial value selected for 'a' should be true").toBe(true);
+ expect(isSelected("b"), "initial value selected for 'b' should be false").toBe(false);
+ setSelected(["c"]);
+ expect(isSelected("a"), "value after change for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change for 'b' should be false").toBe(false);
+ setSelected(["b"]);
+ expect(isSelected("a"), "value after change for 'a' should be false").toBe(false);
+ expect(isSelected("b"), "value after change for 'b' should be true").toBe(true);
+ });
+});
diff --git a/packages/selectors/tsconfig.json b/packages/selectors/tsconfig.json
new file mode 100644
index 000000000..4082f16a5
--- /dev/null
+++ b/packages/selectors/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../../tsconfig.json"
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1d4fba1b1..5ca87dc6b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -834,6 +834,12 @@ importers:
specifier: ^1.7.11
version: 1.7.11
+ packages/selectors:
+ devDependencies:
+ solid-js:
+ specifier: ^1.7.11
+ version: 1.7.11
+
packages/set:
dependencies:
'@solid-primitives/trigger':