@things-factory/station 10.1.36 → 10.1.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,8 +79,9 @@ plant · warehouse · yms · ems 가 각자 한 번씩 한다. 기계에 기본
79
79
  ### 아직 안 정해진 것
80
80
 
81
81
  `act()` 의 **몸통**. 동작 이름 여섯(`start` · `count` · `pause` · `unstage` · `resume` · `finish`)은
82
- 창고에서도 서는 말인데, 그 안은 `startTask({ jobOrderName: … })` 처럼 제품의 인자 이름을 직접 짓는다.
83
- 제품이 그것을 어떻게 갈아 끼우는지가 1층에 아직 없다.
82
+ 창고에서도 서는 말인데, 그 안은 `startTask({ jobOrderName: … })` 처럼 제품의 인자 이름을 직접 짓고, plant 의
83
+ `station-facts` 가 제품의 mutation 둘(실적 · 설비 상태 구간)을 직접 부른다. 제품이 그것을 어떻게 갈아 끼우는지가
84
+ 1층에 아직 없다 — 아키텍트 판정 대기(ADR-0083 3-다).
84
85
 
85
86
  ## 배정 축은 표준의 총칭이다
86
87
 
@@ -105,20 +106,49 @@ plant · warehouse · yms · ems 가 각자 한 번씩 한다. 기계에 기본
105
106
  **plant 에 남는 것** — 선언 다섯의 구현(`station-context-service` 등 8 파일) · 컴포저 · 모델러 ·
106
107
  현장 화면 페이지 · 씬 컴포넌트.
107
108
 
108
- ## 아직 안 온 것
109
+ ## 아직 안 온 것 (2026-09-24 오후)
109
110
 
110
- - **클라이언트.** `client/station` 55 파일 6,257 줄. 씬 열하나 중 여섯이 공통이고 다섯이 제품의 것이다.
111
- 그 확장점의 모양을 UX 레인이 정한다 (ADR-0083 결정 6).
112
- - **컴포저 · 모델러 화면.** 공용이 되는 저작 화면의 틀을 UX 레인이 본다 (ADR-0083 「열어 둔 것」).
113
- - **`Reversibility`.** `server/service/station/reversibility.ts` 에 네 값이 있다. 같은 어휘를 plant 의 활동
114
- 선언 열 개가 쓰고 worklist 가 역할 이름으로 갖고 있다 — 집을 수석 아키텍트가 정한다.
111
+ **operato-plant 는 이제 이 꾸러미의 화면도 쓴다**(3-가, operato-application `1a1c5c9`). 공통 씬 여섯과 바탕은 여기 것만 돈다.
115
112
 
116
- ## plant 가 자기 사본을 걷을 때 할 일
113
+ 앱이 할 일은 둘이다. **씬 등록을 드러나게 부른다** — 이 꾸러미의 입구는 씬을 등록하지 않는다(도우미만 가져오는 쪽에 씬 여섯과
114
+ things-scene 이 따라오지 않게):
115
+
116
+ ```ts
117
+ import '@things-factory/station/dist-client/station/scene/index.js'
118
+ ```
119
+
120
+ **팔레트를 세운다** — 이 꾸러미의 공통 다섯은 `things-scene.config.js` 로 그물에 걸리지만 그물은 **모으기만** 한다. 앱의
121
+ bootstrap 이 `things-scene-components-with-tools` 를 읽어 `registerGroup` · `registerTemplate` 한다. 앱 자신의 타일은 그물에 안
122
+ 걸리므로 손으로 걸되 **그물 뒤에** 건다 — 들어갈 `station` 그룹이 여기서 나오고, 없는 그룹의 항목은 오류 없이 버려진다.
117
123
 
118
- 발행 · 설치 뒤다. 그 전까지 plant 는 자기 것을 그대로 돌리고 여기 것은 안 부른다.
124
+ 남은 것은 ADR-0083 「걸음 3 을 넷으로 나눈다」가 정본이다:
125
+
126
+ ```
127
+ 3-나 남은 기계 이음매 아홉을 plant 에서 가른다 저작 검사 — 항목의 필수 칸 check (UX 판정)
128
+ 3-다 동작 몸통 StationClientProduct.perform (아키텍트 판정, 고친 판)
129
+ 3-라 저작 화면(컴포저 · 모델러 …) UX 가 틀을 먼저 본다
130
+ 걸음 4 창고가 건다 창고가 부를 문은 섰다 · 선언 다섯을 글로 적는 것이 남았다
131
+ ```
132
+
133
+ ## plant 가 자기 사본을 걷을 때 할 일
119
134
 
