@ankhorage/zora 25.5.0 → 25.6.2

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 (106) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -1
  3. package/dist/capabilities/index.d.ts +2 -74
  4. package/dist/capabilities/index.d.ts.map +1 -1
  5. package/dist/capabilities/index.js +6158 -59
  6. package/dist/capabilities/index.js.map +118 -1
  7. package/dist/cli/index.d.ts +2 -74
  8. package/dist/cli/index.d.ts.map +1 -1
  9. package/dist/cli/index.js +2 -1
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/features/grid-view/adapters/inbound/GridView.d.ts +2 -7
  12. package/dist/features/grid-view/adapters/inbound/GridView.d.ts.map +1 -1
  13. package/dist/features/grid-view/adapters/inbound/GridView.js +309 -51
  14. package/dist/features/grid-view/adapters/inbound/GridView.js.map +1 -1
  15. package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts +1 -1
  16. package/dist/features/grid-view/adapters/inbound/TileGrid.d.ts.map +1 -1
  17. package/dist/features/grid-view/adapters/inbound/TileGrid.js +11 -4
  18. package/dist/features/grid-view/adapters/inbound/TileGrid.js.map +1 -1
  19. package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.d.ts +5 -0
  20. package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.d.ts.map +1 -0
  21. package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.js +59 -0
  22. package/dist/features/matrix-grid/adapters/inbound/MatrixGrid.js.map +1 -0
  23. package/dist/features/matrix-grid/application/resolveMatrixGridContentSize.d.ts +7 -0
  24. package/dist/features/matrix-grid/application/resolveMatrixGridContentSize.d.ts.map +1 -0
  25. package/dist/features/matrix-grid/application/resolveMatrixGridContentSize.js +24 -0
  26. package/dist/features/matrix-grid/application/resolveMatrixGridContentSize.js.map +1 -0
  27. package/dist/features/matrix-grid/application/resolveMatrixGridSelection.d.ts +5 -0
  28. package/dist/features/matrix-grid/application/resolveMatrixGridSelection.d.ts.map +1 -0
  29. package/dist/features/matrix-grid/application/resolveMatrixGridSelection.js +8 -0
  30. package/dist/features/matrix-grid/application/resolveMatrixGridSelection.js.map +1 -0
  31. package/dist/features/matrix-grid/meta.d.ts +11 -0
  32. package/dist/features/matrix-grid/meta.d.ts.map +1 -0
  33. package/dist/features/matrix-grid/meta.js +11 -0
  34. package/dist/features/matrix-grid/meta.js.map +1 -0
  35. package/dist/features/matrix-grid/public.d.ts +4 -0
  36. package/dist/features/matrix-grid/public.d.ts.map +1 -0
  37. package/dist/features/matrix-grid/public.js +3 -0
  38. package/dist/features/matrix-grid/public.js.map +1 -0
  39. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.d.ts.map +1 -1
  40. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js +2 -0
  41. package/dist/features/registry/ZORA_COMPONENT_REGISTRY.js.map +1 -1
  42. package/dist/features/registry/componentMeta.d.ts.map +1 -1
  43. package/dist/features/registry/componentMeta.js +2 -0
  44. package/dist/features/registry/componentMeta.js.map +1 -1
  45. package/dist/features/registry/createEventCapabilities.d.ts +4 -0
  46. package/dist/features/registry/createEventCapabilities.d.ts.map +1 -0
  47. package/dist/features/registry/createEventCapabilities.js +76 -0
  48. package/dist/features/registry/createEventCapabilities.js.map +1 -0
  49. package/dist/index.d.ts +2 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/types/grid-view.d.ts +18 -1
  54. package/dist/types/grid-view.d.ts.map +1 -1
  55. package/dist/types/grid-view.js.map +1 -1
  56. package/dist/types/matrix-grid.d.ts +23 -0
  57. package/dist/types/matrix-grid.d.ts.map +1 -0
  58. package/dist/types/matrix-grid.js +2 -0
  59. package/dist/types/matrix-grid.js.map +1 -0
  60. package/package.json +1822 -4
  61. package/src/capabilities/index.test.ts +87 -15
  62. package/src/capabilities/index.ts +5 -2
  63. package/src/cli/index.test.ts +5 -3
  64. package/src/cli/index.ts +5 -2
  65. package/src/features/grid-view/adapters/inbound/GridView.interaction.test.tsx +585 -0
  66. package/src/features/grid-view/adapters/inbound/GridView.test.tsx +74 -0
  67. package/src/features/grid-view/adapters/inbound/GridView.tsx +506 -77
  68. package/src/features/grid-view/adapters/inbound/TileGrid.tsx +26 -3
  69. package/src/features/matrix-grid/adapters/inbound/MatrixGrid.test.tsx +232 -0
  70. package/src/features/matrix-grid/adapters/inbound/MatrixGrid.tsx +142 -0
  71. package/src/features/matrix-grid/application/resolveMatrixGridContentSize.test.ts +32 -0
  72. package/src/features/matrix-grid/application/resolveMatrixGridContentSize.ts +28 -0
  73. package/src/features/matrix-grid/application/resolveMatrixGridSelection.test.ts +10 -0
  74. package/src/features/matrix-grid/application/resolveMatrixGridSelection.ts +15 -0
  75. package/src/features/matrix-grid/application/resolveMatrixGridVisibleCells.test.ts +35 -0
  76. package/src/features/matrix-grid/meta.ts +12 -0
  77. package/src/features/matrix-grid/public.ts +3 -0
  78. package/src/features/registry/ZORA_COMPONENT_REGISTRY.ts +2 -0
  79. package/src/features/registry/componentMeta.ts +2 -0
  80. package/src/features/registry/createEventCapabilities.ts +108 -0
  81. package/src/features/time-grid/adapters/inbound/TimeGrid.test.tsx +35 -8
  82. package/src/index.ts +2 -0
  83. package/src/structureOwnership.test.ts +5 -0
  84. package/src/types/grid-view.ts +27 -1
  85. package/src/types/matrix-grid.ts +29 -0
  86. package/web-dist/chunks/{Accordion-d6azgz09.js → Accordion-2r0gqk3x.js} +1 -1
  87. package/web-dist/chunks/Accordion-a6551mh4.js +515 -0
  88. package/web-dist/chunks/{Accordion-0my2z6qe.js → Accordion-bz04casa.js} +132 -3
  89. package/web-dist/chunks/{Accordion-7qfd4cb4.js → Accordion-jh72azm2.js} +1 -1
  90. package/web-dist/components/explorer/Explorer.js +2 -2
  91. package/web-dist/components/file-explorer/FileExplorer.js +2 -2
  92. package/web-dist/components/grid-line-overlay/GridLineOverlay.js +1 -1
  93. package/web-dist/components/grid-ruler/GridRuler.js +1 -1
  94. package/web-dist/components/grid-view/GridView.js +1 -1
  95. package/web-dist/components/matrix-grid/MatrixGrid.d.ts +3 -0
  96. package/web-dist/components/matrix-grid/MatrixGrid.js +153 -0
  97. package/web-dist/components/matrix-grid/index.d.ts +1 -0
  98. package/web-dist/components/matrix-grid/index.js +2 -0
  99. package/web-dist/components/media-explorer/MediaExplorer.js +2 -2
  100. package/web-dist/components/reader/Reader.js +1 -1
  101. package/web-dist/components/spatial-grid/SpatialGrid.js +1 -1
  102. package/web-dist/components/tile-grid/TileGrid.js +1 -1
  103. package/web-dist/components/time-grid/TimeGrid.js +2 -2
  104. package/web-dist/components/uploader/Uploader.js +2 -2
  105. package/web-dist/manifest.json +53 -24
  106. package/web-dist/chunks/Accordion-gxj5qbpr.js +0 -194
