@operato/scene-storage 10.0.0-beta.40 → 10.0.0-beta.42

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 (102) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/MIGRATION-plan-a-slot-api.md +266 -0
  3. package/PLAN-A-rack-as-slot-holder.md +164 -0
  4. package/dist/box.js +18 -0
  5. package/dist/box.js.map +1 -1
  6. package/dist/crane-3d.d.ts +47 -2
  7. package/dist/crane-3d.js +246 -89
  8. package/dist/crane-3d.js.map +1 -1
  9. package/dist/crane.d.ts +96 -12
  10. package/dist/crane.js +395 -100
  11. package/dist/crane.js.map +1 -1
  12. package/dist/index.d.ts +3 -4
  13. package/dist/index.js +1 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/pallet.d.ts +15 -0
  16. package/dist/pallet.js +38 -2
  17. package/dist/pallet.js.map +1 -1
  18. package/dist/parcel-3d.js +22 -18
  19. package/dist/parcel-3d.js.map +1 -1
  20. package/dist/parcel.d.ts +4 -3
  21. package/dist/parcel.js +24 -5
  22. package/dist/parcel.js.map +1 -1
  23. package/dist/rack-grid-3d.d.ts +18 -7
  24. package/dist/rack-grid-3d.js +372 -69
  25. package/dist/rack-grid-3d.js.map +1 -1
  26. package/dist/rack-grid-cell.d.ts +21 -72
  27. package/dist/rack-grid-cell.js +147 -243
  28. package/dist/rack-grid-cell.js.map +1 -1
  29. package/dist/rack-grid.d.ts +277 -56
  30. package/dist/rack-grid.js +1230 -695
  31. package/dist/rack-grid.js.map +1 -1
  32. package/dist/rack-materials.d.ts +9 -0
  33. package/dist/rack-materials.js +55 -0
  34. package/dist/rack-materials.js.map +1 -0
  35. package/dist/storage-rack-3d.d.ts +15 -0
  36. package/dist/storage-rack-3d.js +165 -29
  37. package/dist/storage-rack-3d.js.map +1 -1
  38. package/dist/storage-rack.d.ts +253 -32
  39. package/dist/storage-rack.js +726 -66
  40. package/dist/storage-rack.js.map +1 -1
  41. package/package.json +3 -3
  42. package/src/box.ts +18 -0
  43. package/src/crane-3d.ts +258 -93
  44. package/src/crane.ts +445 -110
  45. package/src/index.ts +3 -4
  46. package/src/pallet.ts +50 -1
  47. package/src/parcel-3d.ts +23 -18
  48. package/src/parcel.ts +24 -5
  49. package/src/rack-grid-3d.ts +383 -80
  50. package/src/rack-grid-cell.ts +161 -305
  51. package/src/rack-grid.ts +1263 -762
  52. package/src/rack-materials.ts +61 -0
  53. package/src/storage-rack-3d.ts +182 -29
  54. package/src/storage-rack.ts +819 -67
  55. package/test/test-carrier-lifecycle.ts +361 -0
  56. package/test/test-coord-alignment.ts +201 -0
  57. package/test/test-crane-geometry.ts +167 -0
  58. package/test/test-external-to-rack.ts +461 -0
  59. package/test/test-mover-concurrent-bug.ts +304 -0
  60. package/test/test-mover-rollback.ts +290 -0
  61. package/test/test-phase-h-carrier-pickable.ts +4 -3
  62. package/test/test-r19-place-absorb.ts +174 -0
  63. package/test/test-rack-3d-attach-real.ts +301 -0
  64. package/test/test-rack-concurrent.ts +254 -0
  65. package/test/test-rack-edge-cases.ts +323 -0
  66. package/test/test-rack-grid-cell.ts +318 -0
  67. package/test/test-rack-grid-location.ts +657 -0
  68. package/test/test-real-3d-positioning.ts +158 -0
  69. package/test/test-slot-center-convention.ts +116 -0
  70. package/test/test-slot-target.ts +189 -0
  71. package/test/test-storage-rack-batched.ts +606 -0
  72. package/test/test-storage-rack-click.ts +329 -0
  73. package/test/test-storage-rack-slot-api.ts +357 -0
  74. package/test/test-toscene-convention.ts +162 -0
  75. package/test/test-user-scenario-sequential.ts +334 -0
  76. package/translations/en.json +7 -1
  77. package/translations/ja.json +7 -1
  78. package/translations/ko.json +7 -1
  79. package/translations/ms.json +7 -1
  80. package/translations/zh.json +7 -1
  81. package/tsconfig.tsbuildinfo +1 -1
  82. package/dist/rack-column.d.ts +0 -35
  83. package/dist/rack-column.js +0 -258
  84. package/dist/rack-column.js.map +0 -1
  85. package/dist/rack-grid-helpers.d.ts +0 -28
  86. package/dist/rack-grid-helpers.js +0 -71
  87. package/dist/rack-grid-helpers.js.map +0 -1
  88. package/dist/rack-grid-location.d.ts +0 -37
  89. package/dist/rack-grid-location.js +0 -227
  90. package/dist/rack-grid-location.js.map +0 -1
  91. package/dist/storage-cell-3d.d.ts +0 -25
  92. package/dist/storage-cell-3d.js +0 -88
  93. package/dist/storage-cell-3d.js.map +0 -1
  94. package/dist/storage-cell.d.ts +0 -70
  95. package/dist/storage-cell.js +0 -197
  96. package/dist/storage-cell.js.map +0 -1
  97. package/src/rack-column.ts +0 -340
  98. package/src/rack-grid-helpers.ts +0 -77
  99. package/src/rack-grid-location.ts +0 -286
  100. package/src/storage-cell-3d.ts +0 -101
  101. package/src/storage-cell.ts +0 -247
  102. package/test/test-rack-grid.ts +0 -77