120
- - 옮긴 26 + 2 + 4 파일과 그 시험 15 개를 지운다
121
- - 낱말표에서 위 39 개 키를 지운다
122
- - `required-activities.ts` 에서 저작 결재 둘을 뺀다 — 이 모듈이 스스로 등록한다
123
- - `deletionChanges` 를 이 모듈에서 가져온다 (`activity-non-working-withdrawal` 도 쓴다)
124
- - `declareStationProduct` 에 `recordChange` 를 채운다 — 없으면 기동 때 거절한다
135
+ ### 서버 — 했다 (09-20 `23bc7e1` · 09-22 확인)
136
+
137
+ - 옮긴 26 + 2 파일과 그 시험을 지웠다. 제품 쪽 여덟은 선언 다섯의 구현으로 남았다.
138
+ - `declareStationProduct` 에 `recordChange` 를 채웠다 — 걷는 순간 기동 검사가 비었다고 잡았다.
139
+ - `required-activities.ts` 에서 저작 결재 둘은 **안 뺐다.** 이 꾸러미도 등록하지만 같은 이름의 재등록은 덮어쓰기라 해가
140
+ 없고(`assertDoorSlugIsFree` 가 같은 이름을 뺀다), plant 의 문 선언이 그 둘을 계속 읽는다.
141
+ - `deletionChanges` 는 plant 가 자기 `fact-change` 의 것을 계속 쓴다(`activity-non-working-withdrawal`). 그 앱의 이력 쪽 함수라 남긴다.
142
+
143
+ ### 화면 — 3-가 · 했다 (09-24 `1a1c5c9`) · 두 줄 남음
144
+
145
+ 1. **그물을 세운다** — `things-scene-components-with-tools` 를 읽어 `registerGroup` · `registerTemplate` 하는 열 줄
146
+ (operato-twin `client/bootstrap.ts:89-93`). 그물은 모으기만 한다.
147
+ 2. **앱의 제품 타일 다섯은 손으로 건다 — `station` 그룹이 선 뒤에.** 그물은 의존 꾸러미만 걷는다. 그룹 없이 넣은 항목은
148
+ `registerTemplate` 이 오류 없이 버린다.
149
+ 3. **모델러가 항목의 `labelKey` 를 읽는다** — 손 지도(`PART_LABEL_KEYS`, 11)를 걷는다.
150
+ 4. **원문을 경로로 읽는 시험 19 파일을 가른다.**
151
+ 5. **(남음 — 10.1.38 설치 뒤) 낱말표의 겹친 키 58 을 걷는다** — 40 에, 이 꾸러미로 옮긴 흐름 검사 12 · 이름표 6 을 더해서.
152
+ 낱말표는 마지막에 읽힌 것이 이기므로, 한쪽 문구만 고치면 다른 쪽이 오류 없이 덮는다.
153
+ 7. **(남음 — 10.1.38 설치 뒤) plant 의 범위를 `^10.1.38` 로** — 씬을 등록하지 않는 새 입구가 필요하다.
154
+ 6. **`shared/station-*` 넷을 걷는다** — 이 꾸러미에 같은 파일이 있다. 그 앱에서 지금 쓰는 곳 4.
@@ -8,4 +8,3 @@ export * from './station/station-screen-flow.js';
8
8
  export * from './station/station-work-runtime.js';
9
9
  export * from './station/station-work-scenarios.js';
10
10
  export * from './station/task-counts.js';
11
- export * from './station/scene/index.js';
@@ -8,6 +8,16 @@ export * from './station/station-screen-flow.js';
8
8
  export * from './station/station-work-runtime.js';
9
9
  export * from './station/station-work-scenarios.js';
10
10
  export * from './station/task-counts.js';
