@ankhorage/zora 25.11.1 → 26.0.1

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 (97) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -4
  3. package/dist/capabilities/index.js +65 -41
  4. package/dist/capabilities/index.js.map +3 -3
  5. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts +1 -1
  6. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts.map +1 -1
  7. package/dist/features/chess/adapters/inbound/ChessBoard.js +130 -83
  8. package/dist/features/chess/adapters/inbound/ChessBoard.js.map +1 -1
  9. package/dist/features/chess/meta.d.ts +97 -72
  10. package/dist/features/chess/meta.d.ts.map +1 -1
  11. package/dist/features/chess/meta.js +64 -40
  12. package/dist/features/chess/meta.js.map +1 -1
  13. package/dist/features/chess/public.d.ts +1 -7
  14. package/dist/features/chess/public.d.ts.map +1 -1
  15. package/dist/features/chess/public.js +0 -6
  16. package/dist/features/chess/public.js.map +1 -1
  17. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts +6 -0
  18. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts.map +1 -0
  19. package/dist/features/chess/utils/createChessBoardCellPressHandler.js +17 -0
  20. package/dist/features/chess/utils/createChessBoardCellPressHandler.js.map +1 -0
  21. package/dist/features/chess/utils/createChessBoardCells.d.ts +12 -0
  22. package/dist/features/chess/utils/createChessBoardCells.d.ts.map +1 -0
  23. package/dist/features/chess/utils/createChessBoardCells.js +28 -0
  24. package/dist/features/chess/utils/createChessBoardCells.js.map +1 -0
  25. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js +2 -3
  26. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js.map +1 -1
  27. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.js +3 -1
  28. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.js.map +1 -1
  29. package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.d.ts +5 -5
  30. package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.d.ts.map +1 -1
  31. package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.js +13 -7
  32. package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.js.map +1 -1
  33. package/dist/readerFree.d.ts +2 -2
  34. package/dist/readerFree.d.ts.map +1 -1
  35. package/dist/readerFree.js +1 -1
  36. package/dist/readerFree.js.map +1 -1
  37. package/dist/types/authoring.d.ts +2 -1
  38. package/dist/types/authoring.d.ts.map +1 -1
  39. package/dist/types/authoring.js.map +1 -1
  40. package/dist/types/chess.d.ts +27 -20
  41. package/dist/types/chess.d.ts.map +1 -1
  42. package/dist/types/chess.js.map +1 -1
  43. package/package.json +34 -94
  44. package/src/features/chess/adapters/inbound/ChessBoard.tsx +263 -112
  45. package/src/features/chess/meta.ts +64 -40
  46. package/src/features/chess/public.test.tsx +77 -228
  47. package/src/features/chess/public.ts +2 -9
  48. package/src/features/chess/utils/createChessBoardCellPressHandler.ts +30 -0
  49. package/src/features/chess/utils/createChessBoardCells.ts +54 -0
  50. package/src/features/chessTabletopOwnership.test.ts +3 -7
  51. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphController.test.ts +1 -2
  52. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts +2 -3
  53. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.test.ts +45 -0
  54. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts +3 -1
  55. package/src/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.test.ts +65 -3
  56. package/src/features/graph-view/adapters/inbound/web-artifact/getGraphGeometryKey.ts +13 -7
  57. package/src/features/registry/componentMeta.test.ts +12 -1
  58. package/src/readerFree.ts +3 -15
  59. package/src/types/authoring.ts +2 -1
  60. package/src/types/chess.ts +28 -21
  61. package/web-dist/chunks/Accordion-91sjb3zh.js +453 -0
  62. package/web-dist/components/chess-board/ChessBoard.js +2 -1
  63. package/web-dist/components/graph-view/GraphView.js +878 -317
  64. package/web-dist/components/opening-book/OpeningBook.js +2 -1
  65. package/web-dist/manifest.json +8 -4
  66. package/dist/features/chess/utils/chessEngine.d.ts +0 -8
  67. package/dist/features/chess/utils/chessEngine.d.ts.map +0 -1
  68. package/dist/features/chess/utils/chessEngine.js +0 -71
  69. package/dist/features/chess/utils/chessEngine.js.map +0 -1
  70. package/dist/features/chess/utils/chessSquares.d.ts +0 -4
  71. package/dist/features/chess/utils/chessSquares.d.ts.map +0 -1
  72. package/dist/features/chess/utils/chessSquares.js +0 -3
  73. package/dist/features/chess/utils/chessSquares.js.map +0 -1
  74. package/dist/features/chess/utils/createBoardSquares.d.ts +0 -4
  75. package/dist/features/chess/utils/createBoardSquares.d.ts.map +0 -1
  76. package/dist/features/chess/utils/createBoardSquares.js +0 -9
  77. package/dist/features/chess/utils/createBoardSquares.js.map +0 -1
  78. package/dist/features/chess/utils/getSquareFile.d.ts +0 -4
  79. package/dist/features/chess/utils/getSquareFile.d.ts.map +0 -1
  80. package/dist/features/chess/utils/getSquareFile.js +0 -5
  81. package/dist/features/chess/utils/getSquareFile.js.map +0 -1
  82. package/dist/features/chess/utils/getSquareRank.d.ts +0 -4
  83. package/dist/features/chess/utils/getSquareRank.d.ts.map +0 -1
  84. package/dist/features/chess/utils/getSquareRank.js +0 -5
  85. package/dist/features/chess/utils/getSquareRank.js.map +0 -1
  86. package/dist/features/chess/utils/isLightSquare.d.ts +0 -4
  87. package/dist/features/chess/utils/isLightSquare.d.ts.map +0 -1
  88. package/dist/features/chess/utils/isLightSquare.js +0 -6
  89. package/dist/features/chess/utils/isLightSquare.js.map +0 -1
  90. package/src/features/chess/utils/chessEngine.test.ts +0 -35
  91. package/src/features/chess/utils/chessEngine.ts +0 -83
  92. package/src/features/chess/utils/chessSquares.ts +0 -6
  93. package/src/features/chess/utils/createBoardSquares.ts +0 -13
  94. package/src/features/chess/utils/getSquareFile.ts +0 -6
  95. package/src/features/chess/utils/getSquareRank.ts +0 -6
  96. package/src/features/chess/utils/isLightSquare.ts +0 -8
  97. package/web-dist/chunks/Accordion-xcm1qc39.js +0 -3813