@@ -1,36 +1,56 @@
1
- import { __decorate } from "tslib";
2
1
  /*
3
2
  * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * RackGridCell — RackGrid 의 *configuration storage* 단위 = 한 bay 의 메타데이터 핸들.
5
+ *
6
+ * 모드별 역할:
7
+ * - modeling (2D editor): 자체 사각형 render + click + nature.properties UI
8
+ * (rack-table-cell 패턴 그대로)
9
+ * - 2D / 3D view: *data holder 만* — render/mesh 모두 X. 외부 location API 가
10
+ * 이 cell 의 state.section/unit/isEmpty 등을 *configuration source of truth* 로 lookup.
11
+ *
12
+ * 3D mesh 는 *없음* (buildRealObject = undefined). 3D stock 시각화는 *RackGrid
13
+ * 자체의 RackGrid3D + InstancedMesh* 가 처리. cell-component 는 *3D 리소스 0*.
14
+ *
15
+ * 영속 데이터: cellId (bay 위치), section, unit, shelfLocations, isEmpty, border 등.
16
+ * RackGrid 의 hierarchy override 가 *redundant 좌표 (left/top/width/height)* 만 제거 —
17
+ * 위 own 데이터는 그대로 직렬화 (저장/로드 시 복원).
4
18
  */
19
+ import { __decorate } from "tslib";
5
20
  import { Component, RectPath, sceneComponent } from '@hatiolab/things-scene';
6
- import { Rack } from './rack-column.js';
7
21
  const EMPTY_BORDER = {};