11
- /* 씬 부품 — 이 import 자체가 `@sceneComponent` 등록을 돈다. 그려지려면 이것이 불려야 한다. */
12
- export * from './station/scene/index.js';
11
+ /*
12
+ * ── 씬 등록은 이 입구에 없다 (2026-09-24) ─────────────────────────────────────
13
+ * 여기 `export * from './station/scene/index.js'` 가 있었다. 그러면 도우미 하나(`scenarioById` 같은)를 가져오는
14
+ * 쪽마다 씬 여섯이 **부수효과로 등록되고** `@hatiolab/things-scene` 과 lit 이 통째로 따라왔다. operato-plant 의
15
+ * 순수한 저작 검사가 이 입구를 부르자 그 시험이 things-scene 을 못 싣고 멈춰서 드러났다.
16
+ *
17
+ * 그려지게 하는 것은 **앱이 한 번, 드러나게** 부른다:
18
+ *
19
+ * import '@things-factory/station/dist-client/station/scene/index.js'
20
+ *
21
+ * 입구가 그것을 내보내지 않으므로 R1(정본 지정자) 의 「index 가 내보내지 않을 때만 안쪽 경로」에 맞는다.
22
+ */
13
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0BAA0B,CAAA;AAExC,qEAAqE;AACrE,cAAc,0BAA0B,CAAA","sourcesContent":["export * from './station/station-tile-registry.js'\nexport * from './station/station-palette.js'\nexport * from './station/station-board-binding.js'\nexport * from './station/station-context.js'\nexport * from './station/station-runtime.js'\nexport * from './station/station-scene-context.js'\nexport * from './station/station-screen-flow.js'\nexport * from './station/station-work-runtime.js'\nexport * from './station/station-work-scenarios.js'\nexport * from './station/task-counts.js'\n\n/* 씬 부품 — 이 import 자체가 `@sceneComponent` 등록을 돈다. 그려지려면 이것이 불려야 한다. */\nexport * from './station/scene/index.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAA;AAClD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,qCAAqC,CAAA;AACnD,cAAc,0BAA0B,CAAA;AAExC;;;;;;;;;;;GAWG","sourcesContent":["export * from './station/station-tile-registry.js'\nexport * from './station/station-palette.js'\nexport * from './station/station-board-binding.js'\nexport * from './station/station-context.js'\nexport * from './station/station-runtime.js'\nexport * from './station/station-scene-context.js'\nexport * from './station/station-screen-flow.js'\nexport * from './station/station-work-runtime.js'\nexport * from './station/station-work-scenarios.js'\nexport * from './station/task-counts.js'\n\n/*\n * ── 씬 등록은 이 입구에 없다 (2026-09-24) ─────────────────────────────────────\n * 여기 `export * from './station/scene/index.js'` 가 있었다. 그러면 도우미 하나(`scenarioById` 같은)를 가져오는\n * 쪽마다 씬 여섯이 **부수효과로 등록되고** `@hatiolab/things-scene` 과 lit 이 통째로 따라왔다. operato-plant 의\n * 순수한 저작 검사가 이 입구를 부르자 그 시험이 things-scene 을 못 싣고 멈춰서 드러났다.\n *\n * 그려지게 하는 것은 **앱이 한 번, 드러나게** 부른다:\n *\n * import '@things-factory/station/dist-client/station/scene/index.js'\n *\n * 입구가 그것을 내보내지 않으므로 R1(정본 지정자) 의 「index 가 내보내지 않을 때만 안쪽 경로」에 맞는다.\n */\n"]}
@@ -113,7 +113,7 @@ export const stationCommonTiles = [
113
113
  icon: ICON_CONTEXT,
114
114
  description: 'not drawn — sets what this screen reads and how often',
115
115
  group: 'station',
116
- model: { type: 'station-context', ...at(40, 630, 200, 60), showFields: '', refreshSeconds: 10 }
116
+ model: { type: 'station-context', ...at(40, 670, 200, 60), showFields: '', refreshSeconds: 10 }
117
117
  }
118
118
  ];
