@adobe/data 0.9.36 → 0.9.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +91 -0
- package/dist/ecs/database/observe-select-deep.d.ts +23 -0
- package/dist/ecs/database/observe-select-deep.js +15 -0
- package/dist/ecs/database/observe-select-deep.js.map +1 -0
- package/dist/ecs/database/observe-select-deep.type-test.js +111 -0
- package/dist/ecs/database/observe-select-deep.type-test.js.map +1 -0
- package/dist/ecs/persistence-service/create-storage-persistence-service.js +4 -3
- package/dist/ecs/persistence-service/create-storage-persistence-service.js.map +1 -1
- package/dist/ecs/persistence-service/create-storage-persistence-service.test.js +52 -0
- package/dist/ecs/persistence-service/create-storage-persistence-service.test.js.map +1 -0
- package/dist/service/agentic-service/link.d.ts +15 -0
- package/dist/service/agentic-service/link.js +3 -0
- package/dist/service/agentic-service/link.js.map +1 -0
- package/dist/service/async-data-service/is-valid.d.ts +3 -1
- package/dist/service/async-data-service/is-valid.type-test.d.ts +1 -0
- package/dist/service/async-data-service/is-valid.type-test.js +3 -0
- package/dist/service/async-data-service/is-valid.type-test.js.map +1 -0
- package/dist/service/dynamic-service/semantic-service.d.ts +19 -0
- package/dist/service/dynamic-service/semantic-service.js +2 -0
- package/dist/service/dynamic-service/semantic-service.js.map +1 -0
- package/dist/service/semantic-service/semantic-service.d.ts +19 -0
- package/dist/service/semantic-service/semantic-service.js +2 -0
- package/dist/service/semantic-service/semantic-service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -1
- package/references/data-lit/README.md +18 -0
- package/references/data-lit/package.json +35 -0
- package/references/data-lit/src/decorators/apply-decorator.ts +26 -0
- package/references/data-lit/src/decorators/apply-service-decorators.ts +15 -0
- package/references/data-lit/src/decorators/index.ts +4 -0
- package/references/data-lit/src/decorators/require-service.ts +20 -0
- package/references/data-lit/src/elements/application-element.ts +42 -0
- package/references/data-lit/src/elements/application-host.ts +43 -0
- package/references/data-lit/src/elements/database-element.ts +42 -0
- package/references/data-lit/src/elements/index.ts +5 -0
- package/references/data-lit/src/functions/index.ts +3 -0
- package/references/data-lit/src/functions/iterate-self-and-ancestors.ts +23 -0
- package/references/data-lit/src/hooks/attach-decorator.ts +32 -0
- package/references/data-lit/src/hooks/component/component.ts +12 -0
- package/references/data-lit/src/hooks/component/stack.ts +19 -0
- package/references/data-lit/src/hooks/index.ts +21 -0
- package/references/data-lit/src/hooks/use-connected.ts +41 -0
- package/references/data-lit/src/hooks/use-debounce.ts +26 -0
- package/references/data-lit/src/hooks/use-drag-observe.ts +59 -0
- package/references/data-lit/src/hooks/use-drag-transaction.ts +46 -0
- package/references/data-lit/src/hooks/use-draggable.ts +112 -0
- package/references/data-lit/src/hooks/use-effect.ts +19 -0
- package/references/data-lit/src/hooks/use-element.ts +83 -0
- package/references/data-lit/src/hooks/use-memo.ts +16 -0
- package/references/data-lit/src/hooks/use-observable-values.ts +10 -0
- package/references/data-lit/src/hooks/use-observable.ts +15 -0
- package/references/data-lit/src/hooks/use-ref.ts +8 -0
- package/references/data-lit/src/hooks/use-resize-observer.ts +31 -0
- package/references/data-lit/src/hooks/use-state.ts +19 -0
- package/references/data-lit/src/hooks/use-updated.ts +56 -0
- package/references/data-lit/src/hooks/use-window-event.ts +16 -0
- package/references/data-lit/src/hooks/with-hooks.ts +22 -0
- package/references/data-lit/src/index.ts +6 -0
- package/references/data-lit/tsconfig.json +11 -0
- package/references/data-lit-todo/package.json +30 -0
- package/references/data-lit-todo/src/elements/todo-list/todo-list-presentation.ts +22 -0
- package/references/data-lit-todo/src/elements/todo-list/todo-list.css.ts +12 -0
- package/references/data-lit-todo/src/elements/todo-list/todo-list.ts +45 -0
- package/references/data-lit-todo/src/elements/todo-row/index.ts +2 -0
- package/references/data-lit-todo/src/elements/todo-row/todo-row-presentation.ts +68 -0
- package/references/data-lit-todo/src/elements/todo-row/todo-row.css.ts +49 -0
- package/references/data-lit-todo/src/elements/todo-row/todo-row.ts +46 -0
- package/references/data-lit-todo/src/elements/todo-toolbar/index.ts +2 -0
- package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar-presentation.ts +55 -0
- package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar.css.ts +34 -0
- package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar.ts +62 -0
- package/references/data-lit-todo/src/elements/todo-undo-redo/index.ts +3 -0
- package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo-presentation.ts +41 -0
- package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo.css.ts +12 -0
- package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo.ts +37 -0
- package/references/data-lit-todo/src/index.ts +9 -0
- package/references/data-lit-todo/src/main.ts +29 -0
- package/references/data-lit-todo/src/sample-types.ts +14 -0
- package/references/data-lit-todo/src/services/dependent-state-service/create-dependent-state-service.ts +8 -0
- package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/all-todos.ts +5 -0
- package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/complete-todos.ts +5 -0
- package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/incomplete-todos.ts +5 -0
- package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/index.ts +4 -0
- package/references/data-lit-todo/src/services/dependent-state-service/dependent-state-service.ts +4 -0
- package/references/data-lit-todo/src/services/main-service/create-main-service.ts +53 -0
- package/references/data-lit-todo/src/services/main-service/todo-main-service.ts +20 -0
- package/references/data-lit-todo/src/services/state-service/create-todo-database.ts +16 -0
- package/references/data-lit-todo/src/services/state-service/create-todo-store.ts +28 -0
- package/references/data-lit-todo/src/services/state-service/todo-state-service.ts +9 -0
- package/references/data-lit-todo/src/services/state-service/transactions/create-bulk-todos.ts +12 -0
- package/references/data-lit-todo/src/services/state-service/transactions/create-todo.test.ts +17 -0
- package/references/data-lit-todo/src/services/state-service/transactions/create-todo.ts +15 -0
- package/references/data-lit-todo/src/services/state-service/transactions/delete-all-todos.ts +18 -0
- package/references/data-lit-todo/src/services/state-service/transactions/delete-todo.test.ts +25 -0
- package/references/data-lit-todo/src/services/state-service/transactions/delete-todo.ts +11 -0
- package/references/data-lit-todo/src/services/state-service/transactions/drag-todo.ts +19 -0
- package/references/data-lit-todo/src/services/state-service/transactions/index.ts +8 -0
- package/references/data-lit-todo/src/services/state-service/transactions/reorder-todos.ts +13 -0
- package/references/data-lit-todo/src/services/state-service/transactions/toggle-complete.test.ts +78 -0
- package/references/data-lit-todo/src/services/state-service/transactions/toggle-complete.ts +15 -0
- package/references/data-lit-todo/src/todo-element.ts +6 -0
- package/references/data-lit-todo/src/todo-host.ts +29 -0
- package/references/data-lit-todo/src/todo-main-element.ts +40 -0
- package/references/data-lit-todo/src/todo-sample.ts +21 -0
- package/references/data-lit-todo/tsconfig.json +10 -0
- package/references/data-react/README.md +47 -0
- package/references/data-react/package.json +36 -0
- package/references/data-react/src/context/database-context.tsx +41 -0
- package/references/data-react/src/hooks/index.ts +5 -0
- package/references/data-react/src/hooks/use-database.ts +13 -0
- package/references/data-react/src/hooks/use-observable-values.ts +15 -0
- package/references/data-react/src/hooks/use-observable.ts +14 -0
- package/references/data-react/src/index.ts +7 -0
- package/references/data-react/tsconfig.json +12 -0
- package/references/data-react-hello/package.json +25 -0
- package/references/data-react-hello/src/App.tsx +13 -0
- package/references/data-react-hello/src/Counter.tsx +21 -0
- package/references/data-react-hello/src/counter-plugin.ts +14 -0
- package/references/data-react-hello/src/main.tsx +9 -0
- package/references/data-react-hello/tsconfig.json +16 -0
- package/references/data-react-pixie/package.json +28 -0
- package/references/data-react-pixie/src/App.tsx +21 -0
- package/references/data-react-pixie/src/bunny.png +0 -0
- package/references/data-react-pixie/src/filter-toggle.tsx +46 -0
- package/references/data-react-pixie/src/filters.ts +22 -0
- package/references/data-react-pixie/src/fox.png +0 -0
- package/references/data-react-pixie/src/hooks/use-database.ts +6 -0
- package/references/data-react-pixie/src/hooks/use-texture.ts +22 -0
- package/references/data-react-pixie/src/main.tsx +14 -0
- package/references/data-react-pixie/src/pixi-react.d.ts +1 -0
- package/references/data-react-pixie/src/pixie-plugin.ts +100 -0
- package/references/data-react-pixie/src/sprite-container.tsx +23 -0
- package/references/data-react-pixie/src/sprite-urls.ts +9 -0
- package/references/data-react-pixie/src/sprite.tsx +35 -0
- package/references/data-react-pixie/src/tick.tsx +10 -0
- package/references/data-react-pixie/src/vite-env.d.ts +6 -0
- package/references/data-react-pixie/tsconfig.json +16 -0
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -296
- package/dist/package.json +0 -183
- package/dist/service/agentic-service/create-from-config.d.ts +0 -45
- package/dist/service/agentic-service/create-from-config.js +0 -85
- package/dist/service/agentic-service/create-from-config.js.map +0 -1
- package/dist/service/agentic-service/create.interface-first-spike.type-test.js +0 -119
- package/dist/service/agentic-service/create.interface-first-spike.type-test.js.map +0 -1
- package/dist/service/agentic-service/index.d.ts +0 -1
- package/dist/service/agentic-service/index.js +0 -3
- package/dist/service/agentic-service/index.js.map +0 -1
- package/dist/service/dynamic-service/create.interface-first-spike.type-test.js +0 -118
- package/dist/service/dynamic-service/create.interface-first-spike.type-test.js.map +0 -1
- /package/dist/{service/agentic-service/create.interface-first-spike.type-test.d.ts → ecs/database/observe-select-deep.type-test.d.ts} +0 -0
- /package/dist/{service/dynamic-service/create.interface-first-spike.type-test.d.ts → ecs/persistence-service/create-storage-persistence-service.test.d.ts} +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { createTodo } from './create-todo.js';
|
|
3
|
+
import { deleteTodo } from './delete-todo.js';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
|
|
6
|
+
import { createTodoStore } from '../create-todo-store.js';
|
|
7
|
+
|
|
8
|
+
describe('deleteTodo', () => {
|
|
9
|
+
describe('when deleting a todo', () => {
|
|
10
|
+
it('should remove it from the archetype', () => {
|
|
11
|
+
const t = createTodoStore();
|
|
12
|
+
const todoA = createTodo(t, { name: 'A' });
|
|
13
|
+
const todoB = createTodo(t, { name: 'B' });
|
|
14
|
+
const todoC = createTodo(t, { name: 'C' });
|
|
15
|
+
deleteTodo(t, todoA);
|
|
16
|
+
const values = t.read(todoA);
|
|
17
|
+
expect(values).toBeNull();
|
|
18
|
+
const valuesB = t.read(todoB);
|
|
19
|
+
expect(valuesB).toBeDefined();
|
|
20
|
+
const valuesC = t.read(todoC);
|
|
21
|
+
expect(valuesC).toBeDefined();
|
|
22
|
+
expect(t.archetypes.Todo.rowCount).toBe(2);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { reorderTodos } from './reorder-todos.js';
|
|
3
|
+
import type { Entity } from "@adobe/data/ecs";
|
|
4
|
+
|
|
5
|
+
import { type TodoStore } from '../create-todo-store.js';
|
|
6
|
+
|
|
7
|
+
export const deleteTodo = (t: TodoStore, id: Entity) => {
|
|
8
|
+
t.undoable = { coalesce: false };
|
|
9
|
+
t.delete(id);
|
|
10
|
+
reorderTodos(t);
|
|
11
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { reorderTodos } from './reorder-todos.js';
|
|
3
|
+
import type { Entity } from "@adobe/data/ecs";
|
|
4
|
+
|
|
5
|
+
import { type TodoStore } from '../create-todo-store.js';
|
|
6
|
+
|
|
7
|
+
export const dragTodo = (t: TodoStore, props: { todo: Entity; dragPosition: number; finalIndex?: number }) => {
|
|
8
|
+
t.undoable = { coalesce: false };
|
|
9
|
+
const { todo, dragPosition, finalIndex } = props;
|
|
10
|
+
const completed = finalIndex !== undefined;
|
|
11
|
+
if (!completed) {
|
|
12
|
+
t.update(todo, { dragPosition });
|
|
13
|
+
} else {
|
|
14
|
+
// insert it with an order value 0.5 less than the final index
|
|
15
|
+
t.update(todo, { dragPosition: null, order: finalIndex - 0.5 });
|
|
16
|
+
// then we call reorderTodos which will reorder everything to integer order values
|
|
17
|
+
reorderTodos(t); // this is an example of calling another transaction from a transaction
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
export * from './create-todo.js';
|
|
3
|
+
export * from './delete-todo.js';
|
|
4
|
+
export * from './toggle-complete.js';
|
|
5
|
+
export * from './create-bulk-todos.js';
|
|
6
|
+
export * from './drag-todo.js';
|
|
7
|
+
// This is used by the undo-redo actions, the implementation is in the data package.
|
|
8
|
+
export { applyOperations } from "@adobe/data/ecs";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { TodoStore } from '../create-todo-store.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ensures each todo has an monotonically increasing integer order value.
|
|
6
|
+
* You might call this after inserting a todo with a floating point order value for insertion.
|
|
7
|
+
*/
|
|
8
|
+
export const reorderTodos = (t: TodoStore) => {
|
|
9
|
+
const todos = t.select(t.archetypes.Todo.components, { order: { order: true } });
|
|
10
|
+
for (let i = 0; i < todos.length; i++) {
|
|
11
|
+
t.update(todos[i], { order: i });
|
|
12
|
+
}
|
|
13
|
+
};
|
package/references/data-lit-todo/src/services/state-service/transactions/toggle-complete.test.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { createTodo } from './create-todo.js';
|
|
3
|
+
import { toggleComplete } from './toggle-complete.js';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
|
|
6
|
+
import { createTodoStore } from '../create-todo-store.js';
|
|
7
|
+
|
|
8
|
+
describe('toggleComplete', () => {
|
|
9
|
+
describe('when toggling a complete todo', () => {
|
|
10
|
+
it('should mark it as incomplete', () => {
|
|
11
|
+
const t = createTodoStore();
|
|
12
|
+
const todoId = createTodo(t, { name: 'Test todo' });
|
|
13
|
+
// First mark as complete
|
|
14
|
+
t.update(todoId, { complete: true });
|
|
15
|
+
expect(t.read(todoId)?.complete).toBe(true);
|
|
16
|
+
|
|
17
|
+
// Then toggle it
|
|
18
|
+
toggleComplete(t, todoId);
|
|
19
|
+
expect(t.read(todoId)?.complete).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('when toggling an incomplete todo', () => {
|
|
24
|
+
it('should mark it as complete', () => {
|
|
25
|
+
const t = createTodoStore();
|
|
26
|
+
const todoId = createTodo(t, { name: 'Test todo' });
|
|
27
|
+
expect(t.read(todoId)?.complete).toBe(false);
|
|
28
|
+
|
|
29
|
+
toggleComplete(t, todoId);
|
|
30
|
+
expect(t.read(todoId)?.complete).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('when toggling multiple times', () => {
|
|
35
|
+
it('should alternate between complete and incomplete', () => {
|
|
36
|
+
const t = createTodoStore();
|
|
37
|
+
const todoId = createTodo(t, { name: 'Test todo' });
|
|
38
|
+
expect(t.read(todoId)?.complete).toBe(false);
|
|
39
|
+
|
|
40
|
+
// First toggle
|
|
41
|
+
toggleComplete(t, todoId);
|
|
42
|
+
expect(t.read(todoId)?.complete).toBe(true);
|
|
43
|
+
|
|
44
|
+
// Second toggle
|
|
45
|
+
toggleComplete(t, todoId);
|
|
46
|
+
expect(t.read(todoId)?.complete).toBe(false);
|
|
47
|
+
|
|
48
|
+
// Third toggle
|
|
49
|
+
toggleComplete(t, todoId);
|
|
50
|
+
expect(t.read(todoId)?.complete).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe('when toggling a non-existent todo', () => {
|
|
55
|
+
it('should not throw an error and should no-op', () => {
|
|
56
|
+
const t = createTodoStore();
|
|
57
|
+
const nonExistentId = 999;
|
|
58
|
+
expect(t.read(nonExistentId)).toBeNull();
|
|
59
|
+
|
|
60
|
+
// Should not throw
|
|
61
|
+
expect(() => toggleComplete(t, nonExistentId)).not.toThrow();
|
|
62
|
+
|
|
63
|
+
// Should still be null
|
|
64
|
+
expect(t.read(nonExistentId)).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('when toggling with invalid entity id', () => {
|
|
69
|
+
it('should not throw an error and should no-op', () => {
|
|
70
|
+
const t = createTodoStore();
|
|
71
|
+
const invalidId = -1;
|
|
72
|
+
|
|
73
|
+
// Should not throw
|
|
74
|
+
toggleComplete(t, invalidId);
|
|
75
|
+
expect(() => toggleComplete(t, invalidId)).not.toThrow();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import type { Entity } from "@adobe/data/ecs";
|
|
3
|
+
|
|
4
|
+
import { type TodoStore } from '../create-todo-store.js';
|
|
5
|
+
|
|
6
|
+
export const toggleComplete = (t: TodoStore, id: Entity) => {
|
|
7
|
+
t.undoable = { coalesce: false };
|
|
8
|
+
const todo = t.read(id);
|
|
9
|
+
// actions must never throw errors.
|
|
10
|
+
// if state is invalid they must no op.
|
|
11
|
+
// this is important for resolving concurrency conflicts.
|
|
12
|
+
if (todo) {
|
|
13
|
+
t.update(id, { complete: !todo.complete });
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { TodoMainService } from './services/main-service/todo-main-service.js';
|
|
3
|
+
|
|
4
|
+
import { ApplicationElement } from "@adobe/data-lit";
|
|
5
|
+
|
|
6
|
+
export class TodoElement extends ApplicationElement<TodoMainService> { }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { LitElement, html, css } from 'lit';
|
|
4
|
+
import { customElement } from 'lit/decorators.js';
|
|
5
|
+
import { createMainService } from './services/main-service/create-main-service.js';
|
|
6
|
+
import './todo-main-element.js'; // Side effect: registers custom elements
|
|
7
|
+
import "@adobe/data-lit"; // Side effect: registers ApplicationHost and other elements
|
|
8
|
+
|
|
9
|
+
export const tagName = 'todo-host';
|
|
10
|
+
|
|
11
|
+
@customElement(tagName)
|
|
12
|
+
export class TodoHost extends LitElement {
|
|
13
|
+
static styles = css`
|
|
14
|
+
:host {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex: 1 1 auto;
|
|
17
|
+
color: red;
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
render() {
|
|
22
|
+
return html`
|
|
23
|
+
<application-host
|
|
24
|
+
.createService=${createMainService}
|
|
25
|
+
.renderElement=${() => html`<data-todo></data-todo>`}>
|
|
26
|
+
</application-host>
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import './elements/todo-list/todo-list.js';
|
|
3
|
+
import './elements/todo-row/todo-row.js';
|
|
4
|
+
import './elements/todo-toolbar/todo-toolbar.js';
|
|
5
|
+
import './elements/todo-undo-redo/todo-undo-redo.js';
|
|
6
|
+
import { TodoElement } from './todo-element.js';
|
|
7
|
+
import { html, css } from 'lit';
|
|
8
|
+
import { customElement } from 'lit/decorators.js';
|
|
9
|
+
|
|
10
|
+
export const tagName = 'data-todo';
|
|
11
|
+
|
|
12
|
+
@customElement(tagName)
|
|
13
|
+
export class TodoMainElement extends TodoElement {
|
|
14
|
+
static styles = css`
|
|
15
|
+
:host {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
height: 400px;
|
|
19
|
+
max-height: 400px;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
data-todo-toolbar {
|
|
24
|
+
flex-shrink: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
data-todo-list {
|
|
28
|
+
flex: 1;
|
|
29
|
+
overflow-y: auto;
|
|
30
|
+
min-height: 0;
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
render() {
|
|
35
|
+
return html`
|
|
36
|
+
<data-todo-toolbar></data-todo-toolbar>
|
|
37
|
+
<data-todo-list></data-todo-list>
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import type { Sample } from "./sample-types.js";
|
|
4
|
+
import "./todo-host.js"; // Side effect: registers todo-host
|
|
5
|
+
|
|
6
|
+
export const todoSample: Sample = {
|
|
7
|
+
id: 'todo',
|
|
8
|
+
title: 'Todo Application',
|
|
9
|
+
description: 'A complete todo application demonstrating ECS architecture, state management, undo/redo, and persistence.',
|
|
10
|
+
category: 'Application Examples',
|
|
11
|
+
difficulty: 'intermediate',
|
|
12
|
+
features: [
|
|
13
|
+
'Entity-Component-System (ECS)',
|
|
14
|
+
'State Management',
|
|
15
|
+
'Undo/Redo System',
|
|
16
|
+
'Local Storage Persistence',
|
|
17
|
+
'Drag and Drop Reordering',
|
|
18
|
+
'Reactive UI Updates'
|
|
19
|
+
],
|
|
20
|
+
elementTag: 'todo-host'
|
|
21
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# @adobe/data-react
|
|
2
|
+
|
|
3
|
+
React bindings for [@adobe/data](https://www.npmjs.com/package/@adobe/data) — hooks and context for the ECS database and observables.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @adobe/data @adobe/data-react react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependency
|
|
12
|
+
|
|
13
|
+
Requires `react >= 17.0.0` (supports React 17, 18, 19).
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Use `useObservableValues` for everything you need to observe — pass a factory that returns an object of observables:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { DatabaseProvider, useDatabase, useObservableValues } from "@adobe/data-react";
|
|
21
|
+
import { Database } from "@adobe/data/ecs";
|
|
22
|
+
|
|
23
|
+
const myPlugin = Database.Plugin.create({ /* ... */ });
|
|
24
|
+
|
|
25
|
+
function App() {
|
|
26
|
+
return (
|
|
27
|
+
<DatabaseProvider plugin={myPlugin}>
|
|
28
|
+
<Counter />
|
|
29
|
+
</DatabaseProvider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function Counter() {
|
|
34
|
+
const db = useDatabase(myPlugin);
|
|
35
|
+
const values = useObservableValues(() => ({
|
|
36
|
+
count: db.observe.resources.count,
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
if (!values) return null;
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<p>Count: {values.count}</p>
|
|
43
|
+
<button onClick={() => db.transactions.increment()}>Increment</button>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adobe/data-react",
|
|
3
|
+
"version": "0.9.39",
|
|
4
|
+
"description": "Adobe data React bindings — hooks and context for ECS database",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"registry": "https://registry.npmjs.org/",
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "cp ../../LICENSE . && tsc -b",
|
|
13
|
+
"dev": "tsc -b -w",
|
|
14
|
+
"link": "pnpm build && pnpm link --global",
|
|
15
|
+
"test": "vitest --run --passWithNoTests",
|
|
16
|
+
"publish-public": "pnpm build && pnpm publish --no-git-checks --access public"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@adobe/data": "workspace:*"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"react": ">=17.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/react": "^19",
|
|
26
|
+
"react": "^19",
|
|
27
|
+
"typescript": "^5.8.3",
|
|
28
|
+
"vitest": "^1.6.0"
|
|
29
|
+
},
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useMemo,
|
|
6
|
+
useContext,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
type ReactElement,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { Database } from "@adobe/data/ecs";
|
|
11
|
+
|
|
12
|
+
export const DatabaseContext = createContext<Database | null>(null);
|
|
13
|
+
|
|
14
|
+
export type DatabaseProviderProps<P extends Database.Plugin> = {
|
|
15
|
+
plugin: P;
|
|
16
|
+
database?: Database.FromPlugin<P>;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function DatabaseProvider<P extends Database.Plugin>(
|
|
21
|
+
props: DatabaseProviderProps<P>,
|
|
22
|
+
): ReactElement {
|
|
23
|
+
const { plugin, database: providedDatabase, children } = props;
|
|
24
|
+
const ancestor = useContext(DatabaseContext);
|
|
25
|
+
|
|
26
|
+
const database = useMemo(() => {
|
|
27
|
+
if (providedDatabase) {
|
|
28
|
+
return providedDatabase;
|
|
29
|
+
}
|
|
30
|
+
if (ancestor) {
|
|
31
|
+
return ancestor.extend(plugin) as unknown as Database.FromPlugin<P>;
|
|
32
|
+
}
|
|
33
|
+
return Database.create(plugin) as unknown as Database.FromPlugin<P>;
|
|
34
|
+
}, [plugin, providedDatabase, ancestor]);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<DatabaseContext.Provider value={database as unknown as Database}>
|
|
38
|
+
{children}
|
|
39
|
+
</DatabaseContext.Provider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { useContext } from "react";
|
|
4
|
+
import { Database } from "@adobe/data/ecs";
|
|
5
|
+
import { DatabaseContext } from "../context/database-context.js";
|
|
6
|
+
|
|
7
|
+
export function useDatabase<T extends Database.Plugin>(plugin: T): Database.FromPlugin<T> {
|
|
8
|
+
const ancestor = useContext(DatabaseContext);
|
|
9
|
+
if (ancestor) {
|
|
10
|
+
return ancestor.extend(plugin) as unknown as Database.FromPlugin<T>;
|
|
11
|
+
}
|
|
12
|
+
return Database.create(plugin) as unknown as Database.FromPlugin<T>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { Observe } from "@adobe/data/observe";
|
|
5
|
+
import { useObservable } from "./use-observable.js";
|
|
6
|
+
|
|
7
|
+
export function useObservableValues<
|
|
8
|
+
T extends Record<string, Observe<unknown>>,
|
|
9
|
+
>(
|
|
10
|
+
factory: () => T,
|
|
11
|
+
deps: unknown[] = [],
|
|
12
|
+
): { [K in keyof T]: T[K] extends Observe<infer U> ? U : never } | undefined {
|
|
13
|
+
const observable = useMemo(() => Observe.fromProperties(factory()), deps);
|
|
14
|
+
return useObservable(observable);
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from "react";
|
|
4
|
+
import type { Observe } from "@adobe/data/observe";
|
|
5
|
+
|
|
6
|
+
export function useObservable<T>(observable: Observe<T>): T | undefined {
|
|
7
|
+
const [value, setValue] = useState<T | undefined>(undefined);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
return observable((newValue) => {
|
|
10
|
+
setValue(newValue);
|
|
11
|
+
});
|
|
12
|
+
}, [observable]);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
export { DatabaseContext, DatabaseProvider } from "./context/database-context.js";
|
|
4
|
+
export type { DatabaseProviderProps } from "./context/database-context.js";
|
|
5
|
+
export { useDatabase } from "./hooks/use-database.js";
|
|
6
|
+
export { useObservable } from "./hooks/use-observable.js";
|
|
7
|
+
export { useObservableValues } from "./hooks/use-observable-values.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "data-react-hello",
|
|
3
|
+
"version": "0.9.39",
|
|
4
|
+
"description": "Hello World sample - click counter using @adobe/data-react",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": true,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"publish-public": "true"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@adobe/data": "workspace:*",
|
|
14
|
+
"@adobe/data-react": "workspace:*",
|
|
15
|
+
"react": "^19",
|
|
16
|
+
"react-dom": "^19"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/react": "^19",
|
|
20
|
+
"@types/react-dom": "^19",
|
|
21
|
+
"typescript": "^5.8.3",
|
|
22
|
+
"vite": "^5.1.1",
|
|
23
|
+
"@vitejs/plugin-react": "^4.3.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { DatabaseProvider } from "@adobe/data-react";
|
|
4
|
+
import { counterPlugin } from "./counter-plugin";
|
|
5
|
+
import { Counter } from "./Counter";
|
|
6
|
+
|
|
7
|
+
export function App() {
|
|
8
|
+
return (
|
|
9
|
+
<DatabaseProvider plugin={counterPlugin}>
|
|
10
|
+
<Counter />
|
|
11
|
+
</DatabaseProvider>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { useDatabase, useObservableValues } from "@adobe/data-react";
|
|
4
|
+
import { counterPlugin } from "./counter-plugin";
|
|
5
|
+
|
|
6
|
+
export function Counter() {
|
|
7
|
+
const db = useDatabase(counterPlugin);
|
|
8
|
+
const values = useObservableValues(() => ({
|
|
9
|
+
count: db.observe.resources.count,
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
if (!values) return null;
|
|
13
|
+
return (
|
|
14
|
+
<div>
|
|
15
|
+
<p className="counter">Count: {values.count}</p>
|
|
16
|
+
<button type="button" onClick={() => db.transactions.increment()}>
|
|
17
|
+
Increment
|
|
18
|
+
</button>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { Database } from "@adobe/data/ecs";
|
|
4
|
+
|
|
5
|
+
export const counterPlugin = Database.Plugin.create({
|
|
6
|
+
resources: {
|
|
7
|
+
count: { default: 0 as number },
|
|
8
|
+
},
|
|
9
|
+
transactions: {
|
|
10
|
+
increment: (t) => {
|
|
11
|
+
t.resources.count += 1;
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"resolveJsonModule": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"jsx": "react-jsx",
|
|
13
|
+
"strict": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "data-react-pixie",
|
|
3
|
+
"version": "0.9.39",
|
|
4
|
+
"description": "PixiJS React sample - ECS sprites (bunny, fox) with @adobe/data-react",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": true,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"publish-public": "true"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@adobe/data": "workspace:*",
|
|
14
|
+
"@adobe/data-react": "workspace:*",
|
|
15
|
+
"@pixi/react": "8.0.0-beta.25",
|
|
16
|
+
"pixi.js": "^8.2.6",
|
|
17
|
+
"react": "^19",
|
|
18
|
+
"react-dom": "^19"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/react": "^19",
|
|
22
|
+
"@types/react-dom": "^19",
|
|
23
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
24
|
+
"typescript": "^5.8.3",
|
|
25
|
+
"vite": "^5.1.1",
|
|
26
|
+
"vite-plugin-checker": "^0.12.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
|
|
3
|
+
import { Application } from "@pixi/react";
|
|
4
|
+
import { DatabaseProvider } from "@adobe/data-react";
|
|
5
|
+
import { pixiePlugin } from "./pixie-plugin.js";
|
|
6
|
+
import { FilterToggle } from "./filter-toggle.js";
|
|
7
|
+
import { SpriteContainer } from "./sprite-container.js";
|
|
8
|
+
import { Tick } from "./tick.js";
|
|
9
|
+
|
|
10
|
+
export function App() {
|
|
11
|
+
return (
|
|
12
|
+
<DatabaseProvider plugin={pixiePlugin}>
|
|
13
|
+
<FilterToggle />
|
|
14
|
+
<Application background="beige" width={640} height={480}>
|
|
15
|
+
<Tick />
|
|
16
|
+
<SpriteContainer />
|
|
17
|
+
</Application>
|
|
18
|
+
</DatabaseProvider>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
Binary file
|