8
- function isBottomMost(idx, rows, columns) {
9
- return idx >= (rows - 1) * columns;
22
+ const EMPTY_CELL_FILL = '#efefef';
23
+ const EMPTY_CELL_STROKE = '#ccc';
24
+ function hasAnyProperty(o, ...props) {
25
+ for (const p of props)
26
+ if (Object.prototype.hasOwnProperty.call(o, p))
27
+ return true;
28
+ return false;
10
29
  }
11
- function isRightMost(idx, rows, columns) {
12
- return (idx + 1) % columns == 0;
30
+ function isRightMost(idx, _rows, columns) {
31
+ return (idx + 1) % columns === 0;
13
32
  }
14
- function hasAnyProperty(o, ...properties) {
15
- for (let p in properties) {
16
- if (o.hasOwnProperty(properties[p])) {
17
- return true;
18
- }
19
- }
33
+ function isBottomMost(idx, rows, columns) {
34
+ return idx >= (rows - 1) * columns;
20
35
  }
21
- const EMPTY_CELL_STROKE_STYLE = '#ccc';
22
- const EMPTY_CELL_LINE_WIDTH = 1;
23
- const EMPTY_CELL_FILL_STYLE = '#efefef';
24
- /**
25
- * 1. 스타일을 상속 받아야 함. (cascade-style)
26
- * 2. 스타일을 동적처리할 수 있음. (로직처리)
27
- * 3. 데이타를 받을 수 있음.
28
- */
36
+ // RackGridCell refid 충돌 회피 — load 시 root.onadded → _addTraverse 가 자식부터
37
+ // addRefidIndex 호출. cell 의 model.refid 가 *비어있으면* root.getNewRefid() = 1,2,3...
38
+ // 작은 부여 → 부모 RackGrid (refid 7) / Crane (202) 등 *기존 refid 와 충돌*.
39
+ // constructor 에서 *큰 시작값 + monotonic counter* 로 자체 부여 → 충돌 0.
40
+ let _cellRefidCounter = 100_000_000;
29
41
  let RackGridCell = class RackGridCell extends RectPath(Component) {
30
42
  get state() {
31
43
  return super.state;
32
44
  }
33
45
  _focused = false;
46
+ constructor(model, context) {
47
+ super(model, context);
48
+ // refid 미부여 시 큰 값 자체 부여 — root.getNewRefid() 의 1,2,3... 충돌 회피.
49
+ // hierarchy override 가 save 시 refid 제거 → load 마다 fresh.
50
+ if (this.model.refid == null) {
51
+ this.model.refid = _cellRefidCounter++;
52
+ }
53
+ }
34
54
  get hasTextProperty() {
35
55
  return false;
36
56
  }
@@ -40,33 +60,11 @@ let RackGridCell = class RackGridCell extends RectPath(Component) {
40
60
  resizable: true,
41
61
  rotatable: true,
42
62
  properties: [
43
- {
44
- type: 'string',
45
- label: 'section',
46
- name: 'section'
47
- },
48
- {
49
- type: 'string',
50
- label: 'unit',
51
- name: 'unit'
52
- },
53
- {
54
- type: 'string',
55
- label: 'shelf-locations',
56
- name: 'shelfLocations',
57
- placeholder: '1,2,3,... / ,,,04'
58
- },
59
- {
60
- type: 'textarea',
61
- label: 'bin-locations',
62
- name: 'binLocations',
63
- placeholder: '1,2,3,...'
64
- },
65
- {
66
- type: 'checkbox',
67
- label: 'is-empty',
68
- name: 'isEmpty'
69
- },
63
+ { type: 'string', label: 'section', name: 'section' },
64
+ { type: 'string', label: 'unit', name: 'unit' },
65
+ { type: 'string', label: 'shelf-locations', name: 'shelfLocations', placeholder: '1,2,3 또는 ,,,04' },
66
+ { type: 'textarea', label: 'bin-locations', name: 'binLocations', placeholder: '1,2,3,...' },
67
+ { type: 'checkbox', label: 'is-empty', name: 'isEmpty' },
70
68
  {
71
69
  type: 'location-increase-pattern',
72
70
  label: '',
@@ -75,8 +73,16 @@ let RackGridCell = class RackGridCell extends RectPath(Component) {
75
73
  event: {
76
74
  'increase-location-pattern': (event) => {
77
75
  const { increasingDirection, skipNumbering, startSection, startUnit } = event.detail;
78
- const rackTable = this.parent;
79
- rackTable.increaseLocation(increasingDirection, skipNumbering, startSection, startUnit);
76
+ const parent = this.parent;
77
+ if (typeof parent?.increaseLocation === 'function') {
78
+ // RackGrid 의 root.selected 활용 — framework 가 자동 갱신
79
+ const selected = this.root?.selected;
80
+ const keys = (selected || [])
81
+ .filter(c => c?.state?.type === 'rack-grid-cell')
82
+ .map(c => c.state.cellId)
83
+ .filter((k) => !!k);
84
+ parent.increaseLocation(keys, increasingDirection, skipNumbering, startSection, startUnit);
85
+ }
80
86
  }
81
87
  }
82
88
  }
@@ -85,237 +91,135 @@ let RackGridCell = class RackGridCell extends RectPath(Component) {
85
91
  type: 'editor-table',
86
92
  label: '',
87
93
  name: '',
88
- property: {
89
- merge: false,
90
- split: false
91
- }
94
+ property: { merge: false, split: false }
92
95
  }
93
96
  ]
94
97
  };
95
98
  }
99
+ /** 3D mesh 미생성 — view mode 의 리소스 0. */
96
100
  buildRealObject() {
97
- // isEmpty cell 은 3D 에 mesh 를 만들지 않는다. v9 에서는 RackGrid3D.createRacks 가
98
- // cell._realObject 를 사전 설정하면 3D pipeline 이 자동 buildRealObject 호출을 skip
99
- // 하던 것을, v10 의 ThreeCapability 도입 이후로는 *항상* 자동 호출됨. RackGrid3D
100
- // createRacks 의 isEmpty 체크와 이 자동 경로 사이의 불일치로 isEmpty=true cell 도
101
- // 3D 에 그려지던 regression — 여기 isEmpty 체크 추가로 두 경로 정합.
102
- if (this.getState('isEmpty'))
103
- return undefined;
104
- return new Rack(this);
101
+ return undefined;
105
102
  }
106
- set merged(merged) {
107
- this.set('merged', !!merged);
108
- if (merged)
109
- this.set('text', '');
110
- }
111
- get merged() {
112
- return this.getState('merged');
113
- }
114
- set rowspan(rowspan) {
115
- this.set('rowspan', rowspan);
116
- }
117
- get rowspan() {
118
- return this.getState('rowspan');
119
- }
120
- set colspan(colspan) {
121
- this.set('colspan', colspan);
122
- }
123
- get colspan() {
124
- return this.getState('colspan');
103
+ // ── Domain getters ────────────────────────────────────
104
+ get isEmpty() {
105
+ return !!this.getState('isEmpty');
125
106
  }
126
107
  get border() {
127
108
  return this.state.border || EMPTY_BORDER;
128
109
  }
129
- get isEmpty() {
130
- return this.getState('isEmpty');
110
+ set merged(v) {
111
+ this.set('merged', !!v);
112
+ if (v)
113
+ this.set('text', '');
131
114
  }
132
- _drawBorder(context, x, y, to_x, to_y, style) {
133
- if (style && style.strokeStyle && style.lineWidth && style.lineDash) {
134
- context.beginPath();
135
- context.moveTo(x, y);
136
- context.lineTo(to_x, to_y);
137
- Component.drawStroke(context, style);
138
- }
115
+ get merged() {
116
+ return !!this.getState('merged');
139
117
  }
140
- render(context) {
141
- const { left, top, width, height } = this.bounds;
142
- const { isEmpty } = this.state;
143
- const border = this.border;
144
- if (!isEmpty) {
145
- this._draw_rack_cell(context);
146
- }
147
- // Cell 채우기.
148
- context.beginPath();
149
- context.lineWidth = 0;
150
- context.rect(left, top, width, height);
151
- // Border 그리기
118
+ set rowspan(v) { this.set('rowspan', v); }
119
+ get rowspan() { return this.getState('rowspan') ?? 1; }
120
+ set colspan(v) { this.set('colspan', v); }
121
+ get colspan() { return this.getState('colspan') ?? 1; }
122
+ /** Parent (RackGrid) 안에서 자기 (col, row) 인덱스 — components 순서 = row * columns + col. */
123
+ get index() {
152
124
  const parent = this.parent;
125
+ if (!parent)
126
+ return { row: 0, column: 0 };
153
127
  const idx = parent.components.indexOf(this);
154
- const columns = parent.columns || 1;
155
- const rows = parent.rows || 1;
156
- this._drawBorder(context, left, top, left + width, top, border.top);
157
- this._drawBorder(context, left, top + height, left, top, border.left);
158
- if (isRightMost(idx, rows, columns))
159
- this._drawBorder(context, left + width, top, left + width, top + height, border.right);
160
- if (isBottomMost(idx, rows, columns))
161
- this._drawBorder(context, left + width, top + height, left, top + height, border.bottom);
162
- }
163
- _draw_rack_cell(context) {
164
- const { left, top, width, height } = this.bounds;
165
- context.save();
166
- context.fillStyle = EMPTY_CELL_FILL_STYLE;
167
- context.fillRect(left, top, width, height);
168
- context.beginPath();
169
- context.lineWidth = EMPTY_CELL_LINE_WIDTH;
170
- context.strokeStyle = EMPTY_CELL_STROKE_STYLE;
171
- context.moveTo(left, top);
172
- context.lineTo(left + width, top + height);
173
- context.moveTo(left + width, top);
174
- context.lineTo(left, top + height);
175
- context.stroke();
176
- context.closePath();
177
- context.restore();
178
- }
179
- get decotag() {
180
- const rackTable = this.parent;
181
- let { locPattern, zone = '' } = rackTable.model;
182
- locPattern = locPattern.substring(0, locPattern.indexOf('{u}') + 3);
183
- let locationString = '';
184
- if (this.getState('section') && this.getState('unit'))
185
- locationString = locPattern
186
- .replace('{z}', zone)
187
- .replace('{s}', this.getState('section'))
188
- .replace('{u}', this.getState('unit'));
189
- return locationString || '';
190
- }
191
- get index() {
192
- const rackTable = this.parent;
193
- const index = rackTable.components.indexOf(this);
194
- const rowIndex = Math.floor(index / rackTable.columns);
195
- const columnIndex = index % rackTable.columns;
196
- return {
197
- row: rowIndex,
198
- column: columnIndex
199
- };
200
- }
201
- get rowIndex() {
202
- return this.index.row;
203
- }
204
- get columnIndex() {
205
- return this.index.column;
206
- }
207
- get leftCell() {
208
- const rackTable = this.parent;
209
- const rowIndex = this.rowIndex;
210
- const columnIndex = this.columnIndex;
211
- if (columnIndex === 0)
212
- return null;
213
- const leftCell = rackTable.components[rowIndex * rackTable.columns + columnIndex - 1];
214
- return leftCell;
215
- }
216
- get rightCell() {
217
- const rackTable = this.parent;
218
- const rowIndex = this.rowIndex;
219
- const columnIndex = this.columnIndex;
220
- if (columnIndex === rackTable.columns)
221
- return null;
222
- const rightCell = rackTable.components[rowIndex * rackTable.columns + columnIndex + 1];
223
- return rightCell;
224
- }
225
- get aboveCell() {
226
- const rackTable = this.parent;
227
- const rowIndex = this.rowIndex;
228
- const columnIndex = this.columnIndex;
229
- if (rowIndex === 0)
230
- return null;
231
- const aboveCell = rackTable.components[(rowIndex - 1) * rackTable.columns + columnIndex];
232
- return aboveCell;
233
- }
234
- get belowCell() {
235
- const rackTable = this.parent;
236
- const rowIndex = this.rowIndex;
237
- const columnIndex = this.columnIndex;
238
- if (rowIndex === rackTable.rows)
239
- return null;
240
- const belowCell = rackTable.components[(rowIndex + 1) * rackTable.columns + columnIndex];
241
- return belowCell;
128
+ const cols = parent.columns ?? 1;
129
+ return { row: Math.floor(idx / cols), column: idx % cols };
242
130
  }
131
+ get rowIndex() { return this.index.row; }
132
+ get columnIndex() { return this.index.column; }
243
133
  get rowCells() {
244
- const rackTable = this.parent;
245
- return rackTable.getCellsByRow(this.rowIndex);
134
+ const parent = this.parent;
135
+ return parent?.getCellsByRow?.(this.rowIndex) ?? [];
246
136
  }
247
137
  get columnCells() {
248
- const rackTable = this.parent;
249
- return rackTable.getCellsByColumn(this.columnIndex);
250
- }
251
- get aboveRowCells() {
252
- let aboveCell = this.aboveCell;
253
- while (1) {
254
- const aboveRowCells = aboveCell.notEmptyRowCells;
255
- if (aboveRowCells.length > 0)
256
- return aboveRowCells;
257
- aboveCell = aboveCell.aboveCell;
258
- }
259
- }
260
- get lastUnit() {
261
- const rowCells = this.aboveRowCells;
262
- for (let i = rowCells.length - 1; i > 0; i--) {
263
- const cell = rowCells[i];
264
- const unit = cell.getState('unit');
265
- if (unit)
266
- return Number(unit);
267
- }
268
- return 0;
269
- }
270
- get firstUnit() {
271
- const rowCells = this.aboveRowCells;
272
- for (let i = 0; i < rowCells.length; i++) {
273
- const cell = rowCells[i];
274
- const unit = cell.getState('unit');
275
- if (unit)
276
- return Number(unit);
277
- }
278
- return 0;
138
+ const parent = this.parent;
139
+ return parent?.getCellsByColumn?.(this.columnIndex) ?? [];
279
140
  }
280
141
  get notEmptyRowCells() {
281
- return this.rowCells.filter((c) => {
282
- return !c.getState('isEmpty');
283
- });
284
- }
285
- get emptyRowCells() {
286
- return this.rowCells.filter((c) => {
287
- return c.getState('isEmpty');
288
- });
142
+ return this.rowCells.filter(c => !c.getState?.('isEmpty'));
289
143
  }
290
144
  get isAisle() {
291
145
  return this.notEmptyRowCells.length === 0;
292
146
  }
293
- onchange(after, before) {
147
+ // ── Lifecycle ─────────────────────────────────────────
148
+ onchange(after, _before) {
294
149
  if (hasAnyProperty(after, 'isEmpty')) {
295
- // FIXME
150
+ // isEmpty 토글 시 section/unit 클리어 (rack-table-cell 동작)
296
151
  delete this.model.unit;
297
152
  delete this.model.section;
298
153
  }
154
+ // Parent 의 location index 무효화 (RackGrid 가 onchange 다시 안 받으므로 자식이 알림)
155
+ const parent = this.parent;
156
+ parent?.invalidateLocationIndex?.();
299
157
  }
300
- onmouseenter() {
301
- this.trigger('deco');
302
- }
303
- onmouseleave() {
304
- this.trigger('decoreset');
305
- }
158
+ onmouseenter() { this.trigger('deco'); }
159
+ onmouseleave() { this.trigger('decoreset'); }
306
160
  contains(x, y) {
307
- const contains = super.contains(x, y);
308
- if (!contains) {
161
+ const c = super.contains(x, y);
162
+ if (!c) {
309
163
  this._focused = false;
310
164
  this.invalidate();
311
165
  }
312
- return contains;
166
+ return c;
167
+ }
168
+ // ── 2D rendering (modeling editor) ────────────────────
169
+ //
170
+ // *view mode* (= app.isViewMode) 면 안 그림 — *configuration storage 만*. modeling
171
+ // 시에만 사각형 + border + isEmpty 패턴 시각화.
172
+ render(context) {
173
+ if (this.app?.isViewMode)
174
+ return;
175
+ const { left, top, width, height } = this.bounds;
176
+ const { isEmpty } = this.state;
177
+ const border = this.border;
178
+ if (isEmpty) {
179
+ // 빈 cell — 회색 fill + 대각선
180
+ context.save();
181
+ context.fillStyle = EMPTY_CELL_FILL;
182
+ context.fillRect(left, top, width, height);
183
+ context.strokeStyle = EMPTY_CELL_STROKE;
184
+ context.lineWidth = 1;
185
+ context.beginPath();
186
+ context.moveTo(left, top);
187
+ context.lineTo(left + width, top + height);
188
+ context.moveTo(left + width, top);
189
+ context.lineTo(left, top + height);
190
+ context.stroke();
191
+ context.restore();
192
+ }
193
+ // 명시적 cell 영역 표시 (border default — 자식 cell 의 미니 frame)
194
+ context.beginPath();
195
+ context.lineWidth = 0;
196
+ context.rect(left, top, width, height);
197
+ const parent = this.parent;
198
+ const idx = parent?.components?.indexOf?.(this) ?? 0;
199
+ const columns = parent?.columns ?? 1;
200
+ const rows = parent?.rackRows ?? 1;
201
+ this._drawSide(context, left, top, left + width, top, border.top);
202
+ this._drawSide(context, left, top + height, left, top, border.left);
203
+ if (isRightMost(idx, rows, columns)) {
204
+ this._drawSide(context, left + width, top, left + width, top + height, border.right);
205
+ }
206
+ if (isBottomMost(idx, rows, columns)) {
207
+ this._drawSide(context, left + width, top + height, left, top + height, border.bottom);
208
+ }
209
+ }
210
+ _drawSide(ctx, x, y, tx, ty, style) {
211
+ if (!style?.strokeStyle || !style.lineWidth)
212
+ return;
213
+ ctx.beginPath();
214
+ ctx.moveTo(x, y);
215
+ ctx.lineTo(tx, ty);
216
+ Component.drawStroke(ctx, style);
313
217
  }
314
218
  };
315
219
  RackGridCell = __decorate([
316
220
  sceneComponent('rack-grid-cell')
317
221
  ], RackGridCell);
318
- export { RackGridCell };
222
+ export default RackGridCell;
319
223
  ;
320
- ['border'].forEach(getter => Component.memoize(RackGridCell.prototype, getter, false));
224
+ ['border'].forEach(g => Component.memoize(RackGridCell.prototype, g, false));
321
225
  //# sourceMappingURL=rack-grid-cell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rack-grid-cell.js","sourceRoot":"","sources":["../src/rack-grid-cell.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\nimport { Component, Properties, RectPath, sceneComponent, RealObject } from '@hatiolab/things-scene'\nimport type { State } from '@hatiolab/things-scene'\nimport { Rack } from './rack-column.js'\n\n/** RackGridCell 컴포넌트 state */\nexport interface RackGridCellState extends State {\n section?: string\n unit?: string\n shelfLocations?: string\n binLocations?: string\n isEmpty?: boolean\n border?: any\n merged?: boolean\n rowspan?: number\n colspan?: number\n}\n\nconst EMPTY_BORDER = {}\n\nfunction isBottomMost(idx: number, rows: number, columns: number) {\n return idx >= (rows - 1) * columns\n}\n\nfunction isRightMost(idx: number, rows: number, columns: number) {\n return (idx + 1) % columns == 0\n}\n\nfunction hasAnyProperty(o: any, ...properties: string[]) {\n for (let p in properties) {\n if (o.hasOwnProperty(properties[p])) {\n return true\n }\n }\n}\n\nconst EMPTY_CELL_STROKE_STYLE = '#ccc'\nconst EMPTY_CELL_LINE_WIDTH = 1\nconst EMPTY_CELL_FILL_STYLE = '#efefef'\n\n/**\n * 1. 스타일을 상속 받아야 함. (cascade-style)\n * 2. 스타일을 동적처리할 수 있음. (로직처리)\n * 3. 데이타를 받을 수 있음.\n */\n@sceneComponent('rack-grid-cell')\nexport class RackGridCell extends RectPath(Component) {\n override get state(): RackGridCellState {\n return super.state as RackGridCellState\n }\n\n _focused: boolean = false\n\n get hasTextProperty() {\n return false\n }\n\n get nature() {\n return {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n {\n type: 'string',\n label: 'section',\n name: 'section'\n },\n {\n type: 'string',\n label: 'unit',\n name: 'unit'\n },\n {\n type: 'string',\n label: 'shelf-locations',\n name: 'shelfLocations',\n placeholder: '1,2,3,... / ,,,04'\n },\n {\n type: 'textarea',\n label: 'bin-locations',\n name: 'binLocations',\n placeholder: '1,2,3,...'\n },\n {\n type: 'checkbox',\n label: 'is-empty',\n name: 'isEmpty'\n },\n {\n type: 'location-increase-pattern',\n label: '',\n name: '',\n property: {\n event: {\n 'increase-location-pattern': (event: CustomEvent) => {\n const { increasingDirection, skipNumbering, startSection, startUnit } = event.detail\n const rackTable = this.parent as any\n rackTable.increaseLocation(increasingDirection, skipNumbering, startSection, startUnit)\n }\n }\n }\n },\n {\n type: 'editor-table',\n label: '',\n name: '',\n property: {\n merge: false,\n split: false\n }\n }\n ]\n }\n }\n\n buildRealObject(): RealObject | undefined {\n // isEmpty cell 은 3D 에 mesh 를 만들지 않는다. v9 에서는 RackGrid3D.createRacks 가\n // cell._realObject 를 사전 설정하면 3D pipeline 이 자동 buildRealObject 호출을 skip\n // 하던 것을, v10 의 ThreeCapability 도입 이후로는 *항상* 자동 호출됨. RackGrid3D\n // createRacks 의 isEmpty 체크와 이 자동 경로 사이의 불일치로 isEmpty=true cell 도\n // 3D 에 그려지던 regression — 여기 isEmpty 체크 추가로 두 경로 정합.\n if (this.getState('isEmpty')) return undefined\n return new Rack(this)\n }\n\n set merged(merged) {\n this.set('merged', !!merged)\n if (merged) this.set('text', '')\n }\n\n get merged() {\n return this.getState('merged')\n }\n\n set rowspan(rowspan) {\n this.set('rowspan', rowspan)\n }\n\n get rowspan() {\n return this.getState('rowspan')\n }\n\n set colspan(colspan) {\n this.set('colspan', colspan)\n }\n\n get colspan() {\n return this.getState('colspan')\n }\n\n get border() {\n return this.state.border || EMPTY_BORDER\n }\n\n get isEmpty() {\n return this.getState('isEmpty')\n }\n\n _drawBorder(context: CanvasRenderingContext2D, x: number, y: number, to_x: number, to_y: number, style: any) {\n if (style && style.strokeStyle && style.lineWidth && style.lineDash) {\n context.beginPath()\n context.moveTo(x, y)\n context.lineTo(to_x, to_y)\n\n Component.drawStroke(context, style)\n }\n }\n\n render(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n const { isEmpty } = this.state\n\n const border = this.border\n\n if (!isEmpty) {\n this._draw_rack_cell(context)\n }\n\n // Cell 채우기.\n context.beginPath()\n context.lineWidth = 0\n context.rect(left, top, width, height)\n\n // Border 그리기\n const parent = this.parent as any\n const idx = parent.components.indexOf(this)\n const columns = parent.columns || 1\n const rows = parent.rows || 1\n\n this._drawBorder(context, left, top, left + width, top, border.top)\n this._drawBorder(context, left, top + height, left, top, border.left)\n if (isRightMost(idx, rows, columns))\n this._drawBorder(context, left + width, top, left + width, top + height, border.right)\n if (isBottomMost(idx, rows, columns))\n this._drawBorder(context, left + width, top + height, left, top + height, border.bottom)\n }\n\n _draw_rack_cell(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n context.save()\n context.fillStyle = EMPTY_CELL_FILL_STYLE\n context.fillRect(left, top, width, height)\n\n context.beginPath()\n context.lineWidth = EMPTY_CELL_LINE_WIDTH\n context.strokeStyle = EMPTY_CELL_STROKE_STYLE\n\n context.moveTo(left, top)\n context.lineTo(left + width, top + height)\n context.moveTo(left + width, top)\n context.lineTo(left, top + height)\n\n context.stroke()\n context.closePath()\n context.restore()\n }\n\n get decotag() {\n const rackTable = this.parent\n let { locPattern, zone = '' } = rackTable.model\n\n locPattern = locPattern.substring(0, locPattern.indexOf('{u}') + 3)\n\n let locationString = ''\n if (this.getState('section') && this.getState('unit'))\n locationString = locPattern\n .replace('{z}', zone)\n .replace('{s}', this.getState('section'))\n .replace('{u}', this.getState('unit'))\n\n return locationString || ''\n }\n\n get index() {\n const rackTable = this.parent as any\n const index = rackTable.components.indexOf(this)\n\n const rowIndex = Math.floor(index / rackTable.columns)\n const columnIndex = index % rackTable.columns\n\n return {\n row: rowIndex,\n column: columnIndex\n }\n }\n\n get rowIndex() {\n return this.index.row\n }\n\n get columnIndex() {\n return this.index.column\n }\n\n get leftCell() {\n const rackTable = this.parent as any\n\n const rowIndex = this.rowIndex\n const columnIndex = this.columnIndex\n\n if (columnIndex === 0) return null\n\n const leftCell = rackTable.components[rowIndex * rackTable.columns + columnIndex - 1]\n\n return leftCell\n }\n\n get rightCell() {\n const rackTable = this.parent as any\n\n const rowIndex = this.rowIndex\n const columnIndex = this.columnIndex\n\n if (columnIndex === rackTable.columns) return null\n\n const rightCell = rackTable.components[rowIndex * rackTable.columns + columnIndex + 1]\n\n return rightCell\n }\n\n get aboveCell() {\n const rackTable = this.parent as any\n\n const rowIndex = this.rowIndex\n const columnIndex = this.columnIndex\n\n if (rowIndex === 0) return null\n\n const aboveCell = rackTable.components[(rowIndex - 1) * rackTable.columns + columnIndex]\n\n return aboveCell\n }\n\n get belowCell() {\n const rackTable = this.parent as any\n\n const rowIndex = this.rowIndex\n const columnIndex = this.columnIndex\n\n if (rowIndex === rackTable.rows) return null\n\n const belowCell = rackTable.components[(rowIndex + 1) * rackTable.columns + columnIndex]\n\n return belowCell\n }\n\n get rowCells() {\n const rackTable = this.parent as any\n return rackTable.getCellsByRow(this.rowIndex)\n }\n\n get columnCells() {\n const rackTable = this.parent as any\n return rackTable.getCellsByColumn(this.columnIndex)\n }\n\n get aboveRowCells() {\n let aboveCell = this.aboveCell\n while (1) {\n const aboveRowCells = aboveCell.notEmptyRowCells\n\n if (aboveRowCells.length > 0) return aboveRowCells\n\n aboveCell = aboveCell.aboveCell\n }\n }\n\n get lastUnit() {\n const rowCells = this.aboveRowCells\n\n for (let i = rowCells.length - 1; i > 0; i--) {\n const cell = rowCells[i]\n\n const unit = cell.getState('unit')\n\n if (unit) return Number(unit)\n }\n\n return 0\n }\n\n get firstUnit() {\n const rowCells = this.aboveRowCells\n\n for (let i = 0; i < rowCells.length; i++) {\n const cell = rowCells[i]\n\n const unit = cell.getState('unit')\n\n if (unit) return Number(unit)\n }\n\n return 0\n }\n\n get notEmptyRowCells() {\n return this.rowCells.filter((c: Component) => {\n return !c.getState('isEmpty')\n })\n }\n\n get emptyRowCells() {\n return this.rowCells.filter((c: Component) => {\n return c.getState('isEmpty')\n })\n }\n\n get isAisle() {\n return this.notEmptyRowCells.length === 0\n }\n\n onchange(after: Properties, before: Properties) {\n if (hasAnyProperty(after, 'isEmpty')) {\n // FIXME\n delete this.model.unit\n delete this.model.section\n }\n }\n\n onmouseenter() {\n this.trigger('deco')\n }\n\n onmouseleave() {\n this.trigger('decoreset')\n }\n\n contains(x: number, y: number) {\n const contains = super.contains(x, y)\n if (!contains) {\n this._focused = false\n this.invalidate()\n }\n\n return contains\n }\n}\n\n;['border'].forEach(getter => Component.memoize(RackGridCell.prototype, getter, false))\n"]}
1
+ {"version":3,"file":"rack-grid-cell.js","sourceRoot":"","sources":["../src/rack-grid-cell.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * RackGridCell — RackGrid 의 *configuration storage* 단위 = 한 bay 의 메타데이터 핸들.\n *\n * 모드별 역할:\n * - modeling (2D editor): 자체 사각형 render + click + nature.properties UI\n * (rack-table-cell 패턴 그대로)\n * - 2D / 3D view: *data holder 만* — render/mesh 모두 X. 외부 location API 가\n * 이 cell 의 state.section/unit/isEmpty 등을 *configuration source of truth* 로 lookup.\n *\n * 3D mesh 는 *없음* (buildRealObject = undefined). 3D stock 시각화는 *RackGrid\n * 자체의 RackGrid3D + InstancedMesh* 가 처리. cell-component 는 *3D 리소스 0*.\n *\n * 영속 데이터: cellId (bay 위치), section, unit, shelfLocations, isEmpty, border 등.\n * RackGrid 의 hierarchy override 가 *redundant 좌표 (left/top/width/height)* 만 제거 —\n * 위 own 데이터는 그대로 직렬화 (저장/로드 시 복원).\n */\n\nimport {\n Component, ComponentNature, Properties, RectPath, sceneComponent\n} from '@hatiolab/things-scene'\nimport type { State } from '@hatiolab/things-scene'\n\nexport interface RackGridCellState extends State {\n cellId?: string // bayKey 형식: `${col-1}-${row-1}` (0-based, 2 segments)\n section?: string // location 의 {s}\n unit?: string // location 의 {u}\n shelfLocations?: string // cell 별 shelf 명시 (CSV); 미지정 시 parent.shelfLocations\n binLocations?: string // cell 내 bin 명시 (CSV) — rack-table 호환\n isEmpty?: boolean // 통로/공실 표시\n border?: any // 4-side border (top/left/bottom/right)\n merged?: boolean\n rowspan?: number\n colspan?: number\n}\n\nconst EMPTY_BORDER = {}\nconst EMPTY_CELL_FILL = '#efefef'\nconst EMPTY_CELL_STROKE = '#ccc'\n\nfunction hasAnyProperty(o: any, ...props: string[]): boolean {\n for (const p of props) if (Object.prototype.hasOwnProperty.call(o, p)) return true\n return false\n}\n\nfunction isRightMost(idx: number, _rows: number, columns: number): boolean {\n return (idx + 1) % columns === 0\n}\nfunction isBottomMost(idx: number, rows: number, columns: number): boolean {\n return idx >= (rows - 1) * columns\n}\n\n// RackGridCell 의 refid 충돌 회피 — load 시 root.onadded → _addTraverse 가 자식부터\n// addRefidIndex 호출. cell 의 model.refid 가 *비어있으면* root.getNewRefid() = 1,2,3...\n// 작은 값 부여 → 부모 RackGrid (refid 7) / Crane (202) 등 *기존 refid 와 충돌*.\n// constructor 에서 *큰 시작값 + monotonic counter* 로 자체 부여 → 충돌 0.\nlet _cellRefidCounter = 100_000_000\n\n@sceneComponent('rack-grid-cell')\nexport default class RackGridCell extends RectPath(Component) {\n override get state(): RackGridCellState {\n return super.state as RackGridCellState\n }\n\n _focused: boolean = false\n\n constructor(model: any, context: any) {\n super(model, context)\n // refid 미부여 시 큰 값 자체 부여 — root.getNewRefid() 의 1,2,3... 충돌 회피.\n // hierarchy override 가 save 시 refid 제거 → load 마다 fresh.\n if (this.model.refid == null) {\n this.model.refid = _cellRefidCounter++\n }\n }\n\n get hasTextProperty() {\n return false\n }\n\n get nature(): ComponentNature {\n return {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n { type: 'string', label: 'section', name: 'section' },\n { type: 'string', label: 'unit', name: 'unit' },\n { type: 'string', label: 'shelf-locations', name: 'shelfLocations', placeholder: '1,2,3 또는 ,,,04' },\n { type: 'textarea', label: 'bin-locations', name: 'binLocations', placeholder: '1,2,3,...' },\n { type: 'checkbox', label: 'is-empty', name: 'isEmpty' },\n {\n type: 'location-increase-pattern',\n label: '',\n name: '',\n property: {\n event: {\n 'increase-location-pattern': (event: CustomEvent) => {\n const { increasingDirection, skipNumbering, startSection, startUnit } = event.detail\n const parent: any = this.parent\n if (typeof parent?.increaseLocation === 'function') {\n // RackGrid 의 root.selected 활용 — framework 가 자동 갱신\n const selected = (this.root as any)?.selected as RackGridCell[] | undefined\n const keys = (selected || [])\n .filter(c => (c as any)?.state?.type === 'rack-grid-cell')\n .map(c => c.state.cellId)\n .filter((k): k is string => !!k)\n parent.increaseLocation(keys, increasingDirection, skipNumbering, startSection, startUnit)\n }\n }\n }\n }\n },\n {\n type: 'editor-table',\n label: '',\n name: '',\n property: { merge: false, split: false }\n }\n ]\n }\n }\n\n /** 3D mesh 미생성 — view mode 의 리소스 0. */\n buildRealObject(): undefined {\n return undefined\n }\n\n // ── Domain getters ────────────────────────────────────\n\n get isEmpty(): boolean {\n return !!this.getState('isEmpty')\n }\n\n get border(): any {\n return this.state.border || EMPTY_BORDER\n }\n\n set merged(v: boolean) {\n this.set('merged', !!v)\n if (v) this.set('text', '')\n }\n get merged(): boolean {\n return !!this.getState('merged')\n }\n\n set rowspan(v: number) { this.set('rowspan', v) }\n get rowspan(): number { return (this.getState('rowspan') as number) ?? 1 }\n\n set colspan(v: number) { this.set('colspan', v) }\n get colspan(): number { return (this.getState('colspan') as number) ?? 1 }\n\n /** Parent (RackGrid) 안에서 자기 (col, row) 인덱스 — components 순서 = row * columns + col. */\n get index(): { row: number; column: number } {\n const parent = this.parent as any\n if (!parent) return { row: 0, column: 0 }\n const idx = parent.components.indexOf(this)\n const cols = parent.columns ?? 1\n return { row: Math.floor(idx / cols), column: idx % cols }\n }\n\n get rowIndex(): number { return this.index.row }\n get columnIndex(): number { return this.index.column }\n\n get rowCells(): Component[] {\n const parent = this.parent as any\n return parent?.getCellsByRow?.(this.rowIndex) ?? []\n }\n get columnCells(): Component[] {\n const parent = this.parent as any\n return parent?.getCellsByColumn?.(this.columnIndex) ?? []\n }\n get notEmptyRowCells(): Component[] {\n return this.rowCells.filter(c => !(c as any).getState?.('isEmpty'))\n }\n get isAisle(): boolean {\n return this.notEmptyRowCells.length === 0\n }\n\n // ── Lifecycle ─────────────────────────────────────────\n\n onchange(after: Properties, _before: Properties) {\n if (hasAnyProperty(after, 'isEmpty')) {\n // isEmpty 토글 시 section/unit 클리어 (rack-table-cell 동작)\n delete this.model.unit\n delete this.model.section\n }\n // Parent 의 location index 무효화 (RackGrid 가 onchange 다시 안 받으므로 자식이 알림)\n const parent: any = this.parent\n parent?.invalidateLocationIndex?.()\n }\n\n onmouseenter() { this.trigger('deco') }\n onmouseleave() { this.trigger('decoreset') }\n\n contains(x: number, y: number) {\n const c = super.contains(x, y)\n if (!c) {\n this._focused = false\n this.invalidate()\n }\n return c\n }\n\n // ── 2D rendering (modeling editor) ────────────────────\n //\n // *view mode* (= app.isViewMode) 면 안 그림 — *configuration storage 만*. modeling\n // 시에만 사각형 + border + isEmpty 패턴 시각화.\n\n render(context: CanvasRenderingContext2D) {\n if ((this as any).app?.isViewMode) return\n\n const { left, top, width, height } = this.bounds\n const { isEmpty } = this.state\n const border = this.border\n\n if (isEmpty) {\n // 빈 cell — 회색 fill + 대각선\n context.save()\n context.fillStyle = EMPTY_CELL_FILL\n context.fillRect(left, top, width, height)\n context.strokeStyle = EMPTY_CELL_STROKE\n context.lineWidth = 1\n context.beginPath()\n context.moveTo(left, top); context.lineTo(left + width, top + height)\n context.moveTo(left + width, top); context.lineTo(left, top + height)\n context.stroke()\n context.restore()\n }\n\n // 명시적 cell 영역 표시 (border default — 자식 cell 의 미니 frame)\n context.beginPath()\n context.lineWidth = 0\n context.rect(left, top, width, height)\n\n const parent = this.parent as any\n const idx = parent?.components?.indexOf?.(this) ?? 0\n const columns = parent?.columns ?? 1\n const rows = parent?.rackRows ?? 1\n\n this._drawSide(context, left, top, left + width, top, border.top)\n this._drawSide(context, left, top + height, left, top, border.left)\n if (isRightMost(idx, rows, columns)) {\n this._drawSide(context, left + width, top, left + width, top + height, border.right)\n }\n if (isBottomMost(idx, rows, columns)) {\n this._drawSide(context, left + width, top + height, left, top + height, border.bottom)\n }\n }\n\n private _drawSide(ctx: CanvasRenderingContext2D, x: number, y: number, tx: number, ty: number, style: any) {\n if (!style?.strokeStyle || !style.lineWidth) return\n ctx.beginPath()\n ctx.moveTo(x, y)\n ctx.lineTo(tx, ty)\n Component.drawStroke(ctx, style)\n }\n}\n\n;['border'].forEach(g => Component.memoize(RackGridCell.prototype, g, false))\n"]}