@things-factory/worklist 10.1.226 → 10.1.228

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 (38) hide show
  1. package/approval-walk/harness.mjs +2 -2
  2. package/dist-client/bootstrap.js +1 -1
  3. package/dist-client/bootstrap.js.map +1 -1
  4. package/dist-client/components/activity-approval-ribon.d.ts +3 -3
  5. package/dist-client/components/activity-approval-ribon.js +3 -3
  6. package/dist-client/components/activity-approval-ribon.js.map +1 -1
  7. package/dist-client/components/activity-instance-ribon.d.ts +3 -3
  8. package/dist-client/components/activity-instance-ribon.js +3 -3
  9. package/dist-client/components/activity-instance-ribon.js.map +1 -1
  10. package/dist-client/components/activity-thread-ribon.d.ts +3 -3
  11. package/dist-client/components/activity-thread-ribon.js +3 -3
  12. package/dist-client/components/activity-thread-ribon.js.map +1 -1
  13. package/dist-client/components/state-ribon.js +1 -1
  14. package/dist-client/components/state-ribon.js.map +1 -1
  15. package/dist-client/pages/activity-approval/activity-approval-page.js +3 -3
  16. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  17. package/dist-client/pages/activity-catalog/activity-stage.d.ts +1 -1
  18. package/dist-client/pages/activity-catalog/activity-stage.js +1 -1
  19. package/dist-client/pages/activity-catalog/activity-stage.js.map +1 -1
  20. package/dist-client/templates/activity-approval-context-template.js +1 -1
  21. package/dist-client/templates/activity-approval-context-template.js.map +1 -1
  22. package/dist-client/templates/activity-thread-context-template.js +1 -1
  23. package/dist-client/templates/activity-thread-context-template.js.map +1 -1
  24. package/dist-client/templates/context-panel.js +7 -7
  25. package/dist-client/templates/context-panel.js.map +1 -1
  26. package/dist-client/tsconfig.tsbuildinfo +1 -1
  27. package/dist-server/controllers/activity-installation/activity-installation-controller.d.ts +2 -2
  28. package/dist-server/controllers/activity-installation/activity-installation-controller.js +2 -2
  29. package/dist-server/controllers/activity-installation/activity-installation-controller.js.map +1 -1
  30. package/dist-server/tsconfig.tsbuildinfo +1 -1
  31. package/helps/dataset/activity-instance-search-page.ko.md +1 -1
  32. package/helps/worklist/activity-approval.ko.md +1 -1
  33. package/helps/worklist/activity-bank-page.ko.md +1 -1
  34. package/helps/worklist/activity-reporter-list.ko.md +1 -1
  35. package/helps/worklist/activity-store.ko.md +1 -1
  36. package/helps/worklist/activity-template.ko.md +1 -1
  37. package/helps/worklist/installable-activity.ko.md +1 -1
  38. package/package.json +12 -12
@@ -11,7 +11,7 @@
11
11
  * 그 도구를 앱마다 베끼면 앱 수만큼 같은 결함이 생긴다. 실제로 plant 에서 하루에 네 번 값을 치렀다.
12
12
  *
