@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.
Files changed (152) hide show
  1. package/AGENTS.md +91 -0
  2. package/dist/ecs/database/observe-select-deep.d.ts +23 -0
  3. package/dist/ecs/database/observe-select-deep.js +15 -0
  4. package/dist/ecs/database/observe-select-deep.js.map +1 -0
  5. package/dist/ecs/database/observe-select-deep.type-test.js +111 -0
  6. package/dist/ecs/database/observe-select-deep.type-test.js.map +1 -0
  7. package/dist/ecs/persistence-service/create-storage-persistence-service.js +4 -3
  8. package/dist/ecs/persistence-service/create-storage-persistence-service.js.map +1 -1
  9. package/dist/ecs/persistence-service/create-storage-persistence-service.test.js +52 -0
  10. package/dist/ecs/persistence-service/create-storage-persistence-service.test.js.map +1 -0
  11. package/dist/service/agentic-service/link.d.ts +15 -0
  12. package/dist/service/agentic-service/link.js +3 -0
  13. package/dist/service/agentic-service/link.js.map +1 -0
  14. package/dist/service/async-data-service/is-valid.d.ts +3 -1
  15. package/dist/service/async-data-service/is-valid.type-test.d.ts +1 -0
  16. package/dist/service/async-data-service/is-valid.type-test.js +3 -0
  17. package/dist/service/async-data-service/is-valid.type-test.js.map +1 -0
  18. package/dist/service/dynamic-service/semantic-service.d.ts +19 -0
  19. package/dist/service/dynamic-service/semantic-service.js +2 -0
  20. package/dist/service/dynamic-service/semantic-service.js.map +1 -0
  21. package/dist/service/semantic-service/semantic-service.d.ts +19 -0
  22. package/dist/service/semantic-service/semantic-service.js +2 -0
  23. package/dist/service/semantic-service/semantic-service.js.map +1 -0
  24. package/dist/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +3 -1
  26. package/references/data-lit/README.md +18 -0
  27. package/references/data-lit/package.json +35 -0
  28. package/references/data-lit/src/decorators/apply-decorator.ts +26 -0
  29. package/references/data-lit/src/decorators/apply-service-decorators.ts +15 -0
  30. package/references/data-lit/src/decorators/index.ts +4 -0
  31. package/references/data-lit/src/decorators/require-service.ts +20 -0
  32. package/references/data-lit/src/elements/application-element.ts +42 -0
  33. package/references/data-lit/src/elements/application-host.ts +43 -0
  34. package/references/data-lit/src/elements/database-element.ts +42 -0
  35. package/references/data-lit/src/elements/index.ts +5 -0
  36. package/references/data-lit/src/functions/index.ts +3 -0
  37. package/references/data-lit/src/functions/iterate-self-and-ancestors.ts +23 -0
  38. package/references/data-lit/src/hooks/attach-decorator.ts +32 -0
  39. package/references/data-lit/src/hooks/component/component.ts +12 -0
  40. package/references/data-lit/src/hooks/component/stack.ts +19 -0
  41. package/references/data-lit/src/hooks/index.ts +21 -0
  42. package/references/data-lit/src/hooks/use-connected.ts +41 -0
  43. package/references/data-lit/src/hooks/use-debounce.ts +26 -0
  44. package/references/data-lit/src/hooks/use-drag-observe.ts +59 -0
  45. package/references/data-lit/src/hooks/use-drag-transaction.ts +46 -0
  46. package/references/data-lit/src/hooks/use-draggable.ts +112 -0
  47. package/references/data-lit/src/hooks/use-effect.ts +19 -0
  48. package/references/data-lit/src/hooks/use-element.ts +83 -0
  49. package/references/data-lit/src/hooks/use-memo.ts +16 -0
  50. package/references/data-lit/src/hooks/use-observable-values.ts +10 -0
  51. package/references/data-lit/src/hooks/use-observable.ts +15 -0
  52. package/references/data-lit/src/hooks/use-ref.ts +8 -0
  53. package/references/data-lit/src/hooks/use-resize-observer.ts +31 -0
  54. package/references/data-lit/src/hooks/use-state.ts +19 -0
  55. package/references/data-lit/src/hooks/use-updated.ts +56 -0
  56. package/references/data-lit/src/hooks/use-window-event.ts +16 -0
  57. package/references/data-lit/src/hooks/with-hooks.ts +22 -0
  58. package/references/data-lit/src/index.ts +6 -0
  59. package/references/data-lit/tsconfig.json +11 -0
  60. package/references/data-lit-todo/package.json +30 -0
  61. package/references/data-lit-todo/src/elements/todo-list/todo-list-presentation.ts +22 -0
  62. package/references/data-lit-todo/src/elements/todo-list/todo-list.css.ts +12 -0
  63. package/references/data-lit-todo/src/elements/todo-list/todo-list.ts +45 -0
  64. package/references/data-lit-todo/src/elements/todo-row/index.ts +2 -0
  65. package/references/data-lit-todo/src/elements/todo-row/todo-row-presentation.ts +68 -0
  66. package/references/data-lit-todo/src/elements/todo-row/todo-row.css.ts +49 -0
  67. package/references/data-lit-todo/src/elements/todo-row/todo-row.ts +46 -0
  68. package/references/data-lit-todo/src/elements/todo-toolbar/index.ts +2 -0
  69. package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar-presentation.ts +55 -0
  70. package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar.css.ts +34 -0
  71. package/references/data-lit-todo/src/elements/todo-toolbar/todo-toolbar.ts +62 -0
  72. package/references/data-lit-todo/src/elements/todo-undo-redo/index.ts +3 -0
  73. package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo-presentation.ts +41 -0
  74. package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo.css.ts +12 -0
  75. package/references/data-lit-todo/src/elements/todo-undo-redo/todo-undo-redo.ts +37 -0
  76. package/references/data-lit-todo/src/index.ts +9 -0
  77. package/references/data-lit-todo/src/main.ts +29 -0
  78. package/references/data-lit-todo/src/sample-types.ts +14 -0
  79. package/references/data-lit-todo/src/services/dependent-state-service/create-dependent-state-service.ts +8 -0
  80. package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/all-todos.ts +5 -0
  81. package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/complete-todos.ts +5 -0
  82. package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/incomplete-todos.ts +5 -0
  83. package/references/data-lit-todo/src/services/dependent-state-service/dependent-state/index.ts +4 -0
  84. package/references/data-lit-todo/src/services/dependent-state-service/dependent-state-service.ts +4 -0
  85. package/references/data-lit-todo/src/services/main-service/create-main-service.ts +53 -0
  86. package/references/data-lit-todo/src/services/main-service/todo-main-service.ts +20 -0
  87. package/references/data-lit-todo/src/services/state-service/create-todo-database.ts +16 -0
  88. package/references/data-lit-todo/src/services/state-service/create-todo-store.ts +28 -0
  89. package/references/data-lit-todo/src/services/state-service/todo-state-service.ts +9 -0
  90. package/references/data-lit-todo/src/services/state-service/transactions/create-bulk-todos.ts +12 -0
  91. package/references/data-lit-todo/src/services/state-service/transactions/create-todo.test.ts +17 -0
  92. package/references/data-lit-todo/src/services/state-service/transactions/create-todo.ts +15 -0
  93. package/references/data-lit-todo/src/services/state-service/transactions/delete-all-todos.ts +18 -0
  94. package/references/data-lit-todo/src/services/state-service/transactions/delete-todo.test.ts +25 -0
  95. package/references/data-lit-todo/src/services/state-service/transactions/delete-todo.ts +11 -0
  96. package/references/data-lit-todo/src/services/state-service/transactions/drag-todo.ts +19 -0
  97. package/references/data-lit-todo/src/services/state-service/transactions/index.ts +8 -0
  98. package/references/data-lit-todo/src/services/state-service/transactions/reorder-todos.ts +13 -0
  99. package/references/data-lit-todo/src/services/state-service/transactions/toggle-complete.test.ts +78 -0
  100. package/references/data-lit-todo/src/services/state-service/transactions/toggle-complete.ts +15 -0
  101. package/references/data-lit-todo/src/todo-element.ts +6 -0
  102. package/references/data-lit-todo/src/todo-host.ts +29 -0
  103. package/references/data-lit-todo/src/todo-main-element.ts +40 -0
  104. package/references/data-lit-todo/src/todo-sample.ts +21 -0
  105. package/references/data-lit-todo/tsconfig.json +10 -0
  106. package/references/data-react/README.md +47 -0
  107. package/references/data-react/package.json +36 -0
  108. package/references/data-react/src/context/database-context.tsx +41 -0
  109. package/references/data-react/src/hooks/index.ts +5 -0
  110. package/references/data-react/src/hooks/use-database.ts +13 -0
  111. package/references/data-react/src/hooks/use-observable-values.ts +15 -0
  112. package/references/data-react/src/hooks/use-observable.ts +14 -0
  113. package/references/data-react/src/index.ts +7 -0
  114. package/references/data-react/tsconfig.json +12 -0
  115. package/references/data-react-hello/package.json +25 -0
  116. package/references/data-react-hello/src/App.tsx +13 -0
  117. package/references/data-react-hello/src/Counter.tsx +21 -0
  118. package/references/data-react-hello/src/counter-plugin.ts +14 -0
  119. package/references/data-react-hello/src/main.tsx +9 -0
  120. package/references/data-react-hello/tsconfig.json +16 -0
  121. package/references/data-react-pixie/package.json +28 -0
  122. package/references/data-react-pixie/src/App.tsx +21 -0
  123. package/references/data-react-pixie/src/bunny.png +0 -0
  124. package/references/data-react-pixie/src/filter-toggle.tsx +46 -0
  125. package/references/data-react-pixie/src/filters.ts +22 -0
  126. package/references/data-react-pixie/src/fox.png +0 -0
  127. package/references/data-react-pixie/src/hooks/use-database.ts +6 -0
  128. package/references/data-react-pixie/src/hooks/use-texture.ts +22 -0
  129. package/references/data-react-pixie/src/main.tsx +14 -0
  130. package/references/data-react-pixie/src/pixi-react.d.ts +1 -0
  131. package/references/data-react-pixie/src/pixie-plugin.ts +100 -0
  132. package/references/data-react-pixie/src/sprite-container.tsx +23 -0
  133. package/references/data-react-pixie/src/sprite-urls.ts +9 -0
  134. package/references/data-react-pixie/src/sprite.tsx +35 -0
  135. package/references/data-react-pixie/src/tick.tsx +10 -0
  136. package/references/data-react-pixie/src/vite-env.d.ts +6 -0
  137. package/references/data-react-pixie/tsconfig.json +16 -0
  138. package/dist/LICENSE +0 -21
  139. package/dist/README.md +0 -296
  140. package/dist/package.json +0 -183
  141. package/dist/service/agentic-service/create-from-config.d.ts +0 -45
  142. package/dist/service/agentic-service/create-from-config.js +0 -85
  143. package/dist/service/agentic-service/create-from-config.js.map +0 -1
  144. package/dist/service/agentic-service/create.interface-first-spike.type-test.js +0 -119
  145. package/dist/service/agentic-service/create.interface-first-spike.type-test.js.map +0 -1
  146. package/dist/service/agentic-service/index.d.ts +0 -1
  147. package/dist/service/agentic-service/index.js +0 -3
  148. package/dist/service/agentic-service/index.js.map +0 -1
  149. package/dist/service/dynamic-service/create.interface-first-spike.type-test.js +0 -118
  150. package/dist/service/dynamic-service/create.interface-first-spike.type-test.js.map +0 -1
  151. /package/dist/{service/agentic-service/create.interface-first-spike.type-test.d.ts → ecs/database/observe-select-deep.type-test.d.ts} +0 -0
  152. /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,49 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { css } from 'lit';