@@ -6,42 +6,31 @@ export const chessBoardMeta = {
6
6
  allowedChildren: [],
7
7
  blueprint: {
8
8
  label: 'Chess board',
9
- defaultProps: { pieces: [], orientation: 'white', showCoordinates: true, validateMoves: true },
9
+ defaultProps: {
10
+ columns: 8,
11
+ pieces: [],
12
+ orientation: 'white',
13
+ rows: 8,
14
+ showCoordinates: true,
15
+ },
10
16
  },
11
17
  events: {
12
- squarePress: {
13
- label: 'Square press',
14
- eventType: 'chess.squarePress',
15
- payloadFields: [{ path: 'square', type: 'string', label: 'Square' }],
18
+ cellPress: {
19
+ label: 'Cell press',
20
+ eventType: 'chess.cellPress',
21
+ payloadFields: [
22
+ { path: 'column', type: 'number', label: 'Column' },
23
+ { path: 'row', type: 'number', label: 'Row' },
24
+ ],
16
25
  },
17
26
  moveAttempt: {
18
27
  label: 'Move attempt',
19
28
  eventType: 'chess.moveAttempt',
20
29
  payloadFields: [
21
- { path: 'from', type: 'string', label: 'From' },
22
- { path: 'to', type: 'string', label: 'To' },
23
- { path: 'promotion', type: 'string', label: 'Promotion' },
24
- ],
25
- },
26
- legalMove: {
27
- label: 'Legal move',
28
- eventType: 'chess.legalMove',
29
- payloadFields: [
30
- { path: 'from', type: 'string', label: 'From' },
31
- { path: 'to', type: 'string', label: 'To' },
32
- { path: 'fen', type: 'string', label: 'Position' },
33
- { path: 'san', type: 'string', label: 'SAN' },
34
- { path: 'lan', type: 'string', label: 'LAN' },
35
- { path: 'promotion', type: 'string', label: 'Promotion' },
36
- ],
37
- },
38
- invalidMove: {
39
- label: 'Invalid move',
40
- eventType: 'chess.invalidMove',
41
- payloadFields: [
42
- { path: 'from', type: 'string', label: 'From' },
43
- { path: 'to', type: 'string', label: 'To' },
44
- { path: 'promotion', type: 'string', label: 'Promotion' },
30
+ { path: 'from.column', type: 'number', label: 'From column' },
31
+ { path: 'from.row', type: 'number', label: 'From row' },
32
+ { path: 'to.column', type: 'number', label: 'To column' },
33
+ { path: 'to.row', type: 'number', label: 'To row' },
45
34
  ],
46
35
  },
47
36
  },
@@ -53,19 +42,46 @@ export const chessBoardMeta = {
53
42
  acceptsFallback: true,
54
43
  acceptsTransforms: true,
55
44
  },
45
+ selectedCell: {
46
+ label: 'Selected cell',
47
+ value: {
48
+ type: 'object',
49
+ fields: [
50
+ { path: 'column', type: 'number', label: 'Column' },
51
+ { path: 'row', type: 'number', label: 'Row' },
52
+ ],
53
+ },
54
+ acceptsFallback: true,
55
+ acceptsTransforms: true,
56
+ },
56
57
  legalTargets: {
57
58
  label: 'Legal targets',
58
- value: { type: 'array', itemType: 'string' },
59
+ value: {
60
+ type: 'array',
61
+ itemType: 'object',
62
+ fields: [
63
+ { path: '[].column', type: 'number', label: 'Column' },
64
+ { path: '[].row', type: 'number', label: 'Row' },
65
+ ],
66
+ },
59
67
  acceptsFallback: true,
60
68
  acceptsTransforms: true,
61
69
  },
62
70
  },
63
71
  },