13
13
  * ```
14
- * 거절을 문장으로 판별 코드가 문장에서 빠지자 제품이 멀쩡한데 매 판 빨강
14
+ * 거절을 문장으로 판별 코드가 문장에서 빠지자 제품이 멀쩡한데 매 회 빨강
15
15
  * 첫 쪽만 보고 「없다」 끝난 지시 201건 중 앞 50건만 보고 재료가 없다고 말함
16
16
  * 올린 사람이 곧 결재자 그 단계가 건너뛰어져 결재함에 안 오는데 「안 왔다」로 실패
17
17
  * 자기가 남긴 것을 안 셈 자기 로트를 안 쓰고 남의 로트를 깎아 잔량이 −50 이 됨
@@ -96,7 +96,7 @@ export function createCaller({ base, domain, password = 'demo1234', emailOf = no
96
96
  *
97
97
  * 문장으로 가리면 안 된다. plant 의 도구가 `message.includes('(control-not-on)')` 로 갈랐는데,
98
98
  * 거절이 코드를 다는 방식으로 바뀌면서 문장에서 그 괄호가 사라졌다. 제대로 거절된 것을 「다른 사유로
99
- * 거절됐습니다」로 읽고 매 판 빨강을 냈다 — 제품은 멀쩡했다.
99
+ * 거절됐습니다」로 읽고 매 회 빨강을 냈다 — 제품은 멀쩡했다.
100
100
  *
101
101
  * 문장은 번역되고 다듬어진다. 코드는 계약이다.
102
102
  */
@@ -19,7 +19,7 @@ export default function bootstrap() {
19
19
  /*
20
20
  * 여기에 'activity-info-overlay' aside viewpart 를 등록해 두었었다. 걷었다 —
21
21
  * 기본 정보는 이제 팝업으로 연다(activity-thread-ribon 의 openInfo 머리말 참조).
22
- * ASIDEBAR 은 앱이 하나만 갖는 자리이고, 페이지에 매인 판이 그 자리를 차지할 이유가 없다.
22
+ * ASIDEBAR 은 앱이 하나만 갖는 자리이고, 페이지에 매인 패널이 그 자리를 차지할 이유가 없다.
23
23
  */
24
24
  [
25
25
  {
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,mDAAmD,CAAA;AAC1D,OAAO,iDAAiD,CAAA;AACxD,OAAO,mDAAmD,CAAA;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAE5E,OAAO,EAAE,cAAc,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AACtH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uDAAuD,CAAA;AACjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAA;AAClG,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAA;AACtG,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AAEvF,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B,6BAA6B,EAAE,CAAC;IAEhC;;;;OAIG;IACH;QACE;YACE,QAAQ,EAAE,IAAI,CAAA,6EAA6E;YAC3F,OAAO,EAAE,kBAAkB;SAC5B;QACD;YACE,QAAQ,EAAE,IAAI,CAAA,yEAAyE;YACvF,OAAO,EAAE,gBAAgB;SAC1B;QACD;YACE,QAAQ,EAAE,IAAI,CAAA,6EAA6E;YAC3F,OAAO,EAAE,kBAAkB;SAC5B;KACF,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QAClC,KAAK,CAAC,QAAQ,CAAC;YACb,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE;gBACJ,QAAQ,EAAE,aAAa,CAAC,KAAK;gBAC7B,QAAQ,EAAE,IAAI,CAAA;;qBAED,KAAK,EAAC,CAAC,EAAC,EAAE;oBACjB,WAAW,CAAC,yBAAyB,EAAE;wBACrC,QAAQ;qBACT,CAAC,CAAA;gBACJ,CAAC;;;SAGJ;gBACD,OAAO;aACR;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,mBAAmB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAA;IACtD,qBAAqB,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAA;IAC1D,mBAAmB,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAA;IAC1D,qBAAqB,CAAC,YAAY,EAAE,yBAAyB,CAAC,CAAA;IAE9D,mBAAmB,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;IAC1E,qBAAqB,CAAC,sBAAsB,EAAE,+BAA+B,CAAC,CAAA;AAChF,CAAC","sourcesContent":["import '@material/web/icon/icon.js'\nimport './templates/activity-approval-context-template.js'\nimport './templates/activity-thread-context-template.js'\nimport './templates/activity-instance-context-template.js'\n\nimport { html } from 'lit-html'\nimport { store } from '@operato/shell'\nimport { openOverlay, TOOL_POSITION } from '@operato/layout'\nimport { APPEND_CONTEXT_TOOL } from '@things-factory/context-ui/dist-client'\n\nimport { registerEditor as registerGristEditor, registerRenderer as registerGristRenderer } from '@operato/data-grist'\nimport { OxGristEditorDuration } from '@operato/grist-editor/ox-grist-editor-duration.js'\nimport { OxGristEditorQuantifier } from '@operato/grist-editor/ox-grist-editor-quantifier.js'\nimport { OxGristRendererDuration } from '@operato/grist-editor/ox-grist-renderer-duration.js'\nimport { OxGristRendererQuantifier } from '@operato/grist-editor/ox-grist-renderer-quantifier.js'\nimport { GristEditorActivitySearchKeys } from './grist-editor/grist-editor-activity-search-key.js'\nimport { GristRendererActivitySearchKeys } from './grist-editor/grist-renderer-activity-search-key.js'\nimport { registerPersonOpenWorkSection } from './entity360/person-open-work-section.js'\n\nexport default function bootstrap() {\n registerPersonOpenWorkSection();\n\n /*\n * 여기에 'activity-info-overlay' aside viewpart 를 등록해 두었었다. 걷었다 —\n * 기본 정보는 이제 팝업으로 연다(activity-thread-ribon 의 openInfo 머리말 참조).\n * ASIDEBAR 은 앱이 하나만 갖는 자리이고, 페이지에 매인 판이 그 자리를 차지할 이유가 없다.\n */\n [\n {\n template: html` <activity-approval-context-template></activity-approval-context-template> `,\n context: 'activityApproval'\n },\n {\n template: html` <activity-thread-context-template></activity-thread-context-template> `,\n context: 'activityThread'\n },\n {\n template: html` <activity-instance-context-template></activity-instance-context-template> `,\n context: 'activityInstance'\n }\n ].forEach(({ template, context }) => {\n store.dispatch({\n type: APPEND_CONTEXT_TOOL,\n tool: {\n position: TOOL_POSITION.FRONT,\n template: html`\n <md-icon\n @click=${async e => {\n openOverlay('context-toolbar-overlay', {\n template\n })\n }}\n >info</md-icon\n >\n `,\n context\n }\n })\n })\n\n registerGristEditor('duration', OxGristEditorDuration)\n registerGristRenderer('duration', OxGristRendererDuration)\n registerGristEditor('quantifier', OxGristEditorQuantifier)\n registerGristRenderer('quantifier', OxGristRendererQuantifier)\n\n registerGristEditor('activity-search-keys', GristEditorActivitySearchKeys)\n registerGristRenderer('activity-search-keys', GristRendererActivitySearchKeys)\n}\n"]}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,mDAAmD,CAAA;AAC1D,OAAO,iDAAiD,CAAA;AACxD,OAAO,mDAAmD,CAAA;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAA;AAE5E,OAAO,EAAE,cAAc,IAAI,mBAAmB,EAAE,gBAAgB,IAAI,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AACtH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,EAAE,yBAAyB,EAAE,MAAM,uDAAuD,CAAA;AACjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAA;AAClG,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAA;AACtG,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AAEvF,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B,6BAA6B,EAAE,CAAC;IAEhC;;;;OAIG;IACH;QACE;YACE,QAAQ,EAAE,IAAI,CAAA,6EAA6E;YAC3F,OAAO,EAAE,kBAAkB;SAC5B;QACD;YACE,QAAQ,EAAE,IAAI,CAAA,yEAAyE;YACvF,OAAO,EAAE,gBAAgB;SAC1B;QACD;YACE,QAAQ,EAAE,IAAI,CAAA,6EAA6E;YAC3F,OAAO,EAAE,kBAAkB;SAC5B;KACF,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE;QAClC,KAAK,CAAC,QAAQ,CAAC;YACb,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE;gBACJ,QAAQ,EAAE,aAAa,CAAC,KAAK;gBAC7B,QAAQ,EAAE,IAAI,CAAA;;qBAED,KAAK,EAAC,CAAC,EAAC,EAAE;oBACjB,WAAW,CAAC,yBAAyB,EAAE;wBACrC,QAAQ;qBACT,CAAC,CAAA;gBACJ,CAAC;;;SAGJ;gBACD,OAAO;aACR;SACF,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,mBAAmB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAA;IACtD,qBAAqB,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAA;IAC1D,mBAAmB,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAA;IAC1D,qBAAqB,CAAC,YAAY,EAAE,yBAAyB,CAAC,CAAA;IAE9D,mBAAmB,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;IAC1E,qBAAqB,CAAC,sBAAsB,EAAE,+BAA+B,CAAC,CAAA;AAChF,CAAC","sourcesContent":["import '@material/web/icon/icon.js'\nimport './templates/activity-approval-context-template.js'\nimport './templates/activity-thread-context-template.js'\nimport './templates/activity-instance-context-template.js'\n\nimport { html } from 'lit-html'\nimport { store } from '@operato/shell'\nimport { openOverlay, TOOL_POSITION } from '@operato/layout'\nimport { APPEND_CONTEXT_TOOL } from '@things-factory/context-ui/dist-client'\n\nimport { registerEditor as registerGristEditor, registerRenderer as registerGristRenderer } from '@operato/data-grist'\nimport { OxGristEditorDuration } from '@operato/grist-editor/ox-grist-editor-duration.js'\nimport { OxGristEditorQuantifier } from '@operato/grist-editor/ox-grist-editor-quantifier.js'\nimport { OxGristRendererDuration } from '@operato/grist-editor/ox-grist-renderer-duration.js'\nimport { OxGristRendererQuantifier } from '@operato/grist-editor/ox-grist-renderer-quantifier.js'\nimport { GristEditorActivitySearchKeys } from './grist-editor/grist-editor-activity-search-key.js'\nimport { GristRendererActivitySearchKeys } from './grist-editor/grist-renderer-activity-search-key.js'\nimport { registerPersonOpenWorkSection } from './entity360/person-open-work-section.js'\n\nexport default function bootstrap() {\n registerPersonOpenWorkSection();\n\n /*\n * 여기에 'activity-info-overlay' aside viewpart 를 등록해 두었었다. 걷었다 —\n * 기본 정보는 이제 팝업으로 연다(activity-thread-ribon 의 openInfo 머리말 참조).\n * ASIDEBAR 은 앱이 하나만 갖는 자리이고, 페이지에 매인 패널이 그 자리를 차지할 이유가 없다.\n */\n [\n {\n template: html` <activity-approval-context-template></activity-approval-context-template> `,\n context: 'activityApproval'\n },\n {\n template: html` <activity-thread-context-template></activity-thread-context-template> `,\n context: 'activityThread'\n },\n {\n template: html` <activity-instance-context-template></activity-instance-context-template> `,\n context: 'activityInstance'\n }\n ].forEach(({ template, context }) => {\n store.dispatch({\n type: APPEND_CONTEXT_TOOL,\n tool: {\n position: TOOL_POSITION.FRONT,\n template: html`\n <md-icon\n @click=${async e => {\n openOverlay('context-toolbar-overlay', {\n template\n })\n }}\n >info</md-icon\n >\n `,\n context\n }\n })\n })\n\n registerGristEditor('duration', OxGristEditorDuration)\n registerGristRenderer('duration', OxGristRendererDuration)\n registerGristEditor('quantifier', OxGristEditorQuantifier)\n registerGristRenderer('quantifier', OxGristRendererQuantifier)\n\n registerGristEditor('activity-search-keys', GristEditorActivitySearchKeys)\n registerGristRenderer('activity-search-keys', GristRendererActivitySearchKeys)\n}\n"]}
@@ -13,14 +13,14 @@ export declare class ActivityApprovalRibon extends ActivityApprovalRibon_base {
13
13
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
14
14
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
15
15
  *
16
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
16
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
17
17
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
18
18
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
19
19
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
20
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
20
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
21
21
  *
22
22
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
23
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
23
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
24
24
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
25
25
  *
26
26
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -70,14 +70,14 @@ let ActivityApprovalRibon = class ActivityApprovalRibon extends localize(i18next
70
70
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
71
71
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
72
72
  *
73
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
73
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
74
74
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
75
75
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
76
76
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
77
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
77
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
78
78
  *
79
79
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
80
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
80
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
81
81
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
82
82
  *
83
83
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -1 +1 @@
1
- {"version":3,"file":"activity-approval-ribon.js","sourceRoot":"","sources":["../../client/components/activity-approval-ribon.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-approval-context-template.js'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { StateRibonStyles } from './state-ribon.js'\n\n@customElement('activity-approval-ribon')\nexport class ActivityApprovalRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityApproval: any\n\n render() {\n const { activityInstance, state } = this.activityApproval?.activityThread || {}\n const { description, assignee, approvalLine, activity } = activityInstance || {}\n const { startingType, label, labelTKey } = activity || {}\n\n /*\n * What kind of decision this is — the activity's own name, not this instance's.\n *\n * Those are different facts and both belong here: 「부적합 처분 승인」 says what kind, and the\n * headline the activity declares says what this one asks for. The activity's name reached only\n * the catalog until it became a column on the row, so this screen showed the instance\n * description alone.\n *\n * ── The fallback puts English on a Korean screen ──────────────────────\n * Activity.description is what a developer wrote for other developers (\"The disposition waiting\n * for approval\"), so an activity with no label shows that to the person approving. That is worse\n * than the instance description and it is the reason to fill label in — it is not a fallback\n * anybody should be content with.\n */\n const named = label && labelTKey ? String(i18next.t(labelTKey, { defaultValue: label })) : label\n const kind = named || description || ''\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.approval-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${kind}>${kind}</span>\n\n\n ${startingType == 'issue' && assignee\n ? html`<span class=\"who\"><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span>`\n : ''}\n ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${this.activityApproval.order}\n ></approval-line-brief>`\n : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 판을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-approval-context-template .activityApproval=${this.activityApproval} state=${state}></activity-approval-context-template>`,\n { title: i18next.t('label.approval-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityApproval') && this.activityApproval) {\n const { state } = this.activityApproval.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-approval-ribon.js","sourceRoot":"","sources":["../../client/components/activity-approval-ribon.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-approval-context-template.js'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { StateRibonStyles } from './state-ribon.js'\n\n@customElement('activity-approval-ribon')\nexport class ActivityApprovalRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityApproval: any\n\n render() {\n const { activityInstance, state } = this.activityApproval?.activityThread || {}\n const { description, assignee, approvalLine, activity } = activityInstance || {}\n const { startingType, label, labelTKey } = activity || {}\n\n /*\n * What kind of decision this is — the activity's own name, not this instance's.\n *\n * Those are different facts and both belong here: 「부적합 처분 승인」 says what kind, and the\n * headline the activity declares says what this one asks for. The activity's name reached only\n * the catalog until it became a column on the row, so this screen showed the instance\n * description alone.\n *\n * ── The fallback puts English on a Korean screen ──────────────────────\n * Activity.description is what a developer wrote for other developers (\"The disposition waiting\n * for approval\"), so an activity with no label shows that to the person approving. That is worse\n * than the instance description and it is the reason to fill label in — it is not a fallback\n * anybody should be content with.\n */\n const named = label && labelTKey ? String(i18next.t(labelTKey, { defaultValue: label })) : label\n const kind = named || description || ''\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.approval-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${kind}>${kind}</span>\n\n\n ${startingType == 'issue' && assignee\n ? html`<span class=\"who\"><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span>`\n : ''}\n ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${this.activityApproval.order}\n ></approval-line-brief>`\n : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 패널을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-approval-context-template .activityApproval=${this.activityApproval} state=${state}></activity-approval-context-template>`,\n { title: i18next.t('label.approval-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityApproval') && this.activityApproval) {\n const { state } = this.activityApproval.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -14,14 +14,14 @@ export declare class ActivityInstanceRibon extends ActivityInstanceRibon_base {
14
14
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
15
15
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
16
16
  *
17
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
17
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
18
18
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
19
19
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
20
20
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
21
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
21
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
22
22
  *
23
23
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
24
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
24
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
25
25
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
26
26
  *
27
27
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -58,14 +58,14 @@ let ActivityInstanceRibon = class ActivityInstanceRibon extends localize(i18next
58
58
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
59
59
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
60
60
  *
61
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
61
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
62
62
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
63
63
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
64
64
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
65
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
65
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
66
66
  *
67
67
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
68
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
68
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
69
69
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
70
70
  *
71
71
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -1 +1 @@
1
- {"version":3,"file":"activity-instance-ribon.js","sourceRoot":"","sources":["../../client/components/activity-instance-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,oDAAoD,CAAA;AAE3D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAG5C,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAAjE;;QAGuB,qBAAgB,GAAQ,EAAE,CAAA;IA0ExD,CAAC;aA5EQ,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAA;QAC5F,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY,IAAI,OAAO,IAAI,QAAQ;YACnC,CAAC,CAAC,IAAI,CAAA,6CAA6C,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,aAAa,CAAC,QAAQ,CAAC,SAAS;YACxH,CAAC,CAAC,EAAE;;;;;;QAMJ,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA,+BAA+B,YAAY,yBAAyB,CAAC,CAAC,CAAC,EAAE;KAC/F,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,yDAAyD,IAAI,CAAC,gBAAgB,UAAU,KAAK,wCAAwC,EACzI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;YAEvC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AAzE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAA2B;AAH3C,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA6EjC","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-instance-context-template.js'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { StateRibonStyles } from './state-ribon.js'\n\n@customElement('activity-instance-ribon')\nexport class ActivityInstanceRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityInstance: any = {}\n\n render() {\n const { description, state, assignee, approvalLine, activity } = this.activityInstance || {}\n const { startingType } = activity || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${startingType == 'issue' && assignee\n ? html`<span class=\"who\"><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span>`\n : ''}\n <!--\n 결재선의 현재 단계를 넘기지 않는다 — 이 ribbon 이 쓰이는 곳은 업무를 시작하는 화면\n 하나뿐이고(activity-instance-start-page), 거기서는 아직 아무도 판단하지 않았다.\n approval-line-brief 는 값이 없으면 기안자를 현재로 표시하는데, 이 화면에서는 그것이 맞다.\n -->\n ${approvalLine ? html`<approval-line-brief .model=${approvalLine}></approval-line-brief>` : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 판을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-instance-context-template .activityInstance=${this.activityInstance} state=${state}></activity-instance-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityInstance') && this.activityInstance) {\n const { state } = this.activityInstance\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-instance-ribon.js","sourceRoot":"","sources":["../../client/components/activity-instance-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,oDAAoD,CAAA;AAE3D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAG5C,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAAjE;;QAGuB,qBAAgB,GAAQ,EAAE,CAAA;IA0ExD,CAAC;aA5EQ,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAA;QAC5F,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;QAEvC,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY,IAAI,OAAO,IAAI,QAAQ;YACnC,CAAC,CAAC,IAAI,CAAA,6CAA6C,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,aAAa,CAAC,QAAQ,CAAC,SAAS;YACxH,CAAC,CAAC,EAAE;;;;;;QAMJ,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA,+BAA+B,YAAY,yBAAyB,CAAC,CAAC,CAAC,EAAE;KAC/F,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,yDAAyD,IAAI,CAAC,gBAAgB,UAAU,KAAK,wCAAwC,EACzI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAA;YAEvC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AAzE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;+DAA2B;AAH3C,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CA6EjC","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-instance-context-template.js'\n\nimport { html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { StateRibonStyles } from './state-ribon.js'\n\n@customElement('activity-instance-ribon')\nexport class ActivityInstanceRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityInstance: any = {}\n\n render() {\n const { description, state, assignee, approvalLine, activity } = this.activityInstance || {}\n const { startingType } = activity || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${startingType == 'issue' && assignee\n ? html`<span class=\"who\"><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span>`\n : ''}\n <!--\n 결재선의 현재 단계를 넘기지 않는다 — 이 ribbon 이 쓰이는 곳은 업무를 시작하는 화면\n 하나뿐이고(activity-instance-start-page), 거기서는 아직 아무도 판단하지 않았다.\n approval-line-brief 는 값이 없으면 기안자를 현재로 표시하는데, 이 화면에서는 그것이 맞다.\n -->\n ${approvalLine ? html`<approval-line-brief .model=${approvalLine}></approval-line-brief>` : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 패널을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-instance-context-template .activityInstance=${this.activityInstance} state=${state}></activity-instance-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityInstance') && this.activityInstance) {\n const { state } = this.activityInstance\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -20,14 +20,14 @@ export declare class ActivityThreadRibon extends ActivityThreadRibon_base {
20
20
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
21
21
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
22
22
  *
23
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
23
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
24
24
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
25
25
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
26
26
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
27
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
27
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
28
28
  *
29
29
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
30
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
30
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
31
31
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
32
32
  *
33
33
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -62,14 +62,14 @@ let ActivityThreadRibon = class ActivityThreadRibon extends localize(i18next)(Li
62
62
  * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────
63
63
  * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.
64
64
  *
65
- * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다
65
+ * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다
66
66
  * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.
67
67
  * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가
68
68
  * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),
69
- * 이 판을 열면 그중 열려 있던 것이 닫힌다.
69
+ * 이 패널을 열면 그중 열려 있던 것이 닫힌다.
70
70
  *
71
71
  * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이
72
- * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에
72
+ * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에
73
73
  * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.
74
74
  *
75
75
  * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.
@@ -1 +1 @@
1
- {"version":3,"file":"activity-thread-ribon.js","sourceRoot":"","sources":["../../client/components/activity-thread-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,kDAAkD,CAAA;AAEzD,OAAO,EAAO,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEnD;;;;;GAKG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;aAC7D,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACpF,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAE5D,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA;qBACO,YAAY;uBACV,oBAAoB,CAAC,iBAAiB,CAAC;kCAC5B;YAC1B,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,IAAI,CAAA;yCACyB,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,aAAa,CAAC,QAAQ,CAAC;cACvF;gBACJ,CAAC,CAAC,EAAE;KACT,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,qDAAqD,IAAI,CAAC,cAAc,UAAU,KAAK,sCAAsC,EACjI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;YAErC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AA1E2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2DAAoB;AAHpC,mBAAmB;IAD/B,aAAa,CAAC,uBAAuB,CAAC;GAC1B,mBAAmB,CA8E/B","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-thread-context-template.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { currentApprovalOrder } from '../approval-progress.js'\nimport { StateRibonStyles } from './state-ribon.js'\n\n/**\n * 업무 하나의 머리 — **지금 어떤 상태이고, 누구 손에 있나.**\n *\n * 모양은 `state-ribon.ts` 가 정한다(그 파일의 머리말에 왜 채운 띠를 걷었는지 적어 두었다).\n * 여기서는 이 화면이 무엇을 보일지만 고른다.\n */\n@customElement('activity-thread-ribon')\nexport class ActivityThreadRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityThread: any\n\n render() {\n const { state, assignee, activityInstance, activityApprovals } = this.activityThread\n const { description, approvalLine } = activityInstance || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${currentApprovalOrder(activityApprovals)}\n ></approval-line-brief>`\n : assignee\n ? html`<span class=\"who\"\n ><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span\n >`\n : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 판은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 판을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 판은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-thread-context-template .activityThread=${this.activityThread} state=${state}></activity-thread-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityThread') && this.activityThread) {\n const { state } = this.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"activity-thread-ribon.js","sourceRoot":"","sources":["../../client/components/activity-thread-ribon.ts"],"names":[],"mappings":";AAAA,OAAO,yCAAyC,CAAA;AAChD,OAAO,wDAAwD,CAAA;AAC/D,OAAO,2EAA2E,CAAA;AAClF,OAAO,kDAAkD,CAAA;AAEzD,OAAO,EAAO,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAEnD;;;;;GAKG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;aAC7D,WAAM,GAAG,CAAC,gBAAgB,CAAC,AAArB,CAAqB;IAIlC,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;QACpF,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,gBAAgB,IAAI,EAAE,CAAA;QAE5D,OAAO,IAAI,CAAA;;;UAGL,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,KAAK,CAAC;;;;;;;gBAOpC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;iBACrC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;mBACxB,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;;;;iCAIwB,WAAW,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE;;;QAG/D,YAAY;YACZ,CAAC,CAAC,IAAI,CAAA;qBACO,YAAY;uBACV,oBAAoB,CAAC,iBAAiB,CAAC;kCAC5B;YAC1B,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,IAAI,CAAA;yCACyB,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,UAAU,aAAa,CAAC,QAAQ,CAAC;cACvF;gBACJ,CAAC,CAAC,EAAE;KACT,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,QAAQ,CAAC,KAAa;QAC5B,SAAS,CACP,IAAI,CAAA,qDAAqD,IAAI,CAAC,cAAc,UAAU,KAAK,sCAAsC,EACjI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAC1C,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAO;QACb,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,cAAc,CAAA;YAErC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;;AA1E2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2DAAoB;AAHpC,mBAAmB;IAD/B,aAAa,CAAC,uBAAuB,CAAC;GAC1B,mBAAmB,CA8E/B","sourcesContent":["import '@material/web/button/elevated-button.js'\nimport '@operato/property-editor/ox-properties-dynamic-view.js'\nimport '@things-factory/organization/dist-client/component/approval-line-brief.js'\nimport '../templates/activity-thread-context-template.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name, openPopup } from '@operato/layout'\n\nimport { currentApprovalOrder } from '../approval-progress.js'\nimport { StateRibonStyles } from './state-ribon.js'\n\n/**\n * 업무 하나의 머리 — **지금 어떤 상태이고, 누구 손에 있나.**\n *\n * 모양은 `state-ribon.ts` 가 정한다(그 파일의 머리말에 왜 채운 띠를 걷었는지 적어 두었다).\n * 여기서는 이 화면이 무엇을 보일지만 고른다.\n */\n@customElement('activity-thread-ribon')\nexport class ActivityThreadRibon extends localize(i18next)(LitElement) {\n static styles = [StateRibonStyles]\n\n @property({ type: Object }) activityThread: any\n\n render() {\n const { state, assignee, activityInstance, activityApprovals } = this.activityThread\n const { description, approvalLine } = activityInstance || {}\n\n return html`\n <span class=\"state\">\n <i class=\"dot\"></i>\n ${i18next.t('label.activity-state-' + state)}\n </span>\n\n <md-icon\n class=\"info\"\n role=\"button\"\n tabindex=\"0\"\n title=${String(i18next.t('label.thread-info'))}\n @click=${() => this.openInfo(state)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.openInfo(state)\n }\n }}\n >info</md-icon\n >\n\n <span class=\"desc\" title=${description || ''}>${description || ''}</span>\n\n\n ${approvalLine\n ? html`<approval-line-brief\n .model=${approvalLine}\n .current=${currentApprovalOrder(activityApprovals)}\n ></approval-line-brief>`\n : assignee\n ? html`<span class=\"who\"\n ><span class=\"who-label\">${i18next.t('field.assignee')}</span>${entity360Name(assignee)}</span\n >`\n : ''}\n `\n }\n\n /**\n * 이 건의 기본 정보 — **팝업으로 연다.**\n *\n * ── 왜 aside 가 아닌가 (2026-09-06) ────────────────────────────────────\n * 전에는 화면 오른쪽에서 나오는 aside 판이었다. 두 가지가 걸린다.\n *\n * 자리를 다툰다 화면 오른쪽 세로 패널은 operato-twin 의 twin-entity360 이 쓰는 자리다\n * (position: fixed · right: 0 · height: 100vh). 같은 자리에 둘이 선다.\n * 전역 슬롯이다 VIEWPART_POSITION.ASIDEBAR 은 앱이 하나만 갖는다. 열 개가 넘는 패키지가\n * 그 자리를 쓰고 있어(twin 의 AI 협의 도크 · board-ui · help · more-ui …),\n * 이 패널을 열면 그중 열려 있던 것이 닫힌다.\n *\n * 그리고 자리의 뜻이 다르다. 오른쪽 드로어는 **보고 있는 대상을 따라다니는 상세**이고(360 이\n * 그것이다 — 포커스가 바뀌면 내용이 바뀌고 화면을 옮겨도 남는다), 이 패널은 **이 화면의 이 건**에\n * 대한 것이라 화면을 벗어나면 뜻이 없다. 페이지에 매인 것을 앱 전역 자리에 두지 않는다.\n *\n * 내용도 팝업 크기다 — 값 여덟 줄과 접힌 타임라인이라 세로 100vh 를 쓸 일이 없었다.\n */\n private openInfo(state: string) {\n openPopup(\n html`<activity-thread-context-template .activityThread=${this.activityThread} state=${state}></activity-thread-context-template>`,\n { title: i18next.t('label.thread-info') }\n )\n }\n\n updated(changes) {\n if (changes.has('activityThread') && this.activityThread) {\n const { state } = this.activityThread\n\n this.setAttribute('state', state)\n }\n }\n}\n"]}
@@ -161,7 +161,7 @@ const StateRibonOwnStyles = css `
161
161
  * 상태 바로 뒤에 둔다. 전에는 띠의 오른쪽 끝, 결재선 바로 왼쪽에 있었다 — 그 자리에서는
162
162
  * **결재선의 일부처럼** 읽힌다(결재선을 펴 보는 단추인가 하고 누르게 된다).
163
163
  *
164
- * 이 아이콘이 여는 것은 이 건의 기본 정보이고, 그 판의 첫 줄이 상태다. 상태 옆에 붙여
164
+ * 이 아이콘이 여는 것은 이 건의 기본 정보이고, 그 패널의 첫 줄이 상태다. 상태 옆에 붙여
165
165
  * 두 개가 한 덩어리로 읽히게 한다 — 앞의 gap 만 좁혀서 붙이고 뒤는 띠의 기본 간격을 쓴다.
166
166
  */
167
167
  .info {
@@ -1 +1 @@
1
- {"version":3,"file":"state-ribon.js","sourceRoot":"","sources":["../../client/components/state-ribon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCrC,CAAA;AAED,MAAM,mBAAmB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6I9B,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAA","sourcesContent":["import { css } from 'lit'\n\n/**\n * 업무 · 결재 화면의 머리 띠 — **세 화면이 한 모양을 쓴다.**\n *\n * activity-thread-ribon · activity-approval-ribon · activity-instance-ribon 이 같은 자리에 같은\n * 것을 보인다(상태 · 설명 · 결재선 또는 담당자). 그런데 셋이 각자 100여 줄의 CSS 를 갖고 있었고,\n * 상태색 여덟 개가 세 벌로 복사되어 있었다.\n *\n * ── 채운 띠를 걷은 이유 — 글자가 안 읽혔다 ─────────────────────────────────\n * 전에는 상태마다 다른 색으로 띠 전체를 채우고 그 위에 흰 글자를 얹었다. 색은 하드코딩된 hex 여덟\n * 개였고, --md-sys-color-on-primary(대개 흰색)를 글자색으로 썼다. contrast 를 계산하면 12px 글자\n * 기준 AA(4.5:1)에 네 개가 못 미친다.\n *\n * started #56af45 2.76 ← 작업자가 가장 오래 보는 상태\n * ended #02acae 2.79\n * rejected #f27429 2.87\n * submitted #428df3 3.31\n * unassigned #5f7184 5.02 (통과)\n * escalated #595de5 5.09 (통과)\n * aborted #cb3a33 5.01 (통과)\n * delegated #8654b0 5.37 (통과)\n *\n * 색을 여덟 개 다시 고르는 대신 **띠를 채우지 않는다.** SurfaceStyles 가 정한 규칙과 같다 —\n * 흰 면에 1px 선을 두르고, 색은 상태 앞의 점 하나가 말한다. 글자는 --ui-ink 라 어느 상태에서든\n * 읽히고, 점은 UI 요소라 3:1 기준으로 판단한다.\n *\n * ── 색 여덟 개를 뜻 여섯 개로 ──────────────────────────────────────────────\n * 하드코딩된 hex 는 앱 팔레트를 따르지 않는다. worklist 는 framework 패키지라 operato-plant ·\n * operato-gangsters · operato-dataset 이 모두 이 화면을 쓰는데, 어느 앱에서도 그 앱 색이 아니었다.\n * 토큰으로 바꾸면 앱마다 자기 라이트 · 다크 테마를 따라온다.\n *\n * unassigned · assigned --ui-muted 아직 시작하지 않았다\n * started --ui-accent 내 손에서 진행 중이다\n * submitted · escalated · delegated --ui-info 남의 판단을 기다린다\n * rejected --ui-warn 되돌아왔다. 다시 해야 한다\n * ended · approved --ui-good 끝났다\n * aborted --ui-crit 중단됐다\n *\n * 색만으로 뜻을 전하지 않는다 — 상태 이름을 항상 함께 적는다.\n */\n/**\n * The state → colour mapping above, alone - for anything that shows a worklist state, not only the\n * ribbon. Set on `:host([state=...])`; read `--worklist-state-color`. The activity instance view kept\n * a fourth copy of the old eight hex colours after the ribbons moved to meanings; three of them were\n * under 3:1 on a light surface (started 2.62 · rejected 2.73 · ended 2.65, measured on :4000\n * 2026-09-24) and `unassigned` had none, so it drew tomato.\n */\nexport const WorklistStateColors = css`\n :host([state='unassigned']),\n :host([state='assigned']),\n :host([state='draft']) {\n --worklist-state-color: var(--ui-muted, #57676f);\n }\n\n :host([state='started']),\n :host([state='issued']),\n :host([state='posted']) {\n --worklist-state-color: var(--ui-accent, #00727e);\n }\n\n :host([state='submitted']),\n :host([state='escalated']),\n :host([state='delegated']),\n :host([state='pending']) {\n --worklist-state-color: var(--ui-info, #2b72ad);\n }\n\n :host([state='rejected']) {\n --worklist-state-color: var(--ui-warn, #9f5e02);\n }\n\n :host([state='ended']),\n :host([state='approved']) {\n --worklist-state-color: var(--ui-good, #297d39);\n }\n\n :host([state='aborted']),\n :host([state='deprecated']) {\n --worklist-state-color: var(--ui-crit, #d14946);\n }\n`\n\nconst StateRibonOwnStyles = css`\n /*\n * ── 면을 갖지 않는다 (2026-09-06) ─────────────────────────────────────\n * 채운 색 띠를 걷어내면서 흰 면(--ui-panel)으로 바꿨는데, 그것이 카드와 **같은 색**이었다.\n * 그래서 한 화면에 흰 블록이 넷이 되고(머리 띠 · 내용 · 타임라인 · 의견) 위계가 사라졌다.\n * 실측: 결재 화면의 네 블록이 전부 rgb(255,255,255) 에 1px 테두리였다.\n *\n * 이 띠가 말하는 것(상태 · 설명 · 결재선)은 전부 보조다. 사용자가 먼저 묻는 것은 「무엇을\n * 승인하나」이지 「지금 몇 단계인가」가 아니다.\n *\n * 그래서 페이지 바탕이 비치게 두고 아래 구분선도 없앤다. 흰 면은 「읽을 내용」에만 남는다 —\n * 그 규칙이 서면 카드가 곧 본문이라는 것이 모양만으로 읽힌다.\n */\n :host {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n\n /* office control height, the same for mouse and finger (WCAG AA target, user decision 2026-09-17) */\n min-height: 36px;\n padding: 0 var(--spacing-large, 16px);\n box-sizing: border-box;\n\n color: var(--ui-ink, #17242c);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* ── 상태 ────────────────────────────────────────────────────────────── */\n .state {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n font-weight: 600;\n white-space: nowrap;\n }\n\n /*\n * 상태색을 쓰는 자리는 이 점 하나다. 기본값은 --ui-muted — 서버가 아직 모르는 상태 이름이\n * 오더라도 점이 사라지지 않고 회색으로 남는다(색이 없으면 상태가 없는 것처럼 보인다).\n */\n .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--worklist-state-color, var(--ui-muted, #57676f));\n }\n\n /* ── 설명 ────────────────────────────────────────────────────────────── */\n /*\n * 한 줄로 자른다. 이 자리는 머리 띠라 높이가 고정이고, 설명이 길면 아래 내용을 밀어낸다.\n * 전체 글은 정보 아이콘이 여는 overlay 가 갖는다.\n *\n * ── 늘어나지 않는다 (2026-09-20, :4000 실측) ──────────────────────────\n * flex: 1 은 남는 자리를 전부 설명이 가져가게 한다. 그러면 그 뒤의 결재선 · 담당자가 띠의\n * 오른쪽 끝으로 밀린다. 1024px 창의 결재 화면에서 잰 값이다:\n *\n * 설명 「화면 발행 승인」 제 너비 75px → 늘어나서 417px\n * 결재선 왼쪽 끝 x=407 → x=750\n * 본문이 시작하는 자리 x=254\n *\n * 결재선은 이 화면에서 「지금 누구 차례인가」를 말하는 유일한 자리인데, 본문을 훑어 내려가는\n * 눈이 지나는 왼쪽 축에서 496px 떨어져 있었다. 창이 넓어질수록 더 멀어진다 — 설명이 가져가는\n * 자리가 창 폭을 따라 늘기 때문이다.\n *\n * 늘리지 않으면 셋이 왼쪽부터 차례로 선다(상태 · 설명 · 결재선). 긴 설명에서는 여전히 잘린다 —\n * min-width: 0 과 ellipsis 가 이미 있고, 그때는 결재선이 예전 자리로 돌아간다.\n */\n .desc {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--ui-muted, #57676f);\n }\n\n /* ── 정보 아이콘 ─────────────────────────────────────────────────────── */\n /*\n * 상태 바로 뒤에 둔다. 전에는 띠의 오른쪽 끝, 결재선 바로 왼쪽에 있었다 — 그 자리에서는\n * **결재선의 일부처럼** 읽힌다(결재선을 펴 보는 단추인가 하고 누르게 된다).\n *\n * 이 아이콘이 여는 것은 이 건의 기본 정보이고, 그 판의 첫 줄이 상태다. 상태 옆에 붙여\n * 두 개가 한 덩어리로 읽히게 한다 — 앞의 gap 만 좁혀서 붙이고 뒤는 띠의 기본 간격을 쓴다.\n */\n .info {\n flex: none;\n margin-left: calc(var(--spacing-medium, 8px) * -1 + 4px);\n cursor: pointer;\n color: var(--ui-muted, #57676f);\n font-size: 18px;\n }\n\n .info:hover {\n color: var(--ui-ink, #17242c);\n }\n\n /* 키보드로 온 것이 보여야 한다 — 이 아이콘은 role=button 이라 탭 순서에 든다. */\n .info:focus-visible {\n outline: 2px solid var(--ui-accent, #00727e);\n outline-offset: 2px;\n border-radius: 50%;\n color: var(--ui-ink, #17242c);\n }\n\n /* ── 담당자 ──────────────────────────────────────────────────────────── */\n .who {\n display: inline-flex;\n align-items: baseline;\n gap: 5px;\n flex: none;\n white-space: nowrap;\n }\n\n .who-label {\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n /* ── 결재선 ──────────────────────────────────────────────────────────── */\n approval-line-brief {\n flex: none;\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /*\n * 좁은 화면 — 결재선과 담당자를 감춘다. 상태와 설명이 먼저다.\n *\n * 결재선은 단계마다 44px 이상을 쓴다. 세 단계면 이음선까지 200px 을 넘고, 460px 화면에서는\n * 설명이 들어갈 자리가 남지 않는다.\n */\n @media only screen and (max-width: 460px) {\n :host {\n padding: 0 var(--spacing-medium, 8px);\n }\n\n .who,\n approval-line-brief {\n display: none;\n }\n }\n`\n\nexport const StateRibonStyles = [WorklistStateColors, StateRibonOwnStyles]\n"]}
1
+ {"version":3,"file":"state-ribon.js","sourceRoot":"","sources":["../../client/components/state-ribon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCrC,CAAA;AAED,MAAM,mBAAmB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6I9B,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAA","sourcesContent":["import { css } from 'lit'\n\n/**\n * 업무 · 결재 화면의 머리 띠 — **세 화면이 한 모양을 쓴다.**\n *\n * activity-thread-ribon · activity-approval-ribon · activity-instance-ribon 이 같은 자리에 같은\n * 것을 보인다(상태 · 설명 · 결재선 또는 담당자). 그런데 셋이 각자 100여 줄의 CSS 를 갖고 있었고,\n * 상태색 여덟 개가 세 벌로 복사되어 있었다.\n *\n * ── 채운 띠를 걷은 이유 — 글자가 안 읽혔다 ─────────────────────────────────\n * 전에는 상태마다 다른 색으로 띠 전체를 채우고 그 위에 흰 글자를 얹었다. 색은 하드코딩된 hex 여덟\n * 개였고, --md-sys-color-on-primary(대개 흰색)를 글자색으로 썼다. contrast 를 계산하면 12px 글자\n * 기준 AA(4.5:1)에 네 개가 못 미친다.\n *\n * started #56af45 2.76 ← 작업자가 가장 오래 보는 상태\n * ended #02acae 2.79\n * rejected #f27429 2.87\n * submitted #428df3 3.31\n * unassigned #5f7184 5.02 (통과)\n * escalated #595de5 5.09 (통과)\n * aborted #cb3a33 5.01 (통과)\n * delegated #8654b0 5.37 (통과)\n *\n * 색을 여덟 개 다시 고르는 대신 **띠를 채우지 않는다.** SurfaceStyles 가 정한 규칙과 같다 —\n * 흰 면에 1px 선을 두르고, 색은 상태 앞의 점 하나가 말한다. 글자는 --ui-ink 라 어느 상태에서든\n * 읽히고, 점은 UI 요소라 3:1 기준으로 판단한다.\n *\n * ── 색 여덟 개를 뜻 여섯 개로 ──────────────────────────────────────────────\n * 하드코딩된 hex 는 앱 팔레트를 따르지 않는다. worklist 는 framework 패키지라 operato-plant ·\n * operato-gangsters · operato-dataset 이 모두 이 화면을 쓰는데, 어느 앱에서도 그 앱 색이 아니었다.\n * 토큰으로 바꾸면 앱마다 자기 라이트 · 다크 테마를 따라온다.\n *\n * unassigned · assigned --ui-muted 아직 시작하지 않았다\n * started --ui-accent 내 손에서 진행 중이다\n * submitted · escalated · delegated --ui-info 남의 판단을 기다린다\n * rejected --ui-warn 되돌아왔다. 다시 해야 한다\n * ended · approved --ui-good 끝났다\n * aborted --ui-crit 중단됐다\n *\n * 색만으로 뜻을 전하지 않는다 — 상태 이름을 항상 함께 적는다.\n */\n/**\n * The state → colour mapping above, alone - for anything that shows a worklist state, not only the\n * ribbon. Set on `:host([state=...])`; read `--worklist-state-color`. The activity instance view kept\n * a fourth copy of the old eight hex colours after the ribbons moved to meanings; three of them were\n * under 3:1 on a light surface (started 2.62 · rejected 2.73 · ended 2.65, measured on :4000\n * 2026-09-24) and `unassigned` had none, so it drew tomato.\n */\nexport const WorklistStateColors = css`\n :host([state='unassigned']),\n :host([state='assigned']),\n :host([state='draft']) {\n --worklist-state-color: var(--ui-muted, #57676f);\n }\n\n :host([state='started']),\n :host([state='issued']),\n :host([state='posted']) {\n --worklist-state-color: var(--ui-accent, #00727e);\n }\n\n :host([state='submitted']),\n :host([state='escalated']),\n :host([state='delegated']),\n :host([state='pending']) {\n --worklist-state-color: var(--ui-info, #2b72ad);\n }\n\n :host([state='rejected']) {\n --worklist-state-color: var(--ui-warn, #9f5e02);\n }\n\n :host([state='ended']),\n :host([state='approved']) {\n --worklist-state-color: var(--ui-good, #297d39);\n }\n\n :host([state='aborted']),\n :host([state='deprecated']) {\n --worklist-state-color: var(--ui-crit, #d14946);\n }\n`\n\nconst StateRibonOwnStyles = css`\n /*\n * ── 면을 갖지 않는다 (2026-09-06) ─────────────────────────────────────\n * 채운 색 띠를 걷어내면서 흰 면(--ui-panel)으로 바꿨는데, 그것이 카드와 **같은 색**이었다.\n * 그래서 한 화면에 흰 블록이 넷이 되고(머리 띠 · 내용 · 타임라인 · 의견) 위계가 사라졌다.\n * 실측: 결재 화면의 네 블록이 전부 rgb(255,255,255) 에 1px 테두리였다.\n *\n * 이 띠가 말하는 것(상태 · 설명 · 결재선)은 전부 보조다. 사용자가 먼저 묻는 것은 「무엇을\n * 승인하나」이지 「지금 몇 단계인가」가 아니다.\n *\n * 그래서 페이지 바탕이 비치게 두고 아래 구분선도 없앤다. 흰 면은 「읽을 내용」에만 남는다 —\n * 그 규칙이 서면 카드가 곧 본문이라는 것이 모양만으로 읽힌다.\n */\n :host {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n\n /* office control height, the same for mouse and finger (WCAG AA target, user decision 2026-09-17) */\n min-height: 36px;\n padding: 0 var(--spacing-large, 16px);\n box-sizing: border-box;\n\n color: var(--ui-ink, #17242c);\n font-size: var(--ui-t-body, 13px);\n }\n\n /* ── 상태 ────────────────────────────────────────────────────────────── */\n .state {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n font-weight: 600;\n white-space: nowrap;\n }\n\n /*\n * 상태색을 쓰는 자리는 이 점 하나다. 기본값은 --ui-muted — 서버가 아직 모르는 상태 이름이\n * 오더라도 점이 사라지지 않고 회색으로 남는다(색이 없으면 상태가 없는 것처럼 보인다).\n */\n .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--worklist-state-color, var(--ui-muted, #57676f));\n }\n\n /* ── 설명 ────────────────────────────────────────────────────────────── */\n /*\n * 한 줄로 자른다. 이 자리는 머리 띠라 높이가 고정이고, 설명이 길면 아래 내용을 밀어낸다.\n * 전체 글은 정보 아이콘이 여는 overlay 가 갖는다.\n *\n * ── 늘어나지 않는다 (2026-09-20, :4000 실측) ──────────────────────────\n * flex: 1 은 남는 자리를 전부 설명이 가져가게 한다. 그러면 그 뒤의 결재선 · 담당자가 띠의\n * 오른쪽 끝으로 밀린다. 1024px 창의 결재 화면에서 잰 값이다:\n *\n * 설명 「화면 발행 승인」 제 너비 75px → 늘어나서 417px\n * 결재선 왼쪽 끝 x=407 → x=750\n * 본문이 시작하는 자리 x=254\n *\n * 결재선은 이 화면에서 「지금 누구 차례인가」를 말하는 유일한 자리인데, 본문을 훑어 내려가는\n * 눈이 지나는 왼쪽 축에서 496px 떨어져 있었다. 창이 넓어질수록 더 멀어진다 — 설명이 가져가는\n * 자리가 창 폭을 따라 늘기 때문이다.\n *\n * 늘리지 않으면 셋이 왼쪽부터 차례로 선다(상태 · 설명 · 결재선). 긴 설명에서는 여전히 잘린다 —\n * min-width: 0 과 ellipsis 가 이미 있고, 그때는 결재선이 예전 자리로 돌아간다.\n */\n .desc {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--ui-muted, #57676f);\n }\n\n /* ── 정보 아이콘 ─────────────────────────────────────────────────────── */\n /*\n * 상태 바로 뒤에 둔다. 전에는 띠의 오른쪽 끝, 결재선 바로 왼쪽에 있었다 — 그 자리에서는\n * **결재선의 일부처럼** 읽힌다(결재선을 펴 보는 단추인가 하고 누르게 된다).\n *\n * 이 아이콘이 여는 것은 이 건의 기본 정보이고, 그 패널의 첫 줄이 상태다. 상태 옆에 붙여\n * 두 개가 한 덩어리로 읽히게 한다 — 앞의 gap 만 좁혀서 붙이고 뒤는 띠의 기본 간격을 쓴다.\n */\n .info {\n flex: none;\n margin-left: calc(var(--spacing-medium, 8px) * -1 + 4px);\n cursor: pointer;\n color: var(--ui-muted, #57676f);\n font-size: 18px;\n }\n\n .info:hover {\n color: var(--ui-ink, #17242c);\n }\n\n /* 키보드로 온 것이 보여야 한다 — 이 아이콘은 role=button 이라 탭 순서에 든다. */\n .info:focus-visible {\n outline: 2px solid var(--ui-accent, #00727e);\n outline-offset: 2px;\n border-radius: 50%;\n color: var(--ui-ink, #17242c);\n }\n\n /* ── 담당자 ──────────────────────────────────────────────────────────── */\n .who {\n display: inline-flex;\n align-items: baseline;\n gap: 5px;\n flex: none;\n white-space: nowrap;\n }\n\n .who-label {\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, #57676f);\n }\n\n /* ── 결재선 ──────────────────────────────────────────────────────────── */\n approval-line-brief {\n flex: none;\n font-size: var(--ui-t-small, 11.5px);\n }\n\n /*\n * 좁은 화면 — 결재선과 담당자를 감춘다. 상태와 설명이 먼저다.\n *\n * 결재선은 단계마다 44px 이상을 쓴다. 세 단계면 이음선까지 200px 을 넘고, 460px 화면에서는\n * 설명이 들어갈 자리가 남지 않는다.\n */\n @media only screen and (max-width: 460px) {\n :host {\n padding: 0 var(--spacing-medium, 8px);\n }\n\n .who,\n approval-line-brief {\n display: none;\n }\n }\n`\n\nexport const StateRibonStyles = [WorklistStateColors, StateRibonOwnStyles]\n"]}
@@ -109,7 +109,7 @@ export const ActivityThreadStatus = {
109
109
  Ended: 'ended',
110
110
  Aborted: 'aborted'
111
111
  };
112
- /** 타임라인이 옆에 서는 폭 — 읽는 단 1080 + 사이 24 + 최소 판 360 + page 좌우 40. */
112
+ /** 타임라인이 옆에 서는 폭 — 읽는 단 1080 + 사이 24 + 최소 패널 360 + page 좌우 40. */
113
113
  const BESIDE = '(min-width: 1504px)';
114
114
  let ActivityApprovalPage = class ActivityApprovalPage extends localize(i18next)(PageView) {
115
115
  constructor() {
@@ -157,7 +157,7 @@ let ActivityApprovalPage = class ActivityApprovalPage extends localize(i18next)(
157
157
  *
158
158
  * 그래서 **읽는 단을 넘는 여분이 한 판만큼 있을 때만** 편다:
159
159
  *
160
- * 1080(읽는 단) + 24(사이) + 360(최소 판) + 40(page 좌우 여백) = 1504
160
+ * 1080(읽는 단) + 24(사이) + 360(최소 패널) + 40(page 좌우 여백) = 1504
161
161
  *
162
162
  * 그 아래에서는 한 단이고 차례가 그대로다 — 결재선 · 결정 · 타임라인 · 의견. 좁은 화면이
163
163
  * 기본이고 넓은 화면이 덤이다.
@@ -172,7 +172,7 @@ let ActivityApprovalPage = class ActivityApprovalPage extends localize(i18next)(
172
172
  }
173
173
 
174
174
  /*
175
- * 두 판의 자리는 문서 차례가 아니라 격자가 정한다. 문서 차례는 좁은 화면 그대로 두어야
175
+ * 두 패널의 자리는 문서 차례가 아니라 격자가 정한다. 문서 차례는 좁은 화면 그대로 두어야
176
176
  * 하고(결재선 · 결정 · 타임라인 · 의견), 넓은 화면에서만 타임라인이 오른쪽으로 빠진다.
177
177
  */
178
178
  .main {