119
119
  //# sourceMappingURL=station-palette.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"station-palette.js","sourceRoot":"","sources":["../../client/station/station-palette.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACT,MAAM,0BAA0B,CAAA;AAIjC;;;;;GAKG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,kGAAkG;IAC/G,IAAI;IACJ,SAAS,EAAE,EAAE;CACd,CAAA;AAED,0CAA0C;AAC1C,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,KAAa,EAAE,MAAc,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAEvG;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAuB;IACpD;QACE,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,2BAA2B;QACrC,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,6CAA6C;QAC1D,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;KAC9F;IACD;QACE,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,yBAAyB;QACnC,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mCAAmC;QAChD,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;KAChF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,4BAA4B;QACtC,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,gCAAgC;QAC7C,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;KACvE;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,4BAA4B;QACtC,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,mCAAmC;QAChD,KAAK,EAAE,SAAS;QAChB;;;;;WAKG;QACH,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;KACpF;IACD;QACE;;;;;WAKG;QACH,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,6BAA6B;QACvC,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,uDAAuD;QACpE,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;KAChG;CACF,CAAA","sourcesContent":["/**\n * 저작면 팔레트에 서는 **기계의 타일 다섯**과 그 그룹 (ADR-0083 결정 6).\n *\n * ── 어떻게 서나 ─────────────────────────────────────────────────────────────\n * 이 꾸러미의 `package.json` 에 `\"things-scene\": true` 가 있고 뿌리에 `things-scene.config.js` 가\n * 있으면, `@things-factory/env` 가 의존 꾸러미를 훑어 이것을 모으고 보드 모델러가 세운다. 꾸러미\n * 42 개가 이미 그 길이다.\n *\n * operato-plant 는 손으로 등록했었다 — 그 부품이 **앱 안에 있어서** 그물에 안 걸렸기 때문이다. 옮기고\n * 나면 그 까닭이 없어진다. 플랫폼에 길이 있는데 옆에 사설 수집기를 세우지 않는다.\n *\n * ── 제품의 타일은 여기 없다 ─────────────────────────────────────────────────\n * 작업지시 · 정비 · 자재 · 지시서 · 동작은 구조를 읽으므로 제품의 것이고, 제품이\n * `registerStationTiles` 로 건다. 가르는 잣대는 **구조를 읽는가**다.\n *\n * ── 이름표는 열쇠다 ─────────────────────────────────────────────────────────\n * `labelKey` 를 항목이 들고 온다(UX 판정 2026-09-20). 값으로 굳히면 언어를 바꿨을 때 옛말이 남는다 —\n * 등록은 기동 때 한 번이고 언어는 그 뒤에도 바뀐다. 손으로 적은 둘째 지도를 두지 않으려는 것이기도\n * 하다: 지도가 안 갈리면 놓인 타일이 이름 대신 `station-counts` 로 뜬다.\n */\n\nimport {\n ICON_CONTEXT,\n ICON_COUNTS,\n ICON_FIELD,\n ICON_NUMPAD,\n ICON_WHO\n} from './scene/station-icons.js'\n\nimport type { StationTileEntry } from './station-tile-registry.js'\n\n/*\n * 그룹 아이콘 — 작업대 위의 태블릿.\n *\n * 다른 그룹 아이콘과 같은 붓을 쓴다: 주된 것은 굵게(2.5), 윤곽은 가늘게(1.0), 강조는 채운다.\n * `{{strokeColor}}` 는 모델러가 테마 색으로 바꿔 넣는다.\n */\nconst icon = `\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" x=\"0px\" y=\"0px\" viewBox=\"0 0 30 30\" style=\"enable-background:new 0 0 30 30;\" xml:space=\"preserve\">\n <style type=\"text/css\">\n .st0{fill:{{strokeColor}};}\n .st14{fill:none;stroke:{{strokeColor}};stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}\n .st15{fill:none;stroke:{{strokeColor}};stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}\n </style>\n <g>\n <!-- 화면 — 이 그룹의 주인공이라 굵게 -->\n <rect class=\"st14\" x=\"6\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"1.5\"/>\n <!-- 화면 안의 한 줄. 작업자가 읽는 값이 있다는 뜻 -->\n <line class=\"st15\" x1=\"9\" y1=\"8.5\" x2=\"17\" y2=\"8.5\"/>\n <line class=\"st15\" x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/>\n <!-- 받침대 -->\n <line class=\"st15\" x1=\"15\" y1=\"16.5\" x2=\"15\" y2=\"20\"/>\n <!-- 작업대 상판 -->\n <rect class=\"st0\" x=\"4\" y=\"20\" width=\"22\" height=\"2\"/>\n <!-- 다리 -->\n <line class=\"st15\" x1=\"7\" y1=\"22\" x2=\"7\" y2=\"26.5\"/>\n <line class=\"st15\" x1=\"23\" y1=\"22\" x2=\"23\" y2=\"26.5\"/>\n </g>\n</svg>\n`\n\nexport const stationGroup = {\n name: 'station',\n description: 'what an operator sees at a workbench — the values, the prompts, and the buttons that record work',\n icon,\n templates: []\n}\n\n/** 놓았을 때의 자리와 크기. 겹치지 않게 조금씩 어긋나 떨어진다. */\nconst at = (left: number, top: number, width: number, height: number) => ({ left, top, width, height })\n\n/**\n * 기본 크기는 **작업대에서 읽히는 크기**로 잡는다. 저작자가 놓자마자 줄여야 한다면 그 기본값이 틀린\n * 것이다 — 현장 화면은 한 걸음 떨어져서 읽는다.\n *\n * `equipment` 를 비워 둔다. 비면 그 화면이 걸린 작업대를 따르고, 적으면 그 설비에 못 박힌다.\n */\nexport const stationCommonTiles: StationTileEntry[] = [\n {\n type: 'station-field',\n labelKey: 'label.modeller-part-field',\n icon: ICON_FIELD,\n description: 'one value from the station — pick which one',\n group: 'station',\n model: { type: 'station-field', ...at(40, 40, 300, 90), field: '', label: '', valueSize: 26 }\n },\n {\n type: 'station-who',\n labelKey: 'label.modeller-part-who',\n icon: ICON_WHO,\n description: 'who is scanned in at this station',\n group: 'station',\n model: { type: 'station-who', ...at(40, 150, 300, 110), label: '', prompt: '' }\n },\n {\n type: 'station-counts',\n labelKey: 'label.modeller-part-counts',\n icon: ICON_COUNTS,\n description: 'good and reject counted so far',\n group: 'station',\n model: { type: 'station-counts', ...at(360, 40, 300, 110), label: '' }\n },\n {\n type: 'station-numpad',\n labelKey: 'label.modeller-part-numpad',\n icon: ICON_NUMPAD,\n description: 'record a count without a keyboard',\n group: 'station',\n /*\n * 높이는 **저작 검사가 요구하는 최소 위**로 잡는다. 이 검사는 숫자판을 3×4 로 보고 머리 72 를\n * 뺀 뒤 칸이 44 이상인지 본다(`station-design-check`). 240 이던 때는 칸이 42 라, 저작자가 팔레트\n * 에서 놓자마자 「입력 영역을 44px 이상으로 하십시오」가 떴다 — 처음 놓은 것이 이미 틀렸다고\n * 말하는 저작면은 그 검사를 안 믿게 만든다. 260 이면 칸이 47 이다.\n */\n model: { type: 'station-numpad', ...at(360, 160, 300, 260), label: '', counts: '' }\n },\n {\n /*\n * 그리지 않는 부품이다 — 이 화면이 무엇을 얼마나 자주 읽을지를 정한다.\n *\n * 저작면에서는 자리를 차지하지만 작업대에서는 안 보인다. 팔레트에 있어야 하는 이유는, 없으면\n * 저작자가 갱신 주기를 손댈 방법이 아예 없기 때문이다.\n */\n type: 'station-context',\n labelKey: 'label.modeller-part-context',\n icon: ICON_CONTEXT,\n description: 'not drawn — sets what this screen reads and how often',\n group: 'station',\n model: { type: 'station-context', ...at(40, 630, 200, 60), showFields: '', refreshSeconds: 10 }\n }\n]\n"]}