64
72
  props: {
65
- fen: {
66
- type: 'string',
67
- category: 'Position',
68
- label: 'FEN',
73
+ columns: {
74
+ type: 'number',
75
+ category: 'Board',
76
+ label: 'Columns',
77
+ default: 8,
78
+ authoring: { authority: 'instance' },
79
+ },
80
+ rows: {
81
+ type: 'number',
82
+ category: 'Board',
83
+ label: 'Rows',
84
+ default: 8,
69
85
  authoring: { authority: 'instance' },
70
86
  },
71
87
  pieces: {
@@ -83,10 +99,14 @@ export const chessBoardMeta = {
83
99
  default: 'white',
84
100
  authoring: { authority: 'instance' },
85
101
  },
86
- selectedSquare: {
87
- type: 'string',
102
+ selectedCell: {
103
+ type: 'object',
88
104
  category: 'Board',
89
- label: 'Selected square',
105
+ label: 'Selected cell',
106
+ itemSchema: [
107
+ { key: 'column', schema: { type: 'number', category: 'Cell' } },
108
+ { key: 'row', schema: { type: 'number', category: 'Cell' } },
109
+ ],
90
110
  authoring: { authority: 'instance' },
91
111
  },
92
112
  legalTargets: {
@@ -94,6 +114,10 @@ export const chessBoardMeta = {
94
114
  category: 'Board',
95
115
  label: 'Legal targets',
96
116
  default: [],
117
+ itemSchema: [
118
+ { key: 'column', schema: { type: 'number', category: 'Cell' } },
119
+ { key: 'row', schema: { type: 'number', category: 'Cell' } },
120
+ ],
97
121
  authoring: { authority: 'instance' },
98
122
  },
99
123
  showCoordinates: {
@@ -103,11 +127,11 @@ export const chessBoardMeta = {
103
127
  default: false,
104
128
  authoring: { authority: 'instance' },
105
129
  },
106
- validateMoves: {
130
+ resizable: {
107
131
  type: 'boolean',
108
132
  category: 'Behavior',
109
- label: 'Validate moves',
110
- default: true,
133
+ label: 'Resizable',
134
+ default: false,
111
135
  authoring: { authority: 'instance' },
112
136
  },
113
137
  disabled: {
@@ -1 +1 @@
1
- {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/features/chess/meta.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ZoraComponentMeta } from '../../types/authoring';\n\nexport const chessBoardMeta = {\n name: 'ChessBoard',\n category: 'component',\n description:\n 'Renders caller-owned chess pieces, highlights, and move-attempt interactions without chess rules.',\n directManifestNode: true,\n allowedChildren: [],\n blueprint: {\n label: 'Chess board',\n defaultProps: { pieces: [], orientation: 'white', showCoordinates: true, validateMoves: true },\n },\n events: {\n squarePress: {\n label: 'Square press',\n eventType: 'chess.squarePress',\n payloadFields: [{ path: 'square', type: 'string', label: 'Square' }],\n },\n moveAttempt: {\n label: 'Move attempt',\n eventType: 'chess.moveAttempt',\n payloadFields: [\n { path: 'from', type: 'string', label: 'From' },\n { path: 'to', type: 'string', label: 'To' },\n { path: 'promotion', type: 'string', label: 'Promotion' },\n ],\n },\n legalMove: {\n label: 'Legal move',\n eventType: 'chess.legalMove',\n payloadFields: [\n { path: 'from', type: 'string', label: 'From' },\n { path: 'to', type: 'string', label: 'To' },\n { path: 'fen', type: 'string', label: 'Position' },\n { path: 'san', type: 'string', label: 'SAN' },\n { path: 'lan', type: 'string', label: 'LAN' },\n { path: 'promotion', type: 'string', label: 'Promotion' },\n ],\n },\n invalidMove: {\n label: 'Invalid move',\n eventType: 'chess.invalidMove',\n payloadFields: [\n { path: 'from', type: 'string', label: 'From' },\n { path: 'to', type: 'string', label: 'To' },\n { path: 'promotion', type: 'string', label: 'Promotion' },\n ],\n },\n },\n bindings: {\n props: {\n pieces: {\n label: 'Pieces',\n value: { type: 'array', itemType: 'object' },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n legalTargets: {\n label: 'Legal targets',\n value: { type: 'array', itemType: 'string' },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n },\n },\n props: {\n fen: {\n type: 'string',\n category: 'Position',\n label: 'FEN',\n authoring: { authority: 'instance' },\n },\n pieces: {\n type: 'array',\n category: 'Board',\n label: 'Pieces',\n default: [],\n authoring: { authority: 'instance' },\n },\n orientation: {\n type: 'enum',\n category: 'Board',\n label: 'Orientation',\n enum: ['white', 'black'],\n default: 'white',\n authoring: { authority: 'instance' },\n },\n selectedSquare: {\n type: 'string',\n category: 'Board',\n label: 'Selected square',\n authoring: { authority: 'instance' },\n },\n legalTargets: {\n type: 'array',\n category: 'Board',\n label: 'Legal targets',\n default: [],\n authoring: { authority: 'instance' },\n },\n showCoordinates: {\n type: 'boolean',\n category: 'Style',\n label: 'Show coordinates',\n default: false,\n authoring: { authority: 'instance' },\n },\n validateMoves: {\n type: 'boolean',\n category: 'Behavior',\n label: 'Validate moves',\n default: true,\n authoring: { authority: 'instance' },\n },\n disabled: {\n type: 'boolean',\n category: 'State',\n label: 'Disabled',\n default: false,\n authoring: { authority: 'instance' },\n },\n },\n} as const satisfies ZoraComponentMeta;\nexport const openingBookMeta = {\n name: 'OpeningBook',\n category: 'component',\n description:\n 'Presents caller-owned opening suggestions and their loading, empty, selected, and press states.',\n directManifestNode: true,\n allowedChildren: [],\n blueprint: {\n label: 'Opening book',\n defaultProps: {\n moves: [],\n title: 'Opening book',\n emptyText: 'No book moves for this position.',\n },\n },\n events: {\n movePress: {\n label: 'Move press',\n eventType: 'chess.openingMovePress',\n payloadFields: [\n { path: 'san', type: 'string', label: 'SAN' },\n { path: 'uci', type: 'string', label: 'UCI' },\n { path: 'fen', type: 'string', label: 'Position' },\n ],\n },\n },\n bindings: {\n props: {\n moves: {\n label: 'Moves',\n value: { type: 'array', itemType: 'object' },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n },\n },\n props: {\n moves: {\n type: 'array',\n category: 'Content',\n label: 'Moves',\n default: [],\n authoring: { authority: 'instance' },\n },\n title: {\n type: 'string',\n category: 'Content',\n label: 'Title',\n default: 'Opening book',\n authoring: { authority: 'instance' },\n },\n emptyText: {\n type: 'string',\n category: 'Content',\n label: 'Empty text',\n default: 'No book moves for this position.',\n authoring: { authority: 'instance' },\n },\n loading: {\n type: 'boolean',\n category: 'State',\n label: 'Loading',\n default: false,\n authoring: { authority: 'instance' },\n },\n errorText: {\n type: 'string',\n category: 'State',\n label: 'Error text',\n authoring: { authority: 'instance' },\n },\n selectedMove: {\n type: 'string',\n category: 'State',\n label: 'Selected move',\n authoring: { authority: 'instance' },\n },\n },\n} as const satisfies ZoraComponentMeta;\n"]}
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/features/chess/meta.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ZoraComponentMeta } from '../../types/authoring';\n\nexport const chessBoardMeta = {\n name: 'ChessBoard',\n category: 'component',\n description:\n 'Renders caller-owned chess pieces, highlights, and move-attempt interactions without chess rules.',\n directManifestNode: true,\n allowedChildren: [],\n blueprint: {\n label: 'Chess board',\n defaultProps: {\n columns: 8,\n pieces: [],\n orientation: 'white',\n rows: 8,\n showCoordinates: true,\n },\n },\n events: {\n cellPress: {\n label: 'Cell press',\n eventType: 'chess.cellPress',\n payloadFields: [\n { path: 'column', type: 'number', label: 'Column' },\n { path: 'row', type: 'number', label: 'Row' },\n ],\n },\n moveAttempt: {\n label: 'Move attempt',\n eventType: 'chess.moveAttempt',\n payloadFields: [\n { path: 'from.column', type: 'number', label: 'From column' },\n { path: 'from.row', type: 'number', label: 'From row' },\n { path: 'to.column', type: 'number', label: 'To column' },\n { path: 'to.row', type: 'number', label: 'To row' },\n ],\n },\n },\n bindings: {\n props: {\n pieces: {\n label: 'Pieces',\n value: { type: 'array', itemType: 'object' },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n selectedCell: {\n label: 'Selected cell',\n value: {\n type: 'object',\n fields: [\n { path: 'column', type: 'number', label: 'Column' },\n { path: 'row', type: 'number', label: 'Row' },\n ],\n },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n legalTargets: {\n label: 'Legal targets',\n value: {\n type: 'array',\n itemType: 'object',\n fields: [\n { path: '[].column', type: 'number', label: 'Column' },\n { path: '[].row', type: 'number', label: 'Row' },\n ],\n },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n },\n },\n props: {\n columns: {\n type: 'number',\n category: 'Board',\n label: 'Columns',\n default: 8,\n authoring: { authority: 'instance' },\n },\n rows: {\n type: 'number',\n category: 'Board',\n label: 'Rows',\n default: 8,\n authoring: { authority: 'instance' },\n },\n pieces: {\n type: 'array',\n category: 'Board',\n label: 'Pieces',\n default: [],\n authoring: { authority: 'instance' },\n },\n orientation: {\n type: 'enum',\n category: 'Board',\n label: 'Orientation',\n enum: ['white', 'black'],\n default: 'white',\n authoring: { authority: 'instance' },\n },\n selectedCell: {\n type: 'object',\n category: 'Board',\n label: 'Selected cell',\n itemSchema: [\n { key: 'column', schema: { type: 'number', category: 'Cell' } },\n { key: 'row', schema: { type: 'number', category: 'Cell' } },\n ],\n authoring: { authority: 'instance' },\n },\n legalTargets: {\n type: 'array',\n category: 'Board',\n label: 'Legal targets',\n default: [],\n itemSchema: [\n { key: 'column', schema: { type: 'number', category: 'Cell' } },\n { key: 'row', schema: { type: 'number', category: 'Cell' } },\n ],\n authoring: { authority: 'instance' },\n },\n showCoordinates: {\n type: 'boolean',\n category: 'Style',\n label: 'Show coordinates',\n default: false,\n authoring: { authority: 'instance' },\n },\n resizable: {\n type: 'boolean',\n category: 'Behavior',\n label: 'Resizable',\n default: false,\n authoring: { authority: 'instance' },\n },\n disabled: {\n type: 'boolean',\n category: 'State',\n label: 'Disabled',\n default: false,\n authoring: { authority: 'instance' },\n },\n },\n} as const satisfies ZoraComponentMeta;\nexport const openingBookMeta = {\n name: 'OpeningBook',\n category: 'component',\n description:\n 'Presents caller-owned opening suggestions and their loading, empty, selected, and press states.',\n directManifestNode: true,\n allowedChildren: [],\n blueprint: {\n label: 'Opening book',\n defaultProps: {\n moves: [],\n title: 'Opening book',\n emptyText: 'No book moves for this position.',\n },\n },\n events: {\n movePress: {\n label: 'Move press',\n eventType: 'chess.openingMovePress',\n payloadFields: [\n { path: 'san', type: 'string', label: 'SAN' },\n { path: 'uci', type: 'string', label: 'UCI' },\n { path: 'fen', type: 'string', label: 'Position' },\n ],\n },\n },\n bindings: {\n props: {\n moves: {\n label: 'Moves',\n value: { type: 'array', itemType: 'object' },\n acceptsFallback: true,\n acceptsTransforms: true,\n },\n },\n },\n props: {\n moves: {\n type: 'array',\n category: 'Content',\n label: 'Moves',\n default: [],\n authoring: { authority: 'instance' },\n },\n title: {\n type: 'string',\n category: 'Content',\n label: 'Title',\n default: 'Opening book',\n authoring: { authority: 'instance' },\n },\n emptyText: {\n type: 'string',\n category: 'Content',\n label: 'Empty text',\n default: 'No book moves for this position.',\n authoring: { authority: 'instance' },\n },\n loading: {\n type: 'boolean',\n category: 'State',\n label: 'Loading',\n default: false,\n authoring: { authority: 'instance' },\n },\n errorText: {\n type: 'string',\n category: 'State',\n label: 'Error text',\n authoring: { authority: 'instance' },\n },\n selectedMove: {\n type: 'string',\n category: 'State',\n label: 'Selected move',\n authoring: { authority: 'instance' },\n },\n },\n} as const satisfies ZoraComponentMeta;\n"]}
@@ -1,14 +1,8 @@
1
- export type { ChessBoardColorOverrides, ChessBoardColorScheme, ChessBoardOrientation, ChessBoardProps, ChessMoveAttempt, ChessMoveResult, ChessPieceCode, ChessPieceRenderContext, ChessPieceRenderer, ChessPieceState, ChessPromotionPiece, ChessSquareId, OpeningBookColorOverrides, OpeningBookColorScheme, OpeningBookMove, OpeningBookProps, } from '../../types/chess';
1
+ export type { ChessBoardCell, ChessBoardColorOverrides, ChessBoardColorScheme, ChessBoardDimensions, ChessBoardOrientation, ChessBoardProps, ChessMoveAttempt, ChessPieceCode, ChessPieceRenderContext, ChessPieceRenderer, ChessPieceState, OpeningBookColorOverrides, OpeningBookColorScheme, OpeningBookMove, OpeningBookProps, } from '../../types/chess';
2
2
  export { ChessBoard } from './adapters/inbound/ChessBoard';
3
3
  export { OpeningBook } from './adapters/inbound/OpeningBook';
4
4
  export { chessBoardMeta, openingBookMeta } from './meta';
5
- export { getLegalTargets, readChessPieces, tryMove } from './utils/chessEngine';
6
- export { chessSquares } from './utils/chessSquares';
7
- export { createBoardSquares } from './utils/createBoardSquares';
8
5
  export type { ChessColorThemeShape } from './utils/createChessBoardColorScheme';
9
6
  export { createChessBoardColorScheme } from './utils/createChessBoardColorScheme';
10
7
  export { createOpeningBookColorScheme } from './utils/createOpeningBookColorScheme';
11
- export { getSquareFile } from './utils/getSquareFile';
12
- export { getSquareRank } from './utils/getSquareRank';
13
- export { isLightSquare } from './utils/isLightSquare';
14
8
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/features/chess/public.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,yBAAyB,EACzB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/features/chess/public.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC"}
@@ -1,12 +1,6 @@
1
1
  export { ChessBoard } from './adapters/inbound/ChessBoard';
2
2
  export { OpeningBook } from './adapters/inbound/OpeningBook';
3
3
  export { chessBoardMeta, openingBookMeta } from './meta';
4
- export { getLegalTargets, readChessPieces, tryMove } from './utils/chessEngine';
5
- export { chessSquares } from './utils/chessSquares';
6
- export { createBoardSquares } from './utils/createBoardSquares';
7
4
  export { createChessBoardColorScheme } from './utils/createChessBoardColorScheme';
8
5
  export { createOpeningBookColorScheme } from './utils/createOpeningBookColorScheme';
9
- export { getSquareFile } from './utils/getSquareFile';
10
- export { getSquareRank } from './utils/getSquareRank';
11
- export { isLightSquare } from './utils/isLightSquare';
12
6
  //# sourceMappingURL=public.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/features/chess/public.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["export type {\n ChessBoardColorOverrides,\n ChessBoardColorScheme,\n ChessBoardOrientation,\n ChessBoardProps,\n ChessMoveAttempt,\n ChessMoveResult,\n ChessPieceCode,\n ChessPieceRenderContext,\n ChessPieceRenderer,\n ChessPieceState,\n ChessPromotionPiece,\n ChessSquareId,\n OpeningBookColorOverrides,\n OpeningBookColorScheme,\n OpeningBookMove,\n OpeningBookProps,\n} from '../../types/chess';\nexport { ChessBoard } from './adapters/inbound/ChessBoard';\nexport { OpeningBook } from './adapters/inbound/OpeningBook';\nexport { chessBoardMeta, openingBookMeta } from './meta';\nexport { getLegalTargets, readChessPieces, tryMove } from './utils/chessEngine';\nexport { chessSquares } from './utils/chessSquares';\nexport { createBoardSquares } from './utils/createBoardSquares';\nexport type { ChessColorThemeShape } from './utils/createChessBoardColorScheme';\nexport { createChessBoardColorScheme } from './utils/createChessBoardColorScheme';\nexport { createOpeningBookColorScheme } from './utils/createOpeningBookColorScheme';\nexport { getSquareFile } from './utils/getSquareFile';\nexport { getSquareRank } from './utils/getSquareRank';\nexport { isLightSquare } from './utils/isLightSquare';\n"]}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/features/chess/public.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAEzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC","sourcesContent":["export type {\n ChessBoardCell,\n ChessBoardColorOverrides,\n ChessBoardColorScheme,\n ChessBoardDimensions,\n ChessBoardOrientation,\n ChessBoardProps,\n ChessMoveAttempt,\n ChessPieceCode,\n ChessPieceRenderContext,\n ChessPieceRenderer,\n ChessPieceState,\n OpeningBookColorOverrides,\n OpeningBookColorScheme,\n OpeningBookMove,\n OpeningBookProps,\n} from '../../types/chess';\nexport { ChessBoard } from './adapters/inbound/ChessBoard';\nexport { OpeningBook } from './adapters/inbound/OpeningBook';\nexport { chessBoardMeta, openingBookMeta } from './meta';\nexport type { ChessColorThemeShape } from './utils/createChessBoardColorScheme';\nexport { createChessBoardColorScheme } from './utils/createChessBoardColorScheme';\nexport { createOpeningBookColorScheme } from './utils/createOpeningBookColorScheme';\n"]}
@@ -0,0 +1,6 @@
1
+ import type { ChessBoardCell, ChessBoardProps } from '../../../types/chess';
2
+ type ChessBoardCellPressHandlerOptions = Pick<ChessBoardProps, 'disabled' | 'interactionPolicy' | 'onCellPress' | 'onMoveAttempt' | 'selectedCell'>;
3
+ /*** Creates the caller-owned cell and move intent boundary for an interactive chess presentation. */
4
+ export declare function createChessBoardCellPressHandler({ disabled, interactionPolicy, onCellPress, onMoveAttempt, selectedCell, }: ChessBoardCellPressHandlerOptions): (cell: ChessBoardCell) => void;
5
+ export {};
6
+ //# sourceMappingURL=createChessBoardCellPressHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createChessBoardCellPressHandler.d.ts","sourceRoot":"","sources":["../../../../src/features/chess/utils/createChessBoardCellPressHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5E,KAAK,iCAAiC,GAAG,IAAI,CAC3C,eAAe,EACf,UAAU,GAAG,mBAAmB,GAAG,aAAa,GAAG,eAAe,GAAG,cAAc,CACpF,CAAC;AAEF,qGAAqG;AACrG,wBAAgB,gCAAgC,CAAC,EAC/C,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,YAAY,GACb,EAAE,iCAAiC,GAAG,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAUpE"}
@@ -0,0 +1,17 @@
1
+ /*** Creates the caller-owned cell and move intent boundary for an interactive chess presentation. */
2
+ export function createChessBoardCellPressHandler({ disabled, interactionPolicy, onCellPress, onMoveAttempt, selectedCell, }) {
3
+ return (cell) => {
4
+ if (disabled || interactionPolicy === 'passive')
5
+ return;
6
+ onCellPress?.(cell);
7
+ if (selectedCell === null || selectedCell === undefined || cellsEqual(selectedCell, cell)) {
8
+ return;
9
+ }
10
+ onMoveAttempt?.({ from: selectedCell, to: cell });
11
+ };
12
+ }
13
+ /*** Compares caller-owned coordinates without adding chess-rule semantics. */
14
+ function cellsEqual(left, right) {
15
+ return left.column === right.column && left.row === right.row;
16
+ }
17
+ //# sourceMappingURL=createChessBoardCellPressHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createChessBoardCellPressHandler.js","sourceRoot":"","sources":["../../../../src/features/chess/utils/createChessBoardCellPressHandler.ts"],"names":[],"mappings":"AAOA,qGAAqG;AACrG,MAAM,UAAU,gCAAgC,CAAC,EAC/C,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,YAAY,GACsB;IAClC,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,IAAI,QAAQ,IAAI,iBAAiB,KAAK,SAAS;YAAE,OAAO;QAExD,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,SAAS,IAAI,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC;YAC1F,OAAO;QACT,CAAC;QACD,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAS,UAAU,CAAC,IAAoB,EAAE,KAAqB;IAC7D,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAAC;AAChE,CAAC","sourcesContent":["import type { ChessBoardCell, ChessBoardProps } from '../../../types/chess';\n\ntype ChessBoardCellPressHandlerOptions = Pick<\n ChessBoardProps,\n 'disabled' | 'interactionPolicy' | 'onCellPress' | 'onMoveAttempt' | 'selectedCell'\n>;\n\n/*** Creates the caller-owned cell and move intent boundary for an interactive chess presentation. */\nexport function createChessBoardCellPressHandler({\n disabled,\n interactionPolicy,\n onCellPress,\n onMoveAttempt,\n selectedCell,\n}: ChessBoardCellPressHandlerOptions): (cell: ChessBoardCell) => void {\n return (cell) => {\n if (disabled || interactionPolicy === 'passive') return;\n\n onCellPress?.(cell);\n if (selectedCell === null || selectedCell === undefined || cellsEqual(selectedCell, cell)) {\n return;\n }\n onMoveAttempt?.({ from: selectedCell, to: cell });\n };\n}\n\n/*** Compares caller-owned coordinates without adding chess-rule semantics. */\nfunction cellsEqual(left: ChessBoardCell, right: ChessBoardCell): boolean {\n return left.column === right.column && left.row === right.row;\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { ChessBoardCell, ChessBoardOrientation } from '../../../types/chess';
2
+ type ChessBoardGridCell = ChessBoardCell & {
3
+ readonly height: 1;
4
+ readonly id: string;
5
+ readonly width: 1;
6
+ readonly x: number;
7
+ readonly y: number;
8
+ };
9
+ /*** Creates bounded GridView cells whose coordinates represent the requested chess orientation. */
10
+ export declare function createChessBoardCells(columns: number, rows: number, orientation: ChessBoardOrientation): readonly ChessBoardGridCell[];
11
+ export {};
12
+ //# sourceMappingURL=createChessBoardCells.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createChessBoardCells.d.ts","sourceRoot":"","sources":["../../../../src/features/chess/utils/createChessBoardCells.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAKlF,KAAK,kBAAkB,GAAG,cAAc,GAAG;IACzC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,mGAAmG;AACnG,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,qBAAqB,GACjC,SAAS,kBAAkB,EAAE,CAmB/B"}
@@ -0,0 +1,28 @@
1
+ const minimumDimension = 2;
2
+ const maximumDimension = 24;
3
+ /*** Creates bounded GridView cells whose coordinates represent the requested chess orientation. */
4
+ export function createChessBoardCells(columns, rows, orientation) {
5
+ validateChessBoardDimensions(columns, rows);
6
+ return Array.from({ length: rows }, (_, rowIndex) => Array.from({ length: columns }, (_, columnIndex) => {
7
+ const column = columnIndex + 1;
8
+ const row = rowIndex + 1;
9
+ return {
10
+ column,
11
+ height: 1,
12
+ id: `${column}:${row}`,
13
+ row,
14
+ width: 1,
15
+ x: orientation === 'white' ? columnIndex : columns - column,
16
+ y: orientation === 'white' ? rows - row : rowIndex,
17
+ };
18
+ })).flat();
19
+ }
20
+ /*** Rejects dimensions outside the presentation contract before GridView receives them. */
21
+ function validateChessBoardDimensions(columns, rows) {
22
+ if (![columns, rows].every((dimension) => Number.isInteger(dimension) &&
23
+ dimension >= minimumDimension &&
24
+ dimension <= maximumDimension)) {
25
+ throw new RangeError(`ChessBoard dimensions must be whole numbers from ${minimumDimension} through ${maximumDimension}.`);
26
+ }
27
+ }
28
+ //# sourceMappingURL=createChessBoardCells.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createChessBoardCells.js","sourceRoot":"","sources":["../../../../src/features/chess/utils/createChessBoardCells.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAU5B,mGAAmG;AACnG,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,IAAY,EACZ,WAAkC;IAElC,4BAA4B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE5C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAClD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE;QACjD,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,QAAQ,GAAG,CAAC,CAAC;QAEzB,OAAO;YACL,MAAM;YACN,MAAM,EAAE,CAAU;YAClB,EAAE,EAAE,GAAG,MAAM,IAAI,GAAG,EAAE;YACtB,GAAG;YACH,KAAK,EAAE,CAAU;YACjB,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM;YAC3D,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ;SACnD,CAAC;IACJ,CAAC,CAAC,CACH,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AAED,2FAA2F;AAC3F,SAAS,4BAA4B,CAAC,OAAe,EAAE,IAAY;IACjE,IACE,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,CACpB,CAAC,SAAS,EAAE,EAAE,CACZ,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QAC3B,SAAS,IAAI,gBAAgB;QAC7B,SAAS,IAAI,gBAAgB,CAChC,EACD,CAAC;QACD,MAAM,IAAI,UAAU,CAClB,oDAAoD,gBAAgB,YAAY,gBAAgB,GAAG,CACpG,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import type { ChessBoardCell, ChessBoardOrientation } from '../../../types/chess';\n\nconst minimumDimension = 2;\nconst maximumDimension = 24;\n\ntype ChessBoardGridCell = ChessBoardCell & {\n readonly height: 1;\n readonly id: string;\n readonly width: 1;\n readonly x: number;\n readonly y: number;\n};\n\n/*** Creates bounded GridView cells whose coordinates represent the requested chess orientation. */\nexport function createChessBoardCells(\n columns: number,\n rows: number,\n orientation: ChessBoardOrientation,\n): readonly ChessBoardGridCell[] {\n validateChessBoardDimensions(columns, rows);\n\n return Array.from({ length: rows }, (_, rowIndex) =>\n Array.from({ length: columns }, (_, columnIndex) => {\n const column = columnIndex + 1;\n const row = rowIndex + 1;\n\n return {\n column,\n height: 1 as const,\n id: `${column}:${row}`,\n row,\n width: 1 as const,\n x: orientation === 'white' ? columnIndex : columns - column,\n y: orientation === 'white' ? rows - row : rowIndex,\n };\n }),\n ).flat();\n}\n\n/*** Rejects dimensions outside the presentation contract before GridView receives them. */\nfunction validateChessBoardDimensions(columns: number, rows: number): void {\n if (\n ![columns, rows].every(\n (dimension) =>\n Number.isInteger(dimension) &&\n dimension >= minimumDimension &&\n dimension <= maximumDimension,\n )\n ) {\n throw new RangeError(\n `ChessBoard dimensions must be whole numbers from ${minimumDimension} through ${maximumDimension}.`,\n );\n }\n}\n"]}
@@ -151,7 +151,7 @@ function isUsableViewport(viewport) {
151
151
  viewport.width > 0 &&
152
152
  viewport.height > 0);
153
153
  }
154
- /*** Measure rendered node geometry for public consumers while keeping Cytoscape private. */
154
+ /*** Measure rendered node hit geometry without exposing paint-only outlines or Cytoscape. */
155
155
  function measureRenderedNodes(cy, nodeIds) {
156
156
  const viewport = { width: cy.width(), height: cy.height() };
157
157
  if (viewport.width <= 0 || viewport.height <= 0 || nodeIds.length === 0)
@@ -160,12 +160,11 @@ function measureRenderedNodes(cy, nodeIds) {
160
160
  const node = cy.getElementById(id);
161
161
  if (!node.isNode())
162
162
  return [];
163
- const bounds = node.renderedBoundingBox();
164
163
  return [
165
164
  {
166
165
  id,
167
166
  position: node.renderedPosition(),
168
- size: { width: bounds.w, height: bounds.h },
167
+ size: { width: node.renderedOuterWidth(), height: node.renderedOuterHeight() },
169
168
  },
170
169
  ];
171
170
  });
@@ -1 +1 @@
1
- {"version":3,"file":"createGraphController.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Core } from 'cytoscape';\n\nimport type {\n GraphViewController,\n GraphViewFitOptions,\n GraphViewMeasurement,\n} from '../../../../../types/graph-view';\nimport type { GraphRuntimeUpdate } from '../../../../../types/graphViewRuntime';\nimport { fitGraphViewport } from './fitGraphViewport';\n\n/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */\nexport function createGraphController(\n cy: Core,\n fitPaddingRef: { current: number },\n optimizeFit?: (options: GraphViewFitOptions) => void,\n) {\n const state = {\n scale: 1,\n relative: false,\n min: 0.05,\n max: 2,\n readableSize: 0,\n fitSize: Infinity,\n readableZoom: 0,\n fitZoom: Infinity,\n resizeSnapshot: null as GraphResizeSnapshot | null,\n };\n const controller: GraphViewController = {\n fit(options) {\n if (options?.optimizeSpacing && !options.nodeIds?.length && optimizeFit) {\n optimizeFit(options);\n return;\n }\n fitGraphViewport(\n cy,\n {\n nodeIds: options?.nodeIds,\n padding: options?.padding ?? fitPaddingRef.current,\n },\n state.fitZoom,\n );\n },\n measureNodes(nodeIds) {\n return measureRenderedNodes(cy, nodeIds);\n },\n getViewport() {\n return { pan: cy.pan(), zoom: cy.zoom() / state.scale };\n },\n getZoomRange() {\n return { min: cy.minZoom() / state.scale, max: cy.maxZoom() / state.scale };\n },\n setPan(pan) {\n cy.pan(pan);\n },\n setZoom(zoom) {\n setCenteredZoom(cy, zoom * state.scale);\n },\n zoomBy(factor) {\n setCenteredZoom(cy, cy.zoom() * factor);\n },\n };\n\n return {\n controller,\n configure(input: GraphRuntimeUpdate) {\n state.relative = input.zoomMode === 'fit-relative';\n state.min = input.minZoom ?? 0.05;\n state.max = input.maxZoom ?? 2;\n state.readableSize = positiveSize(input.minReadableLabelSize, 0);\n state.fitSize = positiveSize(input.maxFitLabelSize, Infinity);\n if (!state.relative) state.scale = 1;\n applyZoomLimits(cy, state);\n },\n /*** Return the native automatic-fit ceiling used by spacing optimization. */\n getFitZoomLimit() {\n return state.relative ? state.fitZoom : Math.min(state.fitZoom, state.max);\n },\n /*** Return the native label-readability threshold used before allowing background overlap. */\n getReadableZoomTarget() {\n return state.readableZoom;\n },\n /*** Capture the model point beneath the current viewport center before Cytoscape resizes. */\n beginResize() {\n state.resizeSnapshot = captureResizeSnapshot(cy);\n },\n settle(fit: boolean) {\n const logicalZoom = cy.zoom() / state.scale;\n const fonts = cy\n .nodes()\n .filter((node) => !node.isParent() && Boolean(node.style('label')))\n .map((node) => Number.parseFloat(String(node.style('font-size'))))\n .filter((size) => Number.isFinite(size) && size > 0);\n state.readableZoom = fonts.length\n ? state.readableSize / fonts.reduce((minimum, size) => Math.min(minimum, size), Infinity)\n : 0;\n state.fitZoom = fonts.length\n ? state.fitSize / fonts.reduce((maximum, size) => Math.max(maximum, size), 0)\n : Infinity;\n state.scale = state.relative\n ? Math.min(getNodeFitZoom(cy, fitPaddingRef.current), state.fitZoom)\n : 1;\n applyZoomLimits(cy, state);\n if (fit) {\n state.resizeSnapshot = null;\n controller.fit();\n } else if (settlePreservedViewport(cy, state, logicalZoom)) controller.fit();\n },\n };\n}\n\ninterface GraphResizeSnapshot {\n readonly center: { readonly x: number; readonly y: number };\n readonly nodeBounds: GraphNodeBoundsStatus;\n}\n\ntype GraphNodeBoundsStatus = 'clipped' | 'empty' | 'fit' | 'unusable';\n\n/*** Capture the model-space center and whether the prior viewport was an intact graph fit. */\nfunction captureResizeSnapshot(cy: Core): GraphResizeSnapshot | null {\n const viewport = { width: cy.width(), height: cy.height() };\n const zoom = cy.zoom();\n if (!isUsableViewport(viewport) || !Number.isFinite(zoom) || zoom <= 0) return null;\n const pan = cy.pan();\n const renderedCenter = { x: viewport.width / 2, y: viewport.height / 2 };\n return {\n center: {\n x: (renderedCenter.x - pan.x) / zoom,\n y: (renderedCenter.y - pan.y) / zoom,\n },\n nodeBounds: getNodeBoundsStatus(cy, viewport),\n };\n}\n\n/*** Preserve a manual viewport through resize, fitting only when an intact prior fit becomes invalid. */\nfunction settlePreservedViewport(\n cy: Core,\n state: {\n readonly relative: boolean;\n resizeSnapshot: GraphResizeSnapshot | null;\n readonly scale: number;\n },\n logicalZoom: number,\n): boolean {\n const snapshot = state.resizeSnapshot;\n state.resizeSnapshot = null;\n const zoom = state.relative ? logicalZoom * state.scale : cy.zoom();\n if (snapshot === null) {\n if (state.relative) setCenteredZoom(cy, zoom);\n return false;\n }\n const viewport = { width: cy.width(), height: cy.height() };\n if (!isUsableViewport(viewport)) return false;\n cy.viewport({\n zoom,\n pan: {\n x: viewport.width / 2 - snapshot.center.x * zoom,\n y: viewport.height / 2 - snapshot.center.y * zoom,\n },\n });\n const nodeBounds = getNodeBoundsStatus(cy, viewport);\n return nodeBounds === 'unusable' || (snapshot.nodeBounds === 'fit' && nodeBounds === 'clipped');\n}\n\n/*** Accept only finite non-empty node bounds that are wholly visible in a usable viewport. */\nfunction getNodeBoundsStatus(\n cy: Core,\n viewport: { readonly width: number; readonly height: number },\n): GraphNodeBoundsStatus {\n if (cy.nodes().empty()) return 'empty';\n if (!isUsableViewport(viewport)) return 'unusable';\n const bounds = cy.nodes().renderedBoundingBox();\n if (![bounds.x1, bounds.x2, bounds.y1, bounds.y2].every(Number.isFinite)) return 'unusable';\n const fitsHorizontally = bounds.x1 >= 0 && bounds.x2 <= viewport.width;\n const fitsVertically = bounds.y1 >= 0 && bounds.y2 <= viewport.height;\n return fitsHorizontally && fitsVertically ? 'fit' : 'clipped';\n}\n\n/*** Reject zero, negative, and non-finite renderer dimensions before viewport arithmetic. */\nfunction isUsableViewport(viewport: { readonly width: number; readonly height: number }): boolean {\n return (\n Number.isFinite(viewport.width) &&\n Number.isFinite(viewport.height) &&\n viewport.width > 0 &&\n viewport.height > 0\n );\n}\n\n/*** Measure rendered node geometry for public consumers while keeping Cytoscape private. */\nfunction measureRenderedNodes(cy: Core, nodeIds: readonly string[]): GraphViewMeasurement | null {\n const viewport = { width: cy.width(), height: cy.height() };\n if (viewport.width <= 0 || viewport.height <= 0 || nodeIds.length === 0) return null;\n\n const nodes = [...new Set(nodeIds)].flatMap((id) => {\n const node = cy.getElementById(id);\n if (!node.isNode()) return [];\n\n const bounds = node.renderedBoundingBox();\n return [\n {\n id,\n position: node.renderedPosition(),\n size: { width: bounds.w, height: bounds.h },\n },\n ];\n });\n return nodes.length === 0 ? null : { nodes, viewport };\n}\n\n/*** Keep pointer, wheel, and programmatic zoom on the same limits in the engine's native units. */\nfunction applyZoomLimits(\n cy: Core,\n state: {\n readonly min: number;\n readonly max: number;\n readonly scale: number;\n readonly readableZoom: number;\n },\n) {\n const min = state.min * state.scale;\n cy.minZoom(Math.min(cy.minZoom(), min));\n cy.maxZoom(Math.max(min, state.max * state.scale, state.readableZoom));\n cy.minZoom(min);\n}\n\n/*** Ignore invalid optional typography targets at the public configuration boundary. */\nfunction positiveSize(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/***\n * Recompute the fit reference only after layout or resize, never on every pan/zoom event.\n * Cache the geometry-derived scale in the viewport owner; labels are included, edges excluded.\n */\nfunction getNodeFitZoom(cy: Core, padding: number): number {\n if (cy.nodes().empty()) return 1;\n const bounds = cy.nodes().boundingBox();\n const width = cy.width() - 2 * padding;\n const height = cy.height() - 2 * padding;\n if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0) return 1;\n return Math.min(width / bounds.w, height / bounds.h);\n}\n\n/*** Zoom around the visible viewport center instead of its top-left corner. */\nfunction setCenteredZoom(cy: Core, zoom: number) {\n cy.zoom({ level: zoom, renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 } });\n}\n"]}
1
+ {"version":3,"file":"createGraphController.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Core } from 'cytoscape';\n\nimport type {\n GraphViewController,\n GraphViewFitOptions,\n GraphViewMeasurement,\n} from '../../../../../types/graph-view';\nimport type { GraphRuntimeUpdate } from '../../../../../types/graphViewRuntime';\nimport { fitGraphViewport } from './fitGraphViewport';\n\n/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */\nexport function createGraphController(\n cy: Core,\n fitPaddingRef: { current: number },\n optimizeFit?: (options: GraphViewFitOptions) => void,\n) {\n const state = {\n scale: 1,\n relative: false,\n min: 0.05,\n max: 2,\n readableSize: 0,\n fitSize: Infinity,\n readableZoom: 0,\n fitZoom: Infinity,\n resizeSnapshot: null as GraphResizeSnapshot | null,\n };\n const controller: GraphViewController = {\n fit(options) {\n if (options?.optimizeSpacing && !options.nodeIds?.length && optimizeFit) {\n optimizeFit(options);\n return;\n }\n fitGraphViewport(\n cy,\n {\n nodeIds: options?.nodeIds,\n padding: options?.padding ?? fitPaddingRef.current,\n },\n state.fitZoom,\n );\n },\n measureNodes(nodeIds) {\n return measureRenderedNodes(cy, nodeIds);\n },\n getViewport() {\n return { pan: cy.pan(), zoom: cy.zoom() / state.scale };\n },\n getZoomRange() {\n return { min: cy.minZoom() / state.scale, max: cy.maxZoom() / state.scale };\n },\n setPan(pan) {\n cy.pan(pan);\n },\n setZoom(zoom) {\n setCenteredZoom(cy, zoom * state.scale);\n },\n zoomBy(factor) {\n setCenteredZoom(cy, cy.zoom() * factor);\n },\n };\n\n return {\n controller,\n configure(input: GraphRuntimeUpdate) {\n state.relative = input.zoomMode === 'fit-relative';\n state.min = input.minZoom ?? 0.05;\n state.max = input.maxZoom ?? 2;\n state.readableSize = positiveSize(input.minReadableLabelSize, 0);\n state.fitSize = positiveSize(input.maxFitLabelSize, Infinity);\n if (!state.relative) state.scale = 1;\n applyZoomLimits(cy, state);\n },\n /*** Return the native automatic-fit ceiling used by spacing optimization. */\n getFitZoomLimit() {\n return state.relative ? state.fitZoom : Math.min(state.fitZoom, state.max);\n },\n /*** Return the native label-readability threshold used before allowing background overlap. */\n getReadableZoomTarget() {\n return state.readableZoom;\n },\n /*** Capture the model point beneath the current viewport center before Cytoscape resizes. */\n beginResize() {\n state.resizeSnapshot = captureResizeSnapshot(cy);\n },\n settle(fit: boolean) {\n const logicalZoom = cy.zoom() / state.scale;\n const fonts = cy\n .nodes()\n .filter((node) => !node.isParent() && Boolean(node.style('label')))\n .map((node) => Number.parseFloat(String(node.style('font-size'))))\n .filter((size) => Number.isFinite(size) && size > 0);\n state.readableZoom = fonts.length\n ? state.readableSize / fonts.reduce((minimum, size) => Math.min(minimum, size), Infinity)\n : 0;\n state.fitZoom = fonts.length\n ? state.fitSize / fonts.reduce((maximum, size) => Math.max(maximum, size), 0)\n : Infinity;\n state.scale = state.relative\n ? Math.min(getNodeFitZoom(cy, fitPaddingRef.current), state.fitZoom)\n : 1;\n applyZoomLimits(cy, state);\n if (fit) {\n state.resizeSnapshot = null;\n controller.fit();\n } else if (settlePreservedViewport(cy, state, logicalZoom)) controller.fit();\n },\n };\n}\n\ninterface GraphResizeSnapshot {\n readonly center: { readonly x: number; readonly y: number };\n readonly nodeBounds: GraphNodeBoundsStatus;\n}\n\ntype GraphNodeBoundsStatus = 'clipped' | 'empty' | 'fit' | 'unusable';\n\n/*** Capture the model-space center and whether the prior viewport was an intact graph fit. */\nfunction captureResizeSnapshot(cy: Core): GraphResizeSnapshot | null {\n const viewport = { width: cy.width(), height: cy.height() };\n const zoom = cy.zoom();\n if (!isUsableViewport(viewport) || !Number.isFinite(zoom) || zoom <= 0) return null;\n const pan = cy.pan();\n const renderedCenter = { x: viewport.width / 2, y: viewport.height / 2 };\n return {\n center: {\n x: (renderedCenter.x - pan.x) / zoom,\n y: (renderedCenter.y - pan.y) / zoom,\n },\n nodeBounds: getNodeBoundsStatus(cy, viewport),\n };\n}\n\n/*** Preserve a manual viewport through resize, fitting only when an intact prior fit becomes invalid. */\nfunction settlePreservedViewport(\n cy: Core,\n state: {\n readonly relative: boolean;\n resizeSnapshot: GraphResizeSnapshot | null;\n readonly scale: number;\n },\n logicalZoom: number,\n): boolean {\n const snapshot = state.resizeSnapshot;\n state.resizeSnapshot = null;\n const zoom = state.relative ? logicalZoom * state.scale : cy.zoom();\n if (snapshot === null) {\n if (state.relative) setCenteredZoom(cy, zoom);\n return false;\n }\n const viewport = { width: cy.width(), height: cy.height() };\n if (!isUsableViewport(viewport)) return false;\n cy.viewport({\n zoom,\n pan: {\n x: viewport.width / 2 - snapshot.center.x * zoom,\n y: viewport.height / 2 - snapshot.center.y * zoom,\n },\n });\n const nodeBounds = getNodeBoundsStatus(cy, viewport);\n return nodeBounds === 'unusable' || (snapshot.nodeBounds === 'fit' && nodeBounds === 'clipped');\n}\n\n/*** Accept only finite non-empty node bounds that are wholly visible in a usable viewport. */\nfunction getNodeBoundsStatus(\n cy: Core,\n viewport: { readonly width: number; readonly height: number },\n): GraphNodeBoundsStatus {\n if (cy.nodes().empty()) return 'empty';\n if (!isUsableViewport(viewport)) return 'unusable';\n const bounds = cy.nodes().renderedBoundingBox();\n if (![bounds.x1, bounds.x2, bounds.y1, bounds.y2].every(Number.isFinite)) return 'unusable';\n const fitsHorizontally = bounds.x1 >= 0 && bounds.x2 <= viewport.width;\n const fitsVertically = bounds.y1 >= 0 && bounds.y2 <= viewport.height;\n return fitsHorizontally && fitsVertically ? 'fit' : 'clipped';\n}\n\n/*** Reject zero, negative, and non-finite renderer dimensions before viewport arithmetic. */\nfunction isUsableViewport(viewport: { readonly width: number; readonly height: number }): boolean {\n return (\n Number.isFinite(viewport.width) &&\n Number.isFinite(viewport.height) &&\n viewport.width > 0 &&\n viewport.height > 0\n );\n}\n\n/*** Measure rendered node hit geometry without exposing paint-only outlines or Cytoscape. */\nfunction measureRenderedNodes(cy: Core, nodeIds: readonly string[]): GraphViewMeasurement | null {\n const viewport = { width: cy.width(), height: cy.height() };\n if (viewport.width <= 0 || viewport.height <= 0 || nodeIds.length === 0) return null;\n\n const nodes = [...new Set(nodeIds)].flatMap((id) => {\n const node = cy.getElementById(id);\n if (!node.isNode()) return [];\n\n return [\n {\n id,\n position: node.renderedPosition(),\n size: { width: node.renderedOuterWidth(), height: node.renderedOuterHeight() },\n },\n ];\n });\n return nodes.length === 0 ? null : { nodes, viewport };\n}\n\n/*** Keep pointer, wheel, and programmatic zoom on the same limits in the engine's native units. */\nfunction applyZoomLimits(\n cy: Core,\n state: {\n readonly min: number;\n readonly max: number;\n readonly scale: number;\n readonly readableZoom: number;\n },\n) {\n const min = state.min * state.scale;\n cy.minZoom(Math.min(cy.minZoom(), min));\n cy.maxZoom(Math.max(min, state.max * state.scale, state.readableZoom));\n cy.minZoom(min);\n}\n\n/*** Ignore invalid optional typography targets at the public configuration boundary. */\nfunction positiveSize(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/***\n * Recompute the fit reference only after layout or resize, never on every pan/zoom event.\n * Cache the geometry-derived scale in the viewport owner; labels are included, edges excluded.\n */\nfunction getNodeFitZoom(cy: Core, padding: number): number {\n if (cy.nodes().empty()) return 1;\n const bounds = cy.nodes().boundingBox();\n const width = cy.width() - 2 * padding;\n const height = cy.height() - 2 * padding;\n if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0) return 1;\n return Math.min(width / bounds.w, height / bounds.h);\n}\n\n/*** Zoom around the visible viewport center instead of its top-left corner. */\nfunction setCenteredZoom(cy: Core, zoom: number) {\n cy.zoom({ level: zoom, renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 } });\n}\n"]}
@@ -117,7 +117,9 @@ function updateRuntime(state, input) {
117
117
  applyKnownNodeSizes(state);
118
118
  state.loopSizer.update();
119
119
  const geometry = getGraphGeometryKey(state.cy);
120
- const relayout = geometry !== state.geometryRef.current || hasGraphLayoutChanged(previous, input);
120
+ // Keep native double-press targets stable for paint-only class changes. A class that changes
121
+ // measured node dimensions remains a geometry change and must relayout.
122
+ const relayout = hasGraphLayoutChanged(previous, input) || geometry !== state.geometryRef.current;
121
123
  state.geometryRef.current = geometry;
122
124
  if (!relayout) {
123
125
  if (previous?.zoomMode !== input.zoomMode ||