@operato/slot-layout-editor 10.29.57 → 10.29.59
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/CHANGELOG.md +17 -0
- package/dist/src/issue-text.d.ts +7 -0
- package/dist/src/issue-text.js +45 -0
- package/dist/src/issue-text.js.map +1 -1
- package/dist/src/ox-slot-layout-editor.js +19 -10
- package/dist/src/ox-slot-layout-editor.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/translations/en.json +1 -0
- package/translations/es.json +1 -0
- package/translations/ja.json +2 -1
- package/translations/ko.json +5 -4
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [10.29.59](https://github.com/hatiolab/operato/compare/v10.29.58...v10.29.59) (2026-10-28)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @operato/slot-layout-editor
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### [10.29.58](https://github.com/hatiolab/operato/compare/v10.29.57...v10.29.58) (2026-10-27)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### :rocket: New Features
|
|
18
|
+
|
|
19
|
+
* **slot-layout-editor:** one line for a tier's slots past their face, host-set panel look ([9e7946a](https://github.com/hatiolab/operato/commit/9e7946a111e775ef40efdd88fc3d0ef5af613d8c))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
6
23
|
### [10.29.57](https://github.com/hatiolab/operato/compare/v10.29.56...v10.29.57) (2026-10-27)
|
|
7
24
|
|
|
8
25
|
|
package/dist/src/issue-text.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export declare const t: (key: string, fallback: string, opts?: Record<string, un
|
|
|
17
17
|
/** 자리 공간 경고의 기본 문구. 번역 키는 label.slot-layout.space.{코드} */
|
|
18
18
|
export declare const SPACE_TEXT: Record<SlotSpaceCode, string>;
|
|
19
19
|
export declare function spaceWarningText(warning: EditorIssue): string;
|
|
20
|
+
/** Slot numbers as few words: runs of numbers as 1~8, the rest one by one. */
|
|
21
|
+
export declare function slotsWords(slots: readonly (string | number)[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* The space warnings to show: the slots of one tier that reach past their face said in one line. Eight slots past a
|
|
24
|
+
* face were eight red lines that said the same (figure modeller sweep 2026-10-27 M3).
|
|
25
|
+
*/
|
|
26
|
+
export declare function spaceWarningLines(warnings: readonly EditorIssue[]): string[];
|
|
20
27
|
/** 문제 하나를 화면 문구로. 앞에 값의 위치를 붙인다 */
|
|
21
28
|
export declare function issueText(issue: EditorIssue): string;
|
|
22
29
|
/** 문제 하나를 화면 문구로, 위치 없이. 칸 옆에 보일 때 쓴다 */
|
package/dist/src/issue-text.js
CHANGED
|
@@ -36,6 +36,51 @@ export function spaceWarningText(warning) {
|
|
|
36
36
|
const fallback = (_a = SPACE_TEXT[warning.code]) !== null && _a !== void 0 ? _a : warning.code;
|
|
37
37
|
return t(`space.${warning.code}`, fallback, { ...warning.params, interpolation: { escapeValue: false } });
|
|
38
38
|
}
|
|
39
|
+
/** Slot numbers as few words: runs of numbers as 1~8, the rest one by one. */
|
|
40
|
+
export function slotsWords(slots) {
|
|
41
|
+
const numbers = slots.map(Number);
|
|
42
|
+
if (!numbers.every(Number.isInteger))
|
|
43
|
+
return slots.join(', ');
|
|
44
|
+
const sorted = [...new Set(numbers)].sort((a, b) => a - b);
|
|
45
|
+
const runs = [];
|
|
46
|
+
for (let i = 0; i < sorted.length;) {
|
|
47
|
+
let j = i;
|
|
48
|
+
while (j + 1 < sorted.length && sorted[j + 1] === sorted[j] + 1)
|
|
49
|
+
j++;
|
|
50
|
+
runs.push(j - i >= 2 ? `${sorted[i]}~${sorted[j]}` : sorted.slice(i, j + 1).join(', '));
|
|
51
|
+
i = j + 1;
|
|
52
|
+
}
|
|
53
|
+
return runs.join(', ');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The space warnings to show: the slots of one tier that reach past their face said in one line. Eight slots past a
|
|
57
|
+
* face were eight red lines that said the same (figure modeller sweep 2026-10-27 M3).
|
|
58
|
+
*/
|
|
59
|
+
export function spaceWarningLines(warnings) {
|
|
60
|
+
var _a, _b, _c, _d;
|
|
61
|
+
const outside = new Map();
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const w of warnings) {
|
|
64
|
+
if (w.code !== 'SLOT_OUTSIDE_ANCHOR') {
|
|
65
|
+
lines.push(spaceWarningText(w));
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const tier = String((_b = (_a = w.params) === null || _a === void 0 ? void 0 : _a.tier) !== null && _b !== void 0 ? _b : '');
|
|
69
|
+
if (!outside.has(tier)) {
|
|
70
|
+
outside.set(tier, []);
|
|
71
|
+
lines.push({ tier });
|
|
72
|
+
}
|
|
73
|
+
outside.get(tier).push((_d = (_c = w.params) === null || _c === void 0 ? void 0 : _c.slot) !== null && _d !== void 0 ? _d : '');
|
|
74
|
+
}
|
|
75
|
+
return lines.map(line => {
|
|
76
|
+
if (typeof line === 'string')
|
|
77
|
+
return line;
|
|
78
|
+
const slots = outside.get(line.tier);
|
|
79
|
+
if (slots.length === 1)
|
|
80
|
+
return spaceWarningText({ code: 'SLOT_OUTSIDE_ANCHOR', path: '', params: { tier: line.tier, slot: slots[0] } });
|
|
81
|
+
return t('space.SLOT_OUTSIDE_ANCHOR_MANY', 'Tier {tier} slots {slots} reach past their face', { tier: line.tier, slots: slotsWords(slots), interpolation: { escapeValue: false } });
|
|
82
|
+
});
|
|
83
|
+
}
|
|
39
84
|
/** 문제 하나를 화면 문구로. 앞에 값의 위치를 붙인다 */
|
|
40
85
|
export function issueText(issue) {
|
|
41
86
|
var _a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-text.js","sourceRoot":"","sources":["../../src/issue-text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAUvC,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAoC;IACzD,cAAc,EAAE,+BAA+B;IAC/C,aAAa,EAAE,wBAAwB;IACvC,eAAe,EAAE,eAAe;IAChC,cAAc,EAAE,oCAAoC;IACpD,qBAAqB,EAAE,6BAA6B;IACpD,sBAAsB,EAAE,sBAAsB;IAC9C,wBAAwB,EAAE,qCAAqC;IAC/D,yBAAyB,EAAE,yCAAyC;IACpE,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,2BAA2B;IAC5C,YAAY,EAAE,gBAAgB;IAC9B,eAAe,EAAE,kCAAkC;IACnD,cAAc,EAAE,+BAA+B;IAC/C,qBAAqB,EAAE,6BAA6B;IACpD,eAAe,EAAE,2BAA2B;IAC5C,aAAa,EAAE,yEAAyE;CACzF,CAAA;AAED,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,QAAgB,EAAE,OAAgC,EAAE,EAAE,EAAE,CACrF,OAAO,CAAC,CAAC,CAAC,qBAAqB,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;AAE5E,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAkC;IACvD,YAAY,EAAE,oEAAoE;IAClF,mBAAmB,EAAE,+CAA+C;IACpE,oBAAoB,EAAE,sEAAsE;CAC7F,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoB;;IACnD,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,OAAO,CAAC,IAAI,CAAC,mCAAI,OAAO,CAAC,IAAI,CAAA;IACrF,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AAC3G,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,SAAS,CAAC,KAAkB;;IAC1C,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAI,KAAK,CAAC,IAAI,CAAA;IACjF,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;IAC3G,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACrD,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,YAAY,CAAC,KAAkB;;IAC7C,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAI,KAAK,CAAC,IAAI,CAAA;IACjF,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AACvG,CAAC;AAED,uEAAuE;AACvE,MAAM,aAAa,GAA2B;IAC5C,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,YAAY;IACtB,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,YAAY;IAC1B,QAAQ,EAAE,eAAe;IACzB,MAAM,EAAE,SAAS;IACjB,gBAAgB,EAAE,SAAS;IAC3B,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,OAAO;IACvB,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,aAAa,EAAE,MAAM;IACrB,eAAe,EAAE,QAAQ;IACzB,iBAAiB,EAAE,UAAU;IAC7B,iBAAiB,EAAE,UAAU;IAC7B,aAAa,EAAE,MAAM;IACrB,aAAa,EAAE,MAAM;IACrB,cAAc,EAAE,OAAO;IACvB,aAAa,EAAE,eAAe;IAC9B,qBAAqB,EAAE,eAAe;IACtC,2BAA2B,EAAE,eAAe;IAC5C,2BAA2B,EAAE,eAAe;IAC5C,4BAA4B,EAAE,gBAAgB;IAC9C,wBAAwB,EAAE,aAAa;IACvC,sBAAsB,EAAE,UAAU;IAClC,qBAAqB,EAAE,SAAS;CACjC,CAAA;AAED,4DAA4D;AAC5D,MAAM,UAAU,UAAU,CAAC,KAAkB;;IAC3C,MAAM,CAAC,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAA;IAC9D,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;AACnF,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,cAAc,EAAE,2BAA2B;IAC3C,iBAAiB,EAAE,qBAAqB;IACxC,cAAc,EAAE,qBAAqB;IACrC,cAAc,EAAE,sBAAsB;IACtC,eAAe,EAAE,sBAAsB;IACvC,oBAAoB,EAAE,sBAAsB;IAC5C,YAAY,EAAE,0BAA0B;CACzC,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,MAAc;;IACpC,OAAO,CAAC,CAAC,OAAO,MAAM,EAAE,EAAE,MAAA,QAAQ,CAAC,MAAM,CAAC,mCAAI,MAAM,CAAC,CAAA;AACvD,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,YAAY,EAAE,4BAA4B;IAC1C,mBAAmB,EAAE,sBAAsB;IAC3C,oBAAoB,EAAE,uBAAuB;IAC7C,oBAAoB,EAAE,gCAAgC;IACtD,gBAAgB,EAAE,kCAAkC;CACrD,CAAA;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;;IACxC,OAAO,CAAC,CAAC,YAAY,MAAM,EAAE,EAAE,MAAA,aAAa,CAAC,MAAM,CAAC,mCAAI,MAAM,CAAC,CAAA;AACjE,CAAC","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n *\n * 검증 문제(코드·경로·매개변수)를 화면 문구로. 번역 키는 label.slot-layout.issue.{코드} 이고,\n * 번역이 없으면 아래 영어 기본 문구를 쓴다. 호스트 고유 코드는 호스트가 번역을 넣거나 issueText 옵션으로 바꾼다.\n */\n\nimport { i18next } from '@operato/i18n'\nimport type { LayoutIssueCode, SlotSpaceCode } from '@hatiolab/things-scene'\n\n/** 문제 하나. 호스트 고유 코드도 같은 모양으로 온다 */\nexport interface EditorIssue {\n code: string\n path: string\n params?: Record<string, string | number>\n}\n\n/** things-scene 검증 코드의 기본 문구. 자리표시자가 중괄호 하나라서 문구에 중괄호 글자를 쓰지 않는다 */\nexport const ISSUE_TEXT: Record<LayoutIssueCode, string> = {\n TIERS_REQUIRED: 'At least one tier is required',\n MOUNT_INVALID: 'Must be on, in or hang',\n ANCHOR_REQUIRED: 'Choose a face',\n ANCHOR_UNKNOWN: 'This holder has no face {anchorId}',\n TIER_NUMBER_DUPLICATE: 'Tier {tierNo} is used twice',\n FINITE_NUMBER_REQUIRED: 'A number is required',\n POSITIVE_NUMBER_REQUIRED: 'A number greater than 0 is required',\n POSITIVE_INTEGER_REQUIRED: 'A whole number of 1 or more is required',\n ARRAY_REQUIRED: 'A list is required',\n OBJECT_REQUIRED: 'The value is not a layout',\n AXIS_INVALID: 'Must be X or Z',\n PATTERN_INVALID: 'Must be one, row, grid or listed',\n SLOTS_REQUIRED: 'At least one slot is required',\n SLOT_NUMBER_DUPLICATE: 'Slot {slotNo} is used twice',\n NOT_PERSISTABLE: 'Cannot be saved ({value})',\n ACCEPTS_EMPTY: 'The list of types it takes is empty; choose 「Any type」 to take any item'\n}\n\nexport const t = (key: string, fallback: string, opts: Record<string, unknown> = {}) =>\n i18next.t(`label.slot-layout.${key}`, { defaultValue: fallback, ...opts })\n\n/** 자리 공간 경고의 기본 문구. 번역 키는 label.slot-layout.space.{코드} */\nexport const SPACE_TEXT: Record<SlotSpaceCode, string> = {\n SLOT_OVERLAP: 'Tier {tier} slot {slot} overlaps tier {otherTier} slot {otherSlot}',\n SLOT_OUTSIDE_ANCHOR: 'Tier {tier} slot {slot} reaches past its face',\n ANCHOR_SPACE_UNKNOWN: 'Face {anchorId} has no size: whether slots stay on it is not checked'\n}\n\nexport function spaceWarningText(warning: EditorIssue): string {\n const fallback = (SPACE_TEXT as Record<string, string>)[warning.code] ?? warning.code\n return t(`space.${warning.code}`, fallback, { ...warning.params, interpolation: { escapeValue: false } })\n}\n\n/** 문제 하나를 화면 문구로. 앞에 값의 위치를 붙인다 */\nexport function issueText(issue: EditorIssue): string {\n const fallback = (ISSUE_TEXT as Record<string, string>)[issue.code] ?? issue.code\n const text = t(`issue.${issue.code}`, fallback, { ...issue.params, interpolation: { escapeValue: false } })\n return issue.path ? `${issue.path}: ${text}` : text\n}\n\n/** 문제 하나를 화면 문구로, 위치 없이. 칸 옆에 보일 때 쓴다 */\nexport function issueMessage(issue: EditorIssue): string {\n const fallback = (ISSUE_TEXT as Record<string, string>)[issue.code] ?? issue.code\n return t(`issue.${issue.code}`, fallback, { ...issue.params, interpolation: { escapeValue: false } })\n}\n\n/** Tier 안의 경로 → 편집기 칸(data-field). 칸이 없는 경로(CUSTOM 자리 표 등)는 목록에 보인다 */\nconst FIELD_OF_PATH: Record<string, string> = {\n anchorId: 'anchor',\n mount: 'mount',\n position: 'position-x',\n 'position.x': 'position-x',\n 'position.y': 'position-y',\n 'position.z': 'position-z',\n rotation: 'tier-rotation',\n layout: 'pattern',\n 'layout.pattern': 'pattern',\n 'layout.count': 'count',\n 'layout.pitch': 'pitch',\n 'layout.pitch.x': 'pitch-x',\n 'layout.pitch.z': 'pitch-z',\n 'layout.axis': 'axis',\n 'layout.origin': 'origin',\n 'layout.origin.x': 'origin-x',\n 'layout.origin.z': 'origin-z',\n 'layout.rows': 'rows',\n 'layout.cols': 'cols',\n 'layout.order': 'order',\n 'layout.slot': 'allowed-width',\n 'layout.slot.allowed': 'allowed-width',\n 'layout.slot.allowed.width': 'allowed-width',\n 'layout.slot.allowed.depth': 'allowed-depth',\n 'layout.slot.allowed.height': 'allowed-height',\n 'layout.slot.stackLimit': 'stack-limit',\n 'layout.slot.rotation': 'rotation',\n 'layout.slot.accepts': 'accepts'\n}\n\n/** 문제가 어느 Tier(목록 순서)의 어느 칸인지. Tier 밖이거나 칸이 없으면 field 없음 */\nexport function issueField(issue: EditorIssue): { tierIndex?: number; field?: string } {\n const m = /^tiers\\[(\\d+)\\](?:\\.(.+))?$/.exec(issue.path ?? '')\n if (!m) return {}\n return { tierIndex: Number(m[1]), field: m[2] ? FIELD_OF_PATH[m[2]] : undefined }\n}\n\n/** 실린 아이템 판정 까닭의 기본 문구. 번역 키는 label.slot-layout.fit.{까닭} */\nexport const FIT_TEXT: Record<string, string> = {\n SLOT_NOT_FOUND: 'Slot gone: kept, unplaced',\n TYPE_NOT_ACCEPTED: 'Type not taken here',\n WIDTH_EXCEEDED: 'Wider than the slot',\n DEPTH_EXCEEDED: 'Deeper than the slot',\n HEIGHT_EXCEEDED: 'Taller than the slot',\n STACK_LIMIT_EXCEEDED: 'Over the stack limit',\n SPEC_UNKNOWN: 'Size unknown: not judged'\n}\n\nexport function fitText(reason: string): string {\n return t(`fit.${reason}`, FIT_TEXT[reason] ?? reason)\n}\n\n/** 면에 맞출 수 없는 까닭의 기본 문구. 번역 키는 label.slot-layout.fit-face.{까닭} */\nexport const FIT_FACE_TEXT: Record<string, string> = {\n FACE_UNKNOWN: 'The face size is not known',\n PATTERN_UNSUPPORTED: 'Not for listed slots',\n ROTATION_UNSUPPORTED: 'Only for turns of 90°',\n SLOT_WIDER_THAN_FACE: 'A slot is larger than the face',\n SLOTS_DO_NOT_FIT: 'The slots do not fit on the face'\n}\n\nexport function fitFaceText(reason: string): string {\n return t(`fit-face.${reason}`, FIT_FACE_TEXT[reason] ?? reason)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"issue-text.js","sourceRoot":"","sources":["../../src/issue-text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAUvC,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAoC;IACzD,cAAc,EAAE,+BAA+B;IAC/C,aAAa,EAAE,wBAAwB;IACvC,eAAe,EAAE,eAAe;IAChC,cAAc,EAAE,oCAAoC;IACpD,qBAAqB,EAAE,6BAA6B;IACpD,sBAAsB,EAAE,sBAAsB;IAC9C,wBAAwB,EAAE,qCAAqC;IAC/D,yBAAyB,EAAE,yCAAyC;IACpE,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,2BAA2B;IAC5C,YAAY,EAAE,gBAAgB;IAC9B,eAAe,EAAE,kCAAkC;IACnD,cAAc,EAAE,+BAA+B;IAC/C,qBAAqB,EAAE,6BAA6B;IACpD,eAAe,EAAE,2BAA2B;IAC5C,aAAa,EAAE,yEAAyE;CACzF,CAAA;AAED,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,QAAgB,EAAE,OAAgC,EAAE,EAAE,EAAE,CACrF,OAAO,CAAC,CAAC,CAAC,qBAAqB,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;AAE5E,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAkC;IACvD,YAAY,EAAE,oEAAoE;IAClF,mBAAmB,EAAE,+CAA+C;IACpE,oBAAoB,EAAE,sEAAsE;CAC7F,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoB;;IACnD,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,OAAO,CAAC,IAAI,CAAC,mCAAI,OAAO,CAAC,IAAI,CAAA;IACrF,OAAO,CAAC,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AAC3G,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,KAAmC;IAC5D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC7D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC1D,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,CAAA;QACT,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAE,GAAG,CAAC;YAAE,CAAC,EAAE,CAAA;QACrE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QACvF,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgC;;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+B,CAAA;IACtD,MAAM,KAAK,GAAkC,EAAE,CAAA;IAC/C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;YAC/B,SAAQ;QACV,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAA,MAAA,CAAC,CAAC,MAAM,0CAAE,IAAI,mCAAI,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QACtB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,MAAA,MAAA,CAAC,CAAC,MAAM,0CAAE,IAAI,mCAAI,EAAE,CAAC,CAAA;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACtB,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAE,CAAA;QACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,gBAAgB,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAA;QACxI,OAAO,CAAC,CAAC,gCAAgC,EAAE,iDAAiD,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;IACrL,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,SAAS,CAAC,KAAkB;;IAC1C,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAI,KAAK,CAAC,IAAI,CAAA;IACjF,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;IAC3G,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACrD,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,YAAY,CAAC,KAAkB;;IAC7C,MAAM,QAAQ,GAAG,MAAC,UAAqC,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAI,KAAK,CAAC,IAAI,CAAA;IACjF,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;AACvG,CAAC;AAED,uEAAuE;AACvE,MAAM,aAAa,GAA2B;IAC5C,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,YAAY;IACtB,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,YAAY;IAC1B,YAAY,EAAE,YAAY;IAC1B,QAAQ,EAAE,eAAe;IACzB,MAAM,EAAE,SAAS;IACjB,gBAAgB,EAAE,SAAS;IAC3B,cAAc,EAAE,OAAO;IACvB,cAAc,EAAE,OAAO;IACvB,gBAAgB,EAAE,SAAS;IAC3B,gBAAgB,EAAE,SAAS;IAC3B,aAAa,EAAE,MAAM;IACrB,eAAe,EAAE,QAAQ;IACzB,iBAAiB,EAAE,UAAU;IAC7B,iBAAiB,EAAE,UAAU;IAC7B,aAAa,EAAE,MAAM;IACrB,aAAa,EAAE,MAAM;IACrB,cAAc,EAAE,OAAO;IACvB,aAAa,EAAE,eAAe;IAC9B,qBAAqB,EAAE,eAAe;IACtC,2BAA2B,EAAE,eAAe;IAC5C,2BAA2B,EAAE,eAAe;IAC5C,4BAA4B,EAAE,gBAAgB;IAC9C,wBAAwB,EAAE,aAAa;IACvC,sBAAsB,EAAE,UAAU;IAClC,qBAAqB,EAAE,SAAS;CACjC,CAAA;AAED,4DAA4D;AAC5D,MAAM,UAAU,UAAU,CAAC,KAAkB;;IAC3C,MAAM,CAAC,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAA;IAC9D,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;AACnF,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,cAAc,EAAE,2BAA2B;IAC3C,iBAAiB,EAAE,qBAAqB;IACxC,cAAc,EAAE,qBAAqB;IACrC,cAAc,EAAE,sBAAsB;IACtC,eAAe,EAAE,sBAAsB;IACvC,oBAAoB,EAAE,sBAAsB;IAC5C,YAAY,EAAE,0BAA0B;CACzC,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,MAAc;;IACpC,OAAO,CAAC,CAAC,OAAO,MAAM,EAAE,EAAE,MAAA,QAAQ,CAAC,MAAM,CAAC,mCAAI,MAAM,CAAC,CAAA;AACvD,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,YAAY,EAAE,4BAA4B;IAC1C,mBAAmB,EAAE,sBAAsB;IAC3C,oBAAoB,EAAE,uBAAuB;IAC7C,oBAAoB,EAAE,gCAAgC;IACtD,gBAAgB,EAAE,kCAAkC;CACrD,CAAA;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;;IACxC,OAAO,CAAC,CAAC,YAAY,MAAM,EAAE,EAAE,MAAA,aAAa,CAAC,MAAM,CAAC,mCAAI,MAAM,CAAC,CAAA;AACjE,CAAC","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n *\n * 검증 문제(코드·경로·매개변수)를 화면 문구로. 번역 키는 label.slot-layout.issue.{코드} 이고,\n * 번역이 없으면 아래 영어 기본 문구를 쓴다. 호스트 고유 코드는 호스트가 번역을 넣거나 issueText 옵션으로 바꾼다.\n */\n\nimport { i18next } from '@operato/i18n'\nimport type { LayoutIssueCode, SlotSpaceCode } from '@hatiolab/things-scene'\n\n/** 문제 하나. 호스트 고유 코드도 같은 모양으로 온다 */\nexport interface EditorIssue {\n code: string\n path: string\n params?: Record<string, string | number>\n}\n\n/** things-scene 검증 코드의 기본 문구. 자리표시자가 중괄호 하나라서 문구에 중괄호 글자를 쓰지 않는다 */\nexport const ISSUE_TEXT: Record<LayoutIssueCode, string> = {\n TIERS_REQUIRED: 'At least one tier is required',\n MOUNT_INVALID: 'Must be on, in or hang',\n ANCHOR_REQUIRED: 'Choose a face',\n ANCHOR_UNKNOWN: 'This holder has no face {anchorId}',\n TIER_NUMBER_DUPLICATE: 'Tier {tierNo} is used twice',\n FINITE_NUMBER_REQUIRED: 'A number is required',\n POSITIVE_NUMBER_REQUIRED: 'A number greater than 0 is required',\n POSITIVE_INTEGER_REQUIRED: 'A whole number of 1 or more is required',\n ARRAY_REQUIRED: 'A list is required',\n OBJECT_REQUIRED: 'The value is not a layout',\n AXIS_INVALID: 'Must be X or Z',\n PATTERN_INVALID: 'Must be one, row, grid or listed',\n SLOTS_REQUIRED: 'At least one slot is required',\n SLOT_NUMBER_DUPLICATE: 'Slot {slotNo} is used twice',\n NOT_PERSISTABLE: 'Cannot be saved ({value})',\n ACCEPTS_EMPTY: 'The list of types it takes is empty; choose 「Any type」 to take any item'\n}\n\nexport const t = (key: string, fallback: string, opts: Record<string, unknown> = {}) =>\n i18next.t(`label.slot-layout.${key}`, { defaultValue: fallback, ...opts })\n\n/** 자리 공간 경고의 기본 문구. 번역 키는 label.slot-layout.space.{코드} */\nexport const SPACE_TEXT: Record<SlotSpaceCode, string> = {\n SLOT_OVERLAP: 'Tier {tier} slot {slot} overlaps tier {otherTier} slot {otherSlot}',\n SLOT_OUTSIDE_ANCHOR: 'Tier {tier} slot {slot} reaches past its face',\n ANCHOR_SPACE_UNKNOWN: 'Face {anchorId} has no size: whether slots stay on it is not checked'\n}\n\nexport function spaceWarningText(warning: EditorIssue): string {\n const fallback = (SPACE_TEXT as Record<string, string>)[warning.code] ?? warning.code\n return t(`space.${warning.code}`, fallback, { ...warning.params, interpolation: { escapeValue: false } })\n}\n\n/** Slot numbers as few words: runs of numbers as 1~8, the rest one by one. */\nexport function slotsWords(slots: readonly (string | number)[]): string {\n const numbers = slots.map(Number)\n if (!numbers.every(Number.isInteger)) return slots.join(', ')\n const sorted = [...new Set(numbers)].sort((a, b) => a - b)\n const runs: string[] = []\n for (let i = 0; i < sorted.length; ) {\n let j = i\n while (j + 1 < sorted.length && sorted[j + 1] === sorted[j]! + 1) j++\n runs.push(j - i >= 2 ? `${sorted[i]}~${sorted[j]}` : sorted.slice(i, j + 1).join(', '))\n i = j + 1\n }\n return runs.join(', ')\n}\n\n/**\n * The space warnings to show: the slots of one tier that reach past their face said in one line. Eight slots past a\n * face were eight red lines that said the same (figure modeller sweep 2026-10-27 M3).\n */\nexport function spaceWarningLines(warnings: readonly EditorIssue[]): string[] {\n const outside = new Map<string, (string | number)[]>()\n const lines: (string | { tier: string })[] = []\n for (const w of warnings) {\n if (w.code !== 'SLOT_OUTSIDE_ANCHOR') {\n lines.push(spaceWarningText(w))\n continue\n }\n const tier = String(w.params?.tier ?? '')\n if (!outside.has(tier)) {\n outside.set(tier, [])\n lines.push({ tier })\n }\n outside.get(tier)!.push(w.params?.slot ?? '')\n }\n return lines.map(line => {\n if (typeof line === 'string') return line\n const slots = outside.get(line.tier)!\n if (slots.length === 1) return spaceWarningText({ code: 'SLOT_OUTSIDE_ANCHOR', path: '', params: { tier: line.tier, slot: slots[0]! } })\n return t('space.SLOT_OUTSIDE_ANCHOR_MANY', 'Tier {tier} slots {slots} reach past their face', { tier: line.tier, slots: slotsWords(slots), interpolation: { escapeValue: false } })\n })\n}\n\n/** 문제 하나를 화면 문구로. 앞에 값의 위치를 붙인다 */\nexport function issueText(issue: EditorIssue): string {\n const fallback = (ISSUE_TEXT as Record<string, string>)[issue.code] ?? issue.code\n const text = t(`issue.${issue.code}`, fallback, { ...issue.params, interpolation: { escapeValue: false } })\n return issue.path ? `${issue.path}: ${text}` : text\n}\n\n/** 문제 하나를 화면 문구로, 위치 없이. 칸 옆에 보일 때 쓴다 */\nexport function issueMessage(issue: EditorIssue): string {\n const fallback = (ISSUE_TEXT as Record<string, string>)[issue.code] ?? issue.code\n return t(`issue.${issue.code}`, fallback, { ...issue.params, interpolation: { escapeValue: false } })\n}\n\n/** Tier 안의 경로 → 편집기 칸(data-field). 칸이 없는 경로(CUSTOM 자리 표 등)는 목록에 보인다 */\nconst FIELD_OF_PATH: Record<string, string> = {\n anchorId: 'anchor',\n mount: 'mount',\n position: 'position-x',\n 'position.x': 'position-x',\n 'position.y': 'position-y',\n 'position.z': 'position-z',\n rotation: 'tier-rotation',\n layout: 'pattern',\n 'layout.pattern': 'pattern',\n 'layout.count': 'count',\n 'layout.pitch': 'pitch',\n 'layout.pitch.x': 'pitch-x',\n 'layout.pitch.z': 'pitch-z',\n 'layout.axis': 'axis',\n 'layout.origin': 'origin',\n 'layout.origin.x': 'origin-x',\n 'layout.origin.z': 'origin-z',\n 'layout.rows': 'rows',\n 'layout.cols': 'cols',\n 'layout.order': 'order',\n 'layout.slot': 'allowed-width',\n 'layout.slot.allowed': 'allowed-width',\n 'layout.slot.allowed.width': 'allowed-width',\n 'layout.slot.allowed.depth': 'allowed-depth',\n 'layout.slot.allowed.height': 'allowed-height',\n 'layout.slot.stackLimit': 'stack-limit',\n 'layout.slot.rotation': 'rotation',\n 'layout.slot.accepts': 'accepts'\n}\n\n/** 문제가 어느 Tier(목록 순서)의 어느 칸인지. Tier 밖이거나 칸이 없으면 field 없음 */\nexport function issueField(issue: EditorIssue): { tierIndex?: number; field?: string } {\n const m = /^tiers\\[(\\d+)\\](?:\\.(.+))?$/.exec(issue.path ?? '')\n if (!m) return {}\n return { tierIndex: Number(m[1]), field: m[2] ? FIELD_OF_PATH[m[2]] : undefined }\n}\n\n/** 실린 아이템 판정 까닭의 기본 문구. 번역 키는 label.slot-layout.fit.{까닭} */\nexport const FIT_TEXT: Record<string, string> = {\n SLOT_NOT_FOUND: 'Slot gone: kept, unplaced',\n TYPE_NOT_ACCEPTED: 'Type not taken here',\n WIDTH_EXCEEDED: 'Wider than the slot',\n DEPTH_EXCEEDED: 'Deeper than the slot',\n HEIGHT_EXCEEDED: 'Taller than the slot',\n STACK_LIMIT_EXCEEDED: 'Over the stack limit',\n SPEC_UNKNOWN: 'Size unknown: not judged'\n}\n\nexport function fitText(reason: string): string {\n return t(`fit.${reason}`, FIT_TEXT[reason] ?? reason)\n}\n\n/** 면에 맞출 수 없는 까닭의 기본 문구. 번역 키는 label.slot-layout.fit-face.{까닭} */\nexport const FIT_FACE_TEXT: Record<string, string> = {\n FACE_UNKNOWN: 'The face size is not known',\n PATTERN_UNSUPPORTED: 'Not for listed slots',\n ROTATION_UNSUPPORTED: 'Only for turns of 90°',\n SLOT_WIDER_THAN_FACE: 'A slot is larger than the face',\n SLOTS_DO_NOT_FIT: 'The slots do not fit on the face'\n}\n\nexport function fitFaceText(reason: string): string {\n return t(`fit-face.${reason}`, FIT_FACE_TEXT[reason] ?? reason)\n}\n"]}
|
|
@@ -19,7 +19,7 @@ import { customElement, property, state } from 'lit/decorators.js';
|
|
|
19
19
|
import { i18next, localize } from '@operato/i18n';
|
|
20
20
|
import { persistenceIssues, rotatedFootprint, slotSpaceWarnings, validateSlotLayout } from '@hatiolab/things-scene';
|
|
21
21
|
import { addCustomSlot, addressImpact, anchorFaceSlots, applyPreset, copyTier, fitTierToFace, heldItemStatuses, pitchToPoint, removeCustomSlot, removeTier, setTierPattern, updatePattern, updateSlotSpec, updateTier } from './draft.js';
|
|
22
|
-
import { fitFaceText, fitText, issueField, issueMessage, issueText as defaultIssueText, ISSUE_TEXT,
|
|
22
|
+
import { fitFaceText, fitText, issueField, issueMessage, issueText as defaultIssueText, ISSUE_TEXT, spaceWarningLines, t } from './issue-text.js';
|
|
23
23
|
const num = (e) => {
|
|
24
24
|
const n = e.target.valueAsNumber;
|
|
25
25
|
return Number.isFinite(n) ? n : NaN;
|
|
@@ -372,8 +372,10 @@ let OxSlotLayoutEditor = class OxSlotLayoutEditor extends localize(i18next)(LitE
|
|
|
372
372
|
const a = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.anchors) === null || _b === void 0 ? void 0 : _b.find(x => x.id === id);
|
|
373
373
|
if (a === null || a === void 0 ? void 0 : a.label)
|
|
374
374
|
return a.label;
|
|
375
|
+
// 면 이름이 이미 부품을 말한다: id 가 부품 이름과 같으면 다시 적지 않는다(「tub · tub 윗면」, figure 점검 2026-10-27 M5)
|
|
376
|
+
const face = t(`face-${(_c = a === null || a === void 0 ? void 0 : a.face) !== null && _c !== void 0 ? _c : 'top'}`, `{part} ${(_d = a === null || a === void 0 ? void 0 : a.face) !== null && _d !== void 0 ? _d : 'top'}`, { part: a === null || a === void 0 ? void 0 : a.part });
|
|
375
377
|
if (a === null || a === void 0 ? void 0 : a.part)
|
|
376
|
-
return
|
|
378
|
+
return a.part === id ? face : `${id} · ${face}`;
|
|
377
379
|
return id;
|
|
378
380
|
}
|
|
379
381
|
_unit() {
|
|
@@ -478,7 +480,7 @@ let OxSlotLayoutEditor = class OxSlotLayoutEditor extends localize(i18next)(LitE
|
|
|
478
480
|
const warnings = this.warnings.filter(w => { var _a; return !(w.code === 'ANCHOR_SPACE_UNKNOWN' && !faceKnown && ((_a = w.params) === null || _a === void 0 ? void 0 : _a.anchorId) === anchorId); });
|
|
479
481
|
if (!warnings.length)
|
|
480
482
|
return nothing;
|
|
481
|
-
return html `<div class="error" data-warnings>${warnings.map(
|
|
483
|
+
return html `<div class="error" data-warnings>${spaceWarningLines(warnings).map(line => html `<div>· ${line}</div>`)}</div>`;
|
|
482
484
|
}
|
|
483
485
|
/**
|
|
484
486
|
* 실린 아이템이 편집 중인 레이아웃에서 어떻게 되는지. 자리가 없어지면 미배치로 남고(지우거나 옮기지 않는다), 받는 타입·규격은
|
|
@@ -794,18 +796,24 @@ let OxSlotLayoutEditor = class OxSlotLayoutEditor extends localize(i18next)(LitE
|
|
|
794
796
|
`;
|
|
795
797
|
}
|
|
796
798
|
};
|
|
799
|
+
/*
|
|
800
|
+
호스트가 자기 패널의 모양을 줄 수 있다(figure 점검 2026-10-27 M2): 글자 크기, 라벨 열과 정렬, 입력칸의 높이·테두리.
|
|
801
|
+
--slot-layout-font-size · --slot-layout-label-column · --slot-layout-label-align ·
|
|
802
|
+
--slot-layout-field-border · --slot-layout-field-border-bottom · --slot-layout-field-radius · --slot-layout-field-background.
|
|
803
|
+
주지 않으면 지금 모양 그대로다(--property-editor-* 를 따른다).
|
|
804
|
+
*/
|
|
797
805
|
OxSlotLayoutEditor.styles = css `
|
|
798
806
|
:host {
|
|
799
807
|
display: flex;
|
|
800
808
|
flex-direction: column;
|
|
801
809
|
gap: 8px;
|
|
802
810
|
min-width: 0;
|
|
803
|
-
font-size: 12px;
|
|
811
|
+
font-size: var(--slot-layout-font-size, 12px);
|
|
804
812
|
color: var(--property-editor-color, inherit);
|
|
805
813
|
}
|
|
806
814
|
section {
|
|
807
815
|
display: grid;
|
|
808
|
-
grid-template-columns: minmax(64px, 34%) minmax(0, 1fr);
|
|
816
|
+
grid-template-columns: var(--slot-layout-label-column, minmax(64px, 34%)) minmax(0, 1fr);
|
|
809
817
|
gap: 4px 6px;
|
|
810
818
|
align-items: center;
|
|
811
819
|
}
|
|
@@ -813,7 +821,7 @@ OxSlotLayoutEditor.styles = css `
|
|
|
813
821
|
summary {
|
|
814
822
|
grid-column: 1 / -1;
|
|
815
823
|
margin: 4px 0 0;
|
|
816
|
-
font-size: 12px;
|
|
824
|
+
font-size: var(--slot-layout-font-size, 12px);
|
|
817
825
|
font-weight: bold;
|
|
818
826
|
}
|
|
819
827
|
summary {
|
|
@@ -823,7 +831,7 @@ OxSlotLayoutEditor.styles = css `
|
|
|
823
831
|
margin-top: 4px;
|
|
824
832
|
}
|
|
825
833
|
label.l {
|
|
826
|
-
text-align: right;
|
|
834
|
+
text-align: var(--slot-layout-label-align, right);
|
|
827
835
|
font: var(--property-editor-label-font, inherit);
|
|
828
836
|
color: var(--property-editor-label-color, inherit);
|
|
829
837
|
}
|
|
@@ -858,9 +866,10 @@ OxSlotLayoutEditor.styles = css `
|
|
|
858
866
|
min-width: 0;
|
|
859
867
|
min-height: var(--property-editor-field-height, 24px);
|
|
860
868
|
padding: var(--property-editor-field-padding, 1px 4px);
|
|
861
|
-
border: var(--property-editor-border, 1px solid rgba(0, 0, 0, 0.2));
|
|
862
|
-
border-
|
|
863
|
-
|
|
869
|
+
border: var(--slot-layout-field-border, var(--property-editor-border, 1px solid rgba(0, 0, 0, 0.2)));
|
|
870
|
+
border-bottom: var(--slot-layout-field-border-bottom, var(--slot-layout-field-border, var(--property-editor-border, 1px solid rgba(0, 0, 0, 0.2))));
|
|
871
|
+
border-radius: var(--slot-layout-field-radius, var(--property-editor-border-radius, 4px));
|
|
872
|
+
background-color: var(--slot-layout-field-background, var(--property-editor-background, field));
|
|
864
873
|
color: inherit;
|
|
865
874
|
font: var(--property-editor-field-font, inherit);
|
|
866
875
|
outline: none;
|