1
+ {"version":3,"file":"station-palette.js","sourceRoot":"","sources":["../../client/station/station-palette.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACT,MAAM,0BAA0B,CAAA;AAIjC;;;;;GAKG;AACH,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsBZ,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,kGAAkG;IAC/G,IAAI;IACJ,SAAS,EAAE,EAAE;CACd,CAAA;AAED,0CAA0C;AAC1C,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,KAAa,EAAE,MAAc,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAEvG;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAuB;IACpD;QACE,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,2BAA2B;QACrC,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,6CAA6C;QAC1D,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;KAC9F;IACD;QACE,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,yBAAyB;QACnC,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mCAAmC;QAChD,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;KAChF;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,4BAA4B;QACtC,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,gCAAgC;QAC7C,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;KACvE;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,4BAA4B;QACtC,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,mCAAmC;QAChD,KAAK,EAAE,SAAS;QAChB;;;;;WAKG;QACH,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;KACpF;IACD;QACE;;;;;WAKG;QACH,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,6BAA6B;QACvC,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,uDAAuD;QACpE,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;KAChG;CACF,CAAA","sourcesContent":["/**\n * 저작면 팔레트에 서는 **기계의 타일 다섯**과 그 그룹 (ADR-0083 결정 6).\n *\n * ── 어떻게 서나 ─────────────────────────────────────────────────────────────\n * 이 꾸러미의 `package.json` 에 `\"things-scene\": true` 가 있고 뿌리에 `things-scene.config.js` 가\n * 있으면, `@things-factory/env` 가 의존 꾸러미를 훑어 이것을 모으고 보드 모델러가 세운다. 꾸러미\n * 42 개가 이미 그 길이다.\n *\n * operato-plant 는 손으로 등록했었다 — 그 부품이 **앱 안에 있어서** 그물에 안 걸렸기 때문이다. 옮기고\n * 나면 그 까닭이 없어진다. 플랫폼에 길이 있는데 옆에 사설 수집기를 세우지 않는다.\n *\n * ── 제품의 타일은 여기 없다 ─────────────────────────────────────────────────\n * 작업지시 · 정비 · 자재 · 지시서 · 동작은 구조를 읽으므로 제품의 것이고, 제품이\n * `registerStationTiles` 로 건다. 가르는 잣대는 **구조를 읽는가**다.\n *\n * ── 이름표는 열쇠다 ─────────────────────────────────────────────────────────\n * `labelKey` 를 항목이 들고 온다(UX 판정 2026-09-20). 값으로 굳히면 언어를 바꿨을 때 옛말이 남는다 —\n * 등록은 기동 때 한 번이고 언어는 그 뒤에도 바뀐다. 손으로 적은 둘째 지도를 두지 않으려는 것이기도\n * 하다: 지도가 안 갈리면 놓인 타일이 이름 대신 `station-counts` 로 뜬다.\n */\n\nimport {\n ICON_CONTEXT,\n ICON_COUNTS,\n ICON_FIELD,\n ICON_NUMPAD,\n ICON_WHO\n} from './scene/station-icons.js'\n\nimport type { StationTileEntry } from './station-tile-registry.js'\n\n/*\n * 그룹 아이콘 — 작업대 위의 태블릿.\n *\n * 다른 그룹 아이콘과 같은 붓을 쓴다: 주된 것은 굵게(2.5), 윤곽은 가늘게(1.0), 강조는 채운다.\n * `{{strokeColor}}` 는 모델러가 테마 색으로 바꿔 넣는다.\n */\nconst icon = `\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" x=\"0px\" y=\"0px\" viewBox=\"0 0 30 30\" style=\"enable-background:new 0 0 30 30;\" xml:space=\"preserve\">\n <style type=\"text/css\">\n .st0{fill:{{strokeColor}};}\n .st14{fill:none;stroke:{{strokeColor}};stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}\n .st15{fill:none;stroke:{{strokeColor}};stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}\n </style>\n <g>\n <!-- 화면 — 이 그룹의 주인공이라 굵게 -->\n <rect class=\"st14\" x=\"6\" y=\"4.5\" width=\"18\" height=\"12\" rx=\"1.5\"/>\n <!-- 화면 안의 한 줄. 작업자가 읽는 값이 있다는 뜻 -->\n <line class=\"st15\" x1=\"9\" y1=\"8.5\" x2=\"17\" y2=\"8.5\"/>\n <line class=\"st15\" x1=\"9\" y1=\"12\" x2=\"21\" y2=\"12\"/>\n <!-- 받침대 -->\n <line class=\"st15\" x1=\"15\" y1=\"16.5\" x2=\"15\" y2=\"20\"/>\n <!-- 작업대 상판 -->\n <rect class=\"st0\" x=\"4\" y=\"20\" width=\"22\" height=\"2\"/>\n <!-- 다리 -->\n <line class=\"st15\" x1=\"7\" y1=\"22\" x2=\"7\" y2=\"26.5\"/>\n <line class=\"st15\" x1=\"23\" y1=\"22\" x2=\"23\" y2=\"26.5\"/>\n </g>\n</svg>\n`\n\nexport const stationGroup = {\n name: 'station',\n description: 'what an operator sees at a workbench — the values, the prompts, and the buttons that record work',\n icon,\n templates: []\n}\n\n/** 놓았을 때의 자리와 크기. 겹치지 않게 조금씩 어긋나 떨어진다. */\nconst at = (left: number, top: number, width: number, height: number) => ({ left, top, width, height })\n\n/**\n * 기본 크기는 **작업대에서 읽히는 크기**로 잡는다. 저작자가 놓자마자 줄여야 한다면 그 기본값이 틀린\n * 것이다 — 현장 화면은 한 걸음 떨어져서 읽는다.\n *\n * `equipment` 를 비워 둔다. 비면 그 화면이 걸린 작업대를 따르고, 적으면 그 설비에 못 박힌다.\n */\nexport const stationCommonTiles: StationTileEntry[] = [\n {\n type: 'station-field',\n labelKey: 'label.modeller-part-field',\n icon: ICON_FIELD,\n description: 'one value from the station — pick which one',\n group: 'station',\n model: { type: 'station-field', ...at(40, 40, 300, 90), field: '', label: '', valueSize: 26 }\n },\n {\n type: 'station-who',\n labelKey: 'label.modeller-part-who',\n icon: ICON_WHO,\n description: 'who is scanned in at this station',\n group: 'station',\n model: { type: 'station-who', ...at(40, 150, 300, 110), label: '', prompt: '' }\n },\n {\n type: 'station-counts',\n labelKey: 'label.modeller-part-counts',\n icon: ICON_COUNTS,\n description: 'good and reject counted so far',\n group: 'station',\n model: { type: 'station-counts', ...at(360, 40, 300, 110), label: '' }\n },\n {\n type: 'station-numpad',\n labelKey: 'label.modeller-part-numpad',\n icon: ICON_NUMPAD,\n description: 'record a count without a keyboard',\n group: 'station',\n /*\n * 높이는 **저작 검사가 요구하는 최소 위**로 잡는다. 이 검사는 숫자판을 3×4 로 보고 머리 72 를\n * 뺀 뒤 칸이 44 이상인지 본다(`station-design-check`). 240 이던 때는 칸이 42 라, 저작자가 팔레트\n * 에서 놓자마자 「입력 영역을 44px 이상으로 하십시오」가 떴다 — 처음 놓은 것이 이미 틀렸다고\n * 말하는 저작면은 그 검사를 안 믿게 만든다. 260 이면 칸이 47 이다.\n */\n model: { type: 'station-numpad', ...at(360, 160, 300, 260), label: '', counts: '' }\n },\n {\n /*\n * 그리지 않는 부품이다 — 이 화면이 무엇을 얼마나 자주 읽을지를 정한다.\n *\n * 저작면에서는 자리를 차지하지만 작업대에서는 안 보인다. 팔레트에 있어야 하는 이유는, 없으면\n * 저작자가 갱신 주기를 손댈 방법이 아예 없기 때문이다.\n */\n type: 'station-context',\n labelKey: 'label.modeller-part-context',\n icon: ICON_CONTEXT,\n description: 'not drawn — sets what this screen reads and how often',\n group: 'station',\n model: { type: 'station-context', ...at(40, 670, 200, 60), showFields: '', refreshSeconds: 10 }\n }\n]\n"]}