3
+
4
+ export const styles = css`
5
+ :host {
6
+ display: block;
7
+ }
8
+
9
+ .todo-row {
10
+ --todo-row-height: 56px;
11
+ box-sizing: border-box;
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--spectrum-spacing-200);
15
+ padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
16
+ border-bottom: 1px solid var(--spectrum-gray-200);
17
+ min-height: var(--todo-row-height);
18
+ height: var(--todo-row-height);
19
+ contain: layout paint style; /* or at least paint/layout */
20
+ content-visibility: auto; /* skip offscreen work: https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility */
21
+ contain-intrinsic-size: 500px var(--todo-row-height); /* reserve space so auto can skip paint: https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size */
22
+ transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
23
+ }
24
+
25
+ .todo-row.dragging {
26
+ background-color: var(--spectrum-gray-100);
27
+ z-index: 100;
28
+ box-shadow: 0 0 10px var(--spectrum-gray-300);
29
+ }
30
+
31
+ .todo-row:hover {
32
+ background-color: var(--spectrum-gray-100);
33
+ }
34
+
35
+ .todo-name {
36
+ flex: 1;
37
+ font-size: var(--spectrum-font-size-100);
38
+ line-height: var(--spectrum-line-height-100);
39
+ color: var(--spectrum-gray-800);
40
+ }
41
+
42
+ sp-checkbox {
43
+ flex-shrink: 0;
44
+ }
45
+
46
+ sp-action-button {
47
+ flex-shrink: 0;
48
+ }
49
+ `;
@@ -0,0 +1,46 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import * as presentation from './todo-row-presentation.js';
3
+ import { styles } from './todo-row.css.js';
4
+ import type { Entity } from "@adobe/data/ecs";
5
+ import { customElement, property } from 'lit/decorators.js';
6
+
7
+ import { useObservableValues } from "@adobe/data-lit";
8
+ import { TodoElement } from '../../todo-element.js';
9
+
10
+ export const tagName = 'data-todo-row';
11
+
12
+ declare global {
13
+ interface HTMLElementTagNameMap {
14
+ [tagName]: TodoRow;
15
+ }
16
+ }
17
+
18
+ @customElement(tagName)
19
+ export class TodoRow extends TodoElement {
20
+ static styles = styles;
21
+
22
+ @property({ type: Number })
23
+ entity!: Entity;
24
+
25
+ @property({ type: Number })
26
+ index!: number;
27
+
28
+ render() {
29
+ const localized = { toggleComplete: 'Toggle complete', deleteTodo: 'Delete' } as const;
30
+ const values = useObservableValues(() => ({
31
+ todo: this.service.state.observe.entity(this.entity, this.service.state.archetypes.Todo),
32
+ }));
33
+
34
+ if (!values || !values.todo) return;
35
+
36
+ return presentation.render({
37
+ ...values,
38
+ localized,
39
+ todo: values.todo,
40
+ toggleComplete: () => this.service.state.transactions.toggleComplete(this.entity),
41
+ deleteTodo: () => this.service.state.transactions.deleteTodo(this.entity),
42
+ dragTodo: this.service.state.transactions.dragTodo,
43
+ index: this.index,
44
+ });
45
+ }
46
+ }
@@ -0,0 +1,2 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ export * from './todo-toolbar.js';
@@ -0,0 +1,55 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { html } from 'lit';
3
+
4
+ import '../todo-undo-redo/index.js';
5
+ import '@spectrum-web-components/action-button/sp-action-button.js';
6
+
7
+ // Temporarily disable localization for the sample
8
+ // import { Localized, Unlocalized } from '../../../../services/locale-service/locale-service.js';
9
+
10
+ // Simplified localization for sample - using static strings
11
+ const localizedStrings = {
12
+ add1Todo: 'Add 1 Todo',
13
+ add10Todos: 'Add 10 Todos',
14
+ add1000Todos: 'Add 1000 Todos',
15
+ clearCompleted: 'Clear Completed',
16
+ toggleAll: 'Toggle All',
17
+ todoCount: 'todos',
18
+ completedCount: 'completed',
19
+ } as const;
20
+
21
+ type RenderArgs = {
22
+ localized: typeof localizedStrings;
23
+ todoCount: number;
24
+ completedCount: number;
25
+ isGenerating: boolean;
26
+ createBulkTodos: (count: number) => void;
27
+ clearCompleted: () => void;
28
+ toggleAll: () => void;
29
+ };
30
+
31
+ export function render(args: RenderArgs) {
32
+ const { localized, todoCount, completedCount, isGenerating, createBulkTodos, clearCompleted, toggleAll } = args;
33
+
34
+ return html`
35
+ <div class="todo-toolbar">
36
+ <div class="toolbar-left">
37
+ <data-todo-undo-redo></data-todo-undo-redo>
38
+ <sp-action-button @click=${toggleAll} ?disabled=${isGenerating} quiet> ${localized.toggleAll} </sp-action-button>
39
+ </div>
40
+
41
+ <div class="toolbar-center">
42
+ <sp-action-button @click=${() => createBulkTodos(1)} ?disabled=${isGenerating}> ${localized.add1Todo} </sp-action-button>
43
+ <sp-action-button @click=${() => createBulkTodos(10)} ?disabled=${isGenerating}> ${localized.add10Todos} </sp-action-button>
44
+ <sp-action-button @click=${() => createBulkTodos(1000)} ?disabled=${isGenerating}> ${localized.add1000Todos} </sp-action-button>
45
+ </div>
46
+
47
+ <div class="toolbar-right">
48
+ <sp-action-button @click=${clearCompleted} ?disabled=${completedCount === 0 || isGenerating} quiet>
49
+ ${localized.clearCompleted}
50
+ </sp-action-button>
51
+ <span class="todo-stats"> ${completedCount} / ${todoCount} </span>
52
+ </div>
53
+ </div>
54
+ `;
55
+ }
@@ -0,0 +1,34 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { css } from 'lit';
3
+
4
+ export const styles = css`
5
+ .todo-toolbar {
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: space-between;
9
+ padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
10
+ background-color: var(--spectrum-gray-100);
11
+ border-bottom: 1px solid var(--spectrum-gray-300);
12
+ gap: var(--spectrum-spacing-200);
13
+ }
14
+
15
+ .toolbar-left,
16
+ .toolbar-center,
17
+ .toolbar-right {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--spectrum-spacing-100);
21
+ }
22
+
23
+ .toolbar-center {
24
+ flex: 1;
25
+ justify-content: center;
26
+ }
27
+
28
+ .todo-stats {
29
+ font-size: var(--spectrum-font-size-100);
30
+ color: var(--spectrum-gray-600);
31
+ margin-left: var(--spectrum-spacing-200);
32
+ width: 100px;
33
+ }
34
+ `;
@@ -0,0 +1,62 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import * as presentation from './todo-toolbar-presentation.js';
3
+ import { styles } from './todo-toolbar.css.js';
4
+ import { Observe } from "@adobe/data/observe";
5
+ import { customElement } from 'lit/decorators.js';
6
+ import { css } from 'lit';
7
+
8
+ import { useObservableValues } from "@adobe/data-lit";
9
+ import { TodoElement } from '../../todo-element.js';
10
+
11
+ export const tagName = 'data-todo-toolbar';
12
+
13
+ declare global {
14
+ interface HTMLElementTagNameMap {
15
+ [tagName]: TodoToolbar;
16
+ }
17
+ }
18
+
19
+ @customElement(tagName)
20
+ export class TodoToolbar extends TodoElement {
21
+ static styles = [
22
+ styles,
23
+ css`
24
+ :host {
25
+ display: block;
26
+ flex-shrink: 0;
27
+ width: 100%;
28
+ }
29
+ `
30
+ ];
31
+
32
+ render() {
33
+ const localized = {
34
+ add1Todo: 'Add 1 Todo',
35
+ add10Todos: 'Add 10 Todos',
36
+ add1000Todos: 'Add 1000 Todos',
37
+ clearCompleted: 'Clear Completed',
38
+ toggleAll: 'Toggle All',
39
+ todoCount: 'todos',
40
+ completedCount: 'completed',
41
+ } as const;
42
+ const values = useObservableValues(() => ({
43
+ completedCount: Observe.withMap(this.service.dependentState.completeTodos, (todos: unknown) => (todos as { length: number }).length),
44
+ todoCount: Observe.withMap(this.service.dependentState.allTodos, (todos: unknown) => (todos as { length: number }).length),
45
+ }));
46
+
47
+ if (!values) return;
48
+
49
+ return presentation.render({
50
+ ...values,
51
+ localized,
52
+ isGenerating: false,
53
+ createBulkTodos: this.service.state.transactions.createBulkTodos,
54
+ clearCompleted: () => {
55
+ // Placeholder - would need to implement this transaction
56
+ },
57
+ toggleAll: () => {
58
+ // Placeholder - would need to implement this transaction
59
+ },
60
+ });
61
+ }
62
+ }
@@ -0,0 +1,3 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+
3
+ export * from './todo-undo-redo.js';
@@ -0,0 +1,41 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { html } from 'lit';
3
+
4
+ import '@spectrum-web-components/action-button/sp-action-button.js';
5
+ import '@spectrum-web-components/action-group/sp-action-group.js';
6
+ import '@spectrum-web-components/icons-workflow/icons/sp-icon-redo.js';
7
+ import '@spectrum-web-components/icons-workflow/icons/sp-icon-undo.js';
8
+
9
+ // Temporarily disable localization for the sample
10
+ // import { Localized, Unlocalized } from '../../../../services/locale-service/locale-service.js';
11
+
12
+ // Simplified localization for sample - using static strings
13
+ const localizedStrings = {
14
+ undo: 'Undo',
15
+ redo: 'Redo',
16
+ } as const;
17
+
18
+ type RenderArgs = {
19
+ localized: typeof localizedStrings;
20
+ hasUndo: boolean;
21
+ hasRedo: boolean;
22
+ undo: () => void;
23
+ redo: () => void;
24
+ };
25
+
26
+ export function render(args: RenderArgs) {
27
+ const { localized, hasUndo, hasRedo, undo, redo } = args;
28
+
29
+ return html`
30
+ <sp-action-group>
31
+ <sp-action-button @click=${undo} ?disabled=${!hasUndo} quiet>
32
+ <sp-icon-undo slot="icon"></sp-icon-undo>
33
+ ${localized.undo}
34
+ </sp-action-button>
35
+ <sp-action-button @click=${redo} ?disabled=${!hasRedo} quiet>
36
+ <sp-icon-redo slot="icon"></sp-icon-redo>
37
+ ${localized.redo}
38
+ </sp-action-button>
39
+ </sp-action-group>
40
+ `;
41
+ }
@@ -0,0 +1,12 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { css } from 'lit';
3
+
4
+ export const styles = css`
5
+ sp-action-group {
6
+ gap: var(--spectrum-global-dimension-size-100);
7
+ }
8
+
9
+ sp-action-button {
10
+ min-width: var(--spectrum-global-dimension-size-300);
11
+ }
12
+ `;
@@ -0,0 +1,37 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import * as presentation from './todo-undo-redo-presentation.js';
3
+ import { styles } from './todo-undo-redo.css.js';
4
+ import { customElement } from 'lit/decorators.js';
5
+
6
+ import { useObservableValues } from "@adobe/data-lit";
7
+ import { TodoElement } from '../../todo-element.js';
8
+
9
+ export const tagName = 'data-todo-undo-redo';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ [tagName]: TodoUndoRedo;
14
+ }
15
+ }
16
+
17
+ @customElement(tagName)
18
+ export class TodoUndoRedo extends TodoElement {
19
+ static styles = styles;
20
+
21
+ render() {
22
+ const localized = { undo: 'Undo', redo: 'Redo' } as const;
23
+ const values = useObservableValues(() => ({
24
+ hasUndo: this.service.undoRedo.undoEnabled,
25
+ hasRedo: this.service.undoRedo.redoEnabled,
26
+ }));
27
+
28
+ if (!values) return;
29
+
30
+ return presentation.render({
31
+ ...values,
32
+ localized,
33
+ undo: this.service.undoRedo.undo,
34
+ redo: this.service.undoRedo.redo,
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,9 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+
3
+ export type { SampleMetadata, Sample } from "./sample-types.js";
4
+
5
+ import type { Sample } from "./sample-types.js";
6
+ import { todoSample } from "./todo-sample.js";
7
+ import "./todo-host.js"; // Ensure todo-host is registered
8
+
9
+ export const samples: readonly Sample[] = [todoSample];
@@ -0,0 +1,29 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+
3
+ import "@spectrum-web-components/theme/sp-theme.js";
4
+ import "@spectrum-web-components/theme/theme-light.js";
5
+ import "@spectrum-web-components/theme/scale-medium.js";
6
+ import "@spectrum-web-components/styles/all-medium-light.css";
7
+ import { samples } from "./index.js";
8
+
9
+ const app = document.getElementById("app");
10
+ if (app) {
11
+ app.innerHTML = samples
12
+ .map(
13
+ (s) =>
14
+ `<div style="margin-bottom: 1rem;">
15
+ <h2>${s.title}</h2>
16
+ <p>${s.description}</p>
17
+ <div id="sample-${s.id}"></div>
18
+ </div>`
19
+ )
20
+ .join("");
21
+
22
+ samples.forEach((s) => {
23
+ const container = document.getElementById(`sample-${s.id}`);
24
+ if (container) {
25
+ const el = document.createElement(s.elementTag);
26
+ container.appendChild(el);
27
+ }
28
+ });
29
+ }
@@ -0,0 +1,14 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+
3
+ export interface SampleMetadata {
4
+ readonly id: string;
5
+ readonly title: string;
6
+ readonly description: string;
7
+ readonly category: string;
8
+ readonly difficulty: "beginner" | "intermediate" | "advanced";
9
+ readonly features: readonly string[];
10
+ }
11
+
12
+ export interface Sample extends SampleMetadata {
13
+ readonly elementTag: string;
14
+ }
@@ -0,0 +1,8 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { applyArg } from "@adobe/data/functions";
3
+
4
+ import * as dependentState from './dependent-state/index.js';
5
+
6
+ import { TodoCoreService } from '../main-service/todo-main-service.js';
7
+
8
+ export const createDependentStateService = (service: TodoCoreService) => applyArg(service, dependentState);
@@ -0,0 +1,5 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { TodoCoreService } from '../../main-service/todo-main-service.js';
3
+
4
+ export const allTodos = (service: TodoCoreService) =>
5
+ service.state.observe.select(service.state.archetypes.Todo.components, { order: { order: true } });
@@ -0,0 +1,5 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { TodoCoreService } from '../../main-service/todo-main-service.js';
3
+
4
+ export const completeTodos = (service: TodoCoreService) =>
5
+ service.state.observe.select(service.state.archetypes.Todo.components, { where: { complete: true } });
@@ -0,0 +1,5 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { TodoCoreService } from '../../main-service/todo-main-service.js';
3
+
4
+ export const incompleteTodos = (service: TodoCoreService) =>
5
+ service.state.observe.select(service.state.archetypes.Todo.components, { where: { complete: false } });
@@ -0,0 +1,4 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ export * from './all-todos.js';
3
+ export * from './complete-todos.js';
4
+ export * from './incomplete-todos.js';
@@ -0,0 +1,4 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { createDependentStateService } from './create-dependent-state-service.js';
3
+
4
+ export type DependentStateService = ReturnType<typeof createDependentStateService>;
@@ -0,0 +1,53 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { TodoCoreService, TodoMainService } from './todo-main-service.js';
3
+ import { createStoragePersistenceService, createUndoRedoService } from "@adobe/data/ecs";
4
+ import { createDependentStateService } from '../dependent-state-service/create-dependent-state-service.js';
5
+ import { createTodoDatabase } from '../state-service/create-todo-database.js';
6
+ import { todoStoreSchemaVersion } from '../state-service/create-todo-store.js';
7
+ import { TodoStateService } from '../state-service/todo-state-service.js';
8
+
9
+ /**
10
+ * Initializes any core services and returns a new todo main service.
11
+ */
12
+ export async function createMainService(services: {
13
+ state?: TodoStateService;
14
+ } = {}): Promise<TodoMainService> {
15
+ {
16
+ const {
17
+ state = createTodoDatabase(),
18
+ ...rest
19
+ } = services;
20
+
21
+ state.transactions.createTodo({ name: 'Buy groceries' });
22
+ state.transactions.createTodo({ name: 'Pickup dry cleaning' });
23
+ state.transactions.createTodo({ name: 'Buy flowers', complete: true });
24
+
25
+ const persistence = await createStoragePersistenceService({
26
+ database: state,
27
+ storage: sessionStorage,
28
+ defaultFileId: `todo-database-v${todoStoreSchemaVersion}`,
29
+ autoSaveOnChange: true,
30
+ autoLoadOnStart: true,
31
+ });
32
+
33
+ // Create the undo-redo actions
34
+ const undoRedo = createUndoRedoService(state);
35
+
36
+ // The core service is what we call the service without the dependent state service
37
+ const coreService = {
38
+ serviceName: 'todo-core-service' as const,
39
+ ...rest,
40
+ state,
41
+ undoRedo,
42
+ persistence,
43
+ } satisfies TodoCoreService;
44
+
45
+ // We create the dependent state from the core service.
46
+ const dependentState = createDependentStateService(coreService);
47
+
48
+ return {
49
+ ...coreService,
50
+ dependentState,
51
+ } satisfies TodoMainService;
52
+ }
53
+ }
@@ -0,0 +1,20 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { PersistenceService, UndoRedoService } from "@adobe/data/ecs";
3
+ import { Service } from "@adobe/data/service";
4
+ import { DependentStateService } from '../dependent-state-service/dependent-state-service.js';
5
+ import { TodoStateService } from '../state-service/todo-state-service.js';
6
+
7
+ export interface TodoMainService extends Service {
8
+ readonly serviceName: string;
9
+ state: TodoStateService;
10
+ dependentState: DependentStateService;
11
+ undoRedo: UndoRedoService;
12
+ persistence: PersistenceService;
13
+ }
14
+
15
+ export type TodoCoreService = Omit<TodoMainService, 'dependentState'>;
16
+
17
+ /**
18
+ * The main service as used by the UI. We only allow access to the observe and actions properties.
19
+ */
20
+ export type TodoUIMainService = Omit<TodoMainService, 'state'> & { state: Omit<TodoStateService, 'resources'> };
@@ -0,0 +1,16 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { todoStoreSchema } from './create-todo-store.js';
3
+ import { Database } from "@adobe/data/ecs";
4
+
5
+ import * as transactions from './transactions/index.js';
6
+
7
+ export const createTodoDatabase = () => {
8
+ return Database.create(Database.Plugin.create({
9
+ components: todoStoreSchema.components,
10
+ resources: todoStoreSchema.resources,
11
+ archetypes: todoStoreSchema.archetypes,
12
+ transactions,
13
+ }));
14
+ };
15
+
16
+ export type TodoDatabase = ReturnType<typeof createTodoDatabase>;
@@ -0,0 +1,28 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { Store } from "@adobe/data/ecs";
3
+ import { F32, True, Schema } from "@adobe/data/schema";
4
+
5
+ // Increment this value if you change the schema in a non-backwards compatible way
6
+ export const todoStoreSchemaVersion = 1;
7
+
8
+ export const todoStoreSchema = {
9
+ components: {
10
+ todo: True.schema, // a tag that indicates an entity is a todo item.
11
+ complete: { type: 'boolean' as const },
12
+ name: { type: 'string' as const },
13
+ order: F32.schema,
14
+ dragPosition: Schema.Nullable(F32.schema), // null = not being dragged
15
+ },
16
+ resources: {
17
+ displayCompleted: { type: 'boolean' as const, default: false },
18
+ },
19
+ archetypes: {
20
+ Todo: ['todo', 'complete', 'name', 'order', 'dragPosition'],
21
+ }
22
+ } as const;
23
+
24
+ export const createTodoStore = () => {
25
+ return Store.create(todoStoreSchema);
26
+ };
27
+
28
+ export type TodoStore = ReturnType<typeof createTodoStore>;
@@ -0,0 +1,9 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { type TodoDatabase } from './create-todo-database.js';
3
+ import { FromArchetype } from "@adobe/data/ecs";
4
+
5
+ export type TodoStateService = TodoDatabase;
6
+
7
+ export type Todo = FromArchetype<TodoDatabase['archetypes']['Todo']>;
8
+
9
+ export type DragTodoFunction = TodoStateService['transactions']['dragTodo'];
@@ -0,0 +1,12 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { createTodo } from './create-todo.js';
3
+
4
+ import { type TodoStore } from '../create-todo-store.js';
5
+
6
+ export const createBulkTodos = (t: TodoStore, count: number) => {
7
+ t.undoable = { coalesce: false };
8
+ const currentCount = t.archetypes.Todo.rowCount;
9
+ for (let i = 0; i < count; i++) {
10
+ createTodo(t, { name: `Todo ${currentCount + i}`, complete: false });
11
+ }
12
+ };
@@ -0,0 +1,17 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { createTodo } from './create-todo.js';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ import { createTodoStore } from '../create-todo-store.js';
6
+
7
+ describe('createTodo', () => {
8
+ describe('when creating a new todo', () => {
9
+ it('should return the created todo entity id and create the todo', () => {
10
+ const t = createTodoStore();
11
+ const todoId = createTodo(t, { name: 'Buy groceries' });
12
+ expect(todoId).toBeGreaterThanOrEqual(0);
13
+ const values = t.read(todoId);
14
+ expect(values).toEqual({ id: todoId, name: 'Buy groceries', dragPosition: null, complete: false, todo: true, order: 0 });
15
+ });
16
+ });
17
+ });
@@ -0,0 +1,15 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { type TodoStore } from '../create-todo-store.js';
3
+
4
+ export const createTodo = (t: TodoStore, props: { name: string; complete?: boolean }) => {
5
+ t.undoable = { coalesce: false };
6
+ const order = t.archetypes.Todo.rowCount;
7
+ // TODO: Figure out why the order seems to be zero on each added row.
8
+ return t.archetypes.Todo.insert({
9
+ ...props,
10
+ complete: props.complete ?? false,
11
+ todo: true,
12
+ order,
13
+ dragPosition: null,
14
+ });
15
+ };
@@ -0,0 +1,18 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { type TodoStore } from '../create-todo-store.js';
3
+
4
+ export const deleteAllTodos = (t: TodoStore) => {
5
+ t.undoable = { coalesce: false };
6
+ // query for all specific archetypes which satisfy the general todo archetype
7
+ for (const archetype of t.queryArchetypes(t.archetypes.Todo.components)) {
8
+ // traverse each row in reverse order
9
+ // it's slightly more efficient to delete in this order
10
+ // since we don't need to swap the final row to fill in the hole on delete.
11
+ for (let row = archetype.rowCount - 1; row >= 0; row--) {
12
+ // get the id for this row from the id column
13
+ const entityId = archetype.columns.id.get(row);
14
+ // delete the entity
15
+ t.delete(entityId);
16
+ }
17
+ }
18
+ };