@@ -1,9 +1,11 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
 
3
- import { isCapability } from '@ankhorage/contracts/capabilities';
3
+ import { isCapability, isCapabilityId } from '@ankhorage/capability';
4
+ import type { Capability } from '@ankhorage/contracts/capability';
4
5
  import { isRecord } from '@ankhorage/utility/object';
5
6
  import { expect, test } from 'bun:test';
6
7
 
8
+ import { ZORA_COMPONENT_META } from '../features/registry';
7
9
  import { CAPABILITIES } from './index';
8
10
 
9
11
  const packageJson: unknown = JSON.parse(
@@ -13,11 +15,66 @@ const packageCapabilities =
13
15
  isRecord(packageJson) && isRecord(packageJson.ankh) ? packageJson.ankh.capabilities : undefined;
14
16
 
15
17
  test('publishes valid, uniquely identified canonical ZORA capabilities', () => {
16
- expect(CAPABILITIES).toHaveLength(2);
17
18
  expect(CAPABILITIES.every(isCapability)).toBe(true);
18
19
  expect(new Set(CAPABILITIES.map((capability) => capability.id)).size).toBe(CAPABILITIES.length);
19
20
  });
20
21
 
22
+ test('projects each direct-manifest event metadata entry into one canonical event capability', () => {
23
+ const metadataEvents = Object.values(ZORA_COMPONENT_META)
24
+ .filter((component) => component.directManifestNode)
25
+ .flatMap((component) => Object.values(component.events ?? {}));
26
+ const eventCapabilities = CAPABILITIES.filter((capability) => capability.access.includes('emit'));
27
+
28
+ expect(eventCapabilities).toHaveLength(
29
+ new Set(metadataEvents.map((event) => event.eventType)).size,
30
+ );
31
+ const eventCapabilitiesById = new Map<Capability['id'], Capability>(
32
+ eventCapabilities.map((capability) => [capability.id, capability]),
33
+ );
34
+
35
+ for (const event of metadataEvents) {
36
+ if (!isCapabilityId(event.eventType)) throw new Error(`Invalid event id: ${event.eventType}`);
37
+ const capability = eventCapabilitiesById.get(event.eventType);
38
+ expect(capability?.owner).toBe('@ankhorage/zora');
39
+ expect(capability?.access).toEqual(['emit']);
40
+ expect(capability?.binding).toEqual({ kind: 'event', bindableAs: ['source'] });
41
+ expect(capability?.label).toBe(event.label);
42
+ expect(capability?.description).toBe(event.description);
43
+ }
44
+ });
45
+
46
+ test('projects event payload metadata into matching output schemas', () => {
47
+ const eventCapabilities = new Map<Capability['id'], Capability>(
48
+ CAPABILITIES.filter((capability) => capability.access.includes('emit')).map((capability) => [
49
+ capability.id,
50
+ capability,
51
+ ]),
52
+ );
53
+
54
+ for (const component of Object.values(ZORA_COMPONENT_META)) {
55
+ if (!component.directManifestNode) continue;
56
+ for (const event of Object.values(component.events ?? {})) {
57
+ if (!isCapabilityId(event.eventType)) throw new Error(`Invalid event id: ${event.eventType}`);
58
+ const capability = eventCapabilities.get(event.eventType);
59
+ const schema = capability?.output?.schema;
60
+ expect(schema?.type).toBe('object');
61
+
62
+ for (const field of event.payloadFields ?? []) {
63
+ if (field.path.includes('.')) continue;
64
+ const fieldSchema = Object.entries(schema?.properties ?? {}).find(
65
+ ([fieldName]) => fieldName === field.path,
66
+ )?.[1];
67
+ expect(fieldSchema?.type).toBe(
68
+ field.type === 'record' ? 'object' : field.type === 'unknown' ? undefined : field.type,
69
+ );
70
+ expect(fieldSchema?.additionalProperties).toBe(field.type === 'record' ? true : undefined);
71
+ expect(fieldSchema?.title).toBe(field.label);
72
+ expect(fieldSchema?.description).toBe(field.description);
73
+ }
74
+ }
75
+ }
76
+ });
77
+
21
78
  test('keeps Ankh package metadata identical to the canonical catalog', () => {
22
79
  expect(Array.isArray(packageCapabilities)).toBe(true);
23
80
  if (!Array.isArray(packageCapabilities)) {
@@ -37,18 +94,33 @@ test('exports the catalog from the public capabilities subpath', async () => {
37
94
  });
38
95
 
39
96
  test('preserves the executable action semantics of ZORA provider capabilities', () => {
40
- expect(CAPABILITIES).toEqual([
41
- expect.objectContaining({
42
- id: 'zora.create',
43
- owner: '@ankhorage/zora',
44
- access: ['invoke'],
45
- binding: { kind: 'action', bindableAs: ['target'] },
46
- }),
47
- expect.objectContaining({
48
- id: 'zora.sync',
49
- owner: '@ankhorage/zora',
50
- access: ['invoke'],
51
- binding: { kind: 'action', bindableAs: ['target'] },
52
- }),
97
+ const actions = CAPABILITIES.filter((capability) => capability.access.includes('invoke'));
98
+ expect(actions.map((capability) => capability.id)).toEqual(['zora.create', 'zora.sync']);
99
+ expect(actions.every((capability) => capability.binding.kind === 'action')).toBe(true);
100
+ expect(actions.every((capability) => capability.binding.bindableAs.includes('target'))).toBe(
101
+ true,
102
+ );
103
+ });
104
+
105
+ test('built public capability entrypoint imports under Node ESM', async () => {
106
+ const subprocess = Bun.spawn(
107
+ [
108
+ 'node',
109
+ '--input-type=module',
110
+ '-e',
111
+ "import('./dist/capabilities/index.js').then(({ CAPABILITIES }) => { if (!Array.isArray(CAPABILITIES)) process.exit(1); });",
112
+ ],
113
+ {
114
+ cwd: process.cwd(),
115
+ stderr: 'pipe',
116
+ stdout: 'pipe',
117
+ },
118
+ );
119
+ const [exitCode, stderr] = await Promise.all([
120
+ subprocess.exited,
121
+ new Response(subprocess.stderr).text(),
53
122
  ]);
123
+
124
+ expect(stderr).toBe('');
125
+ expect(exitCode).toBe(0);
54
126
  });
@@ -1,4 +1,6 @@
1
- import type { Capability } from '@ankhorage/contracts/capabilities';
1
+ import type { Capability } from '@ankhorage/contracts/capability';
2
+
3
+ import { createEventCapabilities } from '../features/registry/createEventCapabilities.js';
2
4
 
3
5
  export const CAPABILITIES = [
4
6
  {
@@ -60,4 +62,5 @@ export const CAPABILITIES = [
60
62
  },
61
63
  },
62
64
  },
63
- ] as const satisfies readonly Capability[];
65
+ ...createEventCapabilities(),
66
+ ] satisfies readonly Capability[];
@@ -6,7 +6,9 @@ import provider from './index';
6
6
  test('publishes ZORA create and sync through the Ankh provider', () => {
7
7
  expect(provider.id).toBe('@ankhorage/zora');
8
8
  expect(provider.category).toBe('zora');
9
- expect(provider.capabilities).toBe(CAPABILITIES);
9
+ expect(provider.capabilities).toEqual(
10
+ CAPABILITIES.filter((capability) => capability.access.includes('invoke')),
11
+ );
10
12
  expect(provider.commands).toEqual([
11
13
  {
12
14
  path: ['create'],
@@ -24,9 +26,9 @@ test('publishes ZORA create and sync through the Ankh provider', () => {
24
26
  expect(provider.handlers[1]?.path).toEqual(['sync']);
25
27
  });
26
28
 
27
- test('maps every provider command to one canonical capability independent of catalog order', () => {
29
+ test('maps every provider command to one executable canonical capability independent of catalog order', () => {
28
30
  const commandCapabilityIds = provider.commands.map((command) => command.capability);
29
- const capabilityIds = CAPABILITIES.map((capability) => capability.id);
31
+ const capabilityIds = provider.capabilities.map((capability) => capability.id);
30
32
 
31
33
  expect(new Set(commandCapabilityIds).size).toBe(commandCapabilityIds.length);
32
34
  expect(new Set(commandCapabilityIds)).toEqual(new Set(capabilityIds));
package/src/cli/index.ts CHANGED
@@ -3,7 +3,7 @@ import { dirname, resolve } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
 
5
5
  import type { AnkhRuntimeCommandProvider } from '@ankhorage/ankh';
6
- import type { Capability } from '@ankhorage/contracts/capabilities';
6
+ import type { Capability } from '@ankhorage/contracts/capability';
7
7
 
8
8
  import { CAPABILITIES } from '../capabilities';
9
9
  import { create } from './commands/create';
@@ -19,12 +19,15 @@ const SYNC_COMMAND = {
19
19
  capability: 'zora.sync' satisfies Capability['id'],
20
20
  summary: 'Regenerate the declared ZORA web materialization.',
21
21
  } as const;
22
+ const COMMAND_CAPABILITIES = CAPABILITIES.filter((capability) =>
23
+ capability.access.includes('invoke'),
24
+ );
22
25
 
23
26
  const provider = {
24
27
  id: '@ankhorage/zora',
25
28
  category: 'zora',
26
29
  version: readPackageVersion(),
27
- capabilities: CAPABILITIES,
30
+ capabilities: COMMAND_CAPABILITIES,
28
31
  commands: [CREATE_COMMAND, SYNC_COMMAND],
29
32
  handlers: [
30
33
  {